File: | home/maarten/src/libreoffice/core/svx/source/svdraw/svdedtv1.cxx |
Warning: | line 1168, column 29 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |||||
76 | void 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 | |||||
149 | std::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 | |||||
176 | void SdrEditView::AddUndoActions( std::vector< std::unique_ptr<SdrUndoAction> > aUndoActions ) | ||||
177 | { | ||||
178 | for (auto & rAction : aUndoActions) | ||||
179 | AddUndo( std::move(rAction) ); | ||||
180 | } | ||||
181 | |||||
182 | void 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 | |||||
216 | void 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 | } | ||||
247 | void 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 | |||||
283 | long 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 | |||||
298 | void 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 | |||||
354 | void 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 | |||||
418 | void SdrEditView::MirrorMarkedObjHorizontal() | ||||
419 | { | ||||
420 | Point aCenter(GetMarkedObjRect().Center()); | ||||
421 | Point aPt2(aCenter); | ||||
422 | aPt2.AdjustY( 1 ); | ||||
423 | MirrorMarkedObj(aCenter,aPt2); | ||||
424 | } | ||||
425 | |||||
426 | void SdrEditView::MirrorMarkedObjVertical() | ||||
427 | { | ||||
428 | Point aCenter(GetMarkedObjRect().Center()); | ||||
429 | Point aPt2(aCenter); | ||||
430 | aPt2.AdjustX( 1 ); | ||||
431 | MirrorMarkedObj(aCenter,aPt2); | ||||
432 | } | ||||
433 | |||||
434 | long 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 | |||||
454 | void 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 | |||||
488 | void 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 | |||||
566 | void 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 | |||||
610 | void 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 | |||||
644 | void 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 | |||||
685 | void 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 | |||||
771 | void 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 | |||||
878 | SfxItemSet 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 | |||||
894 | void 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 | |||||
1014 | std::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 | |||||
1032 | void SdrEditView::SetAttrToMarked(const SfxItemSet& rAttr, bool bReplaceAll) | ||||
1033 | { | ||||
1034 | if (!AreObjectsMarked()) | ||||
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
| ||||
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 ) | ||||
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 | ||||
1111 | == aAttr.GetItemState(XATTR_LINESTARTWIDTH)); | ||||
1112 | const bool bLineEndWidthExplicitChange(SfxItemState::SET | ||||
1113 | == aAttr.GetItemState(XATTR_LINEENDWIDTH)); | ||||
1114 | // check if LineWidth is part of the change | ||||
1115 | const bool bAdaptStartEndWidths(!(bLineStartWidthExplicitChange
| ||||
1116 | && SfxItemState::SET == aAttr.GetItemState(XATTR_LINEWIDTH)); | ||||
1117 | sal_Int32 nNewLineWidth(0); | ||||
1118 | |||||
1119 | if(bAdaptStartEndWidths
| ||||
1120 | { | ||||
1121 | nNewLineWidth = aAttr.Get(XATTR_LINEWIDTH).GetValue(); | ||||
1122 | } | ||||
1123 | |||||
1124 | for (size_t nm=0; nm<nMarkCount; ++nm) | ||||
1125 | { | ||||
1126 | SdrMark* pM=GetSdrMarkByIndex(nm); | ||||
1127 | SdrObject* pObj = pM->GetMarkedSdrObj(); | ||||
1128 | |||||
1129 | if( bUndo
| ||||
1130 | { | ||||
1131 | SdrEdgeObj* pEdgeObj = dynamic_cast< SdrEdgeObj* >( pObj ); | ||||
1132 | if ( pEdgeObj ) | ||||
1133 | bPossibleGeomChange = true; | ||||
1134 | else | ||||
1135 | AddUndoActions( CreateConnectorUndo( *pObj ) ); | ||||
1136 | } | ||||
1137 | |||||
1138 | // new geometry undo | ||||
1139 | if(bPossibleGeomChange
| ||||
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 | |||||
1251 | SfxStyleSheet* 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 | |||||
1266 | void 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 | |||||
1301 | void 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 | |||||
1313 | void 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 | |||||
1322 | SfxStyleSheet* SdrEditView::GetStyleSheet() const | ||||
1323 | { | ||||
1324 | if (GetMarkedObjectCount()!=0) { | ||||
1325 | return GetStyleSheetFromMarked(); | ||||
1326 | } else { | ||||
1327 | return SdrMarkView::GetStyleSheet(); | ||||
1328 | } | ||||
1329 | } | ||||
1330 | |||||
1331 | void 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 | |||||
1341 | SfxItemSet 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 | |||||
1501 | static 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 | |||||
1517 | void SdrEditView::SetGeoAttrToMarked(const SfxItemSet& rAttr) | ||||
1518 | { | ||||
1519 | const bool bTiledRendering = comphelper::LibreOfficeKit::isActive(); | ||||
1520 | |||||
1521 | tools::Rectangle aRect(GetMarkedObjRect()); | ||||
1522 | |||||
1523 | if(GetSdrPageView()) | ||||
| |||||
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); | ||||
1542 | long nRotateX(0); | ||||
1543 | long nRotateY(0); | ||||
1544 | long nOldRotateX(0); | ||||
1545 | long nOldRotateY(0); | ||||
1546 | if(bModeIsRotate
| ||||
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)) { | ||||
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)){ | ||||
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)) { | ||||
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)) { | ||||
1592 | nSizY=static_cast<const SfxUInt32Item*>(pPoolItem)->GetValue(); | ||||
1593 | bChgSiz=true; | ||||
1594 | bChgHgt=true; | ||||
1595 | } | ||||
1596 | if (bChgSiz
| ||||
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)) { | ||||
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)) { | ||||
1611 | nRotateAngle = static_cast<const SfxInt32Item*>(pPoolItem)->GetValue() - nOldRotateAngle; | ||||
1612 | bRotate = (nRotateAngle != 0); | ||||
1613 | } | ||||
1614 | |||||
1615 | // position rotation point x | ||||
1616 | if(bRotate
| ||||
1617 | nRotateX = rAttr.Get(SID_ATTR_TRANSFORM_ROT_XTypedWhichId<SfxInt32Item>( 10000 + 93 )).GetValue(); | ||||
1618 | |||||
1619 | // position rotation point y | ||||
1620 | if(bRotate
| ||||
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)) { | ||||
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)) { | ||||
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)) { | ||||
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)) { | ||||
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
| ||||
1677 | SetAttrToMarked(aSetAttr,false); | ||||
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 | |||||
1815 | bool 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 | |||||
1824 | void 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: */ |
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 | |
32 | class SfxViewShell; |
33 | |
34 | // The following is not yet implemented, or just partially: |
35 | enum 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 | }; |
53 | namespace o3tl |
54 | { |
55 | template<> struct typed_flags<SdrSearchOptions> : is_typed_flags<SdrSearchOptions, 0x03ff> {}; |
56 | } |
57 | |
58 | enum 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 | |
74 | enum 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() */ |
81 | enum class ImpGetDescriptionOptions |
82 | { |
83 | NONE = 0, |
84 | POINTS = 1, |
85 | GLUEPOINTS = 2, |
86 | }; |
87 | |
88 | class ImplMarkingOverlay; |
89 | class MarkingSubSelectionOverlay; |
90 | |
91 | class 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 | |
102 | protected: |
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 | |
146 | private: |
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 | |
152 | protected: |
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 | |
182 | protected: |
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 | |
190 | public: |
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 | |
245 | protected: |
246 | // all available changing methods |
247 | SdrMarkList& GetMarkedObjectListWriteAccess() { return maSdrViewSelection.GetMarkedObjectListWriteAccess(); } |
248 | |
249 | public: |
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(); } |
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: */ |