diff --git a/src/yaw-tab/ui.cpp b/src/yaw-tab/ui.cpp index 346ba05..33d03ea 100644 --- a/src/yaw-tab/ui.cpp +++ b/src/yaw-tab/ui.cpp @@ -1,5 +1,4 @@ -#include "DistrhoUI.hpp" -#include "tablet.h" +#include "ui.h" #ifdef DEBUG #include #include @@ -7,259 +6,231 @@ START_NAMESPACE_DISTRHO -//UI element for mapping the currently pressed pen button combination to a parameter. -class ButtonMappingWidget : public NanoSubWidget, - public ButtonEventHandler +ButtonMappingWidget::ButtonMappingWidget( + Widget *parent, + float initialSize, + float initialX, + float initialY, + Parameters associatedParameter, + ButtonEventHandler::Callback *const callback) : x(initialX), + y(initialY), + size(initialSize), + param(associatedParameter), + isClicked(false), + isPenPressed(false), + mask(0), + NanoSubWidget(parent), + ButtonEventHandler(this) { -public: - ButtonMappingWidget( - Widget* parent, - float initialSize, - float initialX, - float initialY, - Parameters associatedParameter, - ButtonEventHandler::Callback* const callback) : - x(initialX), - y(initialY), - size(initialSize), - param(associatedParameter), - isClicked(false), - isPenPressed(false), - mask(0), - NanoSubWidget(parent), - ButtonEventHandler(this) - { - setSize(Size(static_cast(size), static_cast(size))); - setAbsolutePos((int)x, (int)y); - ButtonEventHandler::setCallback(callback); - } + setSize(Size(static_cast(size), static_cast(size))); + setAbsolutePos((int)x, (int)y); + ButtonEventHandler::setCallback(callback); +} - void onNanoDisplay() override - { - beginPath(); - strokeColor(200, 200, 200); - fillColor(0.5f, 0.5f, 0.5f, 0.5f * (isClicked + isPenPressed)); - roundedRect(0.f, 0.f, size, size, 0.5f * size); - stroke(); - fill(); - closePath(); - } - - bool onMouse(const MouseEvent& ev) override - { - isClicked = ev.press; - return ButtonEventHandler::mouseEvent(ev); - } - - void setMask(const ButtonMask m) { mask = m; } - bool matchesMask(const ButtonMask m) { return isPenPressed = (m && mask == m); } - - bool isClicked; - bool isPenPressed; - -private: - float x = 0; - float y = 0; - float size = 0; - const Parameters param; - ButtonMask mask; - -}; - - -class TabUI : public UI, - public ButtonEventHandler::Callback +void ButtonMappingWidget::onNanoDisplay() { - static const uint kInitialWidth = 800; - static const uint kInitialHeight = 600; + beginPath(); + strokeColor(200, 200, 200); + fillColor(0.5f, 0.5f, 0.5f, 0.5f * (isClicked + isPenPressed)); + roundedRect(0.f, 0.f, size, size, 0.5f * size); + stroke(); + fill(); + closePath(); +} -public: - TabUI() - : UI(kInitialWidth, kInitialHeight), - tab(getWindow().getNativeWindowHandle()), - AButtonWidget(this, 75.f, 700.f, 500.f, kParameterButtonA, this), - BButtonWidget(this, 75.f, 700.f, 400.f, kParameterButtonB, this) - { +bool ButtonMappingWidget::onMouse(const MouseEvent &ev) +{ + isClicked = ev.press; + return ButtonEventHandler::mouseEvent(ev); +} + +static constexpr uint kInitialWidth = 800; +static constexpr uint kInitialHeight = 600; + +TabUI::TabUI() + : UI(kInitialWidth, kInitialHeight), + tab(getWindow().getNativeWindowHandle()), + AButtonWidget(this, 75.f, 700.f, 500.f, kParameterButtonA, this), + BButtonWidget(this, 75.f, 700.f, 400.f, kParameterButtonB, this) +{ #ifdef DGL_NO_SHARED_RESOURCES - createFontFromFile("sans", "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf"); + createFontFromFile("sans", "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf"); #else - loadSharedResources(); + loadSharedResources(); #endif - if (!tab.initialized) return; - //setGeometryConstraints(400, static_cast(300 * tabletAspectRatio), true, false); - } + if (!tab.initialized) + return; + // setGeometryConstraints(400, static_cast(300 * tabletAspectRatio), true, false); +} -protected: +void TabUI::getTabletData() +{ + if (!tab.initialized || !tab.GetPacket(pkt)) + return; + if (pkt == lastPkt) + return; + if (pkt.x != lastPkt.x) + setParameterValue(ktpax, pkt.x); + if (pkt.y != lastPkt.y) + setParameterValue(ktpay, pkt.y); + if (pkt.z != lastPkt.z) + setParameterValue(ktpaz, pkt.z); + if (pkt.p != lastPkt.p) + setParameterValue(ktpap, pkt.p); + if (pkt.buttons != lastPkt.buttons) + setButtonsValue(pkt.buttons); + lastPkt = pkt; +} - void getTabletData() +void TabUI::setButtonsValue(unsigned long buttonMask) +{ + if (AButtonWidget.matchesMask(buttonMask)) + setParameterValue(kParameterButtonA, 1.f); + else + setParameterValue(kParameterButtonA, 0.f); + + if (BButtonWidget.matchesMask(buttonMask)) + setParameterValue(kParameterButtonB, 1.f); + else + setParameterValue(kParameterButtonB, 0.f); +} + +void TabUI::buttonClicked(SubWidget *const widget, int) +{ + if (widget == &AButtonWidget) + AButtonWidget.setMask(pkt.buttons); + if (widget == &BButtonWidget) + BButtonWidget.setMask(pkt.buttons); +} + +void TabUI::parameterChanged(uint32_t index, float value) +{ + + if (index != kParameterTime && index < kParameterCount) { - if (!tab.initialized || !tab.GetPacket(pkt)) return; - if (pkt == lastPkt) return; - if (pkt.x != lastPkt.x) setParameterValue(ktpax, pkt.x); - if (pkt.y != lastPkt.y) setParameterValue(ktpay, pkt.y); - if (pkt.z != lastPkt.z) setParameterValue(ktpaz, pkt.z); - if (pkt.p != lastPkt.p) setParameterValue(ktpap, pkt.p); - if (pkt.buttons != lastPkt.buttons) setButtonsValue(pkt.buttons); - lastPkt = pkt; - } - - void setButtonsValue(unsigned long buttonMask) - { - if (AButtonWidget.matchesMask(buttonMask)) - setParameterValue(kParameterButtonA, 1.f); - else setParameterValue(kParameterButtonA, 0.f); - - if (BButtonWidget.matchesMask(buttonMask)) - setParameterValue(kParameterButtonB, 1.f); - else setParameterValue(kParameterButtonB, 0.f); - - } - - void buttonClicked(SubWidget* const widget, int ) override - { - if (widget == &AButtonWidget) AButtonWidget.setMask(pkt.buttons); - if (widget == &BButtonWidget) BButtonWidget.setMask(pkt.buttons); - } - - void parameterChanged(uint32_t index, float value) override - { - - if (index != kParameterTime && index < kParameterCount) { - switch (index) - { - case(ktpax): pkt.x = value; - case(ktpay): pkt.y = value; - case(ktpaz): pkt.z = value; - case(ktpap): pkt.p = value; - } - return; + switch (index) + { + case (ktpax): + pkt.x = value; + case (ktpay): + pkt.y = value; + case (ktpaz): + pkt.z = value; + case (ktpap): + pkt.p = value; } - - getTabletData(); - repaint(); + return; } - void uiIdle() override + getTabletData(); + repaint(); +} + +void TabUI::uiIdle() +{ + getTabletData(); + repaint(); +} + +bool TabUI::onMouse(const MouseEvent &ev) +{ + getTabletData(); + repaint(); + return false; // Allow event to propagate. +} + +bool TabUI::onScroll(const ScrollEvent &ev) +{ + double add; + const uint x = getWidth(); + const uint y = getHeight(); + + add = (ev.delta.getY() > 0) ? 1 : -1; + + float tabletAspectRatio; + if (tab.initialized) + tabletAspectRatio = tab.ext.y / tab.ext.x; + else + tabletAspectRatio = 1.f; + setSize(static_cast(x + add + 0.5), static_cast(tabletAspectRatio * (x + add + 0.5))); + return true; +} + +void TabUI::onNanoDisplay() +{ + fontSize(15.0f); + textLineHeight(1.f); + +// Report tablet errors. +#ifdef DEBUG + if (!tab.initialized) { - getTabletData(); - repaint(); - } - - bool onMouse(const MouseEvent& ev) override - { - getTabletData(); - repaint(); - return false; //Allow event to propagate. - } - - bool onScroll(const ScrollEvent& ev) override - { - double add; - const uint x = getWidth(); - const uint y = getHeight(); - - add = (ev.delta.getY() > 0) ? 1 : -1; - - float tabletAspectRatio; - if (tab.initialized) tabletAspectRatio = tab.ext.y / tab.ext.x; else tabletAspectRatio = 1.f; - setSize(static_cast(x + add + 0.5), static_cast(tabletAspectRatio * (x + add + 0.5))); - return true; - } - - - void onNanoDisplay() override - { - fontSize(15.0f); - textLineHeight(1.f); - - //Report tablet errors. - if (!tab.initialized) { - const std::string err = std::vformat("Tablet not supported:\n{}", - std::make_format_args(tab.errormsg)); - beginPath(); - fillColor(200, 200, 200); - textBox(0.f, 15.f, 250.f, err.c_str(), nullptr); - closePath(); - return; - } - - //Numerical feedback. + const std::string err = std::vformat("Tablet not supported:\n{}", + std::make_format_args(tab.errormsg)); beginPath(); fillColor(200, 200, 200); - textBox(0.f, 15.f, 250.f, + textBox(0.f, 15.f, 250.f, err.c_str(), nullptr); + closePath(); + return; + } + + // Numerical feedback. + beginPath(); + fillColor(200, 200, 200); + textBox(0.f, 15.f, 250.f, std::format("x: {:.3f}\ny: {:.3f}\nz: {:.3f}\np: {:.3f}\nb: {}", - pkt.x, pkt.y, pkt.z, pkt.p, pkt.buttons).c_str(), nullptr); - closePath(); + pkt.x, pkt.y, pkt.z, pkt.p, pkt.buttons) + .c_str(), + nullptr); + closePath(); +#endif - //Pen position and pressure. - drawCircle(pkt.x, pkt.y, pkt.z, pkt.p); - } + // Pen position and pressure. + drawCircle(pkt.x, pkt.y, pkt.z, pkt.p); +} - void drawCircle(float x, float y, float z, float p) { +void TabUI::drawCircle(float x, float y, float z, float p) +{ - static constexpr float circleRadius = 25.f; - x *= getWidth(); - y = (1.f - y) * getHeight(); - z = 1.f - z; + static constexpr float circleRadius = 25.f; + x *= getWidth(); + y = (1.f - y) * getHeight(); + z = 1.f - z; - beginPath(); - strokeColor(1.f, 1.f, 1.f, 0.5f); - moveTo(x - z * circleRadius, y); - lineTo(x + z * circleRadius, y); - stroke(); - closePath(); + beginPath(); + strokeColor(1.f, 1.f, 1.f, 0.5f); + moveTo(x - z * circleRadius, y); + lineTo(x + z * circleRadius, y); + stroke(); + closePath(); - beginPath(); - strokeColor(1.f, 1.f, 1.f, 0.5f); - moveTo(x, y - z * circleRadius); - lineTo(x, y + z * circleRadius); - stroke(); - closePath(); + beginPath(); + strokeColor(1.f, 1.f, 1.f, 0.5f); + moveTo(x, y - z * circleRadius); + lineTo(x, y + z * circleRadius); + stroke(); + closePath(); - beginPath(); - fillColor(1.f, 1.f, 1.f, p); - strokeColor(255, 255, 255, 255); - circle(x, y, circleRadius); - fill(); - stroke(); - closePath(); + beginPath(); + fillColor(1.f, 1.f, 1.f, p); + strokeColor(255, 255, 255, 255); + circle(x, y, circleRadius); + fill(); + stroke(); + closePath(); - beginPath(); - strokeColor(1.f, 1.f, 1.f, z); - circle(x, y, z * circleRadius); - stroke(); - closePath(); - } + beginPath(); + strokeColor(1.f, 1.f, 1.f, z); + circle(x, y, z * circleRadius); + stroke(); + closePath(); +} - - // ------------------------------------------------------------------------------------------------------- - -private: - - // Tablet context handler - Tablet tab; - Packet pkt = { 0 }; - Packet lastPkt = { 0 }; - - // Button mapping widgets - ButtonMappingWidget AButtonWidget; - ButtonMappingWidget BButtonWidget; - - - /** - Set our UI class as non-copyable and add a leak detector just in case. - */ - DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(TabUI) -}; - - - -UI* createUI() +UI *createUI() { return new TabUI(); } - END_NAMESPACE_DISTRHO diff --git a/src/yaw-tab/ui.h b/src/yaw-tab/ui.h new file mode 100644 index 0000000..cd57634 --- /dev/null +++ b/src/yaw-tab/ui.h @@ -0,0 +1,68 @@ +#include "DistrhoUI.hpp" +#include "tablet.h" +#ifdef DEBUG +#include +#include +#endif + +START_NAMESPACE_DISTRHO + +class ButtonMappingWidget : public NanoSubWidget, + public ButtonEventHandler +{ +public: + explicit ButtonMappingWidget( + Widget *parent, + float initialSize, + float initialX, + float initialY, + Parameters associatedParameter, + ButtonEventHandler::Callback *const callback); + void onNanoDisplay() override; + bool onMouse(const MouseEvent &ev) override; + void setMask(const ButtonMask m) { mask = m; }; + bool matchesMask(const ButtonMask m) { return isPenPressed = (m && mask == m); }; + + bool isClicked; + bool isPenPressed; + +private: + float x = 0; + float y = 0; + float size = 0; + const Parameters param; + ButtonMask mask; +}; + +class TabUI : public UI, + public ButtonEventHandler::Callback +{ +public: + explicit TabUI(); + + void buttonClicked(SubWidget *const widget, int) override; + void parameterChanged(uint32_t index, float value) override; + + void uiIdle() override; + bool onMouse(const MouseEvent &ev) override; + bool onScroll(const ScrollEvent &ev) override; + void onNanoDisplay() override; + +private: + void getTabletData(); + void setButtonsValue(unsigned long buttonMask); + void drawCircle(float x, float y, float z, float p); + + // Tablet context handler + Tablet tab; + Packet pkt = {0}; + Packet lastPkt = {0}; + + // Button mapping widgets + ButtonMappingWidget AButtonWidget; + ButtonMappingWidget BButtonWidget; + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(TabUI) +}; + +END_NAMESPACE_DISTRHO \ No newline at end of file