xref: /trunk/main/sw/source/core/undo/undraw.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 #include <UndoDraw.hxx>
32 
33 #include <rtl/string.h>
34 #include <rtl/memory.h>
35 
36 #include <rtl/string.h>
37 #include <svx/svdogrp.hxx>
38 #include <svx/svdundo.hxx>
39 #include <svx/svdpage.hxx>
40 #include <svx/svdmark.hxx>
41 
42 #include <hintids.hxx>
43 #include <hints.hxx>
44 #include <fmtanchr.hxx>
45 #include <fmtflcnt.hxx>
46 #include <txtflcnt.hxx>
47 #include <frmfmt.hxx>
48 #include <doc.hxx>
49 #include <IDocumentUndoRedo.hxx>
50 #include <docary.hxx>
51 #include <frame.hxx>
52 #include <swundo.hxx>           // fuer die UndoIds
53 #include <pam.hxx>
54 #include <ndtxt.hxx>
55 #include <UndoCore.hxx>
56 #include <dcontact.hxx>
57 #include <dview.hxx>
58 #include <rootfrm.hxx>
59 #include <viewsh.hxx>
60 
61 
62 struct SwUndoGroupObjImpl
63 {
64     SwDrawFrmFmt* pFmt;
65     SdrObject* pObj;
66     sal_uLong nNodeIdx;
67 };
68 
69 
70 // Draw-Objecte
71 
72 IMPL_LINK( SwDoc, AddDrawUndo, SdrUndoAction *, pUndo )
73 {
74 #if OSL_DEBUG_LEVEL > 1
75     sal_uInt16 nId = pUndo->GetId();
76     (void)nId;
77     String sComment( pUndo->GetComment() );
78 #endif
79 
80     if (GetIDocumentUndoRedo().DoesUndo() &&
81         GetIDocumentUndoRedo().DoesDrawUndo())
82     {
83         const SdrMarkList* pMarkList = 0;
84         ViewShell* pSh = GetCurrentViewShell();
85         if( pSh && pSh->HasDrawView() )
86             pMarkList = &pSh->GetDrawView()->GetMarkedObjectList();
87 
88         GetIDocumentUndoRedo().AppendUndo( new SwSdrUndo(pUndo, pMarkList) );
89     }
90     else
91         delete pUndo;
92     return 0;
93 }
94 
95 SwSdrUndo::SwSdrUndo( SdrUndoAction* pUndo, const SdrMarkList* pMrkLst )
96     : SwUndo( UNDO_DRAWUNDO ), pSdrUndo( pUndo )
97 {
98     if( pMrkLst && pMrkLst->GetMarkCount() )
99         pMarkList = new SdrMarkList( *pMrkLst );
100     else
101         pMarkList = 0;
102 }
103 
104 SwSdrUndo::~SwSdrUndo()
105 {
106     delete pSdrUndo;
107     delete pMarkList;
108 }
109 
110 void SwSdrUndo::UndoImpl(::sw::UndoRedoContext & rContext)
111 {
112     pSdrUndo->Undo();
113     rContext.SetSelections(0, pMarkList);
114 }
115 
116 void SwSdrUndo::RedoImpl(::sw::UndoRedoContext & rContext)
117 {
118     pSdrUndo->Redo();
119     rContext.SetSelections(0, pMarkList);
120 }
121 
122 String SwSdrUndo::GetComment() const
123 {
124     return pSdrUndo->GetComment();
125 }
126 
127 //--------------------------------------------
128 
129 void lcl_SendRemoveToUno( SwFmt& rFmt )
130 {
131     SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, &rFmt );
132     rFmt.ModifyNotification( &aMsgHint, &aMsgHint );
133 }
134 
135 void lcl_SaveAnchor( SwFrmFmt* pFmt, sal_uLong& rNodePos )
136 {
137     const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
138     if ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
139         (FLY_AT_CHAR == rAnchor.GetAnchorId()) ||
140         (FLY_AT_FLY  == rAnchor.GetAnchorId()) ||
141         (FLY_AS_CHAR == rAnchor.GetAnchorId()))
142     {
143         rNodePos = rAnchor.GetCntntAnchor()->nNode.GetIndex();
144         xub_StrLen nCntntPos = 0;
145 
146         if (FLY_AS_CHAR == rAnchor.GetAnchorId())
147         {
148             nCntntPos = rAnchor.GetCntntAnchor()->nContent.GetIndex();
149 
150             // destroy TextAttribute
151             SwTxtNode *pTxtNd = pFmt->GetDoc()->GetNodes()[ rNodePos ]->GetTxtNode();
152             ASSERT( pTxtNd, "No text node found!" );
153             SwTxtFlyCnt* pAttr = static_cast<SwTxtFlyCnt*>(
154                 pTxtNd->GetTxtAttrForCharAt( nCntntPos, RES_TXTATR_FLYCNT ));
155             // attribute still in text node, delete
156             if( pAttr && pAttr->GetFlyCnt().GetFrmFmt() == pFmt )
157             {
158                 // just set pointer to 0, don't delete
159                 ((SwFmtFlyCnt&)pAttr->GetFlyCnt()).SetFlyFmt();
160                 SwIndex aIdx( pTxtNd, nCntntPos );
161                 pTxtNd->EraseText( aIdx, 1 );
162             }
163         }
164         else if (FLY_AT_CHAR == rAnchor.GetAnchorId())
165         {
166             nCntntPos = rAnchor.GetCntntAnchor()->nContent.GetIndex();
167         }
168 
169         pFmt->SetFmtAttr( SwFmtAnchor( rAnchor.GetAnchorId(), nCntntPos ) );
170     }
171 }
172 
173 void lcl_RestoreAnchor( SwFrmFmt* pFmt, sal_uLong& rNodePos )
174 {
175     const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
176     if ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
177         (FLY_AT_CHAR == rAnchor.GetAnchorId()) ||
178         (FLY_AT_FLY  == rAnchor.GetAnchorId()) ||
179         (FLY_AS_CHAR == rAnchor.GetAnchorId()))
180     {
181         xub_StrLen nCntntPos = rAnchor.GetPageNum();
182         SwNodes& rNds = pFmt->GetDoc()->GetNodes();
183 
184         SwNodeIndex aIdx( rNds, rNodePos );
185         SwPosition aPos( aIdx );
186 
187         SwFmtAnchor aTmp( rAnchor.GetAnchorId() );
188         if ((FLY_AS_CHAR == rAnchor.GetAnchorId()) ||
189             (FLY_AT_CHAR == rAnchor.GetAnchorId()))
190         {
191             aPos.nContent.Assign( aIdx.GetNode().GetCntntNode(), nCntntPos );
192         }
193         aTmp.SetAnchor( &aPos );
194         pFmt->SetFmtAttr( aTmp );
195 
196         if (FLY_AS_CHAR == rAnchor.GetAnchorId())
197         {
198             SwTxtNode *pTxtNd = aIdx.GetNode().GetTxtNode();
199             ASSERT( pTxtNd, "no Text Node" );
200             SwFmtFlyCnt aFmt( pFmt );
201             pTxtNd->InsertItem( aFmt, nCntntPos, nCntntPos );
202         }
203     }
204 }
205 
206 SwUndoDrawGroup::SwUndoDrawGroup( sal_uInt16 nCnt )
207     : SwUndo( UNDO_DRAWGROUP ), nSize( nCnt + 1 ), bDelFmt( sal_True )
208 {
209     pObjArr = new SwUndoGroupObjImpl[ nSize ];
210 }
211 
212 SwUndoDrawGroup::~SwUndoDrawGroup()
213 {
214     if( bDelFmt )
215     {
216         SwUndoGroupObjImpl* pTmp = pObjArr + 1;
217         for( sal_uInt16 n = 1; n < nSize; ++n, ++pTmp )
218             delete pTmp->pFmt;
219     }
220     else
221         delete pObjArr->pFmt;
222 
223     delete [] pObjArr;
224 }
225 
226 void SwUndoDrawGroup::UndoImpl(::sw::UndoRedoContext &)
227 {
228     bDelFmt = sal_False;
229 
230     // save group object
231     SwDrawFrmFmt* pFmt = pObjArr->pFmt;
232     SwDrawContact* pDrawContact = (SwDrawContact*)pFmt->FindContactObj();
233     SdrObject* pObj = pDrawContact->GetMaster();
234     pObjArr->pObj = pObj;
235 
236     // object will destroy itself
237     pDrawContact->Changed( *pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
238     pObj->SetUserCall( 0 );
239 
240     ::lcl_SaveAnchor( pFmt, pObjArr->nNodeIdx );
241 
242     // notify UNO objects to decouple
243     ::lcl_SendRemoveToUno( *pFmt );
244 
245     // remove from array
246     SwDoc* pDoc = pFmt->GetDoc();
247     SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
248     rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
249 
250     for( sal_uInt16 n = 1; n < nSize; ++n )
251     {
252         SwUndoGroupObjImpl& rSave = *( pObjArr + n );
253 
254         ::lcl_RestoreAnchor( rSave.pFmt, rSave.nNodeIdx );
255         rFlyFmts.Insert( rSave.pFmt, rFlyFmts.Count() );
256 
257         pObj = rSave.pObj;
258 
259         SwDrawContact *pContact = new SwDrawContact( rSave.pFmt, pObj );
260         pContact->ConnectToLayout();
261         // #i45718# - follow-up of #i35635# move object to visible layer
262         pContact->MoveObjToVisibleLayer( pObj );
263         // #i45952# - notify that position attributes are already set
264         ASSERT( rSave.pFmt->ISA(SwDrawFrmFmt),
265                 "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for drawing object" );
266         if ( rSave.pFmt->ISA(SwDrawFrmFmt) )
267         {
268             static_cast<SwDrawFrmFmt*>(rSave.pFmt)->PosAttrSet();
269         }
270     }
271 }
272 
273 void SwUndoDrawGroup::RedoImpl(::sw::UndoRedoContext &)
274 {
275     bDelFmt = sal_True;
276 
277     // remove from array
278     SwDoc* pDoc = pObjArr->pFmt->GetDoc();
279     SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
280     SdrObject* pObj;
281 
282     for( sal_uInt16 n = 1; n < nSize; ++n )
283     {
284         SwUndoGroupObjImpl& rSave = *( pObjArr + n );
285 
286         pObj = rSave.pObj;
287 
288         SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
289 
290         // object will destroy itself
291         pContact->Changed( *pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
292         pObj->SetUserCall( 0 );
293 
294         ::lcl_SaveAnchor( rSave.pFmt, rSave.nNodeIdx );
295 
296         // notify UNO objects to decouple
297         ::lcl_SendRemoveToUno( *rSave.pFmt );
298 
299         rFlyFmts.Remove( rFlyFmts.GetPos( rSave.pFmt ));
300     }
301 
302     // re-insert group object
303     ::lcl_RestoreAnchor( pObjArr->pFmt, pObjArr->nNodeIdx );
304     rFlyFmts.Insert( pObjArr->pFmt, rFlyFmts.Count() );
305 
306     SwDrawContact *pContact = new SwDrawContact( pObjArr->pFmt, pObjArr->pObj );
307     // #i26791# - correction: connect object to layout
308     pContact->ConnectToLayout();
309     // #i45718# - follow-up of #i35635# move object to visible layer
310     pContact->MoveObjToVisibleLayer( pObjArr->pObj );
311     // #i45952# - notify that position attributes are already set
312     ASSERT( pObjArr->pFmt->ISA(SwDrawFrmFmt),
313             "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for drawing object" );
314     if ( pObjArr->pFmt->ISA(SwDrawFrmFmt) )
315     {
316         static_cast<SwDrawFrmFmt*>(pObjArr->pFmt)->PosAttrSet();
317     }
318 }
319 
320 void SwUndoDrawGroup::AddObj( sal_uInt16 nPos, SwDrawFrmFmt* pFmt, SdrObject* pObj )
321 {
322     SwUndoGroupObjImpl& rSave = *( pObjArr + nPos + 1 );
323     rSave.pObj = pObj;
324     rSave.pFmt = pFmt;
325     ::lcl_SaveAnchor( pFmt, rSave.nNodeIdx );
326 
327     // notify UNO objects to decouple
328     ::lcl_SendRemoveToUno( *pFmt );
329 
330     // remove from array
331     SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pFmt->GetDoc()->GetSpzFrmFmts();
332     rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
333 }
334 
335 void SwUndoDrawGroup::SetGroupFmt( SwDrawFrmFmt* pFmt )
336 {
337     pObjArr->pObj = 0;
338     pObjArr->pFmt = pFmt;
339 }
340 
341 
342 // ------------------------------
343 
344 SwUndoDrawUnGroup::SwUndoDrawUnGroup( SdrObjGroup* pObj )
345     : SwUndo( UNDO_DRAWUNGROUP ), bDelFmt( sal_False )
346 {
347     nSize = (sal_uInt16)pObj->GetSubList()->GetObjCount() + 1;
348     pObjArr = new SwUndoGroupObjImpl[ nSize ];
349 
350     SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
351     SwDrawFrmFmt* pFmt = (SwDrawFrmFmt*)pContact->GetFmt();
352 
353     pObjArr->pObj = pObj;
354     pObjArr->pFmt = pFmt;
355 
356     // object will destroy itself
357     pContact->Changed( *pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
358     pObj->SetUserCall( 0 );
359 
360     ::lcl_SaveAnchor( pFmt, pObjArr->nNodeIdx );
361 
362     // notify UNO objects to decouple
363     ::lcl_SendRemoveToUno( *pFmt );
364 
365     // remove from array
366     SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pFmt->GetDoc()->GetSpzFrmFmts();
367     rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
368 }
369 
370 SwUndoDrawUnGroup::~SwUndoDrawUnGroup()
371 {
372     if( bDelFmt )
373     {
374         SwUndoGroupObjImpl* pTmp = pObjArr + 1;
375         for( sal_uInt16 n = 1; n < nSize; ++n, ++pTmp )
376             delete pTmp->pFmt;
377     }
378     else
379         delete pObjArr->pFmt;
380 
381     delete [] pObjArr;
382 }
383 
384 void SwUndoDrawUnGroup::UndoImpl(::sw::UndoRedoContext & rContext)
385 {
386     bDelFmt = sal_True;
387 
388     SwDoc *const pDoc = & rContext.GetDoc();
389     SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
390 
391     // remove from array
392     for( sal_uInt16 n = 1; n < nSize; ++n )
393     {
394         SwUndoGroupObjImpl& rSave = *( pObjArr + n );
395 
396         ::lcl_SaveAnchor( rSave.pFmt, rSave.nNodeIdx );
397 
398         // notify UNO objects to decouple
399         ::lcl_SendRemoveToUno( *rSave.pFmt );
400 
401         rFlyFmts.Remove( rFlyFmts.GetPos( rSave.pFmt ));
402     }
403 
404     // re-insert group object
405     ::lcl_RestoreAnchor( pObjArr->pFmt, pObjArr->nNodeIdx );
406     rFlyFmts.Insert( pObjArr->pFmt, rFlyFmts.Count() );
407 
408     SwDrawContact *pContact = new SwDrawContact( pObjArr->pFmt, pObjArr->pObj );
409     pContact->ConnectToLayout();
410     // #i45718# - follow-up of #i35635# move object to visible layer
411     pContact->MoveObjToVisibleLayer( pObjArr->pObj );
412     // #i45952# - notify that position attributes are already set
413     ASSERT( pObjArr->pFmt->ISA(SwDrawFrmFmt),
414             "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for drawing object" );
415     if ( pObjArr->pFmt->ISA(SwDrawFrmFmt) )
416     {
417         static_cast<SwDrawFrmFmt*>(pObjArr->pFmt)->PosAttrSet();
418     }
419 }
420 
421 void SwUndoDrawUnGroup::RedoImpl(::sw::UndoRedoContext &)
422 {
423     bDelFmt = sal_False;
424 
425     // save group object
426     SwDrawFrmFmt* pFmt = pObjArr->pFmt;
427     SwDrawContact* pContact = (SwDrawContact*)pFmt->FindContactObj();
428 
429         // object will destroy itself
430     pContact->Changed( *pObjArr->pObj, SDRUSERCALL_DELETE,
431         pObjArr->pObj->GetLastBoundRect() );
432     pObjArr->pObj->SetUserCall( 0 );
433 
434     ::lcl_SaveAnchor( pFmt, pObjArr->nNodeIdx );
435 
436     // notify UNO objects to decouple
437     ::lcl_SendRemoveToUno( *pFmt );
438 
439     // remove from array
440     SwDoc* pDoc = pFmt->GetDoc();
441     SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
442     rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
443 
444     for( sal_uInt16 n = 1; n < nSize; ++n )
445     {
446         SwUndoGroupObjImpl& rSave = *( pObjArr + n );
447 
448         ::lcl_RestoreAnchor( rSave.pFmt, rSave.nNodeIdx );
449         rFlyFmts.Insert( rSave.pFmt, rFlyFmts.Count() );
450 
451         // #i45952# - notify that position attributes are already set
452         ASSERT( rSave.pFmt->ISA(SwDrawFrmFmt),
453                 "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for drawing object" );
454         if ( rSave.pFmt->ISA(SwDrawFrmFmt) )
455         {
456             static_cast<SwDrawFrmFmt*>(rSave.pFmt)->PosAttrSet();
457         }
458     }
459 }
460 
461 void SwUndoDrawUnGroup::AddObj( sal_uInt16 nPos, SwDrawFrmFmt* pFmt )
462 {
463     SwUndoGroupObjImpl& rSave = *( pObjArr + nPos + 1 );
464     rSave.pFmt = pFmt;
465     rSave.pObj = 0;
466 }
467 
468 SwUndoDrawUnGroupConnectToLayout::SwUndoDrawUnGroupConnectToLayout()
469     : SwUndo( UNDO_DRAWUNGROUP )
470 {
471 }
472 
473 SwUndoDrawUnGroupConnectToLayout::~SwUndoDrawUnGroupConnectToLayout()
474 {
475 }
476 
477 void
478 SwUndoDrawUnGroupConnectToLayout::UndoImpl(::sw::UndoRedoContext &)
479 {
480     for ( std::vector< SdrObject >::size_type i = 0;
481           i < aDrawFmtsAndObjs.size(); ++i )
482     {
483         SdrObject* pObj( aDrawFmtsAndObjs[i].second );
484         SwDrawContact* pDrawContact( dynamic_cast<SwDrawContact*>(pObj->GetUserCall()) );
485         ASSERT( pDrawContact,
486                 "<SwUndoDrawUnGroupConnectToLayout::Undo(..)> -- missing SwDrawContact instance" );
487         if ( pDrawContact )
488         {
489             // deletion of instance <pDrawContact> and thus disconnection from
490             // the Writer layout.
491             pDrawContact->Changed( *pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
492             pObj->SetUserCall( 0 );
493         }
494     }
495 }
496 
497 void
498 SwUndoDrawUnGroupConnectToLayout::RedoImpl(::sw::UndoRedoContext &)
499 {
500     for ( std::vector< std::pair< SwDrawFrmFmt*, SdrObject* > >::size_type i = 0;
501           i < aDrawFmtsAndObjs.size(); ++i )
502     {
503         SwDrawFrmFmt* pFmt( aDrawFmtsAndObjs[i].first );
504         SdrObject* pObj( aDrawFmtsAndObjs[i].second );
505         SwDrawContact *pContact = new SwDrawContact( pFmt, pObj );
506         pContact->ConnectToLayout();
507         pContact->MoveObjToVisibleLayer( pObj );
508     }
509 }
510 
511 void SwUndoDrawUnGroupConnectToLayout::AddFmtAndObj( SwDrawFrmFmt* pDrawFrmFmt,
512                                                      SdrObject* pDrawObject )
513 {
514     aDrawFmtsAndObjs.push_back(
515             std::pair< SwDrawFrmFmt*, SdrObject* >( pDrawFrmFmt, pDrawObject ) );
516 }
517 
518 //-------------------------------------
519 
520 SwUndoDrawDelete::SwUndoDrawDelete( sal_uInt16 nCnt )
521     : SwUndo( UNDO_DRAWDELETE ), nSize( nCnt ), bDelFmt( sal_True )
522 {
523     pObjArr = new SwUndoGroupObjImpl[ nSize ];
524     pMarkLst = new SdrMarkList();
525 }
526 
527 SwUndoDrawDelete::~SwUndoDrawDelete()
528 {
529     if( bDelFmt )
530     {
531         SwUndoGroupObjImpl* pTmp = pObjArr;
532         for( sal_uInt16 n = 0; n < pMarkLst->GetMarkCount(); ++n, ++pTmp )
533             delete pTmp->pFmt;
534     }
535     delete [] pObjArr;
536     delete pMarkLst;
537 }
538 
539 void SwUndoDrawDelete::UndoImpl(::sw::UndoRedoContext & rContext)
540 {
541     bDelFmt = sal_False;
542     SwSpzFrmFmts & rFlyFmts = *rContext.GetDoc().GetSpzFrmFmts();
543     for( sal_uInt16 n = 0; n < pMarkLst->GetMarkCount(); ++n )
544     {
545         SwUndoGroupObjImpl& rSave = *( pObjArr + n );
546         ::lcl_RestoreAnchor( rSave.pFmt, rSave.nNodeIdx );
547         rFlyFmts.Insert( rSave.pFmt, rFlyFmts.Count() );
548         SdrObject *pObj = rSave.pObj;
549         SwDrawContact *pContact = new SwDrawContact( rSave.pFmt, pObj );
550         pContact->_Changed( *pObj, SDRUSERCALL_INSERTED, NULL );
551         // #i45718# - follow-up of #i35635# move object to visible layer
552         pContact->MoveObjToVisibleLayer( pObj );
553         // #i45952# - notify that position attributes are already set
554         ASSERT( rSave.pFmt->ISA(SwDrawFrmFmt),
555                 "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for drawing object" );
556         if ( rSave.pFmt->ISA(SwDrawFrmFmt) )
557         {
558             static_cast<SwDrawFrmFmt*>(rSave.pFmt)->PosAttrSet();
559         }
560         // <--
561     }
562     rContext.SetSelections(0, pMarkLst);
563 }
564 
565 void SwUndoDrawDelete::RedoImpl(::sw::UndoRedoContext & rContext)
566 {
567     bDelFmt = sal_True;
568     SwSpzFrmFmts & rFlyFmts = *rContext.GetDoc().GetSpzFrmFmts();
569     for( sal_uInt16 n = 0; n < pMarkLst->GetMarkCount(); ++n )
570     {
571         SwUndoGroupObjImpl& rSave = *( pObjArr + n );
572         SdrObject *pObj = rSave.pObj;
573         SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
574         SwDrawFrmFmt *pFmt = (SwDrawFrmFmt*)pContact->GetFmt();
575 
576         // object will destroy itself
577         pContact->Changed( *pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
578         pObj->SetUserCall( 0 );
579 
580         // notify UNO objects to decouple
581         ::lcl_SendRemoveToUno( *pFmt );
582 
583         rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
584         ::lcl_SaveAnchor( pFmt, rSave.nNodeIdx );
585     }
586 }
587 
588 void SwUndoDrawDelete::AddObj( sal_uInt16 , SwDrawFrmFmt* pFmt,
589                                 const SdrMark& rMark )
590 {
591     SwUndoGroupObjImpl& rSave = *( pObjArr + pMarkLst->GetMarkCount() );
592     rSave.pObj = rMark.GetMarkedSdrObj();
593     rSave.pFmt = pFmt;
594     ::lcl_SaveAnchor( pFmt, rSave.nNodeIdx );
595 
596     // notify UNO objects to decouple
597     ::lcl_SendRemoveToUno( *pFmt );
598 
599     // remove from array
600     SwDoc* pDoc = pFmt->GetDoc();
601     SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
602     rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
603 
604     pMarkLst->InsertEntry( rMark );
605 }
606 
607