WIP: some refactoring of event handling w/ celticminstrel

This commit is contained in:
Charles Dang 2016-07-14 14:48:09 +11:00
parent 7e04c7f8e9
commit 61ccf2fc16
2 changed files with 91 additions and 94 deletions

View file

@ -46,17 +46,6 @@ void context::add_handler(sdl_handler* ptr)
handlers.push_back(ptr); handlers.push_back(ptr);
} }
void context::delete_handler_index(size_t handler)
{
if(focused_handler == static_cast<int>(handler)) {
focused_handler = -1;
} else if(focused_handler > static_cast<int>(handler)) {
--focused_handler;
}
handlers.erase(handlers.begin()+handler);
}
bool context::remove_handler(sdl_handler* ptr) bool context::remove_handler(sdl_handler* ptr)
{ {
if(handlers.empty()) { if(handlers.empty()) {
@ -66,17 +55,26 @@ bool context::remove_handler(sdl_handler* ptr)
static int depth = 0; static int depth = 0;
++depth; ++depth;
//the handler is most likely on the back of the events array, // The handler is most likely on the back of the events list,
//so look there first, otherwise do a complete search. // so look there first, otherwise do a complete search.
if(handlers.back() == ptr) { if(handlers.back() == ptr) {
delete_handler_index(handlers.size()-1); if(*focused_handler == ptr) {
--focused_handler;
}
handlers.pop_back();
} else { } else {
const std::vector<sdl_handler*>::iterator i = std::find(handlers.begin(),handlers.end(),ptr); const handler_list::iterator i = std::find(handlers.begin(), handlers.end(), ptr);
if(i != handlers.end()) {
delete_handler_index(i - handlers.begin()); if(i == handlers.end()) {
} else {
return false; return false;
} }
if(i == focused_handler) {
focused_handler != handlers.begin() ? --focused_handler : ++focused_handler;
}
handlers.erase(i);
} }
--depth; --depth;
@ -84,34 +82,33 @@ bool context::remove_handler(sdl_handler* ptr)
if(depth == 0) { if(depth == 0) {
cycle_focus(); cycle_focus();
} else { } else {
focused_handler = -1; focused_handler = handlers.end();
} }
return true; return true;
} }
int context::cycle_focus() void context::cycle_focus()
{ {
int index = focused_handler+1; handler_list::const_iterator temp_focused_handler = focused_handler;
for(size_t i = 0; i != handlers.size(); ++i) {
if(size_t(index) == handlers.size()) { for(++temp_focused_handler; temp_focused_handler != focused_handler; ++temp_focused_handler) {
index = 0; if(temp_focused_handler == handlers.end()) {
temp_focused_handler = handlers.begin();
} }
if(handlers[size_t(index)]->requires_event_focus()) { if((**temp_focused_handler).requires_event_focus()) {
focused_handler = index; focused_handler = temp_focused_handler;
break; break;
} }
} }
return focused_handler;
} }
void context::set_focus(const sdl_handler* ptr) void context::set_focus(const sdl_handler* ptr)
{ {
const std::vector<sdl_handler*>::const_iterator i = std::find(handlers.begin(),handlers.end(),ptr); const handler_list::const_iterator i = std::find(handlers.begin(),handlers.end(),ptr);
if(i != handlers.end() && (**i).requires_event_focus()) { if(i != handlers.end() && (**i).requires_event_focus()) {
focused_handler = int(i - handlers.begin()); focused_handler = i;
} }
} }
@ -199,14 +196,14 @@ void sdl_handler::join_same(sdl_handler* parent)
} }
for(std::deque<context>::reverse_iterator i = event_contexts.rbegin(); i != event_contexts.rend(); ++i) { for(std::deque<context>::reverse_iterator i = event_contexts.rbegin(); i != event_contexts.rend(); ++i) {
std::vector<sdl_handler *> &handlers = (*i).handlers; handler_list& handlers = (*i).handlers;
if (std::find(handlers.begin(), handlers.end(), parent) != handlers.end()) { if (std::find(handlers.begin(), handlers.end(), parent) != handlers.end()) {
join(*i); join(*i);
return; return;
} }
} }
join(global_context);
join(global_context);
} }
void sdl_handler::leave() void sdl_handler::leave()
@ -276,32 +273,32 @@ bool has_focus(const sdl_handler* hand, const SDL_Event* event)
return true; return true;
} }
const int foc_i = event_contexts.back().focused_handler; const handler_list::const_iterator foc = event_contexts.back().focused_handler;
auto& handlers = event_contexts.back().handlers;
//if no-one has focus at the moment, this handler obviously wants // If no-one has focus at the moment, this handler obviously wants
//focus, so give it to it. // focus, so give it to it.
if(foc_i == -1) { if(foc == handlers.end()) {
focus_handler(hand); focus_handler(hand);
return true; return true;
} }
sdl_handler *const foc_hand = event_contexts.back().handlers[foc_i]; sdl_handler* const foc_hand = *foc;
if(foc_hand == hand){ if(foc_hand == hand){
return true; return true;
} else if(!foc_hand->requires_event_focus(event)) { } else if(!foc_hand->requires_event_focus(event)) {
//if the currently focused handler doesn't need focus for this event // If the currently focused handler doesn't need focus for this event
//allow the most recent interested handler to take care of it // allow the most recent interested handler to take care of it
int back_i = event_contexts.back().handlers.size() - 1; for(auto i = handlers.rbegin(); i != handlers.rend(); ++i) {
for(int i=back_i; i>=0; --i) { sdl_handler* const thief_hand = *i;
sdl_handler *const thief_hand = event_contexts.back().handlers[i];
if(i != foc_i && thief_hand->requires_event_focus(event)) { if(thief_hand != foc_hand && thief_hand->requires_event_focus(event)) {
//steal focus // Steal focus
focus_handler(thief_hand); focus_handler(thief_hand);
if(foc_i < back_i) {
//position the previously focused handler to allow stealing back // Position the previously focused handler to allow stealing back
event_contexts.back().delete_handler_index(foc_i); handlers.splice(handlers.end(), handlers, foc);
event_contexts.back().add_handler(foc_hand);
}
return thief_hand == hand; return thief_hand == hand;
} }
} }
@ -424,14 +421,14 @@ void pump()
//make sure this runs in it's own scope. //make sure this runs in it's own scope.
{ {
for( std::deque<context>::iterator i = event_contexts.begin() ; i != event_contexts.end(); ++i) { for( std::deque<context>::iterator i = event_contexts.begin() ; i != event_contexts.end(); ++i) {
const std::vector<sdl_handler*>& event_handlers = (*i).handlers; const handler_list& event_handlers = (*i).handlers;
for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < event_handlers.size(); ++i1) { for(auto handler : event_handlers) {
event_handlers[i1]->handle_window_event(event); handler->handle_window_event(event);
} }
} }
const std::vector<sdl_handler*>& event_handlers = global_context.handlers; const handler_list& event_handlers = global_context.handlers;
for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < event_handlers.size(); ++i1) { for(auto handler : event_handlers) {
event_handlers[i1]->handle_window_event(event); handler->handle_window_event(event);
} }
} }
@ -473,8 +470,8 @@ void pump()
{ {
/* iterate backwards as the most recent things will be at the top */ /* iterate backwards as the most recent things will be at the top */
for( std::deque<context>::iterator i = event_contexts.begin() ; i != event_contexts.end(); ++i) { for( std::deque<context>::iterator i = event_contexts.begin() ; i != event_contexts.end(); ++i) {
const std::vector<sdl_handler*>& event_handlers = (*i).handlers; const handler_list& event_handlers = (*i).handlers;
for( std::vector<sdl_handler*>::const_iterator i1 = event_handlers.begin(); i1 != event_handlers.end(); ++i1) { for( handler_list::const_iterator i1 = event_handlers.begin(); i1 != event_handlers.end(); ++i1) {
(*i1)->handle_event(event); (*i1)->handle_event(event);
} }
} }
@ -512,19 +509,19 @@ void pump()
} }
} }
const std::vector<sdl_handler*>& event_handlers = global_context.handlers; const handler_list& event_handlers = global_context.handlers;
for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < event_handlers.size(); ++i1) { for(auto handler : event_handlers) {
event_handlers[i1]->handle_event(event); handler->handle_event(event);
} }
if(event_contexts.empty() == false) { if(event_contexts.empty() == false) {
const std::vector<sdl_handler*>& event_handlers = event_contexts.back().handlers; const handler_list& event_handlers = event_contexts.back().handlers;
//events may cause more event handlers to be added and/or removed, //events may cause more event handlers to be added and/or removed,
//so we must use indexes instead of iterators here. //so we must use indexes instead of iterators here.
for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < event_handlers.size(); ++i1) { for(auto handler : event_handlers) {
event_handlers[i1]->handle_event(event); handler->handle_event(event);
} }
} }
@ -540,12 +537,12 @@ void raise_process_event()
{ {
if(event_contexts.empty() == false) { if(event_contexts.empty() == false) {
const std::vector<sdl_handler*>& event_handlers = event_contexts.back().handlers; const handler_list& event_handlers = event_contexts.back().handlers;
//events may cause more event handlers to be added and/or removed, //events may cause more event handlers to be added and/or removed,
//so we must use indexes instead of iterators here. //so we must use indexes instead of iterators here.
for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < event_handlers.size(); ++i1) { for(auto handler : event_handlers) {
event_handlers[i1]->process_event(); handler->process_event();
} }
} }
} }
@ -558,7 +555,7 @@ void raise_resize_event()
event.window.windowID = 0; // We don't check this anyway... I think... event.window.windowID = 0; // We don't check this anyway... I think...
event.window.data1 = CVideo::get_singleton().getx(); event.window.data1 = CVideo::get_singleton().getx();
event.window.data2 = CVideo::get_singleton().gety(); event.window.data2 = CVideo::get_singleton().gety();
SDL_PushEvent(&event); SDL_PushEvent(&event);
} }
@ -566,12 +563,12 @@ void raise_draw_event()
{ {
if(event_contexts.empty() == false) { if(event_contexts.empty() == false) {
const std::vector<sdl_handler*>& event_handlers = event_contexts.back().handlers; const handler_list& event_handlers = event_contexts.back().handlers;
//events may cause more event handlers to be added and/or removed, //events may cause more event handlers to be added and/or removed,
//so we must use indexes instead of iterators here. //so we must use indexes instead of iterators here.
for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < event_handlers.size(); ++i1) { for(auto handler : event_handlers) {
event_handlers[i1]->draw(); handler->draw();
} }
} }
} }
@ -579,9 +576,9 @@ void raise_draw_event()
void raise_draw_all_event() void raise_draw_all_event()
{ {
for( std::deque<context>::iterator i = event_contexts.begin() ; i != event_contexts.end(); ++i) { for( std::deque<context>::iterator i = event_contexts.begin() ; i != event_contexts.end(); ++i) {
const std::vector<sdl_handler*>& event_handlers = (*i).handlers; const handler_list& event_handlers = (*i).handlers;
for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < event_handlers.size(); ++i1) { for(auto handler : event_handlers) {
event_handlers[i1]->draw(); handler->draw();
} }
} }
} }
@ -590,12 +587,12 @@ void raise_volatile_draw_event()
{ {
if(event_contexts.empty() == false) { if(event_contexts.empty() == false) {
const std::vector<sdl_handler*>& event_handlers = event_contexts.back().handlers; const handler_list& event_handlers = event_contexts.back().handlers;
//events may cause more event handlers to be added and/or removed, //events may cause more event handlers to be added and/or removed,
//so we must use indexes instead of iterators here. //so we must use indexes instead of iterators here.
for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < event_handlers.size(); ++i1) { for(auto handler : event_handlers) {
event_handlers[i1]->volatile_draw(); handler->volatile_draw();
} }
} }
} }
@ -603,9 +600,9 @@ void raise_volatile_draw_event()
void raise_volatile_draw_all_event() void raise_volatile_draw_all_event()
{ {
for( std::deque<context>::iterator i = event_contexts.begin() ; i != event_contexts.end(); ++i) { for( std::deque<context>::iterator i = event_contexts.begin() ; i != event_contexts.end(); ++i) {
const std::vector<sdl_handler*>& event_handlers = (*i).handlers; const handler_list& event_handlers = (*i).handlers;
for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < event_handlers.size(); ++i1) { for(auto handler : event_handlers) {
event_handlers[i1]->volatile_draw(); handler->volatile_draw();
} }
} }
} }
@ -614,12 +611,12 @@ void raise_volatile_undraw_event()
{ {
if(event_contexts.empty() == false) { if(event_contexts.empty() == false) {
const std::vector<sdl_handler*>& event_handlers = event_contexts.back().handlers; const handler_list& event_handlers = event_contexts.back().handlers;
//events may cause more event handlers to be added and/or removed, //events may cause more event handlers to be added and/or removed,
//so we must use indexes instead of iterators here. //so we must use indexes instead of iterators here.
for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < event_handlers.size(); ++i1) { for(auto handler : event_handlers) {
event_handlers[i1]->volatile_undraw(); handler->volatile_undraw();
} }
} }
} }
@ -628,11 +625,11 @@ void raise_help_string_event(int mousex, int mousey)
{ {
if(event_contexts.empty() == false) { if(event_contexts.empty() == false) {
const std::vector<sdl_handler*>& event_handlers = event_contexts.back().handlers; const handler_list& event_handlers = event_contexts.back().handlers;
for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < event_handlers.size(); ++i1) { for(auto handler : event_handlers) {
event_handlers[i1]->process_help_string(mousex,mousey); handler->process_help_string(mousex,mousey);
event_handlers[i1]->process_tooltip_string(mousex,mousey); handler->process_tooltip_string(mousex,mousey);
} }
} }
} }

View file

@ -18,6 +18,7 @@
#include <SDL_events.h> #include <SDL_events.h>
#include <SDL_version.h> #include <SDL_version.h>
#include <vector> #include <vector>
#include <list>
//our user-defined double-click event type //our user-defined double-click event type
#define DOUBLE_CLICK_EVENT SDL_USEREVENT #define DOUBLE_CLICK_EVENT SDL_USEREVENT
@ -33,23 +34,23 @@ namespace events
class sdl_handler; class sdl_handler;
typedef std::list<sdl_handler*> handler_list;
struct context struct context
{ {
context() : context() :
handlers(), handlers(),
focused_handler(-1) focused_handler()
{ {
} }
void add_handler(sdl_handler* ptr); void add_handler(sdl_handler* ptr);
bool remove_handler(sdl_handler* ptr); bool remove_handler(sdl_handler* ptr);
int cycle_focus(); void cycle_focus();
void set_focus(const sdl_handler* ptr); void set_focus(const sdl_handler* ptr);
std::vector<sdl_handler*> handlers; handler_list handlers;
int focused_handler; handler_list::const_iterator focused_handler;
void delete_handler_index(size_t handler);
}; };
//any classes that derive from this class will automatically //any classes that derive from this class will automatically
@ -97,7 +98,6 @@ private:
}; };
void focus_handler(const sdl_handler* ptr); void focus_handler(const sdl_handler* ptr);
void cycle_focus();
bool has_focus(const sdl_handler* ptr, const SDL_Event* event); bool has_focus(const sdl_handler* ptr, const SDL_Event* event);