Add ability to copy colors using Ctrl + drag & drop

This commit is contained in:
David Capello 2015-05-09 15:57:46 -03:00
parent cea0970d9d
commit 11d86bb7c5
5 changed files with 134 additions and 28 deletions

View File

@ -68,6 +68,7 @@ PaletteView::PaletteView(bool editable, PaletteViewDelegate* delegate, int boxsi
, m_clipboardEntries(Palette::MaxColors)
, m_isUpdatingColumns(false)
, m_hot(Hit::NONE)
, m_copy(false)
, m_clipboardEditor(nullptr)
{
setFocusStop(true);
@ -253,9 +254,16 @@ bool PaletteView::onProcessMessage(Message* msg)
return true;
}
}
updateCopyFlag(msg);
break;
}
case kMouseEnterMessage:
case kKeyUpMessage:
updateCopyFlag(msg);
break;
case kMouseDownMessage:
switch (m_hot.part) {
@ -350,10 +358,7 @@ bool PaletteView::onProcessMessage(Message* msg)
m_hot = hit;
invalidate();
}
if (m_hot.part == Hit::OUTLINE)
ui::set_mouse_cursor(kMoveCursor);
else
ui::set_mouse_cursor(kArrowCursor);
setCursor();
return true;
}
@ -588,24 +593,55 @@ PaletteView::Hit PaletteView::hitTest(const gfx::Point& pos)
void PaletteView::dropColors(int beforeIndex)
{
Palette* palette = get_current_palette();
Remap remap = Remap::moveSelectedEntriesTo(m_selectedEntries, beforeIndex);
Palette palette(*get_current_palette());
Palette newPalette(palette);
Remap remap(palette.size());
// Copy colors
if (m_copy) {
int picks = m_selectedEntries.picks();
remap = create_remap_to_expand_palette(palette.size(), picks, beforeIndex);
for (int i=0; i<palette.size(); ++i)
newPalette.setEntry(remap[i], palette.getEntry(i));
for (int i=0, j=0; i<palette.size(); ++i) {
if (m_selectedEntries[i])
newPalette.setEntry(beforeIndex + (j++), palette.getEntry(i));
}
for (int i=0, j=0; i<palette.size(); ++i) {
if (m_selectedEntries[i]) {
if (m_currentEntry == i) {
m_currentEntry = beforeIndex + j;
break;
}
++j;
}
}
for (int i=0; i<palette.size(); ++i)
m_selectedEntries[i] = (i >= beforeIndex && i < beforeIndex + picks);
}
// Move colors
else {
remap = create_remap_to_move_picks(m_selectedEntries, beforeIndex);
auto oldSelectedCopies = m_selectedEntries;
Palette oldPalCopy(*palette);
for (int i=0; i<palette->size(); ++i) {
palette->setEntry(remap[i], oldPalCopy.getEntry(i));
for (int i=0; i<palette.size(); ++i) {
newPalette.setEntry(remap[i], palette.getEntry(i));
m_selectedEntries[remap[i]] = oldSelectedCopies[i];
}
m_currentEntry = remap[m_currentEntry];
}
if (m_delegate) {
m_delegate->onPaletteViewRemapColors(remap, palette);
m_delegate->onPaletteViewRemapColors(remap, &newPalette);
m_delegate->onPaletteViewIndexChange(m_currentEntry, ui::kButtonLeft);
}
set_current_palette(palette, false);
set_current_palette(&newPalette, false);
getManager()->invalidate();
}
@ -671,4 +707,25 @@ void PaletteView::setClipboardEditor(Editor* editor)
m_clipboardEditor->addObserver(this);
}
void PaletteView::updateCopyFlag(ui::Message* msg)
{
bool oldCopy = m_copy;
m_copy = (msg->ctrlPressed() || msg->altPressed());
if (oldCopy != m_copy)
setCursor();
}
void PaletteView::setCursor()
{
if (m_state == State::DRAGGING_OUTLINE ||
m_hot.part == Hit::OUTLINE) {
if (m_copy)
ui::set_mouse_cursor(kArrowPlusCursor);
else
ui::set_mouse_cursor(kMoveCursor);
}
else
ui::set_mouse_cursor(kArrowCursor);
}
} // namespace app

View File

@ -121,6 +121,8 @@ namespace app {
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();
State m_state;
bool m_editable;
@ -134,6 +136,7 @@ namespace app {
bool m_isUpdatingColumns;
ScopedConnection m_conn;
Hit m_hot;
bool m_copy;
Editor* m_clipboardEditor;
};

View File

@ -14,10 +14,7 @@
namespace doc {
// TODO this should be a non-member function, it's related to PalettePicks and Remap
// static
Remap Remap::moveSelectedEntriesTo(const PalettePicks& picks, int beforeIndex)
Remap create_remap_to_move_picks(const PalettePicks& picks, int beforeIndex)
{
Remap map(picks.size());
@ -48,6 +45,24 @@ Remap Remap::moveSelectedEntriesTo(const PalettePicks& picks, int beforeIndex)
return map;
}
Remap create_remap_to_expand_palette(int size, int count, int beforeIndex)
{
Remap map(size);
int j, k = 0;
for (int i=0; i<size; ++i) {
if (i < beforeIndex)
j = i;
else if (i + count < size)
j = i + count;
else
j = beforeIndex + (k++);
map.map(i, j);
}
return map;
}
void Remap::merge(const Remap& other)
{
for (int i=0; i<size(); ++i) {

View File

@ -18,11 +18,6 @@ namespace doc {
public:
Remap(int entries) : m_map(entries, 0) { }
// Creates a map to move a set of selected entries before the
// given index "beforeIndex".
static Remap moveSelectedEntriesTo(
const PalettePicks& picks, int beforeIndex);
int size() const {
return (int)m_map.size();
}
@ -50,6 +45,12 @@ namespace doc {
std::vector<int> m_map;
};
// Creates a map to move a set of selected entries before the given
// index "beforeIndex".
Remap create_remap_to_move_picks(const PalettePicks& picks, int beforeIndex);
Remap create_remap_to_expand_palette(int size, int count, int beforeIndex);
} // namespace doc
#endif

View File

@ -11,18 +11,19 @@
#include <gtest/gtest.h>
#include "doc/remap.h"
#include "doc/palette_picks.h"
using namespace doc;
TEST(Remap, Basics)
TEST(Remap, RemapToMovePicks)
{
std::vector<bool> entries(20);
PalettePicks entries(20);
std::fill(entries.begin(), entries.end(), false);
entries[6] =
entries[7] =
entries[14] = true;
Remap map = Remap::moveSelectedEntriesTo(entries, 1);
Remap map = create_remap_to_move_picks(entries, 1);
EXPECT_EQ(0, map[0]);
EXPECT_EQ(4, map[1]);
@ -45,7 +46,7 @@ TEST(Remap, Basics)
EXPECT_EQ(18, map[18]);
EXPECT_EQ(19, map[19]);
map = Remap::moveSelectedEntriesTo(entries, 18);
map = create_remap_to_move_picks(entries, 18);
EXPECT_EQ(0, map[0]);
EXPECT_EQ(1, map[1]);
@ -69,6 +70,35 @@ TEST(Remap, Basics)
EXPECT_EQ(19, map[19]);
}
TEST(Remap, RemapToExpandPalette)
{
Remap map = create_remap_to_expand_palette(10, 3, 1);
EXPECT_EQ(0, map[0]);
EXPECT_EQ(4, map[1]);
EXPECT_EQ(5, map[2]);
EXPECT_EQ(6, map[3]);
EXPECT_EQ(7, map[4]);
EXPECT_EQ(8, map[5]);
EXPECT_EQ(9, map[6]);
EXPECT_EQ(1, map[7]);
EXPECT_EQ(2, map[8]);
EXPECT_EQ(3, map[9]);
map = create_remap_to_expand_palette(10, 3, 8);
EXPECT_EQ(0, map[0]);
EXPECT_EQ(1, map[1]);
EXPECT_EQ(2, map[2]);
EXPECT_EQ(3, map[3]);
EXPECT_EQ(4, map[4]);
EXPECT_EQ(5, map[5]);
EXPECT_EQ(6, map[6]);
EXPECT_EQ(7, map[7]);
EXPECT_EQ(8, map[8]);
EXPECT_EQ(9, map[9]);
}
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);