]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/dataview.cpp
don't leak memory if exceptions are thrown during a new wxDocument creation
[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"
c3c62822
PC
23 #include "wx/settings.h"
24 #include "wx/crt.h"
e4db172a
WS
25#endif
26
790b137e 27#include "wx/stockitem.h"
7ea3a0de
RR
28#include "wx/calctrl.h"
29#include "wx/popupwin.h"
69892729 30#include "wx/listimpl.cpp"
790b137e
RR
31
32#include "wx/gtk/private.h"
888dde65
RR
33#include "wx/gtk/dc.h"
34#include "wx/gtk/dcclient.h"
4d496ecb 35
790b137e 36//-----------------------------------------------------------------------------
790b137e
RR
37//-----------------------------------------------------------------------------
38
8c2654ce 39static wxDataViewCtrlInternal *gs_internal = NULL;
3b6280be
RR
40
41class wxGtkTreeModelNode;
ef427989 42
0be79c8a
RR
43extern "C" {
44typedef struct _GtkWxTreeModel GtkWxTreeModel;
45}
46
af110130
RR
47//-----------------------------------------------------------------------------
48// wxDataViewCtrlInternal
49//-----------------------------------------------------------------------------
50
69892729 51WX_DECLARE_LIST(wxDataViewItem, ItemList);
a76c2f37 52WX_DEFINE_LIST(ItemList)
69892729 53
8c2654ce 54class WXDLLIMPEXP_ADV wxDataViewCtrlInternal
af110130
RR
55{
56public:
7dea20f6 57 wxDataViewCtrlInternal( wxDataViewCtrl *owner, wxDataViewModel *wx_model, GtkWxTreeModel *gtk_model );
af110130 58 ~wxDataViewCtrlInternal();
b9db5f30 59
f6f0ef85 60 // model iface
2056dede 61 GtkTreeModelFlags get_flags();
af110130
RR
62 gboolean get_iter( GtkTreeIter *iter, GtkTreePath *path );
63 GtkTreePath *get_path( GtkTreeIter *iter);
af110130
RR
64 gboolean iter_next( GtkTreeIter *iter );
65 gboolean iter_children( GtkTreeIter *iter, GtkTreeIter *parent);
66 gboolean iter_has_child( GtkTreeIter *iter );
67 gint iter_n_children( GtkTreeIter *iter );
68 gboolean iter_nth_child( GtkTreeIter *iter, GtkTreeIter *parent, gint n );
69 gboolean iter_parent( GtkTreeIter *iter, GtkTreeIter *child );
b9db5f30 70
f6f0ef85 71 // dnd iface
8c2654ce 72
15cac64f 73 bool EnableDragSource( const wxDataFormat &format );
e4de825e 74 bool EnableDropTarget( const wxDataFormat &format );
8c2654ce 75
f6f0ef85
RR
76 gboolean row_draggable( GtkTreeDragSource *drag_source, GtkTreePath *path );
77 gboolean drag_data_delete( GtkTreeDragSource *drag_source, GtkTreePath* path );
7857346a 78 gboolean drag_data_get( GtkTreeDragSource *drag_source, GtkTreePath *path,
f6f0ef85 79 GtkSelectionData *selection_data );
7857346a 80 gboolean drag_data_received( GtkTreeDragDest *drag_dest, GtkTreePath *dest,
f6f0ef85 81 GtkSelectionData *selection_data );
7857346a 82 gboolean row_drop_possible( GtkTreeDragDest *drag_dest, GtkTreePath *dest_path,
f6f0ef85
RR
83 GtkSelectionData *selection_data );
84
85 // notifactions from wxDataViewModel
af110130 86 bool ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item );
469d3e9b 87 bool ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item );
d8331a01
RR
88 bool ItemChanged( const wxDataViewItem &item );
89 bool ValueChanged( const wxDataViewItem &item, unsigned int col );
90 bool Cleared();
af110130 91 void Resort();
b9db5f30 92
f6f0ef85 93 // sorting interface
b8b7b087
RR
94 void SetSortOrder( GtkSortType sort_order ) { m_sort_order = sort_order; }
95 GtkSortType GetSortOrder() { return m_sort_order; }
7ee7191c 96
40196b1e
RR
97 void SetSortColumn( int column ) { m_sort_column = column; }
98 int GetSortColumn() { return m_sort_column; }
b9db5f30 99
d32332aa
RR
100 void SetDataViewSortColumn( wxDataViewColumn *column ) { m_dataview_sort_column = column; }
101 wxDataViewColumn *GetDataViewSortColumn() { return m_dataview_sort_column; }
b9db5f30 102
40196b1e 103 bool IsSorted() { return (m_sort_column >= 0); }
b9db5f30 104
f6f0ef85
RR
105 // accessors
106 wxDataViewModel* GetDataViewModel() { return m_wx_model; }
107 wxDataViewCtrl* GetOwner() { return m_owner; }
108 GtkWxTreeModel* GetGtkModel() { return m_gtk_model; }
b9db5f30 109
af110130
RR
110protected:
111 void InitTree();
112 wxGtkTreeModelNode *FindNode( const wxDataViewItem &item );
113 wxGtkTreeModelNode *FindNode( GtkTreeIter *iter );
114 wxGtkTreeModelNode *FindParentNode( const wxDataViewItem &item );
115 wxGtkTreeModelNode *FindParentNode( GtkTreeIter *iter );
116 void BuildBranch( wxGtkTreeModelNode *branch );
b9db5f30 117
af110130
RR
118private:
119 wxGtkTreeModelNode *m_root;
120 wxDataViewModel *m_wx_model;
121 GtkWxTreeModel *m_gtk_model;
122 wxDataViewCtrl *m_owner;
b8b7b087 123 GtkSortType m_sort_order;
d32332aa 124 wxDataViewColumn *m_dataview_sort_column;
40196b1e 125 int m_sort_column;
8c2654ce 126
15cac64f
RR
127 GtkTargetEntry m_dragSourceTargetEntry;
128 wxCharBuffer m_dragSourceTargetEntryTarget;
591cc82d 129 wxDataObject *m_dragDataObject;
8c2654ce 130
e4de825e
RR
131 GtkTargetEntry m_dropTargetTargetEntry;
132 wxCharBuffer m_dropTargetTargetEntryTarget;
591cc82d 133 wxDataObject *m_dropDataObject;
af110130 134};
ef427989 135
af110130
RR
136
137//-----------------------------------------------------------------------------
138// wxGtkTreeModelNode
139//-----------------------------------------------------------------------------
140
8c2654ce 141static
40196b1e
RR
142int LINKAGEMODE wxGtkTreeModelChildCmp( void** id1, void** id2 )
143{
8c2654ce
PC
144 int ret = gs_internal->GetDataViewModel()->Compare( *id1, *id2,
145 gs_internal->GetSortColumn(), (gs_internal->GetSortOrder() == GTK_SORT_ASCENDING) );
b9db5f30 146
40196b1e
RR
147 return ret;
148}
af110130
RR
149
150WX_DEFINE_ARRAY_PTR( wxGtkTreeModelNode*, wxGtkTreeModelNodes );
40196b1e 151WX_DEFINE_ARRAY_PTR( void*, wxGtkTreeModelChildren );
3b6280be
RR
152
153class wxGtkTreeModelNode
154{
155public:
ef427989 156 wxGtkTreeModelNode( wxGtkTreeModelNode* parent, const wxDataViewItem &item,
c2489d8e 157 wxDataViewCtrlInternal *internal )
b9db5f30
VS
158 {
159 m_parent = parent;
d5025dc0 160 m_item = item;
0be79c8a 161 m_internal = internal;
3b6280be 162 }
b9db5f30 163
3b6280be 164 ~wxGtkTreeModelNode()
b9db5f30 165 {
023eecb7 166 size_t count = m_nodes.GetCount();
3b6280be
RR
167 size_t i;
168 for (i = 0; i < count; i++)
169 {
af110130 170 wxGtkTreeModelNode *child = m_nodes.Item( i );
3b6280be
RR
171 delete child;
172 }
173 }
174
b9db5f30
VS
175 unsigned int AddNode( wxGtkTreeModelNode* child )
176 {
af110130 177 m_nodes.Add( child );
b9db5f30 178
40196b1e 179 void *id = child->GetItem().GetID();
b9db5f30 180
40196b1e 181 m_children.Add( id );
0bd26819
RR
182
183 if (m_internal->IsSorted() || m_internal->GetDataViewModel()->HasDefaultCompare())
40196b1e 184 {
8c2654ce 185 gs_internal = m_internal;
40196b1e
RR
186 m_children.Sort( &wxGtkTreeModelChildCmp );
187 return m_children.Index( id );
188 }
0bd26819 189
40196b1e 190 return m_children.GetCount()-1;
af110130 191 }
b9db5f30 192
af110130
RR
193 unsigned int AddLeave( void* id )
194 {
40196b1e 195 m_children.Add( id );
0bd26819
RR
196
197 if (m_internal->IsSorted() || m_internal->GetDataViewModel()->HasDefaultCompare())
40196b1e 198 {
8c2654ce 199 gs_internal = m_internal;
40196b1e
RR
200 m_children.Sort( &wxGtkTreeModelChildCmp );
201 return m_children.Index( id );
202 }
0bd26819 203
40196b1e 204 return m_children.GetCount()-1;
af110130 205 }
b9db5f30 206
af110130
RR
207 void DeleteChild( void* id )
208 {
40196b1e 209 m_children.Remove( id );
b9db5f30 210
40196b1e
RR
211 unsigned int count = m_nodes.GetCount();
212 unsigned int pos;
af110130 213 for (pos = 0; pos < count; pos++)
b9db5f30 214 {
af110130
RR
215 wxGtkTreeModelNode *node = m_nodes.Item( pos );
216 if (node->GetItem().GetID() == id)
217 {
218 m_nodes.RemoveAt( pos );
219 delete node;
220 break;
221 }
222 }
af110130 223 }
b9db5f30
VS
224
225 wxGtkTreeModelNode* GetParent()
3b6280be 226 { return m_parent; }
b9db5f30 227 wxGtkTreeModelNodes &GetNodes()
af110130 228 { return m_nodes; }
b9db5f30 229 wxGtkTreeModelChildren &GetChildren()
40196b1e 230 { return m_children; }
b9db5f30 231
c2489d8e
FM
232 unsigned int GetChildCount() const { return m_children.GetCount(); }
233 unsigned int GetNodesCount() const { return m_nodes.GetCount(); }
3b6280be
RR
234
235 wxDataViewItem &GetItem() { return m_item; }
0be79c8a 236 wxDataViewCtrlInternal *GetInternal() { return m_internal; }
b9db5f30 237
4508fcd2 238 void Resort();
b9db5f30 239
3b6280be 240private:
0be79c8a 241 wxGtkTreeModelNode *m_parent;
af110130 242 wxGtkTreeModelNodes m_nodes;
40196b1e 243 wxGtkTreeModelChildren m_children;
b9db5f30 244 wxDataViewItem m_item;
0be79c8a 245 wxDataViewCtrlInternal *m_internal;
3b6280be
RR
246};
247
ef427989 248
790b137e
RR
249//-----------------------------------------------------------------------------
250// data
251//-----------------------------------------------------------------------------
252
253extern bool g_blockEventsOnDrag;
254
255//-----------------------------------------------------------------------------
e0062c04 256// define new GTK+ class wxGtkTreeModel
790b137e
RR
257//-----------------------------------------------------------------------------
258
259extern "C" {
260
e0062c04
RR
261#define GTK_TYPE_WX_TREE_MODEL (gtk_wx_tree_model_get_type ())
262#define GTK_WX_TREE_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WX_TREE_MODEL, GtkWxTreeModel))
263#define GTK_WX_TREE_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WX_TREE_MODEL, GtkWxTreeModelClass))
264#define GTK_IS_WX_TREE_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WX_TREE_MODEL))
265#define GTK_IS_WX_TREE_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WX_TREE_MODEL))
266#define GTK_WX_TREE_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WX_TREE_MODEL, GtkWxTreeModelClass))
790b137e 267
e0062c04 268GType gtk_wx_tree_model_get_type (void);
790b137e 269
e0062c04 270typedef struct _GtkWxTreeModelClass GtkWxTreeModelClass;
790b137e 271
e0062c04 272struct _GtkWxTreeModel
790b137e
RR
273{
274 GObject parent;
275
276 /*< private >*/
277 gint stamp;
55fbde12 278 wxDataViewCtrlInternal *internal;
790b137e
RR
279};
280
e0062c04 281struct _GtkWxTreeModelClass
790b137e 282{
e152afc3 283 GObjectClass list_parent_class;
790b137e
RR
284};
285
e0062c04 286static GtkWxTreeModel *wxgtk_tree_model_new (void);
773cca48
RR
287static void wxgtk_tree_model_init (GtkWxTreeModel *tree_model);
288static void wxgtk_tree_model_class_init (GtkWxTreeModelClass *klass);
85136e3b
RR
289
290static void wxgtk_tree_model_tree_model_init (GtkTreeModelIface *iface);
291static void wxgtk_tree_model_sortable_init (GtkTreeSortableIface *iface);
292static void wxgtk_tree_model_drag_source_init(GtkTreeDragSourceIface *iface);
293static void wxgtk_tree_model_drag_dest_init (GtkTreeDragDestIface *iface);
294
e0062c04
RR
295static void wxgtk_tree_model_finalize (GObject *object);
296static GtkTreeModelFlags wxgtk_tree_model_get_flags (GtkTreeModel *tree_model);
297static gint wxgtk_tree_model_get_n_columns (GtkTreeModel *tree_model);
298static GType wxgtk_tree_model_get_column_type (GtkTreeModel *tree_model,
93763ad5 299 gint index);
e0062c04 300static gboolean wxgtk_tree_model_get_iter (GtkTreeModel *tree_model,
93763ad5
WS
301 GtkTreeIter *iter,
302 GtkTreePath *path);
e0062c04 303static GtkTreePath *wxgtk_tree_model_get_path (GtkTreeModel *tree_model,
93763ad5 304 GtkTreeIter *iter);
e0062c04 305static void wxgtk_tree_model_get_value (GtkTreeModel *tree_model,
93763ad5
WS
306 GtkTreeIter *iter,
307 gint column,
308 GValue *value);
e0062c04 309static gboolean wxgtk_tree_model_iter_next (GtkTreeModel *tree_model,
93763ad5 310 GtkTreeIter *iter);
e0062c04 311static gboolean wxgtk_tree_model_iter_children (GtkTreeModel *tree_model,
93763ad5
WS
312 GtkTreeIter *iter,
313 GtkTreeIter *parent);
e0062c04 314static gboolean wxgtk_tree_model_iter_has_child (GtkTreeModel *tree_model,
93763ad5 315 GtkTreeIter *iter);
e0062c04 316static gint wxgtk_tree_model_iter_n_children (GtkTreeModel *tree_model,
93763ad5 317 GtkTreeIter *iter);
e0062c04 318static gboolean wxgtk_tree_model_iter_nth_child (GtkTreeModel *tree_model,
93763ad5
WS
319 GtkTreeIter *iter,
320 GtkTreeIter *parent,
321 gint n);
e0062c04 322static gboolean wxgtk_tree_model_iter_parent (GtkTreeModel *tree_model,
93763ad5
WS
323 GtkTreeIter *iter,
324 GtkTreeIter *child);
790b137e 325
773cca48
RR
326/* sortable */
327static gboolean wxgtk_tree_model_get_sort_column_id (GtkTreeSortable *sortable,
85136e3b 328 gint *sort_column_id,
c2489d8e 329 GtkSortType *order);
773cca48 330static void wxgtk_tree_model_set_sort_column_id (GtkTreeSortable *sortable,
85136e3b
RR
331 gint sort_column_id,
332 GtkSortType order);
773cca48 333static void wxgtk_tree_model_set_sort_func (GtkTreeSortable *sortable,
85136e3b
RR
334 gint sort_column_id,
335 GtkTreeIterCompareFunc func,
336 gpointer data,
337 GtkDestroyNotify destroy);
773cca48 338static void wxgtk_tree_model_set_default_sort_func (GtkTreeSortable *sortable,
85136e3b
RR
339 GtkTreeIterCompareFunc func,
340 gpointer data,
341 GtkDestroyNotify destroy);
773cca48
RR
342static gboolean wxgtk_tree_model_has_default_sort_func (GtkTreeSortable *sortable);
343
85136e3b
RR
344/* drag'n'drop */
345static gboolean wxgtk_tree_model_row_draggable (GtkTreeDragSource *drag_source,
346 GtkTreePath *path);
347static gboolean wxgtk_tree_model_drag_data_delete (GtkTreeDragSource *drag_source,
348 GtkTreePath *path);
349static gboolean wxgtk_tree_model_drag_data_get (GtkTreeDragSource *drag_source,
350 GtkTreePath *path,
351 GtkSelectionData *selection_data);
352static gboolean wxgtk_tree_model_drag_data_received (GtkTreeDragDest *drag_dest,
353 GtkTreePath *dest,
354 GtkSelectionData *selection_data);
355static gboolean wxgtk_tree_model_row_drop_possible (GtkTreeDragDest *drag_dest,
356 GtkTreePath *dest_path,
c2489d8e 357 GtkSelectionData *selection_data);
773cca48
RR
358
359
e152afc3 360static GObjectClass *list_parent_class = NULL;
790b137e
RR
361
362GType
e0062c04 363gtk_wx_tree_model_get_type (void)
790b137e 364{
e0062c04 365 static GType tree_model_type = 0;
790b137e 366
e0062c04 367 if (!tree_model_type)
790b137e 368 {
e0062c04 369 const GTypeInfo tree_model_info =
93763ad5 370 {
e0062c04 371 sizeof (GtkWxTreeModelClass),
93763ad5
WS
372 NULL, /* base_init */
373 NULL, /* base_finalize */
e0062c04 374 (GClassInitFunc) wxgtk_tree_model_class_init,
93763ad5
WS
375 NULL, /* class_finalize */
376 NULL, /* class_data */
e0062c04 377 sizeof (GtkWxTreeModel),
93763ad5 378 0,
e0062c04 379 (GInstanceInitFunc) wxgtk_tree_model_init,
93763ad5 380 };
790b137e 381
773cca48
RR
382 static const GInterfaceInfo tree_model_iface_info =
383 {
384 (GInterfaceInitFunc) wxgtk_tree_model_tree_model_init,
385 NULL,
386 NULL
387 };
388
389 static const GInterfaceInfo sortable_iface_info =
390 {
391 (GInterfaceInitFunc) wxgtk_tree_model_sortable_init,
392 NULL,
393 NULL
394 };
790b137e 395
85136e3b
RR
396 static const GInterfaceInfo drag_source_iface_info =
397 {
398 (GInterfaceInitFunc) wxgtk_tree_model_drag_source_init,
399 NULL,
400 NULL
401 };
402
403 static const GInterfaceInfo drag_dest_iface_info =
404 {
405 (GInterfaceInitFunc) wxgtk_tree_model_drag_dest_init,
406 NULL,
407 NULL
408 };
409
773cca48 410 tree_model_type = g_type_register_static (G_TYPE_OBJECT, "GtkWxTreeModel",
e0062c04 411 &tree_model_info, (GTypeFlags)0 );
790b137e 412
773cca48
RR
413 g_type_add_interface_static (tree_model_type,
414 GTK_TYPE_TREE_MODEL,
415 &tree_model_iface_info);
416 g_type_add_interface_static (tree_model_type,
417 GTK_TYPE_TREE_SORTABLE,
418 &sortable_iface_info);
85136e3b
RR
419 g_type_add_interface_static (tree_model_type,
420 GTK_TYPE_TREE_DRAG_DEST,
421 &drag_dest_iface_info);
422 g_type_add_interface_static (tree_model_type,
423 GTK_TYPE_TREE_DRAG_SOURCE,
424 &drag_source_iface_info);
790b137e
RR
425 }
426
773cca48 427 return tree_model_type;
790b137e
RR
428}
429
e0062c04
RR
430static GtkWxTreeModel *
431wxgtk_tree_model_new(void)
1557c77b 432{
e0062c04 433 GtkWxTreeModel *retval = (GtkWxTreeModel *) g_object_new (GTK_TYPE_WX_TREE_MODEL, NULL);
e152afc3 434 return retval;
1557c77b
RR
435}
436
790b137e 437static void
e0062c04 438wxgtk_tree_model_class_init (GtkWxTreeModelClass *klass)
790b137e 439{
e152afc3
RR
440 list_parent_class = (GObjectClass*) g_type_class_peek_parent (klass);
441 GObjectClass *object_class = (GObjectClass*) klass;
e0062c04 442 object_class->finalize = wxgtk_tree_model_finalize;
790b137e
RR
443}
444
445static void
e0062c04
RR
446wxgtk_tree_model_tree_model_init (GtkTreeModelIface *iface)
447{
448 iface->get_flags = wxgtk_tree_model_get_flags;
449 iface->get_n_columns = wxgtk_tree_model_get_n_columns;
450 iface->get_column_type = wxgtk_tree_model_get_column_type;
451 iface->get_iter = wxgtk_tree_model_get_iter;
452 iface->get_path = wxgtk_tree_model_get_path;
453 iface->get_value = wxgtk_tree_model_get_value;
454 iface->iter_next = wxgtk_tree_model_iter_next;
455 iface->iter_children = wxgtk_tree_model_iter_children;
456 iface->iter_has_child = wxgtk_tree_model_iter_has_child;
457 iface->iter_n_children = wxgtk_tree_model_iter_n_children;
458 iface->iter_nth_child = wxgtk_tree_model_iter_nth_child;
459 iface->iter_parent = wxgtk_tree_model_iter_parent;
790b137e
RR
460}
461
773cca48
RR
462static void
463wxgtk_tree_model_sortable_init (GtkTreeSortableIface *iface)
464{
94b1f7bc
RR
465 iface->get_sort_column_id = wxgtk_tree_model_get_sort_column_id;
466 iface->set_sort_column_id = wxgtk_tree_model_set_sort_column_id;
467 iface->set_sort_func = wxgtk_tree_model_set_sort_func;
468 iface->set_default_sort_func = wxgtk_tree_model_set_default_sort_func;
469 iface->has_default_sort_func = wxgtk_tree_model_has_default_sort_func;
773cca48
RR
470}
471
7857346a 472static void
85136e3b
RR
473wxgtk_tree_model_drag_source_init(GtkTreeDragSourceIface *iface)
474{
475 iface->row_draggable = wxgtk_tree_model_row_draggable;
476 iface->drag_data_delete = wxgtk_tree_model_drag_data_delete;
477 iface->drag_data_get = wxgtk_tree_model_drag_data_get;
478}
479
7857346a 480static void
85136e3b
RR
481wxgtk_tree_model_drag_dest_init (GtkTreeDragDestIface *iface)
482{
483 iface->drag_data_received = wxgtk_tree_model_drag_data_received;
484 iface->row_drop_possible = wxgtk_tree_model_row_drop_possible;
485}
486
790b137e 487static void
e0062c04 488wxgtk_tree_model_init (GtkWxTreeModel *tree_model)
790b137e 489{
55fbde12 490 tree_model->internal = NULL;
e0062c04 491 tree_model->stamp = g_random_int();
790b137e
RR
492}
493
494static void
e0062c04 495wxgtk_tree_model_finalize (GObject *object)
790b137e 496{
790b137e 497 /* must chain up */
e152afc3 498 (* list_parent_class->finalize) (object);
790b137e 499}
93763ad5 500
790b137e
RR
501} // extern "C"
502
503//-----------------------------------------------------------------------------
e0062c04
RR
504// implement callbacks from wxGtkTreeModel class by letting
505// them call the methods of wxWidgets' wxDataViewModel
790b137e
RR
506//-----------------------------------------------------------------------------
507
508static GtkTreeModelFlags
e0062c04 509wxgtk_tree_model_get_flags (GtkTreeModel *tree_model)
790b137e 510{
2056dede
RR
511 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
512 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), (GtkTreeModelFlags)0 );
790b137e 513
2056dede 514 return wxtree_model->internal->get_flags();
790b137e
RR
515}
516
517static gint
e0062c04 518wxgtk_tree_model_get_n_columns (GtkTreeModel *tree_model)
790b137e 519{
e0062c04
RR
520 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
521 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), 0);
790b137e 522
55fbde12 523 return wxtree_model->internal->GetDataViewModel()->GetColumnCount();
790b137e
RR
524}
525
526static GType
e0062c04 527wxgtk_tree_model_get_column_type (GtkTreeModel *tree_model,
93763ad5 528 gint index)
790b137e 529{
e0062c04
RR
530 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
531 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), G_TYPE_INVALID);
790b137e 532
1557c77b 533 GType gtype = G_TYPE_INVALID;
93763ad5 534
55fbde12 535 wxString wxtype = wxtree_model->internal->GetDataViewModel()->GetColumnType( (unsigned int) index );
93763ad5 536
1557c77b
RR
537 if (wxtype == wxT("string"))
538 gtype = G_TYPE_STRING;
72a3ac9b
VZ
539 else
540 {
e94d0c1e
RR
541 gtype = G_TYPE_STRING;
542 // wxFAIL_MSG( _T("non-string columns not supported yet") );
72a3ac9b 543 }
790b137e
RR
544
545 return gtype;
546}
547
548static gboolean
e0062c04 549wxgtk_tree_model_get_iter (GtkTreeModel *tree_model,
93763ad5
WS
550 GtkTreeIter *iter,
551 GtkTreePath *path)
790b137e 552{
e0062c04
RR
553 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
554 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE);
790b137e
RR
555 g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
556
55fbde12 557 return wxtree_model->internal->get_iter( iter, path );
790b137e
RR
558}
559
560static GtkTreePath *
e0062c04 561wxgtk_tree_model_get_path (GtkTreeModel *tree_model,
93763ad5 562 GtkTreeIter *iter)
790b137e 563{
e0062c04
RR
564 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
565 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), NULL);
566 g_return_val_if_fail (iter->stamp == GTK_WX_TREE_MODEL (wxtree_model)->stamp, NULL);
93763ad5 567
55fbde12 568 return wxtree_model->internal->get_path( iter );
790b137e
RR
569}
570
571static void
e0062c04 572wxgtk_tree_model_get_value (GtkTreeModel *tree_model,
93763ad5
WS
573 GtkTreeIter *iter,
574 gint column,
575 GValue *value)
790b137e 576{
e0062c04
RR
577 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
578 g_return_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model) );
239eaa41 579
55fbde12 580 wxDataViewModel *model = wxtree_model->internal->GetDataViewModel();
9861f022 581 wxString mtype = model->GetColumnType( (unsigned int) column );
1557c77b
RR
582 if (mtype == wxT("string"))
583 {
3f3af7e7 584 wxVariant variant;
1557c77b 585 g_value_init( value, G_TYPE_STRING );
9d52aad3 586 wxDataViewItem item( (void*) iter->user_data );
e0062c04 587 model->GetValue( variant, item, (unsigned int) column );
72a3ac9b 588
e0062c04 589 g_value_set_string( value, variant.GetString().utf8_str() );
1557c77b
RR
590 }
591 else
592 {
72a3ac9b 593 wxFAIL_MSG( _T("non-string columns not supported yet") );
1557c77b 594 }
790b137e
RR
595}
596
597static gboolean
e0062c04 598wxgtk_tree_model_iter_next (GtkTreeModel *tree_model,
93763ad5 599 GtkTreeIter *iter)
790b137e 600{
e0062c04 601 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
7857346a 602
c2489d8e
FM
603 //if (wxtree_model->stamp != iter->stamp)
604 // wxPrintf( "crash\n" );
605 // TODO: remove this code
33ba5a05 606
e0062c04 607 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE);
e0062c04 608 g_return_val_if_fail (wxtree_model->stamp == iter->stamp, FALSE);
7857346a 609
55fbde12 610 return wxtree_model->internal->iter_next( iter );
790b137e
RR
611}
612
613static gboolean
e0062c04 614wxgtk_tree_model_iter_children (GtkTreeModel *tree_model,
93763ad5
WS
615 GtkTreeIter *iter,
616 GtkTreeIter *parent)
790b137e 617{
e0062c04
RR
618 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
619 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE);
e0062c04 620 g_return_val_if_fail (wxtree_model->stamp == parent->stamp, FALSE);
790b137e 621
55fbde12 622 return wxtree_model->internal->iter_children( iter, parent );
790b137e
RR
623}
624
625static gboolean
e0062c04 626wxgtk_tree_model_iter_has_child (GtkTreeModel *tree_model,
93763ad5 627 GtkTreeIter *iter)
790b137e 628{
e0062c04
RR
629 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
630 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE);
e0062c04 631 g_return_val_if_fail (wxtree_model->stamp == iter->stamp, FALSE);
d5025dc0 632
55fbde12 633 return wxtree_model->internal->iter_has_child( iter );
790b137e
RR
634}
635
636static gint
e0062c04 637wxgtk_tree_model_iter_n_children (GtkTreeModel *tree_model,
93763ad5 638 GtkTreeIter *iter)
790b137e 639{
e0062c04
RR
640 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
641 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE);
c2489d8e 642
11f20f99
RR
643 if (iter != NULL)
644 g_return_val_if_fail (wxtree_model->stamp == iter->stamp, 0);
c2489d8e 645
55fbde12 646 return wxtree_model->internal->iter_n_children( iter );
790b137e
RR
647}
648
649static gboolean
e0062c04 650wxgtk_tree_model_iter_nth_child (GtkTreeModel *tree_model,
93763ad5
WS
651 GtkTreeIter *iter,
652 GtkTreeIter *parent,
653 gint n)
790b137e 654{
e0062c04
RR
655 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
656 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE);
657
55fbde12 658 return wxtree_model->internal->iter_nth_child( iter, parent, n );
790b137e
RR
659}
660
661static gboolean
e0062c04 662wxgtk_tree_model_iter_parent (GtkTreeModel *tree_model,
93763ad5
WS
663 GtkTreeIter *iter,
664 GtkTreeIter *child)
790b137e 665{
e0062c04
RR
666 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model;
667 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE);
e0062c04 668 g_return_val_if_fail (wxtree_model->stamp == child->stamp, FALSE);
b9db5f30 669
55fbde12 670 return wxtree_model->internal->iter_parent( iter, child );
790b137e
RR
671}
672
85136e3b 673/* drag'n'drop iface */
7857346a 674static gboolean
85136e3b
RR
675wxgtk_tree_model_row_draggable (GtkTreeDragSource *drag_source,
676 GtkTreePath *path)
677{
f6f0ef85
RR
678 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) drag_source;
679 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE);
7857346a 680
f6f0ef85 681 return wxtree_model->internal->row_draggable( drag_source, path );
85136e3b
RR
682}
683
7857346a 684static gboolean
85136e3b
RR
685wxgtk_tree_model_drag_data_delete (GtkTreeDragSource *drag_source,
686 GtkTreePath *path)
687{
f6f0ef85
RR
688 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) drag_source;
689 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE);
7857346a 690
f6f0ef85 691 return wxtree_model->internal->drag_data_delete( drag_source, path );
85136e3b
RR
692}
693
7857346a 694static gboolean
85136e3b
RR
695wxgtk_tree_model_drag_data_get (GtkTreeDragSource *drag_source,
696 GtkTreePath *path,
697 GtkSelectionData *selection_data)
698{
f6f0ef85
RR
699 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) drag_source;
700 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE);
7857346a 701
f6f0ef85 702#if 0
85136e3b 703 wxPrintf( "drag_get_data\n");
7857346a 704
f6f0ef85
RR
705 wxGtkString atom_selection(gdk_atom_name(selection_data->selection));
706 wxPrintf( "selection %s\n", wxString::FromAscii(atom_selection) );
7857346a 707
f6f0ef85
RR
708 wxGtkString atom_target(gdk_atom_name(selection_data->target));
709 wxPrintf( "target %s\n", wxString::FromAscii(atom_target) );
7857346a 710
f6f0ef85
RR
711 wxGtkString atom_type(gdk_atom_name(selection_data->type));
712 wxPrintf( "type %s\n", wxString::FromAscii(atom_type) );
713
714 wxPrintf( "format %d\n", selection_data->format );
715#endif
7857346a 716
f6f0ef85 717 return wxtree_model->internal->drag_data_get( drag_source, path, selection_data );
85136e3b
RR
718}
719
7857346a 720static gboolean
85136e3b
RR
721wxgtk_tree_model_drag_data_received (GtkTreeDragDest *drag_dest,
722 GtkTreePath *dest,
723 GtkSelectionData *selection_data)
724{
f6f0ef85
RR
725 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) drag_dest;
726 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE);
7857346a 727
f6f0ef85 728 return wxtree_model->internal->drag_data_received( drag_dest, dest, selection_data );
85136e3b
RR
729}
730
7857346a 731static gboolean
85136e3b
RR
732wxgtk_tree_model_row_drop_possible (GtkTreeDragDest *drag_dest,
733 GtkTreePath *dest_path,
c2489d8e 734 GtkSelectionData *selection_data)
85136e3b 735{
f6f0ef85
RR
736 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) drag_dest;
737 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE);
7857346a 738
f6f0ef85 739 return wxtree_model->internal->row_drop_possible( drag_dest, dest_path, selection_data );
85136e3b
RR
740}
741
742/* sortable iface */
7857346a 743static gboolean
85136e3b
RR
744wxgtk_tree_model_get_sort_column_id (GtkTreeSortable *sortable,
745 gint *sort_column_id,
746 GtkSortType *order)
773cca48 747{
f6f0ef85 748 GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) sortable;
94b1f7bc
RR
749
750 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (sortable), FALSE);
751
f6f0ef85 752 if (!wxtree_model->internal->IsSorted())
40196b1e
RR
753 {
754 if (sort_column_id)
755 *sort_column_id = -1;
b9db5f30 756
40196b1e
RR
757 return TRUE;
758 }
759
760
94b1f7bc 761 if (sort_column_id)
f6f0ef85 762 *sort_column_id = wxtree_model->internal->GetSortColumn();
b9db5f30 763
94b1f7bc 764 if (order)
f6f0ef85 765 *order = wxtree_model->internal->GetSortOrder();
b9db5f30 766
94b1f7bc 767 return TRUE;
773cca48
RR
768}
769
d32332aa
RR
770wxDataViewColumn *gs_lastLeftClickHeader = NULL;
771
7857346a 772static void
85136e3b
RR
773wxgtk_tree_model_set_sort_column_id (GtkTreeSortable *sortable,
774 gint sort_column_id,
775 GtkSortType order)
773cca48 776{
94b1f7bc 777 GtkWxTreeModel *tree_model = (GtkWxTreeModel *) sortable;
94b1f7bc
RR
778 g_return_if_fail (GTK_IS_WX_TREE_MODEL (sortable) );
779
d32332aa 780 tree_model->internal->SetDataViewSortColumn( gs_lastLeftClickHeader );
b9db5f30 781
d32332aa
RR
782 if ((sort_column_id != (gint) tree_model->internal->GetSortColumn()) ||
783 (order != tree_model->internal->GetSortOrder()))
784 {
785 tree_model->internal->SetSortColumn( sort_column_id );
786 tree_model->internal->SetSortOrder( order );
b9db5f30 787
d32332aa 788 gtk_tree_sortable_sort_column_changed (sortable);
b9db5f30 789
d32332aa
RR
790 tree_model->internal->GetDataViewModel()->Resort();
791 }
a84c5b6f 792
d32332aa
RR
793 if (gs_lastLeftClickHeader)
794 {
b9db5f30 795 wxDataViewCtrl *dv = tree_model->internal->GetOwner();
d32332aa
RR
796 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED, dv->GetId() );
797 event.SetDataViewColumn( gs_lastLeftClickHeader );
798 event.SetModel( dv->GetModel() );
937013e0 799 dv->HandleWindowEvent( event );
d32332aa 800 }
b9db5f30 801
d32332aa 802 gs_lastLeftClickHeader = NULL;
773cca48
RR
803}
804
7857346a 805static void
85136e3b
RR
806wxgtk_tree_model_set_sort_func (GtkTreeSortable *sortable,
807 gint WXUNUSED(sort_column_id),
808 GtkTreeIterCompareFunc func,
809 gpointer WXUNUSED(data),
c2489d8e 810 GtkDestroyNotify WXUNUSED(destroy))
773cca48 811{
94b1f7bc
RR
812 g_return_if_fail (GTK_IS_WX_TREE_MODEL (sortable) );
813 g_return_if_fail (func != NULL);
773cca48
RR
814}
815
c2489d8e
FM
816static void
817wxgtk_tree_model_set_default_sort_func (GtkTreeSortable *sortable,
818 GtkTreeIterCompareFunc func,
819 gpointer WXUNUSED(data),
820 GtkDestroyNotify WXUNUSED(destroy))
773cca48 821{
94b1f7bc 822 g_return_if_fail (GTK_IS_WX_TREE_MODEL (sortable) );
94b1f7bc
RR
823 g_return_if_fail (func != NULL);
824
c2489d8e
FM
825 //wxPrintf( "wxgtk_tree_model_set_default_sort_func\n" );
826 // TODO: remove this code
773cca48
RR
827}
828
c2489d8e
FM
829static gboolean
830wxgtk_tree_model_has_default_sort_func (GtkTreeSortable *sortable)
773cca48 831{
c5c5395b 832 g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (sortable), FALSE );
7857346a 833
773cca48
RR
834 return FALSE;
835}
836
e152afc3 837//-----------------------------------------------------------------------------
baa9ebc4 838// define new GTK+ class wxGtkRendererRenderer
e152afc3
RR
839//-----------------------------------------------------------------------------
840
841extern "C" {
842
843#define GTK_TYPE_WX_CELL_RENDERER (gtk_wx_cell_renderer_get_type ())
844#define GTK_WX_CELL_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRenderer))
845#define GTK_WX_CELL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRendererClass))
846#define GTK_IS_WX_CELL_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WX_CELL_RENDERER))
847#define GTK_IS_WX_CELL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WX_CELL_RENDERER))
848#define GTK_WX_CELL_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRendererClass))
849
850GType gtk_wx_cell_renderer_get_type (void);
851
852typedef struct _GtkWxCellRenderer GtkWxCellRenderer;
853typedef struct _GtkWxCellRendererClass GtkWxCellRendererClass;
854
855struct _GtkWxCellRenderer
856{
857 GtkCellRenderer parent;
858
859 /*< private >*/
baa9ebc4 860 wxDataViewCustomRenderer *cell;
4d496ecb 861 guint32 last_click;
e152afc3
RR
862};
863
864struct _GtkWxCellRendererClass
865{
866 GtkCellRendererClass cell_parent_class;
e152afc3
RR
867};
868
869
870static GtkCellRenderer *gtk_wx_cell_renderer_new (void);
553f7d8f
RR
871static void gtk_wx_cell_renderer_init (
872 GtkWxCellRenderer *cell );
873static void gtk_wx_cell_renderer_class_init(
874 GtkWxCellRendererClass *klass );
875static void gtk_wx_cell_renderer_finalize (
876 GObject *object );
877static void gtk_wx_cell_renderer_get_size (
878 GtkCellRenderer *cell,
93763ad5
WS
879 GtkWidget *widget,
880 GdkRectangle *rectangle,
881 gint *x_offset,
882 gint *y_offset,
883 gint *width,
884 gint *height );
553f7d8f
RR
885static void gtk_wx_cell_renderer_render (
886 GtkCellRenderer *cell,
93763ad5
WS
887 GdkWindow *window,
888 GtkWidget *widget,
889 GdkRectangle *background_area,
890 GdkRectangle *cell_area,
891 GdkRectangle *expose_area,
892 GtkCellRendererState flags );
553f7d8f
RR
893static gboolean gtk_wx_cell_renderer_activate(
894 GtkCellRenderer *cell,
895 GdkEvent *event,
896 GtkWidget *widget,
897 const gchar *path,
898 GdkRectangle *background_area,
899 GdkRectangle *cell_area,
900 GtkCellRendererState flags );
1e510b1e
RR
901static GtkCellEditable *gtk_wx_cell_renderer_start_editing(
902 GtkCellRenderer *cell,
903 GdkEvent *event,
904 GtkWidget *widget,
905 const gchar *path,
906 GdkRectangle *background_area,
907 GdkRectangle *cell_area,
908 GtkCellRendererState flags );
e8375af8 909
e152afc3
RR
910
911static GObjectClass *cell_parent_class = NULL;
912
913} // extern "C"
914
93763ad5 915GType
e152afc3
RR
916gtk_wx_cell_renderer_get_type (void)
917{
553f7d8f 918 static GType cell_wx_type = 0;
e152afc3 919
553f7d8f 920 if (!cell_wx_type)
e152afc3 921 {
de4a74e2 922 const GTypeInfo cell_wx_info =
553f7d8f
RR
923 {
924 sizeof (GtkWxCellRendererClass),
93763ad5
WS
925 NULL, /* base_init */
926 NULL, /* base_finalize */
553f7d8f 927 (GClassInitFunc) gtk_wx_cell_renderer_class_init,
93763ad5
WS
928 NULL, /* class_finalize */
929 NULL, /* class_data */
553f7d8f
RR
930 sizeof (GtkWxCellRenderer),
931 0, /* n_preallocs */
932 (GInstanceInitFunc) gtk_wx_cell_renderer_init,
933 };
934
93763ad5 935 cell_wx_type = g_type_register_static( GTK_TYPE_CELL_RENDERER,
553f7d8f 936 "GtkWxCellRenderer", &cell_wx_info, (GTypeFlags)0 );
e152afc3
RR
937 }
938
553f7d8f 939 return cell_wx_type;
e152afc3
RR
940}
941
942static void
943gtk_wx_cell_renderer_init (GtkWxCellRenderer *cell)
944{
945 cell->cell = NULL;
4d496ecb 946 cell->last_click = 0;
e152afc3
RR
947}
948
949static void
950gtk_wx_cell_renderer_class_init (GtkWxCellRendererClass *klass)
951{
952 GObjectClass *object_class = G_OBJECT_CLASS (klass);
953 GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
954
955 cell_parent_class = (GObjectClass*) g_type_class_peek_parent (klass);
956
957 object_class->finalize = gtk_wx_cell_renderer_finalize;
958
959 cell_class->get_size = gtk_wx_cell_renderer_get_size;
960 cell_class->render = gtk_wx_cell_renderer_render;
553f7d8f 961 cell_class->activate = gtk_wx_cell_renderer_activate;
1e510b1e 962 cell_class->start_editing = gtk_wx_cell_renderer_start_editing;
e152afc3
RR
963}
964
965static void
966gtk_wx_cell_renderer_finalize (GObject *object)
967{
968 /* must chain up */
969 (* G_OBJECT_CLASS (cell_parent_class)->finalize) (object);
970}
971
972GtkCellRenderer*
973gtk_wx_cell_renderer_new (void)
974{
975 return (GtkCellRenderer*) g_object_new (GTK_TYPE_WX_CELL_RENDERER, NULL);
976}
977
1e510b1e
RR
978
979
980static GtkCellEditable *gtk_wx_cell_renderer_start_editing(
981 GtkCellRenderer *renderer,
c5c5395b 982 GdkEvent *WXUNUSED(event),
1e510b1e
RR
983 GtkWidget *widget,
984 const gchar *path,
c5c5395b 985 GdkRectangle *WXUNUSED(background_area),
1e510b1e 986 GdkRectangle *cell_area,
c5c5395b 987 GtkCellRendererState WXUNUSED(flags) )
1e510b1e
RR
988{
989 GtkWxCellRenderer *wxrenderer = (GtkWxCellRenderer *) renderer;
990 wxDataViewCustomRenderer *cell = wxrenderer->cell;
bc0289bf 991
c232dfe5 992 // Renderer doesn't support in-place editing
1e510b1e
RR
993 if (!cell->HasEditorCtrl())
994 return NULL;
bc0289bf 995
c232dfe5
RR
996 // An in-place editing control is still around
997 if (cell->GetEditorCtrl())
998 return NULL;
e8375af8 999
1e510b1e
RR
1000 GdkRectangle rect;
1001 gtk_wx_cell_renderer_get_size (renderer, widget, cell_area,
1002 &rect.x,
1003 &rect.y,
1004 &rect.width,
1005 &rect.height);
1006
1007 rect.x += cell_area->x;
1008 rect.y += cell_area->y;
1009// rect.width -= renderer->xpad * 2;
1010// rect.height -= renderer->ypad * 2;
1011
1012// wxRect renderrect( rect.x, rect.y, rect.width, rect.height );
1013 wxRect renderrect( cell_area->x, cell_area->y, cell_area->width, cell_area->height );
1014
1e510b1e 1015 GtkTreePath *treepath = gtk_tree_path_new_from_string( path );
55fbde12
RR
1016 GtkTreeIter iter;
1017 cell->GetOwner()->GetOwner()->GtkGetInternal()->get_iter( &iter, treepath );
1018 wxDataViewItem item( (void*) iter.user_data );
1e510b1e
RR
1019 gtk_tree_path_free( treepath );
1020
9d52aad3 1021 cell->StartEditing( item, renderrect );
30715fa1 1022
1e510b1e
RR
1023 return NULL;
1024}
1025
e152afc3
RR
1026static void
1027gtk_wx_cell_renderer_get_size (GtkCellRenderer *renderer,
c5c5395b 1028 GtkWidget *WXUNUSED(widget),
93763ad5
WS
1029 GdkRectangle *cell_area,
1030 gint *x_offset,
1031 gint *y_offset,
1032 gint *width,
1033 gint *height)
e152afc3
RR
1034{
1035 GtkWxCellRenderer *wxrenderer = (GtkWxCellRenderer *) renderer;
baa9ebc4 1036 wxDataViewCustomRenderer *cell = wxrenderer->cell;
93763ad5 1037
e152afc3
RR
1038 wxSize size = cell->GetSize();
1039
1040 gint calc_width = (gint) renderer->xpad * 2 + size.x;
1041 gint calc_height = (gint) renderer->ypad * 2 + size.y;
93763ad5
WS
1042
1043 if (x_offset)
e152afc3 1044 *x_offset = 0;
93763ad5 1045 if (y_offset)
e152afc3
RR
1046 *y_offset = 0;
1047
1048 if (cell_area && size.x > 0 && size.y > 0)
1049 {
1050 if (x_offset)
93763ad5 1051 {
e152afc3
RR
1052 *x_offset = (gint)((renderer->xalign *
1053 (cell_area->width - calc_width - 2 * renderer->xpad)));
1054 *x_offset = MAX (*x_offset, 0) + renderer->xpad;
93763ad5 1055 }
e152afc3
RR
1056 if (y_offset)
1057 {
1058 *y_offset = (gint)((renderer->yalign *
1059 (cell_area->height - calc_height - 2 * renderer->ypad)));
1060 *y_offset = MAX (*y_offset, 0) + renderer->ypad;
1061 }
1062 }
1063
1064 if (width)
1065 *width = calc_width;
93763ad5 1066
e152afc3
RR
1067 if (height)
1068 *height = calc_height;
1069}
1070
1071static void
1072gtk_wx_cell_renderer_render (GtkCellRenderer *renderer,
93763ad5
WS
1073 GdkWindow *window,
1074 GtkWidget *widget,
1075 GdkRectangle *background_area,
1076 GdkRectangle *cell_area,
1077 GdkRectangle *expose_area,
1078 GtkCellRendererState flags)
e152afc3
RR
1079
1080{
1081 GtkWxCellRenderer *wxrenderer = (GtkWxCellRenderer *) renderer;
baa9ebc4 1082 wxDataViewCustomRenderer *cell = wxrenderer->cell;
93763ad5 1083
f69c03de
RR
1084 cell->window = window;
1085 cell->widget = widget;
1086 cell->background_area = (void*) background_area;
1087 cell->cell_area = (void*) cell_area;
1088 cell->expose_area = (void*) expose_area;
1089 cell->flags = (int) flags;
1090
e152afc3
RR
1091 GdkRectangle rect;
1092 gtk_wx_cell_renderer_get_size (renderer, widget, cell_area,
93763ad5
WS
1093 &rect.x,
1094 &rect.y,
1095 &rect.width,
1096 &rect.height);
e152afc3
RR
1097
1098 rect.x += cell_area->x;
1099 rect.y += cell_area->y;
1100 rect.width -= renderer->xpad * 2;
1101 rect.height -= renderer->ypad * 2;
bc0289bf 1102
e152afc3
RR
1103 GdkRectangle dummy;
1104 if (gdk_rectangle_intersect (expose_area, &rect, &dummy))
1105 {
1106 wxRect renderrect( rect.x, rect.y, rect.width, rect.height );
1107 wxWindowDC* dc = (wxWindowDC*) cell->GetDC();
888dde65 1108 wxWindowDCImpl *impl = (wxWindowDCImpl *) dc->GetImpl();
c2489d8e
FM
1109
1110 // Reinitialize wxWindowDC's GDK window if drawing occurs into a different
874edbb7
RR
1111 // window such as a DnD drop window.
1112 if (window != impl->m_gdkwindow)
1113 {
1114 impl->Destroy();
1115 impl->m_gdkwindow = window;
1116 impl->SetUpDC();
1117 }
93763ad5 1118
e152afc3
RR
1119 int state = 0;
1120 if (flags & GTK_CELL_RENDERER_SELECTED)
1121 state |= wxDATAVIEW_CELL_SELECTED;
1122 if (flags & GTK_CELL_RENDERER_PRELIT)
1123 state |= wxDATAVIEW_CELL_PRELIT;
1124 if (flags & GTK_CELL_RENDERER_INSENSITIVE)
1125 state |= wxDATAVIEW_CELL_INSENSITIVE;
1126 if (flags & GTK_CELL_RENDERER_INSENSITIVE)
1127 state |= wxDATAVIEW_CELL_INSENSITIVE;
1128 if (flags & GTK_CELL_RENDERER_FOCUSED)
1129 state |= wxDATAVIEW_CELL_FOCUSED;
1130 cell->Render( renderrect, dc, state );
93763ad5 1131 }
e152afc3
RR
1132}
1133
93763ad5 1134static gboolean
553f7d8f
RR
1135gtk_wx_cell_renderer_activate(
1136 GtkCellRenderer *renderer,
1137 GdkEvent *event,
1138 GtkWidget *widget,
1139 const gchar *path,
c5c5395b 1140 GdkRectangle *WXUNUSED(background_area),
553f7d8f 1141 GdkRectangle *cell_area,
c5c5395b 1142 GtkCellRendererState WXUNUSED(flags) )
553f7d8f
RR
1143{
1144 GtkWxCellRenderer *wxrenderer = (GtkWxCellRenderer *) renderer;
baa9ebc4 1145 wxDataViewCustomRenderer *cell = wxrenderer->cell;
93763ad5 1146
553f7d8f
RR
1147 GdkRectangle rect;
1148 gtk_wx_cell_renderer_get_size (renderer, widget, cell_area,
93763ad5
WS
1149 &rect.x,
1150 &rect.y,
1151 &rect.width,
1152 &rect.height);
553f7d8f
RR
1153
1154 rect.x += cell_area->x;
1155 rect.y += cell_area->y;
1156 rect.width -= renderer->xpad * 2;
1157 rect.height -= renderer->ypad * 2;
93763ad5 1158
553f7d8f 1159 wxRect renderrect( rect.x, rect.y, rect.width, rect.height );
93763ad5 1160
e0062c04 1161 wxDataViewModel *model = cell->GetOwner()->GetOwner()->GetModel();
93763ad5 1162
4d496ecb 1163 GtkTreePath *treepath = gtk_tree_path_new_from_string( path );
71c6b455
RR
1164
1165 GtkTreeIter iter;
f69c03de 1166 cell->GetOwner()->GetOwner()->GtkGetInternal()->get_iter( &iter, treepath );
71c6b455 1167 wxDataViewItem item( iter.user_data );
4d496ecb 1168 gtk_tree_path_free( treepath );
93763ad5 1169
0a71f9e9 1170 unsigned int model_col = cell->GetOwner()->GetModelColumn();
93763ad5 1171
456e5c21
RR
1172 if (!event)
1173 {
1174 bool ret = false;
e8375af8 1175
456e5c21 1176 // activated by <ENTER>
9d52aad3 1177 if (cell->Activate( renderrect, model, item, model_col ))
456e5c21 1178 ret = true;
e8375af8 1179
456e5c21
RR
1180 return ret;
1181 }
1182 else if (event->type == GDK_BUTTON_PRESS)
4d496ecb
RR
1183 {
1184 GdkEventButton *button_event = (GdkEventButton*) event;
93763ad5 1185 wxPoint pt( ((int) button_event->x) - renderrect.x,
4d496ecb 1186 ((int) button_event->y) - renderrect.y );
93763ad5 1187
4d496ecb
RR
1188 bool ret = false;
1189 if (button_event->button == 1)
1190 {
9d52aad3 1191 if (cell->LeftClick( pt, renderrect, model, item, model_col ))
4d496ecb 1192 ret = true;
7ea3a0de 1193 // TODO: query system double-click time
4d496ecb 1194 if (button_event->time - wxrenderer->last_click < 400)
9d52aad3 1195 if (cell->Activate( renderrect, model, item, model_col ))
4d496ecb
RR
1196 ret = true;
1197 }
4d496ecb 1198 wxrenderer->last_click = button_event->time;
93763ad5 1199
4d496ecb
RR
1200 return ret;
1201 }
93763ad5 1202
4d496ecb 1203 return false;
553f7d8f
RR
1204}
1205
93763ad5 1206// ---------------------------------------------------------
e0062c04 1207// wxGtkDataViewModelNotifier
93763ad5 1208// ---------------------------------------------------------
6e2e590f 1209
e0062c04 1210class wxGtkDataViewModelNotifier: public wxDataViewModelNotifier
6e2e590f
RR
1211{
1212public:
e0062c04
RR
1213 wxGtkDataViewModelNotifier( GtkWxTreeModel *wxgtk_model,
1214 wxDataViewModel *wx_model,
1215 wxDataViewCtrl *ctrl );
1216 ~wxGtkDataViewModelNotifier();
1217
1218 virtual bool ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item );
469d3e9b 1219 virtual bool ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item );
e0062c04
RR
1220 virtual bool ItemChanged( const wxDataViewItem &item );
1221 virtual bool ValueChanged( const wxDataViewItem &item, unsigned int col );
6e2e590f 1222 virtual bool Cleared();
4508fcd2 1223 virtual void Resort();
93763ad5 1224
33ba5a05
RR
1225 void SetGtkModel( GtkWxTreeModel *model ) { m_wxgtk_model = model; }
1226
1227private:
e0062c04
RR
1228 GtkWxTreeModel *m_wxgtk_model;
1229 wxDataViewModel *m_wx_model;
63415a42 1230 wxDataViewCtrl *m_owner;
6e2e590f
RR
1231};
1232
93763ad5 1233// ---------------------------------------------------------
6e2e590f 1234// wxGtkDataViewListModelNotifier
93763ad5 1235// ---------------------------------------------------------
6e2e590f 1236
e0062c04
RR
1237wxGtkDataViewModelNotifier::wxGtkDataViewModelNotifier(
1238 GtkWxTreeModel* wxgtk_model, wxDataViewModel *wx_model,
63415a42 1239 wxDataViewCtrl *ctrl )
6e2e590f 1240{
e0062c04 1241 m_wxgtk_model = wxgtk_model;
6e2e590f 1242 m_wx_model = wx_model;
63415a42 1243 m_owner = ctrl;
6e2e590f 1244}
93763ad5 1245
e0062c04 1246wxGtkDataViewModelNotifier::~wxGtkDataViewModelNotifier()
f7ed8c89
RR
1247{
1248 m_wx_model = NULL;
e0062c04 1249 m_wxgtk_model = NULL;
f7ed8c89
RR
1250}
1251
e0062c04 1252bool wxGtkDataViewModelNotifier::ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item )
6e2e590f 1253{
55fbde12 1254 m_owner->GtkGetInternal()->ItemAdded( parent, item );
1e08ad10 1255
6e2e590f 1256 GtkTreeIter iter;
e0062c04
RR
1257 iter.stamp = m_wxgtk_model->stamp;
1258 iter.user_data = (gpointer) item.GetID();
93763ad5 1259
b9db5f30 1260 GtkTreePath *path = wxgtk_tree_model_get_path(
e0062c04 1261 GTK_TREE_MODEL(m_wxgtk_model), &iter );
b9db5f30 1262 gtk_tree_model_row_inserted(
e0062c04 1263 GTK_TREE_MODEL(m_wxgtk_model), path, &iter);
6e2e590f 1264 gtk_tree_path_free (path);
93763ad5 1265
6e2e590f
RR
1266 return true;
1267}
1268
469d3e9b 1269bool wxGtkDataViewModelNotifier::ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item )
6e2e590f 1270{
605c2c4a 1271 GtkTreeIter iter;
e0062c04
RR
1272 iter.stamp = m_wxgtk_model->stamp;
1273 iter.user_data = (gpointer) item.GetID();
93763ad5 1274
b9db5f30 1275 GtkTreePath *path = wxgtk_tree_model_get_path(
e0062c04
RR
1276 GTK_TREE_MODEL(m_wxgtk_model), &iter );
1277 gtk_tree_model_row_deleted(
1278 GTK_TREE_MODEL(m_wxgtk_model), path );
605c2c4a 1279 gtk_tree_path_free (path);
93763ad5 1280
469d3e9b 1281 m_owner->GtkGetInternal()->ItemDeleted( parent, item );
b9db5f30 1282
605c2c4a 1283 return true;
6e2e590f
RR
1284}
1285
4508fcd2
RR
1286void wxGtkDataViewModelNotifier::Resort()
1287{
1288 m_owner->GtkGetInternal()->Resort();
1289}
1290
e0062c04 1291bool wxGtkDataViewModelNotifier::ItemChanged( const wxDataViewItem &item )
6e2e590f 1292{
4627af27 1293 GtkTreeIter iter;
e0062c04
RR
1294 iter.stamp = m_wxgtk_model->stamp;
1295 iter.user_data = (gpointer) item.GetID();
6e2e590f 1296
b9db5f30 1297 GtkTreePath *path = wxgtk_tree_model_get_path(
e0062c04
RR
1298 GTK_TREE_MODEL(m_wxgtk_model), &iter );
1299 gtk_tree_model_row_changed(
1300 GTK_TREE_MODEL(m_wxgtk_model), path, &iter );
a7f61f76
RR
1301 gtk_tree_path_free (path);
1302
d8331a01 1303 m_owner->GtkGetInternal()->ItemChanged( item );
b9db5f30 1304
a7f61f76 1305 return true;
6e2e590f
RR
1306}
1307
e0062c04 1308bool wxGtkDataViewModelNotifier::ValueChanged( const wxDataViewItem &item, unsigned int model_col )
6e2e590f 1309{
4eccd3a1 1310 // This adds GTK+'s missing MVC logic for ValueChanged
63415a42
RR
1311 unsigned int index;
1312 for (index = 0; index < m_owner->GetColumnCount(); index++)
8f850e28 1313 {
63415a42
RR
1314 wxDataViewColumn *column = m_owner->GetColumn( index );
1315 if (column->GetModelColumn() == model_col)
8f850e28 1316 {
63415a42
RR
1317 GtkTreeView *widget = GTK_TREE_VIEW(m_owner->m_treeview);
1318 GtkTreeViewColumn *gcolumn = GTK_TREE_VIEW_COLUMN(column->GetGtkHandle());
8f850e28
RR
1319
1320 // Get cell area
e0062c04
RR
1321 GtkTreeIter iter;
1322 iter.stamp = m_wxgtk_model->stamp;
1323 iter.user_data = (gpointer) item.GetID();
b9db5f30 1324 GtkTreePath *path = wxgtk_tree_model_get_path(
e0062c04 1325 GTK_TREE_MODEL(m_wxgtk_model), &iter );
8f850e28 1326 GdkRectangle cell_area;
63415a42 1327 gtk_tree_view_get_cell_area( widget, path, gcolumn, &cell_area );
93763ad5 1328 gtk_tree_path_free( path );
8f850e28 1329
1a64259d
RR
1330 GtkAdjustment* hadjust = gtk_tree_view_get_hadjustment( widget );
1331 double d = gtk_adjustment_get_value( hadjust );
1332 int xdiff = (int) d;
1333
63415a42 1334 int ydiff = gcolumn->button->allocation.height;
8f850e28 1335 // Redraw
93763ad5 1336 gtk_widget_queue_draw_area( GTK_WIDGET(widget),
1a64259d 1337 cell_area.x - xdiff, ydiff + cell_area.y, cell_area.width, cell_area.height );
b9db5f30 1338
d8331a01 1339 m_owner->GtkGetInternal()->ValueChanged( item, model_col );
b9db5f30 1340
d8331a01 1341 return true;
8f850e28 1342 }
8f850e28 1343 }
93763ad5 1344
d8331a01 1345 return false;
6e2e590f
RR
1346}
1347
e0062c04 1348bool wxGtkDataViewModelNotifier::Cleared()
6e2e590f 1349{
33ba5a05 1350 gtk_tree_view_set_model( GTK_TREE_VIEW(m_owner->m_treeview), NULL );
7857346a 1351
33ba5a05 1352 // this will create a new GTK model
d8331a01 1353 m_owner->GtkGetInternal()->Cleared();
7857346a 1354
33ba5a05 1355 SetGtkModel( m_owner->GtkGetInternal()->GetGtkModel() );
b9db5f30 1356
33ba5a05 1357 gtk_tree_view_set_model( GTK_TREE_VIEW(m_owner->m_treeview), GTK_TREE_MODEL(m_wxgtk_model) );
7857346a 1358
6e2e590f
RR
1359 return false;
1360}
1361
93763ad5 1362// ---------------------------------------------------------
baa9ebc4 1363// wxDataViewRenderer
93763ad5 1364// ---------------------------------------------------------
6842a71a 1365
a912e81f
RR
1366static gpointer s_user_data = NULL;
1367
1368static void
c5c5395b 1369wxgtk_cell_editable_editing_done( GtkCellEditable *WXUNUSED(editable),
a912e81f
RR
1370 wxDataViewRenderer *wxrenderer )
1371{
1372 wxDataViewColumn *column = wxrenderer->GetOwner();
1373 wxDataViewCtrl *dv = column->GetOwner();
1374 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE, dv->GetId() );
1375 event.SetDataViewColumn( column );
1376 event.SetModel( dv->GetModel() );
1377 wxDataViewItem item( s_user_data );
1378 event.SetItem( item );
937013e0 1379 dv->HandleWindowEvent( event );
a912e81f
RR
1380}
1381
b9db5f30 1382static void
c5c5395b 1383wxgtk_renderer_editing_started( GtkCellRenderer *WXUNUSED(cell), GtkCellEditable *editable,
a912e81f
RR
1384 gchar *path, wxDataViewRenderer *wxrenderer )
1385{
1386 wxDataViewColumn *column = wxrenderer->GetOwner();
1387 wxDataViewCtrl *dv = column->GetOwner();
1388 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED, dv->GetId() );
1389 event.SetDataViewColumn( column );
1390 event.SetModel( dv->GetModel() );
1391 GtkTreePath *tree_path = gtk_tree_path_new_from_string( path );
1392 GtkTreeIter iter;
1393 dv->GtkGetInternal()->get_iter( &iter, tree_path );
1394 gtk_tree_path_free( tree_path );
1395 wxDataViewItem item( iter.user_data );
1396 event.SetItem( item );
937013e0 1397 dv->HandleWindowEvent( event );
a912e81f
RR
1398
1399 if (GTK_IS_CELL_EDITABLE(editable))
1400 {
1401 s_user_data = iter.user_data;
b9db5f30 1402
a912e81f
RR
1403 g_signal_connect (GTK_CELL_EDITABLE (editable), "editing_done",
1404 G_CALLBACK (wxgtk_cell_editable_editing_done),
1405 (gpointer) wxrenderer );
b9db5f30 1406
a912e81f
RR
1407 }
1408}
1409
1410
baa9ebc4 1411IMPLEMENT_ABSTRACT_CLASS(wxDataViewRenderer, wxDataViewRendererBase)
6842a71a 1412
9861f022
RR
1413wxDataViewRenderer::wxDataViewRenderer( const wxString &varianttype, wxDataViewCellMode mode,
1414 int align ) :
1415 wxDataViewRendererBase( varianttype, mode, align )
6842a71a
RR
1416{
1417 m_renderer = NULL;
9861f022
RR
1418
1419 // NOTE: SetMode() and SetAlignment() needs to be called in the renderer's ctor,
1420 // after the m_renderer pointer has been initialized
1421}
1422
a912e81f
RR
1423void wxDataViewRenderer::GtkInitHandlers()
1424{
1425 if (!gtk_check_version(2,6,0))
1426 {
1427 g_signal_connect (GTK_CELL_RENDERER(m_renderer), "editing_started",
1428 G_CALLBACK (wxgtk_renderer_editing_started),
1429 this);
1430 }
1431}
1432
9861f022
RR
1433void wxDataViewRenderer::SetMode( wxDataViewCellMode mode )
1434{
1435 GtkCellRendererMode gtkMode;
1436 switch (mode)
1437 {
25bc5c55
VZ
1438 case wxDATAVIEW_CELL_INERT:
1439 gtkMode = GTK_CELL_RENDERER_MODE_INERT;
1440 break;
1441
1442 case wxDATAVIEW_CELL_ACTIVATABLE:
1443 gtkMode = GTK_CELL_RENDERER_MODE_ACTIVATABLE;
1444 break;
1445
1446 case wxDATAVIEW_CELL_EDITABLE:
1447 gtkMode = GTK_CELL_RENDERER_MODE_EDITABLE;
1448 break;
1449
1450 default:
1451 wxFAIL_MSG( "unknown wxDataViewCellMode value" );
1452 return;
9861f022
RR
1453 }
1454
b9db5f30 1455 // This value is most often ignored in GtkTreeView
9861f022
RR
1456 GValue gvalue = { 0, };
1457 g_value_init( &gvalue, gtk_cell_renderer_mode_get_type() );
1458 g_value_set_enum( &gvalue, gtkMode );
1459 g_object_set_property( G_OBJECT(m_renderer), "mode", &gvalue );
1460 g_value_unset( &gvalue );
1461}
1462
1463wxDataViewCellMode wxDataViewRenderer::GetMode() const
1464{
1465 wxDataViewCellMode ret;
1466
1467 GValue gvalue;
1468 g_object_get( G_OBJECT(m_renderer), "mode", &gvalue, NULL);
1469
1470 switch (g_value_get_enum(&gvalue))
1471 {
25bc5c55
VZ
1472 default:
1473 wxFAIL_MSG( "unknown GtkCellRendererMode value" );
1474 // fall through (we have to return something)
1475
1476 case GTK_CELL_RENDERER_MODE_INERT:
1477 ret = wxDATAVIEW_CELL_INERT;
1478 break;
1479
1480 case GTK_CELL_RENDERER_MODE_ACTIVATABLE:
1481 ret = wxDATAVIEW_CELL_ACTIVATABLE;
1482 break;
1483
1484 case GTK_CELL_RENDERER_MODE_EDITABLE:
1485 ret = wxDATAVIEW_CELL_EDITABLE;
1486 break;
9861f022
RR
1487 }
1488
1489 g_value_unset( &gvalue );
1490
1491 return ret;
1492}
1493
f2b7492a 1494void wxDataViewRenderer::GtkUpdateAlignment()
9861f022 1495{
f2b7492a 1496 int align = m_alignment;
bc0289bf 1497
f2b7492a
RR
1498 // query alignment from column ?
1499 if (align == -1)
1500 {
1501 // None there yet
1502 if (GetOwner() == NULL)
1503 return;
bc0289bf 1504
f2b7492a
RR
1505 align = GetOwner()->GetAlignment();
1506 align |= wxALIGN_CENTRE_VERTICAL;
1507 }
bc0289bf 1508
9861f022
RR
1509 // horizontal alignment:
1510
1511 gfloat xalign = 0.0;
1512 if (align & wxALIGN_RIGHT)
1513 xalign = 1.0;
1514 else if (align & wxALIGN_CENTER_HORIZONTAL)
1515 xalign = 0.5;
1516
1517 GValue gvalue = { 0, };
1518 g_value_init( &gvalue, G_TYPE_FLOAT );
1519 g_value_set_float( &gvalue, xalign );
1520 g_object_set_property( G_OBJECT(m_renderer), "xalign", &gvalue );
1521 g_value_unset( &gvalue );
1522
1523 // vertical alignment:
1524
1525 gfloat yalign = 0.0;
1526 if (align & wxALIGN_BOTTOM)
1527 yalign = 1.0;
1528 else if (align & wxALIGN_CENTER_VERTICAL)
1529 yalign = 0.5;
1530
1531 GValue gvalue2 = { 0, };
1532 g_value_init( &gvalue2, G_TYPE_FLOAT );
1533 g_value_set_float( &gvalue2, yalign );
1534 g_object_set_property( G_OBJECT(m_renderer), "yalign", &gvalue2 );
1535 g_value_unset( &gvalue2 );
6842a71a
RR
1536}
1537
f2b7492a 1538void wxDataViewRenderer::SetAlignment( int align )
9861f022 1539{
f2b7492a
RR
1540 m_alignment = align;
1541 GtkUpdateAlignment();
9861f022
RR
1542}
1543
f2b7492a
RR
1544int wxDataViewRenderer::GetAlignment() const
1545{
1546 return m_alignment;
1547}
9861f022 1548
93763ad5 1549// ---------------------------------------------------------
baa9ebc4 1550// wxDataViewTextRenderer
93763ad5 1551// ---------------------------------------------------------
6842a71a 1552
a7f61f76 1553extern "C" {
93763ad5 1554static void wxGtkTextRendererEditedCallback( GtkCellRendererText *renderer,
a7f61f76
RR
1555 gchar *arg1, gchar *arg2, gpointer user_data );
1556}
1557
c5c5395b 1558static void wxGtkTextRendererEditedCallback( GtkCellRendererText *WXUNUSED(renderer),
a7f61f76
RR
1559 gchar *arg1, gchar *arg2, gpointer user_data )
1560{
7448d67c 1561 wxDataViewRenderer *cell = (wxDataViewRenderer*) user_data;
93763ad5 1562
1a74f561 1563 wxString tmp = wxGTK_CONV_BACK_FONT(arg2, cell->GetOwner()->GetOwner()->GetFont());
a7f61f76
RR
1564 wxVariant value = tmp;
1565 if (!cell->Validate( value ))
1566 return;
93763ad5 1567
e0062c04 1568 wxDataViewModel *model = cell->GetOwner()->GetOwner()->GetModel();
93763ad5 1569
a7f61f76 1570 GtkTreePath *path = gtk_tree_path_new_from_string( arg1 );
9d52aad3 1571 GtkTreeIter iter;
55fbde12
RR
1572 cell->GetOwner()->GetOwner()->GtkGetInternal()->get_iter( &iter, path );
1573 wxDataViewItem item( (void*) iter.user_data );;
a7f61f76 1574 gtk_tree_path_free( path );
93763ad5 1575
0a71f9e9 1576 unsigned int model_col = cell->GetOwner()->GetModelColumn();
93763ad5 1577
9d52aad3
RR
1578 model->SetValue( value, item, model_col );
1579 model->ValueChanged( item, model_col );
a7f61f76
RR
1580}
1581
baa9ebc4 1582IMPLEMENT_CLASS(wxDataViewTextRenderer, wxDataViewRenderer)
6842a71a 1583
9861f022
RR
1584wxDataViewTextRenderer::wxDataViewTextRenderer( const wxString &varianttype, wxDataViewCellMode mode,
1585 int align ) :
1586 wxDataViewRenderer( varianttype, mode, align )
6842a71a 1587{
ed38aa55 1588 m_renderer = (GtkCellRenderer*) gtk_cell_renderer_text_new();
93763ad5 1589
9861f022 1590 if (mode & wxDATAVIEW_CELL_EDITABLE)
a7f61f76
RR
1591 {
1592 GValue gvalue = { 0, };
1593 g_value_init( &gvalue, G_TYPE_BOOLEAN );
1594 g_value_set_boolean( &gvalue, true );
1595 g_object_set_property( G_OBJECT(m_renderer), "editable", &gvalue );
1596 g_value_unset( &gvalue );
93763ad5 1597
a7f61f76 1598 g_signal_connect_after( m_renderer, "edited", G_CALLBACK(wxGtkTextRendererEditedCallback), this );
b9db5f30 1599
a912e81f 1600 GtkInitHandlers();
a7f61f76 1601 }
9861f022
RR
1602
1603 SetMode(mode);
1604 SetAlignment(align);
6842a71a 1605}
790b137e 1606
baa9ebc4 1607bool wxDataViewTextRenderer::SetValue( const wxVariant &value )
7b4fde82
RR
1608{
1609 wxString tmp = value;
93763ad5 1610
7b4fde82
RR
1611 GValue gvalue = { 0, };
1612 g_value_init( &gvalue, G_TYPE_STRING );
1bf629bd 1613 g_value_set_string( &gvalue, wxGTK_CONV_FONT( tmp, GetOwner()->GetOwner()->GetFont() ) );
7b4fde82
RR
1614 g_object_set_property( G_OBJECT(m_renderer), "text", &gvalue );
1615 g_value_unset( &gvalue );
93763ad5 1616
7b4fde82
RR
1617 return true;
1618}
1619
9861f022 1620bool wxDataViewTextRenderer::GetValue( wxVariant &value ) const
a7f61f76
RR
1621{
1622 GValue gvalue = { 0, };
1623 g_value_init( &gvalue, G_TYPE_STRING );
1624 g_object_get_property( G_OBJECT(m_renderer), "text", &gvalue );
5c33522f 1625 wxString tmp = wxGTK_CONV_BACK_FONT( g_value_get_string( &gvalue ), const_cast<wxDataViewTextRenderer*>(this)->GetOwner()->GetOwner()->GetFont() );
a7f61f76 1626 g_value_unset( &gvalue );
93763ad5 1627
a7f61f76
RR
1628 value = tmp;
1629
1630 return true;
1631}
1632
9861f022
RR
1633void wxDataViewTextRenderer::SetAlignment( int align )
1634{
1635 wxDataViewRenderer::SetAlignment(align);
1636
01705e98
RR
1637 if (gtk_check_version(2,10,0))
1638 return;
9861f022 1639
01705e98 1640 // horizontal alignment:
9861f022
RR
1641 PangoAlignment pangoAlign = PANGO_ALIGN_LEFT;
1642 if (align & wxALIGN_RIGHT)
1643 pangoAlign = PANGO_ALIGN_RIGHT;
1644 else if (align & wxALIGN_CENTER_HORIZONTAL)
1645 pangoAlign = PANGO_ALIGN_CENTER;
1646
1647 GValue gvalue = { 0, };
1648 g_value_init( &gvalue, gtk_cell_renderer_mode_get_type() );
1649 g_value_set_enum( &gvalue, pangoAlign );
1650 g_object_set_property( G_OBJECT(m_renderer), "alignment", &gvalue );
1651 g_value_unset( &gvalue );
1652}
1653
b9db5f30 1654// ---------------------------------------------------------
4264606e 1655// wxDataViewTextRendererAttr
b9db5f30 1656// ---------------------------------------------------------
4264606e
RR
1657
1658IMPLEMENT_CLASS(wxDataViewTextRendererAttr,wxDataViewTextRenderer)
1659
b9db5f30 1660wxDataViewTextRendererAttr::wxDataViewTextRendererAttr( const wxString &varianttype,
4264606e
RR
1661 wxDataViewCellMode mode, int align ) :
1662 wxDataViewTextRenderer( varianttype, mode, align )
1663{
1664}
b9db5f30 1665
f4322df6 1666// ---------------------------------------------------------
baa9ebc4 1667// wxDataViewBitmapRenderer
f4322df6 1668// ---------------------------------------------------------
cbc9145c 1669
baa9ebc4 1670IMPLEMENT_CLASS(wxDataViewBitmapRenderer, wxDataViewRenderer)
cbc9145c 1671
9861f022
RR
1672wxDataViewBitmapRenderer::wxDataViewBitmapRenderer( const wxString &varianttype, wxDataViewCellMode mode,
1673 int align ) :
1674 wxDataViewRenderer( varianttype, mode, align )
cbc9145c 1675{
ed38aa55 1676 m_renderer = (GtkCellRenderer*) gtk_cell_renderer_pixbuf_new();
9861f022
RR
1677
1678 SetMode(mode);
1679 SetAlignment(align);
cbc9145c
RR
1680}
1681
baa9ebc4 1682bool wxDataViewBitmapRenderer::SetValue( const wxVariant &value )
cbc9145c
RR
1683{
1684 if (value.GetType() == wxT("wxBitmap"))
1685 {
2586d4a1
RR
1686 wxBitmap bitmap;
1687 bitmap << value;
f4322df6 1688
2586d4a1
RR
1689 // This may create a Pixbuf representation in the
1690 // wxBitmap object (and it will stay there)
1691 GdkPixbuf *pixbuf = bitmap.GetPixbuf();
f4322df6 1692
2586d4a1
RR
1693 GValue gvalue = { 0, };
1694 g_value_init( &gvalue, G_TYPE_OBJECT );
1695 g_value_set_object( &gvalue, pixbuf );
1696 g_object_set_property( G_OBJECT(m_renderer), "pixbuf", &gvalue );
1697 g_value_unset( &gvalue );
f4322df6 1698
2586d4a1
RR
1699 return true;
1700 }
f4322df6 1701
2586d4a1
RR
1702 if (value.GetType() == wxT("wxIcon"))
1703 {
1704 wxIcon bitmap;
1705 bitmap << value;
f4322df6 1706
cbc9145c
RR
1707 // This may create a Pixbuf representation in the
1708 // wxBitmap object (and it will stay there)
2586d4a1 1709 GdkPixbuf *pixbuf = bitmap.GetPixbuf();
f4322df6 1710
cbc9145c
RR
1711 GValue gvalue = { 0, };
1712 g_value_init( &gvalue, G_TYPE_OBJECT );
1713 g_value_set_object( &gvalue, pixbuf );
1714 g_object_set_property( G_OBJECT(m_renderer), "pixbuf", &gvalue );
1715 g_value_unset( &gvalue );
f4322df6 1716
cbc9145c
RR
1717 return true;
1718 }
f4322df6 1719
cbc9145c
RR
1720 return false;
1721}
1722
c5c5395b 1723bool wxDataViewBitmapRenderer::GetValue( wxVariant &WXUNUSED(value) ) const
cbc9145c
RR
1724{
1725 return false;
1726}
f4322df6 1727
93763ad5 1728// ---------------------------------------------------------
baa9ebc4 1729// wxDataViewToggleRenderer
93763ad5 1730// ---------------------------------------------------------
fa28826d 1731
605c2c4a 1732extern "C" {
93763ad5 1733static void wxGtkToggleRendererToggledCallback( GtkCellRendererToggle *renderer,
605c2c4a
RR
1734 gchar *path, gpointer user_data );
1735}
1736
93763ad5 1737static void wxGtkToggleRendererToggledCallback( GtkCellRendererToggle *renderer,
605c2c4a
RR
1738 gchar *path, gpointer user_data )
1739{
baa9ebc4 1740 wxDataViewToggleRenderer *cell = (wxDataViewToggleRenderer*) user_data;
605c2c4a 1741
93763ad5 1742 // get old value
605c2c4a
RR
1743 GValue gvalue = { 0, };
1744 g_value_init( &gvalue, G_TYPE_BOOLEAN );
1745 g_object_get_property( G_OBJECT(renderer), "active", &gvalue );
93763ad5 1746 bool tmp = g_value_get_boolean( &gvalue );
605c2c4a
RR
1747 g_value_unset( &gvalue );
1748 // invert it
1749 tmp = !tmp;
93763ad5 1750
605c2c4a
RR
1751 wxVariant value = tmp;
1752 if (!cell->Validate( value ))
1753 return;
93763ad5 1754
e0062c04 1755 wxDataViewModel *model = cell->GetOwner()->GetOwner()->GetModel();
93763ad5 1756
605c2c4a 1757 GtkTreePath *gtk_path = gtk_tree_path_new_from_string( path );
55fbde12
RR
1758 GtkTreeIter iter;
1759 cell->GetOwner()->GetOwner()->GtkGetInternal()->get_iter( &iter, gtk_path );
1760 wxDataViewItem item( (void*) iter.user_data );;
605c2c4a 1761 gtk_tree_path_free( gtk_path );
93763ad5 1762
0a71f9e9 1763 unsigned int model_col = cell->GetOwner()->GetModelColumn();
93763ad5 1764
9d52aad3
RR
1765 model->SetValue( value, item, model_col );
1766 model->ValueChanged( item, model_col );
605c2c4a
RR
1767}
1768
baa9ebc4 1769IMPLEMENT_CLASS(wxDataViewToggleRenderer, wxDataViewRenderer)
605c2c4a 1770
baa9ebc4 1771wxDataViewToggleRenderer::wxDataViewToggleRenderer( const wxString &varianttype,
9861f022
RR
1772 wxDataViewCellMode mode, int align ) :
1773 wxDataViewRenderer( varianttype, mode, align )
605c2c4a 1774{
ed38aa55 1775 m_renderer = (GtkCellRenderer*) gtk_cell_renderer_toggle_new();
93763ad5 1776
9861f022 1777 if (mode & wxDATAVIEW_CELL_ACTIVATABLE)
605c2c4a 1778 {
9861f022
RR
1779 g_signal_connect_after( m_renderer, "toggled",
1780 G_CALLBACK(wxGtkToggleRendererToggledCallback), this );
553f7d8f
RR
1781 }
1782 else
1783 {
605c2c4a
RR
1784 GValue gvalue = { 0, };
1785 g_value_init( &gvalue, G_TYPE_BOOLEAN );
553f7d8f 1786 g_value_set_boolean( &gvalue, false );
605c2c4a
RR
1787 g_object_set_property( G_OBJECT(m_renderer), "activatable", &gvalue );
1788 g_value_unset( &gvalue );
605c2c4a 1789 }
9861f022
RR
1790
1791 SetMode(mode);
1792 SetAlignment(align);
605c2c4a
RR
1793}
1794
baa9ebc4 1795bool wxDataViewToggleRenderer::SetValue( const wxVariant &value )
605c2c4a
RR
1796{
1797 bool tmp = value;
93763ad5 1798
605c2c4a
RR
1799 GValue gvalue = { 0, };
1800 g_value_init( &gvalue, G_TYPE_BOOLEAN );
1801 g_value_set_boolean( &gvalue, tmp );
1802 g_object_set_property( G_OBJECT(m_renderer), "active", &gvalue );
1803 g_value_unset( &gvalue );
93763ad5 1804
605c2c4a
RR
1805 return true;
1806}
1807
9861f022 1808bool wxDataViewToggleRenderer::GetValue( wxVariant &value ) const
605c2c4a
RR
1809{
1810 GValue gvalue = { 0, };
1811 g_value_init( &gvalue, G_TYPE_BOOLEAN );
1812 g_object_get_property( G_OBJECT(m_renderer), "active", &gvalue );
93763ad5 1813 bool tmp = g_value_get_boolean( &gvalue );
605c2c4a 1814 g_value_unset( &gvalue );
93763ad5 1815
605c2c4a
RR
1816 value = tmp;
1817
1818 return true;
1819}
93763ad5
WS
1820
1821// ---------------------------------------------------------
baa9ebc4 1822// wxDataViewCustomRenderer
93763ad5 1823// ---------------------------------------------------------
e152afc3 1824
888dde65 1825class wxDataViewCtrlDCImpl: public wxWindowDCImpl
e152afc3
RR
1826{
1827public:
888dde65
RR
1828 wxDataViewCtrlDCImpl( wxDC *owner, wxDataViewCtrl *window ) :
1829 wxWindowDCImpl( owner )
1830 {
1a367564 1831 GtkWidget *widget = window->m_treeview;
e152afc3 1832 // Set later
888dde65 1833 m_gdkwindow = NULL;
7857346a 1834
888dde65 1835 m_window = window;
4d496ecb 1836
496e7ec6 1837 m_context = window->GTKGetPangoDefaultContext();
e152afc3
RR
1838 m_layout = pango_layout_new( m_context );
1839 m_fontdesc = pango_font_description_copy( widget->style->font_desc );
1840
1841 m_cmap = gtk_widget_get_colormap( widget ? widget : window->m_widget );
888dde65
RR
1842
1843 // Set m_gdkwindow later
4d496ecb 1844 // SetUpDC();
e152afc3
RR
1845 }
1846};
1847
888dde65
RR
1848class wxDataViewCtrlDC: public wxWindowDC
1849{
1850public:
c5c5395b
RR
1851 wxDataViewCtrlDC( wxDataViewCtrl *window ) :
1852 wxWindowDC( new wxDataViewCtrlDCImpl( this, window ) )
7857346a 1853 { }
888dde65 1854};
7857346a 1855
888dde65 1856
93763ad5 1857// ---------------------------------------------------------
baa9ebc4 1858// wxDataViewCustomRenderer
93763ad5 1859// ---------------------------------------------------------
e152afc3 1860
baa9ebc4 1861IMPLEMENT_CLASS(wxDataViewCustomRenderer, wxDataViewRenderer)
e152afc3 1862
baa9ebc4 1863wxDataViewCustomRenderer::wxDataViewCustomRenderer( const wxString &varianttype,
9861f022
RR
1864 wxDataViewCellMode mode, int align,
1865 bool no_init ) :
1866 wxDataViewRenderer( varianttype, mode, align )
e152afc3
RR
1867{
1868 m_dc = NULL;
f69c03de 1869 m_text_renderer = NULL;
93763ad5 1870
ad63bf41
RR
1871 if (no_init)
1872 m_renderer = NULL;
1873 else
9861f022 1874 Init(mode, align);
ad63bf41
RR
1875}
1876
7857346a 1877void wxDataViewCustomRenderer::RenderText( const wxString &text, int xoffset,
85136e3b 1878 wxRect WXUNUSED(cell), wxDC *WXUNUSED(dc), int WXUNUSED(state) )
52e750fc 1879{
f69c03de 1880#if 0
52e750fc
RR
1881 wxDataViewCtrl *view = GetOwner()->GetOwner();
1882 wxColour col = (state & wxDATAVIEW_CELL_SELECTED) ?
1883 wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) :
1884 view->GetForegroundColour();
1885 dc->SetTextForeground(col);
1886 dc->DrawText( text, cell.x + xoffset, cell.y + ((cell.height - dc->GetCharHeight()) / 2));
f69c03de
RR
1887#else
1888 if (!m_text_renderer)
1889 m_text_renderer = gtk_cell_renderer_text_new();
b9db5f30 1890
f69c03de
RR
1891 GValue gvalue = { 0, };
1892 g_value_init( &gvalue, G_TYPE_STRING );
1bf629bd 1893 g_value_set_string( &gvalue, wxGTK_CONV_FONT( text, GetOwner()->GetOwner()->GetFont() ) );
f69c03de
RR
1894 g_object_set_property( G_OBJECT(m_text_renderer), "text", &gvalue );
1895 g_value_unset( &gvalue );
1896
1897 ((GdkRectangle*) cell_area)->x += xoffset;
1898 ((GdkRectangle*) cell_area)->width -= xoffset;
b9db5f30 1899
f69c03de
RR
1900 gtk_cell_renderer_render( m_text_renderer,
1901 window,
1902 widget,
1903 (GdkRectangle*) background_area,
1904 (GdkRectangle*) cell_area,
1905 (GdkRectangle*) expose_area,
1906 (GtkCellRendererState) flags );
b9db5f30 1907
f69c03de
RR
1908 ((GdkRectangle*) cell_area)->x -= xoffset;
1909 ((GdkRectangle*) cell_area)->width += xoffset;
1910#endif
52e750fc
RR
1911}
1912
9861f022 1913bool wxDataViewCustomRenderer::Init(wxDataViewCellMode mode, int align)
ad63bf41 1914{
e152afc3
RR
1915 GtkWxCellRenderer *renderer = (GtkWxCellRenderer *) gtk_wx_cell_renderer_new();
1916 renderer->cell = this;
93763ad5 1917
ed38aa55 1918 m_renderer = (GtkCellRenderer*) renderer;
93763ad5 1919
9861f022
RR
1920 SetMode(mode);
1921 SetAlignment(align);
93763ad5 1922
a912e81f 1923 GtkInitHandlers();
b9db5f30 1924
ad63bf41 1925 return true;
e152afc3
RR
1926}
1927
baa9ebc4 1928wxDataViewCustomRenderer::~wxDataViewCustomRenderer()
e152afc3
RR
1929{
1930 if (m_dc)
1931 delete m_dc;
f69c03de
RR
1932
1933 if (m_text_renderer)
352cd79f 1934 gtk_object_sink( GTK_OBJECT(m_text_renderer) );
e152afc3
RR
1935}
1936
baa9ebc4 1937wxDC *wxDataViewCustomRenderer::GetDC()
e152afc3
RR
1938{
1939 if (m_dc == NULL)
4d496ecb
RR
1940 {
1941 if (GetOwner() == NULL)
1942 return NULL;
1943 if (GetOwner()->GetOwner() == NULL)
1944 return NULL;
e152afc3 1945 m_dc = new wxDataViewCtrlDC( GetOwner()->GetOwner() );
4d496ecb 1946 }
93763ad5 1947
e152afc3
RR
1948 return m_dc;
1949}
93763ad5
WS
1950
1951// ---------------------------------------------------------
baa9ebc4 1952// wxDataViewProgressRenderer
93763ad5 1953// ---------------------------------------------------------
ad63bf41 1954
baa9ebc4 1955IMPLEMENT_CLASS(wxDataViewProgressRenderer, wxDataViewCustomRenderer)
ad63bf41 1956
baa9ebc4 1957wxDataViewProgressRenderer::wxDataViewProgressRenderer( const wxString &label,
9861f022
RR
1958 const wxString &varianttype, wxDataViewCellMode mode, int align ) :
1959 wxDataViewCustomRenderer( varianttype, mode, align, true )
ad63bf41
RR
1960{
1961 m_label = label;
1962 m_value = 0;
93763ad5 1963
ad63bf41
RR
1964#ifdef __WXGTK26__
1965 if (!gtk_check_version(2,6,0))
1966 {
ed38aa55 1967 m_renderer = (GtkCellRenderer*) gtk_cell_renderer_progress_new();
93763ad5 1968
ad63bf41
RR
1969 GValue gvalue = { 0, };
1970 g_value_init( &gvalue, G_TYPE_STRING );
09dfa6a0 1971
1bf629bd 1972 g_value_set_string( &gvalue, wxGTK_CONV_FONT( m_label, GetOwner()->GetOwner()->GetFont() ) );
ad63bf41
RR
1973 g_object_set_property( G_OBJECT(m_renderer), "text", &gvalue );
1974 g_value_unset( &gvalue );
9861f022
RR
1975
1976 SetMode(mode);
1977 SetAlignment(align);
ad63bf41
RR
1978 }
1979 else
1980#endif
1981 {
1982 // Use custom cell code
9861f022 1983 wxDataViewCustomRenderer::Init(mode, align);
ad63bf41
RR
1984 }
1985}
1986
baa9ebc4 1987wxDataViewProgressRenderer::~wxDataViewProgressRenderer()
ad63bf41
RR
1988{
1989}
1990
baa9ebc4 1991bool wxDataViewProgressRenderer::SetValue( const wxVariant &value )
ad63bf41
RR
1992{
1993#ifdef __WXGTK26__
1994 if (!gtk_check_version(2,6,0))
1995 {
7226118b 1996 gint tmp = (long) value;
ad63bf41
RR
1997 GValue gvalue = { 0, };
1998 g_value_init( &gvalue, G_TYPE_INT );
7226118b 1999 g_value_set_int( &gvalue, tmp );
ad63bf41
RR
2000 g_object_set_property( G_OBJECT(m_renderer), "value", &gvalue );
2001 g_value_unset( &gvalue );
2002 }
2003 else
2004#endif
2005 {
2006 m_value = (long) value;
93763ad5 2007
ad63bf41
RR
2008 if (m_value < 0) m_value = 0;
2009 if (m_value > 100) m_value = 100;
2010 }
93763ad5 2011
ad63bf41
RR
2012 return true;
2013}
93763ad5 2014
85136e3b 2015bool wxDataViewProgressRenderer::GetValue( wxVariant &WXUNUSED(value) ) const
9861f022
RR
2016{
2017 return false;
2018}
2019
85136e3b 2020bool wxDataViewProgressRenderer::Render( wxRect cell, wxDC *dc, int WXUNUSED(state) )
ad63bf41
RR
2021{
2022 double pct = (double)m_value / 100.0;
2023 wxRect bar = cell;
2024 bar.width = (int)(cell.width * pct);
2025 dc->SetPen( *wxTRANSPARENT_PEN );
2026 dc->SetBrush( *wxBLUE_BRUSH );
2027 dc->DrawRectangle( bar );
2028
2029 dc->SetBrush( *wxTRANSPARENT_BRUSH );
2030 dc->SetPen( *wxBLACK_PEN );
2031 dc->DrawRectangle( cell );
93763ad5 2032
ad63bf41
RR
2033 return true;
2034}
2035
9861f022 2036wxSize wxDataViewProgressRenderer::GetSize() const
ad63bf41
RR
2037{
2038 return wxSize(40,12);
2039}
93763ad5 2040
7448d67c
RR
2041// -------------------------------------
2042// wxDataViewChoiceRenderer
2043// -------------------------------------
2044
2045wxDataViewChoiceRenderer::wxDataViewChoiceRenderer( const wxArrayString &choices,
2046 wxDataViewCellMode mode, int alignment ) :
2047 wxDataViewCustomRenderer( "string", mode, alignment, true )
2048{
2049 m_choices = choices;
2050
2051#ifdef __WXGTK26__
2052 if (!gtk_check_version(2,6,0))
2053 {
2054 m_renderer = (GtkCellRenderer*) gtk_cell_renderer_combo_new();
2055
2056 GtkListStore *store = gtk_list_store_new( 1, G_TYPE_STRING );
5baee1f4
VZ
2057 for (size_t n = 0; n < m_choices.GetCount(); n++)
2058 {
2059 gtk_list_store_insert_with_values(
2060 store, NULL, n, 0,
2061 static_cast<const char *>(m_choices[n].utf8_str()), -1 );
2062 }
bc0289bf 2063
7448d67c
RR
2064 g_object_set (m_renderer,
2065 "model", store,
2066 "text-column", 0,
2067 "has-entry", FALSE,
2068 NULL);
bc0289bf 2069
7448d67c
RR
2070 bool editable = (mode & wxDATAVIEW_CELL_EDITABLE);
2071 g_object_set (m_renderer, "editable", editable, NULL);
bc0289bf 2072
7448d67c 2073 SetAlignment(alignment);
bc0289bf 2074
7448d67c
RR
2075 g_signal_connect_after( m_renderer, "edited", G_CALLBACK(wxGtkTextRendererEditedCallback), this );
2076
2077 GtkInitHandlers();
2078 }
2079 else
2080#endif
2081 {
2082 // Use custom cell code
2083 wxDataViewCustomRenderer::Init(mode, alignment);
2084 }
2085}
2086
2087bool wxDataViewChoiceRenderer::Render( wxRect rect, wxDC *dc, int state )
2088{
2089 RenderText( m_data, 0, rect, dc, state );
2090 return true;
2091}
2092
2093wxSize wxDataViewChoiceRenderer::GetSize() const
2094{
2095 return wxSize(70,20);
2096}
2097
2098bool wxDataViewChoiceRenderer::SetValue( const wxVariant &value )
2099{
bc0289bf 2100
7448d67c
RR
2101#ifdef __WXGTK26__
2102 if (!gtk_check_version(2,6,0))
2103 {
2104 GValue gvalue = { 0, };
2105 g_value_init( &gvalue, G_TYPE_STRING );
2106 g_value_set_string( &gvalue, wxGTK_CONV_FONT( value.GetString(), GetOwner()->GetOwner()->GetFont() ) );
2107 g_object_set_property( G_OBJECT(m_renderer), "text", &gvalue );
2108 g_value_unset( &gvalue );
2109 }
2110 else
2111#endif
2112 m_data = value.GetString();
2113
2114 return true;
2115}
2116
2117bool wxDataViewChoiceRenderer::GetValue( wxVariant &value ) const
2118{
2119#ifdef __WXGTK26__
2120 if (!gtk_check_version(2,6,0))
2121 {
2122 GValue gvalue = { 0, };
2123 g_value_init( &gvalue, G_TYPE_STRING );
2124 g_object_get_property( G_OBJECT(m_renderer), "text", &gvalue );
5baee1f4
VZ
2125 wxString temp = wxGTK_CONV_BACK_FONT( g_value_get_string( &gvalue ),
2126 const_cast<wxDataViewChoiceRenderer*>(this)->GetOwner()->GetOwner()->GetFont() );
7448d67c
RR
2127 g_value_unset( &gvalue );
2128 value = temp;
c2489d8e
FM
2129
2130 //wxPrintf( "temp %s\n", temp );
2131 // TODO: remove this code
7448d67c
RR
2132 }
2133 else
2134#endif
2135 value = m_data;
2136
2137 return true;
2138}
2139
2140void wxDataViewChoiceRenderer::SetAlignment( int align )
2141{
2142 wxDataViewCustomRenderer::SetAlignment(align);
2143
2144 if (gtk_check_version(2,10,0))
2145 return;
2146
2147 // horizontal alignment:
2148 PangoAlignment pangoAlign = PANGO_ALIGN_LEFT;
2149 if (align & wxALIGN_RIGHT)
2150 pangoAlign = PANGO_ALIGN_RIGHT;
2151 else if (align & wxALIGN_CENTER_HORIZONTAL)
2152 pangoAlign = PANGO_ALIGN_CENTER;
2153
2154 GValue gvalue = { 0, };
2155 g_value_init( &gvalue, gtk_cell_renderer_mode_get_type() );
2156 g_value_set_enum( &gvalue, pangoAlign );
2157 g_object_set_property( G_OBJECT(m_renderer), "alignment", &gvalue );
2158 g_value_unset( &gvalue );
2159}
bc0289bf 2160
93763ad5 2161// ---------------------------------------------------------
baa9ebc4 2162// wxDataViewDateRenderer
93763ad5 2163// ---------------------------------------------------------
4d496ecb 2164
baa9ebc4 2165class wxDataViewDateRendererPopupTransient: public wxPopupTransientWindow
7ea3a0de 2166{
93763ad5 2167public:
baa9ebc4 2168 wxDataViewDateRendererPopupTransient( wxWindow* parent, wxDateTime *value,
e0062c04 2169 wxDataViewModel *model, const wxDataViewItem &item, unsigned int col ) :
7ea3a0de
RR
2170 wxPopupTransientWindow( parent, wxBORDER_SIMPLE )
2171 {
2172 m_model = model;
e0062c04 2173 m_item = item;
7ea3a0de 2174 m_col = col;
7ea3a0de
RR
2175 m_cal = new wxCalendarCtrl( this, -1, *value );
2176 wxBoxSizer *sizer = new wxBoxSizer( wxHORIZONTAL );
2177 sizer->Add( m_cal, 1, wxGROW );
2178 SetSizer( sizer );
2179 sizer->Fit( this );
2180 }
93763ad5 2181
7ea3a0de
RR
2182 virtual void OnDismiss()
2183 {
2184 }
93763ad5 2185
7ea3a0de 2186 void OnCalendar( wxCalendarEvent &event );
93763ad5 2187
e0062c04
RR
2188 wxCalendarCtrl *m_cal;
2189 wxDataViewModel *m_model;
2190 wxDataViewItem m_item;
2191 unsigned int m_col;
93763ad5 2192
7ea3a0de
RR
2193private:
2194 DECLARE_EVENT_TABLE()
2195};
2196
baa9ebc4
RR
2197BEGIN_EVENT_TABLE(wxDataViewDateRendererPopupTransient,wxPopupTransientWindow)
2198 EVT_CALENDAR( -1, wxDataViewDateRendererPopupTransient::OnCalendar )
7ea3a0de
RR
2199END_EVENT_TABLE()
2200
baa9ebc4 2201void wxDataViewDateRendererPopupTransient::OnCalendar( wxCalendarEvent &event )
7ea3a0de
RR
2202{
2203 wxDateTime date = event.GetDate();
2204 wxVariant value = date;
e0062c04
RR
2205 m_model->SetValue( value, m_item, m_col );
2206 m_model->ValueChanged( m_item, m_col );
7ea3a0de
RR
2207 DismissAndNotify();
2208}
2209
baa9ebc4 2210IMPLEMENT_CLASS(wxDataViewDateRenderer, wxDataViewCustomRenderer)
4d496ecb 2211
baa9ebc4 2212wxDataViewDateRenderer::wxDataViewDateRenderer( const wxString &varianttype,
9861f022
RR
2213 wxDataViewCellMode mode, int align ) :
2214 wxDataViewCustomRenderer( varianttype, mode, align )
4d496ecb 2215{
9861f022
RR
2216 SetMode(mode);
2217 SetAlignment(align);
4d496ecb 2218}
93763ad5 2219
baa9ebc4 2220bool wxDataViewDateRenderer::SetValue( const wxVariant &value )
4d496ecb
RR
2221{
2222 m_date = value.GetDateTime();
93763ad5 2223
4d496ecb
RR
2224 return true;
2225}
2226
85136e3b 2227bool wxDataViewDateRenderer::GetValue( wxVariant &WXUNUSED(value) ) const
9861f022
RR
2228{
2229 return false;
2230}
2231
baa9ebc4 2232bool wxDataViewDateRenderer::Render( wxRect cell, wxDC *dc, int state )
4d496ecb
RR
2233{
2234 dc->SetFont( GetOwner()->GetOwner()->GetFont() );
2235 wxString tmp = m_date.FormatDate();
52e750fc 2236 RenderText( tmp, 0, cell, dc, state );
4d496ecb
RR
2237 return true;
2238}
2239
9861f022 2240wxSize wxDataViewDateRenderer::GetSize() const
4d496ecb 2241{
4d496ecb
RR
2242 wxString tmp = m_date.FormatDate();
2243 wxCoord x,y,d;
9861f022 2244 GetView()->GetTextExtent( tmp, &x, &y, &d );
4d496ecb
RR
2245 return wxSize(x,y+d);
2246}
2247
85136e3b 2248bool wxDataViewDateRenderer::Activate( wxRect WXUNUSED(cell), wxDataViewModel *model,
e0062c04 2249 const wxDataViewItem &item, unsigned int col )
4d496ecb 2250{
3f3af7e7 2251 wxVariant variant;
e0062c04 2252 model->GetValue( variant, item, col );
7ea3a0de
RR
2253 wxDateTime value = variant.GetDateTime();
2254
baa9ebc4 2255 wxDataViewDateRendererPopupTransient *popup = new wxDataViewDateRendererPopupTransient(
e0062c04 2256 GetOwner()->GetOwner()->GetParent(), &value, model, item, col );
7ea3a0de
RR
2257 wxPoint pos = wxGetMousePosition();
2258 popup->Move( pos );
2259 popup->Layout();
2260 popup->Popup( popup->m_cal );
4d496ecb
RR
2261
2262 return true;
2263}
2264
c9c13e70 2265
b9db5f30 2266// ---------------------------------------------------------
c9c13e70 2267// wxDataViewIconTextRenderer
b9db5f30 2268// ---------------------------------------------------------
c9c13e70
RR
2269
2270IMPLEMENT_CLASS(wxDataViewIconTextRenderer, wxDataViewCustomRenderer)
2271
b9db5f30 2272wxDataViewIconTextRenderer::wxDataViewIconTextRenderer(
c9c13e70
RR
2273 const wxString &varianttype, wxDataViewCellMode mode, int align ) :
2274 wxDataViewCustomRenderer( varianttype, mode, align )
2275{
2276 SetMode(mode);
2277 SetAlignment(align);
2278}
2279
2280wxDataViewIconTextRenderer::~wxDataViewIconTextRenderer()
2281{
2282}
b9db5f30 2283
c9c13e70
RR
2284bool wxDataViewIconTextRenderer::SetValue( const wxVariant &value )
2285{
2286 m_value << value;
2287 return true;
2288}
2289
ad386793 2290bool wxDataViewIconTextRenderer::GetValue( wxVariant &WXUNUSED(value) ) const
c9c13e70
RR
2291{
2292 return false;
2293}
b9db5f30 2294
c9c13e70
RR
2295bool wxDataViewIconTextRenderer::Render( wxRect cell, wxDC *dc, int state )
2296{
c9c13e70 2297 const wxIcon &icon = m_value.GetIcon();
52e750fc 2298 int offset = 0;
c9c13e70
RR
2299 if (icon.IsOk())
2300 {
52e750fc
RR
2301 int yoffset = wxMax( 0, (cell.height - icon.GetHeight()) / 2 );
2302 dc->DrawIcon( icon, cell.x, cell.y + yoffset );
2303 offset = icon.GetWidth() + 4;
c9c13e70 2304 }
b9db5f30 2305
52e750fc 2306 RenderText( m_value.GetText(), offset, cell, dc, state );
c9c13e70
RR
2307
2308 return true;
2309}
2310
2311wxSize wxDataViewIconTextRenderer::GetSize() const
2312{
52e750fc
RR
2313 wxSize size;
2314 if (m_value.GetIcon().IsOk())
2315 size.x = 4 + m_value.GetIcon().GetWidth();
2316 wxCoord x,y,d;
2317 GetView()->GetTextExtent( m_value.GetText(), &x, &y, &d );
2318 size.x += x;
2319 size.y = y+d;
b9db5f30 2320 return size;
c9c13e70
RR
2321}
2322
7857346a 2323wxControl* wxDataViewIconTextRenderer::CreateEditorCtrl(
ad386793 2324 wxWindow *WXUNUSED(parent), wxRect WXUNUSED(labelRect), const wxVariant &WXUNUSED(value) )
c9c13e70
RR
2325{
2326 return NULL;
2327}
2328
7857346a 2329bool wxDataViewIconTextRenderer::GetValueFromEditorCtrl(
ad386793 2330 wxControl* WXUNUSED(editor), wxVariant &WXUNUSED(value) )
c9c13e70
RR
2331{
2332 return false;
2333}
2334
93763ad5 2335// ---------------------------------------------------------
605c2c4a 2336// wxDataViewColumn
93763ad5 2337// ---------------------------------------------------------
7b4fde82 2338
31fb32e1
RR
2339
2340static gboolean
ad386793 2341gtk_dataview_header_button_press_callback( GtkWidget *WXUNUSED(widget),
31fb32e1
RR
2342 GdkEventButton *gdk_event,
2343 wxDataViewColumn *column )
2344{
2345 if (gdk_event->type != GDK_BUTTON_PRESS)
94b1f7bc 2346 return FALSE;
f4322df6 2347
31fb32e1
RR
2348 if (gdk_event->button == 1)
2349 {
d32332aa 2350 gs_lastLeftClickHeader = column;
7857346a 2351
31fb32e1
RR
2352 wxDataViewCtrl *dv = column->GetOwner();
2353 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK, dv->GetId() );
2354 event.SetDataViewColumn( column );
2355 event.SetModel( dv->GetModel() );
937013e0 2356 if (dv->HandleWindowEvent( event ))
a84c5b6f 2357 return FALSE;
31fb32e1 2358 }
f4322df6 2359
dadc879e
RR
2360 if (gdk_event->button == 3)
2361 {
2362 wxDataViewCtrl *dv = column->GetOwner();
2363 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK, dv->GetId() );
2364 event.SetDataViewColumn( column );
2365 event.SetModel( dv->GetModel() );
937013e0 2366 if (dv->HandleWindowEvent( event ))
dadc879e
RR
2367 return FALSE;
2368 }
2369
94b1f7bc 2370 return FALSE;
31fb32e1
RR
2371}
2372
7b4fde82
RR
2373extern "C" {
2374static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *column,
2375 GtkCellRenderer *cell,
2376 GtkTreeModel *model,
2377 GtkTreeIter *iter,
2378 gpointer data );
2379}
2380
2381
ad386793 2382static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *WXUNUSED(column),
7b4fde82
RR
2383 GtkCellRenderer *renderer,
2384 GtkTreeModel *model,
2385 GtkTreeIter *iter,
2386 gpointer data )
2387{
e0062c04
RR
2388 g_return_if_fail (GTK_IS_WX_TREE_MODEL (model));
2389 GtkWxTreeModel *tree_model = (GtkWxTreeModel *) model;
93763ad5 2390
baa9ebc4 2391 wxDataViewRenderer *cell = (wxDataViewRenderer*) data;
a7f61f76 2392
9d52aad3 2393 wxDataViewItem item( (void*) iter->user_data );
93763ad5 2394
a826202e
RR
2395 wxDataViewModel *wx_model = tree_model->internal->GetDataViewModel();
2396
e39de702 2397 if (!wx_model->IsVirtualListModel())
2056dede 2398 {
b9db5f30 2399
a826202e
RR
2400 if (wx_model->IsContainer( item ))
2401 {
2402 if (wx_model->HasContainerColumns( item ) || (cell->GetOwner()->GetModelColumn() == 0))
2403 {
2404 GValue gvalue = { 0, };
2405 g_value_init( &gvalue, G_TYPE_BOOLEAN );
2406 g_value_set_boolean( &gvalue, TRUE );
2407 g_object_set_property( G_OBJECT(renderer), "visible", &gvalue );
2408 g_value_unset( &gvalue );
2409 }
2410 else
2411 {
2412 GValue gvalue = { 0, };
2413 g_value_init( &gvalue, G_TYPE_BOOLEAN );
2414 g_value_set_boolean( &gvalue, FALSE );
2415 g_object_set_property( G_OBJECT(renderer), "visible", &gvalue );
2416 g_value_unset( &gvalue );
b9db5f30 2417
a826202e
RR
2418 return;
2419 }
2420 }
2421 else
2422 {
2423 GValue gvalue = { 0, };
2424 g_value_init( &gvalue, G_TYPE_BOOLEAN );
2425 g_value_set_boolean( &gvalue, TRUE );
2426 g_object_set_property( G_OBJECT(renderer), "visible", &gvalue );
2427 g_value_unset( &gvalue );
2428 }
b9db5f30 2429
2056dede 2430 }
a826202e 2431
3f3af7e7 2432 wxVariant value;
a826202e 2433 wx_model->GetValue( value, item, cell->GetOwner()->GetModelColumn() );
7b4fde82
RR
2434
2435 if (value.GetType() != cell->GetVariantType())
f4322df6
VZ
2436 wxLogError( wxT("Wrong type, required: %s but: %s"),
2437 value.GetType().c_str(),
cbc9145c 2438 cell->GetVariantType().c_str() );
93763ad5 2439
7b4fde82 2440 cell->SetValue( value );
e0743e63 2441
4264606e
RR
2442 if (cell->GtkHasAttributes())
2443 {
2444 wxDataViewItemAttr attr;
2445 bool colour_set = false;
2446 bool style_set = false;
2447 bool weight_set = false;
b9db5f30 2448
4264606e
RR
2449 if (wx_model->GetAttr( item, cell->GetOwner()->GetModelColumn(), attr ))
2450 {
2451 // this must be a GtkCellRendererText
2452 wxColour colour = attr.GetColour();
2453 if (colour.IsOk())
2454 {
2455 const GdkColor * const gcol = colour.GetColor();
2a5e6d1b 2456
4264606e
RR
2457 GValue gvalue = { 0, };
2458 g_value_init( &gvalue, GDK_TYPE_COLOR );
2459 g_value_set_boxed( &gvalue, gcol );
2460 g_object_set_property( G_OBJECT(renderer), "foreground_gdk", &gvalue );
2461 g_value_unset( &gvalue );
b9db5f30 2462
4264606e
RR
2463 colour_set = true;
2464 }
b9db5f30 2465
4264606e
RR
2466 if (attr.GetItalic())
2467 {
2468 GValue gvalue = { 0, };
2469 g_value_init( &gvalue, PANGO_TYPE_STYLE );
2470 g_value_set_enum( &gvalue, PANGO_STYLE_ITALIC );
2471 g_object_set_property( G_OBJECT(renderer), "style", &gvalue );
2472 g_value_unset( &gvalue );
b9db5f30 2473
4264606e
RR
2474 style_set = true;
2475 }
b9db5f30 2476
4264606e
RR
2477 if (attr.GetBold())
2478 {
2479 GValue gvalue = { 0, };
2480 g_value_init( &gvalue, PANGO_TYPE_WEIGHT );
2481 g_value_set_enum( &gvalue, PANGO_WEIGHT_BOLD );
2482 g_object_set_property( G_OBJECT(renderer), "weight", &gvalue );
2483 g_value_unset( &gvalue );
b9db5f30 2484
4264606e
RR
2485 weight_set = true;
2486 }
2487 }
b9db5f30 2488
4264606e
RR
2489 if (!style_set)
2490 {
2491 GValue gvalue = { 0, };
2492 g_value_init( &gvalue, G_TYPE_BOOLEAN );
2493 g_value_set_boolean( &gvalue, FALSE );
2494 g_object_set_property( G_OBJECT(renderer), "style-set", &gvalue );
2495 g_value_unset( &gvalue );
2496 }
b9db5f30 2497
4264606e
RR
2498 if (!weight_set)
2499 {
2500 GValue gvalue = { 0, };
2501 g_value_init( &gvalue, G_TYPE_BOOLEAN );
2502 g_value_set_boolean( &gvalue, FALSE );
2503 g_object_set_property( G_OBJECT(renderer), "weight-set", &gvalue );
2504 g_value_unset( &gvalue );
2505 }
b9db5f30 2506
4264606e
RR
2507 if (!colour_set)
2508 {
2509 GValue gvalue = { 0, };
2510 g_value_init( &gvalue, G_TYPE_BOOLEAN );
2511 g_value_set_boolean( &gvalue, FALSE );
2512 g_object_set_property( G_OBJECT(renderer), "foreground-set", &gvalue );
2513 g_value_unset( &gvalue );
2514 }
2515 }
2516
2517#if 0
2a5e6d1b
RR
2518 if (attr.HasBackgroundColour())
2519 {
2520 wxColour colour = attr.GetBackgroundColour();
1cd5e95c 2521 const GdkColor * const gcol = colour.GetColor();
e0743e63 2522
2a5e6d1b
RR
2523 GValue gvalue = { 0, };
2524 g_value_init( &gvalue, GDK_TYPE_COLOR );
2525 g_value_set_boxed( &gvalue, gcol );
2526 g_object_set_property( G_OBJECT(renderer), "cell-background_gdk", &gvalue );
2527 g_value_unset( &gvalue );
2528 }
2529 else
2530 {
2531 GValue gvalue = { 0, };
2532 g_value_init( &gvalue, G_TYPE_BOOLEAN );
2533 g_value_set_boolean( &gvalue, FALSE );
2534 g_object_set_property( G_OBJECT(renderer), "cell-background-set", &gvalue );
2535 g_value_unset( &gvalue );
2536 }
e0062c04
RR
2537#endif
2538
7b4fde82
RR
2539}
2540
91a6c655 2541#include <wx/listimpl.cpp>
a76c2f37 2542WX_DEFINE_LIST(wxDataViewColumnList)
91a6c655 2543
f4322df6
VZ
2544wxDataViewColumn::wxDataViewColumn( const wxString &title, wxDataViewRenderer *cell,
2545 unsigned int model_column, int width,
835d0d55
VZ
2546 wxAlignment align, int flags )
2547 : wxDataViewColumnBase( cell, model_column )
fa28826d 2548{
9861f022 2549 Init( align, flags, width );
31fb32e1 2550
31fb32e1 2551 SetTitle( title );
fa28826d
RR
2552}
2553
f4322df6
VZ
2554wxDataViewColumn::wxDataViewColumn( const wxBitmap &bitmap, wxDataViewRenderer *cell,
2555 unsigned int model_column, int width,
835d0d55
VZ
2556 wxAlignment align, int flags )
2557 : wxDataViewColumnBase( bitmap, cell, model_column )
9861f022
RR
2558{
2559 Init( align, flags, width );
2560
2561 SetBitmap( bitmap );
2562}
2563
2564void wxDataViewColumn::Init(wxAlignment align, int flags, int width)
07a84e7b 2565{
31fb32e1 2566 m_isConnected = false;
07a84e7b 2567
9861f022 2568 GtkCellRenderer *renderer = (GtkCellRenderer *) GetRenderer()->GetGtkHandle();
07a84e7b 2569 GtkTreeViewColumn *column = gtk_tree_view_column_new();
9861f022 2570 m_column = (GtkWidget*) column;
07a84e7b 2571
9861f022
RR
2572 SetFlags( flags );
2573 SetAlignment( align );
07a84e7b 2574
ad386793 2575 SetWidth( width );
07a84e7b 2576
419a3607
RR
2577 // Create container for icon and label
2578 GtkWidget *box = gtk_hbox_new( FALSE, 1 );
2579 gtk_widget_show( box );
2580 // gtk_container_set_border_width((GtkContainer*)box, 2);
2581 m_image = gtk_image_new();
2582 gtk_box_pack_start(GTK_BOX(box), m_image, FALSE, FALSE, 1);
2583 m_label = gtk_label_new("");
2584 gtk_box_pack_end( GTK_BOX(box), GTK_WIDGET(m_label), FALSE, FALSE, 1 );
2585 gtk_tree_view_column_set_widget( column, box );
bc0289bf 2586
9861f022 2587 gtk_tree_view_column_pack_end( column, renderer, TRUE );
07a84e7b
RR
2588
2589 gtk_tree_view_column_set_cell_data_func( column, renderer,
9861f022 2590 wxGtkTreeCellDataFunc, (gpointer) GetRenderer(), NULL );
07a84e7b
RR
2591}
2592
31fb32e1
RR
2593void wxDataViewColumn::OnInternalIdle()
2594{
2595 if (m_isConnected)
2596 return;
f4322df6 2597
31fb32e1
RR
2598 if (GTK_WIDGET_REALIZED(GetOwner()->m_treeview))
2599 {
9861f022 2600 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
31fb32e1
RR
2601 if (column->button)
2602 {
2603 g_signal_connect(column->button, "button_press_event",
2604 G_CALLBACK (gtk_dataview_header_button_press_callback), this);
f4322df6 2605
31fb32e1
RR
2606 m_isConnected = true;
2607 }
2608 }
2609}
2610
b94db696
RR
2611void wxDataViewColumn::SetOwner( wxDataViewCtrl *owner )
2612{
2613 wxDataViewColumnBase::SetOwner( owner );
f4322df6 2614
9861f022 2615 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
f4322df6 2616
b94db696 2617 gtk_tree_view_column_set_title( column, wxGTK_CONV_FONT(GetTitle(), GetOwner()->GetFont() ) );
b94db696
RR
2618}
2619
fa28826d
RR
2620void wxDataViewColumn::SetTitle( const wxString &title )
2621{
09dfa6a0 2622 wxDataViewCtrl *ctrl = GetOwner();
419a3607 2623 gtk_label_set_text( GTK_LABEL(m_label), ctrl ? wxGTK_CONV_FONT(title, ctrl->GetFont())
09dfa6a0 2624 : wxGTK_CONV_SYS(title) );
419a3607
RR
2625 if (title.empty())
2626 gtk_widget_hide( m_label );
2627 else
2628 gtk_widget_show( m_label );
07a84e7b
RR
2629}
2630
9861f022
RR
2631wxString wxDataViewColumn::GetTitle() const
2632{
7f6cbcea
VZ
2633 return wxGTK_CONV_BACK_FONT(
2634 gtk_label_get_text( GTK_LABEL(m_label) ),
2635 GetOwner()->GetFont()
2636 );
9861f022
RR
2637}
2638
07a84e7b
RR
2639void wxDataViewColumn::SetBitmap( const wxBitmap &bitmap )
2640{
2641 wxDataViewColumnBase::SetBitmap( bitmap );
2642
07a84e7b
RR
2643 if (bitmap.Ok())
2644 {
419a3607 2645 GtkImage *gtk_image = GTK_IMAGE(m_image);
f4322df6 2646
d3b9f782 2647 GdkBitmap *mask = NULL;
07a84e7b
RR
2648 if (bitmap.GetMask())
2649 mask = bitmap.GetMask()->GetBitmap();
2650
2651 if (bitmap.HasPixbuf())
2652 {
2653 gtk_image_set_from_pixbuf(GTK_IMAGE(gtk_image),
2654 bitmap.GetPixbuf());
2655 }
2656 else
2657 {
2658 gtk_image_set_from_pixmap(GTK_IMAGE(gtk_image),
2659 bitmap.GetPixmap(), mask);
2660 }
419a3607 2661 gtk_widget_show( m_image );
07a84e7b
RR
2662 }
2663 else
2664 {
419a3607 2665 gtk_widget_hide( m_image );
07a84e7b 2666 }
fa28826d
RR
2667}
2668
9861f022
RR
2669void wxDataViewColumn::SetHidden( bool hidden )
2670{
2671 gtk_tree_view_column_set_visible( GTK_TREE_VIEW_COLUMN(m_column), !hidden );
2672}
2673
2674void wxDataViewColumn::SetResizeable( bool resizeable )
2675{
2676 gtk_tree_view_column_set_resizable( GTK_TREE_VIEW_COLUMN(m_column), resizeable );
2677}
2678
47cef10f
RR
2679void wxDataViewColumn::SetAlignment( wxAlignment align )
2680{
9861f022 2681 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
f4322df6 2682
47cef10f
RR
2683 gfloat xalign = 0.0;
2684 if (align == wxALIGN_RIGHT)
2685 xalign = 1.0;
9861f022
RR
2686 if (align == wxALIGN_CENTER_HORIZONTAL ||
2687 align == wxALIGN_CENTER)
47cef10f 2688 xalign = 0.5;
f4322df6 2689
9861f022 2690 gtk_tree_view_column_set_alignment( column, xalign );
bc0289bf 2691
f2b7492a
RR
2692 if (m_renderer && m_renderer->GetAlignment() == -1)
2693 m_renderer->GtkUpdateAlignment();
9861f022
RR
2694}
2695
2696wxAlignment wxDataViewColumn::GetAlignment() const
2697{
2698 gfloat xalign = gtk_tree_view_column_get_alignment( GTK_TREE_VIEW_COLUMN(m_column) );
2699
2700 if (xalign == 1.0)
2701 return wxALIGN_RIGHT;
2702 if (xalign == 0.5)
2703 return wxALIGN_CENTER_HORIZONTAL;
f4322df6 2704
9861f022 2705 return wxALIGN_LEFT;
47cef10f
RR
2706}
2707
31fb32e1
RR
2708void wxDataViewColumn::SetSortable( bool sortable )
2709{
9861f022 2710 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
b9db5f30 2711
140a119a
VZ
2712 if ( sortable )
2713 {
2714 gtk_tree_view_column_set_sort_column_id( column, GetModelColumn() );
2715 }
2716 else
2717 {
2718 gtk_tree_view_column_set_sort_column_id( column, -1 );
2719 gtk_tree_view_column_set_sort_indicator( column, FALSE );
2720 gtk_tree_view_column_set_clickable( column, FALSE );
2721 }
e2bfe673
VZ
2722}
2723
2724bool wxDataViewColumn::IsSortable() const
2725{
2726 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
2727 return gtk_tree_view_column_get_clickable( column );
2728}
2729
140a119a 2730void wxDataViewColumn::SetAsSortKey( bool WXUNUSED(sort) )
e2bfe673 2731{
dcb6cbec 2732 // it might not make sense to have this function in wxHeaderColumn at
140a119a
VZ
2733 // all in fact, changing of the sort order should only be done using the
2734 // associated control API
2735 wxFAIL_MSG( "not implemented" );
31fb32e1
RR
2736}
2737
e2bfe673 2738bool wxDataViewColumn::IsSortKey() const
31fb32e1 2739{
9861f022 2740 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
140a119a 2741 return gtk_tree_view_column_get_sort_indicator( column );
31fb32e1
RR
2742}
2743
9861f022
RR
2744bool wxDataViewColumn::IsResizeable() const
2745{
2746 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
2747 return gtk_tree_view_column_get_resizable( column );
2748}
2749
2750bool wxDataViewColumn::IsHidden() const
2751{
2752 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
2753 return !gtk_tree_view_column_get_visible( column );
2754}
2755
47cef10f
RR
2756void wxDataViewColumn::SetSortOrder( bool ascending )
2757{
9861f022 2758 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
f4322df6 2759
47cef10f
RR
2760 if (ascending)
2761 gtk_tree_view_column_set_sort_order( column, GTK_SORT_ASCENDING );
2762 else
2763 gtk_tree_view_column_set_sort_order( column, GTK_SORT_DESCENDING );
0bd26819
RR
2764
2765 gtk_tree_view_column_set_sort_indicator( column, TRUE );
47cef10f
RR
2766}
2767
87f0efe2 2768bool wxDataViewColumn::IsSortOrderAscending() const
31fb32e1 2769{
9861f022 2770 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column);
f4322df6 2771
31fb32e1
RR
2772 return (gtk_tree_view_column_get_sort_order( column ) != GTK_SORT_DESCENDING);
2773}
2774
9861f022 2775void wxDataViewColumn::SetMinWidth( int width )
533544f2 2776{
9861f022 2777 gtk_tree_view_column_set_min_width( GTK_TREE_VIEW_COLUMN(m_column), width );
533544f2
RR
2778}
2779
9861f022
RR
2780int wxDataViewColumn::GetMinWidth() const
2781{
2782 return gtk_tree_view_column_get_min_width( GTK_TREE_VIEW_COLUMN(m_column) );
2783}
2784
2785int wxDataViewColumn::GetWidth() const
533544f2 2786{
9861f022 2787 return gtk_tree_view_column_get_width( GTK_TREE_VIEW_COLUMN(m_column) );
533544f2
RR
2788}
2789
9861f022 2790void wxDataViewColumn::SetWidth( int width )
533544f2 2791{
ad386793
RR
2792 if (width < 0)
2793 {
973dc907
RR
2794#if 1
2795 gtk_tree_view_column_set_sizing( GTK_TREE_VIEW_COLUMN(m_column), GTK_TREE_VIEW_COLUMN_FIXED );
2796
2797 // TODO find a better calculation
97e89e29 2798 gtk_tree_view_column_set_fixed_width( GTK_TREE_VIEW_COLUMN(m_column), wxDVC_DEFAULT_WIDTH );
973dc907
RR
2799#else
2800 // this is unpractical for large numbers of items and disables
2801 // user resizing, which is totally unexpected
ad386793 2802 gtk_tree_view_column_set_sizing( GTK_TREE_VIEW_COLUMN(m_column), GTK_TREE_VIEW_COLUMN_AUTOSIZE );
973dc907 2803#endif
ad386793
RR
2804 }
2805 else
2806 {
2807 gtk_tree_view_column_set_sizing( GTK_TREE_VIEW_COLUMN(m_column), GTK_TREE_VIEW_COLUMN_FIXED );
7857346a 2808
ad386793
RR
2809 gtk_tree_view_column_set_fixed_width( GTK_TREE_VIEW_COLUMN(m_column), width );
2810 }
533544f2
RR
2811}
2812
99c75ebc
RR
2813void wxDataViewColumn::SetReorderable( bool reorderable )
2814{
2815 gtk_tree_view_column_set_reorderable( GTK_TREE_VIEW_COLUMN(m_column), reorderable );
2816}
2817
2818bool wxDataViewColumn::IsReorderable() const
2819{
2820 return gtk_tree_view_column_get_reorderable( GTK_TREE_VIEW_COLUMN(m_column) );
2821}
9861f022 2822
4508fcd2
RR
2823//-----------------------------------------------------------------------------
2824// wxGtkTreeModelNode
2825//-----------------------------------------------------------------------------
2826
2827void wxGtkTreeModelNode::Resort()
2828{
af110130
RR
2829 size_t child_count = GetChildCount();
2830 if (child_count == 0)
0be79c8a
RR
2831 return;
2832
af110130
RR
2833 size_t node_count = GetNodesCount();
2834
2835 if (child_count == 1)
0be79c8a 2836 {
af110130
RR
2837 if (node_count == 1)
2838 {
2839 wxGtkTreeModelNode *node = m_nodes.Item( 0 );
2840 node->Resort();
2841 }
0be79c8a
RR
2842 return;
2843 }
2844
40196b1e
RR
2845 wxGtkTreeModelChildren temp;
2846 WX_APPEND_ARRAY( temp, m_children );
b9db5f30 2847
8c2654ce 2848 gs_internal = m_internal;
40196b1e 2849 m_children.Sort( &wxGtkTreeModelChildCmp );
0be79c8a 2850
af110130 2851 gint *new_order = new gint[child_count];
b9db5f30 2852
40196b1e 2853 unsigned int pos;
af110130 2854 for (pos = 0; pos < child_count; pos++)
4508fcd2 2855 {
40196b1e
RR
2856 void *id = m_children.Item( pos );
2857 int old_pos = temp.Index( id );
2858 new_order[pos] = old_pos;
4508fcd2 2859 }
b9db5f30 2860
0be79c8a
RR
2861 GtkTreeModel *gtk_tree_model = GTK_TREE_MODEL( m_internal->GetGtkModel() );
2862
2863 GtkTreeIter iter;
40196b1e 2864 iter.user_data = GetItem().GetID();
0be79c8a 2865 iter.stamp = m_internal->GetGtkModel()->stamp;
b9db5f30 2866
40196b1e 2867 GtkTreePath *path = m_internal->get_path( &iter );
b9db5f30 2868
0be79c8a 2869 gtk_tree_model_rows_reordered( gtk_tree_model, path, &iter, new_order );
b9db5f30 2870
0be79c8a 2871 gtk_tree_path_free (path);
b9db5f30 2872
0be79c8a 2873 delete [] new_order;
b9db5f30 2874
af110130 2875 for (pos = 0; pos < node_count; pos++)
4508fcd2 2876 {
af110130 2877 wxGtkTreeModelNode *node = m_nodes.Item( pos );
4508fcd2
RR
2878 node->Resort();
2879 }
2880}
2881
55fbde12
RR
2882//-----------------------------------------------------------------------------
2883// wxDataViewCtrlInternal
2884//-----------------------------------------------------------------------------
2885
b9db5f30 2886wxDataViewCtrlInternal::wxDataViewCtrlInternal( wxDataViewCtrl *owner,
55fbde12 2887 wxDataViewModel *wx_model, GtkWxTreeModel *gtk_model )
b9db5f30 2888{
55fbde12 2889 m_owner = owner;
b9db5f30
VS
2890 m_wx_model = wx_model;
2891 m_gtk_model = gtk_model;
2892 m_root = NULL;
b8b7b087 2893 m_sort_order = GTK_SORT_ASCENDING;
40196b1e 2894 m_sort_column = -1;
d32332aa 2895 m_dataview_sort_column = NULL;
8c2654ce 2896
591cc82d
RR
2897 m_dragDataObject = NULL;
2898 m_dropDataObject = NULL;
b9db5f30 2899
e39de702 2900 if (!m_wx_model->IsVirtualListModel())
2056dede 2901 InitTree();
55fbde12 2902}
b9db5f30 2903
55fbde12
RR
2904wxDataViewCtrlInternal::~wxDataViewCtrlInternal()
2905{
2906 g_object_unref( m_gtk_model );
8c2654ce 2907
591cc82d
RR
2908 delete m_dragDataObject;
2909 delete m_dropDataObject;
55fbde12 2910}
b9db5f30 2911
ef427989
RR
2912void wxDataViewCtrlInternal::InitTree()
2913{
2914 wxDataViewItem item;
0be79c8a 2915 m_root = new wxGtkTreeModelNode( NULL, item, this );
ef427989
RR
2916
2917 BuildBranch( m_root );
2918}
2919
55fbde12
RR
2920void wxDataViewCtrlInternal::BuildBranch( wxGtkTreeModelNode *node )
2921{
2922 if (node->GetChildCount() == 0)
2923 {
74fe973b
RR
2924 wxDataViewItemArray children;
2925 unsigned int count = m_wx_model->GetChildren( node->GetItem(), children );
2926 unsigned int pos;
2927 for (pos = 0; pos < count; pos++)
55fbde12 2928 {
74fe973b 2929 wxDataViewItem child = children[pos];
b9db5f30 2930
af110130
RR
2931 if (m_wx_model->IsContainer( child ))
2932 node->AddNode( new wxGtkTreeModelNode( node, child, this ) );
2933 else
2934 node->AddLeave( child.GetID() );
b9db5f30 2935
effd54b0 2936 // Don't send any events here
55fbde12
RR
2937 }
2938 }
2939}
2940
f6f0ef85
RR
2941// GTK+ dnd iface
2942
15cac64f
RR
2943bool wxDataViewCtrlInternal::EnableDragSource( const wxDataFormat &format )
2944{
2945 wxGtkString atom_str( gdk_atom_name( format ) );
2946 m_dragSourceTargetEntryTarget = wxCharBuffer( atom_str );
8c2654ce 2947
15cac64f
RR
2948 m_dragSourceTargetEntry.target = m_dragSourceTargetEntryTarget.data();
2949 m_dragSourceTargetEntry.flags = 0;
2950 m_dragSourceTargetEntry.info = static_cast<guint>(-1);
8c2654ce 2951
15cac64f
RR
2952 gtk_tree_view_enable_model_drag_source( GTK_TREE_VIEW(m_owner->GtkGetTreeView() ),
2953 GDK_BUTTON1_MASK, &m_dragSourceTargetEntry, 1, (GdkDragAction) GDK_ACTION_COPY );
8c2654ce 2954
15cac64f
RR
2955 return true;
2956}
2957
e4de825e
RR
2958bool wxDataViewCtrlInternal::EnableDropTarget( const wxDataFormat &format )
2959{
2960 wxGtkString atom_str( gdk_atom_name( format ) );
2961 m_dropTargetTargetEntryTarget = wxCharBuffer( atom_str );
8c2654ce 2962
b4c40918 2963 m_dropTargetTargetEntry.target = m_dropTargetTargetEntryTarget.data();
e4de825e
RR
2964 m_dropTargetTargetEntry.flags = 0;
2965 m_dropTargetTargetEntry.info = static_cast<guint>(-1);
8c2654ce 2966
e4de825e
RR
2967 gtk_tree_view_enable_model_drag_dest( GTK_TREE_VIEW(m_owner->GtkGetTreeView() ),
2968 &m_dropTargetTargetEntry, 1, (GdkDragAction) GDK_ACTION_COPY );
8c2654ce 2969
e4de825e
RR
2970 return true;
2971}
2972
7857346a 2973gboolean wxDataViewCtrlInternal::row_draggable( GtkTreeDragSource *WXUNUSED(drag_source),
f6f0ef85
RR
2974 GtkTreePath *path )
2975{
591cc82d 2976 delete m_dragDataObject;
8c2654ce 2977
f6f0ef85
RR
2978 GtkTreeIter iter;
2979 if (!get_iter( &iter, path )) return FALSE;
f6f0ef85
RR
2980 wxDataViewItem item( (void*) iter.user_data );
2981
591cc82d 2982 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_BEGIN_DRAG, m_owner->GetId() );
e4de825e 2983 event.SetEventObject( m_owner );
15cac64f
RR
2984 event.SetItem( item );
2985 event.SetModel( m_wx_model );
591cc82d
RR
2986 if (!m_owner->HandleWindowEvent( event ))
2987 return FALSE;
8c2654ce 2988
591cc82d
RR
2989 if (!event.IsAllowed())
2990 return FALSE;
8c2654ce 2991
591cc82d
RR
2992 wxDataObject *obj = event.GetDataObject();
2993 if (!obj)
2994 return FALSE;
8c2654ce 2995
591cc82d 2996 m_dragDataObject = obj;
8c2654ce 2997
591cc82d 2998 return TRUE;
f6f0ef85
RR
2999}
3000
7857346a
VZ
3001gboolean
3002wxDataViewCtrlInternal::drag_data_delete(GtkTreeDragSource *WXUNUSED(drag_source),
3003 GtkTreePath *WXUNUSED(path))
f6f0ef85
RR
3004{
3005 return FALSE;
3006}
3007
7857346a 3008gboolean wxDataViewCtrlInternal::drag_data_get( GtkTreeDragSource *WXUNUSED(drag_source),
f6f0ef85
RR
3009 GtkTreePath *path, GtkSelectionData *selection_data )
3010{
3011 GtkTreeIter iter;
3012 if (!get_iter( &iter, path )) return FALSE;
f6f0ef85 3013 wxDataViewItem item( (void*) iter.user_data );
7857346a 3014
591cc82d
RR
3015 if (!m_dragDataObject->IsSupported( selection_data->target ))
3016 return FALSE;
7857346a 3017
591cc82d
RR
3018 size_t size = m_dragDataObject->GetDataSize( selection_data->target );
3019 if (size == 0)
3020 return FALSE;
8c2654ce 3021
591cc82d 3022 void *buf = malloc( size );
8c2654ce 3023
15cac64f 3024 gboolean res = FALSE;
591cc82d 3025 if (m_dragDataObject->GetDataHere( selection_data->target, buf ))
15cac64f 3026 {
15cac64f 3027 res = TRUE;
8c2654ce 3028
591cc82d
RR
3029 gtk_selection_data_set( selection_data, selection_data->target,
3030 8, (const guchar*) buf, size );
15cac64f 3031 }
f6f0ef85 3032
591cc82d 3033 free( buf );
7857346a 3034
15cac64f 3035 return res;
f6f0ef85
RR
3036}
3037
7857346a
VZ
3038gboolean
3039wxDataViewCtrlInternal::drag_data_received(GtkTreeDragDest *WXUNUSED(drag_dest),
e4de825e
RR
3040 GtkTreePath *path,
3041 GtkSelectionData *selection_data)
f6f0ef85 3042{
e4de825e
RR
3043 GtkTreeIter iter;
3044 if (!get_iter( &iter, path )) return FALSE;
3045 wxDataViewItem item( (void*) iter.user_data );
8c2654ce 3046
e4de825e
RR
3047 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_DROP, m_owner->GetId() );
3048 event.SetEventObject( m_owner );
3049 event.SetItem( item );
3050 event.SetModel( m_wx_model );
3051 event.SetDataFormat( selection_data->target );
3052 event.SetDataSize( selection_data->length );
3053 event.SetDataBuffer( selection_data->data );
3054 if (!m_owner->HandleWindowEvent( event ))
3055 return FALSE;
8c2654ce 3056
e4de825e
RR
3057 if (!event.IsAllowed())
3058 return FALSE;
3059
3060 return TRUE;
f6f0ef85
RR
3061}
3062
7857346a
VZ
3063gboolean
3064wxDataViewCtrlInternal::row_drop_possible(GtkTreeDragDest *WXUNUSED(drag_dest),
e4de825e
RR
3065 GtkTreePath *path,
3066 GtkSelectionData *selection_data)
f6f0ef85 3067{
e4de825e
RR
3068 GtkTreeIter iter;
3069 if (!get_iter( &iter, path )) return FALSE;
3070 wxDataViewItem item( (void*) iter.user_data );
8c2654ce 3071
e4de825e
RR
3072 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE, m_owner->GetId() );
3073 event.SetEventObject( m_owner );
3074 event.SetItem( item );
3075 event.SetModel( m_wx_model );
3076 event.SetDataFormat( selection_data->target );
3077 if (!m_owner->HandleWindowEvent( event ))
3078 return FALSE;
8c2654ce 3079
e4de825e
RR
3080 if (!event.IsAllowed())
3081 return FALSE;
8c2654ce 3082
e4de825e 3083 return TRUE;
f6f0ef85
RR
3084}
3085
3086// notifications from wxDataViewModel
3087
33ba5a05
RR
3088bool wxDataViewCtrlInternal::Cleared()
3089{
3090 if (m_root)
3091 {
3092 delete m_root;
3093 InitTree();
7857346a
VZ
3094 }
3095
33ba5a05
RR
3096 // Create new GTK model
3097 g_object_unref( m_gtk_model );
3098 m_gtk_model = wxgtk_tree_model_new();
3099 m_gtk_model->internal = this;
7857346a 3100
33ba5a05
RR
3101 return true;
3102}
3103
4508fcd2
RR
3104void wxDataViewCtrlInternal::Resort()
3105{
e39de702 3106 if (!m_wx_model->IsVirtualListModel())
2056dede 3107 m_root->Resort();
4508fcd2
RR
3108}
3109
55fbde12
RR
3110bool wxDataViewCtrlInternal::ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item )
3111{
e39de702 3112 if (!m_wx_model->IsVirtualListModel())
2056dede
RR
3113 {
3114 wxGtkTreeModelNode *parent_node = FindNode( parent );
c2489d8e
FM
3115 wxASSERT_MSG(parent_node,
3116 "Did you forget a call to ItemAdded()? The parent node is unknown to the wxGtkTreeModel");
3117
2056dede
RR
3118 if (m_wx_model->IsContainer( item ))
3119 parent_node->AddNode( new wxGtkTreeModelNode( parent_node, item, this ) );
3120 else
3121 parent_node->AddLeave( item.GetID() );
3122 }
b9db5f30 3123
55fbde12
RR
3124 return true;
3125}
3126
469d3e9b 3127bool wxDataViewCtrlInternal::ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item )
55fbde12 3128{
e39de702 3129 if (!m_wx_model->IsVirtualListModel())
2056dede
RR
3130 {
3131 wxGtkTreeModelNode *parent_node = FindNode( parent );
c2489d8e
FM
3132 wxASSERT_MSG(parent_node,
3133 "Did you forget a call to ItemAdded()? The parent node is unknown to the wxGtkTreeModel");
3134
2056dede
RR
3135 parent_node->DeleteChild( item.GetID() );
3136 }
b9db5f30 3137
d8331a01
RR
3138 return true;
3139}
3140
3141bool wxDataViewCtrlInternal::ItemChanged( const wxDataViewItem &item )
3142{
6608fdab 3143 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED, m_owner->GetId() );
d8331a01
RR
3144 event.SetEventObject( m_owner );
3145 event.SetModel( m_owner->GetModel() );
3146 event.SetItem( item );
937013e0 3147 m_owner->HandleWindowEvent( event );
b9db5f30 3148
d8331a01
RR
3149 return true;
3150}
3151
3152bool wxDataViewCtrlInternal::ValueChanged( const wxDataViewItem &item, unsigned int col )
3153{
6608fdab 3154 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED, m_owner->GetId() );
d8331a01
RR
3155 event.SetEventObject( m_owner );
3156 event.SetModel( m_owner->GetModel() );
3157 event.SetColumn( col );
6608fdab 3158 event.SetDataViewColumn( GetOwner()->GetColumn(col) );
d8331a01 3159 event.SetItem( item );
937013e0 3160 m_owner->HandleWindowEvent( event );
b9db5f30 3161
d8331a01
RR
3162 return true;
3163}
3164
f6f0ef85
RR
3165// GTK+ model iface
3166
2056dede
RR
3167GtkTreeModelFlags wxDataViewCtrlInternal::get_flags()
3168{
e39de702 3169 if (m_wx_model->IsVirtualListModel())
2056dede
RR
3170 return GTK_TREE_MODEL_LIST_ONLY;
3171 else
3172 return GTK_TREE_MODEL_ITERS_PERSIST;
3173}
3174
55fbde12
RR
3175gboolean wxDataViewCtrlInternal::get_iter( GtkTreeIter *iter, GtkTreePath *path )
3176{
e39de702 3177 if (m_wx_model->IsVirtualListModel())
2056dede
RR
3178 {
3179 wxDataViewIndexListModel *wx_model = (wxDataViewIndexListModel*) m_wx_model;
b9db5f30 3180
2056dede
RR
3181 unsigned int i = (unsigned int)gtk_tree_path_get_indices (path)[0];
3182
f52984b8 3183 if (i >= wx_model->GetLastIndex() + 1)
2056dede 3184 return FALSE;
55fbde12 3185
2056dede
RR
3186 iter->stamp = m_gtk_model->stamp;
3187 // user_data is just the index
3188 iter->user_data = (gpointer) i;
55fbde12 3189
2056dede
RR
3190 return TRUE;
3191 }
3192 else
55fbde12 3193 {
2056dede
RR
3194 int depth = gtk_tree_path_get_depth( path );
3195
3196 wxGtkTreeModelNode *node = m_root;
3197
3198 int i;
b9db5f30 3199 for (i = 0; i < depth; i++)
2056dede
RR
3200 {
3201 BuildBranch( node );
b9db5f30 3202
2056dede
RR
3203 gint pos = gtk_tree_path_get_indices (path)[i];
3204 if (pos < 0) return FALSE;
3205 if ((size_t)pos >= node->GetChildCount()) return FALSE;
b9db5f30 3206
2056dede 3207 void* id = node->GetChildren().Item( (size_t) pos );
b9db5f30 3208
2056dede 3209 if (i == depth-1)
af110130 3210 {
2056dede
RR
3211 iter->stamp = m_gtk_model->stamp;
3212 iter->user_data = id;
3213 return TRUE;
af110130 3214 }
2056dede
RR
3215
3216 size_t count = node->GetNodes().GetCount();
3217 size_t pos2;
3218 for (pos2 = 0; pos2 < count; pos2++)
3219 {
3220 wxGtkTreeModelNode *child_node = node->GetNodes().Item( pos2 );
3221 if (child_node->GetItem().GetID() == id)
3222 {
3223 node = child_node;
3224 break;
3225 }
b9db5f30 3226 }
2056dede 3227 }
af110130 3228 }
55fbde12 3229
af110130 3230 return FALSE;
55fbde12
RR
3231}
3232
3233GtkTreePath *wxDataViewCtrlInternal::get_path( GtkTreeIter *iter )
3234{
3235 GtkTreePath *retval = gtk_tree_path_new ();
b9db5f30 3236
e39de702 3237 if (m_wx_model->IsVirtualListModel())
2056dede
RR
3238 {
3239 // user_data is just the index
3240 int i = (wxUIntPtr) iter->user_data;
3241 gtk_tree_path_append_index (retval, i);
3242 }
3243 else
55fbde12 3244 {
b9db5f30
VS
3245 void *id = iter->user_data;
3246
2056dede
RR
3247 wxGtkTreeModelNode *node = FindParentNode( iter );
3248 while (node)
3249 {
3250 int pos = node->GetChildren().Index( id );
40196b1e 3251
2056dede 3252 gtk_tree_path_prepend_index( retval, pos );
b9db5f30 3253
2056dede
RR
3254 id = node->GetItem().GetID();
3255 node = node->GetParent();
3256 }
55fbde12 3257 }
b9db5f30 3258
55fbde12
RR
3259 return retval;
3260}
3261
3262gboolean wxDataViewCtrlInternal::iter_next( GtkTreeIter *iter )
3263{
e39de702 3264 if (m_wx_model->IsVirtualListModel())
2056dede
RR
3265 {
3266 wxDataViewIndexListModel *wx_model = (wxDataViewIndexListModel*) m_wx_model;
b9db5f30 3267
2056dede 3268 int n = (wxUIntPtr) iter->user_data;
69892729 3269
2056dede
RR
3270 if (n == -1)
3271 return FALSE;
40196b1e 3272
f52984b8 3273 if (n >= (int) wx_model->GetLastIndex())
2056dede
RR
3274 return FALSE;
3275
3276 iter->user_data = (gpointer) ++n;
3277 }
3278 else
3279 {
3280 wxGtkTreeModelNode *parent = FindParentNode( iter );
3281 if( parent == NULL )
3282 return FALSE;
3283
3284 int pos = parent->GetChildren().Index( iter->user_data );
3285
3286 if (pos == (int) parent->GetChildCount()-1)
3287 return FALSE;
b9db5f30 3288
2056dede
RR
3289 iter->stamp = m_gtk_model->stamp;
3290 iter->user_data = parent->GetChildren().Item( pos+1 );
3291 }
55fbde12
RR
3292
3293 return TRUE;
3294}
3295
3296gboolean wxDataViewCtrlInternal::iter_children( GtkTreeIter *iter, GtkTreeIter *parent )
3297{
e39de702 3298 if (m_wx_model->IsVirtualListModel())
2056dede
RR
3299 {
3300 // this is a list, nodes have no children
3301 if (parent)
3302 return FALSE;
3303
3304 iter->stamp = m_gtk_model->stamp;
3305 iter->user_data = (gpointer) -1;
3306
3307 return TRUE;
3308 }
3309 else
3310 {
3311 wxDataViewItem item( (void*) parent->user_data );
b9db5f30 3312
2056dede
RR
3313 if (!m_wx_model->IsContainer( item ))
3314 return FALSE;
b9db5f30 3315
2056dede 3316 wxGtkTreeModelNode *parent_node = FindNode( parent );
c2489d8e
FM
3317 wxASSERT_MSG(parent_node,
3318 "Did you forget a call to ItemAdded()? The parent node is unknown to the wxGtkTreeModel");
3319
2056dede 3320 BuildBranch( parent_node );
b9db5f30 3321
2056dede
RR
3322 if (parent_node->GetChildCount() == 0)
3323 return FALSE;
b9db5f30 3324
2056dede
RR
3325 iter->stamp = m_gtk_model->stamp;
3326 iter->user_data = (gpointer) parent_node->GetChildren().Item( 0 );
3327 }
b9db5f30 3328
55fbde12
RR
3329 return TRUE;
3330}
3331
3332gboolean wxDataViewCtrlInternal::iter_has_child( GtkTreeIter *iter )
3333{
e39de702 3334 if (m_wx_model->IsVirtualListModel())
2056dede
RR
3335 {
3336 // this is a list, nodes have no children
3337 return FALSE;
3338 }
3339 else
3340 {
3341 wxDataViewItem item( (void*) iter->user_data );
b9db5f30 3342
2056dede 3343 bool is_container = m_wx_model->IsContainer( item );
b9db5f30 3344
2056dede
RR
3345 if (!is_container)
3346 return FALSE;
b9db5f30 3347
2056dede 3348 wxGtkTreeModelNode *node = FindNode( iter );
c2489d8e
FM
3349 wxASSERT_MSG(node,
3350 "Did you forget a call to ItemAdded()? The iterator is unknown to the wxGtkTreeModel");
3351
2056dede 3352 BuildBranch( node );
b9db5f30 3353
2056dede
RR
3354 return (node->GetChildCount() > 0);
3355 }
55fbde12
RR
3356}
3357
3358gint wxDataViewCtrlInternal::iter_n_children( GtkTreeIter *iter )
3359{
e39de702 3360 if (m_wx_model->IsVirtualListModel())
2056dede
RR
3361 {
3362 wxDataViewIndexListModel *wx_model = (wxDataViewIndexListModel*) m_wx_model;
b9db5f30 3363
2056dede 3364 if (iter == NULL)
f52984b8 3365 return (gint) wx_model->GetLastIndex() + 1;
2056dede 3366
55fbde12 3367 return 0;
2056dede
RR
3368 }
3369 else
3370 {
11f20f99
RR
3371 if (iter == NULL)
3372 return m_root->GetChildCount();
c2489d8e 3373
2056dede 3374 wxDataViewItem item( (void*) iter->user_data );
b9db5f30 3375
2056dede
RR
3376 if (!m_wx_model->IsContainer( item ))
3377 return 0;
b9db5f30 3378
2056dede 3379 wxGtkTreeModelNode *parent_node = FindNode( iter );
c2489d8e
FM
3380 wxASSERT_MSG(parent_node,
3381 "Did you forget a call to ItemAdded()? The parent node is unknown to the wxGtkTreeModel");
3382
2056dede 3383 BuildBranch( parent_node );
ef427989 3384
2056dede 3385 // wxPrintf( "iter_n_children %d\n", parent_node->GetChildCount() );
b9db5f30 3386
2056dede
RR
3387 return parent_node->GetChildCount();
3388 }
55fbde12
RR
3389}
3390
3391gboolean wxDataViewCtrlInternal::iter_nth_child( GtkTreeIter *iter, GtkTreeIter *parent, gint n )
3392{
e39de702 3393 if (m_wx_model->IsVirtualListModel())
2056dede
RR
3394 {
3395 wxDataViewIndexListModel *wx_model = (wxDataViewIndexListModel*) m_wx_model;
b9db5f30 3396
2056dede
RR
3397 if (parent)
3398 return FALSE;
3399
3400 if (n < 0)
3401 return FALSE;
3402
f52984b8 3403 if (n >= (gint) wx_model->GetLastIndex() + 1)
2056dede
RR
3404 return FALSE;
3405
3406 iter->stamp = m_gtk_model->stamp;
3407 iter->user_data = (gpointer) n;
3408
3409 return TRUE;
3410 }
3411 else
3412 {
3413 void* id = NULL;
3414 if (parent) id = (void*) parent->user_data;
3415 wxDataViewItem item( id );
b9db5f30 3416
2056dede
RR
3417 if (!m_wx_model->IsContainer( item ))
3418 return FALSE;
b9db5f30 3419
2056dede 3420 wxGtkTreeModelNode *parent_node = FindNode( parent );
c2489d8e
FM
3421 wxASSERT_MSG(parent_node,
3422 "Did you forget a call to ItemAdded()? The parent node is unknown to the wxGtkTreeModel");
3423
2056dede 3424 BuildBranch( parent_node );
55fbde12 3425
2056dede 3426 // wxPrintf( "iter_nth_child %d\n", n );
b9db5f30 3427
2056dede
RR
3428 iter->stamp = m_gtk_model->stamp;
3429 iter->user_data = parent_node->GetChildren().Item( n );
55fbde12 3430
2056dede
RR
3431 return TRUE;
3432 }
55fbde12
RR
3433}
3434
3435gboolean wxDataViewCtrlInternal::iter_parent( GtkTreeIter *iter, GtkTreeIter *child )
3436{
e39de702 3437 if (m_wx_model->IsVirtualListModel())
2056dede 3438 {
55fbde12 3439 return FALSE;
2056dede
RR
3440 }
3441 else
3442 {
3443 wxGtkTreeModelNode *node = FindParentNode( child );
3444 if (!node)
3445 return FALSE;
b9db5f30 3446
2056dede
RR
3447 iter->stamp = m_gtk_model->stamp;
3448 iter->user_data = (gpointer) node->GetItem().GetID();
55fbde12 3449
2056dede
RR
3450 return TRUE;
3451 }
55fbde12 3452}
b9db5f30 3453
55fbde12 3454static wxGtkTreeModelNode*
69892729 3455wxDataViewCtrlInternal_FindNode( wxDataViewModel * model, wxGtkTreeModelNode *treeNode, const wxDataViewItem &item )
55fbde12 3456{
69892729
RR
3457 if( model == NULL )
3458 return NULL;
55fbde12 3459
69892729
RR
3460 ItemList list;
3461 list.DeleteContents( true );
3462 wxDataViewItem it( item );
b9db5f30 3463
69892729 3464 while( it.IsOk() )
55fbde12 3465 {
69892729
RR
3466 wxDataViewItem * pItem = new wxDataViewItem( it );
3467 list.Insert( pItem );
3468 it = model->GetParent( it );
3469 }
3470
3471 wxGtkTreeModelNode * node = treeNode;
966cb94d 3472 for( ItemList::compatibility_iterator n = list.GetFirst(); n; n = n->GetNext() )
69892729
RR
3473 {
3474 if( node && node->GetNodes().GetCount() != 0 )
ef427989 3475 {
69892729
RR
3476 int len = node->GetNodes().GetCount();
3477 wxGtkTreeModelNodes nodes = node->GetNodes();
3478 int j = 0;
3479 for( ; j < len; j ++)
3480 {
3481 if( nodes[j]->GetItem() == *(n->GetData()))
3482 {
3483 node = nodes[j];
3484 break;
b9db5f30 3485 }
69892729
RR
3486 }
3487
3488 if( j == len )
3489 {
3490 return NULL;
3491 }
ef427989 3492 }
69892729
RR
3493 else
3494 return NULL;
55fbde12 3495 }
69892729
RR
3496 return node;
3497
55fbde12
RR
3498}
3499
3500wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( GtkTreeIter *iter )
3501{
3502 if (!iter)
3503 return m_root;
3504
3505 wxDataViewItem item( (void*) iter->user_data );
0be79c8a
RR
3506 if (!item.IsOk())
3507 return m_root;
b9db5f30 3508
69892729 3509 wxGtkTreeModelNode *result = wxDataViewCtrlInternal_FindNode( m_wx_model, m_root, item );
b9db5f30 3510
c2489d8e 3511/*
55fbde12
RR
3512 if (!result)
3513 {
26f119eb 3514 wxLogDebug( "Not found %p", iter->user_data );
55fbde12
RR
3515 char *crash = NULL;
3516 *crash = 0;
3517 }
c2489d8e
FM
3518 // TODO: remove this code
3519*/
b9db5f30 3520
55fbde12
RR
3521 return result;
3522}
3523
3524wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( const wxDataViewItem &item )
3525{
0be79c8a
RR
3526 if (!item.IsOk())
3527 return m_root;
3528
69892729 3529 wxGtkTreeModelNode *result = wxDataViewCtrlInternal_FindNode( m_wx_model, m_root, item );
b9db5f30 3530
c2489d8e 3531/*
55fbde12
RR
3532 if (!result)
3533 {
26f119eb 3534 wxLogDebug( "Not found %p", item.GetID() );
55fbde12
RR
3535 char *crash = NULL;
3536 *crash = 0;
3537 }
c2489d8e
FM
3538 // TODO: remove this code
3539*/
b9db5f30 3540
55fbde12
RR
3541 return result;
3542}
3543
af110130 3544static wxGtkTreeModelNode*
69892729 3545wxDataViewCtrlInternal_FindParentNode( wxDataViewModel * model, wxGtkTreeModelNode *treeNode, const wxDataViewItem &item )
af110130 3546{
69892729
RR
3547 if( model == NULL )
3548 return NULL;
3549
3550 ItemList list;
3551 list.DeleteContents( true );
3552 if( !item.IsOk() )
3553 return NULL;
3554
3555 wxDataViewItem it( model->GetParent( item ) );
3556 while( it.IsOk() )
af110130 3557 {
69892729
RR
3558 wxDataViewItem * pItem = new wxDataViewItem( it );
3559 list.Insert( pItem );
3560 it = model->GetParent( it );
af110130
RR
3561 }
3562
69892729 3563 wxGtkTreeModelNode * node = treeNode;
966cb94d 3564 for( ItemList::compatibility_iterator n = list.GetFirst(); n; n = n->GetNext() )
af110130 3565 {
69892729 3566 if( node && node->GetNodes().GetCount() != 0 )
af110130 3567 {
69892729
RR
3568 int len = node->GetNodes().GetCount();
3569 wxGtkTreeModelNodes nodes = node->GetNodes();
3570 int j = 0;
3571 for( ; j < len; j ++)
3572 {
3573 if( nodes[j]->GetItem() == *(n->GetData()))
3574 {
3575 node = nodes[j];
3576 break;
b9db5f30 3577 }
69892729
RR
3578 }
3579
3580 if( j == len )
3581 {
3582 return NULL;
3583 }
af110130 3584 }
69892729
RR
3585 else
3586 return NULL;
3587 }
3588 //Examine whether the node is item's parent node
3589 int len = node->GetChildCount();
3590 for( int i = 0; i < len ; i ++ )
3591 {
3592 if( node->GetChildren().Item( i ) == item.GetID() )
3593 return node;
af110130 3594 }
af110130
RR
3595 return NULL;
3596}
3597
3598wxGtkTreeModelNode *wxDataViewCtrlInternal::FindParentNode( GtkTreeIter *iter )
3599{
3600 if (!iter)
3601 return NULL;
b9db5f30 3602
af110130
RR
3603 wxDataViewItem item( (void*) iter->user_data );
3604 if (!item.IsOk())
3605 return NULL;
3606
69892729 3607 return wxDataViewCtrlInternal_FindParentNode( m_wx_model, m_root, item );
af110130
RR
3608}
3609
3610wxGtkTreeModelNode *wxDataViewCtrlInternal::FindParentNode( const wxDataViewItem &item )
3611{
3612 if (!item.IsOk())
3613 return NULL;
3614
69892729 3615 return wxDataViewCtrlInternal_FindParentNode( m_wx_model, m_root, item );
af110130
RR
3616}
3617
eb7f97f8
RR
3618//-----------------------------------------------------------------------------
3619// wxDataViewCtrl signal callbacks
3620//-----------------------------------------------------------------------------
3621
3622static void
ad386793 3623wxdataview_selection_changed_callback( GtkTreeSelection* WXUNUSED(selection), wxDataViewCtrl *dv )
eb7f97f8 3624{
b94db696
RR
3625 if (!GTK_WIDGET_REALIZED(dv->m_widget))
3626 return;
f4322df6 3627
d86c1870 3628 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, dv->GetId() );
6848478c 3629 event.SetItem( dv->GetSelection() );
eb7f97f8 3630 event.SetModel( dv->GetModel() );
937013e0 3631 dv->HandleWindowEvent( event );
eb7f97f8
RR
3632}
3633
f828871d 3634static void
ad386793
RR
3635wxdataview_row_activated_callback( GtkTreeView* WXUNUSED(treeview), GtkTreePath *path,
3636 GtkTreeViewColumn *WXUNUSED(column), wxDataViewCtrl *dv )
f828871d 3637{
e0062c04 3638 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, dv->GetId() );
55fbde12
RR
3639
3640 GtkTreeIter iter;
3641 dv->GtkGetInternal()->get_iter( &iter, path );
3642 wxDataViewItem item( (void*) iter.user_data );;
3643 event.SetItem( item );
f828871d 3644 event.SetModel( dv->GetModel() );
937013e0 3645 dv->HandleWindowEvent( event );
f828871d
RR
3646}
3647
718fd180 3648static gboolean
ad386793
RR
3649wxdataview_test_expand_row_callback( GtkTreeView* WXUNUSED(treeview), GtkTreeIter* iter,
3650 GtkTreePath *WXUNUSED(path), wxDataViewCtrl *dv )
718fd180
RR
3651{
3652 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING, dv->GetId() );
3653
3654 wxDataViewItem item( (void*) iter->user_data );;
3655 event.SetItem( item );
3656 event.SetModel( dv->GetModel() );
937013e0 3657 dv->HandleWindowEvent( event );
b9db5f30 3658
718fd180
RR
3659 return !event.IsAllowed();
3660}
3661
3662static void
ad386793
RR
3663wxdataview_row_expanded_callback( GtkTreeView* WXUNUSED(treeview), GtkTreeIter* iter,
3664 GtkTreePath *WXUNUSED(path), wxDataViewCtrl *dv )
718fd180
RR
3665{
3666 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED, dv->GetId() );
3667
3668 wxDataViewItem item( (void*) iter->user_data );;
3669 event.SetItem( item );
3670 event.SetModel( dv->GetModel() );
937013e0 3671 dv->HandleWindowEvent( event );
718fd180
RR
3672}
3673
3674static gboolean
ad386793
RR
3675wxdataview_test_collapse_row_callback( GtkTreeView* WXUNUSED(treeview), GtkTreeIter* iter,
3676 GtkTreePath *WXUNUSED(path), wxDataViewCtrl *dv )
718fd180
RR
3677{
3678 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING, dv->GetId() );
3679
3680 wxDataViewItem item( (void*) iter->user_data );;
3681 event.SetItem( item );
3682 event.SetModel( dv->GetModel() );
937013e0 3683 dv->HandleWindowEvent( event );
b9db5f30 3684
718fd180
RR
3685 return !event.IsAllowed();
3686}
3687
3688static void
ad386793
RR
3689wxdataview_row_collapsed_callback( GtkTreeView* WXUNUSED(treeview), GtkTreeIter* iter,
3690 GtkTreePath *WXUNUSED(path), wxDataViewCtrl *dv )
718fd180
RR
3691{
3692 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED, dv->GetId() );
3693
3694 wxDataViewItem item( (void*) iter->user_data );;
3695 event.SetItem( item );
3696 event.SetModel( dv->GetModel() );
937013e0 3697 dv->HandleWindowEvent( event );
718fd180
RR
3698}
3699
790b137e 3700//-----------------------------------------------------------------------------
718fd180 3701 // wxDataViewCtrl
790b137e
RR
3702//-----------------------------------------------------------------------------
3703
48200154 3704void wxDataViewCtrl::AddChildGTK(wxWindowGTK* child)
1e510b1e 3705{
48200154 3706 GtkWidget* treeview = GtkGetTreeView();
1e510b1e
RR
3707
3708 // Insert widget in GtkTreeView
3709 if (GTK_WIDGET_REALIZED(treeview))
e8375af8 3710 gtk_widget_set_parent_window( child->m_widget,
1e510b1e
RR
3711 gtk_tree_view_get_bin_window( GTK_TREE_VIEW(treeview) ) );
3712 gtk_widget_set_parent( child->m_widget, treeview );
3713}
3714
3715static
3716void gtk_dataviewctrl_size_callback( GtkWidget *WXUNUSED(widget),
ad386793 3717 GtkAllocation *WXUNUSED(gtk_alloc),
1e510b1e
RR
3718 wxDataViewCtrl *win )
3719{
966cb94d 3720 wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
1e510b1e
RR
3721 while (node)
3722 {
3723 wxWindow *child = node->GetData();
e8375af8 3724
1e510b1e
RR
3725 GtkRequisition req;
3726 gtk_widget_size_request( child->m_widget, &req );
e8375af8 3727
1e510b1e
RR
3728 GtkAllocation alloc;
3729 alloc.x = child->m_x;
3730 alloc.y = child->m_y;
3731 alloc.width = child->m_width;
3732 alloc.height = child->m_height;
3733 gtk_widget_size_allocate( child->m_widget, &alloc );
e8375af8 3734
1e510b1e
RR
3735 node = node->GetNext();
3736 }
3737}
3738
3739
6608fdab
RR
3740//-----------------------------------------------------------------------------
3741// "motion_notify_event"
3742//-----------------------------------------------------------------------------
3743
3744static gboolean
ad386793 3745gtk_dataview_motion_notify_callback( GtkWidget *WXUNUSED(widget),
74dea0de
RR
3746 GdkEventMotion *gdk_event,
3747 wxDataViewCtrl *dv )
6608fdab
RR
3748{
3749 if (gdk_event->is_hint)
3750 {
3751 int x = 0;
3752 int y = 0;
3753 GdkModifierType state;
3754 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
3755 gdk_event->x = x;
3756 gdk_event->y = y;
3757 }
3758
3759 GtkTreePath *path = NULL;
3760 GtkTreeViewColumn *column = NULL;
3761 gint cell_x = 0;
3762 gint cell_y = 0;
b9db5f30 3763 if (gtk_tree_view_get_path_at_pos(
6608fdab
RR
3764 GTK_TREE_VIEW(dv->GtkGetTreeView()),
3765 (int) gdk_event->x, (int) gdk_event->y,
3766 &path,
3767 &column,
3768 &cell_x,
3769 &cell_y))
3770 {
3771 if (path)
3772 {
3773 GtkTreeIter iter;
3774 dv->GtkGetInternal()->get_iter( &iter, path );
b9db5f30 3775
6608fdab 3776 // wxPrintf( "mouse %d %d\n", (int) gdk_event->x, (int) gdk_event->y );
b9db5f30 3777
6608fdab
RR
3778 gtk_tree_path_free( path );
3779 }
3780 }
3781
3782
3783 return FALSE;
3784}
3785
74dea0de
RR
3786//-----------------------------------------------------------------------------
3787// "button_press_event"
3788//-----------------------------------------------------------------------------
3789
3790static gboolean
3791gtk_dataview_button_press_callback( GtkWidget *WXUNUSED(widget),
3792 GdkEventButton *gdk_event,
3793 wxDataViewCtrl *dv )
3794{
3795 if ((gdk_event->button == 3) && (gdk_event->type == GDK_BUTTON_PRESS))
3796 {
3797 GtkTreePath *path = NULL;
3798 GtkTreeViewColumn *column = NULL;
3799 gint cell_x = 0;
3800 gint cell_y = 0;
3801 if (gtk_tree_view_get_path_at_pos(
3802 GTK_TREE_VIEW(dv->GtkGetTreeView()),
3803 (int) gdk_event->x, (int) gdk_event->y,
3804 &path,
3805 &column,
3806 &cell_x,
3807 &cell_y))
3808 {
3809 if (path)
3810 {
3811 GtkTreeIter iter;
3812 dv->GtkGetInternal()->get_iter( &iter, path );
3813
3814 wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, dv->GetId() );
3815 wxDataViewItem item( (void*) iter.user_data );;
3816 event.SetItem( item );
3817 event.SetModel( dv->GetModel() );
3818 bool ret = dv->HandleWindowEvent( event );
3819 gtk_tree_path_free( path );
3820 return ret;
3821 }
3822 }
3823 }
3824
3825 return FALSE;
3826}
1e510b1e 3827
239eaa41
RR
3828IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl, wxDataViewCtrlBase)
3829
3830wxDataViewCtrl::~wxDataViewCtrl()
3831{
8f850e28
RR
3832 if (m_notifier)
3833 GetModel()->RemoveNotifier( m_notifier );
87f0efe2 3834
ef11ea71
RR
3835 m_cols.Clear();
3836
87f0efe2
RR
3837 // remove the model from the GtkTreeView before it gets destroyed by the
3838 // wxDataViewCtrlBase's dtor
3839 gtk_tree_view_set_model( GTK_TREE_VIEW(m_treeview), NULL );
b9db5f30 3840
55fbde12 3841 delete m_internal;
239eaa41
RR
3842}
3843
3844void wxDataViewCtrl::Init()
3845{
8f850e28 3846 m_notifier = NULL;
33ba5a05 3847 m_internal = NULL;
bc0289bf 3848
ef11ea71 3849 m_cols.DeleteContents( true );
239eaa41
RR
3850}
3851
3852bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id,
93763ad5 3853 const wxPoint& pos, const wxSize& size,
239eaa41
RR
3854 long style, const wxValidator& validator )
3855{
3856 Init();
93763ad5 3857
239eaa41
RR
3858 if (!PreCreation( parent, pos, size ) ||
3859 !CreateBase( parent, id, pos, size, style, validator ))
3860 {
3861 wxFAIL_MSG( wxT("wxDataViewCtrl creation failed") );
93763ad5 3862 return false;
239eaa41 3863 }
1a367564
RR
3864
3865 m_widget = gtk_scrolled_window_new (NULL, NULL);
9ff9d30c 3866 g_object_ref(m_widget);
6493aaca 3867
496e7ec6 3868 GTKScrolledWindowSetBorder(m_widget, style);
1a367564
RR
3869
3870 m_treeview = gtk_tree_view_new();
3871 gtk_container_add (GTK_CONTAINER (m_widget), m_treeview);
e8375af8 3872
1e510b1e
RR
3873 g_signal_connect (m_treeview, "size_allocate",
3874 G_CALLBACK (gtk_dataviewctrl_size_callback), this);
ed4b0fdc 3875
b94db696
RR
3876#ifdef __WXGTK26__
3877 if (!gtk_check_version(2,6,0))
344ed1f3
RR
3878 {
3879 bool fixed = (style & wxDV_VARIABLE_LINE_HEIGHT) == 0;
3880 gtk_tree_view_set_fixed_height_mode( GTK_TREE_VIEW(m_treeview), fixed );
3881 }
b94db696
RR
3882#endif
3883
daebb44c
RR
3884 if (style & wxDV_MULTIPLE)
3885 {
3886 GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
3887 gtk_tree_selection_set_mode( selection, GTK_SELECTION_MULTIPLE );
3888 }
93763ad5 3889
9861f022
RR
3890 gtk_tree_view_set_headers_visible( GTK_TREE_VIEW(m_treeview), (style & wxDV_NO_HEADER) == 0 );
3891
3892#ifdef __WXGTK210__
3893 if (!gtk_check_version(2,10,0))
3894 {
3895 GtkTreeViewGridLines grid = GTK_TREE_VIEW_GRID_LINES_NONE;
f4322df6
VZ
3896
3897 if ((style & wxDV_HORIZ_RULES) != 0 &&
9861f022
RR
3898 (style & wxDV_VERT_RULES) != 0)
3899 grid = GTK_TREE_VIEW_GRID_LINES_BOTH;
3900 else if (style & wxDV_VERT_RULES)
3901 grid = GTK_TREE_VIEW_GRID_LINES_VERTICAL;
3902 else if (style & wxDV_HORIZ_RULES)
3903 grid = GTK_TREE_VIEW_GRID_LINES_HORIZONTAL;
3904
1a07a730
RR
3905 if (grid != GTK_TREE_VIEW_GRID_LINES_NONE)
3906 gtk_tree_view_set_grid_lines( GTK_TREE_VIEW(m_treeview), grid );
9861f022 3907 }
9861f022 3908#endif
1a07a730
RR
3909
3910 gtk_tree_view_set_rules_hint( GTK_TREE_VIEW(m_treeview), (style & wxDV_ROW_LINES) != 0 );
9861f022 3911
1a367564 3912 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (m_widget),
16eab2e1 3913 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1a367564 3914 gtk_widget_show (m_treeview);
93763ad5 3915
239eaa41
RR
3916 m_parent->DoAddChild( this );
3917
b94db696
RR
3918 PostCreation(size);
3919
b086d55f
RR
3920 GtkEnableSelectionEvents();
3921
718fd180 3922 g_signal_connect_after (m_treeview, "row-activated",
f828871d 3923 G_CALLBACK (wxdataview_row_activated_callback), this);
eb7f97f8 3924
718fd180
RR
3925 g_signal_connect (m_treeview, "test-collapse-row",
3926 G_CALLBACK (wxdataview_test_collapse_row_callback), this);
3927
3928 g_signal_connect_after (m_treeview, "row-collapsed",
3929 G_CALLBACK (wxdataview_row_collapsed_callback), this);
3930
3931 g_signal_connect (m_treeview, "test-expand-row",
3932 G_CALLBACK (wxdataview_test_expand_row_callback), this);
b9db5f30 3933
718fd180
RR
3934 g_signal_connect_after (m_treeview, "row-expanded",
3935 G_CALLBACK (wxdataview_row_expanded_callback), this);
3936
6608fdab
RR
3937 g_signal_connect (m_treeview, "motion_notify_event",
3938 G_CALLBACK (gtk_dataview_motion_notify_callback), this);
3939
74dea0de
RR
3940 g_signal_connect (m_treeview, "button_press_event",
3941 G_CALLBACK (gtk_dataview_button_press_callback), this);
7857346a 3942
239eaa41
RR
3943 return true;
3944}
3945
31fb32e1
RR
3946void wxDataViewCtrl::OnInternalIdle()
3947{
3948 wxWindow::OnInternalIdle();
f4322df6 3949
9861f022 3950 unsigned int cols = GetColumnCount();
31fb32e1
RR
3951 unsigned int i;
3952 for (i = 0; i < cols; i++)
3953 {
3954 wxDataViewColumn *col = GetColumn( i );
3955 col->OnInternalIdle();
3956 }
3957}
3958
e0062c04 3959bool wxDataViewCtrl::AssociateModel( wxDataViewModel *model )
239eaa41 3960{
33ba5a05
RR
3961 if (GetModel())
3962 {
3963 delete m_internal;
3964 m_internal = NULL;
7857346a 3965
33ba5a05
RR
3966 delete m_notifier;
3967 m_notifier = NULL;
3968 }
7857346a 3969
239eaa41
RR
3970 if (!wxDataViewCtrlBase::AssociateModel( model ))
3971 return false;
3972
344ed1f3
RR
3973#ifdef __WXGTK26__
3974 if (!gtk_check_version(2,6,0))
3975 {
3976 bool fixed = (((GetWindowStyle() & wxDV_VARIABLE_LINE_HEIGHT) == 0) || (model->IsVirtualListModel()));
3977 gtk_tree_view_set_fixed_height_mode( GTK_TREE_VIEW(m_treeview), fixed );
3978 }
3979#endif
3980
55fbde12
RR
3981 GtkWxTreeModel *gtk_model = wxgtk_tree_model_new();
3982 m_internal = new wxDataViewCtrlInternal( this, model, gtk_model );
3983 gtk_model->internal = m_internal;
6e2e590f 3984
55fbde12 3985 m_notifier = new wxGtkDataViewModelNotifier( gtk_model, model, this );
6e2e590f 3986
93763ad5 3987 model->AddNotifier( m_notifier );
1557c77b 3988
55fbde12 3989 gtk_tree_view_set_model( GTK_TREE_VIEW(m_treeview), GTK_TREE_MODEL(gtk_model) );
b9db5f30 3990
55fbde12
RR
3991 // unref in wxDataViewCtrlInternal
3992 // g_object_unref( gtk_model );
93763ad5 3993
239eaa41
RR
3994 return true;
3995}
790b137e 3996
15cac64f
RR
3997bool wxDataViewCtrl::EnableDragSource( const wxDataFormat &format )
3998{
3999 return m_internal->EnableDragSource( format );
4000}
4001
e4de825e
RR
4002bool wxDataViewCtrl::EnableDropTarget( const wxDataFormat &format )
4003{
4004 return m_internal->EnableDropTarget( format );
4005}
4006
fa28826d
RR
4007bool wxDataViewCtrl::AppendColumn( wxDataViewColumn *col )
4008{
4009 if (!wxDataViewCtrlBase::AppendColumn(col))
4010 return false;
93763ad5 4011
91a6c655
RR
4012 m_cols.Append( col );
4013
ad386793
RR
4014#ifdef __WXGTK26__
4015 if (!gtk_check_version(2,6,0))
4016 {
4017 if (gtk_tree_view_column_get_sizing( GTK_TREE_VIEW_COLUMN(col->GetGtkHandle()) ) !=
4018 GTK_TREE_VIEW_COLUMN_FIXED)
4019 gtk_tree_view_set_fixed_height_mode( GTK_TREE_VIEW(m_treeview), FALSE );
4020 }
4021#endif
4022
b9db5f30 4023 gtk_tree_view_append_column( GTK_TREE_VIEW(m_treeview),
91a6c655
RR
4024 GTK_TREE_VIEW_COLUMN(col->GetGtkHandle()) );
4025
4026 return true;
4027}
4028
736fe67c
RR
4029bool wxDataViewCtrl::PrependColumn( wxDataViewColumn *col )
4030{
4031 if (!wxDataViewCtrlBase::PrependColumn(col))
4032 return false;
4033
4034 m_cols.Insert( col );
4035
ad386793
RR
4036#ifdef __WXGTK26__
4037 if (!gtk_check_version(2,6,0))
4038 {
4039 if (gtk_tree_view_column_get_sizing( GTK_TREE_VIEW_COLUMN(col->GetGtkHandle()) ) !=
4040 GTK_TREE_VIEW_COLUMN_FIXED)
4041 gtk_tree_view_set_fixed_height_mode( GTK_TREE_VIEW(m_treeview), FALSE );
4042 }
4043#endif
4044
b9db5f30 4045 gtk_tree_view_insert_column( GTK_TREE_VIEW(m_treeview),
736fe67c
RR
4046 GTK_TREE_VIEW_COLUMN(col->GetGtkHandle()), 0 );
4047
4048 return true;
4049}
4050
19723525
RR
4051bool wxDataViewCtrl::InsertColumn( unsigned int pos, wxDataViewColumn *col )
4052{
4053 if (!wxDataViewCtrlBase::InsertColumn(pos,col))
4054 return false;
4055
4056 m_cols.Insert( pos, col );
4057
4058#ifdef __WXGTK26__
4059 if (!gtk_check_version(2,6,0))
4060 {
4061 if (gtk_tree_view_column_get_sizing( GTK_TREE_VIEW_COLUMN(col->GetGtkHandle()) ) !=
4062 GTK_TREE_VIEW_COLUMN_FIXED)
4063 gtk_tree_view_set_fixed_height_mode( GTK_TREE_VIEW(m_treeview), FALSE );
4064 }
4065#endif
4066
4067 gtk_tree_view_insert_column( GTK_TREE_VIEW(m_treeview),
4068 GTK_TREE_VIEW_COLUMN(col->GetGtkHandle()), pos );
4069
4070 return true;
4071}
4072
91a6c655
RR
4073unsigned int wxDataViewCtrl::GetColumnCount() const
4074{
4075 return m_cols.GetCount();
4076}
4077
4078wxDataViewColumn* wxDataViewCtrl::GetColumn( unsigned int pos ) const
4079{
4080 GtkTreeViewColumn *gtk_col = gtk_tree_view_get_column( GTK_TREE_VIEW(m_treeview), pos );
4081 if (!gtk_col)
4082 return NULL;
b9db5f30 4083
91a6c655 4084 wxDataViewColumnList::const_iterator iter;
ef11ea71 4085 for (iter = m_cols.begin(); iter != m_cols.end(); ++iter)
91a6c655
RR
4086 {
4087 wxDataViewColumn *col = *iter;
4088 if (GTK_TREE_VIEW_COLUMN(col->GetGtkHandle()) == gtk_col)
4089 {
4090 return col;
4091 }
4092 }
b9db5f30 4093
91a6c655
RR
4094 return NULL;
4095}
4096
4097bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn *column )
4098{
b9db5f30 4099 gtk_tree_view_remove_column( GTK_TREE_VIEW(m_treeview),
91a6c655
RR
4100 GTK_TREE_VIEW_COLUMN(column->GetGtkHandle()) );
4101
ef11ea71 4102 m_cols.DeleteObject( column );
fa28826d
RR
4103
4104 return true;
4105}
4106
91a6c655
RR
4107bool wxDataViewCtrl::ClearColumns()
4108{
4109 wxDataViewColumnList::iterator iter;
ef11ea71 4110 for (iter = m_cols.begin(); iter != m_cols.end(); ++iter)
91a6c655
RR
4111 {
4112 wxDataViewColumn *col = *iter;
b9db5f30 4113 gtk_tree_view_remove_column( GTK_TREE_VIEW(m_treeview),
91a6c655
RR
4114 GTK_TREE_VIEW_COLUMN(col->GetGtkHandle()) );
4115 }
b9db5f30 4116
ef11ea71 4117 m_cols.Clear();
b9db5f30 4118
91a6c655
RR
4119 return true;
4120}
4121
453091c2
RR
4122int wxDataViewCtrl::GetColumnPosition( const wxDataViewColumn *column ) const
4123{
aed836f3
RR
4124 GtkTreeViewColumn *gtk_column = GTK_TREE_VIEW_COLUMN(column->GetConstGtkHandle());
4125
4126 GList *list = gtk_tree_view_get_columns( GTK_TREE_VIEW(m_treeview) );
b9db5f30 4127
aed836f3 4128 gint pos = g_list_index( list, (gconstpointer) gtk_column );
b9db5f30 4129
aed836f3
RR
4130 g_list_free( list );
4131
4132 return pos;
453091c2
RR
4133}
4134
21f47fb9
RR
4135wxDataViewColumn *wxDataViewCtrl::GetSortingColumn() const
4136{
d32332aa 4137 return m_internal->GetDataViewSortColumn();
21f47fb9
RR
4138}
4139
f71d3ba4
RR
4140void wxDataViewCtrl::Expand( const wxDataViewItem & item )
4141{
4142 GtkTreeIter iter;
4143 iter.user_data = item.GetID();
4144 GtkTreePath *path = m_internal->get_path( &iter );
4145 gtk_tree_view_expand_row( GTK_TREE_VIEW(m_treeview), path, false );
4146 gtk_tree_path_free( path );
4147}
4148
4149void wxDataViewCtrl::Collapse( const wxDataViewItem & item )
4150{
4151 GtkTreeIter iter;
4152 iter.user_data = item.GetID();
4153 GtkTreePath *path = m_internal->get_path( &iter );
4154 gtk_tree_view_collapse_row( GTK_TREE_VIEW(m_treeview), path );
4155 gtk_tree_path_free( path );
739a8399
RR
4156}
4157
4158bool wxDataViewCtrl::IsExpanded( const wxDataViewItem & item ) const
4159{
4160 GtkTreeIter iter;
4161 iter.user_data = item.GetID();
4162 GtkTreePath *path = m_internal->get_path( &iter );
10ab6d4f 4163 bool res = gtk_tree_view_row_expanded( GTK_TREE_VIEW(m_treeview), path );
739a8399 4164 gtk_tree_path_free( path );
8c2654ce 4165
10ab6d4f 4166 return res;
f71d3ba4
RR
4167}
4168
fbda518c 4169wxDataViewItem wxDataViewCtrl::GetSelection() const
1e08ad10
RR
4170{
4171 GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
b9db5f30 4172
1e08ad10
RR
4173 if (m_windowStyle & wxDV_MULTIPLE)
4174 {
6848478c
RR
4175 // Report the first one
4176 GtkTreeModel *model;
4177 GList *list = gtk_tree_selection_get_selected_rows( selection, &model );
b9db5f30 4178
6848478c
RR
4179 if (list)
4180 {
4181 GtkTreePath *path = (GtkTreePath*) list->data;
4182 GtkTreeIter iter;
4183 m_internal->get_iter( &iter, path );
b9db5f30 4184
6848478c
RR
4185 // delete list
4186 g_list_foreach( list, (GFunc) gtk_tree_path_free, NULL );
4187 g_list_free( list );
b9db5f30 4188
6848478c
RR
4189 return wxDataViewItem( (void*) iter.user_data );
4190 }
1e08ad10
RR
4191 }
4192 else
4193 {
4194 GtkTreeIter iter;
4195 if (gtk_tree_selection_get_selected( selection, NULL, &iter ))
4196 {
9d52aad3 4197 wxDataViewItem item( (void*) iter.user_data );
1e08ad10
RR
4198 return item;
4199 }
4200 }
b9db5f30 4201
1e08ad10
RR
4202 return wxDataViewItem(0);
4203}
4204
718fd180
RR
4205int wxDataViewCtrl::GetSelections( wxDataViewItemArray & sel ) const
4206{
6848478c
RR
4207 sel.Clear();
4208
4209 GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
4210 if (HasFlag(wxDV_MULTIPLE))
4211 {
4212 GtkTreeModel *model;
4213 GList *list = gtk_tree_selection_get_selected_rows( selection, &model );
4214
4215 int count = 0;
4216 while (list)
4217 {
4218 GtkTreePath *path = (GtkTreePath*) list->data;
b9db5f30 4219
6848478c
RR
4220 GtkTreeIter iter;
4221 m_internal->get_iter( &iter, path );
4222
4223 sel.Add( wxDataViewItem( (void*) iter.user_data ) );
4224
4225 list = g_list_next( list );
4226 count++;
4227 }
4228
4229 // delete list
4230 g_list_foreach( list, (GFunc) gtk_tree_path_free, NULL );
4231 g_list_free( list );
4232
4233 return count;
4234 }
4235 else
4236 {
4237 GtkTreeModel *model;
4238 GtkTreeIter iter;
4239 gboolean has_selection = gtk_tree_selection_get_selected( selection, &model, &iter );
4240 if (has_selection)
4241 {
4242 sel.Add( wxDataViewItem( (void*) iter.user_data) );
4243 return 1;
4244 }
4245 }
4246
718fd180
RR
4247 return 0;
4248}
4249
4250void wxDataViewCtrl::SetSelections( const wxDataViewItemArray & sel )
4251{
6848478c 4252 GtkDisableSelectionEvents();
b9db5f30 4253
6848478c
RR
4254 GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
4255
4256 gtk_tree_selection_unselect_all( selection );
b9db5f30 4257
4219d8b0
RR
4258 wxDataViewItem last_parent;
4259
6848478c
RR
4260 size_t i;
4261 for (i = 0; i < sel.GetCount(); i++)
4262 {
4219d8b0
RR
4263 wxDataViewItem item = sel[i];
4264 wxDataViewItem parent = GetModel()->GetParent( item );
4265 if (parent)
4266 {
4267 if (parent != last_parent)
4268 ExpandAncestors(item);
4269 }
4270 last_parent = parent;
4271
6848478c 4272 GtkTreeIter iter;
0e50223f 4273 iter.stamp = m_internal->GetGtkModel()->stamp;
4219d8b0 4274 iter.user_data = (gpointer) item.GetID();
6848478c
RR
4275 gtk_tree_selection_select_iter( selection, &iter );
4276 }
b9db5f30 4277
6848478c 4278 GtkEnableSelectionEvents();
718fd180
RR
4279}
4280
4281void wxDataViewCtrl::Select( const wxDataViewItem & item )
4282{
4219d8b0
RR
4283 ExpandAncestors(item);
4284
6848478c
RR
4285 GtkDisableSelectionEvents();
4286
4287 GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
4288
4289 GtkTreeIter iter;
0e50223f 4290 iter.stamp = m_internal->GetGtkModel()->stamp;
6848478c
RR
4291 iter.user_data = (gpointer) item.GetID();
4292 gtk_tree_selection_select_iter( selection, &iter );
4293
4294 GtkEnableSelectionEvents();
718fd180
RR
4295}
4296
4297void wxDataViewCtrl::Unselect( const wxDataViewItem & item )
4298{
6848478c
RR
4299 GtkDisableSelectionEvents();
4300
4301 GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
4302
4303 GtkTreeIter iter;
0e50223f 4304 iter.stamp = m_internal->GetGtkModel()->stamp;
6848478c
RR
4305 iter.user_data = (gpointer) item.GetID();
4306 gtk_tree_selection_unselect_iter( selection, &iter );
4307
4308 GtkEnableSelectionEvents();
718fd180
RR
4309}
4310
4311bool wxDataViewCtrl::IsSelected( const wxDataViewItem & item ) const
4312{
6848478c
RR
4313 GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
4314
4315 GtkTreeIter iter;
0e50223f 4316 iter.stamp = m_internal->GetGtkModel()->stamp;
6848478c 4317 iter.user_data = (gpointer) item.GetID();
b9db5f30 4318
6848478c 4319 return gtk_tree_selection_iter_is_selected( selection, &iter );
718fd180
RR
4320}
4321
4322void wxDataViewCtrl::SelectAll()
4323{
6848478c 4324 GtkDisableSelectionEvents();
b9db5f30 4325
6848478c 4326 GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
b9db5f30 4327
6848478c 4328 gtk_tree_selection_select_all( selection );
b9db5f30 4329
6848478c 4330 GtkEnableSelectionEvents();
718fd180
RR
4331}
4332
4333void wxDataViewCtrl::UnselectAll()
4334{
6848478c 4335 GtkDisableSelectionEvents();
b9db5f30 4336
6848478c 4337 GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
b9db5f30 4338
6848478c 4339 gtk_tree_selection_unselect_all( selection );
b9db5f30 4340
6848478c 4341 GtkEnableSelectionEvents();
718fd180
RR
4342}
4343
7857346a 4344void wxDataViewCtrl::EnsureVisible(const wxDataViewItem& item,
4219d8b0 4345 const wxDataViewColumn *WXUNUSED(column))
718fd180 4346{
4219d8b0 4347 ExpandAncestors(item);
a881f34e 4348
6154212e
RR
4349 GtkTreeIter iter;
4350 iter.user_data = (gpointer) item.GetID();
4351 GtkTreePath *path = m_internal->get_path( &iter );
4352 gtk_tree_view_scroll_to_cell( GTK_TREE_VIEW(m_treeview), path, NULL, false, 0.0, 0.0 );
4353 gtk_tree_path_free( path );
718fd180
RR
4354}
4355
7857346a
VZ
4356void wxDataViewCtrl::HitTest(const wxPoint& WXUNUSED(point),
4357 wxDataViewItem& item,
4358 wxDataViewColumn *& column) const
66e09788
RR
4359{
4360 item = wxDataViewItem(0);
a87b466d 4361 column = NULL;
66e09788
RR
4362}
4363
7857346a
VZ
4364wxRect
4365wxDataViewCtrl::GetItemRect(const wxDataViewItem& WXUNUSED(item),
4366 const wxDataViewColumn *WXUNUSED(column)) const
66e09788
RR
4367{
4368 return wxRect();
4369}
4370
3b6280be
RR
4371void wxDataViewCtrl::DoSetExpanderColumn()
4372{
b9db5f30 4373 gtk_tree_view_set_expander_column( GTK_TREE_VIEW(m_treeview),
1b27b2bd 4374 GTK_TREE_VIEW_COLUMN( GetExpanderColumn()->GetGtkHandle() ) );
3b6280be
RR
4375}
4376
4377void wxDataViewCtrl::DoSetIndent()
4378{
4379}
4380
b086d55f
RR
4381void wxDataViewCtrl::GtkDisableSelectionEvents()
4382{
4383 GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
6848478c
RR
4384 g_signal_handlers_disconnect_by_func( selection,
4385 (gpointer) (wxdataview_selection_changed_callback), this);
b086d55f
RR
4386}
4387
4388void wxDataViewCtrl::GtkEnableSelectionEvents()
4389{
4390 GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
6848478c
RR
4391 g_signal_connect_after (selection, "changed",
4392 G_CALLBACK (wxdataview_selection_changed_callback), this);
b086d55f
RR
4393}
4394
b94db696
RR
4395// static
4396wxVisualAttributes
4397wxDataViewCtrl::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
4398{
4399 return GetDefaultAttributesFromGTKWidget(gtk_tree_view_new);
4400}
4401
6ff7eee7 4402
93763ad5 4403#endif
4ed7af08 4404 // !wxUSE_GENERICDATAVIEWCTRL
790b137e 4405
93763ad5 4406#endif
4ed7af08 4407 // wxUSE_DATAVIEWCTRL