X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b8b7b087775eb1136789dcd7ff6419fc038a01d6..2f26ad2872b0119ade133f387dc28a0a9bfad2f0:/src/gtk/dataview.cpp diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index ead35c4ae6..9ab8f4dfc4 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -20,25 +20,18 @@ #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 #include "wx/stockitem.h" #include "wx/calctrl.h" #include "wx/popupwin.h" -#include "wx/icon.h" -#include "wx/list.h" #include "wx/listimpl.cpp" - #include "wx/gtk/private.h" -#include "wx/gtk/win_gtk.h" - -#include -#include -#include -#include - -#include //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- @@ -58,7 +51,7 @@ typedef struct _GtkWxTreeModel GtkWxTreeModel; //----------------------------------------------------------------------------- WX_DECLARE_LIST(wxDataViewItem, ItemList); -WX_DEFINE_LIST(ItemList); +WX_DEFINE_LIST(ItemList) class wxDataViewCtrlInternal { @@ -68,7 +61,6 @@ public: gboolean get_iter( GtkTreeIter *iter, GtkTreePath *path ); GtkTreePath *get_path( GtkTreeIter *iter); - GtkTreePath *get_path_safe( GtkTreeIter *iter); gboolean iter_next( GtkTreeIter *iter ); gboolean iter_children( GtkTreeIter *iter, GtkTreeIter *parent); gboolean iter_has_child( GtkTreeIter *iter ); @@ -89,6 +81,15 @@ public: void SetSortOrder( GtkSortType sort_order ) { m_sort_order = sort_order; } GtkSortType GetSortOrder() { return m_sort_order; } + + void SetSortColumn( int column ) { m_sort_column = column; } + int GetSortColumn() { 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); } + protected: void InitTree(); @@ -104,6 +105,8 @@ private: GtkWxTreeModel *m_gtk_model; wxDataViewCtrl *m_owner; GtkSortType m_sort_order; + wxDataViewColumn *m_dataview_sort_column; + int m_sort_column; }; @@ -111,10 +114,16 @@ private: // wxGtkTreeModelNode //----------------------------------------------------------------------------- -int LINKAGEMODE wxGtkTreeModelNodeCmp( void *id1, void *id2 ); +int LINKAGEMODE wxGtkTreeModelChildCmp( void** id1, void** id2 ) +{ + int ret = g_internal->GetDataViewModel()->Compare( *id1, *id2, + g_internal->GetSortColumn(), (g_internal->GetSortOrder() == GTK_SORT_ASCENDING) ); + + return ret; +} WX_DEFINE_ARRAY_PTR( wxGtkTreeModelNode*, wxGtkTreeModelNodes ); -WX_DEFINE_SORTED_ARRAY( void* , wxGtkTreeModelChildren ); +WX_DEFINE_ARRAY_PTR( void*, wxGtkTreeModelChildren ); class wxGtkTreeModelNode { @@ -125,50 +134,57 @@ public: m_parent = parent; m_item = item; m_internal = internal; - g_internal = internal; - m_children = new wxGtkTreeModelChildren( wxGtkTreeModelNodeCmp ); } ~wxGtkTreeModelNode() { - g_internal = m_internal; - size_t count = m_children->GetCount(); + size_t count = m_children.GetCount(); size_t i; for (i = 0; i < count; i++) { wxGtkTreeModelNode *child = m_nodes.Item( i ); delete child; } - delete m_children; } unsigned int AddNode( wxGtkTreeModelNode* child ) { - g_internal = m_internal; m_nodes.Add( child ); - return m_children->Add( child->GetItem().GetID() ); + + void *id = child->GetItem().GetID(); + + m_children.Add( id ); + + if (m_internal->IsSorted() || m_internal->GetDataViewModel()->HasDefaultCompare()) + { + g_internal = m_internal; + m_children.Sort( &wxGtkTreeModelChildCmp ); + return m_children.Index( id ); + } + + return m_children.GetCount()-1; } unsigned int AddLeave( void* id ) { - g_internal = m_internal; - return m_children->Add( id ); + m_children.Add( id ); + + if (m_internal->IsSorted() || m_internal->GetDataViewModel()->HasDefaultCompare()) + { + g_internal = m_internal; + m_children.Sort( &wxGtkTreeModelChildCmp ); + return m_children.Index( id ); + } + + return m_children.GetCount()-1; } void DeleteChild( void* id ) { - g_internal = m_internal; - size_t pos; - size_t count = m_children->GetCount(); - for (pos = 0; pos < count; pos++) - { - if (m_children->Item( pos ) == id) - { - m_children->RemoveAt( pos ); - break; - } - } - count = m_nodes.GetCount(); + m_children.Remove( id ); + + unsigned int count = m_nodes.GetCount(); + unsigned int pos; for (pos = 0; pos < count; pos++) { wxGtkTreeModelNode *node = m_nodes.Item( pos ); @@ -187,9 +203,9 @@ public: wxGtkTreeModelNodes &GetNodes() { return m_nodes; } wxGtkTreeModelChildren &GetChildren() - { return *m_children; } + { return m_children; } - unsigned int GetChildCount() { return m_children->GetCount(); } + unsigned int GetChildCount() { return m_children.GetCount(); } unsigned int GetNodesCount() { return m_nodes.GetCount(); } wxDataViewItem &GetItem() { return m_item; } @@ -200,20 +216,12 @@ public: private: wxGtkTreeModelNode *m_parent; wxGtkTreeModelNodes m_nodes; - wxGtkTreeModelChildren *m_children; + wxGtkTreeModelChildren m_children; wxDataViewItem m_item; wxDataViewCtrlInternal *m_internal; }; -int LINKAGEMODE wxGtkTreeModelNodeCmp( void* id1, void* id2 ) -{ - int ret = g_internal->GetDataViewModel()->Compare( id1, id2 ); - if (g_internal->GetSortOrder() == GTK_SORT_DESCENDING) - return -ret; - return ret; -} - //----------------------------------------------------------------------------- // data //----------------------------------------------------------------------------- @@ -266,8 +274,6 @@ static gboolean wxgtk_tree_model_get_iter (GtkTreeModel *tree_mo GtkTreePath *path); static GtkTreePath *wxgtk_tree_model_get_path (GtkTreeModel *tree_model, GtkTreeIter *iter); -static GtkTreePath *wxgtk_tree_model_get_path_safe (GtkTreeModel *tree_model, - GtkTreeIter *iter); static void wxgtk_tree_model_get_value (GtkTreeModel *tree_model, GtkTreeIter *iter, gint column, @@ -454,7 +460,8 @@ wxgtk_tree_model_get_column_type (GtkTreeModel *tree_model, gtype = G_TYPE_STRING; else { - wxFAIL_MSG( _T("non-string columns not supported yet") ); + gtype = G_TYPE_STRING; + // wxFAIL_MSG( _T("non-string columns not supported yet") ); } return gtype; @@ -483,17 +490,6 @@ wxgtk_tree_model_get_path (GtkTreeModel *tree_model, return wxtree_model->internal->get_path( iter ); } -static GtkTreePath * -wxgtk_tree_model_get_path_safe (GtkTreeModel *tree_model, - GtkTreeIter *iter) -{ - GtkWxTreeModel *wxtree_model = (GtkWxTreeModel *) tree_model; - g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (wxtree_model), NULL); - g_return_val_if_fail (iter->stamp == GTK_WX_TREE_MODEL (wxtree_model)->stamp, NULL); - - return wxtree_model->internal->get_path_safe( iter ); -} - static void wxgtk_tree_model_get_value (GtkTreeModel *tree_model, GtkTreeIter *iter, @@ -598,8 +594,17 @@ gboolean wxgtk_tree_model_get_sort_column_id (GtkTreeSortable *sortabl g_return_val_if_fail (GTK_IS_WX_TREE_MODEL (sortable), FALSE); + if (!tree_model->internal->IsSorted()) + { + if (sort_column_id) + *sort_column_id = -1; + + return TRUE; + } + + if (sort_column_id) - *sort_column_id = tree_model->internal->GetDataViewModel()->GetSortingColumn(); + *sort_column_id = tree_model->internal->GetSortColumn(); if (order) *order = tree_model->internal->GetSortOrder(); @@ -607,6 +612,8 @@ gboolean wxgtk_tree_model_get_sort_column_id (GtkTreeSortable *sortabl return TRUE; } +wxDataViewColumn *gs_lastLeftClickHeader = NULL; + void wxgtk_tree_model_set_sort_column_id (GtkTreeSortable *sortable, gint sort_column_id, GtkSortType order) @@ -614,17 +621,29 @@ void wxgtk_tree_model_set_sort_column_id (GtkTreeSortable *sortable, GtkWxTreeModel *tree_model = (GtkWxTreeModel *) sortable; g_return_if_fail (GTK_IS_WX_TREE_MODEL (sortable) ); - if ((sort_column_id == (gint) tree_model->internal->GetDataViewModel()->GetSortingColumn()) && - (order == tree_model->internal->GetSortOrder())) - return; + tree_model->internal->SetDataViewSortColumn( gs_lastLeftClickHeader ); - tree_model->internal->GetDataViewModel()->SetSortingColumn( sort_column_id ); + if ((sort_column_id != (gint) tree_model->internal->GetSortColumn()) || + (order != tree_model->internal->GetSortOrder())) + { + tree_model->internal->SetSortColumn( sort_column_id ); + tree_model->internal->SetSortOrder( order ); - tree_model->internal->SetSortOrder( order ); + gtk_tree_sortable_sort_column_changed (sortable); - gtk_tree_sortable_sort_column_changed (sortable); + tree_model->internal->GetDataViewModel()->Resort(); + } + + if (gs_lastLeftClickHeader) + { + wxDataViewCtrl *dv = tree_model->internal->GetOwner(); + wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED, dv->GetId() ); + event.SetDataViewColumn( gs_lastLeftClickHeader ); + event.SetModel( dv->GetModel() ); + dv->GetEventHandler()->ProcessEvent( event ); + } - tree_model->internal->GetDataViewModel()->Resort(); + gs_lastLeftClickHeader = NULL; } void wxgtk_tree_model_set_sort_func (GtkTreeSortable *sortable, @@ -894,6 +913,13 @@ gtk_wx_cell_renderer_render (GtkCellRenderer *renderer, GtkWxCellRenderer *wxrenderer = (GtkWxCellRenderer *) renderer; wxDataViewCustomRenderer *cell = wxrenderer->cell; + cell->window = window; + cell->widget = widget; + cell->background_area = (void*) background_area; + cell->cell_area = (void*) cell_area; + cell->expose_area = (void*) expose_area; + cell->flags = (int) flags; + GdkRectangle rect; gtk_wx_cell_renderer_get_size (renderer, widget, cell_area, &rect.x, @@ -911,11 +937,20 @@ gtk_wx_cell_renderer_render (GtkCellRenderer *renderer, { wxRect renderrect( rect.x, rect.y, rect.width, rect.height ); wxWindowDC* dc = (wxWindowDC*) cell->GetDC(); +#if wxUSE_NEW_DC + wxGTKWindowImplDC *impldc = (wxGTKWindowImplDC *) dc->GetImpl(); + if (impldc->m_window == NULL) + { + impldc->m_window = window; + impldc->SetUpDC(); + } +#else if (dc->m_window == NULL) { dc->m_window = window; dc->SetUpDC(); } +#endif int state = 0; if (flags & GTK_CELL_RENDERER_SELECTED) @@ -962,8 +997,10 @@ gtk_wx_cell_renderer_activate( wxDataViewModel *model = cell->GetOwner()->GetOwner()->GetModel(); GtkTreePath *treepath = gtk_tree_path_new_from_string( path ); - // TODO - wxDataViewItem item; + + GtkTreeIter iter; + cell->GetOwner()->GetOwner()->GtkGetInternal()->get_iter( &iter, treepath ); + wxDataViewItem item( iter.user_data ); gtk_tree_path_free( treepath ); unsigned int model_col = cell->GetOwner()->GetModelColumn(); @@ -1074,7 +1111,7 @@ bool wxGtkDataViewModelNotifier::ItemDeleted( const wxDataViewItem &parent, cons iter.stamp = m_wxgtk_model->stamp; iter.user_data = (gpointer) item.GetID(); - GtkTreePath *path = wxgtk_tree_model_get_path_safe( + GtkTreePath *path = wxgtk_tree_model_get_path( GTK_TREE_MODEL(m_wxgtk_model), &iter ); gtk_tree_model_row_deleted( GTK_TREE_MODEL(m_wxgtk_model), path ); @@ -1160,6 +1197,51 @@ bool wxGtkDataViewModelNotifier::Cleared() // wxDataViewRenderer // --------------------------------------------------------- +static gpointer s_user_data = NULL; + +static void +wxgtk_cell_editable_editing_done( GtkCellEditable *editable, + wxDataViewRenderer *wxrenderer ) +{ + wxDataViewColumn *column = wxrenderer->GetOwner(); + wxDataViewCtrl *dv = column->GetOwner(); + wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE, dv->GetId() ); + event.SetDataViewColumn( column ); + event.SetModel( dv->GetModel() ); + wxDataViewItem item( s_user_data ); + event.SetItem( item ); + dv->GetEventHandler()->ProcessEvent( event ); +} + +static void +wxgtk_renderer_editing_started( GtkCellRenderer *cell, GtkCellEditable *editable, + gchar *path, wxDataViewRenderer *wxrenderer ) +{ + wxDataViewColumn *column = wxrenderer->GetOwner(); + wxDataViewCtrl *dv = column->GetOwner(); + wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED, dv->GetId() ); + event.SetDataViewColumn( column ); + event.SetModel( dv->GetModel() ); + GtkTreePath *tree_path = gtk_tree_path_new_from_string( path ); + GtkTreeIter iter; + dv->GtkGetInternal()->get_iter( &iter, tree_path ); + gtk_tree_path_free( tree_path ); + wxDataViewItem item( iter.user_data ); + event.SetItem( item ); + dv->GetEventHandler()->ProcessEvent( event ); + + if (GTK_IS_CELL_EDITABLE(editable)) + { + s_user_data = iter.user_data; + + g_signal_connect (GTK_CELL_EDITABLE (editable), "editing_done", + G_CALLBACK (wxgtk_cell_editable_editing_done), + (gpointer) wxrenderer ); + + } +} + + IMPLEMENT_ABSTRACT_CLASS(wxDataViewRenderer, wxDataViewRendererBase) wxDataViewRenderer::wxDataViewRenderer( const wxString &varianttype, wxDataViewCellMode mode, @@ -1172,6 +1254,16 @@ wxDataViewRenderer::wxDataViewRenderer( const wxString &varianttype, wxDataViewC // after the m_renderer pointer has been initialized } +void wxDataViewRenderer::GtkInitHandlers() +{ + if (!gtk_check_version(2,6,0)) + { + g_signal_connect (GTK_CELL_RENDERER(m_renderer), "editing_started", + G_CALLBACK (wxgtk_renderer_editing_started), + this); + } +} + void wxDataViewRenderer::SetMode( wxDataViewCellMode mode ) { GtkCellRendererMode gtkMode; @@ -1188,6 +1280,7 @@ void wxDataViewRenderer::SetMode( wxDataViewCellMode mode ) break; } + // This value is most often ignored in GtkTreeView GValue gvalue = { 0, }; g_value_init( &gvalue, gtk_cell_renderer_mode_get_type() ); g_value_set_enum( &gvalue, gtkMode ); @@ -1336,6 +1429,8 @@ wxDataViewTextRenderer::wxDataViewTextRenderer( const wxString &varianttype, wxD g_value_unset( &gvalue ); g_signal_connect_after( m_renderer, "edited", G_CALLBACK(wxGtkTextRendererEditedCallback), this ); + + GtkInitHandlers(); } SetMode(mode); @@ -1348,7 +1443,7 @@ bool wxDataViewTextRenderer::SetValue( const wxVariant &value ) GValue gvalue = { 0, }; g_value_init( &gvalue, G_TYPE_STRING ); - g_value_set_string( &gvalue, wxGTK_CONV_FONT( tmp, GetOwner()->GetOwner()->GetFont() ) ); + g_value_set_string( &gvalue, wxGTK_CONV( tmp ) ); g_object_set_property( G_OBJECT(m_renderer), "text", &gvalue ); g_value_unset( &gvalue ); @@ -1360,8 +1455,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( g_value_get_string( &gvalue ) ); g_value_unset( &gvalue ); value = tmp; @@ -1390,6 +1484,18 @@ void wxDataViewTextRenderer::SetAlignment( int align ) g_value_unset( &gvalue ); } +// --------------------------------------------------------- +// wxDataViewTextRendererAttr +// --------------------------------------------------------- + +IMPLEMENT_CLASS(wxDataViewTextRendererAttr,wxDataViewTextRenderer) + +wxDataViewTextRendererAttr::wxDataViewTextRendererAttr( const wxString &varianttype, + wxDataViewCellMode mode, int align ) : + wxDataViewTextRenderer( varianttype, mode, align ) +{ +} + // --------------------------------------------------------- // wxDataViewBitmapRenderer // --------------------------------------------------------- @@ -1554,6 +1660,20 @@ class wxDataViewCtrlDC: public wxWindowDC public: wxDataViewCtrlDC( wxDataViewCtrl *window ) { +#if wxUSE_NEW_DC + wxGTKWindowImplDC *impl = (wxGTKWindowImplDC*) GetImpl(); + + GtkWidget *widget = window->m_treeview; + // Set later + impl->m_window = NULL; + + impl->m_context = window->GtkGetPangoDefaultContext(); + impl->m_layout = pango_layout_new( impl->m_context ); + impl->m_fontdesc = pango_font_description_copy( widget->style->font_desc ); + + impl->m_cmap = gtk_widget_get_colormap( widget ? widget : window->m_widget ); + +#else GtkWidget *widget = window->m_treeview; // Set later m_window = NULL; @@ -1563,7 +1683,7 @@ public: m_fontdesc = pango_font_description_copy( widget->style->font_desc ); m_cmap = gtk_widget_get_colormap( widget ? widget : window->m_widget ); - +#endif // Set m_window later // SetUpDC(); // m_owner = window; @@ -1582,6 +1702,7 @@ wxDataViewCustomRenderer::wxDataViewCustomRenderer( const wxString &varianttype, wxDataViewRenderer( varianttype, mode, align ) { m_dc = NULL; + m_text_renderer = NULL; if (no_init) m_renderer = NULL; @@ -1589,6 +1710,41 @@ wxDataViewCustomRenderer::wxDataViewCustomRenderer( const wxString &varianttype, Init(mode, align); } +void wxDataViewCustomRenderer::RenderText( const wxString &text, int xoffset, wxRect cell, wxDC *dc, int state ) +{ +#if 0 + wxDataViewCtrl *view = GetOwner()->GetOwner(); + wxColour col = (state & wxDATAVIEW_CELL_SELECTED) ? + wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) : + view->GetForegroundColour(); + dc->SetTextForeground(col); + dc->DrawText( text, cell.x + xoffset, cell.y + ((cell.height - dc->GetCharHeight()) / 2)); +#else + if (!m_text_renderer) + m_text_renderer = gtk_cell_renderer_text_new(); + + GValue gvalue = { 0, }; + g_value_init( &gvalue, G_TYPE_STRING ); + g_value_set_string( &gvalue, wxGTK_CONV( text ) ); + g_object_set_property( G_OBJECT(m_text_renderer), "text", &gvalue ); + g_value_unset( &gvalue ); + + ((GdkRectangle*) cell_area)->x += xoffset; + ((GdkRectangle*) cell_area)->width -= xoffset; + + gtk_cell_renderer_render( m_text_renderer, + window, + widget, + (GdkRectangle*) background_area, + (GdkRectangle*) cell_area, + (GdkRectangle*) expose_area, + (GtkCellRendererState) flags ); + + ((GdkRectangle*) cell_area)->x -= xoffset; + ((GdkRectangle*) cell_area)->width += xoffset; +#endif +} + bool wxDataViewCustomRenderer::Init(wxDataViewCellMode mode, int align) { GtkWxCellRenderer *renderer = (GtkWxCellRenderer *) gtk_wx_cell_renderer_new(); @@ -1599,6 +1755,8 @@ bool wxDataViewCustomRenderer::Init(wxDataViewCellMode mode, int align) SetMode(mode); SetAlignment(align); + GtkInitHandlers(); + return true; } @@ -1606,6 +1764,9 @@ wxDataViewCustomRenderer::~wxDataViewCustomRenderer() { if (m_dc) delete m_dc; + + if (m_text_renderer) + gtk_object_sink( GTK_OBJECT(m_text_renderer) ); } wxDC *wxDataViewCustomRenderer::GetDC() @@ -1643,8 +1804,7 @@ wxDataViewProgressRenderer::wxDataViewProgressRenderer( const wxString &label, GValue gvalue = { 0, }; g_value_init( &gvalue, G_TYPE_STRING ); - // FIXME: font encoding support - g_value_set_string( &gvalue, wxGTK_CONV_SYS(m_label) ); + g_value_set_string( &gvalue, wxGTK_CONV(m_label) ); g_object_set_property( G_OBJECT(m_renderer), "text", &gvalue ); g_value_unset( &gvalue ); @@ -1788,8 +1948,7 @@ bool wxDataViewDateRenderer::Render( wxRect cell, wxDC *dc, int state ) { dc->SetFont( GetOwner()->GetOwner()->GetFont() ); wxString tmp = m_date.FormatDate(); - dc->DrawText( tmp, cell.x, cell.y ); - + RenderText( tmp, 0, cell, dc, state ); return true; } @@ -1818,6 +1977,74 @@ bool wxDataViewDateRenderer::Activate( wxRect cell, wxDataViewModel *model, return true; } + +// --------------------------------------------------------- +// wxDataViewIconTextRenderer +// --------------------------------------------------------- + +IMPLEMENT_CLASS(wxDataViewIconTextRenderer, wxDataViewCustomRenderer) + +wxDataViewIconTextRenderer::wxDataViewIconTextRenderer( + const wxString &varianttype, wxDataViewCellMode mode, int align ) : + wxDataViewCustomRenderer( varianttype, mode, align ) +{ + SetMode(mode); + SetAlignment(align); +} + +wxDataViewIconTextRenderer::~wxDataViewIconTextRenderer() +{ +} + +bool wxDataViewIconTextRenderer::SetValue( const wxVariant &value ) +{ + m_value << value; + return true; +} + +bool wxDataViewIconTextRenderer::GetValue( wxVariant &value ) const +{ + return false; +} + +bool wxDataViewIconTextRenderer::Render( wxRect cell, wxDC *dc, int state ) +{ + const wxIcon &icon = m_value.GetIcon(); + int offset = 0; + if (icon.IsOk()) + { + int yoffset = wxMax( 0, (cell.height - icon.GetHeight()) / 2 ); + dc->DrawIcon( icon, cell.x, cell.y + yoffset ); + offset = icon.GetWidth() + 4; + } + + RenderText( m_value.GetText(), offset, cell, dc, state ); + + return true; +} + +wxSize wxDataViewIconTextRenderer::GetSize() const +{ + wxSize size; + if (m_value.GetIcon().IsOk()) + size.x = 4 + m_value.GetIcon().GetWidth(); + wxCoord x,y,d; + GetView()->GetTextExtent( m_value.GetText(), &x, &y, &d ); + size.x += x; + size.y = y+d; + return size; +} + +wxControl* wxDataViewIconTextRenderer::CreateEditorCtrl( wxWindow *parent, wxRect labelRect, const wxVariant &value ) +{ + return NULL; +} + +bool wxDataViewIconTextRenderer::GetValueFromEditorCtrl( wxControl* editor, wxVariant &value ) +{ + return false; +} + // --------------------------------------------------------- // wxDataViewColumn // --------------------------------------------------------- @@ -1833,12 +2060,24 @@ 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 ); event.SetModel( dv->GetModel() ); if (dv->GetEventHandler()->ProcessEvent( event )) - return TRUE; + return FALSE; + } + + if (gdk_event->button == 3) + { + wxDataViewCtrl *dv = column->GetOwner(); + wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK, dv->GetId() ); + event.SetDataViewColumn( column ); + event.SetModel( dv->GetModel() ); + if (dv->GetEventHandler()->ProcessEvent( event )) + return FALSE; } return FALSE; @@ -1866,8 +2105,40 @@ static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *column, wxDataViewItem item( (void*) iter->user_data ); + wxDataViewModel *wx_model = tree_model->internal->GetDataViewModel(); + + if (wx_model->IsContainer( item )) + { + if (wx_model->HasContainerColumns( item ) || (cell->GetOwner()->GetModelColumn() == 0)) + { + GValue gvalue = { 0, }; + g_value_init( &gvalue, G_TYPE_BOOLEAN ); + g_value_set_boolean( &gvalue, TRUE ); + g_object_set_property( G_OBJECT(renderer), "visible", &gvalue ); + g_value_unset( &gvalue ); + } + else + { + GValue gvalue = { 0, }; + g_value_init( &gvalue, G_TYPE_BOOLEAN ); + g_value_set_boolean( &gvalue, FALSE ); + g_object_set_property( G_OBJECT(renderer), "visible", &gvalue ); + g_value_unset( &gvalue ); + + return; + } + } + else + { + GValue gvalue = { 0, }; + g_value_init( &gvalue, G_TYPE_BOOLEAN ); + g_value_set_boolean( &gvalue, TRUE ); + g_object_set_property( G_OBJECT(renderer), "visible", &gvalue ); + g_value_unset( &gvalue ); + } + wxVariant value; - tree_model->internal->GetDataViewModel()->GetValue( value, item, cell->GetOwner()->GetModelColumn() ); + wx_model->GetValue( value, item, cell->GetOwner()->GetModelColumn() ); if (value.GetType() != cell->GetVariantType()) wxLogError( wxT("Wrong type, required: %s but: %s"), @@ -1876,10 +2147,82 @@ static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *column, cell->SetValue( value ); -#if 0 - wxListItemAttr attr; - tree_model->model->GetAttr( attr, cell->GetOwner()->GetModelColumn(), model_row ); + if (cell->GtkHasAttributes()) + { + wxDataViewItemAttr attr; + bool colour_set = false; + bool style_set = false; + bool weight_set = false; + + if (wx_model->GetAttr( item, cell->GetOwner()->GetModelColumn(), attr )) + { + // this must be a GtkCellRendererText + wxColour colour = attr.GetColour(); + if (colour.IsOk()) + { + const GdkColor * const gcol = colour.GetColor(); + + GValue gvalue = { 0, }; + g_value_init( &gvalue, GDK_TYPE_COLOR ); + g_value_set_boxed( &gvalue, gcol ); + g_object_set_property( G_OBJECT(renderer), "foreground_gdk", &gvalue ); + g_value_unset( &gvalue ); + + colour_set = true; + } + + if (attr.GetItalic()) + { + GValue gvalue = { 0, }; + g_value_init( &gvalue, PANGO_TYPE_STYLE ); + g_value_set_enum( &gvalue, PANGO_STYLE_ITALIC ); + g_object_set_property( G_OBJECT(renderer), "style", &gvalue ); + g_value_unset( &gvalue ); + + style_set = true; + } + + if (attr.GetBold()) + { + GValue gvalue = { 0, }; + g_value_init( &gvalue, PANGO_TYPE_WEIGHT ); + g_value_set_enum( &gvalue, PANGO_WEIGHT_BOLD ); + g_object_set_property( G_OBJECT(renderer), "weight", &gvalue ); + g_value_unset( &gvalue ); + + weight_set = true; + } + } + + if (!style_set) + { + GValue gvalue = { 0, }; + g_value_init( &gvalue, G_TYPE_BOOLEAN ); + g_value_set_boolean( &gvalue, FALSE ); + g_object_set_property( G_OBJECT(renderer), "style-set", &gvalue ); + g_value_unset( &gvalue ); + } + + if (!weight_set) + { + GValue gvalue = { 0, }; + g_value_init( &gvalue, G_TYPE_BOOLEAN ); + g_value_set_boolean( &gvalue, FALSE ); + g_object_set_property( G_OBJECT(renderer), "weight-set", &gvalue ); + g_value_unset( &gvalue ); + } + + if (!colour_set) + { + GValue gvalue = { 0, }; + g_value_init( &gvalue, G_TYPE_BOOLEAN ); + g_value_set_boolean( &gvalue, FALSE ); + g_object_set_property( G_OBJECT(renderer), "foreground-set", &gvalue ); + g_value_unset( &gvalue ); + } + } +#if 0 if (attr.HasBackgroundColour()) { wxColour colour = attr.GetBackgroundColour(); @@ -1905,6 +2248,9 @@ 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 ) : @@ -2084,9 +2430,14 @@ void wxDataViewColumn::SetSortable( bool sortable ) GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column); if (sortable) + { gtk_tree_view_column_set_sort_column_id( column, GetModelColumn() ); + } else + { gtk_tree_view_column_set_sort_column_id( column, -1 ); + gtk_tree_view_column_set_sort_indicator( column, FALSE ); + } } bool wxDataViewColumn::IsSortable() const @@ -2115,6 +2466,8 @@ void wxDataViewColumn::SetSortOrder( bool ascending ) gtk_tree_view_column_set_sort_order( column, GTK_SORT_ASCENDING ); else gtk_tree_view_column_set_sort_order( column, GTK_SORT_DESCENDING ); + + gtk_tree_view_column_set_sort_indicator( column, TRUE ); } bool wxDataViewColumn::IsSortOrderAscending() const @@ -2151,8 +2504,6 @@ void wxDataViewColumn::SetWidth( int width ) void wxGtkTreeModelNode::Resort() { - g_internal = m_internal; - size_t child_count = GetChildCount(); if (child_count == 0) return; @@ -2169,51 +2520,30 @@ void wxGtkTreeModelNode::Resort() return; } - wxGtkTreeModelChildren *new_array = new wxGtkTreeModelChildren( wxGtkTreeModelNodeCmp ); - - size_t pos; - for (pos = 0; pos < child_count; pos++) - new_array->Add( m_children->Item( pos ) ); + wxGtkTreeModelChildren temp; + WX_APPEND_ARRAY( temp, m_children ); + + g_internal = m_internal; + m_children.Sort( &wxGtkTreeModelChildCmp ); gint *new_order = new gint[child_count]; + unsigned int pos; for (pos = 0; pos < child_count; pos++) { - void *id = new_array->Item( pos ); - size_t old_pos; - for (old_pos = 0; old_pos < child_count; old_pos++) - { - if (id == m_children->Item(old_pos)) - { - new_order[pos] = old_pos; - break; - } - } + void *id = m_children.Item( pos ); + int old_pos = temp.Index( id ); + new_order[pos] = old_pos; } -// for (pos = 0; pos < count; pos++) -// m_children->Clear(); - delete m_children; - - m_children = new_array; - GtkTreeModel *gtk_tree_model = GTK_TREE_MODEL( m_internal->GetGtkModel() ); - GtkTreePath *path = gtk_tree_path_new (); - wxGtkTreeModelNode *parent = GetParent(); - void *id = GetItem().GetID(); - - while (parent) - { - int pos = parent->GetChildren().Index( id ); - gtk_tree_path_prepend_index( path, pos ); - id = parent->GetItem().GetID(); - parent = parent->GetParent(); - } - GtkTreeIter iter; - iter.user_data = id; + iter.user_data = GetItem().GetID(); iter.stamp = m_internal->GetGtkModel()->stamp; + + GtkTreePath *path = m_internal->get_path( &iter ); + gtk_tree_model_rows_reordered( gtk_tree_model, path, &iter, new_order ); gtk_tree_path_free (path); @@ -2239,6 +2569,8 @@ wxDataViewCtrlInternal::wxDataViewCtrlInternal( wxDataViewCtrl *owner, m_gtk_model = gtk_model; m_root = NULL; m_sort_order = GTK_SORT_ASCENDING; + m_sort_column = -1; + m_dataview_sort_column = NULL; InitTree(); } @@ -2259,17 +2591,19 @@ void wxDataViewCtrlInternal::BuildBranch( wxGtkTreeModelNode *node ) { if (node->GetChildCount() == 0) { - wxDataViewItem child = m_wx_model->GetFirstChild( node->GetItem() ); - while (child.IsOk()) + wxDataViewItemArray children; + unsigned int count = m_wx_model->GetChildren( node->GetItem(), children ); + unsigned int pos; + for (pos = 0; pos < count; pos++) { + wxDataViewItem child = children[pos]; + if (m_wx_model->IsContainer( child )) node->AddNode( new wxGtkTreeModelNode( node, child, this ) ); else node->AddLeave( child.GetID() ); // Don't send any events here - - child = m_wx_model->GetNextSibling( child ); } } } @@ -2286,13 +2620,7 @@ bool wxDataViewCtrlInternal::ItemAdded( const wxDataViewItem &parent, const wxDa parent_node->AddNode( new wxGtkTreeModelNode( parent_node, item, this ) ); else parent_node->AddLeave( item.GetID() ); - - wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_ADDED, m_owner->GetId() ); - event.SetEventObject( m_owner ); - event.SetModel( m_owner->GetModel() ); - event.SetItem( item ); - m_owner->GetEventHandler()->ProcessEvent( event ); - + return true; } @@ -2301,18 +2629,12 @@ bool wxDataViewCtrlInternal::ItemDeleted( const wxDataViewItem &parent, const wx wxGtkTreeModelNode *parent_node = FindNode( parent ); parent_node->DeleteChild( item.GetID() ); - wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_DELETED, m_owner->GetId() ); - event.SetEventObject( m_owner ); - event.SetModel( m_owner->GetModel() ); - event.SetItem( item ); - m_owner->GetEventHandler()->ProcessEvent( event ); - return true; } bool wxDataViewCtrlInternal::ItemChanged( const wxDataViewItem &item ) { - wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED, m_owner->GetId() ); + wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED, m_owner->GetId() ); event.SetEventObject( m_owner ); event.SetModel( m_owner->GetModel() ); event.SetItem( item ); @@ -2323,10 +2645,11 @@ bool wxDataViewCtrlInternal::ItemChanged( const wxDataViewItem &item ) bool wxDataViewCtrlInternal::ValueChanged( const wxDataViewItem &item, unsigned int col ) { - wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_MODEL_VALUE_CHANGED, m_owner->GetId() ); + wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED, m_owner->GetId() ); event.SetEventObject( m_owner ); event.SetModel( m_owner->GetModel() ); event.SetColumn( col ); + event.SetDataViewColumn( GetOwner()->GetColumn(col) ); event.SetItem( item ); m_owner->GetEventHandler()->ProcessEvent( event ); @@ -2335,18 +2658,11 @@ bool wxDataViewCtrlInternal::ValueChanged( const wxDataViewItem &item, unsigned bool wxDataViewCtrlInternal::Cleared() { - wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_MODEL_CLEARED, m_owner->GetId() ); - event.SetEventObject( m_owner ); - event.SetModel( m_owner->GetModel() ); - m_owner->GetEventHandler()->ProcessEvent( event ); - return true; } gboolean wxDataViewCtrlInternal::get_iter( GtkTreeIter *iter, GtkTreePath *path ) { - g_internal = this; - int depth = gtk_tree_path_get_depth( path ); wxGtkTreeModelNode *node = m_root; @@ -2387,8 +2703,6 @@ gboolean wxDataViewCtrlInternal::get_iter( GtkTreeIter *iter, GtkTreePath *path GtkTreePath *wxDataViewCtrlInternal::get_path( GtkTreeIter *iter ) { - g_internal = this; - GtkTreePath *retval = gtk_tree_path_new (); void *id = iter->user_data; @@ -2396,6 +2710,7 @@ GtkTreePath *wxDataViewCtrlInternal::get_path( GtkTreeIter *iter ) while (node) { int pos = node->GetChildren().Index( id ); + gtk_tree_path_prepend_index( retval, pos ); id = node->GetItem().GetID(); @@ -2405,44 +2720,15 @@ GtkTreePath *wxDataViewCtrlInternal::get_path( GtkTreeIter *iter ) return retval; } -GtkTreePath *wxDataViewCtrlInternal::get_path_safe( GtkTreeIter *iter ) -{ - g_internal = this; - - GtkTreePath *retval = gtk_tree_path_new (); - void *id = iter->user_data; - - wxGtkTreeModelNode *node = FindParentNode( iter ); - while (node) - { - size_t pos; - for (pos = 0; pos < node->GetChildren().GetCount(); pos++) - { - if (id == node->GetChildren().Item( pos )) - { - gtk_tree_path_prepend_index( retval, (int) pos ); - continue; - } - } - - id = node->GetItem().GetID(); - node = node->GetParent(); - } - - return retval; -} - gboolean wxDataViewCtrlInternal::iter_next( GtkTreeIter *iter ) { - g_internal = this; - wxGtkTreeModelNode *parent = FindParentNode( iter ); if( parent == NULL ) return FALSE; - unsigned int pos = parent->GetChildren().Index( iter->user_data ); - - if (pos == parent->GetChildCount()-1) + int pos = parent->GetChildren().Index( iter->user_data ); + + if (pos == (int) parent->GetChildCount()-1) return FALSE; iter->stamp = m_gtk_model->stamp; @@ -2453,8 +2739,6 @@ gboolean wxDataViewCtrlInternal::iter_next( GtkTreeIter *iter ) gboolean wxDataViewCtrlInternal::iter_children( GtkTreeIter *iter, GtkTreeIter *parent ) { - g_internal = this; - wxDataViewItem item( (void*) parent->user_data ); if (!m_wx_model->IsContainer( item )) @@ -2474,14 +2758,13 @@ gboolean wxDataViewCtrlInternal::iter_children( GtkTreeIter *iter, GtkTreeIter * gboolean wxDataViewCtrlInternal::iter_has_child( GtkTreeIter *iter ) { - g_internal = this; - wxDataViewItem item( (void*) iter->user_data ); + bool is_container = m_wx_model->IsContainer( item ); if (!is_container) return FALSE; - + wxGtkTreeModelNode *node = FindNode( iter ); BuildBranch( node ); @@ -2490,8 +2773,6 @@ gboolean wxDataViewCtrlInternal::iter_has_child( GtkTreeIter *iter ) gint wxDataViewCtrlInternal::iter_n_children( GtkTreeIter *iter ) { - g_internal = this; - wxDataViewItem item( (void*) iter->user_data ); if (!m_wx_model->IsContainer( item )) @@ -2507,8 +2788,6 @@ gint wxDataViewCtrlInternal::iter_n_children( GtkTreeIter *iter ) gboolean wxDataViewCtrlInternal::iter_nth_child( GtkTreeIter *iter, GtkTreeIter *parent, gint n ) { - g_internal = this; - void* id = NULL; if (parent) id = (void*) parent->user_data; wxDataViewItem item( id ); @@ -2529,8 +2808,6 @@ gboolean wxDataViewCtrlInternal::iter_nth_child( GtkTreeIter *iter, GtkTreeIter gboolean wxDataViewCtrlInternal::iter_parent( GtkTreeIter *iter, GtkTreeIter *child ) { - g_internal = this; - wxGtkTreeModelNode *node = FindParentNode( child ); if (!node) return FALSE; @@ -2550,6 +2827,7 @@ wxDataViewCtrlInternal_FindNode( wxDataViewModel * model, wxGtkTreeModelNode *tr ItemList list; list.DeleteContents( true ); wxDataViewItem it( item ); + while( it.IsOk() ) { wxDataViewItem * pItem = new wxDataViewItem( it ); @@ -2599,7 +2877,7 @@ wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( GtkTreeIter *iter ) if (!result) { - wxPrintf( "Not found %d\n", (int) iter->user_data ); + wxLogDebug( "Not found %p", iter->user_data ); char *crash = NULL; *crash = 0; } @@ -2616,7 +2894,7 @@ wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( const wxDataViewItem &item if (!result) { - wxPrintf( "Not found %d\n", (int) item.GetID() ); + wxLogDebug( "Not found %p", item.GetID() ); char *crash = NULL; *crash = 0; } @@ -2708,8 +2986,8 @@ wxdataview_selection_changed_callback( GtkTreeSelection* selection, wxDataViewCt if (!GTK_WIDGET_REALIZED(dv->m_widget)) return; - wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_SELECTED, dv->GetId() ); - // TODO: item + wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, dv->GetId() ); + event.SetItem( dv->GetSelection() ); event.SetModel( dv->GetModel() ); dv->GetEventHandler()->ProcessEvent( event ); } @@ -2728,8 +3006,60 @@ wxdataview_row_activated_callback( GtkTreeView* treeview, GtkTreePath *path, dv->GetEventHandler()->ProcessEvent( event ); } +static gboolean +wxdataview_test_expand_row_callback( GtkTreeView* treeview, GtkTreeIter* iter, + GtkTreePath *path, wxDataViewCtrl *dv ) +{ + wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING, dv->GetId() ); + + wxDataViewItem item( (void*) iter->user_data );; + event.SetItem( item ); + event.SetModel( dv->GetModel() ); + dv->GetEventHandler()->ProcessEvent( event ); + + return !event.IsAllowed(); +} + +static void +wxdataview_row_expanded_callback( GtkTreeView* treeview, GtkTreeIter* iter, + GtkTreePath *path, wxDataViewCtrl *dv ) +{ + wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED, dv->GetId() ); + + wxDataViewItem item( (void*) iter->user_data );; + event.SetItem( item ); + event.SetModel( dv->GetModel() ); + dv->GetEventHandler()->ProcessEvent( event ); +} + +static gboolean +wxdataview_test_collapse_row_callback( GtkTreeView* treeview, GtkTreeIter* iter, + GtkTreePath *path, wxDataViewCtrl *dv ) +{ + wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING, dv->GetId() ); + + wxDataViewItem item( (void*) iter->user_data );; + event.SetItem( item ); + event.SetModel( dv->GetModel() ); + dv->GetEventHandler()->ProcessEvent( event ); + + return !event.IsAllowed(); +} + +static void +wxdataview_row_collapsed_callback( GtkTreeView* treeview, GtkTreeIter* iter, + GtkTreePath *path, wxDataViewCtrl *dv ) +{ + wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED, dv->GetId() ); + + wxDataViewItem item( (void*) iter->user_data );; + event.SetItem( item ); + event.SetModel( dv->GetModel() ); + dv->GetEventHandler()->ProcessEvent( event ); +} + //----------------------------------------------------------------------------- -// wxDataViewCtrl + // wxDataViewCtrl //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- @@ -2773,6 +3103,52 @@ void gtk_dataviewctrl_size_callback( GtkWidget *WXUNUSED(widget), } +//----------------------------------------------------------------------------- +// "motion_notify_event" +//----------------------------------------------------------------------------- + +static gboolean +gtk_dataview_motion_notify_callback( GtkWidget *widget, + GdkEventMotion *gdk_event, + wxDataViewCtrl *dv ) +{ + if (gdk_event->is_hint) + { + int x = 0; + int y = 0; + GdkModifierType state; + gdk_window_get_pointer(gdk_event->window, &x, &y, &state); + gdk_event->x = x; + gdk_event->y = y; + } + + GtkTreePath *path = NULL; + GtkTreeViewColumn *column = NULL; + gint cell_x = 0; + gint cell_y = 0; + if (gtk_tree_view_get_path_at_pos( + GTK_TREE_VIEW(dv->GtkGetTreeView()), + (int) gdk_event->x, (int) gdk_event->y, + &path, + &column, + &cell_x, + &cell_y)) + { + if (path) + { + GtkTreeIter iter; + dv->GtkGetInternal()->get_iter( &iter, path ); + + // wxPrintf( "mouse %d %d\n", (int) gdk_event->x, (int) gdk_event->y ); + + gtk_tree_path_free( path ); + } + } + + + return FALSE; +} + IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl, wxDataViewCtrlBase) @@ -2862,9 +3238,24 @@ bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id, GtkEnableSelectionEvents(); - g_signal_connect_after (m_treeview, "row_activated", + g_signal_connect_after (m_treeview, "row-activated", G_CALLBACK (wxdataview_row_activated_callback), this); + g_signal_connect (m_treeview, "test-collapse-row", + G_CALLBACK (wxdataview_test_collapse_row_callback), this); + + g_signal_connect_after (m_treeview, "row-collapsed", + G_CALLBACK (wxdataview_row_collapsed_callback), this); + + g_signal_connect (m_treeview, "test-expand-row", + G_CALLBACK (wxdataview_test_expand_row_callback), this); + + g_signal_connect_after (m_treeview, "row-expanded", + G_CALLBACK (wxdataview_row_expanded_callback), this); + + g_signal_connect (m_treeview, "motion_notify_event", + G_CALLBACK (gtk_dataview_motion_notify_callback), this); + return true; } @@ -2907,19 +3298,136 @@ bool wxDataViewCtrl::AppendColumn( wxDataViewColumn *col ) if (!wxDataViewCtrlBase::AppendColumn(col)) return false; - GtkTreeViewColumn *column = (GtkTreeViewColumn *)col->GetGtkHandle(); + m_cols.Append( col ); + + gtk_tree_view_append_column( GTK_TREE_VIEW(m_treeview), + GTK_TREE_VIEW_COLUMN(col->GetGtkHandle()) ); + + return true; +} + +bool wxDataViewCtrl::PrependColumn( wxDataViewColumn *col ) +{ + if (!wxDataViewCtrlBase::PrependColumn(col)) + return false; + + m_cols.Insert( col ); + + gtk_tree_view_insert_column( GTK_TREE_VIEW(m_treeview), + GTK_TREE_VIEW_COLUMN(col->GetGtkHandle()), 0 ); + + return true; +} + +unsigned int wxDataViewCtrl::GetColumnCount() const +{ + return m_cols.GetCount(); +} + +wxDataViewColumn* wxDataViewCtrl::GetColumn( unsigned int pos ) const +{ + GtkTreeViewColumn *gtk_col = gtk_tree_view_get_column( GTK_TREE_VIEW(m_treeview), pos ); + if (!gtk_col) + return NULL; + + wxDataViewColumnList::const_iterator iter; + for (iter = m_cols.begin(); iter != m_cols.end(); iter++) + { + wxDataViewColumn *col = *iter; + if (GTK_TREE_VIEW_COLUMN(col->GetGtkHandle()) == gtk_col) + { + return col; + } + } + + return NULL; +} + +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 ); - gtk_tree_view_append_column( GTK_TREE_VIEW(m_treeview), column ); + delete column; return true; } -wxDataViewItem wxDataViewCtrl::GetSelection() +bool wxDataViewCtrl::ClearColumns() +{ + wxDataViewColumnList::iterator 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(); + + return true; +} + +int wxDataViewCtrl::GetColumnPosition( const wxDataViewColumn *column ) const +{ + GtkTreeViewColumn *gtk_column = GTK_TREE_VIEW_COLUMN(column->GetConstGtkHandle()); + + GList *list = gtk_tree_view_get_columns( GTK_TREE_VIEW(m_treeview) ); + + gint pos = g_list_index( list, (gconstpointer) gtk_column ); + + g_list_free( list ); + + return pos; +} + +wxDataViewColumn *wxDataViewCtrl::GetSortingColumn() const +{ + return m_internal->GetDataViewSortColumn(); +} + +void wxDataViewCtrl::Expand( const wxDataViewItem & item ) +{ + GtkTreeIter iter; + iter.user_data = item.GetID(); + GtkTreePath *path = m_internal->get_path( &iter ); + gtk_tree_view_expand_row( GTK_TREE_VIEW(m_treeview), path, false ); + gtk_tree_path_free( path ); +} + +void wxDataViewCtrl::Collapse( const wxDataViewItem & item ) +{ + GtkTreeIter iter; + iter.user_data = item.GetID(); + GtkTreePath *path = m_internal->get_path( &iter ); + gtk_tree_view_collapse_row( GTK_TREE_VIEW(m_treeview), path ); + gtk_tree_path_free( path ); +} + +wxDataViewItem wxDataViewCtrl::GetSelection() const { GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); if (m_windowStyle & wxDV_MULTIPLE) { + // Report the first one + GtkTreeModel *model; + GList *list = gtk_tree_selection_get_selected_rows( selection, &model ); + + if (list) + { + GtkTreePath *path = (GtkTreePath*) list->data; + GtkTreeIter iter; + m_internal->get_iter( &iter, path ); + + // delete list + g_list_foreach( list, (GFunc) gtk_tree_path_free, NULL ); + g_list_free( list ); + + return wxDataViewItem( (void*) iter.user_data ); + } } else { @@ -2934,8 +3442,154 @@ wxDataViewItem wxDataViewCtrl::GetSelection() return wxDataViewItem(0); } +int wxDataViewCtrl::GetSelections( wxDataViewItemArray & sel ) const +{ + sel.Clear(); + + GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); + if (HasFlag(wxDV_MULTIPLE)) + { + GtkTreeModel *model; + GList *list = gtk_tree_selection_get_selected_rows( selection, &model ); + + int count = 0; + while (list) + { + GtkTreePath *path = (GtkTreePath*) list->data; + + GtkTreeIter iter; + m_internal->get_iter( &iter, path ); + + sel.Add( wxDataViewItem( (void*) iter.user_data ) ); + + list = g_list_next( list ); + count++; + } + + // delete list + g_list_foreach( list, (GFunc) gtk_tree_path_free, NULL ); + g_list_free( list ); + + return count; + } + else + { + GtkTreeModel *model; + GtkTreeIter iter; + gboolean has_selection = gtk_tree_selection_get_selected( selection, &model, &iter ); + if (has_selection) + { + sel.Add( wxDataViewItem( (void*) iter.user_data) ); + return 1; + } + } + + return 0; +} + +void wxDataViewCtrl::SetSelections( const wxDataViewItemArray & sel ) +{ + GtkDisableSelectionEvents(); + + GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); + + gtk_tree_selection_unselect_all( selection ); + + size_t i; + for (i = 0; i < sel.GetCount(); i++) + { + GtkTreeIter iter; + iter.user_data = (gpointer) sel[i].GetID(); + gtk_tree_selection_select_iter( selection, &iter ); + } + + GtkEnableSelectionEvents(); +} + +void wxDataViewCtrl::Select( const wxDataViewItem & item ) +{ + GtkDisableSelectionEvents(); + + GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); + + GtkTreeIter iter; + iter.user_data = (gpointer) item.GetID(); + gtk_tree_selection_select_iter( selection, &iter ); + + GtkEnableSelectionEvents(); +} + +void wxDataViewCtrl::Unselect( const wxDataViewItem & item ) +{ + GtkDisableSelectionEvents(); + + GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); + + GtkTreeIter iter; + iter.user_data = (gpointer) item.GetID(); + gtk_tree_selection_unselect_iter( selection, &iter ); + + GtkEnableSelectionEvents(); +} + +bool wxDataViewCtrl::IsSelected( const wxDataViewItem & item ) const +{ + GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); + + GtkTreeIter iter; + iter.user_data = (gpointer) item.GetID(); + + return gtk_tree_selection_iter_is_selected( selection, &iter ); +} + +void wxDataViewCtrl::SelectAll() +{ + GtkDisableSelectionEvents(); + + GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); + + gtk_tree_selection_select_all( selection ); + + GtkEnableSelectionEvents(); +} + +void wxDataViewCtrl::UnselectAll() +{ + GtkDisableSelectionEvents(); + + GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); + + gtk_tree_selection_unselect_all( selection ); + + GtkEnableSelectionEvents(); +} + +void wxDataViewCtrl::EnsureVisible( const wxDataViewItem & item, const wxDataViewColumn *column ) +{ + GtkTreeIter iter; + iter.user_data = (gpointer) item.GetID(); + GtkTreePath *path = m_internal->get_path( &iter ); + gtk_tree_view_scroll_to_cell( GTK_TREE_VIEW(m_treeview), path, NULL, false, 0.0, 0.0 ); + gtk_tree_path_free( path ); +} + +void wxDataViewCtrl::HitTest( const wxPoint &point, + wxDataViewItem &item, wxDataViewColumn *&column ) const +{ + item = wxDataViewItem(0); + column = NULL; +} + +wxRect wxDataViewCtrl::GetItemRect( const wxDataViewItem &item, + const wxDataViewColumn *column ) const +{ + return wxRect(); +} + void wxDataViewCtrl::DoSetExpanderColumn() { + gtk_tree_view_set_expander_column( GTK_TREE_VIEW(m_treeview), + GTK_TREE_VIEW_COLUMN( GetExpanderColumn()->GetGtkHandle() ) ); } void wxDataViewCtrl::DoSetIndent() @@ -2945,15 +3599,15 @@ void wxDataViewCtrl::DoSetIndent() void wxDataViewCtrl::GtkDisableSelectionEvents() { GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); - g_signal_connect_after (selection, "changed", - G_CALLBACK (wxdataview_selection_changed_callback), this); + g_signal_handlers_disconnect_by_func( selection, + (gpointer) (wxdataview_selection_changed_callback), this); } void wxDataViewCtrl::GtkEnableSelectionEvents() { GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); - g_signal_handlers_disconnect_by_func( selection, - (gpointer) (wxdataview_selection_changed_callback), this); + g_signal_connect_after (selection, "changed", + G_CALLBACK (wxdataview_selection_changed_callback), this); } // static