xref: /aoo41x/main/sw/source/core/draw/dflyobj.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 #include "hintids.hxx"
31 #include <svx/svdtrans.hxx>
32 #include <editeng/protitem.hxx>
33 #include <editeng/opaqitem.hxx>
34 #include <svx/svdpage.hxx>
35 
36 
37 #include <fmtclds.hxx>
38 #include <fmtornt.hxx>
39 #include <fmtfsize.hxx>
40 #include <fmturl.hxx>
41 #include "viewsh.hxx"
42 #include "viewimp.hxx"
43 #include "cntfrm.hxx"
44 #include "frmatr.hxx"
45 #include "doc.hxx"
46 #include <IDocumentUndoRedo.hxx>
47 #include "dview.hxx"
48 #include "dflyobj.hxx"
49 #include "flyfrm.hxx"
50 #include "frmfmt.hxx"
51 #include "viewopt.hxx"
52 #include "frmtool.hxx"
53 #include "flyfrms.hxx"
54 #include "ndnotxt.hxx"
55 #include "grfatr.hxx"
56 #include "pagefrm.hxx"
57 #include "rootfrm.hxx"
58 
59 
60 using namespace ::com::sun::star;
61 
62 
63 // --> OD 2004-11-22 #117958#
64 #include <svx/sdr/properties/defaultproperties.hxx>
65 // <--
66 #include <basegfx/range/b2drange.hxx>
67 #include <basegfx/polygon/b2dpolygontools.hxx>
68 #include <basegfx/polygon/b2dpolygon.hxx>
69 
70 // AW: For VCOfDrawVirtObj and stuff
71 #include <svx/sdr/contact/viewcontactofvirtobj.hxx>
72 #include <drawinglayer/primitive2d/baseprimitive2d.hxx>
73 #include <sw_primitivetypes2d.hxx>
74 #include <drawinglayer/primitive2d/sdrdecompositiontools2d.hxx>
75 
76 using namespace ::com::sun::star;
77 
78 static sal_Bool bInResize = sal_False;
79 
80 TYPEINIT1( SwFlyDrawObj, SdrObject )
81 TYPEINIT1( SwVirtFlyDrawObj, SdrVirtObj )
82 
83 /*************************************************************************
84 |*
85 |*	SwFlyDrawObj::Ctor
86 |*
87 |*	Ersterstellung		MA 18. Apr. 95
88 |*	Letzte Aenderung	MA 28. May. 96
89 |*
90 *************************************************************************/
91 
92 ////////////////////////////////////////////////////////////////////////////////////////////////////
93 
94 namespace sdr
95 {
96 	namespace contact
97 	{
98         // #i95264# currently needed since createViewIndependentPrimitive2DSequence()
99         // is called when RecalcBoundRect() is used. There should currently no VOCs being
100         // constructed since it gets not visualized (instead the corresponding SwVirtFlyDrawObj's
101         // referencing this one are visualized).
102 		class VCOfSwFlyDrawObj : public ViewContactOfSdrObj
103 		{
104         protected:
105 			// This method is responsible for creating the graphical visualisation data
106             // ONLY based on model data
107 			virtual drawinglayer::primitive2d::Primitive2DSequence createViewIndependentPrimitive2DSequence() const;
108 
109         public:
110 			// basic constructor, used from SdrObject.
111             VCOfSwFlyDrawObj(SwFlyDrawObj& rObj)
112             :   ViewContactOfSdrObj(rObj)
113             {
114             }
115 			virtual ~VCOfSwFlyDrawObj();
116 		};
117 
118         drawinglayer::primitive2d::Primitive2DSequence VCOfSwFlyDrawObj::createViewIndependentPrimitive2DSequence() const
119         {
120             // currently gets not visualized, return empty sequence
121             return drawinglayer::primitive2d::Primitive2DSequence();
122         }
123 
124         VCOfSwFlyDrawObj::~VCOfSwFlyDrawObj()
125         {
126         }
127 	} // end of namespace contact
128 } // end of namespace sdr
129 
130 ////////////////////////////////////////////////////////////////////////////////////////////////////
131 
132 sdr::properties::BaseProperties* SwFlyDrawObj::CreateObjectSpecificProperties()
133 {
134     // --> OD 2004-11-22 #117958# - create default properties
135     return new sdr::properties::DefaultProperties(*this);
136     // <--
137 }
138 
139 sdr::contact::ViewContact* SwFlyDrawObj::CreateObjectSpecificViewContact()
140 {
141     // #i95264# needs an own VC since createViewIndependentPrimitive2DSequence()
142     // is called when RecalcBoundRect() is used
143 	return new sdr::contact::VCOfSwFlyDrawObj(*this);
144 }
145 
146 SwFlyDrawObj::SwFlyDrawObj()
147 {
148 }
149 
150 SwFlyDrawObj::~SwFlyDrawObj()
151 {
152 }
153 
154 /*************************************************************************
155 |*
156 |*	SwFlyDrawObj::Factory-Methoden
157 |*
158 |*	Ersterstellung		MA 23. Feb. 95
159 |*	Letzte Aenderung	MA 23. Feb. 95
160 |*
161 *************************************************************************/
162 
163 sal_uInt32 __EXPORT SwFlyDrawObj::GetObjInventor() const
164 {
165 	return SWGInventor;
166 }
167 
168 
169 sal_uInt16 __EXPORT SwFlyDrawObj::GetObjIdentifier()	const
170 {
171 	return SwFlyDrawObjIdentifier;
172 }
173 
174 
175 sal_uInt16 __EXPORT SwFlyDrawObj::GetObjVersion() const
176 {
177 	return SwDrawFirst;
178 }
179 
180 /*************************************************************************
181 |*
182 |*	SwVirtFlyDrawObj::CToren, Dtor
183 |*
184 |*	Ersterstellung		MA 08. Dec. 94
185 |*	Letzte Aenderung	MA 28. May. 96
186 |*
187 *************************************************************************/
188 
189 //////////////////////////////////////////////////////////////////////////////////////
190 // AW: Need own primitive to get the FlyFrame paint working
191 
192 namespace drawinglayer
193 {
194 	namespace primitive2d
195 	{
196 		class SwVirtFlyDrawObjPrimitive : public BufferedDecompositionPrimitive2D
197 		{
198         private:
199             const SwVirtFlyDrawObj&                 mrSwVirtFlyDrawObj;
200 			const basegfx::B2DRange					maOuterRange;
201 
202 		protected:
203 			// method which is to be used to implement the local decomposition of a 2D primitive
204 			virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const;
205 
206 		public:
207 			SwVirtFlyDrawObjPrimitive(
208 				const SwVirtFlyDrawObj& rSwVirtFlyDrawObj,
209 				const basegfx::B2DRange &rOuterRange)
210             :   BufferedDecompositionPrimitive2D(),
211                 mrSwVirtFlyDrawObj(rSwVirtFlyDrawObj),
212 				maOuterRange(rOuterRange)
213             {
214             }
215 
216 			// compare operator
217 			virtual bool operator==(const BasePrimitive2D& rPrimitive) const;
218 
219 			// get range
220 			virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const;
221 
222 			// overloaded to allow callbacks to wrap_DoPaintObject
223 			virtual Primitive2DSequence get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const;
224 
225 			// data read access
226 			const SwVirtFlyDrawObj& getSwVirtFlyDrawObj() const { return mrSwVirtFlyDrawObj; }
227 			const basegfx::B2DRange& getOuterRange() const { return maOuterRange; }
228 
229 			// provide unique ID
230 			DeclPrimitrive2DIDBlock()
231 		};
232 	} // end of namespace primitive2d
233 } // end of namespace drawinglayer
234 
235 namespace drawinglayer
236 {
237 	namespace primitive2d
238 	{
239 		Primitive2DSequence SwVirtFlyDrawObjPrimitive::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
240         {
241 			Primitive2DSequence aRetval;
242 
243 			if(!getOuterRange().isEmpty())
244 			{
245 				// currently this SW object has no primitive representation. As long as this is the case,
246 				// create invisible geometry to allow corfect HitTest and BoundRect calculations for the
247                 // object. Use a filled primitive to get 'inside' as default object hit. The special cases from
248                 // the old SwVirtFlyDrawObj::CheckHit implementation are handled now in SwDrawView::PickObj;
249                 // this removed the 'hack' to get a view from inside model data or to react on null-tolerance
250                 // as it was done in the old implementation
251                 const Primitive2DReference aHitTestReference(
252                     createHiddenGeometryPrimitives2D(
253                         true,
254                         getOuterRange()));
255 
256 				aRetval = Primitive2DSequence(&aHitTestReference, 1);
257 			}
258 
259 			return aRetval;
260         }
261 
262 		bool SwVirtFlyDrawObjPrimitive::operator==(const BasePrimitive2D& rPrimitive) const
263         {
264 			if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
265 			{
266 				const SwVirtFlyDrawObjPrimitive& rCompare = (SwVirtFlyDrawObjPrimitive&)rPrimitive;
267 
268 				return (&getSwVirtFlyDrawObj() == &rCompare.getSwVirtFlyDrawObj()
269 					&& getOuterRange() == rCompare.getOuterRange());
270 			}
271 
272 			return false;
273         }
274 
275 		basegfx::B2DRange SwVirtFlyDrawObjPrimitive::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
276         {
277             return getOuterRange();
278         }
279 
280 		Primitive2DSequence SwVirtFlyDrawObjPrimitive::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
281 		{
282             // This is the callback to keep the FlyFrame painting in SW alive as long as it
283             // is not changed to primitives. This is the method which will be called by the processors
284             // when they do not know this primitive (and they do not). Inside wrap_DoPaintObject
285             // there needs to be a test that paint is only done during SW repaints (see there).
286             // Using this mechanism guarantees the correct Z-Order of the VirtualObject-based FlyFrames.
287             getSwVirtFlyDrawObj().wrap_DoPaintObject();
288 
289             // call parent
290             return BufferedDecompositionPrimitive2D::get2DDecomposition(rViewInformation);
291 		}
292 
293         // provide unique ID
294 		ImplPrimitrive2DIDBlock(SwVirtFlyDrawObjPrimitive, PRIMITIVE2D_ID_SWVIRTFLYDRAWOBJPRIMITIVE2D)
295 
296     } // end of namespace primitive2d
297 } // end of namespace drawinglayer
298 
299 //////////////////////////////////////////////////////////////////////////////////////
300 // AW: own sdr::contact::ViewContact (VC) sdr::contact::ViewObjectContact (VOC) needed
301 // since offset is defined different from SdrVirtObj's sdr::contact::ViewContactOfVirtObj.
302 // For paint, that offset is used by setting at the OutputDevice; for primitives this is
303 // not possible since we have no OutputDevice, but define the geometry itself.
304 
305 namespace sdr
306 {
307 	namespace contact
308 	{
309 		class VCOfSwVirtFlyDrawObj : public ViewContactOfVirtObj
310 		{
311         protected:
312 			// This method is responsible for creating the graphical visualisation data
313             // ONLY based on model data
314 			virtual drawinglayer::primitive2d::Primitive2DSequence createViewIndependentPrimitive2DSequence() const;
315 
316         public:
317 			// basic constructor, used from SdrObject.
318             VCOfSwVirtFlyDrawObj(SwVirtFlyDrawObj& rObj)
319             :   ViewContactOfVirtObj(rObj)
320             {
321             }
322 			virtual ~VCOfSwVirtFlyDrawObj();
323 
324             // access to SwVirtFlyDrawObj
325             SwVirtFlyDrawObj& GetSwVirtFlyDrawObj() const
326             {
327 			    return (SwVirtFlyDrawObj&)mrObject;
328             }
329 		};
330 	} // end of namespace contact
331 } // end of namespace sdr
332 
333 namespace sdr
334 {
335 	namespace contact
336 	{
337 		drawinglayer::primitive2d::Primitive2DSequence VCOfSwVirtFlyDrawObj::createViewIndependentPrimitive2DSequence() const
338         {
339             drawinglayer::primitive2d::Primitive2DSequence xRetval;
340             const SdrObject& rReferencedObject = GetSwVirtFlyDrawObj().GetReferencedObj();
341 
342             if(rReferencedObject.ISA(SwFlyDrawObj))
343             {
344                 // create an own specialized primitive which is used as repaint callpoint and HitTest
345 				// for HitTest processor (see primitive implementation above)
346                 const basegfx::B2DRange aOuterRange(GetSwVirtFlyDrawObj().getOuterBound());
347 
348                 if(!aOuterRange.isEmpty())
349                 {
350 					const drawinglayer::primitive2d::Primitive2DReference xPrimitive(
351 						new drawinglayer::primitive2d::SwVirtFlyDrawObjPrimitive(
352 							GetSwVirtFlyDrawObj(),
353 							aOuterRange));
354 
355 					xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xPrimitive, 1);
356 				}
357             }
358 
359             return xRetval;
360         }
361 
362         VCOfSwVirtFlyDrawObj::~VCOfSwVirtFlyDrawObj()
363         {
364         }
365 	} // end of namespace contact
366 } // end of namespace sdr
367 
368 //////////////////////////////////////////////////////////////////////////////////////
369 
370 basegfx::B2DRange SwVirtFlyDrawObj::getOuterBound() const
371 {
372     basegfx::B2DRange aOuterRange;
373     const SdrObject& rReferencedObject = GetReferencedObj();
374 
375     if(rReferencedObject.ISA(SwFlyDrawObj))
376     {
377 		const SwFlyFrm* pFlyFrame = GetFlyFrm();
378 
379         if(pFlyFrame)
380         {
381 		    const Rectangle aOuterRectangle(pFlyFrame->Frm().Pos(), pFlyFrame->Frm().SSize());
382 
383 		    if(!aOuterRectangle.IsEmpty()
384 			    && RECT_EMPTY != aOuterRectangle.Right()
385 			    && RECT_EMPTY != aOuterRectangle.Bottom())
386 		    {
387                 aOuterRange.expand(basegfx::B2DTuple(aOuterRectangle.Left(), aOuterRectangle.Top()));
388                 aOuterRange.expand(basegfx::B2DTuple(aOuterRectangle.Right(), aOuterRectangle.Bottom()));
389             }
390         }
391     }
392 
393     return aOuterRange;
394 }
395 
396 basegfx::B2DRange SwVirtFlyDrawObj::getInnerBound() const
397 {
398     basegfx::B2DRange aInnerRange;
399     const SdrObject& rReferencedObject = GetReferencedObj();
400 
401     if(rReferencedObject.ISA(SwFlyDrawObj))
402     {
403 		const SwFlyFrm* pFlyFrame = GetFlyFrm();
404 
405         if(pFlyFrame)
406         {
407 			const Rectangle aInnerRectangle(pFlyFrame->Frm().Pos() + pFlyFrame->Prt().Pos(), pFlyFrame->Prt().SSize());
408 
409             if(!aInnerRectangle.IsEmpty()
410 			    && RECT_EMPTY != aInnerRectangle.Right()
411 			    && RECT_EMPTY != aInnerRectangle.Bottom())
412 		    {
413 			    aInnerRange.expand(basegfx::B2DTuple(aInnerRectangle.Left(), aInnerRectangle.Top()));
414 			    aInnerRange.expand(basegfx::B2DTuple(aInnerRectangle.Right(), aInnerRectangle.Bottom()));
415             }
416         }
417     }
418 
419     return aInnerRange;
420 }
421 
422 sdr::contact::ViewContact* SwVirtFlyDrawObj::CreateObjectSpecificViewContact()
423 {
424     // need an own ViewContact (VC) to allow creation of a specialized primitive
425     // for being able to visualize the FlyFrames in primitive renderers
426 	return new sdr::contact::VCOfSwVirtFlyDrawObj(*this);
427 }
428 
429 SwVirtFlyDrawObj::SwVirtFlyDrawObj(SdrObject& rNew, SwFlyFrm* pFly) :
430 	SdrVirtObj( rNew ),
431 	pFlyFrm( pFly )
432 {
433 	//#110094#-1
434 	// bNotPersistent = bNeedColorRestore = bWriterFlyFrame = sal_True;
435 	const SvxProtectItem &rP = pFlyFrm->GetFmt()->GetProtect();
436 	bMovProt = rP.IsPosProtected();
437 	bSizProt = rP.IsSizeProtected();
438 }
439 
440 
441 __EXPORT SwVirtFlyDrawObj::~SwVirtFlyDrawObj()
442 {
443 	if ( GetPage() )	//Der SdrPage die Verantwortung entziehen.
444 		GetPage()->RemoveObject( GetOrdNum() );
445 }
446 
447 /*************************************************************************
448 |*
449 |*	SwVirtFlyDrawObj::GetFmt()
450 |*
451 |*	Ersterstellung		MA 08. Dec. 94
452 |*	Letzte Aenderung	MA 08. Dec. 94
453 |*
454 *************************************************************************/
455 
456 const SwFrmFmt *SwVirtFlyDrawObj::GetFmt() const
457 {
458 	return GetFlyFrm()->GetFmt();
459 }
460 
461 
462 SwFrmFmt *SwVirtFlyDrawObj::GetFmt()
463 {
464 	return GetFlyFrm()->GetFmt();
465 }
466 
467 /*************************************************************************
468 |*
469 |*	SwVirtFlyDrawObj::Paint()
470 |*
471 |*	Ersterstellung		MA 20. Dec. 94
472 |*	Letzte Aenderung	MA 18. Dec. 95
473 |*
474 *************************************************************************/
475 
476 // --> OD #i102707#
477 namespace
478 {
479     class RestoreMapMode
480     {
481         public:
482             explicit RestoreMapMode( ViewShell* pViewShell )
483                 : mbMapModeRestored( false )
484                 , mpOutDev( pViewShell->GetOut() )
485             {
486                 if ( pViewShell->getPrePostMapMode() != mpOutDev->GetMapMode() )
487                 {
488                     mpOutDev->Push(PUSH_MAPMODE);
489 
490                     GDIMetaFile* pMetaFile = mpOutDev->GetConnectMetaFile();
491                     if ( pMetaFile &&
492                          pMetaFile->IsRecord() && !pMetaFile->IsPause() )
493                     {
494                         ASSERT( false,
495                                 "MapMode restoration during meta file creation is somehow suspect - using <SetRelativeMapMode(..)>, but not sure, if correct." )
496                         mpOutDev->SetRelativeMapMode( pViewShell->getPrePostMapMode() );
497                     }
498                     else
499                     {
500                         mpOutDev->SetMapMode( pViewShell->getPrePostMapMode() );
501                     }
502 
503                     mbMapModeRestored = true;
504                 }
505             };
506 
507             ~RestoreMapMode()
508             {
509                 if ( mbMapModeRestored )
510                 {
511                     mpOutDev->Pop();
512                 }
513             };
514 
515         private:
516             bool mbMapModeRestored;
517             OutputDevice* mpOutDev;
518     };
519 }
520 // <--
521 
522 void SwVirtFlyDrawObj::wrap_DoPaintObject() const
523 {
524     ViewShell* pShell = pFlyFrm->getRootFrm()->GetCurrShell();
525 
526     // Only paint when we have a current shell and a DrawingLayer paint is in progress.
527     // This avcoids evtl. problems with renderers which do processing stuff,
528     // but no paints. IsPaintInProgress() depends on SW repaint, so, as long
529     // as SW paints self and calls DrawLayer() for Heaven and Hell, this will
530     // be correct
531     if ( pShell && pShell->IsDrawingLayerPaintInProgress() )
532     {
533         sal_Bool bDrawObject(sal_True);
534 
535         if ( !SwFlyFrm::IsPaint( (SdrObject*)this, pShell ) )
536 	    {
537 		    bDrawObject = sal_False;
538 	    }
539 
540         if ( bDrawObject )
541 	    {
542             if ( !pFlyFrm->IsFlyInCntFrm() )
543 		    {
544 				// it is also necessary to restore the VCL MapMode from ViewInformation since e.g.
545 				// the VCL PixelRenderer resets it at the used OutputDevice. Unfortunately, this
546 				// excludes shears and rotates which are not expressable in MapMode.
547                 // OD #i102707#
548                 // new helper class to restore MapMode - restoration, only if
549                 // needed and consideration of paint for meta file creation .
550                 RestoreMapMode aRestoreMapModeIfNeeded( pShell );
551 
552 				// paint the FlyFrame (use standard VCL-Paint)
553                 pFlyFrm->Paint( GetFlyFrm()->Frm() );
554 		    }
555 	    }
556     }
557 }
558 
559 /*************************************************************************
560 |*
561 |*	SwVirtFlyDrawObj::TakeObjInfo()
562 |*
563 |*	Ersterstellung		MA 03. May. 95
564 |*	Letzte Aenderung	MA 03. May. 95
565 |*
566 *************************************************************************/
567 
568 void __EXPORT SwVirtFlyDrawObj::TakeObjInfo( SdrObjTransformInfoRec& rInfo ) const
569 {
570 	rInfo.bSelectAllowed	 = rInfo.bMoveAllowed =
571 	rInfo.bResizeFreeAllowed = rInfo.bResizePropAllowed = sal_True;
572 
573 	rInfo.bRotateFreeAllowed = rInfo.bRotate90Allowed =
574 	rInfo.bMirrorFreeAllowed = rInfo.bMirror45Allowed =
575 	rInfo.bMirror90Allowed   = rInfo.bShearAllowed	  =
576 	rInfo.bCanConvToPath	 = rInfo.bCanConvToPoly	  =
577 	rInfo.bCanConvToPathLineToArea = rInfo.bCanConvToPolyLineToArea = sal_False;
578 }
579 
580 
581 /*************************************************************************
582 |*
583 |*	SwVirtFlyDrawObj::Groessenermittlung
584 |*
585 |*	Ersterstellung		MA 12. Jan. 95
586 |*	Letzte Aenderung	MA 10. Nov. 95
587 |*
588 *************************************************************************/
589 
590 void SwVirtFlyDrawObj::SetRect() const
591 {
592 	if ( GetFlyFrm()->Frm().HasArea() )
593 		((SwVirtFlyDrawObj*)this)->aOutRect = GetFlyFrm()->Frm().SVRect();
594 	else
595 		((SwVirtFlyDrawObj*)this)->aOutRect = Rectangle();
596 }
597 
598 
599 const Rectangle& __EXPORT SwVirtFlyDrawObj::GetCurrentBoundRect() const
600 {
601 	SetRect();
602 	return aOutRect;
603 }
604 
605 const Rectangle& __EXPORT SwVirtFlyDrawObj::GetLastBoundRect() const
606 {
607     return GetCurrentBoundRect();
608 }
609 
610 
611 void __EXPORT SwVirtFlyDrawObj::RecalcBoundRect()
612 {
613 	SetRect();
614 }
615 
616 
617 void __EXPORT SwVirtFlyDrawObj::RecalcSnapRect()
618 {
619 	SetRect();
620 }
621 
622 
623 const Rectangle& __EXPORT SwVirtFlyDrawObj::GetSnapRect()  const
624 {
625 	SetRect();
626 	return aOutRect;
627 }
628 
629 
630 void __EXPORT SwVirtFlyDrawObj::SetSnapRect(const Rectangle& )
631 {
632 	Rectangle aTmp( GetLastBoundRect() );
633 	SetRect();
634 	SetChanged();
635 	BroadcastObjectChange();
636 	if (pUserCall!=NULL)
637 		pUserCall->Changed(*this, SDRUSERCALL_RESIZE, aTmp);
638 }
639 
640 
641 void __EXPORT SwVirtFlyDrawObj::NbcSetSnapRect(const Rectangle& )
642 {
643 	SetRect();
644 }
645 
646 
647 const Rectangle& __EXPORT SwVirtFlyDrawObj::GetLogicRect() const
648 {
649 	SetRect();
650 	return aOutRect;
651 }
652 
653 
654 void __EXPORT SwVirtFlyDrawObj::SetLogicRect(const Rectangle& )
655 {
656 	Rectangle aTmp( GetLastBoundRect() );
657 	SetRect();
658 	SetChanged();
659 	BroadcastObjectChange();
660 	if (pUserCall!=NULL)
661 		pUserCall->Changed(*this, SDRUSERCALL_RESIZE, aTmp);
662 }
663 
664 
665 void __EXPORT SwVirtFlyDrawObj::NbcSetLogicRect(const Rectangle& )
666 {
667 	SetRect();
668 }
669 
670 
671 ::basegfx::B2DPolyPolygon SwVirtFlyDrawObj::TakeXorPoly() const
672 {
673 	const Rectangle aSourceRectangle(GetFlyFrm()->Frm().SVRect());
674 	const ::basegfx::B2DRange aSourceRange(aSourceRectangle.Left(), aSourceRectangle.Top(), aSourceRectangle.Right(), aSourceRectangle.Bottom());
675 	::basegfx::B2DPolyPolygon aRetval;
676 
677 	aRetval.append(::basegfx::tools::createPolygonFromRect(aSourceRange));
678 
679 	return aRetval;
680 }
681 
682 /*************************************************************************
683 |*
684 |*	SwVirtFlyDrawObj::Move() und Resize()
685 |*
686 |*	Ersterstellung		MA 12. Jan. 95
687 |*	Letzte Aenderung	MA 26. Jul. 96
688 |*
689 *************************************************************************/
690 
691 void __EXPORT SwVirtFlyDrawObj::NbcMove(const Size& rSiz)
692 {
693 	MoveRect( aOutRect, rSiz );
694 	const Point aOldPos( GetFlyFrm()->Frm().Pos() );
695 	const Point aNewPos( aOutRect.TopLeft() );
696 	const SwRect aFlyRect( aOutRect );
697 
698 	//Wenn der Fly eine automatische Ausrichtung hat (rechts oder oben),
699 	//so soll die Automatik erhalten bleiben
700 	SwFrmFmt *pFmt = GetFlyFrm()->GetFmt();
701     const sal_Int16 eHori = pFmt->GetHoriOrient().GetHoriOrient();
702     const sal_Int16 eVert = pFmt->GetVertOrient().GetVertOrient();
703     const sal_Int16 eRelHori = pFmt->GetHoriOrient().GetRelationOrient();
704     const sal_Int16 eRelVert = pFmt->GetVertOrient().GetRelationOrient();
705 	//Bei Absatzgebundenen Flys muss ausgehend von der neuen Position ein
706 	//neuer Anker gesetzt werden. Anker und neue RelPos werden vom Fly selbst
707 	//berechnet und gesetzt.
708     if( GetFlyFrm()->IsFlyAtCntFrm() )
709 		((SwFlyAtCntFrm*)GetFlyFrm())->SetAbsPos( aNewPos );
710 	else
711 	{
712         const SwFrmFmt *pTmpFmt = GetFmt();
713         const SwFmtVertOrient &rVert = pTmpFmt->GetVertOrient();
714         const SwFmtHoriOrient &rHori = pTmpFmt->GetHoriOrient();
715 		long lXDiff = aNewPos.X() - aOldPos.X();
716         if( rHori.IsPosToggle() && text::HoriOrientation::NONE == eHori &&
717 			!GetFlyFrm()->FindPageFrm()->OnRightPage() )
718 			lXDiff = -lXDiff;
719 
720         if( GetFlyFrm()->GetAnchorFrm()->IsRightToLeft() &&
721             text::HoriOrientation::NONE == eHori )
722             lXDiff = -lXDiff;
723 
724         long lYDiff = aNewPos.Y() - aOldPos.Y();
725         if( GetFlyFrm()->GetAnchorFrm()->IsVertical() )
726         {
727             //lXDiff -= rVert.GetPos();
728             //lYDiff += rHori.GetPos();
729             //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
730             if ( GetFlyFrm()->GetAnchorFrm()->IsVertLR() )
731 	    	{
732 	    		lXDiff += rVert.GetPos();
733 	    		lXDiff = -lXDiff;
734 	    	}
735 	    	else
736 	    	{
737 				lXDiff -= rVert.GetPos();
738             	lYDiff += rHori.GetPos();
739 			}
740         }
741         else
742         {
743             lXDiff += rHori.GetPos();
744             lYDiff += rVert.GetPos();
745         }
746 
747         if( GetFlyFrm()->GetAnchorFrm()->IsRightToLeft() &&
748             text::HoriOrientation::NONE != eHori )
749             lXDiff = GetFlyFrm()->GetAnchorFrm()->Frm().Width() -
750 					 aFlyRect.Width() - lXDiff;
751 
752         const Point aTmp( lXDiff, lYDiff );
753 		GetFlyFrm()->ChgRelPos( aTmp );
754 	}
755 
756 	SwAttrSet aSet( pFmt->GetDoc()->GetAttrPool(),
757 											RES_VERT_ORIENT, RES_HORI_ORIENT );
758 	SwFmtHoriOrient aHori( pFmt->GetHoriOrient() );
759 	SwFmtVertOrient aVert( pFmt->GetVertOrient() );
760 	sal_Bool bPut = sal_False;
761 
762 	if( !GetFlyFrm()->IsFlyLayFrm() &&
763 		::GetHtmlMode(pFmt->GetDoc()->GetDocShell()) )
764 	{
765 		//Im HTML-Modus sind nur automatische Ausrichtungen erlaubt.
766 		//Einzig einen Snap auf Links/Rechts bzw. Linker-/Rechter-Rand koennen
767 		//wir versuchen.
768         const SwFrm* pAnch = GetFlyFrm()->GetAnchorFrm();
769 		sal_Bool bNextLine = sal_False;
770 
771         if( !GetFlyFrm()->IsAutoPos() || text::RelOrientation::PAGE_FRAME != aHori.GetRelationOrient() )
772 		{
773             if( text::RelOrientation::CHAR == eRelHori )
774 			{
775                 aHori.SetHoriOrient( text::HoriOrientation::LEFT );
776                 aHori.SetRelationOrient( text::RelOrientation::CHAR );
777 			}
778 			else
779 			{
780 				bNextLine = sal_True;
781 				//Horizontale Ausrichtung:
782 				const sal_Bool bLeftFrm =
783 					aFlyRect.Left() < pAnch->Frm().Left() + pAnch->Prt().Left(),
784 					bLeftPrt = aFlyRect.Left() + aFlyRect.Width() <
785 							   pAnch->Frm().Left() + pAnch->Prt().Width()/2;
786 				if ( bLeftFrm || bLeftPrt )
787 				{
788                     aHori.SetHoriOrient( text::HoriOrientation::LEFT );
789                     aHori.SetRelationOrient( bLeftFrm ? text::RelOrientation::FRAME : text::RelOrientation::PRINT_AREA );
790 				}
791 				else
792 				{
793 					const sal_Bool bRightFrm = aFlyRect.Left() >
794 									   pAnch->Frm().Left() + pAnch->Prt().Width();
795                     aHori.SetHoriOrient( text::HoriOrientation::RIGHT );
796                     aHori.SetRelationOrient( bRightFrm ? text::RelOrientation::FRAME : text::RelOrientation::PRINT_AREA );
797 				}
798 			}
799 			aSet.Put( aHori );
800 		}
801 		//Vertikale Ausrichtung bleibt grundsaetzlich schlicht erhalten,
802 		//nur bei nicht automatischer Ausrichtung wird umgeschaltet.
803         sal_Bool bRelChar = text::RelOrientation::CHAR == eRelVert;
804         aVert.SetVertOrient( eVert != text::VertOrientation::NONE ? eVert :
805                 GetFlyFrm()->IsFlyInCntFrm() ? text::VertOrientation::CHAR_CENTER :
806                 bRelChar && bNextLine ? text::VertOrientation::CHAR_TOP : text::VertOrientation::TOP );
807 		if( bRelChar )
808             aVert.SetRelationOrient( text::RelOrientation::CHAR );
809 		else
810             aVert.SetRelationOrient( text::RelOrientation::PRINT_AREA );
811 		aSet.Put( aVert );
812 		bPut = sal_True;
813 	}
814 
815 	//Automatische Ausrichtungen wollen wir moeglichst nicht verlieren.
816 	if ( !bPut && bInResize )
817 	{
818         if ( text::HoriOrientation::NONE != eHori )
819 		{
820 			aHori.SetHoriOrient( eHori );
821 			aHori.SetRelationOrient( eRelHori );
822 			aSet.Put( aHori );
823 			bPut = sal_True;
824 		}
825         if ( text::VertOrientation::NONE != eVert )
826 		{
827 			aVert.SetVertOrient( eVert );
828 			aVert.SetRelationOrient( eRelVert );
829 			aSet.Put( aVert );
830 			bPut = sal_True;
831 		}
832 	}
833 	if ( bPut )
834         pFmt->SetFmtAttr( aSet );
835 }
836 
837 
838 void __EXPORT SwVirtFlyDrawObj::NbcResize(const Point& rRef,
839 			const Fraction& xFact, const Fraction& yFact)
840 {
841 	ResizeRect( aOutRect, rRef, xFact, yFact );
842 
843     const SwFrm* pTmpFrm = GetFlyFrm()->GetAnchorFrm();
844     if( !pTmpFrm )
845         pTmpFrm = GetFlyFrm();
846     const bool bVertX = pTmpFrm->IsVertical();
847 
848     const sal_Bool bRTL = pTmpFrm->IsRightToLeft();
849 
850 	//Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
851 	const bool bVertL2RX = pTmpFrm->IsVertLR();
852     const Point aNewPos( ( bVertX && !bVertL2RX ) || bRTL ?
853 						 aOutRect.Right() + 1 :
854 						 aOutRect.Left(),
855                          aOutRect.Top() );
856 
857 	Size aSz( aOutRect.Right() - aOutRect.Left() + 1,
858 			  aOutRect.Bottom()- aOutRect.Top()  + 1 );
859 	if( aSz != GetFlyFrm()->Frm().SSize() )
860 	{
861 		//Die Breite darf bei Spalten nicht zu schmal werden
862 		if ( GetFlyFrm()->Lower() && GetFlyFrm()->Lower()->IsColumnFrm() )
863 		{
864 			SwBorderAttrAccess aAccess( SwFrm::GetCache(), GetFlyFrm() );
865 			const SwBorderAttrs &rAttrs = *aAccess.Get();
866 			long nMin = rAttrs.CalcLeftLine()+rAttrs.CalcRightLine();
867 			const SwFmtCol& rCol = rAttrs.GetAttrSet().GetCol();
868 			if ( rCol.GetColumns().Count() > 1 )
869 			{
870 				for ( sal_uInt16 i = 0; i < rCol.GetColumns().Count(); ++i )
871 				{
872 					nMin += rCol.GetColumns()[i]->GetLeft() +
873 							rCol.GetColumns()[i]->GetRight() +
874 							MINFLY;
875 				}
876 				nMin -= MINFLY;
877 			}
878 			aSz.Width() = Max( aSz.Width(), nMin );
879 		}
880 
881         SwFrmFmt *pFmt = GetFmt();
882 		const SwFmtFrmSize aOldFrmSz( pFmt->GetFrmSize() );
883 		GetFlyFrm()->ChgSize( aSz );
884 		SwFmtFrmSize aFrmSz( pFmt->GetFrmSize() );
885 		if ( aFrmSz.GetWidthPercent() || aFrmSz.GetHeightPercent() )
886 		{
887 			long nRelWidth, nRelHeight;
888 			const SwFrm *pRel = GetFlyFrm()->IsFlyLayFrm() ?
889                                 GetFlyFrm()->GetAnchorFrm() :
890                                 GetFlyFrm()->GetAnchorFrm()->GetUpper();
891 			const ViewShell *pSh = GetFlyFrm()->getRootFrm()->GetCurrShell();
892             if ( pSh && pRel->IsBodyFrm() &&
893                  pSh->GetViewOptions()->getBrowseMode() &&
894                  pSh->VisArea().HasArea() )
895 			{
896 				nRelWidth  = pSh->GetBrowseWidth();
897 				nRelHeight = pSh->VisArea().Height();
898 				const Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
899 				nRelHeight -= 2*aBorder.Height();
900 			}
901 			else
902 			{
903 				nRelWidth  = pRel->Prt().Width();
904 				nRelHeight = pRel->Prt().Height();
905 			}
906 			if ( aFrmSz.GetWidthPercent() && aFrmSz.GetWidthPercent() != 0xFF &&
907 				 aOldFrmSz.GetWidth() != aFrmSz.GetWidth() )
908 				aFrmSz.SetWidthPercent( sal_uInt8(aSz.Width() * 100L / nRelWidth + 0.5) );
909 			if ( aFrmSz.GetHeightPercent() && aFrmSz.GetHeightPercent() != 0xFF &&
910 				 aOldFrmSz.GetHeight() != aFrmSz.GetHeight() )
911 				aFrmSz.SetHeightPercent( sal_uInt8(aSz.Height() * 100L / nRelHeight + 0.5) );
912 			pFmt->GetDoc()->SetAttr( aFrmSz, *pFmt );
913 		}
914 	}
915 
916 	//Position kann auch veraendert sein!
917 	const Point aOldPos( ( bVertX && !bVertL2RX ) || bRTL ?
918                          GetFlyFrm()->Frm().TopRight() :
919                          GetFlyFrm()->Frm().Pos() );
920     if ( aNewPos != aOldPos )
921 	{
922 		//Kann sich durch das ChgSize veraendert haben!
923         if( bVertX || bRTL )
924         {
925             if( aOutRect.TopRight() != aNewPos )
926             {
927                 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
928                 SwTwips nDeltaX;
929 				if ( bVertL2RX )
930                 	nDeltaX = aNewPos.X() - aOutRect.Left();
931                 else
932                 	nDeltaX = aNewPos.X() - aOutRect.Right();
933                 SwTwips nDeltaY = aNewPos.Y() - aOutRect.Top();
934                 MoveRect( aOutRect, Size( nDeltaX, nDeltaY ) );
935             }
936         }
937         else if ( aOutRect.TopLeft() != aNewPos )
938 			aOutRect.SetPos( aNewPos );
939 		bInResize = sal_True;
940 		NbcMove( Size( 0, 0 ) );
941 		bInResize = sal_False;
942 	}
943 }
944 
945 
946 void __EXPORT SwVirtFlyDrawObj::Move(const Size& rSiz)
947 {
948 	NbcMove( rSiz );
949 	SetChanged();
950     GetFmt()->GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false);
951 }
952 
953 
954 void __EXPORT SwVirtFlyDrawObj::Resize(const Point& rRef,
955 					const Fraction& xFact, const Fraction& yFact)
956 {
957 	NbcResize( rRef, xFact, yFact );
958 	SetChanged();
959     GetFmt()->GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false);
960 }
961 
962 
963 Pointer  __EXPORT SwVirtFlyDrawObj::GetMacroPointer(
964     const SdrObjMacroHitRec& ) const
965 {
966 	return Pointer( POINTER_REFHAND );
967 }
968 
969 
970 FASTBOOL __EXPORT SwVirtFlyDrawObj::HasMacro() const
971 {
972 	const SwFmtURL &rURL = pFlyFrm->GetFmt()->GetURL();
973 	return rURL.GetMap() || rURL.GetURL().Len();
974 }
975 
976 
977 SdrObject* SwVirtFlyDrawObj::CheckMacroHit( const SdrObjMacroHitRec& rRec ) const
978 {
979 	const SwFmtURL &rURL = pFlyFrm->GetFmt()->GetURL();
980 	if( rURL.GetMap() || rURL.GetURL().Len() )
981 	{
982 		SwRect aRect;
983 		if ( pFlyFrm->Lower() && pFlyFrm->Lower()->IsNoTxtFrm() )
984 		{
985 			aRect = pFlyFrm->Prt();
986 			aRect += pFlyFrm->Frm().Pos();
987 		}
988 		else
989 			aRect = pFlyFrm->Frm();
990 
991 		if( aRect.IsInside( rRec.aPos ) )
992 		{
993 			SwRect aActRect( aRect );
994 			Size aActSz( aRect.SSize() );
995 			aRect.Pos().X() += rRec.nTol;
996 			aRect.Pos().Y() += rRec.nTol;
997 			aRect.SSize().Height()-= 2 * rRec.nTol;
998 			aRect.SSize().Width() -= 2 * rRec.nTol;
999 
1000 			if( aRect.IsInside( rRec.aPos ) )
1001 			{
1002 				if( !rURL.GetMap() ||
1003 					pFlyFrm->GetFmt()->GetIMapObject( rRec.aPos, pFlyFrm ))
1004 					return (SdrObject*)this;
1005 
1006 				return 0;
1007 			}
1008 		}
1009 	}
1010 	return SdrObject::CheckMacroHit( rRec );
1011 }
1012 
1013 bool SwVirtFlyDrawObj::supportsFullDrag() const
1014 {
1015     // call parent
1016     return SdrVirtObj::supportsFullDrag();
1017 }
1018 
1019 SdrObject* SwVirtFlyDrawObj::getFullDragClone() const
1020 {
1021     // call parent
1022     return SdrVirtObj::getFullDragClone();
1023 }
1024 
1025 // eof
1026