#include "event_router.hpp" #include "dbc.hpp" #include "events.hpp" namespace gui { namespace routing { using enum Event; using enum State; gui::Event Router::process_event(std::optional ev) { $next_event = gui::Event::TICK; if(ev->is()) { return gui::Event::QUIT; } if(const auto* mouse = ev->getIf()) { if(mouse->button == sf::Mouse::Button::Left) { position = mouse->position; event(MOUSE_DOWN); } } else if(const auto* mouse = ev->getIf()) { if(mouse->button == sf::Mouse::Button::Left) { position = mouse->position; event(MOUSE_UP); } } else if(const auto* mouse = ev->getIf()) { position = mouse->position; event(MOUSE_MOVE); } if(const auto* key = ev->getIf()) { scancode = key->scancode; event(KEY_PRESS); } return $next_event; } void Router::event(Event ev) { switch($state) { FSM_STATE(State, START, ev); FSM_STATE(State, IDLE, ev); FSM_STATE(State, MOUSE_ACTIVE, ev); FSM_STATE(State, MOUSE_MOVING, ev); FSM_STATE(State, MOUSE_DRAGGING, ev); } } void Router::START(Event ) { state(State::IDLE); } void Router::IDLE(Event ev) { switch(ev) { case MOUSE_DOWN: move_count=0; set_event(gui::Event::TICK); state(State::MOUSE_ACTIVE); break; case MOUSE_MOVE: set_event(gui::Event::MOUSE_MOVE); break; case KEY_PRESS: set_event(gui::Event::KEY_PRESS); break; default: dbc::sentinel("invalid event"); } } void Router::MOUSE_ACTIVE(Event ev) { switch(ev) { case MOUSE_UP: set_event(gui::Event::MOUSE_CLICK); state(State::IDLE); break; case MOUSE_MOVE: move_count++; set_event(gui::Event::MOUSE_DRAG); state(State::MOUSE_MOVING); break; case KEY_PRESS: set_event(gui::Event::KEY_PRESS); state(State::IDLE); break; default: dbc::sentinel("invalid event"); } } void Router::MOUSE_MOVING(Event ev) { switch(ev) { case MOUSE_UP: { dbc::check(move_count < $drag_tolerance, "mouse up but not in dragging state"); set_event(gui::Event::MOUSE_CLICK); state(State::IDLE); } break; case MOUSE_MOVE: move_count++; if(move_count < $drag_tolerance) { set_event(gui::Event::MOUSE_DRAG); } else { set_event(gui::Event::MOUSE_DRAG_START); state(State::MOUSE_DRAGGING); } break; case KEY_PRESS: set_event(gui::Event::KEY_PRESS); break; default: dbc::sentinel("invalid event"); } } void Router::MOUSE_DRAGGING(Event ev) { switch(ev) { case MOUSE_UP: set_event(gui::Event::MOUSE_DROP); state(State::IDLE); break; case MOUSE_MOVE: move_count++; set_event(gui::Event::MOUSE_DRAG); break; case KEY_PRESS: set_event(gui::Event::KEY_PRESS); break; default: dbc::sentinel("invalid events"); } } } }