| @@ -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); | ||||
| } | } | ||||