mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-17 13:20:45 +00:00
Add better support for Copy and Cut commands when the selection is being dragged.
This commit is contained in:
parent
98fabee086
commit
d5cfddd820
@ -155,10 +155,13 @@ void clipboard::copy(const DocumentReader& document)
|
||||
}
|
||||
}
|
||||
|
||||
void clipboard::copy_image(Image* image, Palette* pal)
|
||||
void clipboard::copy_image(Image* image, Palette* pal, const gfx::Point& point)
|
||||
{
|
||||
set_clipboard(image_new_copy(image),
|
||||
pal ? new Palette(*pal): NULL, true);
|
||||
|
||||
clipboard_x = point.x;
|
||||
clipboard_y = point.y;
|
||||
}
|
||||
|
||||
void clipboard::paste()
|
||||
|
@ -19,6 +19,7 @@
|
||||
#ifndef UTIL_CLIPBOARD_H_INCLUDED
|
||||
#define UTIL_CLIPBOARD_H_INCLUDED
|
||||
|
||||
#include "gfx/point.h"
|
||||
#include "gfx/size.h"
|
||||
#include "gui/base.h"
|
||||
|
||||
@ -28,11 +29,13 @@ class DocumentWriter;
|
||||
|
||||
namespace clipboard {
|
||||
|
||||
// TODO Horrible API: refactor it.
|
||||
|
||||
bool can_paste();
|
||||
|
||||
void cut(DocumentWriter& document);
|
||||
void copy(const DocumentReader& document);
|
||||
void copy_image(Image* image, Palette* palette);
|
||||
void copy_image(Image* image, Palette* palette, const gfx::Point& point);
|
||||
void paste();
|
||||
|
||||
// Returns true and fills the specified "size"" with the image's
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "app.h"
|
||||
#include "app/color_utils.h"
|
||||
#include "base/unique_ptr.h"
|
||||
#include "commands/command.h"
|
||||
#include "commands/commands.h"
|
||||
#include "gfx/rect.h"
|
||||
#include "gui/manager.h"
|
||||
@ -30,11 +31,13 @@
|
||||
#include "gui/system.h"
|
||||
#include "gui/view.h"
|
||||
#include "modules/editors.h"
|
||||
#include "modules/gui.h"
|
||||
#include "raster/mask.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "tools/ink.h"
|
||||
#include "tools/tool.h"
|
||||
#include "ui_context.h"
|
||||
#include "util/clipboard.h"
|
||||
#include "widgets/editor/editor.h"
|
||||
#include "widgets/editor/editor_customization_delegate.h"
|
||||
#include "widgets/editor/pixels_movement.h"
|
||||
@ -46,6 +49,7 @@
|
||||
|
||||
MovingPixelsState::MovingPixelsState(Editor* editor, Message* msg, PixelsMovement* pixelsMovement, HandleType handle)
|
||||
: m_currentEditor(editor)
|
||||
, m_discarded(false)
|
||||
{
|
||||
// MovingPixelsState needs a selection tool to avoid problems
|
||||
// sharing the extra cel between the drawing cursor preview and the
|
||||
@ -107,7 +111,8 @@ EditorState::BeforeChangeAction MovingPixelsState::onBeforeChangeState(Editor* e
|
||||
// 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();
|
||||
if (!m_discarded)
|
||||
m_pixelsMovement->dropImage();
|
||||
|
||||
editor->getDocument()->resetTransformation();
|
||||
|
||||
@ -290,7 +295,7 @@ bool MovingPixelsState::onKeyDown(Editor* editor, Message* msg)
|
||||
|
||||
if (msg->key.scancode == KEY_ENTER || // TODO make this key customizable
|
||||
msg->key.scancode == KEY_ENTER_PAD ||
|
||||
msg->key.scancode == KEY_ESC) {
|
||||
msg->key.scancode == KEY_ESC ) {
|
||||
dropPixels(editor);
|
||||
|
||||
// The escape key drop pixels and deselect the mask.
|
||||
@ -301,6 +306,38 @@ bool MovingPixelsState::onKeyDown(Editor* editor, Message* msg)
|
||||
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
Command* cmd = get_command_from_key_message(msg);
|
||||
if (cmd) {
|
||||
// Intercept the "Cut" or "Copy" command to handle them locally
|
||||
// with the current m_pixelsMovement data.
|
||||
if (strcmp(cmd->short_name(), CommandId::Cut) == 0 ||
|
||||
strcmp(cmd->short_name(), CommandId::Copy) == 0) {
|
||||
// Copy the floating image to the clipboard.
|
||||
{
|
||||
Document* document = editor->getDocument();
|
||||
gfx::Point origin;
|
||||
UniquePtr<Image> floatingImage(m_pixelsMovement->getDraggedImageCopy(origin));
|
||||
clipboard::copy_image(floatingImage.get(),
|
||||
document->getSprite()->getCurrentPalette(),
|
||||
origin);
|
||||
}
|
||||
|
||||
// In case of "Cut" command.
|
||||
if (strcmp(cmd->short_name(), CommandId::Cut) == 0) {
|
||||
// Discard the dragged image.
|
||||
m_pixelsMovement->discardImage();
|
||||
m_discarded = true;
|
||||
|
||||
// Quit from MovingPixelsState, back to standby.
|
||||
editor->backToPreviousState();
|
||||
}
|
||||
|
||||
// Return true because we've used the keyboard shortcut.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use StandbyState implementation
|
||||
return StandbyState::onKeyDown(editor, msg);
|
||||
|
@ -64,6 +64,10 @@ private:
|
||||
// Helper member to move/translate selection and pixels.
|
||||
PixelsMovement* m_pixelsMovement;
|
||||
Editor* m_currentEditor;
|
||||
|
||||
// True if the image was discarded (e.g. when a "Cut" command was
|
||||
// used to remove the dragged image).
|
||||
bool m_discarded;
|
||||
};
|
||||
|
||||
#endif // WIDGETS_EDITOR_MOVING_PIXELS_STATE_H_INCLUDED
|
||||
|
@ -350,11 +350,42 @@ gfx::Rect PixelsMovement::moveImage(int x, int y, MoveModifier moveModifier)
|
||||
return gfx::Rect(0, 0, m_sprite->getWidth(), m_sprite->getHeight());
|
||||
}
|
||||
|
||||
Image* PixelsMovement::getDraggedImageCopy(gfx::Point& origin)
|
||||
{
|
||||
gfx::Transformation::Corners corners;
|
||||
m_currentData.transformBox(corners);
|
||||
|
||||
gfx::Point leftTop(corners[0]);
|
||||
gfx::Point rightBottom(corners[0]);
|
||||
for (size_t i=1; i<corners.size(); ++i) {
|
||||
if (leftTop.x > corners[i].x) leftTop.x = corners[i].x;
|
||||
if (leftTop.y > corners[i].y) leftTop.y = corners[i].y;
|
||||
if (rightBottom.x < corners[i].x) rightBottom.x = corners[i].x;
|
||||
if (rightBottom.y < corners[i].y) rightBottom.y = corners[i].y;
|
||||
}
|
||||
|
||||
int width = rightBottom.x - leftTop.x;
|
||||
int height = rightBottom.y - leftTop.y;
|
||||
UniquePtr<Image> image(image_new(m_sprite->getImgType(), width, height));
|
||||
image_clear(image, image->mask_color);
|
||||
image_parallelogram(image, m_originalImage,
|
||||
corners.leftTop().x-leftTop.x, corners.leftTop().y-leftTop.y,
|
||||
corners.rightTop().x-leftTop.x, corners.rightTop().y-leftTop.y,
|
||||
corners.rightBottom().x-leftTop.x, corners.rightBottom().y-leftTop.y,
|
||||
corners.leftBottom().x-leftTop.x, corners.leftBottom().y-leftTop.y);
|
||||
|
||||
origin = leftTop;
|
||||
|
||||
return image.release();
|
||||
}
|
||||
|
||||
void PixelsMovement::stampImage()
|
||||
{
|
||||
const Cel* cel = m_documentReader->getExtraCel();
|
||||
const Image* image = m_documentReader->getExtraCelImage();
|
||||
|
||||
ASSERT(cel && image);
|
||||
|
||||
{
|
||||
DocumentWriter documentWriter(m_documentReader);
|
||||
{
|
||||
@ -420,14 +451,33 @@ void PixelsMovement::dropImage()
|
||||
{
|
||||
m_isDragging = false;
|
||||
|
||||
// Stamp the image in the current layer.
|
||||
stampImage();
|
||||
|
||||
// This is the end of the whole undo transaction.
|
||||
m_undoTransaction.commit();
|
||||
|
||||
// Destroy the extra cel (this cel will be used by the drawing
|
||||
// cursor surely).
|
||||
DocumentWriter documentWriter(m_documentReader);
|
||||
documentWriter->destroyExtraCel();
|
||||
}
|
||||
|
||||
void PixelsMovement::discardImage()
|
||||
{
|
||||
m_isDragging = false;
|
||||
|
||||
// Deselect the mask (here we don't stamp the image).
|
||||
m_undoTransaction.deselectMask();
|
||||
m_undoTransaction.commit();
|
||||
|
||||
// Destroy the extra cel and regenerate the mask boundaries (we've
|
||||
// just deselect the mask).
|
||||
DocumentWriter documentWriter(m_documentReader);
|
||||
documentWriter->destroyExtraCel();
|
||||
documentWriter->generateMaskBoundaries();
|
||||
}
|
||||
|
||||
bool PixelsMovement::isDragging() const
|
||||
{
|
||||
return m_isDragging;
|
||||
|
@ -63,11 +63,16 @@ public:
|
||||
// redrawn.
|
||||
gfx::Rect moveImage(int x, int y, MoveModifier moveModifier);
|
||||
|
||||
// Returns a copy of the current image being dragged with the
|
||||
// current transformation.
|
||||
Image* getDraggedImageCopy(gfx::Point& origin);
|
||||
|
||||
// Copies the image being dragged in the current position.
|
||||
void stampImage();
|
||||
|
||||
void dropImageTemporarily();
|
||||
void dropImage();
|
||||
void discardImage();
|
||||
bool isDragging() const;
|
||||
|
||||
gfx::Rect getImageBounds();
|
||||
|
Loading…
x
Reference in New Issue
Block a user