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" 
  20 #include "wx/gtk/private.h" 
  21 #include "wx/gtk/win_gtk.h" 
  23 #include <gobject/gvaluecollector.h> 
  24 #include <gtk/gtktreemodel.h> 
  25 #include <gtk/gtktreednd.h> 
  27 //----------------------------------------------------------------------------- 
  29 //----------------------------------------------------------------------------- 
  33 //----------------------------------------------------------------------------- 
  35 //----------------------------------------------------------------------------- 
  37 extern void wxapp_install_idle_handler(); 
  40 //----------------------------------------------------------------------------- 
  42 //----------------------------------------------------------------------------- 
  44 extern bool   g_blockEventsOnDrag
; 
  46 //----------------------------------------------------------------------------- 
  47 // define new GTK+ class wxGtkListStore 
  48 //----------------------------------------------------------------------------- 
  52 #define GTK_TYPE_WX_LIST_STORE               (gtk_wx_list_store_get_type ()) 
  53 #define GTK_WX_LIST_STORE(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WX_LIST_STORE, GtkWxListStore)) 
  54 #define GTK_WX_LIST_STORE_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WX_LIST_STORE, GtkWxListStoreClass)) 
  55 #define GTK_IS_WX_LIST_STORE(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WX_LIST_STORE)) 
  56 #define GTK_IS_WX_LIST_STORE_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WX_LIST_STORE)) 
  57 #define GTK_WX_LIST_STORE_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WX_LIST_STORE, GtkWxListStoreClass)) 
  59 GType         
gtk_wx_list_store_get_type         (void); 
  61 typedef struct _GtkWxListStore       GtkWxListStore
; 
  62 typedef struct _GtkWxListStoreClass  GtkWxListStoreClass
; 
  64 struct _GtkWxListStore
 
  70   wxDataViewListModel 
*model
; 
  73 struct _GtkWxListStoreClass
 
  75   GObjectClass parent_class
; 
  79 static GtkWxListStore 
*wxgtk_list_store_new          (); 
  80 static void         wxgtk_list_store_init            (GtkWxListStore      
*list_store
); 
  81 static void         wxgtk_list_store_class_init      (GtkWxListStoreClass 
*klass
); 
  82 static void         wxgtk_list_store_tree_model_init (GtkTreeModelIface 
*iface
); 
  83 static void         wxgtk_list_store_finalize        (GObject           
*object
); 
  84 static GtkTreeModelFlags 
wxgtk_list_store_get_flags  (GtkTreeModel      
*tree_model
); 
  85 static gint         
wxgtk_list_store_get_n_columns   (GtkTreeModel      
*tree_model
); 
  86 static GType        
wxgtk_list_store_get_column_type (GtkTreeModel      
*tree_model
, 
  88 static gboolean     
wxgtk_list_store_get_iter        (GtkTreeModel      
*tree_model
, 
  91 static GtkTreePath 
*wxgtk_list_store_get_path        (GtkTreeModel      
*tree_model
, 
  93 static void         wxgtk_list_store_get_value       (GtkTreeModel      
*tree_model
, 
  97 static gboolean     
wxgtk_list_store_iter_next       (GtkTreeModel      
*tree_model
, 
  99 static gboolean     
wxgtk_list_store_iter_children   (GtkTreeModel      
*tree_model
, 
 101                                                     GtkTreeIter       
*parent
); 
 102 static gboolean     
wxgtk_list_store_iter_has_child  (GtkTreeModel      
*tree_model
, 
 104 static gint         
wxgtk_list_store_iter_n_children (GtkTreeModel      
*tree_model
, 
 106 static gboolean     
wxgtk_list_store_iter_nth_child  (GtkTreeModel      
*tree_model
, 
 110 static gboolean     
wxgtk_list_store_iter_parent     (GtkTreeModel      
*tree_model
, 
 114 static GObjectClass 
*parent_class 
= NULL
; 
 117 gtk_wx_list_store_get_type (void) 
 119   static GType list_store_type 
= 0; 
 121   if (!list_store_type
) 
 123       static const GTypeInfo list_store_info 
= 
 125         sizeof (GtkWxListStoreClass
), 
 126         NULL
,           /* base_init */ 
 127         NULL
,           /* base_finalize */ 
 128         (GClassInitFunc
) wxgtk_list_store_class_init
, 
 129         NULL
,           /* class_finalize */ 
 130         NULL
,           /* class_data */ 
 131         sizeof (GtkWxListStore
), 
 133         (GInstanceInitFunc
) wxgtk_list_store_init
, 
 136       static const GInterfaceInfo tree_model_info 
= 
 138         (GInterfaceInitFunc
) wxgtk_list_store_tree_model_init
, 
 143       list_store_type 
= g_type_register_static (G_TYPE_OBJECT
, "GtkWxListStore", 
 144                                                 &list_store_info
, (GTypeFlags
)0 ); 
 146       g_type_add_interface_static (list_store_type
, 
 151   return list_store_type
; 
 154 static GtkWxListStore 
* 
 155 wxgtk_list_store_new() 
 157   GtkWxListStore 
*retval 
= (GtkWxListStore 
*) g_object_new (GTK_TYPE_WX_LIST_STORE
, NULL
); 
 162 wxgtk_list_store_class_init (GtkWxListStoreClass 
*klass
) 
 164     GObjectClass 
*object_class
; 
 165     parent_class 
= (GObjectClass
*) g_type_class_peek_parent (klass
); 
 166     object_class 
= (GObjectClass
*) klass
; 
 167     object_class
->finalize 
= wxgtk_list_store_finalize
; 
 171 wxgtk_list_store_tree_model_init (GtkTreeModelIface 
*iface
) 
 173     iface
->get_flags 
= wxgtk_list_store_get_flags
; 
 174     iface
->get_n_columns 
= wxgtk_list_store_get_n_columns
; 
 175     iface
->get_column_type 
= wxgtk_list_store_get_column_type
; 
 176     iface
->get_iter 
= wxgtk_list_store_get_iter
; 
 177     iface
->get_path 
= wxgtk_list_store_get_path
; 
 178     iface
->get_value 
= wxgtk_list_store_get_value
; 
 179     iface
->iter_next 
= wxgtk_list_store_iter_next
; 
 180     iface
->iter_children 
= wxgtk_list_store_iter_children
; 
 181     iface
->iter_has_child 
= wxgtk_list_store_iter_has_child
; 
 182     iface
->iter_n_children 
= wxgtk_list_store_iter_n_children
; 
 183     iface
->iter_nth_child 
= wxgtk_list_store_iter_nth_child
; 
 184     iface
->iter_parent 
= wxgtk_list_store_iter_parent
; 
 188 wxgtk_list_store_init (GtkWxListStore 
*list_store
) 
 190     list_store
->model 
= NULL
; 
 191     list_store
->stamp 
= g_random_int(); 
 195 wxgtk_list_store_finalize (GObject 
*object
) 
 197     /* GtkWxListStore *list_store = GTK_WX_LIST_STORE (object); */ 
 199     /* we need to sort out, which class deletes what */ 
 200     /* delete list_store->model; */ 
 203     (* parent_class
->finalize
) (object
); 
 208 //----------------------------------------------------------------------------- 
 209 // implement callbacks from wxGtkListStore class by letting 
 210 // them call the methods of wxWidgets' wxDataViewListModel 
 211 //----------------------------------------------------------------------------- 
 213 static GtkTreeModelFlags
 
 214 wxgtk_list_store_get_flags (GtkTreeModel 
*tree_model
) 
 216     g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), (GtkTreeModelFlags
)0 ); 
 218     // GTK+ list store uses a linked list for storing the 
 219     // items and a pointer to a child is used as the member 
 220     // field of a GtkTreeIter. This means that the iter is 
 221     // valid in the GtkListStore as long as the child exists. 
 222     // We use the index of the row and since the index of a 
 223     // specific row will change if a row above is deleted, 
 224     // the iter does not persist 
 225     return /* GTK_TREE_MODEL_ITERS_PERSIST | */ GTK_TREE_MODEL_LIST_ONLY
; 
 229 wxgtk_list_store_get_n_columns (GtkTreeModel 
*tree_model
) 
 231     GtkWxListStore 
*list_store 
= (GtkWxListStore 
*) tree_model
; 
 232     g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), 0); 
 234     return list_store
->model
->GetNumberOfCols(); 
 238 wxgtk_list_store_get_column_type (GtkTreeModel 
*tree_model
, 
 241     GtkWxListStore 
*list_store 
= (GtkWxListStore 
*) tree_model
; 
 242     g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), G_TYPE_INVALID
); 
 244     GType gtype 
= G_TYPE_INVALID
; 
 246     wxString wxtype 
= list_store
->model
->GetColType( (size_t) index 
); 
 248     if (wxtype 
== wxT("string")) 
 249         gtype 
= G_TYPE_STRING
; 
 255 wxgtk_list_store_get_iter (GtkTreeModel 
*tree_model
, 
 259     GtkWxListStore 
*list_store 
= (GtkWxListStore 
*) tree_model
; 
 260     g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), FALSE
); 
 261     g_return_val_if_fail (gtk_tree_path_get_depth (path
) > 0, FALSE
); 
 263     size_t i 
= (size_t)gtk_tree_path_get_indices (path
)[0]; 
 265     if (i 
>= list_store
->model
->GetNumberOfRows()) 
 268     iter
->stamp 
= list_store
->stamp
; 
 269     // user_data is just the index 
 270     iter
->user_data 
= (gpointer
) i
; 
 276 wxgtk_list_store_get_path (GtkTreeModel 
*tree_model
, 
 279     g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), NULL
); 
 280     g_return_val_if_fail (iter
->stamp 
== GTK_WX_LIST_STORE (tree_model
)->stamp
, NULL
); 
 282     GtkTreePath 
*retval 
= gtk_tree_path_new (); 
 283     // user_data is just the index 
 284     int i 
= (int) iter
->user_data
; 
 285     gtk_tree_path_append_index (retval
, i
); 
 290 wxgtk_list_store_get_value (GtkTreeModel 
*tree_model
, 
 295     GtkWxListStore 
*list_store 
= (GtkWxListStore 
*) tree_model
; 
 296     g_return_if_fail (GTK_IS_WX_LIST_STORE (tree_model
) ); 
 298     wxDataViewListModel 
*model 
= list_store
->model
; 
 299     wxString mtype 
= model
->GetColType( (size_t) column 
); 
 300     if (mtype 
== wxT("string")) 
 302         g_value_init( value
, G_TYPE_STRING 
); 
 303         wxVariant variant 
= model
->GetValue( (size_t) column
, (size_t) iter
->user_data 
); 
 304         g_value_set_string( value
, wxGTK_CONV(variant
.GetString()) ); 
 311   GtkTreeDataList 
*list
; 
 312   gint tmp_column 
= column
; 
 314   g_return_if_fail (column 
< GTK_LIST_STORE (tree_model
)->n_columns
); 
 315   g_return_if_fail (GTK_LIST_STORE (tree_model
)->stamp 
== iter
->stamp
); 
 317   list 
= G_SLIST (iter
->user_data
)->data
; 
 319   while (tmp_column
-- > 0 && list
) 
 323     g_value_init (value
, GTK_LIST_STORE (tree_model
)->column_headers
[column
]); 
 325     _gtk_tree_data_list_node_to_value (list
, 
 326                                        GTK_LIST_STORE (tree_model
)->column_headers
[column
], 
 333 wxgtk_list_store_iter_next (GtkTreeModel  
*tree_model
, 
 336     g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), FALSE
); 
 337     GtkWxListStore 
*list_store 
= (GtkWxListStore 
*) tree_model
; 
 339     g_return_val_if_fail (list_store
->stamp 
== iter
->stamp
, FALSE
); 
 341     int n 
= (int) iter
->user_data
; 
 346     if (n 
>= (int) list_store
->model
->GetNumberOfRows()) 
 349     iter
->user_data 
= (gpointer
) ++n
; 
 355 wxgtk_list_store_iter_children (GtkTreeModel 
*tree_model
, 
 359     g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), FALSE
); 
 360     GtkWxListStore 
*list_store 
= (GtkWxListStore 
*) tree_model
; 
 362     // this is a list, nodes have no children 
 366     iter
->stamp 
= list_store
->stamp
; 
 367     iter
->user_data 
= (gpointer
) -1; 
 373 wxgtk_list_store_iter_has_child (GtkTreeModel 
*tree_model
, 
 380 wxgtk_list_store_iter_n_children (GtkTreeModel 
*tree_model
, 
 383     g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), -1); 
 384     GtkWxListStore 
*list_store 
= (GtkWxListStore 
*) tree_model
; 
 387         return (gint
) list_store
->model
->GetNumberOfRows(); 
 389     g_return_val_if_fail (list_store
->stamp 
== iter
->stamp
, -1); 
 395 wxgtk_list_store_iter_nth_child (GtkTreeModel 
*tree_model
, 
 400     g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model
), FALSE
); 
 401     GtkWxListStore 
*list_store 
= (GtkWxListStore 
*) tree_model
; 
 409     if (n 
>= (gint
) list_store
->model
->GetNumberOfRows()) 
 412     iter
->stamp 
= list_store
->stamp
; 
 413     iter
->user_data 
= (gpointer
) n
; 
 419 wxgtk_list_store_iter_parent (GtkTreeModel 
*tree_model
, 
 427 //----------------------------------------------------------------------------- 
 429 //----------------------------------------------------------------------------- 
 431 IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl
, wxDataViewCtrlBase
) 
 433 wxDataViewCtrl::~wxDataViewCtrl() 
 437 void wxDataViewCtrl::Init() 
 441 bool wxDataViewCtrl::Create(wxWindow 
*parent
, wxWindowID id
, 
 442            const wxPoint
& pos
, const wxSize
& size
,  
 443            long style
, const wxValidator
& validator 
) 
 448     m_acceptsFocus 
= TRUE
; 
 450     if (!PreCreation( parent
, pos
, size 
) || 
 451         !CreateBase( parent
, id
, pos
, size
, style
, validator 
)) 
 453         wxFAIL_MSG( wxT("wxDataViewCtrl creation failed") ); 
 457     m_widget 
= gtk_tree_view_new(); 
 459     m_parent
->DoAddChild( this ); 
 466 bool wxDataViewCtrl::AppendStringColumn( const wxString 
&label 
) 
 468     GtkCellRenderer 
*renderer 
 
 469         = gtk_cell_renderer_text_new(); 
 471     GtkTreeViewColumn 
*column
 
 472         = gtk_tree_view_column_new_with_attributes( wxGTK_CONV(label
), renderer
, "text", -1, NULL 
); 
 474     gtk_tree_view_append_column( GTK_TREE_VIEW(m_widget
), column 
); 
 479 bool wxDataViewCtrl::AssociateModel( wxDataViewModel 
*model 
) 
 481     if (!wxDataViewCtrlBase::AssociateModel( model 
)) 
 484     GtkWxListStore 
*wxmodel 
= wxgtk_list_store_new(); 
 485     wxmodel
->model 
= (wxDataViewListModel
*) model
; 
 487     gtk_tree_view_set_model( GTK_TREE_VIEW(m_widget
), GTK_TREE_MODEL(wxmodel
) ); 
 493 #endif // wxUSE_DATAVIEWCTRL