@@ -14,7 +14,7 @@ struct WidgetState { | |||
Widget *selectedWidget; | |||
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. | |||
*/ | |||
struct DragStart : Event { | |||
int button; | |||
EVENT_TRIGGER_DECLARATION(); | |||
}; | |||
@@ -160,7 +159,6 @@ struct DragStart : Event { | |||
/** Occurs when a Widget stops being dragged by releasing the mouse button. | |||
*/ | |||
struct DragEnd : Event { | |||
int button; | |||
EVENT_TRIGGER_DECLARATION(); | |||
}; | |||
@@ -169,7 +167,6 @@ struct DragEnd : Event { | |||
Called once per frame, even when mouseDelta is zero. | |||
*/ | |||
struct DragMove : Event { | |||
int button; | |||
math::Vec mouseDelta; | |||
EVENT_TRIGGER_DECLARATION(); | |||
}; | |||
@@ -179,7 +176,6 @@ struct DragMove : Event { | |||
*/ | |||
struct DragEnter : Event { | |||
Widget *origin = NULL; | |||
int button; | |||
EVENT_TRIGGER_DECLARATION(); | |||
}; | |||
@@ -188,7 +184,6 @@ struct DragEnter : Event { | |||
*/ | |||
struct DragLeave : Event { | |||
Widget *origin = NULL; | |||
int button; | |||
EVENT_TRIGGER_DECLARATION(); | |||
}; | |||
@@ -197,7 +192,6 @@ struct DragLeave : Event { | |||
*/ | |||
struct DragDrop : Event { | |||
Widget *origin = NULL; | |||
int button; | |||
EVENT_TRIGGER_DECLARATION(); | |||
}; | |||
@@ -9,6 +9,7 @@ namespace rack { | |||
/** A widget that responds to events */ | |||
struct EventWidget : Widget { | |||
void handleEvent(event::Event &e) override { | |||
// Call visitor's visit method | |||
e.trigger(this); | |||
} | |||
@@ -20,11 +21,14 @@ struct EventWidget : Widget { | |||
continue; | |||
if (!child->box.contains(e.pos)) | |||
continue; | |||
// Clone event so modifications do not up-propagate | |||
TEvent e2 = e; | |||
e2.pos = e.pos.minus(child->box.pos); | |||
child->handleEvent(e2); | |||
// Up-propagate target if consumed | |||
if (e2.target) { | |||
e.target = e.target; | |||
e.target = e2.target; | |||
break; | |||
} | |||
} | |||
@@ -20,9 +20,10 @@ struct Event; | |||
struct Widget { | |||
/** Stores position and size */ | |||
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; | |||
std::list<Widget*> children; | |||
/** Disable rendering but continue stepping */ | |||
/** Disables rendering but allow stepping */ | |||
bool visible = true; | |||
/** If set to true, parent will delete Widget in the next step() */ | |||
bool requestedDelete = false; | |||
@@ -75,7 +76,9 @@ struct Widget { | |||
virtual void draw(NVGcontext *vg); | |||
/** 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 | |||
WidgetState *gWidgetState = NULL; | |||
@@ -60,49 +60,7 @@ static void mouseButtonCallback(GLFWwindow *window, int button, int action, int | |||
} | |||
#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) { | |||
@@ -216,8 +174,6 @@ void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) { | |||
if (gWidgetState->draggedWidget) { | |||
event::DragMove eDragMove; | |||
// TODO | |||
eDragMove.button = 0; | |||
eDragMove.mouseDelta = mouseDelta; | |||
gWidgetState->draggedWidget->handleEvent(eDragMove); | |||
} | |||