diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /sd/source/ui/slidesorter/model | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sd/source/ui/slidesorter/model')
-rw-r--r-- | sd/source/ui/slidesorter/model/SlideSorterModel.cxx | 676 | ||||
-rw-r--r-- | sd/source/ui/slidesorter/model/SlsPageDescriptor.cxx | 226 | ||||
-rw-r--r-- | sd/source/ui/slidesorter/model/SlsPageEnumeration.cxx | 202 | ||||
-rw-r--r-- | sd/source/ui/slidesorter/model/SlsPageEnumerationProvider.cxx | 81 | ||||
-rw-r--r-- | sd/source/ui/slidesorter/model/SlsVisualState.cxx | 40 |
5 files changed, 1225 insertions, 0 deletions
diff --git a/sd/source/ui/slidesorter/model/SlideSorterModel.cxx b/sd/source/ui/slidesorter/model/SlideSorterModel.cxx new file mode 100644 index 000000000..4d3e79656 --- /dev/null +++ b/sd/source/ui/slidesorter/model/SlideSorterModel.cxx @@ -0,0 +1,676 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <model/SlideSorterModel.hxx> + +#include <SlideSorter.hxx> +#include <sal/log.hxx> +#include <model/SlsPageDescriptor.hxx> +#include <model/SlsPageEnumerationProvider.hxx> +#include <controller/SlideSorterController.hxx> +#include <controller/SlsPageSelector.hxx> +#include <controller/SlsCurrentSlideManager.hxx> +#include <controller/SlsSlotManager.hxx> +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/drawing/XMasterPagesSupplier.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/frame/XController.hpp> + +#include <vcl/uitest/logger.hxx> +#include <vcl/uitest/eventdescription.hxx> + +#include <ViewShellBase.hxx> +#include <DrawDocShell.hxx> +#include <drawdoc.hxx> +#include <sdpage.hxx> +#include <FrameView.hxx> + +#include <o3tl/safeint.hxx> +#include <tools/diagnose_ex.h> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace sd::slidesorter::model { + +namespace { + bool PrintModel (const SlideSorterModel& rModel) + { + for (sal_Int32 nIndex=0,nCount=rModel.GetPageCount(); nIndex<nCount; ++nIndex) + { + SharedPageDescriptor pDescriptor (rModel.GetPageDescriptor(nIndex)); + if (pDescriptor) + { + SAL_INFO( + "sd.sls", + nIndex << " " << pDescriptor->GetPageIndex() << " " + << pDescriptor->GetVisualState().mnPageId << " " + << FromCoreIndex(pDescriptor->GetPage()->GetPageNum()) + << " " << pDescriptor->GetPage()); + } + else + { + SAL_INFO("sd.sls", nIndex); + } + } + + return true; + } + bool CheckModel (const SlideSorterModel& rModel) + { + for (sal_Int32 nIndex=0,nCount=rModel.GetPageCount(); nIndex<nCount; ++nIndex) + { + SharedPageDescriptor pDescriptor (rModel.GetPageDescriptor(nIndex)); + if ( ! pDescriptor) + { + PrintModel(rModel); + assert(pDescriptor); + return false; + } + if (nIndex != pDescriptor->GetPageIndex()) + { + PrintModel(rModel); + assert(nIndex == pDescriptor->GetPageIndex()); + return false; + } + if (nIndex != pDescriptor->GetVisualState().mnPageId) + { + PrintModel(rModel); + assert(nIndex == pDescriptor->GetVisualState().mnPageId); + return false; + } + } + + return true; + } +} + +namespace { + +void collectUIInformation(const OUString& num, const OUString& rAction) +{ + EventDescription aDescription; + aDescription.aID = "impress_win_or_draw_win"; + aDescription.aParameters = {{"POS", num}}; + aDescription.aAction = rAction; + aDescription.aKeyWord = "ImpressWindowUIObject"; + aDescription.aParent = "MainWindow"; + + UITestLogger::getInstance().logEvent(aDescription); +} + +} + +SlideSorterModel::SlideSorterModel (SlideSorter& rSlideSorter) + : mrSlideSorter(rSlideSorter), + meEditMode(EditMode::Page), + maPageDescriptors(0) +{ +} + +SlideSorterModel::~SlideSorterModel() +{ + ClearDescriptorList (); +} + +void SlideSorterModel::Dispose() +{ + ClearDescriptorList (); +} + +SdDrawDocument* SlideSorterModel::GetDocument() +{ + if (mrSlideSorter.GetViewShellBase() != nullptr) + return mrSlideSorter.GetViewShellBase()->GetDocument(); + else + return nullptr; +} + +bool SlideSorterModel::SetEditMode (EditMode eEditMode) +{ + bool bEditModeChanged = false; + if (meEditMode != eEditMode) + { + meEditMode = eEditMode; + UpdatePageList(); + bEditModeChanged = true; + } + return bEditModeChanged; +} + +sal_Int32 SlideSorterModel::GetPageCount() const +{ + return maPageDescriptors.size(); +} + +SharedPageDescriptor SlideSorterModel::GetPageDescriptor ( + const sal_Int32 nPageIndex, + const bool bCreate) const +{ + ::osl::MutexGuard aGuard (maMutex); + + SharedPageDescriptor pDescriptor; + + if (nPageIndex>=0 && nPageIndex<GetPageCount()) + { + pDescriptor = maPageDescriptors[nPageIndex]; + if (pDescriptor == nullptr && bCreate && mxSlides.is()) + { + SdPage* pPage = GetPage(nPageIndex); + pDescriptor = std::make_shared<PageDescriptor>( + Reference<drawing::XDrawPage>(mxSlides->getByIndex(nPageIndex),UNO_QUERY), + pPage, + nPageIndex); + maPageDescriptors[nPageIndex] = pDescriptor; + } + } + + return pDescriptor; +} + +sal_Int32 SlideSorterModel::GetIndex (const Reference<drawing::XDrawPage>& rxSlide) const +{ + ::osl::MutexGuard aGuard (maMutex); + + // First try to guess the right index. + Reference<beans::XPropertySet> xSet (rxSlide, UNO_QUERY); + if (xSet.is()) + { + try + { + const Any aNumber (xSet->getPropertyValue("Number")); + sal_Int16 nNumber (-1); + aNumber >>= nNumber; + nNumber -= 1; + SharedPageDescriptor pDescriptor (GetPageDescriptor(nNumber, false)); + if (pDescriptor + && pDescriptor->GetXDrawPage() == rxSlide) + { + return nNumber; + } + } + catch (uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("sd"); + } + } + + // Guess was wrong, iterate over all slides and search for the right + // one. + const sal_Int32 nCount (maPageDescriptors.size()); + for (sal_Int32 nIndex=0; nIndex<nCount; ++nIndex) + { + SharedPageDescriptor pDescriptor (maPageDescriptors[nIndex]); + + // Make sure that the descriptor exists. Without it the given slide + // can not be found. + if (!pDescriptor) + { + // Call GetPageDescriptor() to create the missing descriptor. + pDescriptor = GetPageDescriptor(nIndex); + } + + if (pDescriptor->GetXDrawPage() == rxSlide) + return nIndex; + } + + return -1; +} + +sal_Int32 SlideSorterModel::GetIndex (const SdrPage* pPage) const +{ + if (pPage == nullptr) + return -1; + + ::osl::MutexGuard aGuard (maMutex); + + // First try to guess the right index. + sal_Int16 nNumber ((pPage->GetPageNum()-1)/2); + SharedPageDescriptor pDescriptor (GetPageDescriptor(nNumber, false)); + if (pDescriptor + && pDescriptor->GetPage() == pPage) + { + return nNumber; + } + + // Guess was wrong, iterate over all slides and search for the right + // one. + const sal_Int32 nCount (maPageDescriptors.size()); + for (sal_Int32 nIndex=0; nIndex<nCount; ++nIndex) + { + pDescriptor = maPageDescriptors[nIndex]; + + // Make sure that the descriptor exists. Without it the given slide + // can not be found. + if (!pDescriptor) + { + // Call GetPageDescriptor() to create the missing descriptor. + pDescriptor = GetPageDescriptor(nIndex); + } + + if (pDescriptor->GetPage() == pPage) + return nIndex; + } + + return -1; +} + +sal_uInt16 SlideSorterModel::GetCoreIndex (const sal_Int32 nIndex) const +{ + SharedPageDescriptor pDescriptor (GetPageDescriptor(nIndex)); + if (pDescriptor) + return pDescriptor->GetPage()->GetPageNum(); + else + return mxSlides->getCount()*2+1; +} + +/** For now this method uses a trivial algorithm: throw away all descriptors + and create them anew (on demand). The main problem that we are facing + when designing a better algorithm is that we can not compare pointers to + pages stored in the PageDescriptor objects and those obtained from the + document: pages may have been deleted and others may have been created + at the exact same memory locations. +*/ +void SlideSorterModel::Resync() +{ + ::osl::MutexGuard aGuard (maMutex); + + // Check if document and this model really differ. + bool bIsUpToDate (true); + SdDrawDocument* pDocument = GetDocument(); + if (pDocument!=nullptr && maPageDescriptors.size()==pDocument->GetSdPageCount(PageKind::Standard)) + { + for (sal_Int32 nIndex=0,nCount=maPageDescriptors.size(); nIndex<nCount; ++nIndex) + { + if (maPageDescriptors[nIndex] + && maPageDescriptors[nIndex]->GetPage() + != GetPage(nIndex)) + { + SAL_INFO("sd.sls", "page " << nIndex << " differs"); + bIsUpToDate = false; + break; + } + } + } + else + { + bIsUpToDate = false; + } + + if ( ! bIsUpToDate) + { + SynchronizeDocumentSelection(); // Try to make the current selection persistent. + ClearDescriptorList (); + AdaptSize(); + SynchronizeModelSelection(); + mrSlideSorter.GetController().GetPageSelector().CountSelectedPages(); + } + CheckModel(*this); +} + +void SlideSorterModel::ClearDescriptorList() +{ + ::std::vector<SharedPageDescriptor> aDescriptors; + + { + ::osl::MutexGuard aGuard (maMutex); + aDescriptors.swap(maPageDescriptors); + } + + for (auto& rxDescriptor : aDescriptors) + { + if (rxDescriptor != nullptr) + { + if (rxDescriptor.use_count() > 1) + { + SAL_INFO( + "sd.sls", + "trying to delete page descriptor that is still used with" + " count " << rxDescriptor.use_count()); + // No assertion here because that can hang the office when + // opening a dialog from here. + } + rxDescriptor.reset(); + } + } +} + +void SlideSorterModel::SynchronizeDocumentSelection() +{ + ::osl::MutexGuard aGuard (maMutex); + + PageEnumeration aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(*this)); + while (aAllPages.HasMoreElements()) + { + SharedPageDescriptor pDescriptor (aAllPages.GetNextElement()); + const bool bIsSelected (pDescriptor->HasState(PageDescriptor::ST_Selected)); + pDescriptor->GetPage()->SetSelected(bIsSelected); + } +} + +void SlideSorterModel::SynchronizeModelSelection() +{ + ::osl::MutexGuard aGuard (maMutex); + + PageEnumeration aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(*this)); + while (aAllPages.HasMoreElements()) + { + SharedPageDescriptor pDescriptor (aAllPages.GetNextElement()); + const bool bIsSelected (pDescriptor->GetPage()->IsSelected()); + pDescriptor->SetState(PageDescriptor::ST_Selected, bIsSelected); + } +} + +void SlideSorterModel::SetDocumentSlides ( + const Reference<container::XIndexAccess>& rxSlides) +{ + ::osl::MutexGuard aGuard (maMutex); + + // Make the current selection persistent and then release the + // current set of pages. + SynchronizeDocumentSelection(); + mxSlides = nullptr; + ClearDescriptorList (); + + // Reset the current page to cause everybody to release references to it. + mrSlideSorter.GetController().GetCurrentSlideManager()->NotifyCurrentSlideChange(-1); + + // Set the new set of pages. + mxSlides = rxSlides; + AdaptSize(); + SynchronizeModelSelection(); + mrSlideSorter.GetController().GetPageSelector().CountSelectedPages(); + + model::PageEnumeration aSelectedPages ( + model::PageEnumerationProvider::CreateSelectedPagesEnumeration(*this)); + if (aSelectedPages.HasMoreElements()) + { + SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement()); + mrSlideSorter.GetController().GetCurrentSlideManager()->NotifyCurrentSlideChange( + pDescriptor->GetPage()); + } + + ViewShell* pViewShell = mrSlideSorter.GetViewShell(); + if (pViewShell != nullptr) + { + SdPage* pPage = pViewShell->getCurrentPage(); + if (pPage != nullptr) + mrSlideSorter.GetController().GetCurrentSlideManager()->NotifyCurrentSlideChange( + pPage); + else + { + // No current page. This can only be when the slide sorter is + // the main view shell. Get current slide form frame view. + const FrameView* pFrameView = pViewShell->GetFrameView(); + if (pFrameView != nullptr) + mrSlideSorter.GetController().GetCurrentSlideManager()->NotifyCurrentSlideChange( + pFrameView->GetSelectedPage()); + else + { + // No frame view. As a last resort use the first slide as + // current slide. + mrSlideSorter.GetController().GetCurrentSlideManager()->NotifyCurrentSlideChange( + sal_Int32(0)); + } + } + } + + mrSlideSorter.GetController().GetSlotManager()->NotifyEditModeChange(); +} + +Reference<container::XIndexAccess> SlideSorterModel::GetDocumentSlides() const +{ + ::osl::MutexGuard aGuard (maMutex); + return mxSlides; +} + +void SlideSorterModel::UpdatePageList() +{ + ::osl::MutexGuard aGuard (maMutex); + + Reference<container::XIndexAccess> xPages; + + // Get the list of pages according to the edit mode. + Reference<frame::XController> xController (mrSlideSorter.GetXController()); + if (xController.is()) + { + switch (meEditMode) + { + case EditMode::MasterPage: + { + Reference<drawing::XMasterPagesSupplier> xSupplier ( + xController->getModel(), UNO_QUERY); + if (xSupplier.is()) + { + xPages = xSupplier->getMasterPages(); + } + } + break; + + case EditMode::Page: + { + Reference<drawing::XDrawPagesSupplier> xSupplier ( + xController->getModel(), UNO_QUERY); + if (xSupplier.is()) + { + xPages = xSupplier->getDrawPages(); + } + } + break; + + default: + // We should never get here. + assert(false); + break; + } + } + + mrSlideSorter.GetController().SetDocumentSlides(xPages); +} + +void SlideSorterModel::AdaptSize() +{ + if (mxSlides.is()) + maPageDescriptors.resize(mxSlides->getCount()); + else + maPageDescriptors.resize(0); +} + +bool SlideSorterModel::IsReadOnly() const +{ + if (mrSlideSorter.GetViewShellBase() != nullptr + && mrSlideSorter.GetViewShellBase()->GetDocShell()) + return mrSlideSorter.GetViewShellBase()->GetDocShell()->IsReadOnly(); + else + return true; +} + +void SlideSorterModel::SaveCurrentSelection() +{ + PageEnumeration aPages (PageEnumerationProvider::CreateAllPagesEnumeration(*this)); + while (aPages.HasMoreElements()) + { + SharedPageDescriptor pDescriptor (aPages.GetNextElement()); + pDescriptor->SetState( + PageDescriptor::ST_WasSelected, + pDescriptor->HasState(PageDescriptor::ST_Selected)); + } +} + +vcl::Region SlideSorterModel::RestoreSelection() +{ + vcl::Region aRepaintRegion; + PageEnumeration aPages (PageEnumerationProvider::CreateAllPagesEnumeration(*this)); + while (aPages.HasMoreElements()) + { + SharedPageDescriptor pDescriptor (aPages.GetNextElement()); + if (pDescriptor->SetState( + PageDescriptor::ST_Selected, + pDescriptor->HasState(PageDescriptor::ST_WasSelected))) + { + aRepaintRegion.Union(pDescriptor->GetBoundingBox()); + } + } + return aRepaintRegion; +} + +bool SlideSorterModel::NotifyPageEvent (const SdrPage* pSdrPage) +{ + ::osl::MutexGuard aGuard (maMutex); + + SdPage* pPage = const_cast<SdPage*>(dynamic_cast<const SdPage*>(pSdrPage)); + if (pPage == nullptr) + return false; + + // We are only interested in pages that are currently served by this + // model. + if (pPage->GetPageKind() != PageKind::Standard) + return false; + if (pPage->IsMasterPage() != (meEditMode==EditMode::MasterPage)) + return false; + + //NotifyPageEvent is called for add, remove, *and* change position so for + //the change position case we must ensure we don't end up with the slide + //duplicated in our list + bool bSelected = DeleteSlide(pPage); + if (pPage->IsInserted()) + { + InsertSlide(pPage, bSelected); + } + CheckModel(*this); + + return true; +} + +void SlideSorterModel::InsertSlide(SdPage* pPage, bool bMarkSelected) +{ + // Find the index at which to insert the given page. + sal_uInt16 nCoreIndex (pPage->GetPageNum()); + sal_Int32 nIndex (FromCoreIndex(nCoreIndex)); + if (pPage != GetPage(nIndex)) + return; + + // Check that the pages in the document before and after the given page + // are present in this model. + if (nIndex>0) + if (GetPage(nIndex-1) != GetPageDescriptor(nIndex-1)->GetPage()) + return; + if (nIndex < static_cast<sal_Int32>(maPageDescriptors.size()) -1) + if (GetPage(nIndex+1) != GetPageDescriptor(nIndex)->GetPage()) + return; + + auto iter = maPageDescriptors.begin() + nIndex; + + // Insert the given page at index nIndex + iter = maPageDescriptors.insert( + iter, + std::make_shared<PageDescriptor>( + Reference<drawing::XDrawPage>(mxSlides->getByIndex(nIndex),UNO_QUERY), + pPage, + nIndex)); + + if (bMarkSelected) + (*iter)->SetState(PageDescriptor::ST_Selected, true); + + // Update page indices. + UpdateIndices(nIndex+1); +} + +bool SlideSorterModel::DeleteSlide (const SdPage* pPage) +{ + sal_Int32 nIndex(0); + + // Caution, GetIndex() may be negative since it uses GetPageNumber()-1 + // for calculation, so do this only when page is inserted, else the + // GetPageNumber() will be zero and thus GetIndex() == -1 + if(pPage->IsInserted()) + { + nIndex = GetIndex(pPage); + } + else + { + // if not inserted, search for page + for(; nIndex < static_cast<sal_Int32>(maPageDescriptors.size()); nIndex++) + { + if(maPageDescriptors[nIndex]->GetPage() == pPage) + { + break; + } + } + } + + bool bMarkedSelected(false); + + if(nIndex >= 0 && o3tl::make_unsigned(nIndex) < maPageDescriptors.size()) + { + if (maPageDescriptors[nIndex]) + if (maPageDescriptors[nIndex]->GetPage() != pPage) + return false; + + auto iter = maPageDescriptors.begin() + nIndex; + bMarkedSelected = (*iter)->HasState(PageDescriptor::ST_Selected); + maPageDescriptors.erase(iter); + UpdateIndices(nIndex); + + collectUIInformation(OUString::number(nIndex + 1), "Delete_Slide_or_Page"); + } + return bMarkedSelected; +} + +void SlideSorterModel::UpdateIndices (const sal_Int32 nFirstIndex) +{ + for (sal_Int32 nDescriptorIndex=0,nCount=maPageDescriptors.size(); + nDescriptorIndex<nCount; + ++nDescriptorIndex) + { + SharedPageDescriptor& rpDescriptor (maPageDescriptors[nDescriptorIndex]); + if (rpDescriptor) + { + if (nDescriptorIndex < nFirstIndex) + { + if (rpDescriptor->GetPageIndex()!=nDescriptorIndex) + { + assert(rpDescriptor->GetPageIndex()==nDescriptorIndex); + } + } + else + { + rpDescriptor->SetPageIndex(nDescriptorIndex); + } + } + } +} + +SdPage* SlideSorterModel::GetPage (const sal_Int32 nSdIndex) const +{ + SdDrawDocument* pModel = const_cast<SlideSorterModel*>(this)->GetDocument(); + if (pModel != nullptr) + { + if (meEditMode == EditMode::Page) + return pModel->GetSdPage (static_cast<sal_uInt16>(nSdIndex), PageKind::Standard); + else + return pModel->GetMasterSdPage (static_cast<sal_uInt16>(nSdIndex), PageKind::Standard); + } + else + return nullptr; +} + +} // end of namespace ::sd::slidesorter::model + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/model/SlsPageDescriptor.cxx b/sd/source/ui/slidesorter/model/SlsPageDescriptor.cxx new file mode 100644 index 000000000..5118cf58e --- /dev/null +++ b/sd/source/ui/slidesorter/model/SlsPageDescriptor.cxx @@ -0,0 +1,226 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <model/SlsPageDescriptor.hxx> + +#include <sdpage.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star; + +namespace sd::slidesorter::model { + +PageDescriptor::PageDescriptor ( + const Reference<drawing::XDrawPage>& rxPage, + SdPage* pPage, + const sal_Int32 nIndex) + : mpPage(pPage), + mxPage(rxPage), + mpMasterPage(nullptr), + mnIndex(nIndex), + maVisualState(nIndex), + mbIsSelected(false), + mbWasSelected(false), + mbIsVisible(false), + mbIsFocused(false), + mbIsCurrent(false), + mbIsMouseOver(false), + mbHasTransition(false) +{ + assert(mpPage); + assert(mpPage == SdPage::getImplementation(rxPage)); + if (mpPage != nullptr) + { + if (mpPage->TRG_HasMasterPage()) + mpMasterPage = &mpPage->TRG_GetMasterPage(); + if (mpPage->getTransitionType() > 0) + mbHasTransition = true; + } +} + +PageDescriptor::~PageDescriptor() +{ +} + +void PageDescriptor::SetPageIndex (const sal_Int32 nNewIndex) +{ + mnIndex = nNewIndex; + maVisualState.mnPageId = nNewIndex; +} + +bool PageDescriptor::UpdateMasterPage() +{ + const SdrPage* pMaster = nullptr; + if (mpPage!=nullptr && mpPage->TRG_HasMasterPage()) + pMaster = &mpPage->TRG_GetMasterPage(); + if (mpMasterPage != pMaster) + { + mpMasterPage = pMaster; + return true; + } + else + return false; +} + +bool PageDescriptor::UpdateTransitionFlag() +{ + bool bHasSlideTransition (false); + if (mpPage != nullptr) + bHasSlideTransition = mpPage->getTransitionType() > 0; + if (bHasSlideTransition != mbHasTransition) + { + mbHasTransition = bHasSlideTransition; + return true; + } + else + return false; +} + +bool PageDescriptor::HasState (const State eState) const +{ + switch (eState) + { + case ST_Visible: + return mbIsVisible; + + case ST_Selected: + return mbIsSelected; + + case ST_WasSelected: + return mbWasSelected; + + case ST_Focused: + return mbIsFocused; + + case ST_MouseOver: + return mbIsMouseOver; + + case ST_Current: + return mbIsCurrent; + + case ST_Excluded: + return mpPage!=nullptr && mpPage->IsExcluded(); + + default: + assert(false); + return false; + } +} + +bool PageDescriptor::SetState (const State eState, const bool bNewStateValue) +{ + bool bModified (false); + switch (eState) + { + case ST_Visible: + bModified = (bNewStateValue!=mbIsVisible); + if (bModified) + mbIsVisible = bNewStateValue; + break; + + case ST_Selected: + bModified = (bNewStateValue!=mbIsSelected); + if (bModified) + mbIsSelected = bNewStateValue; + break; + + case ST_WasSelected: + bModified = (bNewStateValue!=mbWasSelected); + if (bModified) + mbWasSelected = bNewStateValue; + break; + + case ST_Focused: + bModified = (bNewStateValue!=mbIsFocused); + if (bModified) + mbIsFocused = bNewStateValue; + break; + + case ST_MouseOver: + bModified = (bNewStateValue!=mbIsMouseOver); + if (bModified) + mbIsMouseOver = bNewStateValue; + break; + + case ST_Current: + bModified = (bNewStateValue!=mbIsCurrent); + if (bModified) + mbIsCurrent = bNewStateValue; + break; + + case ST_Excluded: + // This is a state of the page and has to be handled differently + // from the view-only states. + if (mpPage != nullptr) + if (bNewStateValue != mpPage->IsExcluded()) + { + mpPage->SetExcluded(bNewStateValue); + bModified = true; + } + break; + } + + return bModified; +} + +bool PageDescriptor::GetCoreSelection() +{ + if (mpPage!=nullptr && mpPage->IsSelected() != mbIsSelected) + return SetState(ST_Selected, !mbIsSelected); + else + return false; +} + +void PageDescriptor::SetCoreSelection() +{ + if (mpPage != nullptr) + if (HasState(ST_Selected)) + mpPage->SetSelected(true); + else + mpPage->SetSelected(false); + else + { + assert(mpPage!=nullptr); + } +} + +::tools::Rectangle PageDescriptor::GetBoundingBox() const +{ + ::tools::Rectangle aBox (maBoundingBox); + const Point aOffset (maVisualState.GetLocationOffset()); + aBox.Move(aOffset.X(), aOffset.Y()); + return aBox; +} + +Point PageDescriptor::GetLocation (const bool bIgnoreOffset) const +{ + if (bIgnoreOffset) + return maBoundingBox.TopLeft(); + else + return maBoundingBox.TopLeft() + maVisualState.GetLocationOffset(); +} + +void PageDescriptor::SetBoundingBox (const ::tools::Rectangle& rBoundingBox) +{ + maBoundingBox = rBoundingBox; +} + +} // end of namespace ::sd::slidesorter::model + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/model/SlsPageEnumeration.cxx b/sd/source/ui/slidesorter/model/SlsPageEnumeration.cxx new file mode 100644 index 000000000..a67f057e7 --- /dev/null +++ b/sd/source/ui/slidesorter/model/SlsPageEnumeration.cxx @@ -0,0 +1,202 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <memory> +#include <sal/config.h> + +#include <utility> + +#include <model/SlsPageEnumeration.hxx> +#include <model/SlideSorterModel.hxx> + +using namespace ::sd::slidesorter; +using namespace ::sd::slidesorter::model; + +namespace { + +class PageEnumerationImpl + : public Enumeration<SharedPageDescriptor> +{ +public: + PageEnumerationImpl ( + const SlideSorterModel& rModel, + const PageEnumeration::PagePredicate& rPredicate); + PageEnumerationImpl(const PageEnumerationImpl&) = delete; + PageEnumerationImpl& operator=(const PageEnumerationImpl&) = delete; + /** Create a copy of the called enumeration object. + */ + virtual ::std::unique_ptr<Enumeration<SharedPageDescriptor> > Clone() override; + + virtual bool HasMoreElements() const override; + virtual SharedPageDescriptor GetNextElement() override; + virtual void Rewind() override; + +private: + const SlideSorterModel& mrModel; + const PageEnumeration::PagePredicate maPredicate; + int mnIndex; + + /** This constructor sets the internal page index to the given value. + It does not call AdvanceToNextValidElement() to skip elements that + do not fulfill Predicate. + */ + PageEnumerationImpl ( + const SlideSorterModel& rModel, + const PageEnumeration::PagePredicate& rPredicate, + int nIndex); + + /** Skip all elements that do not fulfill Predicate starting with the + one pointed to by mnIndex. + */ + void AdvanceToNextValidElement(); +}; + +} // end of anonymous namespace + +namespace sd::slidesorter::model { + +PageEnumeration PageEnumeration::Create ( + const SlideSorterModel& rModel, + const PagePredicate& rPredicate) +{ + return PageEnumeration(::std::unique_ptr<Enumeration<SharedPageDescriptor> >( + new PageEnumerationImpl(rModel, rPredicate))); +} + +PageEnumeration::PageEnumeration ( + ::std::unique_ptr<Enumeration<SharedPageDescriptor> > && pImpl) + : mpImpl(std::move(pImpl)) +{ +} + +PageEnumeration::PageEnumeration (const PageEnumeration& rEnumeration ) +: sd::slidesorter::model::Enumeration<sd::slidesorter::model::SharedPageDescriptor>() +{ + mpImpl = rEnumeration.mpImpl->Clone(); +} + +PageEnumeration::~PageEnumeration() +{ +} + +PageEnumeration& PageEnumeration::operator= ( + const PageEnumeration& rEnumeration) +{ + mpImpl = rEnumeration.mpImpl->Clone(); + return *this; +} + +::std::unique_ptr<Enumeration<SharedPageDescriptor> > PageEnumeration::Clone() +{ + return ::std::unique_ptr<Enumeration<SharedPageDescriptor> >( + new PageEnumeration (*this)); +} + +bool PageEnumeration::HasMoreElements() const +{ + return mpImpl->HasMoreElements(); +} + +SharedPageDescriptor PageEnumeration::GetNextElement() +{ + return mpImpl->GetNextElement(); +} + +void PageEnumeration::Rewind() +{ + return mpImpl->Rewind(); +} + +} // end of namespace ::sd::slidesorter::model + +namespace { + +PageEnumerationImpl::PageEnumerationImpl ( + const SlideSorterModel& rModel, + const PageEnumeration::PagePredicate& rPredicate) + : mrModel(rModel), + maPredicate(rPredicate), + mnIndex(0) +{ + Rewind(); +} + +PageEnumerationImpl::PageEnumerationImpl ( + const SlideSorterModel& rModel, + const PageEnumeration::PagePredicate& rPredicate, + int nIndex) + : mrModel(rModel), + maPredicate(rPredicate), + mnIndex(nIndex) +{ +} + +::std::unique_ptr<Enumeration<SharedPageDescriptor> > + PageEnumerationImpl::Clone() +{ + return ::std::unique_ptr<Enumeration<SharedPageDescriptor> >( + new PageEnumerationImpl(mrModel,maPredicate,mnIndex)); +} + +bool PageEnumerationImpl::HasMoreElements() const +{ + return (mnIndex < mrModel.GetPageCount()); +} + +SharedPageDescriptor PageEnumerationImpl::GetNextElement() +{ + SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(mnIndex)); + + // Go to the following valid element. + mnIndex += 1; + AdvanceToNextValidElement(); + + return pDescriptor; +} + +void PageEnumerationImpl::Rewind() +{ + // Go to first valid element. + mnIndex = 0; + AdvanceToNextValidElement(); +} + +void PageEnumerationImpl::AdvanceToNextValidElement() +{ + while (mnIndex < mrModel.GetPageCount()) + { + SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(mnIndex)); + + // Test for the predicate being fulfilled. + if (pDescriptor && maPredicate(pDescriptor)) + { + // This predicate is valid. + break; + } + else + { + // Advance to next predicate. + mnIndex += 1; + } + } +} + +} // end of anonymous namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/model/SlsPageEnumerationProvider.cxx b/sd/source/ui/slidesorter/model/SlsPageEnumerationProvider.cxx new file mode 100644 index 000000000..800fa12db --- /dev/null +++ b/sd/source/ui/slidesorter/model/SlsPageEnumerationProvider.cxx @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <model/SlsPageEnumerationProvider.hxx> +#include <model/SlsPageEnumeration.hxx> +#include <model/SlsPageDescriptor.hxx> + +namespace sd::slidesorter::model { + +namespace { + +class AllPagesPredicate +{ +public: + bool operator() (const SharedPageDescriptor&) const + { + return true; + } +}; + +class SelectedPagesPredicate +{ +public: + bool operator() (const SharedPageDescriptor& rpDescriptor) + { + return rpDescriptor->HasState(PageDescriptor::ST_Selected); + } +}; + +class VisiblePagesPredicate +{ +public: + bool operator() (const SharedPageDescriptor& rpDescriptor) + { + return rpDescriptor->HasState(PageDescriptor::ST_Visible); + } +}; + +} + +PageEnumeration PageEnumerationProvider::CreateAllPagesEnumeration ( + const SlideSorterModel& rModel) +{ + return PageEnumeration::Create(rModel, AllPagesPredicate()); +} + +PageEnumeration PageEnumerationProvider::CreateSelectedPagesEnumeration ( + const SlideSorterModel& rModel) +{ + return PageEnumeration::Create( + rModel, + SelectedPagesPredicate()); +} + +PageEnumeration PageEnumerationProvider::CreateVisiblePagesEnumeration ( + const SlideSorterModel& rModel) +{ + return PageEnumeration::Create( + rModel, + VisiblePagesPredicate()); +} + +} // end of namespace ::sd::slidesorter::model + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/slidesorter/model/SlsVisualState.cxx b/sd/source/ui/slidesorter/model/SlsVisualState.cxx new file mode 100644 index 000000000..3e16823ff --- /dev/null +++ b/sd/source/ui/slidesorter/model/SlsVisualState.cxx @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <model/SlsVisualState.hxx> + +namespace sd::slidesorter::model +{ +VisualState::VisualState(const sal_Int32 nPageId) + : mnPageId(nPageId) + , maLocationOffset(0, 0) +{ +} + +void VisualState::SetLocationOffset(const Point& rOffset) +{ + if (maLocationOffset != rOffset) + { + maLocationOffset = rOffset; + } +} + +} // end of namespace ::sd::slidesorter::model + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |