summaryrefslogtreecommitdiff
path: root/sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx')
-rw-r--r--[-rwxr-xr-x]sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx1989
1 files changed, 1348 insertions, 641 deletions
diff --git a/sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx b/sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx
index c1d742ce7158..1d4d075fc3ce 100755..100644
--- a/sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx
+++ b/sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx
@@ -31,38 +31,49 @@
#include "SlideSorter.hxx"
#include "SlideSorterViewShell.hxx"
+#include "SlsDragAndDropContext.hxx"
+#include "controller/SlsTransferable.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/SlsInsertionIndicatorHandler.hxx"
#include "controller/SlsSelectionManager.hxx"
#include "controller/SlsProperties.hxx"
+#include "controller/SlsProperties.hxx"
+#include "controller/SlsSlotManager.hxx"
+#include "controller/SlsVisibleAreaManager.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 "view/SlsPageObjectLayouter.hxx"
+#include "view/SlsButtonBar.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 "DrawDocShell.hxx"
+#include "sdxfer.hxx"
#include "ViewShell.hxx"
#include "ViewShellBase.hxx"
#include "FrameView.hxx"
#include "app.hrc"
#include "sdresid.hxx"
#include "strings.hrc"
+#include <vcl/sound.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/dispatch.hxx>
+#include <svx/svdpagv.hxx>
+#include <vcl/msgbox.hxx>
+#include <svx/svxids.hrc>
+#include <boost/bind.hpp>
+#include <boost/optional.hpp>
namespace {
static const sal_uInt32 SINGLE_CLICK (0x00000001);
@@ -73,109 +84,304 @@ 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);
+static const sal_uInt32 MOUSE_DRAG (0x00000800);
// 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 OVER_BUTTON_AREA (0x00080000);
+static const sal_uInt32 OVER_BUTTON (0x00100000);
+static const sal_uInt32 SHIFT_MODIFIER (0x00200000);
+static const sal_uInt32 CONTROL_MODIFIER (0x00400000);
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);
+// Masks
+static const sal_uInt32 MODIFIER_MASK (SHIFT_MODIFIER | CONTROL_MODIFIER);
+static const sal_uInt32 BUTTON_MASK (LEFT_BUTTON | RIGHT_BUTTON | MIDDLE_BUTTON);
} // end of anonymous namespace
+
+// 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
+
namespace sd { namespace slidesorter { namespace controller {
-class SelectionFunction::SubstitutionHandler
+//===== SelectionFunction::EventDescriptor ====================================
+
+class SelectionFunction::EventDescriptor
{
public:
- SubstitutionHandler (SlideSorter& rSlideSorter);
- ~SubstitutionHandler (void);
+ Point maMousePosition;
+ Point maMouseModelPosition;
+ model::SharedPageDescriptor mpHitDescriptor;
+ SdrPage* mpHitPage;
+ sal_uInt32 mnEventCode;
+ bool mbIsOverButton;
+ InsertionIndicatorHandler::Mode meDragMode;
+ bool mbMakeSelectionVisible;
+ bool mbIsLeaving;
- /** Create a substitution display of the currently selected pages and
- use the given position as the anchor point.
+ EventDescriptor (
+ sal_uInt32 nEventType,
+ const MouseEvent& rEvent,
+ SlideSorter& rSlideSorter);
+ EventDescriptor (
+ sal_uInt32 nEventType,
+ const AcceptDropEvent& rEvent,
+ const sal_Int8 nDragAction,
+ SlideSorter& rSlideSorter);
+ EventDescriptor (
+ const KeyEvent& rEvent,
+ SlideSorter& rSlideSorter);
+
+ void SetDragMode (const InsertionIndicatorHandler::Mode eMode);
+
+private:
+ /** Compute a numerical code that describes a mouse event and that can
+ be used for fast look up of the appropriate reaction.
*/
- void Start (const Point& rMouseModelPosition);
+ sal_uInt32 EncodeMouseEvent (const MouseEvent& rEvent) const;
- /** 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.
+ /** Compute a numerical code that describes a key event and that can
+ be used for fast look up of the appropriate reaction.
*/
- void UpdatePosition (const Point& rMouseModelPosition);
+ sal_uInt32 EncodeKeyEvent (const KeyEvent& rEvent) const;
- /** Move the substitution display of the currently selected pages.
+ /** Compute a numerical code that describes the current state like
+ whether the selection rectangle is visible or whether the page under
+ the mouse or the one that has the focus is selected.
*/
- void Process (void);
+ sal_uInt32 EncodeState (void) const;
+};
- void End (void);
- bool HasBeenMoved (void) const;
-private:
+
+//===== SelectionFunction::ModeHandler ========================================
+
+class SelectionFunction::ModeHandler
+{
+public:
+ ModeHandler (
+ SlideSorter& rSlideSorter,
+ SelectionFunction& rSelectionFunction,
+ const bool bIsMouseOverIndicatorAllowed);
+ virtual ~ModeHandler (void);
+
+ virtual Mode GetMode (void) const = 0;
+ virtual void Abort (void) = 0;
+ virtual void ProcessEvent (EventDescriptor& rDescriptor);
+
+ /** Set the selection to exactly the specified page and also set it as
+ the current page.
+ */
+ void SetCurrentPage (const model::SharedPageDescriptor& rpDescriptor);
+
+ /// Deselect all pages.
+ void DeselectAllPages (void);
+ void SelectOnePage (const model::SharedPageDescriptor& rpDescriptor);
+
+ /** When the view on which this selection function is working is the
+ main view then the view is switched to the regular editing view.
+ */
+ void SwitchView (const model::SharedPageDescriptor& rpDescriptor);
+
+ void StartDrag (
+ const Point& rMousePosition,
+ const InsertionIndicatorHandler::Mode eMode);
+
+ bool IsMouseOverIndicatorAllowed (void) const;
+
+protected:
SlideSorter& mrSlideSorter;
+ SelectionFunction& mrSelectionFunction;
+
+ virtual bool ProcessButtonDownEvent (EventDescriptor& rDescriptor);
+ virtual bool ProcessButtonUpEvent (EventDescriptor& rDescriptor);
+ virtual bool ProcessMotionEvent (EventDescriptor& rDescriptor);
+ virtual bool ProcessDragEvent (EventDescriptor& rDescriptor);
+ virtual bool HandleUnprocessedEvent (EventDescriptor& rDescriptor);
- bool mbHasBeenMoved;
+ void ReprocessEvent (EventDescriptor& rDescriptor);
- /** 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.
+private:
+ const bool mbIsMouseOverIndicatorAllowed;
+};
+
+
+/** This is the default handler for processing events. It activates the
+ multi selection or drag-and-drop when the right conditions are met.
+*/
+class NormalModeHandler : public SelectionFunction::ModeHandler
+{
+public:
+ NormalModeHandler (
+ SlideSorter& rSlideSorter,
+ SelectionFunction& rSelectionFunction);
+ virtual ~NormalModeHandler (void);
+
+ virtual SelectionFunction::Mode GetMode (void) const;
+ virtual void Abort (void);
+
+ void ResetButtonDownLocation (void);
+
+protected:
+ virtual bool ProcessButtonDownEvent (SelectionFunction::EventDescriptor& rDescriptor);
+ virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor);
+ virtual bool ProcessMotionEvent (SelectionFunction::EventDescriptor& rDescriptor);
+ virtual bool ProcessDragEvent (SelectionFunction::EventDescriptor& rDescriptor);
+
+private:
+ ::boost::optional<Point> maButtonDownLocation;
+
+ /** Select all pages between and including the selection anchor and the
+ specified page.
*/
- bool IsSubstitutionInsertionNonTrivial (void) const;
+ void RangeSelect (const model::SharedPageDescriptor& rpDescriptor);
};
-class SelectionFunction::EventDescriptor
+/** Handle events during a multi selection, which typically is started by
+ pressing the left mouse button when not over a page.
+*/
+class MultiSelectionModeHandler : public SelectionFunction::ModeHandler
{
public:
+ /** Start a rectangle selection at the given position.
+ */
+ MultiSelectionModeHandler (
+ SlideSorter& rSlideSorter,
+ SelectionFunction& rSelectionFunction,
+ const Point& rMouseModelPosition,
+ const sal_uInt32 nEventCode);
+ virtual ~MultiSelectionModeHandler (void);
- Point maMousePosition;
- Point maMouseModelPosition;
- ::boost::weak_ptr<model::PageDescriptor> mpHitDescriptor;
- SdrPage* mpHitPage;
- sal_uInt32 mnEventCode;
+ virtual SelectionFunction::Mode GetMode (void) const;
+ virtual void Abort (void);
+ virtual void ProcessEvent (SelectionFunction::EventDescriptor& rDescriptor);
- EventDescriptor (
- sal_uInt32 nEventType,
- const MouseEvent& rEvent,
- SlideSorter& rSlideSorter);
- EventDescriptor (
- const KeyEvent& rEvent,
- SlideSorter& rSlideSorter);
+ enum SelectionMode { SM_Normal, SM_Add, SM_Toggle };
+
+ void SetSelectionMode (const SelectionMode eSelectionMode);
+ void SetSelectionModeFromModifier (const sal_uInt32 nEventCode);
+
+protected:
+ virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor);
+ virtual bool ProcessMotionEvent (SelectionFunction::EventDescriptor& rDescriptor);
+ virtual bool HandleUnprocessedEvent (SelectionFunction::EventDescriptor& rDescriptor);
+
+private:
+ SelectionMode meSelectionMode;
+ Point maSecondCorner;
+ Pointer maSavedPointer;
+ sal_Int32 mnAnchorIndex;
+ sal_Int32 mnSecondIndex;
+ view::ButtonBar::Lock maButtonBarLock;
+
+ virtual void UpdateModelPosition (const Point& rMouseModelPosition);
+ virtual void UpdateSelection (void);
+
+ /** Update the rectangle selection so that the given position becomes
+ the new second point of the selection rectangle.
+ */
+ void UpdatePosition (
+ const Point& rMousePosition,
+ const bool bAllowAutoScroll);
+
+ void UpdateSelectionState (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const bool bIsInSelection) const;
};
+/** Handle events during drag-and-drop.
+*/
+class DragAndDropModeHandler : public SelectionFunction::ModeHandler
+{
+public:
+ DragAndDropModeHandler (
+ SlideSorter& rSlideSorter,
+ SelectionFunction& rSelectionFunction,
+ const Point& rMousePosition,
+ ::Window* pWindow);
+ virtual ~DragAndDropModeHandler (void);
+
+ virtual SelectionFunction::Mode GetMode (void) const;
+ virtual void Abort (void);
+
+protected:
+ virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor);
+ virtual bool ProcessDragEvent (SelectionFunction::EventDescriptor& rDescriptor);
+
+private:
+ ::boost::scoped_ptr<DragAndDropContext> mpDragAndDropContext;
+};
+
+
+/** Handle events while the left mouse button is pressed over the button
+ bar.
+*/
+class ButtonModeHandler : public SelectionFunction::ModeHandler
+{
+public:
+ ButtonModeHandler (
+ SlideSorter& rSlideSorter,
+ SelectionFunction& rSelectionFunction);
+ virtual ~ButtonModeHandler (void);
+ virtual void Abort (void);
+
+ virtual SelectionFunction::Mode GetMode (void) const;
+
+protected:
+ virtual bool ProcessButtonDownEvent (SelectionFunction::EventDescriptor& rDescriptor);
+ virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor);
+ virtual bool ProcessMotionEvent (SelectionFunction::EventDescriptor& rDescriptor);
+};
+
+
+
+
+//===== SelectionFunction =====================================================
+
TYPEINIT1(SelectionFunction, FuPoor);
SelectionFunction::SelectionFunction (
SlideSorter& rSlideSorter,
SfxRequest& rRequest)
- : SlideFunction (rSlideSorter, rRequest),
+ : FuPoor (
+ rSlideSorter.GetViewShell(),
+ rSlideSorter.GetContentWindow().get(),
+ &rSlideSorter.GetView(),
+ rSlideSorter.GetModel().GetDocument(),
+ rRequest),
mrSlideSorter(rSlideSorter),
mrController(mrSlideSorter.GetController()),
mbDragSelection(false),
maInsertionMarkerBox(),
mbProcessingMouseButtonDown(false),
- mpSubstitutionHandler(new SubstitutionHandler(mrSlideSorter))
+ mnShiftKeySelectionAnchor(-1),
+ mpModeHandler(new NormalModeHandler(rSlideSorter, *this))
{
- //af aDelayToScrollTimer.SetTimeout(50);
- aDragTimer.SetTimeoutHdl( LINK( this, SelectionFunction, DragSlideHdl ) );
}
+
+
+
SelectionFunction::~SelectionFunction (void)
{
- aDragTimer.Stop();
+ mpModeHandler.reset();
}
@@ -196,9 +402,10 @@ BOOL SelectionFunction::MouseButtonDown (const MouseEvent& rEvent)
{
// #95491# remember button state for creation of own MouseEvents
SetMouseButtonCode (rEvent.GetButtons());
+ aMDPos = rEvent.GetPosPixel();
mbProcessingMouseButtonDown = true;
- mpWindow->CaptureMouse();
+ // mpWindow->CaptureMouse();
ProcessMouseEvent(BUTTON_DOWN, rEvent);
@@ -210,45 +417,7 @@ BOOL SelectionFunction::MouseButtonDown (const MouseEvent& rEvent)
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);
- }
- }
-
+ ProcessMouseEvent(MOUSE_MOTION, rEvent);
return TRUE;
}
@@ -259,16 +428,10 @@ 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();
+// mpWindow->ReleaseMouse();
return TRUE;
}
@@ -276,39 +439,62 @@ BOOL SelectionFunction::MouseButtonUp (const MouseEvent& rEvent)
+void SelectionFunction::NotifyDragFinished (void)
+{
+ SwitchToNormalMode();
+}
+
+
+
+
BOOL SelectionFunction::KeyInput (const KeyEvent& rEvent)
{
+ view::SlideSorterView::DrawLock aDrawLock (mrSlideSorter);
+ PageSelector::UpdateLock aLock (mrSlideSorter);
FocusManager& rFocusManager (mrController.GetFocusManager());
BOOL bResult = FALSE;
- switch (rEvent.GetKeyCode().GetCode())
+ const KeyCode& rCode (rEvent.GetKeyCode());
+ switch (rCode.GetCode())
{
case KEY_RETURN:
- if (rFocusManager.HasFocus())
+ {
+ model::SharedPageDescriptor pDescriptor (rFocusManager.GetFocusedPageDescriptor());
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+ if (rFocusManager.HasFocus() && pDescriptor && pViewShell!=NULL)
{
- model::SharedPageDescriptor pDescriptor (rFocusManager.GetFocusedPageDescriptor());
- if (pDescriptor.get() != NULL)
+ // The Return key triggers different functions depending on
+ // whether the slide sorter is the main view or displayed in
+ // the right pane.
+ if (pViewShell->IsMainViewShell())
+ {
+ mpModeHandler->SetCurrentPage(pDescriptor);
+ mpModeHandler->SwitchView(pDescriptor);
+ }
+ else
{
- SetCurrentPage(pDescriptor);
- SwitchView(pDescriptor);
+ pViewShell->GetDispatcher()->Execute(
+ SID_INSERTPAGE,
+ SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD);
}
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;
+ bResult = TRUE;
+ }
break;
case KEY_ESCAPE:
- rFocusManager.SetFocusToToolBox();
+ // When there is an active multiselection or drag-and-drop
+ // operation then stop that.
+ mpModeHandler->Abort();
+ SwitchToNormalMode();
bResult = TRUE;
break;
@@ -316,12 +502,10 @@ BOOL SelectionFunction::KeyInput (const KeyEvent& rEvent)
{
// Toggle the selection state.
model::SharedPageDescriptor pDescriptor (rFocusManager.GetFocusedPageDescriptor());
- if (pDescriptor.get() != NULL)
+ if (pDescriptor && rCode.IsMod1())
{
- // 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);
+ if (pDescriptor->HasState(model::PageDescriptor::ST_Selected))
+ mrController.GetPageSelector().DeselectPage(pDescriptor, false);
else
mrController.GetPageSelector().SelectPage(pDescriptor);
}
@@ -332,25 +516,25 @@ BOOL SelectionFunction::KeyInput (const KeyEvent& rEvent)
// Move the focus indicator left.
case KEY_LEFT:
- rFocusManager.MoveFocus (FocusManager::FMD_LEFT);
+ MoveFocus(FocusManager::FMD_LEFT, rCode.IsShift(), rCode.IsMod1());
bResult = TRUE;
break;
// Move the focus indicator right.
case KEY_RIGHT:
- rFocusManager.MoveFocus (FocusManager::FMD_RIGHT);
+ MoveFocus(FocusManager::FMD_RIGHT, rCode.IsShift(), rCode.IsMod1());
bResult = TRUE;
break;
// Move the focus indicator up.
case KEY_UP:
- rFocusManager.MoveFocus (FocusManager::FMD_UP);
+ MoveFocus(FocusManager::FMD_UP, rCode.IsShift(), rCode.IsMod1());
bResult = TRUE;
break;
// Move the focus indicator down.
case KEY_DOWN:
- rFocusManager.MoveFocus (FocusManager::FMD_DOWN);
+ MoveFocus(FocusManager::FMD_DOWN, rCode.IsShift(), rCode.IsMod1());
bResult = TRUE;
break;
@@ -366,36 +550,35 @@ BOOL SelectionFunction::KeyInput (const KeyEvent& rEvent)
bResult = TRUE;
break;
+ case KEY_HOME:
+ GotoPage(0);
+ bResult = TRUE;
+ break;
+
+ case KEY_END:
+ GotoPage(mrSlideSorter.GetModel().GetPageCount()-1);
+ bResult = TRUE;
+ break;
+
case KEY_DELETE:
case KEY_BACKSPACE:
{
- if (mrController.GetProperties()->IsUIReadOnly())
+ if (mrSlideSorter.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();
+ mrController.GetSelectionManager()->DeleteSelectedPages(rCode.GetCode()==KEY_DELETE);
+ mnShiftKeySelectionAnchor = -1;
bResult = TRUE;
}
break;
case KEY_F10:
- if (rEvent.GetKeyCode().IsShift())
- ProcessKeyEvent(rEvent);
+ if (rCode.IsShift())
+ {
+ mpModeHandler->SelectOnePage(
+ mrSlideSorter.GetController().GetFocusManager().GetFocusedPageDescriptor());
+ }
break;
default:
@@ -403,7 +586,7 @@ BOOL SelectionFunction::KeyInput (const KeyEvent& rEvent)
}
if ( ! bResult)
- bResult = SlideFunction::KeyInput (rEvent);
+ bResult = FuPoor::KeyInput(rEvent);
return bResult;
}
@@ -411,6 +594,73 @@ BOOL SelectionFunction::KeyInput (const KeyEvent& rEvent)
+void SelectionFunction::MoveFocus (
+ const FocusManager::FocusMoveDirection eDirection,
+ const bool bIsShiftDown,
+ const bool bIsControlDown)
+{
+ // Remember the anchor of shift key multi selection.
+ if (bIsShiftDown)
+ {
+ if (mnShiftKeySelectionAnchor<0)
+ {
+ model::SharedPageDescriptor pFocusedDescriptor (
+ mrController.GetFocusManager().GetFocusedPageDescriptor());
+ mnShiftKeySelectionAnchor = pFocusedDescriptor->GetPageIndex();
+ }
+ }
+ else if ( ! bIsControlDown)
+ ResetShiftKeySelectionAnchor();
+
+ mrController.GetFocusManager().MoveFocus(eDirection);
+
+ PageSelector& rSelector (mrController.GetPageSelector());
+ model::SharedPageDescriptor pFocusedDescriptor (
+ mrController.GetFocusManager().GetFocusedPageDescriptor());
+ if (bIsShiftDown)
+ {
+ // When shift is pressed then select all pages in the range between
+ // the currently and the previously focused pages, including them.
+ if (pFocusedDescriptor)
+ {
+ sal_Int32 nPageRangeEnd (pFocusedDescriptor->GetPageIndex());
+ model::PageEnumeration aPages (
+ model::PageEnumerationProvider::CreateAllPagesEnumeration(
+ mrSlideSorter.GetModel()));
+ while (aPages.HasMoreElements())
+ {
+ model::SharedPageDescriptor pDescriptor (aPages.GetNextElement());
+ if (pDescriptor)
+ {
+ const sal_Int32 nPageIndex(pDescriptor->GetPageIndex());
+ if ((nPageIndex>=mnShiftKeySelectionAnchor && nPageIndex<=nPageRangeEnd)
+ || (nPageIndex<=mnShiftKeySelectionAnchor && nPageIndex>=nPageRangeEnd))
+ {
+ rSelector.SelectPage(pDescriptor);
+ }
+ else
+ {
+ rSelector.DeselectPage(pDescriptor);
+ }
+ }
+ }
+ }
+ }
+ else if (bIsControlDown)
+ {
+ // When control is pressed then do not alter the selection or the
+ // current page, just move the focus.
+ }
+ else
+ {
+ // Without shift just select the focused page.
+ mpModeHandler->SelectOnePage(pFocusedDescriptor);
+ }
+}
+
+
+
+
void SelectionFunction::Activate()
{
FuPoor::Activate();
@@ -442,7 +692,7 @@ void SelectionFunction::ScrollEnd (void)
void SelectionFunction::DoCut (void)
{
- if ( ! mrController.GetProperties()->IsUIReadOnly())
+ if ( ! mrSlideSorter.GetProperties()->IsUIReadOnly())
{
mrController.GetClipboard().DoCut();
}
@@ -461,7 +711,7 @@ void SelectionFunction::DoCopy (void)
void SelectionFunction::DoPaste (void)
{
- if ( ! mrController.GetProperties()->IsUIReadOnly())
+ if ( ! mrSlideSorter.GetProperties()->IsUIReadOnly())
{
mrController.GetClipboard().DoPaste();
}
@@ -470,258 +720,316 @@ void SelectionFunction::DoPaste (void)
-void SelectionFunction::Paint (const Rectangle&, ::sd::Window* )
+bool SelectionFunction::cancel (void)
{
+ mrController.GetFocusManager().ToggleFocus();
+ return true;
}
-IMPL_LINK( SelectionFunction, DragSlideHdl, Timer*, EMPTYARG )
+void SelectionFunction::GotoNextPage (int nOffset)
{
- StartDrag();
- return 0;
+ 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;
+ GotoPage(nIndex + nOffset);
+ }
+ ResetShiftKeySelectionAnchor();
}
-void SelectionFunction::StartDrag (void)
+void SelectionFunction::GotoPage (int nIndex)
{
- if (mbPageHit
- && ! mrController.GetProperties()->IsUIReadOnly())
+ 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)
+ mpModeHandler->SetCurrentPage(pNextPageDescriptor);
+ else
{
- 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);
- }
+ OSL_ASSERT(pNextPageDescriptor.get() != NULL);
}
+ ResetShiftKeySelectionAnchor();
}
-bool SelectionFunction::cancel (void)
+void SelectionFunction::ProcessMouseEvent (sal_uInt32 nEventType, const MouseEvent& rEvent)
{
- mrController.GetFocusManager().ToggleFocus();
- return true;
+ // #95491# remember button state for creation of own MouseEvents
+ SetMouseButtonCode (rEvent.GetButtons());
+
+ EventDescriptor aEventDescriptor (nEventType, rEvent, mrSlideSorter);
+ ProcessEvent(aEventDescriptor);
}
-void SelectionFunction::SelectHitPage (const model::SharedPageDescriptor& rpDescriptor)
+void SelectionFunction::MouseDragged (
+ const AcceptDropEvent& rEvent,
+ const sal_Int8 nDragAction)
{
- mrController.GetPageSelector().SelectPage(rpDescriptor);
+ EventDescriptor aEventDescriptor (MOUSE_DRAG, rEvent, nDragAction, mrSlideSorter);
+ ProcessEvent(aEventDescriptor);
}
-void SelectionFunction::DeselectHitPage (const model::SharedPageDescriptor& rpDescriptor)
+void SelectionFunction::ProcessKeyEvent (const KeyEvent& rEvent)
{
- mrController.GetPageSelector().DeselectPage(rpDescriptor);
+ EventDescriptor aEventDescriptor (rEvent, mrSlideSorter);
+ ProcessEvent(aEventDescriptor);
}
-void SelectionFunction::DeselectAllPages (void)
+void SelectionFunction::ProcessEvent (EventDescriptor& rDescriptor)
{
- mrController.GetPageSelector().DeselectAllPages();
+ // The call to ProcessEvent may switch to another mode handler.
+ // Prevent the untimely destruction of the called handler by aquiring a
+ // temporary reference here.
+ ::boost::shared_ptr<ModeHandler> pModeHandler (mpModeHandler);
+ pModeHandler->ProcessEvent(rDescriptor);
}
-void SelectionFunction::StartRectangleSelection (const Point& rMouseModelPosition)
+bool Match (
+ const sal_uInt32 nEventCode,
+ const sal_uInt32 nPositivePattern)
{
- if (mrController.GetProperties()->IsShowSelection())
- {
- mrSlideSorter.GetView().GetOverlay().GetSelectionRectangleOverlay().Start(
- rMouseModelPosition);
- }
+ return (nEventCode & nPositivePattern)==nPositivePattern;
+}
+
+
+
+
+void SelectionFunction::SwitchToNormalMode (void)
+{
+ if (mpModeHandler->GetMode() != NormalMode)
+ SwitchMode(::boost::shared_ptr<ModeHandler>(
+ new NormalModeHandler(mrSlideSorter, *this)));
}
-void SelectionFunction::UpdateRectangleSelection (const Point& rMouseModelPosition)
+void SelectionFunction::SwitchToDragAndDropMode (const Point aMousePosition)
{
- if (mrController.GetProperties()->IsShowSelection())
+ if (mpModeHandler->GetMode() != DragAndDropMode)
{
- mrSlideSorter.GetView().GetOverlay().GetSelectionRectangleOverlay().Update(
- rMouseModelPosition);
+ SwitchMode(::boost::shared_ptr<ModeHandler>(
+ new DragAndDropModeHandler(mrSlideSorter, *this, aMousePosition, mpWindow)));
}
}
-void SelectionFunction::ProcessRectangleSelection (bool bToggleSelection)
+void SelectionFunction::SwitchToMultiSelectionMode (
+ const Point aMousePosition,
+ const sal_uInt32 nEventCode)
{
- if ( ! mrController.GetProperties()->IsShowSelection())
- return;
+ if (mpModeHandler->GetMode() != MultiSelectionMode)
+ SwitchMode(::boost::shared_ptr<ModeHandler>(
+ new MultiSelectionModeHandler(mrSlideSorter, *this, aMousePosition, nEventCode)));
+}
- view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay());
- if (rOverlay.GetSelectionRectangleOverlay().isVisible())
+
+
+
+bool SelectionFunction::SwitchToButtonMode (void)
+{
+ // Do not show the buttons for draw pages.
+ ::boost::shared_ptr<ViewShell> pMainViewShell (mrSlideSorter.GetViewShellBase()->GetMainViewShell());
+ if (pMainViewShell
+ && pMainViewShell->GetShellType()!=ViewShell::ST_DRAW
+ && mpModeHandler->GetMode() != ButtonMode)
{
- 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);
- }
- }
+ SwitchMode(::boost::shared_ptr<ModeHandler>(new ButtonModeHandler(mrSlideSorter, *this)));
+ return true;
}
+ else
+ return false;
}
-void SelectionFunction::PrepareMouseMotion (const Point& )
+void SelectionFunction::SwitchMode (const ::boost::shared_ptr<ModeHandler>& rpHandler)
{
- if ( ! mrController.GetProperties()->IsUIReadOnly())
+ // Not all modes allow mouse over indicator.
+ if (mpModeHandler->IsMouseOverIndicatorAllowed() != rpHandler->IsMouseOverIndicatorAllowed())
{
- bFirstMouseMove = TRUE;
- aDragTimer.Start();
+ if ( ! rpHandler->IsMouseOverIndicatorAllowed())
+ {
+ mrSlideSorter.GetView().SetPageUnderMouse(model::SharedPageDescriptor());
+ mrSlideSorter.GetView().GetButtonBar().ResetPage();
+ }
+ else
+ mrSlideSorter.GetView().UpdatePageUnderMouse(false);
}
+
+ mpModeHandler = rpHandler;
}
-void SelectionFunction::RangeSelect (const model::SharedPageDescriptor& rpDescriptor)
+void SelectionFunction::ResetShiftKeySelectionAnchor (void)
{
- PageSelector& rSelector (mrController.GetPageSelector());
+ mnShiftKeySelectionAnchor = -1;
+}
- 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::ResetMouseAnchor (void)
+{
+ if (mpModeHandler && mpModeHandler->GetMode() == NormalMode)
+ {
+ ::boost::shared_ptr<NormalModeHandler> pHandler (
+ ::boost::dynamic_pointer_cast<NormalModeHandler>(mpModeHandler));
+ if (pHandler)
+ pHandler->ResetButtonDownLocation();
}
}
-void SelectionFunction::GotoNextPage (int nOffset)
+//===== EventDescriptor =======================================================
+
+SelectionFunction::EventDescriptor::EventDescriptor (
+ const sal_uInt32 nEventType,
+ const MouseEvent& rEvent,
+ SlideSorter& rSlideSorter)
+ : maMousePosition(rEvent.GetPosPixel()),
+ maMouseModelPosition(),
+ mpHitDescriptor(),
+ mpHitPage(),
+ mnEventCode(nEventType),
+ mbIsOverButton(rSlideSorter.GetView().GetButtonBar().IsMouseOverButton()),
+ meDragMode(InsertionIndicatorHandler::MoveMode),
+ mbMakeSelectionVisible(true),
+ mbIsLeaving(false)
{
- model::SharedPageDescriptor pDescriptor
- = mrController.GetCurrentSlideManager()->GetCurrentSlide();
- if (pDescriptor.get() != NULL)
+ maMouseModelPosition = rSlideSorter.GetContentWindow()->PixelToLogic(maMousePosition);
+ mpHitDescriptor = rSlideSorter.GetController().GetPageAt(maMousePosition);
+ if (mpHitDescriptor)
{
- 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);
- }
+ mpHitPage = mpHitDescriptor->GetPage();
}
+
+ mnEventCode |= EncodeMouseEvent(rEvent);
+ mnEventCode |= EncodeState();
+
+ // Detect the mouse leaving the window. When not button is pressed then
+ // we can call IsLeaveWindow at the event. Otherwise we have to make an
+ // explicit test.
+ mbIsLeaving = rEvent.IsLeaveWindow()
+ || ! Rectangle(Point(0,0),
+ rSlideSorter.GetContentWindow()->GetOutputSizePixel()).IsInside(maMousePosition);
}
-void SelectionFunction::ProcessMouseEvent (sal_uInt32 nEventType, const MouseEvent& rEvent)
+SelectionFunction::EventDescriptor::EventDescriptor (
+ const sal_uInt32 nEventType,
+ const AcceptDropEvent& rEvent,
+ const sal_Int8 nDragAction,
+ SlideSorter& rSlideSorter)
+ : maMousePosition(rEvent.maPosPixel),
+ maMouseModelPosition(),
+ mpHitDescriptor(),
+ mpHitPage(),
+ mnEventCode(nEventType),
+ mbIsOverButton(rSlideSorter.GetView().GetButtonBar().IsMouseOverButton()),
+ meDragMode(InsertionIndicatorHandler::GetModeFromDndAction(nDragAction)),
+ mbMakeSelectionVisible(true),
+ mbIsLeaving(false)
{
- // #95491# remember button state for creation of own MouseEvents
- SetMouseButtonCode (rEvent.GetButtons());
+ maMouseModelPosition = rSlideSorter.GetContentWindow()->PixelToLogic(maMousePosition);
+ mpHitDescriptor = rSlideSorter.GetController().GetPageAt(maMousePosition);
+ if (mpHitDescriptor)
+ {
+ mpHitPage = mpHitDescriptor->GetPage();
+ }
+
+ mnEventCode |= EncodeState();
+
+ // Detect the mouse leaving the window. When not button is pressed then
+ // we can call IsLeaveWindow at the event. Otherwise we have to make an
+ // explicit test.
+ mbIsLeaving = rEvent.mbLeaving
+ || ! Rectangle(Point(0,0),
+ rSlideSorter.GetContentWindow()->GetOutputSizePixel()).IsInside(maMousePosition);
+}
- // 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))
+
+SelectionFunction::EventDescriptor::EventDescriptor (
+ const KeyEvent& rEvent,
+ SlideSorter& rSlideSorter)
+ : maMousePosition(),
+ maMouseModelPosition(),
+ mpHitDescriptor(),
+ mpHitPage(),
+ mnEventCode(KEY_EVENT),
+ mbIsOverButton(rSlideSorter.GetView().GetButtonBar().IsMouseOverButton()),
+ meDragMode(InsertionIndicatorHandler::MoveMode),
+ mbMakeSelectionVisible(true),
+ mbIsLeaving(false)
+{
+ model::SharedPageDescriptor pHitDescriptor (
+ rSlideSorter.GetController().GetFocusManager().GetFocusedPageDescriptor());
+ if (pHitDescriptor.get() != NULL)
{
- OSL_TRACE ("can not handle event code %x", pEventDescriptor->mnEventCode);
+ mpHitPage = pHitDescriptor->GetPage();
+ mpHitDescriptor = pHitDescriptor;
}
- EventPostprocessing(*pEventDescriptor);
- if (nEventType == BUTTON_UP)
- mbPageHit = false;
+ mnEventCode |= EncodeKeyEvent(rEvent) | EncodeState();
}
-sal_uInt32 SelectionFunction::EncodeMouseEvent (
- const EventDescriptor& rDescriptor,
+void SelectionFunction::EventDescriptor::SetDragMode (const InsertionIndicatorHandler::Mode eMode)
+{
+ meDragMode = eMode;
+}
+
+
+
+
+sal_uInt32 SelectionFunction::EventDescriptor::EncodeMouseEvent (
const MouseEvent& rEvent) const
{
// Initialize with the type of mouse event.
- sal_uInt32 nEventCode (rDescriptor.mnEventCode & (BUTTON_DOWN | BUTTON_UP | MOUSE_MOTION));
+ sal_uInt32 nEventCode (mnEventCode & (BUTTON_DOWN | BUTTON_UP | MOUSE_MOTION));
// Detect the affected button.
switch (rEvent.GetButtons())
@@ -738,28 +1046,16 @@ sal_uInt32 SelectionFunction::EncodeMouseEvent (
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;
+ // Detect whether the mouse is over one of the active elements inside a
+ // page object.
+ if (mbIsOverButton)
+ nEventCode |= OVER_BUTTON;
return nEventCode;
}
@@ -767,551 +1063,962 @@ sal_uInt32 SelectionFunction::EncodeMouseEvent (
-void SelectionFunction::ProcessKeyEvent (const KeyEvent& rEvent)
+sal_uInt32 SelectionFunction::EventDescriptor::EncodeKeyEvent (const KeyEvent& rEvent) const
{
- // 1. Compute some frequently used values relating to the event.
- ::std::auto_ptr<EventDescriptor> pEventDescriptor (
- new EventDescriptor(rEvent, mrSlideSorter));
+ // The key code in the lower 16 bit.
+ sal_uInt32 nEventCode (rEvent.GetKeyCode().GetCode());
- // 2. Encode the event.
- pEventDescriptor->mnEventCode = EncodeKeyEvent(*pEventDescriptor, rEvent);
+ // Detect pressed modifier keys.
+ if (rEvent.GetKeyCode().IsShift())
+ nEventCode |= SHIFT_MODIFIER;
+ if (rEvent.GetKeyCode().IsMod1())
+ nEventCode |= CONTROL_MODIFIER;
- // 3. Process the event.
- EventPreprocessing(*pEventDescriptor);
- if ( ! EventProcessing(*pEventDescriptor))
- OSL_TRACE ("can not handle event code %x", pEventDescriptor->mnEventCode);
- EventPostprocessing(*pEventDescriptor);
+ return nEventCode;
}
-sal_uInt32 SelectionFunction::EncodeKeyEvent (
- const EventDescriptor& rDescriptor,
- const KeyEvent& rEvent) const
+sal_uInt32 SelectionFunction::EventDescriptor::EncodeState (void) 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;
+ sal_uInt32 nEventCode (0);
// Detect whether the event has happened over a page object.
- if (rDescriptor.mpHitPage != NULL && ! rDescriptor.mpHitDescriptor.expired())
+ if (mpHitPage!=NULL && mpHitDescriptor)
{
- model::SharedPageDescriptor pHitDescriptor (rDescriptor.mpHitDescriptor);
- if (pHitDescriptor->IsSelected())
+ if (mpHitDescriptor->HasState(model::PageDescriptor::ST_Selected))
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;
+ // Detect whether the mouse is over one of the active elements
+ // inside a page object.
+ if (mbIsOverButton)
+ nEventCode |= OVER_BUTTON;
+ }
return nEventCode;
}
-void SelectionFunction::EventPreprocessing (const EventDescriptor& rDescriptor)
+
+//===== SelectionFunction::ModeHandler ========================================
+
+SelectionFunction::ModeHandler::ModeHandler (
+ SlideSorter& rSlideSorter,
+ SelectionFunction& rSelectionFunction,
+ const bool bIsMouseOverIndicatorAllowed)
+ : mrSlideSorter(rSlideSorter),
+ mrSelectionFunction(rSelectionFunction),
+ mbIsMouseOverIndicatorAllowed(bIsMouseOverIndicatorAllowed)
+{
+}
+
+
+
+
+SelectionFunction::ModeHandler::~ModeHandler (void)
{
- // 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);
+
+void SelectionFunction::ModeHandler::ReprocessEvent (EventDescriptor& rDescriptor)
+{
+ mrSelectionFunction.ProcessEvent(rDescriptor);
}
-bool SelectionFunction::EventProcessing (const EventDescriptor& rDescriptor)
+void SelectionFunction::ModeHandler::ProcessEvent (
+ SelectionFunction::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)
+ PageSelector::BroadcastLock aBroadcastLock (mrSlideSorter);
+ PageSelector::UpdateLock aUpdateLock (mrSlideSorter);
+
+ bool bIsProcessed (false);
+ switch (rDescriptor.mnEventCode & (BUTTON_DOWN | BUTTON_UP | MOUSE_MOTION | MOUSE_DRAG))
+ {
+ case BUTTON_DOWN:
+ bIsProcessed = ProcessButtonDownEvent(rDescriptor);
+ break;
+
+ case BUTTON_UP:
+ bIsProcessed = ProcessButtonUpEvent(rDescriptor);
+ break;
+
+ case MOUSE_MOTION:
+ bIsProcessed = ProcessMotionEvent(rDescriptor);
+ break;
+
+ case MOUSE_DRAG:
+ bIsProcessed = ProcessDragEvent(rDescriptor);
+ break;
+ }
+
+ if ( ! bIsProcessed)
+ HandleUnprocessedEvent(rDescriptor);
+}
+
+
+
+
+bool SelectionFunction::ModeHandler::ProcessButtonDownEvent (EventDescriptor&)
+{
+ return false;
+}
+
+
+
+
+bool SelectionFunction::ModeHandler::ProcessButtonUpEvent (EventDescriptor&)
+{
+ mrSelectionFunction.SwitchToNormalMode();
+ return false;
+}
+
+
+
+
+bool SelectionFunction::ModeHandler::ProcessMotionEvent (EventDescriptor& rDescriptor)
+{
+ if (mbIsMouseOverIndicatorAllowed)
+ mrSlideSorter.GetView().UpdatePageUnderMouse(
+ rDescriptor.maMousePosition,
+ (rDescriptor.mnEventCode & LEFT_BUTTON) != 0,
+ true);
+
+ if (rDescriptor.mbIsLeaving)
+ {
+ mrSelectionFunction.SwitchToNormalMode();
+ mrSlideSorter.GetView().SetPageUnderMouse(model::SharedPageDescriptor());
+
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+bool SelectionFunction::ModeHandler::ProcessDragEvent (EventDescriptor&)
+{
+ return false;
+}
+
+
+
+
+bool SelectionFunction::ModeHandler::HandleUnprocessedEvent (EventDescriptor&)
+{
+ return false;
+}
+
+
+
+
+void SelectionFunction::ModeHandler::SetCurrentPage (
+ const model::SharedPageDescriptor& rpDescriptor)
+{
+ SelectOnePage(rpDescriptor);
+ mrSlideSorter.GetController().GetCurrentSlideManager()->SwitchCurrentSlide(rpDescriptor);
+}
+
+
- bool bResult (true);
- bool bMakeSelectionVisible (true);
+void SelectionFunction::ModeHandler::DeselectAllPages (void)
+{
+ mrSlideSorter.GetController().GetPageSelector().DeselectAllPages();
+ mrSelectionFunction.ResetShiftKeySelectionAnchor();
+}
+
+
+
+
+void SelectionFunction::ModeHandler::SelectOnePage (
+ const model::SharedPageDescriptor& rpDescriptor)
+{
+ DeselectAllPages();
+ mrSlideSorter.GetController().GetPageSelector().SelectPage(rpDescriptor);
+}
+
+
+
+
+void SelectionFunction::ModeHandler::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);
+ pViewShell->GetFrameView()->SetSelectedPage(
+ (rpDescriptor->GetPage()->GetPageNum()-1)/2);
+ }
+ if (mrSlideSorter.GetViewShellBase() != NULL)
+ framework::FrameworkHelper::Instance(*mrSlideSorter.GetViewShellBase())->RequestView(
+ framework::FrameworkHelper::msImpressViewURL,
+ framework::FrameworkHelper::msCenterPaneURL);
+ }
+}
+
+
+
+
+void SelectionFunction::ModeHandler::StartDrag (
+ const Point& rMousePosition,
+ const InsertionIndicatorHandler::Mode eMode)
+{
+ (void)eMode;
+ // Do not start a drag-and-drop operation when one is already active.
+ // (when dragging pages from one document into another, pressing a
+ // modifier key can trigger a MouseMotion event in the originating
+ // window (focus still in there). Together with the mouse button pressed
+ // (drag-and-drop is active) this triggers the start of drag-and-drop.)
+ if (SD_MOD()->pTransferDrag != NULL)
+ return;
+
+ if ( ! mrSlideSorter.GetProperties()->IsUIReadOnly())
+ {
+ mrSelectionFunction.SwitchToDragAndDropMode(rMousePosition);
+ }
+}
+
+
+
+
+bool SelectionFunction::ModeHandler::IsMouseOverIndicatorAllowed (void) const
+{
+ return mbIsMouseOverIndicatorAllowed;
+}
+
+
+
+
+//===== NormalModeHandler =====================================================
+
+NormalModeHandler::NormalModeHandler (
+ SlideSorter& rSlideSorter,
+ SelectionFunction& rSelectionFunction)
+ : ModeHandler(rSlideSorter, rSelectionFunction, true),
+ maButtonDownLocation()
+{
+}
+
+
+
+
+NormalModeHandler::~NormalModeHandler (void)
+{
+}
+
+
+
+
+SelectionFunction::Mode NormalModeHandler::GetMode (void) const
+{
+ return SelectionFunction::NormalMode;
+}
+
+
+
+
+void NormalModeHandler::Abort (void)
+{
+}
+
- 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);
+bool NormalModeHandler::ProcessButtonDownEvent (
+ SelectionFunction::EventDescriptor& rDescriptor)
+{
+ // Remember the location where the left button is pressed. With
+ // that we can filter away motion events that are caused by key
+ // presses. We also can tune the minimal motion distance that
+ // triggers a drag-and-drop operation.
+ if ((rDescriptor.mnEventCode & BUTTON_DOWN) != 0)
+ maButtonDownLocation = rDescriptor.maMousePosition;
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();
+ SetCurrentPage(rDescriptor.mpHitDescriptor);
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));
-
+ SetCurrentPage(rDescriptor.mpHitDescriptor);
+ SwitchView(rDescriptor.mpHitDescriptor);
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);
+ // Range selection with the shift modifier.
+ RangeSelect(rDescriptor.mpHitDescriptor);
break;
- // Was: Preview of the page transition effect.
- case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_FADE_INDICATOR:
- // No action.
+ case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | OVER_BUTTON:
+ case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | OVER_BUTTON:
+ OSL_ASSERT(mrSlideSorter.GetView().GetButtonBar().IsMouseOverButton());
+
+ // Switch to button mode only when the buttons are visible
+ // (or being faded in.)
+ if (mrSlideSorter.GetView().GetButtonBar().IsVisible(rDescriptor.mpHitDescriptor))
+ {
+ if (mrSelectionFunction.SwitchToButtonMode())
+ ReprocessEvent(rDescriptor);
+ }
+ else
+ {
+ // When the buttons are not (yet) visible then behave like
+ // the left button had been clicked over any other part of
+ // the slide.
+ SetCurrentPage(rDescriptor.mpHitDescriptor);
+ }
break;
- // Right button for context menu.
+ // 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;
+ SetCurrentPage(rDescriptor.mpHitDescriptor);
+ rDescriptor.mbMakeSelectionVisible = 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;
+ rDescriptor.mbMakeSelectionVisible = 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:
+ // Remember the current selection so that when a multi selection
+ // is started, we can restore the previous selection.
+ mrSlideSorter.GetModel().SaveCurrentSelection();
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);
+ case ANY_MODIFIER(BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE):
+ // Remember the current selection so that when a multi selection
+ // is started, we can restore the previous selection.
+ mrSlideSorter.GetModel().SaveCurrentSelection();
+ DeselectAllPages();
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);
+ default:
+ return false;
+ }
+ return true;
+}
+
+
+
+
+bool NormalModeHandler::ProcessButtonUpEvent (
+ SelectionFunction::EventDescriptor& rDescriptor)
+{
+ bool bIsProcessed (true);
+ switch (rDescriptor.mnEventCode)
+ {
+ case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE:
+ SetCurrentPage(rDescriptor.mpHitDescriptor);
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();
+ // Multi selection with the control modifier.
+ case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | CONTROL_MODIFIER:
+ mrSlideSorter.GetController().GetPageSelector().DeselectPage(
+ rDescriptor.mpHitDescriptor);
break;
- // Rectangle selection.
- case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE | NO_MODIFIER:
- DeselectAllPages();
- StartRectangleSelection(rDescriptor.maMouseModelPosition);
+ case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | CONTROL_MODIFIER:
+ mrSlideSorter.GetController().GetPageSelector().SelectPage(
+ rDescriptor.mpHitDescriptor);
+ mrSlideSorter.GetView().UpdatePageUnderMouse(
+ rDescriptor.mpHitDescriptor,
+ rDescriptor.maMousePosition,
+ false);
+ break;
+ case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE:
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);
+ default:
+ bIsProcessed = false;
break;
+ }
+ mrSelectionFunction.SwitchToNormalMode();
+ return bIsProcessed;
+}
- case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE):
+
+
+
+
+bool NormalModeHandler::ProcessMotionEvent (
+ SelectionFunction::EventDescriptor& rDescriptor)
+{
+ if (ModeHandler::ProcessMotionEvent(rDescriptor))
+ return true;
+
+ bool bIsProcessed (true);
+ switch (rDescriptor.mnEventCode)
+ {
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;
+ // SetCurrentPage(rDescriptor.mpHitDescriptor);
+ // Fallthrough
- case ANY_PAGE(BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | RECTANGLE_VISIBLE | NO_MODIFIER):
- ProcessRectangleSelection(false);
- break;
+ // A mouse motion without visible substitution starts that.
+ case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE):
+ {
+ if (maButtonDownLocation)
+ {
+ const sal_Int32 nDistance (maButtonDownLocation
+ ? ::std::max (
+ abs(maButtonDownLocation->X() - rDescriptor.maMousePosition.X()),
+ abs(maButtonDownLocation->Y() - rDescriptor.maMousePosition.Y()))
+ : 0);
+ if (nDistance > 3)
+ StartDrag(
+ rDescriptor.maMousePosition,
+ (rDescriptor.mnEventCode & CONTROL_MODIFIER) != 0
+ ? InsertionIndicatorHandler::CopyMode
+ : InsertionIndicatorHandler::MoveMode);
+ }
+ }
+ 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);
+ // A mouse motion not over a page starts a rectangle selection.
+ case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE):
+ mrSelectionFunction.SwitchToMultiSelectionMode(
+ rDescriptor.maMouseModelPosition,
+ rDescriptor.mnEventCode);
break;
default:
- bResult = false;
+ bIsProcessed = false;
break;
}
- mrController.GetPageSelector().EnableBroadcasting(bMakeSelectionVisible);
+ return bIsProcessed;
+}
- return bResult;
+
+
+
+bool NormalModeHandler::ProcessDragEvent (SelectionFunction::EventDescriptor& rDescriptor)
+{
+ mrSelectionFunction.SwitchToDragAndDropMode(rDescriptor.maMousePosition);
+ ReprocessEvent(rDescriptor);
+ return true;
}
-void SelectionFunction::EventPostprocessing (const EventDescriptor& rDescriptor)
+void NormalModeHandler::RangeSelect (const model::SharedPageDescriptor& rpDescriptor)
{
- if (rDescriptor.mnEventCode & BUTTON_UP)
+ PageSelector::UpdateLock aLock (mrSlideSorter);
+ PageSelector& rSelector (mrSlideSorter.GetController().GetPageSelector());
+
+ model::SharedPageDescriptor pAnchor (rSelector.GetSelectionAnchor());
+ DeselectAllPages();
+
+ if (pAnchor.get() != NULL)
{
- 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);
+ // Select all pages between the anchor and the given one, including
+ // the two.
+ const USHORT nAnchorIndex ((pAnchor->GetPage()->GetPageNum()-1) / 2);
+ const 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.)
+ const USHORT nStep ((nAnchorIndex < nOtherIndex) ? +1 : -1);
+ USHORT nIndex (nAnchorIndex);
+ while (true)
+ {
+ rSelector.SelectPage(nIndex);
+ if (nIndex == nOtherIndex)
+ break;
+ nIndex = nIndex + nStep;
+ }
}
}
-void SelectionFunction::SetCurrentPage (const model::SharedPageDescriptor& rpDescriptor)
+void NormalModeHandler::ResetButtonDownLocation (void)
{
- PageSelector& rSelector (mrController.GetPageSelector());
- rSelector.DeselectAllPages ();
- rSelector.SelectPage(rpDescriptor);
+ maButtonDownLocation = ::boost::optional<Point>();
+}
+
+
- mrController.GetCurrentSlideManager()->SwitchCurrentSlide(rpDescriptor);
+
+//===== MultiSelectionModeHandler =============================================
+
+MultiSelectionModeHandler::MultiSelectionModeHandler (
+ SlideSorter& rSlideSorter,
+ SelectionFunction& rSelectionFunction,
+ const Point& rMouseModelPosition,
+ const sal_uInt32 nEventCode)
+ : ModeHandler(rSlideSorter, rSelectionFunction, false),
+ meSelectionMode(SM_Normal),
+ maSecondCorner(rMouseModelPosition),
+ maSavedPointer(mrSlideSorter.GetContentWindow()->GetPointer()),
+ mnAnchorIndex(-1),
+ mnSecondIndex(-1),
+ maButtonBarLock(rSlideSorter)
+{
+ const Pointer aSelectionPointer (POINTER_TEXT);
+ mrSlideSorter.GetContentWindow()->SetPointer(aSelectionPointer);
+ SetSelectionModeFromModifier(nEventCode);
}
-void SelectionFunction::SwitchView (const model::SharedPageDescriptor& rpDescriptor)
+
+MultiSelectionModeHandler::~MultiSelectionModeHandler (void)
{
- // 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())
+ mrSlideSorter.GetContentWindow()->SetPointer(maSavedPointer);
+}
+
+
+
+
+SelectionFunction::Mode MultiSelectionModeHandler::GetMode (void) const
+{
+ return SelectionFunction::MultiSelectionMode;
+}
+
+
+
+
+void MultiSelectionModeHandler::Abort (void)
+{
+ mrSlideSorter.GetView().RequestRepaint(mrSlideSorter.GetModel().RestoreSelection());
+}
+
+
+
+
+void MultiSelectionModeHandler::ProcessEvent (
+ SelectionFunction::EventDescriptor& rDescriptor)
+{
+ // During a multi selection we do not want sudden jumps of the
+ // visible area caused by moving newly selected pages into view.
+ // Therefore disable that temporarily. The disabler object is
+ // released at the end of the event processing, after the focus and
+ // current slide have been updated.
+ VisibleAreaManager::TemporaryDisabler aDisabler (mrSlideSorter);
+
+ ModeHandler::ProcessEvent(rDescriptor);
+}
+
+
+
+
+bool MultiSelectionModeHandler::ProcessButtonUpEvent (
+ SelectionFunction::EventDescriptor& rDescriptor)
+{
+ if (Match(rDescriptor.mnEventCode, BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK))
{
- 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);
+ mrSelectionFunction.SwitchToNormalMode();
+ return true;
}
+ else
+ return false;
}
-//===== EventDescriptor =======================================================
+bool MultiSelectionModeHandler::ProcessMotionEvent (
+ SelectionFunction::EventDescriptor& rDescriptor)
+{
+ // The selection rectangle is visible. Handle events accordingly.
+ if (Match(rDescriptor.mnEventCode, MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK))
+ {
+ SetSelectionModeFromModifier(rDescriptor.mnEventCode);
+ UpdatePosition(rDescriptor.maMousePosition, true);
+ rDescriptor.mbMakeSelectionVisible = false;
+ return true;
+ }
+ else
+ return false;
+}
-SelectionFunction::EventDescriptor::EventDescriptor (
- sal_uInt32 nEventType,
- const MouseEvent& rEvent,
- SlideSorter& rSlideSorter)
- : maMousePosition(),
- maMouseModelPosition(),
- mpHitDescriptor(),
- mpHitPage(),
- mnEventCode(nEventType)
+
+
+bool MultiSelectionModeHandler::HandleUnprocessedEvent (
+ SelectionFunction::EventDescriptor& rDescriptor)
{
- ::Window* pWindow = rSlideSorter.GetActiveWindow();
+ if ( ! ModeHandler::HandleUnprocessedEvent(rDescriptor))
+ {
+ // If the event has not been processed then stop multi selection.
+ mrSelectionFunction.SwitchToNormalMode();
+ ReprocessEvent(rDescriptor);
+ }
+ return true;
+}
- maMousePosition = rEvent.GetPosPixel();
- maMouseModelPosition = pWindow->PixelToLogic(maMousePosition);
- model::SharedPageDescriptor pHitDescriptor (
- rSlideSorter.GetController().GetPageAt(maMousePosition));
- if (pHitDescriptor.get() != NULL)
+
+
+
+void MultiSelectionModeHandler::UpdatePosition (
+ const Point& rMousePosition,
+ const bool bAllowAutoScroll)
+{
+ VisibleAreaManager::TemporaryDisabler aDisabler (mrSlideSorter);
+
+ // Convert window coordinates into model coordinates (we need the
+ // window coordinates for auto-scrolling because that remains
+ // constant while scrolling.)
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ const Point aMouseModelPosition (pWindow->PixelToLogic(rMousePosition));
+
+ if ( ! (bAllowAutoScroll && mrSlideSorter.GetController().GetScrollBarManager().AutoScroll(
+ rMousePosition,
+ ::boost::bind(
+ &MultiSelectionModeHandler::UpdatePosition,
+ this,
+ rMousePosition,
+ false))))
{
- mpHitDescriptor = pHitDescriptor;
- mpHitPage = pHitDescriptor->GetPage();
+ UpdateModelPosition(aMouseModelPosition);
}
}
+void MultiSelectionModeHandler::SetSelectionModeFromModifier (
+ const sal_uInt32 nEventCode)
+{
+ switch (nEventCode & MODIFIER_MASK)
+ {
+ case NO_MODIFIER:
+ SetSelectionMode(SM_Normal);
+ break;
-SelectionFunction::EventDescriptor::EventDescriptor (
- const KeyEvent&,
- SlideSorter& rSlideSorter)
- : maMousePosition(),
- maMouseModelPosition(),
- mpHitDescriptor(),
- mpHitPage(),
- mnEventCode(0)
+ case SHIFT_MODIFIER:
+ SetSelectionMode(SM_Add);
+ break;
+
+ case CONTROL_MODIFIER:
+ SetSelectionMode(SM_Toggle);
+ break;
+ }
+}
+
+
+
+
+void MultiSelectionModeHandler::SetSelectionMode (const SelectionMode eSelectionMode)
{
- mpHitDescriptor = rSlideSorter.GetController().GetFocusManager().GetFocusedPageDescriptor();
- model::SharedPageDescriptor pHitDescriptor (
- rSlideSorter.GetController().GetFocusManager().GetFocusedPageDescriptor());
- if (pHitDescriptor.get() != NULL)
+ if (meSelectionMode != eSelectionMode)
{
- mpHitPage = pHitDescriptor->GetPage();
- mpHitDescriptor = pHitDescriptor;
+ meSelectionMode = eSelectionMode;
+ UpdateSelection();
}
}
+void MultiSelectionModeHandler::UpdateSelectionState (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const bool bIsInSelection) const
+{
+ // Determine whether the page was selected before the rectangle
+ // selection was started.
+ const bool bWasSelected (rpDescriptor->HasState(model::PageDescriptor::ST_WasSelected));
+
+ // Combine the two selection states depending on the selection mode.
+ bool bSelect (false);
+ switch(meSelectionMode)
+ {
+ case SM_Normal:
+ bSelect = bIsInSelection;
+ break;
-//===== SubstitutionHandler ===================================================
+ case SM_Add:
+ bSelect = bIsInSelection || bWasSelected;
+ break;
-SelectionFunction::SubstitutionHandler::SubstitutionHandler (SlideSorter& rSlideSorter)
- : mrSlideSorter(rSlideSorter),
- mbHasBeenMoved(false)
+ case SM_Toggle:
+ if (bIsInSelection)
+ bSelect = !bWasSelected;
+ else
+ bSelect = bWasSelected;
+ break;
+ }
+
+ // Set the new selection state.
+ if (bSelect)
+ mrSlideSorter.GetController().GetPageSelector().SelectPage(rpDescriptor);
+ else
+ mrSlideSorter.GetController().GetPageSelector().DeselectPage(rpDescriptor);
+}
+
+
+
+
+void MultiSelectionModeHandler::UpdateModelPosition (const Point& rMouseModelPosition)
{
+ maSecondCorner = rMouseModelPosition;
+ UpdateSelection();
}
-SelectionFunction::SubstitutionHandler::~SubstitutionHandler (void)
+void MultiSelectionModeHandler::UpdateSelection (void)
{
- if (mrSlideSorter.IsValid())
+ view::SlideSorterView::DrawLock aLock (mrSlideSorter);
+
+ model::SlideSorterModel& rModel (mrSlideSorter.GetModel());
+ const sal_Int32 nPageCount (rModel.GetPageCount());
+
+ const sal_Int32 nIndexUnderMouse (
+ mrSlideSorter.GetView().GetLayouter().GetIndexAtPoint (
+ maSecondCorner,
+ false,
+ false));
+ if (nIndexUnderMouse>=0 && nIndexUnderMouse<nPageCount)
{
- view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay());
- rOverlay.GetSubstitutionOverlay().setVisible(false);
- rOverlay.GetSubstitutionOverlay().Clear();
+ if (mnAnchorIndex < 0)
+ mnAnchorIndex = nIndexUnderMouse;
+ mnSecondIndex = nIndexUnderMouse;
+
+ Range aRange (mnAnchorIndex, mnSecondIndex);
+ aRange.Justify();
+
+ for (sal_Int32 nIndex=0; nIndex<nPageCount; ++nIndex)
+ {
+ UpdateSelectionState(rModel.GetPageDescriptor(nIndex), aRange.IsInside(nIndex));
+ }
}
}
-void SelectionFunction::SubstitutionHandler::Start (const Point& rMouseModelPosition)
+//===== DragAndDropModeHandler ================================================
+
+DragAndDropModeHandler::DragAndDropModeHandler (
+ SlideSorter& rSlideSorter,
+ SelectionFunction& rSelectionFunction,
+ const Point& rMousePosition,
+ ::Window* pWindow)
+ : ModeHandler(rSlideSorter, rSelectionFunction, false)
{
- // No Drag-and-Drop for master pages.
- if (mrSlideSorter.GetModel().GetEditMode() != EM_PAGE)
- return;
+ SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag;
+ if (pDragTransferable==NULL && mrSlideSorter.GetViewShell() != NULL)
+ {
+ SlideSorterViewShell* pSlideSorterViewShell
+ = dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell());
+ if (pSlideSorterViewShell != NULL)
+ pSlideSorterViewShell->StartDrag(rMousePosition, pWindow);
+ pDragTransferable = SD_MOD()->pTransferDrag;
+ }
- if (mrSlideSorter.GetController().GetProperties()->IsUIReadOnly())
- return;
+ mpDragAndDropContext.reset(new DragAndDropContext(mrSlideSorter));
+ mrSlideSorter.GetController().GetInsertionIndicatorHandler()->Start(
+ pDragTransferable != NULL
+ && pDragTransferable->GetView()==&mrSlideSorter.GetView());
+}
- view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay());
- if ( ! rOverlay.GetSubstitutionOverlay().isVisible())
+
+
+DragAndDropModeHandler::~DragAndDropModeHandler (void)
+{
+ if (mpDragAndDropContext)
{
- // 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;
+ // Disconnect the substitution handler from this selection function.
+ mpDragAndDropContext->SetTargetSlideSorter();
+ mpDragAndDropContext.reset();
}
- else
- UpdatePosition(rMouseModelPosition);
+ mrSlideSorter.GetController().GetInsertionIndicatorHandler()->End(Animator::AM_Animated);
}
-void SelectionFunction::SubstitutionHandler::UpdatePosition (const Point& rMouseModelPosition)
+SelectionFunction::Mode DragAndDropModeHandler::GetMode (void) const
{
- if (mrSlideSorter.GetController().GetProperties()->IsUIReadOnly())
- return;
+ return SelectionFunction::DragAndDropMode;
+}
- 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 DragAndDropModeHandler::Abort (void)
+{
+ mrSlideSorter.GetController().GetClipboard().Abort();
+ if (mpDragAndDropContext)
+ mpDragAndDropContext->Dispose();
+ // mrSlideSorter.GetView().RequestRepaint(mrSlideSorter.GetModel().RestoreSelection());
}
-void SelectionFunction::SubstitutionHandler::Process (void)
+bool DragAndDropModeHandler::ProcessButtonUpEvent (
+ SelectionFunction::EventDescriptor& rDescriptor)
{
- if (mrSlideSorter.GetController().GetProperties()->IsUIReadOnly())
- return;
+ if (Match(rDescriptor.mnEventCode, BUTTON_UP | LEFT_BUTTON))
+ {
+ // The following Process() call may lead to the desctruction
+ // of rDescriptor.mpHitDescriptor so release our reference to it.
+ rDescriptor.mpHitDescriptor.reset();
+ mrSelectionFunction.SwitchToNormalMode();
+ return true;
+ }
+ else
+ return false;
+}
- 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);
+
+bool DragAndDropModeHandler::ProcessDragEvent (SelectionFunction::EventDescriptor& rDescriptor)
+{
+ OSL_ASSERT(mpDragAndDropContext);
+
+ if (rDescriptor.mbIsLeaving)
+ {
+ mrSelectionFunction.SwitchToNormalMode();
+ }
+ else if (mpDragAndDropContext)
+ {
+ mpDragAndDropContext->UpdatePosition(
+ rDescriptor.maMousePosition,
+ rDescriptor.meDragMode);
}
+
+ return true;
}
-void SelectionFunction::SubstitutionHandler::End (void)
+//===== ButtonModeHandler =====================================================
+
+ButtonModeHandler::ButtonModeHandler (
+ SlideSorter& rSlideSorter,
+ SelectionFunction& rSelectionFunction)
+ : ModeHandler(rSlideSorter, rSelectionFunction, true)
{
- view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay());
- rOverlay.GetSubstitutionOverlay().setVisible(false);
- rOverlay.GetSubstitutionOverlay().Clear();
- rOverlay.GetInsertionIndicatorOverlay().setVisible(false);
}
-bool SelectionFunction::SubstitutionHandler::HasBeenMoved (void) const
+ButtonModeHandler::~ButtonModeHandler (void)
{
- return mbHasBeenMoved;
}
-bool SelectionFunction::SubstitutionHandler::IsSubstitutionInsertionNonTrivial (void) const
+SelectionFunction::Mode ButtonModeHandler::GetMode (void) const
{
- bool bIsNonTrivial = false;
+ return SelectionFunction::ButtonMode;
+}
+
+
+
- do
+void ButtonModeHandler::Abort (void)
+{
+}
+
+
+
+
+bool ButtonModeHandler::ProcessButtonDownEvent (SelectionFunction::EventDescriptor& rDescriptor)
+{
+ switch (rDescriptor.mnEventCode)
{
- view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay());
+ case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | OVER_BUTTON:
+ case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | OVER_BUTTON:
+ // Remember page and button index. When mouse button is
+ // released over same page and button then invoke action of that
+ // button.
+ mrSlideSorter.GetView().GetButtonBar().ProcessButtonDownEvent(
+ rDescriptor.mpHitDescriptor,
+ rDescriptor.maMouseModelPosition);
+ return true;
+
+ default:
+ return false;
+ }
+}
- // 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;
+bool ButtonModeHandler::ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor)
+{
+ switch (rDescriptor.mnEventCode & BUTTON_MASK)
+ {
+ case LEFT_BUTTON:
+ mrSlideSorter.GetView().GetButtonBar().ProcessButtonUpEvent(
+ rDescriptor.mpHitDescriptor,
+ rDescriptor.maMouseModelPosition);
+ mrSelectionFunction.SwitchToNormalMode();
+ return true;
}
- while (false);
- return bIsNonTrivial;
+ return false;
}
+
+
+
+bool ButtonModeHandler::ProcessMotionEvent (SelectionFunction::EventDescriptor& rDescriptor)
+{
+ switch (rDescriptor.mnEventCode & (MOUSE_MOTION | BUTTON_MASK))
+ {
+ case MOUSE_MOTION | LEFT_BUTTON:
+ mrSlideSorter.GetView().GetButtonBar().ProcessMouseMotionEvent(
+ rDescriptor.mpHitDescriptor,
+ rDescriptor.maMouseModelPosition,
+ true);
+ return true;
+
+ case MOUSE_MOTION:
+ mrSlideSorter.GetView().GetButtonBar().ProcessMouseMotionEvent(
+ rDescriptor.mpHitDescriptor,
+ rDescriptor.maMouseModelPosition,
+ false);
+ return true;
+ }
+
+ return false;
+}
+
+
+
+
} } } // end of namespace ::sd::slidesorter::controller