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