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="Exit" shortcut="Ctrl+Q" />
<key command="Exit" shortcut="Alt+F4" />
<key command="Cancel" shortcut="Esc" />
<!-- Edit -->
<key command="Undo" shortcut="Ctrl+Z" /> <key command="Undo" shortcut="Ctrl+U" />
<key command="Redo" shortcut="Ctrl+Y" />

View File

@ -122,6 +122,7 @@ add_library(aseprite-library
commands/cmd_about.cpp
commands/cmd_advanced_mode.cpp
commands/cmd_background_from_layer.cpp
commands/cmd_cancel.cpp
commands/cmd_canvas_size.cpp
commands/cmd_cel_properties.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(AutocropSprite)
FOR_EACH_COMMAND(BackgroundFromLayer)
FOR_EACH_COMMAND(Cancel)
FOR_EACH_COMMAND(CanvasSize)
FOR_EACH_COMMAND(CelProperties)
FOR_EACH_COMMAND(ChangeColor)

View File

@ -23,7 +23,9 @@
#include "app.h"
#include "app/color_utils.h"
#include "base/unique_ptr.h"
#include "commands/commands.h"
#include "gfx/rect.h"
#include "gui/manager.h"
#include "gui/message.h"
#include "gui/system.h"
#include "gui/view.h"
@ -32,6 +34,7 @@
#include "raster/sprite.h"
#include "tools/ink.h"
#include "tools/tool.h"
#include "ui_context.h"
#include "widgets/editor/editor.h"
#include "widgets/editor/editor_customization_delegate.h"
#include "widgets/editor/pixels_movement.h"
@ -42,6 +45,7 @@
#include <allegro.h>
MovingPixelsState::MovingPixelsState(Editor* editor, Message* msg, PixelsMovement* pixelsMovement, HandleType handle)
: m_currentEditor(editor)
{
// MovingPixelsState needs a selection tool to avoid problems
// 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
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);
// Show controls to modify the "pixels movement" options (e.g. the
// transparent color).
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()
{
UIContext::instance()->removeListener(this);
app_get_statusbar()->removeListener(this);
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)
@ -153,6 +176,13 @@ bool MovingPixelsState::onMouseDown(Editor* editor, Message* msg)
// Start "moving pixels" loop
if (editor->isInsideSelection() && (msg->mouse.left ||
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
int 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)
{
ASSERT(m_pixelsMovement != NULL);
EditorCustomizationDelegate* customization = editor->getCustomizationDelegate();
if (customization && customization->isCopySelectionKeyPressed()) {
// If the user presses the CTRL key when he is dragging pixels (but
// not pressing the mouse buttons).
if (!jmouse_b(0) && m_pixelsMovement) {
// Drop pixels (sure the user will press the mouse button to
// start dragging a copy).
dropPixels(editor);
if (msg->key.scancode == KEY_ENTER || // TODO make this key customizable
msg->key.scancode == KEY_ENTER_PAD ||
msg->key.scancode == KEY_ESC) {
dropPixels(editor);
// The escape key drop pixels and deselect the mask.
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;
}
// 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()
{
// Never called as MovingPixelsState is removed automatically as

View File

@ -20,6 +20,7 @@
#define WIDGETS_EDITOR_MOVING_PIXELS_STATE_H_INCLUDED
#include "base/compiler_specific.h"
#include "context_listener.h"
#include "widgets/editor/handle_type.h"
#include "widgets/editor/standby_state.h"
#include "widgets/statebar.h"
@ -28,12 +29,13 @@ class Editor;
class Image;
class PixelsMovement;
class MovingPixelsState : public StandbyState, StatusBarListener
class MovingPixelsState : public StandbyState, StatusBarListener, ContextListener
{
public:
MovingPixelsState(Editor* editor, Message* msg, PixelsMovement* pixelsMovement, HandleType handle);
virtual ~MovingPixelsState();
// EditorState
virtual BeforeChangeAction onBeforeChangeState(Editor* editor, EditorState* newState) OVERRIDE;
virtual void onCurrentToolChange(Editor* editor) OVERRIDE;
virtual bool onMouseDown(Editor* editor, Message* msg) OVERRIDE;
@ -45,6 +47,9 @@ public:
virtual bool onKeyUp(Editor* editor, Message* msg) OVERRIDE;
virtual bool onUpdateStatusBar(Editor* editor) OVERRIDE;
// ContextListener
virtual void onCommandBeforeExecution(Context* context) OVERRIDE;
virtual gfx::Transformation getTransformation(Editor* editor) OVERRIDE;
protected:
@ -58,6 +63,7 @@ private:
// Helper member to move/translate selection and pixels.
PixelsMovement* m_pixelsMovement;
Editor* m_currentEditor;
};
#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());
}
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()
{
m_isDragging = false;
@ -395,28 +420,12 @@ void PixelsMovement::dropImage()
{
m_isDragging = false;
const Cel* cel = m_documentReader->getExtraCel();
const Image* image = m_documentReader->getExtraCelImage();
stampImage();
{
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);
m_undoTransaction.commit();
image_merge(expandCelCanvas.getDestCanvas(), image,
-expandCelCanvas.getCel()->getX(),
-expandCelCanvas.getCel()->getY(),
cel->getOpacity(), BLEND_MODE_NORMAL);
expandCelCanvas.commit();
}
m_undoTransaction.commit();
documentWriter->destroyExtraCel();
}
DocumentWriter documentWriter(m_documentReader);
documentWriter->destroyExtraCel();
}
bool PixelsMovement::isDragging() const

View File

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