Add better support for Copy and Cut commands when the selection is being dragged.

This commit is contained in:
David Capello 2012-02-11 21:06:31 -03:00
parent 98fabee086
commit d5cfddd820
6 changed files with 106 additions and 4 deletions

View File

@ -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()

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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();