From 8f66325395890294b3180b9c88f93617826812f6 Mon Sep 17 00:00:00 2001 From: David Capello Date: Thu, 12 Jan 2012 00:39:39 -0300 Subject: [PATCH] Add support to scroll in MovingPixelsState without calling a full dropImage(). + Added EditorState::isTemporalState() to know if we've to do a dropImage() or a simple dropImageTemporarily() only. + Improved the return type of EditorState::onBeforeChangeState() member function (now it's an enum instead of a bool). --- src/widgets/editor/editor.cpp | 11 +++++-- src/widgets/editor/editor_state.h | 13 +++++++- src/widgets/editor/moving_pixels_state.cpp | 35 +++++++++++++++------- src/widgets/editor/moving_pixels_state.h | 2 +- src/widgets/editor/scrolling_state.h | 1 + src/widgets/editor/standby_state.cpp | 2 +- 6 files changed, 48 insertions(+), 16 deletions(-) diff --git a/src/widgets/editor/editor.cpp b/src/widgets/editor/editor.cpp index 2cfaae5ac..2cc3f83ed 100644 --- a/src/widgets/editor/editor.cpp +++ b/src/widgets/editor/editor.cpp @@ -186,11 +186,12 @@ void Editor::setStateInternal(const EditorStatePtr& newState) // Fire before change state event, set the state, and fire after // change state event. - bool keepInHistory = m_state->onBeforeChangeState(this); + EditorState::BeforeChangeAction beforeChangeAction = + m_state->onBeforeChangeState(this, newState); // Push a new state if (newState) { - if (!keepInHistory) + if (beforeChangeAction == EditorState::DiscardState) m_statesHistory.pop(); m_statesHistory.push(newState); @@ -204,6 +205,8 @@ void Editor::setStateInternal(const EditorStatePtr& newState) m_state = m_statesHistory.top(); } + ASSERT(m_state != NULL); + // Change to the new state. m_state->onAfterChangeState(this); @@ -239,8 +242,10 @@ void Editor::setDocument(Document* document) //jmanager_free_mouse(); // TODO Why is this here? Review this code // Reset all states (back to standby). + EditorStatePtr firstState(new StandbyState); m_statesHistory.clear(); - setState(EditorStatePtr(new StandbyState)); + m_statesHistory.push(firstState); + setState(firstState); if (m_cursor_thick) editor_clean_cursor(); diff --git a/src/widgets/editor/editor_state.h b/src/widgets/editor/editor_state.h index 74291e829..466f8911c 100644 --- a/src/widgets/editor/editor_state.h +++ b/src/widgets/editor/editor_state.h @@ -34,13 +34,24 @@ union Message; class EditorState { public: + enum BeforeChangeAction { + DiscardState, + KeepState + }; + EditorState() { } virtual ~EditorState() { } + // Returns true if this state is a "temporal" state. It means that + // this state doesn't go to other state than the previous one. + virtual bool isTemporalState() const { return false; } + // Called just before this state is replaced by a new state in the // Editor::setState() method. Returns true if this state should be // kept in the EditorStatesHistory. - virtual bool onBeforeChangeState(Editor* editor) { return true; } + virtual BeforeChangeAction onBeforeChangeState(Editor* editor, EditorState* newState) { + return KeepState; + } // Called when this instance is set as the new Editor's state when // Editor::setState() method is used. diff --git a/src/widgets/editor/moving_pixels_state.cpp b/src/widgets/editor/moving_pixels_state.cpp index dbd477f7b..79b365c65 100644 --- a/src/widgets/editor/moving_pixels_state.cpp +++ b/src/widgets/editor/moving_pixels_state.cpp @@ -35,6 +35,7 @@ #include "widgets/editor/editor.h" #include "widgets/editor/editor_customization_delegate.h" #include "widgets/editor/pixels_movement.h" +#include "widgets/editor/scrolling_state.h" #include "widgets/editor/standby_state.h" #include "widgets/editor/transform_handles.h" #include "widgets/statebar.h" @@ -73,7 +74,7 @@ MovingPixelsState::~MovingPixelsState() delete m_pixelsMovement; } -bool MovingPixelsState::onBeforeChangeState(Editor* editor) +EditorState::BeforeChangeAction MovingPixelsState::onBeforeChangeState(Editor* editor, EditorState* newState) { ASSERT(m_pixelsMovement != NULL); @@ -81,18 +82,25 @@ bool MovingPixelsState::onBeforeChangeState(Editor* editor) if (m_pixelsMovement->isDragging()) m_pixelsMovement->dropImageTemporarily(); - // Drop pixels if the user press a button outside the selection - m_pixelsMovement->dropImage(); + // Drop pixels if we are changing to a non-temporary state (a + // temporary state is something like ScrollingState). + if (!newState || !newState->isTemporalState()) { + m_pixelsMovement->dropImage(); - editor->getDocument()->resetTransformation(); + editor->getDocument()->resetTransformation(); - delete m_pixelsMovement; - m_pixelsMovement = NULL; + delete m_pixelsMovement; + m_pixelsMovement = NULL; - editor->releaseMouse(); + editor->releaseMouse(); - app_get_statusbar()->hideMovePixelsOptions(); - return false; // Don't keep this state in history + app_get_statusbar()->hideMovePixelsOptions(); + return DiscardState; + } + else { + editor->releaseMouse(); + return KeepState; + } } void MovingPixelsState::onCurrentToolChange(Editor* editor) @@ -118,6 +126,13 @@ bool MovingPixelsState::onMouseDown(Editor* editor, Message* msg) Decorator* decorator = static_cast(editor->getDecorator()); Document* document = editor->getDocument(); + // Start scroll loop + if (msg->mouse.middle) { // TODO raw msg->mouse.middle here, this should be customizable + editor->setState(EditorStatePtr(new ScrollingState())); + editor->captureMouse(); + return true; + } + // Transform selected pixels if (document->isMaskVisible() && decorator->getTransformHandles(editor)) { @@ -316,7 +331,7 @@ void MovingPixelsState::setTransparentColor(const Color& color) void MovingPixelsState::dropPixels(Editor* editor) { // Just change to default state (StandbyState generally). We'll - // receive an onBeforeChangeState event after this call. + // receive an onBeforeChangeState() event after this call. editor->backToPreviousState(); } diff --git a/src/widgets/editor/moving_pixels_state.h b/src/widgets/editor/moving_pixels_state.h index d932caff5..b078b6806 100644 --- a/src/widgets/editor/moving_pixels_state.h +++ b/src/widgets/editor/moving_pixels_state.h @@ -34,7 +34,7 @@ public: MovingPixelsState(Editor* editor, Message* msg, PixelsMovement* pixelsMovement, HandleType handle); virtual ~MovingPixelsState(); - virtual bool onBeforeChangeState(Editor* editor) OVERRIDE; + virtual BeforeChangeAction onBeforeChangeState(Editor* editor, EditorState* newState) OVERRIDE; virtual void onCurrentToolChange(Editor* editor) OVERRIDE; virtual bool onMouseDown(Editor* editor, Message* msg) OVERRIDE; virtual bool onMouseUp(Editor* editor, Message* msg) OVERRIDE; diff --git a/src/widgets/editor/scrolling_state.h b/src/widgets/editor/scrolling_state.h index 6c11318a8..9b7162d3f 100644 --- a/src/widgets/editor/scrolling_state.h +++ b/src/widgets/editor/scrolling_state.h @@ -27,6 +27,7 @@ class ScrollingState : public EditorState public: ScrollingState(); virtual ~ScrollingState(); + virtual bool isTemporalState() const OVERRIDE { return true; } virtual bool onMouseDown(Editor* editor, Message* msg) OVERRIDE; virtual bool onMouseUp(Editor* editor, Message* msg) OVERRIDE; virtual bool onMouseMove(Editor* editor, Message* msg) OVERRIDE; diff --git a/src/widgets/editor/standby_state.cpp b/src/widgets/editor/standby_state.cpp index 774e46329..f303fe4d0 100644 --- a/src/widgets/editor/standby_state.cpp +++ b/src/widgets/editor/standby_state.cpp @@ -133,7 +133,7 @@ bool StandbyState::onMouseDown(Editor* editor, Message* msg) context->setActiveDocument(document); // Start scroll loop - if (msg->mouse.middle || clicked_ink->isScrollMovement()) { + if (msg->mouse.middle || clicked_ink->isScrollMovement()) { // TODO raw msg->mouse.middle here, this should be customizable editor->setState(EditorStatePtr(new ScrollingState())); editor->captureMouse(); return true;