]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/dataview.cpp
Some restructuring, beginning of wxDataViewDateCell.
[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 #include "wx/dcclient.h"
20
21 #include "wx/gtk/private.h"
22 #include "wx/gtk/win_gtk.h"
23
24 #include <gobject/gvaluecollector.h>
25 #include <gtk/gtktreemodel.h>
26 #include <gtk/gtktreednd.h>
27
28 #include <gdk/gdkkeysyms.h>
29
30 //-----------------------------------------------------------------------------
31 // classes
32 //-----------------------------------------------------------------------------
33
34 class wxDataViewCtrl;
35
36 //-----------------------------------------------------------------------------
37 // idle system
38 //-----------------------------------------------------------------------------
39
40 extern void wxapp_install_idle_handler();
41 extern bool g_isIdle;
42
43 //-----------------------------------------------------------------------------
44 // data
45 //-----------------------------------------------------------------------------
46
47 extern bool g_blockEventsOnDrag;
48
49 //-----------------------------------------------------------------------------
50 // define new GTK+ class wxGtkListStore
51 //-----------------------------------------------------------------------------
52
53 extern "C" {
54
55 #define GTK_TYPE_WX_LIST_STORE (gtk_wx_list_store_get_type ())
56 #define GTK_WX_LIST_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WX_LIST_STORE, GtkWxListStore))
57 #define GTK_WX_LIST_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WX_LIST_STORE, GtkWxListStoreClass))
58 #define GTK_IS_WX_LIST_STORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WX_LIST_STORE))
59 #define GTK_IS_WX_LIST_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WX_LIST_STORE))
60 #define GTK_WX_LIST_STORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WX_LIST_STORE, GtkWxListStoreClass))
61
62 GType gtk_wx_list_store_get_type (void);
63
64 typedef struct _GtkWxListStore GtkWxListStore;
65 typedef struct _GtkWxListStoreClass GtkWxListStoreClass;
66
67 struct _GtkWxListStore
68 {
69 GObject parent;
70
71 /*< private >*/
72 gint stamp;
73 wxDataViewListModel *model;
74 };
75
76 struct _GtkWxListStoreClass
77 {
78 GObjectClass list_parent_class;
79
80 };
81
82 static GtkWxListStore *wxgtk_list_store_new (void);
83 static void wxgtk_list_store_init (GtkWxListStore *list_store);
84 static void wxgtk_list_store_class_init (GtkWxListStoreClass *klass);
85 static void wxgtk_list_store_tree_model_init (GtkTreeModelIface *iface);
86 static void wxgtk_list_store_finalize (GObject *object);
87 static GtkTreeModelFlags wxgtk_list_store_get_flags (GtkTreeModel *tree_model);
88 static gint wxgtk_list_store_get_n_columns (GtkTreeModel *tree_model);
89 static GType wxgtk_list_store_get_column_type (GtkTreeModel *tree_model,
90 gint index);
91 static gboolean wxgtk_list_store_get_iter (GtkTreeModel *tree_model,
92 GtkTreeIter *iter,
93 GtkTreePath *path);
94 static GtkTreePath *wxgtk_list_store_get_path (GtkTreeModel *tree_model,
95 GtkTreeIter *iter);
96 static void wxgtk_list_store_get_value (GtkTreeModel *tree_model,
97 GtkTreeIter *iter,
98 gint column,
99 GValue *value);
100 static gboolean wxgtk_list_store_iter_next (GtkTreeModel *tree_model,
101 GtkTreeIter *iter);
102 static gboolean wxgtk_list_store_iter_children (GtkTreeModel *tree_model,
103 GtkTreeIter *iter,
104 GtkTreeIter *parent);
105 static gboolean wxgtk_list_store_iter_has_child (GtkTreeModel *tree_model,
106 GtkTreeIter *iter);
107 static gint wxgtk_list_store_iter_n_children (GtkTreeModel *tree_model,
108 GtkTreeIter *iter);
109 static gboolean wxgtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
110 GtkTreeIter *iter,
111 GtkTreeIter *parent,
112 gint n);
113 static gboolean wxgtk_list_store_iter_parent (GtkTreeModel *tree_model,
114 GtkTreeIter *iter,
115 GtkTreeIter *child);
116
117 static GObjectClass *list_parent_class = NULL;
118
119 GType
120 gtk_wx_list_store_get_type (void)
121 {
122 static GType list_store_type = 0;
123
124 if (!list_store_type)
125 {
126 static const GTypeInfo list_store_info =
127 {
128 sizeof (GtkWxListStoreClass),
129 NULL, /* base_init */
130 NULL, /* base_finalize */
131 (GClassInitFunc) wxgtk_list_store_class_init,
132 NULL, /* class_finalize */
133 NULL, /* class_data */
134 sizeof (GtkWxListStore),
135 0,
136 (GInstanceInitFunc) wxgtk_list_store_init,
137 };
138
139 static const GInterfaceInfo tree_model_info =
140 {
141 (GInterfaceInitFunc) wxgtk_list_store_tree_model_init,
142 NULL,
143 NULL
144 };
145
146 list_store_type = g_type_register_static (G_TYPE_OBJECT, "GtkWxListStore",
147 &list_store_info, (GTypeFlags)0 );
148
149 g_type_add_interface_static (list_store_type,
150 GTK_TYPE_TREE_MODEL,
151 &tree_model_info);
152 }
153
154 return list_store_type;
155 }
156
157 static GtkWxListStore *
158 wxgtk_list_store_new(void)
159 {
160 GtkWxListStore *retval = (GtkWxListStore *) g_object_new (GTK_TYPE_WX_LIST_STORE, NULL);
161 return retval;
162 }
163
164 static void
165 wxgtk_list_store_class_init (GtkWxListStoreClass *klass)
166 {
167 list_parent_class = (GObjectClass*) g_type_class_peek_parent (klass);
168 GObjectClass *object_class = (GObjectClass*) klass;
169 object_class->finalize = wxgtk_list_store_finalize;
170 }
171
172 static void
173 wxgtk_list_store_tree_model_init (GtkTreeModelIface *iface)
174 {
175 iface->get_flags = wxgtk_list_store_get_flags;
176 iface->get_n_columns = wxgtk_list_store_get_n_columns;
177 iface->get_column_type = wxgtk_list_store_get_column_type;
178 iface->get_iter = wxgtk_list_store_get_iter;
179 iface->get_path = wxgtk_list_store_get_path;
180 iface->get_value = wxgtk_list_store_get_value;
181 iface->iter_next = wxgtk_list_store_iter_next;
182 iface->iter_children = wxgtk_list_store_iter_children;
183 iface->iter_has_child = wxgtk_list_store_iter_has_child;
184 iface->iter_n_children = wxgtk_list_store_iter_n_children;
185 iface->iter_nth_child = wxgtk_list_store_iter_nth_child;
186 iface->iter_parent = wxgtk_list_store_iter_parent;
187 }
188
189 static void
190 wxgtk_list_store_init (GtkWxListStore *list_store)
191 {
192 list_store->model = NULL;
193 list_store->stamp = g_random_int();
194 }
195
196 static void
197 wxgtk_list_store_finalize (GObject *object)
198 {
199 /* GtkWxListStore *list_store = GTK_WX_LIST_STORE (object); */
200
201 /* we need to sort out, which class deletes what */
202 /* delete list_store->model; */
203
204 /* must chain up */
205 (* list_parent_class->finalize) (object);
206 }
207
208 } // extern "C"
209
210 //-----------------------------------------------------------------------------
211 // implement callbacks from wxGtkListStore class by letting
212 // them call the methods of wxWidgets' wxDataViewListModel
213 //-----------------------------------------------------------------------------
214
215 static GtkTreeModelFlags
216 wxgtk_list_store_get_flags (GtkTreeModel *tree_model)
217 {
218 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), (GtkTreeModelFlags)0 );
219
220 // GTK+ list store uses a linked list for storing the
221 // items and a pointer to a child is used as the member
222 // field of a GtkTreeIter. This means that the iter is
223 // valid in the GtkListStore as long as the child exists.
224 // We use the index of the row and since the index of a
225 // specific row will change if a row above is deleted,
226 // the iter does not persist
227 return /* GTK_TREE_MODEL_ITERS_PERSIST | */ GTK_TREE_MODEL_LIST_ONLY;
228 }
229
230 static gint
231 wxgtk_list_store_get_n_columns (GtkTreeModel *tree_model)
232 {
233 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
234 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), 0);
235
236 return list_store->model->GetNumberOfCols();
237 }
238
239 static GType
240 wxgtk_list_store_get_column_type (GtkTreeModel *tree_model,
241 gint index)
242 {
243 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
244 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), G_TYPE_INVALID);
245
246 GType gtype = G_TYPE_INVALID;
247
248 wxString wxtype = list_store->model->GetColType( (size_t) index );
249
250 if (wxtype == wxT("string"))
251 gtype = G_TYPE_STRING;
252
253 return gtype;
254 }
255
256 static gboolean
257 wxgtk_list_store_get_iter (GtkTreeModel *tree_model,
258 GtkTreeIter *iter,
259 GtkTreePath *path)
260 {
261 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
262 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), FALSE);
263 g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
264
265 size_t i = (size_t)gtk_tree_path_get_indices (path)[0];
266
267 if (i >= list_store->model->GetNumberOfRows())
268 return FALSE;
269
270 iter->stamp = list_store->stamp;
271 // user_data is just the index
272 iter->user_data = (gpointer) i;
273
274 return TRUE;
275 }
276
277 static GtkTreePath *
278 wxgtk_list_store_get_path (GtkTreeModel *tree_model,
279 GtkTreeIter *iter)
280 {
281 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);
283
284 GtkTreePath *retval = gtk_tree_path_new ();
285 // user_data is just the index
286 int i = (int) iter->user_data;
287 gtk_tree_path_append_index (retval, i);
288 return retval;
289 }
290
291 static void
292 wxgtk_list_store_get_value (GtkTreeModel *tree_model,
293 GtkTreeIter *iter,
294 gint column,
295 GValue *value)
296 {
297 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
298 g_return_if_fail (GTK_IS_WX_LIST_STORE (tree_model) );
299
300 wxDataViewListModel *model = list_store->model;
301 wxString mtype = model->GetColType( (size_t) column );
302 if (mtype == wxT("string"))
303 {
304 g_value_init( value, G_TYPE_STRING );
305 wxVariant variant = model->GetValue( (size_t) column, (size_t) iter->user_data );
306 g_value_set_string( value, wxGTK_CONV(variant.GetString()) );
307 }
308 else
309 {
310 }
311
312 #if 0
313 GtkTreeDataList *list;
314 gint tmp_column = column;
315
316 g_return_if_fail (column < GTK_LIST_STORE (tree_model)->n_columns);
317 g_return_if_fail (GTK_LIST_STORE (tree_model)->stamp == iter->stamp);
318
319 list = G_SLIST (iter->user_data)->data;
320
321 while (tmp_column-- > 0 && list)
322 list = list->next;
323
324 if (list == NULL)
325 g_value_init (value, GTK_LIST_STORE (tree_model)->column_headers[column]);
326 else
327 _gtk_tree_data_list_node_to_value (list,
328 GTK_LIST_STORE (tree_model)->column_headers[column],
329 value);
330 #endif
331
332 }
333
334 static gboolean
335 wxgtk_list_store_iter_next (GtkTreeModel *tree_model,
336 GtkTreeIter *iter)
337 {
338 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), FALSE);
339 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
340
341 g_return_val_if_fail (list_store->stamp == iter->stamp, FALSE);
342
343 int n = (int) iter->user_data;
344
345 if (n == -1)
346 return FALSE;
347
348 if (n >= (int) list_store->model->GetNumberOfRows()-1)
349 return FALSE;
350
351 iter->user_data = (gpointer) ++n;
352
353 return TRUE;
354 }
355
356 static gboolean
357 wxgtk_list_store_iter_children (GtkTreeModel *tree_model,
358 GtkTreeIter *iter,
359 GtkTreeIter *parent)
360 {
361 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), FALSE);
362 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
363
364 // this is a list, nodes have no children
365 if (parent)
366 return FALSE;
367
368 iter->stamp = list_store->stamp;
369 iter->user_data = (gpointer) -1;
370
371 return TRUE;
372 }
373
374 static gboolean
375 wxgtk_list_store_iter_has_child (GtkTreeModel *tree_model,
376 GtkTreeIter *iter)
377 {
378 return FALSE;
379 }
380
381 static gint
382 wxgtk_list_store_iter_n_children (GtkTreeModel *tree_model,
383 GtkTreeIter *iter)
384 {
385 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), -1);
386 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
387
388 if (iter == NULL)
389 return (gint) list_store->model->GetNumberOfRows();
390
391 g_return_val_if_fail (list_store->stamp == iter->stamp, -1);
392
393 return 0;
394 }
395
396 static gboolean
397 wxgtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
398 GtkTreeIter *iter,
399 GtkTreeIter *parent,
400 gint n)
401 {
402 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), FALSE);
403 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
404
405 if (parent)
406 return FALSE;
407
408 if (n < 0)
409 return FALSE;
410
411 if (n >= (gint) list_store->model->GetNumberOfRows())
412 return FALSE;
413
414 iter->stamp = list_store->stamp;
415 iter->user_data = (gpointer) n;
416
417 return TRUE;
418 }
419
420 static gboolean
421 wxgtk_list_store_iter_parent (GtkTreeModel *tree_model,
422 GtkTreeIter *iter,
423 GtkTreeIter *child)
424 {
425 return FALSE;
426 }
427
428 //-----------------------------------------------------------------------------
429 // define new GTK+ class wxGtkCellRenderer
430 //-----------------------------------------------------------------------------
431
432 extern "C" {
433
434 #define GTK_TYPE_WX_CELL_RENDERER (gtk_wx_cell_renderer_get_type ())
435 #define GTK_WX_CELL_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRenderer))
436 #define GTK_WX_CELL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRendererClass))
437 #define GTK_IS_WX_CELL_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WX_CELL_RENDERER))
438 #define GTK_IS_WX_CELL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WX_CELL_RENDERER))
439 #define GTK_WX_CELL_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRendererClass))
440
441 GType gtk_wx_cell_renderer_get_type (void);
442
443 typedef struct _GtkWxCellRenderer GtkWxCellRenderer;
444 typedef struct _GtkWxCellRendererClass GtkWxCellRendererClass;
445
446 struct _GtkWxCellRenderer
447 {
448 GtkCellRenderer parent;
449
450 /*< private >*/
451 wxDataViewCustomCell *cell;
452 guint32 last_click;
453 };
454
455 struct _GtkWxCellRendererClass
456 {
457 GtkCellRendererClass cell_parent_class;
458 };
459
460
461 static GtkCellRenderer *gtk_wx_cell_renderer_new (void);
462 static void gtk_wx_cell_renderer_init (
463 GtkWxCellRenderer *cell );
464 static void gtk_wx_cell_renderer_class_init(
465 GtkWxCellRendererClass *klass );
466 static void gtk_wx_cell_renderer_finalize (
467 GObject *object );
468 static void gtk_wx_cell_renderer_get_size (
469 GtkCellRenderer *cell,
470 GtkWidget *widget,
471 GdkRectangle *rectangle,
472 gint *x_offset,
473 gint *y_offset,
474 gint *width,
475 gint *height );
476 static void gtk_wx_cell_renderer_render (
477 GtkCellRenderer *cell,
478 GdkWindow *window,
479 GtkWidget *widget,
480 GdkRectangle *background_area,
481 GdkRectangle *cell_area,
482 GdkRectangle *expose_area,
483 GtkCellRendererState flags );
484 static gboolean gtk_wx_cell_renderer_activate(
485 GtkCellRenderer *cell,
486 GdkEvent *event,
487 GtkWidget *widget,
488 const gchar *path,
489 GdkRectangle *background_area,
490 GdkRectangle *cell_area,
491 GtkCellRendererState flags );
492
493 static GObjectClass *cell_parent_class = NULL;
494
495 } // extern "C"
496
497 GType
498 gtk_wx_cell_renderer_get_type (void)
499 {
500 static GType cell_wx_type = 0;
501
502 if (!cell_wx_type)
503 {
504 static const GTypeInfo cell_wx_info =
505 {
506 sizeof (GtkWxCellRendererClass),
507 NULL, /* base_init */
508 NULL, /* base_finalize */
509 (GClassInitFunc) gtk_wx_cell_renderer_class_init,
510 NULL, /* class_finalize */
511 NULL, /* class_data */
512 sizeof (GtkWxCellRenderer),
513 0, /* n_preallocs */
514 (GInstanceInitFunc) gtk_wx_cell_renderer_init,
515 };
516
517 cell_wx_type = g_type_register_static( GTK_TYPE_CELL_RENDERER,
518 "GtkWxCellRenderer", &cell_wx_info, (GTypeFlags)0 );
519 }
520
521 return cell_wx_type;
522 }
523
524 static void
525 gtk_wx_cell_renderer_init (GtkWxCellRenderer *cell)
526 {
527 cell->cell = NULL;
528 cell->last_click = 0;
529 }
530
531 static void
532 gtk_wx_cell_renderer_class_init (GtkWxCellRendererClass *klass)
533 {
534 GObjectClass *object_class = G_OBJECT_CLASS (klass);
535 GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
536
537 cell_parent_class = (GObjectClass*) g_type_class_peek_parent (klass);
538
539 object_class->finalize = gtk_wx_cell_renderer_finalize;
540
541 cell_class->get_size = gtk_wx_cell_renderer_get_size;
542 cell_class->render = gtk_wx_cell_renderer_render;
543 cell_class->activate = gtk_wx_cell_renderer_activate;
544 }
545
546 static void
547 gtk_wx_cell_renderer_finalize (GObject *object)
548 {
549 /* must chain up */
550 (* G_OBJECT_CLASS (cell_parent_class)->finalize) (object);
551 }
552
553 GtkCellRenderer*
554 gtk_wx_cell_renderer_new (void)
555 {
556 return (GtkCellRenderer*) g_object_new (GTK_TYPE_WX_CELL_RENDERER, NULL);
557 }
558
559 static void
560 gtk_wx_cell_renderer_get_size (GtkCellRenderer *renderer,
561 GtkWidget *widget,
562 GdkRectangle *cell_area,
563 gint *x_offset,
564 gint *y_offset,
565 gint *width,
566 gint *height)
567 {
568 GtkWxCellRenderer *wxrenderer = (GtkWxCellRenderer *) renderer;
569 wxDataViewCustomCell *cell = wxrenderer->cell;
570
571 wxSize size = cell->GetSize();
572
573 gint calc_width = (gint) renderer->xpad * 2 + size.x;
574 gint calc_height = (gint) renderer->ypad * 2 + size.y;
575
576 if (x_offset)
577 *x_offset = 0;
578 if (y_offset)
579 *y_offset = 0;
580
581 if (cell_area && size.x > 0 && size.y > 0)
582 {
583 if (x_offset)
584 {
585 *x_offset = (gint)((renderer->xalign *
586 (cell_area->width - calc_width - 2 * renderer->xpad)));
587 *x_offset = MAX (*x_offset, 0) + renderer->xpad;
588 }
589 if (y_offset)
590 {
591 *y_offset = (gint)((renderer->yalign *
592 (cell_area->height - calc_height - 2 * renderer->ypad)));
593 *y_offset = MAX (*y_offset, 0) + renderer->ypad;
594 }
595 }
596
597 if (width)
598 *width = calc_width;
599
600 if (height)
601 *height = calc_height;
602 }
603
604 static void
605 gtk_wx_cell_renderer_render (GtkCellRenderer *renderer,
606 GdkWindow *window,
607 GtkWidget *widget,
608 GdkRectangle *background_area,
609 GdkRectangle *cell_area,
610 GdkRectangle *expose_area,
611 GtkCellRendererState flags)
612
613 {
614 GtkWxCellRenderer *wxrenderer = (GtkWxCellRenderer *) renderer;
615 wxDataViewCustomCell *cell = wxrenderer->cell;
616
617 GdkRectangle rect;
618 gtk_wx_cell_renderer_get_size (renderer, widget, cell_area,
619 &rect.x,
620 &rect.y,
621 &rect.width,
622 &rect.height);
623
624 rect.x += cell_area->x;
625 rect.y += cell_area->y;
626 rect.width -= renderer->xpad * 2;
627 rect.height -= renderer->ypad * 2;
628
629 GdkRectangle dummy;
630 if (gdk_rectangle_intersect (expose_area, &rect, &dummy))
631 {
632 wxRect renderrect( rect.x, rect.y, rect.width, rect.height );
633 wxWindowDC* dc = (wxWindowDC*) cell->GetDC();
634 if (dc->m_window == NULL)
635 {
636 dc->m_window = window;
637 dc->SetUpDC();
638 }
639
640 int state = 0;
641 if (flags & GTK_CELL_RENDERER_SELECTED)
642 state |= wxDATAVIEW_CELL_SELECTED;
643 if (flags & GTK_CELL_RENDERER_PRELIT)
644 state |= wxDATAVIEW_CELL_PRELIT;
645 if (flags & GTK_CELL_RENDERER_INSENSITIVE)
646 state |= wxDATAVIEW_CELL_INSENSITIVE;
647 if (flags & GTK_CELL_RENDERER_INSENSITIVE)
648 state |= wxDATAVIEW_CELL_INSENSITIVE;
649 if (flags & GTK_CELL_RENDERER_FOCUSED)
650 state |= wxDATAVIEW_CELL_FOCUSED;
651 cell->Render( renderrect, dc, state );
652 }
653 }
654
655 static gboolean
656 gtk_wx_cell_renderer_activate(
657 GtkCellRenderer *renderer,
658 GdkEvent *event,
659 GtkWidget *widget,
660 const gchar *path,
661 GdkRectangle *background_area,
662 GdkRectangle *cell_area,
663 GtkCellRendererState flags )
664 {
665 GtkWxCellRenderer *wxrenderer = (GtkWxCellRenderer *) renderer;
666 wxDataViewCustomCell *cell = wxrenderer->cell;
667
668 GdkRectangle rect;
669 gtk_wx_cell_renderer_get_size (renderer, widget, cell_area,
670 &rect.x,
671 &rect.y,
672 &rect.width,
673 &rect.height);
674
675 rect.x += cell_area->x;
676 rect.y += cell_area->y;
677 rect.width -= renderer->xpad * 2;
678 rect.height -= renderer->ypad * 2;
679
680 wxRect renderrect( rect.x, rect.y, rect.width, rect.height );
681
682 wxDataViewListModel *model = cell->GetOwner()->GetOwner()->GetModel();
683
684 GtkTreePath *treepath = gtk_tree_path_new_from_string( path );
685 size_t model_row = (size_t)gtk_tree_path_get_indices (treepath)[0];
686 gtk_tree_path_free( treepath );
687
688 size_t model_col = cell->GetOwner()->GetModelColumn();
689
690 if (event->type == GDK_BUTTON_PRESS)
691 {
692 GdkEventButton *button_event = (GdkEventButton*) event;
693 wxPoint pt( ((int) button_event->x) - renderrect.x,
694 ((int) button_event->y) - renderrect.y );
695
696 bool ret = false;
697 if (button_event->button == 1)
698 {
699 if (cell->LeftClick( pt, renderrect, model, model_col, model_row ))
700 ret = true;
701 if (button_event->time - wxrenderer->last_click < 400)
702 if (cell->Activate( renderrect, model, model_col, model_row ))
703 ret = true;
704 }
705 if (button_event->button == 3)
706 {
707 if (cell->RightClick( pt, renderrect, model, model_col, model_row ))
708 ret = true;
709 }
710
711 wxrenderer->last_click = button_event->time;
712
713 return ret;
714 }
715
716 if (event->type == GDK_KEY_PRESS)
717 {
718 wxPrintf( wxT("key\n") );
719 GdkEventKey *key_event = (GdkEventKey*) event;
720 if ((key_event->keyval == GDK_Return) ||
721 (key_event->keyval == GDK_Linefeed) ||
722 (key_event->keyval == GDK_Execute))
723 {
724 return cell->Activate( renderrect, model, model_col, model_row );
725 }
726 }
727
728 return false;
729 }
730
731 // ---------------------------------------------------------
732 // wxGtkDataViewListModelNotifier
733 // ---------------------------------------------------------
734
735 class wxGtkDataViewListModelNotifier: public wxDataViewListModelNotifier
736 {
737 public:
738 wxGtkDataViewListModelNotifier( GtkWxListStore* gtk_store, wxDataViewListModel *wx_model );
739
740 virtual bool RowAppended();
741 virtual bool RowPrepended();
742 virtual bool RowInserted( size_t before );
743 virtual bool RowDeleted( size_t row );
744 virtual bool RowChanged( size_t row );
745 virtual bool ValueChanged( size_t col, size_t row );
746 virtual bool Cleared();
747
748 GtkWxListStore *m_gtk_store;
749 wxDataViewListModel *m_wx_model;
750 };
751
752 // ---------------------------------------------------------
753 // wxGtkDataViewListModelNotifier
754 // ---------------------------------------------------------
755
756 wxGtkDataViewListModelNotifier::wxGtkDataViewListModelNotifier(
757 GtkWxListStore* gtk_store, wxDataViewListModel *wx_model )
758 {
759 m_gtk_store = gtk_store;
760 m_wx_model = wx_model;
761 }
762
763 bool wxGtkDataViewListModelNotifier::RowAppended()
764 {
765 size_t pos = m_wx_model->GetNumberOfRows()-1;
766
767 GtkTreeIter iter;
768 iter.stamp = m_gtk_store->stamp;
769 iter.user_data = (gpointer) pos;
770
771 GtkTreePath *path = gtk_tree_path_new ();
772 gtk_tree_path_append_index (path, (gint) pos);
773 gtk_tree_model_row_inserted (GTK_TREE_MODEL (m_gtk_store), path, &iter);
774 gtk_tree_path_free (path);
775
776 return true;
777 }
778
779 bool wxGtkDataViewListModelNotifier::RowPrepended()
780 {
781 GtkTreeIter iter;
782 iter.stamp = m_gtk_store->stamp;
783 iter.user_data = (gpointer) 0;
784
785 GtkTreePath *path = gtk_tree_path_new ();
786 gtk_tree_path_append_index (path, (gint) 0);
787 gtk_tree_model_row_inserted (GTK_TREE_MODEL (m_gtk_store), path, &iter);
788 gtk_tree_path_free (path);
789
790 return true;
791 }
792
793 bool wxGtkDataViewListModelNotifier::RowInserted( size_t before )
794 {
795 return false;
796 }
797
798 bool wxGtkDataViewListModelNotifier::RowDeleted( size_t row )
799 {
800 return false;
801 }
802
803 bool wxGtkDataViewListModelNotifier::RowChanged( size_t row )
804 {
805 GtkTreeIter iter;
806 iter.stamp = m_gtk_store->stamp;
807 iter.user_data = (gpointer) row;
808 GtkTreePath *path = gtk_tree_model_get_path (GTK_TREE_MODEL (m_gtk_store), &iter);
809 gtk_tree_model_row_changed (GTK_TREE_MODEL (m_gtk_store), path, &iter);
810 gtk_tree_path_free (path);
811
812 return true;
813 }
814
815 bool wxGtkDataViewListModelNotifier::ValueChanged( size_t col, size_t row )
816 {
817 return RowChanged( row );
818 }
819
820 bool wxGtkDataViewListModelNotifier::Cleared()
821 {
822 return false;
823 }
824
825 // ---------------------------------------------------------
826 // wxDataViewCell
827 // ---------------------------------------------------------
828
829 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCell, wxDataViewCellBase)
830
831 wxDataViewCell::wxDataViewCell( const wxString &varianttype, wxDataViewCellMode mode ) :
832 wxDataViewCellBase( varianttype, mode )
833 {
834 m_renderer = NULL;
835 }
836
837 // ---------------------------------------------------------
838 // wxDataViewTextCell
839 // ---------------------------------------------------------
840
841 extern "C" {
842 static void wxGtkTextRendererEditedCallback( GtkCellRendererText *renderer,
843 gchar *arg1, gchar *arg2, gpointer user_data );
844 }
845
846 static void wxGtkTextRendererEditedCallback( GtkCellRendererText *renderer,
847 gchar *arg1, gchar *arg2, gpointer user_data )
848 {
849 wxDataViewTextCell *cell = (wxDataViewTextCell*) user_data;
850
851 wxString tmp = wxGTK_CONV_BACK( arg2 );
852 wxVariant value = tmp;
853 if (!cell->Validate( value ))
854 return;
855
856 wxDataViewListModel *model = cell->GetOwner()->GetOwner()->GetModel();
857
858 GtkTreePath *path = gtk_tree_path_new_from_string( arg1 );
859 size_t model_row = (size_t)gtk_tree_path_get_indices (path)[0];
860 gtk_tree_path_free( path );
861
862 size_t model_col = cell->GetOwner()->GetModelColumn();
863
864 model->SetValue( value, model_col, model_row );
865 model->ValueChanged( model_col, model_row );
866 }
867
868 IMPLEMENT_ABSTRACT_CLASS(wxDataViewTextCell, wxDataViewCell)
869
870 wxDataViewTextCell::wxDataViewTextCell( const wxString &varianttype, wxDataViewCellMode mode ) :
871 wxDataViewCell( varianttype, mode )
872 {
873 m_renderer = (void*) gtk_cell_renderer_text_new();
874
875 if (m_mode & wxDATAVIEW_CELL_EDITABLE)
876 {
877 GValue gvalue = { 0, };
878 g_value_init( &gvalue, G_TYPE_BOOLEAN );
879 g_value_set_boolean( &gvalue, true );
880 g_object_set_property( G_OBJECT(m_renderer), "editable", &gvalue );
881 g_value_unset( &gvalue );
882
883 g_signal_connect_after( m_renderer, "edited", G_CALLBACK(wxGtkTextRendererEditedCallback), this );
884 }
885 }
886
887 bool wxDataViewTextCell::SetValue( const wxVariant &value )
888 {
889 wxString tmp = value;
890
891 GValue gvalue = { 0, };
892 g_value_init( &gvalue, G_TYPE_STRING );
893 g_value_set_string( &gvalue, wxGTK_CONV( tmp ) );
894 g_object_set_property( G_OBJECT(m_renderer), "text", &gvalue );
895 g_value_unset( &gvalue );
896
897 return true;
898 }
899
900 bool wxDataViewTextCell::GetValue( wxVariant &value )
901 {
902 GValue gvalue = { 0, };
903 g_value_init( &gvalue, G_TYPE_STRING );
904 g_object_get_property( G_OBJECT(m_renderer), "text", &gvalue );
905 wxString tmp = wxGTK_CONV_BACK( g_value_get_string( &gvalue ) );
906 g_value_unset( &gvalue );
907
908 value = tmp;
909
910 return true;
911 }
912
913 // ---------------------------------------------------------
914 // wxDataViewToggleCell
915 // ---------------------------------------------------------
916
917 extern "C" {
918 static void wxGtkToggleRendererToggledCallback( GtkCellRendererToggle *renderer,
919 gchar *path, gpointer user_data );
920 }
921
922 static void wxGtkToggleRendererToggledCallback( GtkCellRendererToggle *renderer,
923 gchar *path, gpointer user_data )
924 {
925 wxDataViewToggleCell *cell = (wxDataViewToggleCell*) user_data;
926
927 // get old value
928 GValue gvalue = { 0, };
929 g_value_init( &gvalue, G_TYPE_BOOLEAN );
930 g_object_get_property( G_OBJECT(renderer), "active", &gvalue );
931 bool tmp = g_value_get_boolean( &gvalue );
932 g_value_unset( &gvalue );
933 // invert it
934 tmp = !tmp;
935
936 wxVariant value = tmp;
937 if (!cell->Validate( value ))
938 return;
939
940 wxDataViewListModel *model = cell->GetOwner()->GetOwner()->GetModel();
941
942 GtkTreePath *gtk_path = gtk_tree_path_new_from_string( path );
943 size_t model_row = (size_t)gtk_tree_path_get_indices (gtk_path)[0];
944 gtk_tree_path_free( gtk_path );
945
946 size_t model_col = cell->GetOwner()->GetModelColumn();
947
948 model->SetValue( value, model_col, model_row );
949 model->ValueChanged( model_col, model_row );
950 }
951
952 IMPLEMENT_ABSTRACT_CLASS(wxDataViewToggleCell, wxDataViewCell)
953
954 wxDataViewToggleCell::wxDataViewToggleCell( const wxString &varianttype,
955 wxDataViewCellMode mode ) :
956 wxDataViewCell( varianttype, mode )
957 {
958 m_renderer = (void*) gtk_cell_renderer_toggle_new();
959
960 if (m_mode & wxDATAVIEW_CELL_EDITABLE)
961 {
962 g_signal_connect_after( m_renderer, "toggled", G_CALLBACK(wxGtkToggleRendererToggledCallback), this );
963 }
964 else
965 {
966
967 GValue gvalue = { 0, };
968 g_value_init( &gvalue, G_TYPE_BOOLEAN );
969 g_value_set_boolean( &gvalue, false );
970 g_object_set_property( G_OBJECT(m_renderer), "activatable", &gvalue );
971 g_value_unset( &gvalue );
972
973 GValue gvalue2 = { 0, };
974 g_value_init( &gvalue2, gtk_cell_renderer_mode_get_type() );
975 g_value_set_enum( &gvalue2, GTK_CELL_RENDERER_MODE_INERT );
976 g_object_set_property( G_OBJECT(m_renderer), "mode", &gvalue2 );
977 g_value_unset( &gvalue2 );
978
979 }
980 }
981
982 bool wxDataViewToggleCell::SetValue( const wxVariant &value )
983 {
984 bool tmp = value;
985
986 GValue gvalue = { 0, };
987 g_value_init( &gvalue, G_TYPE_BOOLEAN );
988 g_value_set_boolean( &gvalue, tmp );
989 g_object_set_property( G_OBJECT(m_renderer), "active", &gvalue );
990 g_value_unset( &gvalue );
991
992 return true;
993 }
994
995 bool wxDataViewToggleCell::GetValue( wxVariant &value )
996 {
997 GValue gvalue = { 0, };
998 g_value_init( &gvalue, G_TYPE_BOOLEAN );
999 g_object_get_property( G_OBJECT(m_renderer), "active", &gvalue );
1000 bool tmp = g_value_get_boolean( &gvalue );
1001 g_value_unset( &gvalue );
1002
1003 value = tmp;
1004
1005 return true;
1006 }
1007
1008 // ---------------------------------------------------------
1009 // wxDataViewCustomCell
1010 // ---------------------------------------------------------
1011
1012 class wxDataViewCtrlDC: public wxWindowDC
1013 {
1014 public:
1015 wxDataViewCtrlDC( wxDataViewCtrl *window )
1016 {
1017 GtkWidget *widget = window->m_treeview;
1018 // Set later
1019 m_window = NULL;
1020
1021 m_context = window->GtkGetPangoDefaultContext();
1022 m_layout = pango_layout_new( m_context );
1023 m_fontdesc = pango_font_description_copy( widget->style->font_desc );
1024
1025 m_cmap = gtk_widget_get_colormap( widget ? widget : window->m_widget );
1026
1027 // Set m_window later
1028 // SetUpDC();
1029 // m_owner = window;
1030 }
1031 };
1032
1033 // ---------------------------------------------------------
1034 // wxDataViewCustomCell
1035 // ---------------------------------------------------------
1036
1037 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCustomCell, wxDataViewCell)
1038
1039 wxDataViewCustomCell::wxDataViewCustomCell( const wxString &varianttype,
1040 wxDataViewCellMode mode, bool no_init ) :
1041 wxDataViewCell( varianttype, mode )
1042 {
1043 m_dc = NULL;
1044
1045 if (no_init)
1046 m_renderer = NULL;
1047 else
1048 Init();
1049 }
1050
1051 bool wxDataViewCustomCell::Init()
1052 {
1053 GtkWxCellRenderer *renderer = (GtkWxCellRenderer *) gtk_wx_cell_renderer_new();
1054 renderer->cell = this;
1055
1056 m_renderer = (void*) renderer;
1057
1058 if (m_mode & wxDATAVIEW_CELL_ACTIVATABLE)
1059 {
1060 GValue gvalue = { 0, };
1061 g_value_init( &gvalue, gtk_cell_renderer_mode_get_type() );
1062 g_value_set_enum( &gvalue, GTK_CELL_RENDERER_MODE_ACTIVATABLE );
1063 g_object_set_property( G_OBJECT(m_renderer), "mode", &gvalue );
1064 g_value_unset( &gvalue );
1065 }
1066
1067 return true;
1068 }
1069
1070 wxDataViewCustomCell::~wxDataViewCustomCell()
1071 {
1072 if (m_dc)
1073 delete m_dc;
1074 }
1075
1076 wxDC *wxDataViewCustomCell::GetDC()
1077 {
1078 if (m_dc == NULL)
1079 {
1080 if (GetOwner() == NULL)
1081 return NULL;
1082 if (GetOwner()->GetOwner() == NULL)
1083 return NULL;
1084 m_dc = new wxDataViewCtrlDC( GetOwner()->GetOwner() );
1085 }
1086
1087 return m_dc;
1088 }
1089
1090 // ---------------------------------------------------------
1091 // wxDataViewProgressCell
1092 // ---------------------------------------------------------
1093
1094 IMPLEMENT_ABSTRACT_CLASS(wxDataViewProgressCell, wxDataViewCustomCell)
1095
1096 wxDataViewProgressCell::wxDataViewProgressCell( const wxString &label,
1097 const wxString &varianttype, wxDataViewCellMode mode ) :
1098 wxDataViewCustomCell( varianttype, mode, true )
1099 {
1100 m_label = label;
1101 m_value = 0;
1102
1103 #ifdef __WXGTK26__
1104 if (!gtk_check_version(2,6,0))
1105 {
1106 m_renderer = (void*) gtk_cell_renderer_progress_new();
1107
1108 GValue gvalue = { 0, };
1109 g_value_init( &gvalue, G_TYPE_STRING );
1110 g_value_set_boolean( &gvalue, wxGTK_CONV(m_label) );
1111 g_object_set_property( G_OBJECT(m_renderer), "text", &gvalue );
1112 g_value_unset( &gvalue );
1113 }
1114 else
1115 #endif
1116 {
1117 // Use custom cell code
1118 wxDataViewCustomCell::Init();
1119 }
1120 }
1121
1122 wxDataViewProgressCell::~wxDataViewProgressCell()
1123 {
1124 }
1125
1126 bool wxDataViewProgressCell::SetValue( const wxVariant &value )
1127 {
1128 #ifdef __WXGTK26__
1129 if (!gtk_check_version(2,6,0))
1130 {
1131 gint tmp = (int) value;
1132 GValue gvalue = { 0, };
1133 g_value_init( &gvalue, G_TYPE_INT );
1134 g_value_set_boolean( &gvalue, tmp );
1135 g_object_set_property( G_OBJECT(m_renderer), "value", &gvalue );
1136 g_value_unset( &gvalue );
1137 }
1138 else
1139 #endif
1140 {
1141 m_value = (long) value;
1142
1143 if (m_value < 0) m_value = 0;
1144 if (m_value > 100) m_value = 100;
1145 }
1146
1147 return true;
1148 }
1149
1150 bool wxDataViewProgressCell::Render( wxRect cell, wxDC *dc, int state )
1151 {
1152 double pct = (double)m_value / 100.0;
1153 wxRect bar = cell;
1154 bar.width = (int)(cell.width * pct);
1155 dc->SetPen( *wxTRANSPARENT_PEN );
1156 dc->SetBrush( *wxBLUE_BRUSH );
1157 dc->DrawRectangle( bar );
1158
1159 dc->SetBrush( *wxTRANSPARENT_BRUSH );
1160 dc->SetPen( *wxBLACK_PEN );
1161 dc->DrawRectangle( cell );
1162
1163 return true;
1164 }
1165
1166 wxSize wxDataViewProgressCell::GetSize()
1167 {
1168 return wxSize(40,12);
1169 }
1170
1171 // ---------------------------------------------------------
1172 // wxDataViewDateCell
1173 // ---------------------------------------------------------
1174
1175 IMPLEMENT_ABSTRACT_CLASS(wxDataViewDateCell, wxDataViewCustomCell)
1176
1177 wxDataViewDateCell::wxDataViewDateCell( const wxString &varianttype,
1178 wxDataViewCellMode mode ) :
1179 wxDataViewCustomCell( varianttype, mode )
1180 {
1181 }
1182
1183 bool wxDataViewDateCell::SetValue( const wxVariant &value )
1184 {
1185 m_date = value.GetDateTime();
1186
1187 return true;
1188 }
1189
1190 bool wxDataViewDateCell::Render( wxRect cell, wxDC *dc, int state )
1191 {
1192 dc->SetFont( GetOwner()->GetOwner()->GetFont() );
1193 wxString tmp = m_date.FormatDate();
1194 dc->DrawText( tmp, cell.x, cell.y );
1195
1196 return true;
1197 }
1198
1199 wxSize wxDataViewDateCell::GetSize()
1200 {
1201 wxDataViewCtrl* view = GetOwner()->GetOwner();
1202 wxString tmp = m_date.FormatDate();
1203 wxCoord x,y,d;
1204 view->GetTextExtent( tmp, &x, &y, &d );
1205 return wxSize(x,y+d);
1206 }
1207
1208 bool wxDataViewDateCell::Activate( wxRect cell, wxDataViewListModel *model, size_t col, size_t row )
1209 {
1210
1211 return true;
1212 }
1213
1214 // ---------------------------------------------------------
1215 // wxDataViewColumn
1216 // ---------------------------------------------------------
1217
1218 extern "C" {
1219 static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *column,
1220 GtkCellRenderer *cell,
1221 GtkTreeModel *model,
1222 GtkTreeIter *iter,
1223 gpointer data );
1224 }
1225
1226
1227 static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *column,
1228 GtkCellRenderer *renderer,
1229 GtkTreeModel *model,
1230 GtkTreeIter *iter,
1231 gpointer data )
1232 {
1233 g_return_if_fail (GTK_IS_WX_LIST_STORE (model));
1234 GtkWxListStore *list_store = (GtkWxListStore *) model;
1235
1236 wxDataViewCell *cell = (wxDataViewCell*) data;
1237
1238 size_t model_row = (size_t) iter->user_data;
1239
1240 wxVariant value = list_store->model->GetValue(
1241 cell->GetOwner()->GetModelColumn(), model_row );
1242
1243 if (value.GetType() != cell->GetVariantType())
1244 wxPrintf( wxT("Wrong type\n") );
1245
1246 cell->SetValue( value );
1247 }
1248
1249 IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumn, wxDataViewColumnBase)
1250
1251 wxDataViewColumn::wxDataViewColumn( const wxString &title, wxDataViewCell *cell,
1252 size_t model_column, int flags ) :
1253 wxDataViewColumnBase( title, cell, model_column, flags )
1254 {
1255 GtkCellRenderer *renderer = (GtkCellRenderer *) cell->GetGtkHandle();
1256
1257 GtkTreeViewColumn *column = gtk_tree_view_column_new();
1258
1259 gtk_tree_view_column_set_title( column, wxGTK_CONV(title) );
1260
1261 gtk_tree_view_column_pack_start( column, renderer, TRUE );
1262
1263 gtk_tree_view_column_set_cell_data_func( column, renderer,
1264 wxGtkTreeCellDataFunc, (gpointer) cell, NULL );
1265
1266 m_column = (void*) column;
1267 }
1268
1269 wxDataViewColumn::~wxDataViewColumn()
1270 {
1271 }
1272
1273 void wxDataViewColumn::SetTitle( const wxString &title )
1274 {
1275 wxDataViewColumnBase::SetTitle( title );
1276
1277 GtkTreeViewColumn *column = (GtkTreeViewColumn *)m_column;
1278 gtk_tree_view_column_set_title( column, wxGTK_CONV(title) );
1279 }
1280
1281 //-----------------------------------------------------------------------------
1282 // wxDataViewCtrl
1283 //-----------------------------------------------------------------------------
1284
1285 IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl, wxDataViewCtrlBase)
1286
1287 wxDataViewCtrl::~wxDataViewCtrl()
1288 {
1289 }
1290
1291 void wxDataViewCtrl::Init()
1292 {
1293 }
1294
1295 bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id,
1296 const wxPoint& pos, const wxSize& size,
1297 long style, const wxValidator& validator )
1298 {
1299 Init();
1300
1301 m_needParent = TRUE;
1302 m_acceptsFocus = TRUE;
1303
1304 if (!PreCreation( parent, pos, size ) ||
1305 !CreateBase( parent, id, pos, size, style, validator ))
1306 {
1307 wxFAIL_MSG( wxT("wxDataViewCtrl creation failed") );
1308 return FALSE;
1309 }
1310
1311 m_widget = gtk_scrolled_window_new (NULL, NULL);
1312 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (m_widget), GTK_SHADOW_IN);
1313
1314 m_treeview = gtk_tree_view_new();
1315 gtk_container_add (GTK_CONTAINER (m_widget), m_treeview);
1316
1317 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (m_widget),
1318 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
1319 gtk_widget_show (m_treeview);
1320
1321 m_parent->DoAddChild( this );
1322
1323 PostCreation(size);
1324
1325 return true;
1326 }
1327
1328 bool wxDataViewCtrl::AssociateModel( wxDataViewListModel *model )
1329 {
1330 if (!wxDataViewCtrlBase::AssociateModel( model ))
1331 return false;
1332
1333 GtkWxListStore *gtk_store = wxgtk_list_store_new();
1334 gtk_store->model = model;
1335
1336 wxGtkDataViewListModelNotifier *notifier =
1337 new wxGtkDataViewListModelNotifier( gtk_store, model );
1338
1339 model->SetNotifier( notifier );
1340
1341 gtk_tree_view_set_model( GTK_TREE_VIEW(m_treeview), GTK_TREE_MODEL(gtk_store) );
1342 g_object_unref( gtk_store );
1343
1344 return true;
1345 }
1346
1347 bool wxDataViewCtrl::AppendColumn( wxDataViewColumn *col )
1348 {
1349 if (!wxDataViewCtrlBase::AppendColumn(col))
1350 return false;
1351
1352 GtkTreeViewColumn *column = (GtkTreeViewColumn *)col->GetGtkHandle();
1353
1354 gtk_tree_view_append_column( GTK_TREE_VIEW(m_treeview), column );
1355
1356 return true;
1357 }
1358
1359
1360 #endif // wxUSE_DATAVIEWCTRL
1361