Signal event handling in a2dObject

Although a2dObject is directly derived from wxEvtHandler, it has some extra function to ease the use of dynamic events for signaling purposes. Within wxArt2D the events are used for signaling changes in the framework. One connects to such an event to get notified of a change in some class. So it is not the idea to handle such events, but more to know something. Normally one uses wxEvthandler::Connect() for that. But that connects directly to a function. It does not go through the static event table of the class from which a member function is connected. For a library it is often best to offer a default implementation, and the user of the library can extend it in a derived class to add his own stuff. For that purpose, static event tables are very nice. The achieve same behavior with dynamic events, it would require a virtual function in the base class, which would be the default implementation on receiving a signal/notify event. Or the user of the library has to disconnect the signal in the base class first, and connect his own implementation. It would be better to the wxWidgets Static event tables, since it act very similar as virtual functions.

That is possible. Instead of connecting directly to a member function, wxArt2D, connects to a2dObject::ProcessConnectedEvent() instead. this function calls wxEvtHandler::ProcessEvent(). So in the end ClassA sends a signal event to classB via the dynamic event system of wxWidgets. There it calls (via ProcessConnectedEvent() ) ProcessEvent() for classB. And therefore it goes to check the static event table of classB to see if the signal event with that wxEventType was intercepted/handled. ClassB will not receive all events of classA, just the events to which it did connect. Also classB does not need to handle the events to which it is connected, it may handle them. In any case handled or not in classB, the event will be skipped. Therefore if a classC connects to the same event in classA, it can be handled there also.

   1 // a2dView connect to its document FOR EVENT wxEVT_CHANGEDTITLE_DOCUMENT.
   2 m_viewDocument->ConnectEvent( wxEVT_CHANGEDTITLE_DOCUMENT, this );
   3 
   4 //a2dView its event table handles wxEVT_CHANGEDTITLE_DOCUMENT EVENT  
   5 BEGIN_EVENT_TABLE( a2dView, a2dObject )
   6     EVT_CHANGEDTITLE_DOCUMENT( a2dView::OnChangeTitle )
   7 END_EVENT_TABLE()

Here the code in a2dObject to achieve this:

   1 //! Used to connect an event coming from classA to classB as a dynamic event.
   2 //! The dynamic can be handled by the static event table of classB.
   3 //! The event is handled by calling ProcessEvent(), but will always be skipped.
   4 void a2dObject::ProcessConnectedEvent( wxEvent& event )
   5 {
   6     if ( ProcessEvent( event ) )
   7     {
   8         //even if the event was handled, and was not skipped,
   9         //we want it to skip it here, so the next dynamic connected event 
  10         //in the calling wxEvtHandler;:ProcessEventIfMatches, will be called too.
  11         //The signal is typically distributed to all connected classes.
  12         event.Skip( true );
  13         return;    
  14     }
  15     event.Skip( true );
  16 }
  17 
  18 //! Connect an event from coming classA to classB as a dynamic event.
  19 //! The event is handled by calling ProcessEvent(), but will always be skipped.
  20 //! \param evtObject ClassB in which to receive the event.
  21 void a2dObject::ConnectEvent( wxEventType type, wxEvtHandler* evtObject )
  22 {
  23     Connect( type, wxObjectEventFunction( &a2dObject::ProcessConnectedEvent ), 0, evtObject );
  24 }
  25 
  26 //! Disconnect an event from classA to classB as a dynamic event.
  27 //! The event is handled by calling ProcessEvent(), but will always be skipped.
  28 //! \param evtObject ClassB in to which connecttion was made.
  29 bool a2dObject::DisconnectEvent( wxEventType type, wxEvtHandler* evtObject )
  30 {
  31     return Disconnect( type, wxObjectEventFunction( &a2dObject::ProcessConnectedEvent ), 0, evtObject );
  32 }
  33 
  34 //! Remove all dynamic events in classA, going to classB (evtObject)
  35 bool a2dObject::DisconnectEventAll( wxEvtHandler* evtObject )
  36 {
  37     bool succeed = false;
  38     bool once = false;
  39     do
  40     {
  41         succeed = Disconnect( wxEVT_NULL, wxObjectEventFunction( &a2dObject::ProcessConnectedEvent ), 0, evtObject );
  42         once = succeed || once;
  43     }
  44     while ( succeed );
  45     return once;
  46 }

wxArt2D: EventDynamicToStatic (last edited 2011-06-01 22:12:46 by KlaasHolwerda)