Bug Summary

File:home/maarten/src/libreoffice/core/svx/source/svdraw/svdedtv1.cxx
Warning:line 339, column 13
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 svdedtv1.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/svdedtv1.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 <basegfx/matrix/b2dhommatrix.hxx>
21#include <basegfx/matrix/b2dhommatrixtools.hxx>
22#include <editeng/eeitem.hxx>
23#include <math.h>
24#include <svl/itemiter.hxx>
25#include <svl/whiter.hxx>
26#include <tools/bigint.hxx>
27#include <vcl/svapp.hxx>
28#include <vcl/weld.hxx>
29
30#include <getallcharpropids.hxx>
31#include <svx/dialmgr.hxx>
32#include <svx/svditer.hxx>
33#include <svx/strings.hrc>
34
35#include <AffineMatrixItem.hxx>
36#include <svx/e3dsceneupdater.hxx>
37#include <svx/obj3d.hxx>
38#include <svx/rectenum.hxx>
39#include <svx/sdr/contact/viewcontact.hxx>
40#include <svx/sdooitm.hxx>
41#include <svx/sderitm.hxx>
42#include <svx/sdtagitm.hxx>
43#include <svx/svdedtv.hxx>
44#include <svx/svdetc.hxx>
45#include <svx/svdopath.hxx>
46#include <svx/svdpage.hxx>
47#include <svx/svdpagv.hxx>
48#include <svx/svdtrans.hxx>
49#include <svx/svdundo.hxx>
50#include <svx/svxids.hrc>
51#include <sxallitm.hxx>
52#include <sxmovitm.hxx>
53#include <sxreaitm.hxx>
54#include <sxreoitm.hxx>
55#include <sxroaitm.hxx>
56#include <sxrooitm.hxx>
57#include <sxsalitm.hxx>
58#include <sxsoitm.hxx>
59#include <sxtraitm.hxx>
60#include <svx/xlnedwit.hxx>
61#include <svx/xlnstwit.hxx>
62#include <svx/xlnwtit.hxx>
63#include <svx/xlnclit.hxx>
64#include <svx/xflclit.hxx>
65#include <svx/xlntrit.hxx>
66#include <svx/xfltrit.hxx>
67#include <svx/sdprcitm.hxx>
68#include <LibreOfficeKit/LibreOfficeKitEnums.h>
69#include <rtl/ustring.hxx>
70#include <sfx2/viewsh.hxx>
71#include <comphelper/lok.hxx>
72
73// EditView
74
75
76void SdrEditView::SetMarkedObjRect(const tools::Rectangle& rRect)
77{
78 DBG_ASSERT(!rRect.IsEmpty(),"SetMarkedObjRect() with an empty Rect does not make sense.")do { if (true && (!(!rRect.IsEmpty()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdedtv1.cxx"
":" "78" ": "), "%s", "SetMarkedObjRect() with an empty Rect does not make sense."
); } } while (false)
;
79 if (rRect.IsEmpty()) return;
80 const size_t nCount=GetMarkedObjectCount();
81 if (nCount==0) return;
82 tools::Rectangle aR0(GetMarkedObjRect());
83 DBG_ASSERT(!aR0.IsEmpty(),"SetMarkedObjRect(): GetMarkedObjRect() is empty.")do { if (true && (!(!aR0.IsEmpty()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdedtv1.cxx"
":" "83" ": "), "%s", "SetMarkedObjRect(): GetMarkedObjRect() is empty."
); } } while (false)
;
84 if (aR0.IsEmpty()) return;
85 long x0=aR0.Left();
86 long y0=aR0.Top();
87 long w0=aR0.Right()-x0;
88 long h0=aR0.Bottom()-y0;
89 long x1=rRect.Left();
90 long y1=rRect.Top();
91 long w1=rRect.Right()-x1;
92 long h1=rRect.Bottom()-y1;
93
94 const bool bUndo = IsUndoEnabled();
95 if( bUndo )
96 {
97 EndTextEditAllViews();
98 BegUndo(ImpGetDescriptionString(STR_EditPosSizereinterpret_cast<char const *>("STR_EditPosSize" "\004"
u8"Set position and size for %1")
));
99 }
100
101 for (size_t nm=0; nm<nCount; ++nm)
102 {
103 SdrMark* pM=GetSdrMarkByIndex(nm);
104 SdrObject* pO=pM->GetMarkedSdrObj();
105 if( bUndo )
106 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
107
108 tools::Rectangle aR1(pO->GetSnapRect());
109 if (!aR1.IsEmpty())
110 {
111 if (aR1==aR0)
112 {
113 aR1=rRect;
114 }
115 else
116 { // transform aR1 to aR0 after rRect
117 aR1.Move(-x0,-y0);
118 BigInt l(aR1.Left());
119 BigInt r(aR1.Right());
120 BigInt t(aR1.Top());
121 BigInt b(aR1.Bottom());
122 if (w0!=0) {
123 l*=w1; l/=w0;
124 r*=w1; r/=w0;
125 } else {
126 l=0; r=w1;
127 }
128 if (h0!=0) {
129 t*=h1; t/=h0;
130 b*=h1; b/=h0;
131 } else {
132 t=0; b=h1;
133 }
134 aR1.SetLeft(long(l) );
135 aR1.SetRight(long(r) );
136 aR1.SetTop(long(t) );
137 aR1.SetBottom(long(b) );
138 aR1.Move(x1,y1);
139 }
140 pO->SetSnapRect(aR1);
141 } else {
142 OSL_FAIL("SetMarkedObjRect(): pObj->GetSnapRect() returns empty Rect")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdedtv1.cxx"
":" "142" ": "), "%s", "SetMarkedObjRect(): pObj->GetSnapRect() returns empty Rect"
); } } while (false)
;
143 }
144 }
145 if( bUndo )
146 EndUndo();
147}
148
149std::vector< std::unique_ptr<SdrUndoAction> > SdrEditView::CreateConnectorUndo( SdrObject& rO )
150{
151 std::vector< std::unique_ptr<SdrUndoAction> > vUndoActions;
152
153 if ( rO.GetBroadcaster() )
154 {
155 const SdrPage* pPage = rO.getSdrPageFromSdrObject();
156 if ( pPage )
157 {
158 SdrObjListIter aIter(pPage, SdrIterMode::DeepWithGroups);
159 while( aIter.IsMore() )
160 {
161 SdrObject* pPartObj = aIter.Next();
162 if ( dynamic_cast<const SdrEdgeObj*>( pPartObj) != nullptr )
163 {
164 if ( ( pPartObj->GetConnectedNode( false ) == &rO ) ||
165 ( pPartObj->GetConnectedNode( true ) == &rO ) )
166 {
167 vUndoActions.push_back( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject( *pPartObj ) );
168 }
169 }
170 }
171 }
172 }
173 return vUndoActions;
174}
175
176void SdrEditView::AddUndoActions( std::vector< std::unique_ptr<SdrUndoAction> > aUndoActions )
177{
178 for (auto & rAction : aUndoActions)
179 AddUndo( std::move(rAction) );
180}
181
182void SdrEditView::MoveMarkedObj(const Size& rSiz, bool bCopy)
183{
184 const bool bUndo = IsUndoEnabled();
185
186 if( bUndo )
187 {
188 EndTextEditAllViews();
189 OUString aStr(SvxResId(STR_EditMovereinterpret_cast<char const *>("STR_EditMove" "\004" u8"Move %1"
)
));
190 if (bCopy)
191 aStr += SvxResId(STR_EditWithCopyreinterpret_cast<char const *>("STR_EditWithCopy" "\004"
u8"with copy")
);
192 // needs its own UndoGroup because of its parameters
193 BegUndo(aStr,GetDescriptionOfMarkedObjects(),SdrRepeatFunc::Move);
194 }
195
196 if (bCopy)
197 CopyMarkedObj();
198
199 const size_t nMarkCount=GetMarkedObjectCount();
200 for (size_t nm=0; nm<nMarkCount; ++nm)
201 {
202 SdrMark* pM=GetSdrMarkByIndex(nm);
203 SdrObject* pO=pM->GetMarkedSdrObj();
204 if( bUndo )
205 {
206 AddUndoActions( CreateConnectorUndo( *pO ) );
207 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoMoveObject(*pO,rSiz));
208 }
209 pO->Move(rSiz);
210 }
211
212 if( bUndo )
213 EndUndo();
214}
215
216void SdrEditView::ResizeMarkedObj(const Point& rRef, const Fraction& xFact, const Fraction& yFact, bool bCopy)
217{
218 const bool bUndo = IsUndoEnabled();
219 if( bUndo )
220 {
221 EndTextEditAllViews();
222 OUString aStr {ImpGetDescriptionString(STR_EditResizereinterpret_cast<char const *>("STR_EditResize" "\004" u8"Resize %1"
)
)};
223 if (bCopy)
224 aStr+=SvxResId(STR_EditWithCopyreinterpret_cast<char const *>("STR_EditWithCopy" "\004"
u8"with copy")
);
225 BegUndo(aStr);
226 }
227
228 if (bCopy)
229 CopyMarkedObj();
230
231 const size_t nMarkCount=GetMarkedObjectCount();
232 for (size_t nm=0; nm<nMarkCount; ++nm)
233 {
234 SdrMark* pM=GetSdrMarkByIndex(nm);
235 SdrObject* pO=pM->GetMarkedSdrObj();
236 if( bUndo )
237 {
238 AddUndoActions( CreateConnectorUndo( *pO ) );
239 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
240 }
241 pO->Resize(rRef,xFact,yFact);
242 }
243
244 if( bUndo )
245 EndUndo();
246}
247void SdrEditView::ResizeMultMarkedObj(const Point& rRef,
248 const Fraction& xFact,
249 const Fraction& yFact,
250 const bool bWdh,
251 const bool bHgt)
252{
253 const bool bUndo = IsUndoEnabled();
254 if( bUndo )
255 {
256 EndTextEditAllViews();
257 BegUndo(ImpGetDescriptionString(STR_EditResizereinterpret_cast<char const *>("STR_EditResize" "\004" u8"Resize %1"
)
));
258 }
259
260 const size_t nMarkCount=GetMarkedObjectCount();
261 for (size_t nm=0; nm<nMarkCount; ++nm)
262 {
263 SdrMark* pM=GetSdrMarkByIndex(nm);
264 SdrObject* pO=pM->GetMarkedSdrObj();
265 if( bUndo )
266 {
267 AddUndoActions( CreateConnectorUndo( *pO ) );
268 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
269 }
270
271 Fraction aFrac(1,1);
272 if (bWdh && bHgt)
273 pO->Resize(rRef, xFact, yFact);
274 else if (bWdh)
275 pO->Resize(rRef, xFact, aFrac);
276 else if (bHgt)
277 pO->Resize(rRef, aFrac, yFact);
278 }
279 if( bUndo )
280 EndUndo();
281}
282
283long SdrEditView::GetMarkedObjRotate() const
284{
285 long nRetval(0);
286
287 if(GetMarkedObjectCount())
288 {
289 SdrMark* pM = GetSdrMarkByIndex(0);
290 SdrObject* pO = pM->GetMarkedSdrObj();
291
292 nRetval = pO->GetRotateAngle();
293 }
294
295 return nRetval;
296}
297
298void SdrEditView::RotateMarkedObj(const Point& rRef, long nAngle, bool bCopy)
299{
300 const bool bUndo = IsUndoEnabled();
301 if( bUndo )
70
Assuming 'bUndo' is false
71
Taking false branch
302 {
303 EndTextEditAllViews();
304 OUString aStr {ImpGetDescriptionString(STR_EditRotatereinterpret_cast<char const *>("STR_EditRotate" "\004" u8"Rotate %1"
)
)};
305 if (bCopy) aStr+=SvxResId(STR_EditWithCopyreinterpret_cast<char const *>("STR_EditWithCopy" "\004"
u8"with copy")
);
306 BegUndo(aStr);
307 }
308
309 if (bCopy
71.1
'bCopy' is false
)
72
Taking false branch
310 CopyMarkedObj();
311
312 double nSin = sin(nAngle * F_PI18000(3.14159265358979323846/18000.0));
313 double nCos = cos(nAngle * F_PI18000(3.14159265358979323846/18000.0));
314 const size_t nMarkCount(GetMarkedObjectCount());
315
316 if(nMarkCount)
73
Assuming 'nMarkCount' is not equal to 0
74
Taking true branch
317 {
318 std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
319
320 for(size_t nm = 0; nm
74.1
'nm' is < 'nMarkCount'
< nMarkCount; ++nm)
75
Loop condition is true. Entering loop body
321 {
322 SdrMark* pM = GetSdrMarkByIndex(nm);
323 SdrObject* pO = pM->GetMarkedSdrObj();
76
'pO' initialized here
324
325 if( bUndo
76.1
'bUndo' is false
)
77
Taking false branch
326 {
327 // extra undo actions for changed connector which now may hold its laid out path (SJ)
328 AddUndoActions( CreateConnectorUndo( *pO ) );
329
330 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
331 }
332
333 // set up a scene updater if object is a 3d object
334 if(dynamic_cast< E3dObject* >(pO))
78
Assuming 'pO' is null
79
Taking false branch
335 {
336 aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pO));
337 }
338
339 pO->Rotate(rRef,nAngle,nSin,nCos);
80
Called C++ object pointer is null
340 }
341
342 // fire scene updaters
343 while(!aUpdaters.empty())
344 {
345 delete aUpdaters.back();
346 aUpdaters.pop_back();
347 }
348 }
349
350 if( bUndo )
351 EndUndo();
352}
353
354void SdrEditView::MirrorMarkedObj(const Point& rRef1, const Point& rRef2, bool bCopy)
355{
356 const bool bUndo = IsUndoEnabled();
357
358 if( bUndo )
359 {
360 EndTextEditAllViews();
361 OUString aStr;
362 Point aDif(rRef2-rRef1);
363 if (aDif.X()==0)
364 aStr = ImpGetDescriptionString(STR_EditMirrorHorireinterpret_cast<char const *>("STR_EditMirrorHori" "\004"
u8"Flip %1 horizontal")
);
365 else if (aDif.Y()==0)
366 aStr = ImpGetDescriptionString(STR_EditMirrorVertreinterpret_cast<char const *>("STR_EditMirrorVert" "\004"
u8"Flip %1 vertical")
);
367 else if (std::abs(aDif.X()) == std::abs(aDif.Y()))
368 aStr = ImpGetDescriptionString(STR_EditMirrorDiagreinterpret_cast<char const *>("STR_EditMirrorDiag" "\004"
u8"Flip %1 diagonal")
);
369 else
370 aStr = ImpGetDescriptionString(STR_EditMirrorFreereinterpret_cast<char const *>("STR_EditMirrorFree" "\004"
u8"Flip %1 freehand")
);
371 if (bCopy) aStr+=SvxResId(STR_EditWithCopyreinterpret_cast<char const *>("STR_EditWithCopy" "\004"
u8"with copy")
);
372 BegUndo(aStr);
373 }
374
375 if (bCopy)
376 CopyMarkedObj();
377
378 const size_t nMarkCount(GetMarkedObjectCount());
379
380 if(nMarkCount)
381 {
382 std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
383
384 for(size_t nm = 0; nm < nMarkCount; ++nm)
385 {
386 SdrMark* pM = GetSdrMarkByIndex(nm);
387 SdrObject* pO = pM->GetMarkedSdrObj();
388
389 if( bUndo )
390 {
391 // extra undo actions for changed connector which now may hold its laid out path (SJ)
392 AddUndoActions( CreateConnectorUndo( *pO ) );
393
394 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
395 }
396
397 // set up a scene updater if object is a 3d object
398 if(dynamic_cast< E3dObject* >(pO))
399 {
400 aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pO));
401 }
402
403 pO->Mirror(rRef1,rRef2);
404 }
405
406 // fire scene updaters
407 while(!aUpdaters.empty())
408 {
409 delete aUpdaters.back();
410 aUpdaters.pop_back();
411 }
412 }
413
414 if( bUndo )
415 EndUndo();
416}
417
418void SdrEditView::MirrorMarkedObjHorizontal()
419{
420 Point aCenter(GetMarkedObjRect().Center());
421 Point aPt2(aCenter);
422 aPt2.AdjustY( 1 );
423 MirrorMarkedObj(aCenter,aPt2);
424}
425
426void SdrEditView::MirrorMarkedObjVertical()
427{
428 Point aCenter(GetMarkedObjRect().Center());
429 Point aPt2(aCenter);
430 aPt2.AdjustX( 1 );
431 MirrorMarkedObj(aCenter,aPt2);
432}
433
434long SdrEditView::GetMarkedObjShear() const
435{
436 bool b1st=true;
437 bool bOk=true;
438 long nAngle=0;
439 const size_t nMarkCount=GetMarkedObjectCount();
440 for (size_t nm=0; nm<nMarkCount && bOk; ++nm) {
441 SdrMark* pM=GetSdrMarkByIndex(nm);
442 SdrObject* pO=pM->GetMarkedSdrObj();
443 long nAngle2=pO->GetShearAngle();
444 if (b1st) nAngle=nAngle2;
445 else if (nAngle2!=nAngle) bOk=false;
446 b1st=false;
447 }
448 if (nAngle>SDRMAXSHEAR8900) nAngle=SDRMAXSHEAR8900;
449 if (nAngle<-SDRMAXSHEAR8900) nAngle=-SDRMAXSHEAR8900;
450 if (!bOk) nAngle=0;
451 return nAngle;
452}
453
454void SdrEditView::ShearMarkedObj(const Point& rRef, long nAngle, bool bVShear, bool bCopy)
455{
456 const bool bUndo = IsUndoEnabled();
457
458 if( bUndo )
459 {
460 EndTextEditAllViews();
461 OUString aStr {ImpGetDescriptionString(STR_EditShearreinterpret_cast<char const *>("STR_EditShear" "\004" u8"Distort %1 (slant)"
)
)};
462 if (bCopy)
463 aStr+=SvxResId(STR_EditWithCopyreinterpret_cast<char const *>("STR_EditWithCopy" "\004"
u8"with copy")
);
464 BegUndo(aStr);
465 }
466
467 if (bCopy)
468 CopyMarkedObj();
469
470 double nTan = tan(nAngle * F_PI18000(3.14159265358979323846/18000.0));
471 const size_t nMarkCount=GetMarkedObjectCount();
472 for (size_t nm=0; nm<nMarkCount; ++nm)
473 {
474 SdrMark* pM=GetSdrMarkByIndex(nm);
475 SdrObject* pO=pM->GetMarkedSdrObj();
476 if( bUndo )
477 {
478 AddUndoActions( CreateConnectorUndo( *pO ) );
479 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
480 }
481 pO->Shear(rRef,nAngle,nTan,bVShear);
482 }
483
484 if( bUndo )
485 EndUndo();
486}
487
488void SdrEditView::ImpCrookObj(SdrObject* pO, const Point& rRef, const Point& rRad,
489 SdrCrookMode eMode, bool bVertical, bool bNoContortion, bool bRotate, const tools::Rectangle& rMarkRect)
490{
491 SdrPathObj* pPath=dynamic_cast<SdrPathObj*>( pO );
492 bool bDone = false;
493
494 if(pPath!=nullptr && !bNoContortion)
495 {
496 XPolyPolygon aXPP(pPath->GetPathPoly());
497 switch (eMode) {
498 case SdrCrookMode::Rotate : CrookRotatePoly (aXPP,rRef,rRad,bVertical); break;
499 case SdrCrookMode::Slant : CrookSlantPoly (aXPP,rRef,rRad,bVertical); break;
500 case SdrCrookMode::Stretch: CrookStretchPoly(aXPP,rRef,rRad,bVertical,rMarkRect); break;
501 } // switch
502 pPath->SetPathPoly(aXPP.getB2DPolyPolygon());
503 bDone = true;
504 }
505
506 if(!bDone && !pPath && pO->IsPolyObj() && 0 != pO->GetPointCount())
507 {
508 // for PolyObj's, but NOT for SdrPathObj's, e.g. the measurement object
509 sal_uInt32 nPointCount(pO->GetPointCount());
510 XPolygon aXP(static_cast<sal_uInt16>(nPointCount));
511 sal_uInt32 nPtNum;
512
513 for(nPtNum = 0; nPtNum < nPointCount; nPtNum++)
514 {
515 Point aPt(pO->GetPoint(nPtNum));
516 aXP[static_cast<sal_uInt16>(nPtNum)]=aPt;
517 }
518
519 switch (eMode)
520 {
521 case SdrCrookMode::Rotate : CrookRotatePoly (aXP,rRef,rRad,bVertical); break;
522 case SdrCrookMode::Slant : CrookSlantPoly (aXP,rRef,rRad,bVertical); break;
523 case SdrCrookMode::Stretch: CrookStretchPoly(aXP,rRef,rRad,bVertical,rMarkRect); break;
524 }
525
526 for(nPtNum = 0; nPtNum < nPointCount; nPtNum++)
527 {
528 // broadcasting could be optimized here, but for the
529 // current two points of the measurement object, it's fine
530 pO->SetPoint(aXP[static_cast<sal_uInt16>(nPtNum)],nPtNum);
531 }
532
533 bDone = true;
534 }
535
536 if(bDone)
537 return;
538
539 // for all others or if bNoContortion
540 Point aCtr0(pO->GetSnapRect().Center());
541 Point aCtr1(aCtr0);
542 bool bRotOk(false);
543 double nSin(0.0), nCos(1.0);
544 double nAngle(0.0);
545
546 if(0 != rRad.X() && 0 != rRad.Y())
547 {
548 bRotOk = bRotate;
549
550 switch (eMode)
551 {
552 case SdrCrookMode::Rotate : nAngle=CrookRotateXPoint (aCtr1,nullptr,nullptr,rRef,rRad,nSin,nCos,bVertical); bRotOk=bRotate; break;
553 case SdrCrookMode::Slant : nAngle=CrookSlantXPoint (aCtr1,nullptr,nullptr,rRef,rRad,nSin,nCos,bVertical); break;
554 case SdrCrookMode::Stretch: nAngle=CrookStretchXPoint(aCtr1,nullptr,nullptr,rRef,rRad,nSin,nCos,bVertical,rMarkRect); break;
555 }
556 }
557
558 aCtr1 -= aCtr0;
559
560 if(bRotOk)
561 pO->Rotate(aCtr0, FRound(nAngle / F_PI18000(3.14159265358979323846/18000.0)), nSin, nCos);
562
563 pO->Move(Size(aCtr1.X(),aCtr1.Y()));
564}
565
566void SdrEditView::CrookMarkedObj(const Point& rRef, const Point& rRad, SdrCrookMode eMode,
567 bool bVertical, bool bNoContortion, bool bCopy)
568{
569 tools::Rectangle aMarkRect(GetMarkedObjRect());
570 const bool bUndo = IsUndoEnabled();
571
572 bool bRotate=bNoContortion && eMode==SdrCrookMode::Rotate && IsRotateAllowed();
573
574 if( bUndo )
575 {
576 EndTextEditAllViews();
577 OUString aStr {ImpGetDescriptionString(bNoContortion ? STR_EditCrookreinterpret_cast<char const *>("STR_EditCrook" "\004" u8"Arrange %1 in circle"
)
: STR_EditCrookContortionreinterpret_cast<char const *>("STR_EditCrookContortion"
"\004" u8"Curve %1 in circle")
)};
578 if (bCopy)
579 aStr+=SvxResId(STR_EditWithCopyreinterpret_cast<char const *>("STR_EditWithCopy" "\004"
u8"with copy")
);
580 BegUndo(aStr);
581 }
582
583 if (bCopy)
584 CopyMarkedObj();
585
586 const size_t nMarkCount=GetMarkedObjectCount();
587 for (size_t nm=0; nm<nMarkCount; ++nm)
588 {
589 SdrMark* pM=GetSdrMarkByIndex(nm);
590 SdrObject* pO=pM->GetMarkedSdrObj();
591 if( bUndo )
592 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
593
594 const SdrObjList* pOL=pO->GetSubList();
595 if (bNoContortion || pOL==nullptr) {
596 ImpCrookObj(pO,rRef,rRad,eMode,bVertical,bNoContortion,bRotate,aMarkRect);
597 } else {
598 SdrObjListIter aIter(pOL,SdrIterMode::DeepNoGroups);
599 while (aIter.IsMore()) {
600 SdrObject* pO1=aIter.Next();
601 ImpCrookObj(pO1,rRef,rRad,eMode,bVertical,bNoContortion,bRotate,aMarkRect);
602 }
603 }
604 }
605
606 if( bUndo )
607 EndUndo();
608}
609
610void SdrEditView::ImpDistortObj(SdrObject* pO, const tools::Rectangle& rRef, const XPolygon& rDistortedRect, bool bNoContortion)
611{
612 SdrPathObj* pPath = dynamic_cast<SdrPathObj*>( pO );
613
614 if(!bNoContortion && pPath)
615 {
616 XPolyPolygon aXPP(pPath->GetPathPoly());
617 aXPP.Distort(rRef, rDistortedRect);
618 pPath->SetPathPoly(aXPP.getB2DPolyPolygon());
619 }
620 else if(pO->IsPolyObj())
621 {
622 // e. g. for the measurement object
623 sal_uInt32 nPointCount(pO->GetPointCount());
624 XPolygon aXP(static_cast<sal_uInt16>(nPointCount));
625 sal_uInt32 nPtNum;
626
627 for(nPtNum = 0; nPtNum < nPointCount; nPtNum++)
628 {
629 Point aPt(pO->GetPoint(nPtNum));
630 aXP[static_cast<sal_uInt16>(nPtNum)]=aPt;
631 }
632
633 aXP.Distort(rRef, rDistortedRect);
634
635 for(nPtNum = 0; nPtNum < nPointCount; nPtNum++)
636 {
637 // broadcasting could be optimized here, but for the
638 // current two points of the measurement object it's fine
639 pO->SetPoint(aXP[static_cast<sal_uInt16>(nPtNum)],nPtNum);
640 }
641 }
642}
643
644void SdrEditView::DistortMarkedObj(const tools::Rectangle& rRef, const XPolygon& rDistortedRect, bool bNoContortion, bool bCopy)
645{
646 const bool bUndo = IsUndoEnabled();
647
648 if( bUndo )
649 {
650 EndTextEditAllViews();
651 OUString aStr {ImpGetDescriptionString(STR_EditDistortreinterpret_cast<char const *>("STR_EditDistort" "\004"
u8"Distort %1")
)};
652 if (bCopy)
653 aStr+=SvxResId(STR_EditWithCopyreinterpret_cast<char const *>("STR_EditWithCopy" "\004"
u8"with copy")
);
654 BegUndo(aStr);
655 }
656
657 if (bCopy)
658 CopyMarkedObj();
659
660 const size_t nMarkCount=GetMarkedObjectCount();
661 for (size_t nm=0; nm<nMarkCount; ++nm)
662 {
663 SdrMark* pM=GetSdrMarkByIndex(nm);
664 SdrObject* pO=pM->GetMarkedSdrObj();
665 if( bUndo )
666 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pO));
667
668 tools::Rectangle aRefRect(rRef);
669 const SdrObjList* pOL=pO->GetSubList();
670 if (bNoContortion || pOL==nullptr) {
671 ImpDistortObj(pO,aRefRect,rDistortedRect,bNoContortion);
672 } else {
673 SdrObjListIter aIter(pOL,SdrIterMode::DeepNoGroups);
674 while (aIter.IsMore()) {
675 SdrObject* pO1=aIter.Next();
676 ImpDistortObj(pO1,aRefRect,rDistortedRect,bNoContortion);
677 }
678 }
679 }
680 if( bUndo )
681 EndUndo();
682}
683
684
685void SdrEditView::SetNotPersistAttrToMarked(const SfxItemSet& rAttr)
686{
687 // bReplaceAll has no effect here
688 tools::Rectangle aAllSnapRect(GetMarkedObjRect());
689 const SfxPoolItem *pPoolItem=nullptr;
690 if (rAttr.GetItemState(SDRATTR_TRANSFORMREF1X,true,&pPoolItem)==SfxItemState::SET) {
46
Assuming the condition is false
47
Taking false branch
691 long n=static_cast<const SdrTransformRef1XItem*>(pPoolItem)->GetValue();
692 SetRef1(Point(n,GetRef1().Y()));
693 }
694 if (rAttr.GetItemState(SDRATTR_TRANSFORMREF1Y,true,&pPoolItem)==SfxItemState::SET) {
48
Assuming the condition is false
49
Taking false branch
695 long n=static_cast<const SdrTransformRef1YItem*>(pPoolItem)->GetValue();
696 SetRef1(Point(GetRef1().X(),n));
697 }
698 if (rAttr.GetItemState(SDRATTR_TRANSFORMREF2X,true,&pPoolItem)==SfxItemState::SET) {
50
Assuming the condition is false
51
Taking false branch
699 long n=static_cast<const SdrTransformRef2XItem*>(pPoolItem)->GetValue();
700 SetRef2(Point(n,GetRef2().Y()));
701 }
702 if (rAttr.GetItemState(SDRATTR_TRANSFORMREF2Y,true,&pPoolItem)==SfxItemState::SET) {
52
Assuming the condition is false
53
Taking false branch
703 long n=static_cast<const SdrTransformRef2YItem*>(pPoolItem)->GetValue();
704 SetRef2(Point(GetRef2().X(),n));
705 }
706 long nAllPosX=0; bool bAllPosX=false;
707 long nAllPosY=0; bool bAllPosY=false;
708 long nAllWdt=0; bool bAllWdt=false;
709 long nAllHgt=0; bool bAllHgt=false;
710 bool bDoIt=false;
711 if (rAttr.GetItemState(SDRATTR_ALLPOSITIONX,true,&pPoolItem)==SfxItemState::SET) {
54
Assuming the condition is false
55
Taking false branch
712 nAllPosX=static_cast<const SdrAllPositionXItem*>(pPoolItem)->GetValue();
713 bAllPosX=true; bDoIt=true;
714 }
715 if (rAttr.GetItemState(SDRATTR_ALLPOSITIONY,true,&pPoolItem)==SfxItemState::SET) {
56
Assuming the condition is false
57
Taking false branch
716 nAllPosY=static_cast<const SdrAllPositionYItem*>(pPoolItem)->GetValue();
717 bAllPosY=true; bDoIt=true;
718 }
719 if (rAttr.GetItemState(SDRATTR_ALLSIZEWIDTH,true,&pPoolItem)==SfxItemState::SET) {
58
Assuming the condition is false
59
Taking false branch
720 nAllWdt=static_cast<const SdrAllSizeWidthItem*>(pPoolItem)->GetValue();
721 bAllWdt=true; bDoIt=true;
722 }
723 if (rAttr.GetItemState(SDRATTR_ALLSIZEHEIGHT,true,&pPoolItem)==SfxItemState::SET) {
60
Assuming the condition is false
61
Taking false branch
724 nAllHgt=static_cast<const SdrAllSizeHeightItem*>(pPoolItem)->GetValue();
725 bAllHgt=true; bDoIt=true;
726 }
727 if (bDoIt
61.1
'bDoIt' is false
) {
62
Taking false branch
728 tools::Rectangle aRect(aAllSnapRect); // TODO: change this for PolyPt's and GluePt's!!!
729 if (bAllPosX) aRect.Move(nAllPosX-aRect.Left(),0);
730 if (bAllPosY) aRect.Move(0,nAllPosY-aRect.Top());
731 if (bAllWdt) aRect.SetRight(aAllSnapRect.Left()+nAllWdt );
732 if (bAllHgt) aRect.SetBottom(aAllSnapRect.Top()+nAllHgt );
733 SetMarkedObjRect(aRect);
734 }
735 if (rAttr.GetItemState(SDRATTR_RESIZEXALL,true,&pPoolItem)==SfxItemState::SET) {
63
Assuming the condition is false
64
Taking false branch
736 Fraction aXFact=static_cast<const SdrResizeXAllItem*>(pPoolItem)->GetValue();
737 ResizeMarkedObj(aAllSnapRect.TopLeft(),aXFact,Fraction(1,1));
738 }
739 if (rAttr.GetItemState(SDRATTR_RESIZEYALL,true,&pPoolItem)==SfxItemState::SET) {
65
Assuming the condition is false
66
Taking false branch
740 Fraction aYFact=static_cast<const SdrResizeYAllItem*>(pPoolItem)->GetValue();
741 ResizeMarkedObj(aAllSnapRect.TopLeft(),Fraction(1,1),aYFact);
742 }
743 if (rAttr.GetItemState(SDRATTR_ROTATEALL,true,&pPoolItem)==SfxItemState::SET) {
67
Assuming the condition is true
68
Taking true branch
744 long nAngle=static_cast<const SdrRotateAllItem*>(pPoolItem)->GetValue();
745 RotateMarkedObj(aAllSnapRect.Center(),nAngle);
69
Calling 'SdrEditView::RotateMarkedObj'
746 }
747 if (rAttr.GetItemState(SDRATTR_HORZSHEARALL,true,&pPoolItem)==SfxItemState::SET) {
748 long nAngle=static_cast<const SdrHorzShearAllItem*>(pPoolItem)->GetValue();
749 ShearMarkedObj(aAllSnapRect.Center(),nAngle);
750 }
751 if (rAttr.GetItemState(SDRATTR_VERTSHEARALL,true,&pPoolItem)==SfxItemState::SET) {
752 long nAngle=static_cast<const SdrVertShearAllItem*>(pPoolItem)->GetValue();
753 ShearMarkedObj(aAllSnapRect.Center(),nAngle,true);
754 }
755
756 const bool bUndo = IsUndoEnabled();
757
758 // TODO: check if WhichRange is necessary.
759 const size_t nMarkCount=GetMarkedObjectCount();
760 for (size_t nm=0; nm<nMarkCount; ++nm)
761 {
762 const SdrMark* pM=GetSdrMarkByIndex(nm);
763 SdrObject* pObj=pM->GetMarkedSdrObj();
764 if( bUndo )
765 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
766
767 pObj->ApplyNotPersistAttr(rAttr);
768 }
769}
770
771void SdrEditView::MergeNotPersistAttrFromMarked(SfxItemSet& rAttr) const
772{
773 // TODO: Take into account the origin and PvPos.
774 tools::Rectangle aAllSnapRect(GetMarkedObjRect()); // TODO: change this for PolyPt's and GluePt's!!!
775 long nAllSnapPosX=aAllSnapRect.Left();
776 long nAllSnapPosY=aAllSnapRect.Top();
777 long nAllSnapWdt=aAllSnapRect.GetWidth()-1;
778 long nAllSnapHgt=aAllSnapRect.GetHeight()-1;
779 // TODO: could go into CheckPossibilities
780 bool bMovProtect = false, bMovProtectDC = false;
781 bool bSizProtect = false, bSizProtectDC = false;
782 bool bPrintable = true, bPrintableDC = false;
783 bool bVisible = true, bVisibleDC = false;
784 SdrLayerID nLayerId(0);
785 bool bLayerDC=false;
786 long nSnapPosX=0; bool bSnapPosXDC=false;
787 long nSnapPosY=0; bool bSnapPosYDC=false;
788 long nSnapWdt=0; bool bSnapWdtDC=false;
789 long nSnapHgt=0; bool bSnapHgtDC=false;
790 long nLogicWdt=0; bool bLogicWdtDC=false,bLogicWdtDiff=false;
791 long nLogicHgt=0; bool bLogicHgtDC=false,bLogicHgtDiff=false;
792 long nRotAngle=0; bool bRotAngleDC=false;
793 long nShrAngle=0; bool bShrAngleDC=false;
794 tools::Rectangle aSnapRect;
795 tools::Rectangle aLogicRect;
796 const size_t nMarkCount=GetMarkedObjectCount();
797 for (size_t nm=0; nm<nMarkCount; ++nm) {
798 const SdrMark* pM=GetSdrMarkByIndex(nm);
799 const SdrObject* pObj=pM->GetMarkedSdrObj();
800 if (nm==0) {
801 nLayerId=pObj->GetLayer();
802 bMovProtect=pObj->IsMoveProtect();
803 bSizProtect=pObj->IsResizeProtect();
804 bPrintable =pObj->IsPrintable();
805 bVisible = pObj->IsVisible();
806 tools::Rectangle aSnapRect2(pObj->GetSnapRect());
807 tools::Rectangle aLogicRect2(pObj->GetLogicRect());
808 nSnapPosX=aSnapRect2.Left();
809 nSnapPosY=aSnapRect2.Top();
810 nSnapWdt=aSnapRect2.GetWidth()-1;
811 nSnapHgt=aSnapRect2.GetHeight()-1;
812 nLogicWdt=aLogicRect2.GetWidth()-1;
813 nLogicHgt=aLogicRect2.GetHeight()-1;
814 bLogicWdtDiff=nLogicWdt!=nSnapWdt;
815 bLogicHgtDiff=nLogicHgt!=nSnapHgt;
816 nRotAngle=pObj->GetRotateAngle();
817 nShrAngle=pObj->GetShearAngle();
818 } else {
819 if (!bLayerDC && nLayerId !=pObj->GetLayer()) bLayerDC = true;
820 if (!bMovProtectDC && bMovProtect!=pObj->IsMoveProtect()) bMovProtectDC = true;
821 if (!bSizProtectDC && bSizProtect!=pObj->IsResizeProtect()) bSizProtectDC = true;
822 if (!bPrintableDC && bPrintable !=pObj->IsPrintable()) bPrintableDC = true;
823 if (!bVisibleDC && bVisible !=pObj->IsVisible()) bVisibleDC=true;
824 if (!bRotAngleDC && nRotAngle !=pObj->GetRotateAngle()) bRotAngleDC=true;
825 if (!bShrAngleDC && nShrAngle !=pObj->GetShearAngle()) bShrAngleDC=true;
826 if (!bSnapWdtDC || !bSnapHgtDC || !bSnapPosXDC || !bSnapPosYDC || !bLogicWdtDiff || !bLogicHgtDiff) {
827 aSnapRect=pObj->GetSnapRect();
828 if (nSnapPosX!=aSnapRect.Left()) bSnapPosXDC=true;
829 if (nSnapPosY!=aSnapRect.Top()) bSnapPosYDC=true;
830 if (nSnapWdt!=aSnapRect.GetWidth()-1) bSnapWdtDC=true;
831 if (nSnapHgt!=aSnapRect.GetHeight()-1) bSnapHgtDC=true;
832 }
833 if (!bLogicWdtDC || !bLogicHgtDC || !bLogicWdtDiff || !bLogicHgtDiff) {
834 aLogicRect=pObj->GetLogicRect();
835 if (nLogicWdt!=aLogicRect.GetWidth()-1) bLogicWdtDC=true;
836 if (nLogicHgt!=aLogicRect.GetHeight()-1) bLogicHgtDC=true;
837 if (!bLogicWdtDiff && aSnapRect.GetWidth()!=aLogicRect.GetWidth()) bLogicWdtDiff=true;
838 if (!bLogicHgtDiff && aSnapRect.GetHeight()!=aLogicRect.GetHeight()) bLogicHgtDiff=true;
839 }
840 }
841 }
842
843 if (bSnapPosXDC || nAllSnapPosX!=nSnapPosX) rAttr.Put(SdrAllPositionXItem(nAllSnapPosX));
844 if (bSnapPosYDC || nAllSnapPosY!=nSnapPosY) rAttr.Put(SdrAllPositionYItem(nAllSnapPosY));
845 if (bSnapWdtDC || nAllSnapWdt !=nSnapWdt ) rAttr.Put(SdrAllSizeWidthItem(nAllSnapWdt));
846 if (bSnapHgtDC || nAllSnapHgt !=nSnapHgt ) rAttr.Put(SdrAllSizeHeightItem(nAllSnapHgt));
847
848 // items for pure transformations
849 rAttr.Put(SdrMoveXItem());
850 rAttr.Put(SdrMoveYItem());
851 rAttr.Put(SdrResizeXOneItem());
852 rAttr.Put(SdrResizeYOneItem());
853 rAttr.Put(SdrRotateOneItem());
854 rAttr.Put(SdrHorzShearOneItem());
855 rAttr.Put(SdrVertShearOneItem());
856
857 if (nMarkCount>1) {
858 rAttr.Put(SdrResizeXAllItem());
859 rAttr.Put(SdrResizeYAllItem());
860 rAttr.Put(SdrRotateAllItem());
861 rAttr.Put(SdrHorzShearAllItem());
862 rAttr.Put(SdrVertShearAllItem());
863 }
864
865 if(meDragMode == SdrDragMode::Rotate || meDragMode == SdrDragMode::Mirror)
866 {
867 rAttr.Put(SdrTransformRef1XItem(GetRef1().X()));
868 rAttr.Put(SdrTransformRef1YItem(GetRef1().Y()));
869 }
870
871 if(meDragMode == SdrDragMode::Mirror)
872 {
873 rAttr.Put(SdrTransformRef2XItem(GetRef2().X()));
874 rAttr.Put(SdrTransformRef2YItem(GetRef2().Y()));
875 }
876}
877
878SfxItemSet SdrEditView::GetAttrFromMarked(bool bOnlyHardAttr) const
879{
880 SfxItemSet aSet(mpModel->GetItemPool());
881 MergeAttrFromMarked(aSet,bOnlyHardAttr);
882 //the EE_FEATURE items should not be set with SetAttrToMarked (see error message there)
883 //so we do not set them here
884 // #i32448#
885 // Do not disable, but clear the items.
886 aSet.ClearItem(EE_FEATURE_TAB);
887 aSet.ClearItem(EE_FEATURE_LINEBR);
888 aSet.ClearItem(EE_FEATURE_NOTCONV);
889 aSet.ClearItem(EE_FEATURE_FIELD);
890
891 return aSet;
892}
893
894void SdrEditView::MergeAttrFromMarked(SfxItemSet& rAttr, bool bOnlyHardAttr) const
895{
896 const size_t nMarkCount(GetMarkedObjectCount());
897
898 for(size_t a = 0; a < nMarkCount; ++a)
899 {
900 // #80277# merging was done wrong in the prev version
901 const SfxItemSet& rSet = GetMarkedObjectByIndex(a)->GetMergedItemSet();
902 SfxWhichIter aIter(rSet);
903 sal_uInt16 nWhich(aIter.FirstWhich());
904
905 while(nWhich)
906 {
907 if(!bOnlyHardAttr)
908 {
909 if(SfxItemState::DONTCARE == rSet.GetItemState(nWhich, false))
910 rAttr.InvalidateItem(nWhich);
911 else
912 rAttr.MergeValue(rSet.Get(nWhich), true);
913 }
914 else if(SfxItemState::SET == rSet.GetItemState(nWhich, false))
915 {
916 const SfxPoolItem& rItem = rSet.Get(nWhich);
917 rAttr.MergeValue(rItem, true);
918 }
919
920 if (comphelper::LibreOfficeKit::isActive())
921 {
922 OUString sPayload;
923 switch(nWhich)
924 {
925 case XATTR_LINECOLOR:
926 {
927 const SfxPoolItem* pItem = rSet.GetItem(XATTR_LINECOLOR);
928 if (pItem)
929 {
930 Color aColor = static_cast<const XLineColorItem*>(pItem)->GetColorValue();
931 sPayload = OUString::number(static_cast<sal_uInt32>(aColor));
932
933 sPayload = ".uno:XLineColor=" + sPayload;
934 }
935 break;
936 }
937
938 case XATTR_FILLCOLOR:
939 {
940 const SfxPoolItem* pItem = rSet.GetItem(XATTR_FILLCOLOR);
941 if (pItem)
942 {
943 Color aColor = static_cast<const XFillColorItem*>(pItem)->GetColorValue();
944 sPayload = OUString::number(static_cast<sal_uInt32>(aColor));
945
946 sPayload = ".uno:FillColor=" + sPayload;
947 }
948 break;
949 }
950
951 case XATTR_FILLTRANSPARENCE:
952 {
953 const SfxPoolItem* pItem = rSet.GetItem(XATTR_FILLTRANSPARENCE);
954 if (pItem)
955 {
956 sal_uInt16 nTransparency = static_cast<const SfxUInt16Item*>(pItem)->GetValue();
957 sPayload = OUString::number(nTransparency);
958
959 sPayload = ".uno:FillTransparence=" + sPayload;
960 }
961 break;
962 }
963
964 case XATTR_LINETRANSPARENCE:
965 {
966 const SfxPoolItem* pItem = rSet.GetItem(XATTR_LINETRANSPARENCE);
967 if (pItem)
968 {
969 sal_uInt16 nTransparency = static_cast<const SfxUInt16Item*>(pItem)->GetValue();
970 sPayload = OUString::number(nTransparency);
971
972 sPayload = ".uno:LineTransparence=" + sPayload;
973 }
974 break;
975 }
976
977 case XATTR_LINEWIDTH:
978 {
979 const SfxPoolItem* pItem = rSet.GetItem(XATTR_LINEWIDTH);
980 if (pItem)
981 {
982 sal_uInt32 nWidth = static_cast<const XLineWidthItem*>(pItem)->GetValue();
983 sPayload = OUString::number(nWidth);
984
985 sPayload = ".uno:LineWidth=" + sPayload;
986 }
987 break;
988 }
989
990 case SDRATTR_SHADOWTRANSPARENCE:
991 {
992 const SfxPoolItem* pItem = rSet.GetItem(SDRATTR_SHADOWTRANSPARENCE);
993 if (pItem)
994 {
995 sal_uInt16 nWidth = static_cast<const SfxUInt16Item*>(pItem)->GetValue();
996 sPayload = OUString::number(nWidth);
997
998 sPayload = ".uno:FillShadowTransparency=" + sPayload;
999 }
1000 break;
1001 }
1002 }
1003
1004 if (!sPayload.isEmpty())
1005 GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED,
1006 OUStringToOString(sPayload, RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11))).getStr());
1007 }
1008
1009 nWhich = aIter.NextWhich();
1010 }
1011 }
1012}
1013
1014std::vector<sal_uInt16> GetAllCharPropIds(const SfxItemSet& rSet)
1015{
1016 std::vector<sal_uInt16> aCharWhichIds;
1017 {
1018 SfxItemIter aIter(rSet);
1019 for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem())
1020 {
1021 if (!IsInvalidItem(pItem))
1022 {
1023 sal_uInt16 nWhich = pItem->Which();
1024 if (nWhich>=EE_CHAR_START && nWhich<=EE_CHAR_END)
1025 aCharWhichIds.push_back( nWhich );
1026 }
1027 }
1028 }
1029 return aCharWhichIds;
1030}
1031
1032void SdrEditView::SetAttrToMarked(const SfxItemSet& rAttr, bool bReplaceAll)
1033{
1034 if (!AreObjectsMarked())
33
Taking false branch
1035 return;
1036
1037#ifdef DBG_UTIL
1038 {
1039 bool bHasEEFeatureItems=false;
1040 SfxItemIter aIter(rAttr);
1041 for (const SfxPoolItem* pItem = aIter.GetCurItem(); !bHasEEFeatureItems && pItem;
1042 pItem = aIter.NextItem())
1043 {
1044 if (!IsInvalidItem(pItem)) {
1045 sal_uInt16 nW=pItem->Which();
1046 if (nW>=EE_FEATURE_START && nW<=EE_FEATURE_END) bHasEEFeatureItems=true;
1047 }
1048 }
1049 if(bHasEEFeatureItems)
1050 {
1051 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(nullptr,
1052 VclMessageType::Info, VclButtonsType::Ok,
1053 "SdrEditView::SetAttrToMarked(): Setting EE_FEATURE items at the SdrView does not make sense! It only leads to overhead and unreadable documents."));
1054 xInfoBox->run();
1055 }
1056 }
1057#endif
1058
1059 // #103836# if the user sets character attributes to the complete shape,
1060 // we want to remove all hard set character attributes with same
1061 // which ids from the text. We do that later but here we remember
1062 // all character attribute which id's that are set.
1063 std::vector<sal_uInt16> aCharWhichIds(GetAllCharPropIds(rAttr));
1064
1065 // To make Undo reconstruct text attributes correctly after Format.Standard
1066 bool bHasEEItems=SearchOutlinerItems(rAttr,bReplaceAll);
1067
1068 // save additional geometry information when paragraph or character attributes
1069 // are changed and the geometrical shape of the text object might be changed
1070 bool bPossibleGeomChange(false);
1071 SfxWhichIter aIter(rAttr);
1072 sal_uInt16 nWhich = aIter.FirstWhich();
1073 while(!bPossibleGeomChange
33.1
'bPossibleGeomChange' is false
&& nWhich)
34
Loop condition is false. Execution continues on line 1091
1074 {
1075 SfxItemState eState = rAttr.GetItemState(nWhich);
1076 if(eState == SfxItemState::SET)
1077 {
1078 if((nWhich >= SDRATTR_TEXT_MINFRAMEHEIGHT && nWhich <= SDRATTR_TEXT_CONTOURFRAME)
1079 || nWhich == SDRATTR_3DOBJ_PERCENT_DIAGONAL
1080 || nWhich == SDRATTR_3DOBJ_BACKSCALE
1081 || nWhich == SDRATTR_3DOBJ_DEPTH
1082 || nWhich == SDRATTR_3DOBJ_END_ANGLE
1083 || nWhich == SDRATTR_3DSCENE_DISTANCE)
1084 {
1085 bPossibleGeomChange = true;
1086 }
1087 }
1088 nWhich = aIter.NextWhich();
1089 }
1090
1091 const bool bUndo = IsUndoEnabled();
1092 if( bUndo )
35
Assuming 'bUndo' is false
36
Taking false branch
1093 {
1094 EndTextEditAllViews();
1095 BegUndo(ImpGetDescriptionString(STR_EditSetAttributesreinterpret_cast<char const *>("STR_EditSetAttributes" "\004"
u8"Apply attributes to %1")
));
1096 }
1097
1098 const size_t nMarkCount(GetMarkedObjectCount());
1099 std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
1100
1101 // create ItemSet without SfxItemState::DONTCARE. Put()
1102 // uses its second parameter (bInvalidAsDefault) to
1103 // remove all such items to set them to default.
1104 SfxItemSet aAttr(*rAttr.GetPool(), rAttr.GetRanges());
1105 aAttr.Put(rAttr);
1106
1107 // #i38135#
1108 bool bResetAnimationTimer(false);
1109
1110 const bool bLineStartWidthExplicitChange(SfxItemState::SET
37
Assuming the condition is true
1111 == aAttr.GetItemState(XATTR_LINESTARTWIDTH));
1112 const bool bLineEndWidthExplicitChange(SfxItemState::SET
38
Assuming the condition is true
1113 == aAttr.GetItemState(XATTR_LINEENDWIDTH));
1114 // check if LineWidth is part of the change
1115 const bool bAdaptStartEndWidths(!(bLineStartWidthExplicitChange
38.1
'bLineStartWidthExplicitChange' is true
&& bLineEndWidthExplicitChange)
1116 && SfxItemState::SET == aAttr.GetItemState(XATTR_LINEWIDTH));
1117 sal_Int32 nNewLineWidth(0);
1118
1119 if(bAdaptStartEndWidths
38.2
'bAdaptStartEndWidths' is false
)
39
Taking false branch
1120 {
1121 nNewLineWidth = aAttr.Get(XATTR_LINEWIDTH).GetValue();
1122 }
1123
1124 for (size_t nm=0; nm<nMarkCount; ++nm)
40
Assuming 'nm' is >= 'nMarkCount'
41
Loop condition is false. Execution continues on line 1230
1125 {
1126 SdrMark* pM=GetSdrMarkByIndex(nm);
1127 SdrObject* pObj = pM->GetMarkedSdrObj();
1128
1129 if( bUndo )
1130 {
1131 SdrEdgeObj* pEdgeObj = dynamic_cast< SdrEdgeObj* >( pObj );
1132 if ( pEdgeObj )
1133 bPossibleGeomChange = true;
1134 else
1135 AddUndoActions( CreateConnectorUndo( *pObj ) );
1136 }
1137
1138 // new geometry undo
1139 if(bPossibleGeomChange && bUndo)
1140 {
1141 // save position and size of object, too
1142 AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
1143 }
1144
1145 if( bUndo )
1146 {
1147 // #i8508#
1148 // If this is a text object also rescue the OutlinerParaObject since
1149 // applying attributes to the object may change text layout when
1150 // multiple portions exist with multiple formats. If an OutlinerParaObject
1151 // really exists and needs to be rescued is evaluated in the undo
1152 // implementation itself.
1153 const bool bRescueText = dynamic_cast< SdrTextObj* >(pObj) != nullptr;
1154
1155 // add attribute undo
1156 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj,false,bHasEEItems || bPossibleGeomChange || bRescueText));
1157 }
1158
1159 // set up a scene updater if object is a 3d object
1160 if(dynamic_cast< E3dObject* >(pObj))
1161 {
1162 aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pObj));
1163 }
1164
1165 sal_Int32 nOldLineWidth(0);
1166 if (bAdaptStartEndWidths)
1167 {
1168 nOldLineWidth = pObj->GetMergedItem(XATTR_LINEWIDTH).GetValue();
1169 }
1170
1171 // set attributes at object
1172 pObj->SetMergedItemSetAndBroadcast(aAttr, bReplaceAll);
1173
1174 if(bAdaptStartEndWidths)
1175 {
1176 const SfxItemSet& rSet = pObj->GetMergedItemSet();
1177
1178 if(nOldLineWidth != nNewLineWidth)
1179 {
1180 if(SfxItemState::DONTCARE != rSet.GetItemState(XATTR_LINESTARTWIDTH))
1181 {
1182 const sal_Int32 nValAct(rSet.Get(XATTR_LINESTARTWIDTH).GetValue());
1183 const sal_Int32 nValNewStart(std::max(sal_Int32(0), nValAct + (((nNewLineWidth - nOldLineWidth) * 15) / 10)));
1184
1185 pObj->SetMergedItem(XLineStartWidthItem(nValNewStart));
1186 }
1187
1188 if(SfxItemState::DONTCARE != rSet.GetItemState(XATTR_LINEENDWIDTH))
1189 {
1190 const sal_Int32 nValAct(rSet.Get(XATTR_LINEENDWIDTH).GetValue());
1191 const sal_Int32 nValNewEnd(std::max(sal_Int32(0), nValAct + (((nNewLineWidth - nOldLineWidth) * 15) / 10)));
1192
1193 pObj->SetMergedItem(XLineEndWidthItem(nValNewEnd));
1194 }
1195 }
1196 }
1197
1198 if(dynamic_cast<const SdrTextObj*>( pObj) != nullptr)
1199 {
1200 SdrTextObj* pTextObj = static_cast<SdrTextObj*>(pObj);
1201
1202 if(!aCharWhichIds.empty())
1203 {
1204 tools::Rectangle aOldBoundRect = pTextObj->GetLastBoundRect();
1205
1206 // #110094#-14 pTextObj->SendRepaintBroadcast(pTextObj->GetBoundRect());
1207 pTextObj->RemoveOutlinerCharacterAttribs( aCharWhichIds );
1208
1209 // object has changed, should be called from
1210 // RemoveOutlinerCharacterAttribs. This will change when the text
1211 // object implementation changes.
1212 pTextObj->SetChanged();
1213
1214 pTextObj->BroadcastObjectChange();
1215 pTextObj->SendUserCall(SdrUserCallType::ChangeAttr, aOldBoundRect);
1216 }
1217 }
1218
1219 // #i38495#
1220 if(!bResetAnimationTimer)
1221 {
1222 if(pObj->GetViewContact().isAnimatedInAnyViewObjectContact())
1223 {
1224 bResetAnimationTimer = true;
1225 }
1226 }
1227 }
1228
1229 // fire scene updaters
1230 while(!aUpdaters.empty())
42
Assuming the condition is false
43
Loop condition is false. Execution continues on line 1237
1231 {
1232 delete aUpdaters.back();
1233 aUpdaters.pop_back();
1234 }
1235
1236 // #i38135#
1237 if(bResetAnimationTimer
43.1
'bResetAnimationTimer' is false
)
44
Taking false branch
1238 {
1239 SetAnimationTimer(0);
1240 }
1241
1242 // better check before what to do:
1243 // pObj->SetAttr() or SetNotPersistAttr()
1244 // TODO: missing implementation!
1245 SetNotPersistAttrToMarked(rAttr);
45
Calling 'SdrEditView::SetNotPersistAttrToMarked'
1246
1247 if( bUndo )
1248 EndUndo();
1249}
1250
1251SfxStyleSheet* SdrEditView::GetStyleSheetFromMarked() const
1252{
1253 SfxStyleSheet* pRet=nullptr;
1254 bool b1st=true;
1255 const size_t nMarkCount=GetMarkedObjectCount();
1256 for (size_t nm=0; nm<nMarkCount; ++nm) {
1257 SdrMark* pM=GetSdrMarkByIndex(nm);
1258 SfxStyleSheet* pSS=pM->GetMarkedSdrObj()->GetStyleSheet();
1259 if (b1st) pRet=pSS;
1260 else if (pRet!=pSS) return nullptr; // different stylesheets
1261 b1st=false;
1262 }
1263 return pRet;
1264}
1265
1266void SdrEditView::SetStyleSheetToMarked(SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr)
1267{
1268 if (!AreObjectsMarked())
1269 return;
1270
1271 const bool bUndo = IsUndoEnabled();
1272
1273 if( bUndo )
1274 {
1275 EndTextEditAllViews();
1276 OUString aStr;
1277 if (pStyleSheet!=nullptr)
1278 aStr = ImpGetDescriptionString(STR_EditSetStylesheetreinterpret_cast<char const *>("STR_EditSetStylesheet" "\004"
u8"Apply Styles to %1")
);
1279 else
1280 aStr = ImpGetDescriptionString(STR_EditDelStylesheetreinterpret_cast<char const *>("STR_EditDelStylesheet" "\004"
u8"Remove Style from %1")
);
1281 BegUndo(aStr);
1282 }
1283
1284 const size_t nMarkCount=GetMarkedObjectCount();
1285 for (size_t nm=0; nm<nMarkCount; ++nm)
1286 {
1287 SdrMark* pM=GetSdrMarkByIndex(nm);
1288 if( bUndo )
1289 {
1290 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pM->GetMarkedSdrObj()));
1291 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pM->GetMarkedSdrObj(),true,true));
1292 }
1293 pM->GetMarkedSdrObj()->SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
1294 }
1295
1296 if( bUndo )
1297 EndUndo();
1298}
1299
1300
1301void SdrEditView::GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const
1302{
1303 if(GetMarkedObjectCount())
1304 {
1305 rTargetSet.Put(GetAttrFromMarked(bOnlyHardAttr), false);
1306 }
1307 else
1308 {
1309 SdrMarkView::GetAttributes(rTargetSet, bOnlyHardAttr);
1310 }
1311}
1312
1313void SdrEditView::SetAttributes(const SfxItemSet& rSet, bool bReplaceAll)
1314{
1315 if (GetMarkedObjectCount()!=0) {
1316 SetAttrToMarked(rSet,bReplaceAll);
1317 } else {
1318 SdrMarkView::SetAttributes(rSet,bReplaceAll);
1319 }
1320}
1321
1322SfxStyleSheet* SdrEditView::GetStyleSheet() const
1323{
1324 if (GetMarkedObjectCount()!=0) {
1325 return GetStyleSheetFromMarked();
1326 } else {
1327 return SdrMarkView::GetStyleSheet();
1328 }
1329}
1330
1331void SdrEditView::SetStyleSheet(SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr)
1332{
1333 if (GetMarkedObjectCount()!=0) {
1334 SetStyleSheetToMarked(pStyleSheet,bDontRemoveHardAttr);
1335 } else {
1336 SdrMarkView::SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
1337 }
1338}
1339
1340
1341SfxItemSet SdrEditView::GetGeoAttrFromMarked() const
1342{
1343 SfxItemSet aRetSet(
1344 mpModel->GetItemPool(),
1345 svl::Items< // SID_ATTR_TRANSFORM_... from s:svxids.hrc
1346 SDRATTR_ECKENRADIUS, SDRATTR_ECKENRADIUS,
1347 SID_ATTR_TRANSFORM_POS_XTypedWhichId<SfxInt32Item>( 10000 + 88 ), SID_ATTR_TRANSFORM_ANGLETypedWhichId<SfxInt32Item>( 10000 + 95 ),
1348 SID_ATTR_TRANSFORM_PROTECT_POSTypedWhichId<SfxBoolItem>( 10000 + 236 ), SID_ATTR_TRANSFORM_AUTOHEIGHT( 10000 + 311 )>{});
1349
1350 if (AreObjectsMarked())
1351 {
1352 SfxItemSet aMarkAttr(GetAttrFromMarked(false)); // because of AutoGrowHeight and corner radius
1353 tools::Rectangle aRect(GetMarkedObjRect());
1354
1355 if(GetSdrPageView())
1356 {
1357 GetSdrPageView()->LogicToPagePos(aRect);
1358 }
1359
1360 // position
1361 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_POS_XTypedWhichId<SfxInt32Item>( 10000 + 88 ),aRect.Left()));
1362 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_POS_YTypedWhichId<SfxInt32Item>( 10000 + 89 ),aRect.Top()));
1363
1364 // size
1365 long nResizeRefX=aRect.Left();
1366 long nResizeRefY=aRect.Top();
1367 if (meDragMode==SdrDragMode::Rotate) { // use rotation axis as a reference for resizing, too
1368 nResizeRefX=maRef1.X();
1369 nResizeRefY=maRef1.Y();
1370 }
1371 aRetSet.Put(SfxUInt32Item(SID_ATTR_TRANSFORM_WIDTHTypedWhichId<SfxUInt32Item>( 10000 + 90 ),aRect.Right()-aRect.Left()));
1372 aRetSet.Put(SfxUInt32Item(SID_ATTR_TRANSFORM_HEIGHTTypedWhichId<SfxUInt32Item>( 10000 + 91 ),aRect.Bottom()-aRect.Top()));
1373 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_RESIZE_REF_X( 10000 + 308 ),nResizeRefX));
1374 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_RESIZE_REF_Y( 10000 + 309 ),nResizeRefY));
1375
1376 Point aRotateAxe(maRef1);
1377
1378 if(GetSdrPageView())
1379 {
1380 GetSdrPageView()->LogicToPagePos(aRotateAxe);
1381 }
1382
1383 // rotation
1384 long nRotateRefX=aRect.Center().X();
1385 long nRotateRefY=aRect.Center().Y();
1386 if (meDragMode==SdrDragMode::Rotate) {
1387 nRotateRefX=aRotateAxe.X();
1388 nRotateRefY=aRotateAxe.Y();
1389 }
1390 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ANGLETypedWhichId<SfxInt32Item>( 10000 + 95 ),GetMarkedObjRotate()));
1391 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ROT_XTypedWhichId<SfxInt32Item>( 10000 + 93 ),nRotateRefX));
1392 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ROT_YTypedWhichId<SfxInt32Item>( 10000 + 94 ),nRotateRefY));
1393
1394 // shearing
1395 long nShearRefX=aRect.Left();
1396 long nShearRefY=aRect.Bottom();
1397 if (meDragMode==SdrDragMode::Rotate) { // use rotation axis as a reference for shearing, too
1398 nShearRefX=aRotateAxe.X();
1399 nShearRefY=aRotateAxe.Y();
1400 }
1401 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR( 10000 + 304 ),GetMarkedObjShear()));
1402 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR_X( 10000 + 305 ),nShearRefX));
1403 aRetSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR_Y( 10000 + 306 ),nShearRefY));
1404
1405 // check every object whether it is protected
1406 const SdrMarkList& rMarkList=GetMarkedObjectList();
1407 const size_t nMarkCount=rMarkList.GetMarkCount();
1408 SdrObject* pObj=rMarkList.GetMark(0)->GetMarkedSdrObj();
1409 bool bPosProt=pObj->IsMoveProtect();
1410 bool bSizProt=pObj->IsResizeProtect();
1411 bool bPosProtDontCare=false;
1412 bool bSizProtDontCare=false;
1413 for (size_t i=1; i<nMarkCount && (!bPosProtDontCare || !bSizProtDontCare); ++i)
1414 {
1415 pObj=rMarkList.GetMark(i)->GetMarkedSdrObj();
1416 if (bPosProt!=pObj->IsMoveProtect()) bPosProtDontCare=true;
1417 if (bSizProt!=pObj->IsResizeProtect()) bSizProtDontCare=true;
1418 }
1419
1420 // InvalidateItem sets item to DONT_CARE
1421 if (bPosProtDontCare) {
1422 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_PROTECT_POSTypedWhichId<SfxBoolItem>( 10000 + 236 ));
1423 } else {
1424 aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_PROTECT_POSTypedWhichId<SfxBoolItem>( 10000 + 236 ),bPosProt));
1425 }
1426 if (bSizProtDontCare) {
1427 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_PROTECT_SIZETypedWhichId<SfxBoolItem>( 10000 + 237 ));
1428 } else {
1429 aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_PROTECT_SIZETypedWhichId<SfxBoolItem>( 10000 + 237 ),bSizProt));
1430 }
1431
1432 SfxItemState eState=aMarkAttr.GetItemState(SDRATTR_TEXT_AUTOGROWWIDTH);
1433 bool bAutoGrow=aMarkAttr.Get(SDRATTR_TEXT_AUTOGROWWIDTH).GetValue();
1434 if (eState==SfxItemState::DONTCARE) {
1435 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_AUTOWIDTH( 10000 + 310 ));
1436 } else if (eState==SfxItemState::SET) {
1437 aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_AUTOWIDTH( 10000 + 310 ),bAutoGrow));
1438 }
1439
1440 eState=aMarkAttr.GetItemState(SDRATTR_TEXT_AUTOGROWHEIGHT);
1441 bAutoGrow=aMarkAttr.Get(SDRATTR_TEXT_AUTOGROWHEIGHT).GetValue();
1442 if (eState==SfxItemState::DONTCARE) {
1443 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_AUTOHEIGHT( 10000 + 311 ));
1444 } else if (eState==SfxItemState::SET) {
1445 aRetSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_AUTOHEIGHT( 10000 + 311 ),bAutoGrow));
1446 }
1447
1448 eState=aMarkAttr.GetItemState(SDRATTR_ECKENRADIUS);
1449 long nRadius=aMarkAttr.Get(SDRATTR_ECKENRADIUS).GetValue();
1450 if (eState==SfxItemState::DONTCARE) {
1451 aRetSet.InvalidateItem(SDRATTR_ECKENRADIUS);
1452 } else if (eState==SfxItemState::SET) {
1453 aRetSet.Put(makeSdrEckenradiusItem(nRadius));
1454 }
1455
1456 basegfx::B2DHomMatrix aTransformation;
1457
1458 if(nMarkCount > 1)
1459 {
1460 // multiple objects, range is collected in aRect
1461 aTransformation = basegfx::utils::createScaleTranslateB2DHomMatrix(
1462 aRect.Left(), aRect.Top(),
1463 aRect.getWidth(), aRect.getHeight());
1464 }
1465 else
1466 {
1467 // single object, get homogen transformation
1468 basegfx::B2DPolyPolygon aPolyPolygon;
1469
1470 pObj->TRGetBaseGeometry(aTransformation, aPolyPolygon);
1471 }
1472
1473 if(aTransformation.isIdentity())
1474 {
1475 aRetSet.InvalidateItem(SID_ATTR_TRANSFORM_MATRIX( 10000 + 1131 ));
1476 }
1477 else
1478 {
1479 css::geometry::AffineMatrix2D aAffineMatrix2D;
1480 Point aPageOffset(0, 0);
1481
1482 if(GetSdrPageView())
1483 {
1484 aPageOffset = GetSdrPageView()->GetPageOrigin();
1485 }
1486
1487 aAffineMatrix2D.m00 = aTransformation.get(0, 0);
1488 aAffineMatrix2D.m01 = aTransformation.get(0, 1);
1489 aAffineMatrix2D.m02 = aTransformation.get(0, 2) - aPageOffset.X();
1490 aAffineMatrix2D.m10 = aTransformation.get(1, 0);
1491 aAffineMatrix2D.m11 = aTransformation.get(1, 1);
1492 aAffineMatrix2D.m12 = aTransformation.get(1, 2) - aPageOffset.Y();
1493
1494 aRetSet.Put(AffineMatrixItem(&aAffineMatrix2D));
1495 }
1496 }
1497
1498 return aRetSet;
1499}
1500
1501static Point ImpGetPoint(const tools::Rectangle& rRect, RectPoint eRP)
1502{
1503 switch(eRP) {
1504 case RectPoint::LT: return rRect.TopLeft();
1505 case RectPoint::MT: return rRect.TopCenter();
1506 case RectPoint::RT: return rRect.TopRight();
1507 case RectPoint::LM: return rRect.LeftCenter();
1508 case RectPoint::MM: return rRect.Center();
1509 case RectPoint::RM: return rRect.RightCenter();
1510 case RectPoint::LB: return rRect.BottomLeft();
1511 case RectPoint::MB: return rRect.BottomCenter();
1512 case RectPoint::RB: return rRect.BottomRight();
1513 }
1514 return Point(); // Should not happen!
1515}
1516
1517void SdrEditView::SetGeoAttrToMarked(const SfxItemSet& rAttr)
1518{
1519 const bool bTiledRendering = comphelper::LibreOfficeKit::isActive();
1520
1521 tools::Rectangle aRect(GetMarkedObjRect());
1522
1523 if(GetSdrPageView())
1
Assuming the condition is false
2
Taking false branch
1524 {
1525 GetSdrPageView()->LogicToPagePos(aRect);
1526 }
1527
1528 long nOldRotateAngle=GetMarkedObjRotate();
1529 long nOldShearAngle=GetMarkedObjShear();
1530 const SdrMarkList& rMarkList=GetMarkedObjectList();
1531 const size_t nMarkCount=rMarkList.GetMarkCount();
1532 SdrObject* pObj=nullptr;
1533
1534 RectPoint eSizePoint=RectPoint::MM;
1535 long nPosDX=0;
1536 long nPosDY=0;
1537 long nSizX=0;
1538 long nSizY=0;
1539 long nRotateAngle=0;
1540
1541 bool bModeIsRotate(meDragMode == SdrDragMode::Rotate);
3
Assuming field 'meDragMode' is not equal to Rotate
1542 long nRotateX(0);
1543 long nRotateY(0);
1544 long nOldRotateX(0);
1545 long nOldRotateY(0);
1546 if(bModeIsRotate
3.1
'bModeIsRotate' is false
)
4
Taking false branch
1547 {
1548 Point aRotateAxe(maRef1);
1549
1550 if(GetSdrPageView())
1551 {
1552 GetSdrPageView()->LogicToPagePos(aRotateAxe);
1553 }
1554
1555 nRotateX = nOldRotateX = aRotateAxe.X();
1556 nRotateY = nOldRotateY = aRotateAxe.Y();
1557 }
1558
1559 long nShearAngle=0;
1560 long nShearX=0;
1561 long nShearY=0;
1562 bool bShearVert=false;
1563
1564 bool bChgPos=false;
1565 bool bChgSiz=false;
1566 bool bChgWdh=false;
1567 bool bChgHgt=false;
1568 bool bRotate=false;
1569 bool bShear =false;
1570
1571 bool bSetAttr=false;
1572 SfxItemSet aSetAttr(mpModel->GetItemPool());
1573
1574 const SfxPoolItem* pPoolItem=nullptr;
1575
1576 // position
1577 if (SfxItemState::SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_POS_XTypedWhichId<SfxInt32Item>( 10000 + 88 ),true,&pPoolItem)) {
5
Assuming the condition is false
6
Taking false branch
1578 nPosDX=static_cast<const SfxInt32Item*>(pPoolItem)->GetValue() - aRect.Left();
1579 bChgPos=true;
1580 }
1581 if (SfxItemState::SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_POS_YTypedWhichId<SfxInt32Item>( 10000 + 89 ),true,&pPoolItem)){
7
Assuming the condition is false
8
Taking false branch
1582 nPosDY=static_cast<const SfxInt32Item*>(pPoolItem)->GetValue() - aRect.Top();
1583 bChgPos=true;
1584 }
1585 // size
1586 if (SfxItemState::SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_WIDTHTypedWhichId<SfxUInt32Item>( 10000 + 90 ),true,&pPoolItem)) {
9
Assuming the condition is false
10
Taking false branch
1587 nSizX=static_cast<const SfxUInt32Item*>(pPoolItem)->GetValue();
1588 bChgSiz=true;
1589 bChgWdh=true;
1590 }
1591 if (SfxItemState::SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_HEIGHTTypedWhichId<SfxUInt32Item>( 10000 + 91 ),true,&pPoolItem)) {
11
Assuming the condition is false
12
Taking false branch
1592 nSizY=static_cast<const SfxUInt32Item*>(pPoolItem)->GetValue();
1593 bChgSiz=true;
1594 bChgHgt=true;
1595 }
1596 if (bChgSiz
12.1
'bChgSiz' is false
) {
13
Taking false branch
1597 if (bTiledRendering && SfxItemState::SET != rAttr.GetItemState(SID_ATTR_TRANSFORM_SIZE_POINTTypedWhichId<SfxUInt16Item>( 10000 + 92 ), true, &pPoolItem))
1598 eSizePoint = RectPoint::LT;
1599 else
1600 eSizePoint = static_cast<RectPoint>(rAttr.Get(SID_ATTR_TRANSFORM_SIZE_POINTTypedWhichId<SfxUInt16Item>( 10000 + 92 )).GetValue());
1601 }
1602
1603 // rotation
1604 if (SfxItemState::SET == rAttr.GetItemState(SID_ATTR_TRANSFORM_DELTA_ANGLETypedWhichId<SfxInt32Item>( 10000 + 96 ), true, &pPoolItem)) {
14
Assuming the condition is false
15
Taking false branch
1605 nRotateAngle = static_cast<const SfxInt32Item*>(pPoolItem)->GetValue();
1606 bRotate = (nRotateAngle != 0);
1607 }
1608
1609 // rotation
1610 if (SfxItemState::SET == rAttr.GetItemState(SID_ATTR_TRANSFORM_ANGLETypedWhichId<SfxInt32Item>( 10000 + 95 ), true, &pPoolItem)) {
16
Assuming the condition is false
17
Taking false branch
1611 nRotateAngle = static_cast<const SfxInt32Item*>(pPoolItem)->GetValue() - nOldRotateAngle;
1612 bRotate = (nRotateAngle != 0);
1613 }
1614
1615 // position rotation point x
1616 if(bRotate
17.1
'bRotate' is false
|| SfxItemState::SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_ROT_XTypedWhichId<SfxInt32Item>( 10000 + 93 ), true ,&pPoolItem))
18
Assuming the condition is false
19
Taking false branch
1617 nRotateX = rAttr.Get(SID_ATTR_TRANSFORM_ROT_XTypedWhichId<SfxInt32Item>( 10000 + 93 )).GetValue();
1618
1619 // position rotation point y
1620 if(bRotate
19.1
'bRotate' is false
|| SfxItemState::SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_ROT_YTypedWhichId<SfxInt32Item>( 10000 + 94 ), true ,&pPoolItem))
20
Assuming the condition is false
21
Taking false branch
1621 nRotateY = rAttr.Get(SID_ATTR_TRANSFORM_ROT_YTypedWhichId<SfxInt32Item>( 10000 + 94 )).GetValue();
1622
1623 // shearing
1624 if (SfxItemState::SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_SHEAR( 10000 + 304 ),true,&pPoolItem)) {
22
Assuming the condition is false
23
Taking false branch
1625 long nNewShearAngle=static_cast<const SfxInt32Item*>(pPoolItem)->GetValue();
1626 if (nNewShearAngle>SDRMAXSHEAR8900) nNewShearAngle=SDRMAXSHEAR8900;
1627 if (nNewShearAngle<-SDRMAXSHEAR8900) nNewShearAngle=-SDRMAXSHEAR8900;
1628 if (nNewShearAngle!=nOldShearAngle) {
1629 bShearVert=static_cast<const SfxBoolItem&>(rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_VERTICAL( 10000 + 307 ))).GetValue();
1630 if (bShearVert) {
1631 nShearAngle=nNewShearAngle;
1632 } else {
1633 if (nNewShearAngle!=0 && nOldShearAngle!=0) {
1634 // bug fix
1635 double nOld = tan(static_cast<double>(nOldShearAngle) * F_PI18000(3.14159265358979323846/18000.0));
1636 double nNew = tan(static_cast<double>(nNewShearAngle) * F_PI18000(3.14159265358979323846/18000.0));
1637 nNew-=nOld;
1638 nNew = atan(nNew) / F_PI18000(3.14159265358979323846/18000.0);
1639 nShearAngle=FRound(nNew);
1640 } else {
1641 nShearAngle=nNewShearAngle-nOldShearAngle;
1642 }
1643 }
1644 bShear=nShearAngle!=0;
1645 if (bShear) {
1646 nShearX=static_cast<const SfxInt32Item&>(rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_X( 10000 + 305 ))).GetValue();
1647 nShearY=static_cast<const SfxInt32Item&>(rAttr.Get(SID_ATTR_TRANSFORM_SHEAR_Y( 10000 + 306 ))).GetValue();
1648 }
1649 }
1650 }
1651
1652 // AutoGrow
1653 if (SfxItemState::SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_AUTOWIDTH( 10000 + 310 ),true,&pPoolItem)) {
24
Assuming the condition is false
25
Taking false branch
1654 bool bAutoGrow=static_cast<const SfxBoolItem*>(pPoolItem)->GetValue();
1655 aSetAttr.Put(makeSdrTextAutoGrowWidthItem(bAutoGrow));
1656 bSetAttr=true;
1657 }
1658
1659 if (SfxItemState::SET==rAttr.GetItemState(SID_ATTR_TRANSFORM_AUTOHEIGHT( 10000 + 311 ),true,&pPoolItem)) {
26
Assuming the condition is false
27
Taking false branch
1660 bool bAutoGrow=static_cast<const SfxBoolItem*>(pPoolItem)->GetValue();
1661 aSetAttr.Put(makeSdrTextAutoGrowHeightItem(bAutoGrow));
1662 bSetAttr=true;
1663 }
1664
1665 // corner radius
1666 if (m_bEdgeRadiusAllowed && SfxItemState::SET==rAttr.GetItemState(SDRATTR_ECKENRADIUS,true,&pPoolItem)) {
28
Assuming field 'm_bEdgeRadiusAllowed' is true
29
Assuming the condition is true
30
Taking true branch
1667 long nRadius=static_cast<const SdrMetricItem*>(pPoolItem)->GetValue();
1668 aSetAttr.Put(makeSdrEckenradiusItem(nRadius));
1669 bSetAttr=true;
1670 }
1671
1672 ForcePossibilities();
1673
1674 BegUndo(SvxResId(STR_EditTransformreinterpret_cast<char const *>("STR_EditTransform" "\004"
u8"Transform %1")
),GetDescriptionOfMarkedObjects());
1675
1676 if (bSetAttr
30.1
'bSetAttr' is true
) {
31
Taking true branch
1677 SetAttrToMarked(aSetAttr,false);
32
Calling 'SdrEditView::SetAttrToMarked'
1678 }
1679
1680 // change size and height
1681 if (bChgSiz && (m_bResizeFreeAllowed || m_bResizePropAllowed)) {
1682 Fraction aWdt(nSizX,aRect.Right()-aRect.Left());
1683 Fraction aHgt(nSizY,aRect.Bottom()-aRect.Top());
1684 Point aRef(ImpGetPoint(aRect,eSizePoint));
1685
1686 if(GetSdrPageView())
1687 {
1688 GetSdrPageView()->PagePosToLogic(aRef);
1689 }
1690
1691 ResizeMultMarkedObj(aRef, aWdt, aHgt, bChgWdh, bChgHgt);
1692 }
1693
1694 // rotate
1695 if (bRotate && (m_bRotateFreeAllowed || m_bRotate90Allowed)) {
1696 Point aRef(nRotateX,nRotateY);
1697
1698 if(GetSdrPageView())
1699 {
1700 GetSdrPageView()->PagePosToLogic(aRef);
1701 }
1702
1703 RotateMarkedObj(aRef,nRotateAngle);
1704 }
1705
1706 // set rotation point position
1707 if(bModeIsRotate && (nRotateX != nOldRotateX || nRotateY != nOldRotateY))
1708 {
1709 Point aNewRef1(nRotateX, nRotateY);
1710
1711 if(GetSdrPageView())
1712 {
1713 GetSdrPageView()->PagePosToLogic(aNewRef1);
1714 }
1715
1716 SetRef1(aNewRef1);
1717 }
1718
1719 // shear
1720 if (bShear && m_bShearAllowed) {
1721 Point aRef(nShearX,nShearY);
1722
1723 if(GetSdrPageView())
1724 {
1725 GetSdrPageView()->PagePosToLogic(aRef);
1726 }
1727
1728 ShearMarkedObj(aRef,nShearAngle,bShearVert);
1729
1730 // #i74358#
1731 // ShearMarkedObj creates a linear combination of the existing transformation and
1732 // the new shear to apply. If the object is already transformed (e.g. rotated) the
1733 // linear combination will not decompose to the same start values again, but to a
1734 // new combination. Thus it makes no sense to check if the wanted shear is reached
1735 // or not. Taking out.
1736 }
1737
1738 // change position
1739 if (bChgPos && m_bMoveAllowed) {
1740 MoveMarkedObj(Size(nPosDX,nPosDY));
1741 }
1742
1743 // protect position
1744 if(SfxItemState::SET == rAttr.GetItemState(SID_ATTR_TRANSFORM_PROTECT_POSTypedWhichId<SfxBoolItem>( 10000 + 236 ), true, &pPoolItem))
1745 {
1746 const bool bProtPos(static_cast<const SfxBoolItem*>(pPoolItem)->GetValue());
1747 bool bChanged(false);
1748
1749 for(size_t i = 0; i < nMarkCount; ++i)
1750 {
1751 pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
1752
1753 if(pObj->IsMoveProtect() != bProtPos)
1754 {
1755 bChanged = true;
1756 pObj->SetMoveProtect(bProtPos);
1757
1758 if(bProtPos)
1759 {
1760 pObj->SetResizeProtect(true);
1761 }
1762 }
1763 }
1764
1765 if(bChanged)
1766 {
1767 m_bMoveProtect = bProtPos;
1768
1769 if(bProtPos)
1770 {
1771 m_bResizeProtect = true;
1772 }
1773
1774 // #i77187# there is no simple method to get the toolbars updated
1775 // in the application. The App is listening to selection change and i
1776 // will use it here (even if not true). It's acceptable since changing
1777 // this model data is pretty rare and only possible using the F4 dialog
1778 MarkListHasChanged();
1779 }
1780 }
1781
1782 if(!m_bMoveProtect)
1783 {
1784 // protect size
1785 if(SfxItemState::SET == rAttr.GetItemState(SID_ATTR_TRANSFORM_PROTECT_SIZETypedWhichId<SfxBoolItem>( 10000 + 237 ), true, &pPoolItem))
1786 {
1787 const bool bProtSize(static_cast<const SfxBoolItem*>(pPoolItem)->GetValue());
1788 bool bChanged(false);
1789
1790 for(size_t i = 0; i < nMarkCount; ++i)
1791 {
1792 pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
1793
1794 if(pObj->IsResizeProtect() != bProtSize)
1795 {
1796 bChanged = true;
1797 pObj->SetResizeProtect(bProtSize);
1798 }
1799 }
1800
1801 if(bChanged)
1802 {
1803 m_bResizeProtect = bProtSize;
1804
1805 // #i77187# see above
1806 MarkListHasChanged();
1807 }
1808 }
1809 }
1810
1811 EndUndo();
1812}
1813
1814
1815bool SdrEditView::IsAlignPossible() const
1816{ // at least two selected objects, at least one of them movable
1817 ForcePossibilities();
1818 const size_t nCount=GetMarkedObjectCount();
1819 if (nCount==0) return false; // nothing selected!
1820 if (nCount==1) return m_bMoveAllowed; // align single object to page
1821 return m_bOneOrMoreMovable; // otherwise: MarkCount>=2
1822}
1823
1824void SdrEditView::AlignMarkedObjects(SdrHorAlign eHor, SdrVertAlign eVert)
1825{
1826 if (eHor==SdrHorAlign::NONE && eVert==SdrVertAlign::NONE)
1827 return;
1828
1829 SortMarkedObjects();
1830 if (!GetMarkedObjectCount())
1831 return;
1832
1833 const bool bUndo = IsUndoEnabled();
1834 if( bUndo )
1835 {
1836 EndTextEditAllViews();
1837 OUString aStr(GetDescriptionOfMarkedObjects());
1838 if (eHor==SdrHorAlign::NONE)
1839 {
1840 switch (eVert)
1841 {
1842 case SdrVertAlign::Top:
1843 aStr = ImpGetDescriptionString(STR_EditAlignVTopreinterpret_cast<char const *>("STR_EditAlignVTop" "\004"
u8"Align %1 to top")
);
1844 break;
1845 case SdrVertAlign::Bottom:
1846 aStr = ImpGetDescriptionString(STR_EditAlignVBottomreinterpret_cast<char const *>("STR_EditAlignVBottom" "\004"
u8"Align %1 to bottom")
);
1847 break;
1848 case SdrVertAlign::Center:
1849 aStr = ImpGetDescriptionString(STR_EditAlignVCenterreinterpret_cast<char const *>("STR_EditAlignVCenter" "\004"
u8"Horizontally center %1")
);
1850 break;
1851 default: break;
1852 }
1853 }
1854 else if (eVert==SdrVertAlign::NONE)
1855 {
1856 switch (eHor)
1857 {
1858 case SdrHorAlign::Left:
1859 aStr = ImpGetDescriptionString(STR_EditAlignHLeftreinterpret_cast<char const *>("STR_EditAlignHLeft" "\004"
u8"Align %1 to left")
);
1860 break;
1861 case SdrHorAlign::Right:
1862 aStr = ImpGetDescriptionString(STR_EditAlignHRightreinterpret_cast<char const *>("STR_EditAlignHRight" "\004"
u8"Align %1 to right")
);
1863 break;
1864 case SdrHorAlign::Center:
1865 aStr = ImpGetDescriptionString(STR_EditAlignHCenterreinterpret_cast<char const *>("STR_EditAlignHCenter" "\004"
u8"Vertically center %1")
);
1866 break;
1867 default: break;
1868 }
1869 }
1870 else if (eHor==SdrHorAlign::Center && eVert==SdrVertAlign::Center)
1871 {
1872 aStr = ImpGetDescriptionString(STR_EditAlignCenterreinterpret_cast<char const *>("STR_EditAlignCenter" "\004"
u8"Center %1")
);
1873 }
1874 else
1875 {
1876 aStr = ImpGetDescriptionString(STR_EditAlignreinterpret_cast<char const *>("STR_EditAlign" "\004" u8"Align %1"
)
);
1877 }
1878 BegUndo(aStr);
1879 }
1880
1881 tools::Rectangle aBound;
1882 const size_t nMarkCount=GetMarkedObjectCount();
1883 bool bHasFixed=false;
1884 for (size_t nm=0; nm<nMarkCount; ++nm)
1885 {
1886 SdrMark* pM=GetSdrMarkByIndex(nm);
1887 SdrObject* pObj=pM->GetMarkedSdrObj();
1888 SdrObjTransformInfoRec aInfo;
1889 pObj->TakeObjInfo(aInfo);
1890 if (!aInfo.bMoveAllowed || pObj->IsMoveProtect())
1891 {
1892 tools::Rectangle aObjRect(pObj->GetSnapRect());
1893 aBound.Union(aObjRect);
1894 bHasFixed=true;
1895 }
1896 }
1897 if (!bHasFixed)
1898 {
1899 if (nMarkCount==1)
1900 { // align single object to page
1901 const SdrObject* pObj=GetMarkedObjectByIndex(0);
1902 const SdrPage* pPage=pObj->getSdrPageFromSdrObject();
1903 const SdrPageGridFrameList* pGFL=pPage->GetGridFrameList(GetSdrPageViewOfMarkedByIndex(0),&(pObj->GetSnapRect()));
1904 const SdrPageGridFrame* pFrame=nullptr;
1905 if (pGFL!=nullptr && pGFL->GetCount()!=0)
1906 { // Writer
1907 pFrame=&((*pGFL)[0]);
1908 }
1909
1910 if (pFrame!=nullptr)
1911 { // Writer
1912 aBound=pFrame->GetUserArea();
1913 }
1914 else
1915 {
1916 aBound=tools::Rectangle(pPage->GetLeftBorder(),pPage->GetUpperBorder(),
1917 pPage->GetWidth()-pPage->GetRightBorder(),
1918 pPage->GetHeight()-pPage->GetLowerBorder());
1919 }
1920 }
1921 else
1922 {
1923 aBound=GetMarkedObjRect();
1924 }
1925 }
1926 Point aCenter(aBound.Center());
1927 for (size_t nm=0; nm<nMarkCount; ++nm)
1928 {
1929 SdrMark* pM=GetSdrMarkByIndex(nm);
1930 SdrObject* pObj=pM->GetMarkedSdrObj();
1931 SdrObjTransformInfoRec aInfo;
1932 pObj->TakeObjInfo(aInfo);
1933 if (aInfo.bMoveAllowed && !pObj->IsMoveProtect())
1934 {
1935 long nXMov=0;
1936 long nYMov=0;
1937 tools::Rectangle aObjRect(pObj->GetSnapRect());
1938 switch (eVert)
1939 {
1940 case SdrVertAlign::Top : nYMov=aBound.Top() -aObjRect.Top() ; break;
1941 case SdrVertAlign::Bottom: nYMov=aBound.Bottom()-aObjRect.Bottom() ; break;
1942 case SdrVertAlign::Center: nYMov=aCenter.Y() -aObjRect.Center().Y(); break;
1943 default: break;
1944 }
1945 switch (eHor)
1946 {
1947 case SdrHorAlign::Left : nXMov=aBound.Left() -aObjRect.Left() ; break;
1948 case SdrHorAlign::Right : nXMov=aBound.Right() -aObjRect.Right() ; break;
1949 case SdrHorAlign::Center: nXMov=aCenter.X() -aObjRect.Center().X(); break;
1950 default: break;
1951 }
1952 if (nXMov!=0 || nYMov!=0)
1953 {
1954 // SdrEdgeObj needs an extra SdrUndoGeoObj since the
1955 // connections may need to be saved
1956 if( bUndo )
1957 {
1958 if( dynamic_cast<SdrEdgeObj*>(pObj) )
1959 {
1960 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
1961 }
1962
1963 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoMoveObject(*pObj,Size(nXMov,nYMov)));
1964 }
1965
1966 pObj->Move(Size(nXMov,nYMov));
1967 }
1968 }
1969 }
1970
1971 if( bUndo )
1972 EndUndo();
1973}
1974
1975/* vim:set shiftwidth=4 softtabstop=4 expandtab: */