File: test_handlers.adb

package info (click to toggle)
libgtkada 2.24.4dfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 12,208 kB
  • ctags: 1,676
  • sloc: ada: 119,686; ansic: 4,719; sh: 3,003; makefile: 690; xml: 338; perl: 70
file content (131 lines) | stat: -rw-r--r-- 4,058 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131

with Ada.Text_IO;  use Ada.Text_IO;
with Glib;         use Glib;
with Gtk.Window;   use Gtk.Window;
with Gtk.Main;     use Gtk.Main;
with Gtk.Enums;    use Gtk.Enums;
with Gtk.Button;   use Gtk.Button;
with Gtk.Box;      use Gtk.Box;
with Gtk.Handlers; use Gtk.Handlers;
with Gtkada.Handlers; use Gtkada.Handlers;
with Gtk.Widget;   use Gtk.Widget;

procedure Test_Handlers is

   type My_Data3 is record
      Button : Gtk_Widget;
      Object : Gtk_Widget;
      Id     : Handler_Id;
   end record;
   type My_Data3_Access is access My_Data3;

   package User_Callback is new Gtk.Handlers.User_Callback
     (Gtk_Widget_Record, Gtk_Widget);
   package User_Callback3 is new Gtk.Handlers.User_Callback
     (Gtk_Widget_Record, My_Data3_Access);

   procedure My_Destroy (Button : access Gtk_Widget_Record'Class) is
   begin
      Put_Line ("My_Destroy");
      Destroy (Button);
   end My_Destroy;

   procedure My_Destroy2
     (Button : access Gtk_Widget_Record'Class;
      Data   : Gtk_Widget) is
   begin
      Put_Line ("My_Destroy2");
      Destroy (Data);
   end My_Destroy2;

   procedure My_Destroy3
     (Button : access Gtk_Widget_Record'Class;
      Data   : My_Data3_Access) is
   begin
      Put_Line ("My_Destroy3");
      Destroy (Data.Button);
      Disconnect (Data.Object, Data.Id);
   end My_Destroy3;

   Win              : Gtk_Window;
   Button1, Button2 : Gtk_Button;
   Vbox, Hbox       : Gtk_Box;
   Id               : Handler_Id;
   Data3            : My_Data3_Access;
begin
   Gtk.Main.Init;

   Gtk_New (Win, Window_Toplevel);

   Gtk_New_Vbox (Vbox);
   Add (Win, Vbox);

   --  Using object_connect.
   --  The callback is automatically destroyed when button2 is destroyed, so
   --  you can press button1 as many times as you want, no problem
   Gtk_New_Hbox (Hbox);
   Pack_Start (Vbox, Hbox);
   Gtk_New (Button1, "button1, object connect");
   Pack_Start (Hbox, Button1);
   Gtk_New (Button2, "button2");
   Pack_Start (Hbox, Button2);

   Widget_Callback.Object_Connect
     (Button1, "clicked",
      Widget_Callback.To_Marshaller (My_Destroy'Unrestricted_Access),
      Button2);

   --  Using user callback.
   --  The callback is not destroyed when Button2 is destroyed. As a result,
   --  the second time you press button1, you get a critical error.
   Gtk_New_Hbox (Hbox);
   Pack_Start (Vbox, Hbox);
   Gtk_New (Button1, "button1, user data (will crash)");
   Pack_Start (Hbox, Button1);
   Gtk_New (Button2, "button2");
   Pack_Start (Hbox, Button2);

   Id := User_Callback.Connect
     (Button1, "clicked",
      User_Callback.To_Marshaller (My_Destroy2'Unrestricted_Access),
      Gtk_Widget (Button2));

   --  Using user callback, with complex protection
   --  Note that memory allocated for Data3 is not freed.
   --  The callback makes sure that the callback is properly unregistered, but
   --  is heavy to put in place
   Gtk_New_Hbox (Hbox);
   Pack_Start (Vbox, Hbox);
   Gtk_New (Button1, "button1, protected user data");
   Pack_Start (Hbox, Button1);
   Gtk_New (Button2, "button2");
   Pack_Start (Hbox, Button2);

   Data3 := new My_Data3'(Object => Gtk_Widget (Button1),
                          Button => Gtk_Widget (Button2),
                          Id     => (Null_Handler_Id, null));
   Id := User_Callback3.Connect
     (Button1, "clicked",
      User_Callback3.To_Marshaller (My_Destroy3'Unrestricted_Access),
      Data3);
   Data3.Id := Id;

   --  Using user callback, simple protection.
   --  This is the same example as 2, but we automatically register the fact
   --  that when button2 is destroyed, the callback should also be destroyed.
   Gtk_New_Hbox (Hbox);
   Pack_Start (Vbox, Hbox);
   Gtk_New (Button1, "button1, watch user data");
   Pack_Start (Hbox, Button1);
   Gtk_New (Button2, "button2");
   Pack_Start (Hbox, Button2);

   Id := User_Callback.Connect
     (Button1, "clicked",
      User_Callback.To_Marshaller (My_Destroy2'Unrestricted_Access),
      Gtk_Widget (Button2));
   Add_Watch (Id, Button2);

   Show_All (Win);
   Gtk.Main.Main;
end Test_Handlers;