From a5d7a0b75b275bc6cffbd00d5240b69a64011c73 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Sun, 21 Apr 2019 11:12:00 -0400 Subject: [PATCH] Add middle-click-drag to ScrollWidget. Fix numerous bugs introduced by event system changes. --- include/app/LedDisplay.hpp | 6 +++--- include/app/RackWidget.hpp | 1 - include/ui/ScrollWidget.hpp | 8 +++++--- include/widget/OpaqueWidget.hpp | 1 - src/Core/Blank.cpp | 9 +++------ src/Core/MIDI_Map.cpp | 1 + src/app/Knob.cpp | 3 +++ src/app/LedDisplay.cpp | 2 ++ src/app/ModuleWidget.cpp | 15 +++++++++------ src/app/ParamWidget.cpp | 5 ++--- src/app/PortWidget.cpp | 7 ++++++- src/app/RackWidget.cpp | 18 ++++++++---------- src/app/Scene.cpp | 8 ++++---- src/app/SvgButton.cpp | 3 +++ src/app/Switch.cpp | 3 +++ src/ui/Button.cpp | 3 +++ src/ui/MenuItem.cpp | 3 +++ src/ui/MenuOverlay.cpp | 6 +++--- src/ui/RadioButton.cpp | 3 +++ src/ui/ScrollBar.cpp | 3 +++ src/ui/ScrollWidget.cpp | 32 ++++++++++++++++++++++++++------ src/ui/Slider.cpp | 3 +++ src/ui/TextField.cpp | 4 ++-- 23 files changed, 98 insertions(+), 49 deletions(-) diff --git a/include/app/LedDisplay.hpp b/include/app/LedDisplay.hpp index eb069a8a..ac1f625b 100644 --- a/include/app/LedDisplay.hpp +++ b/include/app/LedDisplay.hpp @@ -1,7 +1,7 @@ #pragma once #include "app/common.hpp" +#include "widget/Widget.hpp" #include "widget/OpaqueWidget.hpp" -#include "widget/TransparentWidget.hpp" #include "ui/TextField.hpp" @@ -13,12 +13,12 @@ struct LedDisplay : widget::OpaqueWidget { void draw(const DrawArgs &args) override; }; -struct LedDisplaySeparator : widget::TransparentWidget { +struct LedDisplaySeparator : widget::Widget { LedDisplaySeparator(); void draw(const DrawArgs &args) override; }; -struct LedDisplayChoice : widget::TransparentWidget { +struct LedDisplayChoice : widget::OpaqueWidget { std::string text; std::shared_ptr font; math::Vec textOffset; diff --git a/include/app/RackWidget.hpp b/include/app/RackWidget.hpp index 0d7738ec..e5cac52c 100644 --- a/include/app/RackWidget.hpp +++ b/include/app/RackWidget.hpp @@ -32,7 +32,6 @@ struct RackWidget : widget::OpaqueWidget { void onHoverKey(const event::HoverKey &e) override; void onDragHover(const event::DragHover &e) override; void onButton(const event::Button &e) override; - void onZoom(const event::Zoom &e) override; /** Completely clear the rack's modules and cables */ void clear(); diff --git a/include/ui/ScrollWidget.hpp b/include/ui/ScrollWidget.hpp index 294a5c10..ed8bfc68 100644 --- a/include/ui/ScrollWidget.hpp +++ b/include/ui/ScrollWidget.hpp @@ -1,6 +1,6 @@ #pragma once #include "ui/common.hpp" -#include "widget/Widget.hpp" +#include "widget/OpaqueWidget.hpp" #include "ui/ScrollBar.hpp" @@ -9,7 +9,7 @@ namespace ui { /** Handles a container with ScrollBar */ -struct ScrollWidget : widget::Widget { +struct ScrollWidget : widget::OpaqueWidget { widget::Widget *container; ScrollBar *horizontalScrollBar; ScrollBar *verticalScrollBar; @@ -19,7 +19,9 @@ struct ScrollWidget : widget::Widget { void scrollTo(math::Rect r); void draw(const DrawArgs &args) override; void step() override; - void onHover(const event::Hover &e) override; + void onButton(const event::Button &e) override; + void onDragStart(const event::DragStart &e) override; + void onDragMove(const event::DragMove &e) override; void onHoverScroll(const event::HoverScroll &e) override; }; diff --git a/include/widget/OpaqueWidget.hpp b/include/widget/OpaqueWidget.hpp index 629f6bb8..309fb23f 100644 --- a/include/widget/OpaqueWidget.hpp +++ b/include/widget/OpaqueWidget.hpp @@ -8,7 +8,6 @@ namespace widget { /** A Widget that stops propagation of all recursive PositionEvents but gives a chance for children to consume first. Also consumes Hover and Button for left-clicks. -Remember to call these methods in your subclass if you wish to preserve default OpaqueWidget behavior. */ struct OpaqueWidget : Widget { void onHover(const event::Hover &e) override { diff --git a/src/Core/Blank.cpp b/src/Core/Blank.cpp index d92991ef..f4eecdc6 100644 --- a/src/Core/Blank.cpp +++ b/src/Core/Blank.cpp @@ -36,13 +36,10 @@ struct ModuleResizeHandle : OpaqueWidget { box.size = Vec(RACK_GRID_WIDTH * 1, RACK_GRID_HEIGHT); } - void onButton(const event::Button &e) override { - if (e.button == GLFW_MOUSE_BUTTON_LEFT) { - e.consume(this); - } - } - void onDragStart(const event::DragStart &e) override { + if (e.button != GLFW_MOUSE_BUTTON_LEFT) + return; + dragX = APP->scene->rack->mousePos.x; ModuleWidget *m = getAncestorOfType(); originalBox = m->box; diff --git a/src/Core/MIDI_Map.cpp b/src/Core/MIDI_Map.cpp index b752add1..ee7276d3 100644 --- a/src/Core/MIDI_Map.cpp +++ b/src/Core/MIDI_Map.cpp @@ -247,6 +247,7 @@ struct MIDI_MapChoice : LedDisplayChoice { } void onButton(const event::Button &e) override { + e.stopPropagating(); if (!module) return; diff --git a/src/app/Knob.cpp b/src/app/Knob.cpp index 11cadc35..13b3fb7b 100644 --- a/src/app/Knob.cpp +++ b/src/app/Knob.cpp @@ -29,6 +29,9 @@ void Knob::onButton(const event::Button &e) { } void Knob::onDragStart(const event::DragStart &e) { + if (e.button != GLFW_MOUSE_BUTTON_LEFT) + return; + if (paramQuantity) { oldValue = paramQuantity->getSmoothValue(); if (snap) { diff --git a/src/app/LedDisplay.cpp b/src/app/LedDisplay.cpp index 9937f25f..b15899fa 100644 --- a/src/app/LedDisplay.cpp +++ b/src/app/LedDisplay.cpp @@ -62,6 +62,8 @@ void LedDisplayChoice::draw(const DrawArgs &args) { } void LedDisplayChoice::onButton(const event::Button &e) { + OpaqueWidget::onButton(e); + if (e.action == GLFW_PRESS && (e.button == GLFW_MOUSE_BUTTON_LEFT || e.button == GLFW_MOUSE_BUTTON_RIGHT)) { event::Action eAction; onAction(eAction); diff --git a/src/app/ModuleWidget.cpp b/src/app/ModuleWidget.cpp index fa7564c7..05819f6e 100644 --- a/src/app/ModuleWidget.cpp +++ b/src/app/ModuleWidget.cpp @@ -305,8 +305,6 @@ void ModuleWidget::drawShadow(const DrawArgs &args) { } void ModuleWidget::onHover(const event::Hover &e) { - widget::OpaqueWidget::onHover(e); - if (!APP->event->selectedWidget) { // Instead of checking key-down events, delete the module even if key-repeat hasn't fired yet and the cursor is hovering over the widget. if ((glfwGetKey(APP->window->win, GLFW_KEY_DELETE) == GLFW_PRESS @@ -317,11 +315,13 @@ void ModuleWidget::onHover(const event::Hover &e) { return; } } + + OpaqueWidget::onHover(e); } void ModuleWidget::onButton(const event::Button &e) { - widget::OpaqueWidget::onButton(e); - if (e.getTarget() != this) + OpaqueWidget::onButton(e); + if (e.isConsumed()) return; if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) { @@ -331,8 +331,8 @@ void ModuleWidget::onButton(const event::Button &e) { } void ModuleWidget::onHoverKey(const event::HoverKey &e) { - widget::OpaqueWidget::onHoverKey(e); - if (e.getTarget() != this) + OpaqueWidget::onHoverKey(e); + if (e.isConsumed()) return; if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { @@ -384,6 +384,9 @@ void ModuleWidget::onHoverKey(const event::HoverKey &e) { } void ModuleWidget::onDragStart(const event::DragStart &e) { + if (e.button != GLFW_MOUSE_BUTTON_LEFT) + return; + oldPos = box.pos; dragPos = APP->scene->rack->mousePos.minus(box.pos); e.consume(this); diff --git a/src/app/ParamWidget.cpp b/src/app/ParamWidget.cpp index b02c95c1..d6b29fc9 100644 --- a/src/app/ParamWidget.cpp +++ b/src/app/ParamWidget.cpp @@ -119,7 +119,7 @@ void ParamWidget::step() { } } - OpaqueWidget::step(); + Widget::step(); } void ParamWidget::draw(const DrawArgs &args) { @@ -141,14 +141,13 @@ void ParamWidget::draw(const DrawArgs &args) { void ParamWidget::onButton(const event::Button &e) { OpaqueWidget::onButton(e); - if (e.getTarget() != this) - return; // Touch parameter if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT && (e.mods & WINDOW_MOD_MASK) == 0) { if (paramQuantity) { APP->scene->rack->touchedParam = this; } + e.consume(this); } // Right click to open context menu diff --git a/src/app/PortWidget.cpp b/src/app/PortWidget.cpp index 2dfc6638..6ad310e4 100644 --- a/src/app/PortWidget.cpp +++ b/src/app/PortWidget.cpp @@ -46,7 +46,7 @@ void PortWidget::step() { } plugLight->setBrightnesses(values); - OpaqueWidget::step(); + Widget::step(); } void PortWidget::draw(const DrawArgs &args) { @@ -73,6 +73,8 @@ void PortWidget::onButton(const event::Button &e) { APP->scene->rack->removeCable(cw); delete cw; } + + e.consume(this); } } @@ -86,6 +88,9 @@ void PortWidget::onLeave(const event::Leave &e) { } void PortWidget::onDragStart(const event::DragStart &e) { + if (e.button != GLFW_MOUSE_BUTTON_LEFT) + return; + CableWidget *cw = NULL; if ((APP->window->getMods() & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) { if (type == OUTPUT) { diff --git a/src/app/RackWidget.cpp b/src/app/RackWidget.cpp index 8cceb908..ddc8cdbf 100644 --- a/src/app/RackWidget.cpp +++ b/src/app/RackWidget.cpp @@ -109,21 +109,22 @@ void RackWidget::step() { rail->box.size = railFb->box.size; } - OpaqueWidget::step(); + Widget::step(); } void RackWidget::draw(const DrawArgs &args) { - OpaqueWidget::draw(args); + Widget::draw(args); } void RackWidget::onHover(const event::Hover &e) { + // Set before calling children's onHover() mousePos = e.pos; OpaqueWidget::onHover(e); } void RackWidget::onHoverKey(const event::HoverKey &e) { OpaqueWidget::onHoverKey(e); - if (e.getTarget() != this) + if (e.isConsumed()) return; if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { @@ -139,13 +140,14 @@ void RackWidget::onHoverKey(const event::HoverKey &e) { } void RackWidget::onDragHover(const event::DragHover &e) { - OpaqueWidget::onDragHover(e); mousePos = e.pos; + OpaqueWidget::onDragHover(e); } void RackWidget::onButton(const event::Button &e) { - OpaqueWidget::onButton(e); - if (e.getTarget() != this) + Widget::onButton(e); + e.stopPropagating(); + if (e.isConsumed()) return; if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) { @@ -154,10 +156,6 @@ void RackWidget::onButton(const event::Button &e) { } } -void RackWidget::onZoom(const event::Zoom &e) { - OpaqueWidget::onZoom(e); -} - void RackWidget::clear() { // This isn't required because removing all ModuleWidgets should remove all cables, but do it just in case. clearCables(); diff --git a/src/app/Scene.cpp b/src/app/Scene.cpp index b6e59fae..35caf3ae 100644 --- a/src/app/Scene.cpp +++ b/src/app/Scene.cpp @@ -64,16 +64,16 @@ void Scene::step() { latestVersion = ""; } - OpaqueWidget::step(); + Widget::step(); } void Scene::draw(const DrawArgs &args) { - OpaqueWidget::draw(args); + Widget::draw(args); } void Scene::onHoverKey(const event::HoverKey &e) { OpaqueWidget::onHoverKey(e); - if (e.getTarget() != this) + if (e.isConsumed()) return; if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { @@ -135,7 +135,7 @@ void Scene::onHoverKey(const event::HoverKey &e) { void Scene::onPathDrop(const event::PathDrop &e) { OpaqueWidget::onPathDrop(e); - if (e.getTarget() != this) + if (e.isConsumed()) return; if (e.paths.size() >= 1) { diff --git a/src/app/SvgButton.cpp b/src/app/SvgButton.cpp index 245deeb9..8c47471b 100644 --- a/src/app/SvgButton.cpp +++ b/src/app/SvgButton.cpp @@ -31,6 +31,9 @@ void SvgButton::addFrame(std::shared_ptr svg) { } void SvgButton::onDragStart(const event::DragStart &e) { + if (e.button != GLFW_MOUSE_BUTTON_LEFT) + return; + if (frames.size() >= 2) { sw->setSvg(frames[1]); fb->dirty = true; diff --git a/src/app/Switch.cpp b/src/app/Switch.cpp index 1e23c020..50de90dc 100644 --- a/src/app/Switch.cpp +++ b/src/app/Switch.cpp @@ -29,6 +29,9 @@ void Switch::onDoubleClick(const event::DoubleClick &e) { } void Switch::onDragStart(const event::DragStart &e) { + if (e.button != GLFW_MOUSE_BUTTON_LEFT) + return; + if (momentary) { if (paramQuantity) { // Set to maximum value diff --git a/src/ui/Button.cpp b/src/ui/Button.cpp index ce156626..8474a488 100644 --- a/src/ui/Button.cpp +++ b/src/ui/Button.cpp @@ -23,6 +23,9 @@ void Button::onLeave(const event::Leave &e) { } void Button::onDragStart(const event::DragStart &e) { + if (e.button != GLFW_MOUSE_BUTTON_LEFT) + return; + state = BND_ACTIVE; if (quantity) quantity->setMax(); diff --git a/src/ui/MenuItem.cpp b/src/ui/MenuItem.cpp index 472f1a67..929223c8 100644 --- a/src/ui/MenuItem.cpp +++ b/src/ui/MenuItem.cpp @@ -59,6 +59,9 @@ void MenuItem::onEnter(const event::Enter &e) { } void MenuItem::onDragStart(const event::DragStart &e) { + if (e.button != GLFW_MOUSE_BUTTON_LEFT) + return; + e.consume(this); } diff --git a/src/ui/MenuOverlay.cpp b/src/ui/MenuOverlay.cpp index 0da05052..fb5b9575 100644 --- a/src/ui/MenuOverlay.cpp +++ b/src/ui/MenuOverlay.cpp @@ -18,7 +18,7 @@ void MenuOverlay::step() { } void MenuOverlay::onButton(const event::Button &e) { - widget::OpaqueWidget::onButton(e); + OpaqueWidget::onButton(e); if (e.getTarget() != this) return; @@ -28,8 +28,8 @@ void MenuOverlay::onButton(const event::Button &e) { } void MenuOverlay::onHoverKey(const event::HoverKey &e) { - widget::OpaqueWidget::onHoverKey(e); - if (e.getTarget() != this) + OpaqueWidget::onHoverKey(e); + if (e.isConsumed()) return; if (e.action == GLFW_PRESS && e.key == GLFW_KEY_ESCAPE) { diff --git a/src/ui/RadioButton.cpp b/src/ui/RadioButton.cpp index 51dbfa5b..5e58cf82 100644 --- a/src/ui/RadioButton.cpp +++ b/src/ui/RadioButton.cpp @@ -30,6 +30,9 @@ void RadioButton::onLeave(const event::Leave &e) { } void RadioButton::onDragStart(const event::DragStart &e) { + if (e.button != GLFW_MOUSE_BUTTON_LEFT) + return; + e.consume(this); } diff --git a/src/ui/ScrollBar.cpp b/src/ui/ScrollBar.cpp index c0d0da81..7b79443e 100644 --- a/src/ui/ScrollBar.cpp +++ b/src/ui/ScrollBar.cpp @@ -17,6 +17,9 @@ void ScrollBar::draw(const DrawArgs &args) { } void ScrollBar::onDragStart(const event::DragStart &e) { + if (e.button != GLFW_MOUSE_BUTTON_LEFT) + return; + state = BND_ACTIVE; APP->window->cursorLock(); e.consume(this); diff --git a/src/ui/ScrollWidget.cpp b/src/ui/ScrollWidget.cpp index 23a8bd0e..1aaae2c7 100644 --- a/src/ui/ScrollWidget.cpp +++ b/src/ui/ScrollWidget.cpp @@ -63,19 +63,39 @@ void ScrollWidget::step() { verticalScrollBar->box.size.y = horizontalScrollBar->visible ? inner.y : box.size.y; } -void ScrollWidget::onHover(const event::Hover &e) { - widget::Widget::onHover(e); -} +void ScrollWidget::onButton(const event::Button &e) { + Widget::onButton(e); + if (e.isConsumed()) + return; -void ScrollWidget::onHoverScroll(const event::HoverScroll &e) { - widget::Widget::onHoverScroll(e); - if (e.getTarget() != this) + // Consume right button only if the scrollbars are visible + if (!(horizontalScrollBar->visible || verticalScrollBar->visible)) return; + if (e.button == GLFW_MOUSE_BUTTON_MIDDLE) { + e.consume(this); + } +} + +void ScrollWidget::onDragStart(const event::DragStart &e) { + if (e.button == GLFW_MOUSE_BUTTON_MIDDLE) { + e.consume(this); + } +} + +void ScrollWidget::onDragMove(const event::DragMove &e) { // Scroll only if the scrollbars are visible if (!(horizontalScrollBar->visible || verticalScrollBar->visible)) return; + offset = offset.minus(e.mouseDelta); +} + +void ScrollWidget::onHoverScroll(const event::HoverScroll &e) { + OpaqueWidget::onHoverScroll(e); + if (e.isConsumed()) + return; + math::Vec scrollDelta = e.scrollDelta; // Flip coordinates if shift is held if ((APP->window->getMods() & WINDOW_MOD_MASK) == GLFW_MOD_SHIFT) diff --git a/src/ui/Slider.cpp b/src/ui/Slider.cpp index cb3e78a7..05512a22 100644 --- a/src/ui/Slider.cpp +++ b/src/ui/Slider.cpp @@ -19,6 +19,9 @@ void Slider::draw(const DrawArgs &args) { } void Slider::onDragStart(const event::DragStart &e) { + if (e.button != GLFW_MOUSE_BUTTON_LEFT) + return; + state = BND_ACTIVE; APP->window->cursorLock(); e.consume(this); diff --git a/src/ui/TextField.cpp b/src/ui/TextField.cpp index 43afe856..3656cadb 100644 --- a/src/ui/TextField.cpp +++ b/src/ui/TextField.cpp @@ -31,7 +31,7 @@ void TextField::draw(const DrawArgs &args) { } void TextField::onHover(const event::Hover &e) { - widget::OpaqueWidget::onHover(e); + OpaqueWidget::onHover(e); if (this == APP->event->draggedWidget) { int pos = getTextPosition(e.pos); @@ -42,7 +42,7 @@ void TextField::onHover(const event::Hover &e) { } void TextField::onButton(const event::Button &e) { - widget::OpaqueWidget::onButton(e); + OpaqueWidget::onButton(e); if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT) { cursor = selection = getTextPosition(e.pos);