Bug Summary

File:home/maarten/src/libreoffice/core/svx/source/svdraw/svdedtv2.cxx
Warning:line 633, column 39
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name svdedtv2.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SVXCORE_DLLIMPLEMENTATION -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/epoxy/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium/public -D COMPONENT_BUILD -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/svx/inc -I /home/maarten/src/libreoffice/core/svx/source/inc -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/svx/sdi -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/svx/source/svdraw/svdedtv2.cxx

/home/maarten/src/libreoffice/core/svx/source/svdraw/svdedtv2.cxx

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 <svx/svdedtv.hxx>
21#include <svx/svdundo.hxx>
22#include <svx/svdogrp.hxx>
23#include <svx/svdoutl.hxx>
24#include <svx/svdopath.hxx>
25#include <svx/svdpage.hxx>
26#include <svx/svdpagv.hxx>
27#include <svx/svditer.hxx>
28#include <svx/svdograf.hxx>
29#include <svx/svdoole2.hxx>
30#include <svx/dialmgr.hxx>
31#include <svx/sdooitm.hxx>
32#include <svx/sdshitm.hxx>
33#include <svx/xfillit0.hxx>
34#include <svx/xlineit0.hxx>
35#include <svx/xtextit0.hxx>
36#include "svdfmtf.hxx"
37#include <svdpdf.hxx>
38#include <svx/svdetc.hxx>
39#include <editeng/outlobj.hxx>
40#include <editeng/eeitem.hxx>
41#include <basegfx/polygon/b2dpolypolygon.hxx>
42#include <basegfx/polygon/b2dpolypolygontools.hxx>
43#include <svx/svxdlg.hxx>
44#include <svx/strings.hrc>
45#include <svx/svdoashp.hxx>
46#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
47#include <i18nutil/unicode.hxx>
48#include <sal/log.hxx>
49#include <tools/debug.hxx>
50#include <memory>
51#include <vector>
52#include <vcl/graph.hxx>
53#include <svx/svxids.hrc>
54
55using namespace com::sun::star;
56
57SdrObject* SdrEditView::GetMaxToTopObj(SdrObject* /*pObj*/) const
58{
59 return nullptr;
60}
61
62SdrObject* SdrEditView::GetMaxToBtmObj(SdrObject* /*pObj*/) const
63{
64 return nullptr;
65}
66
67void SdrEditView::ObjOrderChanged(SdrObject* /*pObj*/, size_t /*nOldPos*/, size_t /*nNewPos*/)
68{
69}
70
71void SdrEditView::MovMarkedToTop()
72{
73 const size_t nCount=GetMarkedObjectCount();
74 if (nCount==0)
75 return;
76
77 const bool bUndo = IsUndoEnabled();
78
79 if( bUndo )
80 BegUndo(SvxResId(STR_EditMovToTopreinterpret_cast<char const *>("STR_EditMovToTop" "\004"
u8"Move %1 forward")
),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::MoveToTop);
81
82 SortMarkedObjects();
83 for (size_t nm=0; nm<nCount; ++nm)
84 { // All Ordnums have to be correct!
85 GetMarkedObjectByIndex(nm)->GetOrdNum();
86 }
87 bool bChg=false;
88 SdrObjList* pOL0=nullptr;
89 size_t nNewPos=0;
90 for (size_t nm=nCount; nm>0;)
91 {
92 --nm;
93 SdrMark* pM=GetSdrMarkByIndex(nm);
94 SdrObject* pObj=pM->GetMarkedSdrObj();
95 SdrObjList* pOL=pObj->getParentSdrObjListFromSdrObject();
96 if (pOL!=pOL0)
97 {
98 nNewPos = pOL->GetObjCount()-1;
99 pOL0=pOL;
100 }
101 const size_t nNowPos = pObj->GetOrdNumDirect();
102 const tools::Rectangle& rBR=pObj->GetCurrentBoundRect();
103 size_t nCmpPos = nNowPos+1;
104 SdrObject* pMaxObj=GetMaxToTopObj(pObj);
105 if (pMaxObj!=nullptr)
106 {
107 size_t nMaxPos=pMaxObj->GetOrdNum();
108 if (nMaxPos!=0)
109 nMaxPos--;
110 if (nNewPos>nMaxPos)
111 nNewPos=nMaxPos; // neither go faster...
112 if (nNewPos<nNowPos)
113 nNewPos=nNowPos; // nor go in the other direction
114 }
115 bool bEnd=false;
116 while (nCmpPos<nNewPos && !bEnd)
117 {
118 SdrObject* pCmpObj=pOL->GetObj(nCmpPos);
119 if (pCmpObj==nullptr)
120 {
121 OSL_FAIL("MovMarkedToTop(): Reference object not found.")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdedtv2.cxx"
":" "121" ": "), "%s", "MovMarkedToTop(): Reference object not found."
); } } while (false)
;
122 bEnd=true;
123 }
124 else if (pCmpObj==pMaxObj)
125 {
126 nNewPos=nCmpPos;
127 nNewPos--;
128 bEnd=true;
129 }
130 else if (rBR.IsOver(pCmpObj->GetCurrentBoundRect()))
131 {
132 nNewPos=nCmpPos;
133 bEnd=true;
134 }
135 else
136 {
137 nCmpPos++;
138 }
139 }
140 if (nNowPos!=nNewPos)
141 {
142 bChg=true;
143 pOL->SetObjectOrdNum(nNowPos,nNewPos);
144 if( bUndo )
145 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
146 ObjOrderChanged(pObj,nNowPos,nNewPos);
147 }
148 nNewPos--;
149 }
150
151 if( bUndo )
152 EndUndo();
153
154 if (bChg)
155 MarkListHasChanged();
156}
157
158void SdrEditView::MovMarkedToBtm()
159{
160 const size_t nCount=GetMarkedObjectCount();
161 if (nCount==0)
162 return;
163
164 const bool bUndo = IsUndoEnabled();
165
166 if( bUndo )
167 BegUndo(SvxResId(STR_EditMovToBtmreinterpret_cast<char const *>("STR_EditMovToBtm" "\004"
u8"Move %1 further back")
),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::MoveToBottom);
168
169 SortMarkedObjects();
170 for (size_t nm=0; nm<nCount; ++nm)
171 { // All Ordnums have to be correct!
172 GetMarkedObjectByIndex(nm)->GetOrdNum();
173 }
174
175 bool bChg=false;
176 SdrObjList* pOL0=nullptr;
177 size_t nNewPos=0;
178 for (size_t nm=0; nm<nCount; ++nm)
179 {
180 SdrMark* pM=GetSdrMarkByIndex(nm);
181 SdrObject* pObj=pM->GetMarkedSdrObj();
182 SdrObjList* pOL=pObj->getParentSdrObjListFromSdrObject();
183 if (pOL!=pOL0)
184 {
185 nNewPos=0;
186 pOL0=pOL;
187 }
188 const size_t nNowPos = pObj->GetOrdNumDirect();
189 const tools::Rectangle& rBR=pObj->GetCurrentBoundRect();
190 size_t nCmpPos = nNowPos;
191 if (nCmpPos>0)
192 --nCmpPos;
193 SdrObject* pMaxObj=GetMaxToBtmObj(pObj);
194 if (pMaxObj!=nullptr)
195 {
196 const size_t nMinPos=pMaxObj->GetOrdNum()+1;
197 if (nNewPos<nMinPos)
198 nNewPos=nMinPos; // neither go faster...
199 if (nNewPos>nNowPos)
200 nNewPos=nNowPos; // nor go in the other direction
201 }
202 bool bEnd=false;
203 // nNewPos in this case is the "maximum" position
204 // the object may reach without going faster than the object before
205 // it (multiple selection).
206 while (nCmpPos>nNewPos && !bEnd)
207 {
208 SdrObject* pCmpObj=pOL->GetObj(nCmpPos);
209 if (pCmpObj==nullptr)
210 {
211 OSL_FAIL("MovMarkedToBtm(): Reference object not found.")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdedtv2.cxx"
":" "211" ": "), "%s", "MovMarkedToBtm(): Reference object not found."
); } } while (false)
;
212 bEnd=true;
213 }
214 else if (pCmpObj==pMaxObj)
215 {
216 nNewPos=nCmpPos;
217 nNewPos++;
218 bEnd=true;
219 }
220 else if (rBR.IsOver(pCmpObj->GetCurrentBoundRect()))
221 {
222 nNewPos=nCmpPos;
223 bEnd=true;
224 }
225 else
226 {
227 nCmpPos--;
228 }
229 }
230 if (nNowPos!=nNewPos)
231 {
232 bChg=true;
233 pOL->SetObjectOrdNum(nNowPos,nNewPos);
234 if( bUndo )
235 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
236 ObjOrderChanged(pObj,nNowPos,nNewPos);
237 }
238 nNewPos++;
239 }
240
241 if(bUndo)
242 EndUndo();
243
244 if(bChg)
245 MarkListHasChanged();
246}
247
248void SdrEditView::PutMarkedToTop()
249{
250 PutMarkedInFrontOfObj(nullptr);
251}
252
253void SdrEditView::PutMarkedInFrontOfObj(const SdrObject* pRefObj)
254{
255 const size_t nCount=GetMarkedObjectCount();
256 if (nCount==0)
257 return;
258
259 const bool bUndo = IsUndoEnabled();
260 if( bUndo )
261 BegUndo(SvxResId(STR_EditPutToTopreinterpret_cast<char const *>("STR_EditPutToTop" "\004"
u8"Move %1 to front")
),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::PutToTop);
262
263 SortMarkedObjects();
264
265 if (pRefObj!=nullptr)
266 {
267 // Make "in front of the object" work, even if the
268 // selected objects are already in front of the other object
269 const size_t nRefMark=TryToFindMarkedObject(pRefObj);
270 SdrMark aRefMark;
271 if (nRefMark!=SAL_MAX_SIZE((sal_uInt64) 0xFFFFFFFFFFFFFFFFul))
272 {
273 aRefMark=*GetSdrMarkByIndex(nRefMark);
274 GetMarkedObjectListWriteAccess().DeleteMark(nRefMark);
275 }
276 PutMarkedToBtm();
277 if (nRefMark!=SAL_MAX_SIZE((sal_uInt64) 0xFFFFFFFFFFFFFFFFul))
278 {
279 GetMarkedObjectListWriteAccess().InsertEntry(aRefMark);
280 SortMarkedObjects();
281 }
282 }
283 for (size_t nm=0; nm<nCount; ++nm)
284 { // All Ordnums have to be correct!
285 GetMarkedObjectByIndex(nm)->GetOrdNum();
286 }
287 bool bChg=false;
288 SdrObjList* pOL0=nullptr;
289 size_t nNewPos=0;
290 for (size_t nm=nCount; nm>0;)
291 {
292 --nm;
293 SdrMark* pM=GetSdrMarkByIndex(nm);
294 SdrObject* pObj=pM->GetMarkedSdrObj();
295 if (pObj!=pRefObj)
296 {
297 SdrObjList* pOL=pObj->getParentSdrObjListFromSdrObject();
298 if (pOL!=pOL0)
299 {
300 nNewPos=pOL->GetObjCount()-1;
301 pOL0=pOL;
302 }
303 const size_t nNowPos=pObj->GetOrdNumDirect();
304 SdrObject* pMaxObj=GetMaxToTopObj(pObj);
305 if (pMaxObj!=nullptr)
306 {
307 size_t nMaxOrd=pMaxObj->GetOrdNum(); // sadly doesn't work any other way
308 if (nMaxOrd>0)
309 nMaxOrd--;
310 if (nNewPos>nMaxOrd)
311 nNewPos=nMaxOrd; // neither go faster...
312 if (nNewPos<nNowPos)
313 nNewPos=nNowPos; // nor go into the other direction
314 }
315 if (pRefObj!=nullptr)
316 {
317 if (pRefObj->getParentSdrObjListFromSdrObject()==pObj->getParentSdrObjListFromSdrObject())
318 {
319 const size_t nMaxOrd=pRefObj->GetOrdNum(); // sadly doesn't work any other way
320 if (nNewPos>nMaxOrd)
321 nNewPos=nMaxOrd; // neither go faster...
322 if (nNewPos<nNowPos)
323 nNewPos=nNowPos; // nor go into the other direction
324 }
325 else
326 {
327 nNewPos=nNowPos; // different PageView, so don't change
328 }
329 }
330 if (nNowPos!=nNewPos)
331 {
332 bChg=true;
333 pOL->SetObjectOrdNum(nNowPos,nNewPos);
334 if( bUndo )
335 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
336 ObjOrderChanged(pObj,nNowPos,nNewPos);
337 }
338 nNewPos--;
339 } // if (pObj!=pRefObj)
340 } // for loop over all selected objects
341
342 if( bUndo )
343 EndUndo();
344
345 if(bChg)
346 MarkListHasChanged();
347}
348
349void SdrEditView::PutMarkedToBtm()
350{
351 PutMarkedBehindObj(nullptr);
352}
353
354void SdrEditView::PutMarkedBehindObj(const SdrObject* pRefObj)
355{
356 const size_t nCount=GetMarkedObjectCount();
357 if (nCount==0)
358 return;
359
360 const bool bUndo = IsUndoEnabled();
361
362 if( bUndo )
363 BegUndo(SvxResId(STR_EditPutToBtmreinterpret_cast<char const *>("STR_EditPutToBtm" "\004"
u8"Move %1 to back")
),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::PutToBottom);
364
365 SortMarkedObjects();
366 if (pRefObj!=nullptr)
367 {
368 // Make "behind the object" work, even if the
369 // selected objects are already behind the other object
370 const size_t nRefMark=TryToFindMarkedObject(pRefObj);
371 SdrMark aRefMark;
372 if (nRefMark!=SAL_MAX_SIZE((sal_uInt64) 0xFFFFFFFFFFFFFFFFul))
373 {
374 aRefMark=*GetSdrMarkByIndex(nRefMark);
375 GetMarkedObjectListWriteAccess().DeleteMark(nRefMark);
376 }
377 PutMarkedToTop();
378 if (nRefMark!=SAL_MAX_SIZE((sal_uInt64) 0xFFFFFFFFFFFFFFFFul))
379 {
380 GetMarkedObjectListWriteAccess().InsertEntry(aRefMark);
381 SortMarkedObjects();
382 }
383 }
384 for (size_t nm=0; nm<nCount; ++nm) { // All Ordnums have to be correct!
385 GetMarkedObjectByIndex(nm)->GetOrdNum();
386 }
387 bool bChg=false;
388 SdrObjList* pOL0=nullptr;
389 size_t nNewPos=0;
390 for (size_t nm=0; nm<nCount; ++nm) {
391 SdrMark* pM=GetSdrMarkByIndex(nm);
392 SdrObject* pObj=pM->GetMarkedSdrObj();
393 if (pObj!=pRefObj) {
394 SdrObjList* pOL=pObj->getParentSdrObjListFromSdrObject();
395 if (pOL!=pOL0) {
396 nNewPos=0;
397 pOL0=pOL;
398 }
399 const size_t nNowPos=pObj->GetOrdNumDirect();
400 SdrObject* pMinObj=GetMaxToBtmObj(pObj);
401 if (pMinObj!=nullptr) {
402 const size_t nMinOrd=pMinObj->GetOrdNum()+1; // sadly doesn't work any differently
403 if (nNewPos<nMinOrd) nNewPos=nMinOrd; // neither go faster...
404 if (nNewPos>nNowPos) nNewPos=nNowPos; // nor go into the other direction
405 }
406 if (pRefObj!=nullptr) {
407 if (pRefObj->getParentSdrObjListFromSdrObject()==pObj->getParentSdrObjListFromSdrObject()) {
408 const size_t nMinOrd=pRefObj->GetOrdNum(); // sadly doesn't work any differently
409 if (nNewPos<nMinOrd) nNewPos=nMinOrd; // neither go faster...
410 if (nNewPos>nNowPos) nNewPos=nNowPos; // nor go into the other direction
411 } else {
412 nNewPos=nNowPos; // different PageView, so don't change
413 }
414 }
415 if (nNowPos!=nNewPos) {
416 bChg=true;
417 pOL->SetObjectOrdNum(nNowPos,nNewPos);
418 if( bUndo )
419 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj,nNowPos,nNewPos));
420 ObjOrderChanged(pObj,nNowPos,nNewPos);
421 }
422 nNewPos++;
423 } // if (pObj!=pRefObj)
424 } // for loop over all selected objects
425
426 if(bUndo)
427 EndUndo();
428
429 if(bChg)
430 MarkListHasChanged();
431
432}
433
434void SdrEditView::ReverseOrderOfMarked()
435{
436 SortMarkedObjects();
437 const size_t nMarkCount=GetMarkedObjectCount();
438 if (nMarkCount<=0)
439 return;
440
441 bool bChg=false;
442
443 bool bUndo = IsUndoEnabled();
444 if( bUndo )
445 BegUndo(SvxResId(STR_EditRevOrderreinterpret_cast<char const *>("STR_EditRevOrder" "\004"
u8"Reverse order of %1")
),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::ReverseOrder);
446
447 size_t a=0;
448 do {
449 // take into account selection across multiple PageViews
450 size_t b=a+1;
451 while (b<nMarkCount && GetSdrPageViewOfMarkedByIndex(b) == GetSdrPageViewOfMarkedByIndex(a)) ++b;
452 --b;
453 SdrObjList* pOL=GetSdrPageViewOfMarkedByIndex(a)->GetObjList();
454 size_t c=b;
455 if (a<c) { // make sure OrdNums aren't dirty
456 GetMarkedObjectByIndex(a)->GetOrdNum();
457 }
458 while (a<c) {
459 SdrObject* pObj1=GetMarkedObjectByIndex(a);
460 SdrObject* pObj2=GetMarkedObjectByIndex(c);
461 const size_t nOrd1=pObj1->GetOrdNumDirect();
462 const size_t nOrd2=pObj2->GetOrdNumDirect();
463 if( bUndo )
464 {
465 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj1,nOrd1,nOrd2));
466 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoObjectOrdNum(*pObj2,nOrd2-1,nOrd1));
467 }
468 pOL->SetObjectOrdNum(nOrd1,nOrd2);
469 // Obj 2 has moved forward by one position, so now nOrd2-1
470 pOL->SetObjectOrdNum(nOrd2-1,nOrd1);
471 // use Replace instead of SetOrdNum for performance reasons (recalculation of Ordnums)
472 ++a;
473 --c;
474 bChg=true;
475 }
476 a=b+1;
477 } while (a<nMarkCount);
478
479 if(bUndo)
480 EndUndo();
481
482 if(bChg)
483 MarkListHasChanged();
484}
485
486void SdrEditView::ImpCheckToTopBtmPossible()
487{
488 const size_t nCount=GetMarkedObjectCount();
489 if (nCount==0)
490 return;
491 if (nCount==1)
492 { // special-casing for single selection
493 SdrObject* pObj=GetMarkedObjectByIndex(0);
494 SdrObjList* pOL=pObj->getParentSdrObjListFromSdrObject();
495 SAL_WARN_IF(!pOL, "svx", "Object somehow has no ObjList")do { if (true && (!pOL)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "svx")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "Object somehow has no ObjList"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"
), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdedtv2.cxx"
":" "495" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Object somehow has no ObjList"), 0); }
else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Object somehow has no ObjList"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdedtv2.cxx"
":" "495" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Object somehow has no ObjList") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdedtv2.cxx"
":" "495" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Object somehow has no ObjList"), 0); }
else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Object somehow has no ObjList"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdedtv2.cxx"
":" "495" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
496 size_t nMax = pOL ? pOL->GetObjCount() : 0;
497 size_t nMin = 0;
498 const size_t nObjNum=pObj->GetOrdNum();
499 SdrObject* pRestrict=GetMaxToTopObj(pObj);
500 if (pRestrict!=nullptr) {
501 const size_t nRestrict=pRestrict->GetOrdNum();
502 if (nRestrict<nMax) nMax=nRestrict;
503 }
504 pRestrict=GetMaxToBtmObj(pObj);
505 if (pRestrict!=nullptr) {
506 const size_t nRestrict=pRestrict->GetOrdNum();
507 if (nRestrict>nMin) nMin=nRestrict;
508 }
509 m_bToTopPossible=nObjNum<nMax-1;
510 m_bToBtmPossible=nObjNum>nMin;
511 } else { // multiple selection
512 SdrObjList* pOL0=nullptr;
513 size_t nPos0 = 0;
514 for (size_t nm = 0; !m_bToBtmPossible && nm<nCount; ++nm) { // check 'send to background'
515 SdrObject* pObj=GetMarkedObjectByIndex(nm);
516 SdrObjList* pOL=pObj->getParentSdrObjListFromSdrObject();
517 if (pOL!=pOL0) {
518 nPos0 = 0;
519 pOL0=pOL;
520 }
521 const size_t nPos = pObj->GetOrdNum();
522 m_bToBtmPossible = nPos && (nPos-1 > nPos0);
523 nPos0 = nPos;
524 }
525
526 pOL0=nullptr;
527 nPos0 = SAL_MAX_SIZE((sal_uInt64) 0xFFFFFFFFFFFFFFFFul);
528 for (size_t nm=nCount; !m_bToTopPossible && nm>0; ) { // check 'bring to front'
529 --nm;
530 SdrObject* pObj=GetMarkedObjectByIndex(nm);
531 SdrObjList* pOL=pObj->getParentSdrObjListFromSdrObject();
532 if (pOL!=pOL0) {
533 nPos0=pOL->GetObjCount();
534 pOL0=pOL;
535 }
536 const size_t nPos = pObj->GetOrdNum();
537 m_bToTopPossible = nPos+1 < nPos0;
538 nPos0=nPos;
539 }
540 }
541}
542
543
544// Combine
545
546
547void SdrEditView::ImpCopyAttributes(const SdrObject* pSource, SdrObject* pDest) const
548{
549 if (pSource!=nullptr) {
550 SdrObjList* pOL=pSource->GetSubList();
551 if (pOL!=nullptr && !pSource->Is3DObj()) { // get first non-group object from group
552 SdrObjListIter aIter(pOL,SdrIterMode::DeepNoGroups);
553 pSource=aIter.Next();
554 }
555 }
556
557 if(!(pSource && pDest))
558 return;
559
560 SfxItemSet aSet(mpModel->GetItemPool(),
561 svl::Items<SDRATTR_START, SDRATTR_NOTPERSIST_FIRST-1,
562 SDRATTR_NOTPERSIST_LAST+1, SDRATTR_END,
563 EE_ITEMS_START, EE_ITEMS_END>{});
564
565 aSet.Put(pSource->GetMergedItemSet());
566
567 pDest->ClearMergedItem();
568 pDest->SetMergedItemSet(aSet);
569
570 pDest->NbcSetLayer(pSource->GetLayer());
571 pDest->NbcSetStyleSheet(pSource->GetStyleSheet(), true);
572}
573
574bool SdrEditView::ImpCanConvertForCombine1(const SdrObject* pObj)
575{
576 // new condition IsLine() to be able to combine simple Lines
577 bool bIsLine(false);
578
579 const SdrPathObj* pPath = dynamic_cast< const SdrPathObj*>( pObj );
580
581 if(pPath)
582 {
583 bIsLine = pPath->IsLine();
584 }
585
586 SdrObjTransformInfoRec aInfo;
587 pObj->TakeObjInfo(aInfo);
588
589 return (aInfo.bCanConvToPath || aInfo.bCanConvToPoly || bIsLine);
590}
591
592bool SdrEditView::ImpCanConvertForCombine(const SdrObject* pObj)
593{
594 SdrObjList* pOL = pObj->GetSubList();
595
596 if(pOL && !pObj->Is3DObj())
597 {
598 SdrObjListIter aIter(pOL, SdrIterMode::DeepNoGroups);
599
600 while(aIter.IsMore())
601 {
602 SdrObject* pObj1 = aIter.Next();
603
604 // all members of a group have to be convertible
605 if(!ImpCanConvertForCombine1(pObj1))
606 {
607 return false;
608 }
609 }
610 }
611 else
612 {
613 if(!ImpCanConvertForCombine1(pObj))
614 {
615 return false;
616 }
617 }
618
619 return true;
620}
621
622basegfx::B2DPolyPolygon SdrEditView::ImpGetPolyPolygon1(const SdrObject* pObj)
623{
624 basegfx::B2DPolyPolygon aRetval;
625 const SdrPathObj* pPath = dynamic_cast<const SdrPathObj*>( pObj );
626
627 if(pPath && !pObj->GetOutlinerParaObject())
30
Assuming 'pPath' is null
628 {
629 aRetval = pPath->GetPathPoly();
630 }
631 else
632 {
633 SdrObjectUniquePtr pConvObj = pObj->ConvertToPolyObj(true/*bCombine*/, false);
31
Called C++ object pointer is null
634
635 if(pConvObj)
636 {
637 SdrObjList* pOL = pConvObj->GetSubList();
638
639 if(pOL)
640 {
641 SdrObjListIter aIter(pOL, SdrIterMode::DeepNoGroups);
642
643 while(aIter.IsMore())
644 {
645 SdrObject* pObj1 = aIter.Next();
646 pPath = dynamic_cast<SdrPathObj*>( pObj1 );
647
648 if(pPath)
649 {
650 aRetval.append(pPath->GetPathPoly());
651 }
652 }
653 }
654 else
655 {
656 pPath = dynamic_cast<SdrPathObj*>( pConvObj.get() );
657
658 if(pPath)
659 {
660 aRetval = pPath->GetPathPoly();
661 }
662 }
663 }
664 }
665
666 return aRetval;
667}
668
669basegfx::B2DPolyPolygon SdrEditView::ImpGetPolyPolygon(const SdrObject* pObj)
670{
671 SdrObjList* pOL = pObj->GetSubList();
672
673 if(pOL && !pObj->Is3DObj())
8
Assuming 'pOL' is non-null
9
Calling 'SdrObject::Is3DObj'
11
Returning from 'SdrObject::Is3DObj'
12
Taking true branch
674 {
675 basegfx::B2DPolyPolygon aRetval;
676 SdrObjListIter aIter(pOL, SdrIterMode::DeepNoGroups);
677
678 while(aIter.IsMore())
13
Calling 'SdrObjListIter::IsMore'
18
Returning from 'SdrObjListIter::IsMore'
19
Loop condition is true. Entering loop body
679 {
680 SdrObject* pObj1 = aIter.Next();
20
Calling 'SdrObjListIter::Next'
26
Returning from 'SdrObjListIter::Next'
27
'pObj1' initialized here
681 aRetval.append(ImpGetPolyPolygon1(pObj1));
28
Passing value via 1st parameter 'pObj'
29
Calling 'SdrEditView::ImpGetPolyPolygon1'
682 }
683
684 return aRetval;
685 }
686 else
687 {
688 return ImpGetPolyPolygon1(pObj);
689 }
690}
691
692basegfx::B2DPolygon SdrEditView::ImpCombineToSinglePolygon(const basegfx::B2DPolyPolygon& rPolyPolygon)
693{
694 const sal_uInt32 nPolyCount(rPolyPolygon.count());
695
696 if(0 == nPolyCount)
697 {
698 return basegfx::B2DPolygon();
699 }
700 else if(1 == nPolyCount)
701 {
702 return rPolyPolygon.getB2DPolygon(0);
703 }
704 else
705 {
706 basegfx::B2DPolygon aRetval(rPolyPolygon.getB2DPolygon(0));
707
708 for(sal_uInt32 a(1); a < nPolyCount; a++)
709 {
710 basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(a));
711
712 if(aRetval.count())
713 {
714 if(aCandidate.count())
715 {
716 const basegfx::B2DPoint aCA(aCandidate.getB2DPoint(0));
717 const basegfx::B2DPoint aCB(aCandidate.getB2DPoint(aCandidate.count() - 1));
718 const basegfx::B2DPoint aRA(aRetval.getB2DPoint(0));
719 const basegfx::B2DPoint aRB(aRetval.getB2DPoint(aRetval.count() - 1));
720
721 const double fRACA(basegfx::B2DVector(aCA - aRA).getLength());
722 const double fRACB(basegfx::B2DVector(aCB - aRA).getLength());
723 const double fRBCA(basegfx::B2DVector(aCA - aRB).getLength());
724 const double fRBCB(basegfx::B2DVector(aCB - aRB).getLength());
725
726 const double fSmallestRA(std::min(fRACA, fRACB));
727 const double fSmallestRB(std::min(fRBCA, fRBCB));
728
729 if(fSmallestRA < fSmallestRB)
730 {
731 // flip result
732 aRetval.flip();
733 }
734
735 const double fSmallestCA(std::min(fRACA, fRBCA));
736 const double fSmallestCB(std::min(fRACB, fRBCB));
737
738 if(fSmallestCB < fSmallestCA)
739 {
740 // flip candidate
741 aCandidate.flip();
742 }
743
744 // append candidate to retval
745 aRetval.append(aCandidate);
746 }
747 }
748 else
749 {
750 aRetval = aCandidate;
751 }
752 }
753
754 return aRetval;
755 }
756}
757
758namespace {
759
760// for distribution dialog function
761struct ImpDistributeEntry
762{
763 SdrObject* mpObj;
764 sal_Int32 mnPos;
765 sal_Int32 mnLength;
766};
767
768}
769
770typedef std::vector<ImpDistributeEntry> ImpDistributeEntryList;
771
772void SdrEditView::DistributeMarkedObjects(sal_uInt16 SlotID)
773{
774 const size_t nMark(GetMarkedObjectCount());
775
776 if(nMark <= 2)
777 return;
778
779 SvxDistributeHorizontal eHor = SvxDistributeHorizontal::NONE;
780 SvxDistributeVertical eVer = SvxDistributeVertical::NONE;
781
782 switch (SlotID)
783 {
784 case SID_DISTRIBUTE_HLEFT(5000 + 686): eHor = SvxDistributeHorizontal::Left; break;
785 case SID_DISTRIBUTE_HCENTER(5000 + 687): eHor = SvxDistributeHorizontal::Center; break;
786 case SID_DISTRIBUTE_HDISTANCE(5000 + 688): eHor = SvxDistributeHorizontal::Distance; break;
787 case SID_DISTRIBUTE_HRIGHT(5000 + 689): eHor = SvxDistributeHorizontal::Right; break;
788 case SID_DISTRIBUTE_VTOP(5000 + 690): eVer = SvxDistributeVertical::Top; break;
789 case SID_DISTRIBUTE_VCENTER(5000 + 691): eVer = SvxDistributeVertical::Center; break;
790 case SID_DISTRIBUTE_VDISTANCE(5000 + 692): eVer = SvxDistributeVertical::Distance; break;
791 case SID_DISTRIBUTE_VBOTTOM(5000 + 693): eVer = SvxDistributeVertical::Bottom; break;
792 }
793
794 ImpDistributeEntryList aEntryList;
795 ImpDistributeEntryList::iterator itEntryList;
796 sal_uInt32 nFullLength;
797
798 const bool bUndo = IsUndoEnabled();
799 if( bUndo )
800 BegUndo();
801
802 if(eHor != SvxDistributeHorizontal::NONE)
803 {
804 // build sorted entry list
805 nFullLength = 0;
806
807 for( size_t a = 0; a < nMark; ++a )
808 {
809 SdrMark* pMark = GetSdrMarkByIndex(a);
810 ImpDistributeEntry aNew;
811
812 aNew.mpObj = pMark->GetMarkedSdrObj();
813
814 switch(eHor)
815 {
816 case SvxDistributeHorizontal::Left:
817 {
818 aNew.mnPos = aNew.mpObj->GetSnapRect().Left();
819 break;
820 }
821 case SvxDistributeHorizontal::Center:
822 {
823 aNew.mnPos = (aNew.mpObj->GetSnapRect().Right() + aNew.mpObj->GetSnapRect().Left()) / 2;
824 break;
825 }
826 case SvxDistributeHorizontal::Distance:
827 {
828 aNew.mnLength = aNew.mpObj->GetSnapRect().GetWidth() + 1;
829 nFullLength += aNew.mnLength;
830 aNew.mnPos = (aNew.mpObj->GetSnapRect().Right() + aNew.mpObj->GetSnapRect().Left()) / 2;
831 break;
832 }
833 case SvxDistributeHorizontal::Right:
834 {
835 aNew.mnPos = aNew.mpObj->GetSnapRect().Right();
836 break;
837 }
838 default: break;
839 }
840
841 itEntryList = std::find_if(aEntryList.begin(), aEntryList.end(),
842 [&aNew](const ImpDistributeEntry& rEntry) { return rEntry.mnPos >= aNew.mnPos; });
843 if ( itEntryList < aEntryList.end() )
844 aEntryList.insert( itEntryList, aNew );
845 else
846 aEntryList.push_back( aNew );
847 }
848
849 if(eHor == SvxDistributeHorizontal::Distance)
850 {
851 // calculate room in-between
852 sal_Int32 nWidth = GetAllMarkedBoundRect().GetWidth() + 1;
853 double fStepWidth = (static_cast<double>(nWidth) - static_cast<double>(nFullLength)) / static_cast<double>(aEntryList.size() - 1);
854 double fStepStart = static_cast<double>(aEntryList[ 0 ].mnPos);
855 fStepStart += fStepWidth + static_cast<double>((aEntryList[ 0 ].mnLength + aEntryList[ 1 ].mnLength) / 2);
856
857 // move entries 1..n-1
858 for( size_t i = 1, n = aEntryList.size()-1; i < n; ++i )
859 {
860 ImpDistributeEntry& rCurr = aEntryList[ i ];
861 ImpDistributeEntry& rNext = aEntryList[ i + 1];
862 sal_Int32 nDelta = static_cast<sal_Int32>(fStepStart + 0.5) - rCurr.mnPos;
863 if( bUndo )
864 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*rCurr.mpObj));
865 rCurr.mpObj->Move(Size(nDelta, 0));
866 fStepStart += fStepWidth + static_cast<double>((rCurr.mnLength + rNext.mnLength) / 2);
867 }
868 }
869 else
870 {
871 // calculate distances
872 sal_Int32 nWidth = aEntryList[ aEntryList.size() - 1 ].mnPos - aEntryList[ 0 ].mnPos;
873 double fStepWidth = static_cast<double>(nWidth) / static_cast<double>(aEntryList.size() - 1);
874 double fStepStart = static_cast<double>(aEntryList[ 0 ].mnPos);
875 fStepStart += fStepWidth;
876
877 // move entries 1..n-1
878 for( size_t i = 1 ; i < aEntryList.size()-1 ; ++i )
879 {
880 ImpDistributeEntry& rCurr = aEntryList[ i ];
881 sal_Int32 nDelta = static_cast<sal_Int32>(fStepStart + 0.5) - rCurr.mnPos;
882 if( bUndo )
883 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*rCurr.mpObj));
884 rCurr.mpObj->Move(Size(nDelta, 0));
885 fStepStart += fStepWidth;
886 }
887 }
888
889 // clear list
890 aEntryList.clear();
891 }
892
893 if(eVer != SvxDistributeVertical::NONE)
894 {
895 // build sorted entry list
896 nFullLength = 0;
897
898 for( size_t a = 0; a < nMark; ++a )
899 {
900 SdrMark* pMark = GetSdrMarkByIndex(a);
901 ImpDistributeEntry aNew;
902
903 aNew.mpObj = pMark->GetMarkedSdrObj();
904
905 switch(eVer)
906 {
907 case SvxDistributeVertical::Top:
908 {
909 aNew.mnPos = aNew.mpObj->GetSnapRect().Top();
910 break;
911 }
912 case SvxDistributeVertical::Center:
913 {
914 aNew.mnPos = (aNew.mpObj->GetSnapRect().Bottom() + aNew.mpObj->GetSnapRect().Top()) / 2;
915 break;
916 }
917 case SvxDistributeVertical::Distance:
918 {
919 aNew.mnLength = aNew.mpObj->GetSnapRect().GetHeight() + 1;
920 nFullLength += aNew.mnLength;
921 aNew.mnPos = (aNew.mpObj->GetSnapRect().Bottom() + aNew.mpObj->GetSnapRect().Top()) / 2;
922 break;
923 }
924 case SvxDistributeVertical::Bottom:
925 {
926 aNew.mnPos = aNew.mpObj->GetSnapRect().Bottom();
927 break;
928 }
929 default: break;
930 }
931
932 itEntryList = std::find_if(aEntryList.begin(), aEntryList.end(),
933 [&aNew](const ImpDistributeEntry& rEntry) { return rEntry.mnPos >= aNew.mnPos; });
934 if ( itEntryList < aEntryList.end() )
935 aEntryList.insert( itEntryList, aNew );
936 else
937 aEntryList.push_back( aNew );
938 }
939
940 if(eVer == SvxDistributeVertical::Distance)
941 {
942 // calculate room in-between
943 sal_Int32 nHeight = GetAllMarkedBoundRect().GetHeight() + 1;
944 double fStepWidth = (static_cast<double>(nHeight) - static_cast<double>(nFullLength)) / static_cast<double>(aEntryList.size() - 1);
945 double fStepStart = static_cast<double>(aEntryList[ 0 ].mnPos);
946 fStepStart += fStepWidth + static_cast<double>((aEntryList[ 0 ].mnLength + aEntryList[ 1 ].mnLength) / 2);
947
948 // move entries 1..n-1
949 for( size_t i = 1, n = aEntryList.size()-1; i < n; ++i)
950 {
951 ImpDistributeEntry& rCurr = aEntryList[ i ];
952 ImpDistributeEntry& rNext = aEntryList[ i + 1 ];
953 sal_Int32 nDelta = static_cast<sal_Int32>(fStepStart + 0.5) - rCurr.mnPos;
954 if( bUndo )
955 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*rCurr.mpObj));
956 rCurr.mpObj->Move(Size(0, nDelta));
957 fStepStart += fStepWidth + static_cast<double>((rCurr.mnLength + rNext.mnLength) / 2);
958 }
959 }
960 else
961 {
962 // calculate distances
963 sal_Int32 nHeight = aEntryList[ aEntryList.size() - 1 ].mnPos - aEntryList[ 0 ].mnPos;
964 double fStepWidth = static_cast<double>(nHeight) / static_cast<double>(aEntryList.size() - 1);
965 double fStepStart = static_cast<double>(aEntryList[ 0 ].mnPos);
966 fStepStart += fStepWidth;
967
968 // move entries 1..n-1
969 for(size_t i = 1, n = aEntryList.size()-1; i < n; ++i)
970 {
971 ImpDistributeEntry& rCurr = aEntryList[ i ];
972 sal_Int32 nDelta = static_cast<sal_Int32>(fStepStart + 0.5) - rCurr.mnPos;
973 if( bUndo )
974 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*rCurr.mpObj));
975 rCurr.mpObj->Move(Size(0, nDelta));
976 fStepStart += fStepWidth;
977 }
978 }
979
980 // clear list
981 aEntryList.clear();
982 }
983
984 // UNDO-Comment and end of UNDO
985 mpModel->SetUndoComment(SvxResId(STR_DistributeMarkedObjectsreinterpret_cast<char const *>("STR_DistributeMarkedObjects"
"\004" u8"Distribute selected objects")
));
986
987 if( bUndo )
988 EndUndo();
989}
990
991void SdrEditView::MergeMarkedObjects(SdrMergeMode eMode)
992{
993 // #i73441# check content
994 if(!AreObjectsMarked())
995 return;
996
997 SdrMarkList aRemove;
998 SortMarkedObjects();
999
1000 const bool bUndo = IsUndoEnabled();
1001
1002 if( bUndo )
1003 BegUndo();
1004
1005 size_t nInsPos = SAL_MAX_SIZE((sal_uInt64) 0xFFFFFFFFFFFFFFFFul);
1006 const SdrObject* pAttrObj = nullptr;
1007 basegfx::B2DPolyPolygon aMergePolyPolygonA;
1008 basegfx::B2DPolyPolygon aMergePolyPolygonB;
1009
1010 SdrObjList* pInsOL = nullptr;
1011 SdrPageView* pInsPV = nullptr;
1012 bool bFirstObjectComplete(false);
1013
1014 // make sure selected objects are contour objects
1015 // since now basegfx::utils::adaptiveSubdivide() is used, it is no longer
1016 // necessary to use ConvertMarkedToPolyObj which will subdivide curves using the old
1017 // mechanisms. In a next step the polygon clipper will even be able to clip curves...
1018 // ConvertMarkedToPolyObj(true);
1019 ConvertMarkedToPathObj(true);
1020 OSL_ENSURE(AreObjectsMarked(), "no more objects selected after preparations (!)")do { if (true && (!(AreObjectsMarked()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdedtv2.cxx"
":" "1020" ": "), "%s", "no more objects selected after preparations (!)"
); } } while (false)
;
1021
1022 for(size_t a=0; a<GetMarkedObjectCount(); ++a)
1023 {
1024 SdrMark* pM = GetSdrMarkByIndex(a);
1025 SdrObject* pObj = pM->GetMarkedSdrObj();
1026
1027 if(ImpCanConvertForCombine(pObj))
1028 {
1029 if(!pAttrObj)
1030 pAttrObj = pObj;
1031
1032 nInsPos = pObj->GetOrdNum() + 1;
1033 pInsPV = pM->GetPageView();
1034 pInsOL = pObj->getParentSdrObjListFromSdrObject();
1035
1036 // #i76891# use single iteration from SJ here which works on SdrObjects and takes
1037 // groups into account by itself
1038 SdrObjListIter aIter(*pObj, SdrIterMode::DeepWithGroups);
1039
1040 while(aIter.IsMore())
1041 {
1042 SdrObject* pCandidate = aIter.Next();
1043 SdrPathObj* pPathObj = dynamic_cast<SdrPathObj*>( pCandidate );
1044 if(pPathObj)
1045 {
1046 basegfx::B2DPolyPolygon aTmpPoly(pPathObj->GetPathPoly());
1047
1048 // #i76891# unfortunately ConvertMarkedToPathObj has converted all
1049 // involved polygon data to curve segments, even if not necessary.
1050 // It is better to try to reduce to more simple polygons.
1051 aTmpPoly = basegfx::utils::simplifyCurveSegments(aTmpPoly);
1052
1053 // for each part polygon as preparation, remove self-intersections
1054 // correct orientations and get rid of possible neutral polygons.
1055 aTmpPoly = basegfx::utils::prepareForPolygonOperation(aTmpPoly);
1056
1057 if(!bFirstObjectComplete)
1058 {
1059 // #i111987# Also need to collect ORed source shape when more than
1060 // a single polygon is involved
1061 if(aMergePolyPolygonA.count())
1062 {
1063 aMergePolyPolygonA = basegfx::utils::solvePolygonOperationOr(aMergePolyPolygonA, aTmpPoly);
1064 }
1065 else
1066 {
1067 aMergePolyPolygonA = aTmpPoly;
1068 }
1069 }
1070 else
1071 {
1072 if(aMergePolyPolygonB.count())
1073 {
1074 // to topologically correctly collect the 2nd polygon
1075 // group it is necessary to OR the parts (each is seen as
1076 // XOR-FillRule polygon and they are drawn over each-other)
1077 aMergePolyPolygonB = basegfx::utils::solvePolygonOperationOr(aMergePolyPolygonB, aTmpPoly);
1078 }
1079 else
1080 {
1081 aMergePolyPolygonB = aTmpPoly;
1082 }
1083 }
1084 }
1085 }
1086
1087 // was there something added to the first polygon?
1088 if(!bFirstObjectComplete && aMergePolyPolygonA.count())
1089 {
1090 bFirstObjectComplete = true;
1091 }
1092
1093 // move object to temporary delete list
1094 aRemove.InsertEntry(SdrMark(pObj, pM->GetPageView()));
1095 }
1096 }
1097
1098 switch(eMode)
1099 {
1100 case SdrMergeMode::Merge:
1101 {
1102 // merge all contained parts (OR)
1103 aMergePolyPolygonA = basegfx::utils::solvePolygonOperationOr(aMergePolyPolygonA, aMergePolyPolygonB);
1104 break;
1105 }
1106 case SdrMergeMode::Subtract:
1107 {
1108 // Subtract B from A
1109 aMergePolyPolygonA = basegfx::utils::solvePolygonOperationDiff(aMergePolyPolygonA, aMergePolyPolygonB);
1110 break;
1111 }
1112 case SdrMergeMode::Intersect:
1113 {
1114 // AND B and A
1115 aMergePolyPolygonA = basegfx::utils::solvePolygonOperationAnd(aMergePolyPolygonA, aMergePolyPolygonB);
1116 break;
1117 }
1118 }
1119
1120 // #i73441# check insert list before taking actions
1121 if(pInsOL)
1122 {
1123 SdrPathObj* pPath = new SdrPathObj(pAttrObj->getSdrModelFromSdrObject(), OBJ_PATHFILL, aMergePolyPolygonA);
1124 ImpCopyAttributes(pAttrObj, pPath);
1125 pInsOL->InsertObject(pPath, nInsPos);
1126 if( bUndo )
1127 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath));
1128
1129 // #i124760# To have a correct selection with only the new object it is necessary to
1130 // unmark all objects first. If not doing so, there may remain invalid pointers to objects
1131 // TTTT:Not needed for aw080 (!)
1132 UnmarkAllObj(pInsPV);
1133
1134 MarkObj(pPath, pInsPV, false, true);
1135 }
1136
1137 aRemove.ForceSort();
1138 switch(eMode)
1139 {
1140 case SdrMergeMode::Merge:
1141 {
1142 SetUndoComment(
1143 SvxResId(STR_EditMergeMergePolyreinterpret_cast<char const *>("STR_EditMergeMergePoly"
"\004" u8"Merge %1")
),
1144 aRemove.GetMarkDescription());
1145 break;
1146 }
1147 case SdrMergeMode::Subtract:
1148 {
1149 SetUndoComment(
1150 SvxResId(STR_EditMergeSubstractPolyreinterpret_cast<char const *>("STR_EditMergeSubstractPoly"
"\004" u8"Subtract %1")
),
1151 aRemove.GetMarkDescription());
1152 break;
1153 }
1154 case SdrMergeMode::Intersect:
1155 {
1156 SetUndoComment(
1157 SvxResId(STR_EditMergeIntersectPolyreinterpret_cast<char const *>("STR_EditMergeIntersectPoly"
"\004" u8"Intersect %1")
),
1158 aRemove.GetMarkDescription());
1159 break;
1160 }
1161 }
1162 DeleteMarkedList(aRemove);
1163
1164 if( bUndo )
1165 EndUndo();
1166}
1167
1168void SdrEditView::EqualizeMarkedObjects(bool bWidth)
1169{
1170 const SdrMarkList& rMarkList = GetMarkedObjectList();
1171 size_t nMarked = rMarkList.GetMarkCount();
1172
1173 if (nMarked < 2)
1174 return;
1175
1176 size_t nLastSelected = 0;
1177 sal_Int64 nLastSelectedTime = rMarkList.GetMark(0)->getTimeStamp();
1178 for (size_t a = 1; a < nMarked; ++a)
1179 {
1180 sal_Int64 nCandidateTime = rMarkList.GetMark(a)->getTimeStamp();
1181 if (nCandidateTime > nLastSelectedTime)
1182 {
1183 nLastSelectedTime = nCandidateTime;
1184 nLastSelected = a;
1185 }
1186 }
1187
1188 SdrObject* pLastSelectedObj = rMarkList.GetMark(nLastSelected)->GetMarkedSdrObj();
1189 Size aLastRectSize(pLastSelectedObj->GetLogicRect().GetSize());
1190
1191 const bool bUndo = IsUndoEnabled();
1192
1193 if (bUndo)
1194 BegUndo();
1195
1196 for (size_t a = 0; a < nMarked; ++a)
1197 {
1198 if (a == nLastSelected)
1199 continue;
1200 SdrMark* pM = rMarkList.GetMark(a);
1201 SdrObject* pObj = pM->GetMarkedSdrObj();
1202 tools::Rectangle aLogicRect(pObj->GetLogicRect());
1203 Size aLogicRectSize(aLogicRect.GetSize());
1204 if (bWidth)
1205 aLogicRectSize.setWidth( aLastRectSize.Width() );
1206 else
1207 aLogicRectSize.setHeight( aLastRectSize.Height() );
1208 aLogicRect.SetSize(aLogicRectSize);
1209 if (bUndo)
1210 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
1211 pObj->SetLogicRect(aLogicRect);
1212 }
1213
1214 SetUndoComment(
1215 SvxResId(bWidth ? STR_EqualizeWidthMarkedObjectsreinterpret_cast<char const *>("STR_EqualizeWidthMarkedObjects"
"\004" u8"Equalize Width %1")
: STR_EqualizeHeightMarkedObjectsreinterpret_cast<char const *>("STR_EqualizeHeightMarkedObjects"
"\004" u8"Equalize Height %1")
),
1216 rMarkList.GetMarkDescription());
1217
1218 if (bUndo)
1219 EndUndo();
1220}
1221
1222void SdrEditView::CombineMarkedTextObjects()
1223{
1224 SdrPageView* pPageView = GetSdrPageView();
1225 if ( !pPageView || pPageView->IsLayerLocked( GetActiveLayer() ) )
1226 return;
1227
1228 bool bUndo = IsUndoEnabled();
1229
1230 // Undo-String will be set later
1231 if ( bUndo )
1232 BegUndo();
1233
1234 SdrOutliner& rDrawOutliner = getSdrModelFromSdrView().GetDrawOutliner();
1235
1236 SdrObjListIter aIter( GetMarkedObjectList(), SdrIterMode::Flat);
1237 while ( aIter.IsMore() )
1238 {
1239 SdrObject* pObj = aIter.Next();
1240 SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( pObj );
1241 const OutlinerParaObject* pOPO = pTextObj ? pTextObj->GetOutlinerParaObject() : nullptr;
1242 if ( pOPO && pTextObj->IsTextFrame()
1243 && pTextObj->GetObjIdentifier() == OBJ_TEXT // not callouts (OBJ_CAPTION)
1244 && !pTextObj->IsOutlText() // not impress presentation objects
1245 && pTextObj->GetMergedItem(XATTR_FORMTXTSTYLE).GetValue() == XFormTextStyle::NONE // not Fontwork
1246 )
1247 {
1248 // if the last paragraph does not end in paragraph-end punctuation (ignoring whitespace),
1249 // assume this text should be added to the end of the last paragraph, instead of starting a new paragraph.
1250 const sal_Int32 nPara = rDrawOutliner.GetParagraphCount();
1251 const OUString sLastPara = nPara ? rDrawOutliner.GetText( rDrawOutliner.GetParagraph( nPara - 1 ) ) : "";
1252 sal_Int32 n = sLastPara.getLength();
1253 while ( n && unicode::isWhiteSpace( sLastPara[--n] ) )
1254 ;
1255 //TODO: find way to use Locale to identify sentence final punctuation. Copied IsSentenceAtEnd() from autofmt.cxx
1256 const bool bAppend = !n || ( sLastPara[n] != '.' && sLastPara[n] != '?' && sLastPara[n] != '!' );
1257 rDrawOutliner.AddText( *pOPO, bAppend );
1258 }
1259 else
1260 {
1261 // Unmark non-textboxes, because all marked objects are deleted at the end. AdjustMarkHdl later.
1262 MarkObj(pObj, pPageView, /*bUnmark=*/true, /*bImpNoSetMarkHdl=*/true);
1263 }
1264 }
1265
1266 MarkListHasChanged();
1267 AdjustMarkHdl();
1268
1269 if ( GetMarkedObjectCount() > 1 )
1270 {
1271 SdrRectObj* pReplacement = new SdrRectObj( getSdrModelFromSdrView(), OBJ_TEXT );
1272 pReplacement->SetOutlinerParaObject( rDrawOutliner.CreateParaObject() );
1273 pReplacement->SetSnapRect( GetMarkedObjRect() );
1274
1275 const SdrInsertFlags nFlags = SdrInsertFlags::DONTMARK | SdrInsertFlags::SETDEFLAYER;
1276 if ( InsertObjectAtView( pReplacement, *pPageView, nFlags ) )
1277 DeleteMarkedObj();
1278 }
1279
1280 if ( bUndo )
1281 EndUndo();
1282
1283 return;
1284}
1285
1286void SdrEditView::CombineMarkedObjects(bool bNoPolyPoly)
1287{
1288 // #105899# Start of Combine-Undo put to front, else ConvertMarkedToPolyObj would
1289 // create a 2nd Undo-action and Undo-Comment.
1290
1291 bool bUndo = IsUndoEnabled();
1292
1293 // Undo-String will be set later
1294 if( bUndo )
1
Assuming 'bUndo' is false
2
Taking false branch
1295 BegUndo("", "", bNoPolyPoly ? SdrRepeatFunc::CombineOnePoly : SdrRepeatFunc::CombinePolyPoly);
1296
1297 // #105899# First, guarantee that all objects are converted to polyobjects,
1298 // especially for SdrGrafObj with bitmap filling this is necessary to not
1299 // lose the bitmap filling.
1300
1301 // #i12392#
1302 // ConvertMarkedToPolyObj was too strong here, it will lose quality and
1303 // information when curve objects are combined. This can be replaced by
1304 // using ConvertMarkedToPathObj without changing the previous fix.
1305
1306 // #i21250#
1307 // Instead of simply passing true as LineToArea, use bNoPolyPoly as info
1308 // if this command is a 'Combine' or a 'Connect' command. On Connect it's true.
1309 // To not concert line segments with a set line width to polygons in that case,
1310 // use this info. Do not convert LineToArea on Connect commands.
1311 // ConvertMarkedToPathObj(!bNoPolyPoly);
1312
1313 // This is used for Combine and Connect. In no case it is necessary to force
1314 // the content to curve, but it is also not good to force to polygons. Thus,
1315 // curve is the less information losing one. Remember: This place is not
1316 // used for merge.
1317 // LineToArea is never necessary, both commands are able to take over the
1318 // set line style and to display it correctly. Thus, i will use a
1319 // ConvertMarkedToPathObj with a false in any case. Only drawback is that
1320 // simple polygons will be changed to curves, but with no information loss.
1321 ConvertMarkedToPathObj(false /* bLineToArea */);
1322
1323 // continue as before
1324 basegfx::B2DPolyPolygon aPolyPolygon;
1325 SdrObjList* pCurrentOL = nullptr;
1326 SdrMarkList aRemoveBuffer;
1327
1328 SortMarkedObjects();
1329 size_t nInsPos = SAL_MAX_SIZE((sal_uInt64) 0xFFFFFFFFFFFFFFFFul);
1330 SdrObjList* pInsOL = nullptr;
1331 SdrPageView* pInsPV = nullptr;
1332 const SdrObject* pAttrObj = nullptr;
1333
1334 for(size_t a = GetMarkedObjectCount(); a; )
3
Loop condition is true. Entering loop body
1335 {
1336 --a;
1337 SdrMark* pM = GetSdrMarkByIndex(a);
1338 SdrObject* pObj = pM->GetMarkedSdrObj();
1339 SdrObjList* pThisOL = pObj->getParentSdrObjListFromSdrObject();
1340
1341 if(pCurrentOL != pThisOL)
4
Assuming 'pCurrentOL' is equal to 'pThisOL'
5
Taking false branch
1342 {
1343 pCurrentOL = pThisOL;
1344 }
1345
1346 if(ImpCanConvertForCombine(pObj))
6
Taking true branch
1347 {
1348 // remember objects to be able to copy attributes
1349 pAttrObj = pObj;
1350
1351 // unfortunately ConvertMarkedToPathObj has converted all
1352 // involved polygon data to curve segments, even if not necessary.
1353 // It is better to try to reduce to more simple polygons.
1354 basegfx::B2DPolyPolygon aTmpPoly(basegfx::utils::simplifyCurveSegments(ImpGetPolyPolygon(pObj)));
7
Calling 'SdrEditView::ImpGetPolyPolygon'
1355 aPolyPolygon.insert(0, aTmpPoly);
1356
1357 if(!pInsOL)
1358 {
1359 nInsPos = pObj->GetOrdNum() + 1;
1360 pInsPV = pM->GetPageView();
1361 pInsOL = pObj->getParentSdrObjListFromSdrObject();
1362 }
1363
1364 aRemoveBuffer.InsertEntry(SdrMark(pObj, pM->GetPageView()));
1365 }
1366 }
1367
1368 if(bNoPolyPoly)
1369 {
1370 basegfx::B2DPolygon aCombinedPolygon(ImpCombineToSinglePolygon(aPolyPolygon));
1371 aPolyPolygon.clear();
1372 aPolyPolygon.append(aCombinedPolygon);
1373 }
1374
1375 const sal_uInt32 nPolyCount(aPolyPolygon.count());
1376
1377 if (nPolyCount && pAttrObj)
1378 {
1379 SdrObjKind eKind = OBJ_PATHFILL;
1380
1381 if(nPolyCount > 1)
1382 {
1383 aPolyPolygon.setClosed(true);
1384 }
1385 else
1386 {
1387 // check for Polyline
1388 const basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(0));
1389 const sal_uInt32 nPointCount(aPolygon.count());
1390
1391 if(nPointCount <= 2)
1392 {
1393 eKind = OBJ_PATHLINE;
1394 }
1395 else
1396 {
1397 if(!aPolygon.isClosed())
1398 {
1399 const basegfx::B2DPoint aPointA(aPolygon.getB2DPoint(0));
1400 const basegfx::B2DPoint aPointB(aPolygon.getB2DPoint(nPointCount - 1));
1401 const double fDistance(basegfx::B2DVector(aPointB - aPointA).getLength());
1402 const double fJoinTolerance(10.0);
1403
1404 if(fDistance < fJoinTolerance)
1405 {
1406 aPolyPolygon.setClosed(true);
1407 }
1408 else
1409 {
1410 eKind = OBJ_PATHLINE;
1411 }
1412 }
1413 }
1414 }
1415
1416 SdrPathObj* pPath = new SdrPathObj(pAttrObj->getSdrModelFromSdrObject(), eKind, aPolyPolygon);
1417
1418 // attributes of the lowest object
1419 ImpCopyAttributes(pAttrObj, pPath);
1420
1421 // If LineStyle of pAttrObj is drawing::LineStyle_NONE force to drawing::LineStyle_SOLID to make visible.
1422 const drawing::LineStyle eLineStyle = pAttrObj->GetMergedItem(XATTR_LINESTYLE).GetValue();
1423 const drawing::FillStyle eFillStyle = pAttrObj->GetMergedItem(XATTR_FILLSTYLE).GetValue();
1424
1425 // Take fill style/closed state of pAttrObj in account when deciding to change the line style
1426 bool bIsClosedPathObj(dynamic_cast<const SdrPathObj*>( pAttrObj) != nullptr && static_cast<const SdrPathObj*>(pAttrObj)->IsClosed());
1427
1428 if(drawing::LineStyle_NONE == eLineStyle && (drawing::FillStyle_NONE == eFillStyle || !bIsClosedPathObj))
1429 {
1430 pPath->SetMergedItem(XLineStyleItem(drawing::LineStyle_SOLID));
1431 }
1432
1433 pInsOL->InsertObject(pPath,nInsPos);
1434 if( bUndo )
1435 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath));
1436
1437 // Here was a severe error: Without UnmarkAllObj, the new object was marked
1438 // additionally to the two ones which are deleted below. As long as those are
1439 // in the UNDO there is no problem, but as soon as they get deleted, the
1440 // MarkList will contain deleted objects -> GPF.
1441 UnmarkAllObj(pInsPV);
1442 MarkObj(pPath, pInsPV, false, true);
1443 }
1444
1445 // build an UndoComment from the objects actually used
1446 aRemoveBuffer.ForceSort(); // important for remove (see below)
1447 if( bUndo )
1448 SetUndoComment(SvxResId(bNoPolyPoly?STR_EditCombine_OnePolyreinterpret_cast<char const *>("STR_EditCombine_OnePoly"
"\004" u8"Combine %1")
:STR_EditCombine_PolyPolyreinterpret_cast<char const *>("STR_EditCombine_PolyPoly"
"\004" u8"Combine %1")
),aRemoveBuffer.GetMarkDescription());
1449
1450 // remove objects actually used from the list
1451 DeleteMarkedList(aRemoveBuffer);
1452 if( bUndo )
1453 EndUndo();
1454}
1455
1456
1457// Dismantle
1458
1459
1460bool SdrEditView::ImpCanDismantle(const basegfx::B2DPolyPolygon& rPpolyPolygon, bool bMakeLines)
1461{
1462 bool bCan(false);
1463 const sal_uInt32 nPolygonCount(rPpolyPolygon.count());
1464
1465 if(nPolygonCount >= 2)
1466 {
1467 // #i69172# dismantle makes sense with 2 or more polygons in a polyPolygon
1468 bCan = true;
1469 }
1470 else if(bMakeLines && 1 == nPolygonCount)
1471 {
1472 // #i69172# ..or with at least 2 edges (curves or lines)
1473 const basegfx::B2DPolygon& aPolygon(rPpolyPolygon.getB2DPolygon(0));
1474 const sal_uInt32 nPointCount(aPolygon.count());
1475
1476 if(nPointCount > 2)
1477 {
1478 bCan = true;
1479 }
1480 }
1481
1482 return bCan;
1483}
1484
1485bool SdrEditView::ImpCanDismantle(const SdrObject* pObj, bool bMakeLines)
1486{
1487 bool bOtherObjs(false); // true=objects other than PathObj's existent
1488 bool bMin1PolyPoly(false); // true=at least 1 tools::PolyPolygon with more than one Polygon existent
1489 SdrObjList* pOL = pObj->GetSubList();
1490
1491 if(pOL)
1492 {
1493 // group object -- check all members if they're PathObjs
1494 SdrObjListIter aIter(pOL, SdrIterMode::DeepNoGroups);
1495
1496 while(aIter.IsMore() && !bOtherObjs)
1497 {
1498 const SdrObject* pObj1 = aIter.Next();
1499 const SdrPathObj* pPath = dynamic_cast<const SdrPathObj*>( pObj1 );
1500
1501 if(pPath)
1502 {
1503 if(ImpCanDismantle(pPath->GetPathPoly(), bMakeLines))
1504 {
1505 bMin1PolyPoly = true;
1506 }
1507
1508 SdrObjTransformInfoRec aInfo;
1509 pObj1->TakeObjInfo(aInfo);
1510
1511 if(!aInfo.bCanConvToPath)
1512 {
1513 // happens e. g. in the case of FontWork
1514 bOtherObjs = true;
1515 }
1516 }
1517 else
1518 {
1519 bOtherObjs = true;
1520 }
1521 }
1522 }
1523 else
1524 {
1525 const SdrPathObj* pPath = dynamic_cast<const SdrPathObj*>(pObj);
1526 const SdrObjCustomShape* pCustomShape = dynamic_cast<const SdrObjCustomShape*>(pObj);
1527
1528 // #i37011#
1529 if(pPath)
1530 {
1531 if(ImpCanDismantle(pPath->GetPathPoly(),bMakeLines))
1532 {
1533 bMin1PolyPoly = true;
1534 }
1535
1536 SdrObjTransformInfoRec aInfo;
1537 pObj->TakeObjInfo(aInfo);
1538
1539 // new condition IsLine() to be able to break simple Lines
1540 if(!(aInfo.bCanConvToPath || aInfo.bCanConvToPoly) && !pPath->IsLine())
1541 {
1542 // happens e. g. in the case of FontWork
1543 bOtherObjs = true;
1544 }
1545 }
1546 else if(pCustomShape)
1547 {
1548 if(bMakeLines)
1549 {
1550 // allow break command
1551 bMin1PolyPoly = true;
1552 }
1553 }
1554 else
1555 {
1556 bOtherObjs = true;
1557 }
1558 }
1559 return bMin1PolyPoly && !bOtherObjs;
1560}
1561
1562void SdrEditView::ImpDismantleOneObject(const SdrObject* pObj, SdrObjList& rOL, size_t& rPos, SdrPageView* pPV, bool bMakeLines)
1563{
1564 const SdrPathObj* pSrcPath = dynamic_cast<const SdrPathObj*>( pObj );
1565 const SdrObjCustomShape* pCustomShape = dynamic_cast<const SdrObjCustomShape*>( pObj );
1566
1567 const bool bUndo = IsUndoEnabled();
1568
1569 if(pSrcPath)
1570 {
1571 // #i74631# redesigned due to XpolyPolygon removal and explicit constructors
1572 SdrObject* pLast = nullptr; // to be able to apply OutlinerParaObject
1573 const basegfx::B2DPolyPolygon& rPolyPolygon(pSrcPath->GetPathPoly());
1574 const sal_uInt32 nPolyCount(rPolyPolygon.count());
1575
1576 for(sal_uInt32 a(0); a < nPolyCount; a++)
1577 {
1578 const basegfx::B2DPolygon& rCandidate(rPolyPolygon.getB2DPolygon(a));
1579 const sal_uInt32 nPointCount(rCandidate.count());
1580
1581 if(!bMakeLines || nPointCount < 2)
1582 {
1583 SdrPathObj* pPath = new SdrPathObj(
1584 pSrcPath->getSdrModelFromSdrObject(),
1585 static_cast<SdrObjKind>(pSrcPath->GetObjIdentifier()),
1586 basegfx::B2DPolyPolygon(rCandidate));
1587 ImpCopyAttributes(pSrcPath, pPath);
1588 pLast = pPath;
1589 rOL.InsertObject(pPath, rPos);
1590 if( bUndo )
1591 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath, true));
1592 MarkObj(pPath, pPV, false, true);
1593 rPos++;
1594 }
1595 else
1596 {
1597 const sal_uInt32 nLoopCount(rCandidate.isClosed() ? nPointCount : nPointCount - 1);
1598
1599 for(sal_uInt32 b(0); b < nLoopCount; b++)
1600 {
1601 SdrObjKind eKind(OBJ_PLIN);
1602 basegfx::B2DPolygon aNewPolygon;
1603 const sal_uInt32 nNextIndex((b + 1) % nPointCount);
1604
1605 aNewPolygon.append(rCandidate.getB2DPoint(b));
1606
1607 if(rCandidate.areControlPointsUsed())
1608 {
1609 aNewPolygon.appendBezierSegment(
1610 rCandidate.getNextControlPoint(b),
1611 rCandidate.getPrevControlPoint(nNextIndex),
1612 rCandidate.getB2DPoint(nNextIndex));
1613 eKind = OBJ_PATHLINE;
1614 }
1615 else
1616 {
1617 aNewPolygon.append(rCandidate.getB2DPoint(nNextIndex));
1618 }
1619
1620 SdrPathObj* pPath = new SdrPathObj(
1621 pSrcPath->getSdrModelFromSdrObject(),
1622 eKind,
1623 basegfx::B2DPolyPolygon(aNewPolygon));
1624 ImpCopyAttributes(pSrcPath, pPath);
1625 pLast = pPath;
1626 rOL.InsertObject(pPath, rPos);
1627 if( bUndo )
1628 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pPath, true));
1629 MarkObj(pPath, pPV, false, true);
1630 rPos++;
1631 }
1632 }
1633 }
1634
1635 if(pLast && pSrcPath->GetOutlinerParaObject())
1636 {
1637 pLast->SetOutlinerParaObject(std::make_unique<OutlinerParaObject>(*pSrcPath->GetOutlinerParaObject()));
1638 }
1639 }
1640 else if(pCustomShape)
1641 {
1642 if(bMakeLines)
1643 {
1644 // break up custom shape
1645 const SdrObject* pReplacement = pCustomShape->GetSdrObjectFromCustomShape();
1646
1647 if(pReplacement)
1648 {
1649 SdrObject* pCandidate(pReplacement->CloneSdrObject(pReplacement->getSdrModelFromSdrObject()));
1650 DBG_ASSERT(pCandidate, "SdrEditView::ImpDismantleOneObject: Could not clone SdrObject (!)")do { if (true && (!(pCandidate))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdedtv2.cxx"
":" "1650" ": "), "%s", "SdrEditView::ImpDismantleOneObject: Could not clone SdrObject (!)"
); } } while (false)
;
1651
1652 if(pCustomShape->GetMergedItem(SDRATTR_SHADOW).GetValue())
1653 {
1654 if(dynamic_cast<const SdrObjGroup*>( pReplacement) != nullptr)
1655 {
1656 pCandidate->SetMergedItem(makeSdrShadowItem(true));
1657 }
1658 }
1659
1660 rOL.InsertObject(pCandidate, rPos);
1661 if( bUndo )
1662 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pCandidate, true));
1663 MarkObj(pCandidate, pPV, false, true);
1664
1665 if(pCustomShape->HasText() && !pCustomShape->IsTextPath())
1666 {
1667 // #i37011# also create a text object and add at rPos + 1
1668 SdrObject* pTextObj = SdrObjFactory::MakeNewObject(
1669 pCustomShape->getSdrModelFromSdrObject(),
1670 pCustomShape->GetObjInventor(),
1671 OBJ_TEXT);
1672
1673 // Copy text content
1674 OutlinerParaObject* pParaObj = pCustomShape->GetOutlinerParaObject();
1675 if(pParaObj)
1676 {
1677 pTextObj->NbcSetOutlinerParaObject(std::make_unique<OutlinerParaObject>(*pParaObj));
1678 }
1679
1680 // copy all attributes
1681 SfxItemSet aTargetItemSet(pCustomShape->GetMergedItemSet());
1682
1683 // clear fill and line style
1684 aTargetItemSet.Put(XLineStyleItem(drawing::LineStyle_NONE));
1685 aTargetItemSet.Put(XFillStyleItem(drawing::FillStyle_NONE));
1686
1687 // get the text bounds and set at text object
1688 tools::Rectangle aTextBounds = pCustomShape->GetSnapRect();
1689 if(pCustomShape->GetTextBounds(aTextBounds))
1690 {
1691 pTextObj->SetSnapRect(aTextBounds);
1692 }
1693
1694 // if rotated, copy GeoStat, too.
1695 const GeoStat& rSourceGeo = pCustomShape->GetGeoStat();
1696 if(rSourceGeo.nRotationAngle)
1697 {
1698 pTextObj->NbcRotate(
1699 pCustomShape->GetSnapRect().Center(), rSourceGeo.nRotationAngle,
1700 rSourceGeo.nSin, rSourceGeo.nCos);
1701 }
1702
1703 // set modified ItemSet at text object
1704 pTextObj->SetMergedItemSet(aTargetItemSet);
1705
1706 // insert object
1707 rOL.InsertObject(pTextObj, rPos + 1);
1708 if( bUndo )
1709 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pTextObj, true));
1710 MarkObj(pTextObj, pPV, false, true);
1711 }
1712 }
1713 }
1714 }
1715}
1716
1717void SdrEditView::DismantleMarkedObjects(bool bMakeLines)
1718{
1719 // temporary MarkList
1720 SdrMarkList aRemoveBuffer;
1721
1722 SortMarkedObjects();
1723
1724 const bool bUndo = IsUndoEnabled();
1725
1726 if( bUndo )
1727 {
1728 // comment is constructed later
1729 BegUndo("", "", bMakeLines ? SdrRepeatFunc::DismantleLines : SdrRepeatFunc::DismantlePolys);
1730 }
1731
1732 SdrObjList* pOL0=nullptr;
1733 for (size_t nm=GetMarkedObjectCount(); nm>0;) {
1734 --nm;
1735 SdrMark* pM=GetSdrMarkByIndex(nm);
1736 SdrObject* pObj=pM->GetMarkedSdrObj();
1737 SdrPageView* pPV=pM->GetPageView();
1738 SdrObjList* pOL=pObj->getParentSdrObjListFromSdrObject();
1739 if (pOL!=pOL0) { pOL0=pOL; pObj->GetOrdNum(); } // make sure OrdNums are correct!
1740 if (ImpCanDismantle(pObj,bMakeLines)) {
1741 aRemoveBuffer.InsertEntry(SdrMark(pObj,pM->GetPageView()));
1742 const size_t nPos0=pObj->GetOrdNumDirect();
1743 size_t nPos=nPos0+1;
1744 SdrObjList* pSubList=pObj->GetSubList();
1745 if (pSubList!=nullptr && !pObj->Is3DObj()) {
1746 SdrObjListIter aIter(pSubList,SdrIterMode::DeepNoGroups);
1747 while (aIter.IsMore()) {
1748 const SdrObject* pObj1=aIter.Next();
1749 ImpDismantleOneObject(pObj1,*pOL,nPos,pPV,bMakeLines);
1750 }
1751 } else {
1752 ImpDismantleOneObject(pObj,*pOL,nPos,pPV,bMakeLines);
1753 }
1754 if( bUndo )
1755 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj,true));
1756 pOL->RemoveObject(nPos0);
1757
1758 if( !bUndo )
1759 SdrObject::Free(pObj);
1760 }
1761 }
1762
1763 if( bUndo )
1764 {
1765 // construct UndoComment from objects actually used
1766 SetUndoComment(SvxResId(bMakeLines?STR_EditDismantle_Linesreinterpret_cast<char const *>("STR_EditDismantle_Lines"
"\004" u8"Split %1")
:STR_EditDismantle_Polysreinterpret_cast<char const *>("STR_EditDismantle_Polys"
"\004" u8"Split %1")
),aRemoveBuffer.GetMarkDescription());
1767 // remove objects actually used from the list
1768 EndUndo();
1769 }
1770}
1771
1772
1773// Group
1774
1775
1776void SdrEditView::GroupMarked()
1777{
1778 if (!AreObjectsMarked())
1779 return;
1780
1781 SortMarkedObjects();
1782
1783 const bool bUndo = IsUndoEnabled();
1784 if( bUndo )
1785 {
1786 BegUndo(SvxResId(STR_EditGroupreinterpret_cast<char const *>("STR_EditGroup" "\004" u8"Group %1"
)
),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::Group);
1787
1788 for(size_t nm = GetMarkedObjectCount(); nm>0; )
1789 {
1790 // add UndoActions for all affected objects
1791 --nm;
1792 SdrMark* pM=GetSdrMarkByIndex(nm);
1793 SdrObject* pObj = pM->GetMarkedSdrObj();
1794 AddUndoActions( CreateConnectorUndo( *pObj ) );
1795 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoRemoveObject( *pObj ));
1796 }
1797 }
1798
1799 SdrMarkList aNewMark;
1800 SdrPageView* pPV = GetSdrPageView();
1801
1802 if(pPV)
1803 {
1804 SdrObjList* pCurrentLst=pPV->GetObjList();
1805 SdrObjList* pSrcLst=pCurrentLst;
1806 SdrObjList* pSrcLst0=pSrcLst;
1807 // make sure OrdNums are correct
1808 if (pSrcLst->IsObjOrdNumsDirty())
1809 pSrcLst->RecalcObjOrdNums();
1810 SdrObject* pGrp=nullptr;
1811 SdrObjList* pDstLst=nullptr;
1812 // if all selected objects come from foreign object lists.
1813 // the group object is the last one in the list.
1814 size_t nInsPos=pSrcLst->GetObjCount();
1815 bool bNeedInsPos=true;
1816 for (size_t nm=GetMarkedObjectCount(); nm>0;)
1817 {
1818 --nm;
1819 SdrMark* pM=GetSdrMarkByIndex(nm);
1820 if (pM->GetPageView()==pPV)
1821 {
1822 SdrObject* pObj=pM->GetMarkedSdrObj();
1823 if (nullptr==pGrp)
1824 {
1825 pGrp = new SdrObjGroup(pObj->getSdrModelFromSdrObject());
1826 pDstLst=pGrp->GetSubList();
1827 DBG_ASSERT(pDstLst!=nullptr,"Alleged group object doesn't return object list.")do { if (true && (!(pDstLst!=nullptr))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdedtv2.cxx"
":" "1827" ": "), "%s", "Alleged group object doesn't return object list."
); } } while (false)
;
1828 }
1829 pSrcLst=pObj->getParentSdrObjListFromSdrObject();
1830 if (pSrcLst!=pSrcLst0)
1831 {
1832 if (pSrcLst->IsObjOrdNumsDirty())
1833 pSrcLst->RecalcObjOrdNums();
1834 }
1835 bool bForeignList=pSrcLst!=pCurrentLst;
1836 if (!bForeignList && bNeedInsPos)
1837 {
1838 nInsPos=pObj->GetOrdNum(); // this way, all ObjOrdNum of the page are set
1839 nInsPos++;
1840 bNeedInsPos=false;
1841 }
1842 pSrcLst->RemoveObject(pObj->GetOrdNumDirect());
1843 if (!bForeignList)
1844 nInsPos--; // correct InsertPos
1845 pDstLst->InsertObject(pObj,0);
1846 GetMarkedObjectListWriteAccess().DeleteMark(nm);
1847 pSrcLst0=pSrcLst;
1848 }
1849 }
1850 if (pGrp!=nullptr)
1851 {
1852 aNewMark.InsertEntry(SdrMark(pGrp,pPV));
1853 const size_t nCount=pDstLst->GetObjCount();
1854 pCurrentLst->InsertObject(pGrp,nInsPos);
1855 if( bUndo )
1856 {
1857 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pGrp,true)); // no recalculation!
1858 for (size_t no=0; no<nCount; ++no)
1859 {
1860 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoInsertObject(*pDstLst->GetObj(no)));
1861 }
1862 }
1863 }
1864 }
1865 GetMarkedObjectListWriteAccess().Merge(aNewMark);
1866 MarkListHasChanged();
1867
1868 if( bUndo )
1869 EndUndo();
1870}
1871
1872
1873// Ungroup
1874
1875
1876void SdrEditView::UnGroupMarked()
1877{
1878 SdrMarkList aNewMark;
1879
1880 const bool bUndo = IsUndoEnabled();
1881 if( bUndo )
1882 BegUndo("", "", SdrRepeatFunc::Ungroup);
1883
1884 size_t nCount=0;
1885 OUString aName1;
1886 OUString aName;
1887 bool bNameOk=false;
1888 for (size_t nm=GetMarkedObjectCount(); nm>0;) {
1889 --nm;
1890 SdrMark* pM=GetSdrMarkByIndex(nm);
1891 SdrObject* pGrp=pM->GetMarkedSdrObj();
1892 SdrObjList* pSrcLst=pGrp->GetSubList();
1893 if (pSrcLst!=nullptr) {
1894 nCount++;
1895 if (nCount==1) {
1896 aName = pGrp->TakeObjNameSingul(); // retrieve name of group
1897 aName1 = pGrp->TakeObjNamePlural(); // retrieve name of group
1898 bNameOk=true;
1899 } else {
1900 if (nCount==2) aName=aName1; // set plural name
1901 if (bNameOk) {
1902 OUString aStr(pGrp->TakeObjNamePlural()); // retrieve name of group
1903
1904 if (aStr != aName)
1905 bNameOk = false;
1906 }
1907 }
1908 size_t nDstCnt=pGrp->GetOrdNum();
1909 SdrObjList* pDstLst=pM->GetPageView()->GetObjList();
1910
1911 // FIRST move contained objects to parent of group, so that
1912 // the contained objects are NOT migrated to the UNDO-ItemPool
1913 // when AddUndo(new SdrUndoDelObj(*pGrp)) is called.
1914 const size_t nObjCount=pSrcLst->GetObjCount();
1915
1916 if( bUndo )
1917 {
1918 for (size_t no=nObjCount; no>0;)
1919 {
1920 no--;
1921 SdrObject* pObj=pSrcLst->GetObj(no);
1922 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoRemoveObject(*pObj));
1923 }
1924 }
1925 for (size_t no=0; no<nObjCount; ++no)
1926 {
1927 SdrObject* pObj=pSrcLst->RemoveObject(0);
1928 pDstLst->InsertObject(pObj,nDstCnt);
1929 if( bUndo )
1930 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoInsertObject(*pObj,true));
1931 nDstCnt++;
1932 // No SortCheck when inserting into MarkList, because that would
1933 // provoke a RecalcOrdNums() each time because of pObj->GetOrdNum():
1934 aNewMark.InsertEntry(SdrMark(pObj,pM->GetPageView()),false);
1935 }
1936
1937 if( bUndo )
1938 {
1939 // Now it is safe to add the delete-UNDO which triggers the
1940 // MigrateItemPool now only for itself, not for the sub-objects.
1941 // nDstCnt is right, because previous inserts move group
1942 // object deeper and increase nDstCnt.
1943 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pGrp));
1944 }
1945 pDstLst->RemoveObject(nDstCnt);
1946
1947 if( !bUndo )
1948 SdrObject::Free(pGrp);
1949
1950 GetMarkedObjectListWriteAccess().DeleteMark(nm);
1951 }
1952 }
1953 if (nCount!=0)
1954 {
1955 if (!bNameOk)
1956 aName=SvxResId(STR_ObjNamePluralGRUPreinterpret_cast<char const *>("STR_ObjNamePluralGRUP" "\004"
u8"Group objects")
); // Use the term "Group Objects," if different objects are grouped.
1957 SetUndoComment(SvxResId(STR_EditUngroupreinterpret_cast<char const *>("STR_EditUngroup" "\004"
u8"Ungroup %1")
),aName);
1958 }
1959
1960 if( bUndo )
1961 EndUndo();
1962
1963 if (nCount!=0)
1964 {
1965 GetMarkedObjectListWriteAccess().Merge(aNewMark,true); // Because of the sorting above, aNewMark is reversed
1966 MarkListHasChanged();
1967 }
1968}
1969
1970
1971// ConvertToPoly
1972
1973
1974SdrObject* SdrEditView::ImpConvertOneObj(SdrObject* pObj, bool bPath, bool bLineToArea)
1975{
1976 SdrObjectUniquePtr pNewObj = pObj->ConvertToPolyObj(bPath, bLineToArea);
1977 if (pNewObj)
1978 {
1979 SdrObjList* pOL = pObj->getParentSdrObjListFromSdrObject();
1980 const bool bUndo = IsUndoEnabled();
1981 if( bUndo )
1982 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoReplaceObject(*pObj,*pNewObj));
1983
1984 pOL->ReplaceObject(pNewObj.get(), pObj->GetOrdNum());
1985
1986 if( !bUndo )
1987 SdrObject::Free(pObj);
1988 }
1989 return pNewObj.release();
1990}
1991
1992void SdrEditView::ImpConvertTo(bool bPath, bool bLineToArea)
1993{
1994 if (!AreObjectsMarked()) return;
1995
1996 bool bMrkChg = false;
1997 const size_t nMarkCount=GetMarkedObjectCount();
1998 const char* pDscrID = nullptr;
1999 if(bLineToArea)
2000 {
2001 if(nMarkCount == 1)
2002 pDscrID = STR_EditConvToContourreinterpret_cast<char const *>("STR_EditConvToContour" "\004"
u8"Convert %1 to contour")
;
2003 else
2004 pDscrID = STR_EditConvToContoursreinterpret_cast<char const *>("STR_EditConvToContours"
"\004" u8"Convert %1 to contours")
;
2005
2006 BegUndo(SvxResId(pDscrID), GetDescriptionOfMarkedObjects());
2007 }
2008 else
2009 {
2010 if (bPath) {
2011 if (nMarkCount==1) pDscrID=STR_EditConvToCurvereinterpret_cast<char const *>("STR_EditConvToCurve" "\004"
u8"Convert %1 to curve")
;
2012 else pDscrID=STR_EditConvToCurvesreinterpret_cast<char const *>("STR_EditConvToCurves" "\004"
u8"Convert %1 to curves")
;
2013 BegUndo(SvxResId(pDscrID),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::ConvertToPath);
2014 } else {
2015 if (nMarkCount==1) pDscrID=STR_EditConvToPolyreinterpret_cast<char const *>("STR_EditConvToPoly" "\004"
u8"Convert %1 to polygon")
;
2016 else pDscrID=STR_EditConvToPolysreinterpret_cast<char const *>("STR_EditConvToPolys" "\004"
u8"Convert %1 to polygons")
;
2017 BegUndo(SvxResId(pDscrID),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::ConvertToPoly);
2018 }
2019 }
2020 for (size_t nm=nMarkCount; nm>0;) {
2021 --nm;
2022 SdrMark* pM=GetSdrMarkByIndex(nm);
2023 SdrObject* pObj=pM->GetMarkedSdrObj();
2024 SdrPageView* pPV=pM->GetPageView();
2025 if (pObj->IsGroupObject() && !pObj->Is3DObj()) {
2026 SdrObject* pGrp=pObj;
2027 SdrObjListIter aIter(*pGrp, SdrIterMode::DeepNoGroups);
2028 while (aIter.IsMore()) {
2029 pObj=aIter.Next();
2030 ImpConvertOneObj(pObj,bPath,bLineToArea);
2031 }
2032 } else {
2033 SdrObject* pNewObj=ImpConvertOneObj(pObj,bPath,bLineToArea);
2034 if (pNewObj!=nullptr) {
2035 bMrkChg=true;
2036 GetMarkedObjectListWriteAccess().ReplaceMark(SdrMark(pNewObj,pPV),nm);
2037 }
2038 }
2039 }
2040 EndUndo();
2041 if (bMrkChg)
2042 {
2043 AdjustMarkHdl();
2044 MarkListHasChanged();
2045 }
2046}
2047
2048void SdrEditView::ConvertMarkedToPathObj(bool bLineToArea)
2049{
2050 ImpConvertTo(true, bLineToArea);
2051}
2052
2053void SdrEditView::ConvertMarkedToPolyObj()
2054{
2055 ImpConvertTo(false, false/*bLineToArea*/);
2056}
2057
2058namespace
2059{
2060 GDIMetaFile GetMetaFile(SdrGrafObj const * pGraf)
2061 {
2062 if (pGraf->HasGDIMetaFile())
2063 return pGraf->GetTransformedGraphic(SdrGrafObjTransformsAttrs::MIRROR).GetGDIMetaFile();
2064 assert(pGraf->isEmbeddedVectorGraphicData())(static_cast <bool> (pGraf->isEmbeddedVectorGraphicData
()) ? void (0) : __assert_fail ("pGraf->isEmbeddedVectorGraphicData()"
, "/home/maarten/src/libreoffice/core/svx/source/svdraw/svdedtv2.cxx"
, 2064, __extension__ __PRETTY_FUNCTION__))
;
2065 return pGraf->getMetafileFromEmbeddedVectorGraphicData();
2066 }
2067}
2068
2069// Metafile Import
2070void SdrEditView::DoImportMarkedMtf(SvdProgressInfo *pProgrInfo)
2071{
2072 const bool bUndo = IsUndoEnabled();
2073
2074 if( bUndo )
2075 BegUndo("", "", SdrRepeatFunc::ImportMtf);
2076
2077 SortMarkedObjects();
2078 SdrMarkList aForTheDescription;
2079 SdrMarkList aNewMarked;
2080 for (size_t nm =GetMarkedObjectCount(); nm > 0; )
2081 {
2082 // create Undo objects for all new objects
2083 // check for cancellation between the metafiles
2084 if (pProgrInfo != nullptr)
2085 {
2086 pProgrInfo->SetNextObject();
2087 if (!pProgrInfo->ReportActions(0))
2088 break;
2089 }
2090
2091 --nm;
2092 SdrMark* pM=GetSdrMarkByIndex(nm);
2093 SdrObject* pObj=pM->GetMarkedSdrObj();
2094 SdrPageView* pPV=pM->GetPageView();
2095 SdrObjList* pOL=pObj->getParentSdrObjListFromSdrObject();
2096 const size_t nInsPos=pObj->GetOrdNum()+1;
2097 size_t nInsCnt=0;
2098 tools::Rectangle aLogicRect;
2099
2100 SdrGrafObj* pGraf = dynamic_cast<SdrGrafObj*>( pObj );
2101 if (pGraf != nullptr)
2102 {
2103 Graphic aGraphic = pGraf->GetGraphic();
2104 auto const & pVectorGraphicData = aGraphic.getVectorGraphicData();
2105
2106 if (pVectorGraphicData && pVectorGraphicData->getVectorGraphicDataType() == VectorGraphicDataType::Pdf)
2107 {
2108#if HAVE_FEATURE_PDFIUM1
2109 aLogicRect = pGraf->GetLogicRect();
2110 ImpSdrPdfImport aFilter(*mpModel, pObj->GetLayer(), aLogicRect, aGraphic);
2111 if (aGraphic.getPageNumber() < aFilter.GetPageCount())
2112 {
2113 nInsCnt = aFilter.DoImport(*pOL, nInsPos, aGraphic.getPageNumber(), pProgrInfo);
2114 }
2115#endif // HAVE_FEATURE_PDFIUM
2116 }
2117 else if (pGraf->HasGDIMetaFile() || pGraf->isEmbeddedVectorGraphicData() )
2118 {
2119 GDIMetaFile aMetaFile(GetMetaFile(pGraf));
2120 if (aMetaFile.GetActionSize())
2121 {
2122 aLogicRect = pGraf->GetLogicRect();
2123 ImpSdrGDIMetaFileImport aFilter(*mpModel, pObj->GetLayer(), aLogicRect);
2124 nInsCnt = aFilter.DoImport(aMetaFile, *pOL, nInsPos, pProgrInfo);
2125 }
2126 }
2127 }
2128
2129 SdrOle2Obj* pOle2 = dynamic_cast<SdrOle2Obj*>(pObj);
2130 if (pOle2 != nullptr && pOle2->GetGraphic())
2131 {
2132 aLogicRect = pOle2->GetLogicRect();
2133 ImpSdrGDIMetaFileImport aFilter(*mpModel, pObj->GetLayer(), aLogicRect);
2134 nInsCnt = aFilter.DoImport(pOle2->GetGraphic()->GetGDIMetaFile(), *pOL, nInsPos, pProgrInfo);
2135 }
2136
2137 if (nInsCnt != 0)
2138 {
2139 // transformation
2140 GeoStat aGeoStat(pGraf ? pGraf->GetGeoStat() : pOle2->GetGeoStat());
2141 size_t nObj = nInsPos;
2142
2143 if (aGeoStat.nShearAngle)
2144 aGeoStat.RecalcTan();
2145
2146 if (aGeoStat.nRotationAngle)
2147 aGeoStat.RecalcSinCos();
2148
2149 for (size_t i = 0; i < nInsCnt; i++)
2150 {
2151 if (bUndo)
2152 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pOL->GetObj(nObj)));
2153
2154 // update new MarkList
2155 SdrObject* pCandidate = pOL->GetObj(nObj);
2156
2157 // apply original transformation
2158 if (aGeoStat.nShearAngle)
2159 pCandidate->NbcShear(aLogicRect.TopLeft(), aGeoStat.nShearAngle, aGeoStat.nTan, false);
2160
2161 if (aGeoStat.nRotationAngle)
2162 pCandidate->NbcRotate(aLogicRect.TopLeft(), aGeoStat.nRotationAngle, aGeoStat.nSin, aGeoStat.nCos);
2163
2164 SdrMark aNewMark(pCandidate, pPV);
2165 aNewMarked.InsertEntry(aNewMark);
2166
2167 nObj++;
2168 }
2169
2170 aForTheDescription.InsertEntry(*pM);
2171
2172 if (bUndo)
2173 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj));
2174
2175 // remove object from selection and delete
2176 GetMarkedObjectListWriteAccess().DeleteMark(TryToFindMarkedObject(pObj));
2177 pOL->RemoveObject(nInsPos-1);
2178
2179 if (!bUndo)
2180 SdrObject::Free(pObj);
2181 }
2182 }
2183
2184 if (aNewMarked.GetMarkCount())
2185 {
2186 // create new selection
2187 for (size_t a = 0; a < aNewMarked.GetMarkCount(); ++a)
2188 {
2189 GetMarkedObjectListWriteAccess().InsertEntry(*aNewMarked.GetMark(a));
2190 }
2191
2192 SortMarkedObjects();
2193 }
2194
2195 if (bUndo)
2196 {
2197 SetUndoComment(SvxResId(STR_EditImportMtfreinterpret_cast<char const *>("STR_EditImportMtf" "\004"
u8"Split %1")
),aForTheDescription.GetMarkDescription());
2198 EndUndo();
2199 }
2200}
2201
2202/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/svx/svdobj.hxx

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#ifndef INCLUDED_SVX_SVDOBJ_HXX
21#define INCLUDED_SVX_SVDOBJ_HXX
22
23#include <memory>
24#include <com/sun/star/uno/Any.hxx>
25#include <cppuhelper/weakref.hxx>
26#include <rtl/ustring.hxx>
27#include <vcl/outdev.hxx>
28#include <svl/lstner.hxx>
29#include <svl/poolitem.hxx>
30#include <svl/typedwhich.hxx>
31#include <svx/DiagramDataInterface.hxx>
32#include <svx/svdtypes.hxx>
33#include <svx/svxdllapi.h>
34#include <svx/shapeproperty.hxx>
35#include <tools/link.hxx>
36#include <tools/weakbase.h>
37#include <tools/gen.hxx>
38#include <osl/diagnose.h>
39#include <typeinfo>
40
41#include <unordered_set>
42
43class SfxBroadcaster;
44class AutoTimer;
45class OutlinerParaObject;
46class Outliner;
47class SdrOutliner;
48class SdrDragStat;
49class SdrHdl;
50class SdrHdlList;
51class SdrItemPool;
52class SdrModel;
53class SdrObjList;
54class SdrObject;
55class SdrPage;
56class SdrPageView;
57class SdrView;
58class SfxItemSet;
59class SfxGrabBagItem;
60class SfxSetItem;
61class SfxStyleSheet;
62class SfxUndoAction;
63class XFillAttrSetItem;
64class XLineAttrSetItem;
65class SfxItemPool;
66namespace tools { class PolyPolygon; }
67class SfxPoolItem;
68class SdrVirtObj;
69class SdrDragView;
70class SdrObjUserDataList;
71class SdrObjPlusData;
72class SdrGluePoint;
73class SdrGluePointList;
74class SdrLayerIDSet;
75class Fraction;
76enum class PointerStyle;
77
78namespace basegfx
79{
80 class B2DPoint;
81 class B2DPolyPolygon;
82 class B2DHomMatrix;
83}
84
85namespace sdr
86{
87 namespace properties
88 {
89 class BaseProperties;
90 }
91
92 class ObjectUser;
93}
94
95namespace sdr
96{
97 namespace contact
98 {
99 class ViewContact;
100 } // end of namespace contact
101}
102
103namespace svx
104{
105 class PropertyChangeNotifier;
106}
107
108class SvxShape;
109class SdrObject;
110struct SVXCORE_DLLPUBLIC__attribute__ ((visibility("default"))) SdrObjectFreeOp;
111
112// helper for constructing std::unique_ptr for SdrObjects where a
113// deleter is needed - here, SdrObject::Free needs to be used.
114typedef std::unique_ptr< SdrObject, SdrObjectFreeOp > SdrObjectUniquePtr;
115
116enum SdrObjKind {
117 OBJ_NONE = 0, /// abstract object (SdrObject)
118 OBJ_GRUP = 1, /// object group
119 OBJ_LINE = 2, /// line
120 OBJ_RECT = 3, /// rectangle (round corners optional)
121 OBJ_CIRC = 4, /// circle, ellipse
122 OBJ_SECT = 5, /// circle section
123 OBJ_CARC = 6, /// circle arc
124 OBJ_CCUT = 7, /// circle cut
125 OBJ_POLY = 8, /// polygon, PolyPolygon
126 OBJ_PLIN = 9, /// PolyLine
127 OBJ_PATHLINE =10, /// open Bezier-curve
128 OBJ_PATHFILL =11, /// closed Bezier-curve
129 OBJ_FREELINE =12, /// open free-hand line
130 OBJ_FREEFILL =13, /// closed free-hand line
131 OBJ_SPLNLINE =14, /// natural cubic Spline (ni)
132 OBJ_SPLNFILL =15, /// periodic cubic Spline (ni)
133 OBJ_TEXT =16, /// text object
134 OBJ_TITLETEXT =20, /// TitleText, special text object for StarDraw
135 OBJ_OUTLINETEXT=21, /// OutlineText, special text object for StarDraw
136 OBJ_GRAF =22, /// foreign graphic (StarView Graphic)
137 OBJ_OLE2 =23, /// OLE object
138 OBJ_EDGE =24, /// connector object
139 OBJ_CAPTION =25, /// caption object
140 OBJ_PATHPOLY =26, /// Polygon/PolyPolygon represented by SdrPathObj
141 OBJ_PATHPLIN =27, /// Polyline represented by SdrPathObj
142 OBJ_PAGE =28, /// object that represents a SdrPage
143 OBJ_MEASURE =29, /// measurement object
144 OBJ_FRAME =31, /// continuously activated OLE (PlugIn-Frame or similar)
145 OBJ_UNO =32, /// Universal Network Object packed into SvDraw object
146 OBJ_CUSTOMSHAPE=33, /// custom shape
147 OBJ_MEDIA =34, /// media shape
148 OBJ_TABLE =35, /// table
149 OBJ_MAXI
150};
151
152enum class SdrInventor : sal_uInt32 {
153 Unknown = 0,
154 BasicDialog = sal_uInt32( 'D' | ('L' << 8) | ('G' << 16) | ('1' << 24) ),
155 Default = sal_uInt32( 'S' | ('V' << 8) | ('D' << 16) | ('r' << 24) ),
156 E3d = sal_uInt32( 'E' | ('3' << 8) | ('D' << 16) | ('1' << 24) ),
157 FmForm = sal_uInt32( 'F' | ('M' << 8) | ('0' << 16) | ('1' << 24) ),
158 IMap = sal_uInt32( 'I' | ('M' << 8) | ('A' << 16) | ('P' << 24) ),
159 ReportDesign = sal_uInt32( 'R' | ('P' << 8) | ('T' << 16) | ('1' << 24) ),
160 ScOrSwDraw = sal_uInt32( 'S' | ('C' << 8) | ('3' << 16) | ('0' << 24) ), // Used in sc/ and sw/
161 SgaImap = sal_uInt32( 'S' | ('D' << 8) | ('U' << 16) | ('D' << 24) ),
162 StarDrawUserData = sal_uInt32( 'S' | ('D' << 8) | ('U' << 16) | ('D' << 24) ),
163 Swg = sal_uInt32( 'S' | ('W' << 8) | ('G' << 16) ),
164};
165
166enum class SdrUserCallType {
167 MoveOnly, // only moved, size unchanged
168 Resize, // size and maybe position changed
169 ChangeAttr, // attribute changed. Eventually new size, because of line width
170 Delete, // object is going to be deleted soon, no attributes anymore
171 Inserted, // inserted into an object list (e.g. Page)
172 Removed, // removed from an object list
173 ChildMoveOnly, // a child within a group has changed
174 ChildResize, // a child within a group has changed
175 ChildChangeAttr, // a child within a group has changed
176 ChildDelete, // a child within a group has changed
177 ChildInserted, // a child within a group has changed
178 ChildRemoved // a child within a group has changed
179};
180
181class SVXCORE_DLLPUBLIC__attribute__ ((visibility("default"))) SdrObjUserCall
182{
183public:
184 virtual ~SdrObjUserCall();
185 virtual void Changed(const SdrObject& rObj, SdrUserCallType eType, const tools::Rectangle& rOldBoundRect);
186};
187
188class SVXCORE_DLLPUBLIC__attribute__ ((visibility("default"))) SdrObjMacroHitRec
189{
190public:
191 Point aPos;
192 const SdrLayerIDSet* pVisiLayer;
193 const SdrPageView* pPageView;
194 sal_uInt16 nTol;
195
196 SdrObjMacroHitRec();
197};
198
199/**
200 * User data of a drawing object, e.g. application specific data.
201 * Every drawing object can have an arbitrary amount of such records (SV list).
202 * Whoever wants to save data here, must inherit from this and set a corresponding link in the factory.
203 */
204class SVXCORE_DLLPUBLIC__attribute__ ((visibility("default"))) SdrObjUserData
205{
206 SdrInventor nInventor;
207 sal_uInt16 nIdentifier;
208
209 void operator=(const SdrObjUserData& rData) = delete;
210 bool operator==(const SdrObjUserData& rData) const = delete;
211 bool operator!=(const SdrObjUserData& rData) const = delete;
212
213public:
214 SdrObjUserData(SdrInventor nInv, sal_uInt16 nId);
215 SdrObjUserData(const SdrObjUserData& rData);
216 virtual ~SdrObjUserData();
217
218 virtual std::unique_ptr<SdrObjUserData> Clone(SdrObject* pObj1) const = 0; // #i71039# NULL -> 0
219 SdrInventor GetInventor() const { return nInventor;}
220 sal_uInt16 GetId() const { return nIdentifier;}
221};
222
223/**
224 * All geometrical data of an arbitrary object for use in undo/redo
225 */
226class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SdrObjGeoData
227{
228public:
229 tools::Rectangle aBoundRect;
230 Point aAnchor;
231 std::unique_ptr<SdrGluePointList>
232 pGPL;
233 bool bMovProt;
234 bool bSizProt;
235 bool bNoPrint;
236 bool bClosedObj;
237 bool mbVisible;
238 SdrLayerID mnLayerID;
239
240public:
241 SdrObjGeoData();
242 virtual ~SdrObjGeoData();
243};
244
245/**
246 * Provides information about various ZObject properties
247 */
248class SVXCORE_DLLPUBLIC__attribute__ ((visibility("default"))) SdrObjTransformInfoRec
249{
250public:
251 bool bMoveAllowed : 1; // if false, object cannot be moved
252 bool bResizeFreeAllowed : 1; // if false, object cannot be resized freely
253 bool bResizePropAllowed : 1; // if false, object cannot even be resized proportionally
254 bool bRotateFreeAllowed : 1; // if false, object cannot be rotated freely
255 bool bRotate90Allowed : 1; // if false, object cannot even be rotated in 90 degree steps
256 bool bMirrorFreeAllowed : 1; // if false, object cannot be mirrored freely
257 bool bMirror45Allowed : 1; // if false, object cannot even be mirrored over axes in a 45 degree raster
258 bool bMirror90Allowed : 1; // if false, object cannot even be mirrored over axes in a 90 degree raster
259 bool bTransparenceAllowed : 1; // if false, object does not have an interactive transparence control
260 bool bShearAllowed : 1; // if false, object cannot be sheared
261 bool bEdgeRadiusAllowed : 1;
262 bool bNoOrthoDesired : 1; // is true for Rect; is false for BMP, MTF
263 bool bNoContortion : 1; // if false, contortion not possible (for crook, only true for PathObj and grouped PathObjs)
264 bool bCanConvToPath : 1; // if false, no conversion into PathObj possible
265 bool bCanConvToPoly : 1; // if false, no conversion into PolyObj possible
266 bool bCanConvToContour : 1; // if false, no conversion down to whole contour possible
267 bool bCanConvToPathLineToArea : 1; // if false, no conversion into PathObj with transformation from LineToArea possible
268 bool bCanConvToPolyLineToArea : 1; // if false, no conversion into PolyObj with transformation from LineToArea possible
269
270 SdrObjTransformInfoRec();
271};
272
273////////////////////////////////////////////////////////////////////////////////////////////////////
274//
275// SdrObject
276// SdrAttrObj
277// E3dObject
278// E3dCompoundObject
279// E3dCubeObj
280// E3dExtrudeObj
281// E3dLatheObj
282// E3dPolygonObj
283// E3dSphereObj
284// E3dScene
285// SdrTextObj
286// SdrObjCustomShape
287// OCustomShape
288// SdrEdgeObj
289// SdrMeasureObj
290// SdrPathObj
291// SdrRectObj
292// SdrCaptionObj
293// SdrCircObj
294// SdrGrafObj
295// SdrMediaObj
296// SdrOle2Obj
297// OOle2Obj
298// SdrUnoObj
299// DlgEdObj
300// DlgEdForm
301// OUnoObject
302// FmFormObj
303// SdrTableObj
304// SdrObjGroup
305// SdrPageObj
306// SdrVirtObj
307// SwDrawVirtObj
308// SwVirtFlyDrawObj
309// SwFlyDrawObj
310
311/// Abstract DrawObject
312class SVXCORE_DLLPUBLIC__attribute__ ((visibility("default"))) SdrObject : public SfxListener, public tools::WeakBase
313{
314private:
315 friend class SdrObjListIter;
316 friend class SdrVirtObj;
317 friend class SdrRectObj;
318
319 // OperationSmiley: Allow at each SdrObject to set a FillGeometryDefiningShape,
320 // so that for SdrObjects where this is set, the definition of a defined FillStyle
321 // will use this, but the local geometry will be filled. This allows to fill
322 // multiple shapes with a unified fill, e.g think about CustomShapes.
323 // Currently this is *only* used for CustomShapes, but may be developed to get a
324 // common mechanism - usages for it are easy to be found. The current limitation
325 // to CustomShapes allows to think about these SdrObjects to 'vanish' during the
326 // lifetime of 'this' - the SdrObjects without SdrPage and SdrModel are used as helper
327 // objects for SdrObjCustomShape and thus their lifetime is limited to the lifetime
328 // of this local object. For unifying this mechanism, some weak reference of
329 // SdrObjects would have to be thought about (not easy with the current implementation).
330 // So - allow *only* EnhancedCustomShape2d (which creates the visualizations for
331 // SdrObjCustomShape) to set this. Already allow unified read to use it - thus already
332 // allowing to implement as standard case for all kinds of SdrObjects.
333 friend class EnhancedCustomShape2d;
334 const SdrObject* mpFillGeometryDefiningShape;
335 void setFillGeometryDefiningShape(const SdrObject* pNew) { mpFillGeometryDefiningShape = pNew; }
336public:
337 const SdrObject* getFillGeometryDefiningShape() const { return mpFillGeometryDefiningShape; }
338
339private:
340 // the SdrModel this objects was created with, unchanged during SdrObject lifetime
341 SdrModel& mrSdrModelFromSdrObject;
342
343public:
344 // A SdrObject always needs a SdrModel for lifetime (Pool, ...)
345 SdrObject(SdrModel& rSdrModel);
346
347 // SdrModel/SdrPage access on SdrObject level
348 SdrPage* getSdrPageFromSdrObject() const;
349 SdrModel& getSdrModelFromSdrObject() const;
350
351 // access to possible children (SdrObjGroup/E3dScene)
352 virtual SdrObjList* getChildrenOfSdrObject() const;
353
354 // access to parent
355 SdrObjList* getParentSdrObjListFromSdrObject() const;
356 SdrObject* getParentSdrObjectFromSdrObject() const;
357
358private:
359 // only allow SetParentAtSdrObjectFromSdrObjList to call setParentOfSdrObject
360 friend void SetParentAtSdrObjectFromSdrObjList(SdrObject& rSdrObject, SdrObjList* pNew);
361 SVX_DLLPRIVATE__attribute__ ((visibility("hidden"))) void setParentOfSdrObject(SdrObjList* pNew);
362
363public:
364 // react on model/page change
365 virtual void handlePageChange(SdrPage* pOldPage, SdrPage* pNewPage);
366
367 void AddObjectUser(sdr::ObjectUser& rNewUser);
368 void RemoveObjectUser(sdr::ObjectUser& rOldUser);
369
370 sdr::contact::ViewContact& GetViewContact() const;
371
372 virtual sdr::properties::BaseProperties& GetProperties() const;
373
374 // DrawContact support: Methods for handling Object changes
375 void ActionChanged() const;
376
377 static SdrItemPool& GetGlobalDrawObjectItemPool();
378 void SetRelativeWidth( double nValue );
379 void SetRelativeWidthRelation( sal_Int16 eValue );
380 void SetRelativeHeight( double nValue );
381 void SetRelativeHeightRelation( sal_Int16 eValue );
382 const double* GetRelativeWidth() const;
383 sal_Int16 GetRelativeWidthRelation() const;
384 const double* GetRelativeHeight() const;
385 sal_Int16 GetRelativeHeightRelation() const;
386
387 void SetDiagramData(std::shared_ptr<DiagramDataInterface> pDiagramData);
388 std::shared_ptr<DiagramDataInterface> GetDiagramData() const;
389
390 /// @param bNotMyself = true: set only ObjList to dirty, don't mark this object as dirty.
391 ///
392 /// This is needed for instance for NbcMove, because usually one moves SnapRect and aOutRect
393 /// at the same time to avoid recomputation.
394 virtual void SetRectsDirty(bool bNotMyself = false, bool bRecursive = true);
395
396 // frees the SdrObject pointed to by the argument
397 // In case the object has an SvxShape, which has the ownership of the object, it
398 // is actually *not* deleted.
399 static void Free( SdrObject*& _rpObject );
400
401 // this method is only for access from Property objects
402 virtual void SetBoundRectDirty();
403
404 SfxItemPool & GetObjectItemPool() const;
405
406 void AddListener(SfxListener& rListener);
407 void RemoveListener(SfxListener& rListener);
408
409 void AddReference(SdrVirtObj& rVrtObj);
410 void DelReference(SdrVirtObj& rVrtObj);
411 virtual SdrInventor GetObjInventor() const;
412 virtual sal_uInt16 GetObjIdentifier() const;
413 virtual void TakeObjInfo(SdrObjTransformInfoRec& rInfo) const;
414
415 // Layer interface
416 virtual SdrLayerID GetLayer() const;
417 virtual void NbcSetLayer(SdrLayerID nLayer);
418 virtual void SetLayer(SdrLayerID nLayer);
419 // renaming GetSdrLayerIDSet -> getMergedHierarchySdrLayerIDSet to make clear what happens here. rSet needs to be empty.
420 void getMergedHierarchySdrLayerIDSet(SdrLayerIDSet& rSet) const;
421
422 void SendUserCall(SdrUserCallType eUserCall, const tools::Rectangle& rBoundRect) const;
423
424 // #i68101#
425 // An object may have a user-set Name (Get/SetName()), e.g SdrGrafObj, SdrObjGroup
426 // or SdrOle2Obj.
427 // It may also have a Title and a Description for accessibility purposes.
428 void SetName(const OUString& rStr);
429 OUString GetName() const;
430 void MakeNameUnique();
431 void MakeNameUnique(std::unordered_set<OUString>& rNameSet);
432 void SetTitle(const OUString& rStr);
433 OUString GetTitle() const;
434 void SetDescription(const OUString& rStr);
435 OUString GetDescription() const;
436
437 // for group objects
438 bool IsGroupObject() const;
439 virtual SdrObjList* GetSubList() const;
440
441 /// The order number (aka ZOrder, aka z-index) determines whether a
442 /// SdrObject is located above or below another. Objects are painted from
443 /// lowest to highest order number. If the order of SdrObjects in the
444 /// SdrObjList is changed, the bObjOrdNumsDirty flag is set on the SdrPage
445 /// and the next GetOrdNum() call recalculates the order number of all
446 /// SdrObjects in the SdrObjList.
447 sal_uInt32 GetOrdNum() const;
448
449 // setting the order number should only happen from the model or from the page
450 void SetOrdNum(sal_uInt32 nNum);
451
452 // GrabBagItem for interim interop purposes
453 void GetGrabBagItem(css::uno::Any& rVal) const;
454
455 void SetGrabBagItem(const css::uno::Any& rVal);
456
457 // Return the position in the navigation order for the called object.
458 // Note that this method may update the navigation position of the
459 // called and of other SdrObjects. Therefore this method can not be
460 // const.
461 // @return
462 // If no navigation position has been explicitly defined then the
463 // result of GetOrdNum() is returned.
464 sal_uInt32 GetNavigationPosition() const;
465
466 // To make clearer that this method may trigger RecalcBoundRect and thus may be
467 // expensive and sometimes problematic (inside a bigger object change You will get
468 // non-useful BoundRects sometimes) i rename that method from GetBoundRect() to
469 // GetCurrentBoundRect().
470 virtual const tools::Rectangle& GetCurrentBoundRect() const;
471
472 // To have a possibility to get the last calculated BoundRect e.g for producing
473 // the first rectangle for repaints (old and new need to be used) without forcing
474 // a RecalcBoundRect (which may be problematical and expensive sometimes) i add here
475 // a new method for accessing the last BoundRect.
476 virtual const tools::Rectangle& GetLastBoundRect() const;
477
478 virtual void RecalcBoundRect();
479
480 void BroadcastObjectChange() const;
481
482 const SfxBroadcaster* GetBroadcaster() const;
483
484 // set modified-flag in the model
485 virtual void SetChanged();
486
487 // Tooling for painting a single object to an OutputDevice. This will be needed as long
488 // as not all painting is changed to use DrawContact objects.
489 void SingleObjectPainter(OutputDevice& rOut) const;
490 bool LineGeometryUsageIsNecessary() const;
491
492 // RotGrfFlyFrame: If true, this SdrObject supports only limited rotation, that
493 // means no change of the rotation point (only centered) and no shear allowed
494 virtual bool HasLimitedRotation() const;
495
496 // Returns a copy of the object. Every inherited class must reimplement this (in class Foo
497 // it should be sufficient to do "virtual Foo* CloneSdrObject(...) const { return CloneHelper< Foo >(); }".
498 // Note that this function uses operator= internally.
499 virtual SdrObject* CloneSdrObject(SdrModel& rTargetModel) const;
500
501 // implemented mainly for the purposes of CloneSdrObject()
502 SdrObject& operator=(const SdrObject& rObj);
503
504 // TakeObjName...() is for the display in the UI, e.g. "3 frames selected"
505 virtual OUString TakeObjNameSingul() const;
506 virtual OUString TakeObjNamePlural() const;
507
508 /// The Xor-Polygon is required by the View to drag the object.
509 /// All polygons within the PolyPolygon are interpreted as PolyLine.
510 /// To get a closed Polygon, close it explicitly.
511 virtual basegfx::B2DPolyPolygon TakeXorPoly() const;
512
513 /// contour for TextToContour
514 virtual basegfx::B2DPolyPolygon TakeContour() const;
515
516 /// Via GetHdlCount the number of Handles can be retrieved.
517 /// Normally 8, if it's a line 2.
518 /// For Polygon objects (Polygon/Spline/Bezier) the number may be much
519 /// larger. Polygon objects are also allowed to select a point of a
520 /// selected object. The handle of that point will then be replaced by
521 /// a new set of handles (PlusHdl). For a Polygon this would be a simple
522 /// selection Handle, for a Bezier curve this may be up to 3 Handles
523 /// (including Weights).
524 /// GetHdl() and GetPlusHdl() must create Handle instances with new!
525 /// An object that returns true from HasSpacialDrag() must provide these
526 /// methods (incl. FillHdlList()).
527 virtual sal_uInt32 GetHdlCount() const;
528 virtual void AddToPlusHdlList(SdrHdlList& rHdlList, SdrHdl& rHdl) const;
529 virtual void AddToHdlList(SdrHdlList& rHdlList) const;
530 virtual void addCropHandles(SdrHdlList& rTarget) const;
531
532 /// The standard transformations (Move,Resize,Rotate,Mirror,Shear) are
533 /// taken over by the View (TakeXorPoly(),...).
534 /// Object type specific dragging like corner radius of Rectangle,
535 /// control points of Splines, weights of Bezier curves, pointer of
536 /// Label objects must be handled by the object itself.
537 /// To keep the Model free of state, the state is kept in the View
538 /// and then passed to the object. EndDrag usually returns true for success,
539 /// false may be returned if the dragging did not modify the object,
540 /// where the View already handles the case that the pointer was not
541 /// moved at all.
542 virtual bool hasSpecialDrag() const;
543 virtual bool beginSpecialDrag(SdrDragStat& rDrag) const;
544 virtual bool applySpecialDrag(SdrDragStat& rDrag);
545 virtual OUString getSpecialDragComment(const SdrDragStat& rDrag) const;
546 virtual basegfx::B2DPolyPolygon getSpecialDragPoly(const SdrDragStat& rDrag) const;
547
548 // FullDrag support. This is for standard interactions and for SdrObjOwn
549 // support. If supportsFullDrag() returns true, getFullDragClone has to
550 // return a cloned SdrObject (who's ownership it loses) at which modifications
551 // like Move(), Scale(), etc or applySpecialDrag() will be executed. That
552 // object will be visualized on overlay for full drag, but should not be
553 // part of the model, thus not changing anything since it's only a temporary
554 // helper object for interaction
555 virtual bool supportsFullDrag() const;
556 virtual SdrObjectUniquePtr getFullDragClone() const;
557
558 /// Every object must be able to create itself interactively.
559 /// On MouseDown first an object is created, and its BegCreate() method
560 /// is called. On every MouseMove, MovCreate() is called. BrkCreate()
561 /// is called if the user cancels the interactive object creation.
562 /// EndCreate() is called on the MouseUp event. If EndCreate() returns
563 /// true, the creation is finished; the object is inserted into the
564 /// corresponding list. Otherwise it is assumed that further points
565 /// are necessary to create the object (Polygon, ...). The parameter
566 /// eCmd contains the number of mouse clicks (if the application
567 /// provides it).
568 /// BckCreate() will undo the previous EndCreate(), e.g. to delete the
569 /// last point of the Polygon. If BckCreate() returns false, creation
570 /// is cancelled.
571 virtual bool BegCreate(SdrDragStat& rStat);
572 virtual bool MovCreate(SdrDragStat& rStat); // if true, Xor needs to be repainted
573 virtual bool EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd);
574 virtual bool BckCreate(SdrDragStat& rStat);
575 virtual void BrkCreate(SdrDragStat& rStat);
576
577 /// get the cursor/pointer that signals creating this object
578 virtual PointerStyle GetCreatePointer() const;
579
580 /// Polygon dragged by the user when creating the object
581 virtual basegfx::B2DPolyPolygon TakeCreatePoly(const SdrDragStat& rDrag) const;
582
583 /// The methods Move, Resize, Rotate, Mirror, Shear, SetSnapRect and
584 /// SetLogicRect call the corresponding Nbc-methods, send a Repaint
585 /// broadcast and set the Modified state on the Model.
586 /// Derived classes should usually only override the Nbc methods.
587 /// Nbc means "no broadcast".
588 virtual void NbcMove (const Size& rSiz);
589 virtual void NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact);
590 virtual void NbcCrop (const basegfx::B2DPoint& rRef, double fxFact, double fyFact);
591 virtual void NbcRotate(const Point& rRef, long nAngle, double sn, double cs);
592 virtual void NbcMirror(const Point& rRef1, const Point& rRef2);
593 virtual void NbcShear (const Point& rRef, long nAngle, double tn, bool bVShear);
594
595 virtual void Move (const Size& rSiz);
596 virtual void Resize(const Point& rRef, const Fraction& xFact, const Fraction& yFact, bool bUnsetRelative = true);
597 virtual void Crop (const basegfx::B2DPoint& rRef, double fxFact, double fyFact);
598 virtual void Rotate(const Point& rRef, long nAngle, double sn, double cs);
599 virtual void Mirror(const Point& rRef1, const Point& rRef2);
600 virtual void Shear (const Point& rRef, long nAngle, double tn, bool bVShear);
601
602 /// The relative position of a SdrObject is the distance of the upper
603 /// left corner of the logic bounding rectangle (SnapRect) to the anchor.
604 virtual void NbcSetRelativePos(const Point& rPnt);
605 virtual void SetRelativePos(const Point& rPnt);
606 virtual Point GetRelativePos() const;
607 void ImpSetAnchorPos(const Point& rPnt);
608 virtual void NbcSetAnchorPos(const Point& rPnt);
609 virtual void SetAnchorPos(const Point& rPnt);
610
611 /// Snap is not done on the BoundRect but if possible on logic coordinates
612 /// (i.e. without considering stroke width, ...)
613 /// SetSnapRect() tries to size the Object so that it fits into the
614 /// passed Rect (without stroke width, ...)
615 virtual void RecalcSnapRect();
616 virtual const tools::Rectangle& GetSnapRect() const;
617 virtual void SetSnapRect(const tools::Rectangle& rRect);
618 virtual void NbcSetSnapRect(const tools::Rectangle& rRect);
619
620 // Logic Rect: for the Rect for instance without regard to rotation angle, shear, ...
621 virtual const tools::Rectangle& GetLogicRect() const;
622 virtual void SetLogicRect(const tools::Rectangle& rRect);
623 virtual void NbcSetLogicRect(const tools::Rectangle& rRect);
624
625 // the default is to set the logic rect to the given rectangle rMaxRect. If the shape
626 // has an intrinsic aspect ratio it may set the logic rect so the aspect
627 // ratio is kept but still inside the rectangle rMaxRect.
628 // If bShrinkOnly is set to true, the size of the current logic rect will not
629 // be changed if it is smaller than the given rectangle rMaxRect.
630 virtual void AdjustToMaxRect( const tools::Rectangle& rMaxRect, bool bShrinkOnly = false );
631
632 // rotation and shear angle
633 virtual long GetRotateAngle() const;
634 virtual long GetShearAngle(bool bVertical = false) const;
635
636 /// snap to special points of an Object (polygon points, center of circle)
637 virtual sal_uInt32 GetSnapPointCount() const;
638 virtual Point GetSnapPoint(sal_uInt32 i) const;
639
640 // For objects, whose points can be moved individually.
641 // (e.g. polygons, polylines, lines)
642 // The points of those objects are selected (if necessary multiselection),
643 // deleted, inserted, or as a multiselection moved or rotated...
644 // Only such objects can have PlusHandles (e.g. the weights of a Bezier curve).
645 virtual bool IsPolyObj() const;
646 virtual sal_uInt32 GetPointCount() const;
647 virtual Point GetPoint(sal_uInt32 i) const;
648 void SetPoint(const Point& rPnt, sal_uInt32 i);
649 virtual void NbcSetPoint(const Point& rPnt, sal_uInt32 i);
650
651 // get all geometrical data for undo/redo
652 virtual SdrObjGeoData* GetGeoData() const;
653 virtual void SetGeoData(const SdrObjGeoData& rGeo);
654
655 // ItemSet access
656 const SfxItemSet& GetMergedItemSet() const;
657 void SetMergedItem(const SfxPoolItem& rItem);
658 void ClearMergedItem(const sal_uInt16 nWhich = 0);
659 void SetMergedItemSet(const SfxItemSet& rSet, bool bClearAllItems = false);
660 const SfxPoolItem& GetMergedItem(const sal_uInt16 nWhich) const;
661 template<class T>
662 const T& GetMergedItem( TypedWhichId<T> nWhich ) const
663 {
664 return static_cast<const T&>(GetMergedItem(sal_uInt16(nWhich)));
665 }
666
667 // syntactical sugar for ItemSet accesses
668 void SetMergedItemSetAndBroadcast(const SfxItemSet& rSet, bool bClearAllItems = false);
669
670 // NotPersistAttr for Layer, ObjName, geometrical transformations etc.
671 void TakeNotPersistAttr(SfxItemSet& rAttr) const;
672 void ApplyNotPersistAttr(const SfxItemSet& rAttr);
673 void NbcApplyNotPersistAttr(const SfxItemSet& rAttr);
674
675 // if bDontRemoveHardAttr is false, set all attributes, which were set in the style sheet, to their default value
676 // if true, all hard attributes keep their values
677 void SetStyleSheet(SfxStyleSheet* pNewStyleSheet, bool bDontRemoveHardAttr);
678 virtual void NbcSetStyleSheet(SfxStyleSheet* pNewStyleSheet, bool bDontRemoveHardAttr);
679 SfxStyleSheet* GetStyleSheet() const;
680
681 virtual bool HasTextEdit() const;
682
683 // keep text in outliner's format
684 // SetOutlinerParaObject: transfer ownership of *pTextObject!
685 void SetOutlinerParaObject(std::unique_ptr<OutlinerParaObject> pTextObject);
686 virtual void NbcSetOutlinerParaObject(std::unique_ptr<OutlinerParaObject> pTextObject);
687 virtual OutlinerParaObject* GetOutlinerParaObject() const;
688 virtual void NbcReformatText();
689
690 void BurnInStyleSheetAttributes();
691
692 // macro abilities, e.g. a rectangle as PushButton.
693 virtual bool HasMacro() const;
694 virtual SdrObject* CheckMacroHit (const SdrObjMacroHitRec& rRec) const;
695 virtual PointerStyle GetMacroPointer (const SdrObjMacroHitRec& rRec) const;
696 virtual void PaintMacro (OutputDevice& rOut, const tools::Rectangle& rDirtyRect, const SdrObjMacroHitRec& rRec) const;
697 virtual bool DoMacro (const SdrObjMacroHitRec& rRec);
698 bool IsMacroHit(const SdrObjMacroHitRec& rRec) const;
699
700 // Connectors
701 // (see also documentation in SvdoEdge.hxx, SdrEdgeObj, as well as SvdGlue.hxx and SvdGlEV.hxx)
702 //
703 // There are nodes and edges. In theory an edge can also be a node, but this isn't implemented yet.
704 // A node has a number of glue points, onto which edges can glued to
705 // An edge can be either
706 // - without any connection to any node,
707 // - or connected on one end to a node, while the other end is not connected,
708 // - or connected on both ends with exactly one node each.
709 // The edge is listener for its up to two nodes.
710 // Whenever a node is moved or resized, all its connected edges follow.
711 // This is also true for SetGluePoint()... on the node.
712 // On the other hand, moving/resizing an edge breaks the connection.
713
714 // automatic glue points:
715 // a node object must provide four vertex and corner positions
716 // usually 0: top, 1: right, 2: bottom, 3: left
717 virtual SdrGluePoint GetVertexGluePoint(sal_uInt16 nNum) const;
718
719 // usually:
720 // 0: top-left, 1: top-right, 2: bottom-right, 3: bottom-left
721 virtual SdrGluePoint GetCornerGluePoint(sal_uInt16 nNum) const;
722
723 // list of all glue points, can be NULL
724 virtual const SdrGluePointList* GetGluePointList() const;
725
726 // after changing the GluePointList, one has to call the object's SendRepaintBroadcast!
727 virtual SdrGluePointList* ForceGluePointList();
728
729 // to be set temporarily when transforming related object(?)
730 void SetGlueReallyAbsolute(bool bOn);
731 void NbcRotateGluePoints(const Point& rRef, long nAngle, double sn, double cs);
732 void NbcMirrorGluePoints(const Point& rRef1, const Point& rRef2);
733 void NbcShearGluePoints (const Point& rRef, double tn, bool bVShear);
734
735 // if bTail1 is true, line start, otherwise line end
736 // if pObj is null disconnect
737 virtual void ConnectToNode(bool bTail1, SdrObject* pObj);
738 virtual void DisconnectFromNode(bool bTail1);
739 virtual SdrObject* GetConnectedNode(bool bTail1) const;
740
741 // sets the writing mode of the object's context
742 // Objects which itself do not support different writing modes will ignore this call.
743 // Objects which support different writing modes, but have an own, explicit writing mode set,
744 // will also ignore this call.
745 // Objects which support different writing modes, and whose own mode is set to css.text.WritingMode2.CONTEXT,
746 // will use the given writing mode to calculate their "effective writing mode".
747 // The behaviour of this method is undefined if you pass css.text.WritingMode2.CONTEXT.
748 // @param _nContextWritingMode
749 // the effective writing mode of the context of the object
750 virtual void SetContextWritingMode( const sal_Int16 _nContextWritingMode );
751
752 // If an object is able to convert itself into a polygon or into a Bezier curve (or into both),
753 // then the following methods should be overridden.
754 // E.g., convert a RectObj with line width 10, SOLID_PEN into a polygon:
755 // In the bLineToArea=false mode a PolyObj with four supporting points,
756 // line width 10 and SOLID_PEN shall be created.
757 // On the contrary in the bLineToArea=true mode the generated object should
758 // still have a line attribute NULL_PEN, and the line (also line pattern)
759 // itself should be emulated by the polygon area, which thereby can be
760 // manipulated by the user afterwards.
761 // The RectObj therefore can only convert correctly if it has an area attribute NULL_BRUSH.
762 // In this case it would have to:
763 // - set SOLID_BRUSH with the color of the given pen,
764 // - set NULL_PEN, and
765 // - generate tools::PolyPolygon with two polygons with four supporting points each.
766 // In each case the return value is a SdrObject*, because it is also
767 // allowed to return group objects (e.g. for SdrTextObj).
768 // In the case of the conversion from TextObj to PathObj,
769 // both modi (bLineToArea=true/false) would be identical.
770 // The methods' default implementations report "I'm unable to do this" (false/null).
771 virtual SdrObjectUniquePtr DoConvertToPolyObj(bool bBezier, bool bAddText) const;
772 SdrObjectUniquePtr ConvertToPolyObj(bool bBezier, bool bLineToArea) const;
773
774 // convert this path object to contour object; bForceLineDash converts even
775 // when there is no filled new polygon created from line-to-polygon conversion,
776 // specially used for XLINE_DASH and 3D conversion
777 SdrObject* ConvertToContourObj(SdrObject* pRet, bool bForceLineDash = false) const;
778private:
779 SdrObject* ImpConvertToContourObj(bool bForceLineDash);
780public:
781
782 // if true, reference onto an object
783 bool IsVirtualObj() const { return bVirtObj;}
784
785 // is true, if object can probably be filled
786 // is false, if object has probably line ends
787 // is invalid, if this is a group object
788 bool IsClosedObj() const { return bClosedObj;}
789
790 // tdf#118662 reorganize inserted state, no local bool needed anymore,
791 // it depends on being a member of a SdrObjList
792 void InsertedStateChange();
793 bool IsInserted() const { return nullptr != getParentSdrObjListFromSdrObject(); }
794
795 bool IsEdgeObj() const { return bIsEdge;}
796 bool Is3DObj() const { return bIs3DObj;}
10
Returning zero, which participates in a condition later
797 bool IsUnoObj() const { return bIsUnoObj;}
798 void SetMoveProtect(bool bProt);
799 bool IsMoveProtect() const { return bMovProt;}
800 void SetResizeProtect(bool bProt);
801 bool IsResizeProtect() const { return bSizProt;}
802 void SetPrintable(bool bPrn);
803 bool IsPrintable() const { return !bNoPrint;}
804 void SetVisible(bool bVisible);
805 bool IsVisible() const { return mbVisible;}
806 void SetMarkProtect(bool bProt);
807 bool IsMarkProtect() const { return bMarkProt;}
808
809 /// Whether the aspect ratio should be kept by default when resizing.
810 virtual bool shouldKeepAspectRatio() const { return false; }
811
812 // application specific data
813 sal_uInt16 GetUserDataCount() const;
814 SdrObjUserData* GetUserData(sal_uInt16 nNum) const;
815
816 void AppendUserData(std::unique_ptr<SdrObjUserData> pData);
817
818 // removes the record from the list and performs delete (FreeMem+Dtor).
819 void DeleteUserData(sal_uInt16 nNum);
820
821 // access to the UNO representation of the shape
822 virtual css::uno::Reference< css::uno::XInterface > getUnoShape();
823
824 static SdrObject* getSdrObjectFromXShape( const css::uno::Reference< css::uno::XInterface >& xInt );
825
826 // retrieves the instance responsible for notifying changes in the properties of the shape associated with
827 // the SdrObject
828 //
829 // @precond
830 // There already exists an SvxShape instance associated with the SdrObject
831 // @throws css::uno::RuntimeException
832 // if there does nt yet exists an SvxShape instance associated with the SdrObject.
833 svx::PropertyChangeNotifier& getShapePropertyChangeNotifier();
834
835 // notifies a change in the given property, to all applicable listeners registered at the associated SvxShape
836 //
837 // This method is equivalent to calling getShapePropertyChangeNotifier().notifyPropertyChange( _eProperty ),
838 // exception that it is allowed to be called when there does not yet exist an associated SvxShape - in which
839 // case the method will silently return without doing anything.
840 void notifyShapePropertyChange( const svx::ShapeProperty _eProperty ) const;
841
842 // transformation interface for StarOfficeAPI. This implements support for
843 // homogen 3x3 matrices containing the transformation of the SdrObject. At the
844 // moment it contains a shearX, rotation and translation, but for setting all linear
845 // transforms like Scale, ShearX, ShearY, Rotate and Translate are supported.
846 //
847 // gets base transformation and rectangle of object. If it's an SdrPathObj it fills the PolyPolygon
848 // with the base geometry and returns TRUE. Otherwise it returns FALSE.
849 virtual bool TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& rPolyPolygon) const;
850
851 // sets the base geometry of the object using infos contained in the homogen 3x3 matrix.
852 // If it's an SdrPathObj it will use the provided geometry information. The Polygon has
853 // to use (0,0) as upper left and will be scaled to the given size in the matrix.
854 virtual void TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& rPolyPolygon);
855
856 // give info if object is in destruction
857 bool IsInDestruction() const;
858
859 // return if fill is != XFILL_NONE
860 bool HasFillStyle() const;
861 bool HasLineStyle() const;
862
863 // on import of OLE object from MS documents the BLIP size might be retrieved,
864 // the following methods are used to control it;
865 // usually this data makes no sense after the import is finished, since the object
866 // might be resized
867 const tools::Rectangle& GetBLIPSizeRectangle() const { return maBLIPSizeRectangle;}
868 void SetBLIPSizeRectangle( const tools::Rectangle& aRect );
869
870 // #i121917#
871 virtual bool HasText() const;
872
873 bool Equals(const SdrObject&) const;
874
875 virtual void dumpAsXml(xmlTextWriterPtr pWriter) const;
876
877 /// Is this a textbox of a drawinglayer shape?
878 virtual bool IsTextBox() const;
879
880 void SetEmptyPresObj(bool bEpt);
881 bool IsEmptyPresObj() const { return bEmptyPresObj;}
882 void SetNotVisibleAsMaster(bool bFlg);
883 bool IsNotVisibleAsMaster() const { return bNotVisibleAsMaster;}
884 void SetUserCall(SdrObjUserCall* pUser);
885 SdrObjUserCall* GetUserCall() const { return pUserCall;}
886 /// @see mbDoNotInsertIntoPageAutomatically
887 void SetDoNotInsertIntoPageAutomatically(bool bSet);
888 /// @see mbDoNotInsertIntoPageAutomatically
889 bool IsDoNotInsertIntoPageAutomatically() const { return mbDoNotInsertIntoPageAutomatically;}
890
891 // Warning: this method should only be used if you really know what you're doing
892 sal_uInt32 GetOrdNumDirect() const { return nOrdNum;}
893
894 // #i25616#
895 bool DoesSupportTextIndentingOnLineWidthChange() const { return mbSupportTextIndentingOnLineWidthChange;}
896
897 const Point& GetAnchorPos() const;
898
899 // #i25616#
900 bool LineIsOutsideGeometry() const { return mbLineIsOutsideGeometry;}
901
902 // Set the position in the navigation position to the given value.
903 // This method is typically used only by the model after a change to
904 // the navigation order.
905 // This method does not change the navigation position of other
906 // objects.
907 // Use SdrObjList::SetObjectNavigationPosition() instead.
908 void SetNavigationPosition (const sal_uInt32 nPosition);
909
910 // sets a new UNO representation of the shape
911 // This is only a public interface function. The actual work is
912 // done by impl_setUnoShape().
913 // Calling this function is only allowed for the UNO representation
914 // itself!
915 void setUnoShape( const css::uno::Reference<css::uno::XInterface>& _rxUnoShape);
916
917 const css::uno::WeakReference< css::uno::XInterface >& getWeakUnoShape() const { return maWeakUnoShape; }
918
919 void setSuitableOutlinerBg(Outliner& rOutliner) const;
920
921protected:
922 tools::Rectangle aOutRect; // surrounding rectangle for Paint (incl. LineWidth, ...)
923 Point aAnchor; // anchor position (Writer)
924 SdrObjUserCall* pUserCall;
925 std::unique_ptr<SdrObjPlusData>
926 pPlusData; // Broadcaster, UserData, connectors, ... (this is the Bitsack)
927 // object is only pointing to another one
928 bool bVirtObj : 1;
929 bool bSnapRectDirty : 1;
930 // the following flags will be streamed
931 bool bMovProt : 1; // if true, the position is protected
932 bool bSizProt : 1; // if true, the size is protected
933 // If bEmptyPresObj is true, it is a presentation object that has no content yet.
934 // The flag's default value is false.
935 // The management is done by the application.
936 // Neither assign operator nor cloning copies the flag!
937 // The flag is persistent.
938 bool bEmptyPresObj : 1; // empty presentation object (Draw)
939 // if true, object is invisible as object of the MasterPage
940 bool bNotVisibleAsMaster : 1;
941 // if true, the object is closed, i.e. no line, arc...
942 bool bClosedObj : 1;
943 bool bIsEdge : 1;
944 bool bIs3DObj : 1;
945 bool bIsUnoObj : 1;
946 // #i25616#
947 bool mbLineIsOutsideGeometry : 1;
948 // #i25616#
949 bool mbSupportTextIndentingOnLineWidthChange : 1;
950
951 virtual ~SdrObject() override;
952
953 virtual std::unique_ptr<sdr::properties::BaseProperties> CreateObjectSpecificProperties();
954
955 virtual std::unique_ptr<sdr::contact::ViewContact> CreateObjectSpecificViewContact();
956
957 tools::Rectangle ImpDragCalcRect(const SdrDragStat& rDrag) const;
958
959 // for GetDragComment
960 OUString ImpGetDescriptionStr(const char* pStrCacheID) const;
961
962 void ImpForcePlusData();
963
964 OUString GetMetrStr(long nVal) const;
965
966 /// A derived class must override these 3 methods if it has own geometric
967 /// data that must be saved for Undo.
968 /// NewGeoData() creates an empty instance of a class derived from
969 /// SdrObjGeoData.
970 virtual SdrObjGeoData* NewGeoData() const;
971 virtual void SaveGeoData(SdrObjGeoData& rGeo) const;
972 virtual void RestGeoData(const SdrObjGeoData& rGeo);
973
974 // internal versions
975 const SfxItemSet& GetObjectItemSet() const;
976 void SetObjectItem(const SfxPoolItem& rItem);
977 void SetObjectItemSet(const SfxItemSet& rSet);
978 const SfxPoolItem& GetObjectItem(const sal_uInt16 nWhich) const;
979 template<class T> const T& GetObjectItem( TypedWhichId<T> nWhich ) const
980 {
981 return static_cast<const T&>(GetObjectItem(sal_uInt16(nWhich)));
982 }
983
984 /// Sets a new UNO shape
985 ///
986 /// The default implementation of this function sets the new UNO
987 /// shape. Derived classes should override the function to handle
988 /// any other actions that are needed when the shape is being
989 /// changed.
990 ///
991 /// The implementation _must_ call the same method of its parent
992 /// class (preferably as the first step)!
993 virtual void impl_setUnoShape( const css::uno::Reference< css::uno::XInterface >& _rxUnoShape );
994
995 // helper function for reimplementing Clone().
996 template< typename T > T* CloneHelper(SdrModel& rTargetModel) const;
997
998private:
999 struct Impl;
1000 std::unique_ptr<Impl> mpImpl;
1001 SdrObjList* mpParentOfSdrObject; // list that includes this object
1002 sal_uInt32 nOrdNum; // order number of the object in the list
1003 std::unique_ptr<SfxGrabBagItem> pGrabBagItem; // holds the GrabBagItem property
1004 // Position in the navigation order. SAL_MAX_UINT32 when not used.
1005 sal_uInt32 mnNavigationPosition;
1006 SdrLayerID mnLayerID;
1007 bool bNoPrint : 1; // if true, the object is not printed.
1008 bool mbVisible : 1; // if false, the object is not visible on screen (but maybe on printer, depending on bNoprint
1009 bool bMarkProt : 1; // marking forbidden, persistent
1010 // on import of OLE object from MS documents the BLIP size might be retrieved,
1011 // in this case the following member is initialized as nonempty rectangle
1012 tools::Rectangle maBLIPSizeRectangle;
1013 std::unique_ptr<sdr::properties::BaseProperties>
1014 mpProperties;
1015 std::unique_ptr<sdr::contact::ViewContact>
1016 mpViewContact;
1017
1018 // global static ItemPool for not-yet-inserted items
1019 static SdrItemPool* mpGlobalItemPool;
1020
1021 // do not use directly, always use getSvxShape() if you have to!
1022 SvxShape* mpSvxShape;
1023 css::uno::WeakReference< css::uno::XInterface >
1024 maWeakUnoShape;
1025 // HACK: Do not automatically insert newly created object into a page.
1026 // The user needs to do it manually later.
1027 bool mbDoNotInsertIntoPageAutomatically;
1028
1029 // only for internal use!
1030 SvxShape* getSvxShape();
1031
1032 SdrObject( const SdrObject& ) = delete;
1033};
1034
1035struct SVXCORE_DLLPUBLIC__attribute__ ((visibility("default"))) SdrObjectFreeOp
1036{
1037 void operator()(SdrObject* obj)
1038 {
1039 SdrObject::Free(obj);
1040 }
1041};
1042
1043struct SdrObjCreatorParams
1044{
1045 SdrInventor nInventor;
1046 sal_uInt16 nObjIdentifier;
1047 SdrModel& rSdrModel;
1048};
1049
1050/**
1051 * Whoever creates his own objects must set a link in the SdrObjFactory class.
1052 * The handler must have the following signature:
1053 * void Hdl(SdrObjFactory*)
1054 * He must take a look at the referenced instance's nInventor and nIdentifier values,
1055 * and must create a new drawing object instance accordingly.
1056 * He must also make the pNewObj pointer reference to this instance.
1057 */
1058class SVXCORE_DLLPUBLIC__attribute__ ((visibility("default"))) SdrObjFactory
1059{
1060public:
1061 static SdrObject* MakeNewObject(
1062 SdrModel& rSdrModel,
1063 SdrInventor nInventor,
1064 sal_uInt16 nObjIdentifier,
1065 const tools::Rectangle* pSnapRect = nullptr);
1066
1067 static void InsertMakeObjectHdl(Link<SdrObjCreatorParams, SdrObject*> const & rLink);
1068 static void RemoveMakeObjectHdl(Link<SdrObjCreatorParams, SdrObject*> const & rLink);
1069
1070private:
1071 static SVX_DLLPRIVATE__attribute__ ((visibility("hidden"))) SdrObject* CreateObjectFromFactory(
1072 SdrModel& rSdrModel,
1073 SdrInventor nInventor,
1074 sal_uInt16 nIdentifier);
1075
1076 SdrObjFactory() = delete;
1077};
1078
1079template< typename T > T* SdrObject::CloneHelper(SdrModel& rTargetModel) const
1080{
1081 OSL_ASSERT( typeid( T ) == typeid( *this ))do { if (true && (!(typeid( T ) == typeid( *this ))))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/include/svx/svdobj.hxx"
":" "1081" ": "), "OSL_ASSERT: %s", "typeid( T ) == typeid( *this )"
); } } while (false)
;
1082 T* pObj = dynamic_cast< T* >(
1083 SdrObjFactory::MakeNewObject(
1084 rTargetModel,
1085 GetObjInventor(),
1086 GetObjIdentifier()));
1087
1088 if(nullptr != pObj)
1089 {
1090 // use ::operator=()
1091 *pObj = *static_cast< const T* >( this );
1092 }
1093
1094 return pObj;
1095}
1096
1097#endif // INCLUDED_SVX_SVDOBJ_HXX
1098
1099/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/svx/svditer.hxx

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#ifndef INCLUDED_SVX_SVDITER_HXX
21#define INCLUDED_SVX_SVDITER_HXX
22
23#include <vector>
24
25#include <svx/svxdllapi.h>
26
27class SdrObjList;
28class SdrObject;
29class SdrPage;
30class SdrMarkList;
31
32// SdrObjListIter methods:
33// SdrIterMode::Flat : Flat over the list
34// SdrIterMode::DeepWithGroups : With recursive descent parser, Next() also returns group objects
35// SdrIterMode::DeepNoGroups : With recursive descent parser, Next() returns no group objects
36enum class SdrIterMode { Flat, DeepWithGroups, DeepNoGroups };
37
38class SVXCORE_DLLPUBLIC__attribute__ ((visibility("default"))) SdrObjListIter
39{
40 std::vector< const SdrObject* > maObjList;
41 size_t mnIndex;
42 bool mbReverse;
43 bool mbUseZOrder;
44
45 void ImpProcessObjectList(const SdrObjList& rSdrObjList, SdrIterMode eMode);
46 void ImpProcessMarkList(const SdrMarkList& rMarkList, SdrIterMode eMode);
47 void ImpProcessObj(const SdrObject& rSdrObject, SdrIterMode eMode);
48
49public:
50 explicit SdrObjListIter(const SdrObjList* pObjList, SdrIterMode eMode = SdrIterMode::DeepNoGroups, bool bReverse = false);
51 explicit SdrObjListIter(const SdrObjList* pObjList, bool bUseZOrder, SdrIterMode eMode = SdrIterMode::DeepNoGroups, bool bReverse = false);
52
53 /* SJ: the following function can now be used with every
54 SdrObject and is no longer limited to group objects */
55 explicit SdrObjListIter(const SdrObject& rSdrObject, SdrIterMode eMode = SdrIterMode::DeepNoGroups, bool bReverse = false);
56 explicit SdrObjListIter(const SdrPage* pSdrPage, SdrIterMode eMode = SdrIterMode::DeepNoGroups, bool bReverse = false);
57
58 /** Iterates over a list of marked objects received from the SdrMarkView. TTTT used in sc */
59 explicit SdrObjListIter(const SdrMarkList& rMarkList, SdrIterMode eMode = SdrIterMode::DeepNoGroups);
60
61 void Reset() { mnIndex = (mbReverse ? maObjList.size() : 0L); }
62 bool IsMore() const { return (mbReverse ? mnIndex != 0 : ( mnIndex < maObjList.size())); }
14
Assuming field 'mbReverse' is true
15
'?' condition is true
16
Assuming field 'mnIndex' is not equal to 0
17
Returning the value 1, which participates in a condition later
63 SdrObject* Next()
64 {
65 const size_t idx(mbReverse
20.1
Field 'mbReverse' is true
20.1
Field 'mbReverse' is true
20.1
Field 'mbReverse' is true
? --mnIndex : mnIndex++);
21
'?' condition is true
66 return (idx < maObjList.size()) ? const_cast< SdrObject* >(maObjList[idx]) : nullptr;
22
Assuming the condition is true
23
'?' condition is true
24
Returning pointer, which participates in a condition later
25
Returning pointer
67 }
68
69 size_t Count() { return maObjList.size(); }
70};
71
72#endif // INCLUDED_SVX_SVDITER_HXX
73
74/* vim:set shiftwidth=4 softtabstop=4 expandtab: */