1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "OutlinerIterator.hxx"
21 #include "OutlinerIteratorImpl.hxx"
22 #include <svx/svditer.hxx>
23 #include <sfx2/dispatch.hxx>
24 #include <sfx2/viewfrm.hxx>
25 #include "Outliner.hxx"
27 #include "drawdoc.hxx"
28 #include "DrawViewShell.hxx"
29 #include "drawview.hxx"
31 #include "FrameView.hxx"
32 #include "DrawDocShell.hxx"
35 namespace sd
{ namespace outliner
{
37 //===== IteratorPosition ======================================================
39 IteratorPosition::IteratorPosition()
42 , mePageKind(PK_STANDARD
)
47 IteratorPosition::IteratorPosition (const IteratorPosition
& aPosition
)
48 : mxObject(aPosition
.mxObject
)
49 , mnText(aPosition
.mnText
)
50 , mnPageIndex(aPosition
.mnPageIndex
)
51 , mePageKind(aPosition
.mePageKind
)
52 , meEditMode(aPosition
.meEditMode
)
56 IteratorPosition::~IteratorPosition()
60 IteratorPosition
& IteratorPosition::operator= (const IteratorPosition
& aPosition
)
62 mxObject
= aPosition
.mxObject
;
63 mnText
= aPosition
.mnText
;
64 mnPageIndex
= aPosition
.mnPageIndex
;
65 mePageKind
= aPosition
.mePageKind
;
66 meEditMode
= aPosition
.meEditMode
;
70 bool IteratorPosition::operator== (const IteratorPosition
& aPosition
) const
72 return mxObject
.get() == aPosition
.mxObject
.get()
73 && mnText
== aPosition
.mnText
74 && mnPageIndex
== aPosition
.mnPageIndex
75 && mePageKind
== aPosition
.mePageKind
76 && meEditMode
== aPosition
.meEditMode
;
79 //===== Iterator ==============================================================
86 Iterator::Iterator (const Iterator
& rIterator
)
88 mpIterator
= rIterator
.mpIterator
? rIterator
.mpIterator
->Clone() : NULL
;
91 Iterator::Iterator (IteratorImplBase
* pObject
)
101 Iterator
& Iterator::operator= (const Iterator
& rIterator
)
103 if (this != &rIterator
)
106 if (rIterator
.mpIterator
!= NULL
)
107 mpIterator
= rIterator
.mpIterator
->Clone();
114 const IteratorPosition
& Iterator::operator* () const
116 DBG_ASSERT (mpIterator
!=NULL
, "::sd::outliner::Iterator::operator* : missing implementation object");
117 return mpIterator
->GetPosition();
120 Iterator
& Iterator::operator++ ()
122 if (mpIterator
!=NULL
)
123 mpIterator
->GotoNextText();
127 Iterator
Iterator::operator++ (int)
129 Iterator
aTmp (*this);
130 if (mpIterator
!=NULL
)
131 mpIterator
->GotoNextText();
135 bool Iterator::operator== (const Iterator
& rIterator
)
137 if (mpIterator
== NULL
|| rIterator
.mpIterator
==NULL
)
138 return mpIterator
== rIterator
.mpIterator
;
140 return *mpIterator
== *rIterator
.mpIterator
;
143 bool Iterator::operator!= (const Iterator
& rIterator
)
145 return ! operator==(rIterator
);
148 void Iterator::Reverse()
150 if (mpIterator
!= NULL
)
151 mpIterator
->Reverse();
154 //===== IteratorFactory =======================================================
156 OutlinerContainer::OutlinerContainer (Outliner
* pOutliner
)
157 : mpOutliner(pOutliner
)
161 Iterator
OutlinerContainer::begin()
163 return CreateIterator (BEGIN
);
166 Iterator
OutlinerContainer::end()
168 return CreateIterator (END
);
171 Iterator
OutlinerContainer::current()
173 return CreateIterator (CURRENT
);
176 Iterator
OutlinerContainer::CreateIterator (IteratorLocation aLocation
)
178 // Decide on certain features of the outliner which kind of iterator to
180 if (mpOutliner
->mbRestrictSearchToSelection
)
181 // There is a selection. Search only in this.
182 return CreateSelectionIterator (
183 mpOutliner
->maMarkListCopy
,
184 mpOutliner
->mpDrawDocument
,
185 mpOutliner
->mpWeakViewShell
.lock(),
186 mpOutliner
->mbDirectionIsForward
,
189 // Search in the whole document.
190 return CreateDocumentIterator (
191 mpOutliner
->mpDrawDocument
,
192 mpOutliner
->mpWeakViewShell
.lock(),
193 mpOutliner
->mbDirectionIsForward
,
197 Iterator
OutlinerContainer::CreateSelectionIterator (
198 const ::std::vector
<SdrObjectWeakRef
>& rObjectList
,
199 SdDrawDocument
* pDocument
,
200 const ::boost::shared_ptr
<ViewShell
>& rpViewShell
,
201 bool bDirectionIsForward
,
202 IteratorLocation aLocation
)
204 OSL_ASSERT(rpViewShell
.get());
206 sal_Int32 nObjectIndex
;
208 if (bDirectionIsForward
)
217 nObjectIndex
= rObjectList
.size();
226 nObjectIndex
= rObjectList
.size()-1;
233 return Iterator (new SelectionIteratorImpl (
234 rObjectList
, nObjectIndex
, pDocument
, rpViewShell
, bDirectionIsForward
));
237 Iterator
OutlinerContainer::CreateDocumentIterator (
238 SdDrawDocument
* pDocument
,
239 const ::boost::shared_ptr
<ViewShell
>& rpViewShell
,
240 bool bDirectionIsForward
,
241 IteratorLocation aLocation
)
243 OSL_ASSERT(rpViewShell
.get());
252 if (bDirectionIsForward
)
254 ePageKind
= PK_STANDARD
;
259 ePageKind
= PK_HANDOUT
;
260 eEditMode
= EM_MASTERPAGE
;
265 if (bDirectionIsForward
)
267 ePageKind
= PK_HANDOUT
;
268 eEditMode
= EM_MASTERPAGE
;
272 ePageKind
= PK_STANDARD
;
278 const ::boost::shared_ptr
<DrawViewShell
> pDrawViewShell(
279 ::boost::dynamic_pointer_cast
<DrawViewShell
>(rpViewShell
));
280 if (pDrawViewShell
.get())
282 ePageKind
= pDrawViewShell
->GetPageKind();
283 eEditMode
= pDrawViewShell
->GetEditMode();
287 ePageKind
= PK_STANDARD
;
293 sal_Int32 nPageIndex
= GetPageIndex (pDocument
, rpViewShell
,
294 ePageKind
, eEditMode
, bDirectionIsForward
, aLocation
);
297 new DocumentIteratorImpl (nPageIndex
, ePageKind
, eEditMode
,
298 pDocument
, rpViewShell
, bDirectionIsForward
));
301 sal_Int32
OutlinerContainer::GetPageIndex (
302 SdDrawDocument
* pDocument
,
303 const ::boost::shared_ptr
<ViewShell
>& rpViewShell
,
306 bool bDirectionIsForward
,
307 IteratorLocation aLocation
)
309 OSL_ASSERT(rpViewShell
);
311 sal_Int32 nPageIndex
;
312 sal_Int32 nPageCount
;
314 const ::boost::shared_ptr
<DrawViewShell
> pDrawViewShell(
315 ::boost::dynamic_pointer_cast
<DrawViewShell
>(rpViewShell
));
320 nPageCount
= pDocument
->GetSdPageCount (ePageKind
);
323 nPageCount
= pDocument
->GetMasterSdPageCount(ePageKind
);
332 if (pDrawViewShell
.get())
333 nPageIndex
= pDrawViewShell
->GetCurPageId() - 1;
336 const SdPage
* pPage
= rpViewShell
->GetActualPage();
338 nPageIndex
= (pPage
->GetPageNum()-1)/2;
346 if (bDirectionIsForward
)
349 nPageIndex
= nPageCount
-1;
353 if (bDirectionIsForward
)
354 nPageIndex
= nPageCount
;
363 //===== IteratorImplBase ====================================================
365 IteratorImplBase::IteratorImplBase(SdDrawDocument
* pDocument
,
366 const ::boost::weak_ptr
<ViewShell
>& rpViewShellWeak
,
367 bool bDirectionIsForward
)
369 , mpDocument (pDocument
)
370 , mpViewShellWeak (rpViewShellWeak
)
371 , mbDirectionIsForward (bDirectionIsForward
)
373 ::boost::shared_ptr
<DrawViewShell
> pDrawViewShell
;
374 if ( ! mpViewShellWeak
.expired())
375 pDrawViewShell
= ::boost::dynamic_pointer_cast
<DrawViewShell
>(rpViewShellWeak
.lock());
377 if (pDrawViewShell
.get())
379 maPosition
.mePageKind
= pDrawViewShell
->GetPageKind();
380 maPosition
.meEditMode
= pDrawViewShell
->GetEditMode();
384 maPosition
.mePageKind
= PK_STANDARD
;
385 maPosition
.meEditMode
= EM_PAGE
;
389 IteratorImplBase::IteratorImplBase( SdDrawDocument
* pDocument
,
390 const ::boost::weak_ptr
<ViewShell
>& rpViewShellWeak
,
391 bool bDirectionIsForward
, PageKind ePageKind
, EditMode eEditMode
)
393 , mpDocument (pDocument
)
394 , mpViewShellWeak (rpViewShellWeak
)
395 , mbDirectionIsForward (bDirectionIsForward
)
397 maPosition
.mePageKind
= ePageKind
;
398 maPosition
.meEditMode
= eEditMode
;
401 IteratorImplBase::~IteratorImplBase()
404 bool IteratorImplBase::operator== (const IteratorImplBase
& rIterator
) const
406 return maPosition
== rIterator
.maPosition
;
409 bool IteratorImplBase::IsEqual (const IteratorImplBase
& rIterator
, IteratorType
) const
411 // When this method is executed instead of the ones from derived classes
412 // then the argument is of another type then the object itself. In this
413 // just compare the position objects.
414 return maPosition
== rIterator
.maPosition
;
417 const IteratorPosition
& IteratorImplBase::GetPosition()
422 IteratorImplBase
* IteratorImplBase::Clone (IteratorImplBase
* pObject
) const
426 pObject
->maPosition
= maPosition
;
427 pObject
->mpDocument
= mpDocument
;
428 pObject
->mpViewShellWeak
= mpViewShellWeak
;
429 pObject
->mbDirectionIsForward
= mbDirectionIsForward
;
434 void IteratorImplBase::Reverse()
436 mbDirectionIsForward
= ! mbDirectionIsForward
;
439 //===== SelectionIteratorImpl ===========================================
441 SelectionIteratorImpl::SelectionIteratorImpl (
442 const ::std::vector
<SdrObjectWeakRef
>& rObjectList
,
443 sal_Int32 nObjectIndex
,
444 SdDrawDocument
* pDocument
,
445 const ::boost::weak_ptr
<ViewShell
>& rpViewShellWeak
,
446 bool bDirectionIsForward
)
447 : IteratorImplBase (pDocument
, rpViewShellWeak
, bDirectionIsForward
),
448 mrObjectList(rObjectList
),
449 mnObjectIndex(nObjectIndex
)
453 SelectionIteratorImpl::~SelectionIteratorImpl()
456 IteratorImplBase
* SelectionIteratorImpl::Clone (IteratorImplBase
* pObject
) const
458 SelectionIteratorImpl
* pIterator
= static_cast<SelectionIteratorImpl
*>(pObject
);
459 if (pIterator
== NULL
)
460 pIterator
= new SelectionIteratorImpl (
461 mrObjectList
, mnObjectIndex
, mpDocument
, mpViewShellWeak
, mbDirectionIsForward
);
465 void SelectionIteratorImpl::GotoNextText()
467 SdrTextObj
* pTextObj
= dynamic_cast< SdrTextObj
* >( mrObjectList
.at(mnObjectIndex
).get() );
468 if (mbDirectionIsForward
)
473 if( maPosition
.mnText
>= pTextObj
->getTextCount() )
475 maPosition
.mnText
= 0;
489 if( maPosition
.mnText
< 0 )
491 maPosition
.mnText
= -1;
498 maPosition
.mnText
= -1;
501 if( (maPosition
.mnText
== -1) && (mnObjectIndex
>= 0) )
503 pTextObj
= dynamic_cast< SdrTextObj
* >( mrObjectList
.at(mnObjectIndex
).get() );
505 maPosition
.mnText
= pTextObj
->getTextCount() - 1;
508 if( maPosition
.mnText
== -1 )
509 maPosition
.mnText
= 0;
513 const IteratorPosition
& SelectionIteratorImpl::GetPosition()
515 maPosition
.mxObject
= mrObjectList
.at(mnObjectIndex
);
520 bool SelectionIteratorImpl::operator== (const IteratorImplBase
& rIterator
) const
522 return rIterator
.IsEqual (*this, SELECTION
);
525 bool SelectionIteratorImpl::IsEqual (
526 const IteratorImplBase
& rIterator
,
527 IteratorType aType
) const
529 if (aType
== SELECTION
)
531 const SelectionIteratorImpl
* pSelectionIterator
=
532 static_cast<const SelectionIteratorImpl
*>(&rIterator
);
533 return mpDocument
== pSelectionIterator
->mpDocument
534 && mnObjectIndex
== pSelectionIterator
->mnObjectIndex
;
540 //===== ViewIteratorImpl ================================================
542 ViewIteratorImpl::ViewIteratorImpl (
543 sal_Int32 nPageIndex
,
544 SdDrawDocument
* pDocument
,
545 const ::boost::weak_ptr
<ViewShell
>& rpViewShellWeak
,
546 bool bDirectionIsForward
)
547 : IteratorImplBase (pDocument
, rpViewShellWeak
, bDirectionIsForward
),
548 mbPageChangeOccurred(false),
550 mpObjectIterator(NULL
)
552 SetPage (nPageIndex
);
555 ViewIteratorImpl::ViewIteratorImpl (
556 sal_Int32 nPageIndex
,
557 SdDrawDocument
* pDocument
,
558 const ::boost::weak_ptr
<ViewShell
>& rpViewShellWeak
,
559 bool bDirectionIsForward
,
562 : IteratorImplBase (pDocument
, rpViewShellWeak
, bDirectionIsForward
, ePageKind
, eEditMode
),
563 mbPageChangeOccurred(false),
565 mpObjectIterator(NULL
)
567 SetPage (nPageIndex
);
570 ViewIteratorImpl::~ViewIteratorImpl()
574 IteratorImplBase
* ViewIteratorImpl::Clone (IteratorImplBase
* pObject
) const
577 ViewIteratorImpl
* pIterator
= static_cast<ViewIteratorImpl
*>(pObject
);
578 if (pIterator
== NULL
)
579 pIterator
= new ViewIteratorImpl (
580 maPosition
.mnPageIndex
, mpDocument
, mpViewShellWeak
, mbDirectionIsForward
);
582 IteratorImplBase::Clone (pObject
);
584 if (mpObjectIterator
!= NULL
)
586 pIterator
->mpObjectIterator
= new SdrObjListIter(*mpPage
, IM_DEEPNOGROUPS
, !mbDirectionIsForward
);
588 // No direct way to set the object iterator to the current object.
589 pIterator
->maPosition
.mxObject
.reset(NULL
);
590 while (pIterator
->mpObjectIterator
->IsMore() && pIterator
->maPosition
.mxObject
!=maPosition
.mxObject
)
591 pIterator
->maPosition
.mxObject
.reset(pIterator
->mpObjectIterator
->Next());
594 pIterator
->mpObjectIterator
= NULL
;
599 void ViewIteratorImpl::GotoNextText()
601 SdrTextObj
* pTextObj
= dynamic_cast< SdrTextObj
* >( maPosition
.mxObject
.get() );
604 if (mbDirectionIsForward
)
607 if( maPosition
.mnText
< pTextObj
->getTextCount() )
613 if( maPosition
.mnText
>= 0 )
618 if (mpObjectIterator
!= NULL
&& mpObjectIterator
->IsMore())
619 maPosition
.mxObject
.reset(mpObjectIterator
->Next());
621 maPosition
.mxObject
.reset(NULL
);
623 if (!maPosition
.mxObject
.is() )
625 if (mbDirectionIsForward
)
626 SetPage (maPosition
.mnPageIndex
+1);
628 SetPage (maPosition
.mnPageIndex
-1);
631 mpObjectIterator
= new SdrObjListIter(*mpPage
, IM_DEEPNOGROUPS
, !mbDirectionIsForward
);
632 if (mpObjectIterator
!=NULL
&& mpObjectIterator
->IsMore())
633 maPosition
.mxObject
.reset(mpObjectIterator
->Next());
635 maPosition
.mxObject
.reset(NULL
);
638 maPosition
.mnText
= 0;
639 if( !mbDirectionIsForward
&& maPosition
.mxObject
.is() )
641 pTextObj
= dynamic_cast< SdrTextObj
* >( maPosition
.mxObject
.get() );
643 maPosition
.mnText
= pTextObj
->getTextCount() - 1;
647 void ViewIteratorImpl::SetPage (sal_Int32 nPageIndex
)
649 mbPageChangeOccurred
= (maPosition
.mnPageIndex
!=nPageIndex
);
650 if (mbPageChangeOccurred
)
652 maPosition
.mnPageIndex
= nPageIndex
;
654 sal_Int32 nPageCount
;
655 if (maPosition
.meEditMode
== EM_PAGE
)
656 nPageCount
= mpDocument
->GetSdPageCount(maPosition
.mePageKind
);
658 nPageCount
= mpDocument
->GetMasterSdPageCount(
659 maPosition
.mePageKind
);
661 // Get page pointer. Here we have three cases: regular pages,
662 // master pages and invalid page indices. The later ones are not
663 // errors but the effect of the iterator advancing to the next page
664 // and going past the last one. This dropping of the rim at the far
665 // side is detected here and has to be reacted to by the caller.
666 if (nPageIndex
>=0 && nPageIndex
< nPageCount
)
668 if (maPosition
.meEditMode
== EM_PAGE
)
669 mpPage
= mpDocument
->GetSdPage (
670 (sal_uInt16
)nPageIndex
,
671 maPosition
.mePageKind
);
673 mpPage
= mpDocument
->GetMasterSdPage (
674 (sal_uInt16
)nPageIndex
,
675 maPosition
.mePageKind
);
681 // Set up object list iterator.
683 mpObjectIterator
= new SdrObjListIter(*mpPage
, IM_DEEPNOGROUPS
, ! mbDirectionIsForward
);
685 mpObjectIterator
= NULL
;
687 // Get object pointer.
688 if (mpObjectIterator
!=NULL
&& mpObjectIterator
->IsMore())
689 maPosition
.mxObject
.reset( mpObjectIterator
->Next() );
691 maPosition
.mxObject
.reset( NULL
);
693 maPosition
.mnText
= 0;
694 if( !mbDirectionIsForward
&& maPosition
.mxObject
.is() )
696 SdrTextObj
* pTextObj
= dynamic_cast< SdrTextObj
* >( maPosition
.mxObject
.get() );
698 maPosition
.mnText
= pTextObj
->getTextCount() - 1;
703 void ViewIteratorImpl::Reverse()
705 IteratorImplBase::Reverse ();
707 // Create reversed object list iterator.
708 if (mpObjectIterator
!= NULL
)
709 delete mpObjectIterator
;
711 mpObjectIterator
= new SdrObjListIter(*mpPage
, IM_DEEPNOGROUPS
, ! mbDirectionIsForward
);
713 mpObjectIterator
= NULL
;
715 // Move iterator to the current object.
716 SdrObjectWeakRef xObject
= maPosition
.mxObject
;
717 maPosition
.mxObject
.reset(NULL
);
719 if (!mpObjectIterator
)
722 while (mpObjectIterator
->IsMore() && maPosition
.mxObject
!= xObject
)
723 maPosition
.mxObject
.reset(mpObjectIterator
->Next());
726 //===== DocumentIteratorImpl ============================================
728 DocumentIteratorImpl::DocumentIteratorImpl (
729 sal_Int32 nPageIndex
,
730 PageKind ePageKind
, EditMode eEditMode
,
731 SdDrawDocument
* pDocument
,
732 const ::boost::weak_ptr
<ViewShell
>& rpViewShellWeak
,
733 bool bDirectionIsForward
)
734 : ViewIteratorImpl (nPageIndex
, pDocument
, rpViewShellWeak
, bDirectionIsForward
,
735 ePageKind
, eEditMode
)
737 if (eEditMode
== EM_PAGE
)
738 mnPageCount
= pDocument
->GetSdPageCount (ePageKind
);
740 mnPageCount
= pDocument
->GetMasterSdPageCount(ePageKind
);
743 DocumentIteratorImpl::~DocumentIteratorImpl()
746 IteratorImplBase
* DocumentIteratorImpl::Clone (IteratorImplBase
* pObject
) const
748 DocumentIteratorImpl
* pIterator
= static_cast<DocumentIteratorImpl
*>(pObject
);
749 if (pIterator
== NULL
)
750 pIterator
= new DocumentIteratorImpl (
751 maPosition
.mnPageIndex
, maPosition
.mePageKind
, maPosition
.meEditMode
,
752 mpDocument
, mpViewShellWeak
, mbDirectionIsForward
);
753 // Finish the cloning.
754 return ViewIteratorImpl::Clone (pIterator
);
757 void DocumentIteratorImpl::GotoNextText()
759 bool bSetToOnePastLastPage
= false;
760 bool bViewChanged
= false;
762 ViewIteratorImpl::GotoNextText();
764 if (mbDirectionIsForward
)
766 if (maPosition
.mnPageIndex
>= mnPageCount
)
768 // Switch to master page.
769 if (maPosition
.meEditMode
== EM_PAGE
)
771 maPosition
.meEditMode
= EM_MASTERPAGE
;
775 // Switch to next view mode.
778 if (maPosition
.mePageKind
== PK_HANDOUT
)
779 // Not really necessary but makes things more clear.
780 bSetToOnePastLastPage
= true;
783 maPosition
.meEditMode
= EM_PAGE
;
784 if (maPosition
.mePageKind
== PK_STANDARD
)
785 maPosition
.mePageKind
= PK_NOTES
;
786 else if (maPosition
.mePageKind
== PK_NOTES
)
787 maPosition
.mePageKind
= PK_HANDOUT
;
795 if (maPosition
.mnPageIndex
< 0)
797 // Switch from master pages to draw pages.
798 if (maPosition
.meEditMode
== EM_MASTERPAGE
)
800 maPosition
.meEditMode
= EM_PAGE
;
801 bSetToOnePastLastPage
= true;
804 // Switch to previous view mode.
807 if (maPosition
.mePageKind
== PK_STANDARD
)
811 maPosition
.meEditMode
= EM_MASTERPAGE
;
812 if (maPosition
.mePageKind
== PK_HANDOUT
)
813 maPosition
.mePageKind
= PK_NOTES
;
814 else if (maPosition
.mePageKind
== PK_NOTES
)
815 maPosition
.mePageKind
= PK_STANDARD
;
816 bSetToOnePastLastPage
= true;
824 // Get new page count;
825 sal_Int32 nPageCount
;
826 if (maPosition
.meEditMode
== EM_PAGE
)
827 nPageCount
= mpDocument
->GetSdPageCount (maPosition
.mePageKind
);
829 nPageCount
= mpDocument
->GetMasterSdPageCount(maPosition
.mePageKind
);
831 // Now that we know the number of pages we can set the current page index.
832 if (bSetToOnePastLastPage
)
833 SetPage (nPageCount
);
837 } } // end of namespace ::sd::outliner
839 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */