xref: /trunk/main/sd/source/core/sdpage2.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_sd.hxx"
30 #include <sfx2/docfile.hxx>
31 #include <vcl/svapp.hxx>
32 #include <editeng/outliner.hxx>
33 #ifndef _SVXLINK_HXX
34 #include <sfx2/linkmgr.hxx>
35 #endif
36 #include <svx/svdotext.hxx>
37 #include <tools/urlobj.hxx>
38 #include <editeng/outlobj.hxx>
39 #include <svl/urihelper.hxx>
40 #include <editeng/xmlcnitm.hxx>
41 #include <svx/svditer.hxx>
42 #include <tools/list.hxx>
43 
44 #include "sdresid.hxx"
45 #include "sdpage.hxx"
46 #include "glob.hxx"
47 #include "glob.hrc"
48 #include "drawdoc.hxx"
49 #include "stlpool.hxx"
50 //#include "sdiocmpt.hxx"
51 #include "pglink.hxx"
52 //#include "strmname.h"
53 #include "anminfo.hxx"
54 
55 #include "../ui/inc/strings.hrc"
56 #include "../ui/inc/DrawDocShell.hxx"
57 
58 // #90477#
59 #include <tools/tenccvt.hxx>
60 #include <svl/itemset.hxx>
61 
62 using namespace ::sd;
63 using namespace ::com::sun::star;
64 using namespace ::com::sun::star::uno;
65 using namespace ::com::sun::star::office;
66 
67 extern void NotifyDocumentEvent( SdDrawDocument* pDocument, const rtl::OUString& rEventName, const Reference< XInterface >& xSource );
68 
69 /*************************************************************************
70 |*
71 |* SetPresentationLayout, setzt: Layoutnamen, Masterpage-Verkn�pfung und
72 |* Vorlagen fuer Praesentationsobjekte
73 |*
74 |* Vorraussetzungen: - Die Seite muss bereits das richtige Model kennen!
75 |*                   - Die entsprechende Masterpage muss bereits im Model sein.
76 |*                   - Die entsprechenden StyleSheets muessen bereits im
77 |*                     im StyleSheetPool sein.
78 |*
79 |*  bReplaceStyleSheets = sal_True : Benannte StyleSheets werden ausgetauscht
80 |*                        sal_False: Alle StyleSheets werden neu zugewiesen
81 |*
82 |*  bSetMasterPage      = sal_True : MasterPage suchen und zuweisen
83 |*
84 |*  bReverseOrder       = sal_False: MasterPages von vorn nach hinten suchen
85 |*                        sal_True : MasterPages von hinten nach vorn suchen (fuer Undo-Action)
86 |*
87 \************************************************************************/
88 
89 void SdPage::SetPresentationLayout(const String& rLayoutName,
90                                    sal_Bool bReplaceStyleSheets,
91                                    sal_Bool bSetMasterPage,
92                                    sal_Bool bReverseOrder)
93 {
94     /*********************************************************************
95     |* Layoutname der Seite
96     \********************************************************************/
97     String aOldLayoutName(maLayoutName);    // merken
98     maLayoutName = rLayoutName;
99     maLayoutName.AppendAscii( RTL_CONSTASCII_STRINGPARAM( SD_LT_SEPARATOR ));
100     maLayoutName += String(SdResId(STR_LAYOUT_OUTLINE));
101 
102     /*********************************************************************
103     |* ggf. Masterpage suchen und setzen
104     \********************************************************************/
105     if (bSetMasterPage && !IsMasterPage())
106     {
107         SdPage* pMaster;
108         SdPage* pFoundMaster = 0;
109         sal_uInt16 nMaster = 0;
110         sal_uInt16 nMasterCount = pModel->GetMasterPageCount();
111 
112         if( !bReverseOrder )
113         {
114             for ( nMaster = 0; nMaster < nMasterCount; nMaster++ )
115             {
116                 pMaster = static_cast<SdPage*>(pModel->GetMasterPage(nMaster));
117                 if (pMaster->GetPageKind() == mePageKind && pMaster->GetLayoutName() == maLayoutName)
118                 {
119                     pFoundMaster = pMaster;
120                     break;
121                 }
122             }
123         }
124         else
125         {
126             for ( nMaster = nMasterCount; nMaster > 0; nMaster-- )
127             {
128                 pMaster = static_cast<SdPage*>(pModel->GetMasterPage(nMaster - 1));
129                 if (pMaster->GetPageKind() == mePageKind && pMaster->GetLayoutName() == maLayoutName)
130                 {
131                     pFoundMaster = pMaster;
132                     break;
133                 }
134             }
135         }
136 
137         DBG_ASSERT(pFoundMaster, "Masterpage for presentation layout not found!");
138 
139         // this should never happen, but we play failsafe here
140         if( pFoundMaster == 0 )
141             pFoundMaster = static_cast< SdDrawDocument *>(pModel)->GetSdPage( 0, mePageKind );
142 
143         if( pFoundMaster )
144             TRG_SetMasterPage(*pFoundMaster);
145     }
146 
147     /*********************************************************************
148     |* Vorlagen fuer Praesentationsobjekte
149     \********************************************************************/
150     // Listen mit:
151     // - Vorlagenzeigern fuer Gliederungstextobjekt (alte und neue Vorlagen)
152     // -Replacedaten fuer OutlinerParaObject
153     List aOutlineStyles;
154     List aOldOutlineStyles;
155     List aReplList;
156     sal_Bool bListsFilled = sal_False;
157 
158     sal_uLong nObjCount = GetObjCount();
159 
160     for (sal_uLong nObj = 0; nObj < nObjCount; nObj++)
161     {
162         SdrTextObj* pObj = (SdrTextObj*) GetObj(nObj);
163 
164         if (pObj->GetObjInventor() == SdrInventor &&
165             pObj->GetObjIdentifier() == OBJ_OUTLINETEXT)
166         {
167             if (!bListsFilled || !bReplaceStyleSheets)
168             {
169                 String aFullName;
170                 String aOldFullName;
171                 SfxStyleSheetBase* pSheet = NULL;
172                 SfxStyleSheetBasePool* pStShPool = pModel->GetStyleSheetPool();
173 
174                 for (sal_Int16 i = -1; i < 9; i++)
175                 {
176                     aFullName = maLayoutName;
177                     aOldFullName = aOldLayoutName;
178                     aFullName += sal_Unicode( ' ' );
179                     aFullName += String::CreateFromInt32( (sal_Int32) (i <= 0 ) ? 1 : i + 1);
180                     aOldFullName += sal_Unicode( ' ' );
181                     aOldFullName += String::CreateFromInt32( (sal_Int32) (i <= 0 ) ? 1 : i + 1 );
182 
183                     pSheet = pStShPool->Find(aOldFullName, SD_STYLE_FAMILY_MASTERPAGE);
184                     DBG_ASSERT(pSheet, "alte Gliederungsvorlage nicht gefunden");
185                     aOldOutlineStyles.Insert(pSheet, LIST_APPEND);
186 
187                     pSheet = pStShPool->Find(aFullName, SD_STYLE_FAMILY_MASTERPAGE);
188                     DBG_ASSERT(pSheet, "neue Gliederungsvorlage nicht gefunden");
189                     aOutlineStyles.Insert(pSheet, LIST_APPEND);
190 
191                     if (bReplaceStyleSheets && pSheet)
192                     {
193                         // Replace anstatt Set
194                         StyleReplaceData* pReplData = new StyleReplaceData;
195                         pReplData->nNewFamily = pSheet->GetFamily();
196                         pReplData->nFamily    = pSheet->GetFamily();
197                         pReplData->aNewName   = aFullName;
198                         pReplData->aName      = aOldFullName;
199                         aReplList.Insert(pReplData, LIST_APPEND);
200                     }
201                     else
202                     {
203                         OutlinerParaObject* pOPO = ((SdrTextObj*)pObj)->GetOutlinerParaObject();
204 
205                         if( pOPO )
206                             pOPO->SetStyleSheets( i,  aFullName, SD_STYLE_FAMILY_MASTERPAGE );
207                     }
208                 }
209 
210                 bListsFilled = sal_True;
211             }
212 
213             SfxStyleSheet* pSheet = (SfxStyleSheet*)aOutlineStyles.First();
214             SfxStyleSheet* pOldSheet = (SfxStyleSheet*)aOldOutlineStyles.First();
215             while (pSheet)
216             {
217                 if (pSheet != pOldSheet)
218                 {
219                     pObj->EndListening(*pOldSheet);
220 
221                     if (!pObj->IsListening(*pSheet))
222                         pObj->StartListening(*pSheet);
223                 }
224 
225                 pSheet = (SfxStyleSheet*)aOutlineStyles.Next();
226                 pOldSheet = (SfxStyleSheet*)aOldOutlineStyles.Next();
227             }
228 
229             OutlinerParaObject* pOPO = ((SdrTextObj*)pObj)->GetOutlinerParaObject();
230             if ( bReplaceStyleSheets && pOPO )
231             {
232                 StyleReplaceData* pReplData = (StyleReplaceData*) aReplList.First();
233 
234                 while( pReplData )
235                 {
236                     pOPO->ChangeStyleSheets( pReplData->aName, pReplData->nFamily, pReplData->aNewName, pReplData->nNewFamily );
237                     pReplData = (StyleReplaceData*) aReplList.Next();
238                 }
239             }
240         }
241         else if (pObj->GetObjInventor() == SdrInventor &&
242                  pObj->GetObjIdentifier() == OBJ_TITLETEXT)
243         {
244             // PresObjKind nicht ueber GetPresObjKind() holen, da dort nur
245             // die PresObjListe beruecksichtigt wird. Es sollen aber alle
246             // "Titelobjekte" hier beruecksichtigt werden (Paste aus Clipboard usw.)
247             SfxStyleSheet* pSheet = GetStyleSheetForPresObj(PRESOBJ_TITLE);
248 
249             if (pSheet)
250                 pObj->SetStyleSheet(pSheet, sal_True);
251         }
252         else
253         {
254             SfxStyleSheet* pSheet = GetStyleSheetForPresObj(GetPresObjKind(pObj));
255 
256             if (pSheet)
257                 pObj->SetStyleSheet(pSheet, sal_True);
258         }
259     }
260 
261     for (sal_uLong i = 0; i < aReplList.Count(); i++)
262     {
263         delete (StyleReplaceData*) aReplList.GetObject(i);
264     }
265 }
266 
267 
268 /*************************************************************************
269 |*
270 |* das Gliederungstextobjekt bei den Vorlagen fuer die Gliederungsebenen
271 |* abmelden
272 |*
273 \************************************************************************/
274 
275 void SdPage::EndListenOutlineText()
276 {
277     SdrObject* pOutlineTextObj = GetPresObj(PRESOBJ_OUTLINE);
278 
279     if (pOutlineTextObj)
280     {
281         SdStyleSheetPool* pSPool = (SdStyleSheetPool*)pModel->GetStyleSheetPool();
282         DBG_ASSERT(pSPool, "StyleSheetPool nicht gefunden");
283         String aTrueLayoutName(maLayoutName);
284         aTrueLayoutName.Erase( aTrueLayoutName.SearchAscii( SD_LT_SEPARATOR ));
285         List* pOutlineStyles = pSPool->CreateOutlineSheetList(aTrueLayoutName);
286         for (SfxStyleSheet* pSheet = (SfxStyleSheet*)pOutlineStyles->First();
287              pSheet;
288              pSheet = (SfxStyleSheet*)pOutlineStyles->Next())
289             {
290                 pOutlineTextObj->EndListening(*pSheet);
291             }
292 
293         delete pOutlineStyles;
294     }
295 }
296 
297 /*************************************************************************
298 |*
299 |* Neues Model setzen
300 |*
301 \************************************************************************/
302 
303 void SdPage::SetModel(SdrModel* pNewModel)
304 {
305     DisconnectLink();
306 
307     // Model umsetzen
308     FmFormPage::SetModel(pNewModel);
309 
310     ConnectLink();
311 }
312 
313 /*************************************************************************
314 |*
315 |* Ist die Seite read-only?
316 |*
317 \************************************************************************/
318 
319 FASTBOOL SdPage::IsReadOnly() const
320 {
321     return sal_False;
322 }
323 
324 /*************************************************************************
325 |*
326 |* Beim sfx2::LinkManager anmelden
327 |*
328 \************************************************************************/
329 
330 void SdPage::ConnectLink()
331 {
332     sfx2::LinkManager* pLinkManager = pModel!=NULL ? pModel->GetLinkManager() : NULL;
333 
334     if (pLinkManager && !mpPageLink && maFileName.Len() && maBookmarkName.Len() &&
335         mePageKind==PK_STANDARD && !IsMasterPage() &&
336         ( (SdDrawDocument*) pModel)->IsNewOrLoadCompleted())
337     {
338         /**********************************************************************
339         * Anmelden
340         * Nur Standardseiten duerfen gelinkt sein
341         **********************************************************************/
342         ::sd::DrawDocShell* pDocSh = ((SdDrawDocument*) pModel)->GetDocSh();
343 
344         if (!pDocSh || pDocSh->GetMedium()->GetOrigURL() != maFileName)
345         {
346             // Keine Links auf Dokument-eigene Seiten!
347             mpPageLink = new SdPageLink(this, maFileName, maBookmarkName);
348             String aFilterName(SdResId(STR_IMPRESS));
349             pLinkManager->InsertFileLink(*mpPageLink, OBJECT_CLIENT_FILE,
350                                          maFileName, &aFilterName, &maBookmarkName);
351             mpPageLink->Connect();
352         }
353     }
354 }
355 
356 
357 /*************************************************************************
358 |*
359 |* Beim sfx2::LinkManager abmelden
360 |*
361 \************************************************************************/
362 
363 void SdPage::DisconnectLink()
364 {
365     sfx2::LinkManager* pLinkManager = pModel!=NULL ? pModel->GetLinkManager() : NULL;
366 
367     if (pLinkManager && mpPageLink)
368     {
369         /**********************************************************************
370         * Abmelden
371         * (Bei Remove wird *pGraphicLink implizit deleted)
372         **********************************************************************/
373         pLinkManager->Remove(mpPageLink);
374         mpPageLink=NULL;
375     }
376 }
377 
378 /*************************************************************************
379 |*
380 |* Copy-Ctor
381 |*
382 \************************************************************************/
383 
384 SdPage::SdPage(const SdPage& rSrcPage)
385 :   FmFormPage(rSrcPage)
386 ,   SdrObjUserCall()
387 ,   mpItems(NULL)
388 {
389     mePageKind           = rSrcPage.mePageKind;
390     meAutoLayout         = rSrcPage.meAutoLayout;
391 
392     SdrObject* pObj = 0;
393     while((pObj = rSrcPage.maPresentationShapeList.getNextShape(pObj)) != 0)
394         InsertPresObj(GetObj(pObj->GetOrdNum()), rSrcPage.GetPresObjKind(pObj));
395 
396     mbSelected           = sal_False;
397     mnTransitionType    = rSrcPage.mnTransitionType;
398     mnTransitionSubtype = rSrcPage.mnTransitionSubtype;
399     mbTransitionDirection = rSrcPage.mbTransitionDirection;
400     mnTransitionFadeColor = rSrcPage.mnTransitionFadeColor;
401     mfTransitionDuration = rSrcPage.mfTransitionDuration;
402     mePresChange            = rSrcPage.mePresChange;
403     mnTime               = rSrcPage.mnTime;
404     mbSoundOn            = rSrcPage.mbSoundOn;
405     mbExcluded           = rSrcPage.mbExcluded;
406 
407     maLayoutName         = rSrcPage.maLayoutName;
408     maSoundFile          = rSrcPage.maSoundFile;
409     mbLoopSound          = rSrcPage.mbLoopSound;
410     mbStopSound          = rSrcPage.mbStopSound;
411     maCreatedPageName    = String();
412     maFileName           = rSrcPage.maFileName;
413     maBookmarkName       = rSrcPage.maBookmarkName;
414     mbScaleObjects       = rSrcPage.mbScaleObjects;
415     mbBackgroundFullSize = rSrcPage.mbBackgroundFullSize;
416     meCharSet            = rSrcPage.meCharSet;
417     mnPaperBin           = rSrcPage.mnPaperBin;
418     meOrientation        = rSrcPage.meOrientation;
419 
420     // header footer
421     setHeaderFooterSettings( rSrcPage.getHeaderFooterSettings() );
422 
423     mpPageLink           = NULL;    // Wird beim Einfuegen ueber ConnectLink() gesetzt
424 }
425 
426 
427 
428 /*************************************************************************
429 |*
430 |* Clone
431 |*
432 \************************************************************************/
433 
434 SdrPage* SdPage::Clone() const
435 {
436     return Clone(NULL);
437 }
438 
439 SdrPage* SdPage::Clone(SdrModel* pNewModel) const
440 {
441     DBG_ASSERT( pNewModel == 0, "sd::SdPage::Clone(), new page ignored, please check code! CL" );
442     (void)pNewModel;
443 
444     SdPage* pNewPage = new SdPage(*this);
445 
446     cloneAnimations( *pNewPage );
447 
448     // fix user calls for duplicated slide
449     SdrObjListIter aSourceIter( *this, IM_DEEPWITHGROUPS );
450     SdrObjListIter aTargetIter( *pNewPage, IM_DEEPWITHGROUPS );
451 
452     while( aSourceIter.IsMore() && aTargetIter.IsMore() )
453     {
454         SdrObject* pSource = aSourceIter.Next();
455         SdrObject* pTarget = aTargetIter.Next();
456 
457         if( pSource->GetUserCall() )
458             pTarget->SetUserCall( pNewPage );
459     }
460 
461     return pNewPage;
462 }
463 
464 /*************************************************************************
465 |*
466 |* GetTextStyleSheetForObject
467 |*
468 \************************************************************************/
469 
470 
471 SfxStyleSheet* SdPage::GetTextStyleSheetForObject( SdrObject* pObj ) const
472 {
473     const PresObjKind eKind = ((SdPage*)this)->GetPresObjKind(pObj);
474     if( eKind != PRESOBJ_NONE )
475     {
476         return ((SdPage*)this)->GetStyleSheetForPresObj(eKind);
477     }
478 
479     return FmFormPage::GetTextStyleSheetForObject( pObj );
480 }
481 
482 SfxItemSet* SdPage::getOrCreateItems()
483 {
484     if( mpItems == NULL )
485         mpItems = new SfxItemSet( pModel->GetItemPool(), SDRATTR_XMLATTRIBUTES, SDRATTR_XMLATTRIBUTES );
486 
487     return mpItems;
488 }
489 
490 
491 sal_Bool SdPage::setAlienAttributes( const com::sun::star::uno::Any& rAttributes )
492 {
493     SfxItemSet* pSet = getOrCreateItems();
494 
495     SvXMLAttrContainerItem aAlienAttributes( SDRATTR_XMLATTRIBUTES );
496     if( aAlienAttributes.PutValue( rAttributes, 0 ) )
497     {
498         pSet->Put( aAlienAttributes );
499         return sal_True;
500     }
501 
502     return sal_False;
503 }
504 
505 void SdPage::getAlienAttributes( com::sun::star::uno::Any& rAttributes )
506 {
507     const SfxPoolItem* pItem;
508 
509     if( (mpItems == NULL) || ( SFX_ITEM_SET != mpItems->GetItemState( SDRATTR_XMLATTRIBUTES, sal_False, &pItem ) ) )
510     {
511         SvXMLAttrContainerItem aAlienAttributes;
512         aAlienAttributes.QueryValue( rAttributes, 0 );
513     }
514     else
515     {
516         ((SvXMLAttrContainerItem*)pItem)->QueryValue( rAttributes, 0 );
517     }
518 }
519 
520 void SdPage::RemoveEmptyPresentationObjects()
521 {
522     SdrObjListIter  aShapeIter( *this, IM_DEEPWITHGROUPS );
523 
524     SdrObject* pShape;
525     for( pShape = aShapeIter.Next(); pShape; pShape = aShapeIter.Next() )
526     {
527         if( pShape && pShape->IsEmptyPresObj() )
528         {
529             RemoveObject( pShape->GetOrdNum() );
530             SdrObject::Free( pShape );
531         }
532 
533     }
534 }
535 
536 sal_Int16 SdPage::getTransitionType (void) const
537 {
538     return mnTransitionType;
539 }
540 
541 void SdPage::setTransitionType( sal_Int16 nTransitionType )
542 {
543     mnTransitionType = nTransitionType;
544     ActionChanged();
545 }
546 
547 sal_Int16 SdPage::getTransitionSubtype (void) const
548 {
549     return mnTransitionSubtype;
550 }
551 
552 void SdPage::setTransitionSubtype ( sal_Int16 nTransitionSubtype )
553 {
554     mnTransitionSubtype = nTransitionSubtype;
555     ActionChanged();
556 }
557 
558 sal_Bool SdPage::getTransitionDirection (void) const
559 {
560     return mbTransitionDirection;
561 }
562 
563 void SdPage::setTransitionDirection ( sal_Bool bTransitionbDirection )
564 {
565     mbTransitionDirection = bTransitionbDirection;
566     ActionChanged();
567 }
568 
569 sal_Int32 SdPage::getTransitionFadeColor (void) const
570 {
571     return mnTransitionFadeColor;
572 }
573 
574 void SdPage::setTransitionFadeColor ( sal_Int32 nTransitionFadeColor )
575 {
576     mnTransitionFadeColor = nTransitionFadeColor;
577     ActionChanged();
578 }
579 
580 double SdPage::getTransitionDuration (void) const
581 {
582     return mfTransitionDuration;
583 }
584 
585 void SdPage::setTransitionDuration ( double fTranstionDuration )
586 {
587     mfTransitionDuration = fTranstionDuration;
588     ActionChanged();
589 }
590 
591 namespace sd {
592 extern void createAnnotation( Reference< XAnnotation >& xAnnotation, SdPage* pPage );
593 extern SdrUndoAction* CreateUndoInsertOrRemoveAnnotation( const Reference< XAnnotation >& xAnnotation, bool bInsert );
594 }
595 
596 void SdPage::createAnnotation( ::com::sun::star::uno::Reference< ::com::sun::star::office::XAnnotation >& xAnnotation )
597 {
598     sd::createAnnotation( xAnnotation, this );
599 }
600 
601 void SdPage::addAnnotation( const Reference< XAnnotation >& xAnnotation, int nIndex )
602 {
603     if( (nIndex == -1) || (nIndex > (int)maAnnotations.size()) )
604     {
605         maAnnotations.push_back( xAnnotation );
606     }
607     else
608     {
609         maAnnotations.insert( maAnnotations.begin() + nIndex, xAnnotation );
610     }
611 
612     if( pModel && pModel->IsUndoEnabled() )
613     {
614         SdrUndoAction* pAction = CreateUndoInsertOrRemoveAnnotation( xAnnotation, true );
615         if( pAction )
616             pModel->AddUndo( pAction );
617     }
618 
619     SetChanged();
620 
621     if( pModel )
622     {
623         pModel->SetChanged();
624         Reference< XInterface > xSource( xAnnotation, UNO_QUERY );
625         NotifyDocumentEvent( static_cast< SdDrawDocument* >( pModel ), rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OnAnnotationInserted" ) ), xSource );
626     }
627 }
628 
629 void SdPage::removeAnnotation( const Reference< XAnnotation >& xAnnotation )
630 {
631     if( pModel && pModel->IsUndoEnabled() )
632     {
633         SdrUndoAction* pAction = CreateUndoInsertOrRemoveAnnotation( xAnnotation, false );
634         if( pAction )
635             pModel->AddUndo( pAction );
636     }
637 
638     AnnotationVector::iterator iter = std::find( maAnnotations.begin(), maAnnotations.end(), xAnnotation );
639     if( iter != maAnnotations.end() )
640         maAnnotations.erase( iter );
641 
642     if( pModel )
643     {
644         pModel->SetChanged();
645         Reference< XInterface > xSource( xAnnotation, UNO_QUERY );
646         NotifyDocumentEvent( static_cast< SdDrawDocument* >( pModel ), rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OnAnnotationRemoved" ) ), xSource );
647     }
648 }
649