android: Update app-specific/MIME type icons
[LibreOffice.git] / sd / source / ui / view / OutlinerIterator.cxx
bloba7cd6cf66bf2038c97452b4529161ee37af239ee
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <tools/debug.hxx>
24 #include <osl/diagnose.h>
25 #include <Outliner.hxx>
27 #include <drawdoc.hxx>
28 #include <DrawViewShell.hxx>
29 #include <sdpage.hxx>
30 #include <utility>
32 namespace sd::outliner {
34 //===== IteratorPosition ======================================================
36 IteratorPosition::IteratorPosition()
37 : mnText(0)
38 , mnPageIndex(-1)
39 , mePageKind(PageKind::Standard)
40 , meEditMode(EditMode::Page)
44 bool IteratorPosition::operator== (const IteratorPosition& aPosition) const
46 return mxObject.get() == aPosition.mxObject.get()
47 && mnText == aPosition.mnText
48 && mnPageIndex == aPosition.mnPageIndex
49 && mePageKind == aPosition.mePageKind
50 && meEditMode == aPosition.meEditMode;
53 //===== Iterator ==============================================================
55 Iterator::Iterator()
59 Iterator::Iterator (const Iterator& rIterator)
60 : mxIterator(rIterator.mxIterator ? rIterator.mxIterator->Clone() : nullptr)
64 Iterator::Iterator(Iterator&& rIterator) noexcept
65 : mxIterator(std::move(rIterator.mxIterator))
69 Iterator::Iterator (std::unique_ptr<IteratorImplBase> pObject)
70 : mxIterator(std::move(pObject))
74 Iterator::~Iterator()
78 Iterator& Iterator::operator= (const Iterator& rIterator)
80 if (this != &rIterator)
82 if (rIterator.mxIterator)
83 mxIterator.reset(rIterator.mxIterator->Clone());
84 else
85 mxIterator.reset();
87 return *this;
90 Iterator& Iterator::operator=(Iterator&& rIterator) noexcept
92 mxIterator = std::move(rIterator.mxIterator);
93 return *this;
96 const IteratorPosition& Iterator::operator* () const
98 DBG_ASSERT (mxIterator, "::sd::outliner::Iterator::operator* : missing implementation object");
99 return mxIterator->GetPosition();
102 Iterator& Iterator::operator++ ()
104 if (mxIterator)
105 mxIterator->GotoNextText();
106 return *this;
109 bool Iterator::operator== (const Iterator& rIterator) const
111 if (!mxIterator || !rIterator.mxIterator)
112 return mxIterator.get() == rIterator.mxIterator.get();
113 else
114 return *mxIterator == *rIterator.mxIterator;
117 bool Iterator::operator!= (const Iterator& rIterator) const
119 return ! operator==(rIterator);
122 void Iterator::Reverse()
124 if (mxIterator)
125 mxIterator->Reverse();
128 //===== IteratorFactory =======================================================
130 OutlinerContainer::OutlinerContainer (SdOutliner* pOutliner)
131 : mpOutliner(pOutliner)
135 Iterator OutlinerContainer::begin()
137 return CreateIterator (BEGIN);
140 Iterator OutlinerContainer::end()
142 return CreateIterator (END);
145 Iterator OutlinerContainer::current()
147 return CreateIterator (CURRENT);
150 Iterator OutlinerContainer::CreateIterator (IteratorLocation aLocation)
152 // Decide on certain features of the outliner which kind of iterator to
153 // use.
154 if (mpOutliner->mbRestrictSearchToSelection)
155 // There is a selection. Search only in this.
156 return CreateSelectionIterator (
157 mpOutliner->maMarkListCopy,
158 mpOutliner->mpDrawDocument,
159 mpOutliner->mpWeakViewShell.lock(),
160 mpOutliner->mbDirectionIsForward,
161 aLocation);
162 else
163 // Search in the whole document.
164 return CreateDocumentIterator (
165 mpOutliner->mpDrawDocument,
166 mpOutliner->mpWeakViewShell.lock(),
167 mpOutliner->mbDirectionIsForward,
168 aLocation);
171 Iterator OutlinerContainer::CreateSelectionIterator (
172 const ::std::vector<::unotools::WeakReference<SdrObject>>& rObjectList,
173 SdDrawDocument* pDocument,
174 const std::shared_ptr<ViewShell>& rpViewShell,
175 bool bDirectionIsForward,
176 IteratorLocation aLocation)
178 OSL_ASSERT(rpViewShell);
180 sal_Int32 nObjectIndex;
182 if (bDirectionIsForward)
183 switch (aLocation)
185 case CURRENT:
186 case BEGIN:
187 default:
188 nObjectIndex = 0;
189 break;
190 case END:
191 nObjectIndex = rObjectList.size();
192 break;
194 else
195 switch (aLocation)
197 case CURRENT:
198 case BEGIN:
199 default:
200 nObjectIndex = rObjectList.size()-1;
201 break;
202 case END:
203 nObjectIndex = -1;
204 break;
207 return Iterator (std::make_unique<SelectionIteratorImpl> (
208 rObjectList, nObjectIndex, pDocument, rpViewShell, bDirectionIsForward));
211 Iterator OutlinerContainer::CreateDocumentIterator (
212 SdDrawDocument* pDocument,
213 const std::shared_ptr<ViewShell>& rpViewShell,
214 bool bDirectionIsForward,
215 IteratorLocation aLocation)
217 OSL_ASSERT(rpViewShell);
219 PageKind ePageKind;
220 EditMode eEditMode;
222 switch (aLocation)
224 case BEGIN:
225 default:
226 if (bDirectionIsForward)
228 ePageKind = PageKind::Standard;
229 eEditMode = EditMode::Page;
231 else
233 ePageKind = PageKind::Handout;
234 eEditMode = EditMode::MasterPage;
236 break;
238 case END:
239 if (bDirectionIsForward)
241 ePageKind = PageKind::Handout;
242 eEditMode = EditMode::MasterPage;
244 else
246 ePageKind = PageKind::Standard;
247 eEditMode = EditMode::Page;
249 break;
251 case CURRENT:
252 const std::shared_ptr<DrawViewShell> pDrawViewShell(
253 std::dynamic_pointer_cast<DrawViewShell>(rpViewShell));
254 if (pDrawViewShell)
256 ePageKind = pDrawViewShell->GetPageKind();
257 eEditMode = pDrawViewShell->GetEditMode();
259 else
261 ePageKind = PageKind::Standard;
262 eEditMode = EditMode::Page;
264 break;
267 sal_Int32 nPageIndex = GetPageIndex (pDocument, rpViewShell,
268 ePageKind, eEditMode, bDirectionIsForward, aLocation);
270 return Iterator (
271 std::make_unique<DocumentIteratorImpl> (nPageIndex, ePageKind, eEditMode,
272 pDocument, rpViewShell, bDirectionIsForward));
275 sal_Int32 OutlinerContainer::GetPageIndex (
276 SdDrawDocument const * pDocument,
277 const std::shared_ptr<ViewShell>& rpViewShell,
278 PageKind ePageKind,
279 EditMode eEditMode,
280 bool bDirectionIsForward,
281 IteratorLocation aLocation)
283 OSL_ASSERT(rpViewShell);
285 sal_Int32 nPageIndex;
286 sal_Int32 nPageCount;
288 const std::shared_ptr<DrawViewShell> pDrawViewShell(
289 std::dynamic_pointer_cast<DrawViewShell>(rpViewShell));
291 switch (eEditMode)
293 case EditMode::Page:
294 nPageCount = pDocument->GetSdPageCount (ePageKind);
295 break;
296 case EditMode::MasterPage:
297 nPageCount = pDocument->GetMasterSdPageCount(ePageKind);
298 break;
299 default:
300 nPageCount = 0;
303 switch (aLocation)
305 case CURRENT:
306 if (pDrawViewShell)
307 nPageIndex = pDrawViewShell->GetCurPagePos();
308 else
310 const SdPage* pPage = rpViewShell->GetActualPage();
311 if (pPage != nullptr)
312 nPageIndex = (pPage->GetPageNum()-1)/2;
313 else
314 nPageIndex = 0;
316 break;
318 case BEGIN:
319 default:
320 if (bDirectionIsForward)
321 nPageIndex = 0;
322 else
323 nPageIndex = nPageCount-1;
324 break;
326 case END:
327 if (bDirectionIsForward)
328 nPageIndex = nPageCount;
329 else
330 nPageIndex = -1;
331 break;
334 return nPageIndex;
337 //===== IteratorImplBase ====================================================
339 IteratorImplBase::IteratorImplBase(SdDrawDocument* pDocument,
340 const std::weak_ptr<ViewShell>& rpViewShellWeak,
341 bool bDirectionIsForward)
342 : mpDocument (pDocument)
343 , mpViewShellWeak (rpViewShellWeak)
344 , mbDirectionIsForward (bDirectionIsForward)
346 std::shared_ptr<DrawViewShell> pDrawViewShell;
347 if ( ! mpViewShellWeak.expired())
348 pDrawViewShell = std::dynamic_pointer_cast<DrawViewShell>(rpViewShellWeak.lock());
350 if (pDrawViewShell)
352 maPosition.mePageKind = pDrawViewShell->GetPageKind();
353 maPosition.meEditMode = pDrawViewShell->GetEditMode();
355 else
357 maPosition.mePageKind = PageKind::Standard;
358 maPosition.meEditMode = EditMode::Page;
362 IteratorImplBase::IteratorImplBase( SdDrawDocument* pDocument,
363 std::weak_ptr<ViewShell> pViewShellWeak,
364 bool bDirectionIsForward, PageKind ePageKind, EditMode eEditMode)
365 : mpDocument (pDocument)
366 , mpViewShellWeak (std::move(pViewShellWeak))
367 , mbDirectionIsForward (bDirectionIsForward)
369 maPosition.mePageKind = ePageKind;
370 maPosition.meEditMode = eEditMode;
373 IteratorImplBase::~IteratorImplBase()
376 bool IteratorImplBase::operator== (const IteratorImplBase& rIterator) const
378 return maPosition == rIterator.maPosition;
381 bool IteratorImplBase::IsEqualSelection(const IteratorImplBase& rIterator) const
383 // When this method is executed instead of the ones from derived classes
384 // then the argument is of another type then the object itself. In this
385 // just compare the position objects.
386 return maPosition == rIterator.maPosition;
389 const IteratorPosition& IteratorImplBase::GetPosition()
391 return maPosition;
394 IteratorImplBase* IteratorImplBase::Clone (IteratorImplBase* pObject) const
396 if (pObject != nullptr)
398 pObject->maPosition = maPosition;
399 pObject->mpDocument = mpDocument;
400 pObject->mpViewShellWeak = mpViewShellWeak;
401 pObject->mbDirectionIsForward = mbDirectionIsForward;
403 return pObject;
406 void IteratorImplBase::Reverse()
408 mbDirectionIsForward = ! mbDirectionIsForward;
411 //===== SelectionIteratorImpl ===========================================
413 SelectionIteratorImpl::SelectionIteratorImpl (
414 const ::std::vector<::unotools::WeakReference<SdrObject>>& rObjectList,
415 sal_Int32 nObjectIndex,
416 SdDrawDocument* pDocument,
417 const std::weak_ptr<ViewShell>& rpViewShellWeak,
418 bool bDirectionIsForward)
419 : IteratorImplBase (pDocument, rpViewShellWeak, bDirectionIsForward),
420 mrObjectList(rObjectList),
421 mnObjectIndex(nObjectIndex)
425 SelectionIteratorImpl::~SelectionIteratorImpl()
428 IteratorImplBase* SelectionIteratorImpl::Clone (IteratorImplBase* pObject) const
430 SelectionIteratorImpl* pIterator = static_cast<SelectionIteratorImpl*>(pObject);
431 if (pIterator == nullptr)
432 pIterator = new SelectionIteratorImpl (
433 mrObjectList, mnObjectIndex, mpDocument, mpViewShellWeak, mbDirectionIsForward);
434 return pIterator;
437 void SelectionIteratorImpl::GotoNextText()
439 SdrTextObj* pTextObj = DynCastSdrTextObj( mrObjectList.at(mnObjectIndex).get().get() );
440 if (mbDirectionIsForward)
442 if( pTextObj )
444 ++maPosition.mnText;
445 if( maPosition.mnText >= pTextObj->getTextCount() )
447 maPosition.mnText = 0;
448 ++mnObjectIndex;
451 else
453 ++mnObjectIndex;
456 else
458 if( pTextObj )
460 --maPosition.mnText;
461 if( maPosition.mnText < 0 )
463 maPosition.mnText = -1;
464 --mnObjectIndex;
467 else
469 --mnObjectIndex;
470 maPosition.mnText = -1;
473 if( (maPosition.mnText == -1) && (mnObjectIndex >= 0) )
475 pTextObj = DynCastSdrTextObj( mrObjectList.at(mnObjectIndex).get().get() );
476 if( pTextObj )
477 maPosition.mnText = pTextObj->getTextCount() - 1;
480 if( maPosition.mnText == -1 )
481 maPosition.mnText = 0;
485 const IteratorPosition& SelectionIteratorImpl::GetPosition()
487 maPosition.mxObject = mrObjectList.at(mnObjectIndex);
489 return maPosition;
492 bool SelectionIteratorImpl::operator== (const IteratorImplBase& rIterator) const
494 return rIterator.IsEqualSelection(*this);
497 bool SelectionIteratorImpl::IsEqualSelection(const IteratorImplBase& rIterator) const
499 const SelectionIteratorImpl* pSelectionIterator =
500 static_cast<const SelectionIteratorImpl*>(&rIterator);
501 return mpDocument == pSelectionIterator->mpDocument
502 && mnObjectIndex == pSelectionIterator->mnObjectIndex;
505 //===== ViewIteratorImpl ================================================
507 ViewIteratorImpl::ViewIteratorImpl (
508 sal_Int32 nPageIndex,
509 SdDrawDocument* pDocument,
510 const std::weak_ptr<ViewShell>& rpViewShellWeak,
511 bool bDirectionIsForward)
512 : IteratorImplBase (pDocument, rpViewShellWeak, bDirectionIsForward),
513 mbPageChangeOccurred(false),
514 mpPage(nullptr)
516 SetPage (nPageIndex);
519 ViewIteratorImpl::ViewIteratorImpl (
520 sal_Int32 nPageIndex,
521 SdDrawDocument* pDocument,
522 const std::weak_ptr<ViewShell>& rpViewShellWeak,
523 bool bDirectionIsForward,
524 PageKind ePageKind,
525 EditMode eEditMode)
526 : IteratorImplBase (pDocument, rpViewShellWeak, bDirectionIsForward, ePageKind, eEditMode),
527 mbPageChangeOccurred(false),
528 mpPage(nullptr)
530 SetPage (nPageIndex);
533 ViewIteratorImpl::~ViewIteratorImpl()
537 IteratorImplBase* ViewIteratorImpl::Clone (IteratorImplBase* pObject) const
540 ViewIteratorImpl* pIterator = static_cast<ViewIteratorImpl*>(pObject);
541 if (pIterator == nullptr)
542 pIterator = new ViewIteratorImpl (
543 maPosition.mnPageIndex, mpDocument, mpViewShellWeak, mbDirectionIsForward);
545 IteratorImplBase::Clone (pObject);
547 if (moObjectIterator)
549 pIterator->moObjectIterator.emplace(mpPage, SdrIterMode::DeepNoGroups, !mbDirectionIsForward);
551 // No direct way to set the object iterator to the current object.
552 pIterator->maPosition.mxObject = nullptr;
553 while (pIterator->moObjectIterator->IsMore() && pIterator->maPosition.mxObject.get()!=maPosition.mxObject.get())
554 pIterator->maPosition.mxObject = pIterator->moObjectIterator->Next();
556 else
557 pIterator->moObjectIterator.reset();
559 return pIterator;
562 void ViewIteratorImpl::GotoNextText()
564 SdrTextObj* pTextObj = DynCastSdrTextObj( maPosition.mxObject.get().get() );
565 if( pTextObj )
567 if (mbDirectionIsForward)
569 ++maPosition.mnText;
570 if( maPosition.mnText < pTextObj->getTextCount() )
571 return;
573 else
575 --maPosition.mnText;
576 if( maPosition.mnText >= 0 )
577 return;
581 if (moObjectIterator && moObjectIterator->IsMore())
582 maPosition.mxObject = moObjectIterator->Next();
583 else
584 maPosition.mxObject = nullptr;
586 if (!maPosition.mxObject.get().is() )
588 if (mbDirectionIsForward)
589 SetPage (maPosition.mnPageIndex+1);
590 else
591 SetPage (maPosition.mnPageIndex-1);
593 if (mpPage != nullptr)
594 moObjectIterator.emplace( mpPage, SdrIterMode::DeepNoGroups, !mbDirectionIsForward );
595 if (moObjectIterator && moObjectIterator->IsMore())
596 maPosition.mxObject = moObjectIterator->Next();
597 else
598 maPosition.mxObject = nullptr;
601 maPosition.mnText = 0;
602 if( !mbDirectionIsForward && maPosition.mxObject.get().is() )
604 pTextObj = DynCastSdrTextObj( maPosition.mxObject.get().get() );
605 if( pTextObj )
606 maPosition.mnText = pTextObj->getTextCount() - 1;
610 void ViewIteratorImpl::SetPage (sal_Int32 nPageIndex)
612 mbPageChangeOccurred = (maPosition.mnPageIndex!=nPageIndex);
613 if (mbPageChangeOccurred)
615 maPosition.mnPageIndex = nPageIndex;
617 sal_Int32 nPageCount;
618 if (maPosition.meEditMode == EditMode::Page)
619 nPageCount = mpDocument->GetSdPageCount(maPosition.mePageKind);
620 else
621 nPageCount = mpDocument->GetMasterSdPageCount(
622 maPosition.mePageKind);
624 // Get page pointer. Here we have three cases: regular pages,
625 // master pages and invalid page indices. The later ones are not
626 // errors but the effect of the iterator advancing to the next page
627 // and going past the last one. This dropping of the rim at the far
628 // side is detected here and has to be reacted to by the caller.
629 if (nPageIndex>=0 && nPageIndex < nPageCount)
631 if (maPosition.meEditMode == EditMode::Page)
632 mpPage = mpDocument->GetSdPage (
633 static_cast<sal_uInt16>(nPageIndex),
634 maPosition.mePageKind);
635 else
636 mpPage = mpDocument->GetMasterSdPage (
637 static_cast<sal_uInt16>(nPageIndex),
638 maPosition.mePageKind);
640 else
641 mpPage = nullptr;
644 // Set up object list iterator.
645 if (mpPage != nullptr)
646 moObjectIterator.emplace(mpPage, SdrIterMode::DeepNoGroups, ! mbDirectionIsForward);
647 else
648 moObjectIterator.reset();
650 // Get object pointer.
651 if (moObjectIterator && moObjectIterator->IsMore())
652 maPosition.mxObject = moObjectIterator->Next();
653 else
654 maPosition.mxObject = nullptr;
656 maPosition.mnText = 0;
657 if( !mbDirectionIsForward && maPosition.mxObject.get().is() )
659 SdrTextObj* pTextObj = DynCastSdrTextObj( maPosition.mxObject.get().get() );
660 if( pTextObj )
661 maPosition.mnText = pTextObj->getTextCount() - 1;
666 void ViewIteratorImpl::Reverse()
668 IteratorImplBase::Reverse ();
670 // Create reversed object list iterator.
671 if (mpPage != nullptr)
672 moObjectIterator.emplace(mpPage, SdrIterMode::DeepNoGroups, ! mbDirectionIsForward);
673 else
674 moObjectIterator.reset();
676 // Move iterator to the current object.
677 ::unotools::WeakReference<SdrObject> xObject = std::move(maPosition.mxObject);
678 maPosition.mxObject = nullptr;
680 if (!moObjectIterator)
681 return;
683 while (moObjectIterator->IsMore() && maPosition.mxObject.get() != xObject.get())
684 maPosition.mxObject = moObjectIterator->Next();
687 //===== DocumentIteratorImpl ============================================
689 DocumentIteratorImpl::DocumentIteratorImpl (
690 sal_Int32 nPageIndex,
691 PageKind ePageKind, EditMode eEditMode,
692 SdDrawDocument* pDocument,
693 const std::weak_ptr<ViewShell>& rpViewShellWeak,
694 bool bDirectionIsForward)
695 : ViewIteratorImpl (nPageIndex, pDocument, rpViewShellWeak, bDirectionIsForward,
696 ePageKind, eEditMode)
698 if (eEditMode == EditMode::Page)
699 mnPageCount = pDocument->GetSdPageCount (ePageKind);
700 else
701 mnPageCount = pDocument->GetMasterSdPageCount(ePageKind);
704 DocumentIteratorImpl::~DocumentIteratorImpl()
707 IteratorImplBase* DocumentIteratorImpl::Clone (IteratorImplBase* pObject) const
709 DocumentIteratorImpl* pIterator = static_cast<DocumentIteratorImpl*>(pObject);
710 if (pIterator == nullptr)
711 pIterator = new DocumentIteratorImpl (
712 maPosition.mnPageIndex, maPosition.mePageKind, maPosition.meEditMode,
713 mpDocument, mpViewShellWeak, mbDirectionIsForward);
714 // Finish the cloning.
715 return ViewIteratorImpl::Clone (pIterator);
718 void DocumentIteratorImpl::GotoNextText()
720 bool bSetToOnePastLastPage = false;
721 bool bViewChanged = false;
723 ViewIteratorImpl::GotoNextText();
725 if (mbDirectionIsForward)
727 if (maPosition.mnPageIndex >= mnPageCount)
729 // Switch to master page.
730 if (maPosition.meEditMode == EditMode::Page)
732 maPosition.meEditMode = EditMode::MasterPage;
733 SetPage (0);
736 // Switch to next view mode.
737 else
739 if (maPosition.mePageKind == PageKind::Handout)
740 // Not really necessary but makes things more clear.
741 bSetToOnePastLastPage = true;
742 else
744 maPosition.meEditMode = EditMode::Page;
745 if (maPosition.mePageKind == PageKind::Standard)
746 maPosition.mePageKind = PageKind::Notes;
747 else if (maPosition.mePageKind == PageKind::Notes)
748 maPosition.mePageKind = PageKind::Handout;
749 SetPage (0);
752 bViewChanged = true;
755 else
756 if (maPosition.mnPageIndex < 0)
758 // Switch from master pages to draw pages.
759 if (maPosition.meEditMode == EditMode::MasterPage)
761 maPosition.meEditMode = EditMode::Page;
762 bSetToOnePastLastPage = true;
765 // Switch to previous view mode.
766 else
768 if (maPosition.mePageKind == PageKind::Standard)
769 SetPage (-1);
770 else
772 maPosition.meEditMode = EditMode::MasterPage;
773 if (maPosition.mePageKind == PageKind::Handout)
774 maPosition.mePageKind = PageKind::Notes;
775 else if (maPosition.mePageKind == PageKind::Notes)
776 maPosition.mePageKind = PageKind::Standard;
777 bSetToOnePastLastPage = true;
780 bViewChanged = true;
783 if (!bViewChanged)
784 return;
786 // Get new page count;
787 sal_Int32 nPageCount;
788 if (maPosition.meEditMode == EditMode::Page)
789 nPageCount = mpDocument->GetSdPageCount (maPosition.mePageKind);
790 else
791 nPageCount = mpDocument->GetMasterSdPageCount(maPosition.mePageKind);
793 // Now that we know the number of pages we can set the current page index.
794 if (bSetToOnePastLastPage)
795 SetPage (nPageCount);
798 } // end of namespace ::sd::outliner
800 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */