mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-10 15:40:31 +00:00
Add support to copy and paste layers between different documents
This commit is contained in:
parent
1391afb694
commit
5b5a2cfd9f
@ -20,8 +20,11 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "app/app.h"
|
||||||
#include "app/commands/command.h"
|
#include "app/commands/command.h"
|
||||||
#include "app/context_access.h"
|
#include "app/context_access.h"
|
||||||
|
#include "app/ui/main_window.h"
|
||||||
|
#include "app/ui/timeline.h"
|
||||||
#include "app/util/clipboard.h"
|
#include "app/util/clipboard.h"
|
||||||
#include "app/util/misc.h"
|
#include "app/util/misc.h"
|
||||||
#include "raster/layer.h"
|
#include "raster/layer.h"
|
||||||
@ -50,17 +53,23 @@ CopyCommand::CopyCommand()
|
|||||||
|
|
||||||
bool CopyCommand::onEnabled(Context* context)
|
bool CopyCommand::onEnabled(Context* context)
|
||||||
{
|
{
|
||||||
return context->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
return context->checkFlags(ContextFlags::HasActiveDocument);
|
||||||
ContextFlags::ActiveLayerIsReadable |
|
|
||||||
ContextFlags::ActiveLayerIsWritable |
|
|
||||||
ContextFlags::HasActiveImage |
|
|
||||||
ContextFlags::HasVisibleMask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CopyCommand::onExecute(Context* context)
|
void CopyCommand::onExecute(Context* context)
|
||||||
{
|
{
|
||||||
const ContextReader reader(context);
|
const ContextReader reader(context);
|
||||||
clipboard::copy(reader);
|
|
||||||
|
// Copy a range from the timeline.
|
||||||
|
DocumentRange range = App::instance()->getMainWindow()->getTimeline()->range();
|
||||||
|
if (range.enabled()) {
|
||||||
|
clipboard::copy_range(reader, range);
|
||||||
|
}
|
||||||
|
else if (reader.location()->document() &&
|
||||||
|
reader.location()->document()->isMaskVisible() &&
|
||||||
|
reader.location()->image()) {
|
||||||
|
clipboard::copy(reader);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Command* CommandFactory::createCopyCommand()
|
Command* CommandFactory::createCopyCommand()
|
||||||
|
@ -49,11 +49,13 @@ PasteCommand::PasteCommand()
|
|||||||
bool PasteCommand::onEnabled(Context* context)
|
bool PasteCommand::onEnabled(Context* context)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
clipboard::can_paste() &&
|
(clipboard::get_current_format() == clipboard::ClipboardImage &&
|
||||||
context->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
context->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
||||||
ContextFlags::ActiveLayerIsReadable |
|
ContextFlags::ActiveLayerIsReadable |
|
||||||
ContextFlags::ActiveLayerIsWritable |
|
ContextFlags::ActiveLayerIsWritable |
|
||||||
ContextFlags::ActiveLayerIsImage);
|
ContextFlags::ActiveLayerIsImage)) ||
|
||||||
|
(clipboard::get_current_format() == clipboard::ClipboardDocumentRange &&
|
||||||
|
context->checkFlags(ContextFlags::ActiveDocumentIsWritable));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PasteCommand::onExecute(Context* context)
|
void PasteCommand::onExecute(Context* context)
|
||||||
|
@ -315,6 +315,9 @@ void Document::copyLayerContent(const Layer* sourceLayer0, Document* destDoc, La
|
|||||||
|
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
const Cel* sourceCel = *it;
|
const Cel* sourceCel = *it;
|
||||||
|
if (sourceCel->frame() > destLayer->sprite()->lastFrame())
|
||||||
|
break;
|
||||||
|
|
||||||
base::UniquePtr<Cel> newCel(new Cel(*sourceCel));
|
base::UniquePtr<Cel> newCel(new Cel(*sourceCel));
|
||||||
|
|
||||||
const Image* sourceImage = sourceCel->image();
|
const Image* sourceImage = sourceCel->image();
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
#include "app/ui/status_bar.h"
|
#include "app/ui/status_bar.h"
|
||||||
#include "app/ui_context.h"
|
#include "app/ui_context.h"
|
||||||
#include "app/undo_transaction.h"
|
#include "app/undo_transaction.h"
|
||||||
|
#include "app/util/clipboard.h"
|
||||||
#include "base/compiler_specific.h"
|
#include "base/compiler_specific.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "doc/document_event.h"
|
#include "doc/document_event.h"
|
||||||
@ -166,6 +167,8 @@ Timeline::Timeline()
|
|||||||
, m_separator_x(100 * jguiscale())
|
, m_separator_x(100 * jguiscale())
|
||||||
, m_separator_w(1)
|
, m_separator_w(1)
|
||||||
, m_confPopup(NULL)
|
, m_confPopup(NULL)
|
||||||
|
, m_clipboard_timer(100, this)
|
||||||
|
, m_offset_count(0)
|
||||||
{
|
{
|
||||||
m_ctxConn = m_context->AfterCommandExecution.connect(&Timeline::onAfterCommandExecution, this);
|
m_ctxConn = m_context->AfterCommandExecution.connect(&Timeline::onAfterCommandExecution, this);
|
||||||
m_context->documents().addObserver(this);
|
m_context->documents().addObserver(this);
|
||||||
@ -175,6 +178,8 @@ Timeline::Timeline()
|
|||||||
|
|
||||||
Timeline::~Timeline()
|
Timeline::~Timeline()
|
||||||
{
|
{
|
||||||
|
m_clipboard_timer.stop();
|
||||||
|
|
||||||
detachDocument();
|
detachDocument();
|
||||||
m_context->documents().removeObserver(this);
|
m_context->documents().removeObserver(this);
|
||||||
delete m_confPopup;
|
delete m_confPopup;
|
||||||
@ -276,11 +281,37 @@ void Timeline::setFrame(FrameNumber frame)
|
|||||||
m_editor->setFrame(m_frame);
|
m_editor->setFrame(m_frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Timeline::activateClipboardRange()
|
||||||
|
{
|
||||||
|
m_clipboard_timer.start();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
bool Timeline::onProcessMessage(Message* msg)
|
bool Timeline::onProcessMessage(Message* msg)
|
||||||
{
|
{
|
||||||
switch (msg->type()) {
|
switch (msg->type()) {
|
||||||
|
|
||||||
case kTimerMessage:
|
case kTimerMessage:
|
||||||
|
if (static_cast<TimerMessage*>(msg)->timer() == &m_clipboard_timer) {
|
||||||
|
Document* clipboard_document;
|
||||||
|
DocumentRange clipboard_range;
|
||||||
|
clipboard::get_document_range_info(
|
||||||
|
&clipboard_document,
|
||||||
|
&clipboard_range);
|
||||||
|
|
||||||
|
if (isVisible() && m_document && clipboard_document == m_document) {
|
||||||
|
// Set offset to make selection-movement effect
|
||||||
|
if (m_offset_count < 7)
|
||||||
|
m_offset_count++;
|
||||||
|
else
|
||||||
|
m_offset_count = 0;
|
||||||
|
}
|
||||||
|
else if (m_clipboard_timer.isRunning()) {
|
||||||
|
m_clipboard_timer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kMouseDownMessage: {
|
case kMouseDownMessage: {
|
||||||
@ -908,6 +939,7 @@ void Timeline::onPaint(ui::PaintEvent& ev)
|
|||||||
|
|
||||||
drawPaddings(g);
|
drawPaddings(g);
|
||||||
drawLoopRange(g);
|
drawLoopRange(g);
|
||||||
|
drawClipboardRange(g);
|
||||||
drawRangeOutline(g);
|
drawRangeOutline(g);
|
||||||
|
|
||||||
#if 0 // Use this code to debug the calculated m_dropRange by updateDropRange()
|
#if 0 // Use this code to debug the calculated m_dropRange by updateDropRange()
|
||||||
@ -985,6 +1017,7 @@ void Timeline::onAddFrame(doc::DocumentEvent& ev)
|
|||||||
setFrame(ev.frame());
|
setFrame(ev.frame());
|
||||||
|
|
||||||
showCurrentCel();
|
showCurrentCel();
|
||||||
|
clearClipboardRange();
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1003,6 +1036,7 @@ void Timeline::onRemoveFrame(doc::DocumentEvent& ev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
showCurrentCel();
|
showCurrentCel();
|
||||||
|
clearClipboardRange();
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1014,6 +1048,8 @@ void Timeline::onFrameChanged(Editor* editor)
|
|||||||
m_range.disableRange();
|
m_range.disableRange();
|
||||||
|
|
||||||
showCurrentCel();
|
showCurrentCel();
|
||||||
|
clearClipboardRange();
|
||||||
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timeline::onLayerChanged(Editor* editor)
|
void Timeline::onLayerChanged(Editor* editor)
|
||||||
@ -1024,6 +1060,8 @@ void Timeline::onLayerChanged(Editor* editor)
|
|||||||
m_range.disableRange();
|
m_range.disableRange();
|
||||||
|
|
||||||
showCurrentCel();
|
showCurrentCel();
|
||||||
|
clearClipboardRange();
|
||||||
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timeline::setCursor(int x, int y)
|
void Timeline::setCursor(int x, int y)
|
||||||
@ -1101,6 +1139,25 @@ void Timeline::drawPart(ui::Graphics* g, const gfx::Rect& bounds,
|
|||||||
style->paint(g, bounds, text, state);
|
style->paint(g, bounds, text, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Timeline::drawClipboardRange(ui::Graphics* g)
|
||||||
|
{
|
||||||
|
Document* clipboard_document;
|
||||||
|
DocumentRange clipboard_range;
|
||||||
|
clipboard::get_document_range_info(
|
||||||
|
&clipboard_document,
|
||||||
|
&clipboard_range);
|
||||||
|
|
||||||
|
if (!m_document || clipboard_document != m_document)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_clipboard_timer.isRunning())
|
||||||
|
m_clipboard_timer.start();
|
||||||
|
|
||||||
|
dotted_mode(m_offset_count);
|
||||||
|
g->drawRect(0, getRangeBounds(clipboard_range));
|
||||||
|
dotted_mode(-1);
|
||||||
|
}
|
||||||
|
|
||||||
void Timeline::drawHeader(ui::Graphics* g)
|
void Timeline::drawHeader(ui::Graphics* g)
|
||||||
{
|
{
|
||||||
ISettings* settings = UIContext::instance()->settings();
|
ISettings* settings = UIContext::instance()->settings();
|
||||||
@ -1963,6 +2020,21 @@ void Timeline::updateDropRange(const gfx::Point& pt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Timeline::clearClipboardRange()
|
||||||
|
{
|
||||||
|
Document* clipboard_document;
|
||||||
|
DocumentRange clipboard_range;
|
||||||
|
clipboard::get_document_range_info(
|
||||||
|
&clipboard_document,
|
||||||
|
&clipboard_range);
|
||||||
|
|
||||||
|
if (!m_document || clipboard_document != m_document)
|
||||||
|
return;
|
||||||
|
|
||||||
|
clipboard::clear_content();
|
||||||
|
m_clipboard_timer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
bool Timeline::isCopyKeyPressed(ui::Message* msg)
|
bool Timeline::isCopyKeyPressed(ui::Message* msg)
|
||||||
{
|
{
|
||||||
return msg->ctrlPressed();
|
return msg->ctrlPressed();
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "raster/frame_number.h"
|
#include "raster/frame_number.h"
|
||||||
#include "raster/layer_index.h"
|
#include "raster/layer_index.h"
|
||||||
#include "raster/sprite.h"
|
#include "raster/sprite.h"
|
||||||
|
#include "ui/timer.h"
|
||||||
#include "ui/widget.h"
|
#include "ui/widget.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -92,6 +93,8 @@ namespace app {
|
|||||||
|
|
||||||
Range range() const { return m_range; }
|
Range range() const { return m_range; }
|
||||||
|
|
||||||
|
void activateClipboardRange();
|
||||||
|
|
||||||
// Drag-and-drop operations. These actions are used by commands
|
// Drag-and-drop operations. These actions are used by commands
|
||||||
// called from popup menus.
|
// called from popup menus.
|
||||||
void dropRange(DropOp op);
|
void dropRange(DropOp op);
|
||||||
@ -157,6 +160,7 @@ namespace app {
|
|||||||
void drawRangeOutline(ui::Graphics* g);
|
void drawRangeOutline(ui::Graphics* g);
|
||||||
void drawPaddings(ui::Graphics* g);
|
void drawPaddings(ui::Graphics* g);
|
||||||
bool drawPart(ui::Graphics* g, int part, LayerIndex layer, FrameNumber frame);
|
bool drawPart(ui::Graphics* g, int part, LayerIndex layer, FrameNumber frame);
|
||||||
|
void drawClipboardRange(ui::Graphics* g);
|
||||||
gfx::Rect getLayerHeadersBounds() const;
|
gfx::Rect getLayerHeadersBounds() const;
|
||||||
gfx::Rect getFrameHeadersBounds() const;
|
gfx::Rect getFrameHeadersBounds() const;
|
||||||
gfx::Rect getOnionskinFramesBounds() const;
|
gfx::Rect getOnionskinFramesBounds() const;
|
||||||
@ -176,6 +180,7 @@ namespace app {
|
|||||||
bool isFrameActive(FrameNumber frame) const;
|
bool isFrameActive(FrameNumber frame) const;
|
||||||
void updateStatusBar(ui::Message* msg);
|
void updateStatusBar(ui::Message* msg);
|
||||||
void updateDropRange(const gfx::Point& pt);
|
void updateDropRange(const gfx::Point& pt);
|
||||||
|
void clearClipboardRange();
|
||||||
|
|
||||||
bool isCopyKeyPressed(ui::Message* msg);
|
bool isCopyKeyPressed(ui::Message* msg);
|
||||||
|
|
||||||
@ -244,6 +249,11 @@ namespace app {
|
|||||||
// Configure timeline
|
// Configure timeline
|
||||||
ConfigureTimelinePopup* m_confPopup;
|
ConfigureTimelinePopup* m_confPopup;
|
||||||
ScopedConnection m_ctxConn;
|
ScopedConnection m_ctxConn;
|
||||||
|
|
||||||
|
// Marching ants stuff to show the range in the clipboard.
|
||||||
|
// TODO merge this with the marching ants of the sprite editor (ui::Editor)
|
||||||
|
ui::Timer m_clipboard_timer;
|
||||||
|
int m_offset_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "app/document.h"
|
#include "app/document.h"
|
||||||
#include "app/document_api.h"
|
#include "app/document_api.h"
|
||||||
#include "app/document_location.h"
|
#include "app/document_location.h"
|
||||||
|
#include "app/document_range.h"
|
||||||
#include "app/modules/editors.h"
|
#include "app/modules/editors.h"
|
||||||
#include "app/modules/gfx.h"
|
#include "app/modules/gfx.h"
|
||||||
#include "app/modules/gui.h"
|
#include "app/modules/gui.h"
|
||||||
@ -33,9 +34,10 @@
|
|||||||
#include "app/settings/settings.h"
|
#include "app/settings/settings.h"
|
||||||
#include "app/ui/color_bar.h"
|
#include "app/ui/color_bar.h"
|
||||||
#include "app/ui/editor/editor.h"
|
#include "app/ui/editor/editor.h"
|
||||||
|
#include "app/ui/main_window.h"
|
||||||
#include "app/ui/skin/skin_parts.h"
|
#include "app/ui/skin/skin_parts.h"
|
||||||
#include "app/ui/skin/skin_theme.h"
|
#include "app/ui/skin/skin_theme.h"
|
||||||
#include "app/ui/status_bar.h"
|
#include "app/ui/timeline.h"
|
||||||
#include "app/ui_context.h"
|
#include "app/ui_context.h"
|
||||||
#include "app/undo_transaction.h"
|
#include "app/undo_transaction.h"
|
||||||
#include "app/undoers/add_image.h"
|
#include "app/undoers/add_image.h"
|
||||||
@ -57,15 +59,46 @@
|
|||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class ClipboardRange {
|
||||||
|
public:
|
||||||
|
ClipboardRange() : m_doc(NULL) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool valid() {
|
||||||
|
return m_doc != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void invalidate() {
|
||||||
|
m_doc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRange(Document* doc, const DocumentRange& range) {
|
||||||
|
m_doc = doc;
|
||||||
|
m_range = range;
|
||||||
|
}
|
||||||
|
|
||||||
|
Document* document() const { return m_doc; }
|
||||||
|
DocumentRange range() const { return m_range; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Document* m_doc;
|
||||||
|
DocumentRange m_range;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
using namespace raster;
|
using namespace raster;
|
||||||
|
|
||||||
static void set_clipboard(Image* image, Palette* palette, bool set_system_clipboard);
|
static void set_clipboard_image(Image* image, Palette* palette, bool set_system_clipboard);
|
||||||
static bool copy_from_document(const DocumentLocation& location);
|
static bool copy_from_document(const DocumentLocation& location);
|
||||||
|
|
||||||
static bool first_time = true;
|
static bool first_time = true;
|
||||||
|
|
||||||
static Palette* clipboard_palette = NULL;
|
static Palette* clipboard_palette = NULL;
|
||||||
static Image* clipboard_image = NULL;
|
static Image* clipboard_image = NULL;
|
||||||
|
static ClipboardRange clipboard_range;
|
||||||
static int clipboard_x = 0;
|
static int clipboard_x = 0;
|
||||||
static int clipboard_y = 0;
|
static int clipboard_y = 0;
|
||||||
|
|
||||||
@ -75,7 +108,7 @@ static void on_exit_delete_clipboard()
|
|||||||
delete clipboard_image;
|
delete clipboard_image;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_clipboard(Image* image, Palette* palette, bool set_system_clipboard)
|
static void set_clipboard_image(Image* image, Palette* palette, bool set_system_clipboard)
|
||||||
{
|
{
|
||||||
if (first_time) {
|
if (first_time) {
|
||||||
first_time = false;
|
first_time = false;
|
||||||
@ -93,6 +126,8 @@ static void set_clipboard(Image* image, Palette* palette, bool set_system_clipbo
|
|||||||
if (set_system_clipboard)
|
if (set_system_clipboard)
|
||||||
set_win32_clipboard_bitmap(image, palette);
|
set_win32_clipboard_bitmap(image, palette);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
clipboard_range.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool copy_from_document(const DocumentLocation& location)
|
static bool copy_from_document(const DocumentLocation& location)
|
||||||
@ -110,17 +145,39 @@ static bool copy_from_document(const DocumentLocation& location)
|
|||||||
clipboard_y = document->mask()->bounds().y;
|
clipboard_y = document->mask()->bounds().y;
|
||||||
|
|
||||||
const Palette* pal = document->sprite()->getPalette(location.frame());
|
const Palette* pal = document->sprite()->getPalette(location.frame());
|
||||||
set_clipboard(image, pal ? new Palette(*pal): NULL, true);
|
set_clipboard_image(image, pal ? new Palette(*pal): NULL, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool clipboard::can_paste()
|
clipboard::ClipboardFormat clipboard::get_current_format()
|
||||||
{
|
{
|
||||||
#ifdef ALLEGRO_WINDOWS
|
#ifdef ALLEGRO_WINDOWS
|
||||||
if (win32_clipboard_contains_bitmap())
|
if (win32_clipboard_contains_bitmap())
|
||||||
return true;
|
return ClipboardImage;
|
||||||
#endif
|
#endif
|
||||||
return clipboard_image != NULL;
|
|
||||||
|
if (clipboard_image != NULL)
|
||||||
|
return ClipboardImage;
|
||||||
|
else if (clipboard_range.valid())
|
||||||
|
return ClipboardDocumentRange;
|
||||||
|
else
|
||||||
|
return ClipboardNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clipboard::get_document_range_info(Document** document, DocumentRange* range)
|
||||||
|
{
|
||||||
|
if (clipboard_range.valid()) {
|
||||||
|
*document = clipboard_range.document();
|
||||||
|
*range = clipboard_range.range();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*document = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clipboard::clear_content()
|
||||||
|
{
|
||||||
|
set_clipboard_image(NULL, NULL, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clipboard::cut(ContextWriter& writer)
|
void clipboard::cut(ContextWriter& writer)
|
||||||
@ -156,13 +213,29 @@ void clipboard::copy(const ContextReader& reader)
|
|||||||
if (!copy_from_document(*reader.location())) {
|
if (!copy_from_document(*reader.location())) {
|
||||||
Console console;
|
Console console;
|
||||||
console.printf("Can't copying an image portion from the current layer\n");
|
console.printf("Can't copying an image portion from the current layer\n");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clipboard::copy_range(const ContextReader& reader, const DocumentRange& range)
|
||||||
|
{
|
||||||
|
ASSERT(reader.document() != NULL);
|
||||||
|
|
||||||
|
ContextWriter writer(reader);
|
||||||
|
|
||||||
|
set_clipboard_image(NULL, NULL, true);
|
||||||
|
clipboard_range.setRange(writer.document(), range);
|
||||||
|
|
||||||
|
// TODO Replace this with a signal, because here the timeline
|
||||||
|
// depends on the clipboard and the clipboard of the timeline.
|
||||||
|
App::instance()->getMainWindow()
|
||||||
|
->getTimeline()->activateClipboardRange();
|
||||||
|
}
|
||||||
|
|
||||||
void clipboard::copy_image(Image* image, Palette* pal, const gfx::Point& point)
|
void clipboard::copy_image(Image* image, Palette* pal, const gfx::Point& point)
|
||||||
{
|
{
|
||||||
set_clipboard(Image::createCopy(image),
|
set_clipboard_image(Image::createCopy(image),
|
||||||
pal ? new Palette(*pal): NULL, true);
|
pal ? new Palette(*pal): NULL, true);
|
||||||
|
|
||||||
clipboard_x = point.x;
|
clipboard_x = point.x;
|
||||||
clipboard_y = point.y;
|
clipboard_y = point.y;
|
||||||
@ -174,46 +247,87 @@ void clipboard::paste()
|
|||||||
if (editor == NULL)
|
if (editor == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Document* dst_doc = editor->document();
|
||||||
|
Sprite* dst_spr = dst_doc->sprite();
|
||||||
|
|
||||||
|
switch (get_current_format()) {
|
||||||
|
|
||||||
|
case clipboard::ClipboardImage: {
|
||||||
#ifdef ALLEGRO_WINDOWS
|
#ifdef ALLEGRO_WINDOWS
|
||||||
// Get the image from the clipboard.
|
// Get the image from the clipboard.
|
||||||
{
|
{
|
||||||
Image* win32_image = NULL;
|
Image* win32_image = NULL;
|
||||||
Palette* win32_palette = NULL;
|
Palette* win32_palette = NULL;
|
||||||
get_win32_clipboard_bitmap(win32_image, win32_palette);
|
get_win32_clipboard_bitmap(win32_image, win32_palette);
|
||||||
if (win32_image != NULL)
|
if (win32_image != NULL)
|
||||||
set_clipboard(win32_image, win32_palette, false);
|
set_clipboard_image(win32_image, win32_palette, false);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Sprite* dst_sprite = editor->document()->sprite();
|
if (clipboard_image == NULL)
|
||||||
if (clipboard_image == NULL)
|
return;
|
||||||
return;
|
|
||||||
|
|
||||||
Palette* dst_palette = dst_sprite->getPalette(editor->frame());
|
Palette* dst_palette = dst_spr->getPalette(editor->frame());
|
||||||
|
|
||||||
// Source image (clipboard or a converted copy to the destination 'imgtype')
|
// Source image (clipboard or a converted copy to the destination 'imgtype')
|
||||||
Image* src_image;
|
Image* src_image;
|
||||||
if (clipboard_image->pixelFormat() == dst_sprite->pixelFormat() &&
|
if (clipboard_image->pixelFormat() == dst_spr->pixelFormat() &&
|
||||||
// Indexed images can be copied directly only if both images
|
// Indexed images can be copied directly only if both images
|
||||||
// have the same palette.
|
// have the same palette.
|
||||||
(clipboard_image->pixelFormat() != IMAGE_INDEXED ||
|
(clipboard_image->pixelFormat() != IMAGE_INDEXED ||
|
||||||
clipboard_palette->countDiff(dst_palette, NULL, NULL) == 0)) {
|
clipboard_palette->countDiff(dst_palette, NULL, NULL) == 0)) {
|
||||||
src_image = clipboard_image;
|
src_image = clipboard_image;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RgbMap* dst_rgbmap = dst_spr->getRgbMap(editor->frame());
|
||||||
|
|
||||||
|
src_image = quantization::convert_pixel_format(
|
||||||
|
clipboard_image, NULL, dst_spr->pixelFormat(),
|
||||||
|
DITHERING_NONE, dst_rgbmap, clipboard_palette,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change to MovingPixelsState
|
||||||
|
editor->pasteImage(src_image, clipboard_x, clipboard_y);
|
||||||
|
|
||||||
|
if (src_image != clipboard_image)
|
||||||
|
delete src_image;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case clipboard::ClipboardDocumentRange: {
|
||||||
|
DocumentRange range = clipboard_range.range();
|
||||||
|
Document* src_doc = clipboard_range.document();
|
||||||
|
|
||||||
|
switch (range.type()) {
|
||||||
|
|
||||||
|
case DocumentRange::kLayers: {
|
||||||
|
if (src_doc->colorMode() != dst_doc->colorMode())
|
||||||
|
throw std::runtime_error("You cannot copy layers of document with different color modes");
|
||||||
|
|
||||||
|
UndoTransaction undoTransaction(UIContext::instance(), "Paste Layers");
|
||||||
|
std::vector<Layer*> src_layers;
|
||||||
|
src_doc->sprite()->getLayersList(src_layers);
|
||||||
|
|
||||||
|
for (LayerIndex i = range.layerBegin(); i <= range.layerEnd(); ++i) {
|
||||||
|
LayerImage* new_layer = new LayerImage(dst_spr);
|
||||||
|
dst_doc->getApi().addLayer(
|
||||||
|
dst_spr->folder(), new_layer,
|
||||||
|
dst_spr->folder()->getLastLayer());
|
||||||
|
|
||||||
|
src_doc->copyLayerContent(
|
||||||
|
src_layers[i], dst_doc, new_layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
undoTransaction.commit();
|
||||||
|
editor->invalidate();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
RgbMap* dst_rgbmap = dst_sprite->getRgbMap(editor->frame());
|
|
||||||
|
|
||||||
src_image = quantization::convert_pixel_format(
|
|
||||||
clipboard_image, NULL, dst_sprite->pixelFormat(),
|
|
||||||
DITHERING_NONE, dst_rgbmap, clipboard_palette,
|
|
||||||
false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change to MovingPixelsState
|
|
||||||
editor->pasteImage(src_image, clipboard_x, clipboard_y);
|
|
||||||
|
|
||||||
if (src_image != clipboard_image)
|
|
||||||
delete src_image;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool clipboard::get_image_size(gfx::Size& size)
|
bool clipboard::get_image_size(gfx::Size& size)
|
||||||
|
@ -32,16 +32,26 @@ namespace raster {
|
|||||||
namespace app {
|
namespace app {
|
||||||
class ContextReader;
|
class ContextReader;
|
||||||
class ContextWriter;
|
class ContextWriter;
|
||||||
|
class DocumentRange;
|
||||||
|
|
||||||
namespace clipboard {
|
namespace clipboard {
|
||||||
using namespace raster;
|
using namespace raster;
|
||||||
|
|
||||||
|
enum ClipboardFormat {
|
||||||
|
ClipboardNone,
|
||||||
|
ClipboardImage,
|
||||||
|
ClipboardDocumentRange,
|
||||||
|
};
|
||||||
|
|
||||||
// TODO Horrible API: refactor it.
|
// TODO Horrible API: refactor it.
|
||||||
|
|
||||||
bool can_paste();
|
ClipboardFormat get_current_format();
|
||||||
|
void get_document_range_info(Document** document, DocumentRange* range);
|
||||||
|
|
||||||
|
void clear_content();
|
||||||
void cut(ContextWriter& context);
|
void cut(ContextWriter& context);
|
||||||
void copy(const ContextReader& context);
|
void copy(const ContextReader& context);
|
||||||
|
void copy_range(const ContextReader& context, const DocumentRange& range);
|
||||||
void copy_image(Image* image, Palette* palette, const gfx::Point& point);
|
void copy_image(Image* image, Palette* palette, const gfx::Point& point);
|
||||||
void paste();
|
void paste();
|
||||||
|
|
||||||
|
@ -62,6 +62,11 @@ static void set_win32_clipboard_bitmap(Image* image, Palette* palette)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!image) {
|
||||||
|
CloseClipboard();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// information to create the memory necessary for the bitmap
|
// information to create the memory necessary for the bitmap
|
||||||
int padding = 0;
|
int padding = 0;
|
||||||
int scanline = 0;
|
int scanline = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user