mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-01 01:13:40 +00:00
Fix regression bug: user isn't able to copy pixels using Ctrl + selection tool.
+ The problem is that "Ctrl" key is a quicktool (move cel), and it was stealing the "Ctrl" key to the selection tool. + Added <spriteeditor> section in gui.xml to specify which key is used to copy the selection (instead of moving). "Ctrl" is the default. + Added EditorCustomizationDelegate interface.
This commit is contained in:
parent
2623b1af99
commit
d55e4c58e4
@ -160,6 +160,13 @@
|
||||
<key tool="hand" shortcut="Space" />
|
||||
</quicktools>
|
||||
|
||||
<!-- Special keyboard shortcuts for the sprite editor -->
|
||||
<spriteeditor>
|
||||
<!-- When you drag-and-drop the selection, pressing this
|
||||
keyboard shortcut you can copy instead of move -->
|
||||
<key action="CopySelection" shortcut="Ctrl" />
|
||||
</spriteeditor>
|
||||
|
||||
</keyboard>
|
||||
|
||||
<menus>
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "ui_context.h"
|
||||
#include "util/misc.h"
|
||||
#include "widgets/editor/editor.h"
|
||||
#include "widgets/editor/editor_customization_delegate.h"
|
||||
#include "widgets/editor/editor_view.h"
|
||||
#include "widgets/popup_frame_pin.h"
|
||||
#include "widgets/statebar.h"
|
||||
@ -82,19 +83,22 @@ static void update_mini_editor_frame(Editor* editor);
|
||||
static void on_mini_editor_frame_close(CloseEvent& ev);
|
||||
|
||||
class WrappedEditor : public Editor,
|
||||
public EditorListener
|
||||
public EditorListener,
|
||||
public EditorCustomizationDelegate
|
||||
{
|
||||
public:
|
||||
WrappedEditor() {
|
||||
addListener(this);
|
||||
setCustomizationDelegate(this);
|
||||
}
|
||||
|
||||
~WrappedEditor() {
|
||||
removeListener(this);
|
||||
setCustomizationDelegate(NULL);
|
||||
}
|
||||
|
||||
// EditorListener implementation
|
||||
void dispose() {
|
||||
void dispose() OVERRIDE {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@ -111,6 +115,19 @@ public:
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
// EditorCustomizationDelegate implementation
|
||||
tools::Tool* getQuickTool(tools::Tool* currentTool) OVERRIDE {
|
||||
return get_selected_quicktool(currentTool);
|
||||
}
|
||||
|
||||
bool isCopySelectionKeyPressed() OVERRIDE {
|
||||
JAccel accel = get_accel_to_copy_selection();
|
||||
if (accel)
|
||||
return jaccel_check_from_key(accel);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class MiniEditor : public Editor
|
||||
|
@ -29,13 +29,14 @@
|
||||
#endif
|
||||
|
||||
#include "app.h"
|
||||
#include "base/memory.h"
|
||||
#include "base/shared_ptr.h"
|
||||
#include "commands/command.h"
|
||||
#include "commands/commands.h"
|
||||
#include "commands/params.h"
|
||||
#include "console.h"
|
||||
#include "drop_files.h"
|
||||
#include "document_wrappers.h"
|
||||
#include "drop_files.h"
|
||||
#include "gfxmode.h"
|
||||
#include "gui/gui.h"
|
||||
#include "gui/intern.h"
|
||||
@ -50,6 +51,7 @@
|
||||
#include "skin/button_icon_impl.h"
|
||||
#include "skin/skin_property.h"
|
||||
#include "skin/skin_theme.h"
|
||||
#include "tools/ink.h"
|
||||
#include "tools/tool_box.h"
|
||||
#include "ui_context.h"
|
||||
#include "widgets/editor/editor.h"
|
||||
@ -62,6 +64,8 @@
|
||||
|
||||
#define MONITOR_TIMER_MSECS 100
|
||||
|
||||
#define SPRITEDITOR_ACTION_COPYSELECTION "CopySelection"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
using namespace gfx;
|
||||
@ -86,7 +90,8 @@ static GfxMode lastWorkingGfxMode;
|
||||
|
||||
enum ShortcutType { Shortcut_ExecuteCommand,
|
||||
Shortcut_ChangeTool,
|
||||
Shortcut_EditorQuicktool };
|
||||
Shortcut_EditorQuicktool,
|
||||
Shortcut_SpriteEditor };
|
||||
|
||||
struct Shortcut
|
||||
{
|
||||
@ -95,6 +100,7 @@ struct Shortcut
|
||||
union {
|
||||
Command* command;
|
||||
tools::Tool* tool;
|
||||
char* action;
|
||||
};
|
||||
Params* params;
|
||||
|
||||
@ -110,6 +116,7 @@ struct Shortcut
|
||||
static Shortcut* get_keyboard_shortcut_for_command(const char* command_name, Params* params);
|
||||
static Shortcut* get_keyboard_shortcut_for_tool(tools::Tool* tool);
|
||||
static Shortcut* get_keyboard_shortcut_for_quicktool(tools::Tool* tool);
|
||||
static Shortcut* get_keyboard_shortcut_for_spriteeditor(const char* action_name);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -835,7 +842,6 @@ CheckBox* check_button_new(const char *text, int b1, int b2, int b3, int b4)
|
||||
JAccel add_keyboard_shortcut_to_execute_command(const char* shortcut_string, const char* command_name, Params* params)
|
||||
{
|
||||
Shortcut* shortcut = get_keyboard_shortcut_for_command(command_name, params);
|
||||
|
||||
if (!shortcut) {
|
||||
shortcut = new Shortcut(Shortcut_ExecuteCommand);
|
||||
shortcut->command = CommandsModule::instance()->getCommandByName(command_name);
|
||||
@ -851,7 +857,6 @@ JAccel add_keyboard_shortcut_to_execute_command(const char* shortcut_string, con
|
||||
JAccel add_keyboard_shortcut_to_change_tool(const char* shortcut_string, tools::Tool* tool)
|
||||
{
|
||||
Shortcut* shortcut = get_keyboard_shortcut_for_tool(tool);
|
||||
|
||||
if (!shortcut) {
|
||||
shortcut = new Shortcut(Shortcut_ChangeTool);
|
||||
shortcut->tool = tool;
|
||||
@ -866,7 +871,6 @@ JAccel add_keyboard_shortcut_to_change_tool(const char* shortcut_string, tools::
|
||||
JAccel add_keyboard_shortcut_to_quicktool(const char* shortcut_string, tools::Tool* tool)
|
||||
{
|
||||
Shortcut* shortcut = get_keyboard_shortcut_for_quicktool(tool);
|
||||
|
||||
if (!shortcut) {
|
||||
shortcut = new Shortcut(Shortcut_EditorQuicktool);
|
||||
shortcut->tool = tool;
|
||||
@ -878,6 +882,20 @@ JAccel add_keyboard_shortcut_to_quicktool(const char* shortcut_string, tools::To
|
||||
return shortcut->accel;
|
||||
}
|
||||
|
||||
JAccel add_keyboard_shortcut_to_spriteeditor(const char* shortcut_string, const char* action_name)
|
||||
{
|
||||
Shortcut* shortcut = get_keyboard_shortcut_for_spriteeditor(action_name);
|
||||
if (!shortcut) {
|
||||
shortcut = new Shortcut(Shortcut_SpriteEditor);
|
||||
shortcut->action = base_strdup(action_name);
|
||||
|
||||
shortcuts->push_back(shortcut);
|
||||
}
|
||||
|
||||
shortcut->add_shortcut(shortcut_string);
|
||||
return shortcut->accel;
|
||||
}
|
||||
|
||||
Command* get_command_from_key_message(Message* msg)
|
||||
{
|
||||
for (std::vector<Shortcut*>::iterator
|
||||
@ -912,8 +930,23 @@ JAccel get_accel_to_change_tool(tools::Tool* tool)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tools::Tool* get_selected_quicktool()
|
||||
JAccel get_accel_to_copy_selection()
|
||||
{
|
||||
Shortcut* shortcut = get_keyboard_shortcut_for_spriteeditor(SPRITEDITOR_ACTION_COPYSELECTION);
|
||||
if (shortcut)
|
||||
return shortcut->accel;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tools::Tool* get_selected_quicktool(tools::Tool* currentTool)
|
||||
{
|
||||
if (currentTool && currentTool->getInk(0)->isSelection()) {
|
||||
JAccel copyselection_accel = get_accel_to_copy_selection();
|
||||
if (copyselection_accel && jaccel_check_from_key(copyselection_accel))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tools::ToolBox* toolbox = App::instance()->getToolBox();
|
||||
|
||||
// Iterate over all tools
|
||||
@ -941,6 +974,8 @@ Shortcut::Shortcut(ShortcutType type)
|
||||
Shortcut::~Shortcut()
|
||||
{
|
||||
delete params;
|
||||
if (type == Shortcut_SpriteEditor)
|
||||
base_free(action);
|
||||
jaccel_free(accel);
|
||||
}
|
||||
|
||||
@ -1021,6 +1056,21 @@ static Shortcut* get_keyboard_shortcut_for_quicktool(tools::Tool* tool)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Shortcut* get_keyboard_shortcut_for_spriteeditor(const char* action_name)
|
||||
{
|
||||
for (std::vector<Shortcut*>::iterator
|
||||
it = shortcuts->begin(); it != shortcuts->end(); ++it) {
|
||||
Shortcut* shortcut = *it;
|
||||
|
||||
if (shortcut->type == Shortcut_SpriteEditor &&
|
||||
strcmp(shortcut->action, action_name) == 0) {
|
||||
return shortcut;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Adds a routine to be called each 100 milliseconds to monitor
|
||||
// whatever you want. It's mainly used to monitor the progress of a
|
||||
// file-operation (see @ref fop_operate)
|
||||
|
@ -110,11 +110,14 @@ CheckBox* check_button_new(const char* text, int b1, int b2, int b3, int b4);
|
||||
JAccel add_keyboard_shortcut_to_execute_command(const char* shortcut, const char* command_name, Params* params);
|
||||
JAccel add_keyboard_shortcut_to_change_tool(const char* shortcut, tools::Tool* tool);
|
||||
JAccel add_keyboard_shortcut_to_quicktool(const char* shortcut, tools::Tool* tool);
|
||||
JAccel add_keyboard_shortcut_to_spriteeditor(const char* shortcut, const char* action_name);
|
||||
|
||||
Command* get_command_from_key_message(Message* msg);
|
||||
JAccel get_accel_to_execute_command(const char* command, Params* params = NULL);
|
||||
JAccel get_accel_to_change_tool(tools::Tool* tool);
|
||||
tools::Tool* get_selected_quicktool();
|
||||
JAccel get_accel_to_copy_selection();
|
||||
|
||||
tools::Tool* get_selected_quicktool(tools::Tool* currentTool);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Monitors
|
||||
|
@ -184,12 +184,8 @@ static int load_root_menu()
|
||||
xmlKey = xmlKey->NextSiblingElement();
|
||||
}
|
||||
|
||||
/**************************************************/
|
||||
/* load keyboard shortcuts for tools */
|
||||
/**************************************************/
|
||||
|
||||
// Load keyboard shortcuts for tools
|
||||
PRINTF(" - Loading tools keyboard shortcuts from \"%s\"...\n", path);
|
||||
|
||||
// <gui><keyboard><tools><key>
|
||||
xmlKey = handle
|
||||
.FirstChild("gui")
|
||||
@ -207,16 +203,10 @@ static int load_root_menu()
|
||||
add_keyboard_shortcut_to_change_tool(tool_key, tool);
|
||||
}
|
||||
}
|
||||
|
||||
xmlKey = xmlKey->NextSiblingElement();
|
||||
}
|
||||
|
||||
/**************************************************/
|
||||
/* load keyboard shortcuts for quicktools */
|
||||
/**************************************************/
|
||||
|
||||
PRINTF(" - Loading tools keyboard shortcuts from \"%s\"...\n", path);
|
||||
|
||||
// Load keyboard shortcuts for quicktools
|
||||
// <gui><keyboard><quicktools><key>
|
||||
xmlKey = handle
|
||||
.FirstChild("gui")
|
||||
@ -234,7 +224,24 @@ static int load_root_menu()
|
||||
add_keyboard_shortcut_to_quicktool(tool_key, tool);
|
||||
}
|
||||
}
|
||||
xmlKey = xmlKey->NextSiblingElement();
|
||||
}
|
||||
|
||||
// Load special keyboard shortcuts for sprite editor customization
|
||||
// <gui><keyboard><spriteeditor>
|
||||
xmlKey = handle
|
||||
.FirstChild("gui")
|
||||
.FirstChild("keyboard")
|
||||
.FirstChild("spriteeditor")
|
||||
.FirstChild("key").ToElement();
|
||||
while (xmlKey) {
|
||||
const char* tool_action = xmlKey->Attribute("action");
|
||||
const char* tool_key = xmlKey->Attribute("shortcut");
|
||||
|
||||
if (tool_action && tool_key) {
|
||||
PRINTF(" - Shortcut for sprite editor `%s': <%s>\n", tool_action, tool_key);
|
||||
add_keyboard_shortcut_to_spriteeditor(tool_key, tool_action);
|
||||
}
|
||||
xmlKey = xmlKey->NextSiblingElement();
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "util/misc.h"
|
||||
#include "util/render.h"
|
||||
#include "widgets/color_bar.h"
|
||||
#include "widgets/editor/editor_customization_delegate.h"
|
||||
#include "widgets/editor/editor_decorator.h"
|
||||
#include "widgets/editor/standby_state.h"
|
||||
#include "widgets/statebar.h"
|
||||
@ -118,6 +119,7 @@ Editor::Editor()
|
||||
: Widget(editor_type())
|
||||
, m_defaultState(EditorStatePtr(new StandbyState()))
|
||||
, m_state(m_defaultState)
|
||||
, m_customizationDelegate(NULL)
|
||||
{
|
||||
m_document = NULL;
|
||||
m_sprite = NULL;
|
||||
@ -147,6 +149,8 @@ Editor::Editor()
|
||||
|
||||
Editor::~Editor()
|
||||
{
|
||||
setCustomizationDelegate(NULL);
|
||||
|
||||
jmanager_remove_timer(m_mask_timer_id);
|
||||
remove_editor(this);
|
||||
|
||||
@ -773,6 +777,14 @@ void Editor::removeListener(EditorListener* listener)
|
||||
m_listeners.removeListener(listener);
|
||||
}
|
||||
|
||||
void Editor::setCustomizationDelegate(EditorCustomizationDelegate* delegate)
|
||||
{
|
||||
if (m_customizationDelegate)
|
||||
m_customizationDelegate->dispose();
|
||||
|
||||
m_customizationDelegate = delegate;
|
||||
}
|
||||
|
||||
// Returns the visible area of the active sprite.
|
||||
Rect Editor::getVisibleSpriteBounds()
|
||||
{
|
||||
@ -818,14 +830,18 @@ void Editor::updateStatusBar()
|
||||
|
||||
void Editor::editor_update_quicktool()
|
||||
{
|
||||
tools::Tool* old_quicktool = m_quicktool;
|
||||
if (m_customizationDelegate) {
|
||||
UIContext* context = UIContext::instance();
|
||||
tools::Tool* current_tool = context->getSettings()->getCurrentTool();
|
||||
tools::Tool* old_quicktool = m_quicktool;
|
||||
|
||||
m_quicktool = get_selected_quicktool();
|
||||
m_quicktool = m_customizationDelegate->getQuickTool(current_tool);
|
||||
|
||||
// If the tool has changed, we must to update the status bar because
|
||||
// the new tool can display something different in the status bar (e.g. Eyedropper)
|
||||
if (old_quicktool != m_quicktool)
|
||||
updateStatusBar();
|
||||
// If the tool has changed, we must to update the status bar because
|
||||
// the new tool can display something different in the status bar (e.g. Eyedropper)
|
||||
if (old_quicktool != m_quicktool)
|
||||
updateStatusBar();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@ -33,6 +33,7 @@
|
||||
#define MAX_ZOOM 5
|
||||
|
||||
class Context;
|
||||
class EditorCustomizationDelegate;
|
||||
class PixelsMovement;
|
||||
class Sprite;
|
||||
class View;
|
||||
@ -105,6 +106,12 @@ public:
|
||||
void addListener(EditorListener* listener);
|
||||
void removeListener(EditorListener* listener);
|
||||
|
||||
void setCustomizationDelegate(EditorCustomizationDelegate* delegate);
|
||||
|
||||
EditorCustomizationDelegate* getCustomizationDelegate() {
|
||||
return m_customizationDelegate;
|
||||
}
|
||||
|
||||
// Returns the visible area of the active sprite.
|
||||
gfx::Rect getVisibleSpriteBounds();
|
||||
|
||||
@ -225,6 +232,8 @@ private:
|
||||
|
||||
EditorListeners m_listeners;
|
||||
|
||||
EditorCustomizationDelegate* m_customizationDelegate;
|
||||
|
||||
};
|
||||
|
||||
int editor_type();
|
||||
|
44
src/widgets/editor/editor_customization_delegate.h
Normal file
44
src/widgets/editor/editor_customization_delegate.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* 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_CUSTOMIZATION_DELEGATE_H_INCLUDED
|
||||
#define WIDGETS_EDITOR_CUSTOMIZATION_DELEGATE_H_INCLUDED
|
||||
|
||||
class Editor;
|
||||
|
||||
namespace tools {
|
||||
class Tool;
|
||||
}
|
||||
|
||||
class EditorCustomizationDelegate
|
||||
{
|
||||
public:
|
||||
virtual ~EditorCustomizationDelegate() { }
|
||||
virtual void dispose() = 0;
|
||||
|
||||
// Called to know if the user is pressing a keyboard shortcut to
|
||||
// select another tool temporarily (a "quick tool"). The given
|
||||
// "currentTool" is the current tool selected in the toolbox.
|
||||
virtual tools::Tool* getQuickTool(tools::Tool* currentTool) = 0;
|
||||
|
||||
// Returns true if the user wants to copy the selection instead of
|
||||
// to move it.
|
||||
virtual bool isCopySelectionKeyPressed() = 0;
|
||||
};
|
||||
|
||||
#endif // WIDGETS_EDITOR_CUSTOMIZATION_DELEGATE_H_INCLUDED
|
@ -33,6 +33,7 @@
|
||||
#include "tools/tool.h"
|
||||
#include "util/misc.h"
|
||||
#include "widgets/editor/editor.h"
|
||||
#include "widgets/editor/editor_customization_delegate.h"
|
||||
#include "widgets/editor/pixels_movement.h"
|
||||
#include "widgets/editor/standby_state.h"
|
||||
#include "widgets/statebar.h"
|
||||
@ -41,6 +42,8 @@
|
||||
|
||||
MovingPixelsState::MovingPixelsState(Editor* editor, Message* msg, Image* imge, int x, int y, int opacity)
|
||||
{
|
||||
EditorCustomizationDelegate* customization = editor->getCustomizationDelegate();
|
||||
|
||||
// Copy the mask to the extra cel image
|
||||
Document* document = editor->getDocument();
|
||||
Sprite* sprite = editor->getSprite();
|
||||
@ -50,8 +53,8 @@ MovingPixelsState::MovingPixelsState(Editor* editor, Message* msg, Image* imge,
|
||||
m_pixelsMovement = new PixelsMovement(document, sprite, tmpImage, x, y, opacity);
|
||||
delete tmpImage;
|
||||
|
||||
// If the CTRL key is pressed start dragging a copy of the selection
|
||||
if (key[KEY_LCONTROL] || key[KEY_RCONTROL]) // TODO configurable
|
||||
// If the Ctrl key is pressed start dragging a copy of the selection
|
||||
if (customization && customization->isCopySelectionKeyPressed())
|
||||
m_pixelsMovement->copyMask();
|
||||
else
|
||||
m_pixelsMovement->cutMask();
|
||||
@ -205,9 +208,9 @@ bool MovingPixelsState::onSetCursor(Editor* editor)
|
||||
bool MovingPixelsState::onKeyDown(Editor* editor, Message* msg)
|
||||
{
|
||||
ASSERT(m_pixelsMovement != NULL);
|
||||
EditorCustomizationDelegate* customization = editor->getCustomizationDelegate();
|
||||
|
||||
if (msg->key.scancode == KEY_LCONTROL || // TODO configurable
|
||||
msg->key.scancode == KEY_RCONTROL) {
|
||||
if (customization && customization->isCopySelectionKeyPressed()) {
|
||||
// If the user press the CTRL key when he is dragging pixels (but
|
||||
// not pressing the mouse buttons).
|
||||
if (!jmouse_b(0) && m_pixelsMovement) {
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "widgets/color_bar.h"
|
||||
#include "widgets/editor/drawing_state.h"
|
||||
#include "widgets/editor/editor.h"
|
||||
#include "widgets/editor/editor_customization_delegate.h"
|
||||
#include "widgets/editor/moving_cel_state.h"
|
||||
#include "widgets/editor/moving_pixels_state.h"
|
||||
#include "widgets/editor/scrolling_state.h"
|
||||
@ -286,10 +287,11 @@ bool StandbyState::onSetCursor(Editor* editor)
|
||||
if (current_ink->isSelection()) {
|
||||
// Move pixels
|
||||
if (editor->isInsideSelection()) {
|
||||
EditorCustomizationDelegate* customization = editor->getCustomizationDelegate();
|
||||
|
||||
editor->hideDrawingCursor();
|
||||
|
||||
if (key[KEY_LCONTROL] ||
|
||||
key[KEY_RCONTROL]) // TODO configurable keys
|
||||
if (customization && customization->isCopySelectionKeyPressed())
|
||||
jmouse_set_cursor(JI_CURSOR_NORMAL_ADD);
|
||||
else
|
||||
jmouse_set_cursor(JI_CURSOR_MOVE);
|
||||
|
Loading…
x
Reference in New Issue
Block a user