X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/85136e3bf5dadf921652519e71da5db351fb3194..a188ac2988b6fedeead7a809124b8eaa2290c020:/src/gtk/dataview.cpp diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index b8cf9ca2a5..0110325a42 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -20,8 +20,6 @@ #include "wx/log.h" #include "wx/dcclient.h" #include "wx/sizer.h" - #include "wx/icon.h" - #include "wx/list.h" #include "wx/settings.h" #include "wx/crt.h" #endif @@ -38,9 +36,7 @@ //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -class wxDataViewCtrlInternal; - -wxDataViewCtrlInternal *g_internal = NULL; +static wxDataViewCtrlInternal *gs_internal = NULL; class wxGtkTreeModelNode; @@ -55,12 +51,13 @@ typedef struct _GtkWxTreeModel GtkWxTreeModel; WX_DECLARE_LIST(wxDataViewItem, ItemList); WX_DEFINE_LIST(ItemList) -class wxDataViewCtrlInternal +class WXDLLIMPEXP_ADV wxDataViewCtrlInternal { public: - wxDataViewCtrlInternal( wxDataViewCtrl *owner, wxDataViewModel *wx_model, GtkWxTreeModel *owner ); + wxDataViewCtrlInternal( wxDataViewCtrl *owner, wxDataViewModel *wx_model, GtkWxTreeModel *gtk_model ); ~wxDataViewCtrlInternal(); + // model iface GtkTreeModelFlags get_flags(); gboolean get_iter( GtkTreeIter *iter, GtkTreePath *path ); GtkTreePath *get_path( GtkTreeIter *iter); @@ -71,10 +68,21 @@ public: gboolean iter_nth_child( GtkTreeIter *iter, GtkTreeIter *parent, gint n ); gboolean iter_parent( GtkTreeIter *iter, GtkTreeIter *child ); - wxDataViewModel* GetDataViewModel() { return m_wx_model; } - wxDataViewCtrl* GetOwner() { return m_owner; } - GtkWxTreeModel* GetGtkModel() { return m_gtk_model; } + // dnd iface + bool EnableDragSource( const wxDataFormat &format ); + bool EnableDropTarget( const wxDataFormat &format ); + + gboolean row_draggable( GtkTreeDragSource *drag_source, GtkTreePath *path ); + gboolean drag_data_delete( GtkTreeDragSource *drag_source, GtkTreePath* path ); + gboolean drag_data_get( GtkTreeDragSource *drag_source, GtkTreePath *path, + GtkSelectionData *selection_data ); + gboolean drag_data_received( GtkTreeDragDest *drag_dest, GtkTreePath *dest, + GtkSelectionData *selection_data ); + gboolean row_drop_possible( GtkTreeDragDest *drag_dest, GtkTreePath *dest_path, + GtkSelectionData *selection_data ); + + // notifactions from wxDataViewModel bool ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item ); bool ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item ); bool ItemChanged( const wxDataViewItem &item ); @@ -82,17 +90,23 @@ public: bool Cleared(); void Resort(); + // sorting interface void SetSortOrder( GtkSortType sort_order ) { m_sort_order = sort_order; } - GtkSortType GetSortOrder() { return m_sort_order; } + GtkSortType GetSortOrder() const { return m_sort_order; } void SetSortColumn( int column ) { m_sort_column = column; } - int GetSortColumn() { return m_sort_column; } + int GetSortColumn() const { return m_sort_column; } void SetDataViewSortColumn( wxDataViewColumn *column ) { m_dataview_sort_column = column; } wxDataViewColumn *GetDataViewSortColumn() { return m_dataview_sort_column; } bool IsSorted() { return (m_sort_column >= 0); } + // accessors + wxDataViewModel* GetDataViewModel() { return m_wx_model; } + const wxDataViewModel* GetDataViewModel() const { return m_wx_model; } + wxDataViewCtrl* GetOwner() { return m_owner; } + GtkWxTreeModel* GetGtkModel() { return m_gtk_model; } protected: void InitTree(); @@ -110,6 +124,14 @@ private: GtkSortType m_sort_order; wxDataViewColumn *m_dataview_sort_column; int m_sort_column; + + GtkTargetEntry m_dragSourceTargetEntry; + wxCharBuffer m_dragSourceTargetEntryTarget; + wxDataObject *m_dragDataObject; + + GtkTargetEntry m_dropTargetTargetEntry; + wxCharBuffer m_dropTargetTargetEntryTarget; + wxDataObject *m_dropDataObject; }; @@ -117,10 +139,11 @@ private: // wxGtkTreeModelNode //----------------------------------------------------------------------------- +static int LINKAGEMODE wxGtkTreeModelChildCmp( void** id1, void** id2 ) { - int ret = g_internal->GetDataViewModel()->Compare( *id1, *id2, - g_internal->GetSortColumn(), (g_internal->GetSortOrder() == GTK_SORT_ASCENDING) ); + int ret = gs_internal->GetDataViewModel()->Compare( *id1, *id2, + gs_internal->GetSortColumn(), (gs_internal->GetSortOrder() == GTK_SORT_ASCENDING) ); return ret; } @@ -132,7 +155,7 @@ class wxGtkTreeModelNode { public: wxGtkTreeModelNode( wxGtkTreeModelNode* parent, const wxDataViewItem &item, - wxDataViewCtrlInternal *internal ) + wxDataViewCtrlInternal *internal ) { m_parent = parent; m_item = item; @@ -141,7 +164,7 @@ public: ~wxGtkTreeModelNode() { - size_t count = m_children.GetCount(); + size_t count = m_nodes.GetCount(); size_t i; for (i = 0; i < count; i++) { @@ -160,7 +183,7 @@ public: if (m_internal->IsSorted() || m_internal->GetDataViewModel()->HasDefaultCompare()) { - g_internal = m_internal; + gs_internal = m_internal; m_children.Sort( &wxGtkTreeModelChildCmp ); return m_children.Index( id ); } @@ -174,7 +197,7 @@ public: if (m_internal->IsSorted() || m_internal->GetDataViewModel()->HasDefaultCompare()) { - g_internal = m_internal; + gs_internal = m_internal; m_children.Sort( &wxGtkTreeModelChildCmp ); return m_children.Index( id ); } @@ -198,7 +221,6 @@ public: break; } } - } wxGtkTreeModelNode* GetParent() @@ -208,8 +230,8 @@ public: wxGtkTreeModelChildren &GetChildren() { return m_children; } - unsigned int GetChildCount() { return m_children.GetCount(); } - unsigned int GetNodesCount() { return m_nodes.GetCount(); } + unsigned int GetChildCount() const { return m_children.GetCount(); } + unsigned int GetNodesCount() const { return m_nodes.GetCount(); } wxDataViewItem &GetItem() { return m_item; } wxDataViewCtrlInternal *GetInternal() { return m_internal; } @@ -305,7 +327,7 @@ static gboolean wxgtk_tree_model_iter_parent (GtkTreeModel *tree_mo /* sortable */ static gboolean wxgtk_tree_model_get_sort_column_id (GtkTreeSortable *sortable, gint *sort_column_id, - GtkSortType *order); + GtkSortType *order); static void wxgtk_tree_model_set_sort_column_id (GtkTreeSortable *sortable, gint sort_column_id, GtkSortType order); @@ -333,7 +355,7 @@ static gboolean wxgtk_tree_model_drag_data_received (GtkTreeDragDest *d GtkSelectionData *selection_data); static gboolean wxgtk_tree_model_row_drop_possible (GtkTreeDragDest *drag_dest, GtkTreePath *dest_path, - GtkSelectionData *selection_data); + GtkSelectionData *selection_data); static GObjectClass *list_parent_class = NULL; @@ -448,7 +470,7 @@ wxgtk_tree_model_sortable_init (GtkTreeSortableIface *iface) iface->has_default_sort_func = wxgtk_tree_model_has_default_sort_func; } -static void +static void wxgtk_tree_model_drag_source_init(GtkTreeDragSourceIface *iface) { iface->row_draggable = wxgtk_tree_model_row_draggable; @@ -456,7 +478,7 @@ wxgtk_tree_model_drag_source_init(GtkTreeDragSourceIface *iface) iface->drag_data_get = wxgtk_tree_model_drag_data_get; } -static void +static void wxgtk_tree_model_drag_dest_init (GtkTreeDragDestIface *iface) { iface->drag_data_received = wxgtk_tree_model_drag_data_received; @@ -578,13 +600,14 @@ wxgtk_tree_model_iter_next (GtkTreeModel *tree_model, GtkTreeIter *iter) { GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model; - - if (wxtree_model->stamp != iter->stamp) - wxPrintf( "crash\n" ); + + //if (wxtree_model->stamp != iter->stamp) + // wxPrintf( "crash\n" ); + // TODO: remove this code g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE); g_return_val_if_fail (wxtree_model->stamp == iter->stamp, FALSE); - + return wxtree_model->internal->iter_next( iter ); } @@ -617,7 +640,7 @@ wxgtk_tree_model_iter_n_children (GtkTreeModel *tree_model, { GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model; g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE); - g_return_val_if_fail (wxtree_model->stamp == iter->stamp, 0); + g_return_val_if_fail ( !iter || wxtree_model->stamp == iter->stamp, 0); return wxtree_model->internal->iter_n_children( iter ); } @@ -647,81 +670,85 @@ wxgtk_tree_model_iter_parent (GtkTreeModel *tree_model, } /* drag'n'drop iface */ -static gboolean +static gboolean wxgtk_tree_model_row_draggable (GtkTreeDragSource *drag_source, GtkTreePath *path) { - GtkWxTreeModel *tree_model = (GtkWxTreeModel *) drag_source; - - wxPrintf( "draggable 1\n"); - - g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (tree_model), FALSE); - - wxPrintf( "draggable 2\n"); - - return TRUE; + GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) drag_source; + g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE); + + return wxtree_model->internal->row_draggable( drag_source, path ); } -static gboolean +static gboolean wxgtk_tree_model_drag_data_delete (GtkTreeDragSource *drag_source, GtkTreePath *path) { - GtkWxTreeModel *tree_model = (GtkWxTreeModel *) drag_source; - - g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (tree_model), FALSE); - - return FALSE; + GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) drag_source; + g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE); + + return wxtree_model->internal->drag_data_delete( drag_source, path ); } -static gboolean +static gboolean wxgtk_tree_model_drag_data_get (GtkTreeDragSource *drag_source, GtkTreePath *path, GtkSelectionData *selection_data) { - GtkWxTreeModel *tree_model = (GtkWxTreeModel *) drag_source; - + GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) drag_source; + g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE); + +#if 0 wxPrintf( "drag_get_data\n"); - - g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (tree_model), FALSE); - - return FALSE; + + wxGtkString atom_selection(gdk_atom_name(selection_data->selection)); + wxPrintf( "selection %s\n", wxString::FromAscii(atom_selection) ); + + wxGtkString atom_target(gdk_atom_name(selection_data->target)); + wxPrintf( "target %s\n", wxString::FromAscii(atom_target) ); + + wxGtkString atom_type(gdk_atom_name(selection_data->type)); + wxPrintf( "type %s\n", wxString::FromAscii(atom_type) ); + + wxPrintf( "format %d\n", selection_data->format ); +#endif + + return wxtree_model->internal->drag_data_get( drag_source, path, selection_data ); } -static gboolean +static gboolean wxgtk_tree_model_drag_data_received (GtkTreeDragDest *drag_dest, GtkTreePath *dest, GtkSelectionData *selection_data) { - GtkWxTreeModel *tree_model = (GtkWxTreeModel *) drag_dest; - - g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (tree_model), FALSE); - - return FALSE; + GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) drag_dest; + g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE); + + return wxtree_model->internal->drag_data_received( drag_dest, dest, selection_data ); } -static gboolean +static gboolean wxgtk_tree_model_row_drop_possible (GtkTreeDragDest *drag_dest, GtkTreePath *dest_path, - GtkSelectionData *selection_data) + GtkSelectionData *selection_data) { - GtkWxTreeModel *tree_model = (GtkWxTreeModel *) drag_dest; - - g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (tree_model), FALSE); - - return FALSE; + GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) drag_dest; + g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), FALSE); + + return wxtree_model->internal->row_drop_possible( drag_dest, dest_path, selection_data ); } /* sortable iface */ -static gboolean +static gboolean wxgtk_tree_model_get_sort_column_id (GtkTreeSortable *sortable, gint *sort_column_id, GtkSortType *order) { - GtkWxTreeModel *tree_model = (GtkWxTreeModel *) sortable; + GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) sortable; g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (sortable), FALSE); - if (!tree_model->internal->IsSorted()) + if (!wxtree_model->internal->IsSorted()) { if (sort_column_id) *sort_column_id = -1; @@ -731,17 +758,17 @@ wxgtk_tree_model_get_sort_column_id (GtkTreeSortable *sortable, if (sort_column_id) - *sort_column_id = tree_model->internal->GetSortColumn(); + *sort_column_id = wxtree_model->internal->GetSortColumn(); if (order) - *order = tree_model->internal->GetSortOrder(); + *order = wxtree_model->internal->GetSortOrder(); return TRUE; } wxDataViewColumn *gs_lastLeftClickHeader = NULL; -static void +static void wxgtk_tree_model_set_sort_column_id (GtkTreeSortable *sortable, gint sort_column_id, GtkSortType order) @@ -774,37 +801,185 @@ wxgtk_tree_model_set_sort_column_id (GtkTreeSortable *sortable, gs_lastLeftClickHeader = NULL; } -static void +static void wxgtk_tree_model_set_sort_func (GtkTreeSortable *sortable, gint WXUNUSED(sort_column_id), GtkTreeIterCompareFunc func, gpointer WXUNUSED(data), - GtkDestroyNotify WXUNUSED(destroy) ) + GtkDestroyNotify WXUNUSED(destroy)) { g_return_if_fail (GTK_IS_WX_TREE_MODEL (sortable) ); g_return_if_fail (func != NULL); } -void wxgtk_tree_model_set_default_sort_func (GtkTreeSortable *sortable, - GtkTreeIterCompareFunc func, - gpointer WXUNUSED(data), - GtkDestroyNotify WXUNUSED(destroy) ) +static void +wxgtk_tree_model_set_default_sort_func (GtkTreeSortable *sortable, + GtkTreeIterCompareFunc func, + gpointer WXUNUSED(data), + GtkDestroyNotify WXUNUSED(destroy)) { g_return_if_fail (GTK_IS_WX_TREE_MODEL (sortable) ); g_return_if_fail (func != NULL); - wxPrintf( "wxgtk_tree_model_set_default_sort_func\n" ); + //wxPrintf( "wxgtk_tree_model_set_default_sort_func\n" ); + // TODO: remove this code } -gboolean wxgtk_tree_model_has_default_sort_func (GtkTreeSortable *sortable) +static gboolean +wxgtk_tree_model_has_default_sort_func (GtkTreeSortable *sortable) { g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (sortable), FALSE ); - + return FALSE; } //----------------------------------------------------------------------------- -// define new GTK+ class wxGtkRendererRenderer +// define new GTK+ class GtkWxRendererText +//----------------------------------------------------------------------------- + +extern "C" { + +#define GTK_TYPE_WX_CELL_RENDERER_TEXT (gtk_wx_cell_renderer_text_get_type ()) +#define GTK_WX_CELL_RENDERER_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WX_CELL_RENDERER_TEXT, GtkWxCellRendererText)) +#define GTK_WX_CELL_RENDERER_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WX_CELL_RENDERER_TEXT, GtkWxCellRendererTextClass)) +#define GTK_IS_WX_CELL_RENDERER_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WX_CELL_RENDERER_TEXT)) +#define GTK_IS_WX_CELL_RENDERER_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WX_CELL_RENDERER_TEXT)) +#define GTK_WX_CELL_RENDERER_TEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WX_CELL_RENDERER_TEXT, GtkWxCellRendererTextClass)) + +GType gtk_wx_cell_renderer_text_get_type (void); + +typedef struct _GtkWxCellRendererText GtkWxCellRendererText; +typedef struct _GtkWxCellRendererTextClass GtkWxCellRendererTextClass; + +struct _GtkWxCellRendererText +{ + GtkCellRendererText parent; + + wxDataViewRenderer *wx_renderer; +}; + +struct _GtkWxCellRendererTextClass +{ + GtkCellRendererTextClass cell_parent_class; +}; + + +static GtkWxCellRendererText *gtk_wx_cell_renderer_text_new (void); +static void gtk_wx_cell_renderer_text_init ( + GtkWxCellRendererText *cell ); +static void gtk_wx_cell_renderer_text_class_init( + GtkWxCellRendererTextClass *klass ); +static void gtk_wx_cell_renderer_text_finalize ( + GObject *object ); +static GtkCellEditable *gtk_wx_cell_renderer_text_start_editing( + GtkCellRenderer *cell, + GdkEvent *event, + GtkWidget *widget, + const gchar *path, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GtkCellRendererState flags ); + + +static GObjectClass *text_cell_parent_class = NULL; + +} // extern "C" + +GType +gtk_wx_cell_renderer_text_get_type (void) +{ + static GType cell_wx_type = 0; + + if (!cell_wx_type) + { + const GTypeInfo cell_wx_info = + { + sizeof (GtkWxCellRendererTextClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gtk_wx_cell_renderer_text_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GtkWxCellRendererText), + 0, /* n_preallocs */ + (GInstanceInitFunc) gtk_wx_cell_renderer_text_init, + }; + + cell_wx_type = g_type_register_static( GTK_TYPE_CELL_RENDERER_TEXT, + "GtkWxCellRendererText", &cell_wx_info, (GTypeFlags)0 ); + } + + return cell_wx_type; +} + +static void +gtk_wx_cell_renderer_text_init (GtkWxCellRendererText *cell) +{ + cell->wx_renderer = NULL; +} + +static void +gtk_wx_cell_renderer_text_class_init (GtkWxCellRendererTextClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass); + + text_cell_parent_class = (GObjectClass*) g_type_class_peek_parent (klass); + + object_class->finalize = gtk_wx_cell_renderer_text_finalize; + + cell_class->start_editing = gtk_wx_cell_renderer_text_start_editing; +} + +static void +gtk_wx_cell_renderer_text_finalize (GObject *object) +{ + /* must chain up */ + (* G_OBJECT_CLASS (text_cell_parent_class)->finalize) (object); +} + +GtkWxCellRendererText* +gtk_wx_cell_renderer_text_new (void) +{ + return (GtkWxCellRendererText*) g_object_new (GTK_TYPE_WX_CELL_RENDERER_TEXT, NULL); +} + +static GtkCellEditable *gtk_wx_cell_renderer_text_start_editing( + GtkCellRenderer *gtk_renderer, + GdkEvent *gdk_event, + GtkWidget *widget, + const gchar *path, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GtkCellRendererState flags ) +{ + GtkWxCellRendererText *wxgtk_renderer = (GtkWxCellRendererText *) gtk_renderer; + wxDataViewRenderer *wx_renderer = wxgtk_renderer->wx_renderer; + + GtkTreePath *treepath = gtk_tree_path_new_from_string( path ); + GtkTreeIter iter; + wx_renderer->GetOwner()->GetOwner()->GtkGetInternal()->get_iter( &iter, treepath ); + wxDataViewItem item( (void*) iter.user_data );; + gtk_tree_path_free( treepath ); + + wxDataViewColumn *column = wx_renderer->GetOwner(); + wxDataViewCtrl *dv = column->GetOwner(); + wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_START_EDITING, dv->GetId() ); + event.SetDataViewColumn( column ); + event.SetModel( dv->GetModel() ); + event.SetColumn( wx_renderer->GetOwner()->GetModelColumn() ); + event.SetItem( item ); + dv->HandleWindowEvent( event ); + + if (event.IsAllowed()) + return GTK_CELL_RENDERER_CLASS(text_cell_parent_class)-> + start_editing( gtk_renderer, gdk_event, widget, path, background_area, cell_area, flags ); + else + return NULL; +} + +//----------------------------------------------------------------------------- +// define new GTK+ class GtkWxCellRenderer //----------------------------------------------------------------------------- extern "C" { @@ -944,8 +1119,6 @@ gtk_wx_cell_renderer_new (void) return (GtkCellRenderer*) g_object_new (GTK_TYPE_WX_CELL_RENDERER, NULL); } - - static GtkCellEditable *gtk_wx_cell_renderer_start_editing( GtkCellRenderer *renderer, GdkEvent *WXUNUSED(event), @@ -957,9 +1130,15 @@ static GtkCellEditable *gtk_wx_cell_renderer_start_editing( { GtkWxCellRenderer *wxrenderer = (GtkWxCellRenderer *) renderer; wxDataViewCustomRenderer *cell = wxrenderer->cell; + + // Renderer doesn't support in-place editing if (!cell->HasEditorCtrl()) return NULL; + // An in-place editing control is still around + if (cell->GetEditorCtrl()) + return NULL; + GdkRectangle rect; gtk_wx_cell_renderer_get_size (renderer, widget, cell_area, &rect.x, @@ -1069,8 +1248,12 @@ gtk_wx_cell_renderer_render (GtkCellRenderer *renderer, wxRect renderrect( rect.x, rect.y, rect.width, rect.height ); wxWindowDC* dc = (wxWindowDC*) cell->GetDC(); wxWindowDCImpl *impl = (wxWindowDCImpl *) dc->GetImpl(); - if (impl->m_gdkwindow == NULL) + + // Reinitialize wxWindowDC's GDK window if drawing occurs into a different + // window such as a DnD drop window. + if (window != impl->m_gdkwindow) { + impl->Destroy(); impl->m_gdkwindow = window; impl->SetUpDC(); } @@ -1154,12 +1337,6 @@ gtk_wx_cell_renderer_activate( if (cell->Activate( renderrect, model, item, model_col )) ret = true; } - if (button_event->button == 3) - { - if (cell->RightClick( pt, renderrect, model, item, model_col )) - ret = true; - } - wxrenderer->last_click = button_event->time; return ret; @@ -1313,14 +1490,14 @@ bool wxGtkDataViewModelNotifier::ValueChanged( const wxDataViewItem &item, unsig bool wxGtkDataViewModelNotifier::Cleared() { gtk_tree_view_set_model( GTK_TREE_VIEW(m_owner->m_treeview), NULL ); - + // this will create a new GTK model m_owner->GtkGetInternal()->Cleared(); - + SetGtkModel( m_owner->GtkGetInternal()->GetGtkModel() ); gtk_tree_view_set_model( GTK_TREE_VIEW(m_owner->m_treeview), GTK_TREE_MODEL(m_wxgtk_model) ); - + return false; } @@ -1348,6 +1525,9 @@ static void wxgtk_renderer_editing_started( GtkCellRenderer *WXUNUSED(cell), GtkCellEditable *editable, gchar *path, wxDataViewRenderer *wxrenderer ) { + if (!editable) + return; + wxDataViewColumn *column = wxrenderer->GetOwner(); wxDataViewCtrl *dv = column->GetOwner(); wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED, dv->GetId() ); @@ -1400,15 +1580,21 @@ void wxDataViewRenderer::SetMode( wxDataViewCellMode mode ) GtkCellRendererMode gtkMode; switch (mode) { - case wxDATAVIEW_CELL_INERT: - gtkMode = GTK_CELL_RENDERER_MODE_INERT; - break; - case wxDATAVIEW_CELL_ACTIVATABLE: - gtkMode = GTK_CELL_RENDERER_MODE_ACTIVATABLE; - break; - case wxDATAVIEW_CELL_EDITABLE: - gtkMode = GTK_CELL_RENDERER_MODE_EDITABLE; - break; + case wxDATAVIEW_CELL_INERT: + gtkMode = GTK_CELL_RENDERER_MODE_INERT; + break; + + case wxDATAVIEW_CELL_ACTIVATABLE: + gtkMode = GTK_CELL_RENDERER_MODE_ACTIVATABLE; + break; + + case wxDATAVIEW_CELL_EDITABLE: + gtkMode = GTK_CELL_RENDERER_MODE_EDITABLE; + break; + + default: + wxFAIL_MSG( "unknown wxDataViewCellMode value" ); + return; } // This value is most often ignored in GtkTreeView @@ -1428,15 +1614,21 @@ wxDataViewCellMode wxDataViewRenderer::GetMode() const switch (g_value_get_enum(&gvalue)) { - case GTK_CELL_RENDERER_MODE_INERT: - ret = wxDATAVIEW_CELL_INERT; - break; - case GTK_CELL_RENDERER_MODE_ACTIVATABLE: - ret = wxDATAVIEW_CELL_ACTIVATABLE; - break; - case GTK_CELL_RENDERER_MODE_EDITABLE: - ret = wxDATAVIEW_CELL_EDITABLE; - break; + default: + wxFAIL_MSG( "unknown GtkCellRendererMode value" ); + // fall through (we have to return something) + + case GTK_CELL_RENDERER_MODE_INERT: + ret = wxDATAVIEW_CELL_INERT; + break; + + case GTK_CELL_RENDERER_MODE_ACTIVATABLE: + ret = wxDATAVIEW_CELL_ACTIVATABLE; + break; + + case GTK_CELL_RENDERER_MODE_EDITABLE: + ret = wxDATAVIEW_CELL_EDITABLE; + break; } g_value_unset( &gvalue ); @@ -1444,8 +1636,21 @@ wxDataViewCellMode wxDataViewRenderer::GetMode() const return ret; } -void wxDataViewRenderer::SetAlignment( int align ) +void wxDataViewRenderer::GtkUpdateAlignment() { + int align = m_alignment; + + // query alignment from column ? + if (align == -1) + { + // None there yet + if (GetOwner() == NULL) + return; + + align = GetOwner()->GetAlignment(); + align |= wxALIGN_CENTRE_VERTICAL; + } + // horizontal alignment: gfloat xalign = 0.0; @@ -1475,40 +1680,16 @@ void wxDataViewRenderer::SetAlignment( int align ) g_value_unset( &gvalue2 ); } -int wxDataViewRenderer::GetAlignment() const +void wxDataViewRenderer::SetAlignment( int align ) { - int ret = 0; - GValue gvalue; - - // horizontal alignment: - - g_object_get( G_OBJECT(m_renderer), "xalign", &gvalue, NULL ); - float xalign = g_value_get_float( &gvalue ); - if (xalign < 0.5) - ret |= wxALIGN_LEFT; - else if (xalign == 0.5) - ret |= wxALIGN_CENTER_HORIZONTAL; - else - ret |= wxALIGN_RIGHT; - g_value_unset( &gvalue ); - - - // vertical alignment: - - g_object_get( G_OBJECT(m_renderer), "yalign", &gvalue, NULL ); - float yalign = g_value_get_float( &gvalue ); - if (yalign < 0.5) - ret |= wxALIGN_TOP; - else if (yalign == 0.5) - ret |= wxALIGN_CENTER_VERTICAL; - else - ret |= wxALIGN_BOTTOM; - g_value_unset( &gvalue ); - - return ret; + m_alignment = align; + GtkUpdateAlignment(); } - +int wxDataViewRenderer::GetAlignment() const +{ + return m_alignment; +} // --------------------------------------------------------- // wxDataViewTextRenderer @@ -1522,7 +1703,7 @@ static void wxGtkTextRendererEditedCallback( GtkCellRendererText *renderer, static void wxGtkTextRendererEditedCallback( GtkCellRendererText *WXUNUSED(renderer), gchar *arg1, gchar *arg2, gpointer user_data ) { - wxDataViewTextRenderer *cell = (wxDataViewTextRenderer*) user_data; + wxDataViewRenderer *cell = (wxDataViewRenderer*) user_data; wxString tmp = wxGTK_CONV_BACK_FONT(arg2, cell->GetOwner()->GetOwner()->GetFont()); wxVariant value = tmp; @@ -1549,7 +1730,9 @@ wxDataViewTextRenderer::wxDataViewTextRenderer( const wxString &varianttype, wxD int align ) : wxDataViewRenderer( varianttype, mode, align ) { - m_renderer = (GtkCellRenderer*) gtk_cell_renderer_text_new(); + GtkWxCellRendererText *text_renderer = gtk_wx_cell_renderer_text_new(); + text_renderer->wx_renderer = this; + m_renderer = (GtkCellRenderer*) text_renderer; if (mode & wxDATAVIEW_CELL_EDITABLE) { @@ -1586,7 +1769,7 @@ bool wxDataViewTextRenderer::GetValue( wxVariant &value ) const GValue gvalue = { 0, }; g_value_init( &gvalue, G_TYPE_STRING ); g_object_get_property( G_OBJECT(m_renderer), "text", &gvalue ); - wxString tmp = wxGTK_CONV_BACK_FONT( g_value_get_string( &gvalue ), wx_const_cast(wxDataViewTextRenderer*, this)->GetOwner()->GetOwner()->GetFont() ); + wxString tmp = wxGTK_CONV_BACK_FONT( g_value_get_string( &gvalue ), const_cast(this)->GetOwner()->GetOwner()->GetFont() ); g_value_unset( &gvalue ); value = tmp; @@ -1795,10 +1978,10 @@ public: GtkWidget *widget = window->m_treeview; // Set later m_gdkwindow = NULL; - + m_window = window; - m_context = window->GtkGetPangoDefaultContext(); + m_context = window->GTKGetPangoDefaultContext(); m_layout = pango_layout_new( m_context ); m_fontdesc = pango_font_description_copy( widget->style->font_desc ); @@ -1814,9 +1997,9 @@ class wxDataViewCtrlDC: public wxWindowDC public: wxDataViewCtrlDC( wxDataViewCtrl *window ) : wxWindowDC( new wxDataViewCtrlDCImpl( this, window ) ) - { } + { } }; - + // --------------------------------------------------------- // wxDataViewCustomRenderer @@ -1838,7 +2021,7 @@ wxDataViewCustomRenderer::wxDataViewCustomRenderer( const wxString &varianttype, Init(mode, align); } -void wxDataViewCustomRenderer::RenderText( const wxString &text, int xoffset, +void wxDataViewCustomRenderer::RenderText( const wxString &text, int xoffset, wxRect WXUNUSED(cell), wxDC *WXUNUSED(dc), int WXUNUSED(state) ) { #if 0 @@ -2002,53 +2185,173 @@ wxSize wxDataViewProgressRenderer::GetSize() const return wxSize(40,12); } -// --------------------------------------------------------- -// wxDataViewDateRenderer -// --------------------------------------------------------- +// ------------------------------------- +// wxDataViewChoiceRenderer +// ------------------------------------- -class wxDataViewDateRendererPopupTransient: public wxPopupTransientWindow +wxDataViewChoiceRenderer::wxDataViewChoiceRenderer( const wxArrayString &choices, + wxDataViewCellMode mode, int alignment ) : + wxDataViewCustomRenderer( "string", mode, alignment, true ) { -public: - wxDataViewDateRendererPopupTransient( wxWindow* parent, wxDateTime *value, - wxDataViewModel *model, const wxDataViewItem &item, unsigned int col ) : - wxPopupTransientWindow( parent, wxBORDER_SIMPLE ) - { - m_model = model; - m_item = item; - m_col = col; - m_cal = new wxCalendarCtrl( this, -1, *value ); - wxBoxSizer *sizer = new wxBoxSizer( wxHORIZONTAL ); - sizer->Add( m_cal, 1, wxGROW ); - SetSizer( sizer ); - sizer->Fit( this ); - } + m_choices = choices; - virtual void OnDismiss() +#ifdef __WXGTK26__ + if (!gtk_check_version(2,6,0)) { - } + m_renderer = (GtkCellRenderer*) gtk_cell_renderer_combo_new(); - void OnCalendar( wxCalendarEvent &event ); + GtkListStore *store = gtk_list_store_new( 1, G_TYPE_STRING ); + for (size_t n = 0; n < m_choices.GetCount(); n++) + { + gtk_list_store_insert_with_values( + store, NULL, n, 0, + static_cast(m_choices[n].utf8_str()), -1 ); + } - wxCalendarCtrl *m_cal; - wxDataViewModel *m_model; - wxDataViewItem m_item; - unsigned int m_col; + g_object_set (m_renderer, + "model", store, + "text-column", 0, + "has-entry", FALSE, + NULL); -private: - DECLARE_EVENT_TABLE() -}; + bool editable = (mode & wxDATAVIEW_CELL_EDITABLE); + g_object_set (m_renderer, "editable", editable, NULL); -BEGIN_EVENT_TABLE(wxDataViewDateRendererPopupTransient,wxPopupTransientWindow) - EVT_CALENDAR( -1, wxDataViewDateRendererPopupTransient::OnCalendar ) -END_EVENT_TABLE() + SetAlignment(alignment); -void wxDataViewDateRendererPopupTransient::OnCalendar( wxCalendarEvent &event ) -{ - wxDateTime date = event.GetDate(); - wxVariant value = date; - m_model->SetValue( value, m_item, m_col ); - m_model->ValueChanged( m_item, m_col ); - DismissAndNotify(); + g_signal_connect_after( m_renderer, "edited", G_CALLBACK(wxGtkTextRendererEditedCallback), this ); + + GtkInitHandlers(); + } + else +#endif + { + // Use custom cell code + wxDataViewCustomRenderer::Init(mode, alignment); + } +} + +bool wxDataViewChoiceRenderer::Render( wxRect rect, wxDC *dc, int state ) +{ + RenderText( m_data, 0, rect, dc, state ); + return true; +} + +wxSize wxDataViewChoiceRenderer::GetSize() const +{ + return wxSize(70,20); +} + +bool wxDataViewChoiceRenderer::SetValue( const wxVariant &value ) +{ + +#ifdef __WXGTK26__ + if (!gtk_check_version(2,6,0)) + { + GValue gvalue = { 0, }; + g_value_init( &gvalue, G_TYPE_STRING ); + g_value_set_string( &gvalue, wxGTK_CONV_FONT( value.GetString(), GetOwner()->GetOwner()->GetFont() ) ); + g_object_set_property( G_OBJECT(m_renderer), "text", &gvalue ); + g_value_unset( &gvalue ); + } + else +#endif + m_data = value.GetString(); + + return true; +} + +bool wxDataViewChoiceRenderer::GetValue( wxVariant &value ) const +{ +#ifdef __WXGTK26__ + if (!gtk_check_version(2,6,0)) + { + GValue gvalue = { 0, }; + g_value_init( &gvalue, G_TYPE_STRING ); + g_object_get_property( G_OBJECT(m_renderer), "text", &gvalue ); + wxString temp = wxGTK_CONV_BACK_FONT( g_value_get_string( &gvalue ), + const_cast(this)->GetOwner()->GetOwner()->GetFont() ); + g_value_unset( &gvalue ); + value = temp; + + //wxPrintf( "temp %s\n", temp ); + // TODO: remove this code + } + else +#endif + value = m_data; + + return true; +} + +void wxDataViewChoiceRenderer::SetAlignment( int align ) +{ + wxDataViewCustomRenderer::SetAlignment(align); + + if (gtk_check_version(2,10,0)) + return; + + // horizontal alignment: + PangoAlignment pangoAlign = PANGO_ALIGN_LEFT; + if (align & wxALIGN_RIGHT) + pangoAlign = PANGO_ALIGN_RIGHT; + else if (align & wxALIGN_CENTER_HORIZONTAL) + pangoAlign = PANGO_ALIGN_CENTER; + + GValue gvalue = { 0, }; + g_value_init( &gvalue, gtk_cell_renderer_mode_get_type() ); + g_value_set_enum( &gvalue, pangoAlign ); + g_object_set_property( G_OBJECT(m_renderer), "alignment", &gvalue ); + g_value_unset( &gvalue ); +} + +// --------------------------------------------------------- +// wxDataViewDateRenderer +// --------------------------------------------------------- + +class wxDataViewDateRendererPopupTransient: public wxPopupTransientWindow +{ +public: + wxDataViewDateRendererPopupTransient( wxWindow* parent, wxDateTime *value, + wxDataViewModel *model, const wxDataViewItem &item, unsigned int col ) : + wxPopupTransientWindow( parent, wxBORDER_SIMPLE ) + { + m_model = model; + m_item = item; + m_col = col; + m_cal = new wxCalendarCtrl( this, -1, *value ); + wxBoxSizer *sizer = new wxBoxSizer( wxHORIZONTAL ); + sizer->Add( m_cal, 1, wxGROW ); + SetSizer( sizer ); + sizer->Fit( this ); + } + + virtual void OnDismiss() + { + } + + void OnCalendar( wxCalendarEvent &event ); + + wxCalendarCtrl *m_cal; + wxDataViewModel *m_model; + wxDataViewItem m_item; + unsigned int m_col; + +private: + DECLARE_EVENT_TABLE() +}; + +BEGIN_EVENT_TABLE(wxDataViewDateRendererPopupTransient,wxPopupTransientWindow) + EVT_CALENDAR( -1, wxDataViewDateRendererPopupTransient::OnCalendar ) +END_EVENT_TABLE() + +void wxDataViewDateRendererPopupTransient::OnCalendar( wxCalendarEvent &event ) +{ + wxDateTime date = event.GetDate(); + wxVariant value = date; + m_model->SetValue( value, m_item, m_col ); + m_model->ValueChanged( m_item, m_col ); + DismissAndNotify(); } IMPLEMENT_CLASS(wxDataViewDateRenderer, wxDataViewCustomRenderer) @@ -2131,7 +2434,7 @@ bool wxDataViewIconTextRenderer::SetValue( const wxVariant &value ) return true; } -bool wxDataViewIconTextRenderer::GetValue( wxVariant &value ) const +bool wxDataViewIconTextRenderer::GetValue( wxVariant &WXUNUSED(value) ) const { return false; } @@ -2164,12 +2467,14 @@ wxSize wxDataViewIconTextRenderer::GetSize() const return size; } -wxControl* wxDataViewIconTextRenderer::CreateEditorCtrl( wxWindow *parent, wxRect labelRect, const wxVariant &value ) +wxControl* wxDataViewIconTextRenderer::CreateEditorCtrl( + wxWindow *WXUNUSED(parent), wxRect WXUNUSED(labelRect), const wxVariant &WXUNUSED(value) ) { return NULL; } -bool wxDataViewIconTextRenderer::GetValueFromEditorCtrl( wxControl* editor, wxVariant &value ) +bool wxDataViewIconTextRenderer::GetValueFromEditorCtrl( + wxControl* WXUNUSED(editor), wxVariant &WXUNUSED(value) ) { return false; } @@ -2180,7 +2485,7 @@ bool wxDataViewIconTextRenderer::GetValueFromEditorCtrl( wxControl* editor, wxVa static gboolean -gtk_dataview_header_button_press_callback( GtkWidget *widget, +gtk_dataview_header_button_press_callback( GtkWidget *WXUNUSED(widget), GdkEventButton *gdk_event, wxDataViewColumn *column ) { @@ -2190,7 +2495,7 @@ gtk_dataview_header_button_press_callback( GtkWidget *widget, if (gdk_event->button == 1) { gs_lastLeftClickHeader = column; - + wxDataViewCtrl *dv = column->GetOwner(); wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK, dv->GetId() ); event.SetDataViewColumn( column ); @@ -2221,7 +2526,7 @@ static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *column, } -static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *column, +static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *WXUNUSED(column), GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, @@ -2236,7 +2541,7 @@ static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *column, wxDataViewModel *wx_model = tree_model->internal->GetDataViewModel(); - if (!wx_model->IsIndexListModel()) + if (!wx_model->IsVirtualListModel()) { if (wx_model->IsContainer( item )) @@ -2380,26 +2685,23 @@ static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *column, } -IMPLEMENT_CLASS(wxDataViewColumn, wxDataViewColumnBase) - #include WX_DEFINE_LIST(wxDataViewColumnList) wxDataViewColumn::wxDataViewColumn( const wxString &title, wxDataViewRenderer *cell, unsigned int model_column, int width, - wxAlignment align, int flags ) : - wxDataViewColumnBase( title, cell, model_column, width, align, flags ) + wxAlignment align, int flags ) + : wxDataViewColumnBase( cell, model_column ) { Init( align, flags, width ); - gtk_tree_view_column_set_clickable( GTK_TREE_VIEW_COLUMN(m_column), TRUE ); SetTitle( title ); } wxDataViewColumn::wxDataViewColumn( const wxBitmap &bitmap, wxDataViewRenderer *cell, unsigned int model_column, int width, - wxAlignment align, int flags ) : - wxDataViewColumnBase( bitmap, cell, model_column, width, align, flags ) + wxAlignment align, int flags ) + : wxDataViewColumnBase( bitmap, cell, model_column ) { Init( align, flags, width ); @@ -2417,14 +2719,17 @@ void wxDataViewColumn::Init(wxAlignment align, int flags, int width) SetFlags( flags ); SetAlignment( align ); - // NOTE: we prefer not to call SetMinWidth(wxDVC_DEFAULT_MINWIDTH); - // as GTK+ is smart and unless explicitely told, will set the minimal - // width to the title's lenght, which is a better default + SetWidth( width ); - // the GTK_TREE_VIEW_COLUMN_FIXED is required by the "fixed height" mode - // that we use for the wxDataViewCtrl - gtk_tree_view_column_set_fixed_width( column, width < 0 ? wxDVC_DEFAULT_WIDTH : width ); - gtk_tree_view_column_set_sizing( column, GTK_TREE_VIEW_COLUMN_FIXED ); + // Create container for icon and label + GtkWidget *box = gtk_hbox_new( FALSE, 1 ); + gtk_widget_show( box ); + // gtk_container_set_border_width((GtkContainer*)box, 2); + m_image = gtk_image_new(); + gtk_box_pack_start(GTK_BOX(box), m_image, FALSE, FALSE, 1); + m_label = gtk_label_new(""); + gtk_box_pack_end( GTK_BOX(box), GTK_WIDGET(m_label), FALSE, FALSE, 1 ); + gtk_tree_view_column_set_widget( column, box ); gtk_tree_view_column_pack_end( column, renderer, TRUE ); @@ -2432,10 +2737,6 @@ void wxDataViewColumn::Init(wxAlignment align, int flags, int width) wxGtkTreeCellDataFunc, (gpointer) GetRenderer(), NULL ); } -wxDataViewColumn::~wxDataViewColumn() -{ -} - void wxDataViewColumn::OnInternalIdle() { if (m_isConnected) @@ -2465,41 +2766,32 @@ void wxDataViewColumn::SetOwner( wxDataViewCtrl *owner ) void wxDataViewColumn::SetTitle( const wxString &title ) { - GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column); - - if (m_isConnected) - { - // disconnect before column->button gets recreated - g_signal_handlers_disconnect_by_func( column->button, - (GtkWidget*) gtk_dataview_header_button_press_callback, this); - - m_isConnected = false; - } - - // FIXME: can it really happen that we don't have the owner here?? wxDataViewCtrl *ctrl = GetOwner(); - gtk_tree_view_column_set_title( column, ctrl ? wxGTK_CONV_FONT(title, ctrl->GetFont()) + gtk_label_set_text( GTK_LABEL(m_label), ctrl ? wxGTK_CONV_FONT(title, ctrl->GetFont()) : wxGTK_CONV_SYS(title) ); - - gtk_tree_view_column_set_widget( column, NULL ); + if (title.empty()) + gtk_widget_hide( m_label ); + else + gtk_widget_show( m_label ); } wxString wxDataViewColumn::GetTitle() const { - const gchar *str = gtk_tree_view_column_get_title( GTK_TREE_VIEW_COLUMN(m_column) ); - return wxConvFileName->cMB2WX(str); + return wxGTK_CONV_BACK_FONT( + gtk_label_get_text( GTK_LABEL(m_label) ), + GetOwner()->GetFont() + ); } void wxDataViewColumn::SetBitmap( const wxBitmap &bitmap ) { wxDataViewColumnBase::SetBitmap( bitmap ); - GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column); if (bitmap.Ok()) { - GtkImage *gtk_image = GTK_IMAGE( gtk_image_new() ); + GtkImage *gtk_image = GTK_IMAGE(m_image); - GdkBitmap *mask = (GdkBitmap *) NULL; + GdkBitmap *mask = NULL; if (bitmap.GetMask()) mask = bitmap.GetMask()->GetBitmap(); @@ -2513,13 +2805,11 @@ void wxDataViewColumn::SetBitmap( const wxBitmap &bitmap ) gtk_image_set_from_pixmap(GTK_IMAGE(gtk_image), bitmap.GetPixmap(), mask); } - gtk_widget_show( GTK_WIDGET(gtk_image) ); - - gtk_tree_view_column_set_widget( column, GTK_WIDGET(gtk_image) ); + gtk_widget_show( m_image ); } else { - gtk_tree_view_column_set_widget( column, NULL ); + gtk_widget_hide( m_image ); } } @@ -2545,6 +2835,9 @@ void wxDataViewColumn::SetAlignment( wxAlignment align ) xalign = 0.5; gtk_tree_view_column_set_alignment( column, xalign ); + + if (m_renderer && m_renderer->GetAlignment() == -1) + m_renderer->GtkUpdateAlignment(); } wxAlignment wxDataViewColumn::GetAlignment() const @@ -2563,7 +2856,7 @@ void wxDataViewColumn::SetSortable( bool sortable ) { GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column); - if (sortable) + if ( sortable ) { gtk_tree_view_column_set_sort_column_id( column, GetModelColumn() ); } @@ -2571,13 +2864,28 @@ void wxDataViewColumn::SetSortable( bool sortable ) { gtk_tree_view_column_set_sort_column_id( column, -1 ); gtk_tree_view_column_set_sort_indicator( column, FALSE ); + gtk_tree_view_column_set_clickable( column, FALSE ); } } bool wxDataViewColumn::IsSortable() const { GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column); - return (gtk_tree_view_column_get_sort_column_id( column ) != -1); + return gtk_tree_view_column_get_clickable( column ); +} + +void wxDataViewColumn::SetAsSortKey( bool WXUNUSED(sort) ) +{ + // it might not make sense to have this function in wxHeaderColumn at + // all in fact, changing of the sort order should only be done using the + // associated control API + wxFAIL_MSG( "not implemented" ); +} + +bool wxDataViewColumn::IsSortKey() const +{ + GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column); + return gtk_tree_view_column_get_sort_indicator( column ); } bool wxDataViewColumn::IsResizeable() const @@ -2628,7 +2936,25 @@ int wxDataViewColumn::GetWidth() const void wxDataViewColumn::SetWidth( int width ) { - gtk_tree_view_column_set_fixed_width( GTK_TREE_VIEW_COLUMN(m_column), width ); + if (width < 0) + { +#if 1 + gtk_tree_view_column_set_sizing( GTK_TREE_VIEW_COLUMN(m_column), GTK_TREE_VIEW_COLUMN_FIXED ); + + // TODO find a better calculation + gtk_tree_view_column_set_fixed_width( GTK_TREE_VIEW_COLUMN(m_column), wxDVC_DEFAULT_WIDTH ); +#else + // this is unpractical for large numbers of items and disables + // user resizing, which is totally unexpected + gtk_tree_view_column_set_sizing( GTK_TREE_VIEW_COLUMN(m_column), GTK_TREE_VIEW_COLUMN_AUTOSIZE ); +#endif + } + else + { + gtk_tree_view_column_set_sizing( GTK_TREE_VIEW_COLUMN(m_column), GTK_TREE_VIEW_COLUMN_FIXED ); + + gtk_tree_view_column_set_fixed_width( GTK_TREE_VIEW_COLUMN(m_column), width ); + } } void wxDataViewColumn::SetReorderable( bool reorderable ) @@ -2645,6 +2971,36 @@ bool wxDataViewColumn::IsReorderable() const // wxGtkTreeModelNode //----------------------------------------------------------------------------- +#if 0 +class wxGtkTreeModelChildWithPos +{ +public: + unsigned int pos; + void *id; +}; + +static +int wxGtkTreeModelChildWithPosCmp( const void* data1, const void* data2, const void* user_data ) +{ + const wxGtkTreeModelChildWithPos* child1 = (const wxGtkTreeModelChildWithPos*) data1; + const wxGtkTreeModelChildWithPos* child2 = (const wxGtkTreeModelChildWithPos*) data2; + const wxDataViewCtrlInternal *internal = (const wxDataViewCtrlInternal *) user_data; + int ret = internal->GetDataViewModel()->Compare( child1->id, child2->id, + internal->GetSortColumn(), (internal->GetSortOrder() == GTK_SORT_DESCENDING) ); + + return ret; +} +#else +static +int LINKAGEMODE wxGtkTreeModelChildPtrCmp( void*** data1, void*** data2 ) +{ + return gs_internal->GetDataViewModel()->Compare( **data1, **data2, + gs_internal->GetSortColumn(), (gs_internal->GetSortOrder() == GTK_SORT_ASCENDING) ); +} + +WX_DEFINE_ARRAY_PTR( void**, wxGtkTreeModelChildrenPtr ); +#endif + void wxGtkTreeModelNode::Resort() { size_t child_count = GetChildCount(); @@ -2663,14 +3019,68 @@ void wxGtkTreeModelNode::Resort() return; } + gint *new_order = new gint[child_count]; + +#if 1 + // m_children has the original *void + // ptrs points to these + wxGtkTreeModelChildrenPtr ptrs; + size_t i; + for (i = 0; i < child_count; i++) + ptrs.Add( &(m_children[i]) ); + // Sort the ptrs + gs_internal = m_internal; + ptrs.Sort( &wxGtkTreeModelChildPtrCmp ); + wxGtkTreeModelChildren temp; + void** base_ptr = &(m_children[0]); + // Transfer positions to new_order array and + // IDs to temp + for (i = 0; i < child_count; i++) + { + new_order[i] = ptrs[i] - base_ptr; + temp.Add( *ptrs[i] ); + } + + // Transfer IDs back to m_children + m_children.Clear(); WX_APPEND_ARRAY( temp, m_children ); +#endif +#if 0 + // Too slow - g_internal = m_internal; - m_children.Sort( &wxGtkTreeModelChildCmp ); + // Build up array with IDs and original positions + wxGtkTreeModelChildWithPos* temp = new wxGtkTreeModelChildWithPos[child_count]; + size_t i; + for (i = 0; i < child_count; i++) + { + temp[i].pos = i; + temp[i].id = m_children[i]; + } + // Sort array keeping original positions + wxQsort( temp, child_count, sizeof(wxGtkTreeModelChildWithPos), + &wxGtkTreeModelChildWithPosCmp, m_internal ); + // Transfer positions to new_order array and + // IDs to m_children + m_children.Clear(); + for (i = 0; i < child_count; i++) + { + new_order[i] = temp[i].pos; + m_children.Add( temp[i].id ); + } + // Delete array + delete [] temp; +#endif - gint *new_order = new gint[child_count]; +#if 0 + // Too slow + + wxGtkTreeModelChildren temp; + WX_APPEND_ARRAY( temp, m_children ); + gs_internal = m_internal; + m_children.Sort( &wxGtkTreeModelChildCmp ); + unsigned int pos; for (pos = 0; pos < child_count; pos++) { @@ -2678,6 +3088,7 @@ void wxGtkTreeModelNode::Resort() int old_pos = temp.Index( id ); new_order[pos] = old_pos; } +#endif GtkTreeModel *gtk_tree_model = GTK_TREE_MODEL( m_internal->GetGtkModel() ); @@ -2692,7 +3103,8 @@ void wxGtkTreeModelNode::Resort() gtk_tree_path_free (path); delete [] new_order; - + + unsigned int pos; for (pos = 0; pos < node_count; pos++) { wxGtkTreeModelNode *node = m_nodes.Item( pos ); @@ -2715,13 +3127,19 @@ wxDataViewCtrlInternal::wxDataViewCtrlInternal( wxDataViewCtrl *owner, m_sort_column = -1; m_dataview_sort_column = NULL; - if (!m_wx_model->IsIndexListModel()) + m_dragDataObject = NULL; + m_dropDataObject = NULL; + + if (!m_wx_model->IsVirtualListModel()) InitTree(); } wxDataViewCtrlInternal::~wxDataViewCtrlInternal() { g_object_unref( m_gtk_model ); + + delete m_dragDataObject; + delete m_dropDataObject; } void wxDataViewCtrlInternal::InitTree() @@ -2753,33 +3171,183 @@ void wxDataViewCtrlInternal::BuildBranch( wxGtkTreeModelNode *node ) } } +// GTK+ dnd iface + +bool wxDataViewCtrlInternal::EnableDragSource( const wxDataFormat &format ) +{ + wxGtkString atom_str( gdk_atom_name( format ) ); + m_dragSourceTargetEntryTarget = wxCharBuffer( atom_str ); + + m_dragSourceTargetEntry.target = m_dragSourceTargetEntryTarget.data(); + m_dragSourceTargetEntry.flags = 0; + m_dragSourceTargetEntry.info = static_cast(-1); + + gtk_tree_view_enable_model_drag_source( GTK_TREE_VIEW(m_owner->GtkGetTreeView() ), + GDK_BUTTON1_MASK, &m_dragSourceTargetEntry, 1, (GdkDragAction) GDK_ACTION_COPY ); + + return true; +} + +bool wxDataViewCtrlInternal::EnableDropTarget( const wxDataFormat &format ) +{ + wxGtkString atom_str( gdk_atom_name( format ) ); + m_dropTargetTargetEntryTarget = wxCharBuffer( atom_str ); + + m_dropTargetTargetEntry.target = m_dropTargetTargetEntryTarget.data(); + m_dropTargetTargetEntry.flags = 0; + m_dropTargetTargetEntry.info = static_cast(-1); + + gtk_tree_view_enable_model_drag_dest( GTK_TREE_VIEW(m_owner->GtkGetTreeView() ), + &m_dropTargetTargetEntry, 1, (GdkDragAction) GDK_ACTION_COPY ); + + return true; +} + +gboolean wxDataViewCtrlInternal::row_draggable( GtkTreeDragSource *WXUNUSED(drag_source), + GtkTreePath *path ) +{ + delete m_dragDataObject; + + GtkTreeIter iter; + if (!get_iter( &iter, path )) return FALSE; + wxDataViewItem item( (void*) iter.user_data ); + + wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_BEGIN_DRAG, m_owner->GetId() ); + event.SetEventObject( m_owner ); + event.SetItem( item ); + event.SetModel( m_wx_model ); + if (!m_owner->HandleWindowEvent( event )) + return FALSE; + + if (!event.IsAllowed()) + return FALSE; + + wxDataObject *obj = event.GetDataObject(); + if (!obj) + return FALSE; + + m_dragDataObject = obj; + + return TRUE; +} + +gboolean +wxDataViewCtrlInternal::drag_data_delete(GtkTreeDragSource *WXUNUSED(drag_source), + GtkTreePath *WXUNUSED(path)) +{ + return FALSE; +} + +gboolean wxDataViewCtrlInternal::drag_data_get( GtkTreeDragSource *WXUNUSED(drag_source), + GtkTreePath *path, GtkSelectionData *selection_data ) +{ + GtkTreeIter iter; + if (!get_iter( &iter, path )) return FALSE; + wxDataViewItem item( (void*) iter.user_data ); + + if (!m_dragDataObject->IsSupported( selection_data->target )) + return FALSE; + + size_t size = m_dragDataObject->GetDataSize( selection_data->target ); + if (size == 0) + return FALSE; + + void *buf = malloc( size ); + + gboolean res = FALSE; + if (m_dragDataObject->GetDataHere( selection_data->target, buf )) + { + res = TRUE; + + gtk_selection_data_set( selection_data, selection_data->target, + 8, (const guchar*) buf, size ); + } + + free( buf ); + + return res; +} + +gboolean +wxDataViewCtrlInternal::drag_data_received(GtkTreeDragDest *WXUNUSED(drag_dest), + GtkTreePath *path, + GtkSelectionData *selection_data) +{ + GtkTreeIter iter; + if (!get_iter( &iter, path )) return FALSE; + wxDataViewItem item( (void*) iter.user_data ); + + wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_DROP, m_owner->GetId() ); + event.SetEventObject( m_owner ); + event.SetItem( item ); + event.SetModel( m_wx_model ); + event.SetDataFormat( selection_data->target ); + event.SetDataSize( selection_data->length ); + event.SetDataBuffer( selection_data->data ); + if (!m_owner->HandleWindowEvent( event )) + return FALSE; + + if (!event.IsAllowed()) + return FALSE; + + return TRUE; +} + +gboolean +wxDataViewCtrlInternal::row_drop_possible(GtkTreeDragDest *WXUNUSED(drag_dest), + GtkTreePath *path, + GtkSelectionData *selection_data) +{ + GtkTreeIter iter; + if (!get_iter( &iter, path )) return FALSE; + wxDataViewItem item( (void*) iter.user_data ); + + wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE, m_owner->GetId() ); + event.SetEventObject( m_owner ); + event.SetItem( item ); + event.SetModel( m_wx_model ); + event.SetDataFormat( selection_data->target ); + if (!m_owner->HandleWindowEvent( event )) + return FALSE; + + if (!event.IsAllowed()) + return FALSE; + + return TRUE; +} + +// notifications from wxDataViewModel + bool wxDataViewCtrlInternal::Cleared() { if (m_root) { delete m_root; InitTree(); - } - + } + // Create new GTK model g_object_unref( m_gtk_model ); m_gtk_model = wxgtk_tree_model_new(); m_gtk_model->internal = this; - + return true; } void wxDataViewCtrlInternal::Resort() { - if (!m_wx_model->IsIndexListModel()) + if (!m_wx_model->IsVirtualListModel()) m_root->Resort(); } bool wxDataViewCtrlInternal::ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item ) { - if (!m_wx_model->IsIndexListModel()) + if (!m_wx_model->IsVirtualListModel()) { wxGtkTreeModelNode *parent_node = FindNode( parent ); + wxASSERT_MSG(parent_node, + "Did you forget a call to ItemAdded()? The parent node is unknown to the wxGtkTreeModel"); + if (m_wx_model->IsContainer( item )) parent_node->AddNode( new wxGtkTreeModelNode( parent_node, item, this ) ); else @@ -2791,9 +3359,12 @@ bool wxDataViewCtrlInternal::ItemAdded( const wxDataViewItem &parent, const wxDa bool wxDataViewCtrlInternal::ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item ) { - if (!m_wx_model->IsIndexListModel()) + if (!m_wx_model->IsVirtualListModel()) { wxGtkTreeModelNode *parent_node = FindNode( parent ); + wxASSERT_MSG(parent_node, + "Did you forget a call to ItemAdded()? The parent node is unknown to the wxGtkTreeModel"); + parent_node->DeleteChild( item.GetID() ); } @@ -2824,9 +3395,11 @@ bool wxDataViewCtrlInternal::ValueChanged( const wxDataViewItem &item, unsigned return true; } +// GTK+ model iface + GtkTreeModelFlags wxDataViewCtrlInternal::get_flags() { - if (m_wx_model->IsIndexListModel()) + if (m_wx_model->IsVirtualListModel()) return GTK_TREE_MODEL_LIST_ONLY; else return GTK_TREE_MODEL_ITERS_PERSIST; @@ -2834,18 +3407,19 @@ GtkTreeModelFlags wxDataViewCtrlInternal::get_flags() gboolean wxDataViewCtrlInternal::get_iter( GtkTreeIter *iter, GtkTreePath *path ) { - if (m_wx_model->IsIndexListModel()) - { - wxDataViewIndexListModel *wx_model = (wxDataViewIndexListModel*) m_wx_model; + if (m_wx_model->IsVirtualListModel()) + { + wxDataViewVirtualListModel *wx_model = (wxDataViewVirtualListModel*) m_wx_model; + unsigned int i = (unsigned int)gtk_tree_path_get_indices (path)[0]; - - if (i >= wx_model->GetLastIndex() + 1) + + if (i >= wx_model->GetCount()) return FALSE; iter->stamp = m_gtk_model->stamp; - // user_data is just the index - iter->user_data = (gpointer) i; + // user_data is just the index +1 + iter->user_data = (gpointer) (i+1); return TRUE; } @@ -2894,10 +3468,10 @@ GtkTreePath *wxDataViewCtrlInternal::get_path( GtkTreeIter *iter ) { GtkTreePath *retval = gtk_tree_path_new (); - if (m_wx_model->IsIndexListModel()) + if (m_wx_model->IsVirtualListModel()) { - // user_data is just the index - int i = (wxUIntPtr) iter->user_data; + // user_data is just the index +1 + int i = ( (wxUIntPtr) iter->user_data ) -1; gtk_tree_path_append_index (retval, i); } else @@ -2921,19 +3495,21 @@ GtkTreePath *wxDataViewCtrlInternal::get_path( GtkTreeIter *iter ) gboolean wxDataViewCtrlInternal::iter_next( GtkTreeIter *iter ) { - if (m_wx_model->IsIndexListModel()) + if (m_wx_model->IsVirtualListModel()) { - wxDataViewIndexListModel *wx_model = (wxDataViewIndexListModel*) m_wx_model; + wxDataViewVirtualListModel *wx_model = (wxDataViewVirtualListModel*) m_wx_model; - int n = (wxUIntPtr) iter->user_data; + // user_data is just the index +1 + int n = ( (wxUIntPtr) iter->user_data ) -1; if (n == -1) return FALSE; - if (n >= (int) wx_model->GetLastIndex()) + if (n >= (int) wx_model->GetCount()) return FALSE; - iter->user_data = (gpointer) ++n; + // user_data is just the index +1 (+2 because we need the next) + iter->user_data = (gpointer) (n+2); } else { @@ -2955,14 +3531,14 @@ gboolean wxDataViewCtrlInternal::iter_next( GtkTreeIter *iter ) gboolean wxDataViewCtrlInternal::iter_children( GtkTreeIter *iter, GtkTreeIter *parent ) { - if (m_wx_model->IsIndexListModel()) + if (m_wx_model->IsVirtualListModel()) { // this is a list, nodes have no children if (parent) return FALSE; iter->stamp = m_gtk_model->stamp; - iter->user_data = (gpointer) -1; + iter->user_data = (gpointer) 1; return TRUE; } @@ -2974,6 +3550,9 @@ gboolean wxDataViewCtrlInternal::iter_children( GtkTreeIter *iter, GtkTreeIter * return FALSE; wxGtkTreeModelNode *parent_node = FindNode( parent ); + wxASSERT_MSG(parent_node, + "Did you forget a call to ItemAdded()? The parent node is unknown to the wxGtkTreeModel"); + BuildBranch( parent_node ); if (parent_node->GetChildCount() == 0) @@ -2988,8 +3567,13 @@ gboolean wxDataViewCtrlInternal::iter_children( GtkTreeIter *iter, GtkTreeIter * gboolean wxDataViewCtrlInternal::iter_has_child( GtkTreeIter *iter ) { - if (m_wx_model->IsIndexListModel()) + if (m_wx_model->IsVirtualListModel()) { + wxDataViewVirtualListModel *wx_model = (wxDataViewVirtualListModel*) m_wx_model; + + if (iter == NULL) + return (gint) wx_model->GetCount(); + // this is a list, nodes have no children return FALSE; } @@ -3003,6 +3587,9 @@ gboolean wxDataViewCtrlInternal::iter_has_child( GtkTreeIter *iter ) return FALSE; wxGtkTreeModelNode *node = FindNode( iter ); + wxASSERT_MSG(node, + "Did you forget a call to ItemAdded()? The iterator is unknown to the wxGtkTreeModel"); + BuildBranch( node ); return (node->GetChildCount() > 0); @@ -3011,23 +3598,29 @@ gboolean wxDataViewCtrlInternal::iter_has_child( GtkTreeIter *iter ) gint wxDataViewCtrlInternal::iter_n_children( GtkTreeIter *iter ) { - if (m_wx_model->IsIndexListModel()) + if (m_wx_model->IsVirtualListModel()) { - wxDataViewIndexListModel *wx_model = (wxDataViewIndexListModel*) m_wx_model; + wxDataViewVirtualListModel *wx_model = (wxDataViewVirtualListModel*) m_wx_model; if (iter == NULL) - return (gint) wx_model->GetLastIndex() + 1; + return (gint) wx_model->GetCount(); return 0; } else { + if (iter == NULL) + return m_root->GetChildCount(); + wxDataViewItem item( (void*) iter->user_data ); if (!m_wx_model->IsContainer( item )) return 0; wxGtkTreeModelNode *parent_node = FindNode( iter ); + wxASSERT_MSG(parent_node, + "Did you forget a call to ItemAdded()? The parent node is unknown to the wxGtkTreeModel"); + BuildBranch( parent_node ); // wxPrintf( "iter_n_children %d\n", parent_node->GetChildCount() ); @@ -3038,9 +3631,9 @@ gint wxDataViewCtrlInternal::iter_n_children( GtkTreeIter *iter ) gboolean wxDataViewCtrlInternal::iter_nth_child( GtkTreeIter *iter, GtkTreeIter *parent, gint n ) { - if (m_wx_model->IsIndexListModel()) + if (m_wx_model->IsVirtualListModel()) { - wxDataViewIndexListModel *wx_model = (wxDataViewIndexListModel*) m_wx_model; + wxDataViewVirtualListModel *wx_model = (wxDataViewVirtualListModel*) m_wx_model; if (parent) return FALSE; @@ -3048,11 +3641,12 @@ gboolean wxDataViewCtrlInternal::iter_nth_child( GtkTreeIter *iter, GtkTreeIter if (n < 0) return FALSE; - if (n >= (gint) wx_model->GetLastIndex() + 1) + if (n >= (gint) wx_model->GetCount()) return FALSE; iter->stamp = m_gtk_model->stamp; - iter->user_data = (gpointer) n; + // user_data is just the index +1 + iter->user_data = (gpointer) (n+1); return TRUE; } @@ -3066,6 +3660,9 @@ gboolean wxDataViewCtrlInternal::iter_nth_child( GtkTreeIter *iter, GtkTreeIter return FALSE; wxGtkTreeModelNode *parent_node = FindNode( parent ); + wxASSERT_MSG(parent_node, + "Did you forget a call to ItemAdded()? The parent node is unknown to the wxGtkTreeModel"); + BuildBranch( parent_node ); // wxPrintf( "iter_nth_child %d\n", n ); @@ -3079,7 +3676,7 @@ gboolean wxDataViewCtrlInternal::iter_nth_child( GtkTreeIter *iter, GtkTreeIter gboolean wxDataViewCtrlInternal::iter_parent( GtkTreeIter *iter, GtkTreeIter *child ) { - if (m_wx_model->IsIndexListModel()) + if (m_wx_model->IsVirtualListModel()) { return FALSE; } @@ -3153,12 +3750,15 @@ wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( GtkTreeIter *iter ) wxGtkTreeModelNode *result = wxDataViewCtrlInternal_FindNode( m_wx_model, m_root, item ); +/* if (!result) { wxLogDebug( "Not found %p", iter->user_data ); char *crash = NULL; *crash = 0; } + // TODO: remove this code +*/ return result; } @@ -3170,12 +3770,15 @@ wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( const wxDataViewItem &item wxGtkTreeModelNode *result = wxDataViewCtrlInternal_FindNode( m_wx_model, m_root, item ); +/* if (!result) { wxLogDebug( "Not found %p", item.GetID() ); char *crash = NULL; *crash = 0; } + // TODO: remove this code +*/ return result; } @@ -3259,7 +3862,7 @@ wxGtkTreeModelNode *wxDataViewCtrlInternal::FindParentNode( const wxDataViewItem //----------------------------------------------------------------------------- static void -wxdataview_selection_changed_callback( GtkTreeSelection* selection, wxDataViewCtrl *dv ) +wxdataview_selection_changed_callback( GtkTreeSelection* WXUNUSED(selection), wxDataViewCtrl *dv ) { if (!GTK_WIDGET_REALIZED(dv->m_widget)) return; @@ -3271,8 +3874,8 @@ wxdataview_selection_changed_callback( GtkTreeSelection* selection, wxDataViewCt } static void -wxdataview_row_activated_callback( GtkTreeView* treeview, GtkTreePath *path, - GtkTreeViewColumn *column, wxDataViewCtrl *dv ) +wxdataview_row_activated_callback( GtkTreeView* WXUNUSED(treeview), GtkTreePath *path, + GtkTreeViewColumn *WXUNUSED(column), wxDataViewCtrl *dv ) { wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, dv->GetId() ); @@ -3285,8 +3888,8 @@ wxdataview_row_activated_callback( GtkTreeView* treeview, GtkTreePath *path, } static gboolean -wxdataview_test_expand_row_callback( GtkTreeView* treeview, GtkTreeIter* iter, - GtkTreePath *path, wxDataViewCtrl *dv ) +wxdataview_test_expand_row_callback( GtkTreeView* WXUNUSED(treeview), GtkTreeIter* iter, + GtkTreePath *WXUNUSED(path), wxDataViewCtrl *dv ) { wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING, dv->GetId() ); @@ -3299,8 +3902,8 @@ wxdataview_test_expand_row_callback( GtkTreeView* treeview, GtkTreeIter* iter, } static void -wxdataview_row_expanded_callback( GtkTreeView* treeview, GtkTreeIter* iter, - GtkTreePath *path, wxDataViewCtrl *dv ) +wxdataview_row_expanded_callback( GtkTreeView* WXUNUSED(treeview), GtkTreeIter* iter, + GtkTreePath *WXUNUSED(path), wxDataViewCtrl *dv ) { wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED, dv->GetId() ); @@ -3311,8 +3914,8 @@ wxdataview_row_expanded_callback( GtkTreeView* treeview, GtkTreeIter* iter, } static gboolean -wxdataview_test_collapse_row_callback( GtkTreeView* treeview, GtkTreeIter* iter, - GtkTreePath *path, wxDataViewCtrl *dv ) +wxdataview_test_collapse_row_callback( GtkTreeView* WXUNUSED(treeview), GtkTreeIter* iter, + GtkTreePath *WXUNUSED(path), wxDataViewCtrl *dv ) { wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING, dv->GetId() ); @@ -3325,8 +3928,8 @@ wxdataview_test_collapse_row_callback( GtkTreeView* treeview, GtkTreeIter* iter, } static void -wxdataview_row_collapsed_callback( GtkTreeView* treeview, GtkTreeIter* iter, - GtkTreePath *path, wxDataViewCtrl *dv ) +wxdataview_row_collapsed_callback( GtkTreeView* WXUNUSED(treeview), GtkTreeIter* iter, + GtkTreePath *WXUNUSED(path), wxDataViewCtrl *dv ) { wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED, dv->GetId() ); @@ -3340,14 +3943,9 @@ wxdataview_row_collapsed_callback( GtkTreeView* treeview, GtkTreeIter* iter, // wxDataViewCtrl //----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// InsertChild for wxDataViewCtrl -//----------------------------------------------------------------------------- - -static void wxInsertChildInDataViewCtrl( wxWindowGTK* parent, wxWindowGTK* child ) +void wxDataViewCtrl::AddChildGTK(wxWindowGTK* child) { - wxDataViewCtrl * dvc = (wxDataViewCtrl*) parent; - GtkWidget *treeview = dvc->GtkGetTreeView(); + GtkWidget* treeview = GtkGetTreeView(); // Insert widget in GtkTreeView if (GTK_WIDGET_REALIZED(treeview)) @@ -3358,7 +3956,7 @@ static void wxInsertChildInDataViewCtrl( wxWindowGTK* parent, wxWindowGTK* child static void gtk_dataviewctrl_size_callback( GtkWidget *WXUNUSED(widget), - GtkAllocation *alloc, + GtkAllocation *WXUNUSED(gtk_alloc), wxDataViewCtrl *win ) { wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst(); @@ -3386,7 +3984,7 @@ void gtk_dataviewctrl_size_callback( GtkWidget *WXUNUSED(widget), //----------------------------------------------------------------------------- static gboolean -gtk_dataview_motion_notify_callback( GtkWidget *widget, +gtk_dataview_motion_notify_callback( GtkWidget *WXUNUSED(widget), GdkEventMotion *gdk_event, wxDataViewCtrl *dv ) { @@ -3476,6 +4074,8 @@ wxDataViewCtrl::~wxDataViewCtrl() if (m_notifier) GetModel()->RemoveNotifier( m_notifier ); + m_cols.Clear(); + // remove the model from the GtkTreeView before it gets destroyed by the // wxDataViewCtrlBase's dtor gtk_tree_view_set_model( GTK_TREE_VIEW(m_treeview), NULL ); @@ -3487,6 +4087,8 @@ void wxDataViewCtrl::Init() { m_notifier = NULL; m_internal = NULL; + + m_cols.DeleteContents( true ); } bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id, @@ -3502,11 +4104,10 @@ bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id, return false; } - m_insertCallback = wxInsertChildInDataViewCtrl; - m_widget = gtk_scrolled_window_new (NULL, NULL); + g_object_ref(m_widget); - GtkScrolledWindowSetBorder(m_widget, style); + GTKScrolledWindowSetBorder(m_widget, style); m_treeview = gtk_tree_view_new(); gtk_container_add (GTK_CONTAINER (m_widget), m_treeview); @@ -3516,7 +4117,10 @@ bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id, #ifdef __WXGTK26__ if (!gtk_check_version(2,6,0)) - gtk_tree_view_set_fixed_height_mode( GTK_TREE_VIEW(m_treeview), TRUE ); + { + bool fixed = (style & wxDV_VARIABLE_LINE_HEIGHT) == 0; + gtk_tree_view_set_fixed_height_mode( GTK_TREE_VIEW(m_treeview), fixed ); + } #endif if (style & wxDV_MULTIPLE) @@ -3548,7 +4152,7 @@ bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id, gtk_tree_view_set_rules_hint( GTK_TREE_VIEW(m_treeview), (style & wxDV_ROW_LINES) != 0 ); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (m_widget), - GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_widget_show (m_treeview); m_parent->DoAddChild( this ); @@ -3577,7 +4181,7 @@ bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id, g_signal_connect (m_treeview, "button_press_event", G_CALLBACK (gtk_dataview_button_press_callback), this); - + return true; } @@ -3600,14 +4204,22 @@ bool wxDataViewCtrl::AssociateModel( wxDataViewModel *model ) { delete m_internal; m_internal = NULL; - + delete m_notifier; m_notifier = NULL; } - + if (!wxDataViewCtrlBase::AssociateModel( model )) return false; +#ifdef __WXGTK26__ + if (!gtk_check_version(2,6,0)) + { + bool fixed = (((GetWindowStyle() & wxDV_VARIABLE_LINE_HEIGHT) == 0) || (model->IsVirtualListModel())); + gtk_tree_view_set_fixed_height_mode( GTK_TREE_VIEW(m_treeview), fixed ); + } +#endif + GtkWxTreeModel *gtk_model = wxgtk_tree_model_new(); m_internal = new wxDataViewCtrlInternal( this, model, gtk_model ); gtk_model->internal = m_internal; @@ -3624,6 +4236,16 @@ bool wxDataViewCtrl::AssociateModel( wxDataViewModel *model ) return true; } +bool wxDataViewCtrl::EnableDragSource( const wxDataFormat &format ) +{ + return m_internal->EnableDragSource( format ); +} + +bool wxDataViewCtrl::EnableDropTarget( const wxDataFormat &format ) +{ + return m_internal->EnableDropTarget( format ); +} + bool wxDataViewCtrl::AppendColumn( wxDataViewColumn *col ) { if (!wxDataViewCtrlBase::AppendColumn(col)) @@ -3631,6 +4253,15 @@ bool wxDataViewCtrl::AppendColumn( wxDataViewColumn *col ) m_cols.Append( col ); +#ifdef __WXGTK26__ + if (!gtk_check_version(2,6,0)) + { + if (gtk_tree_view_column_get_sizing( GTK_TREE_VIEW_COLUMN(col->GetGtkHandle()) ) != + GTK_TREE_VIEW_COLUMN_FIXED) + gtk_tree_view_set_fixed_height_mode( GTK_TREE_VIEW(m_treeview), FALSE ); + } +#endif + gtk_tree_view_append_column( GTK_TREE_VIEW(m_treeview), GTK_TREE_VIEW_COLUMN(col->GetGtkHandle()) ); @@ -3644,12 +4275,43 @@ bool wxDataViewCtrl::PrependColumn( wxDataViewColumn *col ) m_cols.Insert( col ); +#ifdef __WXGTK26__ + if (!gtk_check_version(2,6,0)) + { + if (gtk_tree_view_column_get_sizing( GTK_TREE_VIEW_COLUMN(col->GetGtkHandle()) ) != + GTK_TREE_VIEW_COLUMN_FIXED) + gtk_tree_view_set_fixed_height_mode( GTK_TREE_VIEW(m_treeview), FALSE ); + } +#endif + gtk_tree_view_insert_column( GTK_TREE_VIEW(m_treeview), GTK_TREE_VIEW_COLUMN(col->GetGtkHandle()), 0 ); return true; } +bool wxDataViewCtrl::InsertColumn( unsigned int pos, wxDataViewColumn *col ) +{ + if (!wxDataViewCtrlBase::InsertColumn(pos,col)) + return false; + + m_cols.Insert( pos, col ); + +#ifdef __WXGTK26__ + if (!gtk_check_version(2,6,0)) + { + if (gtk_tree_view_column_get_sizing( GTK_TREE_VIEW_COLUMN(col->GetGtkHandle()) ) != + GTK_TREE_VIEW_COLUMN_FIXED) + gtk_tree_view_set_fixed_height_mode( GTK_TREE_VIEW(m_treeview), FALSE ); + } +#endif + + gtk_tree_view_insert_column( GTK_TREE_VIEW(m_treeview), + GTK_TREE_VIEW_COLUMN(col->GetGtkHandle()), pos ); + + return true; +} + unsigned int wxDataViewCtrl::GetColumnCount() const { return m_cols.GetCount(); @@ -3662,7 +4324,7 @@ wxDataViewColumn* wxDataViewCtrl::GetColumn( unsigned int pos ) const return NULL; wxDataViewColumnList::const_iterator iter; - for (iter = m_cols.begin(); iter != m_cols.end(); iter++) + for (iter = m_cols.begin(); iter != m_cols.end(); ++iter) { wxDataViewColumn *col = *iter; if (GTK_TREE_VIEW_COLUMN(col->GetGtkHandle()) == gtk_col) @@ -3679,9 +4341,7 @@ bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn *column ) gtk_tree_view_remove_column( GTK_TREE_VIEW(m_treeview), GTK_TREE_VIEW_COLUMN(column->GetGtkHandle()) ); - m_cols.remove( column ); - - delete column; + m_cols.DeleteObject( column ); return true; } @@ -3689,14 +4349,14 @@ bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn *column ) bool wxDataViewCtrl::ClearColumns() { wxDataViewColumnList::iterator iter; - for (iter = m_cols.begin(); iter != m_cols.end(); iter++) + for (iter = m_cols.begin(); iter != m_cols.end(); ++iter) { wxDataViewColumn *col = *iter; gtk_tree_view_remove_column( GTK_TREE_VIEW(m_treeview), GTK_TREE_VIEW_COLUMN(col->GetGtkHandle()) ); } - m_cols.clear(); + m_cols.Clear(); return true; } @@ -3737,6 +4397,17 @@ void wxDataViewCtrl::Collapse( const wxDataViewItem & item ) gtk_tree_path_free( path ); } +bool wxDataViewCtrl::IsExpanded( const wxDataViewItem & item ) const +{ + GtkTreeIter iter; + iter.user_data = item.GetID(); + GtkTreePath *path = m_internal->get_path( &iter ); + bool res = gtk_tree_view_row_expanded( GTK_TREE_VIEW(m_treeview), path ); + gtk_tree_path_free( path ); + + return res; +} + wxDataViewItem wxDataViewCtrl::GetSelection() const { GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); @@ -3826,11 +4497,23 @@ void wxDataViewCtrl::SetSelections( const wxDataViewItemArray & sel ) gtk_tree_selection_unselect_all( selection ); + wxDataViewItem last_parent; + size_t i; for (i = 0; i < sel.GetCount(); i++) { + wxDataViewItem item = sel[i]; + wxDataViewItem parent = GetModel()->GetParent( item ); + if (parent) + { + if (parent != last_parent) + ExpandAncestors(item); + } + last_parent = parent; + GtkTreeIter iter; - iter.user_data = (gpointer) sel[i].GetID(); + iter.stamp = m_internal->GetGtkModel()->stamp; + iter.user_data = (gpointer) item.GetID(); gtk_tree_selection_select_iter( selection, &iter ); } @@ -3839,11 +4522,14 @@ void wxDataViewCtrl::SetSelections( const wxDataViewItemArray & sel ) void wxDataViewCtrl::Select( const wxDataViewItem & item ) { + ExpandAncestors(item); + GtkDisableSelectionEvents(); GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); GtkTreeIter iter; + iter.stamp = m_internal->GetGtkModel()->stamp; iter.user_data = (gpointer) item.GetID(); gtk_tree_selection_select_iter( selection, &iter ); @@ -3857,6 +4543,7 @@ void wxDataViewCtrl::Unselect( const wxDataViewItem & item ) GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); GtkTreeIter iter; + iter.stamp = m_internal->GetGtkModel()->stamp; iter.user_data = (gpointer) item.GetID(); gtk_tree_selection_unselect_iter( selection, &iter ); @@ -3868,6 +4555,7 @@ bool wxDataViewCtrl::IsSelected( const wxDataViewItem & item ) const GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); GtkTreeIter iter; + iter.stamp = m_internal->GetGtkModel()->stamp; iter.user_data = (gpointer) item.GetID(); return gtk_tree_selection_iter_is_selected( selection, &iter ); @@ -3895,8 +4583,11 @@ void wxDataViewCtrl::UnselectAll() GtkEnableSelectionEvents(); } -void wxDataViewCtrl::EnsureVisible( const wxDataViewItem & item, const wxDataViewColumn *column ) +void wxDataViewCtrl::EnsureVisible(const wxDataViewItem& item, + const wxDataViewColumn *WXUNUSED(column)) { + ExpandAncestors(item); + GtkTreeIter iter; iter.user_data = (gpointer) item.GetID(); GtkTreePath *path = m_internal->get_path( &iter ); @@ -3904,15 +4595,17 @@ void wxDataViewCtrl::EnsureVisible( const wxDataViewItem & item, const wxDataVie gtk_tree_path_free( path ); } -void wxDataViewCtrl::HitTest( const wxPoint &point, - wxDataViewItem &item, wxDataViewColumn *&column ) const +void wxDataViewCtrl::HitTest(const wxPoint& WXUNUSED(point), + wxDataViewItem& item, + wxDataViewColumn *& column) const { item = wxDataViewItem(0); column = NULL; } -wxRect wxDataViewCtrl::GetItemRect( const wxDataViewItem &item, - const wxDataViewColumn *column ) const +wxRect +wxDataViewCtrl::GetItemRect(const wxDataViewItem& WXUNUSED(item), + const wxDataViewColumn *WXUNUSED(column)) const { return wxRect(); }