]>
Commit | Line | Data |
---|---|---|
790b137e RR |
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> | |
1557c77b RR |
24 | #include <gtk/gtktreemodel.h> |
25 | #include <gtk/gtktreednd.h> | |
790b137e RR |
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 | ||
1557c77b | 79 | static GtkWxListStore *wxgtk_list_store_new (); |
790b137e | 80 | static void wxgtk_list_store_init (GtkWxListStore *list_store); |
1557c77b | 81 | static void wxgtk_list_store_class_init (GtkWxListStoreClass *klass); |
790b137e RR |
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 | ||
790b137e RR |
114 | static GObjectClass *parent_class = NULL; |
115 | ||
116 | GType | |
111f83c4 | 117 | gtk_wx_list_store_get_type (void) |
790b137e RR |
118 | { |
119 | static GType list_store_type = 0; | |
120 | ||
121 | if (!list_store_type) | |
122 | { | |
123 | static const GTypeInfo list_store_info = | |
124 | { | |
125 | sizeof (GtkWxListStoreClass), | |
126 | NULL, /* base_init */ | |
127 | NULL, /* base_finalize */ | |
128 | (GClassInitFunc) wxgtk_list_store_class_init, | |
129 | NULL, /* class_finalize */ | |
130 | NULL, /* class_data */ | |
131 | sizeof (GtkWxListStore), | |
132 | 0, | |
133 | (GInstanceInitFunc) wxgtk_list_store_init, | |
134 | }; | |
135 | ||
136 | static const GInterfaceInfo tree_model_info = | |
137 | { | |
138 | (GInterfaceInitFunc) wxgtk_list_store_tree_model_init, | |
139 | NULL, | |
140 | NULL | |
141 | }; | |
142 | ||
143 | list_store_type = g_type_register_static (G_TYPE_OBJECT, "GtkWxListStore", | |
1557c77b | 144 | &list_store_info, (GTypeFlags)0 ); |
790b137e RR |
145 | |
146 | g_type_add_interface_static (list_store_type, | |
147 | GTK_TYPE_TREE_MODEL, | |
148 | &tree_model_info); | |
149 | } | |
150 | ||
151 | return list_store_type; | |
152 | } | |
153 | ||
1557c77b RR |
154 | static GtkWxListStore * |
155 | wxgtk_list_store_new() | |
156 | { | |
157 | GtkWxListStore *retval = (GtkWxListStore *) g_object_new (GTK_TYPE_WX_LIST_STORE, NULL); | |
158 | return retval; | |
159 | } | |
160 | ||
790b137e | 161 | static void |
1557c77b | 162 | wxgtk_list_store_class_init (GtkWxListStoreClass *klass) |
790b137e RR |
163 | { |
164 | GObjectClass *object_class; | |
1557c77b RR |
165 | parent_class = (GObjectClass*) g_type_class_peek_parent (klass); |
166 | object_class = (GObjectClass*) klass; | |
790b137e RR |
167 | object_class->finalize = wxgtk_list_store_finalize; |
168 | } | |
169 | ||
170 | static void | |
171 | wxgtk_list_store_tree_model_init (GtkTreeModelIface *iface) | |
172 | { | |
173 | iface->get_flags = wxgtk_list_store_get_flags; | |
174 | iface->get_n_columns = wxgtk_list_store_get_n_columns; | |
175 | iface->get_column_type = wxgtk_list_store_get_column_type; | |
176 | iface->get_iter = wxgtk_list_store_get_iter; | |
177 | iface->get_path = wxgtk_list_store_get_path; | |
178 | iface->get_value = wxgtk_list_store_get_value; | |
179 | iface->iter_next = wxgtk_list_store_iter_next; | |
180 | iface->iter_children = wxgtk_list_store_iter_children; | |
181 | iface->iter_has_child = wxgtk_list_store_iter_has_child; | |
182 | iface->iter_n_children = wxgtk_list_store_iter_n_children; | |
183 | iface->iter_nth_child = wxgtk_list_store_iter_nth_child; | |
184 | iface->iter_parent = wxgtk_list_store_iter_parent; | |
185 | } | |
186 | ||
187 | static void | |
188 | wxgtk_list_store_init (GtkWxListStore *list_store) | |
189 | { | |
190 | list_store->model = NULL; | |
1557c77b | 191 | list_store->stamp = g_random_int(); |
790b137e RR |
192 | } |
193 | ||
194 | static void | |
195 | wxgtk_list_store_finalize (GObject *object) | |
196 | { | |
1557c77b | 197 | /* GtkWxListStore *list_store = GTK_WX_LIST_STORE (object); */ |
790b137e RR |
198 | |
199 | /* we need to sort out, which class deletes what */ | |
111f83c4 | 200 | /* delete list_store->model; */ |
790b137e RR |
201 | |
202 | /* must chain up */ | |
203 | (* parent_class->finalize) (object); | |
204 | } | |
205 | ||
206 | } // extern "C" | |
207 | ||
208 | //----------------------------------------------------------------------------- | |
209 | // implement callbacks from wxGtkListStore class by letting | |
210 | // them call the methods of wxWidgets' wxDataViewListModel | |
211 | //----------------------------------------------------------------------------- | |
212 | ||
213 | static GtkTreeModelFlags | |
214 | wxgtk_list_store_get_flags (GtkTreeModel *tree_model) | |
215 | { | |
1557c77b | 216 | g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), (GtkTreeModelFlags)0 ); |
790b137e | 217 | |
67cbdfc1 RR |
218 | // GTK+ list store uses a linked list for storing the |
219 | // items and a pointer to a child is used as the member | |
220 | // field of a GtkTreeIter. This means that the iter is | |
221 | // valid in the GtkListStore as long as the child exists. | |
222 | // We use the index of the row and since the index of a | |
223 | // specific row will change if a row above is deleted, | |
224 | // the iter does not persist | |
225 | return /* GTK_TREE_MODEL_ITERS_PERSIST | */ GTK_TREE_MODEL_LIST_ONLY; | |
790b137e RR |
226 | } |
227 | ||
228 | static gint | |
229 | wxgtk_list_store_get_n_columns (GtkTreeModel *tree_model) | |
230 | { | |
231 | GtkWxListStore *list_store = (GtkWxListStore *) tree_model; | |
232 | g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), 0); | |
233 | ||
239eaa41 | 234 | return list_store->model->GetNumberOfCols(); |
790b137e RR |
235 | } |
236 | ||
237 | static GType | |
238 | wxgtk_list_store_get_column_type (GtkTreeModel *tree_model, | |
239 | gint index) | |
240 | { | |
241 | GtkWxListStore *list_store = (GtkWxListStore *) tree_model; | |
242 | g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), G_TYPE_INVALID); | |
243 | ||
1557c77b | 244 | GType gtype = G_TYPE_INVALID; |
239eaa41 | 245 | |
1557c77b RR |
246 | wxString wxtype = list_store->model->GetColType( (size_t) index ); |
247 | ||
248 | if (wxtype == wxT("string")) | |
249 | gtype = G_TYPE_STRING; | |
790b137e RR |
250 | |
251 | return gtype; | |
252 | } | |
253 | ||
254 | static gboolean | |
255 | wxgtk_list_store_get_iter (GtkTreeModel *tree_model, | |
256 | GtkTreeIter *iter, | |
257 | GtkTreePath *path) | |
258 | { | |
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); | |
262 | ||
1557c77b | 263 | size_t i = (size_t)gtk_tree_path_get_indices (path)[0]; |
790b137e | 264 | |
1557c77b | 265 | if (i >= list_store->model->GetNumberOfRows()) |
239eaa41 | 266 | return FALSE; |
790b137e | 267 | |
239eaa41 RR |
268 | iter->stamp = list_store->stamp; |
269 | // user_data is just the index | |
270 | iter->user_data = (gpointer) i; | |
790b137e RR |
271 | |
272 | return TRUE; | |
273 | } | |
274 | ||
275 | static GtkTreePath * | |
276 | wxgtk_list_store_get_path (GtkTreeModel *tree_model, | |
277 | GtkTreeIter *iter) | |
278 | { | |
790b137e | 279 | g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), NULL); |
239eaa41 | 280 | g_return_val_if_fail (iter->stamp == GTK_WX_LIST_STORE (tree_model)->stamp, NULL); |
790b137e | 281 | |
239eaa41 RR |
282 | GtkTreePath *retval = gtk_tree_path_new (); |
283 | // user_data is just the index | |
1557c77b | 284 | int i = (int) iter->user_data; |
239eaa41 RR |
285 | gtk_tree_path_append_index (retval, i); |
286 | return retval; | |
790b137e RR |
287 | } |
288 | ||
289 | static void | |
290 | wxgtk_list_store_get_value (GtkTreeModel *tree_model, | |
291 | GtkTreeIter *iter, | |
292 | gint column, | |
293 | GValue *value) | |
294 | { | |
1557c77b | 295 | GtkWxListStore *list_store = (GtkWxListStore *) tree_model; |
790b137e | 296 | g_return_if_fail (GTK_IS_WX_LIST_STORE (tree_model) ); |
239eaa41 | 297 | |
1557c77b RR |
298 | wxDataViewListModel *model = list_store->model; |
299 | wxString mtype = model->GetColType( (size_t) column ); | |
300 | if (mtype == wxT("string")) | |
301 | { | |
302 | g_value_init( value, G_TYPE_STRING ); | |
303 | wxVariant variant = model->GetValue( (size_t) column, (size_t) iter->user_data ); | |
304 | g_value_set_string( value, wxGTK_CONV(variant.GetString()) ); | |
305 | } | |
306 | else | |
307 | { | |
308 | } | |
790b137e RR |
309 | |
310 | #if 0 | |
311 | GtkTreeDataList *list; | |
312 | gint tmp_column = column; | |
313 | ||
314 | g_return_if_fail (column < GTK_LIST_STORE (tree_model)->n_columns); | |
315 | g_return_if_fail (GTK_LIST_STORE (tree_model)->stamp == iter->stamp); | |
316 | ||
317 | list = G_SLIST (iter->user_data)->data; | |
318 | ||
319 | while (tmp_column-- > 0 && list) | |
320 | list = list->next; | |
321 | ||
322 | if (list == NULL) | |
323 | g_value_init (value, GTK_LIST_STORE (tree_model)->column_headers[column]); | |
324 | else | |
325 | _gtk_tree_data_list_node_to_value (list, | |
326 | GTK_LIST_STORE (tree_model)->column_headers[column], | |
327 | value); | |
328 | #endif | |
329 | ||
330 | } | |
331 | ||
332 | static gboolean | |
333 | wxgtk_list_store_iter_next (GtkTreeModel *tree_model, | |
334 | GtkTreeIter *iter) | |
335 | { | |
790b137e | 336 | g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), FALSE); |
1557c77b | 337 | GtkWxListStore *list_store = (GtkWxListStore *) tree_model; |
790b137e | 338 | |
67cbdfc1 | 339 | g_return_val_if_fail (list_store->stamp == iter->stamp, FALSE); |
790b137e | 340 | |
67cbdfc1 RR |
341 | int n = (int) iter->user_data; |
342 | ||
343 | if (n == -1) | |
344 | return FALSE; | |
345 | ||
1557c77b | 346 | if (n >= (int) list_store->model->GetNumberOfRows()) |
67cbdfc1 RR |
347 | return FALSE; |
348 | ||
111f83c4 | 349 | iter->user_data = (gpointer) ++n; |
790b137e | 350 | |
67cbdfc1 | 351 | return TRUE; |
790b137e RR |
352 | } |
353 | ||
354 | static gboolean | |
355 | wxgtk_list_store_iter_children (GtkTreeModel *tree_model, | |
356 | GtkTreeIter *iter, | |
357 | GtkTreeIter *parent) | |
358 | { | |
67cbdfc1 | 359 | g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), FALSE); |
1557c77b | 360 | GtkWxListStore *list_store = (GtkWxListStore *) tree_model; |
67cbdfc1 RR |
361 | |
362 | // this is a list, nodes have no children | |
790b137e RR |
363 | if (parent) |
364 | return FALSE; | |
365 | ||
67cbdfc1 RR |
366 | iter->stamp = list_store->stamp; |
367 | iter->user_data = (gpointer) -1; | |
368 | ||
369 | return TRUE; | |
790b137e RR |
370 | } |
371 | ||
372 | static gboolean | |
373 | wxgtk_list_store_iter_has_child (GtkTreeModel *tree_model, | |
374 | GtkTreeIter *iter) | |
375 | { | |
376 | return FALSE; | |
377 | } | |
378 | ||
379 | static gint | |
380 | wxgtk_list_store_iter_n_children (GtkTreeModel *tree_model, | |
381 | GtkTreeIter *iter) | |
382 | { | |
383 | g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), -1); | |
1557c77b | 384 | GtkWxListStore *list_store = (GtkWxListStore *) tree_model; |
790b137e RR |
385 | |
386 | if (iter == NULL) | |
1557c77b | 387 | return (gint) list_store->model->GetNumberOfRows(); |
790b137e | 388 | |
67cbdfc1 | 389 | g_return_val_if_fail (list_store->stamp == iter->stamp, -1); |
790b137e RR |
390 | |
391 | return 0; | |
392 | } | |
393 | ||
394 | static gboolean | |
395 | wxgtk_list_store_iter_nth_child (GtkTreeModel *tree_model, | |
396 | GtkTreeIter *iter, | |
397 | GtkTreeIter *parent, | |
398 | gint n) | |
399 | { | |
67cbdfc1 | 400 | g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), FALSE); |
1557c77b | 401 | GtkWxListStore *list_store = (GtkWxListStore *) tree_model; |
67cbdfc1 RR |
402 | |
403 | if (parent) | |
404 | return FALSE; | |
790b137e | 405 | |
67cbdfc1 RR |
406 | if (n < 0) |
407 | return FALSE; | |
408 | ||
1557c77b | 409 | if (n >= (gint) list_store->model->GetNumberOfRows()) |
67cbdfc1 | 410 | return FALSE; |
790b137e | 411 | |
67cbdfc1 RR |
412 | iter->stamp = list_store->stamp; |
413 | iter->user_data = (gpointer) n; | |
414 | ||
415 | return TRUE; | |
790b137e RR |
416 | } |
417 | ||
418 | static gboolean | |
419 | wxgtk_list_store_iter_parent (GtkTreeModel *tree_model, | |
420 | GtkTreeIter *iter, | |
421 | GtkTreeIter *child) | |
422 | { | |
423 | return FALSE; | |
424 | } | |
425 | ||
6e2e590f RR |
426 | // --------------------------------------------------------- |
427 | // wxGtkDataViewListModelNotifier | |
428 | // --------------------------------------------------------- | |
429 | ||
430 | class wxGtkDataViewListModelNotifier: public wxDataViewListModelNotifier | |
431 | { | |
432 | public: | |
433 | wxGtkDataViewListModelNotifier( GtkWxListStore* gtk_store, wxDataViewListModel *wx_model ); | |
434 | ||
435 | virtual bool RowAppended(); | |
436 | virtual bool RowPrepended(); | |
437 | virtual bool RowInserted( size_t before ); | |
438 | virtual bool RowDeleted( size_t row ); | |
439 | virtual bool RowChanged( size_t row ); | |
a7f61f76 | 440 | virtual bool ValueChanged( size_t col, size_t row ); |
6e2e590f RR |
441 | virtual bool Cleared(); |
442 | ||
443 | GtkWxListStore *m_gtk_store; | |
444 | wxDataViewListModel *m_wx_model; | |
445 | }; | |
446 | ||
447 | // --------------------------------------------------------- | |
448 | // wxGtkDataViewListModelNotifier | |
449 | // --------------------------------------------------------- | |
450 | ||
451 | wxGtkDataViewListModelNotifier::wxGtkDataViewListModelNotifier( | |
452 | GtkWxListStore* gtk_store, wxDataViewListModel *wx_model ) | |
453 | { | |
454 | m_gtk_store = gtk_store; | |
455 | m_wx_model = wx_model; | |
456 | } | |
457 | ||
458 | bool wxGtkDataViewListModelNotifier::RowAppended() | |
459 | { | |
460 | size_t pos = m_wx_model->GetNumberOfRows()-1; | |
461 | ||
462 | GtkTreeIter iter; | |
463 | iter.stamp = m_gtk_store->stamp; | |
464 | iter.user_data = (gpointer) pos; | |
465 | ||
466 | GtkTreePath *path = gtk_tree_path_new (); | |
467 | gtk_tree_path_append_index (path, (gint) pos); | |
468 | gtk_tree_model_row_inserted (GTK_TREE_MODEL (m_gtk_store), path, &iter); | |
469 | gtk_tree_path_free (path); | |
470 | ||
471 | return true; | |
472 | } | |
473 | ||
474 | bool wxGtkDataViewListModelNotifier::RowPrepended() | |
475 | { | |
605c2c4a RR |
476 | GtkTreeIter iter; |
477 | iter.stamp = m_gtk_store->stamp; | |
478 | iter.user_data = (gpointer) 0; | |
479 | ||
480 | GtkTreePath *path = gtk_tree_path_new (); | |
481 | gtk_tree_path_append_index (path, (gint) 0); | |
482 | gtk_tree_model_row_inserted (GTK_TREE_MODEL (m_gtk_store), path, &iter); | |
483 | gtk_tree_path_free (path); | |
484 | ||
485 | return true; | |
6e2e590f RR |
486 | } |
487 | ||
488 | bool wxGtkDataViewListModelNotifier::RowInserted( size_t before ) | |
489 | { | |
490 | return false; | |
491 | } | |
492 | ||
493 | bool wxGtkDataViewListModelNotifier::RowDeleted( size_t row ) | |
494 | { | |
495 | return false; | |
496 | } | |
497 | ||
498 | bool wxGtkDataViewListModelNotifier::RowChanged( size_t row ) | |
499 | { | |
a7f61f76 RR |
500 | GtkTreeIter iter; |
501 | iter.stamp = m_gtk_store->stamp; | |
502 | iter.user_data = (gpointer) row; | |
503 | GtkTreePath *path = gtk_tree_model_get_path (GTK_TREE_MODEL (m_gtk_store), &iter); | |
504 | gtk_tree_model_row_changed (GTK_TREE_MODEL (m_gtk_store), path, &iter); | |
505 | gtk_tree_path_free (path); | |
506 | ||
507 | return true; | |
6e2e590f RR |
508 | } |
509 | ||
a7f61f76 | 510 | bool wxGtkDataViewListModelNotifier::ValueChanged( size_t col, size_t row ) |
6e2e590f | 511 | { |
a7f61f76 | 512 | return RowChanged( row ); |
6e2e590f RR |
513 | } |
514 | ||
515 | bool wxGtkDataViewListModelNotifier::Cleared() | |
516 | { | |
517 | return false; | |
518 | } | |
519 | ||
6842a71a RR |
520 | // --------------------------------------------------------- |
521 | // wxDataViewCell | |
522 | // --------------------------------------------------------- | |
523 | ||
524 | IMPLEMENT_ABSTRACT_CLASS(wxDataViewCell, wxDataViewCellBase) | |
525 | ||
526 | wxDataViewCell::wxDataViewCell( const wxString &varianttype, wxDataViewCellMode mode ) : | |
527 | wxDataViewCellBase( varianttype, mode ) | |
528 | { | |
529 | m_renderer = NULL; | |
530 | } | |
531 | ||
532 | // --------------------------------------------------------- | |
533 | // wxDataViewTextCell | |
534 | // --------------------------------------------------------- | |
535 | ||
a7f61f76 RR |
536 | extern "C" { |
537 | static void wxGtkTextRendererEditedCallback( GtkCellRendererText *renderer, | |
538 | gchar *arg1, gchar *arg2, gpointer user_data ); | |
539 | } | |
540 | ||
541 | static void wxGtkTextRendererEditedCallback( GtkCellRendererText *renderer, | |
542 | gchar *arg1, gchar *arg2, gpointer user_data ) | |
543 | { | |
544 | wxDataViewTextCell *cell = (wxDataViewTextCell*) user_data; | |
545 | ||
546 | wxString tmp = wxGTK_CONV_BACK( arg2 ); | |
547 | wxVariant value = tmp; | |
548 | if (!cell->Validate( value )) | |
549 | return; | |
550 | ||
551 | wxDataViewListModel *model = cell->GetOwner()->GetOwner()->GetModel(); | |
552 | ||
553 | GtkTreePath *path = gtk_tree_path_new_from_string( arg1 ); | |
554 | size_t model_row = (size_t)gtk_tree_path_get_indices (path)[0]; | |
555 | gtk_tree_path_free( path ); | |
556 | ||
557 | size_t model_col = cell->GetOwner()->GetModelColumn(); | |
558 | ||
559 | model->SetValue( value, model_col, model_row ); | |
560 | model->ValueChanged( model_col, model_row ); | |
561 | } | |
562 | ||
6842a71a RR |
563 | IMPLEMENT_ABSTRACT_CLASS(wxDataViewTextCell, wxDataViewCell) |
564 | ||
565 | wxDataViewTextCell::wxDataViewTextCell( const wxString &varianttype, wxDataViewCellMode mode ) : | |
566 | wxDataViewCell( varianttype, mode ) | |
567 | { | |
568 | m_renderer = (void*) gtk_cell_renderer_text_new(); | |
a7f61f76 RR |
569 | |
570 | if (m_mode & wxDATAVIEW_CELL_EDITABLE) | |
571 | { | |
572 | GValue gvalue = { 0, }; | |
573 | g_value_init( &gvalue, G_TYPE_BOOLEAN ); | |
574 | g_value_set_boolean( &gvalue, true ); | |
575 | g_object_set_property( G_OBJECT(m_renderer), "editable", &gvalue ); | |
576 | g_value_unset( &gvalue ); | |
577 | ||
578 | g_signal_connect_after( m_renderer, "edited", G_CALLBACK(wxGtkTextRendererEditedCallback), this ); | |
579 | } | |
6842a71a | 580 | } |
790b137e | 581 | |
7b4fde82 RR |
582 | bool wxDataViewTextCell::SetValue( const wxVariant &value ) |
583 | { | |
584 | wxString tmp = value; | |
585 | ||
586 | GValue gvalue = { 0, }; | |
587 | g_value_init( &gvalue, G_TYPE_STRING ); | |
588 | g_value_set_string( &gvalue, wxGTK_CONV( tmp ) ); | |
589 | g_object_set_property( G_OBJECT(m_renderer), "text", &gvalue ); | |
590 | g_value_unset( &gvalue ); | |
591 | ||
592 | return true; | |
593 | } | |
594 | ||
a7f61f76 RR |
595 | bool wxDataViewTextCell::GetValue( wxVariant &value ) |
596 | { | |
597 | GValue gvalue = { 0, }; | |
598 | g_value_init( &gvalue, G_TYPE_STRING ); | |
599 | g_object_get_property( G_OBJECT(m_renderer), "text", &gvalue ); | |
600 | wxString tmp = wxGTK_CONV_BACK( g_value_get_string( &gvalue ) ); | |
601 | g_value_unset( &gvalue ); | |
602 | ||
603 | value = tmp; | |
604 | ||
605 | return true; | |
606 | } | |
607 | ||
fa28826d | 608 | // --------------------------------------------------------- |
605c2c4a | 609 | // wxDataViewToggleCell |
fa28826d RR |
610 | // --------------------------------------------------------- |
611 | ||
605c2c4a RR |
612 | extern "C" { |
613 | static void wxGtkToggleRendererToggledCallback( GtkCellRendererToggle *renderer, | |
614 | gchar *path, gpointer user_data ); | |
615 | } | |
616 | ||
617 | static void wxGtkToggleRendererToggledCallback( GtkCellRendererToggle *renderer, | |
618 | gchar *path, gpointer user_data ) | |
619 | { | |
620 | wxDataViewToggleCell *cell = (wxDataViewToggleCell*) user_data; | |
621 | ||
622 | // get old value | |
623 | GValue gvalue = { 0, }; | |
624 | g_value_init( &gvalue, G_TYPE_BOOLEAN ); | |
625 | g_object_get_property( G_OBJECT(renderer), "active", &gvalue ); | |
626 | bool tmp = g_value_get_boolean( &gvalue ); | |
627 | g_value_unset( &gvalue ); | |
628 | // invert it | |
629 | tmp = !tmp; | |
630 | ||
631 | wxVariant value = tmp; | |
632 | if (!cell->Validate( value )) | |
633 | return; | |
634 | ||
635 | wxDataViewListModel *model = cell->GetOwner()->GetOwner()->GetModel(); | |
636 | ||
637 | GtkTreePath *gtk_path = gtk_tree_path_new_from_string( path ); | |
638 | size_t model_row = (size_t)gtk_tree_path_get_indices (gtk_path)[0]; | |
639 | gtk_tree_path_free( gtk_path ); | |
640 | ||
641 | size_t model_col = cell->GetOwner()->GetModelColumn(); | |
642 | ||
643 | model->SetValue( value, model_col, model_row ); | |
644 | model->ValueChanged( model_col, model_row ); | |
645 | } | |
646 | ||
647 | IMPLEMENT_ABSTRACT_CLASS(wxDataViewToggleCell, wxDataViewCell) | |
648 | ||
649 | wxDataViewToggleCell::wxDataViewToggleCell( const wxString &varianttype, | |
650 | wxDataViewCellMode mode ) : | |
651 | wxDataViewCell( varianttype, mode ) | |
652 | { | |
653 | m_renderer = (void*) gtk_cell_renderer_toggle_new(); | |
654 | ||
655 | if (m_mode & wxDATAVIEW_CELL_EDITABLE) | |
656 | { | |
657 | GValue gvalue = { 0, }; | |
658 | g_value_init( &gvalue, G_TYPE_BOOLEAN ); | |
659 | g_value_set_boolean( &gvalue, true ); | |
660 | g_object_set_property( G_OBJECT(m_renderer), "activatable", &gvalue ); | |
661 | g_value_unset( &gvalue ); | |
662 | ||
663 | g_signal_connect_after( m_renderer, "toggled", G_CALLBACK(wxGtkToggleRendererToggledCallback), this ); | |
664 | } | |
665 | } | |
666 | ||
667 | bool wxDataViewToggleCell::SetValue( const wxVariant &value ) | |
668 | { | |
669 | bool tmp = value; | |
670 | ||
671 | GValue gvalue = { 0, }; | |
672 | g_value_init( &gvalue, G_TYPE_BOOLEAN ); | |
673 | g_value_set_boolean( &gvalue, tmp ); | |
674 | g_object_set_property( G_OBJECT(m_renderer), "active", &gvalue ); | |
675 | g_value_unset( &gvalue ); | |
676 | ||
677 | return true; | |
678 | } | |
679 | ||
680 | bool wxDataViewToggleCell::GetValue( wxVariant &value ) | |
681 | { | |
682 | GValue gvalue = { 0, }; | |
683 | g_value_init( &gvalue, G_TYPE_BOOLEAN ); | |
684 | g_object_get_property( G_OBJECT(m_renderer), "active", &gvalue ); | |
685 | bool tmp = g_value_get_boolean( &gvalue ); | |
686 | g_value_unset( &gvalue ); | |
687 | ||
688 | value = tmp; | |
689 | ||
690 | return true; | |
691 | } | |
692 | ||
693 | // --------------------------------------------------------- | |
694 | // wxDataViewColumn | |
695 | // --------------------------------------------------------- | |
7b4fde82 RR |
696 | |
697 | extern "C" { | |
698 | static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *column, | |
699 | GtkCellRenderer *cell, | |
700 | GtkTreeModel *model, | |
701 | GtkTreeIter *iter, | |
702 | gpointer data ); | |
703 | } | |
704 | ||
705 | ||
706 | static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *column, | |
707 | GtkCellRenderer *renderer, | |
708 | GtkTreeModel *model, | |
709 | GtkTreeIter *iter, | |
710 | gpointer data ) | |
711 | { | |
712 | g_return_if_fail (GTK_IS_WX_LIST_STORE (model)); | |
713 | GtkWxListStore *list_store = (GtkWxListStore *) model; | |
714 | ||
715 | wxDataViewCell *cell = (wxDataViewCell*) data; | |
a7f61f76 RR |
716 | |
717 | size_t model_row = (size_t) iter->user_data; | |
7b4fde82 | 718 | |
a7f61f76 RR |
719 | wxVariant value = list_store->model->GetValue( |
720 | cell->GetOwner()->GetModelColumn(), model_row ); | |
7b4fde82 RR |
721 | |
722 | if (value.GetType() != cell->GetVariantType()) | |
723 | wxPrintf( wxT("Wrong type\n") ); | |
724 | ||
725 | cell->SetValue( value ); | |
726 | } | |
727 | ||
fa28826d RR |
728 | IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumn, wxDataViewColumnBase) |
729 | ||
6842a71a RR |
730 | wxDataViewColumn::wxDataViewColumn( const wxString &title, wxDataViewCell *cell, |
731 | size_t model_column, int flags ) : | |
732 | wxDataViewColumnBase( title, cell, model_column, flags ) | |
fa28826d | 733 | { |
6842a71a | 734 | GtkCellRenderer *renderer = (GtkCellRenderer *) cell->GetGtkHandle(); |
fa28826d | 735 | |
6842a71a RR |
736 | GtkTreeViewColumn *column = gtk_tree_view_column_new(); |
737 | ||
738 | gtk_tree_view_column_set_title( column, wxGTK_CONV(title) ); | |
fa28826d | 739 | |
6842a71a RR |
740 | gtk_tree_view_column_pack_start( column, renderer, TRUE ); |
741 | ||
7b4fde82 RR |
742 | gtk_tree_view_column_set_cell_data_func( column, renderer, |
743 | wxGtkTreeCellDataFunc, (gpointer) cell, NULL ); | |
6842a71a | 744 | |
fa28826d RR |
745 | m_column = (void*) column; |
746 | } | |
747 | ||
748 | wxDataViewColumn::~wxDataViewColumn() | |
749 | { | |
750 | } | |
751 | ||
752 | void wxDataViewColumn::SetTitle( const wxString &title ) | |
753 | { | |
754 | wxDataViewColumnBase::SetTitle( title ); | |
755 | ||
756 | GtkTreeViewColumn *column = (GtkTreeViewColumn *)m_column; | |
757 | gtk_tree_view_column_set_title( column, wxGTK_CONV(title) ); | |
758 | } | |
759 | ||
790b137e RR |
760 | //----------------------------------------------------------------------------- |
761 | // wxDataViewCtrl | |
762 | //----------------------------------------------------------------------------- | |
763 | ||
239eaa41 RR |
764 | IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl, wxDataViewCtrlBase) |
765 | ||
766 | wxDataViewCtrl::~wxDataViewCtrl() | |
767 | { | |
768 | } | |
769 | ||
770 | void wxDataViewCtrl::Init() | |
771 | { | |
772 | } | |
773 | ||
774 | bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id, | |
775 | const wxPoint& pos, const wxSize& size, | |
776 | long style, const wxValidator& validator ) | |
777 | { | |
778 | Init(); | |
779 | ||
780 | m_needParent = TRUE; | |
781 | m_acceptsFocus = TRUE; | |
782 | ||
783 | if (!PreCreation( parent, pos, size ) || | |
784 | !CreateBase( parent, id, pos, size, style, validator )) | |
785 | { | |
786 | wxFAIL_MSG( wxT("wxDataViewCtrl creation failed") ); | |
787 | return FALSE; | |
788 | } | |
789 | ||
790 | m_widget = gtk_tree_view_new(); | |
791 | ||
792 | m_parent->DoAddChild( this ); | |
793 | ||
794 | PostCreation(size); | |
795 | ||
796 | return true; | |
797 | } | |
798 | ||
6e2e590f | 799 | bool wxDataViewCtrl::AssociateModel( wxDataViewListModel *model ) |
239eaa41 RR |
800 | { |
801 | if (!wxDataViewCtrlBase::AssociateModel( model )) | |
802 | return false; | |
803 | ||
6e2e590f RR |
804 | GtkWxListStore *gtk_store = wxgtk_list_store_new(); |
805 | gtk_store->model = model; | |
806 | ||
807 | wxGtkDataViewListModelNotifier *notifier = | |
808 | new wxGtkDataViewListModelNotifier( gtk_store, model ); | |
809 | ||
810 | model->SetNotifier( notifier ); | |
1557c77b | 811 | |
6e2e590f | 812 | gtk_tree_view_set_model( GTK_TREE_VIEW(m_widget), GTK_TREE_MODEL(gtk_store) ); |
239eaa41 RR |
813 | |
814 | return true; | |
815 | } | |
790b137e | 816 | |
fa28826d RR |
817 | bool wxDataViewCtrl::AppendColumn( wxDataViewColumn *col ) |
818 | { | |
819 | if (!wxDataViewCtrlBase::AppendColumn(col)) | |
820 | return false; | |
821 | ||
822 | GtkTreeViewColumn *column = (GtkTreeViewColumn *)col->GetGtkHandle(); | |
823 | ||
824 | gtk_tree_view_append_column( GTK_TREE_VIEW(m_widget), column ); | |
825 | ||
826 | return true; | |
827 | } | |
828 | ||
790b137e RR |
829 | |
830 | #endif // wxUSE_DATAVIEWCTRL | |
831 |