mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-13 01:13:22 +00:00
Add ability to cut colors in the ColorBar
This commit is contained in:
parent
cd1f764d85
commit
9fc7b993d4
@ -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<to.size(); ++j)
|
||||
if (to[j])
|
||||
break;
|
||||
@ -608,7 +608,7 @@ void ColorBar::onNewInputPriority(InputChainElement* element)
|
||||
|
||||
bool ColorBar::onCanCut(Context* ctx)
|
||||
{
|
||||
return false; // TODO
|
||||
return (m_paletteView.getSelectedEntriesCount() > 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)
|
||||
|
@ -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();
|
||||
|
@ -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; i<palette.size(); ++i) {
|
||||
if (m_selectedEntries[i])
|
||||
newPalette.setEntry(remap[i], rgba(0, 0, 0, 255));
|
||||
else
|
||||
newPalette.setEntry(remap[i], palette.getEntry(i));
|
||||
}
|
||||
|
||||
m_currentEntry = m_selectedEntries.firstPick();
|
||||
m_selectedEntries.clear();
|
||||
stopMarchingAnts();
|
||||
|
||||
if (m_delegate) {
|
||||
m_delegate->onPaletteViewRemapColors(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; i<palette->size(); ++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; i<clipboardPicks.size(); ++i) {
|
||||
if (!clipboardPicks[i])
|
||||
continue;
|
||||
|
||||
IntersectClip clip(g, clipR);
|
||||
if (clip) {
|
||||
CheckedDrawMode checked(g, getMarchingAntsOffset());
|
||||
g->drawRect(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;
|
||||
|
@ -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<void> 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();
|
||||
|
@ -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<Palette> 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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user