diff options
Diffstat (limited to 'sd/source/ui/slidesorter/controller')
23 files changed, 8593 insertions, 0 deletions
diff --git a/sd/source/ui/slidesorter/controller/SlideSorterController.cxx b/sd/source/ui/slidesorter/controller/SlideSorterController.cxx new file mode 100755 index 000000000000..69c2a02ddc24 --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlideSorterController.cxx @@ -0,0 +1,1000 @@ +/************************************************************************* + * + * 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 "controller/SlideSorterController.hxx" + +#include "SlideSorter.hxx" +#include "controller/SlsPageSelector.hxx" +#include "controller/SlsSelectionFunction.hxx" +#include "controller/SlsProperties.hxx" +#include "controller/SlsCurrentSlideManager.hxx" +#include "SlsListener.hxx" +#include "controller/SlsFocusManager.hxx" +#include "SlsSelectionCommand.hxx" +#include "controller/SlsAnimator.hxx" +#include "controller/SlsClipboard.hxx" +#include "controller/SlsScrollBarManager.hxx" +#include "controller/SlsPageObjectFactory.hxx" +#include "controller/SlsSelectionManager.hxx" +#include "controller/SlsSlotManager.hxx" +#include "model/SlideSorterModel.hxx" +#include "model/SlsPageEnumerationProvider.hxx" +#include "model/SlsPageDescriptor.hxx" +#include "view/SlideSorterView.hxx" +#include "view/SlsLayouter.hxx" +#include "view/SlsViewOverlay.hxx" +#include "view/SlsFontProvider.hxx" +#include "cache/SlsPageCache.hxx" +#include "cache/SlsPageCacheManager.hxx" + +#include "drawdoc.hxx" +#include "DrawViewShell.hxx" +#include "TextLogger.hxx" +#include "ViewShellBase.hxx" +#include "Window.hxx" +#include "FrameView.hxx" +#include "DrawDocShell.hxx" +#include "sdpage.hxx" +#include "res_bmp.hrc" +#include "sdresid.hxx" +#include "strings.hrc" +#include "app.hrc" +#include "glob.hrc" +#include "sdmod.hxx" +#include "sdxfer.hxx" +#include "FrameView.hxx" +#include "ViewShellHint.hxx" +#include "AccessibleSlideSorterView.hxx" +#include "AccessibleSlideSorterObject.hxx" + +#include <vcl/window.hxx> +#include <svx/svdopage.hxx> +#include <svx/svxids.hrc> +#include <svx/ruler.hxx> +#include <svx/zoomitem.hxx> +#include <svtools/tabbar.hxx> +#include <sfx2/request.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/dispatch.hxx> +#include <tools/link.hxx> +#include <vcl/svapp.hxx> + +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/drawing/XMasterPagesSupplier.hpp> +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/drawing/XDrawPages.hpp> +#include <com/sun/star/accessibility/AccessibleEventId.hpp> + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::sd::slidesorter::model; +using namespace ::sd::slidesorter::view; +using namespace ::sd::slidesorter::controller; + +namespace sd { namespace slidesorter { namespace controller { + + +SlideSorterController::SlideSorterController (SlideSorter& rSlideSorter) + : mrSlideSorter(rSlideSorter), + mrModel(mrSlideSorter.GetModel()), + mrView(mrSlideSorter.GetView()), + mpPageSelector(), + mpFocusManager(), + mpSlotManager(), + mpClipboard(), + mpScrollBarManager(), + mpCurrentSlideManager(), + mpSelectionManager(), + mpAnimator(new Animator(rSlideSorter)), + mpListener(), + mnModelChangeLockCount(0), + mbPreModelChangeDone(false), + mbPostModelChangePending(false), + maSelectionBeforeSwitch(), + mnCurrentPageBeforeSwitch(0), + mpEditModeChangeMasterPage(NULL), + maTotalWindowArea(), + mnPaintEntranceCount(0), + mbIsContextMenuOpen(false), + mpProperties(new Properties()) +{ + ::sd::Window* pWindow = mrSlideSorter.GetActiveWindow(); + OSL_ASSERT(pWindow!=NULL); + if (pWindow != NULL) + { + // The whole background is painted by the view and controls. + ::Window* pParentWindow = pWindow->GetParent(); + OSL_ASSERT(pParentWindow!=NULL); + pParentWindow->SetBackground (Wallpaper()); + + // Connect the view with the window that has been created by our base + // class. + pWindow->SetBackground (Wallpaper()); + mrView.AddWindowToPaintView(pWindow); + mrView.SetActualWin(pWindow); + pWindow->SetCenterAllowed (false); + pWindow->SetViewSize (mrView.GetModelArea().GetSize()); + pWindow->EnableRTL(FALSE); + + // Reinitialize colors in Properties with window specific values. + mpProperties->SetBackgroundColor( + pWindow->GetSettings().GetStyleSettings().GetWindowColor()); + mpProperties->SetTextColor( + pWindow->GetSettings().GetStyleSettings().GetWindowTextColor()); + mpProperties->SetSelectionColor( + pWindow->GetSettings().GetStyleSettings().GetMenuHighlightColor()); + mpProperties->SetHighlightColor( + pWindow->GetSettings().GetStyleSettings().GetMenuHighlightColor()); + } +} + + + + +void SlideSorterController::Init (void) +{ + mrView.HandleModelChange(); + + mpCurrentSlideManager.reset(new CurrentSlideManager(mrSlideSorter)); + mpPageSelector.reset(new PageSelector(mrSlideSorter)); + mpFocusManager.reset(new FocusManager(mrSlideSorter)); + mpSlotManager.reset(new SlotManager(mrSlideSorter)); + mpClipboard.reset(new Clipboard(mrSlideSorter)); + mpScrollBarManager.reset(new ScrollBarManager(mrSlideSorter)); + mpSelectionManager.reset(new SelectionManager(mrSlideSorter)); + + mpScrollBarManager->LateInitialization(); + + // Create the selection function. + SfxRequest aRequest ( + SID_OBJECT_SELECT, + 0, + mrModel.GetDocument()->GetItemPool()); + mrSlideSorter.SetCurrentFunction(CreateSelectionFunction(aRequest)); + + mpListener = new Listener(mrSlideSorter); + + mpPageSelector->UpdateAllPages(); + GetSelectionManager()->SelectionHasChanged(); +} + + + + +SlideSorterController::~SlideSorterController (void) +{ + try + { + uno::Reference<lang::XComponent> xComponent ( + static_cast<XWeak*>(mpListener.get()), uno::UNO_QUERY); + if (xComponent.is()) + xComponent->dispose(); + } + catch( uno::Exception& e ) + { + (void)e; + DBG_ERROR( "sd::SlideSorterController::~SlideSorterController(), exception caught!" ); + } + + // dispose should have been called by now so that nothing is to be done + // to shut down cleanly. +} + + + + +model::SharedPageDescriptor SlideSorterController::GetPageAt ( + const Point& aPixelPosition) +{ + sal_Int32 nHitPageIndex (mrView.GetPageIndexAtPoint(aPixelPosition)); + model::SharedPageDescriptor pDescriptorAtPoint; + if (nHitPageIndex >= 0) + pDescriptorAtPoint = mrModel.GetPageDescriptor(nHitPageIndex); + + return pDescriptorAtPoint; +} + +PageSelector& SlideSorterController::GetPageSelector (void) +{ + OSL_ASSERT(mpPageSelector.get()!=NULL); + return *mpPageSelector.get(); +} + + + + +FocusManager& SlideSorterController::GetFocusManager (void) +{ + OSL_ASSERT(mpFocusManager.get()!=NULL); + return *mpFocusManager.get(); +} + + + + +Clipboard& SlideSorterController::GetClipboard (void) +{ + OSL_ASSERT(mpClipboard.get()!=NULL); + return *mpClipboard.get(); +} + + + + +ScrollBarManager& SlideSorterController::GetScrollBarManager (void) +{ + OSL_ASSERT(mpScrollBarManager.get()!=NULL); + return *mpScrollBarManager.get(); +} + + + + +::boost::shared_ptr<CurrentSlideManager> SlideSorterController::GetCurrentSlideManager (void) const +{ + OSL_ASSERT(mpCurrentSlideManager.get()!=NULL); + return mpCurrentSlideManager; +} + + + + +::boost::shared_ptr<SlotManager> SlideSorterController::GetSlotManager (void) const +{ + OSL_ASSERT(mpSlotManager.get()!=NULL); + return mpSlotManager; +} + + + + +::boost::shared_ptr<SelectionManager> SlideSorterController::GetSelectionManager (void) const +{ + OSL_ASSERT(mpSelectionManager.get()!=NULL); + return mpSelectionManager; +} + + + + +void SlideSorterController::PrePaint() +{ + // forward VCLs PrePaint window event to DrawingLayer + mrView.PrePaint(); +} + + + + +void SlideSorterController::Paint ( + const Rectangle& rBBox, + ::Window* pWindow) +{ + // if (mnPaintEntranceCount == 0) + { + ++mnPaintEntranceCount; + + try + { + if (GetSelectionManager()->IsMakeSelectionVisiblePending()) + GetSelectionManager()->MakeSelectionVisible(); + + mrView.SetApplicationDocumentColor(GetProperties()->GetBackgroundColor()); + mrView.CompleteRedraw(pWindow, Region(rBBox), 0); + } + catch (const Exception&) + { + // Ignore all exceptions. + } + + --mnPaintEntranceCount; + } +} + + + + +void SlideSorterController::FuTemporary (SfxRequest& rRequest) +{ + mpSlotManager->FuTemporary (rRequest); +} + + + + +void SlideSorterController::FuPermanent (SfxRequest &rRequest) +{ + mpSlotManager->FuPermanent (rRequest); +} + + + + +void SlideSorterController::FuSupport (SfxRequest &rRequest) +{ + mpSlotManager->FuSupport (rRequest); +} + + + + +bool SlideSorterController::Command ( + const CommandEvent& rEvent, + ::sd::Window* pWindow) +{ + bool bEventHasBeenHandled = false; + + ViewShell* pViewShell = mrSlideSorter.GetViewShell(); + + switch (rEvent.GetCommand()) + { + case COMMAND_CONTEXTMENU: + { + SdPage* pPage = NULL; + USHORT nPopupId; + + model::PageEnumeration aSelectedPages ( + PageEnumerationProvider::CreateSelectedPagesEnumeration(mrModel)); + if (aSelectedPages.HasMoreElements()) + pPage = aSelectedPages.GetNextElement()->GetPage(); + + // Choose the popup menu depending on a) the type of the main + // view shell, b) the edit mode, and c) on whether the selection + // is empty or not. + ViewShell::ShellType eMainViewShellType (ViewShell::ST_NONE); + ::boost::shared_ptr<ViewShell> pMainViewShell ( + pViewShell->GetViewShellBase().GetMainViewShell()); + if (pMainViewShell.get() != NULL) + eMainViewShellType = pMainViewShell->GetShellType(); + switch (eMainViewShellType) + { + case ViewShell::ST_DRAW: + if (pPage != NULL) + nPopupId = RID_SLIDE_SORTER_DRAW_SEL_POPUP; + else + nPopupId = RID_SLIDE_SORTER_DRAW_NOSEL_POPUP; + break; + + default: + if (mrModel.GetEditMode() == EM_PAGE) + if (pPage != NULL) + nPopupId = RID_SLIDE_SORTER_IMPRESS_SEL_POPUP; + else + nPopupId = RID_SLIDE_SORTER_IMPRESS_NOSEL_POPUP; + else + if (pPage != NULL) + nPopupId = RID_SLIDE_SORTER_MASTER_SEL_POPUP; + else + nPopupId = RID_SLIDE_SORTER_MASTER_NOSEL_POPUP; + } + + if (pPage == NULL) + { + // When there is no selection, then we show the insertion + // indicator so that the user knows where a page insertion + // would take place. + mrView.GetOverlay().GetInsertionIndicatorOverlay().SetPosition( + pWindow->PixelToLogic(rEvent.GetMousePosPixel())); + mrView.GetOverlay().GetInsertionIndicatorOverlay().setVisible(true); + } + + pWindow->ReleaseMouse(); + if (rEvent.IsMouseEvent()) + { + mbIsContextMenuOpen = true; + if (pViewShell != NULL) + { + SfxDispatcher* pDispatcher = pViewShell->GetDispatcher(); + if (pDispatcher != NULL) + pDispatcher->ExecutePopup(SdResId(nPopupId)); + } + } + else + { + // The event is not a mouse event. Use the center of the + // focused page as top left position of the context menu. + if (pPage != NULL) + { + model::SharedPageDescriptor pDescriptor ( + GetFocusManager().GetFocusedPageDescriptor()); + if (pDescriptor.get() != NULL) + { + Rectangle aBBox (mrView.GetPageBoundingBox ( + pDescriptor, + view::SlideSorterView::CS_SCREEN, + view::SlideSorterView::BBT_SHAPE)); + Point aPosition (aBBox.Center()); + mbIsContextMenuOpen = true; + if (pViewShell != NULL) + pViewShell->GetViewFrame()->GetDispatcher()->ExecutePopup( + SdResId(nPopupId), + pWindow, + &aPosition); + } + } + } + mbIsContextMenuOpen = false; + if (pPage == NULL) + { + // Remember the position of the insertion indicator before + // it is hidden, so that a pending slide insertion slot call + // finds the right place to insert a new slide. + GetSelectionManager()->SetInsertionPosition( + mrView.GetOverlay().GetInsertionIndicatorOverlay().GetInsertionPageIndex()); + mrView.GetOverlay().GetInsertionIndicatorOverlay().setVisible(false); + } + bEventHasBeenHandled = true; + } + break; + + case COMMAND_WHEEL: + { + // We ignore zooming with control+mouse wheel. + const CommandWheelData* pData = rEvent.GetWheelData(); + if (pData!=NULL && pData->IsMod1()) + bEventHasBeenHandled = true; + } + break; + } + + return bEventHasBeenHandled; +} + + + + +void SlideSorterController::LockModelChange (void) +{ + mnModelChangeLockCount += 1; +} + + + + +void SlideSorterController::UnlockModelChange (void) +{ + mnModelChangeLockCount -= 1; + if (mnModelChangeLockCount==0 && mbPostModelChangePending) + PostModelChange(); +} + + + + +void SlideSorterController::PreModelChange (void) +{ + // Prevent PreModelChange to execute more than once per model lock. + if (mbPostModelChangePending) + return; + mbPreModelChangeDone = true; + + if (mrSlideSorter.GetViewShell() != NULL) + mrSlideSorter.GetViewShell()->Broadcast( + ViewShellHint(ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_START)); + + mpPageSelector->PrepareModelChange(); + GetCurrentSlideManager()->PrepareModelChange(); + + ::sd::Window* pWindow = mrSlideSorter.GetActiveWindow(); + if (pWindow != NULL) + mrView.PreModelChange(); + + mbPostModelChangePending = true; +} + + + + +void SlideSorterController::PostModelChange (void) +{ + mbPostModelChangePending = false; + mrModel.Resync(); + + ::sd::Window* pWindow = mrSlideSorter.GetActiveWindow(); + if (pWindow != NULL) + { + GetCurrentSlideManager()->HandleModelChange(); + + mrView.PostModelChange (); + + pWindow->SetViewOrigin (Point (0,0)); + pWindow->SetViewSize (mrView.GetModelArea().GetSize()); + + // The visibility of the scroll bars may have to be changed. Then + // the size of the view has to change, too. Let Rearrange() handle + // that. + Rearrange(); + } + + mpPageSelector->HandleModelChange (); + + if (mrSlideSorter.GetViewShell() != NULL) + mrSlideSorter.GetViewShell()->Broadcast( + ViewShellHint(ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_END)); +} + + + + +void SlideSorterController::HandleModelChange (void) +{ + // Ignore this call when the document is not in a valid state, i.e. has + // not the same number of regular and notes pages. + bool bIsDocumentValid = (mrModel.GetDocument()->GetPageCount() % 2 == 1); + + if (bIsDocumentValid) + { + ModelChangeLock aLock (*this); + PreModelChange(); + } +} + + + + +IMPL_LINK(SlideSorterController, WindowEventHandler, VclWindowEvent*, pEvent) +{ + if (pEvent != NULL) + { + ::Window* pWindow = pEvent->GetWindow(); + ::sd::Window* pActiveWindow = mrSlideSorter.GetActiveWindow(); + switch (pEvent->GetId()) + { + case VCLEVENT_WINDOW_ACTIVATE: + case VCLEVENT_WINDOW_SHOW: + if (pActiveWindow != NULL && pWindow == pActiveWindow->GetParent()) + mrView.RequestRepaint(); + break; + + case VCLEVENT_WINDOW_GETFOCUS: + if (pActiveWindow != NULL && pWindow == pActiveWindow) + GetFocusManager().ShowFocus(false); + break; + + case VCLEVENT_WINDOW_LOSEFOCUS: + if (pActiveWindow != NULL && pWindow == pActiveWindow) + GetFocusManager().HideFocus(); + break; + + case VCLEVENT_APPLICATION_DATACHANGED: + { + // Invalidate the preview cache. + cache::PageCacheManager::Instance()->InvalidateAllCaches(); + + // Update the draw mode. + ULONG nDrawMode (Application::GetSettings().GetStyleSettings().GetHighContrastMode() + ? ViewShell::OUTPUT_DRAWMODE_CONTRAST + : ViewShell::OUTPUT_DRAWMODE_COLOR); + if (mrSlideSorter.GetViewShell() != NULL) + mrSlideSorter.GetViewShell()->GetFrameView()->SetDrawMode(nDrawMode); + if (pActiveWindow != NULL) + pActiveWindow->SetDrawMode(nDrawMode); + mrView.HandleDrawModeChange(); + + // When the system font has changed a layout has to be done. + mrView.Resize(); + FontProvider::Instance().Invalidate(); + } + break; + + default: + break; + } + } + + return TRUE; +} + + + + +void SlideSorterController::GetCtrlState (SfxItemSet& rSet) +{ + if (rSet.GetItemState(SID_RELOAD) != SFX_ITEM_UNKNOWN) + { + // "Letzte Version" vom SFx en/disablen lassen + SfxViewFrame* pSlideViewFrame = SfxViewFrame::Current(); + DBG_ASSERT(pSlideViewFrame!=NULL, + "SlideSorterController::GetCtrlState: ViewFrame not found"); + if (pSlideViewFrame) + { + pSlideViewFrame->GetSlotState (SID_RELOAD, NULL, &rSet); + } + else // MI sagt: kein MDIFrame --> disablen + { + rSet.DisableItem(SID_RELOAD); + } + } + + // Output quality. + if (rSet.GetItemState(SID_OUTPUT_QUALITY_COLOR)==SFX_ITEM_AVAILABLE + ||rSet.GetItemState(SID_OUTPUT_QUALITY_GRAYSCALE)==SFX_ITEM_AVAILABLE + ||rSet.GetItemState(SID_OUTPUT_QUALITY_BLACKWHITE)==SFX_ITEM_AVAILABLE + ||rSet.GetItemState(SID_OUTPUT_QUALITY_CONTRAST)==SFX_ITEM_AVAILABLE) + { + ::sd::Window* pWindow = mrSlideSorter.GetActiveWindow(); + if (pWindow != NULL) + { + ULONG nMode = pWindow->GetDrawMode(); + UINT16 nQuality = 0; + + switch (nMode) + { + case ViewShell::OUTPUT_DRAWMODE_COLOR: + nQuality = 0; + break; + case ViewShell::OUTPUT_DRAWMODE_GRAYSCALE: + nQuality = 1; + break; + case ViewShell::OUTPUT_DRAWMODE_BLACKWHITE: + nQuality = 2; + break; + case ViewShell::OUTPUT_DRAWMODE_CONTRAST: + nQuality = 3; + break; + } + + rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_COLOR, + (BOOL)(nQuality==0))); + rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_GRAYSCALE, + (BOOL)(nQuality==1))); + rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_BLACKWHITE, + (BOOL)(nQuality==2))); + rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_CONTRAST, + (BOOL)(nQuality==3))); + } + } + + if (rSet.GetItemState(SID_MAIL_SCROLLBODY_PAGEDOWN) == SFX_ITEM_AVAILABLE) + { + rSet.Put (SfxBoolItem( SID_MAIL_SCROLLBODY_PAGEDOWN, TRUE)); + } +} + + + + +void SlideSorterController::GetStatusBarState (SfxItemSet& rSet) +{ + mpSlotManager->GetStatusBarState (rSet); +} + + + + +void SlideSorterController::ExecCtrl (SfxRequest& rRequest) +{ + mpSlotManager->ExecCtrl (rRequest); +} + + + + +void SlideSorterController::GetAttrState (SfxItemSet& rSet) +{ + mpSlotManager->GetAttrState (rSet); +} + + + + +void SlideSorterController::ExecStatusBar (SfxRequest& ) +{ +} + + + + +void SlideSorterController::UpdateAllPages (void) +{ + // Do a redraw. + mrView.InvalidateAllWin(); +} + + + + +Rectangle SlideSorterController::Resize (const Rectangle& rAvailableSpace) +{ + Rectangle aContentArea (rAvailableSpace); + + if (maTotalWindowArea != rAvailableSpace) + { + maTotalWindowArea = rAvailableSpace; + aContentArea = Rearrange(true); + } + + return aContentArea; +} + + + + +Rectangle SlideSorterController::Rearrange (bool bForce) +{ + Rectangle aNewContentArea (maTotalWindowArea); + + ::boost::shared_ptr<sd::Window> pWindow = mrSlideSorter.GetContentWindow(); + if (pWindow.get() != NULL) + { + // Place the scroll bars. + aNewContentArea = GetScrollBarManager().PlaceScrollBars(maTotalWindowArea); + + bool bSizeHasChanged (false); + // Only when bForce is not true we have to test for a size change in + // order to determine whether the window and the view have to be resized. + if ( ! bForce) + { + Rectangle aCurrentContentArea ( + pWindow->GetPosPixel(), + pWindow->GetOutputSizePixel()); + bSizeHasChanged = (aNewContentArea != aCurrentContentArea); + } + if (bForce || bSizeHasChanged) + { + // The browser window gets the remaining space. + pWindow->SetPosSizePixel (aNewContentArea.TopLeft(), aNewContentArea.GetSize()); + mrView.Resize(); + } + + // Adapt the scroll bars to the new zoom factor of the browser + // window and the arrangement of the page objects. + GetScrollBarManager().UpdateScrollBars(false, !bForce); + } + + return aNewContentArea; +} + + + + +FunctionReference SlideSorterController::CreateSelectionFunction (SfxRequest& rRequest) +{ + FunctionReference xFunc( SelectionFunction::Create(mrSlideSorter, rRequest) ); + return xFunc; +} + + + + +void SlideSorterController::PrepareEditModeChange (void) +{ + // Before we throw away the page descriptors we prepare for selecting + // descriptors in the other mode and for restoring the current + // selection when switching back to the current mode. + if (mrModel.GetEditMode() == EM_PAGE) + { + maSelectionBeforeSwitch.clear(); + + // Search for the first selected page and determine the master page + // used by its page object. It will be selected after the switch. + // In the same loop the current selection is stored. + PageEnumeration aSelectedPages ( + PageEnumerationProvider::CreateSelectedPagesEnumeration(mrModel)); + while (aSelectedPages.HasMoreElements()) + { + SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement()); + SdPage* pPage = pDescriptor->GetPage(); + // Remember the master page of the first selected descriptor. + if (pPage!=NULL && mpEditModeChangeMasterPage==NULL) + mpEditModeChangeMasterPage = &static_cast<SdPage&>( + pPage->TRG_GetMasterPage()); + + maSelectionBeforeSwitch.push_back(pPage); + } + + // Remember the current page. + if (mrSlideSorter.GetViewShell() != NULL) + mnCurrentPageBeforeSwitch = (mrSlideSorter.GetViewShell()->GetViewShellBase() + .GetMainViewShell()->GetActualPage()->GetPageNum()-1)/2; + } +} + + + + +bool SlideSorterController::ChangeEditMode (EditMode eEditMode) +{ + bool bResult (false); + if (mrModel.GetEditMode() != eEditMode) + { + ModelChangeLock aLock (*this); + PreModelChange(); + // Do the actual edit mode switching. + bResult = mrModel.SetEditMode(eEditMode); + if (bResult) + HandleModelChange(); + } + return bResult; +} + + + + +void SlideSorterController::FinishEditModeChange (void) +{ + if (mrModel.GetEditMode() == EM_MASTERPAGE) + { + // Search for the master page that was determined in + // PrepareEditModeChange() and make it the current page. + PageEnumeration aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(mrModel)); + while (aAllPages.HasMoreElements()) + { + SharedPageDescriptor pDescriptor (aAllPages.GetNextElement()); + if (pDescriptor->GetPage() == mpEditModeChangeMasterPage) + { + GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor); + break; + } + } + } + else + { + SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(mnCurrentPageBeforeSwitch)); + GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor); + + // Restore the selection. + ::std::vector<SdPage*>::iterator iPage; + for (iPage=maSelectionBeforeSwitch.begin(); + iPage!=maSelectionBeforeSwitch.end(); + ++iPage) + { + mpPageSelector->SelectPage(*iPage); + } + maSelectionBeforeSwitch.clear( ); + } + mpEditModeChangeMasterPage = NULL; +} + + + + +void SlideSorterController::PageNameHasChanged (int nPageIndex, const String& rsOldName) +{ + // Request a repaint for the page object whose name has changed. + model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex)); + if (pDescriptor.get() != NULL) + mrView.RequestRepaint(pDescriptor); + + // Get a pointer to the corresponding accessible object and notify + // that of the name change. + do + { + ::sd::Window* pWindow = mrSlideSorter.GetActiveWindow(); + if (pWindow == NULL) + break; + + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > + xAccessible (pWindow->GetAccessible(FALSE)); + if ( ! xAccessible.is()) + break; + + // Now comes a small hack. We assume that the accessible object is + // an instantiation of AccessibleSlideSorterView and cast it to that + // class. The cleaner alternative to this cast would be a new member + // in which we would store the last AccessibleSlideSorterView object + // created by SlideSorterViewShell::CreateAccessibleDocumentView(). + // But then there is no guaranty that the accessible object obtained + // from the window really is that instance last created by + // CreateAccessibleDocumentView(). + // However, the dynamic cast together with the check of the result + // being NULL should be safe enough. + ::accessibility::AccessibleSlideSorterView* pAccessibleView + = dynamic_cast< ::accessibility::AccessibleSlideSorterView*>(xAccessible.get()); + if (pAccessibleView == NULL) + break; + + ::accessibility::AccessibleSlideSorterObject* pChild + = pAccessibleView->GetAccessibleChildImplementation(nPageIndex); + if (pChild == NULL || pChild->GetPage() == NULL) + break; + + ::rtl::OUString sOldName (rsOldName); + ::rtl::OUString sNewName (pChild->GetPage()->GetName()); + pChild->FireAccessibleEvent( + ::com::sun::star::accessibility::AccessibleEventId::NAME_CHANGED, + makeAny(sOldName), + makeAny(sNewName)); + } + while (false); +} + + + + +bool SlideSorterController::IsContextMenuOpen (void) const +{ + return mbIsContextMenuOpen; +} + + + + +::boost::shared_ptr<Properties> SlideSorterController::GetProperties (void) const +{ + return mpProperties; +} + + + + +void SlideSorterController::SetDocumentSlides (const Reference<container::XIndexAccess>& rxSlides) +{ + if (mrModel.GetDocumentSlides() != rxSlides) + { + ModelChangeLock aLock (*this); + PreModelChange(); + + mrModel.SetDocumentSlides(rxSlides); + mrView.Layout(); + } +} + + + + +::boost::shared_ptr<Animator> SlideSorterController::GetAnimator (void) const +{ + return mpAnimator; +} + + + + +//===== SlideSorterController::ModelChangeLock ================================ + +SlideSorterController::ModelChangeLock::ModelChangeLock ( + SlideSorterController& rController) + : mpController(&rController) +{ + mpController->LockModelChange(); +} + + + + +SlideSorterController::ModelChangeLock::~ModelChangeLock (void) +{ + Release(); +} + + + + +void SlideSorterController::ModelChangeLock::Release (void) +{ + if (mpController != NULL) + { + mpController->UnlockModelChange(); + mpController = NULL; + } +} + +} } } // end of namespace ::sd::slidesorter diff --git a/sd/source/ui/slidesorter/controller/SlsAnimator.cxx b/sd/source/ui/slidesorter/controller/SlsAnimator.cxx new file mode 100644 index 000000000000..56505d9756e6 --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlsAnimator.cxx @@ -0,0 +1,232 @@ +/************************************************************************* + * + * 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 "controller/SlsAnimator.hxx" +#include "view/SlideSorterView.hxx" +#include "View.hxx" + +namespace sd { namespace slidesorter { namespace controller { + +namespace { + static const sal_Int32 gnResolution = 25; +} +/** Handle one animation function by using a timer for frequent calls to + the animations operator(). +*/ +class Animator::Animation +{ +public: + Animation ( + const Animator::AnimationFunction& rAnimation, + const double nDelta); + ~Animation (void); + bool Run (void); + bool IsExpired (void); + Animator::AnimationFunction maAnimation; + double mnValue; + double mnDelta; +}; + + + + +class Animator::DrawLock +{ +public: + DrawLock (View& rView); + ~DrawLock (void); + +private: + View& mrView; +}; + + + + +Animator::Animator (SlideSorter& rSlideSorter) + : mrSlideSorter(rSlideSorter), + maTimer(), + maAnimations(), + mpDrawLock() +{ + maTimer.SetTimeout(gnResolution); + maTimer.SetTimeoutHdl(LINK(this,Animator,TimeoutHandler)); +} + + + + +Animator::~Animator (void) +{ + maTimer.Stop(); + mpDrawLock.reset(); +} + + + + +void Animator::AddAnimation ( + const AnimationFunction& rAnimation, + const sal_Int32 nDuration) +{ + const double nDelta = double(gnResolution) / double(nDuration); + maAnimations.push_back(boost::shared_ptr<Animation>(new Animation(rAnimation, nDelta))); + + // Prevent redraws except for the ones in TimeoutHandler. + // While the Animator is active it will schedule repaints regularly. + // Repaints in between would only lead to visual artifacts. + mpDrawLock.reset(new DrawLock(mrSlideSorter.GetView())); + maTimer.Start(); +} + + + + +bool Animator::ServeAnimations (void) +{ + bool bExpired (false); + + AnimationList aCopy (maAnimations); + AnimationList::const_iterator iAnimation; + for (iAnimation=aCopy.begin(); iAnimation!=aCopy.end(); ++iAnimation) + { + bExpired |= (*iAnimation)->Run(); + } + + return bExpired; +} + + + + +void Animator::CleanUpAnimationList (void) +{ + AnimationList aActiveAnimations; + + AnimationList::const_iterator iAnimation; + for (iAnimation=maAnimations.begin(); iAnimation!=maAnimations.end(); ++iAnimation) + { + if ( ! (*iAnimation)->IsExpired()) + aActiveAnimations.push_back(*iAnimation); + } + + maAnimations.swap(aActiveAnimations); +} + + + + +IMPL_LINK(Animator, TimeoutHandler, Timer*, EMPTYARG) +{ + if (ServeAnimations()) + CleanUpAnimationList(); + + // Unlock the draw lock. This should lead to a repaint. + mpDrawLock.reset(); + + if (maAnimations.size() > 0) + { + mpDrawLock.reset(new DrawLock(mrSlideSorter.GetView())); + maTimer.Start(); + } + + return 0; +} + + + + +//===== Animator::Animation =================================================== + +Animator::Animation::Animation ( + const Animator::AnimationFunction& rAnimation, + const double nDelta) + : maAnimation(rAnimation), + mnValue(0), + mnDelta(nDelta) +{ + + maAnimation(mnValue); + mnValue = mnDelta; + +} + + + + +Animator::Animation::~Animation (void) +{ +} + + + + +bool Animator::Animation::Run (void) +{ + if (mnValue < 1.0) + { + maAnimation(mnValue); + mnValue += mnDelta; + return false; + } + else + { + maAnimation(1.0); + return true; + } +} + + + + +bool Animator::Animation::IsExpired (void) +{ + return mnValue >= 1.0; +} + + + + +//===== Animator::DrawLock ==================================================== + +Animator::DrawLock::DrawLock (View& rView) + : mrView(rView) +{ + mrView.LockRedraw(TRUE); +} + + + + +Animator::DrawLock::~DrawLock (void) +{ + mrView.LockRedraw(FALSE); +} + + +} } } // end of namespace ::sd::slidesorter::controller diff --git a/sd/source/ui/slidesorter/controller/SlsClipboard.cxx b/sd/source/ui/slidesorter/controller/SlsClipboard.cxx new file mode 100644 index 000000000000..d226a8c2e294 --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlsClipboard.cxx @@ -0,0 +1,778 @@ +/************************************************************************* + * + * 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 "controller/SlsClipboard.hxx" + +#include "SlideSorterViewShell.hxx" +#include "SlideSorter.hxx" +#include "model/SlideSorterModel.hxx" +#include "model/SlsPageDescriptor.hxx" +#include "model/SlsPageEnumerationProvider.hxx" +#include "view/SlideSorterView.hxx" +#include "view/SlsViewOverlay.hxx" +#include "view/SlsPageObject.hxx" +#include "controller/SlideSorterController.hxx" +#include "controller/SlsPageSelector.hxx" +#include "controller/SlsSelectionFunction.hxx" +#include "controller/SlsCurrentSlideManager.hxx" +#include "controller/SlsScrollBarManager.hxx" +#include "controller/SlsFocusManager.hxx" +#include "controller/SlsSelectionManager.hxx" +#include "SlsTransferable.hxx" + +#include "ViewShellBase.hxx" +#include "DrawViewShell.hxx" +#include "Window.hxx" +#include "fupoor.hxx" +#include "fuslhide.hxx" +#include "fuzoom.hxx" +#include "fucushow.hxx" +#include "fusldlg.hxx" +#include "fuexpand.hxx" +#include "fusumry.hxx" +#include "app.hrc" +#include "glob.hrc" +#include "strings.hrc" +#include "sdresid.hxx" +#include "sdxfer.hxx" +#include "sdmod.hxx" +#include "sddll.hxx" +#include "ins_paste.hxx" +#include "drawdoc.hxx" +#include "DrawDocShell.hxx" +#include "sdpage.hxx" + +#include <com/sun/star/datatransfer/dnd/DNDConstants.hpp> +#include <sfx2/request.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/docfile.hxx> +#include <svx/svxids.hrc> +#include <vcl/msgbox.hxx> +#include <tools/urlobj.hxx> +#include <rtl/ustring.hxx> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> + +namespace sd { namespace slidesorter { namespace controller { + + +Clipboard::Clipboard (SlideSorter& rSlideSorter) + : ViewClipboard(rSlideSorter.GetView()), + mrSlideSorter(rSlideSorter), + mrController(mrSlideSorter.GetController()), + maPagesToRemove(), + maPagesToSelect(), + mbUpdateSelectionPending(false) +{ +} + + + + +Clipboard::~Clipboard (void) +{ +} + + + + +/** With the current implementation the forwarded calls to the current + function will come back eventually to call the local Do(Cut|Copy|Paste) + methods. A shortcut is possible but would be an unclean hack. +*/ +void Clipboard::HandleSlotCall (SfxRequest& rRequest) +{ + ViewShell* pViewShell = mrSlideSorter.GetViewShell(); + FunctionReference xFunc; + if (pViewShell != NULL) + xFunc = pViewShell->GetCurrentFunction(); + switch (rRequest.GetSlot()) + { + case SID_CUT: + if (mrSlideSorter.GetModel().GetEditMode() != EM_MASTERPAGE) + { + if(xFunc.is()) + xFunc->DoCut(); + else + DoCut(); + } + rRequest.Done(); + break; + + case SID_COPY: + if (mrSlideSorter.GetModel().GetEditMode() != EM_MASTERPAGE) + { + if(xFunc.is()) + xFunc->DoCopy(); + else + DoCopy(); + } + rRequest.Done(); + break; + + case SID_PASTE: + // Prevent redraws while inserting pages from the clipboard + // because the intermediate inconsistent state might lead to + // a crash. + if (mrSlideSorter.GetModel().GetEditMode() != EM_MASTERPAGE) + { + mrSlideSorter.GetView().LockRedraw (TRUE); + if(xFunc.is()) + xFunc->DoPaste(); + else + DoPaste(); + mrController.GetSelectionManager()->MakeSelectionVisible(); + mrSlideSorter.GetView().LockRedraw(FALSE); + } + rRequest.Done(); + break; + + case SID_DELETE: + DoDelete(); + rRequest.Done(); + break; + } +} + + + + +void Clipboard::DoCut (::Window* pWindow) +{ + if (mrSlideSorter.GetModel().GetPageCount() > 1) + { + DoCopy(pWindow); + DoDelete(pWindow); + } +} + + + + +void Clipboard::DoDelete (::Window* ) +{ + if (mrSlideSorter.GetModel().GetPageCount() > 1) + { + mrController.GetSelectionManager()->DeleteSelectedPages(); + } +} + + + + +void Clipboard::DoCopy (::Window* pWindow ) +{ + CreateSlideTransferable( pWindow, FALSE ); +} + + + + +void Clipboard::DoPaste (::Window* pWindow) +{ + SdTransferable* pClipTransferable = SD_MOD()->pTransferClip; + + if (pClipTransferable!=NULL && pClipTransferable->IsPageTransferable()) + { + sal_Int32 nInsertPosition = GetInsertionPosition(pWindow); + + if (nInsertPosition >= 0) + { + // Paste the pages from the clipboard. + sal_Int32 nInsertPageCount = PasteTransferable(nInsertPosition); + // Select the pasted pages and make the first of them the + // current page. + mrSlideSorter.GetView().GetWindow()->GrabFocus(); + SelectPageRange(nInsertPosition, nInsertPageCount); + } + } +} + + + + +sal_Int32 Clipboard::GetInsertionPosition (::Window* pWindow) +{ + sal_Int32 nInsertPosition = -1; + + // Determine the insertion position: + // a) When the insertion indicator is visible, then at that position. + // b) When the focus indicator is visible, then before or after the + // focused page, depending on user input to a dialog. + // c) When there is a selection but no focus, then after the + // selection. + // d) After the last page when there is no selection and no focus. + + view::InsertionIndicatorOverlay& rInsertionIndicatorOverlay ( + mrSlideSorter.GetView().GetOverlay().GetInsertionIndicatorOverlay()); + if (rInsertionIndicatorOverlay.isVisible()) + { + nInsertPosition = rInsertionIndicatorOverlay.GetInsertionPageIndex(); + } + else if (mrController.GetFocusManager().IsFocusShowing()) + { + SdInsertPasteDlg aDialog (pWindow); + if (aDialog.Execute() == RET_OK) + { + nInsertPosition = mrController.GetFocusManager().GetFocusedPageIndex(); + if ( ! aDialog.IsInsertBefore()) + nInsertPosition ++; + } + } + else + { + nInsertPosition = mrController.GetSelectionManager()->GetInsertionPosition(); + } + + return nInsertPosition; +} + + + + +sal_Int32 Clipboard::PasteTransferable (sal_Int32 nInsertPosition) +{ + SdTransferable* pClipTransferable = SD_MOD()->pTransferClip; + bool bMergeMasterPages = !pClipTransferable->HasSourceDoc ( + mrSlideSorter.GetModel().GetDocument()); + USHORT nInsertIndex ((USHORT)(nInsertPosition * 2 + 1)); + sal_Int32 nInsertPageCount (0); + if (pClipTransferable->HasPageBookmarks()) + { + const List& rBookmarkList = pClipTransferable->GetPageBookmarks(); + const ::vos::OGuard aGuard (Application::GetSolarMutex()); + + nInsertPageCount = (USHORT) rBookmarkList.Count(); + mrSlideSorter.GetModel().GetDocument()->InsertBookmarkAsPage( + const_cast<List*>(&rBookmarkList), + NULL, + FALSE, + FALSE, + nInsertIndex, + FALSE, + pClipTransferable->GetPageDocShell(), + TRUE, + bMergeMasterPages, + FALSE); + } + else + { + SfxObjectShell* pShell = pClipTransferable->GetDocShell(); + DrawDocShell* pDataDocSh = (DrawDocShell*)pShell; + SdDrawDocument* pDataDoc = pDataDocSh->GetDoc(); + + if (pDataDoc!=NULL + && pDataDoc->GetSdPageCount(PK_STANDARD)) + { + const ::vos::OGuard aGuard (Application::GetSolarMutex()); + + bMergeMasterPages = (pDataDoc != mrSlideSorter.GetModel().GetDocument()); + nInsertPageCount = pDataDoc->GetSdPageCount( PK_STANDARD ); + mrSlideSorter.GetModel().GetDocument()->InsertBookmarkAsPage( + NULL, + NULL, + FALSE, + FALSE, + nInsertIndex, + FALSE, + pDataDocSh, + TRUE, + bMergeMasterPages, + FALSE); + } + } + mrController.HandleModelChange(); + return nInsertPageCount; +} + + + + +void Clipboard::SelectPageRange (sal_Int32 nFirstIndex, sal_Int32 nPageCount) +{ + // Select the newly inserted pages. That are the nInsertPageCount pages + // after the nInsertIndex position. + PageSelector& rSelector (mrController.GetPageSelector()); + rSelector.DeselectAllPages(); + for (USHORT i=0; i<nPageCount; i++) + { + model::SharedPageDescriptor pDescriptor ( + mrSlideSorter.GetModel().GetPageDescriptor(nFirstIndex + i)); + if (pDescriptor.get() != NULL) + { + rSelector.SelectPage(pDescriptor); + // The first page of the new selection is made the current page. + if (i == 0) + { + mrController.GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor); + mrController.GetFocusManager().SetFocusedPage(pDescriptor); + } + } + } +} + + + + +void Clipboard::CreateSlideTransferable ( + ::Window* pWindow, + bool bDrag) +{ + List aBookmarkList; + + // Insert all selected pages into a bookmark list and remember them in + // maPagesToRemove for possible later removal. + model::PageEnumeration aSelectedPages + (model::PageEnumerationProvider::CreateSelectedPagesEnumeration( + mrSlideSorter.GetModel())); + while (aSelectedPages.HasMoreElements()) + { + model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement()); + aBookmarkList.Insert ( + new String(pDescriptor->GetPage()->GetName()), + LIST_APPEND); + maPagesToRemove.push_back (pDescriptor->GetPage()); + } + + if (aBookmarkList.Count() > 0) + { + mrSlideSorter.GetView().BrkAction(); + SdDrawDocument* pDocument = mrSlideSorter.GetModel().GetDocument(); + SdTransferable* pTransferable = new Transferable ( + pDocument, + NULL, + FALSE, + dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell())); + + if (bDrag) + SD_MOD()->pTransferDrag = pTransferable; + else + SD_MOD()->pTransferClip = pTransferable; + + pDocument->CreatingDataObj (pTransferable); + pTransferable->SetWorkDocument( dynamic_cast<SdDrawDocument*>(pDocument->AllocModel()) ); + pDocument->CreatingDataObj (NULL); + TransferableObjectDescriptor aObjDesc; + pTransferable->GetWorkDocument()->GetDocSh() + ->FillTransferableObjectDescriptor (aObjDesc); + + if (pDocument->GetDocSh() != NULL) + aObjDesc.maDisplayName = pDocument->GetDocSh() + ->GetMedium()->GetURLObject().GetURLNoPass(); + + ::Window* pActionWindow = pWindow; + if (pActionWindow == NULL) + { + ViewShell* pViewShell = mrSlideSorter.GetViewShell(); + if (pViewShell != NULL) + pActionWindow = pViewShell->GetActiveWindow(); + } + + pTransferable->SetStartPos (pActionWindow->PixelToLogic( + pActionWindow->GetPointerPosPixel())); + pTransferable->SetObjectDescriptor (aObjDesc); + pTransferable->SetPageBookmarks (aBookmarkList, !bDrag); + + for (void* p=aBookmarkList.First(); p!=NULL; p=aBookmarkList.Next()) + delete static_cast<String*>(p); + + if (bDrag) + { + pTransferable->SetView (&mrSlideSorter.GetView()); + sal_Int8 nDragSourceActions (DND_ACTION_COPY); + // The move action is available only when not all pages would be + // moved. Otherwise an empty document would remain. Crash. + sal_Int32 nRemainingPages = mrSlideSorter.GetModel().GetPageCount() - aBookmarkList.Count(); + if (nRemainingPages > 0) + nDragSourceActions |= DND_ACTION_MOVE; + pTransferable->StartDrag (pActionWindow, nDragSourceActions); + } + else + pTransferable->CopyToClipboard (pActionWindow); + } +} + + + + +void Clipboard::StartDrag ( + const Point&, + ::Window* pWindow) +{ + maPagesToRemove.clear(); + maPagesToSelect.clear(); + mbUpdateSelectionPending = false; + CreateSlideTransferable (pWindow, TRUE); +} + + + + +void Clipboard::DragFinished (sal_Int8 nDropAction) +{ + // Hide the substitution display and insertion indicator. + mrSlideSorter.GetView().GetOverlay().GetSubstitutionOverlay().setVisible(false); + mrSlideSorter.GetView().GetOverlay().GetInsertionIndicatorOverlay().setVisible(false); + + SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag; + + if (pDragTransferable != NULL) + pDragTransferable->SetView (NULL); + + PageSelector& rSelector (mrController.GetPageSelector()); + if ((nDropAction & DND_ACTION_MOVE) != 0 + && ! maPagesToRemove.empty()) + { + // Remove the pages that have been moved to another place (possibly + // in the same document.) + rSelector.DeselectAllPages(); + PageList::iterator aDraggedPage; + for (aDraggedPage=maPagesToRemove.begin(); + aDraggedPage!=maPagesToRemove.end(); + aDraggedPage++) + { + rSelector.SelectPage (*aDraggedPage); + } + mrController.GetSelectionManager()->DeleteSelectedPages (); + } + + SelectPages(); +} + + + + +void Clipboard::SelectPages (void) +{ + PageSelector& rSelector (mrController.GetPageSelector()); + + // Select the dropped pages. + PageList::iterator iPage; + rSelector.DeselectAllPages(); + for (iPage=maPagesToSelect.begin(); iPage!=maPagesToSelect.end(); ++iPage) + { + rSelector.SelectPage(*iPage); + } +} + + + + +sal_Int8 Clipboard::AcceptDrop ( + const AcceptDropEvent& rEvent, + DropTargetHelper& rTargetHelper, + ::sd::Window* pTargetWindow, + USHORT nPage, + USHORT nLayer) +{ + sal_Int8 nResult = DND_ACTION_NONE; + + switch (IsDropAccepted()) + { + case DT_PAGE: + { + // Accept a drop. + nResult = rEvent.mnAction; + + // Use the copy action when the drop action is the default, i.e. not + // explicitly set to move or link, and when the source and + // target models are not the same. + const SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag; + if (pDragTransferable != NULL + && pDragTransferable->IsPageTransferable() + && ((rEvent.maDragEvent.DropAction + & ::com::sun::star::datatransfer::dnd::DNDConstants::ACTION_DEFAULT) != 0) + && (mrSlideSorter.GetModel().GetDocument()->GetDocSh() + != pDragTransferable->GetPageDocShell())) + { + nResult = DND_ACTION_COPY; + } + + // Show the insertion marker and the substitution for a drop. + Point aPosition = pTargetWindow->PixelToLogic (rEvent.maPosPixel); + view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); + rOverlay.GetInsertionIndicatorOverlay().SetPosition (aPosition); + rOverlay.GetInsertionIndicatorOverlay().setVisible(true); + rOverlay.GetSubstitutionOverlay().SetPosition (aPosition); + + // Scroll the window when the mouse reaches the window border. + mrController.GetScrollBarManager().AutoScroll (rEvent.maPosPixel); + } + break; + + case DT_SHAPE: + nResult = ExecuteOrAcceptShapeDrop( + DC_ACCEPT, + rEvent.maPosPixel, + &rEvent, + rTargetHelper, + pTargetWindow, + nPage, + nLayer); + break; + default: + break; + } + + return nResult; +} + + + + +sal_Int8 Clipboard::ExecuteDrop ( + const ExecuteDropEvent& rEvent, + DropTargetHelper& rTargetHelper, + ::sd::Window* pTargetWindow, + USHORT nPage, + USHORT nLayer) +{ + sal_Int8 nResult = DND_ACTION_NONE; + + switch (IsDropAccepted()) + { + case DT_PAGE: + { + const SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag; + const Point aEventModelPosition ( + pTargetWindow->PixelToLogic (rEvent.maPosPixel)); + long int nXOffset = labs (pDragTransferable->GetStartPos().X() + - aEventModelPosition.X()); + long int nYOffset = labs (pDragTransferable->GetStartPos().Y() + - aEventModelPosition.Y()); + const bool bContinue = + ( pDragTransferable->GetView() != &mrSlideSorter.GetView() ) + || ( nXOffset >= 2 && nYOffset >= 2 ); + + // Get insertion position and then turn off the insertion indicator. + view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); + rOverlay.GetInsertionIndicatorOverlay().SetPosition( + aEventModelPosition); + USHORT nIndex = DetermineInsertPosition (*pDragTransferable); + OSL_TRACE ("Clipboard::AcceptDrop() called for index %d", + nIndex); + rOverlay.GetInsertionIndicatorOverlay().setVisible(false); + + if (bContinue) + { + SlideSorterController::ModelChangeLock aModelChangeLock (mrController); + + if (pDragTransferable->GetView() == &mrSlideSorter.GetView() + && rEvent.mnAction == DND_ACTION_MOVE) + { + // We are asked to move pages inside one view. For this we + // call MoveSelectedPages() which is faster than going the + // generic way. + + // Remember to select the moved pages afterwards. + maPagesToRemove.swap(maPagesToSelect); + maPagesToRemove.clear(); + + USHORT nSdrModelIndex; + if (nIndex != SDRPAGE_NOTFOUND) + nSdrModelIndex = nIndex / 2 - 1; + else + nSdrModelIndex = SDRPAGE_NOTFOUND; + mrController.GetSelectionManager()->MoveSelectedPages(nSdrModelIndex); + mbUpdateSelectionPending = true; + nResult = DND_ACTION_NONE; + } + else + { + // Handle a general drop operation. + HandlePageDrop (*pDragTransferable); + nResult = rEvent.mnAction; + } + } + } + break; + + case DT_SHAPE: + nResult = ExecuteOrAcceptShapeDrop( + DC_EXECUTE, + rEvent.maPosPixel, + &rEvent, + rTargetHelper, + pTargetWindow, + nPage, + nLayer); + break; + default: + break; + } + + return nResult; +} + + + + +USHORT Clipboard::DetermineInsertPosition (const SdTransferable& ) +{ + USHORT nInsertPosition = SDRPAGE_NOTFOUND; + + // Tell the model to move the dragged pages behind the one with the + // index nInsertionIndex which first has to be transformed into an index + // understandable by the document. + view::InsertionIndicatorOverlay& rOverlay ( + mrSlideSorter.GetView().GetOverlay().GetInsertionIndicatorOverlay()); + sal_Int32 nInsertionIndex (rOverlay.GetInsertionPageIndex()); + + // The index returned by the overlay starts with 1 for the first slide. + // This is now converted that to an SdModel index that also starts with 1. + if (nInsertionIndex >= 0) + nInsertPosition = (USHORT)nInsertionIndex * 2 + 1; + + return nInsertPosition; +} + + + + +USHORT Clipboard::InsertSlides ( + const SdTransferable& rTransferable, + USHORT nInsertPosition) +{ + USHORT nInsertedPageCount = ViewClipboard::InsertSlides ( + rTransferable, + nInsertPosition); + + // Remember the inserted pages so that they can be selected when the + // operation is finished. + int nDocumentIndex = nInsertPosition / 2 - 1; + for (USHORT i=1; i<=nInsertedPageCount; i++) + { + model::SharedPageDescriptor pDescriptor ( + mrSlideSorter.GetModel().GetPageDescriptor(nDocumentIndex + i)); + if (pDescriptor.get() != NULL) + maPagesToSelect.push_back (pDescriptor->GetPage()); + } + + mbUpdateSelectionPending |= (nInsertedPageCount>0); + + return nInsertedPageCount; +} + + + + +Clipboard::DropType Clipboard::IsDropAccepted (void) const +{ + DropType eResult (DT_NONE); + + const SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag; + if (pDragTransferable != NULL) + { + if (pDragTransferable->IsPageTransferable()) + { + if (mrSlideSorter.GetModel().GetEditMode() != EM_MASTERPAGE) + eResult = DT_PAGE; + } + else + { + eResult = DT_SHAPE; + } + } + + return eResult; +} + + + + +sal_Int8 Clipboard::ExecuteOrAcceptShapeDrop ( + DropCommand eCommand, + const Point& rPosition, + const void* pDropEvent, + DropTargetHelper& rTargetHelper, + ::sd::Window* pTargetWindow, + USHORT nPage, + USHORT nLayer) +{ + sal_Int8 nResult = 0; + + // The dropping of a shape is accepted or executed only when there is + // DrawViewShell available to which we can forward this call. This has + // technical reasons: The actual code to accept or execute a shape drop + // is implemented in the ViewShell class and uses the page view of the + // main edit view. This is not possible without a DrawViewShell. + ::boost::shared_ptr<DrawViewShell> pDrawViewShell; + if (mrSlideSorter.GetViewShell() != NULL) + pDrawViewShell = ::boost::dynamic_pointer_cast<DrawViewShell>( + mrSlideSorter.GetViewShell()->GetViewShellBase().GetMainViewShell()); + if (pDrawViewShell.get() != NULL + && (pDrawViewShell->GetShellType() == ViewShell::ST_IMPRESS + || pDrawViewShell->GetShellType() == ViewShell::ST_DRAW)) + { + // The drop is only accepted or executed when it takes place over a + // page object. Therefore we replace a missing page number by the + // number of the page under the mouse. + if (nPage == SDRPAGE_NOTFOUND) + { + model::SharedPageDescriptor pDescriptor ( + mrSlideSorter.GetModel().GetPageDescriptor( + mrSlideSorter.GetView().GetPageIndexAtPoint(rPosition))); + if (pDescriptor.get() != NULL && pDescriptor->GetPage()!=NULL) + nPage = (pDescriptor->GetPage()->GetPageNum() - 1) / 2; + } + + // Now comes the code that is different for the Execute and Accept: + // We simply forward the call to the AcceptDrop() or ExecuteDrop() + // methods of the DrawViewShell in the center pane. + if (nPage != SDRPAGE_NOTFOUND) + switch (eCommand) + { + case DC_ACCEPT: + nResult = pDrawViewShell->AcceptDrop( + *reinterpret_cast<const AcceptDropEvent*>(pDropEvent), + rTargetHelper, + pTargetWindow, + nPage, + nLayer); + break; + + case DC_EXECUTE: + nResult = pDrawViewShell->ExecuteDrop( + *reinterpret_cast<const ExecuteDropEvent*>(pDropEvent), + rTargetHelper, + pTargetWindow, + nPage, + nLayer); + break; + } + } + + return nResult; +} + + + +} } } // end of namespace ::sd::slidesorter::controller + diff --git a/sd/source/ui/slidesorter/controller/SlsCommand.hxx b/sd/source/ui/slidesorter/controller/SlsCommand.hxx new file mode 100644 index 000000000000..26980dc51f11 --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlsCommand.hxx @@ -0,0 +1,45 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef SD_SLIDESORTER_COMMAND_HXX +#define SD_SLIDESORTER_COMMAND_HXX + +namespace sd { namespace slidesorter { namespace controller { + +/** Base class for command objects. It specifies the interface for commands + whose execution can be scheduled via the SlotManager. +*/ +class Command +{ +public: + virtual ~Command (void) {}; + virtual void operator() (void) = 0; +}; + +} } } // end of namespace sd::slidesorter::controller + +#endif diff --git a/sd/source/ui/slidesorter/controller/SlsCurrentSlideManager.cxx b/sd/source/ui/slidesorter/controller/SlsCurrentSlideManager.cxx new file mode 100755 index 000000000000..f5864c3307a1 --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlsCurrentSlideManager.cxx @@ -0,0 +1,256 @@ +/************************************************************************* + * + * 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 "SlideSorter.hxx" +#include "model/SlideSorterModel.hxx" +#include "model/SlsPageDescriptor.hxx" +#include "controller/SlsPageSelector.hxx" +#include "controller/SlideSorterController.hxx" +#include "controller/SlsCurrentSlideManager.hxx" +#include "view/SlideSorterView.hxx" +#include "view/SlsPageObjectViewObjectContact.hxx" +#include "ViewShellBase.hxx" +#include "ViewShell.hxx" +#include "DrawViewShell.hxx" +#include "sdpage.hxx" +#include "FrameView.hxx" +#include <com/sun/star/beans/XPropertySet.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +using namespace ::sd::slidesorter::model; + +namespace sd { namespace slidesorter { namespace controller { + +CurrentSlideManager::CurrentSlideManager (SlideSorter& rSlideSorter) + : mrSlideSorter(rSlideSorter), + mnCurrentSlideIndex(-1), + mpCurrentSlide() +{ +} + + + + +CurrentSlideManager::~CurrentSlideManager (void) +{ +} + + + + +void CurrentSlideManager::CurrentSlideHasChanged (const sal_Int32 nSlideIndex) +{ + if (mnCurrentSlideIndex != nSlideIndex) + { + ReleaseCurrentSlide(); + AcquireCurrentSlide(nSlideIndex); + + // Update the selection. + mrSlideSorter.GetController().GetPageSelector().DeselectAllPages(); + if (mpCurrentSlide.get() != NULL) + mrSlideSorter.GetController().GetPageSelector().SelectPage(mpCurrentSlide); + } +} + + + + +void CurrentSlideManager::ReleaseCurrentSlide (void) +{ + if (mpCurrentSlide.get() != NULL) + { + mpCurrentSlide->SetIsCurrentPage(false); + mrSlideSorter.GetView().RequestRepaint(mpCurrentSlide); + } + + mpCurrentSlide.reset(); + mnCurrentSlideIndex = -1; +} + + + + +bool CurrentSlideManager::IsCurrentSlideIsValid (void) +{ + return mnCurrentSlideIndex >= 0 && mnCurrentSlideIndex<mrSlideSorter.GetModel().GetPageCount(); +} + + + + +void CurrentSlideManager::AcquireCurrentSlide (const sal_Int32 nSlideIndex) +{ + mnCurrentSlideIndex = nSlideIndex; + + if (IsCurrentSlideIsValid()) + { + // Get a descriptor for the XDrawPage reference. Note that the + // given XDrawPage may or may not be member of the slide sorter + // document. + mpCurrentSlide = mrSlideSorter.GetModel().GetPageDescriptor(mnCurrentSlideIndex); + if (mpCurrentSlide.get() != NULL) + { + mpCurrentSlide->SetIsCurrentPage(true); + mrSlideSorter.GetView().RequestRepaint(mpCurrentSlide); + } + } +} + + + + +void CurrentSlideManager::SwitchCurrentSlide (const sal_Int32 nSlideIndex) +{ + SwitchCurrentSlide(mrSlideSorter.GetModel().GetPageDescriptor(nSlideIndex)); +} + + + + +void CurrentSlideManager::SwitchCurrentSlide (const SharedPageDescriptor& rpDescriptor) +{ + if (rpDescriptor.get() != NULL) + { + mpCurrentSlide = rpDescriptor; + mnCurrentSlideIndex = (rpDescriptor->GetPage()->GetPageNum()-1)/2; + + ViewShell* pViewShell = mrSlideSorter.GetViewShell(); + if (pViewShell != NULL && pViewShell->IsMainViewShell()) + { + FrameView* pFrameView = pViewShell->GetFrameView(); + if (pFrameView != NULL) + pFrameView->SetSelectedPage(sal::static_int_cast<USHORT>(mnCurrentSlideIndex)); + } + else + { + // Set current page. At the moment we have to do this in two + // different ways. The UNO way is the preferable one but, alas, + // it does not work always correctly (after some kinds of model + // changes). Therefore, we call DrawViewShell::SwitchPage(), + // too. + SetCurrentSlideAtViewShellBase(rpDescriptor); + SetCurrentSlideAtXController(rpDescriptor); + } + } +} + + + + +void CurrentSlideManager::SetCurrentSlideAtViewShellBase (const SharedPageDescriptor& rpDescriptor) +{ + OSL_ASSERT(rpDescriptor.get() != NULL); + + ViewShellBase* pBase = mrSlideSorter.GetViewShellBase(); + if (pBase != NULL) + { + DrawViewShell* pDrawViewShell = dynamic_cast<DrawViewShell*>( + pBase->GetMainViewShell().get()); + if (pDrawViewShell != NULL) + { + USHORT nPageNumber = (rpDescriptor->GetPage()->GetPageNum()-1)/2; + pDrawViewShell->SwitchPage(nPageNumber); + pDrawViewShell->GetPageTabControl()->SetCurPageId(nPageNumber+1); + } + /* + else + { + presenter::PresenterViewShell* pPresenterViewShell + = dynamic_cast<presenter::PresenterViewShell*>(pBase->GetMainViewShell()); + if (pPresenterViewShell != NULL) + { + pPresenterViewShell->SetCurrentSlide( + Reference<drawing::XDrawPage>( + rpDescriptor->GetPage()->getUnoPage(), UNO_QUERY)); + } + } + */ + } +} + + + + +void CurrentSlideManager::SetCurrentSlideAtXController (const SharedPageDescriptor& rpDescriptor) +{ + OSL_ASSERT(rpDescriptor.get() != NULL); + + try + { + Reference<beans::XPropertySet> xSet (mrSlideSorter.GetXController(), UNO_QUERY); + if (xSet.is()) + { + Any aPage; + aPage <<= rpDescriptor->GetPage()->getUnoPage(); + xSet->setPropertyValue ( + String::CreateFromAscii("CurrentPage"), + aPage); + } + } + catch (beans::UnknownPropertyException aException) + { + // We have not been able to set the current page at the main view. + // This is sad but still leaves us in a valid state. Therefore, + // this exception is silently ignored. + } +} + + + + +SharedPageDescriptor CurrentSlideManager::GetCurrentSlide (void) +{ + return mpCurrentSlide; +} + + + + +void CurrentSlideManager::PrepareModelChange (void) +{ + mpCurrentSlide.reset(); +} + + + + +void CurrentSlideManager::HandleModelChange (void) +{ + if (mnCurrentSlideIndex >= 0) + { + mpCurrentSlide = mrSlideSorter.GetModel().GetPageDescriptor( + mnCurrentSlideIndex); + if (mpCurrentSlide.get() != NULL) + mpCurrentSlide->SetIsCurrentPage(true); + } +} + +} } } // end of namespace ::sd::slidesorter::controller diff --git a/sd/source/ui/slidesorter/controller/SlsFocusManager.cxx b/sd/source/ui/slidesorter/controller/SlsFocusManager.cxx new file mode 100755 index 000000000000..dcda73d38dba --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlsFocusManager.cxx @@ -0,0 +1,362 @@ +/************************************************************************* + * + * 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 "controller/SlsFocusManager.hxx" + +#include "SlideSorter.hxx" +#include "PaneDockingWindow.hxx" +#include "controller/SlideSorterController.hxx" +#include "controller/SlsSelectionManager.hxx" +#include "model/SlideSorterModel.hxx" +#include "model/SlsPageDescriptor.hxx" +#include "view/SlideSorterView.hxx" +#include "view/SlsLayouter.hxx" +#include <vcl/toolbox.hxx> + +#include "Window.hxx" +#include "sdpage.hxx" + +namespace sd { namespace slidesorter { namespace controller { + +FocusManager::FocusManager (SlideSorter& rSlideSorter) + : mrSlideSorter(rSlideSorter), + mnPageIndex(0), + mbPageIsFocused(false) +{ + if (mrSlideSorter.GetModel().GetPageCount() > 0) + mnPageIndex = 0; +} + + + + +FocusManager::~FocusManager (void) +{ +} + + + + +void FocusManager::MoveFocus (FocusMoveDirection eDirection) +{ + if (mnPageIndex >= 0 && mbPageIsFocused) + { + HideFocusIndicator (GetFocusedPageDescriptor()); + + int nColumnCount (mrSlideSorter.GetView().GetLayouter().GetColumnCount()); + switch (eDirection) + { + case FMD_NONE: + if (mnPageIndex >= mrSlideSorter.GetModel().GetPageCount()) + mnPageIndex = mrSlideSorter.GetModel().GetPageCount() - 1; + break; + + case FMD_LEFT: + mnPageIndex -= 1; + if (mnPageIndex < 0) + { + mnPageIndex = mrSlideSorter.GetModel().GetPageCount() - 1; + SetFocusToToolBox(); + } + break; + + case FMD_RIGHT: + mnPageIndex += 1; + if (mnPageIndex >= mrSlideSorter.GetModel().GetPageCount()) + { + mnPageIndex = 0; + SetFocusToToolBox(); + } + break; + + case FMD_UP: + { + int nColumn = mnPageIndex % nColumnCount; + mnPageIndex -= nColumnCount; + if (mnPageIndex < 0) + { + // Wrap arround to the bottom row or the one above and + // go to the correct column. + int nCandidate = mrSlideSorter.GetModel().GetPageCount()-1; + int nCandidateColumn = nCandidate % nColumnCount; + if (nCandidateColumn > nColumn) + mnPageIndex = nCandidate - (nCandidateColumn-nColumn); + else if (nCandidateColumn < nColumn) + mnPageIndex = nCandidate + - nColumnCount + + (nColumn - nCandidateColumn); + else + mnPageIndex = nCandidate; + } + } + break; + + case FMD_DOWN: + { + int nColumn = mnPageIndex % nColumnCount; + mnPageIndex += nColumnCount; + if (mnPageIndex >= mrSlideSorter.GetModel().GetPageCount()) + { + // Wrap arround to the correct column. + mnPageIndex = nColumn; + } + } + break; + } + + if (mbPageIsFocused) + ShowFocusIndicator(GetFocusedPageDescriptor(), true); + } +} + + + + +void FocusManager::ShowFocus (const bool bScrollToFocus) +{ + mbPageIsFocused = true; + ShowFocusIndicator(GetFocusedPageDescriptor(), bScrollToFocus); +} + + + + +void FocusManager::HideFocus (void) +{ + mbPageIsFocused = false; + HideFocusIndicator(GetFocusedPageDescriptor()); +} + + + + +bool FocusManager::ToggleFocus (void) +{ + if (mnPageIndex >= 0) + { + if (mbPageIsFocused) + HideFocus (); + else + ShowFocus (); + } + return mbPageIsFocused; +} + + + + +bool FocusManager::HasFocus (void) const +{ + return mrSlideSorter.GetView().GetWindow()->HasFocus(); +} + + + + +model::SharedPageDescriptor FocusManager::GetFocusedPageDescriptor (void) const +{ + return mrSlideSorter.GetModel().GetPageDescriptor(mnPageIndex); +} + + + + +sal_Int32 FocusManager::GetFocusedPageIndex (void) const +{ + return mnPageIndex; +} + + + + +void FocusManager::FocusPage (sal_Int32 nPageIndex) +{ + if (nPageIndex != mnPageIndex) + { + // Hide the focus while switching it to the specified page. + FocusHider aHider (*this); + mnPageIndex = nPageIndex; + } + + if (HasFocus() && !IsFocusShowing()) + ShowFocus(); +} + + + + +void FocusManager::SetFocusedPage (const model::SharedPageDescriptor& rpDescriptor) +{ + if (rpDescriptor.get() != NULL) + { + FocusHider aFocusHider (*this); + mnPageIndex = (rpDescriptor->GetPage()->GetPageNum()-1)/2; + } +} + + + + +void FocusManager::SetFocusedPage (sal_Int32 nPageIndex) +{ + FocusHider aFocusHider (*this); + mnPageIndex = nPageIndex; +} + + + + +bool FocusManager::IsFocusShowing (void) const +{ + return HasFocus() && mbPageIsFocused; +} + + + + +void FocusManager::HideFocusIndicator (const model::SharedPageDescriptor& rpDescriptor) +{ + if (rpDescriptor.get() != NULL) + { + rpDescriptor->RemoveFocus(); + mrSlideSorter.GetView().RequestRepaint(rpDescriptor); + } +} + + + + +void FocusManager::ShowFocusIndicator ( + const model::SharedPageDescriptor& rpDescriptor, + const bool bScrollToFocus) +{ + if (rpDescriptor.get() != NULL) + { + rpDescriptor->SetFocus (); + + if (bScrollToFocus) + { + // Scroll the focused page object into the visible area and repaint + // it, so that the focus indicator becomes visible. + view::SlideSorterView& rView (mrSlideSorter.GetView()); + mrSlideSorter.GetController().GetSelectionManager()->MakeRectangleVisible ( + rView.GetPageBoundingBox ( + GetFocusedPageDescriptor(), + view::SlideSorterView::CS_MODEL, + view::SlideSorterView::BBT_INFO)); + } + + mrSlideSorter.GetView().RequestRepaint (rpDescriptor); + NotifyFocusChangeListeners(); + } +} + + + + +void FocusManager::AddFocusChangeListener (const Link& rListener) +{ + if (::std::find (maFocusChangeListeners.begin(), maFocusChangeListeners.end(), rListener) + == maFocusChangeListeners.end()) + { + maFocusChangeListeners.push_back (rListener); + } +} + + + + +void FocusManager::RemoveFocusChangeListener (const Link& rListener) +{ + maFocusChangeListeners.erase ( + ::std::find (maFocusChangeListeners.begin(), maFocusChangeListeners.end(), rListener)); +} + + + + +void FocusManager::SetFocusToToolBox (void) +{ + HideFocus(); + + if (mrSlideSorter.GetViewShell() != NULL) + { + ::Window* pParentWindow = mrSlideSorter.GetViewShell()->GetParentWindow(); + DockingWindow* pDockingWindow = NULL; + while (pParentWindow!=NULL && pDockingWindow==NULL) + { + pDockingWindow = dynamic_cast<DockingWindow*>(pParentWindow); + pParentWindow = pParentWindow->GetParent(); + } + if (pDockingWindow) + { + PaneDockingWindow* pPaneDockingWindow = dynamic_cast<PaneDockingWindow*>(pDockingWindow); + if (pPaneDockingWindow != NULL) + pPaneDockingWindow->GetToolBox().GrabFocus(); + } + } +} + + + + +void FocusManager::NotifyFocusChangeListeners (void) const +{ + // Create a copy of the listener list to be safe when that is modified. + ::std::vector<Link> aListeners (maFocusChangeListeners); + + // Tell the slection change listeners that the selection has changed. + ::std::vector<Link>::iterator iListener (aListeners.begin()); + ::std::vector<Link>::iterator iEnd (aListeners.end()); + for (; iListener!=iEnd; ++iListener) + { + iListener->Call(NULL); + } +} + + + + +FocusManager::FocusHider::FocusHider (FocusManager& rManager) +: mbFocusVisible(rManager.IsFocusShowing()) +, mrManager(rManager) +{ + mrManager.HideFocus(); +} + + + + +FocusManager::FocusHider::~FocusHider (void) +{ + if (mbFocusVisible) + mrManager.ShowFocus(); +} + +} } } // end of namespace ::sd::slidesorter::controller + diff --git a/sd/source/ui/slidesorter/controller/SlsHideSlideFunction.cxx b/sd/source/ui/slidesorter/controller/SlsHideSlideFunction.cxx new file mode 100644 index 000000000000..666d4b017302 --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlsHideSlideFunction.cxx @@ -0,0 +1,169 @@ +/************************************************************************* + * + * 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 "SlsHideSlideFunction.hxx" + +#include "SlideSorter.hxx" +#include "model/SlsPageEnumerationProvider.hxx" +#include "model/SlsPageDescriptor.hxx" +#include "view/SlideSorterView.hxx" + +#include "app.hrc" +#include "drawdoc.hxx" +#include "sdpage.hxx" +#include "ViewShell.hxx" + +#include <sfx2/viewfrm.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/request.hxx> +#include <svx/svxids.hrc> + +namespace sd { namespace slidesorter { namespace controller { + +TYPEINIT1(HideSlideFunction, SlideFunction); + +HideSlideFunction::HideSlideFunction ( + SlideSorter& rSlideSorter, + SfxRequest& rRequest) + : SlideFunction( rSlideSorter, rRequest), + mrSlideSorter(rSlideSorter) +{ +} + + + + +HideSlideFunction::~HideSlideFunction (void) +{ +} + + + + +FunctionReference HideSlideFunction::Create ( + SlideSorter& rSlideSorter, + SfxRequest& rRequest ) +{ + FunctionReference xFunc( new HideSlideFunction( rSlideSorter, rRequest ) ); + xFunc->DoExecute(rRequest); + return xFunc; +} + + + + +void HideSlideFunction::DoExecute (SfxRequest& rRequest) +{ + SlideFunction::DoExecute(rRequest); + + model::PageEnumeration aSelectedPages ( + model::PageEnumerationProvider::CreateSelectedPagesEnumeration(mrSlideSorter.GetModel())); + + ExclusionState eState (UNDEFINED); + + switch (rRequest.GetSlot()) + { + case SID_HIDE_SLIDE: + eState = EXCLUDED; + break; + + case SID_SHOW_SLIDE: + eState = INCLUDED; + break; + + default: + eState = UNDEFINED; + break; + } + + if (eState != UNDEFINED) + { + // Set status at the selected pages. + aSelectedPages.Rewind (); + while (aSelectedPages.HasMoreElements()) + { + model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement()); + pDescriptor->GetPage()->SetExcluded (eState==EXCLUDED); + static_cast<view::SlideSorterView*>(mpView)->RequestRepaint(pDescriptor); + } + } + + SfxBindings& rBindings = mpViewShell->GetViewFrame()->GetBindings(); + rBindings.Invalidate (SID_PRESENTATION); + rBindings.Invalidate (SID_REHEARSE_TIMINGS); + rBindings.Invalidate (SID_HIDE_SLIDE); + rBindings.Invalidate (SID_SHOW_SLIDE); + mpDoc->SetChanged(); +} + + + + +HideSlideFunction::ExclusionState HideSlideFunction::GetExclusionState ( + model::PageEnumeration& rPageSet) +{ + ExclusionState eState (UNDEFINED); + BOOL bState; + + // Get toggle state of the selected pages. + while (rPageSet.HasMoreElements() && eState!=MIXED) + { + bState = rPageSet.GetNextElement()->GetPage()->IsExcluded(); + switch (eState) + { + case UNDEFINED: + // Use the first selected page to set the inital value. + eState = bState ? EXCLUDED : INCLUDED; + break; + + case EXCLUDED: + // The pages before where all not part of the show, + // this one is. + if ( ! bState) + eState = MIXED; + break; + + case INCLUDED: + // The pages before where all part of the show, + // this one is not. + if (bState) + eState = MIXED; + break; + + case MIXED: + default: + // No need to change anything. + break; + } + } + + return eState; +} + +} } } // end of namespace ::sd::slidesorter::controller diff --git a/sd/source/ui/slidesorter/controller/SlsHideSlideFunction.hxx b/sd/source/ui/slidesorter/controller/SlsHideSlideFunction.hxx new file mode 100644 index 000000000000..8cef9455619f --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlsHideSlideFunction.hxx @@ -0,0 +1,73 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef SD_SLIDESORTER_HIDE_SLIDE_FUNCTION_HXX +#define SD_SLIDESORTER_HIDE_SLIDE_FUNCTION_HXX + +#include "controller/SlsSlideFunction.hxx" +#include "model/SlsPageEnumeration.hxx" + + +namespace sd { namespace slidesorter { namespace controller { + +/** Toggle the hidden flag of the selected slides. + When the selected pages have not all the same state they will all set to + hidden. When all selected pages have the same state this state is + toggled for all of them +*/ +class HideSlideFunction + : public SlideFunction +{ +public: + TYPEINFO(); + + virtual ~HideSlideFunction (void); + + static FunctionReference Create( SlideSorter& rSlideSorter, SfxRequest& rRequest ); + virtual void DoExecute( SfxRequest& rReq ); + + // The state of a set of slides with respect to being excluded from the + // slide show. + enum ExclusionState {UNDEFINED, EXCLUDED, INCLUDED, MIXED}; + + /** Return for the given set of slides whether they included are + excluded from the slide show. + */ + static ExclusionState GetExclusionState (model::PageEnumeration& rPageSet); + +protected: + HideSlideFunction ( + SlideSorter& rSlideSorter, + SfxRequest& rRequest); + + SlideSorter& mrSlideSorter; +}; + +} } } // end of namespace ::sd::slidesorter::controller + +#endif + diff --git a/sd/source/ui/slidesorter/controller/SlsListener.cxx b/sd/source/ui/slidesorter/controller/SlsListener.cxx new file mode 100755 index 000000000000..94b3b4afe717 --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlsListener.cxx @@ -0,0 +1,599 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" +#include "SlsListener.hxx" + +#include "SlideSorter.hxx" +#include "SlideSorterViewShell.hxx" +#include "ViewShellHint.hxx" +#include "controller/SlideSorterController.hxx" +#include "controller/SlsPageSelector.hxx" +#include "controller/SlsCurrentSlideManager.hxx" +#include "model/SlideSorterModel.hxx" +#include "view/SlideSorterView.hxx" +#include "drawdoc.hxx" + +#include "glob.hrc" +#include "ViewShellBase.hxx" +#include "ViewShellManager.hxx" +#include "FrameView.hxx" +#include "EventMultiplexer.hxx" +#include <com/sun/star/document/XEventBroadcaster.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/frame/FrameActionEvent.hpp> +#include <com/sun/star/frame/FrameAction.hpp> +#include <sfx2/viewfrm.hxx> +#include <tools/diagnose_ex.h> + + +using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star; + +namespace sd { namespace slidesorter { namespace controller { + + +Listener::Listener ( + SlideSorter& rSlideSorter) + : ListenerInterfaceBase(maMutex), + mrSlideSorter(rSlideSorter), + mrController(mrSlideSorter.GetController()), + mpBase(mrSlideSorter.GetViewShellBase()), + mbListeningToDocument (false), + mbListeningToUNODocument (false), + mbListeningToController (false), + mbListeningToFrame (false), + mbIsMainViewChangePending(false), + mxControllerWeak(), + mxFrameWeak(), + mpModelChangeLock() +{ + StartListening (*mrSlideSorter.GetModel().GetDocument()); + mbListeningToDocument = true; + + // Connect to the UNO document. + Reference<document::XEventBroadcaster> xBroadcaster ( + mrSlideSorter.GetModel().GetDocument()->getUnoModel(), uno::UNO_QUERY); + if (xBroadcaster.is()) + { + xBroadcaster->addEventListener (this); + mbListeningToUNODocument = true; + } + + // Listen for disposing events from the document. + Reference<XComponent> xComponent (xBroadcaster, UNO_QUERY); + if (xComponent.is()) + xComponent->addEventListener ( + Reference<lang::XEventListener>( + static_cast<XWeak*>(this), UNO_QUERY)); + + // Connect to the frame to listen for controllers being exchanged. + bool bIsMainViewShell (false); + ViewShell* pViewShell = mrSlideSorter.GetViewShell(); + if (pViewShell != NULL) + bIsMainViewShell = pViewShell->IsMainViewShell(); + if ( ! bIsMainViewShell) + { + // Listen to changes of certain properties. + Reference<frame::XFrame> xFrame; + Reference<frame::XController> xController (mrSlideSorter.GetXController()); + if (xController.is()) + xFrame = xController->getFrame(); + mxFrameWeak = xFrame; + if (xFrame.is()) + { + xFrame->addFrameActionListener ( + Reference<frame::XFrameActionListener>( + static_cast<XWeak*>(this), UNO_QUERY)); + mbListeningToFrame = true; + } + + // Connect to the current controller. + ConnectToController (); + } + + // Listen for hints of the MainViewShell as well. If that is not yet + // present then the EventMultiplexer will tell us when it is available. + if (mpBase != NULL) + { + ViewShell* pMainViewShell = mpBase->GetMainViewShell().get(); + if (pMainViewShell != NULL + && pMainViewShell!=pViewShell) + { + StartListening (*pMainViewShell); + } + + Link aLink (LINK(this, Listener, EventMultiplexerCallback)); + mpBase->GetEventMultiplexer()->AddEventListener( + aLink, + tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED + | tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED + | tools::EventMultiplexerEvent::EID_CONTROLLER_ATTACHED + | tools::EventMultiplexerEvent::EID_CONTROLLER_DETACHED + | tools::EventMultiplexerEvent::EID_CONFIGURATION_UPDATED); + } +} + + + + +Listener::~Listener (void) +{ + DBG_ASSERT( !mbListeningToDocument && !mbListeningToUNODocument && !mbListeningToFrame, + "sd::Listener::~Listener(), disposing() was not called, ask DBO!" ); +} + + + + +void Listener::ReleaseListeners (void) +{ + if (mbListeningToDocument) + { + EndListening (*mrSlideSorter.GetModel().GetDocument()); + mbListeningToDocument = false; + } + + if (mbListeningToUNODocument) + { + Reference<document::XEventBroadcaster> xBroadcaster ( + mrSlideSorter.GetModel().GetDocument()->getUnoModel(), UNO_QUERY); + if (xBroadcaster.is()) + xBroadcaster->removeEventListener (this); + + // Remove the dispose listener. + Reference<XComponent> xComponent (xBroadcaster, UNO_QUERY); + if (xComponent.is()) + xComponent->removeEventListener ( + Reference<lang::XEventListener>( + static_cast<XWeak*>(this), UNO_QUERY)); + + mbListeningToUNODocument = false; + } + + if (mbListeningToFrame) + { + // Listen to changes of certain properties. + Reference<frame::XFrame> xFrame (mxFrameWeak); + if (xFrame.is()) + { + xFrame->removeFrameActionListener ( + Reference<frame::XFrameActionListener>( + static_cast<XWeak*>(this), UNO_QUERY)); + mbListeningToFrame = false; + } + } + + DisconnectFromController (); + + if (mpBase != NULL) + { + Link aLink (LINK(this, Listener, EventMultiplexerCallback)); + mpBase->GetEventMultiplexer()->RemoveEventListener( + aLink, + tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED + | tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED + | tools::EventMultiplexerEvent::EID_CONTROLLER_ATTACHED + | tools::EventMultiplexerEvent::EID_CONTROLLER_DETACHED + | tools::EventMultiplexerEvent::EID_CONFIGURATION_UPDATED); + } +} + + + + +void Listener::ConnectToController (void) +{ + ViewShell* pShell = mrSlideSorter.GetViewShell(); + + // Register at the controller of the main view shell (if we are that not + // ourself). + if (pShell==NULL || ! pShell->IsMainViewShell()) + { + Reference<frame::XController> xController (mrSlideSorter.GetXController()); + + // Listen to changes of certain properties. + Reference<beans::XPropertySet> xSet (xController, UNO_QUERY); + if (xSet.is()) + { + try + { + xSet->addPropertyChangeListener(String::CreateFromAscii("CurrentPage"), this); + } + catch (beans::UnknownPropertyException aEvent) + { + DBG_UNHANDLED_EXCEPTION(); + } + try + { + xSet->addPropertyChangeListener(String::CreateFromAscii("IsMasterPageMode"), this); + } + catch (beans::UnknownPropertyException aEvent) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + // Listen for disposing events. + Reference<XComponent> xComponent (xController, UNO_QUERY); + if (xComponent.is()) + { + xComponent->addEventListener ( + Reference<lang::XEventListener>(static_cast<XWeak*>(this), UNO_QUERY)); + + mxControllerWeak = xController; + mbListeningToController = true; + } + } +} + + + + +void Listener::DisconnectFromController (void) +{ + if (mbListeningToController) + { + Reference<frame::XController> xController = mxControllerWeak; + Reference<beans::XPropertySet> xSet (xController, UNO_QUERY); + try + { + // Remove the property listener. + if (xSet.is()) + { + xSet->removePropertyChangeListener ( + String::CreateFromAscii("CurrentPage"), + this); + xSet->removePropertyChangeListener ( + String::CreateFromAscii("IsMasterPageMode"), + this); + } + + // Remove the dispose listener. + Reference<XComponent> xComponent (xController, UNO_QUERY); + if (xComponent.is()) + xComponent->removeEventListener ( + Reference<lang::XEventListener>( + static_cast<XWeak*>(this), UNO_QUERY)); + } + catch (beans::UnknownPropertyException aEvent) + { + DBG_UNHANDLED_EXCEPTION(); + } + + mbListeningToController = false; + mxControllerWeak = Reference<frame::XController>(); + } +} + + + + +void Listener::Notify ( + SfxBroadcaster& rBroadcaster, + const SfxHint& rHint) +{ + if (rHint.ISA(SdrHint)) + { + SdrHint& rSdrHint (*PTR_CAST(SdrHint,&rHint)); + if(rSdrHint.GetKind() == HINT_PAGEORDERCHG ) + { + if (rBroadcaster.ISA(SdDrawDocument)) + { + SdDrawDocument& rDocument ( + static_cast<SdDrawDocument&>(rBroadcaster)); + if (rDocument.GetMasterSdPageCount(PK_STANDARD) + == rDocument.GetMasterSdPageCount(PK_NOTES)) + { + mrController.HandleModelChange(); + } + } + } + } + else if (rHint.ISA(ViewShellHint)) + { + ViewShellHint& rViewShellHint (*PTR_CAST(ViewShellHint,&rHint)); + switch (rViewShellHint.GetHintId()) + { + case ViewShellHint::HINT_PAGE_RESIZE_START: + // Initiate a model change but do nothing (well, not much) + // until we are told that all slides have been resized. + mpModelChangeLock.reset(new SlideSorterController::ModelChangeLock(mrController)); + mrController.HandleModelChange(); + break; + + case ViewShellHint::HINT_PAGE_RESIZE_END: + // All slides have been resized. The model has to be updated. + mpModelChangeLock.reset(); + break; + + case ViewShellHint::HINT_CHANGE_EDIT_MODE_START: + mrController.PrepareEditModeChange(); + break; + + case ViewShellHint::HINT_CHANGE_EDIT_MODE_END: + mrController.FinishEditModeChange(); + break; + + case ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_START: + mpModelChangeLock.reset(new SlideSorterController::ModelChangeLock(mrController)); + break; + + case ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_END: + mpModelChangeLock.reset(); + break; + } + } +} + + + + +IMPL_LINK(Listener, EventMultiplexerCallback, ::sd::tools::EventMultiplexerEvent*, pEvent) +{ + switch (pEvent->meEventId) + { + case tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED: + { + if (mpBase != NULL) + { + ViewShell* pMainViewShell = mpBase->GetMainViewShell().get(); + if (pMainViewShell != NULL) + EndListening(*pMainViewShell); + } + } + break; + + + case tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED: + mbIsMainViewChangePending = true; + break; + + case tools::EventMultiplexerEvent::EID_CONFIGURATION_UPDATED: + if (mbIsMainViewChangePending && mpBase != NULL) + { + mbIsMainViewChangePending = false; + ViewShell* pMainViewShell = mpBase->GetMainViewShell().get(); + if (pMainViewShell != NULL + && pMainViewShell!=mrSlideSorter.GetViewShell()) + { + StartListening (*pMainViewShell); + } + } + break; + + case tools::EventMultiplexerEvent::EID_CONTROLLER_ATTACHED: + { + ConnectToController(); + mrController.GetPageSelector().UpdateAllPages(); + UpdateEditMode(); + } + break; + + + case tools::EventMultiplexerEvent::EID_CONTROLLER_DETACHED: + DisconnectFromController(); + break; + + default: + break; + } + + return 0; +} + + + + +//===== lang::XEventListener ================================================ + +void SAL_CALL Listener::disposing ( + const lang::EventObject& rEventObject) + throw (RuntimeException) +{ + if ((mbListeningToDocument || mbListeningToUNODocument) + && mrSlideSorter.GetModel().GetDocument()!=NULL + && rEventObject.Source + == mrSlideSorter.GetModel().GetDocument()->getUnoModel()) + { + mbListeningToDocument = false; + mbListeningToUNODocument = false; + } + else if (mbListeningToController) + { + Reference<frame::XController> xController (mxControllerWeak); + if (rEventObject.Source == xController) + { + mbListeningToController = false; + } + } +} + + + + +//===== document::XEventListener ============================================ + +void SAL_CALL Listener::notifyEvent ( + const document::EventObject& ) + throw (RuntimeException) +{ +} + + + + +//===== beans::XPropertySetListener ========================================= + +void SAL_CALL Listener::propertyChange ( + const PropertyChangeEvent& rEvent) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + static const ::rtl::OUString sCurrentPagePropertyName ( + RTL_CONSTASCII_USTRINGPARAM("CurrentPage")); + static const ::rtl::OUString sEditModePropertyName ( + RTL_CONSTASCII_USTRINGPARAM("IsMasterPageMode")); + + if (rEvent.PropertyName.equals (sCurrentPagePropertyName)) + { + Any aCurrentPage = rEvent.NewValue; + Reference<beans::XPropertySet> xPageSet (aCurrentPage, UNO_QUERY); + if (xPageSet.is()) + { + try + { + Any aPageNumber = xPageSet->getPropertyValue ( + String(RTL_CONSTASCII_USTRINGPARAM("Number"))); + sal_Int32 nCurrentPage = 0; + aPageNumber >>= nCurrentPage; + mrController.GetPageSelector().UpdateAllPages (); + // The selection is already set but we call SelectPage() + // nevertheless in order to make the new current page the + // last recently selected page of the PageSelector. This is + // used when making the selection visible. + mrController.GetPageSelector().SelectPage(nCurrentPage-1); + mrController.GetCurrentSlideManager()->CurrentSlideHasChanged(nCurrentPage-1); + } + catch (beans::UnknownPropertyException aEvent) + { + DBG_UNHANDLED_EXCEPTION(); + } + catch (lang::DisposedException&) + { + // Something is already disposed. There is not much we can + // do, except not to crash. + } + } + } + else if (rEvent.PropertyName.equals (sEditModePropertyName)) + { + sal_Bool bIsMasterPageMode = sal_False; + rEvent.NewValue >>= bIsMasterPageMode; + mrController.ChangeEditMode ( + bIsMasterPageMode ? EM_MASTERPAGE : EM_PAGE); + } +} + + + + +//===== frame::XFrameActionListener ========================================== + +void SAL_CALL Listener::frameAction (const frame::FrameActionEvent& rEvent) + throw (::com::sun::star::uno::RuntimeException) +{ + switch (rEvent.Action) + { + case frame::FrameAction_COMPONENT_DETACHING: + DisconnectFromController(); + break; + + case frame::FrameAction_COMPONENT_REATTACHED: + { + ConnectToController(); + mrController.GetPageSelector().UpdateAllPages(); + UpdateEditMode(); + } + break; + + default: + break; + } +} + + + + +//===== accessibility::XAccessibleEventListener ============================== + +void SAL_CALL Listener::notifyEvent ( + const AccessibleEventObject& ) + throw (RuntimeException) +{ +} + + + + +void SAL_CALL Listener::disposing (void) +{ + ReleaseListeners(); +} + + + + +void Listener::UpdateEditMode (void) +{ + // When there is a new controller then the edit mode may have changed at + // the same time. + Reference<frame::XController> xController (mxControllerWeak); + Reference<beans::XPropertySet> xSet (xController, UNO_QUERY); + bool bIsMasterPageMode = false; + if (xSet != NULL) + { + try + { + Any aValue (xSet->getPropertyValue( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IsMasterPageMode")))); + aValue >>= bIsMasterPageMode; + } + catch (beans::UnknownPropertyException e) + { + // When the property is not supported then the master page mode + // is not supported, too. + bIsMasterPageMode = false; + } + } + mrController.ChangeEditMode ( + bIsMasterPageMode ? EM_MASTERPAGE : EM_PAGE); +} + + + + +void Listener::ThrowIfDisposed (void) + throw (::com::sun::star::lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + throw lang::DisposedException ( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "SlideSorterController object has already been disposed")), + static_cast<uno::XWeak*>(this)); + } +} + + + + +} } } // end of namespace ::sd::slidesorter::controller diff --git a/sd/source/ui/slidesorter/controller/SlsListener.hxx b/sd/source/ui/slidesorter/controller/SlsListener.hxx new file mode 100644 index 000000000000..5613452a1b59 --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlsListener.hxx @@ -0,0 +1,185 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef SD_SLIDESORTER_SLIDE_SORTER_LISTENER_HXX +#define SD_SLIDESORTER_SLIDE_SORTER_LISTENER_HXX + +#include "MutexOwner.hxx" +#include "controller/SlideSorterController.hxx" +#include <com/sun/star/document/XEventListener.hpp> +#ifndef _COM_SUN_STAR_DOCUMENT_XPROPERTYCHANGELISTENER_HPP_ +#include <com/sun/star/beans/XPropertyChangeListener.hpp> +#endif +#include <com/sun/star/accessibility/XAccessibleEventListener.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/frame/XFrameActionListener.hpp> +#include <cppuhelper/compbase4.hxx> + +#include <svl/lstner.hxx> +#include <tools/link.hxx> +#include <boost/shared_ptr.hpp> + +namespace sd { +class ViewShellBase; +} + +namespace sd { namespace tools { +class EventMultiplexerEvent; +} } + +namespace sd { namespace slidesorter { +class SlideSorter; +} } + + +namespace sd { namespace slidesorter { namespace controller { + +typedef cppu::WeakComponentImplHelper4< + ::com::sun::star::document::XEventListener, + ::com::sun::star::beans::XPropertyChangeListener, + ::com::sun::star::accessibility::XAccessibleEventListener, + ::com::sun::star::frame::XFrameActionListener + > ListenerInterfaceBase; + +class SlideSorterController; + +/** Listen for events of various types and sources and react to them. This + class is a part of the controller. + + When the view shell in the center pane is replaced by another the + associated controller is replaced as well. Therefore we have to + register at the frame and on certain FrameActionEvents to stop listening + to the old controller and register as listener at the new one. +*/ +class Listener + : protected MutexOwner, + public ListenerInterfaceBase, + public SfxListener +{ +public: + Listener (SlideSorter& rSlideSorter); + virtual ~Listener (void); + + /** Connect to the current controller of the view shell as listener. + This method is called once during initialization and every time a + FrameActionEvent signals the current controller being exchanged. + When the connection is successfull then the flag + mbListeningToController is set to <TRUE/>. + */ + void ConnectToController (void); + + /** Disconnect from the current controller of the view shell as + listener. This method is called once during initialization and + every time a FrameActionEvent signals the current controller being + exchanged. When this method terminates then mbListeningToController + is <FALSE/>. + */ + void DisconnectFromController (void); + + virtual void Notify ( + SfxBroadcaster& rBroadcaster, + const SfxHint& rHint); + + //===== lang::XEventListener ============================================ + virtual void SAL_CALL + disposing (const ::com::sun::star::lang::EventObject& rEventObject) + throw (::com::sun::star::uno::RuntimeException); + + + //===== document::XEventListener ======================================== + virtual void SAL_CALL + notifyEvent ( + const ::com::sun::star::document::EventObject& rEventObject) + throw (::com::sun::star::uno::RuntimeException); + + //===== beans::XPropertySetListener ===================================== + virtual void SAL_CALL + propertyChange ( + const com::sun::star::beans::PropertyChangeEvent& rEvent) + throw (::com::sun::star::uno::RuntimeException); + + //===== accessibility::XAccessibleEventListener ========================== + virtual void SAL_CALL + notifyEvent ( + const ::com::sun::star::accessibility::AccessibleEventObject& + rEvent) + throw (::com::sun::star::uno::RuntimeException); + + //===== frame::XFrameActionListener ====================================== + /** For certain actions the listener connects to a new controller of the + frame it is listening to. This usually happens when the view shell + in the center pane is replaced by another view shell. + */ + virtual void SAL_CALL + frameAction (const ::com::sun::star::frame::FrameActionEvent& rEvent) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL disposing (void); + +private: + SlideSorter& mrSlideSorter; + SlideSorterController& mrController; + ViewShellBase* mpBase; + + /// Remember whether we are listening to the document. + bool mbListeningToDocument; + /// Remember whether we are listening to the UNO document. + bool mbListeningToUNODocument; + /// Remember whether we are listening to the UNO controller. + bool mbListeningToController; + /// Remember whether we are listening to the frame. + bool mbListeningToFrame; + bool mbIsMainViewChangePending; + + ::com::sun::star::uno::WeakReference< ::com::sun::star::frame::XController> mxControllerWeak; + ::com::sun::star::uno::WeakReference< ::com::sun::star::frame::XFrame> mxFrameWeak; + + /** This object is used to lock the model between some + events. It is refernce counted in order to cope with events that + are expected but never sent. + */ + ::boost::shared_ptr<SlideSorterController::ModelChangeLock> mpModelChangeLock; + + void ReleaseListeners (void); + + /** Called when the edit mode has changed. Update model accordingly. + */ + void UpdateEditMode (void); + + /** This method throws a DisposedException when the object has already been + disposed. + */ + void ThrowIfDisposed (void) + throw (::com::sun::star::lang::DisposedException); + + DECL_LINK(EventMultiplexerCallback, tools::EventMultiplexerEvent*); +}; + +} } } // end of namespace ::sd::slidesorter::controller + +#endif diff --git a/sd/source/ui/slidesorter/controller/SlsPageObjectFactory.cxx b/sd/source/ui/slidesorter/controller/SlsPageObjectFactory.cxx new file mode 100644 index 000000000000..5ac41849a674 --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlsPageObjectFactory.cxx @@ -0,0 +1,100 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + +#include "controller/SlsPageObjectFactory.hxx" + +#include "view/SlsPageObject.hxx" +#include "view/SlsPageObjectViewContact.hxx" +#include "view/SlsPageObjectViewObjectContact.hxx" + +#include "sdpage.hxx" + + +namespace sd { namespace slidesorter { namespace controller { + + +PageObjectFactory::PageObjectFactory ( + const ::boost::shared_ptr<cache::PageCache>& rpCache, + const ::boost::shared_ptr<controller::Properties>& rpProperties) + : mpPageCache(rpCache), + mpProperties(rpProperties) +{ +} + + + + +PageObjectFactory::~PageObjectFactory (void) +{ +} + + + + +view::PageObject* PageObjectFactory::CreatePageObject ( + SdPage* pPage, + const model::SharedPageDescriptor& rpDescriptor) const +{ + return new view::PageObject( + Rectangle (Point(0,0), pPage->GetSize()), + pPage, + rpDescriptor); +} + + + + +::sdr::contact::ViewContact* + PageObjectFactory::CreateViewContact ( + view::PageObject* pPageObject, + const model::SharedPageDescriptor& rpDescriptor) const +{ + return new view::PageObjectViewContact ( + *pPageObject, + rpDescriptor); +} + + + + +::sdr::contact::ViewObjectContact* + PageObjectFactory::CreateViewObjectContact ( + ::sdr::contact::ObjectContact& rObjectContact, + ::sdr::contact::ViewContact& rViewContact) const +{ + return new view::PageObjectViewObjectContact ( + rObjectContact, + rViewContact, + mpPageCache, + mpProperties); +} + + +} } } // end of namespace ::sd::slidesorter::controller diff --git a/sd/source/ui/slidesorter/controller/SlsPageSelector.cxx b/sd/source/ui/slidesorter/controller/SlsPageSelector.cxx new file mode 100755 index 000000000000..0e8f5e100d1c --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlsPageSelector.cxx @@ -0,0 +1,324 @@ +/************************************************************************* + * + * 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 "controller/SlsPageSelector.hxx" + +#include "SlideSorter.hxx" +#include "SlideSorterViewShell.hxx" +#include "controller/SlideSorterController.hxx" +#include "controller/SlsSelectionManager.hxx" +#include "model/SlsPageDescriptor.hxx" +#include "model/SlsPageEnumerationProvider.hxx" +#include "model/SlideSorterModel.hxx" +#include "view/SlideSorterView.hxx" + +#include "sdpage.hxx" +#include "ViewShell.hxx" +#include "DrawViewShell.hxx" +#include "ViewShellBase.hxx" +#include <com/sun/star/drawing/XDrawView.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::sd::slidesorter::model; +using namespace ::sd::slidesorter::view; + +namespace sd { namespace slidesorter { namespace controller { + + +PageSelector::PageSelector (SlideSorter& rSlideSorter) + : mrModel(rSlideSorter.GetModel()), + mrSlideSorter(rSlideSorter), + mrController(mrSlideSorter.GetController()), + mnSelectedPageCount(0), + mnBroadcastDisableLevel(0), + mbSelectionChangeBroadcastPending(false), + mpMostRecentlySelectedPage(), + mpSelectionAnchor() +{ + CountSelectedPages (); +} + + + + +void PageSelector::SelectAllPages (void) +{ + int nPageCount = mrModel.GetPageCount(); + for (int nPageIndex=0; nPageIndex<nPageCount; nPageIndex++) + SelectPage (nPageIndex); +} + + + + +void PageSelector::DeselectAllPages (void) +{ + int nPageCount = mrModel.GetPageCount(); + for (int nPageIndex=0; nPageIndex<nPageCount; nPageIndex++) + DeselectPage (nPageIndex); + DBG_ASSERT (mnSelectedPageCount==0, + "PageSelector::DeselectAllPages: the selected pages counter is not 0"); + mnSelectedPageCount = 0; + mpMostRecentlySelectedPage.reset(); + mpSelectionAnchor.reset(); +} + + + + +void PageSelector::UpdateAllPages (void) +{ + bool bSelectionHasChanged (true); + mnSelectedPageCount = 0; + model::PageEnumeration aAllPages ( + model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel)); + while (aAllPages.HasMoreElements()) + { + model::SharedPageDescriptor pDescriptor (aAllPages.GetNextElement()); + if (pDescriptor->UpdateSelection()) + { + mrSlideSorter.GetView().RequestRepaint(pDescriptor); + bSelectionHasChanged = true; + } + + if (pDescriptor->IsSelected()) + mnSelectedPageCount++; + } + + if (bSelectionHasChanged) + { + if (mnBroadcastDisableLevel > 0) + mbSelectionChangeBroadcastPending = true; + else + mrController.GetSelectionManager()->SelectionHasChanged(); + } +} + + + + +void PageSelector::SelectPage (int nPageIndex) +{ + SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex)); + if (pDescriptor.get() != NULL) + SelectPage(pDescriptor); +} + + + + +void PageSelector::SelectPage (const SdPage* pPage) +{ + int nPageIndex = (pPage->GetPageNum()-1) / 2; + SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex)); + if (pDescriptor.get()!=NULL && pDescriptor->GetPage()==pPage) + SelectPage(pDescriptor); +} + + + + +void PageSelector::SelectPage (const SharedPageDescriptor& rpDescriptor) +{ + if (rpDescriptor.get()!=NULL && rpDescriptor->Select()) + { + mnSelectedPageCount ++; + mrSlideSorter.GetView().RequestRepaint(rpDescriptor); + + mpMostRecentlySelectedPage = rpDescriptor; + if (mpSelectionAnchor == NULL) + mpSelectionAnchor = rpDescriptor; + + if (mnBroadcastDisableLevel > 0) + mbSelectionChangeBroadcastPending = true; + else + mrController.GetSelectionManager()->SelectionHasChanged(); + } +} + + + + +void PageSelector::DeselectPage (int nPageIndex) +{ + model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex)); + if (pDescriptor.get() != NULL) + DeselectPage(pDescriptor); +} + + + + +void PageSelector::DeselectPage (const SharedPageDescriptor& rpDescriptor) +{ + if (rpDescriptor.get()!=NULL && rpDescriptor->Deselect()) + { + mnSelectedPageCount --; + mrSlideSorter.GetView().RequestRepaint(rpDescriptor); + if (mpMostRecentlySelectedPage == rpDescriptor) + mpMostRecentlySelectedPage.reset(); + if (mnBroadcastDisableLevel > 0) + mbSelectionChangeBroadcastPending = true; + else + mrController.GetSelectionManager()->SelectionHasChanged(); + } +} + + + + +bool PageSelector::IsPageSelected (int nPageIndex) +{ + SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex)); + if (pDescriptor.get() != NULL) + return pDescriptor->IsSelected(); + else + return false; +} + + + + +int PageSelector::GetPageCount (void) const +{ + return mrModel.GetPageCount(); +} + + + + +int PageSelector::GetSelectedPageCount (void) const +{ + return mnSelectedPageCount; +} + + + + +void PageSelector::PrepareModelChange (void) +{ + DeselectAllPages (); +} + + + + +void PageSelector::HandleModelChange (void) +{ + UpdateAllPages(); +} + + + + +SharedPageDescriptor PageSelector::GetMostRecentlySelectedPage (void) const +{ + return mpMostRecentlySelectedPage; +} + + + + +SharedPageDescriptor PageSelector::GetSelectionAnchor (void) const +{ + return mpSelectionAnchor; +} + + + + +void PageSelector::CountSelectedPages (void) +{ + mnSelectedPageCount = 0; + model::PageEnumeration aSelectedPages ( + model::PageEnumerationProvider::CreateSelectedPagesEnumeration(mrModel)); + while (aSelectedPages.HasMoreElements()) + { + mnSelectedPageCount++; + aSelectedPages.GetNextElement(); + } +} + + + + +void PageSelector::EnableBroadcasting (bool bMakeSelectionVisible) +{ + if (mnBroadcastDisableLevel > 0) + mnBroadcastDisableLevel --; + if (mnBroadcastDisableLevel==0 && mbSelectionChangeBroadcastPending) + { + mrController.GetSelectionManager()->SelectionHasChanged(bMakeSelectionVisible); + mbSelectionChangeBroadcastPending = false; + } +} + + + + +void PageSelector::DisableBroadcasting (void) +{ + mnBroadcastDisableLevel ++; +} + + + + +::boost::shared_ptr<PageSelector::PageSelection> PageSelector::GetPageSelection (void) const +{ + ::boost::shared_ptr<PageSelection> pSelection (new PageSelection()); + pSelection->reserve(GetSelectedPageCount()); + + int nPageCount = GetPageCount(); + for (int nIndex=0; nIndex<nPageCount; nIndex++) + { + SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex)); + if (pDescriptor.get()!=NULL && pDescriptor->IsSelected()) + pSelection->push_back(pDescriptor->GetPage()); + } + + return pSelection; +} + + + + +void PageSelector::SetPageSelection (const ::boost::shared_ptr<PageSelection>& rpSelection) +{ + PageSelection::const_iterator iPage; + for (iPage=rpSelection->begin(); iPage!=rpSelection->end(); ++iPage) + SelectPage(*iPage); +} + + + + +} } } // end of namespace ::sd::slidesorter::controller diff --git a/sd/source/ui/slidesorter/controller/SlsProperties.cxx b/sd/source/ui/slidesorter/controller/SlsProperties.cxx new file mode 100644 index 000000000000..7382d769bbe2 --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlsProperties.cxx @@ -0,0 +1,233 @@ +/************************************************************************* + * + * 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 "controller/SlsProperties.hxx" +#include <vcl/svapp.hxx> + +namespace sd { namespace slidesorter { namespace controller { + +Properties::Properties (void) + : mbIsHighlightCurrentSlide(false), + mbIsShowSelection(true), + mbIsShowFocus(true), + mbIsCenterSelection(false), + mbIsSmoothSelectionScrolling(false), + mbIsSuspendPreviewUpdatesDuringFullScreenPresentation(true), + maBackgroundColor(Application::GetSettings().GetStyleSettings().GetWindowColor()), + maTextColor(Application::GetSettings().GetStyleSettings().GetActiveTextColor()), + maSelectionColor(Application::GetSettings().GetStyleSettings().GetMenuHighlightColor()), + maHighlightColor(Application::GetSettings().GetStyleSettings().GetMenuHighlightColor()), + mbIsUIReadOnly(false) +{ +} + + + + +Properties::~Properties (void) +{ +} + + + + +bool Properties::IsHighlightCurrentSlide (void) const +{ + return mbIsHighlightCurrentSlide; +} + + + + +void Properties::SetHighlightCurrentSlide (const bool bIsHighlightCurrentSlide) +{ + mbIsHighlightCurrentSlide = bIsHighlightCurrentSlide; +} + + + + +bool Properties::IsShowSelection (void) const +{ + return mbIsShowSelection; +} + + + + +void Properties::SetShowSelection (const bool bIsShowSelection) +{ + mbIsShowSelection = bIsShowSelection; +} + + + + +bool Properties::IsShowFocus (void) const +{ + return mbIsShowFocus; +} + + + + +void Properties::SetShowFocus (const bool bIsShowFocus) +{ + mbIsShowFocus = bIsShowFocus; +} + + + + +bool Properties::IsCenterSelection (void) const +{ + return mbIsCenterSelection; +} + + + + +void Properties::SetCenterSelection (const bool bIsCenterSelection) +{ + mbIsCenterSelection = bIsCenterSelection; +} + + + + +bool Properties::IsSmoothSelectionScrolling (void) const +{ + return mbIsSmoothSelectionScrolling; +} + + + + +void Properties::SetSmoothSelectionScrolling (const bool bIsSmoothSelectionScrolling) +{ + mbIsSmoothSelectionScrolling = bIsSmoothSelectionScrolling; +} + + + + +bool Properties::IsSuspendPreviewUpdatesDuringFullScreenPresentation (void) const +{ + return mbIsSuspendPreviewUpdatesDuringFullScreenPresentation; +} + + + + +void Properties::SetSuspendPreviewUpdatesDuringFullScreenPresentation (const bool bFlag) +{ + mbIsSuspendPreviewUpdatesDuringFullScreenPresentation = bFlag; +} + + + + +Color Properties::GetBackgroundColor (void) const +{ + return maBackgroundColor; +} + + + + +void Properties::SetBackgroundColor (const Color& rColor) +{ + maBackgroundColor = rColor; +} + + + +Color Properties::GetTextColor (void) const +{ + return maTextColor; +} + + + + +void Properties::SetTextColor (const Color& rColor) +{ + maTextColor = rColor; +} + + + + +Color Properties::GetSelectionColor (void) const +{ + return maSelectionColor; +} + + + + +void Properties::SetSelectionColor (const Color& rColor) +{ + maSelectionColor = rColor; +} + + + + +Color Properties::GetHighlightColor (void) const +{ + return maHighlightColor; +} + + + + +void Properties::SetHighlightColor (const Color& rColor) +{ + maHighlightColor = rColor; +} + + + + +bool Properties::IsUIReadOnly (void) const +{ + return mbIsUIReadOnly; +} + + + + +void Properties::SetUIReadOnly (const bool bIsUIReadOnly) +{ + mbIsUIReadOnly = bIsUIReadOnly; +} + + +} } } // end of namespace ::sd::slidesorter::controller diff --git a/sd/source/ui/slidesorter/controller/SlsScrollBarManager.cxx b/sd/source/ui/slidesorter/controller/SlsScrollBarManager.cxx new file mode 100755 index 000000000000..5ee7f6f58b82 --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlsScrollBarManager.cxx @@ -0,0 +1,631 @@ +/************************************************************************* + * + * 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 "controller/SlsScrollBarManager.hxx" + +#include "SlideSorter.hxx" +#include "controller/SlideSorterController.hxx" +#include "model/SlideSorterModel.hxx" +#include "model/SlsPageDescriptor.hxx" +#include "view/SlideSorterView.hxx" +#include "view/SlsLayouter.hxx" +#include "view/SlsViewOverlay.hxx" +#include "Window.hxx" +#include "sdpage.hxx" + +#include <boost/limits.hpp> + +#include <vcl/scrbar.hxx> + +namespace sd { namespace slidesorter { namespace controller { + +ScrollBarManager::ScrollBarManager (SlideSorter& rSlideSorter) + : mrSlideSorter(rSlideSorter), + mpHorizontalScrollBar(mrSlideSorter.GetHorizontalScrollBar()), + mpVerticalScrollBar(mrSlideSorter.GetVerticalScrollBar()), + mnHorizontalPosition (0), + mnVerticalPosition (0), + maScrollBorder (10,10), + mnHorizontalScrollFactor (0.1), + mnVerticalScrollFactor (0.1), + mpScrollBarFiller(mrSlideSorter.GetScrollBarFiller()), + mpContentWindow(mrSlideSorter.GetContentWindow()) +{ + // Hide the scroll bars by default to prevent display errors while + // switching between view shells: In the short time between initiating + // such a switch and the final rearrangement of UI controls the scroll + // bars and the filler where displayed in the upper left corner of the + // ViewTabBar. + mpHorizontalScrollBar->Hide(); + mpVerticalScrollBar->Hide(); + mpScrollBarFiller->Hide(); + + maAutoScrollTimer.SetTimeout(50); + maAutoScrollTimer.SetTimeoutHdl ( + LINK(this, ScrollBarManager, AutoScrollTimeoutHandler)); +} + + + + +ScrollBarManager::~ScrollBarManager (void) +{ +} + + + + +void ScrollBarManager::LateInitialization (void) +{ +} + + + + +void ScrollBarManager::Connect (void) +{ + if (mpVerticalScrollBar != NULL) + mpVerticalScrollBar->SetScrollHdl ( + LINK( + this, + ScrollBarManager, + VerticalScrollBarHandler)); + if (mpHorizontalScrollBar != NULL) + mpHorizontalScrollBar->SetScrollHdl ( + LINK( + this, + ScrollBarManager, + HorizontalScrollBarHandler)); +} + + + + +void ScrollBarManager::Disconnect (void) +{ + if (mpVerticalScrollBar != NULL) + mpVerticalScrollBar->SetScrollHdl (Link()); + if (mpHorizontalScrollBar != NULL) + mpHorizontalScrollBar->SetScrollHdl (Link()); +} + + + + +/** Placing the scroll bars is an iterative process. The visibility of one + scroll bar affects the remaining size and thus may lead to the other + scroll bar becoming visible. + + First we determine the visibility of the horizontal scroll bar. After + that we do the same for the vertical scroll bar. To have an initial + value for the required size we call the layouter before that. When one + of the two scroll bars is made visible then the size of the browser + window changes and a second call to the layouter becomes necessary. + That call is made anyway after this method returns. +*/ +Rectangle ScrollBarManager::PlaceScrollBars (const Rectangle& rAvailableArea) +{ + Rectangle aRemainingSpace (DetermineScrollBarVisibilities(rAvailableArea)); + PlaceHorizontalScrollBar (rAvailableArea); + PlaceVerticalScrollBar (rAvailableArea); + PlaceFiller (rAvailableArea); + + return aRemainingSpace; +} + + + + +void ScrollBarManager::PlaceHorizontalScrollBar (const Rectangle& aAvailableArea) +{ + if (mpHorizontalScrollBar != NULL + && mpHorizontalScrollBar->IsVisible()) + { + // Save the current relative position. + mnHorizontalPosition = double(mpHorizontalScrollBar->GetThumbPos()) + / double(mpHorizontalScrollBar->GetRange().Len()); + + // Place the scroll bar. + Size aScrollBarSize (mpHorizontalScrollBar->GetSizePixel()); + mpHorizontalScrollBar->SetPosSizePixel ( + Point(aAvailableArea.Left(), + aAvailableArea.Bottom()-aScrollBarSize.Height()+1), + Size (aAvailableArea.GetWidth() - GetVerticalScrollBarWidth(), + aScrollBarSize.Height())); + + // Restore the relative position. + mpHorizontalScrollBar->SetThumbPos( + (long)(0.5 + mnHorizontalPosition * mpHorizontalScrollBar->GetRange().Len())); + } +} + + + + +void ScrollBarManager::PlaceVerticalScrollBar (const Rectangle& aArea) +{ + if (mpVerticalScrollBar != NULL + && mpVerticalScrollBar->IsVisible()) + { + view::Layouter::DoublePoint aLayouterPosition + = mrSlideSorter.GetView().GetLayouter().ConvertModelToLayouterCoordinates ( + Point (0, mpVerticalScrollBar->GetThumbPos())); + + // Place the scroll bar. + Size aScrollBarSize (mpVerticalScrollBar->GetSizePixel()); + Point aPosition (aArea.Right()-aScrollBarSize.Width()+1, aArea.Top()); + Size aSize (aScrollBarSize.Width(), aArea.GetHeight() - GetHorizontalScrollBarHeight()); + mpVerticalScrollBar->SetPosSizePixel(aPosition, aSize); + + // Restore the position. + mpVerticalScrollBar->SetThumbPos( + mrSlideSorter.GetView().GetLayouter().ConvertLayouterToModelCoordinates( + aLayouterPosition).Y()); + mnVerticalPosition = double(mpVerticalScrollBar->GetThumbPos()) + / double(mpVerticalScrollBar->GetRange().Len()); + } +} + + + + +void ScrollBarManager::PlaceFiller (const Rectangle& aArea) +{ + // Place the filler when both scroll bars are visible. + if (mpHorizontalScrollBar != NULL + && mpVerticalScrollBar != NULL + && mpHorizontalScrollBar->IsVisible() + && mpVerticalScrollBar->IsVisible()) + { + mpScrollBarFiller->SetPosSizePixel( + Point( + aArea.Right()-mpVerticalScrollBar->GetSizePixel().Width()+1, + aArea.Bottom()-mpHorizontalScrollBar->GetSizePixel().Height()+1), + Size ( + mpVerticalScrollBar->GetSizePixel().Width(), + mpHorizontalScrollBar->GetSizePixel().Height())); + mpScrollBarFiller->Show(); + } + else + mpScrollBarFiller->Hide(); +} + + + + +void ScrollBarManager::UpdateScrollBars (bool bResetThumbPosition, bool bUseScrolling) +{ + Rectangle aModelArea (mrSlideSorter.GetView().GetModelArea()); + ::sd::Window* pWindow = mrSlideSorter.GetView().GetWindow(); + Size aWindowModelSize (pWindow->PixelToLogic(pWindow->GetSizePixel())); + + // The horizontal scroll bar is only shown when the window is + // horizontally smaller than the view. + if (mpHorizontalScrollBar != NULL && mpHorizontalScrollBar->IsVisible()) + { + mpHorizontalScrollBar->Show(); + mpHorizontalScrollBar->SetRange ( + Range(aModelArea.Left(), aModelArea.Right())); + if (bResetThumbPosition) + { + mpHorizontalScrollBar->SetThumbPos (0); + mnHorizontalPosition = 0; + } + else + mnHorizontalPosition = + double(mpHorizontalScrollBar->GetThumbPos()) + / double(mpHorizontalScrollBar->GetRange().Len()); + + mpHorizontalScrollBar->SetVisibleSize (aWindowModelSize.Width()); + + const long nWidth (mpContentWindow->PixelToLogic( + mpContentWindow->GetSizePixel()).Width()); + // Make the line size about 10% of the visible width. + mpHorizontalScrollBar->SetLineSize (nWidth / 10); + // Make the page size about 90% of the visible width. + mpHorizontalScrollBar->SetPageSize ((nWidth * 9) / 10); + } + else + { + mnHorizontalPosition = 0; + } + + // The vertical scroll bar is always shown. + if (mpVerticalScrollBar != NULL && mpVerticalScrollBar->IsVisible()) + { + mpVerticalScrollBar->SetRange ( + Range(aModelArea.Top(), aModelArea.Bottom())); + if (bResetThumbPosition) + { + mpVerticalScrollBar->SetThumbPos (0); + mnVerticalPosition = 0; + } + else + mnVerticalPosition = + double(mpVerticalScrollBar->GetThumbPos()) + / double(mpVerticalScrollBar->GetRange().Len()); + + mpVerticalScrollBar->SetVisibleSize (aWindowModelSize.Height()); + + const long nHeight (mpContentWindow->PixelToLogic( + mpContentWindow->GetSizePixel()).Height()); + // Make the line size about 10% of the visible height. + mpVerticalScrollBar->SetLineSize (nHeight / 10); + // Make the page size about 90% of the visible height. + mpVerticalScrollBar->SetPageSize ((nHeight * 9) / 10); + } + else + { + mnVerticalPosition = 0; + } + + + double nEps (::std::numeric_limits<double>::epsilon()); + if (fabs(mnHorizontalPosition-pWindow->GetVisibleX()) > nEps + || fabs(mnVerticalPosition-pWindow->GetVisibleY()) > nEps) + { + mrSlideSorter.GetView().InvalidatePageObjectVisibilities(); + if (bUseScrolling) + pWindow->SetVisibleXY(mnHorizontalPosition, mnVerticalPosition); + else + SetWindowOrigin(mnHorizontalPosition, mnVerticalPosition); + } +} + + + + +IMPL_LINK(ScrollBarManager, VerticalScrollBarHandler, ScrollBar*, pScrollBar) +{ + if (pScrollBar!=NULL + && pScrollBar==mpVerticalScrollBar.get() + && pScrollBar->IsVisible() + && mrSlideSorter.GetView().GetWindow()!=NULL) + { + double nRelativePosition = double(pScrollBar->GetThumbPos()) + / double(pScrollBar->GetRange().Len()); + mrSlideSorter.GetView().InvalidatePageObjectVisibilities(); + mrSlideSorter.GetView().GetWindow()->SetVisibleXY ( + -1, + nRelativePosition); + } + return TRUE; +} + + + + +IMPL_LINK(ScrollBarManager, HorizontalScrollBarHandler, ScrollBar*, pScrollBar) +{ + if (pScrollBar!=NULL + && pScrollBar==mpHorizontalScrollBar.get() + && pScrollBar->IsVisible() + && mrSlideSorter.GetView().GetWindow()!=NULL) + { + double nRelativePosition = double(pScrollBar->GetThumbPos()) + / double(pScrollBar->GetRange().Len()); + mrSlideSorter.GetView().InvalidatePageObjectVisibilities(); + mrSlideSorter.GetView().GetWindow()->SetVisibleXY (nRelativePosition, -1); + } + return TRUE; +} + + + + +void ScrollBarManager::SetWindowOrigin ( + double nHorizontalPosition, + double nVerticalPosition) +{ + mnHorizontalPosition = nHorizontalPosition; + mnVerticalPosition = nVerticalPosition; + + ::sd::Window* pWindow = mrSlideSorter.GetView().GetWindow(); + Size aViewSize (pWindow->GetViewSize()); + Point aOrigin ( + (long int) (mnHorizontalPosition * aViewSize.Width()), + (long int) (mnVerticalPosition * aViewSize.Height())); + + pWindow->SetWinViewPos (aOrigin); + pWindow->UpdateMapMode (); + pWindow->Invalidate (); +} + + + + +/** Determining the visibility of the scroll bars is quite complicated. The + visibility of one influences that of the other because showing a scroll + bar makes the available space smaller and may lead to the need of + displaying the other. + To solve this we test all four combinations of showing or hiding each + scroll bar and use the best one. The best one is that combination that + a) shows the least number of scroll bars with preference of showing the + vertical over showing the horizontal and + b) when not showing a scroll bar the area used by the page objects fits + into the available area in the scroll bars orientation. +*/ +Rectangle ScrollBarManager::DetermineScrollBarVisibilities (const Rectangle& rAvailableArea) +{ + // Test which combination of scroll bars is the best. + bool bShowHorizontal = false; + bool bShowVertical = false; + do + { + if (mrSlideSorter.GetModel().GetPageCount() == 0) + // No pages => no scroll bars. + break; + + if (TestScrollBarVisibilities(bShowHorizontal=false, bShowVertical=false, rAvailableArea)) + break; + if (TestScrollBarVisibilities(bShowHorizontal=true, bShowVertical=false, rAvailableArea)) + break; + if (TestScrollBarVisibilities(bShowHorizontal=false, bShowVertical=true, rAvailableArea)) + break; + if (TestScrollBarVisibilities(bShowHorizontal=true, bShowVertical=true, rAvailableArea)) + break; + } + while (false); + + // Make the visibility of the scroll bars permanent. + mpVerticalScrollBar->Show(bShowVertical); + mpHorizontalScrollBar->Show(bShowHorizontal); + + // Adapt the remaining space accordingly. + Rectangle aRemainingSpace (rAvailableArea); + if (bShowVertical) + aRemainingSpace.Right() -= mpVerticalScrollBar->GetSizePixel().Width(); + if (bShowHorizontal) + aRemainingSpace.Bottom() -= mpHorizontalScrollBar->GetSizePixel().Height(); + + return aRemainingSpace; +} + + + + +bool ScrollBarManager::TestScrollBarVisibilities ( + bool bHorizontalScrollBarVisible, + bool bVerticalScrollBarVisible, + const Rectangle& rAvailableArea) +{ + bool bAreVisibilitiesOK = true; + + // Adapt the available size by subtracting the sizes of the scroll bars + // visible in this combination. + Size aBrowserSize (rAvailableArea.GetSize()); + if (bHorizontalScrollBarVisible) + aBrowserSize.Height() -= mpHorizontalScrollBar->GetSizePixel().Height(); + if (bVerticalScrollBarVisible) + aBrowserSize.Width() -= mpVerticalScrollBar->GetSizePixel().Width(); + + // Tell the view to rearrange its page objects and check whether the + // page objects can be shown without clipping. + bool bRearrangeSuccess (false); + if (mrSlideSorter.GetView().GetOrientation() == view::SlideSorterView::HORIZONTAL) + { + bRearrangeSuccess = mrSlideSorter.GetView().GetLayouter().RearrangeHorizontal ( + aBrowserSize, + mrSlideSorter.GetModel().GetPageDescriptor(0)->GetPage()->GetSize(), + mpContentWindow.get(), + mrSlideSorter.GetModel().GetPageCount()); + } + else + { + bRearrangeSuccess = mrSlideSorter.GetView().GetLayouter().RearrangeVertical ( + aBrowserSize, + mrSlideSorter.GetModel().GetPageDescriptor(0)->GetPage()->GetSize(), + mpContentWindow.get()); + } + + if (bRearrangeSuccess) + { + Size aPageSize = mrSlideSorter.GetView().GetLayouter().GetPageBox ( + mrSlideSorter.GetModel().GetPageCount()).GetSize(); + Size aWindowModelSize = mpContentWindow->PixelToLogic(aBrowserSize); + + bool bHorizontallyClipped = (aPageSize.Width() > aWindowModelSize.Width()); + bool bVerticallyClipped = (aPageSize.Height() > aWindowModelSize.Height()); + bAreVisibilitiesOK = (bHorizontallyClipped == bHorizontalScrollBarVisible) + && (bVerticallyClipped == bVerticalScrollBarVisible); + } + else + bAreVisibilitiesOK = false; + + return bAreVisibilitiesOK; +} + + + + +void ScrollBarManager::SetTop (const sal_Int32 nNewTop) +{ + if (mpVerticalScrollBar != NULL + && mpVerticalScrollBar->GetThumbPos() != nNewTop) + { + // Flush pending repaints before scrolling to avoid temporary artifacts. + mrSlideSorter.GetView().GetWindow()->Update(); + + mpVerticalScrollBar->SetThumbPos(nNewTop); + mnVerticalPosition = double(nNewTop) / double(mpVerticalScrollBar->GetRange().Len()); + mrSlideSorter.GetView().GetWindow()->SetVisibleXY ( + mnHorizontalPosition, mnVerticalPosition); + } +} + + + + +void ScrollBarManager::SetLeft (const sal_Int32 nNewLeft) +{ + if (mpHorizontalScrollBar != NULL + && mpHorizontalScrollBar->GetThumbPos() != nNewLeft) + { + // Flush pending repaints before scrolling to avoid temporary artifacts. + mrSlideSorter.GetView().GetWindow()->Update(); + + mpHorizontalScrollBar->SetThumbPos(nNewLeft); + mnHorizontalPosition = double(nNewLeft) / double(mpHorizontalScrollBar->GetRange().Len()); + mrSlideSorter.GetView().GetWindow()->SetVisibleXY ( + mnHorizontalPosition, mnVerticalPosition); + } +} + + + + +int ScrollBarManager::GetVerticalScrollBarWidth (void) const +{ + if (mpVerticalScrollBar != NULL && mpVerticalScrollBar->IsVisible()) + return mpVerticalScrollBar->GetSizePixel().Width(); + else + return 0; +} + + + + +int ScrollBarManager::GetHorizontalScrollBarHeight (void) const +{ + if (mpHorizontalScrollBar != NULL && mpHorizontalScrollBar->IsVisible()) + return mpHorizontalScrollBar->GetSizePixel().Height(); + else + return 0; +} + + + + +void ScrollBarManager::CalcAutoScrollOffset (const Point& rMouseWindowPosition) +{ + ::sd::Window* pWindow = mrSlideSorter.GetView().GetWindow(); + + int nDx = 0; + int nDy = 0; + + Size aWindowSize = pWindow->GetOutputSizePixel(); + Rectangle aWindowArea (pWindow->GetPosPixel(), aWindowSize); + Rectangle aViewPixelArea ( + pWindow->LogicToPixel(mrSlideSorter.GetView().GetModelArea())); + + if (aWindowSize.Width() > maScrollBorder.Width() * 3 + && mpHorizontalScrollBar != NULL + && mpHorizontalScrollBar->IsVisible()) + { + if (rMouseWindowPosition.X() < maScrollBorder.Width() + && aWindowArea.Left() > aViewPixelArea.Left()) + { + nDx = -1 + (int)(mnHorizontalScrollFactor + * (rMouseWindowPosition.X() - maScrollBorder.Width())); + } + + if (rMouseWindowPosition.X() >= (aWindowSize.Width() - maScrollBorder.Width()) + && aWindowArea.Right() < aViewPixelArea.Right()) + { + nDx = 1 + (int)(mnHorizontalScrollFactor + * (rMouseWindowPosition.X() - aWindowSize.Width() + + maScrollBorder.Width())); + } + } + + if (aWindowSize.Height() > maScrollBorder.Height() * 3 + && aWindowSize.Height() < aViewPixelArea.GetHeight()) + { + if (rMouseWindowPosition.Y() < maScrollBorder.Height() + && aWindowArea.Top() > aViewPixelArea.Top()) + { + nDy = -1 + (int)(mnVerticalScrollFactor + * (rMouseWindowPosition.Y() - maScrollBorder.Height())); + } + + if (rMouseWindowPosition.Y() >= (aWindowSize.Height() - maScrollBorder.Height()) + && aWindowArea.Bottom() < aViewPixelArea.Bottom()) + { + nDy = 1 + (int)(mnVerticalScrollFactor + * (rMouseWindowPosition.Y() - aWindowSize.Height() + + maScrollBorder.Height())); + } + } + + maAutoScrollOffset = Size(nDx,nDy); +} + + + + +bool ScrollBarManager::AutoScroll (const Point& rMouseWindowPosition) +{ + CalcAutoScrollOffset (rMouseWindowPosition); + bool bResult = RepeatAutoScroll(); + if (bResult) + { + maAutoScrollTimer.Start(); + } + return bResult; +} + + + + +void ScrollBarManager::StopAutoScroll (void) +{ + maAutoScrollTimer.Stop(); +} + + + + +bool ScrollBarManager::RepeatAutoScroll (void) +{ + if (maAutoScrollOffset != Size(0,0)) + { + if (mrSlideSorter.GetViewShell() != NULL) + { + mrSlideSorter.GetViewShell()->ScrollLines( + maAutoScrollOffset.Width(), + maAutoScrollOffset.Height()); + return true; + } + } + + return false; +} + + + + +IMPL_LINK(ScrollBarManager, AutoScrollTimeoutHandler, Timer *, EMPTYARG) +{ + RepeatAutoScroll(); + + return 0; +} + + +} } } // end of namespace ::sd::slidesorter::controller diff --git a/sd/source/ui/slidesorter/controller/SlsSelectionCommand.cxx b/sd/source/ui/slidesorter/controller/SlsSelectionCommand.cxx new file mode 100755 index 000000000000..687019954feb --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlsSelectionCommand.cxx @@ -0,0 +1,85 @@ +/************************************************************************* + * + * 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 "SlsSelectionCommand.hxx" + +#include "controller/SlsCurrentSlideManager.hxx" +#include "model/SlideSorterModel.hxx" +#include "model/SlsPageDescriptor.hxx" + +#include "sdpage.hxx" + +namespace sd { namespace slidesorter { namespace controller { + + + +SelectionCommand::SelectionCommand ( + PageSelector& rSelector, + const ::boost::shared_ptr<CurrentSlideManager>& rpCurrentSlideManager, + const model::SlideSorterModel& rModel) + : mrPageSelector(rSelector), + mpCurrentSlideManager(rpCurrentSlideManager), + mrModel(rModel), + maPagesToSelect(), + mnCurrentPageIndex(-1) +{ +} + + + + +void SelectionCommand::AddSlide (USHORT nPageIndex) +{ + maPagesToSelect.push_back(nPageIndex); +} + + + + +void SelectionCommand::operator() (void) +{ + OSL_ASSERT(mpCurrentSlideManager.get()!=NULL); + + mrPageSelector.DeselectAllPages(); + + if (mnCurrentPageIndex >= 0) + mpCurrentSlideManager->SwitchCurrentSlide(mnCurrentPageIndex); + + PageList::iterator iPage = maPagesToSelect.begin(); + PageList::iterator iEnd = maPagesToSelect.end(); + for (; iPage!=iEnd; ++iPage) + { + sal_Int32 nIndex (*iPage); + if (nIndex >= 0) + mrPageSelector.SelectPage(mrModel.GetPageDescriptor(nIndex)); + } +} + + +} } } // end of namespace sd::slidesorter::controller diff --git a/sd/source/ui/slidesorter/controller/SlsSelectionCommand.hxx b/sd/source/ui/slidesorter/controller/SlsSelectionCommand.hxx new file mode 100755 index 000000000000..7a9d0f27369e --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlsSelectionCommand.hxx @@ -0,0 +1,95 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef SD_SLIDESORTER_SELECTION_COMMAND_HXX +#define SD_SLIDESORTER_SELECTION_COMMAND_HXX + +#include "controller/SlsPageSelector.hxx" +#include "SlsCommand.hxx" +#include <tools/solar.h> +#include <com/sun/star/drawing/XDrawPage.hpp> + +#include <boost/shared_ptr.hpp> +#include <vector> + +namespace sd { namespace slidesorter { namespace model { +class SlideSorterModel; +} } } + + +namespace sd { namespace slidesorter { namespace controller { + +class CurrentSlideManager; +class PageSelector; + +/** The SelectionCommand stores a list of pages that it will select on its + execution. Furthermore it will make a page the current page. Note that + internally pages are stored with pointers because this command is designed + to be executed after model changes where page indices may change but + page object identities remain. +*/ +class SelectionCommand + : public Command +{ +public: + /** Create a new command object that will on its exection use the given + PageSelector to select a set of pages. + */ + SelectionCommand ( + PageSelector& rSelector, + const ::boost::shared_ptr<controller::CurrentSlideManager>& rpCurrentSlideManager, + const model::SlideSorterModel& rModel); + + /** Remember the specified page to be selected when this command is + executed. + */ + void AddSlide (USHORT nPageIndex); + + /** Execute the command and select the pages added by previous calls to + AddPages() and AddPage(). + */ + virtual void operator() (void); + +private: + /// The page selector is used to select pages and set the current page. + PageSelector& mrPageSelector; + /// Used for setting the current slide. + ::boost::shared_ptr<controller::CurrentSlideManager> mpCurrentSlideManager; + /// The model is used to translate page indices into page pointers. + const model::SlideSorterModel& mrModel; + /// The list of pages to be selected when the command is executed. + typedef ::std::vector<sal_Int32> PageList; + PageList maPagesToSelect; + /** The page that will be made the current page when the command is + executed. + */ + sal_Int32 mnCurrentPageIndex; +}; + +} } } // end of namespace sd::slidesorter::controller + +#endif diff --git a/sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx b/sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx new file mode 100755 index 000000000000..c1d742ce7158 --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx @@ -0,0 +1,1317 @@ +/************************************************************************* + * + * 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 "controller/SlsSelectionFunction.hxx" + +#include "SlideSorter.hxx" +#include "SlideSorterViewShell.hxx" +#include "controller/SlideSorterController.hxx" +#include "controller/SlsPageSelector.hxx" +#include "controller/SlsFocusManager.hxx" +#include "controller/SlsScrollBarManager.hxx" +#include "controller/SlsClipboard.hxx" +#include "controller/SlsCurrentSlideManager.hxx" +#include "controller/SlsSelectionManager.hxx" +#include "controller/SlsProperties.hxx" +#include "model/SlideSorterModel.hxx" +#include "model/SlsPageDescriptor.hxx" +#include "model/SlsPageEnumerationProvider.hxx" +#include "view/SlideSorterView.hxx" +#include "view/SlsViewOverlay.hxx" +#include "view/SlsLayouter.hxx" +#include "view/SlsPageObjectViewObjectContact.hxx" +#include "framework/FrameworkHelper.hxx" +#include "ViewShellBase.hxx" +#include "DrawController.hxx" +#include <vcl/sound.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/dispatch.hxx> +#include <svx/svdpagv.hxx> +#include <vcl/msgbox.hxx> +#include "Window.hxx" +#include "sdpage.hxx" +#include "drawdoc.hxx" +#include "ViewShell.hxx" +#include "ViewShellBase.hxx" +#include "FrameView.hxx" +#include "app.hrc" +#include "sdresid.hxx" +#include "strings.hrc" + +namespace { +static const sal_uInt32 SINGLE_CLICK (0x00000001); +static const sal_uInt32 DOUBLE_CLICK (0x00000002); +static const sal_uInt32 LEFT_BUTTON (0x00000010); +static const sal_uInt32 RIGHT_BUTTON (0x00000020); +static const sal_uInt32 MIDDLE_BUTTON (0x00000040); +static const sal_uInt32 BUTTON_DOWN (0x00000100); +static const sal_uInt32 BUTTON_UP (0x00000200); +static const sal_uInt32 MOUSE_MOTION (0x00000400); +// The rest leaves the lower 16 bit untouched so that it can be used with +// key codes. +static const sal_uInt32 OVER_SELECTED_PAGE (0x00010000); +static const sal_uInt32 OVER_UNSELECTED_PAGE (0x00020000); +static const sal_uInt32 OVER_FADE_INDICATOR (0x00040000); +static const sal_uInt32 SHIFT_MODIFIER (0x00100000); +static const sal_uInt32 CONTROL_MODIFIER (0x00200000); +static const sal_uInt32 SUBSTITUTION_VISIBLE (0x01000000); +static const sal_uInt32 RECTANGLE_VISIBLE (0x02000000); + +static const sal_uInt32 KEY_EVENT (0x10000000); + +// Some absent events are defined so they can be expressed explicitly. +static const sal_uInt32 NO_MODIFIER (0x00000000); +static const sal_uInt32 SUBSTITUTION_NOT_VISIBLE (0x00000000); +static const sal_uInt32 NOT_OVER_PAGE (0x00000000); + + +} // end of anonymous namespace + + +namespace sd { namespace slidesorter { namespace controller { + +class SelectionFunction::SubstitutionHandler +{ +public: + SubstitutionHandler (SlideSorter& rSlideSorter); + ~SubstitutionHandler (void); + + /** Create a substitution display of the currently selected pages and + use the given position as the anchor point. + */ + void Start (const Point& rMouseModelPosition); + + /** Move the substitution display by the distance the mouse has + travelled since the last call to this method or to + CreateSubstitution(). The given point becomes the new anchor. + */ + void UpdatePosition (const Point& rMouseModelPosition); + + /** Move the substitution display of the currently selected pages. + */ + void Process (void); + + void End (void); + + bool HasBeenMoved (void) const; + +private: + SlideSorter& mrSlideSorter; + + bool mbHasBeenMoved; + + /** Determine whether there is a) a substitution and b) its insertion at + the current position of the insertion marker would alter the + document. This would be the case when the substitution has been + moved or is not consecutive. + */ + bool IsSubstitutionInsertionNonTrivial (void) const; +}; + + +class SelectionFunction::EventDescriptor +{ +public: + + Point maMousePosition; + Point maMouseModelPosition; + ::boost::weak_ptr<model::PageDescriptor> mpHitDescriptor; + SdrPage* mpHitPage; + sal_uInt32 mnEventCode; + + EventDescriptor ( + sal_uInt32 nEventType, + const MouseEvent& rEvent, + SlideSorter& rSlideSorter); + EventDescriptor ( + const KeyEvent& rEvent, + SlideSorter& rSlideSorter); +}; + + +TYPEINIT1(SelectionFunction, FuPoor); + + +SelectionFunction::SelectionFunction ( + SlideSorter& rSlideSorter, + SfxRequest& rRequest) + : SlideFunction (rSlideSorter, rRequest), + mrSlideSorter(rSlideSorter), + mrController(mrSlideSorter.GetController()), + mbDragSelection(false), + maInsertionMarkerBox(), + mbProcessingMouseButtonDown(false), + mpSubstitutionHandler(new SubstitutionHandler(mrSlideSorter)) +{ + //af aDelayToScrollTimer.SetTimeout(50); + aDragTimer.SetTimeoutHdl( LINK( this, SelectionFunction, DragSlideHdl ) ); +} + +SelectionFunction::~SelectionFunction (void) +{ + aDragTimer.Stop(); +} + + + + +FunctionReference SelectionFunction::Create( + SlideSorter& rSlideSorter, + SfxRequest& rRequest) +{ + FunctionReference xFunc( new SelectionFunction( rSlideSorter, rRequest ) ); + return xFunc; +} + + + + +BOOL SelectionFunction::MouseButtonDown (const MouseEvent& rEvent) +{ + // #95491# remember button state for creation of own MouseEvents + SetMouseButtonCode (rEvent.GetButtons()); + mbProcessingMouseButtonDown = true; + + mpWindow->CaptureMouse(); + + ProcessMouseEvent(BUTTON_DOWN, rEvent); + + return TRUE; +} + + + + +BOOL SelectionFunction::MouseMove (const MouseEvent& rEvent) +{ + Point aMousePosition (rEvent.GetPosPixel()); + + // Determine page under mouse and show the mouse over effect. + model::SharedPageDescriptor pHitDescriptor (mrController.GetPageAt(aMousePosition)); + view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); + rOverlay.GetMouseOverIndicatorOverlay().SetSlideUnderMouse( + rEvent.IsLeaveWindow() ? model::SharedPageDescriptor() : pHitDescriptor); + if (pHitDescriptor.get() != NULL) + rOverlay.GetMouseOverIndicatorOverlay().setVisible(true); + else + rOverlay.GetMouseOverIndicatorOverlay().setVisible(false); + + // Allow one mouse move before the drag timer is disabled. + if (aDragTimer.IsActive()) + { + if (bFirstMouseMove) + bFirstMouseMove = FALSE; + else + aDragTimer.Stop(); + } + + Rectangle aRectangle (Point(0,0),mpWindow->GetOutputSizePixel()); + if ( ! aRectangle.IsInside(aMousePosition) + && rOverlay.GetSubstitutionOverlay().isVisible()) + { + // Mouse left the window with pressed left button. Make it a drag. + StartDrag(); + } + else + { + // Call ProcessMouseEvent() only when one of the buttons is + // pressed. This prevents calling the method on every motion. + if (rEvent.GetButtons() != 0 + && mbProcessingMouseButtonDown) + { + ProcessMouseEvent(MOUSE_MOTION, rEvent); + } + } + + return TRUE; +} + + + + +BOOL SelectionFunction::MouseButtonUp (const MouseEvent& rEvent) +{ + mrController.GetScrollBarManager().StopAutoScroll (); + + // #95491# remember button state for creation of own MouseEvents + SetMouseButtonCode (rEvent.GetButtons()); + + if (aDragTimer.IsActive()) + aDragTimer.Stop(); + + ProcessMouseEvent(BUTTON_UP, rEvent); + + mbProcessingMouseButtonDown = false; + mpWindow->ReleaseMouse(); + + return TRUE; +} + + + + +BOOL SelectionFunction::KeyInput (const KeyEvent& rEvent) +{ + FocusManager& rFocusManager (mrController.GetFocusManager()); + BOOL bResult = FALSE; + + switch (rEvent.GetKeyCode().GetCode()) + { + case KEY_RETURN: + if (rFocusManager.HasFocus()) + { + model::SharedPageDescriptor pDescriptor (rFocusManager.GetFocusedPageDescriptor()); + if (pDescriptor.get() != NULL) + { + SetCurrentPage(pDescriptor); + SwitchView(pDescriptor); + } + bResult = TRUE; + } + break; + + case KEY_TAB: + if ( ! rFocusManager.IsFocusShowing()) + rFocusManager.ShowFocus(); + else + if (rEvent.GetKeyCode().IsShift()) + rFocusManager.MoveFocus (FocusManager::FMD_LEFT); + else + rFocusManager.MoveFocus (FocusManager::FMD_RIGHT); + bResult = TRUE; + break; + + case KEY_ESCAPE: + rFocusManager.SetFocusToToolBox(); + bResult = TRUE; + break; + + case KEY_SPACE: + { + // Toggle the selection state. + model::SharedPageDescriptor pDescriptor (rFocusManager.GetFocusedPageDescriptor()); + if (pDescriptor.get() != NULL) + { + // Doing a multi selection by default. Can we ask the event + // for the state of the shift key? + if (pDescriptor->IsSelected()) + mrController.GetPageSelector().DeselectPage(pDescriptor); + else + mrController.GetPageSelector().SelectPage(pDescriptor); + } + bResult = TRUE; + } + break; + + + // Move the focus indicator left. + case KEY_LEFT: + rFocusManager.MoveFocus (FocusManager::FMD_LEFT); + bResult = TRUE; + break; + + // Move the focus indicator right. + case KEY_RIGHT: + rFocusManager.MoveFocus (FocusManager::FMD_RIGHT); + bResult = TRUE; + break; + + // Move the focus indicator up. + case KEY_UP: + rFocusManager.MoveFocus (FocusManager::FMD_UP); + bResult = TRUE; + break; + + // Move the focus indicator down. + case KEY_DOWN: + rFocusManager.MoveFocus (FocusManager::FMD_DOWN); + bResult = TRUE; + break; + + // Go to previous page. No wrap around. + case KEY_PAGEUP: + GotoNextPage(-1); + bResult = TRUE; + break; + + // Go to next page. No wrap around.. + case KEY_PAGEDOWN: + GotoNextPage(+1); + bResult = TRUE; + break; + + case KEY_DELETE: + case KEY_BACKSPACE: + { + if (mrController.GetProperties()->IsUIReadOnly()) + break; + + int nSelectedPagesCount = 0; + + // Count the selected pages and look if there any objects on any + // of the selected pages so that we can warn the user and + // prevent an accidental deletion. + model::PageEnumeration aSelectedPages ( + model::PageEnumerationProvider::CreateSelectedPagesEnumeration( + mrSlideSorter.GetModel())); + while (aSelectedPages.HasMoreElements()) + { + nSelectedPagesCount++; + aSelectedPages.GetNextElement(); + } + + if (nSelectedPagesCount > 0) + mrController.GetSelectionManager()->DeleteSelectedPages(); + + bResult = TRUE; + } + break; + + case KEY_F10: + if (rEvent.GetKeyCode().IsShift()) + ProcessKeyEvent(rEvent); + break; + + default: + break; + } + + if ( ! bResult) + bResult = SlideFunction::KeyInput (rEvent); + + return bResult; +} + + + + +void SelectionFunction::Activate() +{ + FuPoor::Activate(); +} + + + + +void SelectionFunction::Deactivate() +{ + FuPoor::Deactivate(); +} + + + +void SelectionFunction::ScrollStart (void) +{ +} + + + + +void SelectionFunction::ScrollEnd (void) +{ +} + + + + +void SelectionFunction::DoCut (void) +{ + if ( ! mrController.GetProperties()->IsUIReadOnly()) + { + mrController.GetClipboard().DoCut(); + } +} + + + + +void SelectionFunction::DoCopy (void) +{ + mrController.GetClipboard().DoCopy(); +} + + + + +void SelectionFunction::DoPaste (void) +{ + if ( ! mrController.GetProperties()->IsUIReadOnly()) + { + mrController.GetClipboard().DoPaste(); + } +} + + + + +void SelectionFunction::Paint (const Rectangle&, ::sd::Window* ) +{ +} + + + + +IMPL_LINK( SelectionFunction, DragSlideHdl, Timer*, EMPTYARG ) +{ + StartDrag(); + return 0; +} + + + + +void SelectionFunction::StartDrag (void) +{ + if (mbPageHit + && ! mrController.GetProperties()->IsUIReadOnly()) + { + view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); + mpSubstitutionHandler->Start(rOverlay.GetSubstitutionOverlay().GetPosition()); + mbPageHit = false; + mpWindow->ReleaseMouse(); + + if (mrSlideSorter.GetViewShell() != NULL) + { + SlideSorterViewShell* pSlideSorterViewShell + = dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell()); + pSlideSorterViewShell->StartDrag ( + rOverlay.GetSubstitutionOverlay().GetPosition(), + mpWindow); + } + } +} + + + + +bool SelectionFunction::cancel (void) +{ + mrController.GetFocusManager().ToggleFocus(); + return true; +} + + + + +void SelectionFunction::SelectHitPage (const model::SharedPageDescriptor& rpDescriptor) +{ + mrController.GetPageSelector().SelectPage(rpDescriptor); +} + + + + +void SelectionFunction::DeselectHitPage (const model::SharedPageDescriptor& rpDescriptor) +{ + mrController.GetPageSelector().DeselectPage(rpDescriptor); +} + + + + +void SelectionFunction::DeselectAllPages (void) +{ + mrController.GetPageSelector().DeselectAllPages(); +} + + + + +void SelectionFunction::StartRectangleSelection (const Point& rMouseModelPosition) +{ + if (mrController.GetProperties()->IsShowSelection()) + { + mrSlideSorter.GetView().GetOverlay().GetSelectionRectangleOverlay().Start( + rMouseModelPosition); + } +} + + + + +void SelectionFunction::UpdateRectangleSelection (const Point& rMouseModelPosition) +{ + if (mrController.GetProperties()->IsShowSelection()) + { + mrSlideSorter.GetView().GetOverlay().GetSelectionRectangleOverlay().Update( + rMouseModelPosition); + } +} + + + + +void SelectionFunction::ProcessRectangleSelection (bool bToggleSelection) +{ + if ( ! mrController.GetProperties()->IsShowSelection()) + return; + + view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); + if (rOverlay.GetSelectionRectangleOverlay().isVisible()) + { + PageSelector& rSelector (mrController.GetPageSelector()); + + rOverlay.GetSelectionRectangleOverlay().setVisible(false); + + // Select all pages whose page object lies completly inside the drag + // rectangle. + const Rectangle& rSelectionRectangle ( + rOverlay.GetSelectionRectangleOverlay().GetSelectionRectangle()); + model::PageEnumeration aPages ( + model::PageEnumerationProvider::CreateAllPagesEnumeration( + mrSlideSorter.GetModel())); + while (aPages.HasMoreElements()) + { + model::SharedPageDescriptor pDescriptor (aPages.GetNextElement()); + Rectangle aPageBox (mrSlideSorter.GetView().GetPageBoundingBox( + pDescriptor, + view::SlideSorterView::CS_MODEL, + view::SlideSorterView::BBT_SHAPE)); + if (rSelectionRectangle.IsOver(aPageBox)) + { + // When we are extending the selection (shift key is + // pressed) then toggle the selection state of the page. + // Otherwise select it: this results in the previously + // selected pages becoming deslected. + if (bToggleSelection && pDescriptor->IsSelected()) + rSelector.DeselectPage(pDescriptor); + else + rSelector.SelectPage(pDescriptor); + } + } + } +} + + + + +void SelectionFunction::PrepareMouseMotion (const Point& ) +{ + if ( ! mrController.GetProperties()->IsUIReadOnly()) + { + bFirstMouseMove = TRUE; + aDragTimer.Start(); + } +} + + + + +void SelectionFunction::RangeSelect (const model::SharedPageDescriptor& rpDescriptor) +{ + PageSelector& rSelector (mrController.GetPageSelector()); + + model::SharedPageDescriptor pAnchor (rSelector.GetSelectionAnchor()); + DeselectAllPages(); + + if (pAnchor.get() != NULL) + { + // Select all pages between the anchor and the given one, including + // the two. + USHORT nAnchorIndex ((pAnchor->GetPage()->GetPageNum()-1) / 2); + USHORT nOtherIndex ((rpDescriptor->GetPage()->GetPageNum()-1) / 2); + + // Iterate over all pages in the range. Start with the anchor + // page. This way the PageSelector will recognize it again as + // anchor (the first selected page after a DeselectAllPages() + // becomes the anchor.) + USHORT nStep = (nAnchorIndex < nOtherIndex) ? +1 : -1; + USHORT nIndex = nAnchorIndex; + while (true) + { + rSelector.SelectPage(nIndex); + if (nIndex == nOtherIndex) + break; + nIndex = nIndex + nStep; + } + } +} + + + + +void SelectionFunction::GotoNextPage (int nOffset) +{ + model::SharedPageDescriptor pDescriptor + = mrController.GetCurrentSlideManager()->GetCurrentSlide(); + if (pDescriptor.get() != NULL) + { + SdPage* pPage = pDescriptor->GetPage(); + OSL_ASSERT(pPage!=NULL); + sal_Int32 nIndex = (pPage->GetPageNum()-1) / 2; + nIndex += nOffset; + USHORT nPageCount = (USHORT)mrSlideSorter.GetModel().GetPageCount(); + + if (nIndex >= nPageCount) + nIndex = nPageCount - 1; + if (nIndex < 0) + nIndex = 0; + + mrController.GetFocusManager().SetFocusedPage(nIndex); + model::SharedPageDescriptor pNextPageDescriptor ( + mrSlideSorter.GetModel().GetPageDescriptor (nIndex)); + if (pNextPageDescriptor.get() != NULL) + SetCurrentPage(pNextPageDescriptor); + else + { + OSL_ASSERT(pNextPageDescriptor.get() != NULL); + } + } +} + + + + +void SelectionFunction::ProcessMouseEvent (sal_uInt32 nEventType, const MouseEvent& rEvent) +{ + // #95491# remember button state for creation of own MouseEvents + SetMouseButtonCode (rEvent.GetButtons()); + + // 1. Compute some frequently used values relating to the event. + ::std::auto_ptr<EventDescriptor> pEventDescriptor ( + new EventDescriptor(nEventType, rEvent, mrSlideSorter)); + + // 2. Compute a numerical code that describes the event and that is used + // for fast look-up of the associated reaction. + pEventDescriptor->mnEventCode = EncodeMouseEvent(*pEventDescriptor, rEvent); + + // 3. Process the event. + EventPreprocessing(*pEventDescriptor); + if ( ! EventProcessing(*pEventDescriptor)) + { + OSL_TRACE ("can not handle event code %x", pEventDescriptor->mnEventCode); + } + EventPostprocessing(*pEventDescriptor); + + if (nEventType == BUTTON_UP) + mbPageHit = false; +} + + + + +sal_uInt32 SelectionFunction::EncodeMouseEvent ( + const EventDescriptor& rDescriptor, + const MouseEvent& rEvent) const +{ + // Initialize with the type of mouse event. + sal_uInt32 nEventCode (rDescriptor.mnEventCode & (BUTTON_DOWN | BUTTON_UP | MOUSE_MOTION)); + + // Detect the affected button. + switch (rEvent.GetButtons()) + { + case MOUSE_LEFT: nEventCode |= LEFT_BUTTON; break; + case MOUSE_RIGHT: nEventCode |= RIGHT_BUTTON; break; + case MOUSE_MIDDLE: nEventCode |= MIDDLE_BUTTON; break; + } + + // Detect the number of clicks. + switch (rEvent.GetClicks()) + { + case 1: nEventCode |= SINGLE_CLICK; break; + case 2: nEventCode |= DOUBLE_CLICK; break; + } + + // Detect whether the event has happened over a page object. + if (rDescriptor.mpHitPage != NULL && ! rDescriptor.mpHitDescriptor.expired()) + { + model::SharedPageDescriptor pHitDescriptor (rDescriptor.mpHitDescriptor); + if (pHitDescriptor->IsSelected()) + nEventCode |= OVER_SELECTED_PAGE; + else + nEventCode |= OVER_UNSELECTED_PAGE; + } + + // Detect pressed modifier keys. + if (rEvent.IsShift()) + nEventCode |= SHIFT_MODIFIER; + if (rEvent.IsMod1()) + nEventCode |= CONTROL_MODIFIER; + + // Detect whether we are dragging pages or dragging a selection rectangle. + view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); + if (rOverlay.GetSubstitutionOverlay().isVisible()) + nEventCode |= SUBSTITUTION_VISIBLE; + if (rOverlay.GetSelectionRectangleOverlay().isVisible()) + nEventCode |= RECTANGLE_VISIBLE; + + return nEventCode; +} + + + + +void SelectionFunction::ProcessKeyEvent (const KeyEvent& rEvent) +{ + // 1. Compute some frequently used values relating to the event. + ::std::auto_ptr<EventDescriptor> pEventDescriptor ( + new EventDescriptor(rEvent, mrSlideSorter)); + + // 2. Encode the event. + pEventDescriptor->mnEventCode = EncodeKeyEvent(*pEventDescriptor, rEvent); + + // 3. Process the event. + EventPreprocessing(*pEventDescriptor); + if ( ! EventProcessing(*pEventDescriptor)) + OSL_TRACE ("can not handle event code %x", pEventDescriptor->mnEventCode); + EventPostprocessing(*pEventDescriptor); +} + + + + +sal_uInt32 SelectionFunction::EncodeKeyEvent ( + const EventDescriptor& rDescriptor, + const KeyEvent& rEvent) const +{ + // Initialize as key event. + sal_uInt32 nEventCode (KEY_EVENT); + + // Add the actual key code in the lower 16 bit. + nEventCode |= rEvent.GetKeyCode().GetCode(); + + // Detect pressed modifier keys. + if (rEvent.GetKeyCode().IsShift()) + nEventCode |= SHIFT_MODIFIER; + if (rEvent.GetKeyCode().IsMod1()) + nEventCode |= CONTROL_MODIFIER; + + // Detect whether the event has happened over a page object. + if (rDescriptor.mpHitPage != NULL && ! rDescriptor.mpHitDescriptor.expired()) + { + model::SharedPageDescriptor pHitDescriptor (rDescriptor.mpHitDescriptor); + if (pHitDescriptor->IsSelected()) + nEventCode |= OVER_SELECTED_PAGE; + else + nEventCode |= OVER_UNSELECTED_PAGE; + } + + // Detect whether we are dragging pages or dragging a selection rectangle. + view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); + if (rOverlay.GetSubstitutionOverlay().isVisible()) + nEventCode |= SUBSTITUTION_VISIBLE; + if (rOverlay.GetSelectionRectangleOverlay().isVisible()) + nEventCode |= RECTANGLE_VISIBLE; + + return nEventCode; +} + + + +void SelectionFunction::EventPreprocessing (const EventDescriptor& rDescriptor) +{ + // Some general processing that is not specific to the exact event code. + if (rDescriptor.mnEventCode & BUTTON_DOWN) + mbPageHit = (rDescriptor.mpHitPage!=NULL); + + // Set the focus to the slide under the mouse. + if (rDescriptor.mpHitPage != NULL) + mrController.GetFocusManager().FocusPage((rDescriptor.mpHitPage->GetPageNum()-1)/2); +} + + + + +bool SelectionFunction::EventProcessing (const EventDescriptor& rDescriptor) +{ + // Define some macros to make the following switch statement more readable. +#define ANY_MODIFIER(code) \ + code|NO_MODIFIER: \ + case code|SHIFT_MODIFIER: \ + case code|CONTROL_MODIFIER +#define ANY_PAGE(code) \ + code|NOT_OVER_PAGE: \ + case code|OVER_UNSELECTED_PAGE: \ + case code|OVER_SELECTED_PAGE +#define ANY_PAGE_AND_MODIFIER(code) \ + ANY_PAGE(code|NO_MODIFIER): \ + case ANY_PAGE(code|SHIFT_MODIFIER): \ + case ANY_PAGE(code|CONTROL_MODIFIER) + + + bool bResult (true); + bool bMakeSelectionVisible (true); + + mrController.GetPageSelector().DisableBroadcasting(); + + // 2b. With the event code determine the type of operation with which to + // react to the event. + + // Acquire a shared_ptr to the hit page descriptor. + model::SharedPageDescriptor pHitDescriptor; + if ( ! rDescriptor.mpHitDescriptor.expired()) + pHitDescriptor = model::SharedPageDescriptor(rDescriptor.mpHitDescriptor); + + switch (rDescriptor.mnEventCode) + { + case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE: + SetCurrentPage(pHitDescriptor); + PrepareMouseMotion(mpWindow->PixelToLogic(rDescriptor.maMousePosition)); + mpSubstitutionHandler->Start(rDescriptor.maMouseModelPosition); + break; + + case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE: + SetCurrentPage(pHitDescriptor); + mpSubstitutionHandler->End(); + break; + + case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE: + PrepareMouseMotion(mpWindow->PixelToLogic(rDescriptor.maMousePosition)); + mpSubstitutionHandler->Start(rDescriptor.maMouseModelPosition); + break; + + case BUTTON_DOWN | LEFT_BUTTON | DOUBLE_CLICK | OVER_SELECTED_PAGE: + case BUTTON_DOWN | LEFT_BUTTON | DOUBLE_CLICK | OVER_UNSELECTED_PAGE: + // A double click allways shows the selected slide in the center + // pane in an edit view. + SetCurrentPage(pHitDescriptor); + SwitchView(pHitDescriptor); + break; + + // Multi selection with the control modifier. + case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | CONTROL_MODIFIER: + DeselectHitPage(pHitDescriptor); + PrepareMouseMotion(mpWindow->PixelToLogic(rDescriptor.maMousePosition)); + break; + + case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | CONTROL_MODIFIER: + SelectHitPage(pHitDescriptor); + PrepareMouseMotion(mpWindow->PixelToLogic(rDescriptor.maMousePosition)); + + break; + + // Range selection with the shift modifier. + case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | SHIFT_MODIFIER: + case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | SHIFT_MODIFIER: + RangeSelect(pHitDescriptor); + break; + + // Was: Preview of the page transition effect. + case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_FADE_INDICATOR: + // No action. + break; + + // Right button for context menu. + case BUTTON_DOWN | RIGHT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE: + case KEY_EVENT | KEY_F10 | SHIFT_MODIFIER | OVER_UNSELECTED_PAGE: + // Single right click and shift+F10 select as preparation to + // show the context menu. Change the selection only when the + // page under the mouse is not selected. In this case the + // selection is set to this single page. Otherwise the + // selection is not modified. + DeselectAllPages(); + SelectHitPage(pHitDescriptor); + SetCurrentPage(pHitDescriptor); + bMakeSelectionVisible = false; + break; + + case BUTTON_DOWN | RIGHT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE: + case KEY_EVENT | KEY_F10 | OVER_SELECTED_PAGE | SHIFT_MODIFIER: + // Do not change the selection. Just adjust the insertion indicator. + bMakeSelectionVisible = false; + break; + + case BUTTON_DOWN | RIGHT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE: + // The Shift+F10 key event is here just for completeness. It should + // not be possible to really receive this (not being over a page.) + case KEY_EVENT | KEY_F10 | SHIFT_MODIFIER | NOT_OVER_PAGE: + DeselectAllPages(); + bMakeSelectionVisible = false; + break; + + // A mouse motion without visible substitution starts that. + case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE): + mrController.GetScrollBarManager().AutoScroll(rDescriptor.maMousePosition); + mpSubstitutionHandler->Start(rDescriptor.maMouseModelPosition); + break; + + // Move substitution. + case ANY_PAGE_AND_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | SUBSTITUTION_VISIBLE): + if ((rDescriptor.mnEventCode & CONTROL_MODIFIER) != 0) + StartDrag(); + mrController.GetScrollBarManager().AutoScroll(rDescriptor.maMousePosition); + mpSubstitutionHandler->UpdatePosition(rDescriptor.maMouseModelPosition); + break; + + // Place substitution. + case ANY_PAGE_AND_MODIFIER(BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | SUBSTITUTION_VISIBLE): + // When the substitution has not been moved the button up event + // is taken to be part of a single click. The selected pages + // are therefore not moved (which technically would be necessary + // for unconsecutive multi selections). Instead the page under + // the mouse becomes the only selected page. + if (mpSubstitutionHandler->HasBeenMoved()) + { + // The following Process() call may lead to the desctruction + // of pHitDescriptor so release our reference to it. + pHitDescriptor.reset(); + mpSubstitutionHandler->Process(); + } + else + if (pHitDescriptor != NULL) + SetCurrentPage(pHitDescriptor); + mpSubstitutionHandler->End(); + break; + + // Rectangle selection. + case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE | NO_MODIFIER: + DeselectAllPages(); + StartRectangleSelection(rDescriptor.maMouseModelPosition); + break; + + case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE | SHIFT_MODIFIER: + case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE | CONTROL_MODIFIER: + StartRectangleSelection(rDescriptor.maMouseModelPosition); + break; + + case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE): + case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE): + case ANY_PAGE_AND_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | RECTANGLE_VISIBLE): + mrController.GetScrollBarManager().AutoScroll(rDescriptor.maMousePosition); + UpdateRectangleSelection(rDescriptor.maMouseModelPosition); + break; + + case ANY_PAGE(BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | RECTANGLE_VISIBLE | NO_MODIFIER): + ProcessRectangleSelection(false); + break; + + case ANY_PAGE(BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | RECTANGLE_VISIBLE | SHIFT_MODIFIER): + case ANY_PAGE(BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | RECTANGLE_VISIBLE | CONTROL_MODIFIER): + ProcessRectangleSelection(true); + break; + + default: + bResult = false; + break; + } + mrController.GetPageSelector().EnableBroadcasting(bMakeSelectionVisible); + + return bResult; +} + + + + +void SelectionFunction::EventPostprocessing (const EventDescriptor& rDescriptor) +{ + if (rDescriptor.mnEventCode & BUTTON_UP) + { + view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); + + mpWindow->ReleaseMouse(); + + // The overlays should not be visible anymore. Warn when one of + // them still is. An exception is th insertion indicator in the + // case that the context menu is visible. + DBG_ASSERT( + mrController.IsContextMenuOpen() + || !rOverlay.GetInsertionIndicatorOverlay().isVisible(), + "slidesorter::SelectionFunction: insertion indicator still visible"); + DBG_ASSERT( + !rOverlay.GetSubstitutionOverlay().isVisible(), + "slidesorter::SelectionFunction: substitution still visible"); + DBG_ASSERT( + !rOverlay.GetSelectionRectangleOverlay().isVisible(), + "slidesorter::SelectionFunction: selection rectangle still visible"); + + // Now turn them off. + if ( ! mrController.IsContextMenuOpen()) + rOverlay.GetInsertionIndicatorOverlay().setVisible(false); + rOverlay.GetSubstitutionOverlay().setVisible(false); + rOverlay.GetSelectionRectangleOverlay().setVisible(false); + } +} + + + + +void SelectionFunction::SetCurrentPage (const model::SharedPageDescriptor& rpDescriptor) +{ + PageSelector& rSelector (mrController.GetPageSelector()); + rSelector.DeselectAllPages (); + rSelector.SelectPage(rpDescriptor); + + mrController.GetCurrentSlideManager()->SwitchCurrentSlide(rpDescriptor); +} + + + + +void SelectionFunction::SwitchView (const model::SharedPageDescriptor& rpDescriptor) +{ + // Switch to the draw view. This is done only when the current + // view is the main view. + ViewShell* pViewShell = mrSlideSorter.GetViewShell(); + if (pViewShell!=NULL && pViewShell->IsMainViewShell()) + { + if (rpDescriptor.get()!=NULL && rpDescriptor->GetPage()!=NULL) + { + mrSlideSorter.GetModel().GetDocument()->SetSelected(rpDescriptor->GetPage(), TRUE); + mpViewShell->GetFrameView()->SetSelectedPage( + (rpDescriptor->GetPage()->GetPageNum()-1)/2); + } + if (mrSlideSorter.GetViewShellBase() != NULL) + framework::FrameworkHelper::Instance(*mrSlideSorter.GetViewShellBase())->RequestView( + framework::FrameworkHelper::msImpressViewURL, + framework::FrameworkHelper::msCenterPaneURL); + } +} + + + + +//===== EventDescriptor ======================================================= + +SelectionFunction::EventDescriptor::EventDescriptor ( + sal_uInt32 nEventType, + const MouseEvent& rEvent, + SlideSorter& rSlideSorter) + : maMousePosition(), + maMouseModelPosition(), + mpHitDescriptor(), + mpHitPage(), + mnEventCode(nEventType) +{ + ::Window* pWindow = rSlideSorter.GetActiveWindow(); + + maMousePosition = rEvent.GetPosPixel(); + maMouseModelPosition = pWindow->PixelToLogic(maMousePosition); + model::SharedPageDescriptor pHitDescriptor ( + rSlideSorter.GetController().GetPageAt(maMousePosition)); + if (pHitDescriptor.get() != NULL) + { + mpHitDescriptor = pHitDescriptor; + mpHitPage = pHitDescriptor->GetPage(); + } +} + + + + + +SelectionFunction::EventDescriptor::EventDescriptor ( + const KeyEvent&, + SlideSorter& rSlideSorter) + : maMousePosition(), + maMouseModelPosition(), + mpHitDescriptor(), + mpHitPage(), + mnEventCode(0) +{ + mpHitDescriptor = rSlideSorter.GetController().GetFocusManager().GetFocusedPageDescriptor(); + model::SharedPageDescriptor pHitDescriptor ( + rSlideSorter.GetController().GetFocusManager().GetFocusedPageDescriptor()); + if (pHitDescriptor.get() != NULL) + { + mpHitPage = pHitDescriptor->GetPage(); + mpHitDescriptor = pHitDescriptor; + } +} + + + + + +//===== SubstitutionHandler =================================================== + +SelectionFunction::SubstitutionHandler::SubstitutionHandler (SlideSorter& rSlideSorter) + : mrSlideSorter(rSlideSorter), + mbHasBeenMoved(false) +{ +} + + + + +SelectionFunction::SubstitutionHandler::~SubstitutionHandler (void) +{ + if (mrSlideSorter.IsValid()) + { + view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); + rOverlay.GetSubstitutionOverlay().setVisible(false); + rOverlay.GetSubstitutionOverlay().Clear(); + } +} + + + + +void SelectionFunction::SubstitutionHandler::Start (const Point& rMouseModelPosition) +{ + // No Drag-and-Drop for master pages. + if (mrSlideSorter.GetModel().GetEditMode() != EM_PAGE) + return; + + if (mrSlideSorter.GetController().GetProperties()->IsUIReadOnly()) + return; + + view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); + + if ( ! rOverlay.GetSubstitutionOverlay().isVisible()) + { + // Show a new substitution for the selected page objects. + model::PageEnumeration aSelectedPages( + model::PageEnumerationProvider::CreateSelectedPagesEnumeration( + mrSlideSorter.GetModel())); + rOverlay.GetSubstitutionOverlay().Create(aSelectedPages, rMouseModelPosition); + rOverlay.GetSubstitutionOverlay().setVisible(true); + mbHasBeenMoved = false; + } + else + UpdatePosition(rMouseModelPosition); +} + + + + +void SelectionFunction::SubstitutionHandler::UpdatePosition (const Point& rMouseModelPosition) +{ + if (mrSlideSorter.GetController().GetProperties()->IsUIReadOnly()) + return; + + view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); + + // Move the existing substitution to the new position. + rOverlay.GetSubstitutionOverlay().SetPosition(rMouseModelPosition); + + rOverlay.GetInsertionIndicatorOverlay().SetPosition(rMouseModelPosition); + rOverlay.GetInsertionIndicatorOverlay().setVisible(true); + + mbHasBeenMoved = true; +} + + + + +void SelectionFunction::SubstitutionHandler::Process (void) +{ + if (mrSlideSorter.GetController().GetProperties()->IsUIReadOnly()) + return; + + view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); + + if (IsSubstitutionInsertionNonTrivial()) + { + // Tell the model to move the selected pages behind the one with the + // index mnInsertionIndex which first has to transformed into an index + // understandable by the document. + sal_Int32 nInsertionIndex = rOverlay.GetInsertionIndicatorOverlay().GetInsertionPageIndex(); + if (nInsertionIndex >= 0) + { + USHORT nDocumentIndex = (USHORT)nInsertionIndex-1; + mrSlideSorter.GetController().GetSelectionManager()->MoveSelectedPages(nDocumentIndex); + } + + ViewShell* pViewShell = mrSlideSorter.GetViewShell(); + if (pViewShell != NULL) + pViewShell->GetViewFrame()->GetBindings().Invalidate(SID_STATUS_PAGE); + } +} + + + + +void SelectionFunction::SubstitutionHandler::End (void) +{ + view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); + rOverlay.GetSubstitutionOverlay().setVisible(false); + rOverlay.GetSubstitutionOverlay().Clear(); + rOverlay.GetInsertionIndicatorOverlay().setVisible(false); +} + + + + +bool SelectionFunction::SubstitutionHandler::HasBeenMoved (void) const +{ + return mbHasBeenMoved; +} + + + + +bool SelectionFunction::SubstitutionHandler::IsSubstitutionInsertionNonTrivial (void) const +{ + bool bIsNonTrivial = false; + + do + { + view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); + + // Make sure that the substitution and the insertion indicator are visible. + if ( ! rOverlay.GetSubstitutionOverlay().isVisible()) + break; + if ( ! rOverlay.GetInsertionIndicatorOverlay().isVisible()) + break; + + // Iterate over all selected pages and check whether there are + // holes. While we do this we remember the indices of the first and + // last selected page as preparation for the next step. + sal_Int32 nCurrentIndex = -1; + sal_Int32 nFirstIndex = -1; + sal_Int32 nLastIndex = -1; + model::PageEnumeration aSelectedPages ( + model::PageEnumerationProvider::CreateSelectedPagesEnumeration( + mrSlideSorter.GetModel())); + while (aSelectedPages.HasMoreElements() && ! bIsNonTrivial) + { + model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement()); + SdPage* pPage = pDescriptor->GetPage(); + if (pPage != NULL) + { + // Get the page number and compare it to the last one. + sal_Int32 nPageNumber = (pPage->GetPageNum()-1)/2; + if (nCurrentIndex>=0 && nPageNumber>(nCurrentIndex+1)) + bIsNonTrivial = true; + else + nCurrentIndex = nPageNumber; + + // Remember indices of the first and last page of the selection. + if (nFirstIndex == -1) + nFirstIndex = nPageNumber; + nLastIndex = nPageNumber; + } + } + if (bIsNonTrivial) + break; + + // When we come here then the selection is consecutive. We still + // have to check that the insertion position is not directly in + // front or directly behind the selection and thus moving the + // selection there would not change the model. + sal_Int32 nInsertionIndex = rOverlay.GetInsertionIndicatorOverlay().GetInsertionPageIndex(); + if (nInsertionIndex<nFirstIndex || nInsertionIndex>(nLastIndex+1)) + bIsNonTrivial = true; + } + while (false); + + return bIsNonTrivial; +} + +} } } // end of namespace ::sd::slidesorter::controller diff --git a/sd/source/ui/slidesorter/controller/SlsSelectionManager.cxx b/sd/source/ui/slidesorter/controller/SlsSelectionManager.cxx new file mode 100755 index 000000000000..f1b4cb6c39be --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlsSelectionManager.cxx @@ -0,0 +1,662 @@ +/************************************************************************* + * + * 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 "controller/SlsSelectionManager.hxx" + +#include "SlideSorter.hxx" +#include "SlsSelectionCommand.hxx" +#include "controller/SlideSorterController.hxx" +#include "controller/SlsAnimator.hxx" +#include "controller/SlsCurrentSlideManager.hxx" +#include "controller/SlsFocusManager.hxx" +#include "controller/SlsProperties.hxx" +#include "controller/SlsScrollBarManager.hxx" +#include "controller/SlsSlotManager.hxx" +#include "model/SlideSorterModel.hxx" +#include "model/SlsPageEnumerationProvider.hxx" +#include "model/SlsPageDescriptor.hxx" +#include "view/SlideSorterView.hxx" +#include "drawdoc.hxx" +#include "Window.hxx" +#include <svx/svxids.hrc> +#include <com/sun/star/drawing/XMasterPagesSupplier.hpp> +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> + +#include "res_bmp.hrc" +#include "sdresid.hxx" +#include "strings.hrc" +#include "app.hrc" +#include "glob.hrc" + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::uno; +using namespace ::sd::slidesorter::model; +using namespace ::sd::slidesorter::view; +using namespace ::sd::slidesorter::controller; + +namespace sd { namespace slidesorter { namespace controller { + + +namespace { + class VerticalVisibleAreaScroller + { + public: + VerticalVisibleAreaScroller (SlideSorter& rSlideSorter, + const double nStart, const double nEnd); + void operator() (const double nValue); + private: + SlideSorter& mrSlideSorter; + double mnStart; + double mnEnd; + }; + class HorizontalVisibleAreaScroller + { + public: + HorizontalVisibleAreaScroller (SlideSorter& rSlideSorter, + const double nStart, const double nEnd); + void operator() (const double nValue); + private: + SlideSorter& mrSlideSorter; + double mnStart; + double mnEnd; + }; +} + + + + +SelectionManager::SelectionManager (SlideSorter& rSlideSorter) + : mrSlideSorter(rSlideSorter), + mrController(rSlideSorter.GetController()), + maSelectionBeforeSwitch(), + mbIsMakeSelectionVisiblePending(true) +{ +} + + + + +SelectionManager::~SelectionManager (void) +{ +} + + + + +void SelectionManager::DeleteSelectedPages (void) +{ + SlideSorterController::ModelChangeLock aLock (mrController); + + // Hide focus. + bool bIsFocusShowing = mrController.GetFocusManager().IsFocusShowing(); + if (bIsFocusShowing) + mrController.GetFocusManager().ToggleFocus(); + + // Store pointers to all selected page descriptors. This is necessary + // because the pages get deselected when the first one is deleted. + model::PageEnumeration aPageEnumeration ( + PageEnumerationProvider::CreateSelectedPagesEnumeration(mrSlideSorter.GetModel())); + ::std::vector<SdPage*> aSelectedPages; + while (aPageEnumeration.HasMoreElements()) + aSelectedPages.push_back (aPageEnumeration.GetNextElement()->GetPage()); + + // The actual deletion of the selected pages is done in one of two + // helper functions. They are specialized for normal respectively for + // master pages. + mrSlideSorter.GetView().BegUndo (SdResId(STR_UNDO_DELETEPAGES)); + if (mrSlideSorter.GetModel().GetEditMode() == EM_PAGE) + DeleteSelectedNormalPages(aSelectedPages); + else + DeleteSelectedMasterPages(aSelectedPages); + mrSlideSorter.GetView().EndUndo (); + + mrController.HandleModelChange(); + aLock.Release(); + + // Show focus and move it to next valid location. + if (bIsFocusShowing) + mrController.GetFocusManager().ToggleFocus (); + mrController.GetFocusManager().MoveFocus (FocusManager::FMD_NONE); +} + + + + +void SelectionManager::DeleteSelectedNormalPages (const ::std::vector<SdPage*>& rSelectedPages) +{ + // Prepare the deletion via the UNO API. + OSL_ASSERT(mrSlideSorter.GetModel().GetEditMode() == EM_PAGE); + + try + { + Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier( mrSlideSorter.GetModel().GetDocument()->getUnoModel(), UNO_QUERY_THROW ); + Reference<drawing::XDrawPages> xPages( xDrawPagesSupplier->getDrawPages(), UNO_QUERY_THROW ); + + // Iterate over all pages that where seleted when this method was called + // and delete the draw page the notes page. The iteration is done in + // reverse order so that when one slide is not deleted (to avoid an + // empty document) the remaining slide is the first one. + ::std::vector<SdPage*>::const_reverse_iterator aI; + for (aI=rSelectedPages.rbegin(); aI!=rSelectedPages.rend(); aI++) + { + // Do not delete the last slide in the document. + if (xPages->getCount() <= 1) + break; + + USHORT nPage = ((*aI)->GetPageNum()-1) / 2; + + Reference< XDrawPage > xPage( xPages->getByIndex( nPage ), UNO_QUERY_THROW ); + xPages->remove(xPage); + } + } + catch( Exception& ) + { + DBG_ERROR("SelectionManager::DeleteSelectedNormalPages(), exception caught!"); + } +} + + + + +void SelectionManager::DeleteSelectedMasterPages (const ::std::vector<SdPage*>& rSelectedPages) +{ + // Prepare the deletion via the UNO API. + OSL_ASSERT(mrSlideSorter.GetModel().GetEditMode() == EM_MASTERPAGE); + + try + { + Reference<drawing::XMasterPagesSupplier> xDrawPagesSupplier( mrSlideSorter.GetModel().GetDocument()->getUnoModel(), UNO_QUERY_THROW ); + Reference<drawing::XDrawPages> xPages( xDrawPagesSupplier->getMasterPages(), UNO_QUERY_THROW ); + + // Iterate over all pages that where seleted when this method was called + // and delete the draw page the notes page. The iteration is done in + // reverse order so that when one slide is not deleted (to avoid an + // empty document) the remaining slide is the first one. + ::std::vector<SdPage*>::const_reverse_iterator aI; + for (aI=rSelectedPages.rbegin(); aI!=rSelectedPages.rend(); aI++) + { + // Do not delete the last slide in the document. + if (xPages->getCount() <= 1) + break; + + USHORT nPage = ((*aI)->GetPageNum()-1) / 2; + + Reference< XDrawPage > xPage( xPages->getByIndex( nPage ), UNO_QUERY_THROW ); + xPages->remove(xPage); + } + } + catch( Exception& ) + { + DBG_ERROR("SelectionManager::DeleteSelectedMasterPages(), exception caught!"); + } +} + + + + +bool SelectionManager::MoveSelectedPages (const sal_Int32 nTargetPageIndex) +{ + bool bMoved (false); + PageSelector& rSelector (mrController.GetPageSelector()); + + mrSlideSorter.GetView().LockRedraw (TRUE); + SlideSorterController::ModelChangeLock aLock (mrController); + + // Transfer selection of the slide sorter to the document. + mrSlideSorter.GetModel().SynchronizeDocumentSelection (); + + // Detect how many pages lie between document start and insertion + // position. + sal_Int32 nPageCountBeforeTarget (0); + ::boost::shared_ptr<PageSelector::PageSelection> pSelection (rSelector.GetPageSelection()); + PageSelector::PageSelection::const_iterator iSelectedPage (pSelection->begin()); + PageSelector::PageSelection::const_iterator iSelectionEnd (pSelection->end()); + for ( ; iSelectedPage!=iSelectionEnd; ++iSelectedPage) + { + if (*iSelectedPage==NULL) + continue; + if (((*iSelectedPage)->GetPageNum()-1)/2 <= nTargetPageIndex) + ++nPageCountBeforeTarget; + else + break; + } + + // Prepare to select the moved pages. + SelectionCommand* pCommand = new SelectionCommand( + rSelector,mrController.GetCurrentSlideManager(),mrSlideSorter.GetModel()); + sal_Int32 nSelectedPageCount (rSelector.GetSelectedPageCount()); + for (sal_Int32 nOffset=0; nOffset<nSelectedPageCount; ++nOffset) + pCommand->AddSlide(sal::static_int_cast<USHORT>( + nTargetPageIndex + nOffset - nPageCountBeforeTarget + 1)); + + // At the moment we can not move master pages. + if (nTargetPageIndex>=0) + { + if (mrSlideSorter.GetModel().GetEditMode() == EM_PAGE) + bMoved = mrSlideSorter.GetModel().GetDocument()->MovePages( + sal::static_int_cast<sal_uInt16>(nTargetPageIndex)); + } + if (bMoved) + mrController.GetSlotManager()->ExecuteCommandAsynchronously( + ::std::auto_ptr<controller::Command>(pCommand)); + + mrSlideSorter.GetView().LockRedraw (FALSE); + + return bMoved; +} + + + + +void SelectionManager::SelectionHasChanged (const bool bMakeSelectionVisible) +{ + if (bMakeSelectionVisible) + mbIsMakeSelectionVisiblePending = true; + + ViewShell* pViewShell = mrSlideSorter.GetViewShell(); + if (pViewShell != NULL) + { + pViewShell->Invalidate (SID_EXPAND_PAGE); + pViewShell->Invalidate (SID_SUMMARY_PAGE); + pViewShell->Invalidate(SID_SHOW_SLIDE); + pViewShell->Invalidate(SID_HIDE_SLIDE); + pViewShell->Invalidate(SID_DELETE_PAGE); + pViewShell->Invalidate(SID_DELETE_MASTER_PAGE); + pViewShell->Invalidate(SID_ASSIGN_LAYOUT); + + // StatusBar + pViewShell->Invalidate (SID_STATUS_PAGE); + pViewShell->Invalidate (SID_STATUS_LAYOUT); + + OSL_ASSERT(mrController.GetCurrentSlideManager()); + SharedPageDescriptor pDescriptor(mrController.GetCurrentSlideManager()->GetCurrentSlide()); + if (pDescriptor.get() != NULL) + pViewShell->UpdatePreview(pDescriptor->GetPage()); + + // Tell the slection change listeners that the selection has changed. + ::std::vector<Link>::iterator iListener (maSelectionChangeListeners.begin()); + ::std::vector<Link>::iterator iEnd (maSelectionChangeListeners.end()); + for (; iListener!=iEnd; ++iListener) + { + iListener->Call(NULL); + } + + // Reset the insertion position: until set again it is calculated from + // the current selection. + mnInsertionPosition = -1; + } +} + + + + +bool SelectionManager::IsMakeSelectionVisiblePending (void) const +{ + return mbIsMakeSelectionVisiblePending; +} + + + + +/** We have to distinguish three cases: 1) the selection is empty, 2) the + selection fits completely into the visible area, 3) it does not. + 1) The visible area is not modified. + 2) When the selection fits completely into the visible area we have to + decide how to align it. It is done by scrolling it there and thus when + we scoll up the (towards the end of the document) the bottom of the + selection is aligned with the bottom of the window. When we scroll + down (towards the beginning of the document) the top of the selection is + aligned with the top of the window. + 3) We have to decide what part of the selection to make visible. Here + we use the eSelectionHint and concentrate on either the first, the last, + or the most recently selected page. We then again apply the algorithm + of a). + +*/ +Size SelectionManager::MakeSelectionVisible (const SelectionHint eSelectionHint) +{ + ::sd::Window* pWindow = mrSlideSorter.GetActiveWindow(); + if (pWindow == NULL) + return Size(0,0); + + mbIsMakeSelectionVisiblePending = false; + + // Determine the descriptors of the first and last selected page and the + // bounding box that encloses their page objects. + model::SharedPageDescriptor pFirst; + model::SharedPageDescriptor pLast; + Rectangle aSelectionBox; + model::PageEnumeration aSelectedPages ( + PageEnumerationProvider::CreateSelectedPagesEnumeration(mrSlideSorter.GetModel())); + while (aSelectedPages.HasMoreElements()) + { + model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement()); + + if (pFirst.get() == NULL) + pFirst = pDescriptor; + pLast = pDescriptor; + + aSelectionBox.Union (mrSlideSorter.GetView().GetPageBoundingBox ( + pDescriptor, + view::SlideSorterView::CS_MODEL, + view::SlideSorterView::BBT_INFO)); + } + + if (pFirst != NULL) + { + // Determine scroll direction and the position in model coordinates + // that will be aligned with the top/left or bottom/right window + // border. + if (DoesSelectionExceedVisibleArea(aSelectionBox)) + { + // We can show only a part of the selection. + aSelectionBox = ResolveLargeSelection(pFirst,pLast, eSelectionHint); + } + + return MakeRectangleVisible(aSelectionBox); + } + + return Size(0,0); +} + + + + +Size SelectionManager::MakeRectangleVisible (const Rectangle& rBox) +{ + ::sd::Window* pWindow = mrSlideSorter.GetActiveWindow(); + if (pWindow == NULL) + return Size(0,0); + + Rectangle aVisibleArea (pWindow->PixelToLogic( + Rectangle( + Point(0,0), + pWindow->GetOutputSizePixel()))); + + if (mrSlideSorter.GetView().GetOrientation() == SlideSorterView::VERTICAL) + { + // Scroll the visible area to make aSelectionBox visible. + sal_Int32 nNewTop (aVisibleArea.Top()); + if (mrSlideSorter.GetController().GetProperties()->IsCenterSelection()) + { + nNewTop = rBox.Top() - (aVisibleArea.GetHeight() - rBox.GetHeight()) / 2; + } + else + { + if (rBox.Top() < aVisibleArea.Top()) + nNewTop = rBox.Top(); + else if (rBox.Bottom() > aVisibleArea.Bottom()) + nNewTop = rBox.Bottom() - aVisibleArea.GetHeight(); + // otherwise we do not modify the visible area. + } + + // Make some corrections of the new visible area. + Rectangle aModelArea (mrSlideSorter.GetView().GetModelArea()); + if (nNewTop + aVisibleArea.GetHeight() > aModelArea.Bottom()) + nNewTop = aModelArea.GetHeight() - aVisibleArea.GetHeight(); + if (nNewTop < aModelArea.Top()) + nNewTop = aModelArea.Top(); + + // Scroll. + if (nNewTop != aVisibleArea.Top()) + { + mrController.GetAnimator()->AddAnimation( + VerticalVisibleAreaScroller(mrSlideSorter, aVisibleArea.Top(), nNewTop), + mrSlideSorter.GetController().GetProperties()->IsSmoothSelectionScrolling() ? + 1000 : 0 + ); + } + + return Size(0,aVisibleArea.Top() - nNewTop); + } + else + { + // Scroll the visible area to make aSelectionBox visible. + sal_Int32 nNewLeft (aVisibleArea.Left()); + if (mrSlideSorter.GetController().GetProperties()->IsCenterSelection()) + { + nNewLeft = rBox.Left() - (aVisibleArea.GetWidth() - rBox.GetWidth()) / 2; + } + else + { + if (rBox.Left() < aVisibleArea.Left()) + nNewLeft = rBox.Left(); + else if (rBox.Right() > aVisibleArea.Right()) + nNewLeft = rBox.Right() - aVisibleArea.GetWidth(); + // otherwise we do not modify the visible area. + } + + // Make some corrections of the new visible area. + Rectangle aModelArea (mrSlideSorter.GetView().GetModelArea()); + if (nNewLeft + aVisibleArea.GetWidth() > aModelArea.Right()) + nNewLeft = aModelArea.GetWidth() - aVisibleArea.GetWidth(); + if (nNewLeft < aModelArea.Left()) + nNewLeft = aModelArea.Left(); + + // Scroll. + if (nNewLeft != aVisibleArea.Left()) + { + mrController.GetAnimator()->AddAnimation( + HorizontalVisibleAreaScroller(mrSlideSorter, aVisibleArea.Left(), nNewLeft), + mrSlideSorter.GetController().GetProperties()->IsSmoothSelectionScrolling() ? + 1000 : 0 + ); + } + + return Size(aVisibleArea.Left() - nNewLeft, 0); + } +} + + + + +void SelectionManager::AddSelectionChangeListener (const Link& rListener) +{ + if (::std::find ( + maSelectionChangeListeners.begin(), + maSelectionChangeListeners.end(), + rListener) == maSelectionChangeListeners.end()) + { + maSelectionChangeListeners.push_back (rListener); + } +} + + + + +void SelectionManager::RemoveSelectionChangeListener(const Link&rListener) +{ + maSelectionChangeListeners.erase ( + ::std::find ( + maSelectionChangeListeners.begin(), + maSelectionChangeListeners.end(), + rListener)); +} + + + + +bool SelectionManager::DoesSelectionExceedVisibleArea (const Rectangle& rSelectionBox) const +{ + ::sd::Window* pWindow = mrSlideSorter.GetActiveWindow(); + if (pWindow == NULL) + return true; + + Rectangle aVisibleArea (pWindow->PixelToLogic( + Rectangle( + Point(0,0), + pWindow->GetOutputSizePixel()))); + if (mrSlideSorter.GetView().GetOrientation() == SlideSorterView::VERTICAL) + return rSelectionBox.GetHeight() > aVisibleArea.GetHeight(); + else + return rSelectionBox.GetWidth() > aVisibleArea.GetWidth(); +} + + + + +Rectangle SelectionManager::ResolveLargeSelection ( + const SharedPageDescriptor& rpFirst, + const SharedPageDescriptor& rpLast, + const SelectionHint eSelectionHint) +{ + OSL_ASSERT(rpFirst.get()!=NULL); + OSL_ASSERT(rpLast.get()!=NULL); + + // The mose recently selected page is assumed to lie in the range + // between first and last selected page. Therefore the bounding box is + // not modified. + model::SharedPageDescriptor pRecent ( + mrController.GetPageSelector().GetMostRecentlySelectedPage()); + + // Get the bounding box of the page object on which to concentrate. + model::SharedPageDescriptor pRepresentative; + switch (eSelectionHint) + { + case SH_FIRST: + pRepresentative = rpFirst; + break; + + case SH_LAST: + pRepresentative = rpLast; + break; + + case SH_RECENT: + default: + if (pRecent.get() == NULL) + pRepresentative = rpFirst; + else + pRepresentative = pRecent; + break; + } + OSL_ASSERT(pRepresentative.get() != NULL); + + return mrSlideSorter.GetView().GetPageBoundingBox ( + pRepresentative, + view::SlideSorterView::CS_MODEL, + view::SlideSorterView::BBT_INFO); +} + + + + +sal_Int32 SelectionManager::GetInsertionPosition (void) const +{ + sal_Int32 nInsertionPosition (mnInsertionPosition); + if (nInsertionPosition < 0) + { + model::PageEnumeration aSelectedPages + (model::PageEnumerationProvider::CreateSelectedPagesEnumeration( + mrSlideSorter.GetModel())); + // Initialize (for the case of an empty selection) with the position + // at the end of the document. + nInsertionPosition = mrSlideSorter.GetModel().GetPageCount(); + while (aSelectedPages.HasMoreElements()) + { + const sal_Int32 nPosition (aSelectedPages.GetNextElement()->GetPage()->GetPageNum()); + // Convert *2+1 index to straight index (n-1)/2 after the page + // (+1). + nInsertionPosition = (nPosition-1)/2 + 1; + } + + } + return nInsertionPosition; +} + + + + +void SelectionManager::SetInsertionPosition (const sal_Int32 nInsertionPosition) +{ + if (nInsertionPosition < 0) + mnInsertionPosition = -1; + else if (nInsertionPosition > mrSlideSorter.GetModel().GetPageCount()) + { + // Assert but then ignore invalid values. + OSL_ASSERT(nInsertionPosition<=mrSlideSorter.GetModel().GetPageCount()); + return; + } + else + mnInsertionPosition = nInsertionPosition; +} + + + + +//===== VerticalVisibleAreaScroller =========================================== + +namespace { + +VerticalVisibleAreaScroller::VerticalVisibleAreaScroller ( + SlideSorter& rSlideSorter, + const double nStart, + const double nEnd) + : mrSlideSorter(rSlideSorter), + mnStart(nStart), + mnEnd(nEnd) +{ +} + + + +void VerticalVisibleAreaScroller::operator() (const double nValue) +{ + mrSlideSorter.GetView().InvalidatePageObjectVisibilities(); + mrSlideSorter.GetController().GetScrollBarManager().SetTop( + int(mnStart * (1.0 - nValue) + mnEnd * nValue)); +} + + + + +HorizontalVisibleAreaScroller::HorizontalVisibleAreaScroller ( + SlideSorter& rSlideSorter, + const double nStart, + const double nEnd) + : mrSlideSorter(rSlideSorter), + mnStart(nStart), + mnEnd(nEnd) +{ +} + + + + +void HorizontalVisibleAreaScroller::operator() (const double nValue) +{ + mrSlideSorter.GetView().InvalidatePageObjectVisibilities(); + mrSlideSorter.GetController().GetScrollBarManager().SetLeft( + int(mnStart * (1.0 - nValue) + mnEnd * nValue)); +} + +} // end of anonymous namespace + +} } } // end of namespace ::sd::slidesorter diff --git a/sd/source/ui/slidesorter/controller/SlsSlideFunction.cxx b/sd/source/ui/slidesorter/controller/SlsSlideFunction.cxx new file mode 100755 index 000000000000..7fe090ad5541 --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlsSlideFunction.cxx @@ -0,0 +1,80 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + +#include "controller/SlsSlideFunction.hxx" + +#include "SlideSorter.hxx" +#include "controller/SlideSorterController.hxx" +#include "view/SlideSorterView.hxx" +#include "model/SlideSorterModel.hxx" + + +namespace sd { namespace slidesorter { namespace controller { + +TYPEINIT1(SlideFunction, FuPoor); + + +SlideFunction::SlideFunction ( + SlideSorter& rSlideSorter, + SfxRequest& rRequest) + : FuPoor ( + rSlideSorter.GetViewShell(), + rSlideSorter.GetView().GetWindow(), + &rSlideSorter.GetView(), + rSlideSorter.GetModel().GetDocument(), + rRequest) +{ +} + +void SlideFunction::ScrollStart (void) +{ +} + +void SlideFunction::ScrollEnd (void) +{ +} + +BOOL SlideFunction::MouseMove(const MouseEvent& ) +{ + return FALSE; +} + +BOOL SlideFunction::MouseButtonUp(const MouseEvent& ) +{ + return FALSE; + +} + +BOOL SlideFunction::MouseButtonDown(const MouseEvent& ) +{ + return FALSE; +} + +} } } // end of namespace ::sd::slidesorter::controller diff --git a/sd/source/ui/slidesorter/controller/SlsSlotManager.cxx b/sd/source/ui/slidesorter/controller/SlsSlotManager.cxx new file mode 100755 index 000000000000..e571a765bdad --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlsSlotManager.cxx @@ -0,0 +1,1134 @@ +/************************************************************************* + * + * 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 <com/sun/star/presentation/XPresentation2.hpp> + +#include "controller/SlsSlotManager.hxx" +#include "SlideSorter.hxx" +#include "SlideSorterViewShell.hxx" +#include "controller/SlideSorterController.hxx" +#include "controller/SlsPageSelector.hxx" +#include "controller/SlsClipboard.hxx" +#include "controller/SlsSelectionFunction.hxx" +#include "controller/SlsFocusManager.hxx" +#include "controller/SlsCurrentSlideManager.hxx" +#include "controller/SlsSelectionManager.hxx" +#include "SlsHideSlideFunction.hxx" +#include "SlsCommand.hxx" +#include "model/SlideSorterModel.hxx" +#include "model/SlsPageEnumerationProvider.hxx" +#include "model/SlsPageDescriptor.hxx" +#include "view/SlideSorterView.hxx" +#include "view/SlsLayouter.hxx" +#include "view/SlsViewOverlay.hxx" +#include "framework/FrameworkHelper.hxx" +#include "Window.hxx" +#include "fupoor.hxx" +#include "fuzoom.hxx" +#include "fucushow.hxx" +#include "fusldlg.hxx" +#include "fuexpand.hxx" +#include "fusumry.hxx" +#include "fuscale.hxx" +#include "slideshow.hxx" +#include "app.hrc" +#include "strings.hrc" +#include "sdresid.hxx" +#include "drawdoc.hxx" +#include "DrawDocShell.hxx" +#include "ViewShellBase.hxx" +#include "ViewShellImplementation.hxx" +#include "sdattr.hxx" +#include "FrameView.hxx" +#include "zoomlist.hxx" +#include "sdpage.hxx" +#include "sdxfer.hxx" +#include "helpids.h" +#include "glob.hrc" +#include "unmodpg.hxx" +#include "DrawViewShell.hxx" + +#include <sfx2/request.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <svx/svxids.hrc> +#include <svx/zoomitem.hxx> +#include <svx/svxdlg.hxx> +#include <svx/dialogs.hrc> +#include <vcl/msgbox.hxx> +#include <svl/intitem.hxx> +#include <svl/whiter.hxx> +#include <svl/itempool.hxx> +#include <svl/aeitem.hxx> +#include <com/sun/star/presentation/FadeEffect.hpp> +#include <com/sun/star/drawing/XMasterPagesSupplier.hpp> +#include <com/sun/star/drawing/XDrawPages.hpp> +#include <vcl/svapp.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::presentation; + +namespace sd { namespace slidesorter { namespace controller { + +SlotManager::SlotManager (SlideSorter& rSlideSorter) + : mrSlideSorter(rSlideSorter), + maCommandQueue() +{ +} + + + + +SlotManager::~SlotManager (void) +{ +} + + + + +void SlotManager::FuTemporary (SfxRequest& rRequest) +{ + SdDrawDocument* pDocument = mrSlideSorter.GetModel().GetDocument(); + + SlideSorterViewShell* pShell + = dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell()); + if (pShell == NULL) + return; + + switch (rRequest.GetSlot()) + { + case SID_PRESENTATION: + case SID_REHEARSE_TIMINGS: + ShowSlideShow (rRequest); + pShell->Cancel(); + rRequest.Done(); + break; + + case SID_HIDE_SLIDE: + case SID_SHOW_SLIDE: + HideSlideFunction::Create(mrSlideSorter, rRequest); + break; + + case SID_PAGES_PER_ROW: + if (rRequest.GetArgs() != NULL) + { + SFX_REQUEST_ARG(rRequest, pPagesPerRow, SfxUInt16Item, + SID_PAGES_PER_ROW, FALSE); + if (pPagesPerRow != NULL) + { + sal_Int32 nColumnCount = pPagesPerRow->GetValue(); + // Force the given number of columns by setting the + // minimal and maximal number of columns to the same + // value. + mrSlideSorter.GetView().GetLayouter().SetColumnCount ( + nColumnCount, nColumnCount); + // Force a repaint and re-layout. + pShell->ArrangeGUIElements (); + // Rearrange the UI-elements controlled by the + // controller and force a rearrangement of the view. + mrSlideSorter.GetController().Rearrange(true); + } + } + rRequest.Done(); + break; + + case SID_SELECTALL: + mrSlideSorter.GetController().GetPageSelector().SelectAllPages(); + rRequest.Done(); + break; + + case SID_SLIDE_TRANSITIONS_PANEL: + { + // Make the slide transition panel visible (expand it) in the + // tool pane. + if (mrSlideSorter.GetViewShellBase() != NULL) + framework::FrameworkHelper::Instance(*mrSlideSorter.GetViewShellBase()) + ->RequestTaskPanel(sd::framework::FrameworkHelper::msSlideTransitionTaskPanelURL); + rRequest.Ignore (); + break; + } + + case SID_PRESENTATION_DLG: + FuSlideShowDlg::Create ( + pShell, + mrSlideSorter.GetView().GetWindow(), + &mrSlideSorter.GetView(), + pDocument, + rRequest); + break; + + case SID_CUSTOMSHOW_DLG: + FuCustomShowDlg::Create ( + pShell, + mrSlideSorter.GetView().GetWindow(), + &mrSlideSorter.GetView(), + pDocument, + rRequest); + break; + + case SID_EXPAND_PAGE: + FuExpandPage::Create ( + pShell, + mrSlideSorter.GetView().GetWindow(), + &mrSlideSorter.GetView(), + pDocument, + rRequest); + break; + + case SID_SUMMARY_PAGE: + FuSummaryPage::Create ( + pShell, + mrSlideSorter.GetView().GetWindow(), + &mrSlideSorter.GetView(), + pDocument, + rRequest); + break; + + case SID_INSERTPAGE: + case SID_INSERT_MASTER_PAGE: + InsertSlide(rRequest); + rRequest.Done(); + break; + + case SID_DELETE_PAGE: + case SID_DELETE_MASTER_PAGE: + case SID_DELETE: // we need SID_CUT to handle the delete key + // (DEL -> accelerator -> SID_CUT). + if (mrSlideSorter.GetModel().GetPageCount() > 1) + { + mrSlideSorter.GetController().GetSelectionManager()->DeleteSelectedPages(); + } + + rRequest.Done(); + break; + + case SID_RENAMEPAGE: + case SID_RENAME_MASTER_PAGE: + RenameSlide (); + rRequest.Done (); + break; + + case SID_ASSIGN_LAYOUT: + { + pShell->mpImpl->AssignLayout( rRequest, mrSlideSorter.GetModel().GetPageType() ); + rRequest.Done (); + } + break; + + default: + break; + } +} + + + + +void SlotManager::FuPermanent (SfxRequest& rRequest) +{ + ViewShell* pShell = mrSlideSorter.GetViewShell(); + if (pShell == NULL) + return; + + if(pShell->GetCurrentFunction().is()) + { + FunctionReference xEmpty; + if (pShell->GetOldFunction() == pShell->GetCurrentFunction()) + pShell->SetOldFunction(xEmpty); + + pShell->GetCurrentFunction()->Deactivate(); + pShell->SetCurrentFunction(xEmpty); + } + + switch(rRequest.GetSlot()) + { + case SID_OBJECT_SELECT: + pShell->SetCurrentFunction( SelectionFunction::Create(mrSlideSorter, rRequest) ); + rRequest.Done(); + break; + + default: + break; + } + + if(pShell->GetOldFunction().is()) + { + pShell->GetOldFunction()->Deactivate(); + FunctionReference xEmpty; + pShell->SetOldFunction(xEmpty); + } + + if(pShell->GetCurrentFunction().is()) + { + pShell->GetCurrentFunction()->Activate(); + pShell->SetOldFunction(pShell->GetCurrentFunction()); + } + + //! das ist nur bis das ENUM-Slots sind + // Invalidate( SID_OBJECT_SELECT ); +} + +void SlotManager::FuSupport (SfxRequest& rRequest) +{ + switch (rRequest.GetSlot()) + { + case SID_STYLE_FAMILY: + if (rRequest.GetArgs() != NULL) + { + SdDrawDocument* pDocument + = mrSlideSorter.GetModel().GetDocument(); + if (pDocument != NULL) + { + const SfxPoolItem& rItem ( + rRequest.GetArgs()->Get(SID_STYLE_FAMILY)); + pDocument->GetDocSh()->SetStyleFamily( + static_cast<const SfxUInt16Item&>(rItem).GetValue()); + } + } + break; + + case SID_PASTE: + { + SdTransferable* pTransferClip = SD_MOD()->pTransferClip; + if( pTransferClip ) + { + SfxObjectShell* pTransferDocShell = pTransferClip->GetDocShell(); + + DrawDocShell* pDocShell = dynamic_cast<DrawDocShell*>(pTransferDocShell); + if (pDocShell && pDocShell->GetDoc()->GetPageCount() > 1) + { + mrSlideSorter.GetController().GetClipboard().HandleSlotCall(rRequest); + break; + } + } + ViewShellBase* pBase = mrSlideSorter.GetViewShellBase(); + if (pBase != NULL) + { + ::boost::shared_ptr<DrawViewShell> pDrawViewShell ( + ::boost::dynamic_pointer_cast<DrawViewShell>(pBase->GetMainViewShell())); + if (pDrawViewShell.get() != NULL) + pDrawViewShell->FuSupport(rRequest); + } + } + break; + + case SID_CUT: + case SID_COPY: + case SID_DELETE: + mrSlideSorter.GetController().GetClipboard().HandleSlotCall(rRequest); + break; + + case SID_DRAWINGMODE: + case SID_NOTESMODE: + case SID_HANDOUTMODE: + case SID_DIAMODE: + case SID_OUTLINEMODE: + { + ViewShellBase* pBase = mrSlideSorter.GetViewShellBase(); + if (pBase != NULL) + { + framework::FrameworkHelper::Instance(*pBase)->HandleModeChangeSlot( + rRequest.GetSlot(), rRequest); + rRequest.Done(); + } + break; + } + + case SID_UNDO : + { + SlideSorterViewShell* pViewShell + = dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell()); + if (pViewShell != NULL) + pViewShell->ImpSidUndo (FALSE, rRequest); + break; + } + + case SID_REDO : + { + SlideSorterViewShell* pViewShell + = dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell()); + if (pViewShell != NULL) + pViewShell->ImpSidRedo (FALSE, rRequest); + break; + } + + default: + break; + } +} + + + + +void SlotManager::ExecCtrl (SfxRequest& rRequest) +{ + ViewShell* pViewShell = mrSlideSorter.GetViewShell(); + USHORT nSlot = rRequest.GetSlot(); + switch (nSlot) + { + case SID_RELOAD: + { + // Undo-Manager leeren + mrSlideSorter.GetModel().GetDocument()->GetDocSh()->ClearUndoBuffer(); + + // Normale Weiterleitung an ViewFrame zur Ausfuehrung + if (pViewShell != NULL) + pViewShell->GetViewFrame()->ExecuteSlot(rRequest); + + // Muss sofort beendet werden + return; + } + + case SID_OUTPUT_QUALITY_COLOR: + case SID_OUTPUT_QUALITY_GRAYSCALE: + case SID_OUTPUT_QUALITY_BLACKWHITE: + case SID_OUTPUT_QUALITY_CONTRAST: + { + // flush page cache + if (pViewShell != NULL) + pViewShell->ExecReq (rRequest); + break; + } + + case SID_MAIL_SCROLLBODY_PAGEDOWN: + { + if (pViewShell != NULL) + pViewShell->ExecReq (rRequest); + break; + } + + case SID_OPT_LOCALE_CHANGED: + { + mrSlideSorter.GetController().UpdateAllPages(); + if (pViewShell != NULL) + pViewShell->UpdatePreview (pViewShell->GetActualPage()); + rRequest.Done(); + break; + } + + case SID_SEARCH_DLG: + // We have to handle the SID_SEARCH_DLG slot explicitly because + // in some cases (when the slide sorter is displayed in the + // center pane) we want to disable the search dialog. Therefore + // we have to handle the execution of that slot as well. + // We try to do that by forwarding the request to the view frame + // of the view shell. + if (pViewShell != NULL) + pViewShell->GetViewFrame()->ExecuteSlot(rRequest); + break; + + default: + break; + } +} + + + + +void SlotManager::GetAttrState (SfxItemSet& rSet) +{ + // Iteratate over all items. + SfxWhichIter aIter (rSet); + USHORT nWhich = aIter.FirstWhich(); + while (nWhich) + { + USHORT nSlotId (nWhich); + if (SfxItemPool::IsWhich(nWhich) && mrSlideSorter.GetViewShell()!=NULL) + nSlotId = mrSlideSorter.GetViewShell()->GetPool().GetSlotId(nWhich); + switch (nSlotId) + { + case SID_PAGES_PER_ROW: + rSet.Put ( + SfxUInt16Item ( + nSlotId, + (USHORT)mrSlideSorter.GetView().GetLayouter().GetColumnCount() + ) + ); + break; + } + nWhich = aIter.NextWhich(); + } +} + +void SlotManager::GetMenuState ( SfxItemSet& rSet) +{ + EditMode eEditMode = mrSlideSorter.GetModel().GetEditMode(); + ViewShell* pShell = mrSlideSorter.GetViewShell(); + DrawDocShell* pDocShell = mrSlideSorter.GetModel().GetDocument()->GetDocSh(); + + if (pShell!=NULL && pShell->GetCurrentFunction().is()) + { + USHORT nSId = pShell->GetCurrentFunction()->GetSlotID(); + + rSet.Put( SfxBoolItem( nSId, TRUE ) ); + } + rSet.Put( SfxBoolItem( SID_DRAWINGMODE, FALSE ) ); + rSet.Put( SfxBoolItem( SID_DIAMODE, TRUE ) ); + rSet.Put( SfxBoolItem( SID_OUTLINEMODE, FALSE ) ); + rSet.Put( SfxBoolItem( SID_NOTESMODE, FALSE ) ); + rSet.Put( SfxBoolItem( SID_HANDOUTMODE, FALSE ) ); + + // Vorlagenkatalog darf nicht aufgerufen werden + rSet.DisableItem(SID_STYLE_CATALOG); + + if (pShell!=NULL && pShell->IsMainViewShell()) + { + rSet.DisableItem(SID_SPELL_DIALOG); + rSet.DisableItem(SID_SEARCH_DLG); + } + + if (SFX_ITEM_AVAILABLE == rSet.GetItemState(SID_EXPAND_PAGE)) + { + bool bDisable = true; + if (eEditMode == EM_PAGE) + { + // At least one of the selected pages has to contain an outline + // presentation objects in order to enable the expand page menu + // entry. + model::PageEnumeration aSelectedPages ( + model::PageEnumerationProvider::CreateSelectedPagesEnumeration( + mrSlideSorter.GetModel())); + while (aSelectedPages.HasMoreElements()) + { + SdPage* pPage = aSelectedPages.GetNextElement()->GetPage(); + SdrObject* pObj = pPage->GetPresObj(PRESOBJ_OUTLINE); + if (pObj!=NULL && !pObj->IsEmptyPresObj()) + bDisable = false; + } + } + + if (bDisable) + rSet.DisableItem (SID_EXPAND_PAGE); + } + + if (SFX_ITEM_AVAILABLE == rSet.GetItemState(SID_SUMMARY_PAGE)) + { + bool bDisable = true; + if (eEditMode == EM_PAGE) + { + // At least one of the selected pages has to contain a title + // presentation objects in order to enable the summary page menu + // entry. + model::PageEnumeration aSelectedPages ( + model::PageEnumerationProvider::CreateSelectedPagesEnumeration( + mrSlideSorter.GetModel())); + while (aSelectedPages.HasMoreElements()) + { + SdPage* pPage = aSelectedPages.GetNextElement()->GetPage(); + SdrObject* pObj = pPage->GetPresObj(PRESOBJ_TITLE); + + if (pObj!=NULL && !pObj->IsEmptyPresObj()) + bDisable = false; + } + } + if (bDisable) + rSet.DisableItem (SID_SUMMARY_PAGE); + } + + // Starten der Praesentation moeglich? + if( SFX_ITEM_AVAILABLE == rSet.GetItemState( SID_PRESENTATION ) || + SFX_ITEM_AVAILABLE == rSet.GetItemState( SID_REHEARSE_TIMINGS ) ) + { + BOOL bDisable = TRUE; + model::PageEnumeration aAllPages ( + model::PageEnumerationProvider::CreateAllPagesEnumeration(mrSlideSorter.GetModel())); + while (aAllPages.HasMoreElements()) + { + SdPage* pPage = aAllPages.GetNextElement()->GetPage(); + + if( !pPage->IsExcluded() ) + bDisable = FALSE; + } + if( bDisable || pDocShell->IsPreview()) + { + rSet.DisableItem( SID_PRESENTATION ); + rSet.DisableItem( SID_REHEARSE_TIMINGS ); + } + } + + + // Disable the rename slots when there are no or more than one slides/master + // pages selected. + if (rSet.GetItemState(SID_RENAMEPAGE) == SFX_ITEM_AVAILABLE + || rSet.GetItemState(SID_RENAME_MASTER_PAGE) == SFX_ITEM_AVAILABLE) + { + if (mrSlideSorter.GetController().GetPageSelector().GetSelectedPageCount() != 1) + { + rSet.DisableItem(SID_RENAMEPAGE); + rSet.DisableItem(SID_RENAME_MASTER_PAGE); + } + } + + if (rSet.GetItemState(SID_HIDE_SLIDE) == SFX_ITEM_AVAILABLE + || rSet.GetItemState(SID_SHOW_SLIDE) == SFX_ITEM_AVAILABLE) + { + model::PageEnumeration aSelectedPages ( + model::PageEnumerationProvider::CreateSelectedPagesEnumeration( + mrSlideSorter.GetModel())); + HideSlideFunction::ExclusionState eState ( + HideSlideFunction::GetExclusionState(aSelectedPages)); + switch (eState) + { + case HideSlideFunction::MIXED: + // Show both entries. + break; + + case HideSlideFunction::EXCLUDED: + rSet.DisableItem(SID_HIDE_SLIDE); + break; + + case HideSlideFunction::INCLUDED: + rSet.DisableItem(SID_SHOW_SLIDE); + break; + + case HideSlideFunction::UNDEFINED: + rSet.DisableItem(SID_HIDE_SLIDE); + rSet.DisableItem(SID_SHOW_SLIDE); + break; + } + } + + PageKind ePageKind = mrSlideSorter.GetModel().GetPageType(); + if( (eEditMode == EM_MASTERPAGE) && (ePageKind != PK_HANDOUT ) ) + { + rSet.DisableItem(SID_ASSIGN_LAYOUT); + } + + if( (eEditMode == EM_MASTERPAGE) || (ePageKind==PK_NOTES) ) + { + rSet.DisableItem(SID_INSERTPAGE); + } +} + + + + +void SlotManager::GetClipboardState ( SfxItemSet& rSet) +{ + SdTransferable* pTransferClip = SD_MOD()->pTransferClip; + + if (rSet.GetItemState(SID_PASTE) == SFX_ITEM_AVAILABLE + || rSet.GetItemState(SID_PASTE_SPECIAL) == SFX_ITEM_AVAILABLE) + { + // Keine eigenen Clipboard-Daten? + if ( !pTransferClip || !pTransferClip->GetDocShell() ) + { + rSet.DisableItem(SID_PASTE); + rSet.DisableItem(SID_PASTE_SPECIAL); + } + else + { + SfxObjectShell* pTransferDocShell = pTransferClip->GetDocShell(); + + if( !pTransferDocShell || ( (DrawDocShell*) pTransferDocShell)->GetDoc()->GetPageCount() <= 1 ) + { + bool bIsPastingSupported (false); + + // No or just one page. Check if there is anything that can be + // pasted via a DrawViewShell. + ViewShellBase* pBase = mrSlideSorter.GetViewShellBase(); + if (pBase != NULL) + { + ::boost::shared_ptr<DrawViewShell> pDrawViewShell ( + ::boost::dynamic_pointer_cast<DrawViewShell>(pBase->GetMainViewShell())); + if (pDrawViewShell.get() != NULL) + { + TransferableDataHelper aDataHelper ( + TransferableDataHelper::CreateFromSystemClipboard( + pDrawViewShell->GetActiveWindow())); + if (aDataHelper.GetFormatCount() > 0) + bIsPastingSupported = true; + } + } + + if ( ! bIsPastingSupported) + { + rSet.DisableItem(SID_PASTE); + rSet.DisableItem(SID_PASTE_SPECIAL); + } + } + } + } + + // Cut, copy and paste of master pages is not yet implemented properly + if (rSet.GetItemState(SID_COPY) == SFX_ITEM_AVAILABLE + || rSet.GetItemState(SID_PASTE) == SFX_ITEM_AVAILABLE + || rSet.GetItemState(SID_PASTE_SPECIAL) == SFX_ITEM_AVAILABLE + || rSet.GetItemState(SID_CUT) == SFX_ITEM_AVAILABLE) + { + if (mrSlideSorter.GetModel().GetEditMode() == EM_MASTERPAGE) + { + if (rSet.GetItemState(SID_CUT) == SFX_ITEM_AVAILABLE) + rSet.DisableItem(SID_CUT); + if (rSet.GetItemState(SID_COPY) == SFX_ITEM_AVAILABLE) + rSet.DisableItem(SID_COPY); + if (rSet.GetItemState(SID_PASTE) == SFX_ITEM_AVAILABLE) + rSet.DisableItem(SID_PASTE); + if (rSet.GetItemState(SID_PASTE_SPECIAL) == SFX_ITEM_AVAILABLE) + rSet.DisableItem(SID_PASTE_SPECIAL); + } + } + + // Cut, copy, and delete page are disabled when there is no selection. + if (rSet.GetItemState(SID_CUT) == SFX_ITEM_AVAILABLE + || rSet.GetItemState(SID_COPY) == SFX_ITEM_AVAILABLE + || rSet.GetItemState(SID_DELETE) == SFX_ITEM_AVAILABLE + || rSet.GetItemState(SID_DELETE_PAGE) == SFX_ITEM_AVAILABLE + || rSet.GetItemState(SID_DELETE_MASTER_PAGE) == SFX_ITEM_AVAILABLE) + { + model::PageEnumeration aSelectedPages ( + model::PageEnumerationProvider::CreateSelectedPagesEnumeration( + mrSlideSorter.GetModel())); + + // For copy to work we have to have at least one selected page. + if ( ! aSelectedPages.HasMoreElements()) + rSet.DisableItem(SID_COPY); + + bool bDisable = false; + // The operations that lead to the deletion of a page are valid if + // a) there is at least one selected page + // b) deleting the selected pages leaves at least one page in the + // document + // c) selected master pages must not be used by slides. + + // Test a). + if ( ! aSelectedPages.HasMoreElements()) + bDisable = true; + // Test b): Count the number of selected pages. It has to be less + // than the number of all pages. + else if (mrSlideSorter.GetController().GetPageSelector().GetSelectedPageCount() + >= mrSlideSorter.GetController().GetPageSelector().GetPageCount()) + bDisable = true; + // Test c): Iterate over the selected pages and look for a master + // page that is used by at least one page. + else while (aSelectedPages.HasMoreElements()) + { + SdPage* pPage = aSelectedPages.GetNextElement()->GetPage(); + int nUseCount (mrSlideSorter.GetModel().GetDocument() + ->GetMasterPageUserCount(pPage)); + if (nUseCount > 0) + { + bDisable = true; + break; + } + } + + if (bDisable) + { + rSet.DisableItem(SID_CUT); + rSet.DisableItem(SID_DELETE_PAGE); + rSet.DisableItem(SID_DELETE_MASTER_PAGE); + } + } +} + + + + +void SlotManager::GetStatusBarState (SfxItemSet& rSet) +{ + // Seitenanzeige und Layout + /* + if( SFX_ITEM_AVAILABLE == rSet.GetItemState( SID_STATUS_PAGE ) || + SFX_ITEM_AVAILABLE == rSet.GetItemState( SID_STATUS_LAYOUT ) ) + */ + SdPage* pPage = NULL; + SdPage* pFirstPage = NULL; + USHORT nFirstPage; + USHORT nSelectedPages = (USHORT)mrSlideSorter.GetController().GetPageSelector().GetSelectedPageCount(); + String aPageStr; + String aLayoutStr; + + if (nSelectedPages > 0) + aPageStr = String(SdResId(STR_SD_PAGE)); + + if (nSelectedPages == 1) + { + model::PageEnumeration aSelectedPages ( + model::PageEnumerationProvider::CreateSelectedPagesEnumeration( + mrSlideSorter.GetModel())); + pPage = aSelectedPages.GetNextElement()->GetPage(); + nFirstPage = pPage->GetPageNum()/2; + pFirstPage = pPage; + + aPageStr += sal_Unicode(' '); + aPageStr += String::CreateFromInt32( nFirstPage + 1 ); + aPageStr.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " / " )); + aPageStr += String::CreateFromInt32( + mrSlideSorter.GetModel().GetPageCount()); + + aLayoutStr = pFirstPage->GetLayoutName(); + aLayoutStr.Erase( aLayoutStr.SearchAscii( SD_LT_SEPARATOR ) ); + } + + rSet.Put( SfxStringItem( SID_STATUS_PAGE, aPageStr ) ); + rSet.Put( SfxStringItem( SID_STATUS_LAYOUT, aLayoutStr ) ); + + if( SFX_ITEM_AVAILABLE == rSet.GetItemState( SID_ATTR_ZOOMSLIDER ) ) + { + rSet.Put( SfxVoidItem( SID_ATTR_ZOOMSLIDER ) ); + } +} + +void SlotManager::ShowSlideShow( SfxRequest& rReq) +{ + Reference< XPresentation2 > xPresentation( mrSlideSorter.GetModel().GetDocument()->getPresentation() ); + if( xPresentation.is() ) + { + if( ( SID_REHEARSE_TIMINGS != rReq.GetSlot() ) ) + xPresentation->start(); + else + xPresentation->rehearseTimings(); + } +} + +void SlotManager::RenameSlide (void) +{ + PageKind ePageKind = mrSlideSorter.GetModel().GetPageType(); + View* pDrView = &mrSlideSorter.GetView(); + + if (ePageKind==PK_STANDARD || ePageKind==PK_NOTES) + { + if ( pDrView->IsTextEdit() ) + { + pDrView->SdrEndTextEdit(); + } + + SdPage* pSelectedPage = NULL; + model::PageEnumeration aSelectedPages ( + model::PageEnumerationProvider::CreateSelectedPagesEnumeration( + mrSlideSorter.GetModel())); + if (aSelectedPages.HasMoreElements()) + pSelectedPage = aSelectedPages.GetNextElement()->GetPage(); + if (pSelectedPage != NULL) + { + String aTitle( SdResId( STR_TITLE_RENAMESLIDE ) ); + String aDescr( SdResId( STR_DESC_RENAMESLIDE ) ); + String aPageName = pSelectedPage->GetName(); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "Dialogdiet fail!"); + AbstractSvxNameDialog* aNameDlg = pFact->CreateSvxNameDialog( + mrSlideSorter.GetActiveWindow(), + aPageName, aDescr); + DBG_ASSERT(aNameDlg, "Dialogdiet fail!"); + aNameDlg->SetText( aTitle ); + aNameDlg->SetCheckNameHdl( LINK( this, SlotManager, RenameSlideHdl ), true ); + aNameDlg->SetEditHelpId( HID_SD_NAMEDIALOG_PAGE ); + + if( aNameDlg->Execute() == RET_OK ) + { + String aNewName; + aNameDlg->GetName( aNewName ); + if( ! aNewName.Equals( aPageName ) ) + { +#ifdef DBG_UTIL + bool bResult = +#endif + RenameSlideFromDrawViewShell( + pSelectedPage->GetPageNum()/2, aNewName ); + DBG_ASSERT( bResult, "Couldn't rename slide" ); + } + } + delete aNameDlg; + + // Tell the slide sorter about the name change (necessary for + // accessibility.) + mrSlideSorter.GetController().PageNameHasChanged( + (pSelectedPage->GetPageNum()-1)/2, aPageName); + } + } +} + +IMPL_LINK(SlotManager, RenameSlideHdl, AbstractSvxNameDialog*, pDialog) +{ + if( ! pDialog ) + return 0; + + String aNewName; + pDialog->GetName( aNewName ); + + model::SharedPageDescriptor pDescriptor ( + mrSlideSorter.GetController().GetCurrentSlideManager()->GetCurrentSlide()); + SdPage* pCurrentPage = NULL; + if (pDescriptor.get() != NULL) + pCurrentPage = pDescriptor->GetPage(); + + return ( (pCurrentPage!=NULL && aNewName.Equals( pCurrentPage->GetName() )) + || (mrSlideSorter.GetViewShell() + && mrSlideSorter.GetViewShell()->GetDocSh()->IsNewPageNameValid( aNewName ) )); +} + +bool SlotManager::RenameSlideFromDrawViewShell( USHORT nPageId, const String & rName ) +{ + BOOL bOutDummy; + SdDrawDocument* pDocument = mrSlideSorter.GetModel().GetDocument(); + if( pDocument->GetPageByName( rName, bOutDummy ) != SDRPAGE_NOTFOUND ) + return false; + + SdPage* pPageToRename = NULL; + PageKind ePageKind = mrSlideSorter.GetModel().GetPageType(); + + SfxUndoManager* pManager = pDocument->GetDocSh()->GetUndoManager(); + + if( mrSlideSorter.GetModel().GetEditMode() == EM_PAGE ) + { + model::SharedPageDescriptor pDescriptor ( + mrSlideSorter.GetController().GetCurrentSlideManager()->GetCurrentSlide()); + if (pDescriptor.get() != NULL) + pPageToRename = pDescriptor->GetPage(); + + if (pPageToRename != NULL) + { + // Undo + SdPage* pUndoPage = pPageToRename; + SdrLayerAdmin & rLayerAdmin = pDocument->GetLayerAdmin(); + BYTE nBackground = rLayerAdmin.GetLayerID( String( SdResId( STR_LAYER_BCKGRND )), FALSE ); + BYTE nBgObj = rLayerAdmin.GetLayerID( String( SdResId( STR_LAYER_BCKGRNDOBJ )), FALSE ); + SetOfByte aVisibleLayers = pPageToRename->TRG_GetMasterPageVisibleLayers(); + + // (#67720#) + ModifyPageUndoAction* pAction = new ModifyPageUndoAction( + pManager, pDocument, pUndoPage, rName, pUndoPage->GetAutoLayout(), + aVisibleLayers.IsSet( nBackground ), + aVisibleLayers.IsSet( nBgObj )); + pManager->AddUndoAction( pAction ); + + // rename + pPageToRename->SetName( rName ); + + if( ePageKind == PK_STANDARD ) + { + // also rename notes-page + SdPage* pNotesPage = pDocument->GetSdPage( nPageId, PK_NOTES ); + if (pNotesPage != NULL) + pNotesPage->SetName (rName); + } + } + } + else + { + // rename MasterPage -> rename LayoutTemplate + pPageToRename = pDocument->GetMasterSdPage( nPageId, ePageKind ); + if (pPageToRename != NULL) + { + const String aOldLayoutName( pPageToRename->GetLayoutName() ); + pManager->AddUndoAction( new RenameLayoutTemplateUndoAction( pDocument, aOldLayoutName, rName ) ); + pDocument->RenameLayoutTemplate( aOldLayoutName, rName ); + } + } + + bool bSuccess = pPageToRename!=NULL && ( FALSE != rName.Equals( pPageToRename->GetName())); + + if( bSuccess ) + { + // user edited page names may be changed by the page so update control + // aTabControl.SetPageText( nPageId, rName ); + + // set document to modified state + pDocument->SetChanged( TRUE ); + + // inform navigator about change + SfxBoolItem aItem( SID_NAVIGATOR_INIT, TRUE ); + if (mrSlideSorter.GetViewShell() != NULL) + mrSlideSorter.GetViewShell()->GetDispatcher()->Execute( + SID_NAVIGATOR_INIT, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD, &aItem, 0L ); + } + + return bSuccess; +} + + + + +/** Insert a slide. The insertion position depends on a) the selection and + b) the mouse position when there is no selection. + + When there is a selection then insertion takes place after the last + slide of the selection. For this to work all but the last selected + slide are deselected first. + + Otherwise, when there is no selection but the insertion marker is visible + the slide is inserted at that position. The slide before that marker is + selected first. + + When both the selection and the insertion marker are not visible--can + that happen?--the new slide is inserted after the last slide. +*/ +void SlotManager::InsertSlide (SfxRequest& rRequest) +{ + PageSelector& rSelector (mrSlideSorter.GetController().GetPageSelector()); + // The fallback insertion position is after the last slide. + sal_Int32 nInsertionIndex (rSelector.GetPageCount() - 1); + if (rSelector.GetSelectedPageCount() > 0) + { + // Deselect all but the last selected slide. + bool bLastSelectedSlideSeen (false); + for (int nIndex=rSelector.GetPageCount()-1; nIndex>=0; --nIndex) + { + if (rSelector.IsPageSelected(nIndex)) + { + if (bLastSelectedSlideSeen) + rSelector.DeselectPage (nIndex); + else + { + nInsertionIndex = nIndex; + bLastSelectedSlideSeen = true; + } + } + } + } + + // No selection. Is there an insertion indicator? + else if (mrSlideSorter.GetView().GetOverlay() + .GetInsertionIndicatorOverlay().isVisible()) + { + // Select the page before the insertion indicator. + nInsertionIndex = mrSlideSorter.GetView().GetOverlay() + .GetInsertionIndicatorOverlay().GetInsertionPageIndex(); + nInsertionIndex --; + rSelector.SelectPage (nInsertionIndex); + } + + // Is there a stored insertion position? + else if (mrSlideSorter.GetController().GetSelectionManager()->GetInsertionPosition() >= 0) + { + nInsertionIndex + = mrSlideSorter.GetController().GetSelectionManager()->GetInsertionPosition() - 1; + rSelector.SelectPage(nInsertionIndex); + } + + // Select the last page when there is at least one page. + else if (rSelector.GetPageCount() > 0) + { + nInsertionIndex = rSelector.GetPageCount() - 1; + rSelector.SelectPage (nInsertionIndex); + } + + // Hope for the best that CreateOrDuplicatePage() can cope with an empty + // selection. + else + { + nInsertionIndex = -1; + } + + USHORT nPageCount ((USHORT)mrSlideSorter.GetModel().GetPageCount()); + + rSelector.DisableBroadcasting(); + // In order for SlideSorterController::GetActualPage() to select the + // selected page as current page we have to turn off the focus + // temporarily. + { + FocusManager::FocusHider aTemporaryFocusHider ( + mrSlideSorter.GetController().GetFocusManager()); + + SdPage* pPreviousPage = NULL; + if (nInsertionIndex >= 0) + pPreviousPage = mrSlideSorter.GetModel() + .GetPageDescriptor(nInsertionIndex)->GetPage(); + + if (mrSlideSorter.GetModel().GetEditMode() == EM_PAGE) + { + SlideSorterViewShell* pShell = dynamic_cast<SlideSorterViewShell*>( + mrSlideSorter.GetViewShell()); + if (pShell != NULL) + { + pShell->CreateOrDuplicatePage ( + rRequest, + mrSlideSorter.GetModel().GetPageType(), + pPreviousPage); + } + } + else + { + // Use the API to create a new page. + SdDrawDocument* pDocument = mrSlideSorter.GetModel().GetDocument(); + Reference<drawing::XMasterPagesSupplier> xMasterPagesSupplier ( + pDocument->getUnoModel(), UNO_QUERY); + if (xMasterPagesSupplier.is()) + { + Reference<drawing::XDrawPages> xMasterPages ( + xMasterPagesSupplier->getMasterPages()); + if (xMasterPages.is()) + { + xMasterPages->insertNewByIndex (nInsertionIndex+1); + + // Create shapes for the default layout. + SdPage* pMasterPage = pDocument->GetMasterSdPage( + (USHORT)(nInsertionIndex+1), PK_STANDARD); + pMasterPage->CreateTitleAndLayout (TRUE,TRUE); + } + } + } + } + + // When a new page has been inserted then select it and make it the + // current page. + mrSlideSorter.GetView().LockRedraw(TRUE); + if (mrSlideSorter.GetModel().GetPageCount() > nPageCount) + { + nInsertionIndex++; + model::SharedPageDescriptor pDescriptor = mrSlideSorter.GetModel().GetPageDescriptor(nInsertionIndex); + if (pDescriptor.get() != NULL) + mrSlideSorter.GetController().GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor); + } + rSelector.EnableBroadcasting(); + mrSlideSorter.GetView().LockRedraw(FALSE); +} + +void SlotManager::ExecuteCommandAsynchronously (::std::auto_ptr<Command> pCommand) +{ + // Ownership of command is (implicitely) transferred to the queue. + maCommandQueue.push(pCommand.get()); + pCommand.release(); + Application::PostUserEvent(LINK(this,SlotManager,UserEventCallback)); +} + +IMPL_LINK(SlotManager, UserEventCallback, void*, EMPTYARG) +{ + if ( ! maCommandQueue.empty()) + { + Command* pCommand = maCommandQueue.front(); + maCommandQueue.pop(); + + if (pCommand != NULL) + { + // The queue ownes the command that has just been removed from + // it. Therefore it is deleted after it has been executed. + (*pCommand)(); + delete pCommand; + } + } + + return 1; +} + +} } } // end of namespace ::sd::slidesorter::controller + diff --git a/sd/source/ui/slidesorter/controller/SlsTransferable.cxx b/sd/source/ui/slidesorter/controller/SlsTransferable.cxx new file mode 100644 index 000000000000..20ddc937469c --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlsTransferable.cxx @@ -0,0 +1,92 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + +#include "SlsTransferable.hxx" + +#include "SlideSorterViewShell.hxx" +#include "View.hxx" + +namespace sd { namespace slidesorter { namespace controller { + +Transferable::Transferable ( + SdDrawDocument* pSrcDoc, + ::sd::View* pWorkView, + BOOL bInitOnGetData, + SlideSorterViewShell* pViewShell) + : SdTransferable (pSrcDoc, pWorkView, bInitOnGetData), + mpViewShell(pViewShell) +{ + if (mpViewShell != NULL) + StartListening(*mpViewShell); +} + + + +Transferable::~Transferable (void) +{ + if (mpViewShell != NULL) + EndListening(*mpViewShell); +} + + + + +void Transferable::DragFinished (sal_Int8 nDropAction) +{ + if (mpViewShell != NULL) + mpViewShell->DragFinished(nDropAction); +} + + + + +void Transferable::Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint) +{ + if (rHint.ISA(SfxSimpleHint) && mpViewShell!=NULL) + { + SfxSimpleHint& rSimpleHint (*PTR_CAST(SfxSimpleHint, &rHint)); + if (rSimpleHint.GetId() == SFX_HINT_DYING) + { + // This hint may come either from the ViewShell or from the + // document (registered by SdTransferable). We do not know + // which but both are sufficient to disconnect from the + // ViewShell. + EndListening(*mpViewShell); + mpViewShell = NULL; + } + } + + SdTransferable::Notify(rBroadcaster, rHint); +} + + + + +} } } // end of namespace ::sd::slidesorter::controller diff --git a/sd/source/ui/slidesorter/controller/SlsTransferable.hxx b/sd/source/ui/slidesorter/controller/SlsTransferable.hxx new file mode 100644 index 000000000000..f527fd4768b9 --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlsTransferable.hxx @@ -0,0 +1,70 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef SD_SLIDESORTER_TRANSFERABLE_HXX +#define SD_SLIDESORTER_TRANSFERABLE_HXX + +#include "sdxfer.hxx" + +class SdDrawDocument; +namespace sd +{ + class pWorkView; + namespace slidesorter + { + class SlideSorterViewShell; + } +} + +namespace sd { namespace slidesorter { namespace controller { + +/** This class exists to have DragFinished call the correct object: the + SlideSorterViewShell instead of the old SlideView. +*/ +class Transferable + : public SdTransferable +{ +public: + Transferable ( + SdDrawDocument* pSrcDoc, + ::sd::View* pWorkView, + BOOL bInitOnGetData, + SlideSorterViewShell* pViewShell); + + virtual ~Transferable (void); + + virtual void DragFinished (sal_Int8 nDropAction); + +private: + SlideSorterViewShell* mpViewShell; + + virtual void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint); +}; + +} } } // end of namespace ::sd::slidesorter::controller + +#endif diff --git a/sd/source/ui/slidesorter/controller/makefile.mk b/sd/source/ui/slidesorter/controller/makefile.mk new file mode 100644 index 000000000000..8ab63ddf776c --- /dev/null +++ b/sd/source/ui/slidesorter/controller/makefile.mk @@ -0,0 +1,71 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +PRJ=..$/..$/..$/.. + +PROJECTPCH=sd +PROJECTPCHSOURCE=$(PRJ)$/util$/sd +PRJNAME=sd +TARGET=slscontroller +ENABLE_EXCEPTIONS=TRUE +AUTOSEG=true +PRJINC=..$/.. + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/SlideSorterController.obj \ + $(SLO)$/SlsAnimator.obj \ + $(SLO)$/SlsClipboard.obj \ + $(SLO)$/SlsCurrentSlideManager.obj \ + $(SLO)$/SlsFocusManager.obj \ + $(SLO)$/SlsListener.obj \ + $(SLO)$/SlsPageObjectFactory.obj \ + $(SLO)$/SlsPageSelector.obj \ + $(SLO)$/SlsProperties.obj \ + $(SLO)$/SlsScrollBarManager.obj \ + $(SLO)$/SlsSelectionCommand.obj \ + $(SLO)$/SlsSelectionManager.obj \ + $(SLO)$/SlsSlotManager.obj \ + $(SLO)$/SlsTransferable.obj \ + \ + $(SLO)$/SlsHideSlideFunction.obj \ + $(SLO)$/SlsSelectionFunction.obj \ + $(SLO)$/SlsSlideFunction.obj + +EXCEPTIONSFILES= \ + $(SLO)$/SlideSorterController.obj + +# --- Tagets ------------------------------------------------------- + +.INCLUDE : target.mk + |