Compiles now..
[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 <gtk/gtktreemodel.h>
25 #include <gtk/gtktreednd.h>
26
27 //-----------------------------------------------------------------------------
28 // classes
29 //-----------------------------------------------------------------------------
30
31 class wxDataViewCtrl;
32
33 //-----------------------------------------------------------------------------
34 // idle system
35 //-----------------------------------------------------------------------------
36
37 extern void wxapp_install_idle_handler();
38 extern bool g_isIdle;
39
40 //-----------------------------------------------------------------------------
41 // data
42 //-----------------------------------------------------------------------------
43
44 extern bool g_blockEventsOnDrag;
45
46 //-----------------------------------------------------------------------------
47 // define new GTK+ class wxGtkListStore
48 //-----------------------------------------------------------------------------
49
50 extern "C" {
51
52 #define GTK_TYPE_WX_LIST_STORE (gtk_wx_list_store_get_type ())
53 #define GTK_WX_LIST_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WX_LIST_STORE, GtkWxListStore))
54 #define GTK_WX_LIST_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WX_LIST_STORE, GtkWxListStoreClass))
55 #define GTK_IS_WX_LIST_STORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WX_LIST_STORE))
56 #define GTK_IS_WX_LIST_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WX_LIST_STORE))
57 #define GTK_WX_LIST_STORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WX_LIST_STORE, GtkWxListStoreClass))
58
59 GType gtk_wx_list_store_get_type (void);
60
61 typedef struct _GtkWxListStore GtkWxListStore;
62 typedef struct _GtkWxListStoreClass GtkWxListStoreClass;
63
64 struct _GtkWxListStore
65 {
66 GObject parent;
67
68 /*< private >*/
69 gint stamp;
70 wxDataViewListModel *model;
71 };
72
73 struct _GtkWxListStoreClass
74 {
75 GObjectClass parent_class;
76
77 };
78
79 static GtkWxListStore *wxgtk_list_store_new ();
80 static void wxgtk_list_store_init (GtkWxListStore *list_store);
81 static void wxgtk_list_store_class_init (GtkWxListStoreClass *klass);
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, (GTypeFlags)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 GtkWxListStore *
161 wxgtk_list_store_new()
162 {
163 GtkWxListStore *retval = (GtkWxListStore *) g_object_new (GTK_TYPE_WX_LIST_STORE, NULL);
164 return retval;
165 }
166
167 static void
168 wxgtk_list_store_class_init (GtkWxListStoreClass *klass)
169 {
170 GObjectClass *object_class;
171 parent_class = (GObjectClass*) g_type_class_peek_parent (klass);
172 object_class = (GObjectClass*) klass;
173 object_class->finalize = wxgtk_list_store_finalize;
174 }
175
176 static void
177 wxgtk_list_store_tree_model_init (GtkTreeModelIface *iface)
178 {
179 iface->get_flags = wxgtk_list_store_get_flags;
180 iface->get_n_columns = wxgtk_list_store_get_n_columns;
181 iface->get_column_type = wxgtk_list_store_get_column_type;
182 iface->get_iter = wxgtk_list_store_get_iter;
183 iface->get_path = wxgtk_list_store_get_path;
184 iface->get_value = wxgtk_list_store_get_value;
185 iface->iter_next = wxgtk_list_store_iter_next;
186 iface->iter_children = wxgtk_list_store_iter_children;
187 iface->iter_has_child = wxgtk_list_store_iter_has_child;
188 iface->iter_n_children = wxgtk_list_store_iter_n_children;
189 iface->iter_nth_child = wxgtk_list_store_iter_nth_child;
190 iface->iter_parent = wxgtk_list_store_iter_parent;
191 }
192
193 static void
194 wxgtk_list_store_init (GtkWxListStore *list_store)
195 {
196 list_store->model = NULL;
197 list_store->stamp = g_random_int();
198 }
199
200 static void
201 wxgtk_list_store_finalize (GObject *object)
202 {
203 /* GtkWxListStore *list_store = GTK_WX_LIST_STORE (object); */
204
205 /* we need to sort out, which class deletes what */
206 /* delete model; */
207
208 /* must chain up */
209 (* parent_class->finalize) (object);
210 }
211
212 } // extern "C"
213
214 //-----------------------------------------------------------------------------
215 // implement callbacks from wxGtkListStore class by letting
216 // them call the methods of wxWidgets' wxDataViewListModel
217 //-----------------------------------------------------------------------------
218
219 static GtkTreeModelFlags
220 wxgtk_list_store_get_flags (GtkTreeModel *tree_model)
221 {
222 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), (GtkTreeModelFlags)0 );
223
224 // GTK+ list store uses a linked list for storing the
225 // items and a pointer to a child is used as the member
226 // field of a GtkTreeIter. This means that the iter is
227 // valid in the GtkListStore as long as the child exists.
228 // We use the index of the row and since the index of a
229 // specific row will change if a row above is deleted,
230 // the iter does not persist
231 return /* GTK_TREE_MODEL_ITERS_PERSIST | */ GTK_TREE_MODEL_LIST_ONLY;
232 }
233
234 static gint
235 wxgtk_list_store_get_n_columns (GtkTreeModel *tree_model)
236 {
237 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
238 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), 0);
239
240 return list_store->model->GetNumberOfCols();
241 }
242
243 static GType
244 wxgtk_list_store_get_column_type (GtkTreeModel *tree_model,
245 gint index)
246 {
247 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
248 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), G_TYPE_INVALID);
249
250 GType gtype = G_TYPE_INVALID;
251
252 wxString wxtype = list_store->model->GetColType( (size_t) index );
253
254 if (wxtype == wxT("string"))
255 gtype = G_TYPE_STRING;
256
257 return gtype;
258 }
259
260 static gboolean
261 wxgtk_list_store_get_iter (GtkTreeModel *tree_model,
262 GtkTreeIter *iter,
263 GtkTreePath *path)
264 {
265 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
266 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), FALSE);
267 g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
268
269 size_t i = (size_t)gtk_tree_path_get_indices (path)[0];
270
271 if (i >= list_store->model->GetNumberOfRows())
272 return FALSE;
273
274 iter->stamp = list_store->stamp;
275 // user_data is just the index
276 iter->user_data = (gpointer) i;
277
278 return TRUE;
279 }
280
281 static GtkTreePath *
282 wxgtk_list_store_get_path (GtkTreeModel *tree_model,
283 GtkTreeIter *iter)
284 {
285 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), NULL);
286 g_return_val_if_fail (iter->stamp == GTK_WX_LIST_STORE (tree_model)->stamp, NULL);
287
288 GtkTreePath *retval = gtk_tree_path_new ();
289 // user_data is just the index
290 int i = (int) iter->user_data;
291 gtk_tree_path_append_index (retval, i);
292 return retval;
293 }
294
295 static void
296 wxgtk_list_store_get_value (GtkTreeModel *tree_model,
297 GtkTreeIter *iter,
298 gint column,
299 GValue *value)
300 {
301 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
302 g_return_if_fail (GTK_IS_WX_LIST_STORE (tree_model) );
303
304 wxDataViewListModel *model = list_store->model;
305 wxString mtype = model->GetColType( (size_t) column );
306 if (mtype == wxT("string"))
307 {
308 g_value_init( value, G_TYPE_STRING );
309 wxVariant variant = model->GetValue( (size_t) column, (size_t) iter->user_data );
310 g_value_set_string( value, wxGTK_CONV(variant.GetString()) );
311 }
312 else
313 {
314 }
315
316 #if 0
317 GtkTreeDataList *list;
318 gint tmp_column = column;
319
320 g_return_if_fail (column < GTK_LIST_STORE (tree_model)->n_columns);
321 g_return_if_fail (GTK_LIST_STORE (tree_model)->stamp == iter->stamp);
322
323 list = G_SLIST (iter->user_data)->data;
324
325 while (tmp_column-- > 0 && list)
326 list = list->next;
327
328 if (list == NULL)
329 g_value_init (value, GTK_LIST_STORE (tree_model)->column_headers[column]);
330 else
331 _gtk_tree_data_list_node_to_value (list,
332 GTK_LIST_STORE (tree_model)->column_headers[column],
333 value);
334 #endif
335
336 }
337
338 static gboolean
339 wxgtk_list_store_iter_next (GtkTreeModel *tree_model,
340 GtkTreeIter *iter)
341 {
342 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), FALSE);
343 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
344
345 g_return_val_if_fail (list_store->stamp == iter->stamp, FALSE);
346
347 int n = (int) iter->user_data;
348
349 if (n == -1)
350 return FALSE;
351
352 if (n >= (int) list_store->model->GetNumberOfRows())
353 return FALSE;
354
355 iter->user_data = (gpointer) n++;
356
357 return TRUE;
358 }
359
360 static gboolean
361 wxgtk_list_store_iter_children (GtkTreeModel *tree_model,
362 GtkTreeIter *iter,
363 GtkTreeIter *parent)
364 {
365 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), FALSE);
366 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
367
368 // this is a list, nodes have no children
369 if (parent)
370 return FALSE;
371
372 iter->stamp = list_store->stamp;
373 iter->user_data = (gpointer) -1;
374
375 return TRUE;
376 }
377
378 static gboolean
379 wxgtk_list_store_iter_has_child (GtkTreeModel *tree_model,
380 GtkTreeIter *iter)
381 {
382 return FALSE;
383 }
384
385 static gint
386 wxgtk_list_store_iter_n_children (GtkTreeModel *tree_model,
387 GtkTreeIter *iter)
388 {
389 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), -1);
390 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
391
392 if (iter == NULL)
393 return (gint) list_store->model->GetNumberOfRows();
394
395 g_return_val_if_fail (list_store->stamp == iter->stamp, -1);
396
397 return 0;
398 }
399
400 static gboolean
401 wxgtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
402 GtkTreeIter *iter,
403 GtkTreeIter *parent,
404 gint n)
405 {
406 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), FALSE);
407 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
408
409 if (parent)
410 return FALSE;
411
412 if (n < 0)
413 return FALSE;
414
415 if (n >= (gint) list_store->model->GetNumberOfRows())
416 return FALSE;
417
418 iter->stamp = list_store->stamp;
419 iter->user_data = (gpointer) n;
420
421 return TRUE;
422 }
423
424 static gboolean
425 wxgtk_list_store_iter_parent (GtkTreeModel *tree_model,
426 GtkTreeIter *iter,
427 GtkTreeIter *child)
428 {
429 return FALSE;
430 }
431
432
433 //-----------------------------------------------------------------------------
434 // wxDataViewCtrl
435 //-----------------------------------------------------------------------------
436
437 IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl, wxDataViewCtrlBase)
438
439 wxDataViewCtrl::~wxDataViewCtrl()
440 {
441 }
442
443 void wxDataViewCtrl::Init()
444 {
445 }
446
447 bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id,
448 const wxPoint& pos, const wxSize& size,
449 long style, const wxValidator& validator )
450 {
451 Init();
452
453 m_needParent = TRUE;
454 m_acceptsFocus = TRUE;
455
456 if (!PreCreation( parent, pos, size ) ||
457 !CreateBase( parent, id, pos, size, style, validator ))
458 {
459 wxFAIL_MSG( wxT("wxDataViewCtrl creation failed") );
460 return FALSE;
461 }
462
463 m_widget = gtk_tree_view_new();
464
465 m_parent->DoAddChild( this );
466
467 PostCreation(size);
468
469 return true;
470 }
471
472 bool wxDataViewCtrl::AppendStringColumn( const wxString &label )
473 {
474 GtkCellRenderer *renderer
475 = gtk_cell_renderer_text_new();
476
477 GtkTreeViewColumn *column
478 = gtk_tree_view_column_new_with_attributes( wxGTK_CONV(label), renderer, "text", index, NULL );
479
480 gtk_tree_view_append_column( GTK_TREE_VIEW(m_widget), column );
481
482 return true;
483 }
484
485 bool wxDataViewCtrl::AssociateModel( wxDataViewModel *model )
486 {
487 if (!wxDataViewCtrlBase::AssociateModel( model ))
488 return false;
489
490 GtkWxListStore *wxmodel = wxgtk_list_store_new();
491 wxmodel->model = (wxDataViewListModel*) model;
492
493 gtk_tree_view_set_model( GTK_TREE_VIEW(m_widget), GTK_TREE_MODEL(wxmodel) );
494
495 return true;
496 }
497
498
499 #endif // wxUSE_DATAVIEWCTRL
500