From 9fc7b993d4eacb834c042d99dfb47531968ca072 Mon Sep 17 00:00:00 2001 From: David Capello Date: Sun, 10 May 2015 21:36:46 -0300 Subject: [PATCH] Add ability to cut colors in the ColorBar --- src/app/ui/color_bar.cpp | 13 ++-- src/app/ui/color_bar.h | 2 +- src/app/ui/palette_view.cpp | 126 +++++++++++++++++------------------- src/app/ui/palette_view.h | 17 +---- src/app/util/clipboard.cpp | 66 +++++++++++++------ src/app/util/clipboard.h | 8 ++- src/doc/doc.h | 1 + 7 files changed, 125 insertions(+), 108 deletions(-) diff --git a/src/app/ui/color_bar.cpp b/src/app/ui/color_bar.cpp index 07a1ceb38..cf27d42cb 100644 --- a/src/app/ui/color_bar.cpp +++ b/src/app/ui/color_bar.cpp @@ -33,6 +33,7 @@ #include "app/ui/status_bar.h" #include "app/ui_context.h" #include "app/ui_context.h" +#include "app/util/clipboard.h" #include "base/bind.h" #include "doc/image.h" #include "doc/palette.h" @@ -421,7 +422,7 @@ void ColorBar::onPaletteViewChangeSize(int boxsize) } void ColorBar::onPaletteViewPasteColors( - Editor* editor, const doc::PalettePicks& from, const doc::PalettePicks& _to) + const Palette* fromPal, const doc::PalettePicks& from, const doc::PalettePicks& _to) { if (!from.picks() || !_to.picks()) // Nothing to do return; @@ -440,7 +441,6 @@ void ColorBar::onPaletteViewPasteColors( } } - Palette* copyFromPalette = editor->sprite()->palette(editor->frame()); Palette newPalette(*get_current_palette()); int i = 0; @@ -449,7 +449,7 @@ void ColorBar::onPaletteViewPasteColors( for (auto state : from) { if (state) { if (j < newPalette.size()) { - newPalette.setEntry(j, copyFromPalette->getEntry(i)); + newPalette.setEntry(j, fromPal->getEntry(i)); for (++j; j 0); } bool ColorBar::onCanCopy(Context* ctx) @@ -618,7 +618,7 @@ bool ColorBar::onCanCopy(Context* ctx) bool ColorBar::onCanPaste(Context* ctx) { - return m_paletteView.areColorsInClipboard(); + return (clipboard::get_current_format() == clipboard::ClipboardPaletteEntries); } bool ColorBar::onCanClear(Context* ctx) @@ -628,7 +628,8 @@ bool ColorBar::onCanClear(Context* ctx) bool ColorBar::onCut(Context* ctx) { - return false; // TODO + m_paletteView.cutToClipboard(); + return true; } bool ColorBar::onCopy(Context* ctx) diff --git a/src/app/ui/color_bar.h b/src/app/ui/color_bar.h index 35dd2362f..e4d74adba 100644 --- a/src/app/ui/color_bar.h +++ b/src/app/ui/color_bar.h @@ -93,7 +93,7 @@ namespace app { void onPaletteViewIndexChange(int index, ui::MouseButtons buttons) override; void onPaletteViewRemapColors(const doc::Remap& remap, const doc::Palette* newPalette) override; void onPaletteViewChangeSize(int boxsize) override; - void onPaletteViewPasteColors(Editor* editor, const doc::PalettePicks& from, const doc::PalettePicks& to) override; + void onPaletteViewPasteColors(const Palette* fromPal, const doc::PalettePicks& from, const doc::PalettePicks& to) override; private: void destroyRemap(); diff --git a/src/app/ui/palette_view.cpp b/src/app/ui/palette_view.cpp index 7a1915289..a727e9ec1 100644 --- a/src/app/ui/palette_view.cpp +++ b/src/app/ui/palette_view.cpp @@ -21,6 +21,7 @@ #include "app/ui/skin/skin_theme.h" #include "app/ui/skin/style.h" #include "app/ui/status_bar.h" +#include "app/util/clipboard.h" #include "doc/blend.h" #include "doc/image.h" #include "doc/palette.h" @@ -64,11 +65,9 @@ PaletteView::PaletteView(bool editable, PaletteViewDelegate* delegate, int boxsi , m_currentEntry(-1) , m_rangeAnchor(-1) , m_selectedEntries(Palette::MaxColors) - , m_clipboardEntries(Palette::MaxColors) , m_isUpdatingColumns(false) , m_hot(Hit::NONE) , m_copy(false) - , m_clipboardEditor(nullptr) { setFocusStop(true); setDoubleBuffered(true); @@ -80,11 +79,6 @@ PaletteView::PaletteView(bool editable, PaletteViewDelegate* delegate, int boxsi m_conn = App::instance()->PaletteChange.connect(&PaletteView::onAppPaletteChange, this); } -PaletteView::~PaletteView() -{ - setClipboardEditor(nullptr); -} - void PaletteView::setColumns(int columns) { int old_columns = m_columns; @@ -211,23 +205,57 @@ void PaletteView::setBoxSize(int boxsize) view->layout(); } +void PaletteView::cutToClipboard() +{ + if (!m_selectedEntries.picks()) + return; + + clipboard::copy_palette(get_current_palette(), m_selectedEntries); + + // Convert selected colors to black and send them to the back of the + // palette. + Palette palette(*get_current_palette()); + Palette newPalette(palette); + Remap remap = create_remap_to_move_picks(m_selectedEntries, palette.size()); + for (int i=0; ionPaletteViewRemapColors(remap, &newPalette); + m_delegate->onPaletteViewIndexChange(m_currentEntry, ui::kButtonLeft); + } + + set_current_palette(&newPalette, false); + getManager()->invalidate(); +} + void PaletteView::copyToClipboard() { - if (current_editor) { - setClipboardEditor(current_editor); - m_clipboardEntries = m_selectedEntries; + if (!m_selectedEntries.picks()) + return; - startMarchingAnts(); - invalidate(); - } + clipboard::copy_palette(get_current_palette(), m_selectedEntries); + + startMarchingAnts(); + invalidate(); } void PaletteView::pasteFromClipboard() { - if (m_clipboardEditor && m_clipboardEntries.picks()) { + if (clipboard::get_current_format() == clipboard::ClipboardPaletteEntries) { if (m_delegate) m_delegate->onPaletteViewPasteColors( - m_clipboardEditor, m_clipboardEntries, m_selectedEntries); + clipboard::get_palette(), + clipboard::get_palette_picks(), + m_selectedEntries); // We just hide the marching ants, the user can paste multiple // times. @@ -238,30 +266,10 @@ void PaletteView::pasteFromClipboard() void PaletteView::discardClipboardSelection() { - bool redraw = false; - - if (m_clipboardEditor) { - setClipboardEditor(nullptr); - redraw = true; - } - - if (m_clipboardEntries.picks() > 0) { - m_clipboardEntries.clear(); - redraw = true; - } - if (isMarchingAntsRunning()) { stopMarchingAnts(); - redraw = true; - } - - if (redraw) invalidate(); -} - -bool PaletteView::areColorsInClipboard() const -{ - return (m_clipboardEditor && m_clipboardEntries.picks()); + } } bool PaletteView::onProcessMessage(Message* msg) @@ -425,20 +433,25 @@ void PaletteView::onPaint(ui::PaintEvent& ev) } // Draw marching ants - if (isMarchingAntsRunning() && - m_clipboardEditor && - m_clipboardEditor == current_editor) { - for (int i=0; isize(); ++i) { - if (!m_clipboardEntries[i]) - continue; + if ((isMarchingAntsRunning()) && + (clipboard::get_current_format() == clipboard::ClipboardPaletteEntries)) { + Palette* clipboardPalette = clipboard::get_palette(); + const PalettePicks& clipboardPicks = clipboard::get_palette_picks(); - gfx::Rect box, clipR; - getEntryBoundsAndClip(i, m_clipboardEntries, box, clipR, outlineWidth); + if (clipboardPalette && + clipboardPalette->countDiff(palette, nullptr, nullptr) == 0) { + for (int i=0; idrawRect(gfx::rgba(0, 0, 0), box); + gfx::Rect box, clipR; + getEntryBoundsAndClip(i, clipboardPicks, box, clipR, outlineWidth); + + IntersectClip clip(g, clipR); + if (clip) { + CheckedDrawMode checked(g, getMarchingAntsOffset()); + g->drawRect(gfx::rgba(0, 0, 0), box); + } } } } @@ -490,12 +503,6 @@ void PaletteView::onDrawMarchingAnts() invalidate(); } -void PaletteView::onDestroyEditor(Editor* editor) -{ - if (m_clipboardEditor == editor) - discardClipboardSelection(); -} - void PaletteView::request_size(int* w, int* h) { div_t d = div(Palette::MaxColors, m_columns); @@ -708,17 +715,6 @@ bool PaletteView::pickedXY(const doc::PalettePicks& entries, int i, int dx, int return false; } -void PaletteView::setClipboardEditor(Editor* editor) -{ - if (m_clipboardEditor) - m_clipboardEditor->removeObserver(this); - - m_clipboardEditor = editor; - - if (m_clipboardEditor) - m_clipboardEditor->addObserver(this); -} - void PaletteView::updateCopyFlag(ui::Message* msg) { bool oldCopy = m_copy; diff --git a/src/app/ui/palette_view.h b/src/app/ui/palette_view.h index edb015986..b23fe3cc5 100644 --- a/src/app/ui/palette_view.h +++ b/src/app/ui/palette_view.h @@ -10,7 +10,6 @@ #pragma once #include "app/color.h" -#include "app/ui/editor/editor_observer.h" #include "app/ui/marching_ants.h" #include "base/connection.h" #include "doc/palette_picks.h" @@ -27,8 +26,6 @@ namespace doc { namespace app { - class Editor; - class PaletteViewDelegate { public: virtual ~PaletteViewDelegate() { } @@ -36,15 +33,13 @@ namespace app { virtual void onPaletteViewRemapColors(const doc::Remap& remap, const doc::Palette* newPalette) { } virtual void onPaletteViewChangeSize(int boxsize) { } virtual void onPaletteViewPasteColors( - Editor* editor, const doc::PalettePicks& from, const doc::PalettePicks& to) { } + const doc::Palette* fromPal, const doc::PalettePicks& from, const doc::PalettePicks& to) { } }; class PaletteView : public ui::Widget - , public MarchingAnts - , public EditorObserver { + , public MarchingAnts { public: PaletteView(bool editable, PaletteViewDelegate* delegate, int boxsize); - ~PaletteView(); bool isEditable() const { return m_editable; } @@ -65,10 +60,10 @@ namespace app { int getBoxSize() const; void setBoxSize(int boxsize); + void cutToClipboard(); void copyToClipboard(); void pasteFromClipboard(); void discardClipboardSelection(); - bool areColorsInClipboard() const; Signal0 FocusEnter; @@ -79,9 +74,6 @@ namespace app { void onPreferredSize(ui::PreferredSizeEvent& ev) override; void onDrawMarchingAnts() override; - // EditorObserver impl - void onDestroyEditor(Editor* editor) override; - private: enum class State { @@ -124,7 +116,6 @@ namespace app { gfx::Rect& box, gfx::Rect& clip, int outlineWidth) const; bool pickedXY(const doc::PalettePicks& entries, int i, int dx, int dy) const; - void setClipboardEditor(Editor* editor); void updateCopyFlag(ui::Message* msg); void setCursor(); @@ -136,12 +127,10 @@ namespace app { int m_currentEntry; int m_rangeAnchor; doc::PalettePicks m_selectedEntries; - doc::PalettePicks m_clipboardEntries; bool m_isUpdatingColumns; ScopedConnection m_conn; Hit m_hot; bool m_copy; - Editor* m_clipboardEditor; }; ui::WidgetType palette_view_type(); diff --git a/src/app/util/clipboard.cpp b/src/app/util/clipboard.cpp index a0c448f41..02d19565c 100644 --- a/src/app/util/clipboard.cpp +++ b/src/app/util/clipboard.cpp @@ -10,8 +10,8 @@ #endif #include "app/app.h" -#include "app/cmd/deselect_mask.h" #include "app/cmd/clear_mask.h" +#include "app/cmd/deselect_mask.h" #include "app/console.h" #include "app/context_access.h" #include "app/document.h" @@ -32,6 +32,7 @@ #include "app/ui_context.h" #include "app/util/clipboard.h" #include "app/util/new_image_from_mask.h" +#include "base/shared_ptr.h" #include "doc/doc.h" #include "render/quantization.h" @@ -86,15 +87,16 @@ static bool copy_from_document(const Site& site); static bool first_time = true; -static Palette* clipboard_palette = NULL; -static Image* clipboard_image = NULL; +static base::SharedPtr clipboard_palette; +static PalettePicks clipboard_picks(Palette::MaxColors); +static ImageRef clipboard_image; static ClipboardRange clipboard_range; static gfx::Point clipboard_pos(0, 0); static void on_exit_delete_clipboard() { - delete clipboard_palette; - delete clipboard_image; + clipboard_palette.reset(); + clipboard_image.reset(); } static void set_clipboard_image(Image* image, Palette* palette, bool set_system_clipboard) @@ -104,11 +106,9 @@ static void set_clipboard_image(Image* image, Palette* palette, bool set_system_ App::instance()->Exit.connect(&on_exit_delete_clipboard); } - delete clipboard_palette; - delete clipboard_image; - - clipboard_palette = palette; - clipboard_image = image; + clipboard_palette.reset(palette); + clipboard_picks.clear(); + clipboard_image.reset(image); // copy to the Windows clipboard #ifdef USE_NATIVE_WIN32_CLIPBOARD @@ -144,10 +144,12 @@ clipboard::ClipboardFormat clipboard::get_current_format() return ClipboardImage; #endif - if (clipboard_image != NULL) + if (clipboard_image) return ClipboardImage; else if (clipboard_range.valid()) return ClipboardDocumentRange; + else if (clipboard_palette && clipboard_picks.picks()) + return ClipboardPaletteEntries; else return ClipboardNone; } @@ -224,6 +226,15 @@ void clipboard::copy_image(Image* image, Palette* pal, const gfx::Point& point) clipboard_pos = point; } +void clipboard::copy_palette(const Palette* palette, const doc::PalettePicks& picks) +{ + if (!picks.picks()) + return; // Do nothing case + + set_clipboard_image(nullptr, new Palette(*palette), true); + clipboard_picks = picks; +} + void clipboard::paste() { Editor* editor = current_editor; @@ -247,13 +258,13 @@ void clipboard::paste() } #endif - if (clipboard_image == NULL) + if (!clipboard_image) return; Palette* dst_palette = dstSpr->palette(editor->frame()); // Source image (clipboard or a converted copy to the destination 'imgtype') - Image* src_image; + ImageRef src_image; if (clipboard_image->pixelFormat() == dstSpr->pixelFormat() && // Indexed images can be copied directly only if both images // have the same palette. @@ -264,17 +275,15 @@ void clipboard::paste() else { RgbMap* dst_rgbmap = dstSpr->rgbMap(editor->frame()); - src_image = render::convert_pixel_format( - clipboard_image, NULL, dstSpr->pixelFormat(), - DitheringMethod::NONE, dst_rgbmap, clipboard_palette, - false); + src_image.reset( + render::convert_pixel_format( + clipboard_image.get(), NULL, dstSpr->pixelFormat(), + DitheringMethod::NONE, dst_rgbmap, clipboard_palette.get(), + false)); } // Change to MovingPixelsState - editor->pasteImage(src_image, clipboard_pos); - - if (src_image != clipboard_image) - delete src_image; + editor->pasteImage(src_image.get(), clipboard_pos); break; } @@ -422,4 +431,19 @@ bool clipboard::get_image_size(gfx::Size& size) #endif } +Palette* clipboard::get_palette() +{ + if (clipboard::get_current_format() == ClipboardPaletteEntries) { + ASSERT(clipboard_palette); + return clipboard_palette.get(); + } + else + return nullptr; +} + +const PalettePicks& clipboard::get_palette_picks() +{ + return clipboard_picks; +} + } // namespace app diff --git a/src/app/util/clipboard.h b/src/app/util/clipboard.h index 00c7b7ce3..a03ae1e2f 100644 --- a/src/app/util/clipboard.h +++ b/src/app/util/clipboard.h @@ -16,6 +16,7 @@ namespace doc { class Image; class Palette; + class PalettePicks; } namespace app { @@ -30,9 +31,10 @@ namespace app { ClipboardNone, ClipboardImage, ClipboardDocumentRange, + ClipboardPaletteEntries, }; - // TODO Horrible API: refactor it. + // TODO Horrible API: refactor it (maybe a merge with she::clipboard). ClipboardFormat get_current_format(); void get_document_range_info(Document** document, DocumentRange* range); @@ -42,6 +44,7 @@ namespace app { 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_palette(const Palette* palette, const PalettePicks& picks); void paste(); // Returns true and fills the specified "size"" with the image's @@ -49,6 +52,9 @@ namespace app { // doesn't contain an image at all. bool get_image_size(gfx::Size& size); + Palette* get_palette(); + const PalettePicks& get_palette_picks(); + } // namespace clipboard } // namespace app diff --git a/src/doc/doc.h b/src/doc/doc.h index 7d7e94974..63a194bbf 100644 --- a/src/doc/doc.h +++ b/src/doc/doc.h @@ -19,6 +19,7 @@ #include "doc/frame_tags.h" #include "doc/image.h" #include "doc/image_bits.h" +#include "doc/image_ref.h" #include "doc/layer.h" #include "doc/mask.h" #include "doc/object.h"