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 
21 #include <svx/svdovirt.hxx>
22 #include <svx/svdhdl.hxx>
23 #include <svx/sdr/contact/viewcontactofvirtobj.hxx>
24 #include <svx/svdograf.hxx>
25 #include <svx/svddrgv.hxx>
26 #include <basegfx/matrix/b2dhommatrixtools.hxx>
27 #include <rtl/ustrbuf.hxx>
28 
GetProperties() const29 sdr::properties::BaseProperties& SdrVirtObj::GetProperties() const
30 {
31     return rRefObj.GetProperties();
32 }
33 
34 
35 // #i27224#
CreateObjectSpecificViewContact()36 std::unique_ptr<sdr::contact::ViewContact> SdrVirtObj::CreateObjectSpecificViewContact()
37 {
38     return std::make_unique<sdr::contact::ViewContactOfVirtObj>(*this);
39 }
40 
SdrVirtObj(SdrModel & rSdrModel,SdrObject & rNewObj)41 SdrVirtObj::SdrVirtObj(
42     SdrModel& rSdrModel,
43     SdrObject& rNewObj)
44 :   SdrObject(rSdrModel),
45     rRefObj(rNewObj)
46 {
47     m_bVirtObj=true; // this is only a virtual object
48     rRefObj.AddReference(*this);
49     m_bClosedObj=rRefObj.IsClosedObj();
50 }
51 
SdrVirtObj(SdrModel & rSdrModel,SdrVirtObj const & rSource)52 SdrVirtObj::SdrVirtObj(
53     SdrModel& rSdrModel, SdrVirtObj const & rSource)
54 :   SdrObject(rSdrModel, rSource),
55     rRefObj(rSource.rRefObj)
56 {
57     m_bVirtObj=true; // this is only a virtual object
58     m_bClosedObj=rRefObj.IsClosedObj();
59 
60     rRefObj.AddReference(*this);
61 
62     aSnapRect = rSource.aSnapRect;
63     m_aAnchor = rSource.m_aAnchor;
64 }
65 
~SdrVirtObj()66 SdrVirtObj::~SdrVirtObj()
67 {
68     rRefObj.DelReference(*this);
69 }
70 
GetReferencedObj() const71 const SdrObject& SdrVirtObj::GetReferencedObj() const
72 {
73     return rRefObj;
74 }
75 
ReferencedObj()76 SdrObject& SdrVirtObj::ReferencedObj()
77 {
78     return rRefObj;
79 }
80 
Notify(SfxBroadcaster &,const SfxHint &)81 void SdrVirtObj::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& /*rHint*/)
82 {
83     m_bClosedObj=rRefObj.IsClosedObj();
84     SetRectsDirty(); // TODO: Optimize this.
85 
86     // Only a repaint here, rRefObj may have changed and broadcasts
87     ActionChanged();
88 }
89 
NbcSetAnchorPos(const Point & rAnchorPos)90 void SdrVirtObj::NbcSetAnchorPos(const Point& rAnchorPos)
91 {
92     m_aAnchor=rAnchorPos;
93 }
94 
TakeObjInfo(SdrObjTransformInfoRec & rInfo) const95 void SdrVirtObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
96 {
97     rRefObj.TakeObjInfo(rInfo);
98 }
99 
GetObjInventor() const100 SdrInventor SdrVirtObj::GetObjInventor() const
101 {
102     return rRefObj.GetObjInventor();
103 }
104 
GetObjIdentifier() const105 SdrObjKind SdrVirtObj::GetObjIdentifier() const
106 {
107     return rRefObj.GetObjIdentifier();
108 }
109 
GetSubList() const110 SdrObjList* SdrVirtObj::GetSubList() const
111 {
112     return rRefObj.GetSubList();
113 }
114 
GetCurrentBoundRect() const115 const tools::Rectangle& SdrVirtObj::GetCurrentBoundRect() const
116 {
117     m_aOutRect = rRefObj.GetCurrentBoundRect(); // TODO: Optimize this.
118     m_aOutRect += m_aAnchor;
119     return m_aOutRect;
120 }
121 
GetLastBoundRect() const122 const tools::Rectangle& SdrVirtObj::GetLastBoundRect() const
123 {
124     m_aOutRect = rRefObj.GetLastBoundRect(); // TODO: Optimize this.
125     m_aOutRect += m_aAnchor;
126     return m_aOutRect;
127 }
128 
RecalcBoundRect()129 void SdrVirtObj::RecalcBoundRect()
130 {
131     m_aOutRect=rRefObj.GetCurrentBoundRect();
132     m_aOutRect+=m_aAnchor;
133 }
134 
CloneSdrObject(SdrModel & rTargetModel) const135 SdrVirtObj* SdrVirtObj::CloneSdrObject(SdrModel& rTargetModel) const
136 {
137     return new SdrVirtObj(rTargetModel, *this);
138     // TTTT not sure if the above works - how could SdrObjFactory::MakeNewObject
139     // create an object with correct rRefObj (?) OTOH VirtObj probably needs not
140     // to be cloned ever - only used in Writer for multiple instances e.g. Header/Footer
141     // return new SdrVirtObj(
142     //     getSdrModelFromSdrObject(),
143     //     rRefObj); // only a further reference
144 }
145 
TakeObjNameSingul() const146 OUString SdrVirtObj::TakeObjNameSingul() const
147 {
148     OUString sName = "[" + rRefObj.TakeObjNameSingul() + "]";
149 
150     OUString aName(GetName());
151     if (!aName.isEmpty())
152         sName += " '" + aName + "'";
153 
154     return sName;
155 }
156 
TakeObjNamePlural() const157 OUString SdrVirtObj::TakeObjNamePlural() const
158 {
159     return "[" + rRefObj.TakeObjNamePlural() + "]";
160 }
161 
HasLimitedRotation() const162 bool SdrVirtObj::HasLimitedRotation() const
163 {
164     // RotGrfFlyFrame: If true, this SdrObject supports only limited rotation
165     return rRefObj.HasLimitedRotation();
166 }
167 
TakeXorPoly() const168 basegfx::B2DPolyPolygon SdrVirtObj::TakeXorPoly() const
169 {
170     basegfx::B2DPolyPolygon aPolyPolygon(rRefObj.TakeXorPoly());
171 
172     if(m_aAnchor.X() || m_aAnchor.Y())
173     {
174         aPolyPolygon.transform(basegfx::utils::createTranslateB2DHomMatrix(m_aAnchor.X(), m_aAnchor.Y()));
175     }
176 
177     return aPolyPolygon;
178 }
179 
180 
GetHdlCount() const181 sal_uInt32 SdrVirtObj::GetHdlCount() const
182 {
183     return rRefObj.GetHdlCount();
184 }
185 
AddToHdlList(SdrHdlList & rHdlList) const186 void SdrVirtObj::AddToHdlList(SdrHdlList& rHdlList) const
187 {
188     SdrHdlList tempList(nullptr);
189     rRefObj.AddToHdlList(tempList);
190     for (size_t i=0; i<tempList.GetHdlCount(); ++i)
191     {
192         SdrHdl* pHdl = tempList.GetHdl(i);
193         Point aP(pHdl->GetPos()+m_aAnchor);
194         pHdl->SetPos(aP);
195     }
196     tempList.MoveTo(rHdlList);
197 }
198 
AddToPlusHdlList(SdrHdlList & rHdlList,SdrHdl & rHdl) const199 void SdrVirtObj::AddToPlusHdlList(SdrHdlList& rHdlList, SdrHdl& rHdl) const
200 {
201     SdrHdlList tempList(nullptr);
202     rRefObj.AddToPlusHdlList(tempList, rHdl);
203     for (size_t i=0; i<tempList.GetHdlCount(); ++i)
204     {
205         SdrHdl* pHdl = tempList.GetHdl(i);
206         Point aP(pHdl->GetPos()+m_aAnchor);
207         pHdl->SetPos(aP);
208     }
209     tempList.MoveTo(rHdlList);
210 }
211 
hasSpecialDrag() const212 bool SdrVirtObj::hasSpecialDrag() const
213 {
214     return rRefObj.hasSpecialDrag();
215 }
216 
supportsFullDrag() const217 bool SdrVirtObj::supportsFullDrag() const
218 {
219     return false;
220 }
221 
getFullDragClone() const222 SdrObjectUniquePtr SdrVirtObj::getFullDragClone() const
223 {
224     SdrObject& rReferencedObject = const_cast<SdrVirtObj*>(this)->ReferencedObj();
225     return SdrObjectUniquePtr(new SdrGrafObj(
226         getSdrModelFromSdrObject(),
227         SdrDragView::GetObjGraphic(rReferencedObject),
228         GetLogicRect()));
229 }
230 
beginSpecialDrag(SdrDragStat & rDrag) const231 bool SdrVirtObj::beginSpecialDrag(SdrDragStat& rDrag) const
232 {
233     return rRefObj.beginSpecialDrag(rDrag);
234 }
235 
applySpecialDrag(SdrDragStat & rDrag)236 bool SdrVirtObj::applySpecialDrag(SdrDragStat& rDrag)
237 {
238     return rRefObj.applySpecialDrag(rDrag);
239 }
240 
getSpecialDragPoly(const SdrDragStat & rDrag) const241 basegfx::B2DPolyPolygon SdrVirtObj::getSpecialDragPoly(const SdrDragStat& rDrag) const
242 {
243     return rRefObj.getSpecialDragPoly(rDrag);
244     // TODO: we don't handle offsets yet!
245 }
246 
getSpecialDragComment(const SdrDragStat & rDrag) const247 OUString SdrVirtObj::getSpecialDragComment(const SdrDragStat& rDrag) const
248 {
249     return rRefObj.getSpecialDragComment(rDrag);
250 }
251 
252 
BegCreate(SdrDragStat & rStat)253 bool SdrVirtObj::BegCreate(SdrDragStat& rStat)
254 {
255     return rRefObj.BegCreate(rStat);
256 }
257 
MovCreate(SdrDragStat & rStat)258 bool SdrVirtObj::MovCreate(SdrDragStat& rStat)
259 {
260     return rRefObj.MovCreate(rStat);
261 }
262 
EndCreate(SdrDragStat & rStat,SdrCreateCmd eCmd)263 bool SdrVirtObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
264 {
265     return rRefObj.EndCreate(rStat,eCmd);
266 }
267 
BckCreate(SdrDragStat & rStat)268 bool SdrVirtObj::BckCreate(SdrDragStat& rStat)
269 {
270     return rRefObj.BckCreate(rStat);
271 }
272 
BrkCreate(SdrDragStat & rStat)273 void SdrVirtObj::BrkCreate(SdrDragStat& rStat)
274 {
275     rRefObj.BrkCreate(rStat);
276 }
277 
TakeCreatePoly(const SdrDragStat & rDrag) const278 basegfx::B2DPolyPolygon SdrVirtObj::TakeCreatePoly(const SdrDragStat& rDrag) const
279 {
280     return rRefObj.TakeCreatePoly(rDrag);
281     // TODO: we don't handle offsets yet!
282 }
283 
284 
NbcMove(const Size & rSiz)285 void SdrVirtObj::NbcMove(const Size& rSiz)
286 {
287     m_aAnchor.Move(rSiz);
288     SetRectsDirty();
289 }
290 
NbcResize(const Point & rRef,const Fraction & xFact,const Fraction & yFact)291 void SdrVirtObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
292 {
293     rRefObj.NbcResize(rRef-m_aAnchor,xFact,yFact);
294     SetRectsDirty();
295 }
296 
NbcRotate(const Point & rRef,Degree100 nAngle,double sn,double cs)297 void SdrVirtObj::NbcRotate(const Point& rRef, Degree100 nAngle, double sn, double cs)
298 {
299     rRefObj.NbcRotate(rRef-m_aAnchor,nAngle,sn,cs);
300     SetRectsDirty();
301 }
302 
NbcMirror(const Point & rRef1,const Point & rRef2)303 void SdrVirtObj::NbcMirror(const Point& rRef1, const Point& rRef2)
304 {
305     rRefObj.NbcMirror(rRef1-m_aAnchor,rRef2-m_aAnchor);
306     SetRectsDirty();
307 }
308 
NbcShear(const Point & rRef,Degree100 nAngle,double tn,bool bVShear)309 void SdrVirtObj::NbcShear(const Point& rRef, Degree100 nAngle, double tn, bool bVShear)
310 {
311     rRefObj.NbcShear(rRef-m_aAnchor,nAngle,tn,bVShear);
312     SetRectsDirty();
313 }
314 
315 
Move(const Size & rSiz)316 void SdrVirtObj::Move(const Size& rSiz)
317 {
318     if (!rSiz.IsEmpty()) {
319         tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
320         NbcMove(rSiz);
321         SetChanged();
322         BroadcastObjectChange();
323         SendUserCall(SdrUserCallType::MoveOnly,aBoundRect0);
324     }
325 }
326 
Resize(const Point & rRef,const Fraction & xFact,const Fraction & yFact,bool bUnsetRelative)327 void SdrVirtObj::Resize(const Point& rRef, const Fraction& xFact, const Fraction& yFact, bool bUnsetRelative)
328 {
329     if (xFact.GetNumerator()!=xFact.GetDenominator() || yFact.GetNumerator()!=yFact.GetDenominator()) {
330         tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
331         rRefObj.Resize(rRef-m_aAnchor,xFact,yFact, bUnsetRelative);
332         SetRectsDirty();
333         SendUserCall(SdrUserCallType::Resize,aBoundRect0);
334     }
335 }
336 
Rotate(const Point & rRef,Degree100 nAngle,double sn,double cs)337 void SdrVirtObj::Rotate(const Point& rRef, Degree100 nAngle, double sn, double cs)
338 {
339     if (nAngle) {
340         tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
341         rRefObj.Rotate(rRef-m_aAnchor,nAngle,sn,cs);
342         SetRectsDirty();
343         SendUserCall(SdrUserCallType::Resize,aBoundRect0);
344     }
345 }
346 
Mirror(const Point & rRef1,const Point & rRef2)347 void SdrVirtObj::Mirror(const Point& rRef1, const Point& rRef2)
348 {
349     tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
350     rRefObj.Mirror(rRef1-m_aAnchor,rRef2-m_aAnchor);
351     SetRectsDirty();
352     SendUserCall(SdrUserCallType::Resize,aBoundRect0);
353 }
354 
Shear(const Point & rRef,Degree100 nAngle,double tn,bool bVShear)355 void SdrVirtObj::Shear(const Point& rRef, Degree100 nAngle, double tn, bool bVShear)
356 {
357     if (nAngle) {
358         tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
359         rRefObj.Shear(rRef-m_aAnchor,nAngle,tn,bVShear);
360         SetRectsDirty();
361         SendUserCall(SdrUserCallType::Resize,aBoundRect0);
362     }
363 }
364 
365 
RecalcSnapRect()366 void SdrVirtObj::RecalcSnapRect()
367 {
368     aSnapRect=rRefObj.GetSnapRect();
369     aSnapRect+=m_aAnchor;
370 }
371 
GetSnapRect() const372 const tools::Rectangle& SdrVirtObj::GetSnapRect() const
373 {
374     const_cast<SdrVirtObj*>(this)->aSnapRect=rRefObj.GetSnapRect();
375     const_cast<SdrVirtObj*>(this)->aSnapRect+=m_aAnchor;
376     return aSnapRect;
377 }
378 
SetSnapRect(const tools::Rectangle & rRect)379 void SdrVirtObj::SetSnapRect(const tools::Rectangle& rRect)
380 {
381     tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
382     tools::Rectangle aR(rRect);
383     aR-=m_aAnchor;
384     rRefObj.SetSnapRect(aR);
385     SetRectsDirty();
386     SendUserCall(SdrUserCallType::Resize,aBoundRect0);
387 }
388 
NbcSetSnapRect(const tools::Rectangle & rRect)389 void SdrVirtObj::NbcSetSnapRect(const tools::Rectangle& rRect)
390 {
391     tools::Rectangle aR(rRect);
392     aR-=m_aAnchor;
393     SetRectsDirty();
394     rRefObj.NbcSetSnapRect(aR);
395 }
396 
397 
GetLogicRect() const398 const tools::Rectangle& SdrVirtObj::GetLogicRect() const
399 {
400     const_cast<SdrVirtObj*>(this)->aSnapRect=rRefObj.GetLogicRect();  // An abuse of aSnapRect!
401     const_cast<SdrVirtObj*>(this)->aSnapRect+=m_aAnchor;                // If there's trouble, we need another Rectangle Member (or a Heap).
402     return aSnapRect;
403 }
404 
SetLogicRect(const tools::Rectangle & rRect)405 void SdrVirtObj::SetLogicRect(const tools::Rectangle& rRect)
406 {
407     tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
408     tools::Rectangle aR(rRect);
409     aR-=m_aAnchor;
410     rRefObj.SetLogicRect(aR);
411     SetRectsDirty();
412     SendUserCall(SdrUserCallType::Resize,aBoundRect0);
413 }
414 
NbcSetLogicRect(const tools::Rectangle & rRect)415 void SdrVirtObj::NbcSetLogicRect(const tools::Rectangle& rRect)
416 {
417     tools::Rectangle aR(rRect);
418     aR-=m_aAnchor;
419     SetRectsDirty();
420     rRefObj.NbcSetLogicRect(aR);
421 }
422 
423 
GetRotateAngle() const424 Degree100 SdrVirtObj::GetRotateAngle() const
425 {
426     return rRefObj.GetRotateAngle();
427 }
428 
GetShearAngle(bool bVertical) const429 Degree100 SdrVirtObj::GetShearAngle(bool bVertical) const
430 {
431     return rRefObj.GetShearAngle(bVertical);
432 }
433 
434 
GetSnapPointCount() const435 sal_uInt32 SdrVirtObj::GetSnapPointCount() const
436 {
437     return rRefObj.GetSnapPointCount();
438 }
439 
GetSnapPoint(sal_uInt32 i) const440 Point SdrVirtObj::GetSnapPoint(sal_uInt32 i) const
441 {
442     Point aP(rRefObj.GetSnapPoint(i));
443     aP+=m_aAnchor;
444     return aP;
445 }
446 
IsPolyObj() const447 bool SdrVirtObj::IsPolyObj() const
448 {
449     return rRefObj.IsPolyObj();
450 }
451 
GetPointCount() const452 sal_uInt32 SdrVirtObj::GetPointCount() const
453 {
454     return rRefObj.GetPointCount();
455 }
456 
GetPoint(sal_uInt32 i) const457 Point SdrVirtObj::GetPoint(sal_uInt32 i) const
458 {
459     return rRefObj.GetPoint(i) + m_aAnchor;
460 }
461 
NbcSetPoint(const Point & rPnt,sal_uInt32 i)462 void SdrVirtObj::NbcSetPoint(const Point& rPnt, sal_uInt32 i)
463 {
464     Point aP(rPnt);
465     aP-=m_aAnchor;
466     rRefObj.SetPoint(aP,i);
467     SetRectsDirty();
468 }
469 
470 
NewGeoData() const471 std::unique_ptr<SdrObjGeoData> SdrVirtObj::NewGeoData() const
472 {
473     return rRefObj.NewGeoData();
474 }
475 
SaveGeoData(SdrObjGeoData & rGeo) const476 void SdrVirtObj::SaveGeoData(SdrObjGeoData& rGeo) const
477 {
478     rRefObj.SaveGeoData(rGeo);
479 }
480 
RestoreGeoData(const SdrObjGeoData & rGeo)481 void SdrVirtObj::RestoreGeoData(const SdrObjGeoData& rGeo)
482 {
483     rRefObj.RestoreGeoData(rGeo);
484     SetRectsDirty();
485 }
486 
487 
GetGeoData() const488 std::unique_ptr<SdrObjGeoData> SdrVirtObj::GetGeoData() const
489 {
490     return rRefObj.GetGeoData();
491 }
492 
SetGeoData(const SdrObjGeoData & rGeo)493 void SdrVirtObj::SetGeoData(const SdrObjGeoData& rGeo)
494 {
495     tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
496     rRefObj.SetGeoData(rGeo);
497     SetRectsDirty();
498     SendUserCall(SdrUserCallType::Resize,aBoundRect0);
499 }
500 
501 
NbcReformatText()502 void SdrVirtObj::NbcReformatText()
503 {
504     rRefObj.NbcReformatText();
505 }
506 
HasMacro() const507 bool SdrVirtObj::HasMacro() const
508 {
509     return rRefObj.HasMacro();
510 }
511 
CheckMacroHit(const SdrObjMacroHitRec & rRec) const512 SdrObject* SdrVirtObj::CheckMacroHit(const SdrObjMacroHitRec& rRec) const
513 {
514     return rRefObj.CheckMacroHit(rRec); // TODO: positioning offset
515 }
516 
GetMacroPointer(const SdrObjMacroHitRec & rRec) const517 PointerStyle SdrVirtObj::GetMacroPointer(const SdrObjMacroHitRec& rRec) const
518 {
519     return rRefObj.GetMacroPointer(rRec); // TODO: positioning offset
520 }
521 
PaintMacro(OutputDevice & rOut,const tools::Rectangle & rDirtyRect,const SdrObjMacroHitRec & rRec) const522 void SdrVirtObj::PaintMacro(OutputDevice& rOut, const tools::Rectangle& rDirtyRect, const SdrObjMacroHitRec& rRec) const
523 {
524     rRefObj.PaintMacro(rOut,rDirtyRect,rRec); // TODO: positioning offset
525 }
526 
DoMacro(const SdrObjMacroHitRec & rRec)527 bool SdrVirtObj::DoMacro(const SdrObjMacroHitRec& rRec)
528 {
529     return rRefObj.DoMacro(rRec); // TODO: positioning offset
530 }
531 
GetOffset() const532 Point SdrVirtObj::GetOffset() const
533 {
534     // #i73248# default offset of SdrVirtObj is aAnchor
535     return m_aAnchor;
536 }
537 
538 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
539