]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/dataview.cpp
wxCocoa: Basic support for font underlining:
[wxWidgets.git] / src / gtk / dataview.cpp
CommitLineData
790b137e 1/////////////////////////////////////////////////////////////////////////////
93763ad5 2// Name: src/gtk/dataview.cpp
790b137e
RR
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
790b137e
RR
13#if wxUSE_DATAVIEWCTRL
14
15#include "wx/dataview.h"
4ed7af08
RR
16
17#ifndef wxUSE_GENERICDATAVIEWCTRL
18
e4db172a
WS
19#ifndef WX_PRECOMP
20 #include "wx/log.h"
ed4b0fdc 21 #include "wx/dcclient.h"
ed2fbeb8 22 #include "wx/sizer.h"
e4db172a
WS
23#endif
24
790b137e 25#include "wx/stockitem.h"
7ea3a0de
RR
26#include "wx/calctrl.h"
27#include "wx/popupwin.h"
2586d4a1
RR
28#include "wx/icon.h"
29
790b137e
RR
30
31#include "wx/gtk/private.h"
32#include "wx/gtk/win_gtk.h"
33
34#include <gobject/gvaluecollector.h>
1557c77b 35#include <gtk/gtktreemodel.h>
773cca48 36#include <gtk/gtktreesortable.h>
1557c77b 37#include <gtk/gtktreednd.h>
790b137e 38
4d496ecb
RR
39#include <gdk/gdkkeysyms.h>
40
790b137e 41//-----------------------------------------------------------------------------
790b137e
RR
42//-----------------------------------------------------------------------------
43
af110130 44wxDataViewModel *g_model = NULL;
3b6280be
RR
45
46class wxGtkTreeModelNode;
ef427989 47
0be79c8a
RR
48extern "C" {
49typedef struct _GtkWxTreeModel GtkWxTreeModel;
50}
51
af110130
RR
52//-----------------------------------------------------------------------------
53// wxDataViewCtrlInternal
54//-----------------------------------------------------------------------------
55
56class wxDataViewCtrlInternal
57{
58public:
59 wxDataViewCtrlInternal( wxDataViewCtrl *owner, wxDataViewModel *wx_model, GtkWxTreeModel *owner );
60 ~wxDataViewCtrlInternal();
61
62 gboolean get_iter( GtkTreeIter *iter, GtkTreePath *path );
63 GtkTreePath *get_path( GtkTreeIter *iter);
64 GtkTreePath *get_path_safe( GtkTreeIter *iter);
65 gboolean iter_next( GtkTreeIter *iter );
66 gboolean iter_children( GtkTreeIter *iter, GtkTreeIter *parent);
67 gboolean iter_has_child( GtkTreeIter *iter );
68 gint iter_n_children( GtkTreeIter *iter );
69 gboolean iter_nth_child( GtkTreeIter *iter, GtkTreeIter *parent, gint n );
70 gboolean iter_parent( GtkTreeIter *iter, GtkTreeIter *child );
71
72 wxDataViewModel* GetDataViewModel() { return m_wx_model; }
73 wxDataViewCtrl* GetOwner() { return m_owner; }
74 GtkWxTreeModel* GetGtkModel() { return m_gtk_model; }
75
76 bool ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item );
77 bool ItemDeleted( const wxDataViewItem &item );
78
79 void Resort();
80
81protected:
82 void InitTree();
83 wxGtkTreeModelNode *FindNode( const wxDataViewItem &item );
84 wxGtkTreeModelNode *FindNode( GtkTreeIter *iter );
85 wxGtkTreeModelNode *FindParentNode( const wxDataViewItem &item );
86 wxGtkTreeModelNode *FindParentNode( GtkTreeIter *iter );
87 void BuildBranch( wxGtkTreeModelNode *branch );
88
89private:
90 wxGtkTreeModelNode *m_root;
91 wxDataViewModel *m_wx_model;
92 GtkWxTreeModel *m_gtk_model;
93 wxDataViewCtrl *m_owner;
94};
ef427989 95
af110130
RR
96
97//-----------------------------------------------------------------------------
98// wxGtkTreeModelNode
99//-----------------------------------------------------------------------------
100
101int LINKAGEMODE wxGtkTreeModelNodeCmp( void *id1, void *id2 );
102
103WX_DEFINE_ARRAY_PTR( wxGtkTreeModelNode*, wxGtkTreeModelNodes );
104WX_DEFINE_SORTED_ARRAY( void* , wxGtkTreeModelChildren );
3b6280be
RR
105
106class wxGtkTreeModelNode
107{
108public:
ef427989 109 wxGtkTreeModelNode( wxGtkTreeModelNode* parent, const wxDataViewItem &item,
0be79c8a 110 wxDataViewCtrlInternal *internal )
3b6280be
RR
111 {
112 m_parent = parent;
d5025dc0 113 m_item = item;
0be79c8a 114 m_internal = internal;
af110130
RR
115 g_model = internal->GetDataViewModel();
116 m_children = new wxGtkTreeModelChildren( wxGtkTreeModelNodeCmp );
3b6280be
RR
117 }
118
119 ~wxGtkTreeModelNode()
120 {
4508fcd2 121 size_t count = m_children->GetCount();
3b6280be
RR
122 size_t i;
123 for (i = 0; i < count; i++)
124 {
af110130 125 wxGtkTreeModelNode *child = m_nodes.Item( i );
3b6280be
RR
126 delete child;
127 }
4508fcd2 128 delete m_children;
3b6280be
RR
129 }
130
af110130
RR
131 unsigned int AddNode( wxGtkTreeModelNode* child )
132 {
133 m_nodes.Add( child );
134 return m_children->Add( child->GetItem().GetID() );
135 }
136
137 unsigned int AddLeave( void* id )
138 {
139 return m_children->Add( id );
140 }
141
142 void DeleteChild( void* id )
143 {
144 size_t pos;
145 size_t count = m_children->GetCount();
146 for (pos = 0; pos < count; pos++)
147 {
148 if (m_children->Item( pos ) == id)
149 {
150 m_children->RemoveAt( pos );
151 break;
152 }
153 }
154 count = m_nodes.GetCount();
155 for (pos = 0; pos < count; pos++)
156 {
157 wxGtkTreeModelNode *node = m_nodes.Item( pos );
158 if (node->GetItem().GetID() == id)
159 {
160 m_nodes.RemoveAt( pos );
161 delete node;
162 break;
163 }
164 }
165
166 }
167
3b6280be
RR
168 wxGtkTreeModelNode* GetParent()
169 { return m_parent; }
af110130
RR
170 wxGtkTreeModelNodes &GetNodes()
171 { return m_nodes; }
172 wxGtkTreeModelChildren &GetChildren()
4508fcd2 173 { return *m_children; }
4508fcd2
RR
174
175 unsigned int GetChildCount() { return m_children->GetCount(); }
af110130 176 unsigned int GetNodesCount() { return m_nodes.GetCount(); }
3b6280be
RR
177
178 wxDataViewItem &GetItem() { return m_item; }
0be79c8a 179 wxDataViewCtrlInternal *GetInternal() { return m_internal; }
3b6280be 180
4508fcd2
RR
181 void Resort();
182
3b6280be 183private:
0be79c8a 184 wxGtkTreeModelNode *m_parent;
af110130
RR
185 wxGtkTreeModelNodes m_nodes;
186 wxGtkTreeModelChildren *m_children;
0be79c8a 187 wxDataViewItem m_item;
0be79c8a 188 wxDataViewCtrlInternal *m_internal;
3b6280be
RR
189};
190
ef427989 191
af110130 192int LINKAGEMODE wxGtkTreeModelNodeCmp( void* id1, void* id2 )
3b6280be 193{
af110130 194 return g_model->Compare( id1, id2 );
0be79c8a
RR
195}
196
790b137e
RR
197//-----------------------------------------------------------------------------
198// data
199//-----------------------------------------------------------------------------
200
201extern bool g_blockEventsOnDrag;
202
203//-----------------------------------------------------------------------------
e0062c04 204// define new GTK+ class wxGtkTreeModel
790b137e
RR
205//-----------------------------------------------------------------------------
206
207extern "C" {
208
e0062c04
RR
209#define GTK_TYPE_WX_TREE_MODEL (gtk_wx_tree_model_get_type ())
210#define GTK_WX_TREE_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WX_TREE_MODEL, GtkWxTreeModel))
211#define GTK_WX_TREE_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WX_TREE_MODEL, GtkWxTreeModelClass))
212#define GTK_IS_WX_TREE_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WX_TREE_MODEL))
213#define GTK_IS_WX_TREE_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WX_TREE_MODEL))
214#define GTK_WX_TREE_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WX_TREE_MODEL, GtkWxTreeModelClass))
790b137e 215
e0062c04 216GType gtk_wx_tree_model_get_type (void);
790b137e 217
e0062c04 218typedef struct _GtkWxTreeModelClass GtkWxTreeModelClass;
790b137e 219
e0062c04 220struct _GtkWxTreeModel
790b137e
RR
221{
222 GObject parent;
223
224 /*< private >*/
225 gint stamp;
55fbde12 226 wxDataViewCtrlInternal *internal;
790b137e
RR
227};
228
e0062c04 229struct _GtkWxTreeModelClass
790b137e 230{
e152afc3 231 GObjectClass list_parent_class;
790b137e
RR
232};
233
e0062c04 234static GtkWxTreeModel *wxgtk_tree_model_new (void);
773cca48
RR
235static void wxgtk_tree_model_init (GtkWxTreeModel *tree_model);
236static void wxgtk_tree_model_class_init (GtkWxTreeModelClass *klass);
237static void wxgtk_tree_model_tree_model_init (GtkTreeModelIface *iface);
238static void wxgtk_tree_model_sortable_init (GtkTreeSortableIface *iface);
e0062c04
RR
239static void wxgtk_tree_model_finalize (GObject *object);
240static GtkTreeModelFlags wxgtk_tree_model_get_flags (GtkTreeModel *tree_model);
241static gint wxgtk_tree_model_get_n_columns (GtkTreeModel *tree_model);
242static GType wxgtk_tree_model_get_column_type (GtkTreeModel *tree_model,
93763ad5 243 gint index);
e0062c04 244static gboolean wxgtk_tree_model_get_iter (GtkTreeModel *tree_model,
93763ad5
WS
245 GtkTreeIter *iter,
246 GtkTreePath *path);
e0062c04 247static GtkTreePath *wxgtk_tree_model_get_path (GtkTreeModel *tree_model,
93763ad5 248 GtkTreeIter *iter);
ef427989
RR
249static GtkTreePath *wxgtk_tree_model_get_path_safe (GtkTreeModel *tree_model,
250 GtkTreeIter *iter);
e0062c04 251static void wxgtk_tree_model_get_value (GtkTreeModel *tree_model,
93763ad5
WS
252 GtkTreeIter *iter,
253 gint column,
254 GValue *value);
e0062c04 255static gboolean wxgtk_tree_model_iter_next (GtkTreeModel *tree_model,
93763ad5 256 GtkTreeIter *iter);
e0062c04 257static gboolean wxgtk_tree_model_iter_children (GtkTreeModel *tree_model,
93763ad5
WS
258 GtkTreeIter *iter,
259 GtkTreeIter *parent);
e0062c04 260static gboolean wxgtk_tree_model_iter_has_child (GtkTreeModel *tree_model,
93763ad5 261 GtkTreeIter *iter);
e0062c04 262static gint wxgtk_tree_model_iter_n_children (GtkTreeModel *tree_model,
93763ad5 263 GtkTreeIter *iter);
e0062c04 264static gboolean wxgtk_tree_model_iter_nth_child (GtkTreeModel *tree_model,
93763ad5
WS
265 GtkTreeIter *iter,
266 GtkTreeIter *parent,
267 gint n);
e0062c04 268static gboolean wxgtk_tree_model_iter_parent (GtkTreeModel *tree_model,
93763ad5
WS
269 GtkTreeIter *iter,
270 GtkTreeIter *child);
790b137e 271
773cca48
RR
272/* sortable */
273static gboolean wxgtk_tree_model_get_sort_column_id (GtkTreeSortable *sortable,
274 gint *sort_column_id,
275 GtkSortType *order);
276static void wxgtk_tree_model_set_sort_column_id (GtkTreeSortable *sortable,
277 gint sort_column_id,
278 GtkSortType order);
279static void wxgtk_tree_model_set_sort_func (GtkTreeSortable *sortable,
280 gint sort_column_id,
281 GtkTreeIterCompareFunc func,
282 gpointer data,
283 GtkDestroyNotify destroy);
284static void wxgtk_tree_model_set_default_sort_func (GtkTreeSortable *sortable,
285 GtkTreeIterCompareFunc func,
286 gpointer data,
287 GtkDestroyNotify destroy);
288static gboolean wxgtk_tree_model_has_default_sort_func (GtkTreeSortable *sortable);
289
290
291
e152afc3 292static GObjectClass *list_parent_class = NULL;
790b137e
RR
293
294GType
e0062c04 295gtk_wx_tree_model_get_type (void)
790b137e 296{
e0062c04 297 static GType tree_model_type = 0;
790b137e 298
e0062c04 299 if (!tree_model_type)
790b137e 300 {
e0062c04 301 const GTypeInfo tree_model_info =
93763ad5 302 {
e0062c04 303 sizeof (GtkWxTreeModelClass),
93763ad5
WS
304 NULL, /* base_init */
305 NULL, /* base_finalize */
e0062c04 306 (GClassInitFunc) wxgtk_tree_model_class_init,
93763ad5
WS
307 NULL, /* class_finalize */
308 NULL, /* class_data */
e0062c04 309 sizeof (GtkWxTreeModel),
93763ad5 310 0,
e0062c04 311 (GInstanceInitFunc) wxgtk_tree_model_init,
93763ad5 312 };
790b137e 313
773cca48
RR
314 static const GInterfaceInfo tree_model_iface_info =
315 {
316 (GInterfaceInitFunc) wxgtk_tree_model_tree_model_init,
317 NULL,
318 NULL
319 };
320
321 static const GInterfaceInfo sortable_iface_info =
322 {
323 (GInterfaceInitFunc) wxgtk_tree_model_sortable_init,
324 NULL,
325 NULL
326 };
790b137e 327
773cca48 328 tree_model_type = g_type_register_static (G_TYPE_OBJECT, "GtkWxTreeModel",
e0062c04 329 &tree_model_info, (GTypeFlags)0 );
790b137e 330
773cca48
RR
331 g_type_add_interface_static (tree_model_type,
332 GTK_TYPE_TREE_MODEL,
333 &tree_model_iface_info);
334 g_type_add_interface_static (tree_model_type,
335 GTK_TYPE_TREE_SORTABLE,
336 &sortable_iface_info);
790b137e
RR
337 }
338
773cca48 339 return tree_model_type;
790b137e
RR
340}
341
e0062c04
RR
342static GtkWxTreeModel *
343wxgtk_tree_model_new(void)
1557c77b 344{
e0062c04 345 GtkWxTreeModel *retval = (GtkWxTreeModel *) g_object_new (GTK_TYPE_WX_TREE_MODEL, NULL);
e152afc3 346 return retval;
1557c77b
RR
347}
348
790b137e 349static void
e0062c04 350wxgtk_tree_model_class_init (GtkWxTreeModelClass *klass)
790b137e 351{
e152afc3
RR
352 list_parent_class = (GObjectClass*) g_type_class_peek_parent (klass);
353 GObjectClass *object_class = (GObjectClass*) klass;
e0062c04 354 object_class->finalize = wxgtk_tree_model_finalize;
790b137e
RR
355}
356
357static void
e0062c04
RR
358wxgtk_tree_model_tree_model_init (GtkTreeModelIface *iface)
359{
360 iface->get_flags = wxgtk_tree_model_get_flags;
361 iface->get_n_columns = wxgtk_tree_model_get_n_columns;
362 iface->get_column_type = wxgtk_tree_model_get_column_type;
363 iface->get_iter = wxgtk_tree_model_get_iter;
364 iface->get_path = wxgtk_tree_model_get_path;
365 iface->get_value = wxgtk_tree_model_get_value;
366 iface->iter_next = wxgtk_tree_model_iter_next;
367 iface->iter_children = wxgtk_tree_model_iter_children;
368 iface->iter_has_child = wxgtk_tree_model_iter_has_child;
369 iface->iter_n_children = wxgtk_tree_model_iter_n_children;
370 iface->iter_nth_child = wxgtk_tree_model_iter_nth_child;
371 iface->iter_parent = wxgtk_tree_model_iter_parent;
790b137e
RR
372}
373
773cca48
RR
374static void
375wxgtk_tree_model_sortable_init (GtkTreeSortableIface *iface)
376{
94b1f7bc
RR
377 iface->get_sort_column_id = wxgtk_tree_model_get_sort_column_id;
378 iface->set_sort_column_id = wxgtk_tree_model_set_sort_column_id;
379 iface->set_sort_func = wxgtk_tree_model_set_sort_func;
380 iface->set_default_sort_func = wxgtk_tree_model_set_default_sort_func;
381 iface->has_default_sort_func = wxgtk_tree_model_has_default_sort_func;
773cca48
RR
382}
383
790b137e 384static void
e0062c04 385wxgtk_tree_model_init (GtkWxTreeModel *tree_model)
790b137e 386{
55fbde12 387 tree_model->internal = NULL;
e0062c04 388 tree_model->stamp = g_random_int();
790b137e
RR
389}
390
391static void
e0062c04 392wxgtk_tree_model_finalize (GObject *object)
790b137e 393{
790b137e 394 /* must chain up */
e152afc3 395 (* list_parent_class->finalize) (object);
790b137e 396}
93763ad5 397
790b137e
RR
398} // extern "C"
399
400//-----------------------------------------------------------------------------
e0062c04
RR
401// implement callbacks from wxGtkTreeModel class by letting
402// them call the methods of wxWidgets' wxDataViewModel
790b137e
RR
403//-----------------------------------------------------------------------------
404
405static GtkTreeModelFlags
e0062c04 406wxgtk_tree_model_get_flags (GtkTreeModel *tree_model)
790b137e 407{
e0062c04 408 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (tree_model), (GtkTreeModelFlags)0 );
790b137e 409
e0062c04 410 return GTK_TREE_MODEL_ITERS_PERSIST;
790b137e
RR
411}
412
413static gint
e0062c04 414wxgtk_tree_model_get_n_columns (GtkTreeModel *tree_model)
790b137e 415{
e0062c04
RR
416 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
417 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), 0);
790b137e 418
55fbde12 419 return wxtree_model->internal->GetDataViewModel()->GetColumnCount();
790b137e
RR
420}
421
422static GType
e0062c04 423wxgtk_tree_model_get_column_type (GtkTreeModel *tree_model,
93763ad5 424 gint index)
790b137e 425{
e0062c04
RR
426 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
427 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), G_TYPE_INVALID);
790b137e 428
1557c77b 429 GType gtype = G_TYPE_INVALID;
93763ad5 430
55fbde12 431 wxString wxtype = wxtree_model->internal->GetDataViewModel()->GetColumnType( (unsigned int) index );
93763ad5 432
1557c77b
RR
433 if (wxtype == wxT("string"))
434 gtype = G_TYPE_STRING;
72a3ac9b
VZ
435 else
436 {
437 wxFAIL_MSG( _T("non-string columns not supported yet") );
438 }
790b137e
RR
439
440 return gtype;
441}
442
443static gboolean
e0062c04 444wxgtk_tree_model_get_iter (GtkTreeModel *tree_model,
93763ad5
WS
445 GtkTreeIter *iter,
446 GtkTreePath *path)
790b137e 447{
e0062c04
RR
448 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
449 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE);
790b137e
RR
450 g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
451
55fbde12 452 return wxtree_model->internal->get_iter( iter, path );
790b137e
RR
453}
454
455static GtkTreePath *
e0062c04 456wxgtk_tree_model_get_path (GtkTreeModel *tree_model,
93763ad5 457 GtkTreeIter *iter)
790b137e 458{
e0062c04
RR
459 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
460 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), NULL);
461 g_return_val_if_fail (iter->stamp == GTK_WX_TREE_MODEL (wxtree_model)->stamp, NULL);
93763ad5 462
55fbde12 463 return wxtree_model->internal->get_path( iter );
790b137e
RR
464}
465
ef427989
RR
466static GtkTreePath *
467wxgtk_tree_model_get_path_safe (GtkTreeModel *tree_model,
468 GtkTreeIter *iter)
469{
470 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
471 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), NULL);
472 g_return_val_if_fail (iter->stamp == GTK_WX_TREE_MODEL (wxtree_model)->stamp, NULL);
473
474 return wxtree_model->internal->get_path_safe( iter );
475}
476
790b137e 477static void
e0062c04 478wxgtk_tree_model_get_value (GtkTreeModel *tree_model,
93763ad5
WS
479 GtkTreeIter *iter,
480 gint column,
481 GValue *value)
790b137e 482{
e0062c04
RR
483 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
484 g_return_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model) );
239eaa41 485
55fbde12 486 wxDataViewModel *model = wxtree_model->internal->GetDataViewModel();
9861f022 487 wxString mtype = model->GetColumnType( (unsigned int) column );
1557c77b
RR
488 if (mtype == wxT("string"))
489 {
3f3af7e7 490 wxVariant variant;
1557c77b 491 g_value_init( value, G_TYPE_STRING );
9d52aad3 492 wxDataViewItem item( (void*) iter->user_data );
e0062c04 493 model->GetValue( variant, item, (unsigned int) column );
72a3ac9b 494
e0062c04 495 g_value_set_string( value, variant.GetString().utf8_str() );
1557c77b
RR
496 }
497 else
498 {
72a3ac9b 499 wxFAIL_MSG( _T("non-string columns not supported yet") );
1557c77b 500 }
790b137e
RR
501}
502
503static gboolean
e0062c04 504wxgtk_tree_model_iter_next (GtkTreeModel *tree_model,
93763ad5 505 GtkTreeIter *iter)
790b137e 506{
e0062c04
RR
507 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
508 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE);
e0062c04 509 g_return_val_if_fail (wxtree_model->stamp == iter->stamp, FALSE);
93763ad5 510
55fbde12 511 return wxtree_model->internal->iter_next( iter );
790b137e
RR
512}
513
514static gboolean
e0062c04 515wxgtk_tree_model_iter_children (GtkTreeModel *tree_model,
93763ad5
WS
516 GtkTreeIter *iter,
517 GtkTreeIter *parent)
790b137e 518{
e0062c04
RR
519 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
520 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE);
e0062c04 521 g_return_val_if_fail (wxtree_model->stamp == parent->stamp, FALSE);
790b137e 522
55fbde12 523 return wxtree_model->internal->iter_children( iter, parent );
790b137e
RR
524}
525
526static gboolean
e0062c04 527wxgtk_tree_model_iter_has_child (GtkTreeModel *tree_model,
93763ad5 528 GtkTreeIter *iter)
790b137e 529{
e0062c04
RR
530 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
531 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE);
e0062c04 532 g_return_val_if_fail (wxtree_model->stamp == iter->stamp, FALSE);
d5025dc0 533
55fbde12 534 return wxtree_model->internal->iter_has_child( iter );
790b137e
RR
535}
536
537static gint
e0062c04 538wxgtk_tree_model_iter_n_children (GtkTreeModel *tree_model,
93763ad5 539 GtkTreeIter *iter)
790b137e 540{
e0062c04
RR
541 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
542 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE);
e0062c04 543 g_return_val_if_fail (wxtree_model->stamp == iter->stamp, 0);
d5025dc0 544
55fbde12 545 return wxtree_model->internal->iter_n_children( iter );
790b137e
RR
546}
547
548static gboolean
e0062c04 549wxgtk_tree_model_iter_nth_child (GtkTreeModel *tree_model,
93763ad5
WS
550 GtkTreeIter *iter,
551 GtkTreeIter *parent,
552 gint n)
790b137e 553{
e0062c04
RR
554 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
555 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE);
556
55fbde12 557 return wxtree_model->internal->iter_nth_child( iter, parent, n );
790b137e
RR
558}
559
560static gboolean
e0062c04 561wxgtk_tree_model_iter_parent (GtkTreeModel *tree_model,
93763ad5
WS
562 GtkTreeIter *iter,
563 GtkTreeIter *child)
790b137e 564{
e0062c04
RR
565 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
566 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE);
e0062c04
RR
567 g_return_val_if_fail (wxtree_model->stamp == child->stamp, FALSE);
568
55fbde12 569 return wxtree_model->internal->iter_parent( iter, child );
790b137e
RR
570}
571
773cca48
RR
572/* sortable */
573gboolean wxgtk_tree_model_get_sort_column_id (GtkTreeSortable *sortable,
574 gint *sort_column_id,
575 GtkSortType *order)
576{
94b1f7bc
RR
577 GtkWxTreeModel *tree_model = (GtkWxTreeModel *) sortable;
578
579 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (sortable), FALSE);
580
94b1f7bc 581 if (sort_column_id)
ef427989 582 *sort_column_id = tree_model->internal->GetDataViewModel()->GetSortingColumn();
94b1f7bc
RR
583
584 if (order)
ef427989
RR
585 {
586 bool ascending = tree_model->internal->GetDataViewModel()->GetSortOrderAscending();
587 if (ascending)
588 *order = GTK_SORT_ASCENDING;
589 else
590 *order = GTK_SORT_DESCENDING;
591 }
94b1f7bc
RR
592
593 return TRUE;
773cca48
RR
594}
595
596void wxgtk_tree_model_set_sort_column_id (GtkTreeSortable *sortable,
597 gint sort_column_id,
598 GtkSortType order)
599{
94b1f7bc 600 GtkWxTreeModel *tree_model = (GtkWxTreeModel *) sortable;
94b1f7bc
RR
601 g_return_if_fail (GTK_IS_WX_TREE_MODEL (sortable) );
602
ef427989
RR
603 bool ascending = TRUE;
604 if (order != GTK_SORT_ASCENDING)
605 ascending = FALSE;
0be79c8a 606
af110130 607 if ((sort_column_id == (gint) tree_model->internal->GetDataViewModel()->GetSortingColumn()) &&
0be79c8a
RR
608 (ascending == tree_model->internal->GetDataViewModel()->GetSortOrderAscending()))
609 return;
610
611 tree_model->internal->GetDataViewModel()->SetSortingColumn( sort_column_id );
612
ef427989
RR
613 tree_model->internal->GetDataViewModel()->SetSortOrderAscending( ascending );
614
0be79c8a
RR
615 gtk_tree_sortable_sort_column_changed (sortable);
616
ef427989 617 tree_model->internal->GetDataViewModel()->Resort();
773cca48
RR
618}
619
620void wxgtk_tree_model_set_sort_func (GtkTreeSortable *sortable,
621 gint sort_column_id,
622 GtkTreeIterCompareFunc func,
623 gpointer data,
624 GtkDestroyNotify destroy)
625{
94b1f7bc
RR
626 g_return_if_fail (GTK_IS_WX_TREE_MODEL (sortable) );
627 g_return_if_fail (func != NULL);
773cca48
RR
628}
629
630void wxgtk_tree_model_set_default_sort_func (GtkTreeSortable *sortable,
631 GtkTreeIterCompareFunc func,
632 gpointer data,
633 GtkDestroyNotify destroy)
634{
94b1f7bc 635 g_return_if_fail (GTK_IS_WX_TREE_MODEL (sortable) );
94b1f7bc
RR
636 g_return_if_fail (func != NULL);
637
94b1f7bc 638 wxPrintf( "wxgtk_tree_model_set_default_sort_func\n" );
773cca48
RR
639}
640
641gboolean wxgtk_tree_model_has_default_sort_func (GtkTreeSortable *sortable)
642{
643 return FALSE;
644}
645
e152afc3 646//-----------------------------------------------------------------------------
baa9ebc4 647// define new GTK+ class wxGtkRendererRenderer
e152afc3
RR
648//-----------------------------------------------------------------------------
649
650extern "C" {
651
652#define GTK_TYPE_WX_CELL_RENDERER (gtk_wx_cell_renderer_get_type ())
653#define GTK_WX_CELL_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRenderer))
654#define GTK_WX_CELL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRendererClass))
655#define GTK_IS_WX_CELL_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WX_CELL_RENDERER))
656#define GTK_IS_WX_CELL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WX_CELL_RENDERER))
657#define GTK_WX_CELL_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRendererClass))
658
659GType gtk_wx_cell_renderer_get_type (void);
660
661typedef struct _GtkWxCellRenderer GtkWxCellRenderer;
662typedef struct _GtkWxCellRendererClass GtkWxCellRendererClass;
663
664struct _GtkWxCellRenderer
665{
666 GtkCellRenderer parent;
667
668 /*< private >*/
baa9ebc4 669 wxDataViewCustomRenderer *cell;
4d496ecb 670 guint32 last_click;
e152afc3
RR
671};
672
673struct _GtkWxCellRendererClass
674{
675 GtkCellRendererClass cell_parent_class;
e152afc3
RR
676};
677
678
679static GtkCellRenderer *gtk_wx_cell_renderer_new (void);
553f7d8f
RR
680static void gtk_wx_cell_renderer_init (
681 GtkWxCellRenderer *cell );
682static void gtk_wx_cell_renderer_class_init(
683 GtkWxCellRendererClass *klass );
684static void gtk_wx_cell_renderer_finalize (
685 GObject *object );
686static void gtk_wx_cell_renderer_get_size (
687 GtkCellRenderer *cell,
93763ad5
WS
688 GtkWidget *widget,
689 GdkRectangle *rectangle,
690 gint *x_offset,
691 gint *y_offset,
692 gint *width,
693 gint *height );
553f7d8f
RR
694static void gtk_wx_cell_renderer_render (
695 GtkCellRenderer *cell,
93763ad5
WS
696 GdkWindow *window,
697 GtkWidget *widget,
698 GdkRectangle *background_area,
699 GdkRectangle *cell_area,
700 GdkRectangle *expose_area,
701 GtkCellRendererState flags );
553f7d8f
RR
702static gboolean gtk_wx_cell_renderer_activate(
703 GtkCellRenderer *cell,
704 GdkEvent *event,
705 GtkWidget *widget,
706 const gchar *path,
707 GdkRectangle *background_area,
708 GdkRectangle *cell_area,
709 GtkCellRendererState flags );
1e510b1e
RR
710static GtkCellEditable *gtk_wx_cell_renderer_start_editing(
711 GtkCellRenderer *cell,
712 GdkEvent *event,
713 GtkWidget *widget,
714 const gchar *path,
715 GdkRectangle *background_area,
716 GdkRectangle *cell_area,
717 GtkCellRendererState flags );
e8375af8 718
e152afc3
RR
719
720static GObjectClass *cell_parent_class = NULL;
721
722} // extern "C"
723
93763ad5 724GType
e152afc3
RR
725gtk_wx_cell_renderer_get_type (void)
726{
553f7d8f 727 static GType cell_wx_type = 0;
e152afc3 728
553f7d8f 729 if (!cell_wx_type)
e152afc3 730 {
de4a74e2 731 const GTypeInfo cell_wx_info =
553f7d8f
RR
732 {
733 sizeof (GtkWxCellRendererClass),
93763ad5
WS
734 NULL, /* base_init */
735 NULL, /* base_finalize */
553f7d8f 736 (GClassInitFunc) gtk_wx_cell_renderer_class_init,
93763ad5
WS
737 NULL, /* class_finalize */
738 NULL, /* class_data */
553f7d8f
RR
739 sizeof (GtkWxCellRenderer),
740 0, /* n_preallocs */
741 (GInstanceInitFunc) gtk_wx_cell_renderer_init,
742 };
743
93763ad5 744 cell_wx_type = g_type_register_static( GTK_TYPE_CELL_RENDERER,
553f7d8f 745 "GtkWxCellRenderer", &cell_wx_info, (GTypeFlags)0 );
e152afc3
RR
746 }
747
553f7d8f 748 return cell_wx_type;
e152afc3
RR
749}
750
751static void
752gtk_wx_cell_renderer_init (GtkWxCellRenderer *cell)
753{
754 cell->cell = NULL;
4d496ecb 755 cell->last_click = 0;
e152afc3
RR
756}
757
758static void
759gtk_wx_cell_renderer_class_init (GtkWxCellRendererClass *klass)
760{
761 GObjectClass *object_class = G_OBJECT_CLASS (klass);
762 GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
763
764 cell_parent_class = (GObjectClass*) g_type_class_peek_parent (klass);
765
766 object_class->finalize = gtk_wx_cell_renderer_finalize;
767
768 cell_class->get_size = gtk_wx_cell_renderer_get_size;
769 cell_class->render = gtk_wx_cell_renderer_render;
553f7d8f 770 cell_class->activate = gtk_wx_cell_renderer_activate;
1e510b1e 771 cell_class->start_editing = gtk_wx_cell_renderer_start_editing;
e152afc3
RR
772}
773
774static void
775gtk_wx_cell_renderer_finalize (GObject *object)
776{
777 /* must chain up */
778 (* G_OBJECT_CLASS (cell_parent_class)->finalize) (object);
779}
780
781GtkCellRenderer*
782gtk_wx_cell_renderer_new (void)
783{
784 return (GtkCellRenderer*) g_object_new (GTK_TYPE_WX_CELL_RENDERER, NULL);
785}
786
1e510b1e
RR
787
788
789static GtkCellEditable *gtk_wx_cell_renderer_start_editing(
790 GtkCellRenderer *renderer,
791 GdkEvent *event,
792 GtkWidget *widget,
793 const gchar *path,
794 GdkRectangle *background_area,
795 GdkRectangle *cell_area,
796 GtkCellRendererState flags )
797{
798 GtkWxCellRenderer *wxrenderer = (GtkWxCellRenderer *) renderer;
799 wxDataViewCustomRenderer *cell = wxrenderer->cell;
800 if (!cell->HasEditorCtrl())
801 return NULL;
e8375af8 802
1e510b1e
RR
803 GdkRectangle rect;
804 gtk_wx_cell_renderer_get_size (renderer, widget, cell_area,
805 &rect.x,
806 &rect.y,
807 &rect.width,
808 &rect.height);
809
810 rect.x += cell_area->x;
811 rect.y += cell_area->y;
812// rect.width -= renderer->xpad * 2;
813// rect.height -= renderer->ypad * 2;
814
815// wxRect renderrect( rect.x, rect.y, rect.width, rect.height );
816 wxRect renderrect( cell_area->x, cell_area->y, cell_area->width, cell_area->height );
817
1e510b1e 818 GtkTreePath *treepath = gtk_tree_path_new_from_string( path );
55fbde12
RR
819 GtkTreeIter iter;
820 cell->GetOwner()->GetOwner()->GtkGetInternal()->get_iter( &iter, treepath );
821 wxDataViewItem item( (void*) iter.user_data );
1e510b1e
RR
822 gtk_tree_path_free( treepath );
823
9d52aad3 824 cell->StartEditing( item, renderrect );
30715fa1 825
1e510b1e
RR
826 return NULL;
827}
828
e152afc3
RR
829static void
830gtk_wx_cell_renderer_get_size (GtkCellRenderer *renderer,
93763ad5
WS
831 GtkWidget *widget,
832 GdkRectangle *cell_area,
833 gint *x_offset,
834 gint *y_offset,
835 gint *width,
836 gint *height)
e152afc3
RR
837{
838 GtkWxCellRenderer *wxrenderer = (GtkWxCellRenderer *) renderer;
baa9ebc4 839 wxDataViewCustomRenderer *cell = wxrenderer->cell;
93763ad5 840
e152afc3
RR
841 wxSize size = cell->GetSize();
842
843 gint calc_width = (gint) renderer->xpad * 2 + size.x;
844 gint calc_height = (gint) renderer->ypad * 2 + size.y;
93763ad5
WS
845
846 if (x_offset)
e152afc3 847 *x_offset = 0;
93763ad5 848 if (y_offset)
e152afc3
RR
849 *y_offset = 0;
850
851 if (cell_area && size.x > 0 && size.y > 0)
852 {
853 if (x_offset)
93763ad5 854 {
e152afc3
RR
855 *x_offset = (gint)((renderer->xalign *
856 (cell_area->width - calc_width - 2 * renderer->xpad)));
857 *x_offset = MAX (*x_offset, 0) + renderer->xpad;
93763ad5 858 }
e152afc3
RR
859 if (y_offset)
860 {
861 *y_offset = (gint)((renderer->yalign *
862 (cell_area->height - calc_height - 2 * renderer->ypad)));
863 *y_offset = MAX (*y_offset, 0) + renderer->ypad;
864 }
865 }
866
867 if (width)
868 *width = calc_width;
93763ad5 869
e152afc3
RR
870 if (height)
871 *height = calc_height;
872}
873
874static void
875gtk_wx_cell_renderer_render (GtkCellRenderer *renderer,
93763ad5
WS
876 GdkWindow *window,
877 GtkWidget *widget,
878 GdkRectangle *background_area,
879 GdkRectangle *cell_area,
880 GdkRectangle *expose_area,
881 GtkCellRendererState flags)
e152afc3
RR
882
883{
884 GtkWxCellRenderer *wxrenderer = (GtkWxCellRenderer *) renderer;
baa9ebc4 885 wxDataViewCustomRenderer *cell = wxrenderer->cell;
93763ad5 886
e152afc3
RR
887 GdkRectangle rect;
888 gtk_wx_cell_renderer_get_size (renderer, widget, cell_area,
93763ad5
WS
889 &rect.x,
890 &rect.y,
891 &rect.width,
892 &rect.height);
e152afc3
RR
893
894 rect.x += cell_area->x;
895 rect.y += cell_area->y;
896 rect.width -= renderer->xpad * 2;
897 rect.height -= renderer->ypad * 2;
93763ad5 898
e152afc3
RR
899 GdkRectangle dummy;
900 if (gdk_rectangle_intersect (expose_area, &rect, &dummy))
901 {
902 wxRect renderrect( rect.x, rect.y, rect.width, rect.height );
903 wxWindowDC* dc = (wxWindowDC*) cell->GetDC();
4d496ecb
RR
904 if (dc->m_window == NULL)
905 {
906 dc->m_window = window;
907 dc->SetUpDC();
908 }
93763ad5 909
e152afc3
RR
910 int state = 0;
911 if (flags & GTK_CELL_RENDERER_SELECTED)
912 state |= wxDATAVIEW_CELL_SELECTED;
913 if (flags & GTK_CELL_RENDERER_PRELIT)
914 state |= wxDATAVIEW_CELL_PRELIT;
915 if (flags & GTK_CELL_RENDERER_INSENSITIVE)
916 state |= wxDATAVIEW_CELL_INSENSITIVE;
917 if (flags & GTK_CELL_RENDERER_INSENSITIVE)
918 state |= wxDATAVIEW_CELL_INSENSITIVE;
919 if (flags & GTK_CELL_RENDERER_FOCUSED)
920 state |= wxDATAVIEW_CELL_FOCUSED;
921 cell->Render( renderrect, dc, state );
93763ad5 922 }
e152afc3
RR
923}
924
93763ad5 925static gboolean
553f7d8f
RR
926gtk_wx_cell_renderer_activate(
927 GtkCellRenderer *renderer,
928 GdkEvent *event,
929 GtkWidget *widget,
930 const gchar *path,
931 GdkRectangle *background_area,
932 GdkRectangle *cell_area,
933 GtkCellRendererState flags )
934{
935 GtkWxCellRenderer *wxrenderer = (GtkWxCellRenderer *) renderer;
baa9ebc4 936 wxDataViewCustomRenderer *cell = wxrenderer->cell;
93763ad5 937
553f7d8f
RR
938 GdkRectangle rect;
939 gtk_wx_cell_renderer_get_size (renderer, widget, cell_area,
93763ad5
WS
940 &rect.x,
941 &rect.y,
942 &rect.width,
943 &rect.height);
553f7d8f
RR
944
945 rect.x += cell_area->x;
946 rect.y += cell_area->y;
947 rect.width -= renderer->xpad * 2;
948 rect.height -= renderer->ypad * 2;
93763ad5 949
553f7d8f 950 wxRect renderrect( rect.x, rect.y, rect.width, rect.height );
93763ad5 951
e0062c04 952 wxDataViewModel *model = cell->GetOwner()->GetOwner()->GetModel();
93763ad5 953
4d496ecb 954 GtkTreePath *treepath = gtk_tree_path_new_from_string( path );
9d52aad3
RR
955 // TODO
956 wxDataViewItem item;
4d496ecb 957 gtk_tree_path_free( treepath );
93763ad5 958
0a71f9e9 959 unsigned int model_col = cell->GetOwner()->GetModelColumn();
93763ad5 960
456e5c21
RR
961 if (!event)
962 {
963 bool ret = false;
e8375af8 964
456e5c21 965 // activated by <ENTER>
9d52aad3 966 if (cell->Activate( renderrect, model, item, model_col ))
456e5c21 967 ret = true;
e8375af8 968
456e5c21
RR
969 return ret;
970 }
971 else if (event->type == GDK_BUTTON_PRESS)
4d496ecb
RR
972 {
973 GdkEventButton *button_event = (GdkEventButton*) event;
93763ad5 974 wxPoint pt( ((int) button_event->x) - renderrect.x,
4d496ecb 975 ((int) button_event->y) - renderrect.y );
93763ad5 976
4d496ecb
RR
977 bool ret = false;
978 if (button_event->button == 1)
979 {
9d52aad3 980 if (cell->LeftClick( pt, renderrect, model, item, model_col ))
4d496ecb 981 ret = true;
7ea3a0de 982 // TODO: query system double-click time
4d496ecb 983 if (button_event->time - wxrenderer->last_click < 400)
9d52aad3 984 if (cell->Activate( renderrect, model, item, model_col ))
4d496ecb
RR
985 ret = true;
986 }
987 if (button_event->button == 3)
988 {
9d52aad3 989 if (cell->RightClick( pt, renderrect, model, item, model_col ))
4d496ecb
RR
990 ret = true;
991 }
93763ad5 992
4d496ecb 993 wxrenderer->last_click = button_event->time;
93763ad5 994
4d496ecb
RR
995 return ret;
996 }
93763ad5 997
4d496ecb 998 return false;
553f7d8f
RR
999}
1000
93763ad5 1001// ---------------------------------------------------------
e0062c04 1002// wxGtkDataViewModelNotifier
93763ad5 1003// ---------------------------------------------------------
6e2e590f 1004
e0062c04 1005class wxGtkDataViewModelNotifier: public wxDataViewModelNotifier
6e2e590f
RR
1006{
1007public:
e0062c04
RR
1008 wxGtkDataViewModelNotifier( GtkWxTreeModel *wxgtk_model,
1009 wxDataViewModel *wx_model,
1010 wxDataViewCtrl *ctrl );
1011 ~wxGtkDataViewModelNotifier();
1012
1013 virtual bool ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item );
1014 virtual bool ItemDeleted( const wxDataViewItem &item );
1015 virtual bool ItemChanged( const wxDataViewItem &item );
1016 virtual bool ValueChanged( const wxDataViewItem &item, unsigned int col );
6e2e590f 1017 virtual bool Cleared();
4508fcd2 1018 virtual void Resort();
93763ad5 1019
e0062c04
RR
1020 GtkWxTreeModel *m_wxgtk_model;
1021 wxDataViewModel *m_wx_model;
63415a42 1022 wxDataViewCtrl *m_owner;
6e2e590f
RR
1023};
1024
93763ad5 1025// ---------------------------------------------------------
6e2e590f 1026// wxGtkDataViewListModelNotifier
93763ad5 1027// ---------------------------------------------------------
6e2e590f 1028
e0062c04
RR
1029wxGtkDataViewModelNotifier::wxGtkDataViewModelNotifier(
1030 GtkWxTreeModel* wxgtk_model, wxDataViewModel *wx_model,
63415a42 1031 wxDataViewCtrl *ctrl )
6e2e590f 1032{
e0062c04 1033 m_wxgtk_model = wxgtk_model;
6e2e590f 1034 m_wx_model = wx_model;
63415a42 1035 m_owner = ctrl;
6e2e590f 1036}
93763ad5 1037
e0062c04 1038wxGtkDataViewModelNotifier::~wxGtkDataViewModelNotifier()
f7ed8c89
RR
1039{
1040 m_wx_model = NULL;
e0062c04 1041 m_wxgtk_model = NULL;
f7ed8c89
RR
1042}
1043
e0062c04 1044bool wxGtkDataViewModelNotifier::ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item )
6e2e590f 1045{
55fbde12 1046 m_owner->GtkGetInternal()->ItemAdded( parent, item );
1e08ad10 1047
6e2e590f 1048 GtkTreeIter iter;
e0062c04
RR
1049 iter.stamp = m_wxgtk_model->stamp;
1050 iter.user_data = (gpointer) item.GetID();
93763ad5 1051
e0062c04
RR
1052 GtkTreePath *path = wxgtk_tree_model_get_path(
1053 GTK_TREE_MODEL(m_wxgtk_model), &iter );
1054 gtk_tree_model_row_inserted(
1055 GTK_TREE_MODEL(m_wxgtk_model), path, &iter);
6e2e590f 1056 gtk_tree_path_free (path);
93763ad5 1057
6e2e590f
RR
1058 return true;
1059}
1060
e0062c04 1061bool wxGtkDataViewModelNotifier::ItemDeleted( const wxDataViewItem &item )
6e2e590f 1062{
605c2c4a 1063 GtkTreeIter iter;
e0062c04
RR
1064 iter.stamp = m_wxgtk_model->stamp;
1065 iter.user_data = (gpointer) item.GetID();
93763ad5 1066
ef427989 1067 GtkTreePath *path = wxgtk_tree_model_get_path_safe(
e0062c04
RR
1068 GTK_TREE_MODEL(m_wxgtk_model), &iter );
1069 gtk_tree_model_row_deleted(
1070 GTK_TREE_MODEL(m_wxgtk_model), path );
605c2c4a 1071 gtk_tree_path_free (path);
93763ad5 1072
55fbde12 1073 m_owner->GtkGetInternal()->ItemDeleted( item );
e63807a8 1074
605c2c4a 1075 return true;
6e2e590f
RR
1076}
1077
4508fcd2
RR
1078void wxGtkDataViewModelNotifier::Resort()
1079{
1080 m_owner->GtkGetInternal()->Resort();
1081}
1082
e0062c04 1083bool wxGtkDataViewModelNotifier::ItemChanged( const wxDataViewItem &item )
6e2e590f 1084{
4627af27 1085 GtkTreeIter iter;
e0062c04
RR
1086 iter.stamp = m_wxgtk_model->stamp;
1087 iter.user_data = (gpointer) item.GetID();
6e2e590f 1088
e0062c04
RR
1089 GtkTreePath *path = wxgtk_tree_model_get_path(
1090 GTK_TREE_MODEL(m_wxgtk_model), &iter );
1091 gtk_tree_model_row_changed(
1092 GTK_TREE_MODEL(m_wxgtk_model), path, &iter );
a7f61f76
RR
1093 gtk_tree_path_free (path);
1094
1095 return true;
6e2e590f
RR
1096}
1097
e0062c04 1098bool wxGtkDataViewModelNotifier::ValueChanged( const wxDataViewItem &item, unsigned int model_col )
6e2e590f 1099{
4eccd3a1 1100 // This adds GTK+'s missing MVC logic for ValueChanged
63415a42
RR
1101 unsigned int index;
1102 for (index = 0; index < m_owner->GetColumnCount(); index++)
8f850e28 1103 {
63415a42
RR
1104 wxDataViewColumn *column = m_owner->GetColumn( index );
1105 if (column->GetModelColumn() == model_col)
8f850e28 1106 {
63415a42
RR
1107 GtkTreeView *widget = GTK_TREE_VIEW(m_owner->m_treeview);
1108 GtkTreeViewColumn *gcolumn = GTK_TREE_VIEW_COLUMN(column->GetGtkHandle());
8f850e28
RR
1109
1110 // Get cell area
e0062c04
RR
1111 GtkTreeIter iter;
1112 iter.stamp = m_wxgtk_model->stamp;
1113 iter.user_data = (gpointer) item.GetID();
1114 GtkTreePath *path = wxgtk_tree_model_get_path(
1115 GTK_TREE_MODEL(m_wxgtk_model), &iter );
8f850e28 1116 GdkRectangle cell_area;
63415a42 1117 gtk_tree_view_get_cell_area( widget, path, gcolumn, &cell_area );
93763ad5 1118 gtk_tree_path_free( path );
8f850e28 1119
1a64259d
RR
1120 GtkAdjustment* hadjust = gtk_tree_view_get_hadjustment( widget );
1121 double d = gtk_adjustment_get_value( hadjust );
1122 int xdiff = (int) d;
1123
63415a42 1124 int ydiff = gcolumn->button->allocation.height;
8f850e28 1125 // Redraw
93763ad5 1126 gtk_widget_queue_draw_area( GTK_WIDGET(widget),
1a64259d 1127 cell_area.x - xdiff, ydiff + cell_area.y, cell_area.width, cell_area.height );
8f850e28 1128 }
8f850e28 1129 }
93763ad5 1130
8f850e28 1131 return true;
6e2e590f
RR
1132}
1133
e0062c04 1134bool wxGtkDataViewModelNotifier::Cleared()
6e2e590f
RR
1135{
1136 return false;
1137}
1138
93763ad5 1139// ---------------------------------------------------------
baa9ebc4 1140// wxDataViewRenderer
93763ad5 1141// ---------------------------------------------------------
6842a71a 1142
baa9ebc4 1143IMPLEMENT_ABSTRACT_CLASS(wxDataViewRenderer, wxDataViewRendererBase)
6842a71a 1144
9861f022
RR
1145wxDataViewRenderer::wxDataViewRenderer( const wxString &varianttype, wxDataViewCellMode mode,
1146 int align ) :
1147 wxDataViewRendererBase( varianttype, mode, align )
6842a71a
RR
1148{
1149 m_renderer = NULL;
9861f022
RR
1150
1151 // NOTE: SetMode() and SetAlignment() needs to be called in the renderer's ctor,
1152 // after the m_renderer pointer has been initialized
1153}
1154
1155void wxDataViewRenderer::SetMode( wxDataViewCellMode mode )
1156{
1157 GtkCellRendererMode gtkMode;
1158 switch (mode)
1159 {
1160 case wxDATAVIEW_CELL_INERT:
1161 gtkMode = GTK_CELL_RENDERER_MODE_INERT;
1162 break;
1163 case wxDATAVIEW_CELL_ACTIVATABLE:
1164 gtkMode = GTK_CELL_RENDERER_MODE_ACTIVATABLE;
1165 break;
1166 case wxDATAVIEW_CELL_EDITABLE:
1167 gtkMode = GTK_CELL_RENDERER_MODE_EDITABLE;
1168 break;
1169 }
1170
1171 GValue gvalue = { 0, };
1172 g_value_init( &gvalue, gtk_cell_renderer_mode_get_type() );
1173 g_value_set_enum( &gvalue, gtkMode );
1174 g_object_set_property( G_OBJECT(m_renderer), "mode", &gvalue );
1175 g_value_unset( &gvalue );
1176}
1177
1178wxDataViewCellMode wxDataViewRenderer::GetMode() const
1179{
1180 wxDataViewCellMode ret;
1181
1182 GValue gvalue;
1183 g_object_get( G_OBJECT(m_renderer), "mode", &gvalue, NULL);
1184
1185 switch (g_value_get_enum(&gvalue))
1186 {
1187 case GTK_CELL_RENDERER_MODE_INERT:
1188 ret = wxDATAVIEW_CELL_INERT;
1189 break;
1190 case GTK_CELL_RENDERER_MODE_ACTIVATABLE:
1191 ret = wxDATAVIEW_CELL_ACTIVATABLE;
1192 break;
1193 case GTK_CELL_RENDERER_MODE_EDITABLE:
1194 ret = wxDATAVIEW_CELL_EDITABLE;
1195 break;
1196 }
1197
1198 g_value_unset( &gvalue );
1199
1200 return ret;
1201}
1202
1203void wxDataViewRenderer::SetAlignment( int align )
1204{
1205 // horizontal alignment:
1206
1207 gfloat xalign = 0.0;
1208 if (align & wxALIGN_RIGHT)
1209 xalign = 1.0;
1210 else if (align & wxALIGN_CENTER_HORIZONTAL)
1211 xalign = 0.5;
1212
1213 GValue gvalue = { 0, };
1214 g_value_init( &gvalue, G_TYPE_FLOAT );
1215 g_value_set_float( &gvalue, xalign );
1216 g_object_set_property( G_OBJECT(m_renderer), "xalign", &gvalue );
1217 g_value_unset( &gvalue );
1218
1219 // vertical alignment:
1220
1221 gfloat yalign = 0.0;
1222 if (align & wxALIGN_BOTTOM)
1223 yalign = 1.0;
1224 else if (align & wxALIGN_CENTER_VERTICAL)
1225 yalign = 0.5;
1226
1227 GValue gvalue2 = { 0, };
1228 g_value_init( &gvalue2, G_TYPE_FLOAT );
1229 g_value_set_float( &gvalue2, yalign );
1230 g_object_set_property( G_OBJECT(m_renderer), "yalign", &gvalue2 );
1231 g_value_unset( &gvalue2 );
6842a71a
RR
1232}
1233
9861f022
RR
1234int wxDataViewRenderer::GetAlignment() const
1235{
1236 int ret = 0;
1237 GValue gvalue;
1238
1239 // horizontal alignment:
1240
1241 g_object_get( G_OBJECT(m_renderer), "xalign", &gvalue, NULL );
1242 float xalign = g_value_get_float( &gvalue );
1243 if (xalign < 0.5)
1244 ret |= wxALIGN_LEFT;
1245 else if (xalign == 0.5)
1246 ret |= wxALIGN_CENTER_HORIZONTAL;
1247 else
1248 ret |= wxALIGN_RIGHT;
1249 g_value_unset( &gvalue );
1250
1251
1252 // vertical alignment:
1253
1254 g_object_get( G_OBJECT(m_renderer), "yalign", &gvalue, NULL );
1255 float yalign = g_value_get_float( &gvalue );
1256 if (yalign < 0.5)
1257 ret |= wxALIGN_TOP;
1258 else if (yalign == 0.5)
1259 ret |= wxALIGN_CENTER_VERTICAL;
1260 else
1261 ret |= wxALIGN_BOTTOM;
1262 g_value_unset( &gvalue );
1263
1264 return ret;
1265}
1266
1267
1268
93763ad5 1269// ---------------------------------------------------------
baa9ebc4 1270// wxDataViewTextRenderer
93763ad5 1271// ---------------------------------------------------------
6842a71a 1272
a7f61f76 1273extern "C" {
93763ad5 1274static void wxGtkTextRendererEditedCallback( GtkCellRendererText *renderer,
a7f61f76
RR
1275 gchar *arg1, gchar *arg2, gpointer user_data );
1276}
1277
93763ad5 1278static void wxGtkTextRendererEditedCallback( GtkCellRendererText *renderer,
a7f61f76
RR
1279 gchar *arg1, gchar *arg2, gpointer user_data )
1280{
baa9ebc4 1281 wxDataViewTextRenderer *cell = (wxDataViewTextRenderer*) user_data;
93763ad5 1282
1a74f561 1283 wxString tmp = wxGTK_CONV_BACK_FONT(arg2, cell->GetOwner()->GetOwner()->GetFont());
a7f61f76
RR
1284 wxVariant value = tmp;
1285 if (!cell->Validate( value ))
1286 return;
93763ad5 1287
e0062c04 1288 wxDataViewModel *model = cell->GetOwner()->GetOwner()->GetModel();
93763ad5 1289
a7f61f76 1290 GtkTreePath *path = gtk_tree_path_new_from_string( arg1 );
9d52aad3 1291 GtkTreeIter iter;
55fbde12
RR
1292 cell->GetOwner()->GetOwner()->GtkGetInternal()->get_iter( &iter, path );
1293 wxDataViewItem item( (void*) iter.user_data );;
a7f61f76 1294 gtk_tree_path_free( path );
93763ad5 1295
0a71f9e9 1296 unsigned int model_col = cell->GetOwner()->GetModelColumn();
93763ad5 1297
9d52aad3
RR
1298 model->SetValue( value, item, model_col );
1299 model->ValueChanged( item, model_col );
a7f61f76
RR
1300}
1301
baa9ebc4 1302IMPLEMENT_CLASS(wxDataViewTextRenderer, wxDataViewRenderer)
6842a71a 1303
9861f022
RR
1304wxDataViewTextRenderer::wxDataViewTextRenderer( const wxString &varianttype, wxDataViewCellMode mode,
1305 int align ) :
1306 wxDataViewRenderer( varianttype, mode, align )
6842a71a 1307{
ed38aa55 1308 m_renderer = (GtkCellRenderer*) gtk_cell_renderer_text_new();
93763ad5 1309
9861f022 1310 if (mode & wxDATAVIEW_CELL_EDITABLE)
a7f61f76
RR
1311 {
1312 GValue gvalue = { 0, };
1313 g_value_init( &gvalue, G_TYPE_BOOLEAN );
1314 g_value_set_boolean( &gvalue, true );
1315 g_object_set_property( G_OBJECT(m_renderer), "editable", &gvalue );
1316 g_value_unset( &gvalue );
93763ad5 1317
a7f61f76
RR
1318 g_signal_connect_after( m_renderer, "edited", G_CALLBACK(wxGtkTextRendererEditedCallback), this );
1319 }
9861f022
RR
1320
1321 SetMode(mode);
1322 SetAlignment(align);
6842a71a 1323}
790b137e 1324
baa9ebc4 1325bool wxDataViewTextRenderer::SetValue( const wxVariant &value )
7b4fde82
RR
1326{
1327 wxString tmp = value;
93763ad5 1328
7b4fde82
RR
1329 GValue gvalue = { 0, };
1330 g_value_init( &gvalue, G_TYPE_STRING );
b94db696 1331 g_value_set_string( &gvalue, wxGTK_CONV_FONT( tmp, GetOwner()->GetOwner()->GetFont() ) );
7b4fde82
RR
1332 g_object_set_property( G_OBJECT(m_renderer), "text", &gvalue );
1333 g_value_unset( &gvalue );
93763ad5 1334
7b4fde82
RR
1335 return true;
1336}
1337
9861f022 1338bool wxDataViewTextRenderer::GetValue( wxVariant &value ) const
a7f61f76
RR
1339{
1340 GValue gvalue = { 0, };
1341 g_value_init( &gvalue, G_TYPE_STRING );
1342 g_object_get_property( G_OBJECT(m_renderer), "text", &gvalue );
1a74f561
VZ
1343 wxString tmp = wxGTK_CONV_BACK_FONT( g_value_get_string( &gvalue ),
1344 wx_const_cast(wxDataViewTextRenderer*, this)->GetOwner()->GetOwner()->GetFont() );
a7f61f76 1345 g_value_unset( &gvalue );
93763ad5 1346
a7f61f76
RR
1347 value = tmp;
1348
1349 return true;
1350}
1351
9861f022
RR
1352void wxDataViewTextRenderer::SetAlignment( int align )
1353{
1354 wxDataViewRenderer::SetAlignment(align);
1355
01705e98
RR
1356 if (gtk_check_version(2,10,0))
1357 return;
9861f022 1358
01705e98 1359 // horizontal alignment:
9861f022
RR
1360 PangoAlignment pangoAlign = PANGO_ALIGN_LEFT;
1361 if (align & wxALIGN_RIGHT)
1362 pangoAlign = PANGO_ALIGN_RIGHT;
1363 else if (align & wxALIGN_CENTER_HORIZONTAL)
1364 pangoAlign = PANGO_ALIGN_CENTER;
1365
1366 GValue gvalue = { 0, };
1367 g_value_init( &gvalue, gtk_cell_renderer_mode_get_type() );
1368 g_value_set_enum( &gvalue, pangoAlign );
1369 g_object_set_property( G_OBJECT(m_renderer), "alignment", &gvalue );
1370 g_value_unset( &gvalue );
1371}
1372
f4322df6 1373// ---------------------------------------------------------
baa9ebc4 1374// wxDataViewBitmapRenderer
f4322df6 1375// ---------------------------------------------------------
cbc9145c 1376
baa9ebc4 1377IMPLEMENT_CLASS(wxDataViewBitmapRenderer, wxDataViewRenderer)
cbc9145c 1378
9861f022
RR
1379wxDataViewBitmapRenderer::wxDataViewBitmapRenderer( const wxString &varianttype, wxDataViewCellMode mode,
1380 int align ) :
1381 wxDataViewRenderer( varianttype, mode, align )
cbc9145c 1382{
ed38aa55 1383 m_renderer = (GtkCellRenderer*) gtk_cell_renderer_pixbuf_new();
9861f022
RR
1384
1385 SetMode(mode);
1386 SetAlignment(align);
cbc9145c
RR
1387}
1388
baa9ebc4 1389bool wxDataViewBitmapRenderer::SetValue( const wxVariant &value )
cbc9145c
RR
1390{
1391 if (value.GetType() == wxT("wxBitmap"))
1392 {
2586d4a1
RR
1393 wxBitmap bitmap;
1394 bitmap << value;
f4322df6 1395
2586d4a1
RR
1396 // This may create a Pixbuf representation in the
1397 // wxBitmap object (and it will stay there)
1398 GdkPixbuf *pixbuf = bitmap.GetPixbuf();
f4322df6 1399
2586d4a1
RR
1400 GValue gvalue = { 0, };
1401 g_value_init( &gvalue, G_TYPE_OBJECT );
1402 g_value_set_object( &gvalue, pixbuf );
1403 g_object_set_property( G_OBJECT(m_renderer), "pixbuf", &gvalue );
1404 g_value_unset( &gvalue );
f4322df6 1405
2586d4a1
RR
1406 return true;
1407 }
f4322df6 1408
2586d4a1
RR
1409 if (value.GetType() == wxT("wxIcon"))
1410 {
1411 wxIcon bitmap;
1412 bitmap << value;
f4322df6 1413
cbc9145c
RR
1414 // This may create a Pixbuf representation in the
1415 // wxBitmap object (and it will stay there)
2586d4a1 1416 GdkPixbuf *pixbuf = bitmap.GetPixbuf();
f4322df6 1417
cbc9145c
RR
1418 GValue gvalue = { 0, };
1419 g_value_init( &gvalue, G_TYPE_OBJECT );
1420 g_value_set_object( &gvalue, pixbuf );
1421 g_object_set_property( G_OBJECT(m_renderer), "pixbuf", &gvalue );
1422 g_value_unset( &gvalue );
f4322df6 1423
cbc9145c
RR
1424 return true;
1425 }
f4322df6 1426
cbc9145c
RR
1427 return false;
1428}
1429
9861f022 1430bool wxDataViewBitmapRenderer::GetValue( wxVariant &value ) const
cbc9145c
RR
1431{
1432 return false;
1433}
f4322df6 1434
93763ad5 1435// ---------------------------------------------------------
baa9ebc4 1436// wxDataViewToggleRenderer
93763ad5 1437// ---------------------------------------------------------
fa28826d 1438
605c2c4a 1439extern "C" {
93763ad5 1440static void wxGtkToggleRendererToggledCallback( GtkCellRendererToggle *renderer,
605c2c4a
RR
1441 gchar *path, gpointer user_data );
1442}
1443
93763ad5 1444static void wxGtkToggleRendererToggledCallback( GtkCellRendererToggle *renderer,
605c2c4a
RR
1445 gchar *path, gpointer user_data )
1446{
baa9ebc4 1447 wxDataViewToggleRenderer *cell = (wxDataViewToggleRenderer*) user_data;
605c2c4a 1448
93763ad5 1449 // get old value
605c2c4a
RR
1450 GValue gvalue = { 0, };
1451 g_value_init( &gvalue, G_TYPE_BOOLEAN );
1452 g_object_get_property( G_OBJECT(renderer), "active", &gvalue );
93763ad5 1453 bool tmp = g_value_get_boolean( &gvalue );
605c2c4a
RR
1454 g_value_unset( &gvalue );
1455 // invert it
1456 tmp = !tmp;
93763ad5 1457
605c2c4a
RR
1458 wxVariant value = tmp;
1459 if (!cell->Validate( value ))
1460 return;
93763ad5 1461
e0062c04 1462 wxDataViewModel *model = cell->GetOwner()->GetOwner()->GetModel();
93763ad5 1463
605c2c4a 1464 GtkTreePath *gtk_path = gtk_tree_path_new_from_string( path );
55fbde12
RR
1465 GtkTreeIter iter;
1466 cell->GetOwner()->GetOwner()->GtkGetInternal()->get_iter( &iter, gtk_path );
1467 wxDataViewItem item( (void*) iter.user_data );;
605c2c4a 1468 gtk_tree_path_free( gtk_path );
93763ad5 1469
0a71f9e9 1470 unsigned int model_col = cell->GetOwner()->GetModelColumn();
93763ad5 1471
9d52aad3
RR
1472 model->SetValue( value, item, model_col );
1473 model->ValueChanged( item, model_col );
605c2c4a
RR
1474}
1475
baa9ebc4 1476IMPLEMENT_CLASS(wxDataViewToggleRenderer, wxDataViewRenderer)
605c2c4a 1477
baa9ebc4 1478wxDataViewToggleRenderer::wxDataViewToggleRenderer( const wxString &varianttype,
9861f022
RR
1479 wxDataViewCellMode mode, int align ) :
1480 wxDataViewRenderer( varianttype, mode, align )
605c2c4a 1481{
ed38aa55 1482 m_renderer = (GtkCellRenderer*) gtk_cell_renderer_toggle_new();
93763ad5 1483
9861f022 1484 if (mode & wxDATAVIEW_CELL_ACTIVATABLE)
605c2c4a 1485 {
9861f022
RR
1486 g_signal_connect_after( m_renderer, "toggled",
1487 G_CALLBACK(wxGtkToggleRendererToggledCallback), this );
553f7d8f
RR
1488 }
1489 else
1490 {
605c2c4a
RR
1491 GValue gvalue = { 0, };
1492 g_value_init( &gvalue, G_TYPE_BOOLEAN );
553f7d8f 1493 g_value_set_boolean( &gvalue, false );
605c2c4a
RR
1494 g_object_set_property( G_OBJECT(m_renderer), "activatable", &gvalue );
1495 g_value_unset( &gvalue );
605c2c4a 1496 }
9861f022
RR
1497
1498 SetMode(mode);
1499 SetAlignment(align);
605c2c4a
RR
1500}
1501
baa9ebc4 1502bool wxDataViewToggleRenderer::SetValue( const wxVariant &value )
605c2c4a
RR
1503{
1504 bool tmp = value;
93763ad5 1505
605c2c4a
RR
1506 GValue gvalue = { 0, };
1507 g_value_init( &gvalue, G_TYPE_BOOLEAN );
1508 g_value_set_boolean( &gvalue, tmp );
1509 g_object_set_property( G_OBJECT(m_renderer), "active", &gvalue );
1510 g_value_unset( &gvalue );
93763ad5 1511
605c2c4a
RR
1512 return true;
1513}
1514
9861f022 1515bool wxDataViewToggleRenderer::GetValue( wxVariant &value ) const
605c2c4a
RR
1516{
1517 GValue gvalue = { 0, };
1518 g_value_init( &gvalue, G_TYPE_BOOLEAN );
1519 g_object_get_property( G_OBJECT(m_renderer), "active", &gvalue );
93763ad5 1520 bool tmp = g_value_get_boolean( &gvalue );
605c2c4a 1521 g_value_unset( &gvalue );
93763ad5 1522
605c2c4a
RR
1523 value = tmp;
1524
1525 return true;
1526}
93763ad5
WS
1527
1528// ---------------------------------------------------------
baa9ebc4 1529// wxDataViewCustomRenderer
93763ad5 1530// ---------------------------------------------------------
e152afc3
RR
1531
1532class wxDataViewCtrlDC: public wxWindowDC
1533{
1534public:
1535 wxDataViewCtrlDC( wxDataViewCtrl *window )
1536 {
1a367564 1537 GtkWidget *widget = window->m_treeview;
e152afc3
RR
1538 // Set later
1539 m_window = NULL;
4d496ecb 1540
e152afc3
RR
1541 m_context = window->GtkGetPangoDefaultContext();
1542 m_layout = pango_layout_new( m_context );
1543 m_fontdesc = pango_font_description_copy( widget->style->font_desc );
1544
1545 m_cmap = gtk_widget_get_colormap( widget ? widget : window->m_widget );
1546
4d496ecb
RR
1547 // Set m_window later
1548 // SetUpDC();
1549 // m_owner = window;
e152afc3
RR
1550 }
1551};
1552
93763ad5 1553// ---------------------------------------------------------
baa9ebc4 1554// wxDataViewCustomRenderer
93763ad5 1555// ---------------------------------------------------------
e152afc3 1556
baa9ebc4 1557IMPLEMENT_CLASS(wxDataViewCustomRenderer, wxDataViewRenderer)
e152afc3 1558
baa9ebc4 1559wxDataViewCustomRenderer::wxDataViewCustomRenderer( const wxString &varianttype,
9861f022
RR
1560 wxDataViewCellMode mode, int align,
1561 bool no_init ) :
1562 wxDataViewRenderer( varianttype, mode, align )
e152afc3
RR
1563{
1564 m_dc = NULL;
93763ad5 1565
ad63bf41
RR
1566 if (no_init)
1567 m_renderer = NULL;
1568 else
9861f022 1569 Init(mode, align);
ad63bf41
RR
1570}
1571
9861f022 1572bool wxDataViewCustomRenderer::Init(wxDataViewCellMode mode, int align)
ad63bf41 1573{
e152afc3
RR
1574 GtkWxCellRenderer *renderer = (GtkWxCellRenderer *) gtk_wx_cell_renderer_new();
1575 renderer->cell = this;
93763ad5 1576
ed38aa55 1577 m_renderer = (GtkCellRenderer*) renderer;
93763ad5 1578
9861f022
RR
1579 SetMode(mode);
1580 SetAlignment(align);
93763ad5 1581
ad63bf41 1582 return true;
e152afc3
RR
1583}
1584
baa9ebc4 1585wxDataViewCustomRenderer::~wxDataViewCustomRenderer()
e152afc3
RR
1586{
1587 if (m_dc)
1588 delete m_dc;
1589}
1590
baa9ebc4 1591wxDC *wxDataViewCustomRenderer::GetDC()
e152afc3
RR
1592{
1593 if (m_dc == NULL)
4d496ecb
RR
1594 {
1595 if (GetOwner() == NULL)
1596 return NULL;
1597 if (GetOwner()->GetOwner() == NULL)
1598 return NULL;
e152afc3 1599 m_dc = new wxDataViewCtrlDC( GetOwner()->GetOwner() );
4d496ecb 1600 }
93763ad5 1601
e152afc3
RR
1602 return m_dc;
1603}
93763ad5
WS
1604
1605// ---------------------------------------------------------
baa9ebc4 1606// wxDataViewProgressRenderer
93763ad5 1607// ---------------------------------------------------------
ad63bf41 1608
baa9ebc4 1609IMPLEMENT_CLASS(wxDataViewProgressRenderer, wxDataViewCustomRenderer)
ad63bf41 1610
baa9ebc4 1611wxDataViewProgressRenderer::wxDataViewProgressRenderer( const wxString &label,
9861f022
RR
1612 const wxString &varianttype, wxDataViewCellMode mode, int align ) :
1613 wxDataViewCustomRenderer( varianttype, mode, align, true )
ad63bf41
RR
1614{
1615 m_label = label;
1616 m_value = 0;
93763ad5 1617
ad63bf41
RR
1618#ifdef __WXGTK26__
1619 if (!gtk_check_version(2,6,0))
1620 {
ed38aa55 1621 m_renderer = (GtkCellRenderer*) gtk_cell_renderer_progress_new();
93763ad5 1622
ad63bf41
RR
1623 GValue gvalue = { 0, };
1624 g_value_init( &gvalue, G_TYPE_STRING );
09dfa6a0
VZ
1625
1626 // FIXME: font encoding support
b94db696 1627 g_value_set_string( &gvalue, wxGTK_CONV_SYS(m_label) );
ad63bf41
RR
1628 g_object_set_property( G_OBJECT(m_renderer), "text", &gvalue );
1629 g_value_unset( &gvalue );
9861f022
RR
1630
1631 SetMode(mode);
1632 SetAlignment(align);
ad63bf41
RR
1633 }
1634 else
1635#endif
1636 {
1637 // Use custom cell code
9861f022 1638 wxDataViewCustomRenderer::Init(mode, align);
ad63bf41
RR
1639 }
1640}
1641
baa9ebc4 1642wxDataViewProgressRenderer::~wxDataViewProgressRenderer()
ad63bf41
RR
1643{
1644}
1645
baa9ebc4 1646bool wxDataViewProgressRenderer::SetValue( const wxVariant &value )
ad63bf41
RR
1647{
1648#ifdef __WXGTK26__
1649 if (!gtk_check_version(2,6,0))
1650 {
7226118b 1651 gint tmp = (long) value;
ad63bf41
RR
1652 GValue gvalue = { 0, };
1653 g_value_init( &gvalue, G_TYPE_INT );
7226118b 1654 g_value_set_int( &gvalue, tmp );
ad63bf41
RR
1655 g_object_set_property( G_OBJECT(m_renderer), "value", &gvalue );
1656 g_value_unset( &gvalue );
1657 }
1658 else
1659#endif
1660 {
1661 m_value = (long) value;
93763ad5 1662
ad63bf41
RR
1663 if (m_value < 0) m_value = 0;
1664 if (m_value > 100) m_value = 100;
1665 }
93763ad5 1666
ad63bf41
RR
1667 return true;
1668}
93763ad5 1669
9861f022
RR
1670bool wxDataViewProgressRenderer::GetValue( wxVariant &value ) const
1671{
1672 return false;
1673}
1674
baa9ebc4 1675bool wxDataViewProgressRenderer::Render( wxRect cell, wxDC *dc, int state )
ad63bf41
RR
1676{
1677 double pct = (double)m_value / 100.0;
1678 wxRect bar = cell;
1679 bar.width = (int)(cell.width * pct);
1680 dc->SetPen( *wxTRANSPARENT_PEN );
1681 dc->SetBrush( *wxBLUE_BRUSH );
1682 dc->DrawRectangle( bar );
1683
1684 dc->SetBrush( *wxTRANSPARENT_BRUSH );
1685 dc->SetPen( *wxBLACK_PEN );
1686 dc->DrawRectangle( cell );
93763ad5 1687
ad63bf41
RR
1688 return true;
1689}
1690
9861f022 1691wxSize wxDataViewProgressRenderer::GetSize() const
ad63bf41
RR
1692{
1693 return wxSize(40,12);
1694}
93763ad5
WS
1695
1696// ---------------------------------------------------------
baa9ebc4 1697// wxDataViewDateRenderer
93763ad5 1698// ---------------------------------------------------------
4d496ecb 1699
baa9ebc4 1700class wxDataViewDateRendererPopupTransient: public wxPopupTransientWindow
7ea3a0de 1701{
93763ad5 1702public:
baa9ebc4 1703 wxDataViewDateRendererPopupTransient( wxWindow* parent, wxDateTime *value,
e0062c04 1704 wxDataViewModel *model, const wxDataViewItem &item, unsigned int col ) :
7ea3a0de
RR
1705 wxPopupTransientWindow( parent, wxBORDER_SIMPLE )
1706 {
1707 m_model = model;
e0062c04 1708 m_item = item;
7ea3a0de 1709 m_col = col;
7ea3a0de
RR
1710 m_cal = new wxCalendarCtrl( this, -1, *value );
1711 wxBoxSizer *sizer = new wxBoxSizer( wxHORIZONTAL );
1712 sizer->Add( m_cal, 1, wxGROW );
1713 SetSizer( sizer );
1714 sizer->Fit( this );
1715 }
93763ad5 1716
7ea3a0de
RR
1717 virtual void OnDismiss()
1718 {
1719 }
93763ad5 1720
7ea3a0de 1721 void OnCalendar( wxCalendarEvent &event );
93763ad5 1722
e0062c04
RR
1723 wxCalendarCtrl *m_cal;
1724 wxDataViewModel *m_model;
1725 wxDataViewItem m_item;
1726 unsigned int m_col;
93763ad5 1727
7ea3a0de
RR
1728private:
1729 DECLARE_EVENT_TABLE()
1730};
1731
baa9ebc4
RR
1732BEGIN_EVENT_TABLE(wxDataViewDateRendererPopupTransient,wxPopupTransientWindow)
1733 EVT_CALENDAR( -1, wxDataViewDateRendererPopupTransient::OnCalendar )
7ea3a0de
RR
1734END_EVENT_TABLE()
1735
baa9ebc4 1736void wxDataViewDateRendererPopupTransient::OnCalendar( wxCalendarEvent &event )
7ea3a0de
RR
1737{
1738 wxDateTime date = event.GetDate();
1739 wxVariant value = date;
e0062c04
RR
1740 m_model->SetValue( value, m_item, m_col );
1741 m_model->ValueChanged( m_item, m_col );
7ea3a0de
RR
1742 DismissAndNotify();
1743}
1744
baa9ebc4 1745IMPLEMENT_CLASS(wxDataViewDateRenderer, wxDataViewCustomRenderer)
4d496ecb 1746
baa9ebc4 1747wxDataViewDateRenderer::wxDataViewDateRenderer( const wxString &varianttype,
9861f022
RR
1748 wxDataViewCellMode mode, int align ) :
1749 wxDataViewCustomRenderer( varianttype, mode, align )
4d496ecb 1750{
9861f022
RR
1751 SetMode(mode);
1752 SetAlignment(align);
4d496ecb 1753}
93763ad5 1754
baa9ebc4 1755bool wxDataViewDateRenderer::SetValue( const wxVariant &value )
4d496ecb
RR
1756{
1757 m_date = value.GetDateTime();
93763ad5 1758
4d496ecb
RR
1759 return true;
1760}
1761
9861f022
RR
1762bool wxDataViewDateRenderer::GetValue( wxVariant &value ) const
1763{
1764 return false;
1765}
1766
baa9ebc4 1767bool wxDataViewDateRenderer::Render( wxRect cell, wxDC *dc, int state )
4d496ecb
RR
1768{
1769 dc->SetFont( GetOwner()->GetOwner()->GetFont() );
1770 wxString tmp = m_date.FormatDate();
1771 dc->DrawText( tmp, cell.x, cell.y );
1772
1773 return true;
1774}
1775
9861f022 1776wxSize wxDataViewDateRenderer::GetSize() const
4d496ecb 1777{
4d496ecb
RR
1778 wxString tmp = m_date.FormatDate();
1779 wxCoord x,y,d;
9861f022 1780 GetView()->GetTextExtent( tmp, &x, &y, &d );
4d496ecb
RR
1781 return wxSize(x,y+d);
1782}
1783
e0062c04
RR
1784bool wxDataViewDateRenderer::Activate( wxRect cell, wxDataViewModel *model,
1785 const wxDataViewItem &item, unsigned int col )
4d496ecb 1786{
3f3af7e7 1787 wxVariant variant;
e0062c04 1788 model->GetValue( variant, item, col );
7ea3a0de
RR
1789 wxDateTime value = variant.GetDateTime();
1790
baa9ebc4 1791 wxDataViewDateRendererPopupTransient *popup = new wxDataViewDateRendererPopupTransient(
e0062c04 1792 GetOwner()->GetOwner()->GetParent(), &value, model, item, col );
7ea3a0de
RR
1793 wxPoint pos = wxGetMousePosition();
1794 popup->Move( pos );
1795 popup->Layout();
1796 popup->Popup( popup->m_cal );
4d496ecb
RR
1797
1798 return true;
1799}
1800
93763ad5 1801// ---------------------------------------------------------
605c2c4a 1802// wxDataViewColumn
93763ad5 1803// ---------------------------------------------------------
7b4fde82 1804
31fb32e1
RR
1805
1806static gboolean
1807gtk_dataview_header_button_press_callback( GtkWidget *widget,
1808 GdkEventButton *gdk_event,
1809 wxDataViewColumn *column )
1810{
1811 if (gdk_event->type != GDK_BUTTON_PRESS)
94b1f7bc 1812 return FALSE;
f4322df6 1813
31fb32e1
RR
1814 if (gdk_event->button == 1)
1815 {
1816 wxDataViewCtrl *dv = column->GetOwner();
1817 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK, dv->GetId() );
1818 event.SetDataViewColumn( column );
1819 event.SetModel( dv->GetModel() );
94b1f7bc
RR
1820 if (dv->GetEventHandler()->ProcessEvent( event ))
1821 return TRUE;
31fb32e1 1822 }
f4322df6 1823
94b1f7bc 1824 return FALSE;
31fb32e1
RR
1825}
1826
7b4fde82
RR
1827extern "C" {
1828static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *column,
1829 GtkCellRenderer *cell,
1830 GtkTreeModel *model,
1831 GtkTreeIter *iter,
1832 gpointer data );
1833}
1834
1835
1836static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *column,
1837 GtkCellRenderer *renderer,
1838 GtkTreeModel *model,
1839 GtkTreeIter *iter,
1840 gpointer data )
1841{
e0062c04
RR
1842 g_return_if_fail (GTK_IS_WX_TREE_MODEL (model));
1843 GtkWxTreeModel *tree_model = (GtkWxTreeModel *) model;
93763ad5 1844
baa9ebc4 1845 wxDataViewRenderer *cell = (wxDataViewRenderer*) data;
a7f61f76 1846
9d52aad3 1847 wxDataViewItem item( (void*) iter->user_data );
93763ad5 1848
3f3af7e7 1849 wxVariant value;
55fbde12 1850 tree_model->internal->GetDataViewModel()->GetValue( value, item, cell->GetOwner()->GetModelColumn() );
7b4fde82
RR
1851
1852 if (value.GetType() != cell->GetVariantType())
f4322df6
VZ
1853 wxLogError( wxT("Wrong type, required: %s but: %s"),
1854 value.GetType().c_str(),
cbc9145c 1855 cell->GetVariantType().c_str() );
93763ad5 1856
7b4fde82 1857 cell->SetValue( value );
e0743e63 1858
e0062c04 1859#if 0
2a5e6d1b 1860 wxListItemAttr attr;
e0062c04 1861 tree_model->model->GetAttr( attr, cell->GetOwner()->GetModelColumn(), model_row );
2a5e6d1b
RR
1862
1863 if (attr.HasBackgroundColour())
1864 {
1865 wxColour colour = attr.GetBackgroundColour();
1cd5e95c 1866 const GdkColor * const gcol = colour.GetColor();
e0743e63 1867
2a5e6d1b
RR
1868 GValue gvalue = { 0, };
1869 g_value_init( &gvalue, GDK_TYPE_COLOR );
1870 g_value_set_boxed( &gvalue, gcol );
1871 g_object_set_property( G_OBJECT(renderer), "cell-background_gdk", &gvalue );
1872 g_value_unset( &gvalue );
1873 }
1874 else
1875 {
1876 GValue gvalue = { 0, };
1877 g_value_init( &gvalue, G_TYPE_BOOLEAN );
1878 g_value_set_boolean( &gvalue, FALSE );
1879 g_object_set_property( G_OBJECT(renderer), "cell-background-set", &gvalue );
1880 g_value_unset( &gvalue );
1881 }
e0062c04
RR
1882#endif
1883
7b4fde82
RR
1884}
1885
cbc9145c 1886IMPLEMENT_CLASS(wxDataViewColumn, wxDataViewColumnBase)
fa28826d 1887
f4322df6
VZ
1888wxDataViewColumn::wxDataViewColumn( const wxString &title, wxDataViewRenderer *cell,
1889 unsigned int model_column, int width,
87f0efe2
RR
1890 wxAlignment align, int flags ) :
1891 wxDataViewColumnBase( title, cell, model_column, width, align, flags )
fa28826d 1892{
9861f022 1893 Init( align, flags, width );
31fb32e1 1894
9861f022 1895 gtk_tree_view_column_set_clickable( GTK_TREE_VIEW_COLUMN(m_column), TRUE );
31fb32e1 1896 SetTitle( title );
fa28826d
RR
1897}
1898
f4322df6
VZ
1899wxDataViewColumn::wxDataViewColumn( const wxBitmap &bitmap, wxDataViewRenderer *cell,
1900 unsigned int model_column, int width,
87f0efe2
RR
1901 wxAlignment align, int flags ) :
1902 wxDataViewColumnBase( bitmap, cell, model_column, width, align, flags )
9861f022
RR
1903{
1904 Init( align, flags, width );
1905
1906 SetBitmap( bitmap );
1907}
1908
1909void wxDataViewColumn::Init(wxAlignment align, int flags, int width)
07a84e7b 1910{
31fb32e1 1911 m_isConnected = false;
07a84e7b 1912
9861f022 1913 GtkCellRenderer *renderer = (GtkCellRenderer *) GetRenderer()->GetGtkHandle();
07a84e7b 1914 GtkTreeViewColumn *column = gtk_tree_view_column_new();
9861f022 1915 m_column = (GtkWidget*) column;
07a84e7b 1916
9861f022
RR
1917 SetFlags( flags );
1918 SetAlignment( align );
07a84e7b 1919
9861f022
RR
1920 // NOTE: we prefer not to call SetMinWidth(wxDVC_DEFAULT_MINWIDTH);
1921 // as GTK+ is smart and unless explicitely told, will set the minimal
1922 // width to the title's lenght, which is a better default
07a84e7b 1923
9861f022
RR
1924 // the GTK_TREE_VIEW_COLUMN_FIXED is required by the "fixed height" mode
1925 // that we use for the wxDataViewCtrl
1926 gtk_tree_view_column_set_fixed_width( column, width < 0 ? wxDVC_DEFAULT_WIDTH : width );
b94db696 1927 gtk_tree_view_column_set_sizing( column, GTK_TREE_VIEW_COLUMN_FIXED );
07a84e7b 1928
9861f022 1929 gtk_tree_view_column_pack_end( column, renderer, TRUE );
07a84e7b
RR
1930
1931 gtk_tree_view_column_set_cell_data_func( column, renderer,
9861f022 1932 wxGtkTreeCellDataFunc, (gpointer) GetRenderer(), NULL );
07a84e7b
RR
1933}
1934
fa28826d
RR
1935wxDataViewColumn::~wxDataViewColumn()
1936{
1937}
1938
31fb32e1
RR
1939void wxDataViewColumn::OnInternalIdle()
1940{
1941 if (m_isConnected)
1942 return;
f4322df6 1943
31fb32e1
RR
1944 if (GTK_WIDGET_REALIZED(GetOwner()->m_treeview))
1945 {
9861f022 1946 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
31fb32e1
RR
1947 if (column->button)
1948 {
1949 g_signal_connect(column->button, "button_press_event",
1950 G_CALLBACK (gtk_dataview_header_button_press_callback), this);
f4322df6 1951
31fb32e1
RR
1952 m_isConnected = true;
1953 }
1954 }
1955}
1956
b94db696
RR
1957void wxDataViewColumn::SetOwner( wxDataViewCtrl *owner )
1958{
1959 wxDataViewColumnBase::SetOwner( owner );
f4322df6 1960
9861f022 1961 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
f4322df6 1962
b94db696 1963 gtk_tree_view_column_set_title( column, wxGTK_CONV_FONT(GetTitle(), GetOwner()->GetFont() ) );
b94db696
RR
1964}
1965
fa28826d
RR
1966void wxDataViewColumn::SetTitle( const wxString &title )
1967{
9861f022 1968 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
f4322df6 1969
31fb32e1
RR
1970 if (m_isConnected)
1971 {
1972 // disconnect before column->button gets recreated
f4322df6 1973 g_signal_handlers_disconnect_by_func( column->button,
9861f022 1974 (GtkWidget*) gtk_dataview_header_button_press_callback, this);
f4322df6 1975
31fb32e1
RR
1976 m_isConnected = false;
1977 }
1978
09dfa6a0
VZ
1979 // FIXME: can it really happen that we don't have the owner here??
1980 wxDataViewCtrl *ctrl = GetOwner();
1981 gtk_tree_view_column_set_title( column, ctrl ? wxGTK_CONV_FONT(title, ctrl->GetFont())
1982 : wxGTK_CONV_SYS(title) );
31fb32e1 1983
07a84e7b
RR
1984 gtk_tree_view_column_set_widget( column, NULL );
1985}
1986
9861f022
RR
1987wxString wxDataViewColumn::GetTitle() const
1988{
1989 const gchar *str = gtk_tree_view_column_get_title( GTK_TREE_VIEW_COLUMN(m_column) );
1990 return wxConvFileName->cMB2WX(str);
1991}
1992
07a84e7b
RR
1993void wxDataViewColumn::SetBitmap( const wxBitmap &bitmap )
1994{
1995 wxDataViewColumnBase::SetBitmap( bitmap );
1996
9861f022 1997 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
07a84e7b
RR
1998 if (bitmap.Ok())
1999 {
2000 GtkImage *gtk_image = GTK_IMAGE( gtk_image_new() );
f4322df6 2001
07a84e7b
RR
2002 GdkBitmap *mask = (GdkBitmap *) NULL;
2003 if (bitmap.GetMask())
2004 mask = bitmap.GetMask()->GetBitmap();
2005
2006 if (bitmap.HasPixbuf())
2007 {
2008 gtk_image_set_from_pixbuf(GTK_IMAGE(gtk_image),
2009 bitmap.GetPixbuf());
2010 }
2011 else
2012 {
2013 gtk_image_set_from_pixmap(GTK_IMAGE(gtk_image),
2014 bitmap.GetPixmap(), mask);
2015 }
2016 gtk_widget_show( GTK_WIDGET(gtk_image) );
f4322df6 2017
07a84e7b
RR
2018 gtk_tree_view_column_set_widget( column, GTK_WIDGET(gtk_image) );
2019 }
2020 else
2021 {
2022 gtk_tree_view_column_set_widget( column, NULL );
2023 }
fa28826d
RR
2024}
2025
9861f022
RR
2026void wxDataViewColumn::SetHidden( bool hidden )
2027{
2028 gtk_tree_view_column_set_visible( GTK_TREE_VIEW_COLUMN(m_column), !hidden );
2029}
2030
2031void wxDataViewColumn::SetResizeable( bool resizeable )
2032{
2033 gtk_tree_view_column_set_resizable( GTK_TREE_VIEW_COLUMN(m_column), resizeable );
2034}
2035
47cef10f
RR
2036void wxDataViewColumn::SetAlignment( wxAlignment align )
2037{
9861f022 2038 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
f4322df6 2039
47cef10f
RR
2040 gfloat xalign = 0.0;
2041 if (align == wxALIGN_RIGHT)
2042 xalign = 1.0;
9861f022
RR
2043 if (align == wxALIGN_CENTER_HORIZONTAL ||
2044 align == wxALIGN_CENTER)
47cef10f 2045 xalign = 0.5;
f4322df6 2046
9861f022
RR
2047 gtk_tree_view_column_set_alignment( column, xalign );
2048}
2049
2050wxAlignment wxDataViewColumn::GetAlignment() const
2051{
2052 gfloat xalign = gtk_tree_view_column_get_alignment( GTK_TREE_VIEW_COLUMN(m_column) );
2053
2054 if (xalign == 1.0)
2055 return wxALIGN_RIGHT;
2056 if (xalign == 0.5)
2057 return wxALIGN_CENTER_HORIZONTAL;
f4322df6 2058
9861f022 2059 return wxALIGN_LEFT;
47cef10f
RR
2060}
2061
31fb32e1
RR
2062void wxDataViewColumn::SetSortable( bool sortable )
2063{
9861f022 2064 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
94b1f7bc
RR
2065
2066 if (sortable)
2067 gtk_tree_view_column_set_sort_column_id( column, GetModelColumn() );
2068 else
2069 gtk_tree_view_column_set_sort_column_id( column, -1 );
31fb32e1
RR
2070}
2071
87f0efe2 2072bool wxDataViewColumn::IsSortable() const
31fb32e1 2073{
9861f022 2074 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
94b1f7bc 2075 return (gtk_tree_view_column_get_sort_column_id( column ) != -1);
31fb32e1
RR
2076}
2077
9861f022
RR
2078bool wxDataViewColumn::IsResizeable() const
2079{
2080 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
2081 return gtk_tree_view_column_get_resizable( column );
2082}
2083
2084bool wxDataViewColumn::IsHidden() const
2085{
2086 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
2087 return !gtk_tree_view_column_get_visible( column );
2088}
2089
47cef10f
RR
2090void wxDataViewColumn::SetSortOrder( bool ascending )
2091{
9861f022 2092 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
f4322df6 2093
47cef10f
RR
2094 if (ascending)
2095 gtk_tree_view_column_set_sort_order( column, GTK_SORT_ASCENDING );
2096 else
2097 gtk_tree_view_column_set_sort_order( column, GTK_SORT_DESCENDING );
2098}
2099
87f0efe2 2100bool wxDataViewColumn::IsSortOrderAscending() const
31fb32e1 2101{
9861f022 2102 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
f4322df6 2103
31fb32e1
RR
2104 return (gtk_tree_view_column_get_sort_order( column ) != GTK_SORT_DESCENDING);
2105}
2106
9861f022 2107void wxDataViewColumn::SetMinWidth( int width )
533544f2 2108{
9861f022 2109 gtk_tree_view_column_set_min_width( GTK_TREE_VIEW_COLUMN(m_column), width );
533544f2
RR
2110}
2111
9861f022
RR
2112int wxDataViewColumn::GetMinWidth() const
2113{
2114 return gtk_tree_view_column_get_min_width( GTK_TREE_VIEW_COLUMN(m_column) );
2115}
2116
2117int wxDataViewColumn::GetWidth() const
533544f2 2118{
9861f022 2119 return gtk_tree_view_column_get_width( GTK_TREE_VIEW_COLUMN(m_column) );
533544f2
RR
2120}
2121
9861f022 2122void wxDataViewColumn::SetWidth( int width )
533544f2 2123{
9861f022 2124 gtk_tree_view_column_set_fixed_width( GTK_TREE_VIEW_COLUMN(m_column), width );
533544f2
RR
2125}
2126
9861f022 2127
4508fcd2
RR
2128//-----------------------------------------------------------------------------
2129// wxGtkTreeModelNode
2130//-----------------------------------------------------------------------------
2131
2132void wxGtkTreeModelNode::Resort()
2133{
af110130
RR
2134 size_t child_count = GetChildCount();
2135 if (child_count == 0)
0be79c8a
RR
2136 return;
2137
af110130
RR
2138 size_t node_count = GetNodesCount();
2139
2140 if (child_count == 1)
0be79c8a 2141 {
af110130
RR
2142 if (node_count == 1)
2143 {
2144 wxGtkTreeModelNode *node = m_nodes.Item( 0 );
2145 node->Resort();
2146 }
0be79c8a
RR
2147 return;
2148 }
2149
af110130 2150 wxGtkTreeModelChildren *new_array = new wxGtkTreeModelChildren( wxGtkTreeModelNodeCmp );
4508fcd2
RR
2151
2152 size_t pos;
af110130 2153 for (pos = 0; pos < child_count; pos++)
0be79c8a
RR
2154 new_array->Add( m_children->Item( pos ) );
2155
af110130 2156 gint *new_order = new gint[child_count];
4508fcd2 2157
af110130 2158 for (pos = 0; pos < child_count; pos++)
4508fcd2 2159 {
af110130 2160 void *id = new_array->Item( pos );
0be79c8a 2161 size_t old_pos;
af110130 2162 for (old_pos = 0; old_pos < child_count; old_pos++)
0be79c8a 2163 {
af110130 2164 if (id == m_children->Item(old_pos))
0be79c8a
RR
2165 {
2166 new_order[pos] = old_pos;
2167 break;
2168 }
2169 }
4508fcd2 2170 }
0be79c8a
RR
2171
2172// for (pos = 0; pos < count; pos++)
2173// m_children->Clear();
4508fcd2 2174 delete m_children;
0be79c8a 2175
4508fcd2
RR
2176 m_children = new_array;
2177
0be79c8a
RR
2178 GtkTreeModel *gtk_tree_model = GTK_TREE_MODEL( m_internal->GetGtkModel() );
2179
af110130
RR
2180 GtkTreePath *path = gtk_tree_path_new ();
2181 wxGtkTreeModelNode *parent = GetParent();
2182 void *id = GetItem().GetID();
2183
2184 while (parent)
2185 {
2186 int pos = parent->GetChildren().Index( id );
2187 gtk_tree_path_prepend_index( path, pos );
2188 id = parent->GetItem().GetID();
2189 parent = parent->GetParent();
2190 }
2191
0be79c8a 2192 GtkTreeIter iter;
af110130 2193 iter.user_data = id;
0be79c8a 2194 iter.stamp = m_internal->GetGtkModel()->stamp;
0be79c8a
RR
2195 gtk_tree_model_rows_reordered( gtk_tree_model, path, &iter, new_order );
2196
2197 gtk_tree_path_free (path);
2198
2199 delete [] new_order;
2200
af110130 2201 for (pos = 0; pos < node_count; pos++)
4508fcd2 2202 {
af110130 2203 wxGtkTreeModelNode *node = m_nodes.Item( pos );
4508fcd2
RR
2204 node->Resort();
2205 }
2206}
2207
55fbde12
RR
2208//-----------------------------------------------------------------------------
2209// wxDataViewCtrlInternal
2210//-----------------------------------------------------------------------------
2211
2212wxDataViewCtrlInternal::wxDataViewCtrlInternal( wxDataViewCtrl *owner,
2213 wxDataViewModel *wx_model, GtkWxTreeModel *gtk_model )
2214{
2215 m_owner = owner;
2216 m_wx_model = wx_model;
2217 m_gtk_model = gtk_model;
2218 m_root = NULL;
2219 InitTree();
2220}
2221
2222wxDataViewCtrlInternal::~wxDataViewCtrlInternal()
2223{
2224 g_object_unref( m_gtk_model );
2225}
2226
ef427989
RR
2227void wxDataViewCtrlInternal::InitTree()
2228{
2229 wxDataViewItem item;
0be79c8a 2230 m_root = new wxGtkTreeModelNode( NULL, item, this );
ef427989
RR
2231
2232 BuildBranch( m_root );
2233}
2234
55fbde12
RR
2235void wxDataViewCtrlInternal::BuildBranch( wxGtkTreeModelNode *node )
2236{
2237 if (node->GetChildCount() == 0)
2238 {
2239 wxDataViewItem child = m_wx_model->GetFirstChild( node->GetItem() );
2240 while (child.IsOk())
2241 {
af110130
RR
2242 if (m_wx_model->IsContainer( child ))
2243 node->AddNode( new wxGtkTreeModelNode( node, child, this ) );
2244 else
2245 node->AddLeave( child.GetID() );
55fbde12
RR
2246 child = m_wx_model->GetNextSibling( child );
2247 }
2248 }
2249}
2250
4508fcd2
RR
2251void wxDataViewCtrlInternal::Resort()
2252{
2253 m_root->Resort();
2254}
2255
55fbde12
RR
2256bool wxDataViewCtrlInternal::ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item )
2257{
2258 wxGtkTreeModelNode *parent_node = FindNode( parent );
af110130
RR
2259 if (m_wx_model->IsContainer( item ))
2260 parent_node->AddNode( new wxGtkTreeModelNode( parent_node, item, this ) );
2261 else
2262 parent_node->AddLeave( item.GetID() );
55fbde12
RR
2263 return true;
2264}
2265
2266bool wxDataViewCtrlInternal::ItemDeleted( const wxDataViewItem &item )
2267{
af110130
RR
2268 wxGtkTreeModelNode *parent = FindParentNode( item );
2269 parent->DeleteChild( item.GetID() );
55fbde12
RR
2270 return true;
2271}
2272
2273gboolean wxDataViewCtrlInternal::get_iter( GtkTreeIter *iter, GtkTreePath *path )
2274{
2275 int depth = gtk_tree_path_get_depth( path );
2276
2277 wxGtkTreeModelNode *node = m_root;
2278
2279 int i;
2280 for (i = 0; i < depth; i++)
2281 {
2282 BuildBranch( node );
2283
2284 gint pos = gtk_tree_path_get_indices (path)[i];
2285 if (pos < 0) return FALSE;
2286 if ((size_t)pos >= node->GetChildCount()) return FALSE;
2287
af110130
RR
2288 void* id = node->GetChildren().Item( (size_t) pos );
2289
2290 if (i == depth-1)
2291 {
2292 iter->stamp = m_gtk_model->stamp;
2293 iter->user_data = id;
2294 return TRUE;
2295 }
55fbde12 2296
af110130
RR
2297 size_t count = node->GetNodes().GetCount();
2298 size_t pos2;
2299 for (pos2 = 0; pos2 < count; pos2++)
2300 {
2301 wxGtkTreeModelNode *child_node = node->GetNodes().Item( pos2 );
2302 if (child_node->GetItem().GetID() == id)
2303 {
2304 node = child_node;
2305 break;
2306 }
2307 }
2308 }
55fbde12 2309
af110130 2310 return FALSE;
55fbde12
RR
2311}
2312
2313GtkTreePath *wxDataViewCtrlInternal::get_path( GtkTreeIter *iter )
2314{
2315 GtkTreePath *retval = gtk_tree_path_new ();
af110130 2316 void *id = iter->user_data;
55fbde12 2317
af110130
RR
2318 wxGtkTreeModelNode *node = FindParentNode( iter );
2319 while (node)
55fbde12 2320 {
af110130 2321 int pos = node->GetChildren().Index( id );
55fbde12 2322 gtk_tree_path_prepend_index( retval, pos );
af110130
RR
2323
2324 id = node->GetItem().GetID();
2325 node = node->GetParent();
55fbde12
RR
2326 }
2327
2328 return retval;
2329}
2330
ef427989
RR
2331GtkTreePath *wxDataViewCtrlInternal::get_path_safe( GtkTreeIter *iter )
2332{
2333 GtkTreePath *retval = gtk_tree_path_new ();
af110130 2334 void *id = iter->user_data;
ef427989 2335
af110130
RR
2336 wxGtkTreeModelNode *node = FindParentNode( iter );
2337 while (node)
ef427989 2338 {
ef427989 2339 size_t pos;
af110130 2340 for (pos = 0; pos < node->GetChildren().GetCount(); pos++)
ef427989 2341 {
af110130 2342 if (id == node->GetChildren().Item( pos ))
ef427989
RR
2343 {
2344 gtk_tree_path_prepend_index( retval, (int) pos );
2345 continue;
2346 }
2347 }
2348
af110130
RR
2349 id = node->GetItem().GetID();
2350 node = node->GetParent();
ef427989
RR
2351 }
2352
2353 return retval;
2354}
2355
55fbde12
RR
2356gboolean wxDataViewCtrlInternal::iter_next( GtkTreeIter *iter )
2357{
af110130
RR
2358 wxGtkTreeModelNode *parent = FindParentNode( iter );
2359 unsigned int pos = parent->GetChildren().Index( iter->user_data );
ef427989 2360
af110130 2361 if (pos == parent->GetChildCount()-1)
55fbde12 2362 return FALSE;
ef427989 2363
ef427989 2364 iter->stamp = m_gtk_model->stamp;
af110130 2365 iter->user_data = parent->GetChildren().Item( pos+1 );
55fbde12
RR
2366
2367 return TRUE;
2368}
2369
2370gboolean wxDataViewCtrlInternal::iter_children( GtkTreeIter *iter, GtkTreeIter *parent )
2371{
2372 wxDataViewItem item( (void*) parent->user_data );
2373
ed903e42 2374 if (!m_wx_model->IsContainer( item ))
55fbde12
RR
2375 return FALSE;
2376
2377 wxGtkTreeModelNode *parent_node = FindNode( parent );
2378 BuildBranch( parent_node );
ee5aa9d4 2379
af110130 2380 if (parent_node->GetChildCount() == 0)
ee5aa9d4 2381 return FALSE;
55fbde12 2382
55fbde12 2383 iter->stamp = m_gtk_model->stamp;
af110130 2384 iter->user_data = (gpointer) parent_node->GetChildren().Item( 0 );
55fbde12
RR
2385
2386 return TRUE;
2387}
2388
2389gboolean wxDataViewCtrlInternal::iter_has_child( GtkTreeIter *iter )
2390{
2391 wxDataViewItem item( (void*) iter->user_data );
af110130 2392 bool is_container = m_wx_model->IsContainer( item );
ee5aa9d4 2393
af110130 2394 if (!is_container)
ee5aa9d4
RR
2395 return FALSE;
2396
2397 wxGtkTreeModelNode *node = FindNode( iter );
2398 BuildBranch( node );
55fbde12 2399
af110130 2400 return (node->GetChildCount() > 0);
55fbde12
RR
2401}
2402
2403gint wxDataViewCtrlInternal::iter_n_children( GtkTreeIter *iter )
2404{
2405 wxDataViewItem item( (void*) iter->user_data );
2406
ed903e42 2407 if (!m_wx_model->IsContainer( item ))
55fbde12
RR
2408 return 0;
2409
2410 wxGtkTreeModelNode *parent_node = FindNode( iter );
2411 BuildBranch( parent_node );
ef427989
RR
2412
2413 // wxPrintf( "iter_n_children %d\n", parent_node->GetChildCount() );
55fbde12
RR
2414
2415 return parent_node->GetChildCount();
2416}
2417
2418gboolean wxDataViewCtrlInternal::iter_nth_child( GtkTreeIter *iter, GtkTreeIter *parent, gint n )
2419{
2420 void* id = NULL;
2421 if (parent) id = (void*) parent->user_data;
2422 wxDataViewItem item( id );
2423
ed903e42 2424 if (!m_wx_model->IsContainer( item ))
55fbde12
RR
2425 return FALSE;
2426
2427 wxGtkTreeModelNode *parent_node = FindNode( parent );
2428 BuildBranch( parent_node );
2429
ef427989 2430 // wxPrintf( "iter_nth_child %d\n", n );
55fbde12
RR
2431
2432 iter->stamp = m_gtk_model->stamp;
af110130 2433 iter->user_data = parent_node->GetChildren().Item( n );
55fbde12
RR
2434
2435 return TRUE;
2436}
2437
2438gboolean wxDataViewCtrlInternal::iter_parent( GtkTreeIter *iter, GtkTreeIter *child )
2439{
af110130 2440 wxGtkTreeModelNode *node = FindParentNode( child );
55fbde12
RR
2441 if (!node)
2442 return FALSE;
2443
2444 iter->stamp = m_gtk_model->stamp;
2445 iter->user_data = (gpointer) node->GetItem().GetID();
2446
2447 return TRUE;
2448}
2449
55fbde12
RR
2450static wxGtkTreeModelNode*
2451wxDataViewCtrlInternal_FindNode( wxGtkTreeModelNode *node, const wxDataViewItem &item )
2452{
2453 if (!node) return NULL;
2454
af110130 2455 size_t count = node->GetNodesCount();
55fbde12
RR
2456 size_t i;
2457 for (i = 0; i < count; i++)
2458 {
af110130 2459 wxGtkTreeModelNode *child = node->GetNodes().Item( i );
55fbde12 2460 if (child->GetItem().GetID() == item.GetID())
ef427989
RR
2461 {
2462 // wxPrintf( "leave findnode at %d\n", i );
55fbde12 2463 return child;
ef427989 2464 }
55fbde12
RR
2465
2466 wxGtkTreeModelNode *node2 = wxDataViewCtrlInternal_FindNode( child, item );
2467 if (node2)
ef427989
RR
2468 {
2469 // wxPrintf( "branch findnode at %d\n", i );
55fbde12 2470 return node2;
ef427989 2471 }
55fbde12
RR
2472 }
2473
2474 return NULL;
2475}
2476
2477wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( GtkTreeIter *iter )
2478{
2479 if (!iter)
2480 return m_root;
2481
2482 wxDataViewItem item( (void*) iter->user_data );
0be79c8a
RR
2483 if (!item.IsOk())
2484 return m_root;
55fbde12
RR
2485
2486 wxGtkTreeModelNode *result = wxDataViewCtrlInternal_FindNode( m_root, item );
2487
2488 if (!result)
2489 {
2490 wxPrintf( "Not found %d\n", (int) iter->user_data );
2491 char *crash = NULL;
2492 *crash = 0;
2493 }
2494
2495 return result;
2496}
2497
2498wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( const wxDataViewItem &item )
2499{
0be79c8a
RR
2500 if (!item.IsOk())
2501 return m_root;
2502
55fbde12
RR
2503 wxGtkTreeModelNode *result = wxDataViewCtrlInternal_FindNode( m_root, item );
2504
2505 if (!result)
2506 {
2507 wxPrintf( "Not found %d\n", (int) item.GetID() );
2508 char *crash = NULL;
2509 *crash = 0;
2510 }
2511
2512 return result;
2513}
2514
af110130
RR
2515static wxGtkTreeModelNode*
2516wxDataViewCtrlInternal_FindParentNode( wxGtkTreeModelNode *node, const wxDataViewItem &item )
2517{
2518 size_t child_count = node->GetChildCount();
2519 void *id = item.GetID();
2520 const wxGtkTreeModelChildren &children = node->GetChildren();
2521 size_t pos;
2522 for (pos = 0; pos < child_count; pos++)
2523 {
2524 if (children.Item( pos ) == id)
2525 return node;
2526 }
2527
2528 size_t node_count = node->GetNodesCount();
2529 for (pos = 0; pos < node_count; pos++)
2530 {
2531 wxGtkTreeModelNode *child = node->GetNodes().Item( pos );
2532
2533 wxGtkTreeModelNode *node2 = wxDataViewCtrlInternal_FindParentNode( child, item );
2534 if (node2)
2535 {
2536 // wxPrintf( "branch findnode at %d\n", i );
2537 return node2;
2538 }
2539 }
2540
2541 return NULL;
2542}
2543
2544wxGtkTreeModelNode *wxDataViewCtrlInternal::FindParentNode( GtkTreeIter *iter )
2545{
2546 if (!iter)
2547 return NULL;
2548
2549 wxDataViewItem item( (void*) iter->user_data );
2550 if (!item.IsOk())
2551 return NULL;
2552
2553 return wxDataViewCtrlInternal_FindParentNode( m_root, item );
2554}
2555
2556wxGtkTreeModelNode *wxDataViewCtrlInternal::FindParentNode( const wxDataViewItem &item )
2557{
2558 if (!item.IsOk())
2559 return NULL;
2560
2561 return wxDataViewCtrlInternal_FindParentNode( m_root, item );
2562}
2563
eb7f97f8
RR
2564//-----------------------------------------------------------------------------
2565// wxDataViewCtrl signal callbacks
2566//-----------------------------------------------------------------------------
2567
2568static void
2569wxdataview_selection_changed_callback( GtkTreeSelection* selection, wxDataViewCtrl *dv )
2570{
b94db696
RR
2571 if (!GTK_WIDGET_REALIZED(dv->m_widget))
2572 return;
f4322df6 2573
e0062c04
RR
2574 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_SELECTED, dv->GetId() );
2575 // TODO: item
eb7f97f8
RR
2576 event.SetModel( dv->GetModel() );
2577 dv->GetEventHandler()->ProcessEvent( event );
2578}
2579
f828871d 2580static void
f4322df6 2581wxdataview_row_activated_callback( GtkTreeView* treeview, GtkTreePath *path,
f828871d
RR
2582 GtkTreeViewColumn *column, wxDataViewCtrl *dv )
2583{
e0062c04 2584 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, dv->GetId() );
55fbde12
RR
2585
2586 GtkTreeIter iter;
2587 dv->GtkGetInternal()->get_iter( &iter, path );
2588 wxDataViewItem item( (void*) iter.user_data );;
2589 event.SetItem( item );
f828871d
RR
2590 event.SetModel( dv->GetModel() );
2591 dv->GetEventHandler()->ProcessEvent( event );
2592}
2593
790b137e
RR
2594//-----------------------------------------------------------------------------
2595// wxDataViewCtrl
2596//-----------------------------------------------------------------------------
2597
1e510b1e
RR
2598//-----------------------------------------------------------------------------
2599// InsertChild for wxDataViewCtrl
2600//-----------------------------------------------------------------------------
2601
2602static void wxInsertChildInDataViewCtrl( wxWindowGTK* parent, wxWindowGTK* child )
2603{
2604 wxDataViewCtrl * dvc = (wxDataViewCtrl*) parent;
2605 GtkWidget *treeview = dvc->GtkGetTreeView();
2606
2607 // Insert widget in GtkTreeView
2608 if (GTK_WIDGET_REALIZED(treeview))
e8375af8 2609 gtk_widget_set_parent_window( child->m_widget,
1e510b1e
RR
2610 gtk_tree_view_get_bin_window( GTK_TREE_VIEW(treeview) ) );
2611 gtk_widget_set_parent( child->m_widget, treeview );
2612}
2613
2614static
2615void gtk_dataviewctrl_size_callback( GtkWidget *WXUNUSED(widget),
2616 GtkAllocation *alloc,
2617 wxDataViewCtrl *win )
2618{
e8375af8 2619
1e510b1e
RR
2620 wxWindowList::Node *node = win->GetChildren().GetFirst();
2621 while (node)
2622 {
2623 wxWindow *child = node->GetData();
e8375af8 2624
1e510b1e
RR
2625 GtkRequisition req;
2626 gtk_widget_size_request( child->m_widget, &req );
e8375af8 2627
1e510b1e
RR
2628 GtkAllocation alloc;
2629 alloc.x = child->m_x;
2630 alloc.y = child->m_y;
2631 alloc.width = child->m_width;
2632 alloc.height = child->m_height;
2633 gtk_widget_size_allocate( child->m_widget, &alloc );
e8375af8 2634
1e510b1e
RR
2635 node = node->GetNext();
2636 }
2637}
2638
2639
2640
239eaa41
RR
2641IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl, wxDataViewCtrlBase)
2642
2643wxDataViewCtrl::~wxDataViewCtrl()
2644{
8f850e28
RR
2645 if (m_notifier)
2646 GetModel()->RemoveNotifier( m_notifier );
87f0efe2
RR
2647
2648 // remove the model from the GtkTreeView before it gets destroyed by the
2649 // wxDataViewCtrlBase's dtor
2650 gtk_tree_view_set_model( GTK_TREE_VIEW(m_treeview), NULL );
55fbde12
RR
2651
2652 delete m_internal;
239eaa41
RR
2653}
2654
2655void wxDataViewCtrl::Init()
2656{
8f850e28 2657 m_notifier = NULL;
239eaa41
RR
2658}
2659
2660bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id,
93763ad5 2661 const wxPoint& pos, const wxSize& size,
239eaa41
RR
2662 long style, const wxValidator& validator )
2663{
2664 Init();
93763ad5 2665
239eaa41
RR
2666 if (!PreCreation( parent, pos, size ) ||
2667 !CreateBase( parent, id, pos, size, style, validator ))
2668 {
2669 wxFAIL_MSG( wxT("wxDataViewCtrl creation failed") );
93763ad5 2670 return false;
239eaa41 2671 }
1a367564 2672
1e510b1e
RR
2673 m_insertCallback = wxInsertChildInDataViewCtrl;
2674
1a367564 2675 m_widget = gtk_scrolled_window_new (NULL, NULL);
6493aaca
VZ
2676
2677 GtkScrolledWindowSetBorder(m_widget, style);
1a367564
RR
2678
2679 m_treeview = gtk_tree_view_new();
2680 gtk_container_add (GTK_CONTAINER (m_widget), m_treeview);
e8375af8 2681
1e510b1e
RR
2682 g_signal_connect (m_treeview, "size_allocate",
2683 G_CALLBACK (gtk_dataviewctrl_size_callback), this);
ed4b0fdc 2684
b94db696
RR
2685#ifdef __WXGTK26__
2686 if (!gtk_check_version(2,6,0))
2687 gtk_tree_view_set_fixed_height_mode( GTK_TREE_VIEW(m_treeview), TRUE );
2688#endif
2689
daebb44c
RR
2690 if (style & wxDV_MULTIPLE)
2691 {
2692 GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
2693 gtk_tree_selection_set_mode( selection, GTK_SELECTION_MULTIPLE );
2694 }
93763ad5 2695
9861f022
RR
2696 gtk_tree_view_set_headers_visible( GTK_TREE_VIEW(m_treeview), (style & wxDV_NO_HEADER) == 0 );
2697
2698#ifdef __WXGTK210__
2699 if (!gtk_check_version(2,10,0))
2700 {
2701 GtkTreeViewGridLines grid = GTK_TREE_VIEW_GRID_LINES_NONE;
f4322df6
VZ
2702
2703 if ((style & wxDV_HORIZ_RULES) != 0 &&
9861f022
RR
2704 (style & wxDV_VERT_RULES) != 0)
2705 grid = GTK_TREE_VIEW_GRID_LINES_BOTH;
2706 else if (style & wxDV_VERT_RULES)
2707 grid = GTK_TREE_VIEW_GRID_LINES_VERTICAL;
2708 else if (style & wxDV_HORIZ_RULES)
2709 grid = GTK_TREE_VIEW_GRID_LINES_HORIZONTAL;
2710
2711 gtk_tree_view_set_grid_lines( GTK_TREE_VIEW(m_treeview), grid );
2712 }
2713 else
2714#endif
2fa73716 2715 {
9861f022 2716 gtk_tree_view_set_rules_hint( GTK_TREE_VIEW(m_treeview), (style & wxDV_HORIZ_RULES) != 0 );
2fa73716 2717 }
9861f022 2718
1a367564
RR
2719 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (m_widget),
2720 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2721 gtk_widget_show (m_treeview);
93763ad5 2722
239eaa41
RR
2723 m_parent->DoAddChild( this );
2724
b94db696
RR
2725 PostCreation(size);
2726
b086d55f
RR
2727 GtkEnableSelectionEvents();
2728
f828871d
RR
2729 g_signal_connect_after (m_treeview, "row_activated",
2730 G_CALLBACK (wxdataview_row_activated_callback), this);
eb7f97f8 2731
239eaa41
RR
2732 return true;
2733}
2734
31fb32e1
RR
2735void wxDataViewCtrl::OnInternalIdle()
2736{
2737 wxWindow::OnInternalIdle();
f4322df6 2738
9861f022 2739 unsigned int cols = GetColumnCount();
31fb32e1
RR
2740 unsigned int i;
2741 for (i = 0; i < cols; i++)
2742 {
2743 wxDataViewColumn *col = GetColumn( i );
2744 col->OnInternalIdle();
2745 }
2746}
2747
e0062c04 2748bool wxDataViewCtrl::AssociateModel( wxDataViewModel *model )
239eaa41
RR
2749{
2750 if (!wxDataViewCtrlBase::AssociateModel( model ))
2751 return false;
2752
55fbde12
RR
2753 GtkWxTreeModel *gtk_model = wxgtk_tree_model_new();
2754 m_internal = new wxDataViewCtrlInternal( this, model, gtk_model );
2755 gtk_model->internal = m_internal;
6e2e590f 2756
55fbde12 2757 m_notifier = new wxGtkDataViewModelNotifier( gtk_model, model, this );
6e2e590f 2758
93763ad5 2759 model->AddNotifier( m_notifier );
1557c77b 2760
55fbde12
RR
2761 gtk_tree_view_set_model( GTK_TREE_VIEW(m_treeview), GTK_TREE_MODEL(gtk_model) );
2762
2763 // unref in wxDataViewCtrlInternal
2764 // g_object_unref( gtk_model );
93763ad5 2765
239eaa41
RR
2766 return true;
2767}
790b137e 2768
fa28826d
RR
2769bool wxDataViewCtrl::AppendColumn( wxDataViewColumn *col )
2770{
2771 if (!wxDataViewCtrlBase::AppendColumn(col))
2772 return false;
93763ad5 2773
fa28826d
RR
2774 GtkTreeViewColumn *column = (GtkTreeViewColumn *)col->GetGtkHandle();
2775
1a367564 2776 gtk_tree_view_append_column( GTK_TREE_VIEW(m_treeview), column );
fa28826d
RR
2777
2778 return true;
2779}
2780
1e08ad10
RR
2781wxDataViewItem wxDataViewCtrl::GetSelection()
2782{
2783 GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
2784
2785 if (m_windowStyle & wxDV_MULTIPLE)
2786 {
2787 }
2788 else
2789 {
2790 GtkTreeIter iter;
2791 if (gtk_tree_selection_get_selected( selection, NULL, &iter ))
2792 {
9d52aad3 2793 wxDataViewItem item( (void*) iter.user_data );
1e08ad10
RR
2794 return item;
2795 }
2796 }
2797
2798 return wxDataViewItem(0);
2799}
2800
3b6280be
RR
2801void wxDataViewCtrl::DoSetExpanderColumn()
2802{
2803}
2804
2805void wxDataViewCtrl::DoSetIndent()
2806{
2807}
2808
b086d55f
RR
2809void wxDataViewCtrl::GtkDisableSelectionEvents()
2810{
2811 GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
2812 g_signal_connect_after (selection, "changed",
2813 G_CALLBACK (wxdataview_selection_changed_callback), this);
2814}
2815
2816void wxDataViewCtrl::GtkEnableSelectionEvents()
2817{
2818 GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
e0743e63 2819 g_signal_handlers_disconnect_by_func( selection,
b086d55f
RR
2820 (gpointer) (wxdataview_selection_changed_callback), this);
2821}
2822
b94db696
RR
2823// static
2824wxVisualAttributes
2825wxDataViewCtrl::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
2826{
2827 return GetDefaultAttributesFromGTKWidget(gtk_tree_view_new);
2828}
2829
6ff7eee7 2830
93763ad5 2831#endif
4ed7af08 2832 // !wxUSE_GENERICDATAVIEWCTRL
790b137e 2833
93763ad5 2834#endif
4ed7af08 2835 // wxUSE_DATAVIEWCTRL