diff --git a/src/app/color.cpp b/src/app/color.cpp index e8a842968..cbd42ad1e 100644 --- a/src/app/color.cpp +++ b/src/app/color.cpp @@ -898,4 +898,37 @@ int Color::getAlpha() const return -1; } +void Color::setAlpha(int alpha) +{ + alpha = MID(0, alpha, 255); + + switch (getType()) { + + case Color::MaskType: + break; + + case Color::RgbType: + m_value.rgb.a = alpha; + break; + + case Color::HsvType: + m_value.hsv.a = alpha; + break; + + case Color::HslType: + m_value.hsl.a = alpha; + break; + + case Color::GrayType: + m_value.gray.a = alpha; + break; + + case Color::IndexType: + *this = Color::fromRgb(getRed(), + getGreen(), + getBlue(), alpha); + break; + } +} + } // namespace app diff --git a/src/app/color.h b/src/app/color.h index bba1f7f2d..be57a32fe 100644 --- a/src/app/color.h +++ b/src/app/color.h @@ -80,6 +80,9 @@ namespace app { int getIndex() const; int getAlpha() const; + // Setters + void setAlpha(int alpha); + private: Color(Type type) : m_type(type) { } diff --git a/src/app/modules/gfx.cpp b/src/app/modules/gfx.cpp index f5fd1a534..976a88b91 100644 --- a/src/app/modules/gfx.cpp +++ b/src/app/modules/gfx.cpp @@ -37,6 +37,8 @@ static void rectgrid(ui::Graphics* g, const gfx::Rect& rc, const gfx::Size& tile return; int x, y, u, v; + + // TODO these values are hard-coded in ColorSelector::onPaintAlphaBar() too, use pref.xml values gfx::Color c1 = gfx::rgba(128, 128, 128); gfx::Color c2 = gfx::rgba(192, 192, 192); diff --git a/src/app/ui/color_selector.cpp b/src/app/ui/color_selector.cpp index 993f28556..9307a4137 100644 --- a/src/app/ui/color_selector.cpp +++ b/src/app/ui/color_selector.cpp @@ -10,9 +10,11 @@ #include "app/ui/color_selector.h" +#include "app/color_utils.h" #include "app/ui/skin/skin_theme.h" #include "app/ui/status_bar.h" #include "base/scoped_value.h" +#include "doc/blend_funcs.h" #include "she/surface.h" #include "ui/manager.h" #include "ui/message.h" @@ -32,6 +34,7 @@ ColorSelector::ColorSelector() : Widget(kGenericWidget) , m_lockColor(false) , m_capturedInBottom(false) + , m_capturedInAlpha(false) { setBorder(gfx::Border(3*ui::guiscale())); } @@ -51,18 +54,31 @@ app::Color ColorSelector::getColorByPosition(const gfx::Point& pos) if (rc.isEmpty()) return app::Color::fromMask(); - int u, v, umax, vmax; - int barSize = getBottomBarSize(); - u = pos.x - rc.x; - v = pos.y - rc.y; - umax = MAX(1, rc.w-1); - vmax = MAX(1, rc.h-1-barSize); + const int u = pos.x - rc.x; + const int umax = MAX(1, rc.w-1); + const gfx::Rect bottomBarBounds = this->bottomBarBounds(); if (( hasCapture() && m_capturedInBottom) || - (!hasCapture() && inBottomBarArea(pos))) + (!hasCapture() && bottomBarBounds.contains(pos))) return getBottomBarColor(u, umax); - else - return getMainAreaColor(u, umax, v, vmax); + + const gfx::Rect alphaBarBounds = this->alphaBarBounds(); + if (( hasCapture() && m_capturedInAlpha) || + (!hasCapture() && alphaBarBounds.contains(pos))) + return getAlphaBarColor(u, umax); + + const int v = pos.y - rc.y; + const int vmax = MAX(1, rc.h-bottomBarBounds.h-alphaBarBounds.h-1); + return getMainAreaColor(u, umax, + v, vmax); +} + +app::Color ColorSelector::getAlphaBarColor(const int u, const int umax) +{ + int alpha = (255 * u / umax); + app::Color color = m_color; + color.setAlpha(MID(0, alpha, 255)); + return color; } void ColorSelector::onSizeHint(SizeHintEvent& ev) @@ -84,11 +100,14 @@ bool ColorSelector::onProcessMessage(ui::Message* msg) case kMouseMoveMessage: { MouseMessage* mouseMsg = static_cast(msg); + const gfx::Point pos = mouseMsg->position(); - if (msg->type() == kMouseDownMessage) - m_capturedInBottom = inBottomBarArea(mouseMsg->position()); + if (msg->type() == kMouseDownMessage) { + m_capturedInBottom = bottomBarBounds().contains(pos); + m_capturedInAlpha = alphaBarBounds().contains(pos); + } - app::Color color = getColorByPosition(mouseMsg->position()); + app::Color color = getColorByPosition(pos); if (color != app::Color::fromMask()) { base::ScopedValue switcher(m_lockColor, subColorPicked(), false); @@ -101,6 +120,8 @@ bool ColorSelector::onProcessMessage(ui::Message* msg) case kMouseUpMessage: if (hasCapture()) { + m_capturedInBottom = false; + m_capturedInAlpha = false; releaseMouse(); } return true; @@ -137,7 +158,8 @@ bool ColorSelector::onProcessMessage(ui::Message* msg) app::Color::fromHsv( newHue, m_color.getHsvSaturation(), - m_color.getHsvValue()); + m_color.getHsvValue(), + m_color.getAlpha()); ColorChange(newColor, kButtonNone); } @@ -162,15 +184,51 @@ void ColorSelector::onPaint(ui::PaintEvent& ev) if (rc.isEmpty()) return; - int barSize = getBottomBarSize(); - rc.h -= barSize; + gfx::Rect bottomBarBounds = this->bottomBarBounds(); + gfx::Rect alphaBarBounds = this->alphaBarBounds(); + rc.h -= bottomBarBounds.h + alphaBarBounds.h; onPaintMainArea(g, rc); - if (barSize > 0) { - rc.y += rc.h; - rc.h = barSize; - onPaintBottomBar(g, rc); + if (!bottomBarBounds.isEmpty()) { + bottomBarBounds.offset(-bounds().origin()); + onPaintBottomBar(g, bottomBarBounds); } + + if (!alphaBarBounds.isEmpty()) { + alphaBarBounds.offset(-bounds().origin()); + onPaintAlphaBar(g, alphaBarBounds); + } +} + +void ColorSelector::onPaintAlphaBar(ui::Graphics* g, const gfx::Rect& rc) +{ + const int xmax = MAX(1, rc.w-1); + const int alpha = m_color.getAlpha(); + const doc::color_t c = + (m_color.getType() != app::Color::MaskType ? + doc::rgba(m_color.getRed(), + m_color.getGreen(), + m_color.getBlue(), 255): 0); + + for (int x=0; xdrawVLine( + app::color_utils::color_for_ui(app::Color::fromImage(IMAGE_RGB, odd ? c2: c1)), + rc.x+x, rc.y, mid); + g->drawVLine( + app::color_utils::color_for_ui(app::Color::fromImage(IMAGE_RGB, odd ? c1: c2)), + rc.x+x, rc.y+mid, rc.h-mid); + } + + gfx::Point pos(rc.x + int(rc.w * alpha / 255), + rc.y + rc.h/2); + paintColorIndicator(g, pos, false); } void ColorSelector::paintColorIndicator(ui::Graphics* g, @@ -187,20 +245,28 @@ void ColorSelector::paintColorIndicator(ui::Graphics* g, pos.y-icon->height()/2); } -bool ColorSelector::inBottomBarArea(const gfx::Point& pos) const +gfx::Rect ColorSelector::bottomBarBounds() const { - gfx::Rect rc = childrenBounds(); - if (rc.isEmpty() || !rc.contains(pos)) - return false; + const gfx::Rect rc = childrenBounds(); + const int size = 8*guiscale(); // TODO 8 should be configurable in theme.xml + if (rc.h > 2*size) { + if (rc.h > 3*size) // Alpha bar is visible too + return gfx::Rect(rc.x, rc.y2()-size*2, rc.w, size); + else + return gfx::Rect(rc.x, rc.y2()-size, rc.w, size); + } else - return (pos.y >= rc.y+rc.h-getBottomBarSize()); + return gfx::Rect(); } -int ColorSelector::getBottomBarSize() const +gfx::Rect ColorSelector::alphaBarBounds() const { - gfx::Rect rc = clientChildrenBounds(); - int size = 8*guiscale(); - return rc.h < 2*size ? 0: size; + const gfx::Rect rc = childrenBounds(); + const int size = 8*guiscale(); // TODO 8 should be configurable in theme.xml + if (rc.h > 3*size) + return gfx::Rect(rc.x, rc.y2()-size, rc.w, size); + else + return gfx::Rect(); } } // namespace app diff --git a/src/app/ui/color_selector.h b/src/app/ui/color_selector.h index 643dbc6a6..b5cb7f0a8 100644 --- a/src/app/ui/color_selector.h +++ b/src/app/ui/color_selector.h @@ -48,8 +48,11 @@ namespace app { bool onProcessMessage(ui::Message* msg) override; void onPaint(ui::PaintEvent& ev) override; - bool inBottomBarArea(const gfx::Point& pos) const; - int getBottomBarSize() const; + app::Color getAlphaBarColor(const int u, const int umax); + void onPaintAlphaBar(ui::Graphics* g, const gfx::Rect& rc); + + gfx::Rect bottomBarBounds() const; + gfx::Rect alphaBarBounds() const; // Internal flag used to lock the modification of m_color. // E.g. When the user picks a color harmony, we don't want to @@ -61,6 +64,7 @@ namespace app { // area vs bottom slider) when we drag the mouse above this // widget. bool m_capturedInBottom; + bool m_capturedInAlpha; }; } // namespace app diff --git a/src/app/ui/color_spectrum.cpp b/src/app/ui/color_spectrum.cpp index 58723a9df..71dea0b20 100644 --- a/src/app/ui/color_spectrum.cpp +++ b/src/app/ui/color_spectrum.cpp @@ -39,7 +39,8 @@ app::Color ColorSpectrum::getMainAreaColor(const int u, const int umax, return app::Color::fromHsl( MID(0.0, hue, 360.0), m_color.getHslSaturation(), - MID(0.0, lit, 1.0)); + MID(0.0, lit, 1.0), + m_color.getAlpha()); } app::Color ColorSpectrum::getBottomBarColor(const int u, const int umax) @@ -48,7 +49,8 @@ app::Color ColorSpectrum::getBottomBarColor(const int u, const int umax) return app::Color::fromHsl( m_color.getHslHue(), MID(0.0, sat, 1.0), - m_color.getHslLightness()); + m_color.getHslLightness(), + m_color.getAlpha()); } void ColorSpectrum::onPaintMainArea(ui::Graphics* g, const gfx::Rect& rc) diff --git a/src/app/ui/color_tint_shade_tone.cpp b/src/app/ui/color_tint_shade_tone.cpp index a5df7cb76..79bb91076 100644 --- a/src/app/ui/color_tint_shade_tone.cpp +++ b/src/app/ui/color_tint_shade_tone.cpp @@ -32,7 +32,8 @@ app::Color ColorTintShadeTone::getMainAreaColor(const int u, const int umax, return app::Color::fromHsv( m_color.getHsvHue(), MID(0.0, sat, 1.0), - MID(0.0, val, 1.0)); + MID(0.0, val, 1.0), + m_color.getAlpha()); } app::Color ColorTintShadeTone::getBottomBarColor(const int u, const int umax) @@ -41,7 +42,8 @@ app::Color ColorTintShadeTone::getBottomBarColor(const int u, const int umax) return app::Color::fromHsv( MID(0.0, hue, 360.0), m_color.getHsvSaturation(), - m_color.getHsvValue()); + m_color.getHsvValue(), + m_color.getAlpha()); } void ColorTintShadeTone::onPaintMainArea(ui::Graphics* g, const gfx::Rect& rc) diff --git a/src/app/ui/color_wheel.cpp b/src/app/ui/color_wheel.cpp index f39768b5d..e0bada148 100644 --- a/src/app/ui/color_wheel.cpp +++ b/src/app/ui/color_wheel.cpp @@ -100,7 +100,8 @@ app::Color ColorWheel::getMainAreaColor(const int _u, const int umax, return app::Color::fromHsv( MID(0, hue, 360), MID(0, sat / 100.0, 1.0), - m_color.getHsvValue()); + m_color.getHsvValue(), + m_color.getAlpha()); } // Pick harmonies @@ -119,7 +120,8 @@ app::Color ColorWheel::getMainAreaColor(const int _u, const int umax, color = app::Color::fromHsv(convertHueAngle(int(color.getHsvHue()), 1), color.getHsvSaturation(), - color.getHsvValue()); + color.getHsvValue(), + m_color.getAlpha()); return color; } } @@ -159,6 +161,7 @@ void ColorWheel::onPaintMainArea(ui::Graphics* g, const gfx::Rect& rc) gfx::Color color; if (appColor.getType() != app::Color::MaskType) { + appColor.setAlpha(255); color = color_utils::color_for_ui(appColor); } else {