]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/dataview.cpp
Warning fix
[wxWidgets.git] / src / gtk / dataview.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: dataview.cpp
3 // Purpose: wxDataViewCtrl GTK+2 implementation
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 // For compilers that support precompilation, includes "wx.h".
11 #include "wx/wxprec.h"
12
13 #include "wx/defs.h"
14
15 #if wxUSE_DATAVIEWCTRL
16
17 #include "wx/dataview.h"
18 #include "wx/stockitem.h"
19
20 #include "wx/gtk/private.h"
21 #include "wx/gtk/win_gtk.h"
22
23 #include <gobject/gvaluecollector.h>
24 #include "gtktreemodel.h"
25 #include "gtktreedatalist.h"
26 #include "gtktreednd.h"
27
28 //-----------------------------------------------------------------------------
29 // classes
30 //-----------------------------------------------------------------------------
31
32 class wxDataViewCtrl;
33
34 //-----------------------------------------------------------------------------
35 // idle system
36 //-----------------------------------------------------------------------------
37
38 extern void wxapp_install_idle_handler();
39 extern bool g_isIdle;
40
41 //-----------------------------------------------------------------------------
42 // data
43 //-----------------------------------------------------------------------------
44
45 extern bool g_blockEventsOnDrag;
46
47 //-----------------------------------------------------------------------------
48 // define new GTK+ class wxGtkListStore
49 //-----------------------------------------------------------------------------
50
51 extern "C" {
52
53 #define GTK_TYPE_WX_LIST_STORE (gtk_wx_list_store_get_type ())
54 #define GTK_WX_LIST_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WX_LIST_STORE, GtkWxListStore))
55 #define GTK_WX_LIST_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WX_LIST_STORE, GtkWxListStoreClass))
56 #define GTK_IS_WX_LIST_STORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WX_LIST_STORE))
57 #define GTK_IS_WX_LIST_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WX_LIST_STORE))
58 #define GTK_WX_LIST_STORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WX_LIST_STORE, GtkWxListStoreClass))
59
60 GType gtk_wx_list_store_get_type (void);
61
62 typedef struct _GtkWxListStore GtkWxListStore;
63 typedef struct _GtkWxListStoreClass GtkWxListStoreClass;
64
65 struct _GtkWxListStore
66 {
67 GObject parent;
68
69 /*< private >*/
70 gint stamp;
71 wxDataViewListModel *model;
72 };
73
74 struct _GtkWxListStoreClass
75 {
76 GObjectClass parent_class;
77
78 };
79
80 static void wxgtk_list_store_init (GtkWxListStore *list_store);
81 static void wxgtk_list_store_class_init (GtkWxListStoreClass *class);
82 static void wxgtk_list_store_tree_model_init (GtkTreeModelIface *iface);
83 static void wxgtk_list_store_finalize (GObject *object);
84 static GtkTreeModelFlags wxgtk_list_store_get_flags (GtkTreeModel *tree_model);
85 static gint wxgtk_list_store_get_n_columns (GtkTreeModel *tree_model);
86 static GType wxgtk_list_store_get_column_type (GtkTreeModel *tree_model,
87 gint index);
88 static gboolean wxgtk_list_store_get_iter (GtkTreeModel *tree_model,
89 GtkTreeIter *iter,
90 GtkTreePath *path);
91 static GtkTreePath *wxgtk_list_store_get_path (GtkTreeModel *tree_model,
92 GtkTreeIter *iter);
93 static void wxgtk_list_store_get_value (GtkTreeModel *tree_model,
94 GtkTreeIter *iter,
95 gint column,
96 GValue *value);
97 static gboolean wxgtk_list_store_iter_next (GtkTreeModel *tree_model,
98 GtkTreeIter *iter);
99 static gboolean wxgtk_list_store_iter_children (GtkTreeModel *tree_model,
100 GtkTreeIter *iter,
101 GtkTreeIter *parent);
102 static gboolean wxgtk_list_store_iter_has_child (GtkTreeModel *tree_model,
103 GtkTreeIter *iter);
104 static gint wxgtk_list_store_iter_n_children (GtkTreeModel *tree_model,
105 GtkTreeIter *iter);
106 static gboolean wxgtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
107 GtkTreeIter *iter,
108 GtkTreeIter *parent,
109 gint n);
110 static gboolean wxgtk_list_store_iter_parent (GtkTreeModel *tree_model,
111 GtkTreeIter *iter,
112 GtkTreeIter *child);
113
114 static void gtk_list_store_set_n_columns (GtkWxListStore *list_store,
115 gint n_columns);
116 static void gtk_list_store_set_column_type (GtkWxListStore *list_store,
117 gint column,
118 GType type);
119
120 static GObjectClass *parent_class = NULL;
121
122 GType
123 wxgtk_list_store_get_type (void)
124 {
125 static GType list_store_type = 0;
126
127 if (!list_store_type)
128 {
129 static const GTypeInfo list_store_info =
130 {
131 sizeof (GtkWxListStoreClass),
132 NULL, /* base_init */
133 NULL, /* base_finalize */
134 (GClassInitFunc) wxgtk_list_store_class_init,
135 NULL, /* class_finalize */
136 NULL, /* class_data */
137 sizeof (GtkWxListStore),
138 0,
139 (GInstanceInitFunc) wxgtk_list_store_init,
140 };
141
142 static const GInterfaceInfo tree_model_info =
143 {
144 (GInterfaceInitFunc) wxgtk_list_store_tree_model_init,
145 NULL,
146 NULL
147 };
148
149 list_store_type = g_type_register_static (G_TYPE_OBJECT, "GtkWxListStore",
150 &list_store_info, 0);
151
152 g_type_add_interface_static (list_store_type,
153 GTK_TYPE_TREE_MODEL,
154 &tree_model_info);
155 }
156
157 return list_store_type;
158 }
159
160 static void
161 wxgtk_list_store_class_init (GtkWxListStoreClass *class)
162 {
163 GObjectClass *object_class;
164 parent_class = g_type_class_peek_parent (class);
165 object_class = (GObjectClass*) class;
166 object_class->finalize = wxgtk_list_store_finalize;
167 }
168
169 static void
170 wxgtk_list_store_tree_model_init (GtkTreeModelIface *iface)
171 {
172 iface->get_flags = wxgtk_list_store_get_flags;
173 iface->get_n_columns = wxgtk_list_store_get_n_columns;
174 iface->get_column_type = wxgtk_list_store_get_column_type;
175 iface->get_iter = wxgtk_list_store_get_iter;
176 iface->get_path = wxgtk_list_store_get_path;
177 iface->get_value = wxgtk_list_store_get_value;
178 iface->iter_next = wxgtk_list_store_iter_next;
179 iface->iter_children = wxgtk_list_store_iter_children;
180 iface->iter_has_child = wxgtk_list_store_iter_has_child;
181 iface->iter_n_children = wxgtk_list_store_iter_n_children;
182 iface->iter_nth_child = wxgtk_list_store_iter_nth_child;
183 iface->iter_parent = wxgtk_list_store_iter_parent;
184 }
185
186 static void
187 wxgtk_list_store_init (GtkWxListStore *list_store)
188 {
189 list_store->model = NULL;
190 list_store->stamp = g_random_init();
191 }
192
193 static void
194 wxgtk_list_store_finalize (GObject *object)
195 {
196 GtkWxListStore *list_store = GTK_LIST_STORE (object);
197
198 /* we need to sort out, which class deletes what */
199 delete model;
200
201 /* must chain up */
202 (* parent_class->finalize) (object);
203 }
204
205 } // extern "C"
206
207 //-----------------------------------------------------------------------------
208 // implement callbacks from wxGtkListStore class by letting
209 // them call the methods of wxWidgets' wxDataViewListModel
210 //-----------------------------------------------------------------------------
211
212 static GtkTreeModelFlags
213 wxgtk_list_store_get_flags (GtkTreeModel *tree_model)
214 {
215 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), 0);
216
217 // GTK+ list store uses a linked list for storing the
218 // items and a pointer to a child is used as the member
219 // field of a GtkTreeIter. This means that the iter is
220 // valid in the GtkListStore as long as the child exists.
221 // We use the index of the row and since the index of a
222 // specific row will change if a row above is deleted,
223 // the iter does not persist
224 return /* GTK_TREE_MODEL_ITERS_PERSIST | */ GTK_TREE_MODEL_LIST_ONLY;
225 }
226
227 static gint
228 wxgtk_list_store_get_n_columns (GtkTreeModel *tree_model)
229 {
230 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
231 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), 0);
232
233 return list_store->model->GetColumns();
234 }
235
236 static GType
237 wxgtk_list_store_get_column_type (GtkTreeModel *tree_model,
238 gint index)
239 {
240 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
241 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), G_TYPE_INVALID);
242
243 GType gtype = G_TYPE_INVALID;
244 #if 0
245 list_store->model->GetColumnType( index );
246 // convert wxtype to GType
247 gtype = ..
248 #endif
249
250 return gtype;
251 }
252
253 static gboolean
254 wxgtk_list_store_get_iter (GtkTreeModel *tree_model,
255 GtkTreeIter *iter,
256 GtkTreePath *path)
257 {
258 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
259 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), FALSE);
260 g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
261
262 #if 0
263 i = gtk_tree_path_get_indices (path)[0];
264
265 if (i >= list_store->length)
266 return FALSE;
267
268 list = g_slist_nth (G_SLIST (list_store->root), i);
269
270 /* If this fails, list_store->length has gotten mangled. */
271 g_assert (list);
272
273 iter->stamp = list_store->stamp;
274 iter->user_data = list;
275 #endif
276
277 return TRUE;
278 }
279
280 static GtkTreePath *
281 wxgtk_list_store_get_path (GtkTreeModel *tree_model,
282 GtkTreeIter *iter)
283 {
284 GtkWxListStore *list_store = (GtkListStore *) tree_model;
285 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), NULL);
286
287 #if 0
288 g_return_val_if_fail (iter->stamp == GTK_WX_LIST_STORE (tree_model)->stamp, NULL);
289
290 GtkTreePath *retval;
291 GSList *list;
292 gint i = 0;
293
294 if (G_SLIST (iter->user_data) == G_SLIST (GTK_LIST_STORE (tree_model)->tail))
295 {
296 retval = gtk_tree_path_new ();
297 gtk_tree_path_append_index (retval, GTK_LIST_STORE (tree_model)->length - 1);
298 return retval;
299 }
300
301 for (list = G_SLIST (GTK_LIST_STORE (tree_model)->root); list; list = list->next)
302 {
303 if (list == G_SLIST (iter->user_data))
304 break;
305 i++;
306 }
307 if (list == NULL)
308 return NULL;
309
310 retval = gtk_tree_path_new ();
311 gtk_tree_path_append_index (retval, i);
312 return retval;
313 #endif
314
315 return NULL;
316 }
317
318 static void
319 wxgtk_list_store_get_value (GtkTreeModel *tree_model,
320 GtkTreeIter *iter,
321 gint column,
322 GValue *value)
323 {
324 GtkWxListStore *list_store = (GtkListStore *) tree_model;
325 g_return_if_fail (GTK_IS_WX_LIST_STORE (tree_model) );
326
327 #if 0
328 GtkTreeDataList *list;
329 gint tmp_column = column;
330
331 g_return_if_fail (column < GTK_LIST_STORE (tree_model)->n_columns);
332 g_return_if_fail (GTK_LIST_STORE (tree_model)->stamp == iter->stamp);
333
334 list = G_SLIST (iter->user_data)->data;
335
336 while (tmp_column-- > 0 && list)
337 list = list->next;
338
339 if (list == NULL)
340 g_value_init (value, GTK_LIST_STORE (tree_model)->column_headers[column]);
341 else
342 _gtk_tree_data_list_node_to_value (list,
343 GTK_LIST_STORE (tree_model)->column_headers[column],
344 value);
345 #endif
346
347 }
348
349 static gboolean
350 wxgtk_list_store_iter_next (GtkTreeModel *tree_model,
351 GtkTreeIter *iter)
352 {
353 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), FALSE);
354 GtkWxListStore *list_store = (GtkListStore *) tree_model;
355
356 g_return_val_if_fail (list_store->stamp == iter->stamp, FALSE);
357
358 int n = (int) iter->user_data;
359
360 if (n == -1)
361 return FALSE;
362
363 if (n >= (int) list_store->model->GetRowCount())
364 return FALSE;
365
366 iter->user_data = (gpointer) n++;
367
368 return TRUE;
369 }
370
371 static gboolean
372 wxgtk_list_store_iter_children (GtkTreeModel *tree_model,
373 GtkTreeIter *iter,
374 GtkTreeIter *parent)
375 {
376 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), FALSE);
377 GtkWxListStore *list_store = (GtkListStore *) tree_model;
378
379 // this is a list, nodes have no children
380 if (parent)
381 return FALSE;
382
383 iter->stamp = list_store->stamp;
384 iter->user_data = (gpointer) -1;
385
386 return TRUE;
387 }
388
389 static gboolean
390 wxgtk_list_store_iter_has_child (GtkTreeModel *tree_model,
391 GtkTreeIter *iter)
392 {
393 return FALSE;
394 }
395
396 static gint
397 wxgtk_list_store_iter_n_children (GtkTreeModel *tree_model,
398 GtkTreeIter *iter)
399 {
400 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), -1);
401 GtkWxListStore *list_store = (GtkListStore *) tree_model;
402
403 if (iter == NULL)
404 return (gint) list_store->model->GetRowCount();
405
406 g_return_val_if_fail (list_store->stamp == iter->stamp, -1);
407
408 return 0;
409 }
410
411 static gboolean
412 wxgtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
413 GtkTreeIter *iter,
414 GtkTreeIter *parent,
415 gint n)
416 {
417 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), FALSE);
418 GtkWxListStore *list_store = (GtkListStore *) tree_model;
419
420 if (parent)
421 return FALSE;
422
423 if (n < 0)
424 return FALSE;
425
426 if (n >= (gint) list_store->model->GetRowCount())
427 return FALSE;
428
429 iter->stamp = list_store->stamp;
430 iter->user_data = (gpointer) n;
431
432 return TRUE;
433 }
434
435 static gboolean
436 wxgtk_list_store_iter_parent (GtkTreeModel *tree_model,
437 GtkTreeIter *iter,
438 GtkTreeIter *child)
439 {
440 return FALSE;
441 }
442
443
444 //-----------------------------------------------------------------------------
445 // wxDataViewCtrl
446 //-----------------------------------------------------------------------------
447
448 IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl,wxControl)
449
450
451 #endif // wxUSE_DATAVIEWCTRL
452