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