event_handler.cpp

Go to the documentation of this file.
00001 /* $Id: event_handler.cpp 26681 2008-05-18 06:05:59Z mordante $ */
00002 /*
00003    Copyright (C) 2007 - 2008 by Mark de Wever <koraq@xs4all.nl>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License version 2
00008    or at your option any later version.
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY.
00011 
00012    See the COPYING file for more details.
00013 */
00014 
00015 //! @file event_handler.cpp
00016 //! Implementation of event_handler.hpp.
00017 //!
00018 //! More documentation at the end of the file.
00019 
00020 #include "gui/widgets/event_handler.hpp"
00021 
00022 #include "clipboard.hpp"
00023 #include "config.hpp"
00024 #include "gui/widgets/widget.hpp"
00025 #include "gui/widgets/window.hpp"
00026 #include "log.hpp"
00027 #include "serialization/parser.hpp"
00028 #include "tstring.hpp"
00029 #include "variable.hpp"
00030 
00031 #define DBG_G_E LOG_STREAM_INDENT(debug, gui_event)
00032 #define LOG_G_E LOG_STREAM_INDENT(info, gui_event)
00033 #define WRN_G_E LOG_STREAM_INDENT(warn, gui_event)
00034 #define ERR_G_E LOG_STREAM_INDENT(err, gui_event)
00035 
00036 namespace gui2{
00037 
00038 static Uint32 hover_callback(Uint32 /*interval*/, void *param)
00039 {
00040     DBG_G_E << "Pushing hover event in queue.\n";
00041 
00042     SDL_Event event;
00043     SDL_UserEvent data;
00044 
00045     data.type = HOVER_EVENT;
00046     data.code = 0;
00047     data.data1 = param;
00048     data.data2 = 0;
00049 
00050     event.type = HOVER_EVENT;
00051     event.user = data;
00052     
00053     SDL_PushEvent(&event);
00054     return 0;
00055 }
00056 
00057 static Uint32 popup_callback(Uint32 /*interval*/, void*)
00058 {
00059     DBG_G_E << "Pushing popup removal event in queue.\n";
00060 
00061     SDL_Event event;
00062     SDL_UserEvent data;
00063 
00064     data.type = HOVER_REMOVE_POPUP_EVENT;
00065     data.code = 0;
00066     data.data1 = 0;
00067     data.data2 = 0;
00068 
00069     event.type = HOVER_REMOVE_POPUP_EVENT;
00070     event.user = data;
00071     
00072     SDL_PushEvent(&event);
00073     return 0;
00074 }
00075 
00076 //! At construction we should get the state and from that moment on we keep
00077 //! track of the changes ourselves, not yet sure what happens when an input
00078 //! blocker is used.
00079 tevent_handler::tevent_handler() :
00080     // fixme get state at construction
00081     events::handler(false), // don't join we haven't created a context yet
00082     event_context_(),
00083     mouse_x_(-1),
00084     mouse_y_(-1),
00085     left_("left",
00086         &tevent_executor::mouse_left_button_down,
00087         &tevent_executor::mouse_left_button_up,
00088         &tevent_executor::mouse_left_button_click,
00089         &tevent_executor::mouse_left_button_double_click,
00090         &tevent_executor::wants_mouse_left_double_click),
00091     middle_("middle",
00092         &tevent_executor::mouse_middle_button_down,
00093         &tevent_executor::mouse_middle_button_up,
00094         &tevent_executor::mouse_middle_button_click,
00095         &tevent_executor::mouse_middle_button_double_click,
00096         &tevent_executor::wants_mouse_middle_double_click),
00097     right_("right",
00098         &tevent_executor::mouse_right_button_down,
00099         &tevent_executor::mouse_right_button_up,
00100         &tevent_executor::mouse_right_button_click,
00101         &tevent_executor::mouse_right_button_double_click,
00102         &tevent_executor::wants_mouse_right_double_click),
00103     hover_pending_(false),
00104     hover_id_(0),
00105     hover_box_(),
00106     had_hover_(false),
00107     tooltip_(0),
00108     help_popup_(0),
00109     mouse_focus_(0),
00110     mouse_captured_(false),
00111     keyboard_focus_(0)
00112 {
00113     if(SDL_WasInit(SDL_INIT_TIMER) == 0) {
00114         if(SDL_InitSubSystem(SDL_INIT_TIMER) == -1) {
00115             assert(false);
00116         }
00117     }
00118 
00119     // The event context is created now we join it.
00120     join();
00121 }
00122 
00123 void tevent_handler::handle_event(const SDL_Event& event)
00124 {
00125 
00126     twidget* mouse_over = 0; 
00127     switch(event.type) {
00128         case SDL_MOUSEMOTION:
00129 
00130             mouse_x_ = event.motion.x;
00131             mouse_y_ = event.motion.y;
00132             mouse_over =
00133                 find_widget(get_window().client_position(tpoint(mouse_x_, mouse_y_)), true);
00134 
00135             mouse_move(event, mouse_over);
00136 
00137             break;
00138 
00139         case SDL_MOUSEBUTTONDOWN:
00140 
00141             mouse_x_ = event.button.x;
00142             mouse_y_ = event.button.y;
00143             mouse_over =
00144                 find_widget(get_window().client_position(tpoint(mouse_x_, mouse_y_)), true);
00145 
00146             switch(event.button.button) {
00147                 case SDL_BUTTON_LEFT : 
00148                     DBG_G_E << "Event: Left button down.\n";
00149                     mouse_button_down(event, mouse_over, left_);
00150                     break;
00151                 case SDL_BUTTON_MIDDLE :
00152                     DBG_G_E << "Event: Middle button down.\n";
00153                     mouse_button_down(event, mouse_over, middle_);
00154                     break;
00155                 case SDL_BUTTON_RIGHT :
00156                     DBG_G_E << "Event: Right button down.\n";
00157                     mouse_button_down(event, mouse_over, right_);
00158                     break;
00159                 default:
00160                     // cast to avoid being printed as char.
00161                     WRN_G_E << "Unhandled 'mouse button down' event for button " 
00162                         << static_cast<Uint32>(event.button.button) << ".\n";
00163                     assert(false);
00164                     break;
00165             }
00166             break;
00167 
00168         case SDL_MOUSEBUTTONUP:
00169 
00170             mouse_x_ = event.button.x;
00171             mouse_y_ = event.button.y;
00172             mouse_over =
00173                 find_widget(get_window().client_position(tpoint(mouse_x_, mouse_y_)), true);
00174 
00175             switch(event.button.button) {
00176 
00177                 case SDL_BUTTON_LEFT : 
00178                     DBG_G_E << "Event: Left button up.\n";
00179                     mouse_button_up(event, mouse_over, left_);
00180                     break;
00181                 case SDL_BUTTON_MIDDLE :
00182                     DBG_G_E << "Event: Middle button up.\n";
00183                     mouse_button_up(event, mouse_over, middle_);
00184                     break;
00185                 case SDL_BUTTON_RIGHT :
00186                     DBG_G_E << "Event: Right button up.\n";
00187                     mouse_button_up(event, mouse_over, right_);
00188                     break;
00189                 default:
00190                     // cast to avoid being printed as char.
00191                     WRN_G_E << "Unhandled 'mouse button up' event for button " 
00192                         << static_cast<Uint32>(event.button.button) << ".\n";
00193                     assert(false);
00194                     break;
00195             }
00196             break;
00197 
00198         case HOVER_EVENT:
00199             mouse_hover(event, 0);
00200             break;
00201 
00202         case HOVER_REMOVE_POPUP_EVENT:
00203             remove_tooltip();
00204             remove_help_popup();
00205             break;
00206 
00207         case SDL_KEYDOWN:
00208             key_down(event);
00209             break;
00210 
00211         case SDL_VIDEORESIZE:
00212             get_window().window_resize(*this, event.resize.w, event.resize.h);
00213             break;
00214 
00215 #if defined(_X11) && !defined(__APPLE__)
00216             case SDL_SYSWMEVENT: {
00217                 DBG_G_E << "Event: System event.\n";
00218                 //clipboard support for X11
00219                 handle_system_event(event);
00220                 break;
00221             }
00222 #endif
00223 
00224         default:
00225         
00226             // cast to avoid being printed as char.
00227             WRN_G_E << "Unhandled event " << static_cast<Uint32>(event.type) << ".\n";
00228             break;
00229         }
00230 }
00231 
00232 void tevent_handler::mouse_capture(const bool capture)
00233 {
00234     assert(mouse_focus_);
00235     mouse_captured_ = capture;
00236 }
00237 
00238 tpoint tevent_handler::get_mouse() const
00239 { 
00240     return get_window().client_position(tpoint(mouse_x_, mouse_y_)); 
00241 }
00242 
00243 void tevent_handler::show_tooltip(const t_string& tooltip, const unsigned timeout)
00244 {
00245     DBG_G_E << "Event: show tooltip.\n";
00246 
00247     assert(!tooltip_);
00248 
00249     if(help_popup_) {
00250         remove_help_popup();
00251     }
00252 
00253     tooltip_ = mouse_focus_;
00254 
00255     do_show_tooltip(get_window().client_position(tpoint(mouse_x_, mouse_y_)), tooltip);
00256 
00257     if(timeout) {
00258         SDL_AddTimer(timeout, popup_callback, 0);
00259     }
00260 }
00261 
00262 void tevent_handler::remove_tooltip()
00263 {
00264     if(!tooltip_) {
00265         return;
00266     }
00267 
00268     tooltip_ = 0;
00269 
00270     do_remove_tooltip();
00271 }
00272 
00273 void tevent_handler::show_help_popup(const t_string& help_popup, const unsigned timeout)
00274 {
00275     DBG_G_E << "Event: show help popup.\n";
00276 
00277     if(help_popup_) {
00278         DBG_G_E << "Help is already there, bailing out.\n";
00279         return;
00280     }
00281 
00282     if(tooltip_) {
00283         remove_tooltip();
00284     }
00285 
00286     // Kill hover events FIXME not documented.
00287     had_hover_ = true;
00288     hover_pending_ = false;
00289 
00290     help_popup_ = mouse_focus_;
00291 
00292     do_show_help_popup(get_window().client_position(tpoint(mouse_x_, mouse_y_)), help_popup);
00293 
00294     if(timeout) {
00295         SDL_AddTimer(timeout, popup_callback, 0);
00296     }
00297 }
00298 
00299 void tevent_handler::remove_help_popup()
00300 {
00301     if(!help_popup_) {
00302         return;
00303     }
00304 
00305     help_popup_ = 0;
00306 
00307     do_remove_help_popup();
00308 }
00309 
00310 void tevent_handler::mouse_enter(const SDL_Event& /*event*/, twidget* mouse_over)
00311 {
00312     DBG_G_E << "Event: remove tooltip.\n";
00313 
00314     assert(mouse_over);
00315 
00316     mouse_focus_ = mouse_over;
00317     mouse_over->mouse_enter(*this);
00318 
00319     set_hover();
00320 }
00321 
00322 void tevent_handler::mouse_hover(const SDL_Event& event, twidget* /*mouse_over*/)
00323 {
00324     const unsigned hover_id = *static_cast<unsigned*>(event.user.data1);
00325     delete static_cast<unsigned*>(event.user.data1);
00326 
00327     if(!hover_pending_ || hover_id != hover_id_) {
00328         return;
00329     }
00330     
00331     assert(mouse_focus_);
00332 
00333     mouse_focus_->mouse_hover(*this);
00334 
00335     had_hover_ = true;
00336 }
00337 
00338 void tevent_handler::mouse_move(const SDL_Event& event, twidget* mouse_over)
00339 {
00340     // Note we use the fact that a NULL pointer evaluates to false
00341     // and non NULL pointer to true;
00342     if(mouse_captured_) {
00343         mouse_focus_->mouse_move(*this);
00344         set_hover(true); 
00345     } else {
00346         if(!mouse_focus_ && mouse_over) {
00347             mouse_enter(event, mouse_over);
00348         } else if (mouse_focus_ && !mouse_over) {
00349             mouse_leave(event, mouse_over);
00350         } else if(mouse_focus_ && mouse_focus_ == mouse_over) { 
00351             mouse_over->mouse_move(*this);
00352             set_hover();
00353         } else if(mouse_focus_ && mouse_over) {
00354             // moved from one widget to the next
00355             mouse_leave(event, mouse_over);
00356             mouse_enter(event, mouse_over);
00357         } else {
00358             assert(!mouse_focus_ && !mouse_over);
00359         }
00360     }
00361 }
00362 
00363 void tevent_handler::mouse_leave(const SDL_Event& /*event*/, twidget* /*mouse_over*/)
00364 {
00365     assert(mouse_focus_);
00366 
00367     had_hover_ = false;
00368     hover_pending_ =false;
00369 
00370     remove_tooltip();
00371     remove_help_popup();
00372 
00373     mouse_focus_->mouse_leave(*this);
00374     mouse_focus_ = 0;
00375 }
00376 
00377 void tevent_handler::mouse_button_down(const SDL_Event& /*event*/, twidget* mouse_over, tmouse_button& button)
00378 {
00379     if(button.is_down) {
00380         WRN_G_E << "In 'button down' for button '" << button.name 
00381             << "' but the mouse button is already down, we missed an event.\n";
00382         return;
00383     }
00384     button.is_down = true;
00385     hover_pending_ = false;
00386 
00387     if(mouse_captured_) {
00388         button.focus = mouse_focus_;
00389         (mouse_focus_->*button.down)(*this);
00390     } else {
00391         if(!mouse_over) {
00392             return;
00393         }
00394 
00395         if(mouse_over != mouse_focus_) {
00396             WRN_G_E << "Mouse down event on non focussed widget "
00397                 << "and mouse not captured, we missed events.\n";
00398         }
00399 
00400         button.focus = mouse_over;
00401         (mouse_over->*button.down)(*this);
00402     }
00403 }
00404 
00405 void tevent_handler::mouse_button_up(const SDL_Event& event, twidget* mouse_over, tmouse_button& button)
00406 {
00407     if(!button.is_down) {
00408         WRN_G_E << "In 'button up' for button '" << button.name 
00409             << "' but the mouse button is already up, we missed an event.\n";
00410         return;
00411     }
00412 
00413     button.is_down = false;
00414     if(button.focus) {
00415         (button.focus->*button.up)(*this);
00416     }
00417 
00418     if(mouse_captured_) {
00419         if (!left_.is_down && !middle_.is_down && !right_.is_down) {
00420             mouse_captured_ = false;
00421         }
00422 
00423         if(mouse_focus_ != mouse_over) {
00424             mouse_leave(event, mouse_over);
00425 
00426             if(mouse_over) {
00427                 mouse_enter(event, mouse_over);
00428             }
00429         } else {
00430             mouse_click(mouse_focus_, button);
00431         }
00432     } else if(button.focus && button.focus == mouse_over) {
00433         mouse_click(button.focus, button);
00434     }
00435 
00436     button.focus = 0;
00437     set_hover();
00438 }
00439 
00440 void tevent_handler::mouse_click(twidget* widget, tmouse_button& button)
00441 {
00442     if((widget->*button.wants_double_click)()) {
00443         Uint32 stamp = SDL_GetTicks();
00444         if(button.last_click_stamp + settings::double_click_time >= stamp) {
00445 
00446             (widget->*button.double_click)(*this);
00447             button.last_click_stamp = 0;
00448 
00449         } else {
00450 
00451             (widget->*button.click)(*this);
00452             button.last_click_stamp = stamp;
00453         }
00454 
00455     } else {
00456     
00457         (widget->*button.click)(*this);
00458     }
00459 }
00460 
00461 void tevent_handler::set_hover(const bool test_on_widget)
00462 {
00463     // Only one hover event.
00464     if(had_hover_) {
00465         return;
00466     }
00467 
00468     // Don't want a hover.
00469     if(!mouse_focus_ || !mouse_focus_->wants_mouse_hover()) {
00470         return;
00471     }
00472 
00473     // Have an hover and still in the bounding rect.
00474     if(hover_pending_ && point_in_rect(mouse_x_, mouse_y_, hover_box_)) {
00475         return;
00476     }
00477 
00478     // Mouse down, no hovering
00479     if(left_.is_down || middle_.is_down || right_.is_down) {
00480         return;
00481     } 
00482 
00483     if(test_on_widget) {
00484         // FIXME implement
00485     }
00486 
00487     static unsigned hover_id = 0;
00488 
00489     hover_pending_ = true;
00490     // FIXME hover dimentions should be from the settings
00491     // also should check the entire box is on the widget???
00492     hover_box_ = ::create_rect(mouse_x_ - 5, mouse_y_ - 5, 10, 10);
00493 
00494     unsigned *hover = new unsigned;
00495     *hover = hover_id;
00496     hover_id_ = hover_id++;
00497             
00498     SDL_AddTimer(settings::popup_show_delay, hover_callback, hover);
00499 }
00500 
00501 void tevent_handler::key_down(const SDL_Event& event)
00502 {
00503     // We capture the F! for the help, but only if the mouse is on an object.
00504     if(mouse_focus_/* && !mouse_captured_ 
00505             && event.key.keysym.mod == 0 */ && event.key.keysym.sym == SDLK_F1) {
00506 
00507         mouse_focus_->help_key(*this);
00508         return;
00509     }
00510 
00511     bool handled = false;
00512     if(keyboard_focus_) {
00513         keyboard_focus_->key_press(*this, handled, event.key.keysym.sym, event.key.keysym.mod, event.key.keysym.unicode);
00514     }
00515 
00516     if(!handled) {
00517         get_window().key_press(*this, handled, event.key.keysym.sym, event.key.keysym.mod, event.key.keysym.unicode);
00518     }
00519 }
00520 
00521 /**
00522  * The event handling system.
00523  *
00524  * In this system there are two kind of focus
00525  * - mouse focus, the widget that will get the mouse events. There are two modes
00526  *   captured and uncaptured. Basically when a mouse button is pressed that 
00527  *   widget will capture the mouse and all following mouse events are send to
00528  *   that widget.
00529  *   
00530  * - keyboard focus, the widget that will get the keyboard events.
00531  *
00532  * Keyboard events are first processed by the top level window and if not 
00533  * handled it will be send to the item with the keyboard focus (if any).
00534  *
00535  * * Mouse events *
00536  *
00537  * Note by button the X can be:
00538  * - left button
00539  * - middle button
00540  * - right button
00541  *
00542  * For the mouse the following events are defined:
00543  * - mouse enter, the mouse moves on a widget it wasn't on before.
00544  * - mouse move, the mouse moves. This can either be that the mouse moves over
00545  *   the widget under the mouse or it's send to the widget that captured the 
00546  *   focus.
00547  * - mouse leave, the mouse leaves the area that bounds the mouse, in captured
00548  *   mode the release is delayed until the focus is released.
00549  * - hover, a widget needs to tell it wants this event. The event will be send
00550  *   when the user doesn't move (or just a little) for a while. (Times are 
00551  *   themable.)
00552  *
00553  * - mouse_button_X_down, the mouse button is being pressed on this widget.
00554  * - mouse_button_X_up, the mouse button has been moved up again.  
00555  * - mouse_button_X_click, a single click on a widget.
00556  * - mouse_button_X_double_click, a double click on the widget. The widget 
00557  *   needs to subscribe to this event and when doing so a single click will be
00558  *   delayed a bit. (The double click time is themable.)
00559  *
00560  * * Mouse event flow chart *
00561  *
00562  *       --------------------
00563  *      ( mouse somewhere    ) 
00564  *       --------------------
00565  *                 |
00566  *  -------------->|
00567  * |               |
00568  * |               V 
00569  * |     --------------------        -------------------- 
00570  * |    | moves upon widget  | -->  / fire mouse enter  /
00571  * |     --------------------      ---------------------
00572  * |                                        |
00573  * |                                        V
00574  * |                                        /\  Want hover event?
00575  * |                                    no /  \ yes     --------------------
00576  * |               ----------------------- \  / -----> / place hover event /  
00577  * |              |                         \/         --------------------
00578  * |              |                                            |
00579  * |              |<--------------------------------------------
00580  * |              |
00581  * |              V
00582  * |     --------------------        -------------------- 
00583  * |    | moves on widget    | -->  / fire mouse move   /
00584  * |     --------------------      ---------------------
00585  * |                                        |
00586  * |                                        V
00587  * |                                        /\  Want hover event?
00588  * |                                    no /  \ 
00589  * |               ----------------------- \  /
00590  * |              |                         \/ 
00591  * |              |                         | yew
00592  * |              |                         V
00593  * |              |                         /\  Hover location outside threshold? 
00594  * |              |                     no /  \ yes     --------------------
00595  * |              |<---------------------- \  / -----> / place hover event /  
00596  * |              |                         \/         --------------------
00597  * |              |                                            |
00598  * |              |<--------------------------------------------
00599  * |              |                                             
00600  * |              V                         
00601  * |     --------------------        -------------------- 
00602  * |    | receive hover event| -->  / set hover shown   /  
00603  * |     --------------------      ---------------------
00604  * |                                        |  
00605  * |                                        V
00606  * |                                 -------------------- 
00607  * |                                / fire hover event  /
00608  * |                               ---------------------
00609  * |                                        |
00610  * |               ------------------------- 
00611  * |              |
00612  * |              |--------------------------------------------------
00613  * |              V                                                  |
00614  * |     --------------------        --------------------            |
00615  * |    | moves off widget   | -->  / fire mouse leave  /            |
00616  * |     --------------------      ---------------------             |
00617  * |                                         |                       |
00618  * |                                         V                       |
00619  * |                                 ---------------------           |
00620  * |                                / cancel pending     /           |
00621  * |                               /  hover events      /            |
00622  * |                               ---------------------             |
00623  * |                                         |                       |
00624  * |                                         V                       |
00625  * |                                 --------------------            |
00626  * |                                / reset hover shown /            |
00627  * |                               ---------------------             |
00628  * |                                         |                       |
00629  * |<----------------------------------------                        |
00630  * |                                                                 |
00631  * |                                                                 |
00632  * |                                                                 |
00633  * |                                                                 |
00634  * |                                                                 |
00635  * |               --------------------------------------------------
00636  * |              |
00637  * |              V                         
00638  * |     --------------------        -------------------- 
00639  * |    | mouse down         | -->  / cancel pending    /
00640  * |     --------------------      /  hover events     / 
00641  * |                               --------------------
00642  * |                                        |  
00643  * |                                        V
00644  * |                                 -------------------- 
00645  * |                                / fire 'mouse down' /
00646  * |                               ---------------------
00647  * |                                        |
00648  * |               -------------------------
00649  * |              |              
00650  * |              V
00651  * |     --------------------        -------------------- 
00652  * |    | moves on widget    | -->  / fire mouse move   /
00653  * |     --------------------      ---------------------
00654  * |                                        |
00655  * |               --------------------------------------------------
00656  * |              |                                                  |
00657  * |              V                                                  |
00658  * |     --------------------        --------------------            |
00659  * |    | moves off widget   | -->  / fire mouse move   /            |
00660  * |     --------------------      ---------------------             |
00661  * |                                        |                        |
00662  * |               -------------------------                         |
00663  * |              |                                                  |
00664  * |              V                                                  |
00665  * |     --------------------        --------------------            |
00666  * |    | moves up           | -->  / release capture   /            |
00667  * |     --------------------      ---------------------             |
00668  * |                                        |                        |
00669  * |                                        V                        |
00670  * |                                 --------------------            |
00671  * |                                / fire mouse up     /            |
00672  * |                               ---------------------             |
00673  * |                                        |                        |
00674  * |                                        V                        |
00675  * |                                 --------------------            |
00676  * |                                / fire mouse leave  /            |
00677  * |                               ---------------------             |
00678  * |                                         |                       |
00679  * |<----------------------------------------                        |
00680  * |                                                                 |
00681  * |                                                                 |
00682  * |                                                                 |
00683  * |                                                                 |
00684  * |                                                                 |
00685  * |               --------------------------------------------------
00686  * |              |
00687  * |              V 
00688  * |     -------------------- 
00689  * |    | capture mouse      |
00690  * |     --------------------
00691  * |              |              
00692  * |              V
00693  * |     --------------------        -------------------- 
00694  * |    | moves up           | -->  / release capture   /
00695  * |     --------------------      ---------------------
00696  * |                                        |  
00697  * |                                        V
00698  * |                                 -------------------- 
00699  * |                                / fire mouse up     /
00700  * |                               ---------------------
00701  * |                                        |  
00702  * |                                        V
00703  * |                                        /\
00704  * |                                       /  \ Want double click? 
00705  * |                                       \  / no       -------------------- 
00706  * |                                        \/  ------> / fire click        /
00707  * |                                   yes  |          --------------------- 
00708  * |                                        |                  |   
00709  * |                                        V                   -----------------
00710  * |                                        /\                                   |
00711  * |                                       /  \ Has click pending?               |
00712  * |         -----------------------  yes  \  / no       --------------------    |
00713  * |        / remove click pending /<------ \/  ------> / set click pending /    |
00714  * |        -----------------------                    ---------------------     |
00715  * |                 |                                         |                 |
00716  * |                 V                                         V                 |
00717  * |         -----------------------                     -------------------     |
00718  * |        / fire double click    /                    / fire click       /     |
00719  * |       ------------------------                     -------------------      |
00720  * |                 |                                         |                 |
00721  * |                 V                                         V                 |
00722  *  -----------------------------------------------------------------------------
00723  * 
00724  */
00725 
00726 } // namespace gui2
00727 

Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs