comp.lang.ada
 help / color / mirror / Atom feed
From: "Lucretia" <lucretia9@lycos.co.uk>
Subject: Adding support for multiple tasks in wxAda
Date: 25 Oct 2005 07:02:11 -0700
Date: 2005-10-25T07:02:11-07:00	[thread overview]
Message-ID: <1130248931.682116.143660@g14g2000cwa.googlegroups.com> (raw)

Hi,

Here's that question I promised I'd bring in ;-D

Here's the basic structure of wxAda types which can handle events.

<wx.Base.Event_Handler>
package wx.Base.Event_Handler is

  -- This is the actual type (wxEvtHandler) we are creating here.
  type Event_Handler_Type is new wx.Base.Object.Object_Type with
private;

  ...
  procedure Add_Pending_Event(
    Self  : in out Event_Handler_Type;
    Event : in wxEvent.Event_Type);

  -- The Connect procedure need to be a generic, so that the Callback
can be passed properly. It can be a number of different types.
  generic
    type Connect_Callback_Type is private;
  procedure Connect(
    Self      : in Event_Handler_Type'Class;
    Id,
    LastId    : in wx.Base.Id.Id_Type;
    EventType : in wxEvent.Event_Id_Type;
    Callback  : in Connect_Callback_Type);
  ...
  function Process_Event(
    Self  : in Event_Handler_Type;
    Event : in wxEvent.Event_Type) return Boolean;
  ...

end wx.Base.Event_Handler;
</wx.Base.Event_Handler>

<wx.Core.Window>
package wx.Core.Window is

  -- This is the actual type (wxWindow) we are creating here.
  type Window_Type is new wx.Base.Event_Handler.Event_Handler_Type with
private;

  ...

end wx.Core.Window;
</wx.Core.Window>

<wx.Core.Control>
package wx.Core.Control is

  -- This is the actual type (wxControl) we are creating here.
  type Control_Type is new wx.Core.Window.Window_Type with private;

  ...

end wx.Core.Control;
</wx.Core.Control>

This basically means that all windows and controls can handle their own
events.

The Connect generic procedure in wx.Base.Event_Handler is used to
connect event id's to callbacks, it's this generic that glues the C/C++
code to the Ada code, via the C wxEvtHandler_Connect function. Within
this function I use a C++ static function as the basic event handler
callback and package up the data passed to Connect from wxAda as the
callback data. Then within this callback, I then unpack the data from
wxAda and call the event handler within Ada (exported as a C function).

<wxbase_evthandler.cc>
void wxAdaCallbackObject::EventHandler(wxEvent &Event)
    {
    wxAdaCallbackObject *CallbackObject =
        wx_static_cast(wxAdaCallbackObject *,
Event.m_callbackUserData);

    Ada_Event_Handler(
        CallbackObject->_ParentEventHandler,
        CallbackObject->_Callback,
        &Event,
        Event.GetClassInfo()->GetClassName());
    }


void wxEvtHandler_Connect(
    wxAdaEvtHandler *Self,
    int              Id,
    int              LastId,
    int              EventType,
    void            *ParentEventHandler,
    void            *Callback)
    {
    wxObjectEventFunction EventCallback =
        wx_static_cast(wxObjectEventFunction,
&wxAdaCallbackObject::EventHandler);

    Self->Connect(
        Id,
        LastId,
        EventType,
        EventCallback,
        new wxAdaCallbackObject(ParentEventHandler, Callback));
    }
</wxbase_evthandler.cc>

>From this function I then determine whether it is a wxAda derived type
(inside Create_Ada_Event). If so, there exists a wxAda type which I can
just get hold of otherwise I "new" a proxy type. This returned event
type is then passed as a parameter to the actual Ada callback function
which was originally passed to the Connect generic above.

This proxy type has to be allocated dynamically, because at this point
we only know an event has been triggered, but not which type of event.
Inside the event handler (at the Ada level) the programmer will provide
a callback with the correct event type as a parameter, so we implicitly
convert the event type to the correct type to get the extra primitives
and/or data that that event type implements.

<wx.Base.Event_Handler>
package body wx.Base.Event_Handler is

  ...

  procedure Ada_Event_Handler(
    Parent     : Event_Handler_Class;
    Callback   : in Event_Function;
    Event      : in System.Address;
    Class_Name : in Interfaces.C.Strings.chars_ptr) is

    CXX_Class_Name : String              :=
Interfaces.C.To_Ada(Interfaces.C.Strings.Value(Class_Name));
    Ada_Event      : wxEvent.Event_Class := null;

    type Event_Access is access all wxEvent.Event_Type;

    procedure Free is new Ada.Unchecked_Deallocation(
      Object => wxEvent.Event_Type,
      Name   => Event_Access);

    function To_Access is new Ada.Unchecked_Conversion(
      Source => wxEvent.Event_Class,
      Target => Event_Access);

    Ada_Event_Acccess : Event_Access := null;

  begin

    Text_IO.Put_Line("Ada_Event_Handler: " & CXX_Class_Name);

    Ada_Event := Create_Ada_Event(Event, CXX_Class_Name);

    Callback(Parent, wxEvent.Event_Type(Ada_Event.all));

    if CXX_Class_Name /= "wxAdaEvent" then

      -- The next line would work, if it didn't get called again on
exit of the app!
      --Finalize(Ada_Event.all);

      Ada_Event_Acccess := To_Access(Ada_Event);

      Free(Ada_Event_Acccess);

    end if;

    return;

  end Ada_Event_Handler;

  ...

end wx.Base.Event_Handler;
</wx.Base.Event_Handler>

In wxWidgets a programmer would normally create a window (usually a
wxPanel) and then layout the controls on this panel, all the event
handlers (the callbacks) for the controls would be connected to the
wxPanel rather than the individual controls. It would be possible to
set up an event handler for each control, but that's really a special
case.

So given a contrived example, some Panel_Type has some controls
displayed upon it. There are a load of event handlers connected to the
Panel_Type. We also have one task per control, which does some trivial
update by sending events to the Panel_Type. Now we need to make the
event handling protected in some way, but seeing as Ada_Event_Handler
is essentially called from C this could be a problem. If I were to
create a protected type for handling events, can this safely be called
from C or from within a C function (Ada_Event_Handler)?

Thanks,
Luke.




                 reply	other threads:[~2005-10-25 14:02 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox