1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk/dataview.cpp 
   3 // Purpose:     wxDataViewCtrl GTK+2 implementation 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 // For compilers that support precompilation, includes "wx.h". 
  11 #include "wx/wxprec.h" 
  13 #if wxUSE_DATAVIEWCTRL 
  15 #include "wx/dataview.h" 
  17 #ifndef wxUSE_GENERICDATAVIEWCTRL 
  21     #include "wx/dcclient.h" 
  25 #include "wx/stockitem.h" 
  26 #include "wx/calctrl.h" 
  27 #include "wx/popupwin.h" 
  31 #include "wx/gtk/private.h" 
  32 #include "wx/gtk/win_gtk.h" 
  34 #include <gobject/gvaluecollector.h> 
  35 #include <gtk/gtktreemodel.h> 
  36 #include <gtk/gtktreesortable.h> 
  37 #include <gtk/gtktreednd.h> 
  39 #include <gdk/gdkkeysyms.h> 
  41 //----------------------------------------------------------------------------- 
  43 //----------------------------------------------------------------------------- 
  45 //----------------------------------------------------------------------------- 
  47 //----------------------------------------------------------------------------- 
  49 class wxGtkTreeModelNode
; 
  51 int LINKAGEMODE 
wxGtkTreeModelNodeCmp( wxGtkTreeModelNode
* node1
, wxGtkTreeModelNode
* node2 
); 
  53 WX_DEFINE_SORTED_ARRAY( wxGtkTreeModelNode
*, wxGtkTreeModelNodes 
); 
  55 class wxGtkTreeModelNode
 
  58     wxGtkTreeModelNode( wxGtkTreeModelNode
* parent
, const wxDataViewItem 
&item
, 
  59       wxDataViewModel 
*model 
) : 
  60        m_children( wxGtkTreeModelNodeCmp 
) 
  69         size_t count 
= m_children
.GetCount(); 
  71         for (i 
= 0; i 
< count
; i
++) 
  73             wxGtkTreeModelNode 
*child 
= m_children
[i
]; 
  78     wxGtkTreeModelNode
* GetParent()  
  80     wxGtkTreeModelNodes 
&GetChildren()  
  81         { return m_children
; } 
  82     wxGtkTreeModelNode
* GetNthChild( unsigned int n 
)  
  83         { return m_children
.Item( n 
); } 
  84     unsigned int Add( wxGtkTreeModelNode
* child 
)  
  85         { return m_children
.Add( child 
); } 
  87     unsigned int GetChildCount() { return m_children
.GetCount(); } 
  89     wxDataViewItem 
&GetItem() { return m_item
; } 
  90     wxDataViewModel 
*GetModel() { return m_model
; } 
  92     bool HasChildren() { return m_hasChildren
; } 
  93     void SetHasChildren( bool has 
) { m_hasChildren 
= has
; } 
  96     wxGtkTreeModelNode  
*m_parent
; 
  97     wxGtkTreeModelNodes  m_children
;  
  98     wxDataViewItem       m_item
;  
 100     wxDataViewModel     
*m_model
; 
 103 int LINKAGEMODE 
wxGtkTreeModelNodeCmp( wxGtkTreeModelNode
* node1
, wxGtkTreeModelNode
* node2 
) 
 105     return node1
->GetModel()->Compare( node1
->GetItem(), node2
->GetItem() ); 
 110 typedef struct _GtkWxTreeModel       GtkWxTreeModel
; 
 113 class wxDataViewCtrlInternal
 
 116     wxDataViewCtrlInternal( wxDataViewCtrl 
*owner
, wxDataViewModel 
*wx_model
, GtkWxTreeModel 
*owner 
); 
 117     ~wxDataViewCtrlInternal(); 
 119     gboolean 
get_iter( GtkTreeIter 
*iter
, GtkTreePath 
*path 
); 
 120     GtkTreePath 
*get_path( GtkTreeIter 
*iter
); 
 121     GtkTreePath 
*get_path_safe( GtkTreeIter 
*iter
); 
 122     gboolean 
iter_next( GtkTreeIter 
*iter 
); 
 123     gboolean 
iter_children( GtkTreeIter 
*iter
, GtkTreeIter 
*parent
); 
 124     gboolean 
iter_has_child( GtkTreeIter 
*iter 
); 
 125     gint 
iter_n_children( GtkTreeIter 
*iter 
); 
 126     gboolean 
iter_nth_child( GtkTreeIter 
*iter
, GtkTreeIter 
*parent
, gint n 
); 
 127     gboolean 
iter_parent( GtkTreeIter 
*iter
, GtkTreeIter 
*child 
); 
 129     wxDataViewModel
* GetDataViewModel() { return m_wx_model
; } 
 130     GtkWxTreeModel
* GetOwner()          { return m_gtk_model
; } 
 132     bool ItemAdded( const wxDataViewItem 
&parent
, const wxDataViewItem 
&item 
); 
 133     bool ItemDeleted( const wxDataViewItem 
&item 
); 
 137     wxGtkTreeModelNode 
*FindNode( const wxDataViewItem 
&item 
); 
 138     wxGtkTreeModelNode 
*FindNode( GtkTreeIter 
*iter 
); 
 139     void BuildBranch( wxGtkTreeModelNode 
*branch 
); 
 142     wxGtkTreeModelNode   
*m_root
; 
 143     wxDataViewModel      
*m_wx_model
; 
 144     GtkWxTreeModel       
*m_gtk_model
; 
 145     wxDataViewCtrl       
*m_owner
; 
 148 //----------------------------------------------------------------------------- 
 150 //----------------------------------------------------------------------------- 
 152 extern bool   g_blockEventsOnDrag
; 
 154 //----------------------------------------------------------------------------- 
 155 // define new GTK+ class wxGtkTreeModel 
 156 //----------------------------------------------------------------------------- 
 160 #define GTK_TYPE_WX_TREE_MODEL               (gtk_wx_tree_model_get_type ()) 
 161 #define GTK_WX_TREE_MODEL(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WX_TREE_MODEL, GtkWxTreeModel)) 
 162 #define GTK_WX_TREE_MODEL_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WX_TREE_MODEL, GtkWxTreeModelClass)) 
 163 #define GTK_IS_WX_TREE_MODEL(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WX_TREE_MODEL)) 
 164 #define GTK_IS_WX_TREE_MODEL_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WX_TREE_MODEL)) 
 165 #define GTK_WX_TREE_MODEL_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WX_TREE_MODEL, GtkWxTreeModelClass)) 
 167 GType         
gtk_wx_tree_model_get_type         (void); 
 169 typedef struct _GtkWxTreeModelClass  GtkWxTreeModelClass
; 
 171 struct _GtkWxTreeModel
 
 177   wxDataViewCtrlInternal 
*internal
; 
 180 struct _GtkWxTreeModelClass
 
 182   GObjectClass list_parent_class
; 
 185 static GtkWxTreeModel 
*wxgtk_tree_model_new          (void); 
 186 static void         wxgtk_tree_model_init            (GtkWxTreeModel       
*tree_model
); 
 187 static void         wxgtk_tree_model_class_init      (GtkWxTreeModelClass  
*klass
); 
 188 static void         wxgtk_tree_model_tree_model_init (GtkTreeModelIface    
*iface
); 
 189 static void         wxgtk_tree_model_sortable_init   (GtkTreeSortableIface 
*iface
); 
 190 static void         wxgtk_tree_model_finalize        (GObject           
*object
); 
 191 static GtkTreeModelFlags 
wxgtk_tree_model_get_flags  (GtkTreeModel      
*tree_model
); 
 192 static gint         
wxgtk_tree_model_get_n_columns   (GtkTreeModel      
*tree_model
); 
 193 static GType        
wxgtk_tree_model_get_column_type (GtkTreeModel      
*tree_model
, 
 195 static gboolean     
wxgtk_tree_model_get_iter        (GtkTreeModel      
*tree_model
, 
 198 static GtkTreePath 
*wxgtk_tree_model_get_path        (GtkTreeModel      
*tree_model
, 
 200 static GtkTreePath 
*wxgtk_tree_model_get_path_safe   (GtkTreeModel      
*tree_model
, 
 202 static void         wxgtk_tree_model_get_value       (GtkTreeModel      
*tree_model
, 
 206 static gboolean     
wxgtk_tree_model_iter_next       (GtkTreeModel      
*tree_model
, 
 208 static gboolean     
wxgtk_tree_model_iter_children   (GtkTreeModel      
*tree_model
, 
 210                                                       GtkTreeIter       
*parent
); 
 211 static gboolean     
wxgtk_tree_model_iter_has_child  (GtkTreeModel      
*tree_model
, 
 213 static gint         
wxgtk_tree_model_iter_n_children (GtkTreeModel      
*tree_model
, 
 215 static gboolean     
wxgtk_tree_model_iter_nth_child  (GtkTreeModel      
*tree_model
, 
 219 static gboolean     
wxgtk_tree_model_iter_parent     (GtkTreeModel      
*tree_model
, 
 224 static gboolean 
wxgtk_tree_model_get_sort_column_id    (GtkTreeSortable       
*sortable
, 
 225                                                       gint                     
*sort_column_id
, 
 227 static void     wxgtk_tree_model_set_sort_column_id    (GtkTreeSortable       
*sortable
, 
 230 static void     wxgtk_tree_model_set_sort_func         (GtkTreeSortable       
*sortable
, 
 232                                                       GtkTreeIterCompareFunc    func
, 
 234                                                       GtkDestroyNotify          destroy
); 
 235 static void     wxgtk_tree_model_set_default_sort_func (GtkTreeSortable       
*sortable
, 
 236                                                       GtkTreeIterCompareFunc    func
, 
 238                                                       GtkDestroyNotify          destroy
); 
 239 static gboolean 
wxgtk_tree_model_has_default_sort_func (GtkTreeSortable       
*sortable
); 
 243 static GObjectClass 
*list_parent_class 
= NULL
; 
 246 gtk_wx_tree_model_get_type (void) 
 248     static GType tree_model_type 
= 0; 
 250     if (!tree_model_type
) 
 252         const GTypeInfo tree_model_info 
= 
 254             sizeof (GtkWxTreeModelClass
), 
 255             NULL
,   /* base_init */ 
 256             NULL
,   /* base_finalize */ 
 257             (GClassInitFunc
) wxgtk_tree_model_class_init
, 
 258             NULL
,   /* class_finalize */ 
 259             NULL
,   /* class_data */ 
 260             sizeof (GtkWxTreeModel
), 
 262             (GInstanceInitFunc
) wxgtk_tree_model_init
, 
 265         static const GInterfaceInfo tree_model_iface_info 
= 
 267             (GInterfaceInitFunc
) wxgtk_tree_model_tree_model_init
, 
 272         static const GInterfaceInfo sortable_iface_info 
= 
 274             (GInterfaceInitFunc
) wxgtk_tree_model_sortable_init
, 
 279         tree_model_type 
= g_type_register_static (G_TYPE_OBJECT
, "GtkWxTreeModel", 
 280                                                 &tree_model_info
, (GTypeFlags
)0 ); 
 282         g_type_add_interface_static (tree_model_type
, 
 284                                      &tree_model_iface_info
); 
 285         g_type_add_interface_static (tree_model_type
, 
 286                                      GTK_TYPE_TREE_SORTABLE
, 
 287                                      &sortable_iface_info
); 
 290     return tree_model_type
; 
 293 static GtkWxTreeModel 
* 
 294 wxgtk_tree_model_new(void) 
 296     GtkWxTreeModel 
*retval 
= (GtkWxTreeModel 
*) g_object_new (GTK_TYPE_WX_TREE_MODEL
, NULL
); 
 301 wxgtk_tree_model_class_init (GtkWxTreeModelClass 
*klass
) 
 303     list_parent_class 
= (GObjectClass
*) g_type_class_peek_parent (klass
); 
 304     GObjectClass 
*object_class 
= (GObjectClass
*) klass
; 
 305     object_class
->finalize 
= wxgtk_tree_model_finalize
; 
 309 wxgtk_tree_model_tree_model_init (GtkTreeModelIface 
*iface
) 
 311     iface
->get_flags 
= wxgtk_tree_model_get_flags
; 
 312     iface
->get_n_columns 
= wxgtk_tree_model_get_n_columns
; 
 313     iface
->get_column_type 
= wxgtk_tree_model_get_column_type
; 
 314     iface
->get_iter 
= wxgtk_tree_model_get_iter
; 
 315     iface
->get_path 
= wxgtk_tree_model_get_path
; 
 316     iface
->get_value 
= wxgtk_tree_model_get_value
; 
 317     iface
->iter_next 
= wxgtk_tree_model_iter_next
; 
 318     iface
->iter_children 
= wxgtk_tree_model_iter_children
; 
 319     iface
->iter_has_child 
= wxgtk_tree_model_iter_has_child
; 
 320     iface
->iter_n_children 
= wxgtk_tree_model_iter_n_children
; 
 321     iface
->iter_nth_child 
= wxgtk_tree_model_iter_nth_child
; 
 322     iface
->iter_parent 
= wxgtk_tree_model_iter_parent
; 
 326 wxgtk_tree_model_sortable_init (GtkTreeSortableIface 
*iface
) 
 328     iface
->get_sort_column_id 
= wxgtk_tree_model_get_sort_column_id
; 
 329     iface
->set_sort_column_id 
= wxgtk_tree_model_set_sort_column_id
; 
 330     iface
->set_sort_func 
= wxgtk_tree_model_set_sort_func
; 
 331     iface
->set_default_sort_func 
= wxgtk_tree_model_set_default_sort_func
; 
 332     iface
->has_default_sort_func 
= wxgtk_tree_model_has_default_sort_func
; 
 336 wxgtk_tree_model_init (GtkWxTreeModel 
*tree_model
) 
 338     tree_model
->internal 
= NULL
; 
 339     tree_model
->stamp 
= g_random_int(); 
 343 wxgtk_tree_model_finalize (GObject 
*object
) 
 346     (* list_parent_class
->finalize
) (object
); 
 351 //----------------------------------------------------------------------------- 
 352 // implement callbacks from wxGtkTreeModel class by letting 
 353 // them call the methods of wxWidgets' wxDataViewModel 
 354 //----------------------------------------------------------------------------- 
 356 static GtkTreeModelFlags
 
 357 wxgtk_tree_model_get_flags (GtkTreeModel 
*tree_model
) 
 359     g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (tree_model
), (GtkTreeModelFlags
)0 ); 
 361     return GTK_TREE_MODEL_ITERS_PERSIST
; 
 365 wxgtk_tree_model_get_n_columns (GtkTreeModel 
*tree_model
) 
 367     GtkWxTreeModel 
*wxtree_model 
= (GtkWxTreeModel 
*) tree_model
; 
 368     g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model
), 0); 
 370     return wxtree_model
->internal
->GetDataViewModel()->GetColumnCount(); 
 374 wxgtk_tree_model_get_column_type (GtkTreeModel 
*tree_model
, 
 377     GtkWxTreeModel 
*wxtree_model 
= (GtkWxTreeModel 
*) tree_model
; 
 378     g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model
), G_TYPE_INVALID
); 
 380     GType gtype 
= G_TYPE_INVALID
; 
 382     wxString wxtype 
= wxtree_model
->internal
->GetDataViewModel()->GetColumnType( (unsigned int) index 
); 
 384     if (wxtype 
== wxT("string")) 
 385         gtype 
= G_TYPE_STRING
; 
 388         wxFAIL_MSG( _T("non-string columns not supported yet") ); 
 395 wxgtk_tree_model_get_iter (GtkTreeModel 
*tree_model
, 
 399     GtkWxTreeModel 
*wxtree_model 
= (GtkWxTreeModel 
*) tree_model
; 
 400     g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model
), FALSE
); 
 401     g_return_val_if_fail (gtk_tree_path_get_depth (path
) > 0, FALSE
); 
 403     return wxtree_model
->internal
->get_iter( iter
, path 
); 
 407 wxgtk_tree_model_get_path (GtkTreeModel 
*tree_model
, 
 410     GtkWxTreeModel 
*wxtree_model 
= (GtkWxTreeModel 
*) tree_model
; 
 411     g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model
), NULL
); 
 412     g_return_val_if_fail (iter
->stamp 
== GTK_WX_TREE_MODEL (wxtree_model
)->stamp
, NULL
); 
 414     return wxtree_model
->internal
->get_path( iter 
); 
 418 wxgtk_tree_model_get_path_safe (GtkTreeModel 
*tree_model
, 
 421     GtkWxTreeModel 
*wxtree_model 
= (GtkWxTreeModel 
*) tree_model
; 
 422     g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model
), NULL
); 
 423     g_return_val_if_fail (iter
->stamp 
== GTK_WX_TREE_MODEL (wxtree_model
)->stamp
, NULL
); 
 425     return wxtree_model
->internal
->get_path_safe( iter 
); 
 429 wxgtk_tree_model_get_value (GtkTreeModel 
*tree_model
, 
 434     GtkWxTreeModel 
*wxtree_model 
= (GtkWxTreeModel 
*) tree_model
; 
 435     g_return_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model
) ); 
 437     wxDataViewModel 
*model 
= wxtree_model
->internal
->GetDataViewModel(); 
 438     wxString mtype 
= model
->GetColumnType( (unsigned int) column 
); 
 439     if (mtype 
== wxT("string")) 
 442         g_value_init( value
, G_TYPE_STRING 
); 
 443         wxDataViewItem 
item( (void*) iter
->user_data 
); 
 444         model
->GetValue( variant
, item
, (unsigned int) column 
); 
 446         g_value_set_string( value
, variant
.GetString().utf8_str() ); 
 450         wxFAIL_MSG( _T("non-string columns not supported yet") ); 
 455 wxgtk_tree_model_iter_next (GtkTreeModel  
*tree_model
, 
 458     GtkWxTreeModel 
*wxtree_model 
= (GtkWxTreeModel 
*) tree_model
; 
 459     g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model
), FALSE
); 
 460     g_return_val_if_fail (wxtree_model
->stamp 
== iter
->stamp
, FALSE
); 
 462     return wxtree_model
->internal
->iter_next( iter 
); 
 466 wxgtk_tree_model_iter_children (GtkTreeModel 
*tree_model
, 
 470     GtkWxTreeModel 
*wxtree_model 
= (GtkWxTreeModel 
*) tree_model
; 
 471     g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model
), FALSE
); 
 472     g_return_val_if_fail (wxtree_model
->stamp 
== parent
->stamp
, FALSE
); 
 474     return wxtree_model
->internal
->iter_children( iter
, parent 
); 
 478 wxgtk_tree_model_iter_has_child (GtkTreeModel 
*tree_model
, 
 481     GtkWxTreeModel 
*wxtree_model 
= (GtkWxTreeModel 
*) tree_model
; 
 482     g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model
), FALSE
); 
 483     g_return_val_if_fail (wxtree_model
->stamp 
== iter
->stamp
, FALSE
); 
 485     return wxtree_model
->internal
->iter_has_child( iter 
); 
 489 wxgtk_tree_model_iter_n_children (GtkTreeModel 
*tree_model
, 
 492     GtkWxTreeModel 
*wxtree_model 
= (GtkWxTreeModel 
*) tree_model
; 
 493     g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model
), FALSE
); 
 494     g_return_val_if_fail (wxtree_model
->stamp 
== iter
->stamp
, 0); 
 496     return wxtree_model
->internal
->iter_n_children( iter 
); 
 500 wxgtk_tree_model_iter_nth_child (GtkTreeModel 
*tree_model
, 
 505     GtkWxTreeModel 
*wxtree_model 
= (GtkWxTreeModel 
*) tree_model
; 
 506     g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model
), FALSE
); 
 508     return wxtree_model
->internal
->iter_nth_child( iter
, parent
, n 
); 
 512 wxgtk_tree_model_iter_parent (GtkTreeModel 
*tree_model
, 
 516     GtkWxTreeModel 
*wxtree_model 
= (GtkWxTreeModel 
*) tree_model
; 
 517     g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model
), FALSE
); 
 518     g_return_val_if_fail (wxtree_model
->stamp 
== child
->stamp
, FALSE
); 
 520     return wxtree_model
->internal
->iter_parent( iter
, child 
); 
 524 gboolean 
wxgtk_tree_model_get_sort_column_id    (GtkTreeSortable        
*sortable
, 
 525                                                       gint                     
*sort_column_id
, 
 528     GtkWxTreeModel 
*tree_model 
= (GtkWxTreeModel 
*) sortable
; 
 530     g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (sortable
), FALSE
); 
 533         *sort_column_id 
= tree_model
->internal
->GetDataViewModel()->GetSortingColumn(); 
 537         bool ascending 
= tree_model
->internal
->GetDataViewModel()->GetSortOrderAscending(); 
 539             *order 
= GTK_SORT_ASCENDING
; 
 541             *order 
= GTK_SORT_DESCENDING
; 
 547 void     wxgtk_tree_model_set_sort_column_id    (GtkTreeSortable        
*sortable
, 
 551     GtkWxTreeModel 
*tree_model 
= (GtkWxTreeModel 
*) sortable
; 
 552     g_return_if_fail (GTK_IS_WX_TREE_MODEL (sortable
) ); 
 554     // TODO check for equality 
 558     gtk_tree_sortable_sort_column_changed (sortable
); 
 560     tree_model
->internal
->GetDataViewModel()->SetSortingColumn( sort_column_id 
); 
 562     bool ascending 
= TRUE
; 
 563     if (order 
!= GTK_SORT_ASCENDING
) 
 565     tree_model
->internal
->GetDataViewModel()->SetSortOrderAscending( ascending 
); 
 567     tree_model
->internal
->GetDataViewModel()->Resort(); 
 570 void     wxgtk_tree_model_set_sort_func         (GtkTreeSortable        
*sortable
, 
 572                                                       GtkTreeIterCompareFunc    func
, 
 574                                                       GtkDestroyNotify          destroy
) 
 576     g_return_if_fail (GTK_IS_WX_TREE_MODEL (sortable
) ); 
 577     g_return_if_fail (func 
!= NULL
); 
 580 void     wxgtk_tree_model_set_default_sort_func (GtkTreeSortable        
*sortable
, 
 581                                                       GtkTreeIterCompareFunc    func
, 
 583                                                       GtkDestroyNotify          destroy
) 
 585     g_return_if_fail (GTK_IS_WX_TREE_MODEL (sortable
) ); 
 586     g_return_if_fail (func 
!= NULL
); 
 588     wxPrintf( "wxgtk_tree_model_set_default_sort_func\n" ); 
 591 gboolean 
wxgtk_tree_model_has_default_sort_func (GtkTreeSortable        
*sortable
) 
 596 //----------------------------------------------------------------------------- 
 597 // define new GTK+ class wxGtkRendererRenderer 
 598 //----------------------------------------------------------------------------- 
 602 #define GTK_TYPE_WX_CELL_RENDERER               (gtk_wx_cell_renderer_get_type ()) 
 603 #define GTK_WX_CELL_RENDERER(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRenderer)) 
 604 #define GTK_WX_CELL_RENDERER_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRendererClass)) 
 605 #define GTK_IS_WX_CELL_RENDERER(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WX_CELL_RENDERER)) 
 606 #define GTK_IS_WX_CELL_RENDERER_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WX_CELL_RENDERER)) 
 607 #define GTK_WX_CELL_RENDERER_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRendererClass)) 
 609 GType            
gtk_wx_cell_renderer_get_type (void); 
 611 typedef struct _GtkWxCellRenderer GtkWxCellRenderer
; 
 612 typedef struct _GtkWxCellRendererClass GtkWxCellRendererClass
; 
 614 struct _GtkWxCellRenderer
 
 616   GtkCellRenderer parent
; 
 619   wxDataViewCustomRenderer 
*cell
; 
 623 struct _GtkWxCellRendererClass
 
 625   GtkCellRendererClass cell_parent_class
; 
 629 static GtkCellRenderer 
*gtk_wx_cell_renderer_new   (void); 
 630 static void gtk_wx_cell_renderer_init ( 
 631                         GtkWxCellRenderer      
*cell 
); 
 632 static void gtk_wx_cell_renderer_class_init( 
 633                         GtkWxCellRendererClass 
*klass 
); 
 634 static void gtk_wx_cell_renderer_finalize ( 
 636 static void gtk_wx_cell_renderer_get_size ( 
 637                         GtkCellRenderer         
*cell
, 
 639                         GdkRectangle            
*rectangle
, 
 644 static void gtk_wx_cell_renderer_render ( 
 645                         GtkCellRenderer         
*cell
, 
 648                         GdkRectangle            
*background_area
, 
 649                         GdkRectangle            
*cell_area
, 
 650                         GdkRectangle            
*expose_area
, 
 651                         GtkCellRendererState     flags 
); 
 652 static gboolean 
gtk_wx_cell_renderer_activate( 
 653                         GtkCellRenderer         
*cell
, 
 657                         GdkRectangle            
*background_area
, 
 658                         GdkRectangle            
*cell_area
, 
 659                         GtkCellRendererState     flags 
); 
 660 static GtkCellEditable 
*gtk_wx_cell_renderer_start_editing( 
 661                         GtkCellRenderer         
*cell
, 
 665                         GdkRectangle            
*background_area
, 
 666                         GdkRectangle            
*cell_area
, 
 667                         GtkCellRendererState     flags 
); 
 670 static GObjectClass 
*cell_parent_class 
= NULL
; 
 675 gtk_wx_cell_renderer_get_type (void) 
 677     static GType cell_wx_type 
= 0; 
 681         const GTypeInfo cell_wx_info 
= 
 683             sizeof (GtkWxCellRendererClass
), 
 684             NULL
, /* base_init */ 
 685             NULL
, /* base_finalize */ 
 686             (GClassInitFunc
) gtk_wx_cell_renderer_class_init
, 
 687             NULL
, /* class_finalize */ 
 688             NULL
, /* class_data */ 
 689             sizeof (GtkWxCellRenderer
), 
 691             (GInstanceInitFunc
) gtk_wx_cell_renderer_init
, 
 694         cell_wx_type 
= g_type_register_static( GTK_TYPE_CELL_RENDERER
, 
 695             "GtkWxCellRenderer", &cell_wx_info
, (GTypeFlags
)0 ); 
 702 gtk_wx_cell_renderer_init (GtkWxCellRenderer 
*cell
) 
 705     cell
->last_click 
= 0; 
 709 gtk_wx_cell_renderer_class_init (GtkWxCellRendererClass 
*klass
) 
 711     GObjectClass 
*object_class 
= G_OBJECT_CLASS (klass
); 
 712     GtkCellRendererClass 
*cell_class 
= GTK_CELL_RENDERER_CLASS (klass
); 
 714     cell_parent_class 
= (GObjectClass
*) g_type_class_peek_parent (klass
); 
 716     object_class
->finalize 
= gtk_wx_cell_renderer_finalize
; 
 718     cell_class
->get_size 
= gtk_wx_cell_renderer_get_size
; 
 719     cell_class
->render 
= gtk_wx_cell_renderer_render
; 
 720     cell_class
->activate 
= gtk_wx_cell_renderer_activate
; 
 721     cell_class
->start_editing 
= gtk_wx_cell_renderer_start_editing
; 
 725 gtk_wx_cell_renderer_finalize (GObject 
*object
) 
 728     (* G_OBJECT_CLASS (cell_parent_class
)->finalize
) (object
); 
 732 gtk_wx_cell_renderer_new (void) 
 734     return (GtkCellRenderer
*) g_object_new (GTK_TYPE_WX_CELL_RENDERER
, NULL
); 
 739 static GtkCellEditable 
*gtk_wx_cell_renderer_start_editing( 
 740                         GtkCellRenderer         
*renderer
, 
 744                         GdkRectangle            
*background_area
, 
 745                         GdkRectangle            
*cell_area
, 
 746                         GtkCellRendererState     flags 
) 
 748     GtkWxCellRenderer 
*wxrenderer 
= (GtkWxCellRenderer 
*) renderer
; 
 749     wxDataViewCustomRenderer 
*cell 
= wxrenderer
->cell
; 
 750     if (!cell
->HasEditorCtrl()) 
 754     gtk_wx_cell_renderer_get_size (renderer
, widget
, cell_area
, 
 760     rect
.x 
+= cell_area
->x
; 
 761     rect
.y 
+= cell_area
->y
; 
 762 //    rect.width  -= renderer->xpad * 2; 
 763 //    rect.height -= renderer->ypad * 2; 
 765 //    wxRect renderrect( rect.x, rect.y, rect.width, rect.height ); 
 766     wxRect 
renderrect( cell_area
->x
, cell_area
->y
, cell_area
->width
, cell_area
->height 
); 
 768     GtkTreePath 
*treepath 
= gtk_tree_path_new_from_string( path 
); 
 770     cell
->GetOwner()->GetOwner()->GtkGetInternal()->get_iter( &iter
, treepath 
); 
 771     wxDataViewItem 
item( (void*) iter
.user_data 
); 
 772     gtk_tree_path_free( treepath 
); 
 774     cell
->StartEditing( item
, renderrect 
); 
 780 gtk_wx_cell_renderer_get_size (GtkCellRenderer 
*renderer
, 
 782                                GdkRectangle    
*cell_area
, 
 788     GtkWxCellRenderer 
*wxrenderer 
= (GtkWxCellRenderer 
*) renderer
; 
 789     wxDataViewCustomRenderer 
*cell 
= wxrenderer
->cell
; 
 791     wxSize size 
= cell
->GetSize(); 
 793     gint calc_width  
= (gint
) renderer
->xpad 
* 2 + size
.x
; 
 794     gint calc_height 
= (gint
) renderer
->ypad 
* 2 + size
.y
; 
 801     if (cell_area 
&& size
.x 
> 0 && size
.y 
> 0) 
 805             *x_offset 
= (gint
)((renderer
->xalign 
* 
 806                                (cell_area
->width 
- calc_width 
- 2 * renderer
->xpad
))); 
 807             *x_offset 
= MAX (*x_offset
, 0) + renderer
->xpad
; 
 811             *y_offset 
= (gint
)((renderer
->yalign 
* 
 812                                (cell_area
->height 
- calc_height 
- 2 * renderer
->ypad
))); 
 813             *y_offset 
= MAX (*y_offset
, 0) + renderer
->ypad
; 
 821         *height 
= calc_height
; 
 825 gtk_wx_cell_renderer_render (GtkCellRenderer      
*renderer
, 
 828                              GdkRectangle         
*background_area
, 
 829                              GdkRectangle         
*cell_area
, 
 830                              GdkRectangle         
*expose_area
, 
 831                              GtkCellRendererState  flags
) 
 834     GtkWxCellRenderer 
*wxrenderer 
= (GtkWxCellRenderer 
*) renderer
; 
 835     wxDataViewCustomRenderer 
*cell 
= wxrenderer
->cell
; 
 838     gtk_wx_cell_renderer_get_size (renderer
, widget
, cell_area
, 
 844     rect
.x 
+= cell_area
->x
; 
 845     rect
.y 
+= cell_area
->y
; 
 846     rect
.width  
-= renderer
->xpad 
* 2; 
 847     rect
.height 
-= renderer
->ypad 
* 2; 
 850     if (gdk_rectangle_intersect (expose_area
, &rect
, &dummy
)) 
 852         wxRect 
renderrect( rect
.x
, rect
.y
, rect
.width
, rect
.height 
); 
 853         wxWindowDC
* dc 
= (wxWindowDC
*) cell
->GetDC(); 
 854         if (dc
->m_window 
== NULL
) 
 856             dc
->m_window 
= window
; 
 861         if (flags 
& GTK_CELL_RENDERER_SELECTED
) 
 862             state 
|= wxDATAVIEW_CELL_SELECTED
; 
 863         if (flags 
& GTK_CELL_RENDERER_PRELIT
) 
 864             state 
|= wxDATAVIEW_CELL_PRELIT
; 
 865         if (flags 
& GTK_CELL_RENDERER_INSENSITIVE
) 
 866             state 
|= wxDATAVIEW_CELL_INSENSITIVE
; 
 867         if (flags 
& GTK_CELL_RENDERER_INSENSITIVE
) 
 868             state 
|= wxDATAVIEW_CELL_INSENSITIVE
; 
 869         if (flags 
& GTK_CELL_RENDERER_FOCUSED
) 
 870             state 
|= wxDATAVIEW_CELL_FOCUSED
; 
 871         cell
->Render( renderrect
, dc
, state 
); 
 876 gtk_wx_cell_renderer_activate( 
 877                         GtkCellRenderer         
*renderer
, 
 881                         GdkRectangle            
*background_area
, 
 882                         GdkRectangle            
*cell_area
, 
 883                         GtkCellRendererState     flags 
) 
 885     GtkWxCellRenderer 
*wxrenderer 
= (GtkWxCellRenderer 
*) renderer
; 
 886     wxDataViewCustomRenderer 
*cell 
= wxrenderer
->cell
; 
 889     gtk_wx_cell_renderer_get_size (renderer
, widget
, cell_area
, 
 895     rect
.x 
+= cell_area
->x
; 
 896     rect
.y 
+= cell_area
->y
; 
 897     rect
.width  
-= renderer
->xpad 
* 2; 
 898     rect
.height 
-= renderer
->ypad 
* 2; 
 900     wxRect 
renderrect( rect
.x
, rect
.y
, rect
.width
, rect
.height 
); 
 902     wxDataViewModel 
*model 
= cell
->GetOwner()->GetOwner()->GetModel(); 
 904     GtkTreePath 
*treepath 
= gtk_tree_path_new_from_string( path 
); 
 907     gtk_tree_path_free( treepath 
); 
 909     unsigned int model_col 
= cell
->GetOwner()->GetModelColumn(); 
 915         // activated by <ENTER> 
 916         if (cell
->Activate( renderrect
, model
, item
, model_col 
)) 
 921     else if (event
->type 
== GDK_BUTTON_PRESS
) 
 923         GdkEventButton 
*button_event 
= (GdkEventButton
*) event
; 
 924         wxPoint 
pt( ((int) button_event
->x
) - renderrect
.x
, 
 925                     ((int) button_event
->y
) - renderrect
.y 
); 
 928         if (button_event
->button 
== 1) 
 930             if (cell
->LeftClick( pt
, renderrect
, model
, item
, model_col 
)) 
 932             // TODO: query system double-click time 
 933             if (button_event
->time 
- wxrenderer
->last_click 
< 400) 
 934                 if (cell
->Activate( renderrect
, model
, item
, model_col 
)) 
 937         if (button_event
->button 
== 3) 
 939             if (cell
->RightClick( pt
, renderrect
, model
, item
, model_col 
)) 
 943         wxrenderer
->last_click 
= button_event
->time
; 
 951 // --------------------------------------------------------- 
 952 // wxGtkDataViewModelNotifier 
 953 // --------------------------------------------------------- 
 955 class wxGtkDataViewModelNotifier
: public wxDataViewModelNotifier
 
 958     wxGtkDataViewModelNotifier( GtkWxTreeModel  
*wxgtk_model
, 
 959                                 wxDataViewModel 
*wx_model
, 
 960                                 wxDataViewCtrl  
*ctrl 
); 
 961     ~wxGtkDataViewModelNotifier(); 
 963     virtual bool ItemAdded( const wxDataViewItem 
&parent
, const wxDataViewItem 
&item 
); 
 964     virtual bool ItemDeleted( const wxDataViewItem 
&item 
); 
 965     virtual bool ItemChanged( const wxDataViewItem 
&item 
); 
 966     virtual bool ValueChanged( const wxDataViewItem 
&item
, unsigned int col 
); 
 967     virtual bool Cleared(); 
 969     GtkWxTreeModel      
*m_wxgtk_model
; 
 970     wxDataViewModel     
*m_wx_model
; 
 971     wxDataViewCtrl      
*m_owner
; 
 974 // --------------------------------------------------------- 
 975 // wxGtkDataViewListModelNotifier 
 976 // --------------------------------------------------------- 
 978 wxGtkDataViewModelNotifier::wxGtkDataViewModelNotifier( 
 979     GtkWxTreeModel
* wxgtk_model
, wxDataViewModel 
*wx_model
, 
 980     wxDataViewCtrl 
*ctrl 
) 
 982     m_wxgtk_model 
= wxgtk_model
; 
 983     m_wx_model 
= wx_model
; 
 987 wxGtkDataViewModelNotifier::~wxGtkDataViewModelNotifier() 
 990     m_wxgtk_model 
= NULL
; 
 993 bool wxGtkDataViewModelNotifier::ItemAdded( const wxDataViewItem 
&parent
, const wxDataViewItem 
&item 
) 
 995     m_owner
->GtkGetInternal()->ItemAdded( parent
, item 
); 
 998     iter
.stamp 
= m_wxgtk_model
->stamp
; 
 999     iter
.user_data 
= (gpointer
) item
.GetID(); 
1001     GtkTreePath 
*path 
= wxgtk_tree_model_get_path(  
1002         GTK_TREE_MODEL(m_wxgtk_model
), &iter 
); 
1003     gtk_tree_model_row_inserted(  
1004         GTK_TREE_MODEL(m_wxgtk_model
), path
, &iter
); 
1005     gtk_tree_path_free (path
); 
1010 bool wxGtkDataViewModelNotifier::ItemDeleted( const wxDataViewItem 
&item 
) 
1013     iter
.stamp 
= m_wxgtk_model
->stamp
; 
1014     iter
.user_data 
= (gpointer
) item
.GetID(); 
1016     GtkTreePath 
*path 
= wxgtk_tree_model_get_path_safe(  
1017         GTK_TREE_MODEL(m_wxgtk_model
), &iter 
); 
1018     gtk_tree_model_row_deleted( 
1019         GTK_TREE_MODEL(m_wxgtk_model
), path 
); 
1020     gtk_tree_path_free (path
); 
1022     m_owner
->GtkGetInternal()->ItemDeleted( item 
); 
1027 bool wxGtkDataViewModelNotifier::ItemChanged( const wxDataViewItem 
&item 
) 
1030     iter
.stamp 
= m_wxgtk_model
->stamp
; 
1031     iter
.user_data 
= (gpointer
) item
.GetID(); 
1033     GtkTreePath 
*path 
= wxgtk_tree_model_get_path(  
1034         GTK_TREE_MODEL(m_wxgtk_model
), &iter 
); 
1035     gtk_tree_model_row_changed( 
1036         GTK_TREE_MODEL(m_wxgtk_model
), path
, &iter 
); 
1037     gtk_tree_path_free (path
); 
1042 bool wxGtkDataViewModelNotifier::ValueChanged( const wxDataViewItem 
&item
, unsigned int model_col 
) 
1044     // This adds GTK+'s missing MVC logic for ValueChanged 
1046     for (index 
= 0; index 
< m_owner
->GetColumnCount(); index
++) 
1048         wxDataViewColumn 
*column 
= m_owner
->GetColumn( index 
); 
1049         if (column
->GetModelColumn() == model_col
) 
1051             GtkTreeView 
*widget 
= GTK_TREE_VIEW(m_owner
->m_treeview
); 
1052             GtkTreeViewColumn 
*gcolumn 
= GTK_TREE_VIEW_COLUMN(column
->GetGtkHandle()); 
1056             iter
.stamp 
= m_wxgtk_model
->stamp
; 
1057             iter
.user_data 
= (gpointer
) item
.GetID(); 
1058             GtkTreePath 
*path 
= wxgtk_tree_model_get_path(  
1059                 GTK_TREE_MODEL(m_wxgtk_model
), &iter 
); 
1060             GdkRectangle cell_area
; 
1061             gtk_tree_view_get_cell_area( widget
, path
, gcolumn
, &cell_area 
); 
1062             gtk_tree_path_free( path 
); 
1064             GtkAdjustment
* hadjust 
= gtk_tree_view_get_hadjustment( widget 
); 
1065             double d 
= gtk_adjustment_get_value( hadjust 
); 
1066             int xdiff 
= (int) d
; 
1068             int ydiff 
= gcolumn
->button
->allocation
.height
; 
1070             gtk_widget_queue_draw_area( GTK_WIDGET(widget
), 
1071                 cell_area
.x 
- xdiff
, ydiff 
+ cell_area
.y
, cell_area
.width
, cell_area
.height 
); 
1078 bool wxGtkDataViewModelNotifier::Cleared() 
1083 // --------------------------------------------------------- 
1084 // wxDataViewRenderer 
1085 // --------------------------------------------------------- 
1087 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRenderer
, wxDataViewRendererBase
) 
1089 wxDataViewRenderer::wxDataViewRenderer( const wxString 
&varianttype
, wxDataViewCellMode mode
, 
1091     wxDataViewRendererBase( varianttype
, mode
, align 
) 
1095     // NOTE: SetMode() and SetAlignment() needs to be called in the renderer's ctor, 
1096     //       after the m_renderer pointer has been initialized 
1099 void wxDataViewRenderer::SetMode( wxDataViewCellMode mode 
) 
1101     GtkCellRendererMode gtkMode
; 
1104     case wxDATAVIEW_CELL_INERT
: 
1105         gtkMode 
= GTK_CELL_RENDERER_MODE_INERT
; 
1107     case wxDATAVIEW_CELL_ACTIVATABLE
: 
1108         gtkMode 
= GTK_CELL_RENDERER_MODE_ACTIVATABLE
; 
1110     case wxDATAVIEW_CELL_EDITABLE
: 
1111         gtkMode 
= GTK_CELL_RENDERER_MODE_EDITABLE
; 
1115     GValue gvalue 
= { 0, }; 
1116     g_value_init( &gvalue
, gtk_cell_renderer_mode_get_type() ); 
1117     g_value_set_enum( &gvalue
, gtkMode 
); 
1118     g_object_set_property( G_OBJECT(m_renderer
), "mode", &gvalue 
); 
1119     g_value_unset( &gvalue 
); 
1122 wxDataViewCellMode 
wxDataViewRenderer::GetMode() const 
1124     wxDataViewCellMode ret
; 
1127     g_object_get( G_OBJECT(m_renderer
), "mode", &gvalue
, NULL
); 
1129     switch (g_value_get_enum(&gvalue
)) 
1131     case GTK_CELL_RENDERER_MODE_INERT
: 
1132         ret 
= wxDATAVIEW_CELL_INERT
; 
1134     case GTK_CELL_RENDERER_MODE_ACTIVATABLE
: 
1135         ret 
= wxDATAVIEW_CELL_ACTIVATABLE
; 
1137     case GTK_CELL_RENDERER_MODE_EDITABLE
: 
1138         ret 
= wxDATAVIEW_CELL_EDITABLE
; 
1142     g_value_unset( &gvalue 
); 
1147 void wxDataViewRenderer::SetAlignment( int align 
) 
1149     // horizontal alignment: 
1151     gfloat xalign 
= 0.0; 
1152     if (align 
& wxALIGN_RIGHT
) 
1154     else if (align 
& wxALIGN_CENTER_HORIZONTAL
) 
1157     GValue gvalue 
= { 0, }; 
1158     g_value_init( &gvalue
, G_TYPE_FLOAT 
); 
1159     g_value_set_float( &gvalue
, xalign 
); 
1160     g_object_set_property( G_OBJECT(m_renderer
), "xalign", &gvalue 
); 
1161     g_value_unset( &gvalue 
); 
1163     // vertical alignment: 
1165     gfloat yalign 
= 0.0; 
1166     if (align 
& wxALIGN_BOTTOM
) 
1168     else if (align 
& wxALIGN_CENTER_VERTICAL
) 
1171     GValue gvalue2 
= { 0, }; 
1172     g_value_init( &gvalue2
, G_TYPE_FLOAT 
); 
1173     g_value_set_float( &gvalue2
, yalign 
); 
1174     g_object_set_property( G_OBJECT(m_renderer
), "yalign", &gvalue2 
); 
1175     g_value_unset( &gvalue2 
); 
1178 int wxDataViewRenderer::GetAlignment() const 
1183     // horizontal alignment: 
1185     g_object_get( G_OBJECT(m_renderer
), "xalign", &gvalue
, NULL 
); 
1186     float xalign 
= g_value_get_float( &gvalue 
); 
1188         ret 
|= wxALIGN_LEFT
; 
1189     else if (xalign 
== 0.5) 
1190         ret 
|= wxALIGN_CENTER_HORIZONTAL
; 
1192         ret 
|= wxALIGN_RIGHT
; 
1193     g_value_unset( &gvalue 
); 
1196     // vertical alignment: 
1198     g_object_get( G_OBJECT(m_renderer
), "yalign", &gvalue
, NULL 
); 
1199     float yalign 
= g_value_get_float( &gvalue 
); 
1202     else if (yalign 
== 0.5) 
1203         ret 
|= wxALIGN_CENTER_VERTICAL
; 
1205         ret 
|= wxALIGN_BOTTOM
; 
1206     g_value_unset( &gvalue 
); 
1213 // --------------------------------------------------------- 
1214 // wxDataViewTextRenderer 
1215 // --------------------------------------------------------- 
1218 static void wxGtkTextRendererEditedCallback( GtkCellRendererText 
*renderer
, 
1219     gchar 
*arg1
, gchar 
*arg2
, gpointer user_data 
); 
1222 static void wxGtkTextRendererEditedCallback( GtkCellRendererText 
*renderer
, 
1223     gchar 
*arg1
, gchar 
*arg2
, gpointer user_data 
) 
1225     wxDataViewTextRenderer 
*cell 
= (wxDataViewTextRenderer
*) user_data
; 
1227     wxString tmp 
= wxGTK_CONV_BACK_FONT(arg2
, cell
->GetOwner()->GetOwner()->GetFont()); 
1228     wxVariant value 
= tmp
; 
1229     if (!cell
->Validate( value 
)) 
1232     wxDataViewModel 
*model 
= cell
->GetOwner()->GetOwner()->GetModel(); 
1234     GtkTreePath 
*path 
= gtk_tree_path_new_from_string( arg1 
); 
1236     cell
->GetOwner()->GetOwner()->GtkGetInternal()->get_iter( &iter
, path 
); 
1237     wxDataViewItem 
item( (void*) iter
.user_data 
);; 
1238     gtk_tree_path_free( path 
); 
1240     unsigned int model_col 
= cell
->GetOwner()->GetModelColumn(); 
1242     model
->SetValue( value
, item
, model_col 
); 
1243     model
->ValueChanged( item
, model_col 
); 
1246 IMPLEMENT_CLASS(wxDataViewTextRenderer
, wxDataViewRenderer
) 
1248 wxDataViewTextRenderer::wxDataViewTextRenderer( const wxString 
&varianttype
, wxDataViewCellMode mode
, 
1250     wxDataViewRenderer( varianttype
, mode
, align 
) 
1252     m_renderer 
= (GtkCellRenderer
*) gtk_cell_renderer_text_new(); 
1254     if (mode 
& wxDATAVIEW_CELL_EDITABLE
) 
1256         GValue gvalue 
= { 0, }; 
1257         g_value_init( &gvalue
, G_TYPE_BOOLEAN 
); 
1258         g_value_set_boolean( &gvalue
, true ); 
1259         g_object_set_property( G_OBJECT(m_renderer
), "editable", &gvalue 
); 
1260         g_value_unset( &gvalue 
); 
1262         g_signal_connect_after( m_renderer
, "edited", G_CALLBACK(wxGtkTextRendererEditedCallback
), this ); 
1266     SetAlignment(align
); 
1269 bool wxDataViewTextRenderer::SetValue( const wxVariant 
&value 
) 
1271     wxString tmp 
= value
; 
1273     GValue gvalue 
= { 0, }; 
1274     g_value_init( &gvalue
, G_TYPE_STRING 
); 
1275     g_value_set_string( &gvalue
, wxGTK_CONV_FONT( tmp
, GetOwner()->GetOwner()->GetFont() ) ); 
1276     g_object_set_property( G_OBJECT(m_renderer
), "text", &gvalue 
); 
1277     g_value_unset( &gvalue 
); 
1282 bool wxDataViewTextRenderer::GetValue( wxVariant 
&value 
) const 
1284     GValue gvalue 
= { 0, }; 
1285     g_value_init( &gvalue
, G_TYPE_STRING 
); 
1286     g_object_get_property( G_OBJECT(m_renderer
), "text", &gvalue 
); 
1287     wxString tmp 
= wxGTK_CONV_BACK_FONT( g_value_get_string( &gvalue 
), 
1288         wx_const_cast(wxDataViewTextRenderer
*, this)->GetOwner()->GetOwner()->GetFont() ); 
1289     g_value_unset( &gvalue 
); 
1296 void wxDataViewTextRenderer::SetAlignment( int align 
) 
1298     wxDataViewRenderer::SetAlignment(align
); 
1300     if (gtk_check_version(2,10,0)) 
1303     // horizontal alignment: 
1304     PangoAlignment pangoAlign 
= PANGO_ALIGN_LEFT
; 
1305     if (align 
& wxALIGN_RIGHT
) 
1306         pangoAlign 
= PANGO_ALIGN_RIGHT
; 
1307     else if (align 
& wxALIGN_CENTER_HORIZONTAL
) 
1308         pangoAlign 
= PANGO_ALIGN_CENTER
; 
1310     GValue gvalue 
= { 0, }; 
1311     g_value_init( &gvalue
, gtk_cell_renderer_mode_get_type() ); 
1312     g_value_set_enum( &gvalue
, pangoAlign 
); 
1313     g_object_set_property( G_OBJECT(m_renderer
), "alignment", &gvalue 
); 
1314     g_value_unset( &gvalue 
); 
1317 // --------------------------------------------------------- 
1318 // wxDataViewBitmapRenderer 
1319 // --------------------------------------------------------- 
1321 IMPLEMENT_CLASS(wxDataViewBitmapRenderer
, wxDataViewRenderer
) 
1323 wxDataViewBitmapRenderer::wxDataViewBitmapRenderer( const wxString 
&varianttype
, wxDataViewCellMode mode
, 
1325     wxDataViewRenderer( varianttype
, mode
, align 
) 
1327     m_renderer 
= (GtkCellRenderer
*) gtk_cell_renderer_pixbuf_new(); 
1330     SetAlignment(align
); 
1333 bool wxDataViewBitmapRenderer::SetValue( const wxVariant 
&value 
) 
1335     if (value
.GetType() == wxT("wxBitmap")) 
1340         // This may create a Pixbuf representation in the 
1341         // wxBitmap object (and it will stay there) 
1342         GdkPixbuf 
*pixbuf 
= bitmap
.GetPixbuf(); 
1344         GValue gvalue 
= { 0, }; 
1345         g_value_init( &gvalue
, G_TYPE_OBJECT 
); 
1346         g_value_set_object( &gvalue
, pixbuf 
); 
1347         g_object_set_property( G_OBJECT(m_renderer
), "pixbuf", &gvalue 
); 
1348         g_value_unset( &gvalue 
); 
1353     if (value
.GetType() == wxT("wxIcon")) 
1358         // This may create a Pixbuf representation in the 
1359         // wxBitmap object (and it will stay there) 
1360         GdkPixbuf 
*pixbuf 
= bitmap
.GetPixbuf(); 
1362         GValue gvalue 
= { 0, }; 
1363         g_value_init( &gvalue
, G_TYPE_OBJECT 
); 
1364         g_value_set_object( &gvalue
, pixbuf 
); 
1365         g_object_set_property( G_OBJECT(m_renderer
), "pixbuf", &gvalue 
); 
1366         g_value_unset( &gvalue 
); 
1374 bool wxDataViewBitmapRenderer::GetValue( wxVariant 
&value 
) const 
1379 // --------------------------------------------------------- 
1380 // wxDataViewToggleRenderer 
1381 // --------------------------------------------------------- 
1384 static void wxGtkToggleRendererToggledCallback( GtkCellRendererToggle 
*renderer
, 
1385     gchar 
*path
, gpointer user_data 
); 
1388 static void wxGtkToggleRendererToggledCallback( GtkCellRendererToggle 
*renderer
, 
1389     gchar 
*path
, gpointer user_data 
) 
1391     wxDataViewToggleRenderer 
*cell 
= (wxDataViewToggleRenderer
*) user_data
; 
1394     GValue gvalue 
= { 0, }; 
1395     g_value_init( &gvalue
, G_TYPE_BOOLEAN 
); 
1396     g_object_get_property( G_OBJECT(renderer
), "active", &gvalue 
); 
1397     bool tmp 
= g_value_get_boolean( &gvalue 
); 
1398     g_value_unset( &gvalue 
); 
1402     wxVariant value 
= tmp
; 
1403     if (!cell
->Validate( value 
)) 
1406     wxDataViewModel 
*model 
= cell
->GetOwner()->GetOwner()->GetModel(); 
1408     GtkTreePath 
*gtk_path 
= gtk_tree_path_new_from_string( path 
); 
1410     cell
->GetOwner()->GetOwner()->GtkGetInternal()->get_iter( &iter
, gtk_path 
); 
1411     wxDataViewItem 
item( (void*) iter
.user_data 
);; 
1412     gtk_tree_path_free( gtk_path 
); 
1414     unsigned int model_col 
= cell
->GetOwner()->GetModelColumn(); 
1416     model
->SetValue( value
, item
, model_col 
); 
1417     model
->ValueChanged( item
, model_col 
); 
1420 IMPLEMENT_CLASS(wxDataViewToggleRenderer
, wxDataViewRenderer
) 
1422 wxDataViewToggleRenderer::wxDataViewToggleRenderer( const wxString 
&varianttype
, 
1423                                                     wxDataViewCellMode mode
, int align 
) : 
1424     wxDataViewRenderer( varianttype
, mode
, align 
) 
1426     m_renderer 
= (GtkCellRenderer
*) gtk_cell_renderer_toggle_new(); 
1428     if (mode 
& wxDATAVIEW_CELL_ACTIVATABLE
) 
1430         g_signal_connect_after( m_renderer
, "toggled", 
1431                                 G_CALLBACK(wxGtkToggleRendererToggledCallback
), this ); 
1435         GValue gvalue 
= { 0, }; 
1436         g_value_init( &gvalue
, G_TYPE_BOOLEAN 
); 
1437         g_value_set_boolean( &gvalue
, false ); 
1438         g_object_set_property( G_OBJECT(m_renderer
), "activatable", &gvalue 
); 
1439         g_value_unset( &gvalue 
); 
1443     SetAlignment(align
); 
1446 bool wxDataViewToggleRenderer::SetValue( const wxVariant 
&value 
) 
1450     GValue gvalue 
= { 0, }; 
1451     g_value_init( &gvalue
, G_TYPE_BOOLEAN 
); 
1452     g_value_set_boolean( &gvalue
, tmp 
); 
1453     g_object_set_property( G_OBJECT(m_renderer
), "active", &gvalue 
); 
1454     g_value_unset( &gvalue 
); 
1459 bool wxDataViewToggleRenderer::GetValue( wxVariant 
&value 
) const 
1461     GValue gvalue 
= { 0, }; 
1462     g_value_init( &gvalue
, G_TYPE_BOOLEAN 
); 
1463     g_object_get_property( G_OBJECT(m_renderer
), "active", &gvalue 
); 
1464     bool tmp 
= g_value_get_boolean( &gvalue 
); 
1465     g_value_unset( &gvalue 
); 
1472 // --------------------------------------------------------- 
1473 // wxDataViewCustomRenderer 
1474 // --------------------------------------------------------- 
1476 class wxDataViewCtrlDC
: public wxWindowDC
 
1479     wxDataViewCtrlDC( wxDataViewCtrl 
*window 
) 
1481         GtkWidget 
*widget 
= window
->m_treeview
; 
1485         m_context 
= window
->GtkGetPangoDefaultContext(); 
1486         m_layout 
= pango_layout_new( m_context 
); 
1487         m_fontdesc 
= pango_font_description_copy( widget
->style
->font_desc 
); 
1489         m_cmap 
= gtk_widget_get_colormap( widget 
? widget 
: window
->m_widget 
); 
1491         // Set m_window later 
1493         // m_owner = window; 
1497 // --------------------------------------------------------- 
1498 // wxDataViewCustomRenderer 
1499 // --------------------------------------------------------- 
1501 IMPLEMENT_CLASS(wxDataViewCustomRenderer
, wxDataViewRenderer
) 
1503 wxDataViewCustomRenderer::wxDataViewCustomRenderer( const wxString 
&varianttype
, 
1504                                                     wxDataViewCellMode mode
, int align
, 
1506     wxDataViewRenderer( varianttype
, mode
, align 
) 
1516 bool wxDataViewCustomRenderer::Init(wxDataViewCellMode mode
, int align
) 
1518     GtkWxCellRenderer 
*renderer 
= (GtkWxCellRenderer 
*) gtk_wx_cell_renderer_new(); 
1519     renderer
->cell 
= this; 
1521     m_renderer 
= (GtkCellRenderer
*) renderer
; 
1524     SetAlignment(align
); 
1529 wxDataViewCustomRenderer::~wxDataViewCustomRenderer() 
1535 wxDC 
*wxDataViewCustomRenderer::GetDC() 
1539         if (GetOwner() == NULL
) 
1541         if (GetOwner()->GetOwner() == NULL
) 
1543         m_dc 
= new wxDataViewCtrlDC( GetOwner()->GetOwner() ); 
1549 // --------------------------------------------------------- 
1550 // wxDataViewProgressRenderer 
1551 // --------------------------------------------------------- 
1553 IMPLEMENT_CLASS(wxDataViewProgressRenderer
, wxDataViewCustomRenderer
) 
1555 wxDataViewProgressRenderer::wxDataViewProgressRenderer( const wxString 
&label
, 
1556     const wxString 
&varianttype
, wxDataViewCellMode mode
, int align 
) : 
1557     wxDataViewCustomRenderer( varianttype
, mode
, align
, true ) 
1563     if (!gtk_check_version(2,6,0)) 
1565         m_renderer 
= (GtkCellRenderer
*) gtk_cell_renderer_progress_new(); 
1567         GValue gvalue 
= { 0, }; 
1568         g_value_init( &gvalue
, G_TYPE_STRING 
); 
1570         // FIXME: font encoding support 
1571         g_value_set_string( &gvalue
, wxGTK_CONV_SYS(m_label
) ); 
1572         g_object_set_property( G_OBJECT(m_renderer
), "text", &gvalue 
); 
1573         g_value_unset( &gvalue 
); 
1576         SetAlignment(align
); 
1581         // Use custom cell code 
1582         wxDataViewCustomRenderer::Init(mode
, align
); 
1586 wxDataViewProgressRenderer::~wxDataViewProgressRenderer() 
1590 bool wxDataViewProgressRenderer::SetValue( const wxVariant 
&value 
) 
1593     if (!gtk_check_version(2,6,0)) 
1595         gint tmp 
= (long) value
; 
1596         GValue gvalue 
= { 0, }; 
1597         g_value_init( &gvalue
, G_TYPE_INT 
); 
1598         g_value_set_int( &gvalue
, tmp 
); 
1599         g_object_set_property( G_OBJECT(m_renderer
), "value", &gvalue 
); 
1600         g_value_unset( &gvalue 
); 
1605         m_value 
= (long) value
; 
1607         if (m_value 
< 0) m_value 
= 0; 
1608         if (m_value 
> 100) m_value 
= 100; 
1614 bool wxDataViewProgressRenderer::GetValue( wxVariant 
&value 
) const 
1619 bool wxDataViewProgressRenderer::Render( wxRect cell
, wxDC 
*dc
, int state 
) 
1621     double pct 
= (double)m_value 
/ 100.0; 
1623     bar
.width 
= (int)(cell
.width 
* pct
); 
1624     dc
->SetPen( *wxTRANSPARENT_PEN 
); 
1625     dc
->SetBrush( *wxBLUE_BRUSH 
); 
1626     dc
->DrawRectangle( bar 
); 
1628     dc
->SetBrush( *wxTRANSPARENT_BRUSH 
); 
1629     dc
->SetPen( *wxBLACK_PEN 
); 
1630     dc
->DrawRectangle( cell 
); 
1635 wxSize 
wxDataViewProgressRenderer::GetSize() const 
1637     return wxSize(40,12); 
1640 // --------------------------------------------------------- 
1641 // wxDataViewDateRenderer 
1642 // --------------------------------------------------------- 
1644 class wxDataViewDateRendererPopupTransient
: public wxPopupTransientWindow
 
1647     wxDataViewDateRendererPopupTransient( wxWindow
* parent
, wxDateTime 
*value
, 
1648         wxDataViewModel 
*model
, const wxDataViewItem 
&item
, unsigned int col 
) : 
1649         wxPopupTransientWindow( parent
, wxBORDER_SIMPLE 
) 
1654         m_cal 
= new wxCalendarCtrl( this, -1, *value 
); 
1655         wxBoxSizer 
*sizer 
= new wxBoxSizer( wxHORIZONTAL 
); 
1656         sizer
->Add( m_cal
, 1, wxGROW 
); 
1661     virtual void OnDismiss() 
1665     void OnCalendar( wxCalendarEvent 
&event 
); 
1667     wxCalendarCtrl   
*m_cal
; 
1668     wxDataViewModel  
*m_model
; 
1669     wxDataViewItem    m_item
; 
1673     DECLARE_EVENT_TABLE() 
1676 BEGIN_EVENT_TABLE(wxDataViewDateRendererPopupTransient
,wxPopupTransientWindow
) 
1677     EVT_CALENDAR( -1, wxDataViewDateRendererPopupTransient::OnCalendar 
) 
1680 void wxDataViewDateRendererPopupTransient::OnCalendar( wxCalendarEvent 
&event 
) 
1682     wxDateTime date 
= event
.GetDate(); 
1683     wxVariant value 
= date
; 
1684     m_model
->SetValue( value
, m_item
, m_col 
); 
1685     m_model
->ValueChanged( m_item
, m_col 
); 
1689 IMPLEMENT_CLASS(wxDataViewDateRenderer
, wxDataViewCustomRenderer
) 
1691 wxDataViewDateRenderer::wxDataViewDateRenderer( const wxString 
&varianttype
, 
1692                         wxDataViewCellMode mode
, int align 
) : 
1693     wxDataViewCustomRenderer( varianttype
, mode
, align 
) 
1696     SetAlignment(align
); 
1699 bool wxDataViewDateRenderer::SetValue( const wxVariant 
&value 
) 
1701     m_date 
= value
.GetDateTime(); 
1706 bool wxDataViewDateRenderer::GetValue( wxVariant 
&value 
) const 
1711 bool wxDataViewDateRenderer::Render( wxRect cell
, wxDC 
*dc
, int state 
) 
1713     dc
->SetFont( GetOwner()->GetOwner()->GetFont() ); 
1714     wxString tmp 
= m_date
.FormatDate(); 
1715     dc
->DrawText( tmp
, cell
.x
, cell
.y 
); 
1720 wxSize 
wxDataViewDateRenderer::GetSize() const 
1722     wxString tmp 
= m_date
.FormatDate(); 
1724     GetView()->GetTextExtent( tmp
, &x
, &y
, &d 
); 
1725     return wxSize(x
,y
+d
); 
1728 bool wxDataViewDateRenderer::Activate( wxRect cell
, wxDataViewModel 
*model
, 
1729                                        const wxDataViewItem 
&item
, unsigned int col 
) 
1732     model
->GetValue( variant
, item
, col 
); 
1733     wxDateTime value 
= variant
.GetDateTime(); 
1735     wxDataViewDateRendererPopupTransient 
*popup 
= new wxDataViewDateRendererPopupTransient( 
1736         GetOwner()->GetOwner()->GetParent(), &value
, model
, item
, col 
); 
1737     wxPoint pos 
= wxGetMousePosition(); 
1740     popup
->Popup( popup
->m_cal 
); 
1745 // --------------------------------------------------------- 
1747 // --------------------------------------------------------- 
1751 gtk_dataview_header_button_press_callback( GtkWidget 
*widget
, 
1752                                            GdkEventButton 
*gdk_event
, 
1753                                            wxDataViewColumn 
*column 
) 
1755     if (gdk_event
->type 
!= GDK_BUTTON_PRESS
) 
1758     if (gdk_event
->button 
== 1) 
1760         wxDataViewCtrl 
*dv 
= column
->GetOwner(); 
1761         wxDataViewEvent 
event( wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK
, dv
->GetId() ); 
1762         event
.SetDataViewColumn( column 
); 
1763         event
.SetModel( dv
->GetModel() ); 
1764         if (dv
->GetEventHandler()->ProcessEvent( event 
)) 
1772 static void wxGtkTreeCellDataFunc( GtkTreeViewColumn 
*column
, 
1773                             GtkCellRenderer 
*cell
, 
1774                             GtkTreeModel 
*model
, 
1780 static void wxGtkTreeCellDataFunc( GtkTreeViewColumn 
*column
, 
1781                             GtkCellRenderer 
*renderer
, 
1782                             GtkTreeModel 
*model
, 
1786     g_return_if_fail (GTK_IS_WX_TREE_MODEL (model
)); 
1787     GtkWxTreeModel 
*tree_model 
= (GtkWxTreeModel 
*) model
; 
1789     wxDataViewRenderer 
*cell 
= (wxDataViewRenderer
*) data
; 
1791     wxDataViewItem 
item( (void*) iter
->user_data 
); 
1794     tree_model
->internal
->GetDataViewModel()->GetValue( value
, item
, cell
->GetOwner()->GetModelColumn() ); 
1796     if (value
.GetType() != cell
->GetVariantType()) 
1797         wxLogError( wxT("Wrong type, required: %s but: %s"), 
1798                     value
.GetType().c_str(), 
1799                     cell
->GetVariantType().c_str() ); 
1801     cell
->SetValue( value 
); 
1804     wxListItemAttr attr
; 
1805     tree_model
->model
->GetAttr( attr
, cell
->GetOwner()->GetModelColumn(), model_row 
); 
1807     if (attr
.HasBackgroundColour()) 
1809         wxColour colour 
= attr
.GetBackgroundColour(); 
1810         const GdkColor 
* const gcol 
= colour
.GetColor(); 
1812         GValue gvalue 
= { 0, }; 
1813         g_value_init( &gvalue
, GDK_TYPE_COLOR 
); 
1814         g_value_set_boxed( &gvalue
, gcol 
); 
1815         g_object_set_property( G_OBJECT(renderer
), "cell-background_gdk", &gvalue 
); 
1816         g_value_unset( &gvalue 
); 
1820         GValue gvalue 
= { 0, }; 
1821         g_value_init( &gvalue
, G_TYPE_BOOLEAN 
); 
1822         g_value_set_boolean( &gvalue
, FALSE 
); 
1823         g_object_set_property( G_OBJECT(renderer
), "cell-background-set", &gvalue 
); 
1824         g_value_unset( &gvalue 
); 
1830 IMPLEMENT_CLASS(wxDataViewColumn
, wxDataViewColumnBase
) 
1832 wxDataViewColumn::wxDataViewColumn( const wxString 
&title
, wxDataViewRenderer 
*cell
, 
1833                                     unsigned int model_column
, int width
, 
1834                                     wxAlignment align
, int flags 
) : 
1835     wxDataViewColumnBase( title
, cell
, model_column
, width
, align
, flags 
) 
1837     Init( align
, flags
, width 
); 
1839     gtk_tree_view_column_set_clickable( GTK_TREE_VIEW_COLUMN(m_column
), TRUE 
); 
1843 wxDataViewColumn::wxDataViewColumn( const wxBitmap 
&bitmap
, wxDataViewRenderer 
*cell
, 
1844                                     unsigned int model_column
, int width
, 
1845                                     wxAlignment align
, int flags 
) : 
1846     wxDataViewColumnBase( bitmap
, cell
, model_column
, width
, align
, flags 
) 
1848     Init( align
, flags
, width 
); 
1850     SetBitmap( bitmap 
); 
1853 void wxDataViewColumn::Init(wxAlignment align
, int flags
, int width
) 
1855     m_isConnected 
= false; 
1857     GtkCellRenderer 
*renderer 
= (GtkCellRenderer 
*) GetRenderer()->GetGtkHandle(); 
1858     GtkTreeViewColumn 
*column 
= gtk_tree_view_column_new(); 
1859     m_column 
= (GtkWidget
*) column
; 
1862     SetAlignment( align 
); 
1864     // NOTE: we prefer not to call SetMinWidth(wxDVC_DEFAULT_MINWIDTH); 
1865     //       as GTK+ is smart and unless explicitely told, will set the minimal 
1866     //       width to the title's lenght, which is a better default 
1868     // the GTK_TREE_VIEW_COLUMN_FIXED is required by the "fixed height" mode 
1869     // that we use for the wxDataViewCtrl 
1870     gtk_tree_view_column_set_fixed_width( column
, width 
< 0 ? wxDVC_DEFAULT_WIDTH 
: width 
); 
1871     gtk_tree_view_column_set_sizing( column
, GTK_TREE_VIEW_COLUMN_FIXED 
); 
1873     gtk_tree_view_column_pack_end( column
, renderer
, TRUE 
); 
1875     gtk_tree_view_column_set_cell_data_func( column
, renderer
, 
1876         wxGtkTreeCellDataFunc
, (gpointer
) GetRenderer(), NULL 
); 
1879 wxDataViewColumn::~wxDataViewColumn() 
1883 void wxDataViewColumn::OnInternalIdle() 
1888     if (GTK_WIDGET_REALIZED(GetOwner()->m_treeview
)) 
1890         GtkTreeViewColumn 
*column 
= GTK_TREE_VIEW_COLUMN(m_column
); 
1893             g_signal_connect(column
->button
, "button_press_event", 
1894                       G_CALLBACK (gtk_dataview_header_button_press_callback
), this); 
1896             m_isConnected 
= true; 
1901 void wxDataViewColumn::SetOwner( wxDataViewCtrl 
*owner 
) 
1903     wxDataViewColumnBase::SetOwner( owner 
); 
1905     GtkTreeViewColumn 
*column 
= GTK_TREE_VIEW_COLUMN(m_column
); 
1907     gtk_tree_view_column_set_title( column
, wxGTK_CONV_FONT(GetTitle(), GetOwner()->GetFont() ) ); 
1910 void wxDataViewColumn::SetTitle( const wxString 
&title 
) 
1912     GtkTreeViewColumn 
*column 
= GTK_TREE_VIEW_COLUMN(m_column
); 
1916         // disconnect before column->button gets recreated 
1917         g_signal_handlers_disconnect_by_func( column
->button
, 
1918                       (GtkWidget
*) gtk_dataview_header_button_press_callback
, this); 
1920         m_isConnected 
= false; 
1923     // FIXME: can it really happen that we don't have the owner here?? 
1924     wxDataViewCtrl 
*ctrl 
= GetOwner(); 
1925     gtk_tree_view_column_set_title( column
, ctrl 
? wxGTK_CONV_FONT(title
, ctrl
->GetFont()) 
1926                                                  : wxGTK_CONV_SYS(title
) ); 
1928     gtk_tree_view_column_set_widget( column
, NULL 
); 
1931 wxString 
wxDataViewColumn::GetTitle() const 
1933     const gchar 
*str 
= gtk_tree_view_column_get_title( GTK_TREE_VIEW_COLUMN(m_column
) ); 
1934     return wxConvFileName
->cMB2WX(str
); 
1937 void wxDataViewColumn::SetBitmap( const wxBitmap 
&bitmap 
) 
1939     wxDataViewColumnBase::SetBitmap( bitmap 
); 
1941     GtkTreeViewColumn 
*column 
= GTK_TREE_VIEW_COLUMN(m_column
); 
1944         GtkImage 
*gtk_image 
= GTK_IMAGE( gtk_image_new() ); 
1946         GdkBitmap 
*mask 
= (GdkBitmap 
*) NULL
; 
1947         if (bitmap
.GetMask()) 
1948             mask 
= bitmap
.GetMask()->GetBitmap(); 
1950         if (bitmap
.HasPixbuf()) 
1952             gtk_image_set_from_pixbuf(GTK_IMAGE(gtk_image
), 
1953                                       bitmap
.GetPixbuf()); 
1957             gtk_image_set_from_pixmap(GTK_IMAGE(gtk_image
), 
1958                                       bitmap
.GetPixmap(), mask
); 
1960         gtk_widget_show( GTK_WIDGET(gtk_image
) ); 
1962         gtk_tree_view_column_set_widget( column
, GTK_WIDGET(gtk_image
) ); 
1966         gtk_tree_view_column_set_widget( column
, NULL 
); 
1970 void wxDataViewColumn::SetHidden( bool hidden 
) 
1972     gtk_tree_view_column_set_visible( GTK_TREE_VIEW_COLUMN(m_column
), !hidden 
); 
1975 void wxDataViewColumn::SetResizeable( bool resizeable 
) 
1977     gtk_tree_view_column_set_resizable( GTK_TREE_VIEW_COLUMN(m_column
), resizeable 
); 
1980 void wxDataViewColumn::SetAlignment( wxAlignment align 
) 
1982     GtkTreeViewColumn 
*column 
= GTK_TREE_VIEW_COLUMN(m_column
); 
1984     gfloat xalign 
= 0.0; 
1985     if (align 
== wxALIGN_RIGHT
) 
1987     if (align 
== wxALIGN_CENTER_HORIZONTAL 
|| 
1988         align 
== wxALIGN_CENTER
) 
1991     gtk_tree_view_column_set_alignment( column
, xalign 
); 
1994 wxAlignment 
wxDataViewColumn::GetAlignment() const 
1996     gfloat xalign 
= gtk_tree_view_column_get_alignment( GTK_TREE_VIEW_COLUMN(m_column
) ); 
1999         return wxALIGN_RIGHT
; 
2001         return wxALIGN_CENTER_HORIZONTAL
; 
2003     return wxALIGN_LEFT
; 
2006 void wxDataViewColumn::SetSortable( bool sortable 
) 
2008     GtkTreeViewColumn 
*column 
= GTK_TREE_VIEW_COLUMN(m_column
); 
2011         gtk_tree_view_column_set_sort_column_id( column
, GetModelColumn() ); 
2013         gtk_tree_view_column_set_sort_column_id( column
, -1 ); 
2016 bool wxDataViewColumn::IsSortable() const 
2018     GtkTreeViewColumn 
*column 
= GTK_TREE_VIEW_COLUMN(m_column
); 
2019     return (gtk_tree_view_column_get_sort_column_id( column 
) != -1); 
2022 bool wxDataViewColumn::IsResizeable() const 
2024     GtkTreeViewColumn 
*column 
= GTK_TREE_VIEW_COLUMN(m_column
); 
2025     return gtk_tree_view_column_get_resizable( column 
); 
2028 bool wxDataViewColumn::IsHidden() const 
2030     GtkTreeViewColumn 
*column 
= GTK_TREE_VIEW_COLUMN(m_column
); 
2031     return !gtk_tree_view_column_get_visible( column 
); 
2034 void wxDataViewColumn::SetSortOrder( bool ascending 
) 
2036     GtkTreeViewColumn 
*column 
= GTK_TREE_VIEW_COLUMN(m_column
); 
2039         gtk_tree_view_column_set_sort_order( column
, GTK_SORT_ASCENDING 
); 
2041         gtk_tree_view_column_set_sort_order( column
, GTK_SORT_DESCENDING 
); 
2044 bool wxDataViewColumn::IsSortOrderAscending() const 
2046     GtkTreeViewColumn 
*column 
= GTK_TREE_VIEW_COLUMN(m_column
); 
2048     return (gtk_tree_view_column_get_sort_order( column 
) != GTK_SORT_DESCENDING
); 
2051 void wxDataViewColumn::SetMinWidth( int width 
) 
2053     gtk_tree_view_column_set_min_width( GTK_TREE_VIEW_COLUMN(m_column
), width 
); 
2056 int wxDataViewColumn::GetMinWidth() const 
2058     return gtk_tree_view_column_get_min_width( GTK_TREE_VIEW_COLUMN(m_column
) ); 
2061 int wxDataViewColumn::GetWidth() const 
2063     return gtk_tree_view_column_get_width( GTK_TREE_VIEW_COLUMN(m_column
) ); 
2066 void wxDataViewColumn::SetWidth( int width 
) 
2068     gtk_tree_view_column_set_fixed_width( GTK_TREE_VIEW_COLUMN(m_column
), width 
); 
2072 //----------------------------------------------------------------------------- 
2073 // wxDataViewCtrlInternal 
2074 //----------------------------------------------------------------------------- 
2076 wxDataViewCtrlInternal::wxDataViewCtrlInternal( wxDataViewCtrl 
*owner
,  
2077     wxDataViewModel 
*wx_model
, GtkWxTreeModel 
*gtk_model 
) 
2080     m_wx_model 
= wx_model
;  
2081     m_gtk_model 
= gtk_model
;  
2086 wxDataViewCtrlInternal::~wxDataViewCtrlInternal() 
2088     g_object_unref( m_gtk_model 
); 
2091 void wxDataViewCtrlInternal::InitTree() 
2093     wxDataViewItem item
; 
2094     m_root 
= new wxGtkTreeModelNode( NULL
, item
, m_wx_model 
); 
2096     BuildBranch( m_root 
); 
2099 void wxDataViewCtrlInternal::BuildBranch( wxGtkTreeModelNode 
*node 
) 
2101     if (node
->GetChildCount() == 0) 
2103         wxDataViewItem child 
= m_wx_model
->GetFirstChild( node
->GetItem() ); 
2104         while (child
.IsOk()) 
2106             node
->Add( new wxGtkTreeModelNode( node
, child
, node
->GetModel() ) ); 
2107             child 
= m_wx_model
->GetNextSibling( child 
); 
2112 bool wxDataViewCtrlInternal::ItemAdded( const wxDataViewItem 
&parent
, const wxDataViewItem 
&item 
) 
2114     wxGtkTreeModelNode 
*parent_node 
= FindNode( parent 
); 
2115     parent_node
->Add( new wxGtkTreeModelNode( parent_node
, item
, parent_node
->GetModel() ) ); 
2119 bool wxDataViewCtrlInternal::ItemDeleted( const wxDataViewItem 
&item 
) 
2121     wxGtkTreeModelNode 
*node 
= FindNode( item 
); 
2122     wxGtkTreeModelNode 
*parent 
= node
->GetParent(); 
2124     for (pos 
= 0; pos 
< parent
->GetChildren().GetCount(); pos
++) 
2126         if (node 
== parent
->GetChildren().Item( pos 
)) 
2128             parent
->GetChildren().RemoveAt( pos 
); 
2136 gboolean 
wxDataViewCtrlInternal::get_iter( GtkTreeIter 
*iter
, GtkTreePath 
*path 
) 
2138     int depth 
= gtk_tree_path_get_depth( path 
); 
2140     wxGtkTreeModelNode 
*node 
= m_root
; 
2143     for (i 
= 0; i 
< depth
; i
++)     
2145         BuildBranch( node 
); 
2147         gint pos 
= gtk_tree_path_get_indices (path
)[i
]; 
2148         if (pos 
< 0) return FALSE
; 
2149         if ((size_t)pos 
>= node
->GetChildCount()) return FALSE
; 
2151         node 
= node
->GetChildren().Item( (size_t) pos 
); 
2154     iter
->stamp 
= m_gtk_model
->stamp
; 
2155     iter
->user_data 
= (gpointer
) node
->GetItem().GetID(); 
2160 GtkTreePath 
*wxDataViewCtrlInternal::get_path( GtkTreeIter 
*iter 
) 
2162     GtkTreePath 
*retval 
= gtk_tree_path_new (); 
2164     wxGtkTreeModelNode 
*node 
= FindNode( iter 
); 
2165     while (node
->GetParent()) 
2167         wxGtkTreeModelNode 
*parent 
= node
->GetParent(); 
2168         int pos 
= parent
->GetChildren().Index( node 
); 
2170         gtk_tree_path_prepend_index( retval
, pos 
); 
2178 GtkTreePath 
*wxDataViewCtrlInternal::get_path_safe( GtkTreeIter 
*iter 
) 
2180     GtkTreePath 
*retval 
= gtk_tree_path_new (); 
2182     wxGtkTreeModelNode 
*node 
= FindNode( iter 
); 
2183     while (node
->GetParent()) 
2185         wxGtkTreeModelNode 
*parent 
= node
->GetParent(); 
2187         for (pos 
= 0; pos 
< parent
->GetChildren().GetCount(); pos
++) 
2189             if (node 
== parent
->GetChildren().Item( pos 
)) 
2191                 gtk_tree_path_prepend_index( retval
, (int) pos 
); 
2202 gboolean 
wxDataViewCtrlInternal::iter_next( GtkTreeIter 
*iter 
) 
2204     wxGtkTreeModelNode 
*node 
= FindNode( iter 
); 
2205     wxGtkTreeModelNode 
*parent 
= node
->GetParent(); 
2206     unsigned int pos 
= parent
->GetChildren().Index( node 
); 
2208     if (pos 
== parent
->GetChildren().GetCount()-1) 
2211     node 
= parent
->GetChildren().Item( pos
+1 ); 
2213     iter
->stamp 
= m_gtk_model
->stamp
; 
2214     iter
->user_data 
= (gpointer
) node
->GetItem().GetID(); 
2219 gboolean 
wxDataViewCtrlInternal::iter_children( GtkTreeIter 
*iter
, GtkTreeIter 
*parent 
) 
2221     wxDataViewItem 
item( (void*) parent
->user_data 
); 
2223     if (!m_wx_model
->HasChildren( item 
)) 
2226     wxGtkTreeModelNode 
*parent_node 
= FindNode( parent 
); 
2227     BuildBranch( parent_node 
); 
2229     wxGtkTreeModelNode 
*first_child_node 
= parent_node
->GetChildren().Item( 0 ); 
2231     iter
->stamp 
= m_gtk_model
->stamp
; 
2232     iter
->user_data 
= (gpointer
) first_child_node
->GetItem().GetID(); 
2237 gboolean 
wxDataViewCtrlInternal::iter_has_child( GtkTreeIter 
*iter 
) 
2239     wxDataViewItem 
item( (void*) iter
->user_data 
); 
2241     return m_wx_model
->HasChildren( item 
); 
2244 gint 
wxDataViewCtrlInternal::iter_n_children( GtkTreeIter 
*iter 
) 
2246     wxDataViewItem 
item( (void*) iter
->user_data 
); 
2248     if (!m_wx_model
->HasChildren( item 
)) 
2251     wxGtkTreeModelNode 
*parent_node 
= FindNode( iter 
); 
2252     BuildBranch( parent_node 
); 
2254     // wxPrintf( "iter_n_children %d\n", parent_node->GetChildCount() ); 
2256     return parent_node
->GetChildCount(); 
2259 gboolean 
wxDataViewCtrlInternal::iter_nth_child( GtkTreeIter 
*iter
, GtkTreeIter 
*parent
, gint n 
) 
2262     if (parent
) id 
= (void*) parent
->user_data
; 
2263     wxDataViewItem 
item( id 
); 
2265     if (!m_wx_model
->HasChildren( item 
)) 
2268     wxGtkTreeModelNode 
*parent_node 
= FindNode( parent 
); 
2269     BuildBranch( parent_node 
); 
2271     wxGtkTreeModelNode 
*child_node 
= parent_node
->GetChildren().Item( (size_t) n 
); 
2275     // wxPrintf( "iter_nth_child %d\n", n ); 
2277     iter
->stamp 
= m_gtk_model
->stamp
; 
2278     iter
->user_data 
= (gpointer
) child_node
->GetItem().GetID(); 
2283 gboolean 
wxDataViewCtrlInternal::iter_parent( GtkTreeIter 
*iter
, GtkTreeIter 
*child 
) 
2285     wxDataViewItem 
item( (void*) child
->user_data 
); 
2287     wxGtkTreeModelNode 
*node 
= FindNode( child 
); 
2288     node 
= node
->GetParent(); 
2292     iter
->stamp 
= m_gtk_model
->stamp
; 
2293     iter
->user_data 
= (gpointer
) node
->GetItem().GetID(); 
2298 static wxGtkTreeModelNode
* 
2299 wxDataViewCtrlInternal_FindNode( wxGtkTreeModelNode 
*node
, const wxDataViewItem 
&item 
) 
2301     if (!node
) return NULL
; 
2303     size_t count 
= node
->GetChildCount(); 
2305     for (i 
= 0; i 
< count
; i
++) 
2307         wxGtkTreeModelNode 
*child 
= node
->GetChildren().Item( i 
); 
2308         if (child
->GetItem().GetID() == item
.GetID()) 
2310             // wxPrintf( "leave findnode at %d\n", i ); 
2314         wxGtkTreeModelNode 
*node2 
= wxDataViewCtrlInternal_FindNode( child
, item 
); 
2317             // wxPrintf( "branch findnode at %d\n", i ); 
2325 wxGtkTreeModelNode 
*wxDataViewCtrlInternal::FindNode( GtkTreeIter 
*iter 
) 
2330     wxDataViewItem 
item( (void*) iter
->user_data 
); 
2332     wxGtkTreeModelNode 
*result 
= wxDataViewCtrlInternal_FindNode( m_root
, item 
); 
2336         wxPrintf( "Not found %d\n", (int) iter
->user_data 
); 
2344 wxGtkTreeModelNode 
*wxDataViewCtrlInternal::FindNode( const wxDataViewItem 
&item 
) 
2346     wxGtkTreeModelNode 
*result 
= wxDataViewCtrlInternal_FindNode( m_root
, item 
); 
2350         wxPrintf( "Not found %d\n", (int) item
.GetID() ); 
2358 //----------------------------------------------------------------------------- 
2359 // wxDataViewCtrl signal callbacks 
2360 //----------------------------------------------------------------------------- 
2363 wxdataview_selection_changed_callback( GtkTreeSelection
* selection
, wxDataViewCtrl 
*dv 
) 
2365     if (!GTK_WIDGET_REALIZED(dv
->m_widget
)) 
2368     wxDataViewEvent 
event( wxEVT_COMMAND_DATAVIEW_ITEM_SELECTED
, dv
->GetId() ); 
2370     event
.SetModel( dv
->GetModel() ); 
2371     dv
->GetEventHandler()->ProcessEvent( event 
); 
2375 wxdataview_row_activated_callback( GtkTreeView
* treeview
, GtkTreePath 
*path
, 
2376                                    GtkTreeViewColumn 
*column
, wxDataViewCtrl 
*dv 
) 
2378     wxDataViewEvent 
event( wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED
, dv
->GetId() ); 
2381     dv
->GtkGetInternal()->get_iter( &iter
, path 
); 
2382     wxDataViewItem 
item( (void*) iter
.user_data 
);; 
2383     event
.SetItem( item 
); 
2384     event
.SetModel( dv
->GetModel() ); 
2385     dv
->GetEventHandler()->ProcessEvent( event 
); 
2388 //----------------------------------------------------------------------------- 
2390 //----------------------------------------------------------------------------- 
2392 //----------------------------------------------------------------------------- 
2393 // InsertChild for wxDataViewCtrl 
2394 //----------------------------------------------------------------------------- 
2396 static void wxInsertChildInDataViewCtrl( wxWindowGTK
* parent
, wxWindowGTK
* child 
) 
2398     wxDataViewCtrl 
* dvc 
= (wxDataViewCtrl
*) parent
; 
2399     GtkWidget 
*treeview 
= dvc
->GtkGetTreeView(); 
2401     // Insert widget in GtkTreeView 
2402     if (GTK_WIDGET_REALIZED(treeview
)) 
2403         gtk_widget_set_parent_window( child
->m_widget
, 
2404           gtk_tree_view_get_bin_window( GTK_TREE_VIEW(treeview
) ) ); 
2405     gtk_widget_set_parent( child
->m_widget
, treeview 
); 
2409 void gtk_dataviewctrl_size_callback( GtkWidget 
*WXUNUSED(widget
), 
2410                                      GtkAllocation 
*alloc
, 
2411                                      wxDataViewCtrl 
*win 
) 
2414     wxWindowList::Node 
*node 
= win
->GetChildren().GetFirst(); 
2417         wxWindow 
*child 
= node
->GetData(); 
2420         gtk_widget_size_request( child
->m_widget
, &req 
); 
2422         GtkAllocation alloc
; 
2423         alloc
.x 
= child
->m_x
; 
2424         alloc
.y 
= child
->m_y
; 
2425         alloc
.width 
= child
->m_width
; 
2426         alloc
.height 
= child
->m_height
; 
2427         gtk_widget_size_allocate( child
->m_widget
, &alloc 
); 
2429         node 
= node
->GetNext(); 
2435 IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl
, wxDataViewCtrlBase
) 
2437 wxDataViewCtrl::~wxDataViewCtrl() 
2440         GetModel()->RemoveNotifier( m_notifier 
); 
2442     // remove the model from the GtkTreeView before it gets destroyed by the 
2443     // wxDataViewCtrlBase's dtor 
2444     gtk_tree_view_set_model( GTK_TREE_VIEW(m_treeview
), NULL 
); 
2449 void wxDataViewCtrl::Init() 
2454 bool wxDataViewCtrl::Create(wxWindow 
*parent
, wxWindowID id
, 
2455            const wxPoint
& pos
, const wxSize
& size
, 
2456            long style
, const wxValidator
& validator 
) 
2460     if (!PreCreation( parent
, pos
, size 
) || 
2461         !CreateBase( parent
, id
, pos
, size
, style
, validator 
)) 
2463         wxFAIL_MSG( wxT("wxDataViewCtrl creation failed") ); 
2467     m_insertCallback 
= wxInsertChildInDataViewCtrl
; 
2469     m_widget 
= gtk_scrolled_window_new (NULL
, NULL
); 
2471     GtkScrolledWindowSetBorder(m_widget
, style
); 
2473     m_treeview 
= gtk_tree_view_new(); 
2474     gtk_container_add (GTK_CONTAINER (m_widget
), m_treeview
); 
2476     g_signal_connect (m_treeview
, "size_allocate", 
2477                      G_CALLBACK (gtk_dataviewctrl_size_callback
), this); 
2480     if (!gtk_check_version(2,6,0)) 
2481         gtk_tree_view_set_fixed_height_mode( GTK_TREE_VIEW(m_treeview
), TRUE 
); 
2484     if (style 
& wxDV_MULTIPLE
) 
2486         GtkTreeSelection 
*selection 
= gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview
) ); 
2487         gtk_tree_selection_set_mode( selection
, GTK_SELECTION_MULTIPLE 
); 
2490     gtk_tree_view_set_headers_visible( GTK_TREE_VIEW(m_treeview
), (style 
& wxDV_NO_HEADER
) == 0 ); 
2493     if (!gtk_check_version(2,10,0)) 
2495         GtkTreeViewGridLines grid 
= GTK_TREE_VIEW_GRID_LINES_NONE
; 
2497         if ((style 
& wxDV_HORIZ_RULES
) != 0 && 
2498             (style 
& wxDV_VERT_RULES
) != 0) 
2499             grid 
= GTK_TREE_VIEW_GRID_LINES_BOTH
; 
2500         else if (style 
& wxDV_VERT_RULES
) 
2501             grid 
= GTK_TREE_VIEW_GRID_LINES_VERTICAL
; 
2502         else if (style 
& wxDV_HORIZ_RULES
) 
2503             grid 
= GTK_TREE_VIEW_GRID_LINES_HORIZONTAL
; 
2505         gtk_tree_view_set_grid_lines( GTK_TREE_VIEW(m_treeview
), grid 
); 
2510         gtk_tree_view_set_rules_hint( GTK_TREE_VIEW(m_treeview
), (style 
& wxDV_HORIZ_RULES
) != 0 ); 
2513     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (m_widget
), 
2514         GTK_POLICY_AUTOMATIC
, GTK_POLICY_ALWAYS
); 
2515     gtk_widget_show (m_treeview
); 
2517     m_parent
->DoAddChild( this ); 
2521     GtkEnableSelectionEvents(); 
2523     g_signal_connect_after (m_treeview
, "row_activated", 
2524                             G_CALLBACK (wxdataview_row_activated_callback
), this); 
2529 void wxDataViewCtrl::OnInternalIdle() 
2531     wxWindow::OnInternalIdle(); 
2533     unsigned int cols 
= GetColumnCount(); 
2535     for (i 
= 0; i 
< cols
; i
++) 
2537         wxDataViewColumn 
*col 
= GetColumn( i 
); 
2538         col
->OnInternalIdle(); 
2542 bool wxDataViewCtrl::AssociateModel( wxDataViewModel 
*model 
) 
2544     if (!wxDataViewCtrlBase::AssociateModel( model 
)) 
2547     GtkWxTreeModel 
*gtk_model 
= wxgtk_tree_model_new(); 
2548     m_internal 
= new wxDataViewCtrlInternal( this, model
, gtk_model 
); 
2549     gtk_model
->internal 
= m_internal
; 
2551     m_notifier 
= new wxGtkDataViewModelNotifier( gtk_model
, model
, this ); 
2553     model
->AddNotifier( m_notifier 
); 
2555     gtk_tree_view_set_model( GTK_TREE_VIEW(m_treeview
), GTK_TREE_MODEL(gtk_model
) ); 
2557     // unref in wxDataViewCtrlInternal 
2558     // g_object_unref( gtk_model ); 
2563 bool wxDataViewCtrl::AppendColumn( wxDataViewColumn 
*col 
) 
2565     if (!wxDataViewCtrlBase::AppendColumn(col
)) 
2568     GtkTreeViewColumn 
*column 
= (GtkTreeViewColumn 
*)col
->GetGtkHandle(); 
2570     gtk_tree_view_append_column( GTK_TREE_VIEW(m_treeview
), column 
); 
2575 wxDataViewItem 
wxDataViewCtrl::GetSelection() 
2577     GtkTreeSelection 
*selection 
= gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview
) ); 
2579     if (m_windowStyle 
& wxDV_MULTIPLE
) 
2585         if (gtk_tree_selection_get_selected( selection
, NULL
, &iter 
)) 
2587             wxDataViewItem 
item( (void*) iter
.user_data 
); 
2592     return wxDataViewItem(0); 
2595 void wxDataViewCtrl::DoSetExpanderColumn() 
2599 void wxDataViewCtrl::DoSetIndent() 
2603 void wxDataViewCtrl::GtkDisableSelectionEvents() 
2605     GtkTreeSelection 
*selection 
= gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview
) ); 
2606     g_signal_connect_after (selection
, "changed", 
2607                             G_CALLBACK (wxdataview_selection_changed_callback
), this); 
2610 void wxDataViewCtrl::GtkEnableSelectionEvents() 
2612     GtkTreeSelection 
*selection 
= gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview
) ); 
2613     g_signal_handlers_disconnect_by_func( selection
, 
2614                             (gpointer
) (wxdataview_selection_changed_callback
), this); 
2619 wxDataViewCtrl::GetClassDefaultAttributes(wxWindowVariant 
WXUNUSED(variant
)) 
2621     return GetDefaultAttributesFromGTKWidget(gtk_tree_view_new
); 
2626     // !wxUSE_GENERICDATAVIEWCTRL 
2629     // wxUSE_DATAVIEWCTRL