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