Bug Summary

File:home/maarten/src/libreoffice/core/svx/source/svdraw/svdedtv1.cxx
Warning:line 1135, column 33
Forming reference to null pointer

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

/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 )
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)
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)
317 {
318 std::vector< E3DModifySceneSnapRectUpdater* > aUpdaters;
319
320 for(size_t nm = 0; nm < nMarkCount; ++nm)
321 {
322 SdrMark* pM = GetSdrMarkByIndex(nm);
323 SdrObject* pO = pM->GetMarkedSdrObj();
324
325 if( bUndo )
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))
335 {
336 aUpdaters.push_back(new E3DModifySceneSnapRectUpdater(pO));
337 }
338
339 pO->Rotate(rRef,nAngle,nSin,nCos);
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) {
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) {
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) {
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) {
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) {
712 nAllPosX=static_cast<const SdrAllPositionXItem*>(pPoolItem)->GetValue();
713 bAllPosX=true; bDoIt=true;
714 }
715 if (rAttr.GetItemState(SDRATTR_ALLPOSITIONY,true,&pPoolItem)==SfxItemState::SET) {
716 nAllPosY=static_cast<const SdrAllPositionYItem*>(pPoolItem)->GetValue();
717 bAllPosY=true; bDoIt=true;
718 }
719 if (rAttr.GetItemState(SDRATTR_ALLSIZEWIDTH,true,&pPoolItem)==SfxItemState::SET) {
720 nAllWdt=static_cast<const SdrAllSizeWidthItem*>(pPoolItem)->GetValue();
721 bAllWdt=true; bDoIt=true;
722 }
723 if (rAttr.GetItemState(SDRATTR_ALLSIZEHEIGHT,true,&pPoolItem)==SfxItemState::SET) {
724 nAllHgt=static_cast<const SdrAllSizeHeightItem*>(pPoolItem)->GetValue();
725 bAllHgt=true; bDoIt=true;
726 }
727 if (bDoIt) {
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) {
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) {
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) {
744 long nAngle=static_cast<const SdrRotateAllItem*>(pPoolItem)->GetValue();
745 RotateMarkedObj(aAllSnapRect.Center(),nAngle);
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
Calling 'SdrMarkView::AreObjectsMarked'
36
Returning from 'SdrMarkView::AreObjectsMarked'
37
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
37.1
'bPossibleGeomChange' is false
37.1
'bPossibleGeomChange' is false
&& nWhich)
38
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 )
39
Assuming 'bUndo' is true
40
Taking true 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
41
Assuming the condition is true
1111 == aAttr.GetItemState(XATTR_LINESTARTWIDTH));
1112 const bool bLineEndWidthExplicitChange(SfxItemState::SET
42
Assuming the condition is true
1113 == aAttr.GetItemState(XATTR_LINEENDWIDTH));
1114 // check if LineWidth is part of the change
1115 const bool bAdaptStartEndWidths(!(bLineStartWidthExplicitChange
42.1
'bLineStartWidthExplicitChange' is true
42.1
'bLineStartWidthExplicitChange' is true
&& bLineEndWidthExplicitChange)
1116 && SfxItemState::SET == aAttr.GetItemState(XATTR_LINEWIDTH));
1117 sal_Int32 nNewLineWidth(0);
1118
1119 if(bAdaptStartEndWidths
42.2
'bAdaptStartEndWidths' is false
42.2
'bAdaptStartEndWidths' is false
)
43
Taking false branch
1120 {
1121 nNewLineWidth = aAttr.Get(XATTR_LINEWIDTH).GetValue();
1122 }
1123
1124 for (size_t nm=0; nm<nMarkCount; ++nm)
44
Assuming 'nm' is < 'nMarkCount'
45
Loop condition is true. Entering loop body
1125 {
1126 SdrMark* pM=GetSdrMarkByIndex(nm);
1127 SdrObject* pObj = pM->GetMarkedSdrObj();
46
'pObj' initialized here
1128
1129 if( bUndo
46.1
'bUndo' is true
46.1
'bUndo' is true
)
47
Taking true branch
1130 {
1131 SdrEdgeObj* pEdgeObj = dynamic_cast< SdrEdgeObj* >( pObj );
1132 if ( pEdgeObj )
48
Assuming 'pEdgeObj' is null
49
Taking false branch
1133 bPossibleGeomChange = true;
1134 else
1135 AddUndoActions( CreateConnectorUndo( *pObj ) );
50
Forming reference to null pointer
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())
1231 {
1232 delete aUpdaters.back();
1233 aUpdaters.pop_back();
1234 }
1235
1236 // #i38135#
1237 if(bResetAnimationTimer)
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);
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
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
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
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
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
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: */

/home/maarten/src/libreoffice/core/include/svx/svdmrkv.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_SVDMRKV_HXX
21#define INCLUDED_SVX_SVDMRKV_HXX
22
23#include <svx/svdmark.hxx>
24#include <svx/svdhdl.hxx>
25#include <svx/svdsnpv.hxx>
26#include <svx/svdtypes.hxx>
27#include <svx/svxdllapi.h>
28#include <o3tl/typed_flags_set.hxx>
29#include <basegfx/range/b2drectangle.hxx>
30
31
32class SfxViewShell;
33
34// The following is not yet implemented, or just partially:
35enum class SdrSearchOptions
36{
37 NONE = 0x0000,
38 DEEP = 0x0001, /* recursive into group objects */
39 ALSOONMASTER = 0x0002, /* MasterPages are also scanned */
40 WHOLEPAGE = 0x0004, /* Not just the ObjList of PageView */
41 TESTMARKABLE = 0x0008, /* just markable objects/points/handles/... */
42 TESTMACRO = 0x0010, /* Just objects with macro */
43 TESTTEXTEDIT = 0x0020, /* Just TextEdit-enabled objects */
44 MARKED = 0x0040, /* Just marked objects/points/... */
45 PASS2BOUND = 0x0080, /* In case of empty search results, then 2nd. try with BoundRectHit */
46 BEFOREMARK = 0x0100, /* if one marked one found, ignore all behind that */
47
48 IMPISMASTER = 0x0200, /* MasterPage is being searched right now */
49 PICKMARKABLE = TESTMARKABLE,
50 PICKTEXTEDIT = DEEP | TESTMARKABLE | TESTTEXTEDIT,
51 PICKMACRO = DEEP | ALSOONMASTER | WHOLEPAGE | TESTMACRO,
52};
53namespace o3tl
54{
55 template<> struct typed_flags<SdrSearchOptions> : is_typed_flags<SdrSearchOptions, 0x03ff> {};
56}
57
58enum class SdrHitKind
59{
60 NONE, // No hit
61 Object, // Hit
62 Handle, // Marking handle
63 HelpLine, // Reference line
64 Gluepoint, // Glue point
65 TextEdit, // Open OutlinerView was hit
66 TextEditObj, // Object for SdrBeginTextEdit (Textbereich)
67 UrlField, // Field in TextObj was hit (while it is currently not edited)
68 Macro, // Object for BegMacroObj
69 MarkedObject, // Marked object (e.g. for dragging)
70 UnmarkedObject, // non-marked Object (e.g. for marking)
71 Cell // hit on a cell inside a table shape (outside of the cells text area)
72};
73
74enum class SdrViewEditMode {
75 Edit, // Also known as arrow or pointer mode
76 Create, // Tool for object creation
77 GluePointEdit // Glue point editing mode
78};
79
80/** options for ImpGetDescriptionString() */
81enum class ImpGetDescriptionOptions
82{
83 NONE = 0,
84 POINTS = 1,
85 GLUEPOINTS = 2,
86};
87
88class ImplMarkingOverlay;
89class MarkingSubSelectionOverlay;
90
91class SVXCORE_DLLPUBLIC__attribute__ ((visibility("default"))) SdrMarkView : public SdrSnapView
92{
93 friend class SdrPageView;
94
95 // #114409#-3 Migrate selections
96 std::unique_ptr<ImplMarkingOverlay> mpMarkObjOverlay;
97 std::unique_ptr<ImplMarkingOverlay> mpMarkPointsOverlay;
98 std::unique_ptr<ImplMarkingOverlay> mpMarkGluePointsOverlay;
99
100 std::unique_ptr<MarkingSubSelectionOverlay> mpMarkingSubSelectionOverlay;
101
102protected:
103 SdrObject* mpMarkedObj; // If not just one object ( i.e. More than one object ) is marked.
104 SdrPageView* mpMarkedPV; // If all marked objects are situated on the same PageView.
105
106 Point maRef1; // Persistent - Rotation center / axis of reflection
107 Point maRef2; // Persistent
108 SdrHdlList maHdlList;
109
110 sdr::ViewSelection maSdrViewSelection;
111
112 std::vector<basegfx::B2DRectangle> maSubSelectionList;
113 tools::Rectangle maMarkedObjRect;
114 tools::Rectangle maMarkedPointsRect;
115 tools::Rectangle maMarkedGluePointsRect;
116
117 static constexpr sal_uInt16 mnFrameHandlesLimit = 50;
118
119 SdrDragMode meDragMode; // Persistent
120 SdrViewEditMode meEditMode; // Persistent
121 SdrViewEditMode meEditMode0; // Persistent
122
123 bool mbDesignMode : 1; // DesignMode for SdrUnoObj
124 bool mbForceFrameHandles : 1; // Persistent - FrameDrag also for single objects
125 bool mbPlusHdlAlways : 1; // Persistent
126 bool mbInsPolyPoint : 1; // at this time InsPolyPointDragging
127 bool mbMarkedObjRectDirty : 1;
128 bool mbMrkPntDirty : 1;
129 bool mbMarkedPointsRectsDirty : 1;
130
131 // flag to completely disable handles at the view
132 bool mbMarkHandlesHidden : 1;
133
134 // Helper to get a possible GridOffset from SdrObject
135 bool getPossibleGridOffsetForSdrObject(
136 basegfx::B2DVector& rOffset,
137 const SdrObject* pObj,
138 const SdrPageView* pPV) const;
139
140 // Helper to get a possible GridOffset from Position
141 bool getPossibleGridOffsetForPosition(
142 basegfx::B2DVector& rOffset,
143 const basegfx::B2DPoint& rPoint,
144 const SdrPageView* pPV) const;
145
146private:
147 SVX_DLLPRIVATE__attribute__ ((visibility("hidden"))) void ImpSetPointsRects() const;
148 void UndirtyMrkPnt() const;
149
150 void SetMarkHandlesForLOKit(tools::Rectangle const & rRect, const SfxViewShell* pOtherShell);
151
152protected:
153 virtual void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override;
154 virtual void ModelHasChanged() override; // Is called by the PaintView
155 virtual void SetMarkHandles(SfxViewShell* pOtherShell); // maHdlList - fill (List of handles)
156 void SetMarkRects(); // Rects at the PageViews
157 void CheckMarked(); // Scan MarkList after Del and Lock Layer ...
158 void AddDragModeHdl(SdrDragMode eMode);
159 virtual bool MouseMove(const MouseEvent& rMEvt, OutputDevice* pWin) override;
160 virtual bool RequestHelp(const HelpEvent& rHEvt) override;
161
162 // add custom handles (used by other apps, e.g. AnchorPos)
163 virtual void AddCustomHdl();
164
165 void ForceRefToMarked();
166 void ForceUndirtyMrkPnt() const { if (mbMrkPntDirty) UndirtyMrkPnt(); }
167
168 virtual SdrObject* CheckSingleSdrObjectHit(const Point& rPnt, sal_uInt16 nTol, SdrObject* pObj, SdrPageView* pPV, SdrSearchOptions nOptions, const SdrLayerIDSet* pMVisLay) const;
169 SdrObject* CheckSingleSdrObjectHit(const Point& rPnt, sal_uInt16 nTol, SdrObjList const * pOL, SdrPageView* pPV, SdrSearchOptions nOptions, const SdrLayerIDSet* pMVisLay, SdrObject*& rpRootObj) const;
170 SdrObject* CheckSingleSdrObjectHit(const Point& rPnt, sal_uInt16 nTol, SdrObjList const * pOL, SdrPageView* pPV, SdrSearchOptions nOptions, const SdrLayerIDSet* pMVisLay, SdrObject*& rpRootObj,const SdrMarkList * pMarkList) const;
171 bool ImpIsFrameHandles() const;
172 OUString ImpGetDescriptionString(const char* pStrCacheID, ImpGetDescriptionOptions nOpt=ImpGetDescriptionOptions::NONE) const;
173
174 // Generates a string including degrees symbol, from an angel specification in 1/100deg
175 bool ImpMarkPoint(SdrHdl* pHdl, SdrMark* pMark, bool bUnmark);
176 virtual bool MarkPoints(const tools::Rectangle* pRect, bool bUnmark);
177 bool MarkGluePoints(const tools::Rectangle* pRect, bool bUnmark);
178
179 void SetMoveOutside(bool bOn);
180 bool MarkableObjectsExceed( int n ) const;
181
182protected:
183 // #i71538# make constructors of SdrView sub-components protected to avoid incomplete incarnations which may get casted to SdrView
184 SdrMarkView(
185 SdrModel& rSdrModel,
186 OutputDevice* pOut);
187
188 virtual ~SdrMarkView() override;
189
190public:
191 virtual bool IsAction() const override;
192 virtual void MovAction(const Point& rPnt) override;
193 virtual void EndAction() override;
194 virtual void BckAction() override;
195 virtual void BrkAction() override;
196 virtual void TakeActionRect(tools::Rectangle& rRect) const override;
197
198 virtual void ClearPageView() override;
199 virtual void HideSdrPage() override;
200 bool IsObjMarkable(SdrObject const * pObj, SdrPageView const * pPV) const;
201
202 // Returns sal_True if objects, points or glue points are selected by drawing a frame
203 // (as long as the frame is drawn).
204 bool IsMarking() const { return IsMarkObj() || IsMarkPoints() || IsMarkGluePoints(); }
205
206 // Marking objects by drawing of a selection frame
207 void BegMarkObj(const Point& rPnt, bool bUnmark = false);
208 void MovMarkObj(const Point& rPnt);
209 bool EndMarkObj();
210 void BrkMarkObj();
211 bool IsMarkObj() const { return (nullptr != mpMarkObjOverlay); }
212
213 // DragModes: SDRDRAG_CREATE,SdrDragMode::Move,SdrDragMode::Resize,SdrDragMode::Rotate,SdrDragMode::Mirror,SdrDragMode::Shear,SdrDragMode::Crook
214 // Move==Resize
215 // The interface might maybe be changed in the future because of Ortho-Drag
216 void SetDragMode(SdrDragMode eMode);
217 SdrDragMode GetDragMode() const { return meDragMode; }
218 void SetFrameHandles(bool bOn);
219 bool IsFrameHandles() const { return mbForceFrameHandles; }
220
221 // returns true if number of markable objects is greater than 1
222 bool HasMultipleMarkableObjects() const { return MarkableObjectsExceed(1); };
223
224 void SetEditMode(SdrViewEditMode eMode);
225 SdrViewEditMode GetEditMode() const { return meEditMode; }
226
227 void SetEditMode(bool bOn) { SetEditMode(bOn?SdrViewEditMode::Edit:SdrViewEditMode::Create); }
228 bool IsEditMode() const { return meEditMode==SdrViewEditMode::Edit; }
229 void SetCreateMode(bool bOn) { SetEditMode(bOn?SdrViewEditMode::Create:SdrViewEditMode::Edit); }
230 bool IsCreateMode() const { return meEditMode==SdrViewEditMode::Create; }
231 void SetGluePointEditMode(bool bOn) { SetEditMode(bOn?SdrViewEditMode::GluePointEdit:meEditMode0); }
232 bool IsGluePointEditMode() const { return meEditMode==SdrViewEditMode::GluePointEdit; }
233
234 void SetDesignMode(bool bOn = true);
235 bool IsDesignMode() const { return mbDesignMode; }
236
237 void SetFrameDragSingles(bool bOn=true) { SetFrameHandles(bOn); }
238 bool IsFrameDragSingles() const { return IsFrameHandles(); }
239
240 bool HasMarkableObj() const { return MarkableObjectsExceed(0); };
241
242
243// migrate selections
244
245protected:
246 // all available changing methods
247 SdrMarkList& GetMarkedObjectListWriteAccess() { return maSdrViewSelection.GetMarkedObjectListWriteAccess(); }
248
249public:
250 // all available const methods for read access to selection
251 const SdrMarkList& GetMarkedObjectList() const { return maSdrViewSelection.GetMarkedObjectList(); }
252 // returns SAL_MAX_SIZE if not found
253 size_t TryToFindMarkedObject(const SdrObject* pObj) const { return GetMarkedObjectList().FindObject(pObj); }
254 SdrPageView* GetSdrPageViewOfMarkedByIndex(size_t nNum) const { return GetMarkedObjectList().GetMark(nNum)->GetPageView(); }
255 SdrMark* GetSdrMarkByIndex(size_t nNum) const { return GetMarkedObjectList().GetMark(nNum); }
256 SdrObject* GetMarkedObjectByIndex(size_t nNum) const { return GetMarkedObjectList().GetMark(nNum)->GetMarkedSdrObj(); }
257 size_t GetMarkedObjectCount() const { return GetMarkedObjectList().GetMarkCount(); }
258 void SortMarkedObjects() const { GetMarkedObjectList().ForceSort(); }
259 bool AreObjectsMarked() const { return 0 != GetMarkedObjectList().GetMarkCount(); }
34
Assuming the condition is true
35
Returning the value 1, which participates in a condition later
260 OUString const & GetDescriptionOfMarkedObjects() const { return GetMarkedObjectList().GetMarkDescription(); }
261 OUString const & GetDescriptionOfMarkedPoints() const { return GetMarkedObjectList().GetPointMarkDescription(); }
262 OUString const & GetDescriptionOfMarkedGluePoints() const { return GetMarkedObjectList().GetGluePointMarkDescription(); }
263
264 // Get a list of all those links which are connected to marked nodes,
265 // but which are not marked themselves.
266 const SdrMarkList& GetEdgesOfMarkedNodes() const { return maSdrViewSelection.GetEdgesOfMarkedNodes(); }
267 const SdrMarkList& GetMarkedEdgesOfMarkedNodes() const { return maSdrViewSelection.GetMarkedEdgesOfMarkedNodes(); }
268 const std::vector<SdrObject*>& GetTransitiveHullOfMarkedObjects() const { return maSdrViewSelection.GetAllMarkedObjects(); }
269
270
271 // mechanism to complete disable handles at the view. Handles will be hidden and deleted
272 // when set, no new ones created, no interaction allowed. Handles will be recreated and shown
273 // when reset. Default is false.
274 void hideMarkHandles();
275 void showMarkHandles();
276 bool areMarkHandlesHidden() const { return mbMarkHandlesHidden; }
277
278 bool IsMarkedHit(const Point& rPnt, short nTol=-2) const { return IsMarkedObjHit(rPnt,nTol); }
279 bool IsMarkedObjHit(const Point& rPnt, short nTol=-2) const;
280
281 SdrHdl* PickHandle(const Point& rPnt) const;
282
283 // Pick: Supported options for nOptions are:
284 // SdrSearchOptions::DEEP SdrSearchOptions::ALSOONMASTER SdrSearchOptions::TESTMARKABLE SdrSearchOptions::TESTTEXTEDIT
285 // SdrSearchOptions::MARKED
286 // SdrSearchOptions::WHOLEPAGE
287 SdrObject* PickObj(const Point& rPnt, short nTol, SdrPageView*& rpPV, SdrSearchOptions nOptions, SdrObject** ppRootObj, bool* pbHitPassDirect=nullptr) const;
288 SdrObject* PickObj(const Point& rPnt, short nTol, SdrPageView*& rpPV, SdrSearchOptions nOptions=SdrSearchOptions::NONE) const;
289 bool MarkObj(const Point& rPnt, short nTol=-2, bool bToggle=false, bool bDeep=false);
290
291 // Pick: Supported options for nOptions are SdrSearchOptions::PASS2BOUND
292 bool PickMarkedObj(const Point& rPnt, SdrObject*& rpObj, SdrPageView*& rpPV, SdrSearchOptions nOptions) const;
293
294 // Selects the most upper of the marked objects (O1) and scans from there
295 // towards bottom direction, selecting the first non-marked object (O2).
296 // In case of success the marking of O1 is deleted, a marking is created at
297 // O2 and TRUE is returned. With the parameter bPrev=sal_True the scan
298 // direction is turned to the other direction.
299 bool MarkNextObj(bool bPrev=false);
300
301 // Selects the most upper of the marked objects which is hit by rPnt/nTol
302 // and scans from there to bottom direction, selecting the first non-marked
303 // object (O2). In case of success the marking of O1 is deleted, a marking
304 // is created at O2 and sal_True is returned. With the parameter
305 // bPrev=sal_True the scan direction is turned to the other direction.
306 bool MarkNextObj(const Point& rPnt, short nTol, bool bPrev);
307
308 // Mark all objects within a rectangular area
309 // Just objects are marked which are inclosed completely
310 void MarkObj(const tools::Rectangle& rRect, bool bUnmark);
311 void MarkObj(SdrObject* pObj, SdrPageView* pPV, bool bUnmark = false, bool bDoNoSetMarkHdl = false,
312 std::vector<basegfx::B2DRectangle> const & rSubSelections = std::vector<basegfx::B2DRectangle>());
313 void MarkAllObj(SdrPageView* pPV=nullptr); // pPage=NULL => all displayed pages
314 void UnmarkAllObj(SdrPageView const * pPV=nullptr); // pPage=NULL => all displayed pages
315
316 // This function is time-consuming intensive, as the MarkList has to be scanned.
317 bool IsObjMarked(SdrObject const * pObj) const;
318 void UnMarkAll(SdrPageView const * pPV=nullptr) { UnmarkAllObj(pPV); }
319
320 // Request/set the size of the marking handles. Declaration in Pixel.
321 // The value is meant to be the edge length ( link length ).
322 // Pair values are round up to impair values: 3->3, 4->5, 5->5, 6->7, 7->7, ...
323 // Default value is 7, minimum value is 3 Pixels.
324 sal_uInt16 GetMarkHdlSizePixel() const;
325 void SetMarkHdlSizePixel(sal_uInt16 nSiz);
326
327 virtual bool HasMarkablePoints() const;
328 virtual sal_Int32 GetMarkablePointCount() const;
329 virtual bool HasMarkedPoints() const;
330
331 // There might be points which can't be marked:
332 bool IsPointMarkable(const SdrHdl& rHdl) const;
333 virtual bool MarkPoint(SdrHdl& rHdl, bool bUnmark=false);
334
335 /** should only be used from outside svx for special ui elements */
336 bool MarkPointHelper(SdrHdl* pHdl, SdrMark* pMark, bool bUnmark);
337
338 bool UnmarkPoint(SdrHdl& rHdl) { return MarkPoint(rHdl,true); }
339 bool IsPointMarked(const SdrHdl& rHdl) const { ForceUndirtyMrkPnt(); return rHdl.IsSelected(); }
340 bool MarkAllPoints() { return MarkPoints(nullptr,false); }
341 bool UnmarkAllPoints() { return MarkPoints(nullptr,true); }
342
343 // Selects the first marked point (P1) which is hit by rPnt
344 // and from there it searches the first non-marked point(P2).
345 // In case of success the marking of
346 // P1 is deleted, a mark is set at P2.
347 void MarkNextPoint();
348
349 // Search for the number of the suitable handle. In case of empty search result,
350 // SAL_MAX_SIZE is returned.
351 size_t GetHdlNum(SdrHdl const * pHdl) const { return maHdlList.GetHdlNum(pHdl); }
352 SdrHdl* GetHdl(size_t nHdlNum) const { return maHdlList.GetHdl(nHdlNum); }
353 const SdrHdlList& GetHdlList() const { return maHdlList; }
354
355 // Draw a selection frame for marking of points.
356 // This routine will just be started in case that HasMarkablePoints() returns sal_True.
357 bool BegMarkPoints(const Point& rPnt, bool bUnmark = false);
358 void MovMarkPoints(const Point& rPnt);
359 bool EndMarkPoints();
360 void BrkMarkPoints();
361 bool IsMarkPoints() const { return (nullptr != mpMarkPointsOverlay); }
362
363 // Select that additional handles are displayed permanently.
364 void SetPlusHandlesAlwaysVisible(bool bOn);
365 bool IsPlusHandlesAlwaysVisible() const { return mbPlusHdlAlways; }
366
367 bool HasMarkableGluePoints() const;
368 bool HasMarkedGluePoints() const;
369
370 // A gluepoint is clearly identified by the SdrObject
371 // (to which it belongs) as well as by a sal_uInt16 nId (as each SdrObject may consist of
372 // several glue points. Here at the View there is an additional
373 // SdrPageView, which should be defined correctly always.
374 // Alternatively a gluepoint may be characterized by a SdrHdl.
375 // In this case the SdrHdl instance consists of all required information.
376 // And in this case, the glue point are always is marked by enforcement
377 // (Handlers are just situated at marked gluepoints )
378 // Attention: With each change of the glue point status the handle list is re-calculated.
379 // All previously saved SdrHdl* became invalid by this, the same with the point IDs!
380 bool PickGluePoint(const Point& rPnt, SdrObject*& rpObj, sal_uInt16& rnId, SdrPageView*& rpPV) const;
381 bool MarkGluePoint(const SdrObject* pObj, sal_uInt16 nId, bool bUnmark);
382 void UnmarkGluePoint(const SdrObject* pObj, sal_uInt16 nId) { MarkGluePoint(pObj,nId,true); }
383 bool IsGluePointMarked(const SdrObject* pObj, sal_uInt16 nId) const;
384
385 // Get the Hdl (handle) of a marked GluePoint. Non-marked
386 // GluePoints don`t have handles
387 SdrHdl* GetGluePointHdl(const SdrObject* pObj, sal_uInt16 nId) const;
388
389 // Mark all points within this rectangular (View coordinates)
390 bool MarkAllGluePoints() { return MarkGluePoints(nullptr,false); }
391 bool UnmarkAllGluePoints() { return MarkGluePoints(nullptr,true); }
392
393 // Selects the first marked point (P1) which is hit by rPnt
394 // and from there it searches the first non-marked point(P2).
395 // In case of success the marking of
396 // P1 is deleted, a mark is set at P2.
397 void MarkNextGluePoint();
398
399 // Draw a selection frame for glue point marking.
400 // This routine will just be started in case that HasMarkablePoints() returns sal_True.
401 // The GlueEditMode sal_True is disregarded.
402 // bool BegMarkGluePoints(const Point& rPnt, OutputDevice* pOut);
403 bool BegMarkGluePoints(const Point& rPnt, bool bUnmark = false);
404 void MovMarkGluePoints(const Point& rPnt);
405 void EndMarkGluePoints();
406 void BrkMarkGluePoints();
407 bool IsMarkGluePoints() const { return (nullptr != mpMarkGluePointsOverlay); }
408
409 // bRestraintPaint=sal_False causes the handles not to be drawn immediately.
410 // AdjustMarkHdl is just called in case of changes; usually this causes an Invalidate
411 // At the end of a redraw the handles are drawn automatically.
412 // The purpose is to avoid unnecessary flickering. -> This does not yet work, that's why sal_True!
413 void AdjustMarkHdl(SfxViewShell* pOtherShell = nullptr); //HMHBOOL bRestraintPaint=sal_True);
414
415 const tools::Rectangle& GetMarkedObjRect() const; // SnapRects of Objects, without line width
416 tools::Rectangle GetMarkedObjBoundRect() const; // incl. line width, overlapping rags, ...
417 const tools::Rectangle& GetMarkedPointsRect() const; // Enclosing rectangle of all marked points
418 const tools::Rectangle& GetMarkedGluePointsRect() const; // Enclosing rectangle of all marked glue points
419 const tools::Rectangle& GetAllMarkedRect() const { return GetMarkedObjRect(); }
420 tools::Rectangle GetAllMarkedBoundRect() const { return GetMarkedObjBoundRect(); }
421
422 // Will be always called, if the list of marked objects might be changed.
423 // If you override this method, be sure that you call the
424 // methods of the base class!
425 virtual void MarkListHasChanged();
426
427 // Entering (Editing) of a maybe marked object group. If there are several
428 // object groups marked, the most upper group is selected. After that
429 // all member objects of the group are directly accessible. All other
430 // objects may not be processed in the meantime (until the next
431 // LeaveGroup()). With markings which overlaps pages, every page is processed
432 // separately. The method returns sal_True, if at least one group was entered.
433 void EnterMarkedGroup();
434
435 // Rotation center point and start point of the axis of reflection, respectively
436 const Point& GetRef1() const { return maRef1; }
437 void SetRef1(const Point& rPt);
438
439 // End point of the axis of reflection
440 const Point& GetRef2() const { return maRef2; }
441 void SetRef2(const Point& rPt);
442 /// Get access to the view shell owning this draw view, if any.
443 virtual SfxViewShell* GetSfxViewShell() const;
444};
445
446
447// - Hit tolerances:
448// It has to be declared in logical coordinates. So please translate the
449// wanted pixel value with PixelToLogic in Logical values.
450// Taking as example a logical value of 100:
451// - For a horizontal hairline (Object with height 0), the generated data is +/-100, i.e.
452// a vertical area of 200 logical units is sensitive.
453// - For a polygon, a rectangular of the size (200,200) is generated and a
454// touch test between Poly and this Rect is processed.
455// - Objects which respond SdrObject::HasEdit()==TRUE ( e.g. a text frame ),
456// are specially treated: An additional sensitive area with a width of
457// 2*Tol (200 units for this example) is created around the object.
458// When an object is directly hit, the Edit method is called.
459// In opposite, a hit in the surrounding sensitive area enables Dragging.
460
461
462#endif // INCLUDED_SVX_SVDMRKV_HXX
463
464/* vim:set shiftwidth=4 softtabstop=4 expandtab: */