From 26970832ac7a63ef498ba62eb50a9415e51640d1 Mon Sep 17 00:00:00 2001 From: David Capello Date: Fri, 20 Mar 2015 14:46:48 -0300 Subject: [PATCH] PaletteView: highlight selection outline when the mouse is over it --- src/app/ui/palette_view.cpp | 109 ++++++++++++++++++++++++++++++++---- src/app/ui/palette_view.h | 25 +++++++++ 2 files changed, 123 insertions(+), 11 deletions(-) diff --git a/src/app/ui/palette_view.cpp b/src/app/ui/palette_view.cpp index 18731a04a..461235af4 100644 --- a/src/app/ui/palette_view.cpp +++ b/src/app/ui/palette_view.cpp @@ -11,6 +11,7 @@ #include "app/app.h" #include "app/color.h" +#include "app/color_utils.h" #include "app/modules/gui.h" #include "app/modules/palettes.h" #include "app/ui/palette_view.h" @@ -57,6 +58,7 @@ PaletteView::PaletteView(bool editable) , m_rangeAnchor(-1) , m_selectedEntries(Palette::MaxColors, false) , m_isUpdatingColumns(false) + , m_hot(Hit::NONE) { setFocusStop(true); setDoubleBuffered(true); @@ -175,12 +177,12 @@ bool PaletteView::onProcessMessage(Message* msg) case kMouseMoveMessage: { MouseMessage* mouseMsg = static_cast(msg); - app::Color color = getColorByPosition(mouseMsg->position()); - if (color.getType() == app::Color::IndexType) { - int idx = color.getIndex(); + if (m_hot.part == Hit::COLOR) { + int idx = m_hot.color; - StatusBar::instance()->showColor(0, "", color, 255); + StatusBar::instance()->showColor(0, "", + app::Color::fromIndex(idx), 255); if (hasCapture() && idx != m_currentEntry) { clearSelection(); @@ -203,7 +205,8 @@ bool PaletteView::onProcessMessage(Message* msg) } case kMouseUpMessage: - releaseMouse(); + if (hasCapture()) + releaseMouse(); return true; case kMouseWheelMessage: { @@ -218,8 +221,24 @@ bool PaletteView::onProcessMessage(Message* msg) case kMouseLeaveMessage: StatusBar::instance()->clearText(); + m_hot = Hit(Hit::NONE); + invalidate(); break; + case kSetCursorMessage: { + MouseMessage* mouseMsg = static_cast(msg); + Hit hit = hitTest(mouseMsg->position() - getBounds().getOrigin()); + if (hit != m_hot) { + m_hot = hit; + invalidate(); + } + if (m_hot.part == Hit::OUTLINE) + ui::set_mouse_cursor(kMoveCursor); + else + ui::set_mouse_cursor(kArrowCursor); + return true; + } + } return Widget::onProcessMessage(msg); @@ -234,7 +253,7 @@ void PaletteView::onPaint(ui::PaintEvent& ev) Palette* palette = get_current_palette(); gfx::Color bordercolor = gfx::rgba(255, 255, 255); - g->fillRect(gfx::rgba(0 , 0, 0), bounds); + g->fillRect(gfx::rgba(0, 0, 0), bounds); // Draw palette entries for (int i=0; isize(); ++i) { @@ -245,9 +264,16 @@ void PaletteView::onPaint(ui::PaintEvent& ev) rgba_getb(palette->getEntry(i))); g->fillRect(color, box); + + if (m_currentEntry == i) + g->fillRect(color_utils::blackandwhite_neg(color), + gfx::Rect(box.getCenter(), gfx::Size(1, 1))); } // Draw selected entries + Style::State state = Style::active(); + if (m_hot.part == Hit::OUTLINE) state += Style::hover(); + for (int i=0; isize(); ++i) { if (!m_selectedEntries[i]) continue; @@ -261,15 +287,35 @@ void PaletteView::onPaint(ui::PaintEvent& ev) gfx::Rect box = getPaletteEntryBounds(i); gfx::Rect clipR = box; box.enlarge(outlineWidth); - if (!top ) clipR.y -= outlineWidth, clipR.h += outlineWidth; - if (!bottom) clipR.h += outlineWidth; - if (!left ) clipR.x -= outlineWidth, clipR.w += outlineWidth; - if (!right ) clipR.w += outlineWidth; + + if (!left) { + clipR.x -= outlineWidth; + clipR.w += outlineWidth; + } + + if (!top) { + clipR.y -= outlineWidth; + clipR.h += outlineWidth; + } + + if (!right) + clipR.w += outlineWidth; + else { + clipR.w += guiscale(); + box.w += outlineWidth; + } + + if (!bottom) + clipR.h += outlineWidth; + else { + clipR.h += guiscale(); + box.h += outlineWidth; + } IntersectClip clip(g, clipR); if (clip) { theme->styles.timelineRangeOutline()->paint(g, box, - NULL, Style::active()); + NULL, state); } } } @@ -363,4 +409,45 @@ gfx::Rect PaletteView::getPaletteEntryBounds(int index) m_boxsize, m_boxsize); } +PaletteView::Hit PaletteView::hitTest(const gfx::Point& pos) +{ + SkinTheme* theme = static_cast(getTheme()); + int outlineWidth = theme->dimensions.paletteOutlineWidth(); + Palette* palette = get_current_palette(); + + if (!hasCapture()) { + // First check if the mouse is inside the selection outline. + for (int i=0; isize(); ++i) { + if (!m_selectedEntries[i]) + continue; + + const int max = Palette::MaxColors; + bool top = (i >= m_columns && i-m_columns >= 0 ? m_selectedEntries[i-m_columns]: false); + bool bottom = (i < max-m_columns && i+m_columns < max ? m_selectedEntries[i+m_columns]: false); + bool left = ((i%m_columns)>0 && i-1 >= 0 ? m_selectedEntries[i-1]: false); + bool right = ((i%m_columns)size(); ++i) { + gfx::Rect box = getPaletteEntryBounds(i); + box.w += child_spacing; + box.h += child_spacing; + if (box.contains(pos)) + return Hit(Hit::COLOR, i); + } + + return Hit(Hit::NONE); +} + } // namespace app diff --git a/src/app/ui/palette_view.h b/src/app/ui/palette_view.h index 816b8225b..8e8aeef4e 100644 --- a/src/app/ui/palette_view.h +++ b/src/app/ui/palette_view.h @@ -63,10 +63,34 @@ namespace app { void onPreferredSize(ui::PreferredSizeEvent& ev) override; private: + + struct Hit { + enum Part { + NONE, + COLOR, + OUTLINE + }; + + Part part; + int color; + + Hit(Part part, int color = -1) : part(part), color(color) { + } + + bool operator==(const Hit& hit) const { + return (part == hit.part && color == hit.color); + } + + bool operator!=(const Hit& hit) const { + return !operator==(hit); + } + }; + void request_size(int* w, int* h); void update_scroll(int color); void onAppPaletteChange(); gfx::Rect getPaletteEntryBounds(int index); + Hit hitTest(const gfx::Point& pos); bool m_editable; int m_columns; @@ -76,6 +100,7 @@ namespace app { SelectedEntries m_selectedEntries; bool m_isUpdatingColumns; ScopedConnection m_conn; + Hit m_hot; }; ui::WidgetType palette_view_type();