Remove the editor's default state. Now the editor has a decorator property.

+ Removed Editor::setDefaultState.
+ Removed EditorState::getDecorator.
+ Added Editor::get/setDecorator.
+ Added EditorStatesHistory class and Editor::backToPreviousState() method.
+ Added EditorState::onBeforePopState event.
This commit is contained in:
David Capello 2011-11-13 20:40:19 -03:00
parent 18a0a2a8c7
commit 4f6c43edc5
15 changed files with 213 additions and 66 deletions

View File

@ -310,6 +310,7 @@ add_library(aseprite-library
widgets/editor/drawing_state.cpp
widgets/editor/editor.cpp
widgets/editor/editor_listeners.cpp
widgets/editor/editor_states_history.cpp
widgets/editor/editor_view.cpp
widgets/editor/keys.cpp
widgets/editor/moving_cel_state.cpp

View File

@ -74,12 +74,12 @@ public:
m_top ->EntryChange.connect(Bind<void>(&CanvasSizeFrame::onEntriesChange, this));
m_bottom->EntryChange.connect(Bind<void>(&CanvasSizeFrame::onEntriesChange, this));
m_editor->setDefaultState(m_selectBoxState);
m_editor->setState(m_selectBoxState);
}
~CanvasSizeFrame()
{
m_editor->setDefaultState(EditorStatePtr(new StandbyState));
m_editor->backToPreviousState();
}
bool pressedOk() { return get_killer() == m_ok; }

View File

@ -275,16 +275,18 @@ private:
if (m_document && !m_editor) {
m_rect = gfx::Rect(0, 0, 16, 16);
m_editor = current_editor;
m_editor->setDefaultState(EditorStatePtr(new SelectBoxState(this, m_rect,
SelectBoxState::PaintRulers |
SelectBoxState::PaintGrid)));
EditorStatePtr newState(new SelectBoxState(this, m_rect,
SelectBoxState::PaintRulers |
SelectBoxState::PaintGrid));
m_editor->setState(newState);
}
}
void releaseEditor()
{
if (m_editor) {
m_editor->setDefaultState(EditorStatePtr(new StandbyState));
m_editor->backToPreviousState();
m_editor = NULL;
}
}

View File

@ -80,7 +80,7 @@ bool DrawingState::onMouseDown(Editor* editor, Message* msg)
m_toolLoopManager = NULL;
// Change to standby state
editor->setState(editor->getDefaultState());
editor->backToPreviousState();
editor->releaseMouse();
}
@ -98,7 +98,7 @@ bool DrawingState::onMouseUp(Editor* editor, Message* msg)
m_toolLoopManager->releaseLoop(pointer_from_msg(msg));
// Back to standby state.
editor->setState(editor->getDefaultState());
editor->backToPreviousState();
editor->releaseMouse();
return true;
}

View File

@ -117,10 +117,13 @@ private:
Editor::Editor()
: Widget(editor_type())
, m_defaultState(EditorStatePtr(new StandbyState()))
, m_state(m_defaultState)
, m_state(new StandbyState())
, m_decorator(NULL)
, m_customizationDelegate(NULL)
{
// Add the first state into the history.
m_statesHistory.push(m_state);
m_document = NULL;
m_sprite = NULL;
m_zoom = 0;
@ -171,22 +174,31 @@ int editor_type()
return type;
}
void Editor::setDefaultState(const EditorStatePtr& newState)
{
m_defaultState = newState;
setState(newState);
}
void Editor::setState(const EditorStatePtr& newState)
void Editor::setStateInternal(const EditorStatePtr& newState)
{
hideDrawingCursor();
// Fire before change state event, set the state, and fire after
// change state event.
m_state->onBeforeChangeState(this);
bool keepInHistory = m_state->onBeforeChangeState(this);
// Push a new state
if (newState) {
if (!keepInHistory)
m_statesHistory.pop();
m_statesHistory.push(newState);
m_state = newState;
}
// Go to previous state
else {
m_state->onBeforePopState(this);
m_statesHistory.pop();
m_state = m_statesHistory.top();
}
// Change to the new state.
m_state = newState;
m_state->onAfterChangeState(this);
// Redraw all the editors with the same document of this editor
@ -205,13 +217,24 @@ void Editor::setState(const EditorStatePtr& newState)
updateStatusBar();
}
void Editor::setState(const EditorStatePtr& newState)
{
setStateInternal(newState);
}
void Editor::backToPreviousState()
{
setStateInternal(EditorStatePtr(NULL));
}
void Editor::setDocument(Document* document)
{
//if (this->hasMouse())
//jmanager_free_mouse(); // TODO Why is this here? Review this code
// Reset current state.
setDefaultState(EditorStatePtr(new StandbyState));
// Reset all states (back to standby).
m_statesHistory.clear();
setState(EditorStatePtr(new StandbyState));
if (m_cursor_thick)
editor_clean_cursor();
@ -404,10 +427,10 @@ void Editor::drawSprite(int x1, int y1, int x2, int y2)
if (rendered) {
// Pre-render decorator.
if (EditorDecorator* decorator = m_defaultState->getDecorator()) {
if (m_decorator) {
EditorPreRenderImpl preRender(this, rendered,
Point(-source_x, -source_y), m_zoom);
decorator->preRenderDecorator(&preRender);
m_decorator->preRenderDecorator(&preRender);
}
#ifdef DRAWSPRITE_DOUBLEBUFFERED
@ -446,9 +469,9 @@ void Editor::drawSprite(int x1, int y1, int x2, int y2)
settings->getGridColor());
// Post-render decorator.
if (EditorDecorator* decorator = m_defaultState->getDecorator()) {
if (m_decorator) {
EditorPostRenderImpl postRender(this);
decorator->postRenderDecorator(&postRender);
m_decorator->postRenderDecorator(&postRender);
}
}

View File

@ -21,13 +21,13 @@
#include "app/color.h"
#include "base/compiler_specific.h"
#include "base/shared_ptr.h"
#include "base/signal.h"
#include "document.h"
#include "gui/base.h"
#include "gui/widget.h"
#include "widgets/editor/editor_listeners.h"
#include "widgets/editor/editor_state.h"
#include "widgets/editor/editor_states_history.h"
#define MIN_ZOOM 0
#define MAX_ZOOM 5
@ -42,25 +42,26 @@ namespace tools {
class Tool;
}
typedef SharedPtr<EditorState> EditorStatePtr;
class Editor : public Widget
{
public:
// in editor.c
Editor();
~Editor();
EditorStatePtr getDefaultState() { return m_defaultState; }
// Returns the current state.
EditorStatePtr getState() { return m_state; }
// Changes the state of the editor and uses it as the default one.
void setDefaultState(const EditorStatePtr& newState);
// Changes the state of the editor.
void setState(const EditorStatePtr& newState);
// Backs to previous state.
void backToPreviousState();
// Gets/sets the current decorator. The decorator is not owned by
// the Editor, so it must be deleted by the caller.
EditorDecorator* getDecorator() { return m_decorator; }
void setDecorator(EditorDecorator* decorator) { m_decorator = decorator; }
Document* getDocument() { return m_document; }
void setDocument(Document* document);
@ -145,15 +146,6 @@ public:
static void editor_cursor_init();
static void editor_cursor_exit();
private:
void editor_update_quicktool();
void editor_draw_cursor(int x, int y, bool refresh = true);
void editor_move_cursor(int x, int y, bool refresh = true);
void editor_clean_cursor(bool refresh = true);
bool editor_cursor_is_subpixel();
public:
// click.c
enum {
@ -180,6 +172,13 @@ protected:
}
private:
void setStateInternal(const EditorStatePtr& newState);
void editor_update_quicktool();
void editor_draw_cursor(int x, int y, bool refresh = true);
void editor_move_cursor(int x, int y, bool refresh = true);
void editor_clean_cursor(bool refresh = true);
bool editor_cursor_is_subpixel();
void drawGrid(const gfx::Rect& gridBounds, const Color& color);
void editor_request_size(int *w, int *h);
@ -189,15 +188,15 @@ private:
int sprite_x, int sprite_y, int color,
void (*pixel)(BITMAP *bmp, int x, int y, int color));
// Default state when the editor is in standby (generally
// StandbyState). Transitory states should back to the default
// state (e.g. ScrollingState returns to the default state when the
// mouse button is released).
EditorStatePtr m_defaultState;
// Stack of states. The top element in the stack is the current state (m_state).
EditorStatesHistory m_statesHistory;
// Current editor state (it can be shared between several editors to
// the same document). This member cannot be NULL.
EditorStatePtr m_state;
// Current decorator (to draw extra UI elements).
EditorDecorator* m_decorator;
Document* m_document; // Active document in the editor
Sprite* m_sprite; // Active sprite in the editor

View File

@ -20,6 +20,7 @@
#define WIDGETS_EDITOR_EDITOR_STATE_H_INCLUDED
#include "base/disable_copying.h"
#include "base/shared_ptr.h"
class Editor;
class EditorDecorator;
@ -36,14 +37,20 @@ public:
EditorState() { }
virtual ~EditorState() { }
// Called just before this state is deleted and replaced by a new
// state in the Editor::setState() method.
virtual void onBeforeChangeState(Editor* editor) { }
// 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; }
// Called when this instance is set as the new Editor's state when
// Editor::setState() method is used.
virtual void onAfterChangeState(Editor* editor) { }
// Called just before the state will be removed from the
// EditorStatesHistory. This event is useful to remove the
// decorator from the editor.
virtual void onBeforePopState(Editor* editor) { }
// Called when the current tool in the tool bar changes. It is
// useful for states which depends on the selected current tool (as
// MovingPixelsState which drops the pixels in case the user selects
@ -80,11 +87,10 @@ public:
// drawing cursor.
virtual bool requirePenPreview() { return false; }
// Called after the sprite is painted.
virtual EditorDecorator* getDecorator() { return NULL; }
private:
DISABLE_COPYING(EditorState);
};
typedef SharedPtr<EditorState> EditorStatePtr;
#endif // WIDGETS_EDITOR_EDITOR_STATE_H_INCLUDED

View File

@ -0,0 +1,58 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2011 David Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "widgets/editor/editor_states_history.h"
EditorStatesHistory::EditorStatesHistory()
{
}
EditorStatesHistory::~EditorStatesHistory()
{
clear();
}
EditorStatePtr EditorStatesHistory::top()
{
return (!m_states.empty() ? m_states.back(): EditorStatePtr(NULL));
}
void EditorStatesHistory::push(const EditorStatePtr& state)
{
ASSERT(state != NULL);
m_states.push_back(state);
}
void EditorStatesHistory::pop()
{
ASSERT(!m_states.empty());
m_states.pop_back();
}
void EditorStatesHistory::clear()
{
// Free shared pointers in reverse order
std::vector<EditorStatePtr>::reverse_iterator it = m_states.rbegin();
std::vector<EditorStatePtr>::reverse_iterator end = m_states.rend();
for (; it != end; ++it)
(*it).reset();
m_states.clear();
}

View File

@ -0,0 +1,52 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2011 David Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef WIDGETS_EDITOR_STATES_HISTORY_H_INCLUDED
#define WIDGETS_EDITOR_STATES_HISTORY_H_INCLUDED
#include "widgets/editor/editor_state.h"
#include <vector>
// Stack of states in the editor. The top state is the current state
// of the editor.
class EditorStatesHistory
{
public:
EditorStatesHistory();
~EditorStatesHistory();
// Gets the current state.
EditorStatePtr top();
// Adds a new state in the history.
void push(const EditorStatePtr& state);
// Removes a state from the history (you should keep a reference of
// the state with top() if you want to keep it in memory).
void pop();
// Deletes all the history.
void clear();
private:
// Stack of states (the back of the vector is the top of the stack).
std::vector<EditorStatePtr> m_states;
};
#endif

View File

@ -102,7 +102,7 @@ bool MovingCelState::onMouseUp(Editor* editor, Message* msg)
document->generateMaskBoundaries();
}
editor->setState(editor->getDefaultState());
editor->backToPreviousState();
editor->releaseMouse();
return true;
}

View File

@ -80,7 +80,7 @@ MovingPixelsState::~MovingPixelsState()
delete m_pixelsMovement;
}
void MovingPixelsState::onBeforeChangeState(Editor* editor)
bool MovingPixelsState::onBeforeChangeState(Editor* editor)
{
ASSERT(m_pixelsMovement != NULL);
@ -96,6 +96,7 @@ void MovingPixelsState::onBeforeChangeState(Editor* editor)
editor->releaseMouse();
app_get_statusbar()->hideMovePixelsOptions();
return false; // Don't keep this state in history
}
void MovingPixelsState::onCurrentToolChange(Editor* editor)
@ -274,6 +275,5 @@ void MovingPixelsState::dropPixels(Editor* editor)
{
// Just change to default state (StandbyState generally). We'll
// receive an onBeforeChangeState event after this call.
editor->setState(editor->getDefaultState());
editor->backToPreviousState();
}

View File

@ -33,7 +33,7 @@ public:
MovingPixelsState(Editor* editor, Message* msg, Image* imge, int x, int y, int opacity);
virtual ~MovingPixelsState();
virtual void onBeforeChangeState(Editor* editor) OVERRIDE;
virtual bool onBeforeChangeState(Editor* editor) 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

@ -45,7 +45,7 @@ bool ScrollingState::onMouseDown(Editor* editor, Message* msg)
bool ScrollingState::onMouseUp(Editor* editor, Message* msg)
{
editor->setState(editor->getDefaultState());
editor->backToPreviousState();
editor->releaseMouse();
return true;
}

View File

@ -56,6 +56,16 @@ void SelectBoxState::setBoxBounds(const gfx::Rect& box)
m_rulers[V2] = Ruler(Ruler::Vertical, box.x+box.w);
}
void SelectBoxState::onAfterChangeState(Editor* editor)
{
editor->setDecorator(this);
}
void SelectBoxState::onBeforePopState(Editor* editor)
{
editor->setDecorator(NULL);
}
bool SelectBoxState::onMouseDown(Editor* editor, Message* msg)
{
if (msg->mouse.left || msg->mouse.right) {
@ -135,11 +145,6 @@ bool SelectBoxState::onSetCursor(Editor* editor)
return false;
}
EditorDecorator* SelectBoxState::getDecorator()
{
return this;
}
void SelectBoxState::preRenderDecorator(EditorPreRender* render)
{
// Without black shadow?

View File

@ -53,11 +53,12 @@ public:
void setBoxBounds(const gfx::Rect& rc);
// EditorState overrides
virtual void onAfterChangeState(Editor* editor) OVERRIDE;
virtual void onBeforePopState(Editor* editor) OVERRIDE;
virtual bool onMouseDown(Editor* editor, Message* msg) OVERRIDE;
virtual bool onMouseUp(Editor* editor, Message* msg) OVERRIDE;
virtual bool onMouseMove(Editor* editor, Message* msg) OVERRIDE;
virtual bool onSetCursor(Editor* editor) OVERRIDE;
virtual EditorDecorator* getDecorator() OVERRIDE;
// Returns false as it overrides default standby state behavior &
// look. This state uses normal arrow cursors.