comp.lang.ada
 help / color / mirror / Atom feed
* Where do I get my Cairo context from (in GTK3)?
@ 2016-04-24 20:44 hreba
  2016-04-25  7:40 ` Dmitry A. Kazakov
  2016-08-05 15:56 ` borisgaertner56
  0 siblings, 2 replies; 13+ messages in thread
From: hreba @ 2016-04-24 20:44 UTC (permalink / raw)


In GTk2 you got it from a call of Gdk.Cairo.Create.

In GTK3 it is passed as a parameter of the callback function for the 
"draw" signal with the C prototype:

    gboolean
    user_function (GtkWidget    *widget,
                   CairoContext *cr,
                   gpointer      user_data)

So I wrote in my Ada program (GNAT, gtkada):

    package DA_Ret_Callback is new Gtk.Handlers.User_Return_Callback
      (Gtk.Widget.Gtk_Widget_Record, Boolean, Handler_DataD);


    function Draw_Handler
      (da: access Gtk.Widget.Gtk_Widget_Record'Class;
       cc: Cairo.Cairo_Context;
       hd: Handler_DataD) return Boolean is
    begin
       ...
    end Draw_Handler;


    procedure Connect_Handlers
      (obj: Glib.Object.GObject; hd: Handler_DataD;
       sn_realize, sn_config, sn_draw: Glib.Signal_Name) is
    begin
       ...
       DA_Ret_Callback.Connect
	(Gtk.Widget.Gtk_Widget(obj), sn_draw,
	 DA_Ret_Callback.To_Marshaller(Draw_Handler'Access),
	 hd);
    end Connect_Handlers;


The compiler then tells me

    gui-canvas.adb:79:25: no candidate interpretations match the actuals:
    gui-canvas.adb:79:52: expected type "Handler" defined at
    gtk-marshallers.ads:309, instance at gtk-handlers.ads:468,
    instance at line 20

That means that he expects a handler

          type Handler is access function
	           (Widget    : access Widget_Type'Class;
	            User_Data : User_Type) return Return_Type;
	
So where do I get the cairo context from?
-- 
Frank Hrebabetzky		+49 / 6355 / 989 5070

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Where do I get my Cairo context from (in GTK3)?
  2016-04-24 20:44 Where do I get my Cairo context from (in GTK3)? hreba
@ 2016-04-25  7:40 ` Dmitry A. Kazakov
  2016-04-25 10:03   ` hreba
  2016-08-05 15:56 ` borisgaertner56
  1 sibling, 1 reply; 13+ messages in thread
From: Dmitry A. Kazakov @ 2016-04-25  7:40 UTC (permalink / raw)


On 24/04/2016 22:44, hreba wrote:
> In GTk2 you got it from a call of Gdk.Cairo.Create.
>
> In GTK3 it is passed as a parameter of the callback function for the
> "draw" signal with the C prototype:
>
>    gboolean
>    user_function (GtkWidget    *widget,
>                   CairoContext *cr,
>                   gpointer      user_data)
>
> So I wrote in my Ada program (GNAT, gtkada):
>
>    package DA_Ret_Callback is new Gtk.Handlers.User_Return_Callback
>      (Gtk.Widget.Gtk_Widget_Record, Boolean, Handler_DataD);
>
>
>    function Draw_Handler
>      (da: access Gtk.Widget.Gtk_Widget_Record'Class;

If you instantiate it with GObject, why using Gtk_Widget instead?

>       cc: Cairo.Cairo_Context;
>       hd: Handler_DataD) return Boolean is
>    begin
>       ...
>    end Draw_Handler;
>
>
>    procedure Connect_Handlers
>      (obj: Glib.Object.GObject; hd: Handler_DataD;
>       sn_realize, sn_config, sn_draw: Glib.Signal_Name) is
>    begin
>       ...
>       DA_Ret_Callback.Connect
>     (Gtk.Widget.Gtk_Widget(obj), sn_draw,

I suppose sn_draw is "draw".

>      DA_Ret_Callback.To_Marshaller(Draw_Handler'Access),
>      hd);
>    end Connect_Handlers;
>
> The compiler then tells me
>
>    gui-canvas.adb:79:25: no candidate interpretations match the actuals:
>    gui-canvas.adb:79:52: expected type "Handler" defined at
>    gtk-marshallers.ads:309, instance at gtk-handlers.ads:468,
>    instance at line 20

These messages are always misleading. There are too many overloading 
Connects in the package. When there is any problem with any parameter, 
GNAT is practically never able to pinpoint the true reason.

> That means that he expects a handler
>
>          type Handler is access function
>                (Widget    : access Widget_Type'Class;
>                 User_Data : User_Type) return Return_Type;
>
> So where do I get the cairo context from?

As you did. Just make sure that all parameters of Connect match. Instead 
of pointer conversion use object conversion. E.g.

    Gtk_Widget_Record'Class (Obj.all)'Unchecked_Access

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Where do I get my Cairo context from (in GTK3)?
  2016-04-25  7:40 ` Dmitry A. Kazakov
@ 2016-04-25 10:03   ` hreba
  2016-04-25 11:58     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 13+ messages in thread
From: hreba @ 2016-04-25 10:03 UTC (permalink / raw)


On 04/25/2016 09:40 AM, Dmitry A. Kazakov wrote:

> If you instantiate it with GObject, why using Gtk_Widget instead?

I use Glade and Gtk_Builder.Get_Object returns GObject. Nearly all 
examples for handler connection use Gtk_Widget so I did the same.
>
> I suppose sn_draw is "draw".
>
Correct.

>> So where do I get the cairo context from?
>
> As you did. Just make sure that all parameters of Connect match. Instead
> of pointer conversion use object conversion. E.g.
>
>     Gtk_Widget_Record'Class (Obj.all)'Unchecked_Access

So I changed my call of Connect to

        DA_Ret_Callback.Connect
	(Gtk.Widget.Gtk_Widget_Record'Class(obj.all)'Unchecked_Access,
	 sn_draw,
	 DA_Ret_Callback.To_Marshaller(Draw_Handler'Access),
	 hd);

but I still get the same error message from the compiler.
-- 
Frank Hrebabetzky		+49 / 6355 / 989 5070


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Where do I get my Cairo context from (in GTK3)?
  2016-04-25 10:03   ` hreba
@ 2016-04-25 11:58     ` Dmitry A. Kazakov
  2016-04-26  7:22       ` briot.emmanuel
  0 siblings, 1 reply; 13+ messages in thread
From: Dmitry A. Kazakov @ 2016-04-25 11:58 UTC (permalink / raw)


On 25/04/2016 12:03, hreba wrote:
> On 04/25/2016 09:40 AM, Dmitry A. Kazakov wrote:
>
>> If you instantiate it with GObject, why using Gtk_Widget instead?
>
> I use Glade and Gtk_Builder.Get_Object returns GObject. Nearly all
> examples for handler connection use Gtk_Widget so I did the same.

But it is still GObject_Record.

>> I suppose sn_draw is "draw".
>>
> Correct.

Is it Signal_Name in Connect? Recent GtkAda changes broke a lot of 
things. Try a plain string literal instead.

>>> So where do I get the cairo context from?
>>
>> As you did. Just make sure that all parameters of Connect match. Instead
>> of pointer conversion use object conversion. E.g.
>>
>>     Gtk_Widget_Record'Class (Obj.all)'Unchecked_Access
>
> So I changed my call of Connect to
>
>        DA_Ret_Callback.Connect
>     (Gtk.Widget.Gtk_Widget_Record'Class(obj.all)'Unchecked_Access,
>      sn_draw,
>      DA_Ret_Callback.To_Marshaller(Draw_Handler'Access),
>      hd);
>
> but I still get the same error message from the compiler.

Try to specify a concrete marshaller in conversion, to narrow the 
problem. To_Marshaler is a renaming. Use the original full name from the 
marshaler package that instantiates the Draw's profile. You have a type 
mismatch in some of the parameters.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Where do I get my Cairo context from (in GTK3)?
  2016-04-25 11:58     ` Dmitry A. Kazakov
@ 2016-04-26  7:22       ` briot.emmanuel
  2016-04-26  7:34         ` hreba
  0 siblings, 1 reply; 13+ messages in thread
From: briot.emmanuel @ 2016-04-26  7:22 UTC (permalink / raw)


> Is it Signal_Name in Connect? Recent GtkAda changes broke a lot of 
> things. Try a plain string literal instead.

No they did not :-)

In fact, the code can be much simplified now:

   function Custom_Draw
       (Self : access Gtk_Widget_Record'Class;
        Cr    : Cairo.Cairo_Context) return Boolean is ...

   Obj.On_Draw (Custom_Draw'Access);     --  defined in gtk-widget.ads

No need for the marshallers any more in almost all cases. I recommend using
the new On_* procedures defined in all the GtkAda packages, they might signal
handling much easier, and safer too (since the compiler can check statically that
the signal is valid for the given widget)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Where do I get my Cairo context from (in GTK3)?
  2016-04-26  7:22       ` briot.emmanuel
@ 2016-04-26  7:34         ` hreba
  2016-04-27  7:47           ` briot.emmanuel
  0 siblings, 1 reply; 13+ messages in thread
From: hreba @ 2016-04-26  7:34 UTC (permalink / raw)


On 04/26/2016 09:22 AM, briot.emmanuel@gmail.com wrote:
>> Is it Signal_Name in Connect? Recent GtkAda changes broke a lot of
>> things. Try a plain string literal instead.
>
> No they did not :-)
>
> In fact, the code can be much simplified now:
>
>     function Custom_Draw
>         (Self : access Gtk_Widget_Record'Class;
>          Cr    : Cairo.Cairo_Context) return Boolean is ...
>
>     Obj.On_Draw (Custom_Draw'Access);     --  defined in gtk-widget.ads
>
> No need for the marshallers any more in almost all cases. I recommend using
> the new On_* procedures defined in all the GtkAda packages, they might signal
> handling much easier, and safer too (since the compiler can check statically that
> the signal is valid for the given widget)
>

I would use On_* procedures if I didn't need user data. Until now no 
success.
-- 
Frank Hrebabetzky		+49 / 6355 / 989 5070

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Where do I get my Cairo context from (in GTK3)?
  2016-04-26  7:34         ` hreba
@ 2016-04-27  7:47           ` briot.emmanuel
  2016-04-27  8:08             ` Dmitry A. Kazakov
  2016-04-27 13:15             ` hreba
  0 siblings, 2 replies; 13+ messages in thread
From: briot.emmanuel @ 2016-04-27  7:47 UTC (permalink / raw)


> I would use On_* procedures if I didn't need user data. Until now no 
> success.

Are you sure you really need that user data ? In my experience, it is often
better to extend the widget type in your application, store whatever information
is needed in that child type, and then use the On_* procedure passing a Slot
object (so that the callback receives your widget type, rather than the widget
on which the action occurred). This works in 95% of the cases.

The GNAT Development Studio (GPS), which is about 500_000 lines of code
has almost no use of user data, and those that remain are mostly because
that part of the code hasn't been updated yet.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Where do I get my Cairo context from (in GTK3)?
  2016-04-27  7:47           ` briot.emmanuel
@ 2016-04-27  8:08             ` Dmitry A. Kazakov
  2016-04-28  7:48               ` briot.emmanuel
  2016-04-27 13:15             ` hreba
  1 sibling, 1 reply; 13+ messages in thread
From: Dmitry A. Kazakov @ 2016-04-27  8:08 UTC (permalink / raw)


On 27/04/2016 09:47, briot.emmanuel@gmail.com wrote:
>> I would use On_* procedures if I didn't need user data. Until now no
>> success.
>
> Are you sure you really need that user data ? In my experience, it is often
> better to extend the widget type in your application, store whatever information
> is needed in that child type, and then use the On_* procedure passing a Slot
> object (so that the callback receives your widget type, rather than the widget
> on which the action occurred). This works in 95% of the cases.

Quite the opposite, this works in only few cases. The problem is that 
the handler of a signal is practically never the issuer of. So handling 
own events is very rare, only when the widget is a reusable extension of 
some other widget and the signal is used internally.

End instances of widgets are never like that. The most frequent case is 
a container widget handling signals from its children. The first 
parameter of the handler is never ever used, because the identification 
of the issuer is the handler procedure itself. The user parameter is the 
container widget, which is the case for the OP, I suppose.

> The GNAT Development Studio (GPS), which is about 500_000 lines of code
> has almost no use of user data, and those that remain are mostly because
> that part of the code hasn't been updated yet.

I have several GTK projects with exactly opposite statistics. Callbacks 
without user data are never used. Though many widgets are extensions as 
you suggested.

The design of handler connecting should have a reverse version 
"connect-from" in addition to current "connect-to", in a language like 
Ada without full double dispatch.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Where do I get my Cairo context from (in GTK3)?
  2016-04-27  7:47           ` briot.emmanuel
  2016-04-27  8:08             ` Dmitry A. Kazakov
@ 2016-04-27 13:15             ` hreba
  2016-04-27 13:37               ` Dmitry A. Kazakov
  1 sibling, 1 reply; 13+ messages in thread
From: hreba @ 2016-04-27 13:15 UTC (permalink / raw)


On 04/27/2016 09:47 AM, briot.emmanuel@gmail.com wrote:
>> I would use On_* procedures if I didn't need user data. Until now no
>> success.
>
> Are you sure you really need that user data ? In my experience, it is often
> better to extend the widget type in your application, store whatever information
> is needed in that child type, and then use the On_* procedure passing a Slot
> object (so that the callback receives your widget type, rather than the widget
> on which the action occurred). This works in 95% of the cases.
>
> The GNAT Development Studio (GPS), which is about 500_000 lines of code
> has almost no use of user data, and those that remain are mostly because
> that part of the code hasn't been updated yet.
>

I am creating a drawing surface, a new layer for isolating the end user 
from GTK. The idea is that the end user gets a constructor for a new 
type "Canvas". He has to specify 3 handlers: the first is called once 
after the canvas appears on the screen, the second is called after each 
resizing, the third one when the canvas needs redrawing. Drawing is done 
by calling a series of of standardized drawing procedures (for lines, 
arcs etc.) The end user needs no knowledge about connecting handlers, 
about cairo contexts or "Stroke" calls. He gets a framework for 
technical drawings with a simple user interface.

The drawing handler at the end user level is a subprogram with basically 
one parameter: the user data which specifies what has to be drawn. I am 
implementing the framework and I don't now what the end user will draw, 
so I write a GTK "draw" handler which calls the handler of the end user 
and passes the end user's data.

Probably I will never do it, but in principle the framework could be 
implemented with other graphics toolkits than GTK and the end user would 
have the same API.

Meanwhile I have found a solution for my problem. It compiles but is not 
tested yet. It doesn't use a marshaller:

--
    package DA_Ret_Callback is new Gtk.Handlers.User_Return_Callback
      (Gtk.Drawing_Area.Gtk_Drawing_Area_Record, Boolean, Handler_DataD);

    function Draw_Handler
      (da: access Gtk.Drawing_Area.Gtk_Drawing_Area_Record'Class;
       pars: Glib.Values.GValues;
       hd: Handler_DataD) return Boolean is
    begin
       hd.can.cc:= Cairo.Get_Context (Glib.Values.Nth(pars, 1));
       hd.Draw (hd.data, hd.gads);
       return True;	-- don't propagate signal further
    end Draw_Handler;

    procedure Connect_Handlers
      (obj: Glib.Object.GObject; hd: Handler_DataD;
       sn_realize, sn_config, sn_draw: Glib.Signal_Name) is
    begin
       ...
       DA_Ret_Callback.Connect
	(Gtk.Drawing_Area.Gtk_Drawing_Area(obj),
	 sn_draw, Draw_Handler'Access, hd);
    end Connect_Handlers;
-- 

hd.Draw is the drawing handler of the end user, and hd.data is the end 
user's data.

-- 
Frank Hrebabetzky		+49 / 6355 / 989 5070


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Where do I get my Cairo context from (in GTK3)?
  2016-04-27 13:15             ` hreba
@ 2016-04-27 13:37               ` Dmitry A. Kazakov
  2016-04-28  7:49                 ` briot.emmanuel
  0 siblings, 1 reply; 13+ messages in thread
From: Dmitry A. Kazakov @ 2016-04-27 13:37 UTC (permalink / raw)


On 27/04/2016 15:15, hreba wrote:

> I am creating a drawing surface, a new layer for isolating the end user
> from GTK. The idea is that the end user gets a constructor for a new
> type "Canvas". He has to specify 3 handlers: the first is called once
> after the canvas appears on the screen, the second is called after each
> resizing, the third one when the canvas needs redrawing. Drawing is done
> by calling a series of of standardized drawing procedures (for lines,
> arcs etc.) The end user needs no knowledge about connecting handlers,
> about cairo contexts or "Stroke" calls. He gets a framework for
> technical drawings with a simple user interface.

I used another approach. Instead of asking the user to draw anything, I 
let him create an object, e.g. a line, which will knows how to draw 
itself. The object is put into a list of objects.

This has the advantage that once done objects can be reused. The user 
need not to care about signals. The objects configuration can be easily 
serialized (e.g. configuration stored and restored). The objects know 
how to resize themselves, e.g. linear objects may become larger, but 
line thickness remain same, some object may wish to keep aspect ratio etc.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Where do I get my Cairo context from (in GTK3)?
  2016-04-27  8:08             ` Dmitry A. Kazakov
@ 2016-04-28  7:48               ` briot.emmanuel
  0 siblings, 0 replies; 13+ messages in thread
From: briot.emmanuel @ 2016-04-28  7:48 UTC (permalink / raw)


> End instances of widgets are never like that. The most frequent case is 
> a container widget handling signals from its children. The first 
> parameter of the handler is never ever used, because the identification 
> of the issuer is the handler procedure itself. The user parameter is the 
> container widget, which is the case for the OP, I suppose.

We are in agreement on that, but to me that's exactly what the "Slot"
parameter (or Object_Connect) is for (and that is exactly what we use
in GPS. I agree 100% that in most cases the widget that emits the event
is irrelevant in the handling of the signal.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Where do I get my Cairo context from (in GTK3)?
  2016-04-27 13:37               ` Dmitry A. Kazakov
@ 2016-04-28  7:49                 ` briot.emmanuel
  0 siblings, 0 replies; 13+ messages in thread
From: briot.emmanuel @ 2016-04-28  7:49 UTC (permalink / raw)


> I used another approach. Instead of asking the user to draw anything, I 
> let him create an object, e.g. a line, which will knows how to draw 
> itself. The object is put into a list of objects.

I use a similar approach indeed, and ended up creating GtkAda.Canvas_View
with exactly that design ( and a model-view-controller approach too). This
might be what the original poster was looking for.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Where do I get my Cairo context from (in GTK3)?
  2016-04-24 20:44 Where do I get my Cairo context from (in GTK3)? hreba
  2016-04-25  7:40 ` Dmitry A. Kazakov
@ 2016-08-05 15:56 ` borisgaertner56
  1 sibling, 0 replies; 13+ messages in thread
From: borisgaertner56 @ 2016-08-05 15:56 UTC (permalink / raw)


Am Sonntag, 24. April 2016 22:44:25 UTC+2 schrieb hreba:
> In GTk2 you got it from a call of Gdk.Cairo.Create.
> 
> In GTK3 it is passed as a parameter of the callback function for the 
> "draw" signal with the C prototype:
.....


To make a long story short, you have to add two lines and to modify one line:

    package DA_Ret_Callback is new Gtk.Handlers.User_Return_Callback
      (Gtk.Widget.Gtk_Widget_Record, Boolean, Handler_DataD);

    -- begin of addition
    package Context_Marshaller is new 
            DA_Ret_Callback.Marshallers.Generic_Marshaller
                  (Cairo.Cairo_context, Cairo.Get_Context);
    .. end of addition 

    function Draw_Handler
      (da: access Gtk.Widget.Gtk_Widget_Record'Class;
       cc: Cairo.Cairo_Context;
       hd: Handler_DataD) return Boolean is
    begin
       ...
    end Draw_Handler;


    procedure Connect_Handlers
      (obj: Glib.Object.GObject; hd: Handler_DataD;
       sn_realize, sn_config, sn_draw: Glib.Signal_Name) is
    begin
       ...
       DA_Ret_Callback.Connect
        (Gtk.Widget.Gtk_Widget(obj), sn_draw,
         Context_Marshaller.To_Marshaller(Draw_Handler'Access),
            --modified, was: DA_Ret_Callback.To_Marshaller( .... )
         hd);
    end Connect_Handlers; 

The point is that, in Gtk-3, a callback function that draws into a widget, is
called with a Cairo context,whereeas in Gtk-2, your created the context yourself.

In GtkAda for Gtk-3, the instantiations of the generic package Return_Callback provide a marshaller that can forward a cairo context to a callback function.

In generic package User_Return_Callback such a marshaller is still missing. Therefore you have to define it yourself. This is done as shown above. The good thing is that you can do it in your application - there is no need to modify and to recompile the GtkAda sources.
--
Boris Gaertner

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2016-08-05 15:56 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-24 20:44 Where do I get my Cairo context from (in GTK3)? hreba
2016-04-25  7:40 ` Dmitry A. Kazakov
2016-04-25 10:03   ` hreba
2016-04-25 11:58     ` Dmitry A. Kazakov
2016-04-26  7:22       ` briot.emmanuel
2016-04-26  7:34         ` hreba
2016-04-27  7:47           ` briot.emmanuel
2016-04-27  8:08             ` Dmitry A. Kazakov
2016-04-28  7:48               ` briot.emmanuel
2016-04-27 13:15             ` hreba
2016-04-27 13:37               ` Dmitry A. Kazakov
2016-04-28  7:49                 ` briot.emmanuel
2016-08-05 15:56 ` borisgaertner56

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