1 ///////////////////////////////////////////////////////////////////////////// 
   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" 
  15 #if wxUSE_DATAVIEWCTRL 
  17 #include "wx/dataview.h" 
  18 #include "wx/stockitem.h" 
  19 #include "wx/dcclient.h" 
  21 #include "wx/gtk/private.h" 
  22 #include "wx/gtk/win_gtk.h" 
  24 #include <gobject/gvaluecollector.h> 
  25 #include <gtk/gtktreemodel.h> 
  26 #include <gtk/gtktreednd.h> 
  28 #include <gdk/gdkkeysyms.h> 
  30 //----------------------------------------------------------------------------- 
  32 //----------------------------------------------------------------------------- 
  36 //----------------------------------------------------------------------------- 
  38 //----------------------------------------------------------------------------- 
  40 extern void wxapp_install_idle_handler(); 
  43 //----------------------------------------------------------------------------- 
  45 //----------------------------------------------------------------------------- 
  47 extern bool   g_blockEventsOnDrag
; 
  49 //----------------------------------------------------------------------------- 
  50 // define new GTK+ class wxGtkListStore 
  51 //----------------------------------------------------------------------------- 
  55 #define GTK_TYPE_WX_LIST_STORE               (gtk_wx_list_store_get_type ()) 
  56 #define GTK_WX_LIST_STORE(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WX_LIST_STORE, GtkWxListStore)) 
  57 #define GTK_WX_LIST_STORE_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WX_LIST_STORE, GtkWxListStoreClass)) 
  58 #define GTK_IS_WX_LIST_STORE(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WX_LIST_STORE)) 
  59 #define GTK_IS_WX_LIST_STORE_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WX_LIST_STORE)) 
  60 #define GTK_WX_LIST_STORE_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WX_LIST_STORE, GtkWxListStoreClass)) 
  62 GType         
gtk_wx_list_store_get_type         (void); 
  64 typedef struct _GtkWxListStore       GtkWxListStore
; 
  65 typedef struct _GtkWxListStoreClass  GtkWxListStoreClass
; 
  67 struct _GtkWxListStore
 
  73   wxDataViewListModel 
*model
; 
  76 struct _GtkWxListStoreClass
 
  78   GObjectClass list_parent_class
; 
  82 static GtkWxListStore 
*wxgtk_list_store_new          (void); 
  83 static void         wxgtk_list_store_init            (GtkWxListStore      
*list_store
); 
  84 static void         wxgtk_list_store_class_init      (GtkWxListStoreClass 
*klass
); 
  85 static void         wxgtk_list_store_tree_model_init (GtkTreeModelIface 
*iface
); 
  86 static void         wxgtk_list_store_finalize        (GObject           
*object
); 
  87 static GtkTreeModelFlags 
wxgtk_list_store_get_flags  (GtkTreeModel      
*tree_model
); 
  88 static gint         
wxgtk_list_store_get_n_columns   (GtkTreeModel      
*tree_model
); 
  89 static GType        
wxgtk_list_store_get_column_type (GtkTreeModel      
*tree_model
, 
  91 static gboolean     
wxgtk_list_store_get_iter        (GtkTreeModel      
*tree_model
, 
  94 static GtkTreePath 
*wxgtk_list_store_get_path        (GtkTreeModel      
*tree_model
, 
  96 static void         wxgtk_list_store_get_value       (GtkTreeModel      
*tree_model
, 
 100 static gboolean     
wxgtk_list_store_iter_next       (GtkTreeModel      
*tree_model
, 
 102 static gboolean     
wxgtk_list_store_iter_children   (GtkTreeModel      
*tree_model
, 
 104                                                     GtkTreeIter       
*parent
); 
 105 static gboolean     
wxgtk_list_store_iter_has_child  (GtkTreeModel      
*tree_model
, 
 107 static gint         
wxgtk_list_store_iter_n_children (GtkTreeModel      
*tree_model
, 
 109 static gboolean     
wxgtk_list_store_iter_nth_child  (GtkTreeModel      
*tree_model
, 
 113 static gboolean     
wxgtk_list_store_iter_parent     (GtkTreeModel      
*tree_model
, 
 117 static GObjectClass 
*list_parent_class 
= NULL
; 
 120 gtk_wx_list_store_get_type (void) 
 122   static GType list_store_type 
= 0; 
 124   if (!list_store_type
) 
 126       static const GTypeInfo list_store_info 
= 
 128         sizeof (GtkWxListStoreClass
), 
 129         NULL
,           /* base_init */ 
 130         NULL
,           /* base_finalize */ 
 131         (GClassInitFunc
) wxgtk_list_store_class_init
, 
 132         NULL
,           /* class_finalize */ 
 133         NULL
,           /* class_data */ 
 134         sizeof (GtkWxListStore
), 
 136         (GInstanceInitFunc
) wxgtk_list_store_init
, 
 139       static const GInterfaceInfo tree_model_info 
= 
 141         (GInterfaceInitFunc
) wxgtk_list_store_tree_model_init
, 
 146       list_store_type 
= g_type_register_static (G_TYPE_OBJECT
, "GtkWxListStore", 
 147                                                 &list_store_info
, (GTypeFlags
)0 ); 
 149       g_type_add_interface_static (list_store_type
, 
 154   return list_store_type
; 
 157 static GtkWxListStore 
* 
 158 wxgtk_list_store_new(void) 
 160     GtkWxListStore 
*retval 
= (GtkWxListStore 
*) g_object_new (GTK_TYPE_WX_LIST_STORE
, NULL
); 
 165 wxgtk_list_store_class_init (GtkWxListStoreClass 
*klass
) 
 167     list_parent_class 
= (GObjectClass
*) g_type_class_peek_parent (klass
); 
 168     GObjectClass 
*object_class 
= (GObjectClass
*) klass
; 
 169     object_class
->finalize 
= wxgtk_list_store_finalize
; 
 173 wxgtk_list_store_tree_model_init (GtkTreeModelIface 
*iface
) 
 175     iface
->get_flags 
= wxgtk_list_store_get_flags
; 
 176     iface
->get_n_columns 
= wxgtk_list_store_get_n_columns
; 
 177     iface
->get_column_type 
= wxgtk_list_store_get_column_type
; 
 178     iface
->get_iter 
= wxgtk_list_store_get_iter
; 
 179     iface
->get_path 
= wxgtk_list_store_get_path
; 
 180     iface
->get_value 
= wxgtk_list_store_get_value
; 
 181     iface
->iter_next 
= wxgtk_list_store_iter_next
; 
 182     iface
->iter_children 
= wxgtk_list_store_iter_children
; 
 183     iface
->iter_has_child 
= wxgtk_list_store_iter_has_child
; 
 184     iface
->iter_n_children 
= wxgtk_list_store_iter_n_children
; 
 185     iface
->iter_nth_child 
= wxgtk_list_store_iter_nth_child
; 
 186     iface
->iter_parent 
= wxgtk_list_store_iter_parent
; 
 190 wxgtk_list_store_init (GtkWxListStore 
*list_store
) 
 192     list_store
->model 
= NULL
; 
 193     list_store
->stamp 
= g_random_int(); 
 197 wxgtk_list_store_finalize (GObject 
*object
) 
 199     /* GtkWxListStore *list_store = GTK_WX_LIST_STORE (object); */ 
 201     /* we need to sort out, which class deletes what */ 
 202     /* delete list_store->model; */ 
 205     (* list_parent_class
->finalize
) (object
); 
 210 //----------------------------------------------------------------------------- 
 211 // implement callbacks from wxGtkListStore class by letting 
 212 // them call the methods of wxWidgets' wxDataViewListModel 
 213 //----------------------------------------------------------------------------- 
 215 static GtkTreeModelFlags
 
 216 wxgtk_list_store_get_flags (GtkTreeModel 
*tree_model
) 
 218     g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), (GtkTreeModelFlags
)0 ); 
 220     // GTK+ list store uses a linked list for storing the 
 221     // items and a pointer to a child is used as the member 
 222     // field of a GtkTreeIter. This means that the iter is 
 223     // valid in the GtkListStore as long as the child exists. 
 224     // We use the index of the row and since the index of a 
 225     // specific row will change if a row above is deleted, 
 226     // the iter does not persist 
 227     return /* GTK_TREE_MODEL_ITERS_PERSIST | */ GTK_TREE_MODEL_LIST_ONLY
; 
 231 wxgtk_list_store_get_n_columns (GtkTreeModel 
*tree_model
) 
 233     GtkWxListStore 
*list_store 
= (GtkWxListStore 
*) tree_model
; 
 234     g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), 0); 
 236     return list_store
->model
->GetNumberOfCols(); 
 240 wxgtk_list_store_get_column_type (GtkTreeModel 
*tree_model
, 
 243     GtkWxListStore 
*list_store 
= (GtkWxListStore 
*) tree_model
; 
 244     g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), G_TYPE_INVALID
); 
 246     GType gtype 
= G_TYPE_INVALID
; 
 248     wxString wxtype 
= list_store
->model
->GetColType( (size_t) index 
); 
 250     if (wxtype 
== wxT("string")) 
 251         gtype 
= G_TYPE_STRING
; 
 257 wxgtk_list_store_get_iter (GtkTreeModel 
*tree_model
, 
 261     GtkWxListStore 
*list_store 
= (GtkWxListStore 
*) tree_model
; 
 262     g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), FALSE
); 
 263     g_return_val_if_fail (gtk_tree_path_get_depth (path
) > 0, FALSE
); 
 265     size_t i 
= (size_t)gtk_tree_path_get_indices (path
)[0]; 
 267     if (i 
>= list_store
->model
->GetNumberOfRows()) 
 270     iter
->stamp 
= list_store
->stamp
; 
 271     // user_data is just the index 
 272     iter
->user_data 
= (gpointer
) i
; 
 278 wxgtk_list_store_get_path (GtkTreeModel 
*tree_model
, 
 281     g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), NULL
); 
 282     g_return_val_if_fail (iter
->stamp 
== GTK_WX_LIST_STORE (tree_model
)->stamp
, NULL
); 
 284     GtkTreePath 
*retval 
= gtk_tree_path_new (); 
 285     // user_data is just the index 
 286     int i 
= (int) iter
->user_data
; 
 287     gtk_tree_path_append_index (retval
, i
); 
 292 wxgtk_list_store_get_value (GtkTreeModel 
*tree_model
, 
 297     GtkWxListStore 
*list_store 
= (GtkWxListStore 
*) tree_model
; 
 298     g_return_if_fail (GTK_IS_WX_LIST_STORE (tree_model
) ); 
 300     wxDataViewListModel 
*model 
= list_store
->model
; 
 301     wxString mtype 
= model
->GetColType( (size_t) column 
); 
 302     if (mtype 
== wxT("string")) 
 304         g_value_init( value
, G_TYPE_STRING 
); 
 305         wxVariant variant 
= model
->GetValue( (size_t) column
, (size_t) iter
->user_data 
); 
 306         g_value_set_string( value
, wxGTK_CONV(variant
.GetString()) ); 
 313   GtkTreeDataList 
*list
; 
 314   gint tmp_column 
= column
; 
 316   g_return_if_fail (column 
< GTK_LIST_STORE (tree_model
)->n_columns
); 
 317   g_return_if_fail (GTK_LIST_STORE (tree_model
)->stamp 
== iter
->stamp
); 
 319   list 
= G_SLIST (iter
->user_data
)->data
; 
 321   while (tmp_column
-- > 0 && list
) 
 325     g_value_init (value
, GTK_LIST_STORE (tree_model
)->column_headers
[column
]); 
 327     _gtk_tree_data_list_node_to_value (list
, 
 328                                        GTK_LIST_STORE (tree_model
)->column_headers
[column
], 
 335 wxgtk_list_store_iter_next (GtkTreeModel  
*tree_model
, 
 338     g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), FALSE
); 
 339     GtkWxListStore 
*list_store 
= (GtkWxListStore 
*) tree_model
; 
 341     g_return_val_if_fail (list_store
->stamp 
== iter
->stamp
, FALSE
); 
 343     int n 
= (int) iter
->user_data
; 
 348     if (n 
>= (int) list_store
->model
->GetNumberOfRows()-1) 
 351     iter
->user_data 
= (gpointer
) ++n
; 
 357 wxgtk_list_store_iter_children (GtkTreeModel 
*tree_model
, 
 361     g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), FALSE
); 
 362     GtkWxListStore 
*list_store 
= (GtkWxListStore 
*) tree_model
; 
 364     // this is a list, nodes have no children 
 368     iter
->stamp 
= list_store
->stamp
; 
 369     iter
->user_data 
= (gpointer
) -1; 
 375 wxgtk_list_store_iter_has_child (GtkTreeModel 
*tree_model
, 
 382 wxgtk_list_store_iter_n_children (GtkTreeModel 
*tree_model
, 
 385     g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), -1); 
 386     GtkWxListStore 
*list_store 
= (GtkWxListStore 
*) tree_model
; 
 389         return (gint
) list_store
->model
->GetNumberOfRows(); 
 391     g_return_val_if_fail (list_store
->stamp 
== iter
->stamp
, -1); 
 397 wxgtk_list_store_iter_nth_child (GtkTreeModel 
*tree_model
, 
 402     g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), FALSE
); 
 403     GtkWxListStore 
*list_store 
= (GtkWxListStore 
*) tree_model
; 
 411     if (n 
>= (gint
) list_store
->model
->GetNumberOfRows()) 
 414     iter
->stamp 
= list_store
->stamp
; 
 415     iter
->user_data 
= (gpointer
) n
; 
 421 wxgtk_list_store_iter_parent (GtkTreeModel 
*tree_model
, 
 428 //----------------------------------------------------------------------------- 
 429 // define new GTK+ class wxGtkCellRenderer 
 430 //----------------------------------------------------------------------------- 
 434 #define GTK_TYPE_WX_CELL_RENDERER               (gtk_wx_cell_renderer_get_type ()) 
 435 #define GTK_WX_CELL_RENDERER(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRenderer)) 
 436 #define GTK_WX_CELL_RENDERER_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRendererClass)) 
 437 #define GTK_IS_WX_CELL_RENDERER(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WX_CELL_RENDERER)) 
 438 #define GTK_IS_WX_CELL_RENDERER_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WX_CELL_RENDERER)) 
 439 #define GTK_WX_CELL_RENDERER_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRendererClass)) 
 441 GType            
gtk_wx_cell_renderer_get_type (void); 
 443 typedef struct _GtkWxCellRenderer GtkWxCellRenderer
; 
 444 typedef struct _GtkWxCellRendererClass GtkWxCellRendererClass
; 
 446 struct _GtkWxCellRenderer
 
 448   GtkCellRenderer parent
; 
 451   wxDataViewCustomCell 
*cell
; 
 455 struct _GtkWxCellRendererClass
 
 457   GtkCellRendererClass cell_parent_class
; 
 461 static GtkCellRenderer 
*gtk_wx_cell_renderer_new   (void); 
 462 static void gtk_wx_cell_renderer_init ( 
 463                         GtkWxCellRenderer      
*cell 
); 
 464 static void gtk_wx_cell_renderer_class_init( 
 465                         GtkWxCellRendererClass 
*klass 
); 
 466 static void gtk_wx_cell_renderer_finalize ( 
 468 static void gtk_wx_cell_renderer_get_size ( 
 469                         GtkCellRenderer         
*cell
, 
 471                                                 GdkRectangle            
*rectangle
, 
 476 static void gtk_wx_cell_renderer_render ( 
 477                         GtkCellRenderer         
*cell
, 
 480                                                 GdkRectangle            
*background_area
, 
 481                                                 GdkRectangle            
*cell_area
, 
 482                                                 GdkRectangle            
*expose_area
, 
 483                                                 GtkCellRendererState     flags 
); 
 484 static gboolean 
gtk_wx_cell_renderer_activate( 
 485                         GtkCellRenderer         
*cell
, 
 489                         GdkRectangle            
*background_area
, 
 490                         GdkRectangle            
*cell_area
, 
 491                         GtkCellRendererState     flags 
); 
 493 static GObjectClass 
*cell_parent_class 
= NULL
; 
 498 gtk_wx_cell_renderer_get_type (void) 
 500     static GType cell_wx_type 
= 0; 
 504         static const GTypeInfo cell_wx_info 
= 
 506             sizeof (GtkWxCellRendererClass
), 
 507             NULL
,               /* base_init */ 
 508             NULL
,               /* base_finalize */ 
 509             (GClassInitFunc
) gtk_wx_cell_renderer_class_init
, 
 510             NULL
,               /* class_finalize */ 
 511             NULL
,               /* class_data */ 
 512             sizeof (GtkWxCellRenderer
), 
 514             (GInstanceInitFunc
) gtk_wx_cell_renderer_init
, 
 517         cell_wx_type 
= g_type_register_static( GTK_TYPE_CELL_RENDERER
,  
 518             "GtkWxCellRenderer", &cell_wx_info
, (GTypeFlags
)0 ); 
 525 gtk_wx_cell_renderer_init (GtkWxCellRenderer 
*cell
) 
 528     cell
->last_click 
= 0; 
 532 gtk_wx_cell_renderer_class_init (GtkWxCellRendererClass 
*klass
) 
 534     GObjectClass 
*object_class 
= G_OBJECT_CLASS (klass
); 
 535     GtkCellRendererClass 
*cell_class 
= GTK_CELL_RENDERER_CLASS (klass
); 
 537     cell_parent_class 
= (GObjectClass
*) g_type_class_peek_parent (klass
); 
 539     object_class
->finalize 
= gtk_wx_cell_renderer_finalize
; 
 541     cell_class
->get_size 
= gtk_wx_cell_renderer_get_size
; 
 542     cell_class
->render 
= gtk_wx_cell_renderer_render
; 
 543     cell_class
->activate 
= gtk_wx_cell_renderer_activate
; 
 547 gtk_wx_cell_renderer_finalize (GObject 
*object
) 
 550     (* G_OBJECT_CLASS (cell_parent_class
)->finalize
) (object
); 
 554 gtk_wx_cell_renderer_new (void) 
 556     return (GtkCellRenderer
*) g_object_new (GTK_TYPE_WX_CELL_RENDERER
, NULL
); 
 560 gtk_wx_cell_renderer_get_size (GtkCellRenderer 
*renderer
, 
 562                                    GdkRectangle    
*cell_area
, 
 568     GtkWxCellRenderer 
*wxrenderer 
= (GtkWxCellRenderer 
*) renderer
; 
 569     wxDataViewCustomCell 
*cell 
= wxrenderer
->cell
; 
 571     wxSize size 
= cell
->GetSize(); 
 573     gint calc_width  
= (gint
) renderer
->xpad 
* 2 + size
.x
; 
 574     gint calc_height 
= (gint
) renderer
->ypad 
* 2 + size
.y
; 
 581     if (cell_area 
&& size
.x 
> 0 && size
.y 
> 0) 
 585             *x_offset 
= (gint
)((renderer
->xalign 
* 
 586                                (cell_area
->width 
- calc_width 
- 2 * renderer
->xpad
))); 
 587             *x_offset 
= MAX (*x_offset
, 0) + renderer
->xpad
; 
 591             *y_offset 
= (gint
)((renderer
->yalign 
* 
 592                                (cell_area
->height 
- calc_height 
- 2 * renderer
->ypad
))); 
 593             *y_offset 
= MAX (*y_offset
, 0) + renderer
->ypad
; 
 601         *height 
= calc_height
; 
 605 gtk_wx_cell_renderer_render (GtkCellRenderer      
*renderer
, 
 608                                  GdkRectangle         
*background_area
, 
 609                                  GdkRectangle         
*cell_area
, 
 610                                  GdkRectangle         
*expose_area
, 
 611                                  GtkCellRendererState  flags
) 
 614     GtkWxCellRenderer 
*wxrenderer 
= (GtkWxCellRenderer 
*) renderer
; 
 615     wxDataViewCustomCell 
*cell 
= wxrenderer
->cell
; 
 618     gtk_wx_cell_renderer_get_size (renderer
, widget
, cell_area
, 
 624     rect
.x 
+= cell_area
->x
; 
 625     rect
.y 
+= cell_area
->y
; 
 626     rect
.width  
-= renderer
->xpad 
* 2; 
 627     rect
.height 
-= renderer
->ypad 
* 2; 
 630     if (gdk_rectangle_intersect (expose_area
, &rect
, &dummy
)) 
 632         wxRect 
renderrect( rect
.x
, rect
.y
, rect
.width
, rect
.height 
); 
 633         wxWindowDC
* dc 
= (wxWindowDC
*) cell
->GetDC(); 
 634         if (dc
->m_window 
== NULL
) 
 636             dc
->m_window 
= window
; 
 641         if (flags 
& GTK_CELL_RENDERER_SELECTED
) 
 642             state 
|= wxDATAVIEW_CELL_SELECTED
; 
 643         if (flags 
& GTK_CELL_RENDERER_PRELIT
) 
 644             state 
|= wxDATAVIEW_CELL_PRELIT
; 
 645         if (flags 
& GTK_CELL_RENDERER_INSENSITIVE
) 
 646             state 
|= wxDATAVIEW_CELL_INSENSITIVE
; 
 647         if (flags 
& GTK_CELL_RENDERER_INSENSITIVE
) 
 648             state 
|= wxDATAVIEW_CELL_INSENSITIVE
; 
 649         if (flags 
& GTK_CELL_RENDERER_FOCUSED
) 
 650             state 
|= wxDATAVIEW_CELL_FOCUSED
; 
 651         cell
->Render( renderrect
, dc
, state 
); 
 656 gtk_wx_cell_renderer_activate( 
 657                         GtkCellRenderer         
*renderer
, 
 661                         GdkRectangle            
*background_area
, 
 662                         GdkRectangle            
*cell_area
, 
 663                         GtkCellRendererState     flags 
) 
 665     GtkWxCellRenderer 
*wxrenderer 
= (GtkWxCellRenderer 
*) renderer
; 
 666     wxDataViewCustomCell 
*cell 
= wxrenderer
->cell
; 
 669     gtk_wx_cell_renderer_get_size (renderer
, widget
, cell_area
, 
 675     rect
.x 
+= cell_area
->x
; 
 676     rect
.y 
+= cell_area
->y
; 
 677     rect
.width  
-= renderer
->xpad 
* 2; 
 678     rect
.height 
-= renderer
->ypad 
* 2; 
 680     wxRect 
renderrect( rect
.x
, rect
.y
, rect
.width
, rect
.height 
); 
 682     wxDataViewListModel 
*model 
= cell
->GetOwner()->GetOwner()->GetModel(); 
 684     GtkTreePath 
*treepath 
= gtk_tree_path_new_from_string( path 
); 
 685     size_t model_row 
= (size_t)gtk_tree_path_get_indices (treepath
)[0]; 
 686     gtk_tree_path_free( treepath 
); 
 688     size_t model_col 
= cell
->GetOwner()->GetModelColumn(); 
 690     if (event
->type 
== GDK_BUTTON_PRESS
) 
 692         GdkEventButton 
*button_event 
= (GdkEventButton
*) event
; 
 693         wxPoint 
pt( ((int) button_event
->x
) - renderrect
.x
,  
 694                     ((int) button_event
->y
) - renderrect
.y 
); 
 697         if (button_event
->button 
== 1) 
 699             if (cell
->LeftClick( pt
, renderrect
, model
, model_col
, model_row 
)) 
 701             if (button_event
->time 
- wxrenderer
->last_click 
< 400) 
 702                 if (cell
->Activate( renderrect
, model
, model_col
, model_row 
)) 
 705         if (button_event
->button 
== 3) 
 707             if (cell
->RightClick( pt
, renderrect
, model
, model_col
, model_row 
)) 
 711         wxrenderer
->last_click 
= button_event
->time
; 
 716     if (event
->type 
== GDK_KEY_PRESS
) 
 718         wxPrintf( wxT("key\n") ); 
 719         GdkEventKey 
*key_event 
= (GdkEventKey
*) event
; 
 720         if ((key_event
->keyval 
== GDK_Return
) || 
 721             (key_event
->keyval 
== GDK_Linefeed
) ||  
 722             (key_event
->keyval 
== GDK_Execute
)) 
 724             return cell
->Activate( renderrect
, model
, model_col
, model_row 
); 
 731 // ---------------------------------------------------------  
 732 // wxGtkDataViewListModelNotifier 
 733 // ---------------------------------------------------------  
 735 class wxGtkDataViewListModelNotifier
: public wxDataViewListModelNotifier
 
 738     wxGtkDataViewListModelNotifier( GtkWxListStore
* gtk_store
, wxDataViewListModel 
*wx_model 
); 
 740     virtual bool RowAppended(); 
 741     virtual bool RowPrepended(); 
 742     virtual bool RowInserted( size_t before 
); 
 743     virtual bool RowDeleted( size_t row 
); 
 744     virtual bool RowChanged( size_t row 
); 
 745     virtual bool ValueChanged( size_t col
, size_t row 
); 
 746     virtual bool Cleared(); 
 748     GtkWxListStore      
*m_gtk_store
; 
 749     wxDataViewListModel 
*m_wx_model
; 
 752 // ---------------------------------------------------------  
 753 // wxGtkDataViewListModelNotifier 
 754 // ---------------------------------------------------------  
 756 wxGtkDataViewListModelNotifier::wxGtkDataViewListModelNotifier(  
 757     GtkWxListStore
* gtk_store
, wxDataViewListModel 
*wx_model 
) 
 759     m_gtk_store 
= gtk_store
; 
 760     m_wx_model 
= wx_model
; 
 763 bool wxGtkDataViewListModelNotifier::RowAppended() 
 765     size_t pos 
= m_wx_model
->GetNumberOfRows()-1; 
 768     iter
.stamp 
= m_gtk_store
->stamp
; 
 769     iter
.user_data 
= (gpointer
) pos
; 
 771     GtkTreePath 
*path 
= gtk_tree_path_new (); 
 772     gtk_tree_path_append_index (path
, (gint
) pos
); 
 773     gtk_tree_model_row_inserted (GTK_TREE_MODEL (m_gtk_store
), path
, &iter
); 
 774     gtk_tree_path_free (path
); 
 779 bool wxGtkDataViewListModelNotifier::RowPrepended() 
 782     iter
.stamp 
= m_gtk_store
->stamp
; 
 783     iter
.user_data 
= (gpointer
) 0; 
 785     GtkTreePath 
*path 
= gtk_tree_path_new (); 
 786     gtk_tree_path_append_index (path
, (gint
) 0); 
 787     gtk_tree_model_row_inserted (GTK_TREE_MODEL (m_gtk_store
), path
, &iter
); 
 788     gtk_tree_path_free (path
); 
 793 bool wxGtkDataViewListModelNotifier::RowInserted( size_t before 
) 
 798 bool wxGtkDataViewListModelNotifier::RowDeleted( size_t row 
) 
 803 bool wxGtkDataViewListModelNotifier::RowChanged( size_t row 
) 
 806     iter
.stamp 
= m_gtk_store
->stamp
; 
 807     iter
.user_data 
= (gpointer
) row
; 
 808     GtkTreePath 
*path 
= gtk_tree_model_get_path (GTK_TREE_MODEL (m_gtk_store
), &iter
); 
 809     gtk_tree_model_row_changed (GTK_TREE_MODEL (m_gtk_store
), path
, &iter
); 
 810     gtk_tree_path_free (path
); 
 815 bool wxGtkDataViewListModelNotifier::ValueChanged( size_t col
, size_t row 
) 
 817     return RowChanged( row 
); 
 820 bool wxGtkDataViewListModelNotifier::Cleared() 
 825 // ---------------------------------------------------------  
 827 // ---------------------------------------------------------  
 829 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCell
, wxDataViewCellBase
) 
 831 wxDataViewCell::wxDataViewCell( const wxString 
&varianttype
, wxDataViewCellMode mode 
) : 
 832     wxDataViewCellBase( varianttype
, mode 
) 
 837 // ---------------------------------------------------------  
 838 // wxDataViewTextCell 
 839 // ---------------------------------------------------------  
 842 static void wxGtkTextRendererEditedCallback( GtkCellRendererText 
*renderer
,  
 843     gchar 
*arg1
, gchar 
*arg2
, gpointer user_data 
); 
 846 static void wxGtkTextRendererEditedCallback( GtkCellRendererText 
*renderer
,  
 847     gchar 
*arg1
, gchar 
*arg2
, gpointer user_data 
) 
 849     wxDataViewTextCell 
*cell 
= (wxDataViewTextCell
*) user_data
; 
 851     wxString tmp 
= wxGTK_CONV_BACK( arg2 
); 
 852     wxVariant value 
= tmp
; 
 853     if (!cell
->Validate( value 
)) 
 856     wxDataViewListModel 
*model 
= cell
->GetOwner()->GetOwner()->GetModel(); 
 858     GtkTreePath 
*path 
= gtk_tree_path_new_from_string( arg1 
); 
 859     size_t model_row 
= (size_t)gtk_tree_path_get_indices (path
)[0]; 
 860     gtk_tree_path_free( path 
); 
 862     size_t model_col 
= cell
->GetOwner()->GetModelColumn(); 
 864     model
->SetValue( value
, model_col
, model_row 
); 
 865     model
->ValueChanged( model_col
, model_row 
); 
 868 IMPLEMENT_ABSTRACT_CLASS(wxDataViewTextCell
, wxDataViewCell
) 
 870 wxDataViewTextCell::wxDataViewTextCell( const wxString 
&varianttype
, wxDataViewCellMode mode 
) : 
 871     wxDataViewCell( varianttype
, mode 
) 
 873     m_renderer 
= (void*) gtk_cell_renderer_text_new(); 
 875     if (m_mode 
& wxDATAVIEW_CELL_EDITABLE
) 
 877         GValue gvalue 
= { 0, }; 
 878         g_value_init( &gvalue
, G_TYPE_BOOLEAN 
); 
 879         g_value_set_boolean( &gvalue
, true ); 
 880         g_object_set_property( G_OBJECT(m_renderer
), "editable", &gvalue 
); 
 881         g_value_unset( &gvalue 
); 
 883         g_signal_connect_after( m_renderer
, "edited", G_CALLBACK(wxGtkTextRendererEditedCallback
), this ); 
 887 bool wxDataViewTextCell::SetValue( const wxVariant 
&value 
) 
 889     wxString tmp 
= value
; 
 891     GValue gvalue 
= { 0, }; 
 892     g_value_init( &gvalue
, G_TYPE_STRING 
); 
 893     g_value_set_string( &gvalue
, wxGTK_CONV( tmp 
) ); 
 894     g_object_set_property( G_OBJECT(m_renderer
), "text", &gvalue 
); 
 895     g_value_unset( &gvalue 
); 
 900 bool wxDataViewTextCell::GetValue( wxVariant 
&value 
) 
 902     GValue gvalue 
= { 0, }; 
 903     g_value_init( &gvalue
, G_TYPE_STRING 
); 
 904     g_object_get_property( G_OBJECT(m_renderer
), "text", &gvalue 
); 
 905     wxString tmp 
= wxGTK_CONV_BACK( g_value_get_string( &gvalue 
) );  
 906     g_value_unset( &gvalue 
); 
 913 // ---------------------------------------------------------  
 914 // wxDataViewToggleCell 
 915 // ---------------------------------------------------------  
 918 static void wxGtkToggleRendererToggledCallback( GtkCellRendererToggle 
*renderer
,  
 919     gchar 
*path
, gpointer user_data 
); 
 922 static void wxGtkToggleRendererToggledCallback( GtkCellRendererToggle 
*renderer
,  
 923     gchar 
*path
, gpointer user_data 
) 
 925     wxDataViewToggleCell 
*cell 
= (wxDataViewToggleCell
*) user_data
; 
 928     GValue gvalue 
= { 0, }; 
 929     g_value_init( &gvalue
, G_TYPE_BOOLEAN 
); 
 930     g_object_get_property( G_OBJECT(renderer
), "active", &gvalue 
); 
 931     bool tmp 
= g_value_get_boolean( &gvalue 
);  
 932     g_value_unset( &gvalue 
); 
 936     wxVariant value 
= tmp
; 
 937     if (!cell
->Validate( value 
)) 
 940     wxDataViewListModel 
*model 
= cell
->GetOwner()->GetOwner()->GetModel(); 
 942     GtkTreePath 
*gtk_path 
= gtk_tree_path_new_from_string( path 
); 
 943     size_t model_row 
= (size_t)gtk_tree_path_get_indices (gtk_path
)[0]; 
 944     gtk_tree_path_free( gtk_path 
); 
 946     size_t model_col 
= cell
->GetOwner()->GetModelColumn(); 
 948     model
->SetValue( value
, model_col
, model_row 
); 
 949     model
->ValueChanged( model_col
, model_row 
); 
 952 IMPLEMENT_ABSTRACT_CLASS(wxDataViewToggleCell
, wxDataViewCell
) 
 954 wxDataViewToggleCell::wxDataViewToggleCell( const wxString 
&varianttype
,  
 955                         wxDataViewCellMode mode 
) : 
 956     wxDataViewCell( varianttype
, mode 
) 
 958     m_renderer 
= (void*) gtk_cell_renderer_toggle_new(); 
 960     if (m_mode 
& wxDATAVIEW_CELL_EDITABLE
) 
 962         g_signal_connect_after( m_renderer
, "toggled", G_CALLBACK(wxGtkToggleRendererToggledCallback
), this ); 
 967         GValue gvalue 
= { 0, }; 
 968         g_value_init( &gvalue
, G_TYPE_BOOLEAN 
); 
 969         g_value_set_boolean( &gvalue
, false ); 
 970         g_object_set_property( G_OBJECT(m_renderer
), "activatable", &gvalue 
); 
 971         g_value_unset( &gvalue 
); 
 973         GValue gvalue2 
= { 0, }; 
 974         g_value_init( &gvalue2
, gtk_cell_renderer_mode_get_type() ); 
 975         g_value_set_enum( &gvalue2
, GTK_CELL_RENDERER_MODE_INERT 
); 
 976         g_object_set_property( G_OBJECT(m_renderer
), "mode", &gvalue2 
); 
 977         g_value_unset( &gvalue2 
); 
 982 bool wxDataViewToggleCell::SetValue( const wxVariant 
&value 
) 
 986     GValue gvalue 
= { 0, }; 
 987     g_value_init( &gvalue
, G_TYPE_BOOLEAN 
); 
 988     g_value_set_boolean( &gvalue
, tmp 
); 
 989     g_object_set_property( G_OBJECT(m_renderer
), "active", &gvalue 
); 
 990     g_value_unset( &gvalue 
); 
 995 bool wxDataViewToggleCell::GetValue( wxVariant 
&value 
) 
 997     GValue gvalue 
= { 0, }; 
 998     g_value_init( &gvalue
, G_TYPE_BOOLEAN 
); 
 999     g_object_get_property( G_OBJECT(m_renderer
), "active", &gvalue 
); 
1000     bool tmp 
= g_value_get_boolean( &gvalue 
);  
1001     g_value_unset( &gvalue 
); 
1008 // ---------------------------------------------------------  
1009 // wxDataViewCustomCell 
1010 // ---------------------------------------------------------  
1012 class wxDataViewCtrlDC
: public wxWindowDC
 
1015     wxDataViewCtrlDC( wxDataViewCtrl 
*window 
) 
1017         GtkWidget 
*widget 
= window
->m_treeview
; 
1021         m_context 
= window
->GtkGetPangoDefaultContext(); 
1022         m_layout 
= pango_layout_new( m_context 
); 
1023         m_fontdesc 
= pango_font_description_copy( widget
->style
->font_desc 
); 
1025         m_cmap 
= gtk_widget_get_colormap( widget 
? widget 
: window
->m_widget 
); 
1027         // Set m_window later 
1029         // m_owner = window; 
1033 // ---------------------------------------------------------  
1034 // wxDataViewCustomCell 
1035 // ---------------------------------------------------------  
1037 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCustomCell
, wxDataViewCell
) 
1039 wxDataViewCustomCell::wxDataViewCustomCell( const wxString 
&varianttype
,  
1040                           wxDataViewCellMode mode
, bool no_init 
) : 
1041     wxDataViewCell( varianttype
, mode 
) 
1051 bool wxDataViewCustomCell::Init() 
1053     GtkWxCellRenderer 
*renderer 
= (GtkWxCellRenderer 
*) gtk_wx_cell_renderer_new(); 
1054     renderer
->cell 
= this; 
1056     m_renderer 
= (void*) renderer
; 
1058     if (m_mode 
& wxDATAVIEW_CELL_ACTIVATABLE
) 
1060         GValue gvalue 
= { 0, }; 
1061         g_value_init( &gvalue
, gtk_cell_renderer_mode_get_type() ); 
1062         g_value_set_enum( &gvalue
, GTK_CELL_RENDERER_MODE_ACTIVATABLE 
); 
1063         g_object_set_property( G_OBJECT(m_renderer
), "mode", &gvalue 
); 
1064         g_value_unset( &gvalue 
); 
1070 wxDataViewCustomCell::~wxDataViewCustomCell() 
1076 wxDC 
*wxDataViewCustomCell::GetDC() 
1080         if (GetOwner() == NULL
) 
1082         if (GetOwner()->GetOwner() == NULL
) 
1084         m_dc 
= new wxDataViewCtrlDC( GetOwner()->GetOwner() ); 
1090 // ---------------------------------------------------------  
1091 // wxDataViewProgressCell 
1092 // ---------------------------------------------------------  
1094 IMPLEMENT_ABSTRACT_CLASS(wxDataViewProgressCell
, wxDataViewCustomCell
) 
1096 wxDataViewProgressCell::wxDataViewProgressCell( const wxString 
&label
,  
1097     const wxString 
&varianttype
, wxDataViewCellMode mode 
) : 
1098     wxDataViewCustomCell( varianttype
, mode
, true )   
1104     if (!gtk_check_version(2,6,0)) 
1106         m_renderer 
= (void*) gtk_cell_renderer_progress_new(); 
1108         GValue gvalue 
= { 0, }; 
1109         g_value_init( &gvalue
, G_TYPE_STRING 
); 
1110         g_value_set_boolean( &gvalue
, wxGTK_CONV(m_label
) ); 
1111         g_object_set_property( G_OBJECT(m_renderer
), "text", &gvalue 
); 
1112         g_value_unset( &gvalue 
); 
1117         // Use custom cell code 
1118         wxDataViewCustomCell::Init(); 
1122 wxDataViewProgressCell::~wxDataViewProgressCell() 
1126 bool wxDataViewProgressCell::SetValue( const wxVariant 
&value 
) 
1129     if (!gtk_check_version(2,6,0)) 
1131         gint tmp 
= (int) value
; 
1132         GValue gvalue 
= { 0, }; 
1133         g_value_init( &gvalue
, G_TYPE_INT 
); 
1134         g_value_set_boolean( &gvalue
, tmp 
); 
1135         g_object_set_property( G_OBJECT(m_renderer
), "value", &gvalue 
); 
1136         g_value_unset( &gvalue 
); 
1141         m_value 
= (long) value
; 
1143         if (m_value 
< 0) m_value 
= 0; 
1144         if (m_value 
> 100) m_value 
= 100; 
1150 bool wxDataViewProgressCell::Render( wxRect cell
, wxDC 
*dc
, int state 
) 
1152     double pct 
= (double)m_value 
/ 100.0; 
1154     bar
.width 
= (int)(cell
.width 
* pct
); 
1155     dc
->SetPen( *wxTRANSPARENT_PEN 
); 
1156     dc
->SetBrush( *wxBLUE_BRUSH 
); 
1157     dc
->DrawRectangle( bar 
); 
1159     dc
->SetBrush( *wxTRANSPARENT_BRUSH 
); 
1160     dc
->SetPen( *wxBLACK_PEN 
); 
1161     dc
->DrawRectangle( cell 
); 
1166 wxSize 
wxDataViewProgressCell::GetSize() 
1168     return wxSize(40,12); 
1171 // ---------------------------------------------------------  
1172 // wxDataViewDateCell 
1173 // ---------------------------------------------------------  
1175 IMPLEMENT_ABSTRACT_CLASS(wxDataViewDateCell
, wxDataViewCustomCell
) 
1177 wxDataViewDateCell::wxDataViewDateCell( const wxString 
&varianttype
, 
1178                         wxDataViewCellMode mode 
) : 
1179     wxDataViewCustomCell( varianttype
, mode 
) 
1183 bool wxDataViewDateCell::SetValue( const wxVariant 
&value 
) 
1185     m_date 
= value
.GetDateTime(); 
1190 bool wxDataViewDateCell::Render( wxRect cell
, wxDC 
*dc
, int state 
) 
1192     dc
->SetFont( GetOwner()->GetOwner()->GetFont() ); 
1193     wxString tmp 
= m_date
.FormatDate(); 
1194     dc
->DrawText( tmp
, cell
.x
, cell
.y 
); 
1199 wxSize 
wxDataViewDateCell::GetSize() 
1201     wxDataViewCtrl
* view 
= GetOwner()->GetOwner(); 
1202     wxString tmp 
= m_date
.FormatDate(); 
1204     view
->GetTextExtent( tmp
, &x
, &y
, &d 
); 
1205     return wxSize(x
,y
+d
); 
1208 bool wxDataViewDateCell::Activate( wxRect cell
, wxDataViewListModel 
*model
, size_t col
, size_t row 
) 
1214 // ---------------------------------------------------------  
1216 // ---------------------------------------------------------  
1219 static void wxGtkTreeCellDataFunc( GtkTreeViewColumn 
*column
, 
1220                             GtkCellRenderer 
*cell
, 
1221                             GtkTreeModel 
*model
, 
1227 static void wxGtkTreeCellDataFunc( GtkTreeViewColumn 
*column
, 
1228                             GtkCellRenderer 
*renderer
, 
1229                             GtkTreeModel 
*model
, 
1233     g_return_if_fail (GTK_IS_WX_LIST_STORE (model
)); 
1234     GtkWxListStore 
*list_store 
= (GtkWxListStore 
*) model
; 
1236     wxDataViewCell 
*cell 
= (wxDataViewCell
*) data
; 
1238     size_t model_row 
= (size_t) iter
->user_data
; 
1240     wxVariant value 
= list_store
->model
->GetValue(  
1241         cell
->GetOwner()->GetModelColumn(), model_row 
); 
1243     if (value
.GetType() != cell
->GetVariantType()) 
1244         wxPrintf( wxT("Wrong type\n") ); 
1246     cell
->SetValue( value 
); 
1249 IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumn
, wxDataViewColumnBase
) 
1251 wxDataViewColumn::wxDataViewColumn( const wxString 
&title
, wxDataViewCell 
*cell
,  
1252     size_t model_column
, int flags 
) : 
1253     wxDataViewColumnBase( title
, cell
, model_column
, flags 
) 
1255     GtkCellRenderer 
*renderer 
= (GtkCellRenderer 
*) cell
->GetGtkHandle(); 
1257     GtkTreeViewColumn 
*column 
= gtk_tree_view_column_new(); 
1259     gtk_tree_view_column_set_title( column
, wxGTK_CONV(title
) ); 
1261     gtk_tree_view_column_pack_start( column
, renderer
, TRUE 
); 
1263     gtk_tree_view_column_set_cell_data_func( column
, renderer
,  
1264         wxGtkTreeCellDataFunc
, (gpointer
) cell
, NULL 
); 
1266     m_column 
= (void*) column
; 
1269 wxDataViewColumn::~wxDataViewColumn() 
1273 void wxDataViewColumn::SetTitle( const wxString 
&title 
) 
1275     wxDataViewColumnBase::SetTitle( title 
); 
1277     GtkTreeViewColumn 
*column 
= (GtkTreeViewColumn 
*)m_column
; 
1278     gtk_tree_view_column_set_title( column
, wxGTK_CONV(title
) ); 
1281 //----------------------------------------------------------------------------- 
1283 //----------------------------------------------------------------------------- 
1285 IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl
, wxDataViewCtrlBase
) 
1287 wxDataViewCtrl::~wxDataViewCtrl() 
1291 void wxDataViewCtrl::Init() 
1295 bool wxDataViewCtrl::Create(wxWindow 
*parent
, wxWindowID id
, 
1296            const wxPoint
& pos
, const wxSize
& size
,  
1297            long style
, const wxValidator
& validator 
) 
1301     m_needParent 
= TRUE
; 
1302     m_acceptsFocus 
= TRUE
; 
1304     if (!PreCreation( parent
, pos
, size 
) || 
1305         !CreateBase( parent
, id
, pos
, size
, style
, validator 
)) 
1307         wxFAIL_MSG( wxT("wxDataViewCtrl creation failed") ); 
1311     m_widget 
= gtk_scrolled_window_new (NULL
, NULL
); 
1312     gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (m_widget
), GTK_SHADOW_IN
); 
1314     m_treeview 
= gtk_tree_view_new(); 
1315     gtk_container_add (GTK_CONTAINER (m_widget
), m_treeview
); 
1317     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (m_widget
), 
1318         GTK_POLICY_AUTOMATIC
, GTK_POLICY_ALWAYS
); 
1319     gtk_widget_show (m_treeview
); 
1321     m_parent
->DoAddChild( this ); 
1328 bool wxDataViewCtrl::AssociateModel( wxDataViewListModel 
*model 
) 
1330     if (!wxDataViewCtrlBase::AssociateModel( model 
)) 
1333     GtkWxListStore 
*gtk_store 
= wxgtk_list_store_new(); 
1334     gtk_store
->model 
= model
; 
1336     wxGtkDataViewListModelNotifier 
*notifier 
=  
1337         new wxGtkDataViewListModelNotifier( gtk_store
, model 
); 
1339     model
->SetNotifier( notifier 
);     
1341     gtk_tree_view_set_model( GTK_TREE_VIEW(m_treeview
), GTK_TREE_MODEL(gtk_store
) ); 
1342     g_object_unref( gtk_store 
); 
1347 bool wxDataViewCtrl::AppendColumn( wxDataViewColumn 
*col 
) 
1349     if (!wxDataViewCtrlBase::AppendColumn(col
)) 
1352     GtkTreeViewColumn 
*column 
= (GtkTreeViewColumn 
*)col
->GetGtkHandle(); 
1354     gtk_tree_view_append_column( GTK_TREE_VIEW(m_treeview
), column 
); 
1360 #endif // wxUSE_DATAVIEWCTRL