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).
This commit is contained in:
David Capello 2012-01-12 00:39:39 -03:00
parent 18de85f18e
commit 8f66325395
6 changed files with 48 additions and 16 deletions

View File

@ -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();

View File

@ -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.

View File

@ -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<Decorator*>(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();
}

View File

@ -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;

View File

@ -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;

View File

@ -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;