]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/dataview.cpp
Test commit
[wxWidgets.git] / src / gtk / dataview.cpp
CommitLineData
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
31class wxDataViewCtrl;
32
33//-----------------------------------------------------------------------------
34// idle system
35//-----------------------------------------------------------------------------
36
37extern void wxapp_install_idle_handler();
38extern bool g_isIdle;
39
40//-----------------------------------------------------------------------------
41// data
42//-----------------------------------------------------------------------------
43
44extern bool g_blockEventsOnDrag;
45
46//-----------------------------------------------------------------------------
47// define new GTK+ class wxGtkListStore
48//-----------------------------------------------------------------------------
49
50extern "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
59GType gtk_wx_list_store_get_type (void);
60
61typedef struct _GtkWxListStore GtkWxListStore;
62typedef struct _GtkWxListStoreClass GtkWxListStoreClass;
63
64struct _GtkWxListStore
65{
66 GObject parent;
67
68 /*< private >*/
69 gint stamp;
70 wxDataViewListModel *model;
71};
72
73struct _GtkWxListStoreClass
74{
75 GObjectClass parent_class;
76
77};
78
1557c77b 79static GtkWxListStore *wxgtk_list_store_new ();
790b137e 80static void wxgtk_list_store_init (GtkWxListStore *list_store);
1557c77b 81static void wxgtk_list_store_class_init (GtkWxListStoreClass *klass);
790b137e
RR
82static void wxgtk_list_store_tree_model_init (GtkTreeModelIface *iface);
83static void wxgtk_list_store_finalize (GObject *object);
84static GtkTreeModelFlags wxgtk_list_store_get_flags (GtkTreeModel *tree_model);
85static gint wxgtk_list_store_get_n_columns (GtkTreeModel *tree_model);
86static GType wxgtk_list_store_get_column_type (GtkTreeModel *tree_model,
87 gint index);
88static gboolean wxgtk_list_store_get_iter (GtkTreeModel *tree_model,
89 GtkTreeIter *iter,
90 GtkTreePath *path);
91static GtkTreePath *wxgtk_list_store_get_path (GtkTreeModel *tree_model,
92 GtkTreeIter *iter);
93static void wxgtk_list_store_get_value (GtkTreeModel *tree_model,
94 GtkTreeIter *iter,
95 gint column,
96 GValue *value);
97static gboolean wxgtk_list_store_iter_next (GtkTreeModel *tree_model,
98 GtkTreeIter *iter);
99static gboolean wxgtk_list_store_iter_children (GtkTreeModel *tree_model,
100 GtkTreeIter *iter,
101 GtkTreeIter *parent);
102static gboolean wxgtk_list_store_iter_has_child (GtkTreeModel *tree_model,
103 GtkTreeIter *iter);
104static gint wxgtk_list_store_iter_n_children (GtkTreeModel *tree_model,
105 GtkTreeIter *iter);
106static gboolean wxgtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
107 GtkTreeIter *iter,
108 GtkTreeIter *parent,
109 gint n);
110static gboolean wxgtk_list_store_iter_parent (GtkTreeModel *tree_model,
111 GtkTreeIter *iter,
112 GtkTreeIter *child);
113
790b137e
RR
114static GObjectClass *parent_class = NULL;
115
116GType
111f83c4 117gtk_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
154static GtkWxListStore *
155wxgtk_list_store_new()
156{
157 GtkWxListStore *retval = (GtkWxListStore *) g_object_new (GTK_TYPE_WX_LIST_STORE, NULL);
158 return retval;
159}
160
790b137e 161static void
1557c77b 162wxgtk_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
170static void
171wxgtk_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
187static void
188wxgtk_list_store_init (GtkWxListStore *list_store)
189{
190 list_store->model = NULL;
1557c77b 191 list_store->stamp = g_random_int();
790b137e
RR
192}
193
194static void
195wxgtk_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
213static GtkTreeModelFlags
214wxgtk_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
228static gint
229wxgtk_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
237static GType
238wxgtk_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
254static gboolean
255wxgtk_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
275static GtkTreePath *
276wxgtk_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
289static void
290wxgtk_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
332static gboolean
333wxgtk_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
354static gboolean
355wxgtk_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
372static gboolean
373wxgtk_list_store_iter_has_child (GtkTreeModel *tree_model,
374 GtkTreeIter *iter)
375{
376 return FALSE;
377}
378
379static gint
380wxgtk_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
394static gboolean
395wxgtk_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
418static gboolean
419wxgtk_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
430class wxGtkDataViewListModelNotifier: public wxDataViewListModelNotifier
431{
432public:
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
451wxGtkDataViewListModelNotifier::wxGtkDataViewListModelNotifier(
452 GtkWxListStore* gtk_store, wxDataViewListModel *wx_model )
453{
454 m_gtk_store = gtk_store;
455 m_wx_model = wx_model;
456}
457
458bool 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
474bool 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
488bool wxGtkDataViewListModelNotifier::RowInserted( size_t before )
489{
490 return false;
491}
492
493bool wxGtkDataViewListModelNotifier::RowDeleted( size_t row )
494{
495 return false;
496}
497
498bool 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 510bool wxGtkDataViewListModelNotifier::ValueChanged( size_t col, size_t row )
6e2e590f 511{
a7f61f76 512 return RowChanged( row );
6e2e590f
RR
513}
514
515bool wxGtkDataViewListModelNotifier::Cleared()
516{
517 return false;
518}
519
6842a71a
RR
520// ---------------------------------------------------------
521// wxDataViewCell
522// ---------------------------------------------------------
523
524IMPLEMENT_ABSTRACT_CLASS(wxDataViewCell, wxDataViewCellBase)
525
526wxDataViewCell::wxDataViewCell( const wxString &varianttype, wxDataViewCellMode mode ) :
527 wxDataViewCellBase( varianttype, mode )
528{
529 m_renderer = NULL;
530}
531
532// ---------------------------------------------------------
533// wxDataViewTextCell
534// ---------------------------------------------------------
535
a7f61f76
RR
536extern "C" {
537static void wxGtkTextRendererEditedCallback( GtkCellRendererText *renderer,
538 gchar *arg1, gchar *arg2, gpointer user_data );
539}
540
541static 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
563IMPLEMENT_ABSTRACT_CLASS(wxDataViewTextCell, wxDataViewCell)
564
565wxDataViewTextCell::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
582bool 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
595bool 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
612extern "C" {
613static void wxGtkToggleRendererToggledCallback( GtkCellRendererToggle *renderer,
614 gchar *path, gpointer user_data );
615}
616
617static 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
647IMPLEMENT_ABSTRACT_CLASS(wxDataViewToggleCell, wxDataViewCell)
648
649wxDataViewToggleCell::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
667bool 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
680bool 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
697extern "C" {
698static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *column,
699 GtkCellRenderer *cell,
700 GtkTreeModel *model,
701 GtkTreeIter *iter,
702 gpointer data );
703}
704
705
706static 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
728IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumn, wxDataViewColumnBase)
729
6842a71a
RR
730wxDataViewColumn::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
748wxDataViewColumn::~wxDataViewColumn()
749{
750}
751
752void 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
764IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl, wxDataViewCtrlBase)
765
766wxDataViewCtrl::~wxDataViewCtrl()
767{
768}
769
770void wxDataViewCtrl::Init()
771{
772}
773
774bool 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 799bool 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
817bool 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