xref: /trunk/main/sw/source/core/draw/dflyobj.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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