Moved more code from wxDataViewCtrl to wxDataViewCtrlInternal.

Add new special API for wxDataViewVirtualIndexModel::Reset() as
wxDataViewModel::Clear is something different and needs a different, two
step API under GTK+, one for destroying the current view and one for
rereading the new contents.
Added ::BeforeReset() and ::AfterReset() notifications for that purpose.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@65533 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robert Roebling 2010-09-12 20:07:28 +00:00
parent 5249673498
commit 673810eeb8
4 changed files with 136 additions and 68 deletions

View File

@ -125,6 +125,10 @@ public:
virtual bool ItemsChanged( const wxDataViewItemArray &items ); virtual bool ItemsChanged( const wxDataViewItemArray &items );
virtual bool ValueChanged( const wxDataViewItem &item, unsigned int col ) = 0; virtual bool ValueChanged( const wxDataViewItem &item, unsigned int col ) = 0;
virtual bool Cleared() = 0; virtual bool Cleared() = 0;
// this is needed for the virtual list model under GTK+
virtual bool BeforeReset( size_t WXUNUSED(old_size), size_t WXUNUSED(new_size) ) { return true; }
virtual bool AfterReset() { return Cleared(); }
virtual void Resort() = 0; virtual void Resort() = 0;
@ -245,7 +249,12 @@ public:
bool ValueChanged( const wxDataViewItem &item, unsigned int col ); bool ValueChanged( const wxDataViewItem &item, unsigned int col );
bool Cleared(); bool Cleared();
// delegatd action // this is needed for the virtual list model under GTK+
bool BeforeReset( size_t old_size, size_t new_size );
bool AfterReset();
// delegated action
virtual void Resort(); virtual void Resort();
void AddNotifier( wxDataViewModelNotifier *notifier ); void AddNotifier( wxDataViewModelNotifier *notifier );

View File

@ -195,11 +195,9 @@ private:
friend class wxDataViewCtrlDCImpl; friend class wxDataViewCtrlDCImpl;
friend class wxDataViewColumn; friend class wxDataViewColumn;
friend class wxGtkDataViewModelNotifier;
friend class wxDataViewCtrlInternal; friend class wxDataViewCtrlInternal;
GtkWidget *m_treeview; GtkWidget *m_treeview;
wxDataViewModelNotifier *m_notifier;
wxDataViewCtrlInternal *m_internal; wxDataViewCtrlInternal *m_internal;
wxDataViewColumnList m_cols; wxDataViewColumnList m_cols;

View File

@ -235,6 +235,36 @@ bool wxDataViewModel::Cleared()
return ret; return ret;
} }
bool wxDataViewModel::BeforeReset( size_t old_size, size_t new_size )
{
bool ret = true;
wxDataViewModelNotifiers::iterator iter;
for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
{
wxDataViewModelNotifier* notifier = *iter;
if (!notifier->BeforeReset(old_size,new_size))
ret = false;
}
return ret;
}
bool wxDataViewModel::AfterReset()
{
bool ret = true;
wxDataViewModelNotifiers::iterator iter;
for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
{
wxDataViewModelNotifier* notifier = *iter;
if (!notifier->AfterReset())
ret = false;
}
return ret;
}
void wxDataViewModel::Resort() void wxDataViewModel::Resort()
{ {
wxDataViewModelNotifiers::iterator iter; wxDataViewModelNotifiers::iterator iter;
@ -499,9 +529,11 @@ wxDataViewVirtualListModel::wxDataViewVirtualListModel( unsigned int initial_siz
void wxDataViewVirtualListModel::Reset( unsigned int new_size ) void wxDataViewVirtualListModel::Reset( unsigned int new_size )
{ {
m_size = new_size; /* wxDataViewModel:: */ BeforeReset( m_size, new_size );
/* wxDataViewModel:: */ Cleared(); m_size = new_size;
/* wxDataViewModel:: */ AfterReset();
} }
void wxDataViewVirtualListModel::RowPrepended() void wxDataViewVirtualListModel::RowPrepended()

View File

@ -36,6 +36,8 @@
#include "wx/gtk/private/gdkconv.h" #include "wx/gtk/private/gdkconv.h"
using namespace wxGTKImpl; using namespace wxGTKImpl;
class wxGtkDataViewModelNotifier;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -197,7 +199,7 @@ WX_DEFINE_LIST(ItemList)
class wxDataViewCtrlInternal class wxDataViewCtrlInternal
{ {
public: public:
wxDataViewCtrlInternal( wxDataViewCtrl *owner, wxDataViewModel *wx_model, GtkWxTreeModel *gtk_model ); wxDataViewCtrlInternal( wxDataViewCtrl *owner, wxDataViewModel *wx_model );
~wxDataViewCtrlInternal(); ~wxDataViewCtrlInternal();
// model iface // model iface
@ -231,6 +233,8 @@ public:
bool ItemChanged( const wxDataViewItem &item ); bool ItemChanged( const wxDataViewItem &item );
bool ValueChanged( const wxDataViewItem &item, unsigned int col ); bool ValueChanged( const wxDataViewItem &item, unsigned int col );
bool Cleared(); bool Cleared();
bool BeforeReset(size_t old_Size,size_t new_size);
bool AfterReset();
void Resort(); void Resort();
// sorting interface // sorting interface
@ -278,6 +282,8 @@ private:
GtkTargetEntry m_dropTargetTargetEntry; GtkTargetEntry m_dropTargetTargetEntry;
wxCharBuffer m_dropTargetTargetEntryTarget; wxCharBuffer m_dropTargetTargetEntryTarget;
wxDataObject *m_dropDataObject; wxDataObject *m_dropDataObject;
wxGtkDataViewModelNotifier *m_notifier;
}; };
@ -1472,9 +1478,7 @@ gtk_wx_cell_renderer_activate(
class wxGtkDataViewModelNotifier: public wxDataViewModelNotifier class wxGtkDataViewModelNotifier: public wxDataViewModelNotifier
{ {
public: public:
wxGtkDataViewModelNotifier( GtkWxTreeModel *wxgtk_model, wxGtkDataViewModelNotifier( wxDataViewModel *wx_model, wxDataViewCtrlInternal *internal );
wxDataViewModel *wx_model,
wxDataViewCtrl *ctrl );
~wxGtkDataViewModelNotifier(); ~wxGtkDataViewModelNotifier();
virtual bool ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item ); virtual bool ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item );
@ -1483,13 +1487,14 @@ public:
virtual bool ValueChanged( const wxDataViewItem &item, unsigned int col ); virtual bool ValueChanged( const wxDataViewItem &item, unsigned int col );
virtual bool Cleared(); virtual bool Cleared();
virtual void Resort(); virtual void Resort();
virtual bool BeforeReset(size_t old_size,size_t new_size);
void SetGtkModel( GtkWxTreeModel *model ) { m_wxgtk_model = model; } virtual bool AfterReset();
void UpdateLastCount();
private: private:
GtkWxTreeModel *m_wxgtk_model; wxDataViewModel *m_wx_model;
wxDataViewModel *m_wx_model; wxDataViewCtrlInternal *m_internal;
wxDataViewCtrl *m_owner;
}; };
// --------------------------------------------------------- // ---------------------------------------------------------
@ -1497,105 +1502,110 @@ private:
// --------------------------------------------------------- // ---------------------------------------------------------
wxGtkDataViewModelNotifier::wxGtkDataViewModelNotifier( wxGtkDataViewModelNotifier::wxGtkDataViewModelNotifier(
GtkWxTreeModel* wxgtk_model, wxDataViewModel *wx_model, wxDataViewModel *wx_model, wxDataViewCtrlInternal *internal )
wxDataViewCtrl *ctrl )
{ {
m_wxgtk_model = wxgtk_model;
m_wx_model = wx_model; m_wx_model = wx_model;
m_owner = ctrl; m_internal = internal;
} }
wxGtkDataViewModelNotifier::~wxGtkDataViewModelNotifier() wxGtkDataViewModelNotifier::~wxGtkDataViewModelNotifier()
{ {
m_wx_model = NULL; m_wx_model = NULL;
m_wxgtk_model = NULL; m_internal = NULL;
} }
bool wxGtkDataViewModelNotifier::ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item ) bool wxGtkDataViewModelNotifier::ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item )
{ {
m_owner->GtkGetInternal()->ItemAdded( parent, item ); m_internal->ItemAdded( parent, item );
GtkWxTreeModel *wxgtk_model = m_internal->GetGtkModel();
GtkTreeIter iter; GtkTreeIter iter;
iter.stamp = m_wxgtk_model->stamp; iter.stamp = wxgtk_model->stamp;
iter.user_data = item.GetID(); iter.user_data = item.GetID();
wxGtkTreePath path(wxgtk_tree_model_get_path( wxGtkTreePath path(wxgtk_tree_model_get_path(
GTK_TREE_MODEL(m_wxgtk_model), &iter )); GTK_TREE_MODEL(wxgtk_model), &iter ));
gtk_tree_model_row_inserted( gtk_tree_model_row_inserted(
GTK_TREE_MODEL(m_wxgtk_model), path, &iter); GTK_TREE_MODEL(wxgtk_model), path, &iter);
return true; return true;
} }
bool wxGtkDataViewModelNotifier::ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item ) bool wxGtkDataViewModelNotifier::ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item )
{ {
GtkWxTreeModel *wxgtk_model = m_internal->GetGtkModel();
#if 0 #if 0
// using _get_path for a deleted item cannot be // using _get_path for a deleted item cannot be
// a good idea // a good idea
GtkTreeIter iter; GtkTreeIter iter;
iter.stamp = m_wxgtk_model->stamp; iter.stamp = wxgtk_model->stamp;
iter.user_data = (gpointer) item.GetID(); iter.user_data = (gpointer) item.GetID();
wxGtkTreePath path(wxgtk_tree_model_get_path( wxGtkTreePath path(wxgtk_tree_model_get_path(
GTK_TREE_MODEL(m_wxgtk_model), &iter )); GTK_TREE_MODEL(wxgtk_model), &iter ));
#else #else
// so get the path from the parent // so get the path from the parent
GtkTreeIter iter; GtkTreeIter iter;
iter.stamp = m_wxgtk_model->stamp; iter.stamp = wxgtk_model->stamp;
iter.user_data = (gpointer) parent.GetID(); iter.user_data = (gpointer) parent.GetID();
wxGtkTreePath path(wxgtk_tree_model_get_path( wxGtkTreePath path(wxgtk_tree_model_get_path(
GTK_TREE_MODEL(m_wxgtk_model), &iter )); GTK_TREE_MODEL(wxgtk_model), &iter ));
// and add the final index ourselves // and add the final index ourselves
int index = m_owner->GtkGetInternal()->GetIndexOf( parent, item ); int index = m_internal->GetIndexOf( parent, item );
gtk_tree_path_append_index( path, index ); gtk_tree_path_append_index( path, index );
#endif #endif
gtk_tree_model_row_deleted( gtk_tree_model_row_deleted(
GTK_TREE_MODEL(m_wxgtk_model), path ); GTK_TREE_MODEL(wxgtk_model), path );
m_owner->GtkGetInternal()->ItemDeleted( parent, item ); m_internal->ItemDeleted( parent, item );
return true; return true;
} }
void wxGtkDataViewModelNotifier::Resort() void wxGtkDataViewModelNotifier::Resort()
{ {
m_owner->GtkGetInternal()->Resort(); m_internal->Resort();
} }
bool wxGtkDataViewModelNotifier::ItemChanged( const wxDataViewItem &item ) bool wxGtkDataViewModelNotifier::ItemChanged( const wxDataViewItem &item )
{ {
GtkWxTreeModel *wxgtk_model = m_internal->GetGtkModel();
GtkTreeIter iter; GtkTreeIter iter;
iter.stamp = m_wxgtk_model->stamp; iter.stamp = wxgtk_model->stamp;
iter.user_data = (gpointer) item.GetID(); iter.user_data = (gpointer) item.GetID();
wxGtkTreePath path(wxgtk_tree_model_get_path( wxGtkTreePath path(wxgtk_tree_model_get_path(
GTK_TREE_MODEL(m_wxgtk_model), &iter )); GTK_TREE_MODEL(wxgtk_model), &iter ));
gtk_tree_model_row_changed( gtk_tree_model_row_changed(
GTK_TREE_MODEL(m_wxgtk_model), path, &iter ); GTK_TREE_MODEL(wxgtk_model), path, &iter );
m_owner->GtkGetInternal()->ItemChanged( item ); m_internal->ItemChanged( item );
return true; return true;
} }
bool wxGtkDataViewModelNotifier::ValueChanged( const wxDataViewItem &item, unsigned int model_col ) bool wxGtkDataViewModelNotifier::ValueChanged( const wxDataViewItem &item, unsigned int model_col )
{ {
GtkWxTreeModel *wxgtk_model = m_internal->GetGtkModel();
wxDataViewCtrl *ctrl = m_internal->GetOwner();
// This adds GTK+'s missing MVC logic for ValueChanged // This adds GTK+'s missing MVC logic for ValueChanged
unsigned int index; unsigned int index;
for (index = 0; index < m_owner->GetColumnCount(); index++) for (index = 0; index < ctrl->GetColumnCount(); index++)
{ {
wxDataViewColumn *column = m_owner->GetColumn( index ); wxDataViewColumn *column = ctrl->GetColumn( index );
if (column->GetModelColumn() == model_col) if (column->GetModelColumn() == model_col)
{ {
GtkTreeView *widget = GTK_TREE_VIEW(m_owner->m_treeview); GtkTreeView *widget = GTK_TREE_VIEW(ctrl->GtkGetTreeView());
GtkTreeViewColumn *gcolumn = GTK_TREE_VIEW_COLUMN(column->GetGtkHandle()); GtkTreeViewColumn *gcolumn = GTK_TREE_VIEW_COLUMN(column->GetGtkHandle());
// Get cell area // Get cell area
GtkTreeIter iter; GtkTreeIter iter;
iter.stamp = m_wxgtk_model->stamp; iter.stamp = wxgtk_model->stamp;
iter.user_data = (gpointer) item.GetID(); iter.user_data = (gpointer) item.GetID();
wxGtkTreePath path(wxgtk_tree_model_get_path( wxGtkTreePath path(wxgtk_tree_model_get_path(
GTK_TREE_MODEL(m_wxgtk_model), &iter )); GTK_TREE_MODEL(wxgtk_model), &iter ));
GdkRectangle cell_area; GdkRectangle cell_area;
gtk_tree_view_get_cell_area( widget, path, gcolumn, &cell_area ); gtk_tree_view_get_cell_area( widget, path, gcolumn, &cell_area );
@ -1608,7 +1618,7 @@ bool wxGtkDataViewModelNotifier::ValueChanged( const wxDataViewItem &item, unsig
gtk_widget_queue_draw_area( GTK_WIDGET(widget), gtk_widget_queue_draw_area( GTK_WIDGET(widget),
cell_area.x - xdiff, ydiff + cell_area.y, cell_area.width, cell_area.height ); cell_area.x - xdiff, ydiff + cell_area.y, cell_area.width, cell_area.height );
m_owner->GtkGetInternal()->ValueChanged( item, model_col ); m_internal->ValueChanged( item, model_col );
return true; return true;
} }
@ -1617,23 +1627,45 @@ bool wxGtkDataViewModelNotifier::ValueChanged( const wxDataViewItem &item, unsig
return false; return false;
} }
bool wxGtkDataViewModelNotifier::BeforeReset(size_t WXUNUSED(old_size), size_t WXUNUSED(new_size))
{
GtkWidget *treeview = m_internal->GetOwner()->GtkGetTreeView();
gtk_tree_view_set_model( GTK_TREE_VIEW(treeview), NULL );
return true;
}
bool wxGtkDataViewModelNotifier::AfterReset()
{
GtkWxTreeModel *wxgtk_model = m_internal->GetGtkModel();
GtkWidget *treeview = m_internal->GetOwner()->GtkGetTreeView();
gtk_tree_view_set_model( GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(wxgtk_model) );
m_internal->Cleared();
return true;
}
bool wxGtkDataViewModelNotifier::Cleared() bool wxGtkDataViewModelNotifier::Cleared()
{ {
GtkWxTreeModel *wxgtk_model = m_internal->GetGtkModel();
// There is no call to tell the model that everything // There is no call to tell the model that everything
// has been deleted so call row_deleted() for every // has been deleted so call row_deleted() for every
// child of root... // child of root...
int count = m_owner->GtkGetInternal()->iter_n_children( NULL ); // number of children of root int count = m_internal->iter_n_children( NULL ); // number of children of root
GtkTreePath *path = gtk_tree_path_new_first(); // points to root GtkTreePath *path = gtk_tree_path_new_first(); // points to root
int i; int i;
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
gtk_tree_model_row_deleted( GTK_TREE_MODEL(m_wxgtk_model), path ); gtk_tree_model_row_deleted( GTK_TREE_MODEL(wxgtk_model), path );
gtk_tree_path_free( path ); gtk_tree_path_free( path );
m_owner->GtkGetInternal()->Cleared(); m_internal->Cleared();
return true; return true;
} }
@ -3344,12 +3376,12 @@ void wxGtkTreeModelNode::Resort()
// wxDataViewCtrlInternal // wxDataViewCtrlInternal
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
wxDataViewCtrlInternal::wxDataViewCtrlInternal( wxDataViewCtrl *owner, wxDataViewCtrlInternal::wxDataViewCtrlInternal( wxDataViewCtrl *owner, wxDataViewModel *wx_model )
wxDataViewModel *wx_model, GtkWxTreeModel *gtk_model )
{ {
m_owner = owner; m_owner = owner;
m_wx_model = wx_model; m_wx_model = wx_model;
m_gtk_model = gtk_model;
m_gtk_model = NULL;
m_root = NULL; m_root = NULL;
m_sort_order = GTK_SORT_ASCENDING; m_sort_order = GTK_SORT_ASCENDING;
m_sort_column = -1; m_sort_column = -1;
@ -3358,12 +3390,28 @@ wxDataViewCtrlInternal::wxDataViewCtrlInternal( wxDataViewCtrl *owner,
m_dragDataObject = NULL; m_dragDataObject = NULL;
m_dropDataObject = NULL; m_dropDataObject = NULL;
m_gtk_model = wxgtk_tree_model_new();
m_gtk_model->internal = this;
m_notifier = new wxGtkDataViewModelNotifier( wx_model, this );
wx_model->AddNotifier( m_notifier );
// g_object_unref( gtk_model ); ???
if (!m_wx_model->IsVirtualListModel()) if (!m_wx_model->IsVirtualListModel())
InitTree(); InitTree();
gtk_tree_view_set_model( GTK_TREE_VIEW(m_owner->GtkGetTreeView()), GTK_TREE_MODEL(m_gtk_model) );
} }
wxDataViewCtrlInternal::~wxDataViewCtrlInternal() wxDataViewCtrlInternal::~wxDataViewCtrlInternal()
{ {
m_wx_model->RemoveNotifier( m_notifier );
// remove the model from the GtkTreeView before it gets destroyed
gtk_tree_view_set_model( GTK_TREE_VIEW( m_owner->GtkGetTreeView() ), NULL );
g_object_unref( m_gtk_model ); g_object_unref( m_gtk_model );
delete m_dragDataObject; delete m_dragDataObject;
@ -4340,21 +4388,13 @@ IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl, wxDataViewCtrlBase)
wxDataViewCtrl::~wxDataViewCtrl() wxDataViewCtrl::~wxDataViewCtrl()
{ {
if (m_notifier)
GetModel()->RemoveNotifier( m_notifier );
m_cols.Clear(); 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 );
delete m_internal; delete m_internal;
} }
void wxDataViewCtrl::Init() void wxDataViewCtrl::Init()
{ {
m_notifier = NULL;
m_internal = NULL; m_internal = NULL;
m_cols.DeleteContents( true ); m_cols.DeleteContents( true );
@ -4492,18 +4532,7 @@ bool wxDataViewCtrl::AssociateModel( wxDataViewModel *model )
} }
#endif #endif
GtkWxTreeModel *gtk_model = wxgtk_tree_model_new(); m_internal = new wxDataViewCtrlInternal( this, model );
m_internal = new wxDataViewCtrlInternal( this, model, gtk_model );
gtk_model->internal = m_internal;
m_notifier = new wxGtkDataViewModelNotifier( gtk_model, model, this );
model->AddNotifier( m_notifier );
gtk_tree_view_set_model( GTK_TREE_VIEW(m_treeview), GTK_TREE_MODEL(gtk_model) );
// unref in wxDataViewCtrlInternal
// g_object_unref( gtk_model );
return true; return true;
} }