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 <gtk/gtktreemodel.h>
25 #include <gtk/gtktreednd.h>
27 //-----------------------------------------------------------------------------
29 //-----------------------------------------------------------------------------
33 //-----------------------------------------------------------------------------
35 //-----------------------------------------------------------------------------
37 extern void wxapp_install_idle_handler();
40 //-----------------------------------------------------------------------------
42 //-----------------------------------------------------------------------------
44 extern bool g_blockEventsOnDrag
;
46 //-----------------------------------------------------------------------------
47 // define new GTK+ class wxGtkListStore
48 //-----------------------------------------------------------------------------
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))
59 GType
gtk_wx_list_store_get_type (void);
61 typedef struct _GtkWxListStore GtkWxListStore
;
62 typedef struct _GtkWxListStoreClass GtkWxListStoreClass
;
64 struct _GtkWxListStore
70 wxDataViewListModel
*model
;
73 struct _GtkWxListStoreClass
75 GObjectClass parent_class
;
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
,
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
, (GTypeFlags
)0 );
152 g_type_add_interface_static (list_store_type
,
157 return list_store_type
;
160 static GtkWxListStore
*
161 wxgtk_list_store_new()
163 GtkWxListStore
*retval
= (GtkWxListStore
*) g_object_new (GTK_TYPE_WX_LIST_STORE
, NULL
);
168 wxgtk_list_store_class_init (GtkWxListStoreClass
*klass
)
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
;
177 wxgtk_list_store_tree_model_init (GtkTreeModelIface
*iface
)
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
;
194 wxgtk_list_store_init (GtkWxListStore
*list_store
)
196 list_store
->model
= NULL
;
197 list_store
->stamp
= g_random_int();
201 wxgtk_list_store_finalize (GObject
*object
)
203 /* GtkWxListStore *list_store = GTK_WX_LIST_STORE (object); */
205 /* we need to sort out, which class deletes what */
209 (* parent_class
->finalize
) (object
);
214 //-----------------------------------------------------------------------------
215 // implement callbacks from wxGtkListStore class by letting
216 // them call the methods of wxWidgets' wxDataViewListModel
217 //-----------------------------------------------------------------------------
219 static GtkTreeModelFlags
220 wxgtk_list_store_get_flags (GtkTreeModel
*tree_model
)
222 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), (GtkTreeModelFlags
)0 );
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
;
235 wxgtk_list_store_get_n_columns (GtkTreeModel
*tree_model
)
237 GtkWxListStore
*list_store
= (GtkWxListStore
*) tree_model
;
238 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), 0);
240 return list_store
->model
->GetNumberOfCols();
244 wxgtk_list_store_get_column_type (GtkTreeModel
*tree_model
,
247 GtkWxListStore
*list_store
= (GtkWxListStore
*) tree_model
;
248 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), G_TYPE_INVALID
);
250 GType gtype
= G_TYPE_INVALID
;
252 wxString wxtype
= list_store
->model
->GetColType( (size_t) index
);
254 if (wxtype
== wxT("string"))
255 gtype
= G_TYPE_STRING
;
261 wxgtk_list_store_get_iter (GtkTreeModel
*tree_model
,
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
);
269 size_t i
= (size_t)gtk_tree_path_get_indices (path
)[0];
271 if (i
>= list_store
->model
->GetNumberOfRows())
274 iter
->stamp
= list_store
->stamp
;
275 // user_data is just the index
276 iter
->user_data
= (gpointer
) i
;
282 wxgtk_list_store_get_path (GtkTreeModel
*tree_model
,
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
);
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
);
296 wxgtk_list_store_get_value (GtkTreeModel
*tree_model
,
301 GtkWxListStore
*list_store
= (GtkWxListStore
*) tree_model
;
302 g_return_if_fail (GTK_IS_WX_LIST_STORE (tree_model
) );
304 wxDataViewListModel
*model
= list_store
->model
;
305 wxString mtype
= model
->GetColType( (size_t) column
);
306 if (mtype
== wxT("string"))
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()) );
317 GtkTreeDataList
*list
;
318 gint tmp_column
= column
;
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
);
323 list
= G_SLIST (iter
->user_data
)->data
;
325 while (tmp_column
-- > 0 && list
)
329 g_value_init (value
, GTK_LIST_STORE (tree_model
)->column_headers
[column
]);
331 _gtk_tree_data_list_node_to_value (list
,
332 GTK_LIST_STORE (tree_model
)->column_headers
[column
],
339 wxgtk_list_store_iter_next (GtkTreeModel
*tree_model
,
342 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), FALSE
);
343 GtkWxListStore
*list_store
= (GtkWxListStore
*) tree_model
;
345 g_return_val_if_fail (list_store
->stamp
== iter
->stamp
, FALSE
);
347 int n
= (int) iter
->user_data
;
352 if (n
>= (int) list_store
->model
->GetNumberOfRows())
355 iter
->user_data
= (gpointer
) n
++;
361 wxgtk_list_store_iter_children (GtkTreeModel
*tree_model
,
365 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), FALSE
);
366 GtkWxListStore
*list_store
= (GtkWxListStore
*) tree_model
;
368 // this is a list, nodes have no children
372 iter
->stamp
= list_store
->stamp
;
373 iter
->user_data
= (gpointer
) -1;
379 wxgtk_list_store_iter_has_child (GtkTreeModel
*tree_model
,
386 wxgtk_list_store_iter_n_children (GtkTreeModel
*tree_model
,
389 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), -1);
390 GtkWxListStore
*list_store
= (GtkWxListStore
*) tree_model
;
393 return (gint
) list_store
->model
->GetNumberOfRows();
395 g_return_val_if_fail (list_store
->stamp
== iter
->stamp
, -1);
401 wxgtk_list_store_iter_nth_child (GtkTreeModel
*tree_model
,
406 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), FALSE
);
407 GtkWxListStore
*list_store
= (GtkWxListStore
*) tree_model
;
415 if (n
>= (gint
) list_store
->model
->GetNumberOfRows())
418 iter
->stamp
= list_store
->stamp
;
419 iter
->user_data
= (gpointer
) n
;
425 wxgtk_list_store_iter_parent (GtkTreeModel
*tree_model
,
433 //-----------------------------------------------------------------------------
435 //-----------------------------------------------------------------------------
437 IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl
, wxDataViewCtrlBase
)
439 wxDataViewCtrl::~wxDataViewCtrl()
443 void wxDataViewCtrl::Init()
447 bool wxDataViewCtrl::Create(wxWindow
*parent
, wxWindowID id
,
448 const wxPoint
& pos
, const wxSize
& size
,
449 long style
, const wxValidator
& validator
)
454 m_acceptsFocus
= TRUE
;
456 if (!PreCreation( parent
, pos
, size
) ||
457 !CreateBase( parent
, id
, pos
, size
, style
, validator
))
459 wxFAIL_MSG( wxT("wxDataViewCtrl creation failed") );
463 m_widget
= gtk_tree_view_new();
465 m_parent
->DoAddChild( this );
472 bool wxDataViewCtrl::AppendStringColumn( const wxString
&label
)
474 GtkCellRenderer
*renderer
475 = gtk_cell_renderer_text_new();
477 GtkTreeViewColumn
*column
478 = gtk_tree_view_column_new_with_attributes( wxGTK_CONV(label
), renderer
, "text", index
, NULL
);
480 gtk_tree_view_append_column( GTK_TREE_VIEW(m_widget
), column
);
485 bool wxDataViewCtrl::AssociateModel( wxDataViewModel
*model
)
487 if (!wxDataViewCtrlBase::AssociateModel( model
))
490 GtkWxListStore
*wxmodel
= wxgtk_list_store_new();
491 wxmodel
->model
= (wxDataViewListModel
*) model
;
493 gtk_tree_view_set_model( GTK_TREE_VIEW(m_widget
), GTK_TREE_MODEL(wxmodel
) );
499 #endif // wxUSE_DATAVIEWCTRL