Add TildaController class
[tilda-gobject.git] / tilda-controller.c
1 #include "tilda.h"
2 #include "tilda-controller.h"
3 #include "tilda-controller-dbus-glue.h"
4 #include "tilda-window.h"
5
6 /**
7  * Register this object with DBus, so it can be interacted with!
8  */
9 static void
10 tilda_controller_dbus_register_object (TildaController *self)
11 {
12         debug_enter  ();
13         debug_assert (TILDA_IS_CONTROLLER(self));
14
15         static const gchar object_path[] = "/net/sourceforge/Tilda";
16
17         dbus_g_connection_register_g_object (dbus_connection, object_path, G_OBJECT(self));
18 }
19
20 /**
21  * Find the next free window number, so it can be used by a TildaWindow
22  */
23 static gint
24 tilda_controller_find_next_free_window_number (TildaController *self)
25 {
26         debug_enter  ();
27         debug_assert (TILDA_IS_CONTROLLER(self));
28
29         gint i, j;
30         gboolean found;
31
32         for (i=0; i<INT_MAX; ++i)
33         {
34                 found = FALSE;
35
36                 for (j=0; j<self->windows->len; ++j)
37                 {
38                         TildaWindow *tw = g_ptr_array_index (self->windows, j);
39
40                         if (tw->number == i)
41                         {
42                                 found = TRUE;
43                                 break;
44                         }
45                 }
46
47                 if (!found)
48                         return i;
49         }
50
51         return 0;
52 }
53
54 gboolean
55 tilda_controller_add_window (TildaController *self)
56 {
57         debug_enter  ();
58         debug_assert (TILDA_IS_CONTROLLER(self));
59
60         TildaWindow *ret;
61         gint number;
62
63         number = tilda_controller_find_next_free_window_number (self);
64         ret = g_object_new (TILDA_TYPE_WINDOW,
65                                                 "number", number,
66                                                 "controller", G_OBJECT(self),
67                                                 NULL);
68
69         g_ptr_array_add (self->windows, ret);
70
71         debug_printf ("Adding window: 0x%x (number %d of %d)\n", ret, ret->number, self->windows->len);
72         return TRUE;
73 }
74
75 gboolean
76 tilda_controller_delete_window (TildaController *self, gint window_number)
77 {
78         debug_enter  ();
79         debug_assert (TILDA_IS_CONTROLLER(self));
80         debug_assert (window_number >= 0);
81
82         gint i;
83         TildaWindow *win;
84
85         for (i=0; i<self->windows->len; ++i)
86         {
87                 win = g_ptr_array_index (self->windows, i);
88
89                 if (win->number == window_number)
90                 {
91                         debug_printf ("Deleting TildaWindow 0x%x (number %d of %d)\n",
92                                                   win, win->number, self->windows->len);
93                         g_ptr_array_remove_index (self->windows, i);
94                         g_object_unref (G_OBJECT(win));
95
96                         if (self->windows->len == 0)
97                         {
98                                 debug_printf ("No windows left, exiting...\n");
99
100                                 /* We get unref'd in main() */
101                                 gtk_main_quit ();
102                         }
103
104                         /* We were able to delete the window */
105                         return TRUE;
106                 }
107         }
108
109         /* There must have been no window to delete */
110         return FALSE;
111 }
112
113 gboolean
114 tilda_controller_quit (TildaController *self, GError **error)
115 {
116         debug_enter  ();
117         debug_assert (TILDA_IS_CONTROLLER(self));
118
119         /* Not much left but to quit, since we get unref'd in main() */
120         gtk_main_quit ();
121
122         return TRUE;
123 }
124
125 /*******************************************************************************
126  * GObject code below... it is doubtful you'll need to make big changes :)
127  ******************************************************************************/
128
129 static GObjectClass *parent_class = NULL;
130
131 static void
132 tilda_controller_instance_init (GTypeInstance *instance,
133                                                                 gpointer       g_class)
134 {
135         debug_enter ();
136
137         TildaController *self = (TildaController *) instance;
138
139         self->dispose_has_run = FALSE;
140         self->windows = g_ptr_array_new ();
141 }
142
143 static void
144 tilda_controller_set_property (GObject      *object,
145                                                            guint         property_id,
146                                                            const GValue *value,
147                                                            GParamSpec   *pspec)
148 {
149         TildaController *self = (TildaController *) self;
150
151         switch (property_id)
152         {
153                 default:
154                         /* We don't have any other properties */
155                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
156                         break;
157         }
158 }
159
160 static void
161 tilda_controller_get_property (GObject    *object,
162                                                            guint       property_id,
163                                                            GValue     *value,
164                                                            GParamSpec *pspec)
165 {
166         TildaController *self = (TildaController *) object;
167
168         switch (property_id)
169         {
170                 default:
171                         /* We don't have any other properties */
172                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
173                         break;
174         }
175 }
176
177 static GObject *
178 tilda_controller_constructor (GType                  type,
179                                                           guint                  n_construct_properties,
180                                                           GObjectConstructParam *construct_properties)
181 {
182         debug_enter ();
183
184         GObject *obj;
185         TildaControllerClass *klass;
186         TildaController *self;
187
188         /* Invoke the parent constructor */
189         klass = TILDA_CONTROLLER_CLASS (g_type_class_peek (TILDA_TYPE_CONTROLLER));
190         obj = parent_class->constructor (type,
191                                                                          n_construct_properties,
192                                                                          construct_properties);
193
194         /* The object is ready, and all constructor-time properties have been set.
195          * Have fun! */
196         self = TILDA_CONTROLLER(obj);
197
198         /* Register this object with DBus */
199         tilda_controller_dbus_register_object (self);
200
201         /* Add a window -- FIXME: the number should be configurable */
202         tilda_controller_add_window (self);
203
204         return obj;
205 }
206
207 static void
208 tilda_controller_dispose (GObject *obj)
209 {
210         debug_enter ();
211
212         TildaController *self = (TildaController *) obj;
213
214         /* We must only run dispose once ... */
215         if (self->dispose_has_run)
216                 return;
217
218         self->dispose_has_run = TRUE;
219
220         /*
221          * In dispose, you are supposed to free all types referenced from this
222          * object which might themselves hold a reference to self. Generally,
223          * the most simple solution is to unref all members on which you own a
224          * reference.
225          */
226         g_ptr_array_foreach (self->windows, g_object_unref, NULL);
227
228         /* Chain up to the parent class */
229         G_OBJECT_CLASS (parent_class)->dispose (obj);
230 }
231
232 static void
233 tilda_controller_finalize (GObject *obj)
234 {
235         debug_enter ();
236
237         TildaController *self = (TildaController *) obj;
238
239         /*
240          * Here, complete the object's destruction.
241          * You might not need to do much more than
242          * g_free() any primitives.
243          */
244
245         /* Chain up to the parent class */
246         G_OBJECT_CLASS (parent_class)->finalize (obj);
247 }
248
249 static void
250 tilda_controller_class_init (gpointer g_class,
251                                            gpointer g_class_data)
252 {
253         debug_enter ();
254
255         GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
256         TildaControllerClass *klass = TILDA_CONTROLLER_CLASS (g_class);
257         GParamSpec *pspec;
258
259         gobject_class->set_property = tilda_controller_set_property;
260         gobject_class->get_property = tilda_controller_get_property;
261         gobject_class->dispose = tilda_controller_dispose;
262         gobject_class->finalize = tilda_controller_finalize;
263         gobject_class->constructor = tilda_controller_constructor;
264
265         parent_class = g_type_class_peek_parent (klass);
266
267         /* Add properties here */
268
269         /* Hook the TildaController type into DBus */
270         dbus_g_object_type_install_info (tilda_controller_get_type(),
271                                                                          &dbus_glib_tilda_controller_object_info);
272 }
273
274 GType tilda_controller_get_type (void)
275 {
276         static GType type = 0;
277
278         if (type == 0)
279         {
280                 static const GTypeInfo info = {
281                         sizeof (TildaControllerClass),
282                         NULL,   /* base_init */
283                         NULL,   /* base_finalize */
284                         tilda_controller_class_init,    /* class_init */
285                         NULL,   /* class_finalize */
286                         NULL,   /* class_data */
287                         sizeof (TildaController),
288                         0,              /* n_preallocs */
289                         tilda_controller_instance_init, /* instance_init */
290                 };
291
292                 type = g_type_register_static (G_TYPE_OBJECT,
293                                                                            "TildaControllerType",
294                                                                            &info,
295                                                                            0);
296         }
297
298         return type;
299 }
300
301 /* vim: set ts=4 sts=4 sw=4 noet tw=112: */