xref: /trunk/main/sw/source/core/draw/dcontact.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 <editeng/protitem.hxx>
32 #include <editeng/opaqitem.hxx>
33 #include <editeng/ulspitem.hxx>
34 #include <editeng/lrspitem.hxx>
35 #include <svx/svdpage.hxx>
36 #include <svx/svditer.hxx>
37 #include <svx/fmglob.hxx>
38 #include <svx/svdogrp.hxx>
39 #include <svx/svdotext.hxx>
40 #include <svx/svdmodel.hxx>
41 #include <svx/svdpagv.hxx>
42 #include <svx/svdviter.hxx>
43 #include <svx/svdview.hxx>
44 #include <svx/shapepropertynotifier.hxx>
45 #include <svx/sdr/contact/objectcontactofobjlistpainter.hxx>
46 #include <svx/sdr/contact/displayinfo.hxx>
47 #include <fmtornt.hxx>
48 #include <viewimp.hxx>
49 #include <fmtsrnd.hxx>
50 #include <fmtanchr.hxx>
51 #include <node.hxx>
52 #include <fmtcntnt.hxx>
53 #include <pagefrm.hxx>
54 #include <rootfrm.hxx>
55 #include <frmtool.hxx>	// Notify_Background
56 #include <flyfrm.hxx>
57 #include <frmfmt.hxx>
58 #include <dflyobj.hxx>
59 #include <dcontact.hxx>
60 #include <unodraw.hxx>
61 #include <IDocumentDrawModelAccess.hxx>
62 #include <doc.hxx>
63 #include <hints.hxx>
64 #include <txtfrm.hxx>
65 #include <editsh.hxx>
66 #include <docary.hxx>
67 #include <flyfrms.hxx>
68 #include <sortedobjs.hxx>
69 #include <basegfx/matrix/b2dhommatrix.hxx>
70 #include <basegfx/matrix/b2dhommatrixtools.hxx>
71 #include <svx/sdr/contact/viewcontactofvirtobj.hxx>
72 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
73 #include <svx/sdr/contact/viewobjectcontactofsdrobj.hxx>
74 #include <com/sun/star/text/WritingMode2.hpp>
75 #include <switerator.hxx>
76 #include <algorithm>
77 
78 using namespace ::com::sun::star;
79 
80 
81 TYPEINIT1( SwContact, SwClient )
82 TYPEINIT1( SwFlyDrawContact, SwContact )
83 TYPEINIT1( SwDrawContact, SwContact )
84 
85 void setContextWritingMode( SdrObject* pObj, SwFrm* pAnchor )
86 {
87     if( pObj && pAnchor )
88     {
89         short nWritingDirection = text::WritingMode2::LR_TB;
90         if( pAnchor->IsVertical() )
91         {
92             nWritingDirection = text::WritingMode2::TB_RL;
93         } else if( pAnchor->IsRightToLeft() )
94         {
95             nWritingDirection = text::WritingMode2::RL_TB;
96         }
97         pObj->SetContextWritingMode( nWritingDirection );
98     }
99 }
100 
101 
102 //Der Umgekehrte Weg: Sucht das Format zum angegebenen Objekt.
103 //Wenn das Object ein SwVirtFlyDrawObj ist so wird das Format von
104 //selbigem besorgt.
105 //Anderfalls ist es eben ein einfaches Zeichenobjekt. Diese hat einen
106 //UserCall und der ist Client vom gesuchten Format.
107 
108 SwFrmFmt *FindFrmFmt( SdrObject *pObj )
109 {
110     SwFrmFmt* pRetval = 0L;
111 
112 	if ( pObj->ISA(SwVirtFlyDrawObj) )
113 	{
114        pRetval = ((SwVirtFlyDrawObj*)pObj)->GetFmt();
115 	}
116 	else
117 	{
118         SwDrawContact* pContact = static_cast<SwDrawContact*>(GetUserCall( pObj ));
119         if ( pContact )
120 		{
121 			pRetval = pContact->GetFmt();
122 		}
123 	}
124 /* SJ: after prior consultation with OD we decided to remove this Assertion
125 #if OSL_DEBUG_LEVEL > 1
126     ASSERT( pRetval,
127             "<::FindFrmFmt(..)> - no frame format found for given object. Please inform OD." );
128 #endif
129 */
130     return pRetval;
131 }
132 
133 sal_Bool HasWrap( const SdrObject* pObj )
134 {
135     if ( pObj )
136     {
137         const SwFrmFmt* pFmt = ::FindFrmFmt( pObj );
138         if ( pFmt )
139         {
140             return SURROUND_THROUGHT != pFmt->GetSurround().GetSurround();
141         }
142     }
143 
144     return sal_False;
145 }
146 
147 /*****************************************************************************
148  *
149  * GetBoundRect liefert das BoundRect _inklusive_ Abstand des Objekts.
150  *
151  *****************************************************************************/
152 
153 // --> OD 2006-08-15 #i68520# - change naming
154 SwRect GetBoundRectOfAnchoredObj( const SdrObject* pObj )
155 // <--
156 {
157 	SwRect aRet( pObj->GetCurrentBoundRect() );
158     // --> OD 2006-08-10 #i68520# - call cache of <SwAnchoredObject>
159     SwContact* pContact( GetUserCall( pObj ) );
160     if ( pContact )
161     {
162         const SwAnchoredObject* pAnchoredObj( pContact->GetAnchoredObj( pObj ) );
163         if ( pAnchoredObj )
164         {
165             aRet = pAnchoredObj->GetObjRectWithSpaces();
166         }
167     }
168     // <--
169 	return aRet;
170 }
171 
172 //Liefert den UserCall ggf. vom Gruppenobjekt
173 // OD 2004-03-31 #i26791# - change return type
174 SwContact* GetUserCall( const SdrObject* pObj )
175 {
176     SdrObject *pTmp;
177 	while ( !pObj->GetUserCall() && 0 != (pTmp = pObj->GetUpGroup()) )
178 		pObj = pTmp;
179     ASSERT( !pObj->GetUserCall() || pObj->GetUserCall()->ISA(SwContact),
180             "<::GetUserCall(..)> - wrong type of found object user call." );
181     return static_cast<SwContact*>(pObj->GetUserCall());
182 }
183 
184 // liefert sal_True falls das SrdObject ein Marquee-Object (Lauftext) ist
185 sal_Bool IsMarqueeTextObj( const SdrObject& rObj )
186 {
187 	SdrTextAniKind eTKind;
188 	return SdrInventor == rObj.GetObjInventor() &&
189 		OBJ_TEXT == rObj.GetObjIdentifier() &&
190 		( SDRTEXTANI_SCROLL == ( eTKind = ((SdrTextObj&)rObj).GetTextAniKind())
191 		 || SDRTEXTANI_ALTERNATE == eTKind || SDRTEXTANI_SLIDE == eTKind );
192 }
193 
194 /*************************************************************************
195 |*
196 |*	SwContact, Ctor und Dtor
197 |*
198 |*	Ersterstellung		AMA 27.Sep.96 18:13
199 |*	Letzte Aenderung	AMA 27.Sep.96
200 |*
201 |*************************************************************************/
202 
203 SwContact::SwContact( SwFrmFmt *pToRegisterIn ) :
204 	SwClient( pToRegisterIn ),
205     // OD 05.09.2003 #112039# - init member <mbInDTOR>
206     mbInDTOR( false )
207 {}
208 
209 SwContact::~SwContact()
210 {
211     // OD 05.09.2003 #112039# - set <mbInDTOR>
212     SetInDTOR();
213 }
214 
215 // OD 05.09.2003 #112039# - accessor for member <mbInDTOR>
216 bool SwContact::IsInDTOR() const
217 {
218     return mbInDTOR;
219 }
220 
221 // OD 05.09.2003 #112039# - accessor to set member <mbInDTOR>
222 void SwContact::SetInDTOR()
223 {
224     mbInDTOR = true;
225 }
226 
227 /** method to move drawing object to corresponding visible layer
228 
229     OD 21.08.2003 #i18447#
230 
231     @author OD
232 */
233 void SwContact::MoveObjToVisibleLayer( SdrObject* _pDrawObj )
234 {
235     // --> OD 2005-06-08 #i46297# - notify background about the arriving of
236     // the object and invalidate its position.
237     const bool bNotify( !GetFmt()->getIDocumentDrawModelAccess()->IsVisibleLayerId( _pDrawObj->GetLayer() ) );
238     // <--
239 
240     _MoveObjToLayer( true, _pDrawObj );
241 
242     // --> OD 2005-05-23 #i46297#
243     if ( bNotify )
244     {
245         SwAnchoredObject* pAnchoredObj = GetAnchoredObj( _pDrawObj );
246         ASSERT( pAnchoredObj,
247                 "<SwContact::MoveObjToInvisibleLayer(..)> - missing anchored object" );
248         if ( pAnchoredObj )
249         {
250             ::setContextWritingMode( _pDrawObj, pAnchoredObj->GetAnchorFrmContainingAnchPos() );
251             // Note: as-character anchored objects aren't registered at a page frame and
252             //       a notification of its background isn't needed.
253             if ( pAnchoredObj->GetPageFrm() )
254             {
255                 ::Notify_Background( _pDrawObj, pAnchoredObj->GetPageFrm(),
256                                      pAnchoredObj->GetObjRect(), PREP_FLY_ARRIVE, sal_True );
257             }
258 
259             pAnchoredObj->InvalidateObjPos();
260         }
261     }
262     // <--
263 }
264 
265 /** method to move drawing object to corresponding invisible layer
266 
267     OD 21.08.2003 #i18447#
268 
269     @author OD
270 */
271 void SwContact::MoveObjToInvisibleLayer( SdrObject* _pDrawObj )
272 {
273     // --> OD 2005-06-08 #i46297# - notify background about the leaving of the object.
274     const bool bNotify( GetFmt()->getIDocumentDrawModelAccess()->IsVisibleLayerId( _pDrawObj->GetLayer() ) );
275     // <--
276 
277     _MoveObjToLayer( false, _pDrawObj );
278 
279     // --> OD 2005-05-19 #i46297#
280     if ( bNotify )
281     {
282         SwAnchoredObject* pAnchoredObj = GetAnchoredObj( _pDrawObj );
283         ASSERT( pAnchoredObj,
284                 "<SwContact::MoveObjToInvisibleLayer(..)> - missing anchored object" );
285         // Note: as-character anchored objects aren't registered at a page frame and
286         //       a notification of its background isn't needed.
287         if ( pAnchoredObj && pAnchoredObj->GetPageFrm() )
288         {
289             ::Notify_Background( _pDrawObj, pAnchoredObj->GetPageFrm(),
290                                  pAnchoredObj->GetObjRect(), PREP_FLY_LEAVE, sal_True );
291         }
292     }
293     // <--
294 }
295 
296 /** method to move object to visible/invisible layer
297 
298     OD 21.08.2003 #i18447#
299     implementation for the public method <MoveObjToVisibleLayer(..)>
300     and <MoveObjToInvisibleLayer(..)>
301 
302     @author OD
303 */
304 void SwContact::_MoveObjToLayer( const bool _bToVisible,
305                                  SdrObject* _pDrawObj )
306 {
307     if ( !_pDrawObj )
308     {
309         ASSERT( false, "SwDrawContact::_MoveObjToLayer(..) - no drawing object!" );
310         return;
311     }
312 
313     if ( !GetRegisteredIn() )
314     {
315         ASSERT( false, "SwDrawContact::_MoveObjToLayer(..) - no drawing frame format!" );
316         return;
317     }
318 
319     const IDocumentDrawModelAccess* pIDDMA = static_cast<SwFrmFmt*>(GetRegisteredInNonConst())->getIDocumentDrawModelAccess();
320     if ( !pIDDMA )
321     {
322         ASSERT( false, "SwDrawContact::_MoveObjToLayer(..) - no writer document!" );
323         return;
324     }
325 
326     SdrLayerID nToHellLayerId =
327         _bToVisible ? pIDDMA->GetHellId() : pIDDMA->GetInvisibleHellId();
328     SdrLayerID nToHeavenLayerId =
329         _bToVisible ? pIDDMA->GetHeavenId() : pIDDMA->GetInvisibleHeavenId();
330     SdrLayerID nToControlLayerId =
331         _bToVisible ? pIDDMA->GetControlsId() : pIDDMA->GetInvisibleControlsId();
332     SdrLayerID nFromHellLayerId =
333         _bToVisible ? pIDDMA->GetInvisibleHellId() : pIDDMA->GetHellId();
334     SdrLayerID nFromHeavenLayerId =
335         _bToVisible ? pIDDMA->GetInvisibleHeavenId() : pIDDMA->GetHeavenId();
336     SdrLayerID nFromControlLayerId =
337         _bToVisible ? pIDDMA->GetInvisibleControlsId() : pIDDMA->GetControlsId();
338 
339     if ( _pDrawObj->ISA( SdrObjGroup ) )
340     {
341         // determine layer for group object
342         {
343             // proposed layer of a group object is the hell layer
344             SdrLayerID nNewLayerId = nToHellLayerId;
345             if ( ::CheckControlLayer( _pDrawObj ) )
346             {
347                 // it has to be the control layer, if one of the member
348                 // is a control
349                 nNewLayerId = nToControlLayerId;
350             }
351             else if ( _pDrawObj->GetLayer() == pIDDMA->GetHeavenId() ||
352                       _pDrawObj->GetLayer() == pIDDMA->GetInvisibleHeavenId() )
353             {
354                 // it has to be the heaven layer, if method <GetLayer()> reveals
355                 // a heaven layer
356                 nNewLayerId = nToHeavenLayerId;
357             }
358             // set layer at group object, but do *not* broadcast and
359             // no propagation to the members.
360             // Thus, call <NbcSetLayer(..)> at super class
361             _pDrawObj->SdrObject::NbcSetLayer( nNewLayerId );
362         }
363 
364         // call method recursively for group object members
365         const SdrObjList* pLst =
366                 static_cast<SdrObjGroup*>(_pDrawObj)->GetSubList();
367         if ( pLst )
368         {
369             for ( sal_uInt16 i = 0; i < pLst->GetObjCount(); ++i )
370             {
371                 _MoveObjToLayer( _bToVisible, pLst->GetObj( i ) );
372             }
373         }
374     }
375     else
376     {
377         const SdrLayerID nLayerIdOfObj = _pDrawObj->GetLayer();
378         if ( nLayerIdOfObj == nFromHellLayerId )
379         {
380             _pDrawObj->SetLayer( nToHellLayerId );
381         }
382         else if ( nLayerIdOfObj == nFromHeavenLayerId )
383         {
384             _pDrawObj->SetLayer( nToHeavenLayerId );
385         }
386         else if ( nLayerIdOfObj == nFromControlLayerId )
387         {
388             _pDrawObj->SetLayer( nToControlLayerId );
389         }
390     }
391 }
392 
393 // -------------------------------------------------------------------------
394 // OD 2004-01-16 #110582# - some virtual helper methods for information
395 // about the object (Writer fly frame resp. drawing object)
396 
397 const SwIndex& SwContact::GetCntntAnchorIndex() const
398 {
399     return GetCntntAnchor().nContent;
400 }
401 
402 /** get minimum order number of anchored objects handled by with contact
403 
404     OD 2004-08-24 #110810#
405 
406     @author
407 */
408 sal_uInt32 SwContact::GetMinOrdNum() const
409 {
410     sal_uInt32 nMinOrdNum( SAL_MAX_UINT32 );
411 
412     std::list< SwAnchoredObject* > aObjs;
413     GetAnchoredObjs( aObjs );
414 
415     while ( !aObjs.empty() )
416     {
417         sal_uInt32 nTmpOrdNum = aObjs.back()->GetDrawObj()->GetOrdNum();
418 
419         if ( nTmpOrdNum < nMinOrdNum )
420         {
421             nMinOrdNum = nTmpOrdNum;
422         }
423 
424         aObjs.pop_back();
425     }
426 
427     ASSERT( nMinOrdNum != SAL_MAX_UINT32,
428             "<SwContact::GetMinOrdNum()> - no order number found." );
429     return nMinOrdNum;
430 }
431 
432 /** get maximum order number of anchored objects handled by with contact
433 
434     OD 2004-08-24 #110810#
435 
436     @author
437 */
438 sal_uInt32 SwContact::GetMaxOrdNum() const
439 {
440     sal_uInt32 nMaxOrdNum( 0L );
441 
442     std::list< SwAnchoredObject* > aObjs;
443     GetAnchoredObjs( aObjs );
444 
445     while ( !aObjs.empty() )
446     {
447         sal_uInt32 nTmpOrdNum = aObjs.back()->GetDrawObj()->GetOrdNum();
448 
449         if ( nTmpOrdNum > nMaxOrdNum )
450         {
451             nMaxOrdNum = nTmpOrdNum;
452         }
453 
454         aObjs.pop_back();
455     }
456 
457     return nMaxOrdNum;
458 }
459 // -------------------------------------------------------------------------
460 
461 /*************************************************************************
462 |*
463 |*	SwFlyDrawContact, Ctor und Dtor
464 |*
465 |*	Ersterstellung		OK 23.11.94 18:13
466 |*	Letzte Aenderung	MA 06. Apr. 95
467 |*
468 |*************************************************************************/
469 
470 SwFlyDrawContact::SwFlyDrawContact( SwFlyFrmFmt *pToRegisterIn, SdrModel * ) :
471 	SwContact( pToRegisterIn )
472 {
473     // OD 2004-04-01 #i26791# - class <SwFlyDrawContact> contains the 'master'
474     // drawing object of type <SwFlyDrawObj> on its own.
475     mpMasterObj = new SwFlyDrawObj;
476     mpMasterObj->SetOrdNum( 0xFFFFFFFE );
477     mpMasterObj->SetUserCall( this );
478 }
479 
480 SwFlyDrawContact::~SwFlyDrawContact()
481 {
482     if ( mpMasterObj )
483     {
484         mpMasterObj->SetUserCall( 0 );
485         if ( mpMasterObj->GetPage() )
486             mpMasterObj->GetPage()->RemoveObject( mpMasterObj->GetOrdNum() );
487         delete mpMasterObj;
488     }
489 }
490 
491 // OD 2004-03-29 #i26791#
492 const SwAnchoredObject* SwFlyDrawContact::GetAnchoredObj( const SdrObject* _pSdrObj ) const
493 {
494     ASSERT( _pSdrObj,
495             "<SwFlyDrawContact::GetAnchoredObj(..)> - no object provided" );
496     ASSERT( _pSdrObj->ISA(SwVirtFlyDrawObj),
497             "<SwFlyDrawContact::GetAnchoredObj(..)> - wrong object type object provided" );
498     ASSERT( GetUserCall( _pSdrObj ) == const_cast<SwFlyDrawContact*>(this),
499             "<SwFlyDrawContact::GetAnchoredObj(..)> - provided object doesn't belongs to this contact" );
500 
501     const SwAnchoredObject* pRetAnchoredObj = 0L;
502 
503     if ( _pSdrObj && _pSdrObj->ISA(SwVirtFlyDrawObj) )
504     {
505         pRetAnchoredObj = static_cast<const SwVirtFlyDrawObj*>(_pSdrObj)->GetFlyFrm();
506     }
507 
508     return pRetAnchoredObj;
509 }
510 
511 SwAnchoredObject* SwFlyDrawContact::GetAnchoredObj( SdrObject* _pSdrObj )
512 {
513     ASSERT( _pSdrObj,
514             "<SwFlyDrawContact::GetAnchoredObj(..)> - no object provided" );
515     ASSERT( _pSdrObj->ISA(SwVirtFlyDrawObj),
516             "<SwFlyDrawContact::GetAnchoredObj(..)> - wrong object type provided" );
517     ASSERT( GetUserCall( _pSdrObj ) == this,
518             "<SwFlyDrawContact::GetAnchoredObj(..)> - provided object doesn't belongs to this contact" );
519 
520     SwAnchoredObject* pRetAnchoredObj = 0L;
521 
522     if ( _pSdrObj && _pSdrObj->ISA(SwVirtFlyDrawObj) )
523     {
524         pRetAnchoredObj = static_cast<SwVirtFlyDrawObj*>(_pSdrObj)->GetFlyFrm();
525     }
526 
527     return pRetAnchoredObj;
528 }
529 
530 const SdrObject* SwFlyDrawContact::GetMaster() const
531 {
532     return mpMasterObj;
533 }
534 
535 SdrObject* SwFlyDrawContact::GetMaster()
536 {
537     return mpMasterObj;
538 }
539 
540 void SwFlyDrawContact::SetMaster( SdrObject* _pNewMaster )
541 {
542     ASSERT( _pNewMaster->ISA(SwFlyDrawObj),
543             "<SwFlyDrawContact::SetMaster(..)> - wrong type of new master object" );
544     mpMasterObj = static_cast<SwFlyDrawObj *>(_pNewMaster);
545 }
546 
547 /*************************************************************************
548 |*
549 |*	SwFlyDrawContact::Modify()
550 |*
551 |*	Ersterstellung		OK 08.11.94 10:21
552 |*	Letzte Aenderung	MA 06. Dec. 94
553 |*
554 |*************************************************************************/
555 
556 void SwFlyDrawContact::Modify( const SfxPoolItem*, const SfxPoolItem * )
557 {
558 }
559 
560 // OD 2004-01-16 #110582# - override method to control Writer fly frames,
561 // which are linked, and to assure that all objects anchored at/inside the
562 // Writer fly frame are also made visible.
563 void SwFlyDrawContact::MoveObjToVisibleLayer( SdrObject* _pDrawObj )
564 {
565     ASSERT( _pDrawObj->ISA(SwVirtFlyDrawObj),
566             "<SwFlyDrawContact::MoveObjToVisibleLayer(..)> - wrong SdrObject type -> crash" );
567 
568     if ( GetFmt()->getIDocumentDrawModelAccess()->IsVisibleLayerId( _pDrawObj->GetLayer() ) )
569     {
570         // nothing to do
571         return;
572     }
573 
574     SwFlyFrm* pFlyFrm = static_cast<SwVirtFlyDrawObj*>(_pDrawObj)->GetFlyFrm();
575 
576     // --> OD 2005-03-09 #i44464# - consider, that Writer fly frame content
577     // already exists - (e.g. WW8 document is inserted into a existing document).
578     if ( !pFlyFrm->Lower() )
579     {
580         pFlyFrm->InsertColumns();
581         pFlyFrm->Chain( pFlyFrm->AnchorFrm() );
582         pFlyFrm->InsertCnt();
583     }
584     if ( pFlyFrm->GetDrawObjs() )
585     {
586         for ( sal_uInt8 i = 0; i < pFlyFrm->GetDrawObjs()->Count(); ++i)
587         {
588             // --> OD 2004-07-01 #i28701# - consider type of objects in sorted object list.
589             SdrObject* pObj = (*pFlyFrm->GetDrawObjs())[i]->DrawObj();
590             SwContact* pContact = static_cast<SwContact*>(pObj->GetUserCall());
591             pContact->MoveObjToVisibleLayer( pObj );
592         }
593     }
594 
595     // make fly frame visible
596     SwContact::MoveObjToVisibleLayer( _pDrawObj );
597 }
598 
599 // OD 2004-01-16 #110582# - override method to control Writer fly frames,
600 // which are linked, and to assure that all objects anchored at/inside the
601 // Writer fly frame are also made invisible.
602 void SwFlyDrawContact::MoveObjToInvisibleLayer( SdrObject* _pDrawObj )
603 {
604     ASSERT( _pDrawObj->ISA(SwVirtFlyDrawObj),
605             "<SwFlyDrawContact::MoveObjToInvisibleLayer(..)> - wrong SdrObject type -> crash" );
606 
607     if ( !GetFmt()->getIDocumentDrawModelAccess()->IsVisibleLayerId( _pDrawObj->GetLayer() ) )
608     {
609         // nothing to do
610         return;
611     }
612 
613     SwFlyFrm* pFlyFrm = static_cast<SwVirtFlyDrawObj*>(_pDrawObj)->GetFlyFrm();
614 
615     pFlyFrm->Unchain();
616     pFlyFrm->DeleteCnt();
617     if ( pFlyFrm->GetDrawObjs() )
618     {
619         for ( sal_uInt8 i = 0; i < pFlyFrm->GetDrawObjs()->Count(); ++i)
620         {
621             // --> OD 2004-07-01 #i28701# - consider type of objects in sorted object list.
622             SdrObject* pObj = (*pFlyFrm->GetDrawObjs())[i]->DrawObj();
623             SwContact* pContact = static_cast<SwContact*>(pObj->GetUserCall());
624             pContact->MoveObjToInvisibleLayer( pObj );
625         }
626     }
627 
628     // make fly frame invisible
629     SwContact::MoveObjToInvisibleLayer( _pDrawObj );
630 }
631 
632 /** get data collection of anchored objects, handled by with contact
633 
634     OD 2004-08-23 #110810#
635 
636     @author
637 */
638 void SwFlyDrawContact::GetAnchoredObjs( std::list<SwAnchoredObject*>& _roAnchoredObjs ) const
639 {
640     const SwFrmFmt* pFmt = GetFmt();
641     SwFlyFrm::GetAnchoredObjects( _roAnchoredObjs, *pFmt );
642 }
643 
644 /*************************************************************************
645 |*
646 |*	SwDrawContact, Ctor+Dtor
647 |*
648 |*	Ersterstellung		MA 09. Jan. 95
649 |*	Letzte Aenderung	MA 22. Jul. 98
650 |*
651 |*************************************************************************/
652 bool CheckControlLayer( const SdrObject *pObj )
653 {
654 	if ( FmFormInventor == pObj->GetObjInventor() )
655         return true;
656 	if ( pObj->ISA( SdrObjGroup ) )
657 	{
658 		const SdrObjList *pLst = ((SdrObjGroup*)pObj)->GetSubList();
659 		for ( sal_uInt16 i = 0; i < pLst->GetObjCount(); ++i )
660         {
661             if ( ::CheckControlLayer( pLst->GetObj( i ) ) )
662             {
663                 // OD 21.08.2003 #i18447# - return correct value ;-)
664                 return true;
665             }
666         }
667 	}
668     return false;
669 }
670 
671 SwDrawContact::SwDrawContact( SwFrmFmt* pToRegisterIn, SdrObject* pObj ) :
672     SwContact( pToRegisterIn ),
673     maAnchoredDrawObj(),
674     mbMasterObjCleared( false ),
675     // OD 10.10.2003 #112299#
676     mbDisconnectInProgress( false ),
677     // --> OD 2006-01-18 #129959#
678     mbUserCallActive( false ),
679     // Note: value of <meEventTypeOfCurrentUserCall> isn't of relevance, because
680     //       <mbUserCallActive> is sal_False.
681     meEventTypeOfCurrentUserCall( SDRUSERCALL_MOVEONLY )
682     // <--
683 {
684     // clear list containing 'virtual' drawing objects.
685     maDrawVirtObjs.clear();
686 
687     // --> OD 2004-09-22 #i33909# - assure, that drawing object is inserted
688     // in the drawing page.
689     if ( !pObj->IsInserted() )
690     {
691         pToRegisterIn->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage(0)->
692                                 InsertObject( pObj, pObj->GetOrdNumDirect() );
693     }
694     // <--
695 
696     //Controls muessen immer im Control-Layer liegen. Das gilt auch fuer
697 	//Gruppenobjekte, wenn diese Controls enthalten.
698     if ( ::CheckControlLayer( pObj ) )
699     {
700         // OD 25.06.2003 #108784# - set layer of object to corresponding invisible layer.
701         pObj->SetLayer( pToRegisterIn->getIDocumentDrawModelAccess()->GetInvisibleControlsId() );
702     }
703 
704     // OD 2004-03-29 #i26791#
705     pObj->SetUserCall( this );
706     maAnchoredDrawObj.SetDrawObj( *pObj );
707 
708     // if there already exists an SwXShape for the object, ensure it knows about us, and the SdrObject
709     // FS 2009-04-07 #i99056#
710     SwXShape::AddExistingShapeToFmt( *pObj );
711 }
712 
713 SwDrawContact::~SwDrawContact()
714 {
715     // OD 05.09.2003 #112039# - set <mbInDTOR>
716     SetInDTOR();
717 
718     DisconnectFromLayout();
719 
720     // OD 25.06.2003 #108784# - remove 'master' from drawing page
721     RemoveMasterFromDrawPage();
722 
723     // remove and destroy 'virtual' drawing objects.
724     RemoveAllVirtObjs();
725 
726     if ( !mbMasterObjCleared )
727     {
728         SdrObject* pObject = const_cast< SdrObject* >( maAnchoredDrawObj.GetDrawObj() );
729         SdrObject::Free( pObject );
730     }
731 }
732 
733 void SwDrawContact::GetTextObjectsFromFmt( std::list<SdrTextObj*>& rTextObjects, SwDoc* pDoc )
734 {
735     for( sal_Int32 n=0; n<pDoc->GetSpzFrmFmts()->Count(); n++ )
736     {
737         SwFrmFmt* pFly = (*pDoc->GetSpzFrmFmts())[n];
738         if( pFly->IsA( TYPE(SwDrawFrmFmt) ) )
739         {
740             std::list<SdrTextObj*> aTextObjs;
741             SwDrawContact* pContact = SwIterator<SwDrawContact,SwFrmFmt>::FirstElement(*pFly);
742             if( pContact )
743             {
744                 SdrObject* pSdrO = pContact->GetMaster();
745                 if ( pSdrO )
746                 {
747                     if ( pSdrO->IsA( TYPE(SdrObjGroup) ) )
748                     {
749                         SdrObjListIter aListIter( *pSdrO, IM_DEEPNOGROUPS );
750                         //iterate inside of a grouped object
751                         while( aListIter.IsMore() )
752                         {
753                             SdrObject* pSdrOElement = aListIter.Next();
754                             if( pSdrOElement && pSdrOElement->IsA( TYPE(SdrTextObj) ) &&
755                                 static_cast<SdrTextObj*>( pSdrOElement)->HasText() )
756                             {
757                                 rTextObjects.push_back((SdrTextObj*) pSdrOElement);
758                             }
759                         }
760                     }
761                     else if( pSdrO->IsA( TYPE(SdrTextObj) ) &&
762                             static_cast<SdrTextObj*>( pSdrO )->HasText() )
763                     {
764                         rTextObjects.push_back((SdrTextObj*) pSdrO);
765                     }
766                 }
767             }
768         }
769     }
770 }
771 
772 // OD 2004-03-29 #i26791#
773 const SwAnchoredObject* SwDrawContact::GetAnchoredObj( const SdrObject* _pSdrObj ) const
774 {
775     // handle default parameter value
776     if ( !_pSdrObj )
777     {
778         _pSdrObj = GetMaster();
779     }
780 
781     ASSERT( _pSdrObj,
782             "<SwDrawContact::GetAnchoredObj(..)> - no object provided" );
783     ASSERT( _pSdrObj->ISA(SwDrawVirtObj) ||
784             ( !_pSdrObj->ISA(SdrVirtObj) && !_pSdrObj->ISA(SwDrawVirtObj) ),
785             "<SwDrawContact::GetAnchoredObj(..)> - wrong object type object provided" );
786     ASSERT( GetUserCall( _pSdrObj ) == const_cast<SwDrawContact*>(this) ||
787             _pSdrObj == GetMaster(),
788             "<SwDrawContact::GetAnchoredObj(..)> - provided object doesn't belongs to this contact" );
789 
790     const SwAnchoredObject* pRetAnchoredObj = 0L;
791 
792     if ( _pSdrObj )
793     {
794         if ( _pSdrObj->ISA(SwDrawVirtObj) )
795         {
796             pRetAnchoredObj = static_cast<const SwDrawVirtObj*>(_pSdrObj)->GetAnchoredObj();
797         }
798         else if ( !_pSdrObj->ISA(SdrVirtObj) && !_pSdrObj->ISA(SwDrawVirtObj) )
799         {
800             pRetAnchoredObj = &maAnchoredDrawObj;
801         }
802     }
803 
804     return pRetAnchoredObj;
805 }
806 
807 SwAnchoredObject* SwDrawContact::GetAnchoredObj( SdrObject* _pSdrObj )
808 {
809     // handle default parameter value
810     if ( !_pSdrObj )
811     {
812         _pSdrObj = GetMaster();
813     }
814 
815     ASSERT( _pSdrObj,
816             "<SwDrawContact::GetAnchoredObj(..)> - no object provided" );
817     ASSERT( _pSdrObj->ISA(SwDrawVirtObj) ||
818             ( !_pSdrObj->ISA(SdrVirtObj) && !_pSdrObj->ISA(SwDrawVirtObj) ),
819             "<SwDrawContact::GetAnchoredObj(..)> - wrong object type object provided" );
820     ASSERT( GetUserCall( _pSdrObj ) == this || _pSdrObj == GetMaster(),
821             "<SwDrawContact::GetAnchoredObj(..)> - provided object doesn't belongs to this contact" );
822 
823     SwAnchoredObject* pRetAnchoredObj = 0L;
824 
825     if ( _pSdrObj )
826     {
827         if ( _pSdrObj->ISA(SwDrawVirtObj) )
828         {
829             pRetAnchoredObj = static_cast<SwDrawVirtObj*>(_pSdrObj)->AnchoredObj();
830         }
831         else if ( !_pSdrObj->ISA(SdrVirtObj) && !_pSdrObj->ISA(SwDrawVirtObj) )
832         {
833             pRetAnchoredObj = &maAnchoredDrawObj;
834         }
835     }
836 
837     return pRetAnchoredObj;
838 }
839 
840 const SdrObject* SwDrawContact::GetMaster() const
841 {
842     return !mbMasterObjCleared
843            ? maAnchoredDrawObj.GetDrawObj()
844            : 0L;
845 }
846 
847 SdrObject* SwDrawContact::GetMaster()
848 {
849     return !mbMasterObjCleared
850            ? maAnchoredDrawObj.DrawObj()
851            : 0L;
852 }
853 
854 // OD 16.05.2003 #108784# - overload <SwContact::SetMaster(..)> in order to
855 // assert, if the 'master' drawing object is replaced.
856 // OD 10.07.2003 #110742# - replace of master object correctly handled, if
857 // handled by method <SwDrawContact::ChangeMasterObject(..)>. Thus, assert
858 // only, if a debug level is given.
859 void SwDrawContact::SetMaster( SdrObject* _pNewMaster )
860 {
861     if ( _pNewMaster )
862     {
863 #if OSL_DEBUG_LEVEL > 1
864         ASSERT( false, "debug notification - master replaced!" );
865 #endif
866         maAnchoredDrawObj.SetDrawObj( *_pNewMaster );
867     }
868     else
869     {
870         mbMasterObjCleared = true;
871     }
872 }
873 
874 const SwFrm* SwDrawContact::GetAnchorFrm( const SdrObject* _pDrawObj ) const
875 {
876     const SwFrm* pAnchorFrm = 0L;
877     if ( !_pDrawObj ||
878          _pDrawObj == GetMaster() ||
879          ( !_pDrawObj->GetUserCall() &&
880            GetUserCall( _pDrawObj ) == static_cast<const SwContact* const>(this) ) )
881     {
882         pAnchorFrm = maAnchoredDrawObj.GetAnchorFrm();
883     }
884     else if ( _pDrawObj->ISA(SwDrawVirtObj) )
885     {
886         pAnchorFrm = static_cast<const SwDrawVirtObj*>(_pDrawObj)->GetAnchorFrm();
887     }
888     else
889     {
890         ASSERT( false,
891                 "<SwDrawContact::GetAnchorFrm(..)> - unknown drawing object." )
892     }
893 
894     return pAnchorFrm;
895 }
896 SwFrm* SwDrawContact::GetAnchorFrm( SdrObject* _pDrawObj )
897 {
898     SwFrm* pAnchorFrm = 0L;
899     if ( !_pDrawObj ||
900          _pDrawObj == GetMaster() ||
901          ( !_pDrawObj->GetUserCall() &&
902            GetUserCall( _pDrawObj ) == this ) )
903     {
904         pAnchorFrm = maAnchoredDrawObj.AnchorFrm();
905     }
906     else
907     {
908         ASSERT( _pDrawObj->ISA(SwDrawVirtObj),
909                 "<SwDrawContact::GetAnchorFrm(..)> - unknown drawing object." )
910         pAnchorFrm = static_cast<SwDrawVirtObj*>(_pDrawObj)->AnchorFrm();
911     }
912 
913     return pAnchorFrm;
914 }
915 
916 // OD 23.06.2003 #108784# - method to create a new 'virtual' drawing object.
917 SwDrawVirtObj* SwDrawContact::CreateVirtObj()
918 {
919     // determine 'master'
920     SdrObject* pOrgMasterSdrObj = GetMaster();
921 
922     // create 'virtual' drawing object
923     SwDrawVirtObj* pNewDrawVirtObj = new SwDrawVirtObj ( *(pOrgMasterSdrObj), *(this) );
924 
925     // add new 'virtual' drawing object managing data structure
926     maDrawVirtObjs.push_back( pNewDrawVirtObj );
927 
928     return pNewDrawVirtObj;
929 }
930 
931 // OD 23.06.2003 #108784# - destroys a given 'virtual' drawing object.
932 // side effect: 'virtual' drawing object is removed from data structure
933 //              <maDrawVirtObjs>.
934 void SwDrawContact::DestroyVirtObj( SwDrawVirtObj* _pVirtObj )
935 {
936     if ( _pVirtObj )
937     {
938         delete _pVirtObj;
939         _pVirtObj = 0;
940     }
941 }
942 
943 // OD 16.05.2003 #108784# - add a 'virtual' drawing object to drawing page.
944 // Use an already created one, which isn't used, or create a new one.
945 SwDrawVirtObj* SwDrawContact::AddVirtObj()
946 {
947     SwDrawVirtObj* pAddedDrawVirtObj = 0L;
948 
949     // check, if a disconnected 'virtual' drawing object exist and use it
950     std::list<SwDrawVirtObj*>::const_iterator aFoundVirtObjIter =
951             std::find_if( maDrawVirtObjs.begin(), maDrawVirtObjs.end(),
952                           UsedOrUnusedVirtObjPred( false ) );
953 
954     if ( aFoundVirtObjIter != maDrawVirtObjs.end() )
955     {
956         // use already created, disconnected 'virtual' drawing object
957         pAddedDrawVirtObj = (*aFoundVirtObjIter);
958     }
959     else
960     {
961         // create new 'virtual' drawing object.
962         pAddedDrawVirtObj = CreateVirtObj();
963     }
964     pAddedDrawVirtObj->AddToDrawingPage();
965 
966     return pAddedDrawVirtObj;
967 }
968 
969 // OD 16.05.2003 #108784# - remove 'virtual' drawing objects and destroy them.
970 void SwDrawContact::RemoveAllVirtObjs()
971 {
972     for ( std::list<SwDrawVirtObj*>::iterator aDrawVirtObjsIter = maDrawVirtObjs.begin();
973           aDrawVirtObjsIter != maDrawVirtObjs.end();
974           ++aDrawVirtObjsIter )
975     {
976         // remove and destroy 'virtual object'
977         SwDrawVirtObj* pDrawVirtObj = (*aDrawVirtObjsIter);
978         pDrawVirtObj->RemoveFromWriterLayout();
979         pDrawVirtObj->RemoveFromDrawingPage();
980         DestroyVirtObj( pDrawVirtObj );
981     }
982     maDrawVirtObjs.clear();
983 }
984 
985 SwDrawContact::VirtObjAnchoredAtFrmPred::VirtObjAnchoredAtFrmPred(
986                                                 const SwFrm& _rAnchorFrm )
987     : mpAnchorFrm( &_rAnchorFrm )
988 {
989     if ( mpAnchorFrm->IsCntntFrm() )
990     {
991         const SwCntntFrm* pTmpFrm =
992                             static_cast<const SwCntntFrm*>( mpAnchorFrm );
993         while ( pTmpFrm->IsFollow() )
994         {
995             pTmpFrm = pTmpFrm->FindMaster();
996         }
997         mpAnchorFrm = pTmpFrm;
998     }
999 }
1000 
1001 // OD 2004-04-14 #i26791# - compare with master frame
1002 bool SwDrawContact::VirtObjAnchoredAtFrmPred::operator() ( const SwDrawVirtObj* _pDrawVirtObj )
1003 {
1004     const SwFrm* pObjAnchorFrm = _pDrawVirtObj->GetAnchorFrm();
1005     if ( pObjAnchorFrm && pObjAnchorFrm->IsCntntFrm() )
1006     {
1007         const SwCntntFrm* pTmpFrm =
1008                             static_cast<const SwCntntFrm*>( pObjAnchorFrm );
1009         while ( pTmpFrm->IsFollow() )
1010         {
1011             pTmpFrm = pTmpFrm->FindMaster();
1012         }
1013         pObjAnchorFrm = pTmpFrm;
1014     }
1015 
1016     return ( pObjAnchorFrm == mpAnchorFrm );
1017 }
1018 
1019 // OD 19.06.2003 #108784# - get drawing object ('master' or 'virtual') by frame.
1020 SdrObject* SwDrawContact::GetDrawObjectByAnchorFrm( const SwFrm& _rAnchorFrm )
1021 {
1022     SdrObject* pRetDrawObj = 0L;
1023 
1024     // OD 2004-04-14 #i26791# - compare master frames instead of direct frames
1025     const SwFrm* pProposedAnchorFrm = &_rAnchorFrm;
1026     if ( pProposedAnchorFrm->IsCntntFrm() )
1027     {
1028         const SwCntntFrm* pTmpFrm =
1029                             static_cast<const SwCntntFrm*>( pProposedAnchorFrm );
1030         while ( pTmpFrm->IsFollow() )
1031         {
1032             pTmpFrm = pTmpFrm->FindMaster();
1033         }
1034         pProposedAnchorFrm = pTmpFrm;
1035     }
1036 
1037     const SwFrm* pMasterObjAnchorFrm = GetAnchorFrm();
1038     if ( pMasterObjAnchorFrm && pMasterObjAnchorFrm->IsCntntFrm() )
1039     {
1040         const SwCntntFrm* pTmpFrm =
1041                             static_cast<const SwCntntFrm*>( pMasterObjAnchorFrm );
1042         while ( pTmpFrm->IsFollow() )
1043         {
1044             pTmpFrm = pTmpFrm->FindMaster();
1045         }
1046         pMasterObjAnchorFrm = pTmpFrm;
1047     }
1048 
1049     if ( pMasterObjAnchorFrm && pMasterObjAnchorFrm == pProposedAnchorFrm )
1050     {
1051         pRetDrawObj = GetMaster();
1052     }
1053     else
1054     {
1055         std::list<SwDrawVirtObj*>::const_iterator aFoundVirtObjIter =
1056                 std::find_if( maDrawVirtObjs.begin(), maDrawVirtObjs.end(),
1057                               VirtObjAnchoredAtFrmPred( *pProposedAnchorFrm ) );
1058 
1059         if ( aFoundVirtObjIter != maDrawVirtObjs.end() )
1060         {
1061             pRetDrawObj = (*aFoundVirtObjIter);
1062         }
1063     }
1064 
1065     return pRetDrawObj;
1066 }
1067 
1068 /*************************************************************************
1069 |*
1070 |*	SwDrawContact::Changed
1071 |*
1072 |*	Ersterstellung		MA 09. Jan. 95
1073 |*	Letzte Aenderung	MA 29. May. 96
1074 |*
1075 |*************************************************************************/
1076 
1077 // OD 03.07.2003 #108784#
1078 void SwDrawContact::NotifyBackgrdOfAllVirtObjs( const Rectangle* pOldBoundRect )
1079 {
1080     for ( std::list<SwDrawVirtObj*>::iterator aDrawVirtObjIter = maDrawVirtObjs.begin();
1081           aDrawVirtObjIter != maDrawVirtObjs.end();
1082           ++aDrawVirtObjIter )
1083     {
1084         SwDrawVirtObj* pDrawVirtObj = (*aDrawVirtObjIter);
1085         if ( pDrawVirtObj->GetAnchorFrm() )
1086         {
1087             // --> OD 2004-10-21 #i34640# - determine correct page frame
1088             SwPageFrm* pPage = pDrawVirtObj->AnchoredObj()->FindPageFrmOfAnchor();
1089             // <--
1090             if( pOldBoundRect && pPage )
1091             {
1092                 SwRect aOldRect( *pOldBoundRect );
1093                 aOldRect.Pos() += pDrawVirtObj->GetOffset();
1094                 if( aOldRect.HasArea() )
1095                     ::Notify_Background( pDrawVirtObj, pPage,
1096                                          aOldRect, PREP_FLY_LEAVE,sal_True);
1097             }
1098             // --> OD 2004-10-21 #i34640# - include spacing for wrapping
1099             SwRect aRect( pDrawVirtObj->GetAnchoredObj()->GetObjRectWithSpaces() );
1100             // <--
1101             if( aRect.HasArea() )
1102             {
1103                 // --> OD 2004-10-21 #i34640# - simplify
1104                 SwPageFrm* pPg = (SwPageFrm*)::FindPage( aRect, pPage );
1105                 // <--
1106                 if ( pPg )
1107                     ::Notify_Background( pDrawVirtObj, pPg, aRect,
1108                                          PREP_FLY_ARRIVE, sal_True );
1109             }
1110             ::ClrContourCache( pDrawVirtObj );
1111         }
1112     }
1113 }
1114 
1115 // OD 2004-04-08 #i26791# - local method to notify the background for a drawing object
1116 void lcl_NotifyBackgroundOfObj( SwDrawContact& _rDrawContact,
1117                                 const SdrObject& _rObj,
1118                                 const Rectangle* _pOldObjRect )
1119 {
1120     // --> OD 2004-10-21 #i34640#
1121     SwAnchoredObject* pAnchoredObj =
1122         const_cast<SwAnchoredObject*>(_rDrawContact.GetAnchoredObj( &_rObj ));
1123     if ( pAnchoredObj && pAnchoredObj->GetAnchorFrm() )
1124     // <--
1125     {
1126         // --> OD 2004-10-21 #i34640# - determine correct page frame
1127         SwPageFrm* pPageFrm = pAnchoredObj->FindPageFrmOfAnchor();
1128         // <--
1129         if( _pOldObjRect && pPageFrm )
1130         {
1131             SwRect aOldRect( *_pOldObjRect );
1132             if( aOldRect.HasArea() )
1133             {
1134                 // --> OD 2004-10-21 #i34640# - determine correct page frame
1135                 SwPageFrm* pOldPageFrm = (SwPageFrm*)::FindPage( aOldRect, pPageFrm );
1136                 // <--
1137                 ::Notify_Background( &_rObj, pOldPageFrm, aOldRect,
1138                                      PREP_FLY_LEAVE, sal_True);
1139             }
1140         }
1141         // --> OD 2004-10-21 #i34640# - include spacing for wrapping
1142         SwRect aNewRect( pAnchoredObj->GetObjRectWithSpaces() );
1143         // <--
1144         if( aNewRect.HasArea() && pPageFrm )
1145         {
1146             pPageFrm = (SwPageFrm*)::FindPage( aNewRect, pPageFrm );
1147             ::Notify_Background( &_rObj, pPageFrm, aNewRect,
1148                                  PREP_FLY_ARRIVE, sal_True );
1149         }
1150         ClrContourCache( &_rObj );
1151     }
1152 }
1153 
1154 void SwDrawContact::Changed( const SdrObject& rObj,
1155                              SdrUserCallType eType,
1156                              const Rectangle& rOldBoundRect )
1157 {
1158     // OD 2004-06-01 #i26791# - no event handling, if existing <ViewShell>
1159     // is in contruction
1160     SwDoc* pDoc = GetFmt()->GetDoc();
1161     if ( pDoc->GetCurrentViewShell() &&
1162          pDoc->GetCurrentViewShell()->IsInConstructor() )
1163     {
1164         return;
1165     }
1166 
1167     // --> OD 2005-03-08 #i44339#
1168     // no event handling, if document is in destruction.
1169     // Exception: It's the SDRUSERCALL_DELETE event
1170     if ( pDoc->IsInDtor() && eType != SDRUSERCALL_DELETE )
1171     {
1172         return;
1173     }
1174     // <--
1175 
1176     //Action aufsetzen, aber nicht wenn gerade irgendwo eine Action laeuft.
1177 	ViewShell *pSh = 0, *pOrg;
1178 	SwRootFrm *pTmpRoot = pDoc->GetCurrentLayout();//swmod 080317
1179 	if ( pTmpRoot && pTmpRoot->IsCallbackActionEnabled() )
1180 	{
1181 		pDoc->GetEditShell( &pOrg );
1182 		pSh = pOrg;
1183 		if ( pSh )
1184 			do
1185 			{   if ( pSh->Imp()->IsAction() || pSh->Imp()->IsIdleAction() )
1186 					pSh = 0;
1187 				else
1188 					pSh = (ViewShell*)pSh->GetNext();
1189 
1190 			} while ( pSh && pSh != pOrg );
1191 
1192 		if ( pSh )
1193 			pTmpRoot->StartAllAction();
1194 	}
1195 	SdrObjUserCall::Changed( rObj, eType, rOldBoundRect );
1196     _Changed( rObj, eType, &rOldBoundRect );    //Achtung, ggf. Suizid!
1197 
1198 	if ( pSh )
1199 		pTmpRoot->EndAllAction();
1200 }
1201 
1202 // --> OD 2006-01-18 #129959#
1203 // helper class for method <SwDrawContact::_Changed(..)> for handling nested
1204 // <SdrObjUserCall> events
1205 class NestedUserCallHdl
1206 {
1207     private:
1208         SwDrawContact* mpDrawContact;
1209         bool mbParentUserCallActive;
1210         SdrUserCallType meParentUserCallEventType;
1211 
1212     public:
1213         NestedUserCallHdl( SwDrawContact* _pDrawContact,
1214                            SdrUserCallType _eEventType )
1215             : mpDrawContact( _pDrawContact ),
1216               mbParentUserCallActive( _pDrawContact->mbUserCallActive ),
1217               meParentUserCallEventType( _pDrawContact->meEventTypeOfCurrentUserCall )
1218         {
1219             mpDrawContact->mbUserCallActive = true;
1220             mpDrawContact->meEventTypeOfCurrentUserCall = _eEventType;
1221         }
1222 
1223         ~NestedUserCallHdl()
1224         {
1225             if ( mpDrawContact )
1226             {
1227                 mpDrawContact->mbUserCallActive = mbParentUserCallActive;
1228                 mpDrawContact->meEventTypeOfCurrentUserCall = meParentUserCallEventType;
1229             }
1230         }
1231 
1232         void DrawContactDeleted()
1233         {
1234             mpDrawContact = 0;
1235         }
1236 
1237         bool IsNestedUserCall()
1238         {
1239             return mbParentUserCallActive;
1240         }
1241 
1242         void AssertNestedUserCall()
1243         {
1244             if ( IsNestedUserCall() )
1245             {
1246                 bool bTmpAssert( true );
1247                 // Currently its known, that a nested event SDRUSERCALL_RESIZE
1248                 // could occur during parent user call SDRUSERCALL_INSERTED,
1249                 // SDRUSERCALL_DELETE and SDRUSERCALL_RESIZE for edge objects.
1250                 // Also possible are nested SDRUSERCALL_CHILD_RESIZE events for
1251                 // edge objects
1252                 // Thus, assert all other combinations
1253                 if ( ( meParentUserCallEventType == SDRUSERCALL_INSERTED ||
1254                        meParentUserCallEventType == SDRUSERCALL_DELETE ||
1255                        meParentUserCallEventType == SDRUSERCALL_RESIZE ) &&
1256                      mpDrawContact->meEventTypeOfCurrentUserCall == SDRUSERCALL_RESIZE )
1257                 {
1258                     bTmpAssert = false;
1259                 }
1260                 else if ( meParentUserCallEventType == SDRUSERCALL_CHILD_RESIZE &&
1261                           mpDrawContact->meEventTypeOfCurrentUserCall == SDRUSERCALL_CHILD_RESIZE )
1262                 {
1263                     bTmpAssert = false;
1264                 }
1265 
1266                 if ( bTmpAssert )
1267                 {
1268                     ASSERT( false,
1269                             "<SwDrawContact::_Changed(..)> - unknown nested <UserCall> event. This is serious, please inform OD." );
1270                 }
1271             }
1272         }
1273 };
1274 
1275 // <--
1276 //
1277 // !!!ACHTUNG!!! The object may commit suicide!!!
1278 //
1279 void SwDrawContact::_Changed( const SdrObject& rObj,
1280                               SdrUserCallType eType,
1281                               const Rectangle* pOldBoundRect )
1282 {
1283     // --> OD 2006-01-18 #129959#
1284     // suppress handling of nested <SdrObjUserCall> events
1285     NestedUserCallHdl aNestedUserCallHdl( this, eType );
1286     if ( aNestedUserCallHdl.IsNestedUserCall() )
1287     {
1288         aNestedUserCallHdl.AssertNestedUserCall();
1289         return;
1290     }
1291     // <--
1292     // OD 05.08.2002 #100843# - do *not* notify, if document is destructing
1293     // --> OD 2004-10-21 #i35912# - do *not* notify for as-character anchored
1294     // drawing objects.
1295     // --> OD 2004-11-11 #i35007#
1296     // improvement: determine as-character anchored object flag only once.
1297     const bool bAnchoredAsChar = ObjAnchoredAsChar();
1298     // <--
1299     const bool bNotify = !(GetFmt()->GetDoc()->IsInDtor()) &&
1300                          ( SURROUND_THROUGHT != GetFmt()->GetSurround().GetSurround() ) &&
1301                          !bAnchoredAsChar;
1302     // <--
1303 	switch( eType )
1304 	{
1305 		case SDRUSERCALL_DELETE:
1306 			{
1307                 if ( bNotify )
1308                 {
1309                     lcl_NotifyBackgroundOfObj( *this, rObj, pOldBoundRect );
1310                     // --> OD 2004-10-27 #i36181# - background of 'virtual'
1311                     // drawing objects have also been notified.
1312                     NotifyBackgrdOfAllVirtObjs( pOldBoundRect );
1313                     // <--
1314                 }
1315                 DisconnectFromLayout( false );
1316 				SetMaster( NULL );
1317 				delete this;
1318                 // --> FME 2006-07-12 #i65784# Prevent memory corruption
1319                 aNestedUserCallHdl.DrawContactDeleted();
1320                 // <--
1321 				break;
1322 			}
1323 		case SDRUSERCALL_INSERTED:
1324 			{
1325                 // OD 10.10.2003 #112299#
1326                 if ( mbDisconnectInProgress )
1327                 {
1328                     ASSERT( false,
1329                             "<SwDrawContact::_Changed(..)> - Insert event during disconnection from layout is invalid." );
1330                 }
1331                 else
1332                 {
1333                     ConnectToLayout();
1334                     if ( bNotify )
1335                     {
1336                         lcl_NotifyBackgroundOfObj( *this, rObj, pOldBoundRect );
1337                     }
1338                 }
1339 				break;
1340 			}
1341 		case SDRUSERCALL_REMOVED:
1342 			{
1343                 if ( bNotify )
1344                 {
1345                     lcl_NotifyBackgroundOfObj( *this, rObj, pOldBoundRect );
1346                 }
1347                 DisconnectFromLayout( false );
1348 				break;
1349 			}
1350         case SDRUSERCALL_CHILD_INSERTED :
1351         case SDRUSERCALL_CHILD_REMOVED :
1352         {
1353             // --> AW, OD 2010-09-13 #i113730#
1354             // force layer of controls for group objects containing control objects
1355             if(dynamic_cast< SdrObjGroup* >(maAnchoredDrawObj.DrawObj()))
1356             {
1357                 if(::CheckControlLayer(maAnchoredDrawObj.DrawObj()))
1358                 {
1359                     const IDocumentDrawModelAccess* pIDDMA = static_cast<SwFrmFmt*>(GetRegisteredInNonConst())->getIDocumentDrawModelAccess();
1360                     const SdrLayerID aCurrentLayer(maAnchoredDrawObj.DrawObj()->GetLayer());
1361                     const SdrLayerID aControlLayerID(pIDDMA->GetControlsId());
1362                     const SdrLayerID aInvisibleControlLayerID(pIDDMA->GetInvisibleControlsId());
1363 
1364                     if(aCurrentLayer != aControlLayerID && aCurrentLayer != aInvisibleControlLayerID)
1365                     {
1366                         if ( aCurrentLayer == pIDDMA->GetInvisibleHellId() ||
1367                              aCurrentLayer == pIDDMA->GetInvisibleHeavenId() )
1368                         {
1369                             maAnchoredDrawObj.DrawObj()->SetLayer(aInvisibleControlLayerID);
1370                         }
1371                         else
1372                         {
1373                             maAnchoredDrawObj.DrawObj()->SetLayer(aControlLayerID);
1374                         }
1375                     }
1376                 }
1377             }
1378             // fallthrough intended here
1379             // <--
1380         }
1381         case SDRUSERCALL_MOVEONLY:
1382 		case SDRUSERCALL_RESIZE:
1383 		case SDRUSERCALL_CHILD_MOVEONLY :
1384 		case SDRUSERCALL_CHILD_RESIZE :
1385 		case SDRUSERCALL_CHILD_CHGATTR :
1386 		case SDRUSERCALL_CHILD_DELETE :
1387 		case SDRUSERCALL_CHILD_COPY :
1388         {
1389             // --> OD 2004-08-04 #i31698# - improvement:
1390             // get instance <SwAnchoredDrawObject> only once
1391             const SwAnchoredDrawObject* pAnchoredDrawObj =
1392                 static_cast<const SwAnchoredDrawObject*>( GetAnchoredObj( &rObj ) );
1393             // <--
1394             // OD 2004-04-06 #i26791# - adjust positioning and alignment attributes,
1395             // if positioning of drawing object isn't in progress.
1396             // --> OD 2005-08-15 #i53320# - no adjust of positioning attributes,
1397             // if drawing object isn't positioned.
1398             if ( !pAnchoredDrawObj->IsPositioningInProgress() &&
1399                  !pAnchoredDrawObj->NotYetPositioned() )
1400             // <--
1401             {
1402                 // --> OD 2004-09-29 #i34748# - If no last object rectangle is
1403                 // provided by the anchored object, use parameter <pOldBoundRect>.
1404                 const Rectangle& aOldObjRect = pAnchoredDrawObj->GetLastObjRect()
1405                                                ? *(pAnchoredDrawObj->GetLastObjRect())
1406                                                : *(pOldBoundRect);
1407                 // <--
1408                 // --> OD 2008-02-18 #i79400#
1409                 // always invalidate object rectangle inclusive spaces
1410                 pAnchoredDrawObj->InvalidateObjRectWithSpaces();
1411                 // <--
1412                 // --> OD 2005-01-28 #i41324# - notify background before
1413                 // adjusting position
1414                 if ( bNotify )
1415                 {
1416                     // --> OD 2004-07-20 #i31573# - correction: Only invalidate
1417                     // background of given drawing object.
1418                     lcl_NotifyBackgroundOfObj( *this, rObj, &aOldObjRect );
1419                 }
1420                 // <--
1421                 // --> OD 2004-08-04 #i31698# - determine layout direction
1422                 // via draw frame format.
1423                 SwFrmFmt::tLayoutDir eLayoutDir =
1424                                 pAnchoredDrawObj->GetFrmFmt().GetLayoutDir();
1425                 // <--
1426                 // use geometry of drawing object
1427                 SwRect aObjRect( rObj.GetSnapRect() );
1428                 // If drawing object is a member of a group, the adjustment
1429                 // of the positioning and the alignment attributes has to
1430                 // be done for the top group object.
1431                 if ( rObj.GetUpGroup() )
1432                 {
1433                     const SdrObject* pGroupObj = rObj.GetUpGroup();
1434                     while ( pGroupObj->GetUpGroup() )
1435                     {
1436                         pGroupObj = pGroupObj->GetUpGroup();
1437                     }
1438                     // use geometry of drawing object
1439                     aObjRect = pGroupObj->GetSnapRect();
1440                 }
1441                 SwTwips nXPosDiff(0L);
1442                 SwTwips nYPosDiff(0L);
1443                 switch ( eLayoutDir )
1444                 {
1445                     case SwFrmFmt::HORI_L2R:
1446                     {
1447                         nXPosDiff = aObjRect.Left() - aOldObjRect.Left();
1448                         nYPosDiff = aObjRect.Top() - aOldObjRect.Top();
1449                     }
1450                     break;
1451                     case SwFrmFmt::HORI_R2L:
1452                     {
1453                         nXPosDiff = aOldObjRect.Right() - aObjRect.Right();
1454                         nYPosDiff = aObjRect.Top() - aOldObjRect.Top();
1455                     }
1456                     break;
1457                     case SwFrmFmt::VERT_R2L:
1458                     {
1459                         nXPosDiff = aObjRect.Top() - aOldObjRect.Top();
1460                         nYPosDiff = aOldObjRect.Right() - aObjRect.Right();
1461                     }
1462                     break;
1463                     default:
1464                     {
1465                         ASSERT( false,
1466                                 "<SwDrawContact::_Changed(..)> - unsupported layout direction" );
1467                     }
1468                 }
1469                 SfxItemSet aSet( GetFmt()->GetDoc()->GetAttrPool(),
1470                                  RES_VERT_ORIENT, RES_HORI_ORIENT, 0 );
1471                 const SwFmtVertOrient& rVert = GetFmt()->GetVertOrient();
1472                 if ( nYPosDiff != 0 )
1473                 {
1474 
1475                     if ( rVert.GetRelationOrient() == text::RelOrientation::CHAR ||
1476                          rVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE )
1477                     {
1478                         nYPosDiff = -nYPosDiff;
1479                     }
1480                     aSet.Put( SwFmtVertOrient( rVert.GetPos()+nYPosDiff,
1481                                                text::VertOrientation::NONE,
1482                                                rVert.GetRelationOrient() ) );
1483                 }
1484 
1485                 const SwFmtHoriOrient& rHori = GetFmt()->GetHoriOrient();
1486                 if ( !bAnchoredAsChar && nXPosDiff != 0 )
1487                 {
1488                     aSet.Put( SwFmtHoriOrient( rHori.GetPos()+nXPosDiff,
1489                                                text::HoriOrientation::NONE,
1490                                                rHori.GetRelationOrient() ) );
1491                 }
1492 
1493                 if ( nYPosDiff ||
1494                      ( !bAnchoredAsChar && nXPosDiff != 0 ) )
1495                 {
1496                     GetFmt()->GetDoc()->SetFlyFrmAttr( *(GetFmt()), aSet );
1497                     // keep new object rectangle, to avoid multiple
1498                     // changes of the attributes by multiple event from
1499                     // the drawing layer - e.g. group objects and its members
1500                     // --> OD 2004-09-29 #i34748# - use new method
1501                     // <SwAnchoredDrawObject::SetLastObjRect(..)>.
1502                     const_cast<SwAnchoredDrawObject*>(pAnchoredDrawObj)
1503                                     ->SetLastObjRect( aObjRect.SVRect() );
1504                 }
1505                 else if ( aObjRect.SSize() != aOldObjRect.GetSize() )
1506                 {
1507                     _InvalidateObjs();
1508                     // --> OD 2004-11-11 #i35007# - notify anchor frame
1509                     // of as-character anchored object
1510                     if ( bAnchoredAsChar )
1511                     {
1512                         const_cast<SwAnchoredDrawObject*>(pAnchoredDrawObj)
1513                             ->AnchorFrm()->Prepare( PREP_FLY_ATTR_CHG, GetFmt() );
1514                     }
1515                     // <--
1516                 }
1517             }
1518             // --> OD 2006-01-18 #129959#
1519             // It reveals that the following code causes several defects -
1520             // on copying or on ungrouping a group shape containing edge objects.
1521             // Testing fix for #i53320# also reveal that the following code
1522             // isn't necessary.
1523 //            // --> OD 2005-08-15 #i53320# - reset positioning attributes,
1524 //            // if anchored drawing object isn't yet positioned.
1525 //            else if ( pAnchoredDrawObj->NotYetPositioned() &&
1526 //                      static_cast<const SwDrawFrmFmt&>(pAnchoredDrawObj->GetFrmFmt()).IsPosAttrSet() )
1527 //            {
1528 //                const_cast<SwDrawFrmFmt&>(
1529 //                    static_cast<const SwDrawFrmFmt&>(pAnchoredDrawObj->GetFrmFmt()))
1530 //                        .ResetPosAttr();
1531 //            }
1532 //            // <--
1533             // <--
1534         }
1535         break;
1536 		case SDRUSERCALL_CHGATTR:
1537             if ( bNotify )
1538             {
1539                 lcl_NotifyBackgroundOfObj( *this, rObj, pOldBoundRect );
1540             }
1541 			break;
1542         default:
1543             break;
1544 	}
1545 }
1546 
1547 namespace
1548 {
1549     static const SwFmtAnchor* lcl_getAnchorFmt( const SfxPoolItem& _rItem )
1550     {
1551 	    sal_uInt16 nWhich = _rItem.Which();
1552         const SwFmtAnchor* pAnchorFmt = NULL;
1553         if ( RES_ATTRSET_CHG == nWhich )
1554 	    {
1555             static_cast<const SwAttrSetChg&>(_rItem).GetChgSet()->
1556                 GetItemState( RES_ANCHOR, sal_False, (const SfxPoolItem**)&pAnchorFmt );
1557 	    }
1558         else if ( RES_ANCHOR == nWhich )
1559         {
1560             pAnchorFmt = &static_cast<const SwFmtAnchor&>(_rItem);
1561         }
1562         return pAnchorFmt;
1563     }
1564 }
1565 
1566 /*************************************************************************
1567 |*
1568 |*	SwDrawContact::Modify()
1569 |*
1570 |*	Ersterstellung		MA 09. Jan. 95
1571 |*	Letzte Aenderung	MA 03. Dec. 95
1572 |*
1573 |*************************************************************************/
1574 
1575 void SwDrawContact::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
1576 {
1577     // OD 10.10.2003 #112299#
1578     ASSERT( !mbDisconnectInProgress,
1579             "<SwDrawContact::Modify(..)> called during disconnection.");
1580 
1581 	sal_uInt16 nWhich = pNew ? pNew->Which() : 0;
1582     const SwFmtAnchor* pNewAnchorFmt = pNew ? lcl_getAnchorFmt( *pNew ) : NULL;
1583 
1584     if ( pNewAnchorFmt )
1585 	{
1586 		// JP 10.04.95: nicht auf ein Reset Anchor reagieren !!!!!
1587         if ( SFX_ITEM_SET ==
1588                 GetFmt()->GetAttrSet().GetItemState( RES_ANCHOR, sal_False ) )
1589 		{
1590             // OD 10.10.2003 #112299# - no connect to layout during disconnection
1591             if ( !mbDisconnectInProgress )
1592             {
1593                 // determine old object retangle of 'master' drawing object
1594                 // for notification
1595                 const Rectangle* pOldRect = 0L;
1596                 Rectangle aOldRect;
1597                 if ( GetAnchorFrm() )
1598                 {
1599                     // --> OD 2004-10-27 #i36181# - include spacing in object
1600                     // rectangle for notification.
1601                     aOldRect = maAnchoredDrawObj.GetObjRectWithSpaces().SVRect();
1602                     pOldRect = &aOldRect;
1603                     // <--
1604                 }
1605                 // re-connect to layout due to anchor format change
1606                 ConnectToLayout( pNewAnchorFmt );
1607                 // notify background of drawing objects
1608                 lcl_NotifyBackgroundOfObj( *this, *GetMaster(), pOldRect );
1609                 NotifyBackgrdOfAllVirtObjs( pOldRect );
1610 
1611                 const SwFmtAnchor* pOldAnchorFmt = pOld ? lcl_getAnchorFmt( *pOld ) : NULL;
1612                 if ( !pOldAnchorFmt || ( pOldAnchorFmt->GetAnchorId() != pNewAnchorFmt->GetAnchorId() ) )
1613                 {
1614                     ASSERT( maAnchoredDrawObj.DrawObj(), "SwDrawContact::Modify: no draw object here?" );
1615                     if ( maAnchoredDrawObj.DrawObj() )
1616                     {
1617                         // --> OD 2009-07-10 #i102752#
1618                         // assure that a ShapePropertyChangeNotifier exists
1619                         maAnchoredDrawObj.DrawObj()->notifyShapePropertyChange( ::svx::eTextShapeAnchorType );
1620                         // <--
1621                     }
1622                 }
1623             }
1624 		}
1625 		else
1626 			DisconnectFromLayout();
1627 	}
1628     // --> OD 2006-03-17 #i62875# - revised fix for issue #124157#
1629     // no further notification, if not connected to Writer layout
1630     else if ( maAnchoredDrawObj.GetAnchorFrm() &&
1631               maAnchoredDrawObj.GetDrawObj()->GetUserCall() )
1632     {
1633         // --> OD 2004-07-01 #i28701# - on change of wrapping style, hell|heaven layer,
1634         // or wrapping style influence an update of the <SwSortedObjs> list,
1635         // the drawing object is registered in, has to be performed. This is triggered
1636         // by the 1st parameter of method call <_InvalidateObjs(..)>.
1637         if ( RES_SURROUND == nWhich ||
1638              RES_OPAQUE == nWhich ||
1639              RES_WRAP_INFLUENCE_ON_OBJPOS == nWhich ||
1640              ( RES_ATTRSET_CHG == nWhich &&
1641                ( SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
1642                            RES_SURROUND, sal_False ) ||
1643                  SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
1644                            RES_OPAQUE, sal_False ) ||
1645                  SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
1646                            RES_WRAP_INFLUENCE_ON_OBJPOS, sal_False ) ) ) )
1647         {
1648             lcl_NotifyBackgroundOfObj( *this, *GetMaster(), 0L );
1649             NotifyBackgrdOfAllVirtObjs( 0L );
1650             _InvalidateObjs( true );
1651         }
1652         else if ( RES_UL_SPACE == nWhich || RES_LR_SPACE == nWhich ||
1653                   RES_HORI_ORIENT == nWhich || RES_VERT_ORIENT == nWhich ||
1654                   // --> OD 2004-07-01 #i28701# - add attribute 'Follow text flow'
1655                   RES_FOLLOW_TEXT_FLOW == nWhich ||
1656                   ( RES_ATTRSET_CHG == nWhich &&
1657                     ( SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
1658                                 RES_LR_SPACE, sal_False ) ||
1659                       SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
1660                                 RES_UL_SPACE, sal_False ) ||
1661                       SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
1662                                 RES_HORI_ORIENT, sal_False ) ||
1663                       SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
1664                                 RES_VERT_ORIENT, sal_False ) ||
1665                       SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
1666                                 RES_FOLLOW_TEXT_FLOW, sal_False ) ) ) )
1667         {
1668             lcl_NotifyBackgroundOfObj( *this, *GetMaster(), 0L );
1669             NotifyBackgrdOfAllVirtObjs( 0L );
1670             _InvalidateObjs();
1671         }
1672         // --> OD 2004-10-26 #i35443#
1673         else if ( RES_ATTRSET_CHG == nWhich )
1674         {
1675             lcl_NotifyBackgroundOfObj( *this, *GetMaster(), 0L );
1676             NotifyBackgrdOfAllVirtObjs( 0L );
1677             _InvalidateObjs();
1678         }
1679         // <--
1680         else if ( RES_REMOVE_UNO_OBJECT == nWhich )
1681         {
1682             // nothing to do
1683         }
1684 #if OSL_DEBUG_LEVEL > 1
1685         else
1686         {
1687             ASSERT( false,
1688                     "<SwDrawContact::Modify(..)> - unhandled attribute? - please inform od@openoffice.org" );
1689         }
1690 #endif
1691     }
1692 
1693     // --> OD 2005-07-18 #i51474#
1694     GetAnchoredObj( 0L )->ResetLayoutProcessBools();
1695     // <--
1696 }
1697 
1698 // OD 2004-03-31 #i26791#
1699 // --> OD 2004-07-01 #i28701# - added parameter <_bUpdateSortedObjsList>
1700 void SwDrawContact::_InvalidateObjs( const bool _bUpdateSortedObjsList )
1701 {
1702     // invalidate position of existing 'virtual' drawing objects
1703     for ( std::list<SwDrawVirtObj*>::iterator aDisconnectIter = maDrawVirtObjs.begin();
1704           aDisconnectIter != maDrawVirtObjs.end();
1705           ++aDisconnectIter )
1706     {
1707         SwDrawVirtObj* pDrawVirtObj = (*aDisconnectIter);
1708         // --> OD 2004-08-23 #i33313# - invalidation only for connected
1709         // 'virtual' drawing objects
1710         if ( pDrawVirtObj->IsConnected() )
1711         {
1712             pDrawVirtObj->AnchoredObj()->InvalidateObjPos();
1713             // --> OD 2004-07-01 #i28701#
1714             if ( _bUpdateSortedObjsList )
1715             {
1716                 pDrawVirtObj->AnchoredObj()->UpdateObjInSortedList();
1717             }
1718             // <--
1719         }
1720         // <--
1721     }
1722 
1723     // invalidate position of 'master' drawing object
1724     SwAnchoredObject* pAnchoredObj = GetAnchoredObj( 0L );
1725     pAnchoredObj->InvalidateObjPos();
1726     // --> OD 2004-07-01 #i28701#
1727     if ( _bUpdateSortedObjsList )
1728     {
1729         pAnchoredObj->UpdateObjInSortedList();
1730     }
1731     // <--
1732 }
1733 
1734 /*************************************************************************
1735 |*
1736 |*	SwDrawContact::DisconnectFromLayout()
1737 |*
1738 |*	Ersterstellung		MA 09. Jan. 95
1739 |*	Letzte Aenderung	MA 25. Mar. 99
1740 |*
1741 |*************************************************************************/
1742 
1743 void SwDrawContact::DisconnectFromLayout( bool _bMoveMasterToInvisibleLayer )
1744 {
1745     // OD 10.10.2003 #112299#
1746     mbDisconnectInProgress = true;
1747 
1748     // --> OD 2004-10-27 #i36181# - notify background of drawing object
1749     if ( _bMoveMasterToInvisibleLayer &&
1750          !(GetFmt()->GetDoc()->IsInDtor()) &&
1751          GetAnchorFrm() )
1752     {
1753         const Rectangle aOldRect( maAnchoredDrawObj.GetObjRectWithSpaces().SVRect() );
1754         lcl_NotifyBackgroundOfObj( *this, *GetMaster(), &aOldRect );
1755         NotifyBackgrdOfAllVirtObjs( &aOldRect );
1756     }
1757     // <--
1758 
1759     // OD 16.05.2003 #108784# - remove 'virtual' drawing objects from writer
1760     // layout and from drawing page
1761     for ( std::list<SwDrawVirtObj*>::iterator aDisconnectIter = maDrawVirtObjs.begin();
1762           aDisconnectIter != maDrawVirtObjs.end();
1763           ++aDisconnectIter )
1764     {
1765         SwDrawVirtObj* pDrawVirtObj = (*aDisconnectIter);
1766         pDrawVirtObj->RemoveFromWriterLayout();
1767         pDrawVirtObj->RemoveFromDrawingPage();
1768     }
1769 
1770     if ( maAnchoredDrawObj.GetAnchorFrm() )
1771     {
1772         maAnchoredDrawObj.AnchorFrm()->RemoveDrawObj( maAnchoredDrawObj );
1773     }
1774 
1775     if ( _bMoveMasterToInvisibleLayer && GetMaster() && GetMaster()->IsInserted() )
1776 	{
1777 		SdrViewIter aIter( GetMaster() );
1778 		for( SdrView* pView = aIter.FirstView(); pView;
1779 					pView = aIter.NextView() )
1780         {
1781 			pView->MarkObj( GetMaster(), pView->GetSdrPageView(), sal_True );
1782         }
1783 
1784         // OD 25.06.2003 #108784# - Instead of removing 'master' object from
1785         // drawing page, move the 'master' drawing object into the corresponding
1786         // invisible layer.
1787         {
1788             //((SwFrmFmt*)GetRegisteredIn())->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage(0)->
1789             //                            RemoveObject( GetMaster()->GetOrdNum() );
1790             // OD 21.08.2003 #i18447# - in order to consider group object correct
1791             // use new method <SwDrawContact::MoveObjToInvisibleLayer(..)>
1792             MoveObjToInvisibleLayer( GetMaster() );
1793         }
1794 	}
1795 
1796     // OD 10.10.2003 #112299#
1797     mbDisconnectInProgress = false;
1798 }
1799 
1800 // OD 26.06.2003 #108784# - method to remove 'master' drawing object
1801 // from drawing page.
1802 void SwDrawContact::RemoveMasterFromDrawPage()
1803 {
1804     if ( GetMaster() )
1805     {
1806         GetMaster()->SetUserCall( 0 );
1807         if ( GetMaster()->IsInserted() )
1808         {
1809             ((SwFrmFmt*)GetRegisteredIn())->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage(0)->
1810                                         RemoveObject( GetMaster()->GetOrdNum() );
1811         }
1812     }
1813 }
1814 
1815 // OD 19.06.2003 #108784# - disconnect for a dedicated drawing object -
1816 // could be 'master' or 'virtual'.
1817 // a 'master' drawing object will disconnect a 'virtual' drawing object
1818 // in order to take its place.
1819 // OD 13.10.2003 #i19919# - no special case, if drawing object isn't in
1820 // page header/footer, in order to get drawing objects in repeating table headers
1821 // also working.
1822 void SwDrawContact::DisconnectObjFromLayout( SdrObject* _pDrawObj )
1823 {
1824     if ( _pDrawObj->ISA(SwDrawVirtObj) )
1825     {
1826         SwDrawVirtObj* pDrawVirtObj = static_cast<SwDrawVirtObj*>(_pDrawObj);
1827         pDrawVirtObj->RemoveFromWriterLayout();
1828         pDrawVirtObj->RemoveFromDrawingPage();
1829     }
1830     else
1831     {
1832         std::list<SwDrawVirtObj*>::const_iterator aFoundVirtObjIter =
1833                 std::find_if( maDrawVirtObjs.begin(), maDrawVirtObjs.end(),
1834                               UsedOrUnusedVirtObjPred( true ) );
1835         if ( aFoundVirtObjIter != maDrawVirtObjs.end() )
1836         {
1837             // replace found 'virtual' drawing object by 'master' drawing
1838             // object and disconnect the 'virtual' one
1839             SwDrawVirtObj* pDrawVirtObj = (*aFoundVirtObjIter);
1840             SwFrm* pNewAnchorFrmOfMaster = pDrawVirtObj->AnchorFrm();
1841             // disconnect 'virtual' drawing object
1842             pDrawVirtObj->RemoveFromWriterLayout();
1843             pDrawVirtObj->RemoveFromDrawingPage();
1844             // disconnect 'master' drawing object from current frame
1845             GetAnchorFrm()->RemoveDrawObj( maAnchoredDrawObj );
1846             // re-connect 'master' drawing object to frame of found 'virtual'
1847             // drawing object.
1848             pNewAnchorFrmOfMaster->AppendDrawObj( maAnchoredDrawObj );
1849         }
1850         else
1851         {
1852             // no connected 'virtual' drawing object found. Thus, disconnect
1853             // completely from layout.
1854             DisconnectFromLayout();
1855         }
1856     }
1857 }
1858 
1859 /*************************************************************************
1860 |*
1861 |*	SwDrawContact::ConnectToLayout()
1862 |*
1863 |*	Ersterstellung		MA 09. Jan. 95
1864 |*	Letzte Aenderung	MA 25. Mar. 99
1865 |*
1866 |*************************************************************************/
1867 SwTxtFrm* lcl_GetFlyInCntntAnchor( SwTxtFrm* _pProposedAnchorFrm,
1868                                    const xub_StrLen _nTxtOfs )
1869 {
1870     SwTxtFrm* pAct = _pProposedAnchorFrm;
1871     SwTxtFrm* pTmp;
1872     do
1873     {
1874         pTmp = pAct;
1875         pAct = pTmp->GetFollow();
1876     }
1877     while( pAct && _nTxtOfs >= pAct->GetOfst() );
1878     return pTmp;
1879 }
1880 
1881 void SwDrawContact::ConnectToLayout( const SwFmtAnchor* pAnch )
1882 {
1883     // OD 10.10.2003 #112299# - *no* connect to layout during disconnection from
1884     // layout.
1885     if ( mbDisconnectInProgress )
1886     {
1887         ASSERT( false,
1888                 "<SwDrawContact::ConnectToLayout(..)> called during disconnection.");
1889         return;
1890     }
1891 
1892     // --> OD 2004-09-22 #i33909# - *no* connect to layout, if 'master' drawing
1893     // object isn't inserted in the drawing page
1894     if ( !GetMaster()->IsInserted() )
1895     {
1896         ASSERT( false, "<SwDrawContact::ConnectToLayout(..)> - master drawing object not inserted -> no connect to layout. Please inform od@openoffice.org" );
1897         return;
1898     }
1899     // <--
1900 
1901     SwFrmFmt* pDrawFrmFmt = (SwFrmFmt*)GetRegisteredIn();
1902 
1903     if( !pDrawFrmFmt->getIDocumentLayoutAccess()->GetCurrentViewShell() )
1904 		return;
1905 
1906     // OD 16.05.2003 #108784# - remove 'virtual' drawing objects from writer
1907     // layout and from drawing page, and remove 'master' drawing object from
1908     // writer layout - 'master' object will remain in drawing page.
1909     DisconnectFromLayout( false );
1910 
1911 	if ( !pAnch )
1912     {
1913         pAnch = &(pDrawFrmFmt->GetAnchor());
1914     }
1915 
1916 	switch ( pAnch->GetAnchorId() )
1917 	{
1918         case FLY_AT_PAGE:
1919                 {
1920                 sal_uInt16 nPgNum = pAnch->GetPageNum();
1921                 ViewShell *pShell = pDrawFrmFmt->getIDocumentLayoutAccess()->GetCurrentViewShell();
1922                 if( !pShell )
1923                     break;
1924                 SwRootFrm* pRoot = pShell->GetLayout();
1925                 SwPageFrm *pPage = static_cast<SwPageFrm*>(pRoot->Lower());
1926 
1927                 for ( sal_uInt16 i = 1; i < nPgNum && pPage; ++i )
1928                 {
1929                     pPage = static_cast<SwPageFrm*>(pPage->GetNext());
1930                 }
1931 
1932                 if ( pPage )
1933                 {
1934                     pPage->AppendDrawObj( maAnchoredDrawObj );
1935                 }
1936                 else
1937                     //Sieht doof aus, ist aber erlaubt (vlg. SwFEShell::SetPageObjsNewPage)
1938                     pRoot->SetAssertFlyPages();
1939                 }
1940                 break;
1941 
1942         case FLY_AT_CHAR:
1943         case FLY_AT_PARA:
1944         case FLY_AT_FLY:
1945         case FLY_AS_CHAR:
1946             {
1947                 if ( pAnch->GetAnchorId() == FLY_AS_CHAR )
1948                 {
1949                     ClrContourCache( GetMaster() );
1950                 }
1951                 // OD 16.05.2003 #108784# - support drawing objects in header/footer,
1952                 // but not control objects:
1953                 // anchor at first found frame the 'master' object and
1954                 // at the following frames 'virtual' drawing objects.
1955                 // Note: method is similar to <SwFlyFrmFmt::MakeFrms(..)>
1956                 SwModify *pModify = 0;
1957                 if( pAnch->GetCntntAnchor() )
1958                 {
1959                     if ( pAnch->GetAnchorId() == FLY_AT_FLY )
1960                     {
1961                         SwNodeIndex aIdx( pAnch->GetCntntAnchor()->nNode );
1962                         SwCntntNode* pCNd = pDrawFrmFmt->GetDoc()->GetNodes().GoNext( &aIdx );
1963                         if ( SwIterator<SwFrm,SwCntntNode>::FirstElement( *pCNd ) )
1964                             pModify = pCNd;
1965                         else
1966                         {
1967                             const SwNodeIndex& rIdx = pAnch->GetCntntAnchor()->nNode;
1968                             SwSpzFrmFmts& rFmts = *(pDrawFrmFmt->GetDoc()->GetSpzFrmFmts());
1969                             for( sal_uInt16 i = 0; i < rFmts.Count(); ++i )
1970                             {
1971                                 SwFrmFmt* pFlyFmt = rFmts[i];
1972                                 if( pFlyFmt->GetCntnt().GetCntntIdx() &&
1973                                     rIdx == *(pFlyFmt->GetCntnt().GetCntntIdx()) )
1974                                 {
1975                                     pModify = pFlyFmt;
1976                                     break;
1977                                 }
1978                             }
1979                         }
1980                         // --> OD 2004-06-15 #i29199# - It is possible, that
1981                         // the anchor doesn't exist - E.g., reordering the
1982                         // sub-documents in a master document.
1983                         // Note: The anchor will be inserted later.
1984                         if ( !pModify )
1985                         {
1986                             // break to end of the current switch case.
1987                             break;
1988                         }
1989                     }
1990                     else
1991                     {
1992                         pModify = pAnch->GetCntntAnchor()->nNode.GetNode().GetCntntNode();
1993                     }
1994                 }
1995                 SwIterator<SwFrm,SwModify> aIter( *pModify );
1996                 SwFrm* pAnchorFrmOfMaster = 0;
1997                 for( SwFrm *pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
1998                 {
1999                     // append drawing object, if
2000                     // (1) proposed anchor frame isn't a follow and
2001                     // (2) drawing object isn't a control object to be anchored
2002                     //     in header/footer.
2003                     const bool bAdd = ( !pFrm->IsCntntFrm() ||
2004                                         !((SwCntntFrm*)pFrm)->IsFollow() ) &&
2005                                       ( !::CheckControlLayer( GetMaster() ) ||
2006                                         !pFrm->FindFooterOrHeader() );
2007 
2008                     if( bAdd )
2009                     {
2010                         if ( FLY_AT_FLY == pAnch->GetAnchorId() && !pFrm->IsFlyFrm() )
2011                         {
2012                             pFrm = pFrm->FindFlyFrm();
2013                             ASSERT( pFrm,
2014                                     "<SwDrawContact::ConnectToLayout(..)> - missing fly frame -> crash." );
2015                         }
2016 
2017                         // OD 2004-01-20 #110582# - find correct follow for
2018                         // as character anchored objects.
2019                         if ((pAnch->GetAnchorId() == FLY_AS_CHAR) &&
2020                              pFrm->IsTxtFrm() )
2021                         {
2022                             pFrm = lcl_GetFlyInCntntAnchor(
2023                                         static_cast<SwTxtFrm*>(pFrm),
2024                                         pAnch->GetCntntAnchor()->nContent.GetIndex() );
2025                         }
2026 
2027                         if ( !pAnchorFrmOfMaster )
2028                         {
2029                             // append 'master' drawing object
2030                             pAnchorFrmOfMaster = pFrm;
2031                             pFrm->AppendDrawObj( maAnchoredDrawObj );
2032                         }
2033                         else
2034                         {
2035                             // append 'virtual' drawing object
2036                             SwDrawVirtObj* pDrawVirtObj = AddVirtObj();
2037                             if ( pAnch->GetAnchorId() == FLY_AS_CHAR )
2038                             {
2039                                 ClrContourCache( pDrawVirtObj );
2040                             }
2041                             pFrm->AppendDrawObj( *(pDrawVirtObj->AnchoredObj()) );
2042 
2043 							// for repaint, use new ActionChanged()
2044                             // pDrawVirtObj->SendRepaintBroadcast();
2045                             pDrawVirtObj->ActionChanged();
2046                         }
2047 
2048                         if ( pAnch->GetAnchorId() == FLY_AS_CHAR )
2049                         {
2050                             pFrm->InvalidatePrt();
2051                         }
2052                     }
2053                 }
2054 			}
2055 			break;
2056         default:
2057             ASSERT( sal_False, "Unknown Anchor." )
2058             break;
2059     }
2060     if ( GetAnchorFrm() )
2061 	{
2062         ::setContextWritingMode( maAnchoredDrawObj.DrawObj(), GetAnchorFrm() );
2063         // OD 2004-04-01 #i26791# - invalidate objects instead of direct positioning
2064         _InvalidateObjs();
2065 	}
2066 }
2067 
2068 // OD 27.06.2003 #108784# - insert 'master' drawing object into drawing page
2069 void SwDrawContact::InsertMasterIntoDrawPage()
2070 {
2071     if ( !GetMaster()->IsInserted() )
2072     {
2073         GetFmt()->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage(0)
2074                 ->InsertObject( GetMaster(), GetMaster()->GetOrdNumDirect() );
2075     }
2076     GetMaster()->SetUserCall( this );
2077 }
2078 
2079 /*************************************************************************
2080 |*
2081 |*	SwDrawContact::FindPage(), ChkPage()
2082 |*
2083 |*	Ersterstellung		MA 21. Mar. 95
2084 |*	Letzte Aenderung	MA 19. Jul. 96
2085 |*
2086 |*************************************************************************/
2087 
2088 SwPageFrm* SwDrawContact::FindPage( const SwRect &rRect )
2089 {
2090     // --> OD 2004-07-01 #i28701# - use method <GetPageFrm()>
2091     SwPageFrm* pPg = GetPageFrm();
2092     if ( !pPg && GetAnchorFrm() )
2093         pPg = GetAnchorFrm()->FindPageFrm();
2094 	if ( pPg )
2095 		pPg = (SwPageFrm*)::FindPage( rRect, pPg );
2096 	return pPg;
2097 }
2098 
2099 void SwDrawContact::ChkPage()
2100 {
2101     // OD 10.10.2003 #112299#
2102     if ( mbDisconnectInProgress )
2103     {
2104         ASSERT( false,
2105                 "<SwDrawContact::ChkPage()> called during disconnection." );
2106         return;
2107     }
2108 
2109     // --> OD 2004-07-01 #i28701#
2110     SwPageFrm* pPg = ( maAnchoredDrawObj.GetAnchorFrm() &&
2111                        maAnchoredDrawObj.GetAnchorFrm()->IsPageFrm() )
2112                      ? GetPageFrm()
2113                      : FindPage( GetMaster()->GetCurrentBoundRect() );
2114     if ( GetPageFrm() != pPg )
2115 	{
2116         // OD 27.06.2003 #108784# - if drawing object is anchor in header/footer
2117         // a change of the page is a dramatic change. Thus, completely re-connect
2118         // to the layout
2119         if ( maAnchoredDrawObj.GetAnchorFrm() &&
2120              maAnchoredDrawObj.GetAnchorFrm()->FindFooterOrHeader() )
2121         {
2122             ConnectToLayout();
2123         }
2124         else
2125         {
2126             // --> OD 2004-07-01 #i28701# - use methods <GetPageFrm()> and <SetPageFrm>
2127             if ( GetPageFrm() )
2128                 GetPageFrm()->RemoveDrawObjFromPage( maAnchoredDrawObj );
2129             pPg->AppendDrawObjToPage( maAnchoredDrawObj );
2130             SetPageFrm( pPg );
2131         }
2132 	}
2133 }
2134 
2135 /*************************************************************************
2136 |*
2137 |*	SwDrawContact::ChangeMasterObject()
2138 |*
2139 |*	Ersterstellung		MA 07. Aug. 95
2140 |*	Letzte Aenderung	MA 20. Apr. 99
2141 |*
2142 |*************************************************************************/
2143 // OD 10.07.2003 #110742# - Important note:
2144 // method is called by method <SwDPage::ReplaceObject(..)>, which called its
2145 // corresponding superclass method <FmFormPage::ReplaceObject(..)>.
2146 // Note: 'master' drawing object *has* to be connected to layout triggered
2147 //       by the caller of this, if method is called.
2148 void SwDrawContact::ChangeMasterObject( SdrObject *pNewMaster )
2149 {
2150     DisconnectFromLayout( false );
2151     // OD 10.07.2003 #110742# - consider 'virtual' drawing objects
2152     RemoveAllVirtObjs();
2153 
2154     GetMaster()->SetUserCall( 0 );
2155 	SetMaster( pNewMaster );
2156 	GetMaster()->SetUserCall( this );
2157 
2158     _InvalidateObjs();
2159 }
2160 
2161 /** get data collection of anchored objects, handled by with contact
2162 
2163     OD 2004-08-23 #110810#
2164 
2165     @author
2166 */
2167 void SwDrawContact::GetAnchoredObjs( std::list<SwAnchoredObject*>& _roAnchoredObjs ) const
2168 {
2169     _roAnchoredObjs.push_back( const_cast<SwAnchoredDrawObject*>(&maAnchoredDrawObj) );
2170 
2171     for ( std::list<SwDrawVirtObj*>::const_iterator aDrawVirtObjsIter = maDrawVirtObjs.begin();
2172           aDrawVirtObjsIter != maDrawVirtObjs.end();
2173           ++aDrawVirtObjsIter )
2174     {
2175         _roAnchoredObjs.push_back( (*aDrawVirtObjsIter)->AnchoredObj() );
2176     }
2177 }
2178 
2179 //////////////////////////////////////////////////////////////////////////////////////
2180 // AW: own sdr::contact::ViewContact (VC) sdr::contact::ViewObjectContact (VOC) needed
2181 // since offset is defined different from SdrVirtObj's sdr::contact::ViewContactOfVirtObj.
2182 // For paint, that offset is used by setting at the OutputDevice; for primitives this is
2183 // not possible since we have no OutputDevice, but define the geometry itself.
2184 
2185 namespace sdr
2186 {
2187 	namespace contact
2188 	{
2189         class VOCOfDrawVirtObj : public ViewObjectContactOfSdrObj
2190 		{
2191 		protected:
2192 			// This method is responsible for creating the graphical visualisation data which is
2193 			// stored/cached in the local primitive. Default gets view-independent Primitive
2194 			// from the ViewContact using ViewContact::getViewIndependentPrimitive2DSequence(), takes care of
2195 			// visibility, handles glue and ghosted.
2196 			// This method will not handle included hierarchies and not check geometric visibility.
2197 			virtual drawinglayer::primitive2d::Primitive2DSequence createPrimitive2DSequence(const DisplayInfo& rDisplayInfo) const;
2198 
2199         public:
2200 			VOCOfDrawVirtObj(ObjectContact& rObjectContact, ViewContact& rViewContact)
2201             :   ViewObjectContactOfSdrObj(rObjectContact, rViewContact)
2202             {
2203             }
2204 
2205 			virtual ~VOCOfDrawVirtObj();
2206 		};
2207 
2208 		class VCOfDrawVirtObj : public ViewContactOfVirtObj
2209 		{
2210         protected:
2211 			// Create a Object-Specific ViewObjectContact, set ViewContact and
2212 			// ObjectContact. Always needs to return something. Default is to create
2213 			// a standard ViewObjectContact containing the given ObjectContact and *this
2214 			virtual ViewObjectContact& CreateObjectSpecificViewObjectContact(ObjectContact& rObjectContact);
2215 
2216         public:
2217 			// basic constructor, used from SdrObject.
2218             VCOfDrawVirtObj(SwDrawVirtObj& rObj)
2219             :   ViewContactOfVirtObj(rObj)
2220             {
2221             }
2222 			virtual ~VCOfDrawVirtObj();
2223 
2224             // access to SwDrawVirtObj
2225             SwDrawVirtObj& GetSwDrawVirtObj() const
2226             {
2227 			    return (SwDrawVirtObj&)mrObject;
2228             }
2229 		};
2230 	} // end of namespace contact
2231 } // end of namespace sdr
2232 
2233 namespace sdr
2234 {
2235 	namespace contact
2236 	{
2237         // recursively collect primitive data from given VOC with given offset
2238         void impAddPrimitivesFromGroup(const ViewObjectContact& rVOC, const basegfx::B2DHomMatrix& rOffsetMatrix, const DisplayInfo& rDisplayInfo, drawinglayer::primitive2d::Primitive2DSequence& rxTarget)
2239         {
2240 			const sal_uInt32 nSubHierarchyCount(rVOC.GetViewContact().GetObjectCount());
2241 
2242 			for(sal_uInt32 a(0L); a < nSubHierarchyCount; a++)
2243 			{
2244 				const ViewObjectContact& rCandidate(rVOC.GetViewContact().GetViewContact(a).GetViewObjectContact(rVOC.GetObjectContact()));
2245 
2246                 if(rCandidate.GetViewContact().GetObjectCount())
2247                 {
2248                     // is a group object itself, call resursively
2249                     impAddPrimitivesFromGroup(rCandidate, rOffsetMatrix, rDisplayInfo, rxTarget);
2250                 }
2251                 else
2252                 {
2253                     // single object, add primitives; check model-view visibility
2254 			        if(rCandidate.isPrimitiveVisible(rDisplayInfo))
2255 			        {
2256                         drawinglayer::primitive2d::Primitive2DSequence aNewSequence(rCandidate.getPrimitive2DSequence(rDisplayInfo));
2257 
2258 				        if(aNewSequence.hasElements())
2259 				        {
2260 					        // get ranges
2261 					        const drawinglayer::geometry::ViewInformation2D& rViewInformation2D(rCandidate.GetObjectContact().getViewInformation2D());
2262 					        const basegfx::B2DRange aViewRange(rViewInformation2D.getViewport());
2263 					        basegfx::B2DRange aObjectRange(rCandidate.getObjectRange());
2264 
2265                             // correct with virtual object's offset
2266                             aObjectRange.transform(rOffsetMatrix);
2267 
2268 					        // check geometrical visibility (with offset)
2269 					        if(!aViewRange.overlaps(aObjectRange))
2270 					        {
2271 						        // not visible, release
2272 						        aNewSequence.realloc(0);
2273 					        }
2274 				        }
2275 
2276 				        if(aNewSequence.hasElements())
2277 				        {
2278                             drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rxTarget, aNewSequence);
2279                         }
2280                     }
2281                 }
2282 			}
2283         }
2284 
2285         drawinglayer::primitive2d::Primitive2DSequence VOCOfDrawVirtObj::createPrimitive2DSequence(const DisplayInfo& rDisplayInfo) const
2286         {
2287 #ifdef DBG_UTIL
2288 			// #i101734#
2289 			static bool bCheckOtherThanTranslate(false);
2290 			static double fShearX(0.0);
2291 			static double fRotation(0.0);
2292 			static double fScaleX(0.0);
2293 			static double fScaleY(0.0);
2294 #endif
2295 
2296 			const VCOfDrawVirtObj& rVC = static_cast< const VCOfDrawVirtObj& >(GetViewContact());
2297             const SdrObject& rReferencedObject = rVC.GetSwDrawVirtObj().GetReferencedObj();
2298 			drawinglayer::primitive2d::Primitive2DSequence xRetval;
2299 
2300 		    // create offset transformation
2301 		    basegfx::B2DHomMatrix aOffsetMatrix;
2302             const Point aLocalOffset(rVC.GetSwDrawVirtObj().GetOffset());
2303 
2304 		    if(aLocalOffset.X() || aLocalOffset.Y())
2305 		    {
2306 #ifdef DBG_UTIL
2307 				// #i101734# added debug code to check more complex transformations
2308 				// than just a translation
2309 				if(bCheckOtherThanTranslate)
2310 				{
2311 					aOffsetMatrix.scale(fScaleX, fScaleY);
2312 					aOffsetMatrix.shearX(tan(fShearX * F_PI180));
2313 					aOffsetMatrix.rotate(fRotation * F_PI180);
2314 				}
2315 #endif
2316 
2317 			    aOffsetMatrix.set(0, 2, aLocalOffset.X());
2318 			    aOffsetMatrix.set(1, 2, aLocalOffset.Y());
2319 
2320 		    }
2321 
2322             if(rReferencedObject.ISA(SdrObjGroup))
2323             {
2324                 // group object. Since the VOC/OC/VC hierarchy does not represent the
2325                 // hierarchy virtual objects when they have group objects
2326                 // (ViewContactOfVirtObj::GetObjectCount() returns null for that purpose)
2327                 // to avoid multiple usages of VOCs (which would not work), the primitives
2328                 // for the sub-hierarchy need to be collected here
2329 
2330                 // Get the VOC of the referenced object (the Group) and fetch primitives from it
2331                 const ViewObjectContact& rVOCOfRefObj = rReferencedObject.GetViewContact().GetViewObjectContact(GetObjectContact());
2332                 impAddPrimitivesFromGroup(rVOCOfRefObj, aOffsetMatrix, rDisplayInfo, xRetval);
2333             }
2334             else
2335             {
2336 			    // single object, use method from referenced object to get the Primitive2DSequence
2337 			    xRetval = rReferencedObject.GetViewContact().getViewIndependentPrimitive2DSequence();
2338             }
2339 
2340             if(xRetval.hasElements())
2341 		    {
2342 			    // create transform primitive
2343 			    const drawinglayer::primitive2d::Primitive2DReference xReference(new drawinglayer::primitive2d::TransformPrimitive2D(aOffsetMatrix, xRetval));
2344                 xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1);
2345 		    }
2346 
2347             return xRetval;
2348         }
2349 
2350         VOCOfDrawVirtObj::~VOCOfDrawVirtObj()
2351         {
2352         }
2353 
2354 		ViewObjectContact& VCOfDrawVirtObj::CreateObjectSpecificViewObjectContact(ObjectContact& rObjectContact)
2355         {
2356 			return *(new VOCOfDrawVirtObj(rObjectContact, *this));
2357         }
2358 
2359         VCOfDrawVirtObj::~VCOfDrawVirtObj()
2360         {
2361         }
2362 	} // end of namespace contact
2363 } // end of namespace sdr
2364 
2365 //////////////////////////////////////////////////////////////////////////////////////
2366 
2367 // =============================================================================
2368 /** implementation of class <SwDrawVirtObj>
2369 
2370     OD 14.05.2003 #108784#
2371 
2372     @author OD
2373 */
2374 
2375 TYPEINIT1(SwDrawVirtObj,SdrVirtObj);
2376 
2377 sdr::contact::ViewContact* SwDrawVirtObj::CreateObjectSpecificViewContact()
2378 {
2379 	return new sdr::contact::VCOfDrawVirtObj(*this);
2380 }
2381 
2382 // #108784#
2383 // implemetation of SwDrawVirtObj
2384 SwDrawVirtObj::SwDrawVirtObj( SdrObject&        _rNewObj,
2385                               SwDrawContact&    _rDrawContact )
2386     : SdrVirtObj( _rNewObj ),
2387       // OD 2004-03-29 #i26791# - init new member <maAnchoredDrawObj>
2388       maAnchoredDrawObj(),
2389       mrDrawContact( _rDrawContact )
2390 {
2391     // OD 2004-03-29 #i26791#
2392     maAnchoredDrawObj.SetDrawObj( *this );
2393     // --> OD 2004-11-17 #i35635# - set initial position out of sight
2394     NbcMove( Size( -RECT_EMPTY, -RECT_EMPTY ) );
2395     // <--
2396 }
2397 
2398 SwDrawVirtObj::~SwDrawVirtObj()
2399 {}
2400 
2401 void SwDrawVirtObj::operator=( const SdrObject& rObj )
2402 {
2403 	SdrVirtObj::operator=(rObj);
2404     // Note: Members <maAnchoredDrawObj> and <mrDrawContact>
2405     //       haven't to be considered.
2406 }
2407 
2408 SdrObject* SwDrawVirtObj::Clone() const
2409 {
2410     SwDrawVirtObj* pObj = new SwDrawVirtObj( rRefObj, mrDrawContact );
2411 
2412     if ( pObj )
2413     {
2414         pObj->operator=(static_cast<const SdrObject&>(*this));
2415         // Note: Member <maAnchoredDrawObj> hasn't to be considered.
2416     }
2417 
2418     return pObj;
2419 }
2420 
2421 // --------------------------------------------------------------------
2422 // connection to writer layout: <GetAnchoredObj()>, <SetAnchorFrm(..)>,
2423 // <GetAnchorFrm()>, <SetPageFrm(..)>, <GetPageFrm()> and <RemoveFromWriterLayout()>
2424 // --------------------------------------------------------------------
2425 const SwAnchoredObject* SwDrawVirtObj::GetAnchoredObj() const
2426 {
2427     return &maAnchoredDrawObj;
2428 }
2429 
2430 SwAnchoredObject* SwDrawVirtObj::AnchoredObj()
2431 {
2432     return &maAnchoredDrawObj;
2433 }
2434 
2435 const SwFrm* SwDrawVirtObj::GetAnchorFrm() const
2436 {
2437     // OD 2004-03-29 #i26791# - use new member <maAnchoredDrawObj>
2438     return maAnchoredDrawObj.GetAnchorFrm();
2439 }
2440 
2441 SwFrm* SwDrawVirtObj::AnchorFrm()
2442 {
2443     // OD 2004-03-29 #i26791# - use new member <maAnchoredDrawObj>
2444     return maAnchoredDrawObj.AnchorFrm();
2445 }
2446 
2447 void SwDrawVirtObj::RemoveFromWriterLayout()
2448 {
2449     // remove contact object from frame for 'virtual' drawing object
2450     // OD 2004-03-29 #i26791# - use new member <maAnchoredDrawObj>
2451     if ( maAnchoredDrawObj.GetAnchorFrm() )
2452     {
2453         maAnchoredDrawObj.AnchorFrm()->RemoveDrawObj( maAnchoredDrawObj );
2454     }
2455 }
2456 
2457 // --------------------------------------------------------------------
2458 // connection to writer layout: <AddToDrawingPage()>, <RemoveFromDrawingPage()>
2459 // --------------------------------------------------------------------
2460 void SwDrawVirtObj::AddToDrawingPage()
2461 {
2462     // determine 'master'
2463     SdrObject* pOrgMasterSdrObj = mrDrawContact.GetMaster();
2464 
2465     // insert 'virtual' drawing object into page, set layer and user call.
2466     SdrPage* pDrawPg;
2467     // --> OD 2004-08-16 #i27030# - apply order number of referenced object
2468     if ( 0 != ( pDrawPg = pOrgMasterSdrObj->GetPage() ) )
2469     {
2470         // --> OD 2004-08-16 #i27030# - apply order number of referenced object
2471         pDrawPg->InsertObject( this, GetReferencedObj().GetOrdNum() );
2472     }
2473     else
2474     {
2475         pDrawPg = GetPage();
2476         if ( pDrawPg )
2477         {
2478             pDrawPg->SetObjectOrdNum( GetOrdNumDirect(),
2479                                       GetReferencedObj().GetOrdNum() );
2480         }
2481         else
2482         {
2483             SetOrdNum( GetReferencedObj().GetOrdNum() );
2484         }
2485     }
2486     // <--
2487     SetUserCall( &mrDrawContact );
2488 }
2489 
2490 void SwDrawVirtObj::RemoveFromDrawingPage()
2491 {
2492     SetUserCall( 0 );
2493     if ( GetPage() )
2494     {
2495         GetPage()->RemoveObject( GetOrdNum() );
2496     }
2497 }
2498 
2499 // is 'virtual' drawing object connected to writer layout and to drawing layer.
2500 bool SwDrawVirtObj::IsConnected() const
2501 {
2502     bool bRetVal = GetAnchorFrm() &&
2503                    ( GetPage() && GetUserCall() );
2504 
2505     return bRetVal;
2506 }
2507 
2508 void SwDrawVirtObj::NbcSetAnchorPos(const Point& rPnt)
2509 {
2510     SdrObject::NbcSetAnchorPos( rPnt );
2511 }
2512 
2513 //////////////////////////////////////////////////////////////////////////////
2514 // #i97197#
2515 // the methods relevant for positioning
2516 
2517 const Rectangle& SwDrawVirtObj::GetCurrentBoundRect() const
2518 {
2519     if(aOutRect.IsEmpty())
2520     {
2521         const_cast<SwDrawVirtObj*>(this)->RecalcBoundRect();
2522     }
2523 
2524     return aOutRect;
2525 }
2526 
2527 const Rectangle& SwDrawVirtObj::GetLastBoundRect() const
2528 {
2529 	return aOutRect;
2530 }
2531 
2532 const Point SwDrawVirtObj::GetOffset() const
2533 {
2534     // do NOT use IsEmpty() here, there is already a useful offset
2535     // in the position
2536     if(aOutRect == Rectangle())
2537     {
2538         return Point();
2539     }
2540     else
2541     {
2542         return aOutRect.TopLeft() - GetReferencedObj().GetCurrentBoundRect().TopLeft();
2543     }
2544 }
2545 
2546 void SwDrawVirtObj::SetBoundRectDirty()
2547 {
2548     // do nothing to not lose model information in aOutRect
2549 }
2550 
2551 void SwDrawVirtObj::RecalcBoundRect()
2552 {
2553     // OD 2004-04-05 #i26791# - switch order of calling <GetOffset()> and
2554     // <ReferencedObj().GetCurrentBoundRect()>, because <GetOffset()> calculates
2555     // its value by the 'BoundRect' of the referenced object.
2556     //aOutRect = rRefObj.GetCurrentBoundRect();
2557     //aOutRect += GetOffset();
2558 
2559     const Point aOffset(GetOffset());
2560     aOutRect = ReferencedObj().GetCurrentBoundRect() + aOffset;
2561 }
2562 
2563 basegfx::B2DPolyPolygon SwDrawVirtObj::TakeXorPoly() const
2564 {
2565 	basegfx::B2DPolyPolygon aRetval(rRefObj.TakeXorPoly());
2566 	aRetval.transform(basegfx::tools::createTranslateB2DHomMatrix(GetOffset().X(), GetOffset().Y()));
2567 
2568 	return aRetval;
2569 }
2570 
2571 basegfx::B2DPolyPolygon SwDrawVirtObj::TakeContour() const
2572 {
2573     basegfx::B2DPolyPolygon aRetval(rRefObj.TakeContour());
2574 	aRetval.transform(basegfx::tools::createTranslateB2DHomMatrix(GetOffset().X(), GetOffset().Y()));
2575 
2576 	return aRetval;
2577 }
2578 
2579 SdrHdl* SwDrawVirtObj::GetHdl(sal_uInt32 nHdlNum) const
2580 {
2581 	SdrHdl* pHdl = rRefObj.GetHdl(nHdlNum);
2582     Point aP(pHdl->GetPos() + GetOffset());
2583 	pHdl->SetPos(aP);
2584 
2585 	return pHdl;
2586 }
2587 
2588 SdrHdl* SwDrawVirtObj::GetPlusHdl(const SdrHdl& rHdl, sal_uInt16 nPlNum) const
2589 {
2590 	SdrHdl* pHdl = rRefObj.GetPlusHdl(rHdl, nPlNum);
2591     pHdl->SetPos(pHdl->GetPos() + GetOffset());
2592 
2593 	return pHdl;
2594 }
2595 
2596 void SwDrawVirtObj::NbcMove(const Size& rSiz)
2597 {
2598     SdrObject::NbcMove( rSiz );
2599 }
2600 
2601 void SwDrawVirtObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
2602 {
2603     rRefObj.NbcResize(rRef - GetOffset(), xFact, yFact);
2604 	SetRectsDirty();
2605 }
2606 
2607 void SwDrawVirtObj::NbcRotate(const Point& rRef, long nWink, double sn, double cs)
2608 {
2609     rRefObj.NbcRotate(rRef - GetOffset(), nWink, sn, cs);
2610 	SetRectsDirty();
2611 }
2612 
2613 void SwDrawVirtObj::NbcMirror(const Point& rRef1, const Point& rRef2)
2614 {
2615     rRefObj.NbcMirror(rRef1 - GetOffset(), rRef2 - GetOffset());
2616 	SetRectsDirty();
2617 }
2618 
2619 void SwDrawVirtObj::NbcShear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear)
2620 {
2621     rRefObj.NbcShear(rRef - GetOffset(), nWink, tn, bVShear);
2622 	SetRectsDirty();
2623 }
2624 
2625 void SwDrawVirtObj::Move(const Size& rSiz)
2626 {
2627     SdrObject::Move( rSiz );
2628 //    Rectangle aBoundRect0; if(pUserCall) aBoundRect0 = GetLastBoundRect();
2629 //    rRefObj.Move( rSiz );
2630 //    SetRectsDirty();
2631 //    SendUserCall(SDRUSERCALL_RESIZE, aBoundRect0);
2632 }
2633 
2634 void SwDrawVirtObj::Resize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
2635 {
2636 	if(xFact.GetNumerator() != xFact.GetDenominator() || yFact.GetNumerator() != yFact.GetDenominator())
2637 	{
2638 		Rectangle aBoundRect0; if(pUserCall) aBoundRect0 = GetLastBoundRect();
2639         rRefObj.Resize(rRef - GetOffset(), xFact, yFact);
2640 		SetRectsDirty();
2641 		SendUserCall(SDRUSERCALL_RESIZE, aBoundRect0);
2642 	}
2643 }
2644 
2645 void SwDrawVirtObj::Rotate(const Point& rRef, long nWink, double sn, double cs)
2646 {
2647 	if(nWink)
2648 	{
2649 		Rectangle aBoundRect0; if(pUserCall) aBoundRect0 = GetLastBoundRect();
2650         rRefObj.Rotate(rRef - GetOffset(), nWink, sn, cs);
2651 		SetRectsDirty();
2652 		SendUserCall(SDRUSERCALL_RESIZE, aBoundRect0);
2653 	}
2654 }
2655 
2656 void SwDrawVirtObj::Mirror(const Point& rRef1, const Point& rRef2)
2657 {
2658 	Rectangle aBoundRect0; if(pUserCall) aBoundRect0 = GetLastBoundRect();
2659     rRefObj.Mirror(rRef1 - GetOffset(), rRef2 - GetOffset());
2660 	SetRectsDirty();
2661 	SendUserCall(SDRUSERCALL_RESIZE, aBoundRect0);
2662 }
2663 
2664 void SwDrawVirtObj::Shear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear)
2665 {
2666 	if(nWink)
2667 	{
2668 		Rectangle aBoundRect0; if(pUserCall) aBoundRect0 = GetLastBoundRect();
2669         rRefObj.Shear(rRef - GetOffset(), nWink, tn, bVShear);
2670 		SetRectsDirty();
2671 		SendUserCall(SDRUSERCALL_RESIZE, aBoundRect0);
2672 	}
2673 }
2674 
2675 void SwDrawVirtObj::RecalcSnapRect()
2676 {
2677     aSnapRect = rRefObj.GetSnapRect();
2678     aSnapRect += GetOffset();
2679 }
2680 
2681 const Rectangle& SwDrawVirtObj::GetSnapRect() const
2682 {
2683     ((SwDrawVirtObj*)this)->aSnapRect = rRefObj.GetSnapRect();
2684     ((SwDrawVirtObj*)this)->aSnapRect += GetOffset();
2685 
2686     return aSnapRect;
2687 }
2688 
2689 void SwDrawVirtObj::SetSnapRect(const Rectangle& rRect)
2690 {
2691 	Rectangle aBoundRect0; if(pUserCall) aBoundRect0 = GetLastBoundRect();
2692 	Rectangle aR(rRect);
2693     aR -= GetOffset();
2694 	rRefObj.SetSnapRect(aR);
2695 	SetRectsDirty();
2696 	SendUserCall(SDRUSERCALL_RESIZE, aBoundRect0);
2697 }
2698 
2699 void SwDrawVirtObj::NbcSetSnapRect(const Rectangle& rRect)
2700 {
2701 	Rectangle aR(rRect);
2702     aR -= GetOffset();
2703 	SetRectsDirty();
2704 	rRefObj.NbcSetSnapRect(aR);
2705 }
2706 
2707 const Rectangle& SwDrawVirtObj::GetLogicRect() const
2708 {
2709 	((SwDrawVirtObj*)this)->aSnapRect = rRefObj.GetLogicRect();
2710     ((SwDrawVirtObj*)this)->aSnapRect += GetOffset();
2711 
2712 	return aSnapRect;
2713 }
2714 
2715 void SwDrawVirtObj::SetLogicRect(const Rectangle& rRect)
2716 {
2717 	Rectangle aBoundRect0; if(pUserCall) aBoundRect0 = GetLastBoundRect();
2718 	Rectangle aR(rRect);
2719     aR -= GetOffset();
2720 	rRefObj.SetLogicRect(aR);
2721 	SetRectsDirty();
2722 	SendUserCall(SDRUSERCALL_RESIZE, aBoundRect0);
2723 }
2724 
2725 void SwDrawVirtObj::NbcSetLogicRect(const Rectangle& rRect)
2726 {
2727 	Rectangle aR(rRect);
2728     aR -= GetOffset();
2729 	rRefObj.NbcSetLogicRect(aR);
2730 	SetRectsDirty();
2731 }
2732 
2733 Point SwDrawVirtObj::GetSnapPoint(sal_uInt32 i) const
2734 {
2735 	Point aP(rRefObj.GetSnapPoint(i));
2736     aP += GetOffset();
2737 
2738 	return aP;
2739 }
2740 
2741 Point SwDrawVirtObj::GetPoint(sal_uInt32 i) const
2742 {
2743 	return Point(rRefObj.GetPoint(i) + GetOffset());
2744 }
2745 
2746 void SwDrawVirtObj::NbcSetPoint(const Point& rPnt, sal_uInt32 i)
2747 {
2748 	Point aP(rPnt);
2749     aP -= GetOffset();
2750 	rRefObj.SetPoint(aP, i);
2751 	SetRectsDirty();
2752 }
2753 
2754 // #108784#
2755 FASTBOOL SwDrawVirtObj::HasTextEdit() const
2756 {
2757 	return rRefObj.HasTextEdit();
2758 }
2759 
2760 // OD 18.06.2003 #108784# - overloaded 'layer' methods for 'virtual' drawing
2761 // object to assure, that layer of 'virtual' object is the layer of the referenced
2762 // object.
2763 SdrLayerID SwDrawVirtObj::GetLayer() const
2764 {
2765     return GetReferencedObj().GetLayer();
2766 }
2767 
2768 void SwDrawVirtObj::NbcSetLayer(SdrLayerID nLayer)
2769 {
2770     ReferencedObj().NbcSetLayer( nLayer );
2771     SdrVirtObj::NbcSetLayer( ReferencedObj().GetLayer() );
2772 }
2773 
2774 void SwDrawVirtObj::SetLayer(SdrLayerID nLayer)
2775 {
2776     ReferencedObj().SetLayer( nLayer );
2777     SdrVirtObj::NbcSetLayer( ReferencedObj().GetLayer() );
2778 }
2779 
2780 bool SwDrawVirtObj::supportsFullDrag() const
2781 {
2782     // call parent
2783     return SdrVirtObj::supportsFullDrag();
2784 }
2785 
2786 SdrObject* SwDrawVirtObj::getFullDragClone() const
2787 {
2788     // call parent
2789     return SdrVirtObj::getFullDragClone();
2790 }
2791 
2792 // eof
2793 
2794