Browse Source

Add `event::Context::consumed`.

tags/v1.0.0
Andrew Belt 6 years ago
parent
commit
b232b8db37
3 changed files with 72 additions and 44 deletions
  1. +39
    -23
      include/event.hpp
  2. +8
    -5
      include/widget/OpaqueWidget.hpp
  3. +25
    -16
      src/event.cpp

+ 39
- 23
include/event.hpp View File

@@ -17,8 +17,12 @@ namespace event {


/** A per-event state shared and writable by all widgets that recursively handle an event. */ /** A per-event state shared and writable by all widgets that recursively handle an event. */
struct Context { struct Context {
widget::Widget *target = NULL;
/** Whether the event should continue recursing to children Widgets. */
bool propagating = true; bool propagating = true;
/** Whether the event has been consumed by an event handler and no more handlers should consume the event. */
bool consumed = false;
/** The widget that responded to the event. */
widget::Widget *target = NULL;
}; };




@@ -29,30 +33,36 @@ struct Base {
/** Prevents the event from being handled by more Widgets. /** Prevents the event from being handled by more Widgets.
*/ */
void stopPropagating() const { void stopPropagating() const {
if (context)
context->propagating = false;
if (!context) return;
context->propagating = false;
} }
bool isPropagating() const { bool isPropagating() const {
if (context)
return context->propagating;
return true;
if (!context) return true;
return context->propagating;
} }
/** Tells the event handler that a particular Widget consumed the event. /** Tells the event handler that a particular Widget consumed the event.
You usually want to stop propagation as well, so call consume() instead. You usually want to stop propagation as well, so call consume() instead.
*/ */
void setTarget(widget::Widget *w) const { void setTarget(widget::Widget *w) const {
if (context)
context->target = w;
if (!context) return;
context->target = w;
} }
widget::Widget *getTarget() const { widget::Widget *getTarget() const {
if (context)
return context->target;
return NULL;
if (!context) return NULL;
return context->target;
} }
/** Sets the target Widget and stops propagation. */
/** Sets the target Widget and stops propagating.
A NULL Widget may be passed to consume but not set a target.
*/
void consume(widget::Widget *w) const { void consume(widget::Widget *w) const {
setTarget(w);
stopPropagating();
if (!context) return;
context->propagating = false;
context->consumed = true;
context->target = w;
}
bool isConsumed() const {
if (!context) return false;
return context->consumed;
} }
}; };


@@ -150,7 +160,7 @@ struct Leave : Base {
}; };




/** Occurs when a Widget begins consuming the Button press event.
/** Occurs when a Widget begins consuming the Button press event for the left mouse button.
Must consume to set the widget as selected. Must consume to set the widget as selected.
*/ */
struct Select : Base { struct Select : Base {
@@ -177,22 +187,27 @@ struct SelectText : Base, TextBase {
}; };




struct DragBase : Base {
/** The mouse button held during the drag. */
int button;
};

/** Occurs when a Widget begins being dragged. /** Occurs when a Widget begins being dragged.
Must consume to set the widget as dragged. Must consume to set the widget as dragged.
*/ */
struct DragStart : Base {
struct DragStart : DragBase {
}; };




/** Occurs when a Widget stops being dragged by releasing the mouse button. /** Occurs when a Widget stops being dragged by releasing the mouse button.
*/ */
struct DragEnd : Base {
struct DragEnd : DragBase {
}; };




/** Occurs every frame on the dragged Widget. /** Occurs every frame on the dragged Widget.
*/ */
struct DragMove : Base {
struct DragMove : DragBase {
/** Change in mouse position since the last frame. Can be zero. */ /** Change in mouse position since the last frame. Can be zero. */
math::Vec mouseDelta; math::Vec mouseDelta;
}; };
@@ -201,7 +216,7 @@ struct DragMove : Base {
/** Occurs every frame when the mouse is hovering over a Widget while another Widget (possibly the same one) is being dragged. /** Occurs every frame when the mouse is hovering over a Widget while another Widget (possibly the same one) is being dragged.
Recurses until consumed. Recurses until consumed.
*/ */
struct DragHover : Base, PositionBase {
struct DragHover : DragBase, PositionBase {
/** The dragged widget */ /** The dragged widget */
widget::Widget *origin = NULL; widget::Widget *origin = NULL;
/** Change in mouse position since the last frame. Can be zero. */ /** Change in mouse position since the last frame. Can be zero. */
@@ -211,7 +226,7 @@ struct DragHover : Base, PositionBase {
/** Occurs when the mouse enters a Widget while dragging. /** Occurs when the mouse enters a Widget while dragging.
Must consume to set the widget as drag-hovered. Must consume to set the widget as drag-hovered.
*/ */
struct DragEnter : Base {
struct DragEnter : DragBase {
/** The dragged widget */ /** The dragged widget */
widget::Widget *origin = NULL; widget::Widget *origin = NULL;
}; };
@@ -219,7 +234,7 @@ struct DragEnter : Base {


/** Occurs when the mouse leaves a Widget while dragging. /** Occurs when the mouse leaves a Widget while dragging.
*/ */
struct DragLeave : Base {
struct DragLeave : DragBase {
/** The dragged widget */ /** The dragged widget */
widget::Widget *origin = NULL; widget::Widget *origin = NULL;
}; };
@@ -227,7 +242,7 @@ struct DragLeave : Base {


/** Occurs when the mouse button is released over a Widget while dragging. /** Occurs when the mouse button is released over a Widget while dragging.
*/ */
struct DragDrop : Base {
struct DragDrop : DragBase {
/** The dragged widget */ /** The dragged widget */
widget::Widget *origin = NULL; widget::Widget *origin = NULL;
}; };
@@ -308,6 +323,7 @@ struct State {
*/ */
widget::Widget *hoveredWidget = NULL; widget::Widget *hoveredWidget = NULL;
widget::Widget *draggedWidget = NULL; widget::Widget *draggedWidget = NULL;
int dragButton = 0;
widget::Widget *dragHoveredWidget = NULL; widget::Widget *dragHoveredWidget = NULL;
widget::Widget *selectedWidget = NULL; widget::Widget *selectedWidget = NULL;
/** For double-clicking */ /** For double-clicking */
@@ -315,7 +331,7 @@ struct State {
widget::Widget *lastClickedWidget = NULL; widget::Widget *lastClickedWidget = NULL;


void setHovered(widget::Widget *w); void setHovered(widget::Widget *w);
void setDragged(widget::Widget *w);
void setDragged(widget::Widget *w, int button);
void setDragHovered(widget::Widget *w); void setDragHovered(widget::Widget *w);
void setSelected(widget::Widget *w); void setSelected(widget::Widget *w);
/** Prepares a widget for deletion */ /** Prepares a widget for deletion */


+ 8
- 5
include/widget/OpaqueWidget.hpp View File

@@ -7,6 +7,7 @@ namespace widget {




/** A Widget that stops propagation of all recursive PositionEvents but gives a chance for children to consume first. /** 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. Remember to call these methods in your subclass if you wish to preserve default OpaqueWidget behavior.
*/ */
struct OpaqueWidget : Widget { struct OpaqueWidget : Widget {
@@ -14,15 +15,17 @@ struct OpaqueWidget : Widget {
Widget::onHover(e); Widget::onHover(e);
e.stopPropagating(); e.stopPropagating();
// Consume if not consumed by child // Consume if not consumed by child
if (!e.getTarget())
e.setTarget(this);
if (!e.isConsumed())
e.consume(this);
} }
void onButton(const event::Button &e) override { void onButton(const event::Button &e) override {
Widget::onButton(e); Widget::onButton(e);
e.stopPropagating(); e.stopPropagating();
// Consume if not consumed by child
if (!e.getTarget())
e.setTarget(this);
if (e.button == GLFW_MOUSE_BUTTON_LEFT) {
// Consume if not consumed by child
if (!e.isConsumed())
e.consume(this);
}
} }
void onHoverKey(const event::HoverKey &e) override { void onHoverKey(const event::HoverKey &e) override {
Widget::onHoverKey(e); Widget::onHoverKey(e);


+ 25
- 16
src/event.cpp View File

@@ -27,22 +27,26 @@ void State::setHovered(widget::Widget *w) {
} }
} }


void State::setDragged(widget::Widget *w) {
void State::setDragged(widget::Widget *w, int button) {
if (w == draggedWidget) if (w == draggedWidget)
return; return;


if (draggedWidget) { if (draggedWidget) {
// DragEnd // DragEnd
DragEnd eDragEnd; DragEnd eDragEnd;
eDragEnd.button = dragButton;
draggedWidget->onDragEnd(eDragEnd); draggedWidget->onDragEnd(eDragEnd);
draggedWidget = NULL; draggedWidget = NULL;
} }


dragButton = button;

if (w) { if (w) {
// DragStart // DragStart
Context cDragStart; Context cDragStart;
DragStart eDragStart; DragStart eDragStart;
eDragStart.context = &cDragStart; eDragStart.context = &cDragStart;
eDragStart.button = dragButton;
w->onDragStart(eDragStart); w->onDragStart(eDragStart);
draggedWidget = cDragStart.target; draggedWidget = cDragStart.target;
} }
@@ -55,6 +59,7 @@ void State::setDragHovered(widget::Widget *w) {
if (dragHoveredWidget) { if (dragHoveredWidget) {
// DragLeave // DragLeave
DragLeave eDragLeave; DragLeave eDragLeave;
eDragLeave.button = dragButton;
eDragLeave.origin = draggedWidget; eDragLeave.origin = draggedWidget;
dragHoveredWidget->onDragLeave(eDragLeave); dragHoveredWidget->onDragLeave(eDragLeave);
dragHoveredWidget = NULL; dragHoveredWidget = NULL;
@@ -65,6 +70,7 @@ void State::setDragHovered(widget::Widget *w) {
Context cDragEnter; Context cDragEnter;
DragEnter eDragEnter; DragEnter eDragEnter;
eDragEnter.context = &cDragEnter; eDragEnter.context = &cDragEnter;
eDragEnter.button = dragButton;
eDragEnter.origin = draggedWidget; eDragEnter.origin = draggedWidget;
w->onDragEnter(eDragEnter); w->onDragEnter(eDragEnter);
dragHoveredWidget = cDragEnter.target; dragHoveredWidget = cDragEnter.target;
@@ -94,7 +100,7 @@ void State::setSelected(widget::Widget *w) {


void State::finalizeWidget(widget::Widget *w) { void State::finalizeWidget(widget::Widget *w) {
if (hoveredWidget == w) setHovered(NULL); if (hoveredWidget == w) setHovered(NULL);
if (draggedWidget == w) setDragged(NULL);
if (draggedWidget == w) setDragged(NULL, 0);
if (dragHoveredWidget == w) setDragHovered(NULL); if (dragHoveredWidget == w) setDragHovered(NULL);
if (selectedWidget == w) setSelected(NULL); if (selectedWidget == w) setSelected(NULL);
if (lastClickedWidget == w) lastClickedWidget = NULL; if (lastClickedWidget == w) lastClickedWidget = NULL;
@@ -112,24 +118,25 @@ void State::handleButton(math::Vec pos, int button, int action, int mods) {
rootWidget->onButton(eButton); rootWidget->onButton(eButton);
widget::Widget *clickedWidget = cButton.target; widget::Widget *clickedWidget = cButton.target;


if (button == GLFW_MOUSE_BUTTON_LEFT) {
if (action == GLFW_PRESS) {
setDragged(clickedWidget);
}

if (action == GLFW_RELEASE) {
setDragHovered(NULL);
if (action == GLFW_PRESS) {
setDragged(clickedWidget, button);
}


if (clickedWidget && draggedWidget) {
// DragDrop
DragDrop eDragDrop;
eDragDrop.origin = draggedWidget;
clickedWidget->onDragDrop(eDragDrop);
}
if (action == GLFW_RELEASE) {
setDragHovered(NULL);


setDragged(NULL);
if (clickedWidget && draggedWidget) {
// DragDrop
DragDrop eDragDrop;
eDragDrop.button = dragButton;
eDragDrop.origin = draggedWidget;
clickedWidget->onDragDrop(eDragDrop);
} }


setDragged(NULL, 0);
}

if (button == GLFW_MOUSE_BUTTON_LEFT) {
if (action == GLFW_PRESS) { if (action == GLFW_PRESS) {
setSelected(clickedWidget); setSelected(clickedWidget);
} }
@@ -159,6 +166,7 @@ void State::handleHover(math::Vec pos, math::Vec mouseDelta) {
if (draggedWidget) { if (draggedWidget) {
// DragMove // DragMove
DragMove eDragMove; DragMove eDragMove;
eDragMove.button = dragButton;
eDragMove.mouseDelta = mouseDelta; eDragMove.mouseDelta = mouseDelta;
draggedWidget->onDragMove(eDragMove); draggedWidget->onDragMove(eDragMove);


@@ -166,6 +174,7 @@ void State::handleHover(math::Vec pos, math::Vec mouseDelta) {
Context cDragHover; Context cDragHover;
DragHover eDragHover; DragHover eDragHover;
eDragHover.context = &cDragHover; eDragHover.context = &cDragHover;
eDragHover.button = dragButton;
eDragHover.pos = pos; eDragHover.pos = pos;
eDragHover.mouseDelta = mouseDelta; eDragHover.mouseDelta = mouseDelta;
eDragHover.origin = draggedWidget; eDragHover.origin = draggedWidget;


Loading…
Cancel
Save