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

View file

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