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 
31 #include "OutlinerIterator.hxx"
32 #include "OutlinerIteratorImpl.hxx"
33 #include <svx/svditer.hxx>
34 #include <sfx2/dispatch.hxx>
35 #include <sfx2/viewfrm.hxx>
36 #include "Outliner.hxx"
37 
38 #include "drawdoc.hxx"
39 #include "DrawViewShell.hxx"
40 #include "drawview.hxx"
41 #include "sdpage.hxx"
42 #ifndef SD_FRAME_VIEW
43 #include "FrameView.hxx"
44 #endif
45 #include "DrawDocShell.hxx"
46 #include "Window.hxx"
47 
48 namespace sd { namespace outliner {
49 
50 
51 //===== IteratorPosition ======================================================
52 
53 IteratorPosition::IteratorPosition (void)
54 : mnText(0)
55 , mnPageIndex(-1)
56 , mePageKind(PK_STANDARD)
57 , meEditMode(EM_PAGE)
58 {
59 }
60 
61 IteratorPosition::IteratorPosition (const IteratorPosition& aPosition)
62 : mxObject(aPosition.mxObject)
63 , mnText(aPosition.mnText)
64 , mnPageIndex(aPosition.mnPageIndex)
65 , mePageKind(aPosition.mePageKind)
66 , meEditMode(aPosition.meEditMode)
67 {
68 }
69 
70 IteratorPosition::~IteratorPosition (void)
71 {
72 }
73 
74 IteratorPosition& IteratorPosition::operator= (const IteratorPosition& aPosition)
75 {
76     mxObject = aPosition.mxObject;
77 	mnText = aPosition.mnText;
78     mnPageIndex = aPosition.mnPageIndex;
79     mePageKind = aPosition.mePageKind;
80     meEditMode = aPosition.meEditMode;
81     return *this;
82 }
83 
84 bool IteratorPosition::operator== (const IteratorPosition& aPosition) const
85 {
86     return mxObject.get() == aPosition.mxObject.get()
87 		&& mnText == aPosition.mnText
88         && mnPageIndex == aPosition.mnPageIndex
89         && mePageKind == aPosition.mePageKind
90         && meEditMode == aPosition.meEditMode;
91 }
92 
93 
94 
95 
96 //===== Iterator ==============================================================
97 
98 Iterator::Iterator (void)
99 {
100     mpIterator = NULL;
101 }
102 
103 Iterator::Iterator (const Iterator& rIterator)
104 {
105     mpIterator = rIterator.mpIterator->Clone();
106 }
107 
108 Iterator::Iterator (IteratorImplBase* pObject)
109 {
110     mpIterator = pObject;
111 }
112 
113 Iterator::~Iterator (void)
114 {
115     delete mpIterator;
116 }
117 
118 Iterator& Iterator::operator= (const Iterator& rIterator)
119 {
120     if (this != &rIterator)
121     {
122         delete mpIterator;
123         if (rIterator.mpIterator != NULL)
124             mpIterator = rIterator.mpIterator->Clone();
125         else
126             mpIterator = NULL;
127     }
128     return *this;
129 }
130 
131 const IteratorPosition& Iterator::operator* () const
132 {
133     DBG_ASSERT (mpIterator!=NULL, "::sd::outliner::Iterator::operator* : missing implementation object");
134     return mpIterator->GetPosition();
135 }
136 
137 Iterator& Iterator::operator++ ()
138 {
139     if (mpIterator!=NULL)
140         mpIterator->GotoNextText();
141     return *this;
142 }
143 
144 Iterator Iterator::operator++ (int)
145 {
146     Iterator aTmp (*this);
147     if (mpIterator!=NULL)
148         mpIterator->GotoNextText();
149     return aTmp;
150 }
151 
152 bool Iterator::operator== (const Iterator& rIterator)
153 {
154     if (mpIterator == NULL || rIterator.mpIterator==NULL)
155         return mpIterator == rIterator.mpIterator;
156     else
157         return *mpIterator == *rIterator.mpIterator;
158 }
159 
160 bool Iterator::operator!= (const Iterator& rIterator)
161 {
162     return ! operator==(rIterator);
163 }
164 
165 void Iterator::Reverse (void)
166 {
167     if (mpIterator != NULL)
168         mpIterator->Reverse();
169 }
170 
171 //===== IteratorFactory =======================================================
172 
173 OutlinerContainer::OutlinerContainer (Outliner* pOutliner)
174 : mpOutliner(pOutliner)
175 {
176 }
177 
178 Iterator OutlinerContainer::begin (void)
179 {
180     return CreateIterator (BEGIN);
181 }
182 
183 Iterator OutlinerContainer::end (void)
184 {
185     return CreateIterator (END);
186 }
187 
188 Iterator OutlinerContainer::current (void)
189 {
190     return CreateIterator (CURRENT);
191 }
192 
193 
194 Iterator OutlinerContainer::CreateIterator (IteratorLocation aLocation)
195 {
196     // Decide on certain features of the outliner which kind of iterator to
197     // use.
198     if (mpOutliner->mbRestrictSearchToSelection)
199         // There is a selection.  Search only in this.
200         return CreateSelectionIterator (
201             mpOutliner->maMarkListCopy,
202             mpOutliner->mpDrawDocument,
203             mpOutliner->mpWeakViewShell.lock(),
204             mpOutliner->mbDirectionIsForward,
205             aLocation);
206     else
207         // Search in the whole document.
208         return CreateDocumentIterator (
209             mpOutliner->mpDrawDocument,
210             mpOutliner->mpWeakViewShell.lock(),
211             mpOutliner->mbDirectionIsForward,
212             aLocation);
213 }
214 
215 Iterator OutlinerContainer::CreateSelectionIterator (
216     const ::std::vector<SdrObjectWeakRef>& rObjectList,
217     SdDrawDocument* pDocument,
218     const ::boost::shared_ptr<ViewShell>& rpViewShell,
219     bool bDirectionIsForward,
220     IteratorLocation aLocation)
221 {
222     OSL_ASSERT(rpViewShell.get());
223 
224     sal_Int32 nObjectIndex;
225 
226     if (bDirectionIsForward)
227         switch (aLocation)
228         {
229             case CURRENT:
230             case BEGIN:
231             default:
232                 nObjectIndex = 0;
233                 break;
234             case END:
235                 nObjectIndex = rObjectList.size();
236                 break;
237         }
238     else
239         switch (aLocation)
240         {
241             case CURRENT:
242             case BEGIN:
243             default:
244                 nObjectIndex = rObjectList.size()-1;
245                 break;
246             case END:
247                 nObjectIndex = -1;
248                 break;
249         }
250 
251     return Iterator (new SelectionIteratorImpl (
252         rObjectList, nObjectIndex, pDocument, rpViewShell, bDirectionIsForward));
253 }
254 
255 Iterator OutlinerContainer::CreateDocumentIterator (
256     SdDrawDocument* pDocument,
257     const ::boost::shared_ptr<ViewShell>& rpViewShell,
258     bool bDirectionIsForward,
259     IteratorLocation aLocation)
260 {
261     OSL_ASSERT(rpViewShell.get());
262 
263     PageKind ePageKind;
264     EditMode eEditMode;
265 
266     switch (aLocation)
267     {
268         case BEGIN:
269         default:
270             if (bDirectionIsForward)
271             {
272                 ePageKind = PK_STANDARD;
273                 eEditMode = EM_PAGE;
274             }
275             else
276             {
277                 ePageKind = PK_HANDOUT;
278                 eEditMode = EM_MASTERPAGE;
279             }
280             break;
281 
282         case END:
283             if (bDirectionIsForward)
284             {
285                 ePageKind = PK_HANDOUT;
286                 eEditMode = EM_MASTERPAGE;
287             }
288             else
289             {
290                 ePageKind = PK_STANDARD;
291                 eEditMode = EM_PAGE;
292             }
293             break;
294 
295         case CURRENT:
296             const ::boost::shared_ptr<DrawViewShell> pDrawViewShell(
297                 ::boost::dynamic_pointer_cast<DrawViewShell>(rpViewShell));
298             if (pDrawViewShell.get())
299             {
300                 ePageKind = pDrawViewShell->GetPageKind();
301                 eEditMode = pDrawViewShell->GetEditMode();
302             }
303             else
304             {
305                 ePageKind = PK_STANDARD;
306                 eEditMode = EM_PAGE;
307             }
308             break;
309     }
310 
311     sal_Int32 nPageIndex = GetPageIndex (pDocument, rpViewShell,
312         ePageKind, eEditMode, bDirectionIsForward, aLocation);
313 
314     return Iterator (
315         new DocumentIteratorImpl (nPageIndex, ePageKind, eEditMode,
316             pDocument, rpViewShell, bDirectionIsForward));
317 }
318 
319 sal_Int32 OutlinerContainer::GetPageIndex (
320     SdDrawDocument* pDocument,
321     const ::boost::shared_ptr<ViewShell>& rpViewShell,
322     PageKind ePageKind,
323     EditMode eEditMode,
324     bool bDirectionIsForward,
325     IteratorLocation aLocation)
326 {
327     OSL_ASSERT(rpViewShell);
328 
329     sal_Int32 nPageIndex;
330     sal_Int32 nPageCount;
331 
332     const ::boost::shared_ptr<DrawViewShell> pDrawViewShell(
333         ::boost::dynamic_pointer_cast<DrawViewShell>(rpViewShell));
334 
335     switch (eEditMode)
336     {
337         case EM_PAGE:
338             nPageCount = pDocument->GetSdPageCount (ePageKind);
339             break;
340         case EM_MASTERPAGE:
341             nPageCount = pDocument->GetMasterSdPageCount(ePageKind);
342             break;
343         default:
344             nPageCount = 0;
345     }
346 
347     switch (aLocation)
348     {
349         case CURRENT:
350             if (pDrawViewShell.get())
351                 nPageIndex = pDrawViewShell->GetCurPageId() - 1;
352             else
353             {
354                 const SdPage* pPage = rpViewShell->GetActualPage();
355                 if (pPage != NULL)
356                     nPageIndex = (pPage->GetPageNum()-1)/2;
357                 else
358                     nPageIndex = 0;
359             }
360             break;
361 
362         case BEGIN:
363         default:
364             if (bDirectionIsForward)
365                 nPageIndex = 0;
366             else
367                 nPageIndex = nPageCount-1;
368             break;
369 
370         case END:
371             if (bDirectionIsForward)
372                 nPageIndex = nPageCount;
373             else
374                 nPageIndex = -1;
375             break;
376     }
377 
378     return nPageIndex;
379 }
380 
381 
382 
383 
384 //===== IteratorImplBase ====================================================
385 
386 IteratorImplBase::IteratorImplBase(SdDrawDocument* pDocument,
387     const ::boost::weak_ptr<ViewShell>& rpViewShellWeak,
388     bool bDirectionIsForward)
389 :	maPosition()
390 ,	mpDocument (pDocument)
391 ,	mpViewShellWeak (rpViewShellWeak)
392 ,	mbDirectionIsForward (bDirectionIsForward)
393 {
394     ::boost::shared_ptr<DrawViewShell> pDrawViewShell;
395     if ( ! mpViewShellWeak.expired())
396         pDrawViewShell = ::boost::dynamic_pointer_cast<DrawViewShell>(rpViewShellWeak.lock());
397 
398     if (pDrawViewShell.get())
399     {
400         maPosition.mePageKind = pDrawViewShell->GetPageKind();
401         maPosition.meEditMode = pDrawViewShell->GetEditMode();
402     }
403     else
404     {
405         maPosition.mePageKind = PK_STANDARD;
406         maPosition.meEditMode = EM_PAGE;
407     }
408 }
409 
410 IteratorImplBase::IteratorImplBase( SdDrawDocument* pDocument,
411     const ::boost::weak_ptr<ViewShell>& rpViewShellWeak,
412     bool bDirectionIsForward, PageKind ePageKind, EditMode eEditMode)
413 : maPosition()
414 , mpDocument (pDocument)
415 , mpViewShellWeak (rpViewShellWeak)
416 , mbDirectionIsForward (bDirectionIsForward)
417 {
418     maPosition.mePageKind = ePageKind;
419     maPosition.meEditMode = eEditMode;
420 }
421 
422 IteratorImplBase::~IteratorImplBase (void)
423 {}
424 
425 bool IteratorImplBase::operator== (const IteratorImplBase& rIterator) const
426 {
427     return maPosition == rIterator.maPosition;
428 }
429 
430 bool IteratorImplBase::IsEqual (const IteratorImplBase& rIterator, IteratorType ) const
431 {
432     // When this method is executed instead of the ones from derived classes
433     // then the argument is of another type then the object itself.  In this
434     // just compare the position objects.
435     return maPosition == rIterator.maPosition;
436 }
437 
438 const IteratorPosition& IteratorImplBase::GetPosition (void)
439 {
440     return maPosition;
441 }
442 
443 
444 
445 
446 IteratorImplBase* IteratorImplBase::Clone (IteratorImplBase* pObject) const
447 {
448     if (pObject != NULL)
449     {
450         pObject->maPosition = maPosition;
451         pObject->mpDocument = mpDocument;
452         pObject->mpViewShellWeak = mpViewShellWeak;
453         pObject->mbDirectionIsForward = mbDirectionIsForward;
454     }
455     return pObject;
456 }
457 
458 
459 
460 void IteratorImplBase::Reverse (void)
461 {
462     mbDirectionIsForward = ! mbDirectionIsForward;
463 }
464 
465 
466 
467 //===== SelectionIteratorImpl ===========================================
468 
469 SelectionIteratorImpl::SelectionIteratorImpl (
470     const ::std::vector<SdrObjectWeakRef>& rObjectList,
471     sal_Int32 nObjectIndex,
472     SdDrawDocument* pDocument,
473     const ::boost::weak_ptr<ViewShell>& rpViewShellWeak,
474     bool bDirectionIsForward)
475     : IteratorImplBase (pDocument, rpViewShellWeak, bDirectionIsForward),
476       mrObjectList(rObjectList),
477       mnObjectIndex(nObjectIndex)
478 {
479 }
480 
481 SelectionIteratorImpl::~SelectionIteratorImpl (void)
482 {}
483 
484 IteratorImplBase* SelectionIteratorImpl::Clone (IteratorImplBase* pObject) const
485 {
486     SelectionIteratorImpl* pIterator = static_cast<SelectionIteratorImpl*>(pObject);
487     if (pIterator == NULL)
488         pIterator = new SelectionIteratorImpl (
489             mrObjectList, mnObjectIndex, mpDocument, mpViewShellWeak, mbDirectionIsForward);
490     return pIterator;
491 }
492 
493 
494 void SelectionIteratorImpl::GotoNextText (void)
495 {
496 	SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mrObjectList.at(mnObjectIndex).get() );
497     if (mbDirectionIsForward)
498 	{
499 		if( pTextObj )
500 		{
501 			++maPosition.mnText;
502 			if( maPosition.mnText >= pTextObj->getTextCount() )
503 			{
504 				maPosition.mnText = 0;
505 		        ++mnObjectIndex;
506 			}
507 		}
508 		else
509 		{
510 			++mnObjectIndex;
511 		}
512 	}
513     else
514 	{
515 		if( pTextObj )
516 		{
517 			--maPosition.mnText;
518 			if( maPosition.mnText < 0 )
519 			{
520 				maPosition.mnText = -1;
521 		        --mnObjectIndex;
522 			}
523 		}
524 		else
525 		{
526 			--mnObjectIndex;
527 			maPosition.mnText = -1;
528 		}
529 
530 		if( (maPosition.mnText == -1) && (mnObjectIndex >= 0) )
531 		{
532 			pTextObj = dynamic_cast< SdrTextObj* >( mrObjectList.at(mnObjectIndex).get() );
533 			if( pTextObj )
534 				maPosition.mnText = pTextObj->getTextCount() - 1;
535 		}
536 
537 		if( maPosition.mnText == -1 )
538 			maPosition.mnText = 0;
539 	}
540 }
541 
542 
543 const IteratorPosition& SelectionIteratorImpl::GetPosition (void)
544 {
545     maPosition.mxObject = mrObjectList.at(mnObjectIndex);
546 
547     return maPosition;
548 }
549 
550 
551 bool SelectionIteratorImpl::operator== (const IteratorImplBase& rIterator) const
552 {
553     return rIterator.IsEqual (*this, SELECTION);
554 }
555 
556 
557 bool SelectionIteratorImpl::IsEqual (
558     const IteratorImplBase& rIterator,
559     IteratorType aType) const
560 {
561     if (aType == SELECTION)
562     {
563         const SelectionIteratorImpl* pSelectionIterator =
564             static_cast<const SelectionIteratorImpl*>(&rIterator);
565         return mpDocument == pSelectionIterator->mpDocument
566             && mnObjectIndex == pSelectionIterator->mnObjectIndex;
567     }
568     else
569         return false;
570 }
571 
572 
573 
574 
575 //===== ViewIteratorImpl ================================================
576 
577 ViewIteratorImpl::ViewIteratorImpl (
578     sal_Int32 nPageIndex,
579     SdDrawDocument* pDocument,
580     const ::boost::weak_ptr<ViewShell>& rpViewShellWeak,
581     bool bDirectionIsForward)
582     : IteratorImplBase (pDocument, rpViewShellWeak, bDirectionIsForward),
583       mbPageChangeOccured(false),
584       mpPage(NULL),
585       mpObjectIterator(NULL)
586 {
587     SetPage (nPageIndex);
588 }
589 
590 
591 
592 
593 ViewIteratorImpl::ViewIteratorImpl (
594     sal_Int32 nPageIndex,
595     SdDrawDocument* pDocument,
596     const ::boost::weak_ptr<ViewShell>& rpViewShellWeak,
597     bool bDirectionIsForward,
598     PageKind ePageKind,
599     EditMode eEditMode)
600     : IteratorImplBase (pDocument, rpViewShellWeak, bDirectionIsForward, ePageKind, eEditMode),
601       mbPageChangeOccured(false),
602       mpPage(NULL),
603       mpObjectIterator(NULL)
604 {
605     SetPage (nPageIndex);
606 }
607 
608 
609 
610 
611 ViewIteratorImpl::~ViewIteratorImpl (void)
612 {
613 }
614 
615 
616 
617 
618 IteratorImplBase* ViewIteratorImpl::Clone (IteratorImplBase* pObject) const
619 {
620 
621     ViewIteratorImpl* pIterator = static_cast<ViewIteratorImpl*>(pObject);
622     if (pIterator == NULL)
623         pIterator = new ViewIteratorImpl (
624             maPosition.mnPageIndex, mpDocument, mpViewShellWeak, mbDirectionIsForward);
625 
626     IteratorImplBase::Clone (pObject);
627 
628     if (mpObjectIterator != NULL)
629     {
630         pIterator->mpObjectIterator = new SdrObjListIter(*mpPage, IM_DEEPNOGROUPS, !mbDirectionIsForward);
631 
632         // No direct way to set the object iterator to the current object.
633         pIterator->maPosition.mxObject.reset(NULL);
634         while (pIterator->mpObjectIterator->IsMore() && pIterator->maPosition.mxObject!=maPosition.mxObject)
635             pIterator->maPosition.mxObject.reset(pIterator->mpObjectIterator->Next());
636     }
637     else
638         pIterator->mpObjectIterator = NULL;
639 
640     return pIterator;
641 }
642 
643 
644 
645 void ViewIteratorImpl::GotoNextText(void)
646 {
647 	SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( maPosition.mxObject.get() );
648 	if( pTextObj )
649 	{
650 	    if (mbDirectionIsForward)
651 		{
652 			++maPosition.mnText;
653 			if( maPosition.mnText < pTextObj->getTextCount() )
654 				return;
655 		}
656 		else
657 		{
658 			--maPosition.mnText;
659 			if( maPosition.mnText >= 0 )
660 				return;
661 		}
662 	}
663 
664     if (mpObjectIterator != NULL && mpObjectIterator->IsMore())
665         maPosition.mxObject.reset(mpObjectIterator->Next());
666     else
667         maPosition.mxObject.reset(NULL);
668 
669     if (!maPosition.mxObject.is() )
670     {
671         if (mbDirectionIsForward)
672             SetPage (maPosition.mnPageIndex+1);
673         else
674             SetPage (maPosition.mnPageIndex-1);
675 
676         if (mpPage != NULL)
677             mpObjectIterator = new SdrObjListIter(*mpPage, IM_DEEPNOGROUPS, !mbDirectionIsForward);
678         if (mpObjectIterator!=NULL && mpObjectIterator->IsMore())
679             maPosition.mxObject.reset(mpObjectIterator->Next());
680         else
681             maPosition.mxObject.reset(NULL);
682     }
683 
684 	maPosition.mnText = 0;
685 	if( !mbDirectionIsForward && maPosition.mxObject.is() )
686 	{
687 		pTextObj = dynamic_cast< SdrTextObj* >( maPosition.mxObject.get() );
688 		if( pTextObj )
689 			maPosition.mnText = pTextObj->getTextCount() - 1;
690 	}
691 }
692 
693 
694 
695 
696 void ViewIteratorImpl::SetPage (sal_Int32 nPageIndex)
697 {
698     mbPageChangeOccured = (maPosition.mnPageIndex!=nPageIndex);
699     if (mbPageChangeOccured)
700     {
701         maPosition.mnPageIndex = nPageIndex;
702 
703         sal_Int32 nPageCount;
704         if (maPosition.meEditMode == EM_PAGE)
705             nPageCount = mpDocument->GetSdPageCount(maPosition.mePageKind);
706         else
707             nPageCount = mpDocument->GetMasterSdPageCount(
708                 maPosition.mePageKind);
709 
710         // Get page pointer.  Here we have three cases: regular pages,
711         // master pages and invalid page indices.  The later ones are not
712         // errors but the effect of the iterator advancing to the next page
713         // and going past the last one.  This dropping of the rim at the far
714         // side is detected here and has to be reacted to by the caller.
715         if (nPageIndex>=0 && nPageIndex < nPageCount)
716         {
717             if (maPosition.meEditMode == EM_PAGE)
718                 mpPage = mpDocument->GetSdPage (
719                     (sal_uInt16)nPageIndex,
720                     maPosition.mePageKind);
721             else
722                 mpPage = mpDocument->GetMasterSdPage (
723                     (sal_uInt16)nPageIndex,
724                     maPosition.mePageKind);
725         }
726         else
727             mpPage = NULL;
728     }
729 
730     // Set up object list iterator.
731     if (mpPage != NULL)
732         mpObjectIterator = new SdrObjListIter(*mpPage, IM_DEEPNOGROUPS, ! mbDirectionIsForward);
733     else
734         mpObjectIterator = NULL;
735 
736     // Get object pointer.
737     if (mpObjectIterator!=NULL && mpObjectIterator->IsMore())
738         maPosition.mxObject.reset( mpObjectIterator->Next() );
739     else
740         maPosition.mxObject.reset( NULL );
741 
742 	maPosition.mnText = 0;
743 	if( !mbDirectionIsForward && maPosition.mxObject.is() )
744 	{
745 		SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( maPosition.mxObject.get() );
746 		if( pTextObj )
747 			maPosition.mnText = pTextObj->getTextCount() - 1;
748 	}
749 
750 }
751 
752 
753 
754 
755 void ViewIteratorImpl::Reverse (void)
756 {
757     IteratorImplBase::Reverse ();
758 
759     // Create reversed object list iterator.
760     if (mpObjectIterator != NULL)
761         delete mpObjectIterator;
762     if (mpPage != NULL)
763         mpObjectIterator = new SdrObjListIter(*mpPage, IM_DEEPNOGROUPS, ! mbDirectionIsForward);
764     else
765         mpObjectIterator = NULL;
766 
767     // Move iterator to the current object.
768     SdrObjectWeakRef xObject = maPosition.mxObject;
769     maPosition.mxObject.reset(NULL);
770     while (mpObjectIterator->IsMore() && maPosition.mxObject != xObject)
771         maPosition.mxObject.reset(mpObjectIterator->Next());
772 }
773 
774 
775 
776 
777 //===== DocumentIteratorImpl ============================================
778 
779 DocumentIteratorImpl::DocumentIteratorImpl (
780     sal_Int32 nPageIndex,
781     PageKind ePageKind, EditMode eEditMode,
782     SdDrawDocument* pDocument,
783     const ::boost::weak_ptr<ViewShell>& rpViewShellWeak,
784     bool bDirectionIsForward)
785     : ViewIteratorImpl (nPageIndex, pDocument, rpViewShellWeak, bDirectionIsForward,
786         ePageKind, eEditMode)
787 {
788     if (eEditMode == EM_PAGE)
789         mnPageCount = pDocument->GetSdPageCount (ePageKind);
790     else
791         mnPageCount = pDocument->GetMasterSdPageCount(ePageKind);
792 }
793 
794 
795 
796 
797 DocumentIteratorImpl::~DocumentIteratorImpl (void)
798 {}
799 
800 
801 
802 
803 IteratorImplBase* DocumentIteratorImpl::Clone (IteratorImplBase* pObject) const
804 {
805     DocumentIteratorImpl* pIterator = static_cast<DocumentIteratorImpl*>(pObject);
806     if (pIterator == NULL)
807         pIterator = new DocumentIteratorImpl (
808             maPosition.mnPageIndex, maPosition.mePageKind, maPosition.meEditMode,
809             mpDocument, mpViewShellWeak, mbDirectionIsForward);
810     // Finish the cloning.
811     return ViewIteratorImpl::Clone (pIterator);
812 }
813 
814 
815 
816 
817 void DocumentIteratorImpl::GotoNextText (void)
818 {
819     bool bSetToOnePastLastPage = false;
820     bool bViewChanged = false;
821 
822     ViewIteratorImpl::GotoNextText();
823 
824     if (mbDirectionIsForward)
825     {
826         if (maPosition.mnPageIndex >= mnPageCount)
827         {
828             // Switch to master page.
829             if (maPosition.meEditMode == EM_PAGE)
830             {
831                 maPosition.meEditMode = EM_MASTERPAGE;
832                 SetPage (0);
833             }
834 
835             // Switch to next view mode.
836             else
837             {
838                 if (maPosition.mePageKind == PK_HANDOUT)
839                     // Not really necessary but makes things more clear.
840                     bSetToOnePastLastPage = true;
841                 else
842                 {
843                     maPosition.meEditMode = EM_PAGE;
844                     if (maPosition.mePageKind == PK_STANDARD)
845                         maPosition.mePageKind = PK_NOTES;
846                     else if (maPosition.mePageKind == PK_NOTES)
847                         maPosition.mePageKind = PK_HANDOUT;
848                     SetPage (0);
849                 }
850             }
851             bViewChanged = true;
852         }
853     }
854     else
855         if (maPosition.mnPageIndex < 0)
856         {
857             // Switch from master pages to draw pages.
858             if (maPosition.meEditMode == EM_MASTERPAGE)
859             {
860                 maPosition.meEditMode = EM_PAGE;
861                 bSetToOnePastLastPage = true;
862             }
863 
864             // Switch to previous view mode.
865             else
866             {
867                 if (maPosition.mePageKind == PK_STANDARD)
868                     SetPage (-1);
869                 else
870                 {
871                     maPosition.meEditMode = EM_MASTERPAGE;
872                     if (maPosition.mePageKind == PK_HANDOUT)
873                         maPosition.mePageKind = PK_NOTES;
874                     else if (maPosition.mePageKind == PK_NOTES)
875                         maPosition.mePageKind = PK_STANDARD;
876                     bSetToOnePastLastPage = true;
877                 }
878             }
879             bViewChanged = true;
880         }
881 
882     if (bViewChanged)
883     {
884         // Get new page count;
885         sal_Int32 nPageCount;
886         if (maPosition.meEditMode == EM_PAGE)
887             nPageCount = mpDocument->GetSdPageCount (maPosition.mePageKind);
888         else
889             nPageCount = mpDocument->GetMasterSdPageCount(maPosition.mePageKind);
890 
891         // Now that we know the number of pages we can set the current page index.
892         if (bSetToOnePastLastPage)
893             SetPage (nPageCount);
894     }
895 }
896 
897 
898 } } // end of namespace ::sd::outliner
899