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
->GetNumberOfCols();
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_STRING
;
246 wxString wxtype
= list_store
->model
->GetColType( index
);
247 // convert wxtype to GType
255 wxgtk_list_store_get_iter (GtkTreeModel
*tree_model
,
259 GtkWxListStore
*list_store
= (GtkWxListStore
*) tree_model
;
260 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), FALSE
);
261 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
->model
->GetCount())
268 iter
->stamp
= list_store
->stamp
;
269 // user_data is just the index
270 iter
->user_data
= (gpointer
) i
;
276 wxgtk_list_store_get_path (GtkTreeModel
*tree_model
,
279 GtkWxListStore
*list_store
= (GtkListStore
*) tree_model
;
280 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), NULL
);
282 g_return_val_if_fail (iter
->stamp
== GTK_WX_LIST_STORE (tree_model
)->stamp
, NULL
);
284 GtkTreePath
*retval
= gtk_tree_path_new ();
285 // user_data is just the index
286 int i
= (int) item
->user_data
;
287 gtk_tree_path_append_index (retval
, i
);
292 wxgtk_list_store_get_value (GtkTreeModel
*tree_model
,
297 GtkWxListStore
*list_store
= (GtkListStore
*) tree_model
;
298 g_return_if_fail (GTK_IS_WX_LIST_STORE (tree_model
) );
300 g_value_init( value
, G_TYPE_STRING
);
301 g_value_set_string( value
, "Hello" );
304 GtkTreeDataList
*list
;
305 gint tmp_column
= column
;
307 g_return_if_fail (column
< GTK_LIST_STORE (tree_model
)->n_columns
);
308 g_return_if_fail (GTK_LIST_STORE (tree_model
)->stamp
== iter
->stamp
);
310 list
= G_SLIST (iter
->user_data
)->data
;
312 while (tmp_column
-- > 0 && list
)
316 g_value_init (value
, GTK_LIST_STORE (tree_model
)->column_headers
[column
]);
318 _gtk_tree_data_list_node_to_value (list
,
319 GTK_LIST_STORE (tree_model
)->column_headers
[column
],
326 wxgtk_list_store_iter_next (GtkTreeModel
*tree_model
,
329 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), FALSE
);
330 GtkWxListStore
*list_store
= (GtkListStore
*) tree_model
;
332 g_return_val_if_fail (list_store
->stamp
== iter
->stamp
, FALSE
);
334 int n
= (int) iter
->user_data
;
339 if (n
>= (int) list_store
->model
->GetRowCount())
342 iter
->user_data
= (gpointer
) n
++;
348 wxgtk_list_store_iter_children (GtkTreeModel
*tree_model
,
352 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), FALSE
);
353 GtkWxListStore
*list_store
= (GtkListStore
*) tree_model
;
355 // this is a list, nodes have no children
359 iter
->stamp
= list_store
->stamp
;
360 iter
->user_data
= (gpointer
) -1;
366 wxgtk_list_store_iter_has_child (GtkTreeModel
*tree_model
,
373 wxgtk_list_store_iter_n_children (GtkTreeModel
*tree_model
,
376 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), -1);
377 GtkWxListStore
*list_store
= (GtkListStore
*) tree_model
;
380 return (gint
) list_store
->model
->GetRowCount();
382 g_return_val_if_fail (list_store
->stamp
== iter
->stamp
, -1);
388 wxgtk_list_store_iter_nth_child (GtkTreeModel
*tree_model
,
393 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), FALSE
);
394 GtkWxListStore
*list_store
= (GtkListStore
*) tree_model
;
402 if (n
>= (gint
) list_store
->model
->GetRowCount())
405 iter
->stamp
= list_store
->stamp
;
406 iter
->user_data
= (gpointer
) n
;
412 wxgtk_list_store_iter_parent (GtkTreeModel
*tree_model
,
420 //-----------------------------------------------------------------------------
422 //-----------------------------------------------------------------------------
424 IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl
, wxDataViewCtrlBase
)
426 wxDataViewCtrl::~wxDataViewCtrl()
430 void wxDataViewCtrl::Init()
434 bool wxDataViewCtrl::Create(wxWindow
*parent
, wxWindowID id
,
435 const wxPoint
& pos
, const wxSize
& size
,
436 long style
, const wxValidator
& validator
)
441 m_acceptsFocus
= TRUE
;
443 if (!PreCreation( parent
, pos
, size
) ||
444 !CreateBase( parent
, id
, pos
, size
, style
, validator
))
446 wxFAIL_MSG( wxT("wxDataViewCtrl creation failed") );
450 m_widget
= gtk_tree_view_new();
452 m_parent
->DoAddChild( this );
459 bool wxDataViewCtrl::AppendStringColumn( const wxString
&label
)
461 GtkCellRenderer
*renderer
462 = gtk_cell_renderer_text_new();
464 GtkTreeViewColumn
*column
465 = gtk_tree_view_column_new_with_attributes( wxGTK_CONV(label
), renderer
, "text", index
, NULL
);
467 gtk_tree_view_append_column( GTK_TREE_VIEW(m_widget
), column
);
472 bool wxDataViewCtrl::AssociateModel( wxDataViewStore
*model
)
474 if (!wxDataViewCtrlBase::AssociateModel( model
))
477 // Right now we only have the GTK+ port's
478 // list store variant, so cast to that...
480 wxDataViewListStore
*liststore
= (wxDataViewListStore
*) store
;
482 gtk_tree_view_set_model( GTK_TREE_VIEW(m_widget
), GTK_TREE_MODEL(liststore
->GetGtkListStore()) );
488 #endif // wxUSE_DATAVIEWCTRL