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