1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxDataViewCtrl GTK+2 implementation
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 // For compilers that support precompilation, includes "wx.h".
11 #include "wx/wxprec.h"
15 #if wxUSE_DATAVIEWCTRL
17 #include "wx/dataview.h"
18 #include "wx/stockitem.h"
20 #include "wx/gtk/private.h"
21 #include "wx/gtk/win_gtk.h"
23 #include <gobject/gvaluecollector.h>
24 #include "gtktreemodel.h"
25 #include "gtktreedatalist.h"
26 #include "gtktreednd.h"
28 //-----------------------------------------------------------------------------
30 //-----------------------------------------------------------------------------
34 //-----------------------------------------------------------------------------
36 //-----------------------------------------------------------------------------
38 extern void wxapp_install_idle_handler();
41 //-----------------------------------------------------------------------------
43 //-----------------------------------------------------------------------------
45 extern bool g_blockEventsOnDrag
;
47 //-----------------------------------------------------------------------------
48 // define new GTK+ class wxGtkListStore
49 //-----------------------------------------------------------------------------
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))
60 GType
gtk_wx_list_store_get_type (void);
62 typedef struct _GtkWxListStore GtkWxListStore
;
63 typedef struct _GtkWxListStoreClass GtkWxListStoreClass
;
65 struct _GtkWxListStore
71 wxDataViewListModel
*model
;
74 struct _GtkWxListStoreClass
76 GObjectClass parent_class
;
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
,
88 static gboolean
wxgtk_list_store_get_iter (GtkTreeModel
*tree_model
,
91 static GtkTreePath
*wxgtk_list_store_get_path (GtkTreeModel
*tree_model
,
93 static void wxgtk_list_store_get_value (GtkTreeModel
*tree_model
,
97 static gboolean
wxgtk_list_store_iter_next (GtkTreeModel
*tree_model
,
99 static gboolean
wxgtk_list_store_iter_children (GtkTreeModel
*tree_model
,
101 GtkTreeIter
*parent
);
102 static gboolean
wxgtk_list_store_iter_has_child (GtkTreeModel
*tree_model
,
104 static gint
wxgtk_list_store_iter_n_children (GtkTreeModel
*tree_model
,
106 static gboolean
wxgtk_list_store_iter_nth_child (GtkTreeModel
*tree_model
,
110 static gboolean
wxgtk_list_store_iter_parent (GtkTreeModel
*tree_model
,
114 static void gtk_list_store_set_n_columns (GtkWxListStore
*list_store
,
116 static void gtk_list_store_set_column_type (GtkWxListStore
*list_store
,
120 static GObjectClass
*parent_class
= NULL
;
123 wxgtk_list_store_get_type (void)
125 static GType list_store_type
= 0;
127 if (!list_store_type
)
129 static const GTypeInfo list_store_info
=
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
),
139 (GInstanceInitFunc
) wxgtk_list_store_init
,
142 static const GInterfaceInfo tree_model_info
=
144 (GInterfaceInitFunc
) wxgtk_list_store_tree_model_init
,
149 list_store_type
= g_type_register_static (G_TYPE_OBJECT
, "GtkWxListStore",
150 &list_store_info
, 0);
152 g_type_add_interface_static (list_store_type
,
157 return list_store_type
;
161 wxgtk_list_store_class_init (GtkWxListStoreClass
*class)
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
;
170 wxgtk_list_store_tree_model_init (GtkTreeModelIface
*iface
)
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
;
187 wxgtk_list_store_init (GtkWxListStore
*list_store
)
189 list_store
->model
= NULL
;
190 list_store
->stamp
= g_random_init();
194 wxgtk_list_store_finalize (GObject
*object
)
196 GtkWxListStore
*list_store
= GTK_LIST_STORE (object
);
198 /* we need to sort out, which class deletes what */
202 (* parent_class
->finalize
) (object
);
207 //-----------------------------------------------------------------------------
208 // implement callbacks from wxGtkListStore class by letting
209 // them call the methods of wxWidgets' wxDataViewListModel
210 //-----------------------------------------------------------------------------
212 static GtkTreeModelFlags
213 wxgtk_list_store_get_flags (GtkTreeModel
*tree_model
)
215 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), 0);
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
;
228 wxgtk_list_store_get_n_columns (GtkTreeModel
*tree_model
)
230 GtkWxListStore
*list_store
= (GtkWxListStore
*) tree_model
;
231 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), 0);
233 return list_store
->model
->GetColumns();
237 wxgtk_list_store_get_column_type (GtkTreeModel
*tree_model
,
240 GtkWxListStore
*list_store
= (GtkWxListStore
*) tree_model
;
241 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), G_TYPE_INVALID
);
243 GType gtype
= G_TYPE_INVALID
;
245 list_store
->model
->GetColumnType( index
);
246 // convert wxtype to GType
254 wxgtk_list_store_get_iter (GtkTreeModel
*tree_model
,
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
);
263 i
= gtk_tree_path_get_indices (path
)[0];
265 if (i
>= list_store
->length
)
268 list
= g_slist_nth (G_SLIST (list_store
->root
), i
);
270 /* If this fails, list_store->length has gotten mangled. */
273 iter
->stamp
= list_store
->stamp
;
274 iter
->user_data
= list
;
281 wxgtk_list_store_get_path (GtkTreeModel
*tree_model
,
284 GtkWxListStore
*list_store
= (GtkListStore
*) tree_model
;
285 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), NULL
);
288 g_return_val_if_fail (iter
->stamp
== GTK_WX_LIST_STORE (tree_model
)->stamp
, NULL
);
294 if (G_SLIST (iter
->user_data
) == G_SLIST (GTK_LIST_STORE (tree_model
)->tail
))
296 retval
= gtk_tree_path_new ();
297 gtk_tree_path_append_index (retval
, GTK_LIST_STORE (tree_model
)->length
- 1);
301 for (list
= G_SLIST (GTK_LIST_STORE (tree_model
)->root
); list
; list
= list
->next
)
303 if (list
== G_SLIST (iter
->user_data
))
310 retval
= gtk_tree_path_new ();
311 gtk_tree_path_append_index (retval
, i
);
319 wxgtk_list_store_get_value (GtkTreeModel
*tree_model
,
324 GtkWxListStore
*list_store
= (GtkListStore
*) tree_model
;
325 g_return_if_fail (GTK_IS_WX_LIST_STORE (tree_model
) );
328 GtkTreeDataList
*list
;
329 gint tmp_column
= column
;
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
);
334 list
= G_SLIST (iter
->user_data
)->data
;
336 while (tmp_column
-- > 0 && list
)
340 g_value_init (value
, GTK_LIST_STORE (tree_model
)->column_headers
[column
]);
342 _gtk_tree_data_list_node_to_value (list
,
343 GTK_LIST_STORE (tree_model
)->column_headers
[column
],
350 wxgtk_list_store_iter_next (GtkTreeModel
*tree_model
,
353 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), FALSE
);
354 GtkWxListStore
*list_store
= (GtkListStore
*) tree_model
;
356 g_return_val_if_fail (list_store
->stamp
== iter
->stamp
, FALSE
);
358 int n
= (int) iter
->user_data
;
363 if (n
>= (int) list_store
->model
->GetRowCount())
366 iter
->user_data
= (gpointer
) n
++;
372 wxgtk_list_store_iter_children (GtkTreeModel
*tree_model
,
376 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), FALSE
);
377 GtkWxListStore
*list_store
= (GtkListStore
*) tree_model
;
379 // this is a list, nodes have no children
383 iter
->stamp
= list_store
->stamp
;
384 iter
->user_data
= (gpointer
) -1;
390 wxgtk_list_store_iter_has_child (GtkTreeModel
*tree_model
,
397 wxgtk_list_store_iter_n_children (GtkTreeModel
*tree_model
,
400 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), -1);
401 GtkWxListStore
*list_store
= (GtkListStore
*) tree_model
;
404 return (gint
) list_store
->model
->GetRowCount();
406 g_return_val_if_fail (list_store
->stamp
== iter
->stamp
, -1);
412 wxgtk_list_store_iter_nth_child (GtkTreeModel
*tree_model
,
417 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), FALSE
);
418 GtkWxListStore
*list_store
= (GtkListStore
*) tree_model
;
426 if (n
>= (gint
) list_store
->model
->GetRowCount())
429 iter
->stamp
= list_store
->stamp
;
430 iter
->user_data
= (gpointer
) n
;
436 wxgtk_list_store_iter_parent (GtkTreeModel
*tree_model
,
444 //-----------------------------------------------------------------------------
446 //-----------------------------------------------------------------------------
448 IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl
,wxControl
)
451 #endif // wxUSE_DATAVIEWCTRL