@@ -14,7 +14,7 @@ struct WidgetState { | |||||
Widget *selectedWidget; | Widget *selectedWidget; | ||||
WidgetState(); | WidgetState(); | ||||
void handleButton(math::Vec pos, int button, int action, int mods); | |||||
}; | }; | ||||
@@ -152,7 +152,6 @@ struct SelectText : Event, Text { | |||||
Must consume to allow the drag to occur. | Must consume to allow the drag to occur. | ||||
*/ | */ | ||||
struct DragStart : Event { | struct DragStart : Event { | ||||
int button; | |||||
EVENT_TRIGGER_DECLARATION(); | EVENT_TRIGGER_DECLARATION(); | ||||
}; | }; | ||||
@@ -160,7 +159,6 @@ struct DragStart : Event { | |||||
/** 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 : Event { | struct DragEnd : Event { | ||||
int button; | |||||
EVENT_TRIGGER_DECLARATION(); | EVENT_TRIGGER_DECLARATION(); | ||||
}; | }; | ||||
@@ -169,7 +167,6 @@ struct DragEnd : Event { | |||||
Called once per frame, even when mouseDelta is zero. | Called once per frame, even when mouseDelta is zero. | ||||
*/ | */ | ||||
struct DragMove : Event { | struct DragMove : Event { | ||||
int button; | |||||
math::Vec mouseDelta; | math::Vec mouseDelta; | ||||
EVENT_TRIGGER_DECLARATION(); | EVENT_TRIGGER_DECLARATION(); | ||||
}; | }; | ||||
@@ -179,7 +176,6 @@ struct DragMove : Event { | |||||
*/ | */ | ||||
struct DragEnter : Event { | struct DragEnter : Event { | ||||
Widget *origin = NULL; | Widget *origin = NULL; | ||||
int button; | |||||
EVENT_TRIGGER_DECLARATION(); | EVENT_TRIGGER_DECLARATION(); | ||||
}; | }; | ||||
@@ -188,7 +184,6 @@ struct DragEnter : Event { | |||||
*/ | */ | ||||
struct DragLeave : Event { | struct DragLeave : Event { | ||||
Widget *origin = NULL; | Widget *origin = NULL; | ||||
int button; | |||||
EVENT_TRIGGER_DECLARATION(); | EVENT_TRIGGER_DECLARATION(); | ||||
}; | }; | ||||
@@ -197,7 +192,6 @@ struct DragLeave : Event { | |||||
*/ | */ | ||||
struct DragDrop : Event { | struct DragDrop : Event { | ||||
Widget *origin = NULL; | Widget *origin = NULL; | ||||
int button; | |||||
EVENT_TRIGGER_DECLARATION(); | EVENT_TRIGGER_DECLARATION(); | ||||
}; | }; | ||||
@@ -9,6 +9,7 @@ namespace rack { | |||||
/** A widget that responds to events */ | /** A widget that responds to events */ | ||||
struct EventWidget : Widget { | struct EventWidget : Widget { | ||||
void handleEvent(event::Event &e) override { | void handleEvent(event::Event &e) override { | ||||
// Call visitor's visit method | |||||
e.trigger(this); | e.trigger(this); | ||||
} | } | ||||
@@ -20,11 +21,14 @@ struct EventWidget : Widget { | |||||
continue; | continue; | ||||
if (!child->box.contains(e.pos)) | if (!child->box.contains(e.pos)) | ||||
continue; | continue; | ||||
// Clone event so modifications do not up-propagate | |||||
TEvent e2 = e; | TEvent e2 = e; | ||||
e2.pos = e.pos.minus(child->box.pos); | e2.pos = e.pos.minus(child->box.pos); | ||||
child->handleEvent(e2); | child->handleEvent(e2); | ||||
// Up-propagate target if consumed | |||||
if (e2.target) { | if (e2.target) { | ||||
e.target = e.target; | |||||
e.target = e2.target; | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
@@ -20,9 +20,10 @@ struct Event; | |||||
struct Widget { | struct Widget { | ||||
/** Stores position and size */ | /** Stores position and size */ | ||||
math::Rect box = math::Rect(math::Vec(), math::Vec(INFINITY, INFINITY)); | math::Rect box = math::Rect(math::Vec(), math::Vec(INFINITY, INFINITY)); | ||||
/** Automatically set when Widget is added as a child to another Widget */ | |||||
Widget *parent = NULL; | Widget *parent = NULL; | ||||
std::list<Widget*> children; | std::list<Widget*> children; | ||||
/** Disable rendering but continue stepping */ | |||||
/** Disables rendering but allow stepping */ | |||||
bool visible = true; | bool visible = true; | ||||
/** If set to true, parent will delete Widget in the next step() */ | /** If set to true, parent will delete Widget in the next step() */ | ||||
bool requestedDelete = false; | bool requestedDelete = false; | ||||
@@ -75,7 +76,9 @@ struct Widget { | |||||
virtual void draw(NVGcontext *vg); | virtual void draw(NVGcontext *vg); | ||||
/** Trigger an event on this Widget. */ | /** Trigger an event on this Widget. */ | ||||
virtual void handleEvent(event::Event &e) {} | |||||
virtual void handleEvent(event::Event &e) { | |||||
// Basic widgets do not handle events, but the EventWidget subclass does. | |||||
} | |||||
}; | }; | ||||
@@ -12,6 +12,51 @@ WidgetState::WidgetState() { | |||||
} | } | ||||
void WidgetState::handleButton(math::Vec pos, int button, int action, int mods) { | |||||
// Button event | |||||
event::Button eButton; | |||||
eButton.button = button; | |||||
eButton.action = action; | |||||
eButton.mods = mods; | |||||
rootWidget->handleEvent(eButton); | |||||
Widget *clickedWidget = eButton.target; | |||||
if (button == GLFW_MOUSE_BUTTON_LEFT && clickedWidget) { | |||||
// Drag events | |||||
if (action == GLFW_PRESS && !draggedWidget) { | |||||
event::DragStart eDragStart; | |||||
clickedWidget->handleEvent(eDragStart); | |||||
draggedWidget = eDragStart.target; | |||||
} | |||||
if (action == GLFW_RELEASE && draggedWidget) { | |||||
event::DragDrop eDragDrop; | |||||
eDragDrop.origin = draggedWidget; | |||||
clickedWidget->handleEvent(eDragDrop); | |||||
event::DragEnd eDragEnd; | |||||
draggedWidget->handleEvent(eDragEnd); | |||||
draggedWidget = NULL; | |||||
} | |||||
// Select events | |||||
if (action == GLFW_PRESS && clickedWidget != selectedWidget) { | |||||
if (selectedWidget) { | |||||
event::Deselect eDeselect; | |||||
selectedWidget->handleEvent(eDeselect); | |||||
} | |||||
selectedWidget = clickedWidget; | |||||
if (selectedWidget) { | |||||
event::Select eSelect; | |||||
selectedWidget->handleEvent(eSelect); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
// TODO Move this elsewhere | // TODO Move this elsewhere | ||||
WidgetState *gWidgetState = NULL; | WidgetState *gWidgetState = NULL; | ||||
@@ -60,49 +60,7 @@ static void mouseButtonCallback(GLFWwindow *window, int button, int action, int | |||||
} | } | ||||
#endif | #endif | ||||
// event::Button | |||||
event::Button eButton; | |||||
eButton.button = button; | |||||
eButton.action = action; | |||||
eButton.mods = mods; | |||||
gWidgetState->rootWidget->handleEvent(eButton); | |||||
Widget *clickedWidget = eButton.target; | |||||
// Dragging | |||||
if (clickedWidget) { | |||||
// TODO keep track of dragged mouse button | |||||
if (action == GLFW_PRESS) { | |||||
event::DragStart eDragStart; | |||||
eDragStart.button = button; | |||||
clickedWidget->handleEvent(eDragStart); | |||||
gWidgetState->draggedWidget = eDragStart.target; | |||||
} | |||||
if (action == GLFW_RELEASE) { | |||||
event::DragEnd eDragEnd; | |||||
// TODO Use dragged button | |||||
eDragEnd.button = button; | |||||
clickedWidget->handleEvent(eDragEnd); | |||||
gWidgetState->draggedWidget = eDragEnd.target; | |||||
} | |||||
} | |||||
// Selection | |||||
if (action == GLFW_PRESS && button == GLFW_MOUSE_BUTTON_LEFT) { | |||||
if (clickedWidget != gWidgetState->selectedWidget) { | |||||
if (gWidgetState->selectedWidget) { | |||||
event::Deselect eDeselect; | |||||
gWidgetState->selectedWidget->handleEvent(eDeselect); | |||||
} | |||||
gWidgetState->selectedWidget = clickedWidget; | |||||
if (gWidgetState->selectedWidget) { | |||||
event::Select eSelect; | |||||
gWidgetState->selectedWidget->handleEvent(eSelect); | |||||
} | |||||
} | |||||
} | |||||
gWidgetState->handleButton(gMousePos, button, action, mods); | |||||
/* | /* | ||||
if (action == GLFW_PRESS) { | if (action == GLFW_PRESS) { | ||||
@@ -216,8 +174,6 @@ void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) { | |||||
if (gWidgetState->draggedWidget) { | if (gWidgetState->draggedWidget) { | ||||
event::DragMove eDragMove; | event::DragMove eDragMove; | ||||
// TODO | |||||
eDragMove.button = 0; | |||||
eDragMove.mouseDelta = mouseDelta; | eDragMove.mouseDelta = mouseDelta; | ||||
gWidgetState->draggedWidget->handleEvent(eDragMove); | gWidgetState->draggedWidget->handleEvent(eDragMove); | ||||
} | } | ||||