Browse Source

Replace `Event::consumed` with `target` and `propogating`.

tags/v1.0.0
Andrew Belt 5 years ago
parent
commit
13b3fabd8b
21 changed files with 134 additions and 142 deletions
  1. +1
    -0
      include/app/ParamWidget.hpp
  2. +2
    -2
      include/ui/MenuOverlay.hpp
  3. +1
    -1
      include/ui/TextField.hpp
  4. +0
    -31
      include/widget/ObstructWidget.hpp
  5. +21
    -13
      include/widget/OpaqueWidget.hpp
  6. +0
    -25
      include/widget/OverlayWidget.hpp
  7. +9
    -4
      include/widget/Widget.hpp
  8. +27
    -8
      include/widget/event.hpp
  9. +5
    -5
      src/Core/Blank.cpp
  10. +7
    -7
      src/app/ModuleBrowser.cpp
  11. +9
    -7
      src/app/ModuleWidget.cpp
  12. +5
    -4
      src/app/ParamWidget.cpp
  13. +2
    -1
      src/app/PortWidget.cpp
  14. +8
    -5
      src/app/RackWidget.cpp
  15. +8
    -6
      src/app/Scene.cpp
  16. +2
    -2
      src/app/Toolbar.cpp
  17. +1
    -1
      src/ui/MenuItem.cpp
  18. +6
    -2
      src/ui/MenuOverlay.cpp
  19. +1
    -1
      src/ui/ScrollWidget.cpp
  20. +10
    -8
      src/ui/TextField.cpp
  21. +9
    -9
      src/widget/event.cpp

+ 1
- 0
include/app/ParamWidget.hpp View File

@@ -18,6 +18,7 @@ struct ParamWidget : widget::OpaqueWidget {

void step() override;
void draw(const DrawArgs &args) override;

void onButton(const widget::ButtonEvent &e) override;
void onDoubleClick(const widget::DoubleClickEvent &e) override;
void onEnter(const widget::EnterEvent &e) override;


+ 2
- 2
include/ui/MenuOverlay.hpp View File

@@ -1,5 +1,5 @@
#pragma once
#include "widget/OverlayWidget.hpp"
#include "widget/OpaqueWidget.hpp"
#include "ui/common.hpp"


@@ -8,7 +8,7 @@ namespace ui {


/** Deletes itself from parent when clicked */
struct MenuOverlay : widget::OverlayWidget {
struct MenuOverlay : widget::OpaqueWidget {
void step() override;
void onButton(const widget::ButtonEvent &e) override;
void onHoverKey(const widget::HoverKeyEvent &e) override;


+ 1
- 1
include/ui/TextField.hpp View File

@@ -22,8 +22,8 @@ struct TextField : widget::OpaqueWidget {

TextField();
void draw(const DrawArgs &args) override;
void onButton(const widget::ButtonEvent &e) override;
void onHover(const widget::HoverEvent &e) override;
void onButton(const widget::ButtonEvent &e) override;
void onEnter(const widget::EnterEvent &e) override;
void onSelect(const widget::SelectEvent &e) override;
void onSelectText(const widget::SelectTextEvent &e) override;


+ 0
- 31
include/widget/ObstructWidget.hpp View File

@@ -1,31 +0,0 @@
#pragma once
#include "widget/Widget.hpp"


namespace rack {
namespace widget {


/** A Widget that consumes recursing events without giving a chance for children to consume.
*/
struct ObstructWidget : Widget {
void onHover(const HoverEvent &e) override {
e.consume(this);
}
void onButton(const ButtonEvent &e) override {
e.consume(this);
}
void onHoverKey(const HoverKeyEvent &e) override {
e.consume(this);
}
void onHoverText(const HoverTextEvent &e) override {
e.consume(this);
}
void onDragHover(const DragHoverEvent &e) override {
e.consume(this);
}
};


} // namespace widget
} // namespace rack

+ 21
- 13
include/widget/OpaqueWidget.hpp View File

@@ -6,35 +6,43 @@ namespace rack {
namespace widget {


/** A Widget that consumes recursing events but gives a chance for children to consume first.
You can of course override the events.
You may also call OpaqueWidget::on*() from the overridden method to continue recursing/consuming the event.
/** A Widget that stops propagation of all recursive PositionEvents but gives a chance for children to consume first.
Remember to call these methods in your subclass if you wish to preserve default OpaqueWidget behavior.
*/
struct OpaqueWidget : Widget {
void onHover(const HoverEvent &e) override {
Widget::onHover(e);
if (!e.getConsumed())
e.consume(this);
e.stopPropagating();
// Consume if not consumed by child
if (!e.getTarget())
e.setTarget(this);
}
void onButton(const ButtonEvent &e) override {
Widget::onButton(e);
if (!e.getConsumed())
e.consume(this);
e.stopPropagating();
// Consume if not consumed by child
if (!e.getTarget())
e.setTarget(this);
}
void onHoverKey(const HoverKeyEvent &e) override {
Widget::onHoverKey(e);
if (!e.getConsumed())
e.consume(this);
e.stopPropagating();
}
void onHoverText(const HoverTextEvent &e) override {
Widget::onHoverText(e);
if (!e.getConsumed())
e.consume(this);
e.stopPropagating();
}
void onHoverScroll(const HoverScrollEvent &e) override {
Widget::onHoverScroll(e);
e.stopPropagating();
}
void onDragHover(const DragHoverEvent &e) override {
Widget::onDragHover(e);
if (!e.getConsumed())
e.consume(this);
e.stopPropagating();
}
void onPathDrop(const PathDropEvent &e) override {
Widget::onPathDrop(e);
e.stopPropagating();
}
};



+ 0
- 25
include/widget/OverlayWidget.hpp View File

@@ -1,25 +0,0 @@
#pragma once
#include "widget/OpaqueWidget.hpp"


namespace rack {
namespace widget {


/** Like OpaqueWidget but consumes even more events. */
struct OverlayWidget : OpaqueWidget {
void onHoverScroll(const HoverScrollEvent &e) override {
Widget::onHoverScroll(e);
if (!e.getConsumed())
e.consume(this);
}
void onPathDrop(const PathDropEvent &e) override {
Widget::onPathDrop(e);
if (!e.getConsumed())
e.consume(this);
}
};


} // namespace widget
} // namespace rack

+ 9
- 4
include/widget/Widget.hpp View File

@@ -98,13 +98,18 @@ struct Widget {
template <typename TMethod, class TEvent>
void recurseEvent(TMethod f, const TEvent &e) {
for (auto it = children.rbegin(); it != children.rend(); it++) {
// Stop propagation if requested
if (!e.isPropagating())
break;
Widget *child = *it;
// Filter child by visibility
if (!child->visible)
continue;

// Clone event for (currently) no reason
TEvent e2 = e;
// Call child event handler
(child->*f)(e);
(child->*f)(e2);
}
}

@@ -112,6 +117,9 @@ struct Widget {
template <typename TMethod, class TEvent>
void recursePositionEvent(TMethod f, const TEvent &e) {
for (auto it = children.rbegin(); it != children.rend(); it++) {
// Stop propagation if requested
if (!e.isPropagating())
break;
Widget *child = *it;
// Filter child by visibility and position
if (!child->visible)
@@ -124,9 +132,6 @@ struct Widget {
e2.pos = e.pos.minus(child->box.pos);
// Call child event handler
(child->*f)(e2);
// Stop iterating if consumed
if (e.getConsumed())
break;
}
}



+ 27
- 8
include/widget/event.hpp View File

@@ -13,10 +13,8 @@ struct Widget;

/** A per-event state shared and writable by all widgets that recursively handle an event. */
struct EventContext {
/** The Widget that consumes the event.
This stops propagation of the event if applicable.
*/
Widget *consumed = NULL;
Widget *target = NULL;
bool propagating = true;
};


@@ -24,12 +22,33 @@ struct EventContext {
struct Event {
EventContext *context = NULL;

void consume(Widget *w) const {
/** Prevents the Event from being handled by more Widgets.
*/
void stopPropagating() const {
if (context)
context->consumed = w;
context->propagating = false;
}
Widget *getConsumed() const {
return context ? context->consumed : NULL;
bool isPropagating() const {
if (context)
return context->propagating;
return true;
}
/** Tells the event handler that a particular Widget consumed the event.
You usually want to stop propagation as well, so call consume() instead.
*/
void setTarget(Widget *w) const {
if (context)
context->target = w;
}
Widget *getTarget() const {
if (context)
return context->target;
return NULL;
}
/** Sets the target Widget and stops propagation. */
void consume(Widget *w) const {
setTarget(w);
stopPropagating();
}
};



+ 5
- 5
src/Core/Blank.cpp View File

@@ -27,7 +27,7 @@ struct BlankPanel : Widget {
};


struct ModuleResizeHandle : Widget {
struct ModuleResizeHandle : OpaqueWidget {
bool right = false;
float dragX;
Rect originalBox;
@@ -59,13 +59,13 @@ struct ModuleResizeHandle : Widget {
const float minWidth = 3 * RACK_GRID_WIDTH;
if (right) {
newBox.size.x += deltaX;
newBox.size.x = fmaxf(newBox.size.x, minWidth);
newBox.size.x = roundf(newBox.size.x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH;
newBox.size.x = std::fmax(newBox.size.x, minWidth);
newBox.size.x = std::round(newBox.size.x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH;
}
else {
newBox.size.x -= deltaX;
newBox.size.x = fmaxf(newBox.size.x, minWidth);
newBox.size.x = roundf(newBox.size.x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH;
newBox.size.x = std::fmax(newBox.size.x, minWidth);
newBox.size.x = std::round(newBox.size.x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH;
newBox.pos.x = originalBox.pos.x + originalBox.size.x - newBox.size.x;
}
APP->scene->rack->requestModuleBox(m, newBox);


+ 7
- 7
src/app/ModuleBrowser.cpp View File

@@ -1,6 +1,5 @@
#include "app/ModuleBrowser.hpp"
#include "widget/OpaqueWidget.hpp"
#include "widget/OverlayWidget.hpp"
#include "widget/TransparentWidget.hpp"
#include "widget/ZoomWidget.hpp"
#include "ui/ScrollWidget.hpp"
@@ -53,21 +52,22 @@ static float modelScore(plugin::Model *model, const std::string &search) {
}


struct BrowserOverlay : widget::OverlayWidget {
struct BrowserOverlay : widget::OpaqueWidget {
void step() override {
box = parent->box.zeroPos();
// Only step if visible, since there are potentially thousands of descendants that don't need to be stepped.
if (visible)
OverlayWidget::step();
OpaqueWidget::step();
}

void onButton(const widget::ButtonEvent &e) override {
OverlayWidget::onButton(e);
if (e.getConsumed() != this)
OpaqueWidget::onButton(e);
if (e.getTarget() != this)
return;

if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT) {
hide();
e.consume(this);
}
}
};
@@ -291,7 +291,7 @@ struct BrowserSearchField : ui::TextField {
}
}

if (!e.getConsumed())
if (!e.getTarget())
ui::TextField::onSelectKey(e);
}

@@ -615,7 +615,7 @@ struct ModuleBrowser : widget::OpaqueWidget {

inline void ModelBox::onButton(const widget::ButtonEvent &e) {
OpaqueWidget::onButton(e);
if (e.getConsumed() != this)
if (e.getTarget() != this)
return;

if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT) {


+ 9
- 7
src/app/ModuleWidget.cpp View File

@@ -321,15 +321,20 @@ void ModuleWidget::onHover(const widget::HoverEvent &e) {

void ModuleWidget::onButton(const widget::ButtonEvent &e) {
widget::OpaqueWidget::onButton(e);
if (e.getTarget() != this)
return;

if (e.getConsumed() == this) {
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) {
createContextMenu();
}
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) {
createContextMenu();
e.consume(this);
}
}

void ModuleWidget::onHoverKey(const widget::HoverKeyEvent &e) {
widget::OpaqueWidget::onHoverKey(e);
if (e.getTarget() != this)
return;

if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) {
switch (e.key) {
case GLFW_KEY_I: {
@@ -376,9 +381,6 @@ void ModuleWidget::onHoverKey(const widget::HoverKeyEvent &e) {
} break;
}
}

if (!e.getConsumed())
widget::OpaqueWidget::onHoverKey(e);
}

void ModuleWidget::onDragStart(const widget::DragStartEvent &e) {


+ 5
- 4
src/app/ParamWidget.cpp View File

@@ -51,7 +51,7 @@ struct ParamField : ui::TextField {
e.consume(this);
}

if (!e.getConsumed())
if (!e.getTarget())
TextField::onSelectKey(e);
}
};
@@ -140,6 +140,10 @@ void ParamWidget::draw(const DrawArgs &args) {
}

void ParamWidget::onButton(const widget::ButtonEvent &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) {
@@ -152,9 +156,6 @@ void ParamWidget::onButton(const widget::ButtonEvent &e) {
createContextMenu();
e.consume(this);
}

if (!e.getConsumed())
OpaqueWidget::onButton(e);
}

void ParamWidget::onDoubleClick(const widget::DoubleClickEvent &e) {


+ 2
- 1
src/app/PortWidget.cpp View File

@@ -60,6 +60,8 @@ void PortWidget::draw(const DrawArgs &args) {
}

void PortWidget::onButton(const widget::ButtonEvent &e) {
OpaqueWidget::onButton(e);

if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) {
CableWidget *cw = APP->scene->rack->getTopCable(this);
if (cw) {
@@ -72,7 +74,6 @@ void PortWidget::onButton(const widget::ButtonEvent &e) {
delete cw;
}
}
e.consume(this);
}

void PortWidget::onEnter(const widget::EnterEvent &e) {


+ 8
- 5
src/app/RackWidget.cpp View File

@@ -123,7 +123,7 @@ void RackWidget::onHover(const widget::HoverEvent &e) {

void RackWidget::onHoverKey(const widget::HoverKeyEvent &e) {
OpaqueWidget::onHoverKey(e);
if (e.getConsumed() != this)
if (e.getTarget() != this)
return;

if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) {
@@ -132,6 +132,7 @@ void RackWidget::onHoverKey(const widget::HoverKeyEvent &e) {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
pastePresetClipboardAction();
}
e.consume(this);
} break;
}
}
@@ -144,10 +145,12 @@ void RackWidget::onDragHover(const widget::DragHoverEvent &e) {

void RackWidget::onButton(const widget::ButtonEvent &e) {
OpaqueWidget::onButton(e);
if (e.getConsumed() == this) {
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) {
APP->scene->moduleBrowser->show();
}
if (e.getTarget() != this)
return;

if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) {
APP->scene->moduleBrowser->show();
e.consume(this);
}
}



+ 8
- 6
src/app/Scene.cpp View File

@@ -72,6 +72,10 @@ void Scene::draw(const DrawArgs &args) {
}

void Scene::onHoverKey(const widget::HoverKeyEvent &e) {
OpaqueWidget::onHoverKey(e);
if (e.getTarget() != this)
return;

if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) {
switch (e.key) {
case GLFW_KEY_N: {
@@ -127,12 +131,13 @@ void Scene::onHoverKey(const widget::HoverKeyEvent &e) {
}
}
}

if (!e.getConsumed())
OpaqueWidget::onHoverKey(e);
}

void Scene::onPathDrop(const widget::PathDropEvent &e) {
OpaqueWidget::onPathDrop(e);
if (e.getTarget() != this)
return;

if (e.paths.size() >= 1) {
const std::string &path = e.paths[0];
if (string::filenameExtension(string::filename(path)) == "vcv") {
@@ -140,9 +145,6 @@ void Scene::onPathDrop(const widget::PathDropEvent &e) {
e.consume(this);
}
}

if (!e.getConsumed())
OpaqueWidget::onPathDrop(e);
}

void Scene::runCheckVersion() {


+ 2
- 2
src/app/Toolbar.cpp View File

@@ -423,7 +423,7 @@ struct AccountEmailField : ui::TextField {
e.consume(this);
}

if (!e.getConsumed())
if (!e.getTarget())
ui::TextField::onSelectKey(e);
}
};
@@ -437,7 +437,7 @@ struct AccountPasswordField : ui::PasswordField {
e.consume(this);
}

if (!e.getConsumed())
if (!e.getTarget())
ui::PasswordField::onSelectKey(e);
}
};


+ 1
- 1
src/ui/MenuItem.cpp View File

@@ -78,7 +78,7 @@ void MenuItem::doAction() {
// Consume event by default, but allow action to un-consume it to prevent the menu from being removed.
eAction.consume(this);
onAction(eAction);
if (!cAction.consumed)
if (!cAction.target)
return;

MenuOverlay *overlay = getAncestorOfType<MenuOverlay>();


+ 6
- 2
src/ui/MenuOverlay.cpp View File

@@ -19,16 +19,20 @@ void MenuOverlay::step() {

void MenuOverlay::onButton(const widget::ButtonEvent &e) {
widget::OpaqueWidget::onButton(e);
if (e.getTarget() != this)
return;

if (e.getConsumed() == this && e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT) {
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT) {
requestedDelete = true;
}
}

void MenuOverlay::onHoverKey(const widget::HoverKeyEvent &e) {
widget::OpaqueWidget::onHoverKey(e);
if (e.getTarget() != this)
return;

if (e.getConsumed() == this && e.action == GLFW_PRESS && e.key == GLFW_KEY_ESCAPE) {
if (e.action == GLFW_PRESS && e.key == GLFW_KEY_ESCAPE) {
requestedDelete = true;
}
}


+ 1
- 1
src/ui/ScrollWidget.cpp View File

@@ -70,7 +70,7 @@ void ScrollWidget::onHover(const widget::HoverEvent &e) {

void ScrollWidget::onHoverScroll(const widget::HoverScrollEvent &e) {
widget::Widget::onHoverScroll(e);
if (e.getConsumed())
if (e.getTarget() != this)
return;

// Scroll only if the scrollbars are visible


+ 10
- 8
src/ui/TextField.cpp View File

@@ -30,21 +30,23 @@ void TextField::draw(const DrawArgs &args) {
nvgResetScissor(args.vg);
}

void TextField::onButton(const widget::ButtonEvent &e) {
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT) {
cursor = selection = getTextPosition(e.pos);
}
widget::OpaqueWidget::onButton(e);
}

void TextField::onHover(const widget::HoverEvent &e) {
widget::OpaqueWidget::onHover(e);

if (this == APP->event->draggedWidget) {
int pos = getTextPosition(e.pos);
if (pos != selection) {
cursor = pos;
}
}
widget::OpaqueWidget::onHover(e);
}

void TextField::onButton(const widget::ButtonEvent &e) {
widget::OpaqueWidget::onButton(e);

if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT) {
cursor = selection = getTextPosition(e.pos);
}
}

void TextField::onEnter(const widget::EnterEvent &e) {


+ 9
- 9
src/widget/event.cpp View File

@@ -23,7 +23,7 @@ void EventState::setHovered(Widget *w) {
EnterEvent eEnter;
eEnter.context = &cEnter;
w->onEnter(eEnter);
hoveredWidget = cEnter.consumed;
hoveredWidget = cEnter.target;
}
}

@@ -44,7 +44,7 @@ void EventState::setDragged(Widget *w) {
DragStartEvent eDragStart;
eDragStart.context = &cDragStart;
w->onDragStart(eDragStart);
draggedWidget = cDragStart.consumed;
draggedWidget = cDragStart.target;
}
}

@@ -67,7 +67,7 @@ void EventState::setDragHovered(Widget *w) {
eDragEnter.context = &cDragEnter;
eDragEnter.origin = draggedWidget;
w->onDragEnter(eDragEnter);
dragHoveredWidget = cDragEnter.consumed;
dragHoveredWidget = cDragEnter.target;
}
}

@@ -88,7 +88,7 @@ void EventState::setSelected(Widget *w) {
SelectEvent eSelect;
eSelect.context = &cSelect;
w->onSelect(eSelect);
selectedWidget = cSelect.consumed;
selectedWidget = cSelect.target;
}
}

@@ -110,7 +110,7 @@ void EventState::handleButton(math::Vec pos, int button, int action, int mods) {
eButton.action = action;
eButton.mods = mods;
rootWidget->onButton(eButton);
Widget *clickedWidget = cButton.consumed;
Widget *clickedWidget = cButton.target;

if (button == GLFW_MOUSE_BUTTON_LEFT) {
if (action == GLFW_PRESS) {
@@ -171,7 +171,7 @@ void EventState::handleHover(math::Vec pos, math::Vec mouseDelta) {
eDragHover.origin = draggedWidget;
rootWidget->onDragHover(eDragHover);

setDragHovered(cDragHover.consumed);
setDragHovered(cDragHover.target);

return;
}
@@ -184,7 +184,7 @@ void EventState::handleHover(math::Vec pos, math::Vec mouseDelta) {
eHover.mouseDelta = mouseDelta;
rootWidget->onHover(eHover);

setHovered(cHover.consumed);
setHovered(cHover.target);
}

void EventState::handleLeave() {
@@ -219,7 +219,7 @@ void EventState::handleText(math::Vec pos, int codepoint) {
eSelectText.context = &cSelectText;
eSelectText.codepoint = codepoint;
selectedWidget->onSelectText(eSelectText);
if (cSelectText.consumed)
if (cSelectText.target)
return;
}

@@ -243,7 +243,7 @@ void EventState::handleKey(math::Vec pos, int key, int scancode, int action, int
eSelectKey.action = action;
eSelectKey.mods = mods;
selectedWidget->onSelectKey(eSelectKey);
if (cSelectKey.consumed)
if (cSelectKey.target)
return;
}



Loading…
Cancel
Save