INCLUDE(Common)
INCLUDE(FindQt5)
+ADD_SUBDIRECTORY (src/Event)
#ADD_SUBDIRECTORY (src/ModelAPI)
ADD_SUBDIRECTORY (src/Model)
ADD_SUBDIRECTORY (src/XGUI)
--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8.11)
+
+INCLUDE(Common)
+
+SET(PROJECT_HEADERS
+ Event.hxx
+ Event_Message.hxx
+ Event_Listener.hxx
+ Event_Loop.hxx
+)
+
+SET(PROJECT_SOURCES
+ Event_Message.cxx
+ Event_Listener.cxx
+ Event_Loop.cxx
+)
+
+ADD_DEFINITIONS(-DEVENT_EXPORTS)
+ADD_LIBRARY(Event SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS})
+TARGET_LINK_LIBRARIES(Event ${PROJECT_LIBRARIES})
+
+INCLUDE_DIRECTORIES(
+)
--- /dev/null
+#ifndef EVENT_H
+#define EVENT_H
+
+#if defined EVENT_EXPORTS
+#if defined WIN32
+#define EVENT_EXPORT __declspec( dllexport )
+#else
+#define EVENT_EXPORT
+#endif
+#else
+#if defined WIN32
+#define EVENT_EXPORT __declspec( dllimport )
+#else
+#define EVENT_EXPORT
+#endif
+#endif
+
+#endif
--- /dev/null
+// File: Event_Listener.cxx
+// Created: Thu Mar 13 2014
+// Author: Mikhail PONIKAROV
+
+#include <Event_Listener.hxx>
\ No newline at end of file
--- /dev/null
+// File: Event_Listener.hxx
+// Created: Thu Mar 13 2014
+// Author: Mikhail PONIKAROV
+
+#ifndef Event_Listener_HeaderFile
+#define Event_Listener_HeaderFile
+
+#include <Event.hxx>
+class Event_Message;
+
+/**\class Event_Listener
+ * \ingroup EventLoop
+ * \brief Base interface for any event listener.
+ *
+ * If some object wants to listen some events it must inherit
+ * this class and register in the Loop.
+ */
+EVENT_EXPORT class Event_Listener {
+
+public:
+ //! This method is called by loop when the event is started to process.
+ virtual void ProcessEvent(const Event_Message* theMessage) = 0;
+};
+
+#endif
--- /dev/null
+// File: Event_Loop.hxx
+// Created: Thu Mar 13 2014
+// Author: Mikhail PONIKAROV
+
+#include <Event_Loop.hxx>
+#include <string>
+
+using namespace std;
+
+Event_Loop* Event_Loop::Loop()
+{
+ // initialized on initialization of the application
+ static Event_Loop MAIN_LOOP;
+ return &MAIN_LOOP;
+}
+
+Event_ID Event_Loop::EventByName(const char* theName)
+{
+ ///! All events created in this session, uniquely identified by the text and char pointer
+ static map<string, char*> CREATED_EVENTS;
+ char* aResult;
+ string aName(theName);
+ map<string, char*>::iterator aFound = CREATED_EVENTS.find(aName);
+ if (aFound == CREATED_EVENTS.end()) { //not created yet
+ aResult = strdup(theName); // copy to make unique internal pointer
+ CREATED_EVENTS[aName] = aResult;
+ } else
+ aResult = aFound->second;
+
+ return Event_ID(aResult);
+}
+
+void Event_Loop::Send(Event_Message theMessage)
+{
+ // TO DO: make it in thread and wit husage of semaphores
+
+ map<char*, map<void*, list<Event_Listener*> > >::iterator aFindID =
+ myListeners.find(theMessage.ID().EventText());
+ if (aFindID != myListeners.end()) {
+ map<void*, list<Event_Listener*> >::iterator aFindSender =
+ aFindID->second.find(theMessage.Sender());
+ if (aFindSender != aFindID->second.end()) {
+ list<Event_Listener*>& aListeners = aFindSender->second;
+ for(list<Event_Listener*>::iterator aL = aListeners.begin(); aL != aListeners.end(); aL++)
+ (*aL)->ProcessEvent(&theMessage);
+ }
+ if (theMessage.Sender()) { // also call for NULL senders registered
+ aFindSender = aFindID->second.find(NULL);
+ if (aFindSender != aFindID->second.end()) {
+ list<Event_Listener*>& aListeners = aFindSender->second;
+ for(list<Event_Listener*>::iterator aL = aListeners.begin(); aL != aListeners.end(); aL++)
+ (*aL)->ProcessEvent(&theMessage);
+ }
+ }
+ }
+}
+
+void Event_Loop::RegisterListener(
+ Event_Listener* theListener, const Event_ID theID, void* theSender)
+{
+ map<char*, map<void*, list<Event_Listener*> > >::iterator aFindID =
+ myListeners.find(theID.EventText());
+ if (aFindID == myListeners.end()) { // create container associated with ID
+ myListeners[theID.EventText()] = map<void*, list<Event_Listener*> >();
+ aFindID = myListeners.find(theID.EventText());
+ }
+
+ map<void*, list<Event_Listener*> >::iterator aFindSender =
+ aFindID->second.find(theSender);
+ if (aFindSender == aFindID->second.end()) { // create container associated with sender
+ aFindID->second[theSender] = list<Event_Listener*>();
+ aFindSender = aFindID->second.find(theSender);
+ }
+ // check that listener was not registered wit hsuch parameters before
+ list<Event_Listener*>& aListeners = aFindSender->second;
+ for(list<Event_Listener*>::iterator aL = aListeners.begin(); aL != aListeners.end(); aL++)
+ if (*aL == theListener) return; // avoid duplicates
+
+ aListeners.push_back(theListener);
+}
--- /dev/null
+// File: Event_Loop.hxx
+// Created: Thu Mar 13 2014
+// Author: Mikhail PONIKAROV
+
+#ifndef Event_Loop_HeaderFile
+#define Event_Loop_HeaderFile
+
+#include <Event_Message.hxx>
+#include <Event_Listener.hxx>
+
+#include <map>
+#include <list>
+
+/**\class Event_Lopp
+ * \ingroup EventLoop
+ * \brief Base class that manages the receiving and sending of all
+ * not Qt-events in the application.
+ *
+ * One per application, initialized on start. Listeners must register in this loop
+ * to get events, called by senders. Sending of events is very fast (just adding to container).
+ * Performing of events is processed in separated thread, so, sender takes
+ * control back immideately.
+ */
+class Event_Loop {
+ std::map<char*, std::map<void*, std::list<Event_Listener*> > >
+ myListeners; ///< map from event ID to sender pointer to listeners that must be called for this
+
+ //! The empty constructor, will be called at startup of the application, only once
+ Event_Loop() {};
+public:
+ ///! Returns the main object of the loop, one per application.
+ EVENT_EXPORT static Event_Loop* Loop();
+ //! Returns the unique event by the given name. Call this method only on initialization of object
+ //! to speedup the events processing without parsing of the string.
+ EVENT_EXPORT static Event_ID EventByName(const char* theName);
+
+ //! Allows to send an event
+ EVENT_EXPORT void Send(Event_Message theMessage);
+
+ //! Registers (or adds if such listener is already registered) a listener
+ //! that will be called on the event and from the defined sender
+ EVENT_EXPORT void RegisterListener(Event_Listener* theListener, const Event_ID theID,
+ void* theSender = 0);
+};
+
+#endif
--- /dev/null
+// File: Event_Message.cxx
+// Created: Thu Mar 13 2014
+// Author: Mikhail PONIKAROV
+
+#include <Event_Message.hxx>
--- /dev/null
+// File: Event_Message.hxx
+// Created: Thu Mar 13 2014
+// Author: Mikhail PONIKAROV
+
+#ifndef Event_Message_HeaderFile
+#define Event_Message_HeaderFile
+
+#include <Event.hxx>
+
+/**\class Event_ID
+ * \ingroup EventLoop
+ * \brief Identifier of the event kind.
+ *
+ * Each event ID is created in main Envent_Loop class
+ * that stores correspondance between the string-name of the
+ * identifier and the pointer to the static string that is really
+ * used as an identifier (this is usefull for debugging of the events
+ * with log files and in debugger).
+ */
+EVENT_EXPORT class Event_ID {
+ char* myID; ///< pointer to the text-identifier of the event, unique pointer for all events of such type
+
+ Event_ID(char* theID) {myID = theID;}
+
+ friend class Event_Loop;
+public:
+ /// Returns the text-identifier of the event (for debugging reasons)
+ char* EventText() const {return myID;}
+ /// Allows to compare identifiers
+ bool operator==(const Event_ID& theID) const {return myID == theID.myID;}
+};
+
+/**\class Event_Message
+ * \ingroup EventLoop
+ * \brief Message for communication between sender and listener of event.
+ * Normally it is inherited by the higher-level
+ */
+EVENT_EXPORT class Event_Message {
+ Event_ID myID; ///< identifier of the event
+ void* mySender; ///< the sender object
+
+public:
+
+ //! Creates the message
+ Event_Message(const Event_ID theID, const void* theSender = 0);
+
+ //! Returns identifier of the message
+ const Event_ID& ID() const {return myID;}
+
+ //! Returns sender of the message or NULL if it is anonymous message
+ void* Sender() {return mySender;}
+};
+
+#endif