Add UI to drag and drop colors in PaletteView

This commit is contained in:
David Capello 2015-03-20 15:29:44 -03:00
parent 26970832ac
commit d41b08caa8
2 changed files with 71 additions and 24 deletions

View File

@ -51,6 +51,7 @@ WidgetType palette_view_type()
PaletteView::PaletteView(bool editable) PaletteView::PaletteView(bool editable)
: Widget(palette_view_type()) : Widget(palette_view_type())
, m_state(State::WAITING)
, m_editable(editable) , m_editable(editable)
, m_columns(16) , m_columns(16)
, m_boxsize(7*guiscale()) , m_boxsize(7*guiscale())
@ -172,29 +173,42 @@ bool PaletteView::onProcessMessage(Message* msg)
switch (msg->type()) { switch (msg->type()) {
case kMouseDownMessage: case kMouseDownMessage:
switch (m_hot.part) {
case Hit::COLOR:
m_state = State::SELECTING_COLOR;
break;
case Hit::OUTLINE:
m_state = State::DRAGGING_OUTLINE;
break;
}
captureMouse(); captureMouse();
// Continue... // Continue...
case kMouseMoveMessage: { case kMouseMoveMessage: {
MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg); MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg);
if (m_hot.part == Hit::COLOR) { if (m_state == State::SELECTING_COLOR) {
int idx = m_hot.color; if (m_hot.part == Hit::COLOR) {
int idx = m_hot.color;
StatusBar::instance()->showColor(0, "", StatusBar::instance()->showColor(0, "",
app::Color::fromIndex(idx), 255); app::Color::fromIndex(idx), 255);
if (hasCapture() && idx != m_currentEntry) { if (hasCapture() && idx != m_currentEntry) {
clearSelection(); if (!msg->ctrlPressed())
clearSelection();
if (msg->type() == kMouseMoveMessage) if (msg->type() == kMouseMoveMessage)
selectRange(m_rangeAnchor, idx); selectRange(m_rangeAnchor, idx);
else else
selectColor(idx); selectColor(idx);
// Emit signal // Emit signal
PaletteIndexChangeEvent ev(this, idx, mouseMsg->buttons()); PaletteIndexChangeEvent ev(this, idx, mouseMsg->buttons());
IndexChange(ev); IndexChange(ev);
}
} }
} }
@ -205,8 +219,12 @@ bool PaletteView::onProcessMessage(Message* msg)
} }
case kMouseUpMessage: case kMouseUpMessage:
if (hasCapture()) if (hasCapture()) {
releaseMouse(); releaseMouse();
m_state = State::WAITING;
invalidate();
}
return true; return true;
case kMouseWheelMessage: { case kMouseWheelMessage: {
@ -318,6 +336,23 @@ void PaletteView::onPaint(ui::PaintEvent& ev)
NULL, state); NULL, state);
} }
} }
// Draw drop target
if (m_state == State::DRAGGING_OUTLINE) {
if (m_hot.part == Hit::COLOR) {
gfx::Rect box = getPaletteEntryBounds(m_hot.color);
if (m_hot.after)
box.x += box.w+guiscale();
box.x -= 3*guiscale();
box.y -= 3*guiscale();
box.w = 5*guiscale();
box.h += 6*guiscale();
theme->styles.timelineDropFrameDeco()->paint(g,
box, NULL, Style::active());
}
}
} }
void PaletteView::onResize(ui::ResizeEvent& ev) void PaletteView::onResize(ui::ResizeEvent& ev)
@ -415,7 +450,7 @@ PaletteView::Hit PaletteView::hitTest(const gfx::Point& pos)
int outlineWidth = theme->dimensions.paletteOutlineWidth(); int outlineWidth = theme->dimensions.paletteOutlineWidth();
Palette* palette = get_current_palette(); Palette* palette = get_current_palette();
if (!hasCapture()) { if (m_state == State::WAITING) {
// First check if the mouse is inside the selection outline. // First check if the mouse is inside the selection outline.
for (int i=0; i<palette->size(); ++i) { for (int i=0; i<palette->size(); ++i) {
if (!m_selectedEntries[i]) if (!m_selectedEntries[i])
@ -431,9 +466,9 @@ PaletteView::Hit PaletteView::hitTest(const gfx::Point& pos)
box.enlarge(outlineWidth); box.enlarge(outlineWidth);
if ((!top && gfx::Rect(box.x, box.y, box.w, outlineWidth).contains(pos)) || if ((!top && gfx::Rect(box.x, box.y, box.w, outlineWidth).contains(pos)) ||
(!bottom && gfx::Rect(box.x, box.y+box.h-outlineWidth, box.w, outlineWidth).contains(pos)) || (!bottom && gfx::Rect(box.x, box.y+box.h-outlineWidth, box.w, outlineWidth).contains(pos)) ||
(!left && gfx::Rect(box.x, box.y, outlineWidth, box.h).contains(pos)) || (!left && gfx::Rect(box.x, box.y, outlineWidth, box.h).contains(pos)) ||
(!right && gfx::Rect(box.x+box.w-outlineWidth, box.y, outlineWidth, box.h).contains(pos))) (!right && gfx::Rect(box.x+box.w-outlineWidth, box.y, outlineWidth, box.h).contains(pos)))
return Hit(Hit::OUTLINE, i); return Hit(Hit::OUTLINE, i);
} }
} }
@ -443,8 +478,11 @@ PaletteView::Hit PaletteView::hitTest(const gfx::Point& pos)
gfx::Rect box = getPaletteEntryBounds(i); gfx::Rect box = getPaletteEntryBounds(i);
box.w += child_spacing; box.w += child_spacing;
box.h += child_spacing; box.h += child_spacing;
if (box.contains(pos)) if (box.contains(pos)) {
return Hit(Hit::COLOR, i); Hit hit(Hit::COLOR, i);
hit.after = (pos.x > box.x+box.w/2);
return hit;
}
} }
return Hit(Hit::NONE); return Hit(Hit::NONE);

View File

@ -64,23 +64,31 @@ namespace app {
private: private:
enum class State {
WAITING,
SELECTING_COLOR,
DRAGGING_OUTLINE,
};
struct Hit { struct Hit {
enum Part { enum Part {
NONE, NONE,
COLOR, COLOR,
OUTLINE OUTLINE
}; };
Part part; Part part;
int color; int color;
bool after;
Hit(Part part, int color = -1) : part(part), color(color) { Hit(Part part, int color = -1) : part(part), color(color), after(false) {
} }
bool operator==(const Hit& hit) const { bool operator==(const Hit& hit) const {
return (part == hit.part && color == hit.color); return (
part == hit.part &&
color == hit.color &&
after == hit.after);
} }
bool operator!=(const Hit& hit) const { bool operator!=(const Hit& hit) const {
return !operator==(hit); return !operator==(hit);
} }
@ -92,6 +100,7 @@ namespace app {
gfx::Rect getPaletteEntryBounds(int index); gfx::Rect getPaletteEntryBounds(int index);
Hit hitTest(const gfx::Point& pos); Hit hitTest(const gfx::Point& pos);
State m_state;
bool m_editable; bool m_editable;
int m_columns; int m_columns;
int m_boxsize; int m_boxsize;