00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef GUI_WIDGETS_AUXILIARY_EVENT_DISPATCHER_HPP_INCLUDED
00017 #define GUI_WIDGETS_AUXILIARY_EVENT_DISPATCHER_HPP_INCLUDED
00018
00019 #include "gui/auxiliary/event/handler.hpp"
00020 #include "hotkeys.hpp"
00021
00022 #include <boost/function.hpp>
00023 #include <boost/mpl/int.hpp>
00024 #include <boost/utility/enable_if.hpp>
00025
00026 #include <map>
00027
00028 namespace gui2 {
00029
00030 struct tpoint;
00031 class twidget;
00032
00033 namespace event {
00034
00035 struct tmessage;
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 typedef
00046 boost::function<void(
00047 tdispatcher& dispatcher
00048 , const tevent event
00049 , bool& handled
00050 , bool& halt)>
00051 tsignal_function;
00052
00053
00054
00055
00056
00057
00058 typedef
00059 boost::function<void(
00060 tdispatcher& dispatcher
00061 , const tevent event
00062 , bool& handled
00063 , bool& halt
00064 , const tpoint& coordinate)>
00065 tsignal_mouse_function;
00066
00067
00068
00069
00070
00071
00072 typedef
00073 boost::function<void(
00074 tdispatcher& dispatcher
00075 , const tevent event
00076 , bool& handled
00077 , bool& halt
00078 , const SDLKey key
00079 , const SDLMod modifier
00080 , const Uint16 unicode) >
00081 tsignal_keyboard_function;
00082
00083
00084
00085
00086
00087
00088
00089
00090 typedef
00091 boost::function<void(
00092 tdispatcher& dispatcher
00093 , const tevent event
00094 , bool& handled
00095 , bool& halt
00096 , void*)>
00097 tsignal_notification_function;
00098
00099
00100
00101
00102
00103
00104 typedef
00105 boost::function<void(
00106 tdispatcher& dispatcher
00107 , const tevent event
00108 , bool& handled
00109 , bool& halt
00110 , tmessage& message)>
00111 tsignal_message_function;
00112
00113
00114 typedef
00115 boost::function<bool(
00116 tdispatcher& dispatcher
00117 , hotkey::HOTKEY_COMMAND id)>
00118 thotkey_function;
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 class tdispatcher
00136 {
00137 friend struct tdispatcher_implementation;
00138 public:
00139 tdispatcher();
00140 virtual ~tdispatcher();
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 void connect();
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 virtual bool is_at(const tpoint& coordinate) const = 0;
00166
00167 enum tevent_type
00168 {
00169 pre = 1
00170 , child = 2
00171 , post = 4
00172 };
00173
00174 bool has_event(const tevent event, const tevent_type event_type);
00175
00176
00177 bool fire(const tevent event, twidget& target);
00178
00179
00180
00181
00182
00183
00184
00185
00186 bool fire(const tevent event, twidget& target, const tpoint& coordinate);
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 bool fire(const tevent event
00198 , twidget& target
00199 , const SDLKey key
00200 , const SDLMod modifier
00201 , const Uint16 unicode);
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 bool fire(const tevent event, twidget& target, void*);
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 bool fire(const tevent event, twidget& target, tmessage& message);
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 enum tposition
00263 {
00264 front_pre_child,
00265 back_pre_child,
00266 front_child,
00267 back_child,
00268 front_post_child,
00269 back_post_child
00270 };
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 template<tevent E>
00290 typename boost::enable_if<boost::mpl::has_key<
00291 tset_event, boost::mpl::int_<E> > >::type
00292 connect_signal(const tsignal_function& signal
00293 , const tposition position = back_child)
00294 {
00295 signal_queue_.connect_signal(E, position, signal);
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 template<tevent E>
00309 typename boost::enable_if<boost::mpl::has_key<
00310 tset_event, boost::mpl::int_<E> > >::type
00311 disconnect_signal(const tsignal_function& signal
00312 , const tposition position = back_child)
00313 {
00314 signal_queue_.disconnect_signal(E, position, signal);
00315 }
00316
00317
00318
00319
00320
00321
00322
00323
00324 template<tevent E>
00325 typename boost::enable_if<boost::mpl::has_key<
00326 tset_event_mouse, boost::mpl::int_<E> > >::type
00327 connect_signal(const tsignal_mouse_function& signal
00328 , const tposition position = back_child)
00329 {
00330 signal_mouse_queue_.connect_signal(E, position, signal);
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 template<tevent E>
00344 typename boost::enable_if<boost::mpl::has_key<
00345 tset_event_mouse, boost::mpl::int_<E> > >::type
00346 disconnect_signal(const tsignal_mouse_function& signal
00347 , const tposition position = back_child)
00348 {
00349 signal_mouse_queue_.disconnect_signal(E, position, signal);
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359 template<tevent E>
00360 typename boost::enable_if<boost::mpl::has_key<
00361 tset_event_keyboard, boost::mpl::int_<E> > >::type
00362 connect_signal(const tsignal_keyboard_function& signal
00363 , const tposition position = back_child)
00364 {
00365 signal_keyboard_queue_.connect_signal(E, position, signal);
00366 }
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378 template<tevent E>
00379 typename boost::enable_if<boost::mpl::has_key<
00380 tset_event_keyboard, boost::mpl::int_<E> > >::type
00381 disconnect_signal(const tsignal_keyboard_function& signal
00382 , const tposition position = back_child)
00383 {
00384 signal_keyboard_queue_.disconnect_signal(E, position, signal);
00385 }
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397 template<tevent E>
00398 typename boost::enable_if<boost::mpl::has_key<
00399 tset_event_notification, boost::mpl::int_<E> > >::type
00400 connect_signal(const tsignal_notification_function& signal
00401 , const tposition position = back_child)
00402 {
00403 signal_notification_queue_.connect_signal(E, position, signal);
00404 }
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421 template<tevent E>
00422 typename boost::enable_if<boost::mpl::has_key<
00423 tset_event_notification, boost::mpl::int_<E> > >::type
00424 disconnect_signal(const tsignal_notification_function& signal
00425 , const tposition position = back_child)
00426 {
00427 signal_notification_queue_.disconnect_signal(E, position, signal);
00428 }
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 template<tevent E>
00441 typename boost::enable_if<boost::mpl::has_key<
00442 tset_event_message, boost::mpl::int_<E> > >::type
00443 connect_signal(const tsignal_message_function& signal
00444 , const tposition position = back_child)
00445 {
00446 signal_message_queue_.connect_signal(E, position, signal);
00447 }
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464 template<tevent E>
00465 typename boost::enable_if<boost::mpl::has_key<
00466 tset_event_message, boost::mpl::int_<E> > >::type
00467 disconnect_signal(const tsignal_message_function& signal
00468 , const tposition position = back_child)
00469 {
00470 signal_message_queue_.disconnect_signal(E, position, signal);
00471 }
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 enum tmouse_behaviour
00491 {
00492 all
00493 , hit
00494 , none
00495 };
00496
00497
00498 void capture_mouse()
00499 {
00500 gui2::event::capture_mouse(this);
00501 }
00502
00503
00504 void release_mouse()
00505 {
00506 gui2::event::release_mouse(this);
00507 }
00508
00509
00510
00511 void set_mouse_behaviour(const tmouse_behaviour mouse_behaviour)
00512 {
00513 mouse_behaviour_ = mouse_behaviour;
00514 }
00515
00516 tmouse_behaviour get_mouse_behaviour() const
00517 {
00518 return mouse_behaviour_;
00519 }
00520
00521 void set_want_keyboard_input(const bool want_keyboard_input)
00522 {
00523 want_keyboard_input_ = want_keyboard_input;
00524 }
00525
00526 bool get_want_keyboard_input() const
00527 {
00528 return want_keyboard_input_;
00529 }
00530
00531
00532 template<class T>
00533 struct tsignal
00534 {
00535 tsignal()
00536 : pre_child()
00537 , child()
00538 , post_child()
00539 {
00540 }
00541
00542 std::vector<T> pre_child;
00543 std::vector<T> child;
00544 std::vector<T> post_child;
00545 };
00546
00547
00548 template<class T>
00549 struct tsignal_queue
00550 {
00551 tsignal_queue()
00552 : queue()
00553 {
00554 }
00555
00556 std::map<tevent, tsignal<T> > queue;
00557
00558 void connect_signal(const tevent event
00559 , const tposition position
00560 , const T& signal)
00561 {
00562 switch(position) {
00563 case front_pre_child :
00564 queue[event].pre_child.insert(
00565 queue[event].pre_child.begin(), signal);
00566 break;
00567 case back_pre_child :
00568 queue[event].pre_child.push_back(signal);
00569 break;
00570
00571 case front_child :
00572 queue[event].child.insert(
00573 queue[event].child.begin(), signal);
00574 break;
00575 case back_child :
00576 queue[event].child.push_back(signal);
00577 break;
00578
00579 case front_post_child :
00580 queue[event].post_child.insert(
00581 queue[event].post_child.begin(), signal);
00582 break;
00583 case back_post_child :
00584 queue[event].post_child.push_back(signal);
00585 break;
00586 }
00587
00588 }
00589
00590 void disconnect_signal(const tevent event
00591 , const tposition position
00592 , const T& signal)
00593 {
00594
00595
00596
00597
00598 switch(position) {
00599 case front_pre_child :
00600 case back_pre_child : {
00601 tsignal<T>& signal_queue = queue[event];
00602 for(typename std::vector<T>::iterator itor =
00603 signal_queue.child.begin()
00604 ; itor != signal_queue.child.end()
00605 ; ++itor) {
00606
00607 if(signal.target_type() == itor->target_type()) {
00608 signal_queue.child.erase(itor);
00609 return;
00610 }
00611 }
00612 }
00613 break;
00614
00615 case front_child :
00616 case back_child : {
00617 tsignal<T>& signal_queue = queue[event];
00618 for(typename std::vector<T>::iterator itor =
00619 signal_queue.child.begin()
00620 ; itor != signal_queue.child.end()
00621 ; ++itor) {
00622
00623 if(signal.target_type() == itor->target_type()) {
00624 signal_queue.child.erase(itor);
00625 return;
00626 }
00627 }
00628 }
00629 break;
00630
00631 case front_post_child :
00632 case back_post_child : {
00633 tsignal<T>& signal_queue = queue[event];
00634 for(typename std::vector<T>::iterator itor =
00635 signal_queue.child.begin()
00636 ; itor != signal_queue.child.end()
00637 ; ++itor) {
00638
00639 if(signal.target_type() == itor->target_type()) {
00640 signal_queue.child.erase(itor);
00641 return;
00642 }
00643 }
00644 }
00645 break;
00646 }
00647 }
00648 };
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661 void register_hotkey(const hotkey::HOTKEY_COMMAND id
00662 , const thotkey_function& function);
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672 bool execute_hotkey(const hotkey::HOTKEY_COMMAND id);
00673
00674 private:
00675
00676
00677 tmouse_behaviour mouse_behaviour_;
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689 bool want_keyboard_input_;
00690
00691
00692 tsignal_queue<tsignal_function> signal_queue_;
00693
00694
00695 tsignal_queue<tsignal_mouse_function> signal_mouse_queue_;
00696
00697
00698 tsignal_queue<tsignal_keyboard_function> signal_keyboard_queue_;
00699
00700
00701 tsignal_queue<tsignal_notification_function> signal_notification_queue_;
00702
00703
00704 tsignal_queue<tsignal_message_function> signal_message_queue_;
00705
00706
00707 bool connected_;
00708
00709
00710 std::map<hotkey::HOTKEY_COMMAND, thotkey_function> hotkeys_;
00711 };
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726 inline void connect_signal_pre_key_press(
00727 tdispatcher& dispatcher
00728 , const tsignal_keyboard_function& signal)
00729 {
00730 dispatcher.connect_signal<SDL_KEY_DOWN>(
00731 signal
00732 , tdispatcher::front_child);
00733 }
00734
00735
00736 inline void connect_signal_mouse_left_click(
00737 tdispatcher& dispatcher
00738 , const tsignal_function& signal)
00739 {
00740 dispatcher.connect_signal<LEFT_BUTTON_CLICK>(signal);
00741 }
00742
00743
00744 inline void disconnect_signal_mouse_left_click(
00745 tdispatcher& dispatcher
00746 , const tsignal_function& signal)
00747 {
00748 dispatcher.disconnect_signal<LEFT_BUTTON_CLICK>(signal);
00749 }
00750
00751
00752 inline void connect_signal_notify_modified(
00753 tdispatcher& dispatcher
00754 , const tsignal_notification_function& signal)
00755 {
00756 dispatcher.connect_signal<event::NOTIFY_MODIFIED>(signal);
00757 }
00758
00759 }
00760
00761 }
00762
00763 #endif
00764