summaryrefslogtreecommitdiff
path: root/sd/source/ui/slidesorter/model/SlideSorterModel.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sd/source/ui/slidesorter/model/SlideSorterModel.cxx')
-rw-r--r--sd/source/ui/slidesorter/model/SlideSorterModel.cxx735
1 files changed, 735 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 000000000000..5eaf64db7bf8
--- /dev/null
+++ b/sd/source/ui/slidesorter/model/SlideSorterModel.cxx
@@ -0,0 +1,735 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "model/SlideSorterModel.hxx"
+
+#include "SlideSorter.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "model/SlsPageEnumerationProvider.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsProperties.hxx"
+#include "controller/SlsPageSelector.hxx"
+#include "controller/SlsCurrentSlideManager.hxx"
+#include "controller/SlsSlotManager.hxx"
+#include "view/SlideSorterView.hxx"
+#include "taskpane/SlideSorterCacheDisplay.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/beans/UnknownPropertyException.hpp>
+
+#include "ViewShellBase.hxx"
+#include "DrawViewShell.hxx"
+#include "DrawDocShell.hxx"
+#include "drawdoc.hxx"
+#include "sdpage.hxx"
+#include "FrameView.hxx"
+
+#include <tools/diagnose_ex.h>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace sd { namespace slidesorter { namespace model {
+
+namespace {
+ class CompareToXDrawPage
+ {
+ public:
+ CompareToXDrawPage (const Reference<drawing::XDrawPage>& rxSlide) : mxSlide(rxSlide) {}
+ bool operator() (const SharedPageDescriptor& rpDescriptor)
+ { return rpDescriptor.get()!=NULL && rpDescriptor->GetXDrawPage()==mxSlide; }
+ private:
+ Reference<drawing::XDrawPage> mxSlide;
+ };
+
+ bool PrintModel (const SlideSorterModel& rModel)
+ {
+ for (sal_Int32 nIndex=0,nCount=rModel.GetPageCount(); nIndex<nCount; ++nIndex)
+ {
+ SharedPageDescriptor pDescriptor (rModel.GetPageDescriptor(nIndex));
+ if (pDescriptor)
+ {
+ OSL_TRACE("%d %d %d %d %x",
+ nIndex,
+ pDescriptor->GetPageIndex(),
+ pDescriptor->GetVisualState().mnPageId,
+ FromCoreIndex(pDescriptor->GetPage()->GetPageNum()),
+ pDescriptor->GetPage());
+ }
+ else
+ {
+ OSL_TRACE("%d", 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);
+ OSL_ASSERT(pDescriptor);
+ return false;
+ }
+ if (nIndex != pDescriptor->GetPageIndex())
+ {
+ PrintModel(rModel);
+ OSL_ASSERT(nIndex == pDescriptor->GetPageIndex());
+ return false;
+ }
+ if (nIndex != pDescriptor->GetVisualState().mnPageId)
+ {
+ PrintModel(rModel);
+ OSL_ASSERT(nIndex == pDescriptor->GetVisualState().mnPageId);
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
+
+
+
+
+SlideSorterModel::SlideSorterModel (SlideSorter& rSlideSorter)
+ : maMutex(),
+ mrSlideSorter(rSlideSorter),
+ mxSlides(),
+ mePageKind(PK_STANDARD),
+ meEditMode(EM_PAGE),
+ maPageDescriptors(0)
+{
+}
+
+
+
+
+SlideSorterModel::~SlideSorterModel (void)
+{
+ ClearDescriptorList ();
+}
+
+
+
+
+void SlideSorterModel::Init (void)
+{
+}
+
+
+
+
+void SlideSorterModel::Dispose (void)
+{
+ ClearDescriptorList ();
+}
+
+
+
+
+SdDrawDocument* SlideSorterModel::GetDocument (void)
+{
+ if (mrSlideSorter.GetViewShellBase() != NULL)
+ return mrSlideSorter.GetViewShellBase()->GetDocument();
+ else
+ return NULL;
+}
+
+
+
+
+bool SlideSorterModel::SetEditMode (EditMode eEditMode)
+{
+ bool bEditModeChanged = false;
+ if (meEditMode != eEditMode)
+ {
+ meEditMode = eEditMode;
+ UpdatePageList();
+ ClearDescriptorList();
+ bEditModeChanged = true;
+ }
+ return bEditModeChanged;
+}
+
+
+
+
+EditMode SlideSorterModel::GetEditMode (void) const
+{
+ return meEditMode;
+}
+
+
+
+
+PageKind SlideSorterModel::GetPageType (void) const
+{
+ return mePageKind;
+}
+
+
+
+
+sal_Int32 SlideSorterModel::GetPageCount (void) 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 == NULL && bCreate && mxSlides.is())
+ {
+ SdPage* pPage = GetPage(nPageIndex);
+ pDescriptor.reset(new 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(::rtl::OUString::createFromAscii("Number")));
+ sal_Int16 nNumber (-1);
+ aNumber >>= nNumber;
+ nNumber -= 1;
+ SharedPageDescriptor pDescriptor (GetPageDescriptor(nNumber, false));
+ if (pDescriptor.get() != NULL
+ && pDescriptor->GetXDrawPage() == rxSlide)
+ {
+ return nNumber;
+ }
+ }
+ catch (uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+
+ // 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.get() == NULL)
+ {
+ // Call GetPageDescriptor() to create the missing descriptor.
+ pDescriptor = GetPageDescriptor(nIndex,true);
+ }
+
+ if (pDescriptor->GetXDrawPage() == rxSlide)
+ return nIndex;
+ }
+
+ return -1;
+}
+
+
+
+
+sal_Int32 SlideSorterModel::GetIndex (const SdrPage* pPage) const
+{
+ if (pPage == NULL)
+ 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.get() != NULL
+ && 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.get() == NULL)
+ {
+ // Call GetPageDescriptor() to create the missing descriptor.
+ pDescriptor = GetPageDescriptor(nIndex, true);
+ }
+
+ if (pDescriptor->GetPage() == pPage)
+ return nIndex;
+ }
+
+ return -1;
+}
+
+
+
+
+USHORT 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 (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ // Check if document and this model really differ.
+ bool bIsUpToDate (true);
+ SdDrawDocument* pDocument = GetDocument();
+ if (pDocument!=NULL && maPageDescriptors.size()==pDocument->GetSdPageCount(mePageKind))
+ {
+ for (sal_Int32 nIndex=0,nCount=maPageDescriptors.size(); nIndex<nCount; ++nIndex)
+ {
+ if (maPageDescriptors[nIndex]
+ && maPageDescriptors[nIndex]->GetPage()
+ != GetPage(nIndex))
+ {
+ OSL_TRACE("page %d differs\n", nIndex);
+ bIsUpToDate = false;
+ break;
+ }
+ }
+ }
+ else
+ {
+ bIsUpToDate = false;
+ OSL_TRACE("models differ");
+ }
+
+ if ( ! bIsUpToDate)
+ {
+ SynchronizeDocumentSelection(); // Try to make the current selection persistent.
+ ClearDescriptorList ();
+ AdaptSize();
+ SynchronizeModelSelection();
+ mrSlideSorter.GetController().GetPageSelector().CountSelectedPages();
+ }
+ CheckModel(*this);
+}
+
+
+
+
+void SlideSorterModel::ClearDescriptorList (void)
+{
+ DescriptorContainer aDescriptors;
+
+ {
+ ::osl::MutexGuard aGuard (maMutex);
+ aDescriptors.swap(maPageDescriptors);
+ }
+
+ for (DescriptorContainer::iterator iDescriptor=aDescriptors.begin(), iEnd=aDescriptors.end();
+ iDescriptor!=iEnd;
+ ++iDescriptor)
+ {
+ if (iDescriptor->get() != NULL)
+ {
+ if ( ! iDescriptor->unique())
+ {
+ OSL_TRACE("SlideSorterModel::ClearDescriptorList: trying to delete page descriptor that is still used with count %d", iDescriptor->use_count());
+ // No assertion here because that can hang the office when
+ // opening a dialog from here.
+ }
+ iDescriptor->reset();
+ }
+ }
+}
+
+
+
+
+void SlideSorterModel::SynchronizeDocumentSelection (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ PageEnumeration aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(*this));
+ while (aAllPages.HasMoreElements())
+ {
+ SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
+ pDescriptor->GetPage()->SetSelected(pDescriptor->HasState(PageDescriptor::ST_Selected));
+ }
+}
+
+
+
+
+void SlideSorterModel::SynchronizeModelSelection (void)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ PageEnumeration aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(*this));
+ while (aAllPages.HasMoreElements())
+ {
+ SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
+ pDescriptor->SetState(PageDescriptor::ST_Selected, pDescriptor->GetPage()->IsSelected());
+ }
+}
+
+
+
+
+::osl::Mutex& SlideSorterModel::GetMutex (void)
+{
+ return maMutex;
+}
+
+
+
+
+void SlideSorterModel::SetDocumentSlides (
+ const Reference<container::XIndexAccess>& rxSlides)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ // Reset the current page so to cause everbody to release references to it.
+ mrSlideSorter.GetController().GetCurrentSlideManager()->NotifyCurrentSlideChange(-1);
+
+ mxSlides = rxSlides;
+ Resync();
+
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+ if (pViewShell != NULL)
+ {
+ SdPage* pPage = pViewShell->getCurrentPage();
+ if (pPage != NULL)
+ 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 != NULL)
+ 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 (void) const
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ return mxSlides;
+}
+
+
+
+
+void SlideSorterModel::UpdatePageList (void)
+{
+ ::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 EM_MASTERPAGE:
+ {
+ Reference<drawing::XMasterPagesSupplier> xSupplier (
+ xController->getModel(), UNO_QUERY);
+ if (xSupplier.is())
+ {
+ xPages = Reference<container::XIndexAccess>(
+ xSupplier->getMasterPages(), UNO_QUERY);
+ }
+ }
+ break;
+
+ case EM_PAGE:
+ {
+ Reference<drawing::XDrawPagesSupplier> xSupplier (
+ xController->getModel(), UNO_QUERY);
+ if (xSupplier.is())
+ {
+ xPages = Reference<container::XIndexAccess>(
+ xSupplier->getDrawPages(), UNO_QUERY);
+ }
+ }
+ break;
+
+ default:
+ // We should never get here.
+ OSL_ASSERT(false);
+ break;
+ }
+ }
+
+ mrSlideSorter.GetController().SetDocumentSlides(xPages);
+}
+
+
+
+
+void SlideSorterModel::AdaptSize (void)
+{
+ if (mxSlides.is())
+ maPageDescriptors.resize(mxSlides->getCount());
+ else
+ maPageDescriptors.resize(0);
+}
+
+
+
+
+bool SlideSorterModel::IsReadOnly (void) const
+{
+ if (mrSlideSorter.GetViewShellBase() != NULL
+ && mrSlideSorter.GetViewShellBase()->GetDocShell())
+ return mrSlideSorter.GetViewShellBase()->GetDocShell()->IsReadOnly();
+ else
+ return true;
+}
+
+
+
+
+void SlideSorterModel::SaveCurrentSelection (void)
+{
+ PageEnumeration aPages (PageEnumerationProvider::CreateAllPagesEnumeration(*this));
+ while (aPages.HasMoreElements())
+ {
+ SharedPageDescriptor pDescriptor (aPages.GetNextElement());
+ pDescriptor->SetState(
+ PageDescriptor::ST_WasSelected,
+ pDescriptor->HasState(PageDescriptor::ST_Selected));
+ }
+}
+
+
+
+
+Region SlideSorterModel::RestoreSelection (void)
+{
+ 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 == NULL)
+ return false;
+
+ // We are only interested in pages that are currently served by this
+ // model.
+ if (pPage->GetPageKind() != mePageKind)
+ return false;
+ if (pPage->IsMasterPage() != (meEditMode==EM_MASTERPAGE))
+ return false;
+
+ if (pPage->IsInserted())
+ InsertSlide(pPage);
+ else
+ DeleteSlide(pPage);
+ CheckModel(*this);
+
+ return true;
+}
+
+
+
+
+void SlideSorterModel::InsertSlide (SdPage* pPage)
+{
+ // Find the index at which to insert the given page.
+ USHORT 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 (size_t(nIndex)<maPageDescriptors.size()-1)
+ if (GetPage(nIndex+1) != GetPageDescriptor(nIndex)->GetPage())
+ return;
+
+ // Insert the given page at index nIndex
+ maPageDescriptors.insert(
+ maPageDescriptors.begin()+nIndex,
+ SharedPageDescriptor(
+ new PageDescriptor (
+ Reference<drawing::XDrawPage>(mxSlides->getByIndex(nIndex),UNO_QUERY),
+ pPage,
+ nIndex)));
+
+ // Update page indices.
+ UpdateIndices(nIndex+1);
+ OSL_TRACE("page inserted");
+}
+
+
+
+
+void SlideSorterModel::DeleteSlide (const SdPage* pPage)
+{
+ const sal_Int32 nIndex (GetIndex(pPage));
+ if (maPageDescriptors[nIndex])
+ if (maPageDescriptors[nIndex]->GetPage() != pPage)
+ return;
+
+ maPageDescriptors.erase(maPageDescriptors.begin()+nIndex);
+ UpdateIndices(nIndex);
+ OSL_TRACE("page removed");
+}
+
+
+
+
+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)
+ {
+ OSL_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 != NULL)
+ {
+ if (meEditMode == EM_PAGE)
+ return pModel->GetSdPage ((USHORT)nSdIndex, mePageKind);
+ else
+ return pModel->GetMasterSdPage ((USHORT)nSdIndex, mePageKind);
+ }
+ else
+ return NULL;
+}
+
+
+} } } // end of namespace ::sd::slidesorter::model