00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef OMGUI_EVENT_H
00024 #define OMGUI_EVENT_H
00025
00026 #include <omgui/dllimpexp.h>
00027 #include <omgui/event-id.h>
00028 #include <omgui/types.h>
00029
00030 #include <map>
00031 #include <list>
00032 #include <queue>
00033
00034 namespace omgui {
00035
00036 class Event;
00037 class ConnectionBody;
00038 class ConnectionImpl;
00039
00040 const event_id EVENT_ID_ANY = 0;
00041
00045 class OMGUI_API SlotBase : public RefCounted
00046 {
00047 public:
00051 virtual ~SlotBase() { }
00052
00056 virtual bool operator() (const Event &e) = 0;
00057 };
00058
00062 template<typename E> class PointerSlot : public SlotBase
00063 {
00064 public:
00065 typedef E event_type;
00066 typedef bool(*function_type)(const event_type&);
00067
00068 PointerSlot(const function_type& f): func(f) { }
00069
00070 bool operator() (const Event &e) {
00071 return func(dynamic_cast<const event_type&>(e));
00072 }
00073
00074 private:
00075 function_type func;
00076 };
00077
00085 template<typename E, typename T> class MemberSlot : public SlotBase
00086 {
00087 public:
00088 typedef E event_type;
00089 typedef bool(T::*function_type)(const event_type &e);
00090
00091 MemberSlot(const function_type &function, T &t): func(function), instance(t) { }
00092
00093 bool operator() (const Event &e) {
00094 return (instance.*func)(dynamic_cast<const event_type&>(e));
00095 }
00096
00097 private:
00098 function_type func;
00099 T &instance;
00100 };
00101
00109 template<typename E, typename T> class ConstMemberSlot : public SlotBase
00110 {
00111 public:
00112 typedef E event_type;
00113 typedef bool(T::*function_type)(const event_type &e) const;
00114
00115 ConstMemberSlot(const function_type &function, T &t): func(function), instance(t) { }
00116
00117 bool operator() (const Event &e) {
00118 return (instance.*func)(dynamic_cast<const event_type&>(e));
00119 }
00120
00121 private:
00122 function_type func;
00123 T &instance;
00124 };
00125
00131 template<typename E, typename F> class FunctorSlot : public SlotBase
00132 {
00133 public:
00134 typedef E event_type;
00135 typedef F function_type;
00136
00137 FunctorSlot(const function_type& f): func(f) { }
00138
00139 bool operator() (const Event &e) {
00140 return func(dynamic_cast<const event_type&>(e));
00141 }
00142
00143 private:
00144 function_type func;
00145 };
00146
00152 class OMGUI_API Connection
00153 {
00154 public:
00155 Connection();
00156 ~Connection();
00157
00161 void disconnect();
00162
00166 bool connected() const;
00167
00172 void block(bool b = true);
00173
00177 void unblock() { block(false); }
00178
00182 bool blocked() const;
00183
00184 private:
00185 Connection(const Pointer<ConnectionBody> &body);
00186
00187 Pointer<ConnectionBody> body;
00188
00189 friend class Signal;
00190 };
00191
00196 class ConnectionBody : public RefCounted
00197 {
00198 public:
00199 virtual ~ConnectionBody() { }
00200
00204 virtual void disconnect() = 0;
00205
00209 virtual bool connected() const = 0;
00210
00215 virtual void block(bool) = 0;
00216
00220 virtual bool blocked() const = 0;
00221 };
00222
00229 class OMGUI_API Signal
00230 {
00231 public:
00232 typedef Pointer<SlotBase> slot_type;
00233
00234 Signal();
00235
00239 ~Signal();
00240
00245 Connection connect(const slot_type &slot);
00246
00252 bool operator() (const Event&);
00253
00257 void disconnect_all();
00258
00259 private:
00260 friend class ConnectionImpl;
00261 typedef std::list< Pointer<ConnectionImpl> > Slots;
00262 typedef std::queue<Slots::iterator> DisconnectedSlots;
00263
00269 void disconnect(const Slots::iterator &it);
00270
00271 Slots slots;
00272 DisconnectedSlots disconnected_slots;
00273 int signaling_;
00274 };
00275
00281 class ConnectionImpl : public ConnectionBody
00282 {
00283 public:
00284 ConnectionImpl(Signal &signal, Signal::slot_type slot);
00285
00286 void set_iterator(const Signal::Slots::iterator &it);
00287
00288 void disconnect();
00289
00290 bool connected() const;
00291
00292 void block(bool b = true);
00293 bool blocked() const;
00294
00295 SlotBase &get_slot() const;
00296
00300 bool operator==(const ConnectionImpl &other) const;
00301
00302 private:
00303 enum {
00304 CONNECTED = 1,
00305 BLOCKED = 2,
00306 };
00307
00309 int state_;
00310 Signal::slot_type slot_;
00311 Signal &signal_;
00312 Signal::Slots::iterator it_;
00313 };
00314
00323 const int SIGNAL_PRIORITY_RUN_FIRST = 1;
00324 const int SIGNAL_PRIORITY_HIGHER = 9;
00326 const int SIGNAL_PRIORITY_NORMAL = 10;
00327 const int SIGNAL_PRIORITY_LOWER = 11;
00328 const int SIGNAL_PRIORITY_RUN_LAST = 20;
00330
00334 class OMGUI_API EventManager
00335 {
00336 public:
00351 static Connection connect(object_id object, event_id event, SlotBase* slot, int priority = SIGNAL_PRIORITY_NORMAL);
00352
00357 static void disconnect_all(object_id object);
00358
00362 static bool send_event(const Event &event);
00363
00367 static void disconnect_all();
00368
00369 private:
00370 typedef std::map<event_id, Signal> EventSignals;
00371 typedef std::map<object_id, EventSignals> ObjectEventSignals;
00372
00373 struct SignalsGroup
00374 {
00375
00376
00378
00380 ObjectEventSignals object_event_signals;
00381
00382 void disconnect_all()
00383 {
00384
00385
00386 object_event_signals.clear();
00387 }
00388 };
00389
00390 typedef std::map<int, SignalsGroup> Signals;
00391 static Signals signals;
00392 static int sending_event;
00393 struct ObjectEventEraseBufferData
00394 {
00395 ObjectEventEraseBufferData(ObjectEventSignals &container, ObjectEventSignals::iterator iterator): container(container), iterator(iterator) { }
00396 ObjectEventSignals &container;
00397 ObjectEventSignals::iterator iterator;
00398 };
00399 static std::deque<ObjectEventEraseBufferData> object_event_erase_buffer;
00400
00407 static bool send_event(SignalsGroup &group, const Event &event, bool &processed);
00408 };
00409
00415 template<typename E>
00416 SlotBase *make_slot(typename PointerSlot<E>::function_type const &func)
00417 {
00418 return new PointerSlot<E>(func);
00419 }
00420
00424 template<typename E, typename T>
00425 SlotBase *make_slot(typename MemberSlot<E,T>::function_type func, T &instance)
00426 {
00427 return new MemberSlot<E, T>(func, instance);
00428 }
00429
00433 template<typename E, typename T>
00434 SlotBase *make_slot(typename ConstMemberSlot<E,T>::function_type func, T &instance)
00435 {
00436 return new ConstMemberSlot<E, T>(func, instance);
00437 }
00438
00445 template<typename E, typename Functor>
00446 SlotBase *make_slot(const Functor &func)
00447 {
00448 return new FunctorSlot<E, Functor>(func);
00449 }
00450
00451
00452
00453
00454
00455 class OMGUI_API Event
00456 {
00457 public:
00465 Event(event_id id, object_id obj);
00466
00467 Event(const Event &other);
00468
00469 virtual ~Event();
00470
00474 event_id get_id() const;
00475
00479 object_id get_object_id() const;
00480
00486 void veto(bool v = true) const;
00487
00491 bool get_veto() const;
00492
00496 virtual bool can_veto() const;
00497
00498 private:
00499 const event_id m_id;
00500 const object_id m_obj_id;
00501 mutable bool m_veto;
00502 };
00503
00520 class OMGUI_API MouseEvent : public Event
00521 {
00522 public:
00532 MouseEvent(event_id id, object_id obj, const omgui::Point &pos, int button_flags, int key_flags);
00533 MouseEvent(const MouseEvent &other);
00534
00538 enum KEY_FLAGS {
00539 NONE = 0x0,
00540 SHIFT = 0x1,
00541 ALT = 0x2,
00542 CONTROL = 0x4,
00543 };
00544
00548 enum BUTTON_FLAGS {
00549 LEFT = 0x1,
00550 RIGHT = 0x2,
00551 MIDDLE = 0x4
00552 };
00553
00557 int get_button_flags() const;
00558
00562 bool get_button_state(BUTTON_FLAGS button) const;
00563
00567 int get_key_flags() const;
00568
00572 bool get_key_state(KEY_FLAGS key) const;
00573
00577 omgui::Point get_position() const;
00578
00579 private:
00581 omgui::Point m_position;
00582
00584 int m_button_flags;
00585
00587 int m_key_flags;
00588 };
00589
00594 class WindowCloseEvent : public Event
00595 {
00596 public:
00604 WindowCloseEvent(event_id id, object_id obj, bool vetoable = true);
00605 WindowCloseEvent(const WindowCloseEvent &other);
00606
00612 bool can_veto() const;
00613
00614 private:
00615 bool m_vetoable;
00616 };
00617
00622 class NotebookEvent : public Event
00623 {
00624 public:
00632 NotebookEvent(event_id id, object_id obj, omgui::NotebookPage current_page);
00633 NotebookEvent(const NotebookEvent &other);
00634
00638 omgui::NotebookPage get_current_page() const;
00639
00643 bool can_veto() const;
00644
00645 private:
00646 omgui::NotebookPage m_current_page;
00647 };
00648
00653 class MenuEvent : public Event
00654 {
00655 public:
00663 MenuEvent(event_id e_id, object_id obj, menu_id m_id);
00664
00665 menu_id get_menu_id() const;
00666
00667 protected:
00668 menu_id m_menu_id;
00669 };
00670
00671 }
00672
00673 #endif // OMGUI_EVENT_H