Browse Source

Add `event::Context::consumed`.

tags/v1.0.0
Andrew Belt 5 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. */
struct Context {
widget::Widget *target = NULL;
/** Whether the event should continue recursing to children Widgets. */
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.
*/
void stopPropagating() const {
if (context)
context->propagating = false;
if (!context) return;
context->propagating = false;
}
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.
You usually want to stop propagation as well, so call consume() instead.
*/
void setTarget(widget::Widget *w) const {
if (context)
context->target = w;
if (!context) return;
context->target = w;
}
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 {
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.
*/
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.
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.
*/
struct DragEnd : Base {
struct DragEnd : DragBase {
};


/** Occurs every frame on the dragged Widget.
*/
struct DragMove : Base {
struct DragMove : DragBase {
/** Change in mouse position since the last frame. Can be zero. */
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.
Recurses until consumed.
*/
struct DragHover : Base, PositionBase {
struct DragHover : DragBase, PositionBase {
/** The dragged widget */
widget::Widget *origin = NULL;
/** 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.
Must consume to set the widget as drag-hovered.
*/
struct DragEnter : Base {
struct DragEnter : DragBase {
/** The dragged widget */
widget::Widget *origin = NULL;
};
@@ -219,7 +234,7 @@ struct DragEnter : Base {

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

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

void setHovered(widget::Widget *w);
void setDragged(widget::Widget *w);
void setDragged(widget::Widget *w, int button);
void setDragHovered(widget::Widget *w);
void setSelected(widget::Widget *w);
/** 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.
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 {
@@ -14,15 +15,17 @@ struct OpaqueWidget : Widget {
Widget::onHover(e);
e.stopPropagating();
// 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 {
Widget::onButton(e);
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 {
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)
return;

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

dragButton = button;

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

void State::finalizeWidget(widget::Widget *w) {
if (hoveredWidget == w) setHovered(NULL);
if (draggedWidget == w) setDragged(NULL);
if (draggedWidget == w) setDragged(NULL, 0);
if (dragHoveredWidget == w) setDragHovered(NULL);
if (selectedWidget == w) setSelected(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);
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) {
setSelected(clickedWidget);
}
@@ -159,6 +166,7 @@ void State::handleHover(math::Vec pos, math::Vec mouseDelta) {
if (draggedWidget) {
// DragMove
DragMove eDragMove;
eDragMove.button = dragButton;
eDragMove.mouseDelta = mouseDelta;
draggedWidget->onDragMove(eDragMove);

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


Loading…
Cancel
Save