Improve the MovingPixelsState to support Enter and Esc keys to drop the pixels.

Also any executed command will drop the pixels and return the editor to
its standby state.
This commit is contained in:
David Capello 2012-02-06 00:17:42 -03:00
parent 354f6a15fa
commit 0d582f9d5f
8 changed files with 148 additions and 29 deletions

View File

@ -18,6 +18,7 @@
<key command="ScreenShot" shortcut="F12" /> <key command="ScreenShot" shortcut="F12" />
<key command="Exit" shortcut="Ctrl+Q" /> <key command="Exit" shortcut="Ctrl+Q" />
<key command="Exit" shortcut="Alt+F4" /> <key command="Exit" shortcut="Alt+F4" />
<key command="Cancel" shortcut="Esc" />
<!-- Edit --> <!-- Edit -->
<key command="Undo" shortcut="Ctrl+Z" /> <key command="Undo" shortcut="Ctrl+U" /> <key command="Undo" shortcut="Ctrl+Z" /> <key command="Undo" shortcut="Ctrl+U" />
<key command="Redo" shortcut="Ctrl+Y" /> <key command="Redo" shortcut="Ctrl+Y" />

View File

@ -122,6 +122,7 @@ add_library(aseprite-library
commands/cmd_about.cpp commands/cmd_about.cpp
commands/cmd_advanced_mode.cpp commands/cmd_advanced_mode.cpp
commands/cmd_background_from_layer.cpp commands/cmd_background_from_layer.cpp
commands/cmd_cancel.cpp
commands/cmd_canvas_size.cpp commands/cmd_canvas_size.cpp
commands/cmd_cel_properties.cpp commands/cmd_cel_properties.cpp
commands/cmd_change_color.cpp commands/cmd_change_color.cpp

View File

@ -0,0 +1,60 @@
/* ASEPRITE
* Copyright (C) 2001-2012 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 "commands/command.h"
#include "commands/commands.h"
#include "context.h"
#include "document.h"
#include "document_wrappers.h"
class CancelCommand : public Command
{
public:
CancelCommand();
Command* clone() { return new CancelCommand(*this); }
protected:
void onExecute(Context* context);
};
CancelCommand::CancelCommand()
: Command("Cancel",
"Cancel",
CmdUIOnlyFlag)
{
}
void CancelCommand::onExecute(Context* context)
{
if (context->checkFlags(ContextFlags::ActiveDocumentIsWritable |
ContextFlags::HasVisibleMask)) {
Command* cmd = CommandsModule::instance()->getCommandByName(CommandId::DeselectMask);
context->executeCommand(cmd);
}
}
//////////////////////////////////////////////////////////////////////
// CommandFactory
Command* CommandFactory::createCancelCommand()
{
return new CancelCommand;
}

View File

@ -20,6 +20,7 @@ FOR_EACH_COMMAND(About)
FOR_EACH_COMMAND(AdvancedMode) FOR_EACH_COMMAND(AdvancedMode)
FOR_EACH_COMMAND(AutocropSprite) FOR_EACH_COMMAND(AutocropSprite)
FOR_EACH_COMMAND(BackgroundFromLayer) FOR_EACH_COMMAND(BackgroundFromLayer)
FOR_EACH_COMMAND(Cancel)
FOR_EACH_COMMAND(CanvasSize) FOR_EACH_COMMAND(CanvasSize)
FOR_EACH_COMMAND(CelProperties) FOR_EACH_COMMAND(CelProperties)
FOR_EACH_COMMAND(ChangeColor) FOR_EACH_COMMAND(ChangeColor)

View File

@ -23,7 +23,9 @@
#include "app.h" #include "app.h"
#include "app/color_utils.h" #include "app/color_utils.h"
#include "base/unique_ptr.h" #include "base/unique_ptr.h"
#include "commands/commands.h"
#include "gfx/rect.h" #include "gfx/rect.h"
#include "gui/manager.h"
#include "gui/message.h" #include "gui/message.h"
#include "gui/system.h" #include "gui/system.h"
#include "gui/view.h" #include "gui/view.h"
@ -32,6 +34,7 @@
#include "raster/sprite.h" #include "raster/sprite.h"
#include "tools/ink.h" #include "tools/ink.h"
#include "tools/tool.h" #include "tools/tool.h"
#include "ui_context.h"
#include "widgets/editor/editor.h" #include "widgets/editor/editor.h"
#include "widgets/editor/editor_customization_delegate.h" #include "widgets/editor/editor_customization_delegate.h"
#include "widgets/editor/pixels_movement.h" #include "widgets/editor/pixels_movement.h"
@ -42,6 +45,7 @@
#include <allegro.h> #include <allegro.h>
MovingPixelsState::MovingPixelsState(Editor* editor, Message* msg, PixelsMovement* pixelsMovement, HandleType handle) MovingPixelsState::MovingPixelsState(Editor* editor, Message* msg, PixelsMovement* pixelsMovement, HandleType handle)
: m_currentEditor(editor)
{ {
// MovingPixelsState needs a selection tool to avoid problems // MovingPixelsState needs a selection tool to avoid problems
// sharing the extra cel between the drawing cursor preview and the // sharing the extra cel between the drawing cursor preview and the
@ -62,15 +66,34 @@ MovingPixelsState::MovingPixelsState(Editor* editor, Message* msg, PixelsMovemen
// Setup mask color // Setup mask color
setTransparentColor(app_get_statusbar()->getTransparentColor()); setTransparentColor(app_get_statusbar()->getTransparentColor());
// Add this class as:
// - listener of the UI context: so we know if the user wants to execute
// other command, so we can drop pixels.
// - listener of the status bar to know if the user has changed the
// transparent color.
UIContext::instance()->addListener(this);
app_get_statusbar()->addListener(this); app_get_statusbar()->addListener(this);
// Show controls to modify the "pixels movement" options (e.g. the
// transparent color).
app_get_statusbar()->showMovePixelsOptions(); app_get_statusbar()->showMovePixelsOptions();
// Add the current editor as filter for key message of the manager
// so we can catch the Enter key, and avoid to execute the
// PlayAnimation command.
jmanager_add_msg_filter(JM_KEYPRESSED, m_currentEditor);
jmanager_add_msg_filter(JM_KEYRELEASED, m_currentEditor);
} }
MovingPixelsState::~MovingPixelsState() MovingPixelsState::~MovingPixelsState()
{ {
UIContext::instance()->removeListener(this);
app_get_statusbar()->removeListener(this); app_get_statusbar()->removeListener(this);
delete m_pixelsMovement; delete m_pixelsMovement;
jmanager_remove_msg_filter(JM_KEYPRESSED, m_currentEditor);
jmanager_remove_msg_filter(JM_KEYRELEASED, m_currentEditor);
} }
EditorState::BeforeChangeAction MovingPixelsState::onBeforeChangeState(Editor* editor, EditorState* newState) EditorState::BeforeChangeAction MovingPixelsState::onBeforeChangeState(Editor* editor, EditorState* newState)
@ -153,6 +176,13 @@ bool MovingPixelsState::onMouseDown(Editor* editor, Message* msg)
// Start "moving pixels" loop // Start "moving pixels" loop
if (editor->isInsideSelection() && (msg->mouse.left || if (editor->isInsideSelection() && (msg->mouse.left ||
msg->mouse.right)) { msg->mouse.right)) {
// In case that the user is pressing the copy-selection keyboard shortcut.
EditorCustomizationDelegate* customization = editor->getCustomizationDelegate();
if (customization && customization->isCopySelectionKeyPressed()) {
// Stamp the pixels to create the copy.
m_pixelsMovement->stampImage();
}
// Re-catch the image // Re-catch the image
int x, y; int x, y;
editor->screenToEditor(msg->mouse.x, msg->mouse.y, &x, &y); editor->screenToEditor(msg->mouse.x, msg->mouse.y, &x, &y);
@ -257,15 +287,16 @@ bool MovingPixelsState::onSetCursor(Editor* editor)
bool MovingPixelsState::onKeyDown(Editor* editor, Message* msg) bool MovingPixelsState::onKeyDown(Editor* editor, Message* msg)
{ {
ASSERT(m_pixelsMovement != NULL); ASSERT(m_pixelsMovement != NULL);
EditorCustomizationDelegate* customization = editor->getCustomizationDelegate();
if (customization && customization->isCopySelectionKeyPressed()) { if (msg->key.scancode == KEY_ENTER || // TODO make this key customizable
// If the user presses the CTRL key when he is dragging pixels (but msg->key.scancode == KEY_ENTER_PAD ||
// not pressing the mouse buttons). msg->key.scancode == KEY_ESC) {
if (!jmouse_b(0) && m_pixelsMovement) { dropPixels(editor);
// Drop pixels (sure the user will press the mouse button to
// start dragging a copy). // The escape key drop pixels and deselect the mask.
dropPixels(editor); if (msg->key.scancode == KEY_ESC) { // TODO make this key customizable
Command* cmd = CommandsModule::instance()->getCommandByName(CommandId::DeselectMask);
UIContext::instance()->executeCommand(cmd);
} }
} }
@ -301,6 +332,13 @@ bool MovingPixelsState::onUpdateStatusBar(Editor* editor)
return true; return true;
} }
// Before executing any command, we drop the pixels (go back to standby).
void MovingPixelsState::onCommandBeforeExecution(Context* context)
{
if (m_pixelsMovement)
dropPixels(m_currentEditor);
}
void MovingPixelsState::dispose() void MovingPixelsState::dispose()
{ {
// Never called as MovingPixelsState is removed automatically as // Never called as MovingPixelsState is removed automatically as

View File

@ -20,6 +20,7 @@
#define WIDGETS_EDITOR_MOVING_PIXELS_STATE_H_INCLUDED #define WIDGETS_EDITOR_MOVING_PIXELS_STATE_H_INCLUDED
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "context_listener.h"
#include "widgets/editor/handle_type.h" #include "widgets/editor/handle_type.h"
#include "widgets/editor/standby_state.h" #include "widgets/editor/standby_state.h"
#include "widgets/statebar.h" #include "widgets/statebar.h"
@ -28,12 +29,13 @@ class Editor;
class Image; class Image;
class PixelsMovement; class PixelsMovement;
class MovingPixelsState : public StandbyState, StatusBarListener class MovingPixelsState : public StandbyState, StatusBarListener, ContextListener
{ {
public: public:
MovingPixelsState(Editor* editor, Message* msg, PixelsMovement* pixelsMovement, HandleType handle); MovingPixelsState(Editor* editor, Message* msg, PixelsMovement* pixelsMovement, HandleType handle);
virtual ~MovingPixelsState(); virtual ~MovingPixelsState();
// EditorState
virtual BeforeChangeAction onBeforeChangeState(Editor* editor, EditorState* newState) OVERRIDE; virtual BeforeChangeAction onBeforeChangeState(Editor* editor, EditorState* newState) OVERRIDE;
virtual void onCurrentToolChange(Editor* editor) OVERRIDE; virtual void onCurrentToolChange(Editor* editor) OVERRIDE;
virtual bool onMouseDown(Editor* editor, Message* msg) OVERRIDE; virtual bool onMouseDown(Editor* editor, Message* msg) OVERRIDE;
@ -45,6 +47,9 @@ public:
virtual bool onKeyUp(Editor* editor, Message* msg) OVERRIDE; virtual bool onKeyUp(Editor* editor, Message* msg) OVERRIDE;
virtual bool onUpdateStatusBar(Editor* editor) OVERRIDE; virtual bool onUpdateStatusBar(Editor* editor) OVERRIDE;
// ContextListener
virtual void onCommandBeforeExecution(Context* context) OVERRIDE;
virtual gfx::Transformation getTransformation(Editor* editor) OVERRIDE; virtual gfx::Transformation getTransformation(Editor* editor) OVERRIDE;
protected: protected:
@ -58,6 +63,7 @@ private:
// Helper member to move/translate selection and pixels. // Helper member to move/translate selection and pixels.
PixelsMovement* m_pixelsMovement; PixelsMovement* m_pixelsMovement;
Editor* m_currentEditor;
}; };
#endif // WIDGETS_EDITOR_MOVING_PIXELS_STATE_H_INCLUDED #endif // WIDGETS_EDITOR_MOVING_PIXELS_STATE_H_INCLUDED

View File

@ -350,6 +350,31 @@ gfx::Rect PixelsMovement::moveImage(int x, int y, MoveModifier moveModifier)
return gfx::Rect(0, 0, m_sprite->getWidth(), m_sprite->getHeight()); return gfx::Rect(0, 0, m_sprite->getWidth(), m_sprite->getHeight());
} }
void PixelsMovement::stampImage()
{
const Cel* cel = m_documentReader->getExtraCel();
const Image* image = m_documentReader->getExtraCelImage();
{
DocumentWriter documentWriter(m_documentReader);
{
// Expand the canvas to paste the image in the fully visible
// portion of sprite.
ExpandCelCanvas expandCelCanvas(documentWriter, m_sprite,
m_sprite->getCurrentLayer(), TILED_NONE);
image_merge(expandCelCanvas.getDestCanvas(), image,
-expandCelCanvas.getCel()->getX(),
-expandCelCanvas.getCel()->getY(),
cel->getOpacity(), BLEND_MODE_NORMAL);
expandCelCanvas.commit();
}
// TODO
// m_undoTransaction.commit();
}
}
void PixelsMovement::dropImageTemporarily() void PixelsMovement::dropImageTemporarily()
{ {
m_isDragging = false; m_isDragging = false;
@ -395,28 +420,12 @@ void PixelsMovement::dropImage()
{ {
m_isDragging = false; m_isDragging = false;
const Cel* cel = m_documentReader->getExtraCel(); stampImage();
const Image* image = m_documentReader->getExtraCelImage();
{ m_undoTransaction.commit();
DocumentWriter documentWriter(m_documentReader);
{
// Expand the canvas to paste the image in the fully visible
// portion of sprite.
ExpandCelCanvas expandCelCanvas(documentWriter, m_sprite,
m_sprite->getCurrentLayer(), TILED_NONE);
image_merge(expandCelCanvas.getDestCanvas(), image, DocumentWriter documentWriter(m_documentReader);
-expandCelCanvas.getCel()->getX(), documentWriter->destroyExtraCel();
-expandCelCanvas.getCel()->getY(),
cel->getOpacity(), BLEND_MODE_NORMAL);
expandCelCanvas.commit();
}
m_undoTransaction.commit();
documentWriter->destroyExtraCel();
}
} }
bool PixelsMovement::isDragging() const bool PixelsMovement::isDragging() const

View File

@ -63,6 +63,9 @@ public:
// redrawn. // redrawn.
gfx::Rect moveImage(int x, int y, MoveModifier moveModifier); gfx::Rect moveImage(int x, int y, MoveModifier moveModifier);
// Copies the image being dragged in the current position.
void stampImage();
void dropImageTemporarily(); void dropImageTemporarily();
void dropImage(); void dropImage();
bool isDragging() const; bool isDragging() const;