Implement most of AppendRow(), PrependRow(), InsertRow(),

DeleteRow() for GTK+ version and sorted model.
  Added tests for these.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41450 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robert Roebling
2006-09-25 21:11:14 +00:00
parent 627e49c80c
commit 4627af27d4
4 changed files with 273 additions and 22 deletions

View File

@@ -24,7 +24,7 @@
#if defined(__WXGTK20__) #if defined(__WXGTK20__)
// for testing // for testing
#define wxUSE_GENERICDATAVIEWCTRL 1 // #define wxUSE_GENERICDATAVIEWCTRL 1
#elif defined(__WXMAC__) #elif defined(__WXMAC__)
#define wxUSE_GENERICDATAVIEWCTRL 1 #define wxUSE_GENERICDATAVIEWCTRL 1
#else #else
@@ -168,7 +168,7 @@ public:
// set value, call ValueChanged() afterwards! // set value, call ValueChanged() afterwards!
virtual bool SetValue( wxVariant &variant, size_t col, size_t row ); virtual bool SetValue( wxVariant &variant, size_t col, size_t row );
// delegated notifiers // called from user
virtual bool RowAppended(); virtual bool RowAppended();
virtual bool RowPrepended(); virtual bool RowPrepended();
virtual bool RowInserted( size_t before ); virtual bool RowInserted( size_t before );
@@ -178,7 +178,15 @@ public:
virtual bool RowsReordered( size_t *new_order ); virtual bool RowsReordered( size_t *new_order );
virtual bool Cleared(); virtual bool Cleared();
// called if child's notifiers are called
bool ChildRowAppended();
bool ChildRowPrepended();
bool ChildRowInserted( size_t before );
bool ChildRowDeleted( size_t row );
bool ChildRowChanged( size_t row );
bool ChildValueChanged( size_t col, size_t row ); bool ChildValueChanged( size_t col, size_t row );
bool ChildRowsReordered( size_t *new_order );
bool ChildCleared();
virtual void Resort(); virtual void Resort();

View File

@@ -218,6 +218,30 @@ public:
} }
void AppendRow( const wxString &text )
{
m_list.Add( text );
RowAppended();
}
void PrependRow( const wxString &text )
{
m_list.Insert( text, 0 );
RowPrepended();
}
void InsertRowAt1( const wxString &text )
{
m_list.Insert( text, 1 );
RowInserted( 1 );
}
void DeleteRow( size_t index )
{
m_list.RemoveAt( index );
RowDeleted( index );
}
wxArrayString m_list; wxArrayString m_list;
}; };
@@ -293,6 +317,8 @@ private:
wxDataViewCtrl* dataview_left; wxDataViewCtrl* dataview_left;
wxDataViewCtrl* dataview_right; wxDataViewCtrl* dataview_right;
MyUnsortedTextModel *m_unsorted_model;
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };
@@ -412,6 +438,9 @@ void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event) )
BEGIN_EVENT_TABLE(MySortingFrame,wxFrame) BEGIN_EVENT_TABLE(MySortingFrame,wxFrame)
EVT_BUTTON( ID_APPEND_ROW_LEFT, MySortingFrame::OnAppendRowLeft ) EVT_BUTTON( ID_APPEND_ROW_LEFT, MySortingFrame::OnAppendRowLeft )
EVT_BUTTON( ID_PREPEND_ROW_LEFT, MySortingFrame::OnPrependRowLeft )
EVT_BUTTON( ID_INSERT_ROW_LEFT, MySortingFrame::OnInsertRowLeft )
EVT_BUTTON( ID_DELETE_ROW_LEFT, MySortingFrame::OnDeleteRowLeft )
END_EVENT_TABLE() END_EVENT_TABLE()
MySortingFrame::MySortingFrame(wxFrame *frame, wxChar *title, int x, int y, int w, int h): MySortingFrame::MySortingFrame(wxFrame *frame, wxChar *title, int x, int y, int w, int h):
@@ -439,8 +468,8 @@ MySortingFrame::MySortingFrame(wxFrame *frame, wxChar *title, int x, int y, int
// Left wxDataViewCtrl // Left wxDataViewCtrl
dataview_left = new wxDataViewCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_MULTIPLE ); dataview_left = new wxDataViewCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_MULTIPLE );
MyUnsortedTextModel *model = new MyUnsortedTextModel; m_unsorted_model = new MyUnsortedTextModel;
dataview_left->AssociateModel( model ); dataview_left->AssociateModel( m_unsorted_model );
wxDataViewTextCell *text_cell = new wxDataViewTextCell( wxT("string"), wxDATAVIEW_CELL_EDITABLE ); wxDataViewTextCell *text_cell = new wxDataViewTextCell( wxT("string"), wxDATAVIEW_CELL_EDITABLE );
wxDataViewColumn *column = new wxDataViewColumn( wxT("editable"), text_cell, 0 ); wxDataViewColumn *column = new wxDataViewColumn( wxT("editable"), text_cell, 0 );
dataview_left->AppendColumn( column ); dataview_left->AppendColumn( column );
@@ -449,7 +478,7 @@ MySortingFrame::MySortingFrame(wxFrame *frame, wxChar *title, int x, int y, int
// Right wxDataViewCtrl using the sorting model // Right wxDataViewCtrl using the sorting model
dataview_right = new wxDataViewCtrl( this, wxID_ANY ); dataview_right = new wxDataViewCtrl( this, wxID_ANY );
wxDataViewSortedListModel *sorted_model = wxDataViewSortedListModel *sorted_model =
new wxDataViewSortedListModel( model ); new wxDataViewSortedListModel( m_unsorted_model );
dataview_right->AssociateModel( sorted_model ); dataview_right->AssociateModel( sorted_model );
text_cell = new wxDataViewTextCell( wxT("string"), wxDATAVIEW_CELL_EDITABLE ); text_cell = new wxDataViewTextCell( wxT("string"), wxDATAVIEW_CELL_EDITABLE );
column = new wxDataViewColumn( wxT("editable"), text_cell, 0 ); column = new wxDataViewColumn( wxT("editable"), text_cell, 0 );
@@ -504,18 +533,40 @@ void MySortingFrame::OnAbout(wxCommandEvent& WXUNUSED(event) )
void MySortingFrame::OnAppendRowLeft(wxCommandEvent& WXUNUSED(event)) void MySortingFrame::OnAppendRowLeft(wxCommandEvent& WXUNUSED(event))
{ {
wxTextEntryDialog dialog( this, wxT("Enter text to append") );
if (dialog.ShowModal() == wxID_OK)
{
wxString value = dialog.GetValue();
if (!value.empty())
m_unsorted_model->AppendRow( value );
}
} }
void MySortingFrame::OnPrependRowLeft(wxCommandEvent& WXUNUSED(event)) void MySortingFrame::OnPrependRowLeft(wxCommandEvent& WXUNUSED(event))
{ {
wxTextEntryDialog dialog( this, wxT("Enter text to prepend") );
if (dialog.ShowModal() == wxID_OK)
{
wxString value = dialog.GetValue();
if (!value.empty())
m_unsorted_model->PrependRow( value );
}
} }
void MySortingFrame::OnInsertRowLeft(wxCommandEvent& WXUNUSED(event)) void MySortingFrame::OnInsertRowLeft(wxCommandEvent& WXUNUSED(event))
{ {
wxTextEntryDialog dialog( this, wxT("Enter text to insert at #2") );
if (dialog.ShowModal() == wxID_OK)
{
wxString value = dialog.GetValue();
if (!value.empty())
m_unsorted_model->InsertRowAt1( value );
}
} }
void MySortingFrame::OnDeleteRowLeft(wxCommandEvent& WXUNUSED(event)) void MySortingFrame::OnDeleteRowLeft(wxCommandEvent& WXUNUSED(event))
{ {
m_unsorted_model->DeleteRow( 1 );
} }
void MySortingFrame::OnEditRowLeft(wxCommandEvent& WXUNUSED(event)) void MySortingFrame::OnEditRowLeft(wxCommandEvent& WXUNUSED(event))

View File

@@ -216,17 +216,31 @@ class wxDataViewSortedListModelNotifier: public wxDataViewListModelNotifier
{ {
public: public:
wxDataViewSortedListModelNotifier( wxDataViewSortedListModel *model ) wxDataViewSortedListModelNotifier( wxDataViewSortedListModel *model )
{ m_model = model; } { m_model = model; }
virtual bool RowAppended() { return true; } virtual bool RowAppended()
virtual bool RowPrepended() { return true; } { return m_model->ChildRowAppended(); }
virtual bool RowInserted( size_t WXUNUSED(before) ) { return true; }
virtual bool RowDeleted( size_t WXUNUSED(row) ) { return true; } virtual bool RowPrepended()
virtual bool RowChanged( size_t WXUNUSED(row) ) { return true; } { return m_model->ChildRowPrepended(); }
virtual bool RowInserted( size_t before )
{ return m_model->ChildRowInserted( before ); }
virtual bool RowDeleted( size_t row )
{ return m_model->ChildRowDeleted( row ); }
virtual bool RowChanged( size_t row )
{ return m_model->ChildRowChanged( row ); }
virtual bool ValueChanged( size_t col, size_t row ) virtual bool ValueChanged( size_t col, size_t row )
{ return m_model->ChildValueChanged( col, row); } { return m_model->ChildValueChanged( col, row); }
virtual bool RowsReordered( size_t *WXUNUSED(new_order) ) { return true; }
virtual bool Cleared() { return true; } virtual bool RowsReordered( size_t *new_order )
{ return m_model->ChildRowsReordered( new_order ); }
virtual bool Cleared()
{ return m_model->ChildCleared(); }
wxDataViewSortedListModel *m_model; wxDataViewSortedListModel *m_model;
}; };
@@ -332,6 +346,152 @@ static void Dump( wxDataViewListModel *model, size_t col )
} }
#endif #endif
bool wxDataViewSortedListModel::ChildRowAppended()
{
// no need to fix up array
size_t len = m_array.GetCount();
size_t pos = m_array.Add( len );
if (pos == 0)
return wxDataViewListModel::RowPrepended();
if (pos == len)
return wxDataViewListModel::RowAppended();
return wxDataViewListModel::RowInserted( pos );
}
bool wxDataViewSortedListModel::ChildRowPrepended()
{
// fix up array
size_t i;
size_t len = m_array.GetCount();
for (i = 0; i < len; i++)
{
size_t value = m_array[i];
m_array[i] = value+1;
}
size_t pos = m_array.Add( 0 );
if (pos == 0)
return wxDataViewListModel::RowPrepended();
if (pos == len)
return wxDataViewListModel::RowAppended();
return wxDataViewListModel::RowInserted( pos );
}
bool wxDataViewSortedListModel::ChildRowInserted( size_t before )
{
// fix up array
size_t i;
size_t len = m_array.GetCount();
for (i = 0; i < len; i++)
{
size_t value = m_array[i];
if (value >= before)
m_array[i] = value+1;
}
size_t pos = m_array.Add( before );
if (pos == 0)
return wxDataViewListModel::RowPrepended();
if (pos == len)
return wxDataViewListModel::RowAppended();
return wxDataViewListModel::RowInserted( pos );
}
bool wxDataViewSortedListModel::ChildRowDeleted( size_t row )
{
size_t i;
size_t len = m_array.GetCount();
int pos = -1;
for (i = 0; i < len; i++)
{
size_t value = m_array[i];
if (value == row)
{
// delete later
pos = (int) i;
}
else
{
// Fix up array
if (value > row)
m_array[i] = value-1;
}
}
if (pos == -1)
return false; // we should probably assert
// remove
m_array.RemoveAt( (size_t) pos );
return wxDataViewListModel::RowDeleted( (size_t) pos);
}
bool wxDataViewSortedListModel::ChildRowChanged( size_t row )
{
size_t i;
size_t len = m_array.GetCount();
// Remove and readd sorted. Find out at which
// position it was and where it ended.
size_t start_pos = 0,end_pos = 0;
for (i = 0; i < len; i++)
if (m_array[i] == row)
{
start_pos = i;
break;
}
m_array.RemoveAt( start_pos );
m_array.Add( row );
for (i = 0; i < len; i++)
if (m_array[i] == row)
{
end_pos = i;
break;
}
if (end_pos == start_pos)
return wxDataViewListModel::RowChanged( start_pos );
// Create an array where order[old] -> new_pos, so that
// if nothing changed order[0] -> 0 etc.
size_t *order = new size_t[ len ];
// Fill up initial values.
for (i = 0; i < len; i++)
order[i] = i;
if (start_pos < end_pos)
{
for (i = start_pos; i < end_pos; i++)
order[i] = order[i+1];
order[end_pos] = start_pos;
}
else
{
for (i = end_pos; i > start_pos; i--)
order[i] = order[i-1];
order[start_pos] = end_pos;
}
wxDataViewListModel::RowsReordered( order );
delete [] order;
return true;
}
bool wxDataViewSortedListModel::ChildValueChanged( size_t col, size_t row ) bool wxDataViewSortedListModel::ChildValueChanged( size_t col, size_t row )
{ {
size_t i; size_t i;
@@ -386,6 +546,19 @@ bool wxDataViewSortedListModel::ChildValueChanged( size_t col, size_t row )
return true; return true;
} }
bool wxDataViewSortedListModel::ChildRowsReordered( size_t *new_order )
{
// Nothing needs to be done. If the sort criteria
// of this list don't change, the order of the
// items of the child list isn't relevant.
return true;
}
bool wxDataViewSortedListModel::ChildCleared()
{
return wxDataViewListModel::Cleared();
}
size_t wxDataViewSortedListModel::GetNumberOfRows() size_t wxDataViewSortedListModel::GetNumberOfRows()
{ {
return m_array.GetCount(); return m_array.GetCount();
@@ -412,7 +585,8 @@ bool wxDataViewSortedListModel::SetValue( wxVariant &variant, size_t col, size_t
size_t child_row = m_array[row]; size_t child_row = m_array[row];
bool ret = m_child->SetValue( variant, col, child_row ); bool ret = m_child->SetValue( variant, col, child_row );
// Resort in ::ChildValueChanged() which gets reported back. // Do nothing here as the change in the
// child model will be reported back.
return ret; return ret;
} }
@@ -422,7 +596,8 @@ bool wxDataViewSortedListModel::RowAppended()
// you can only append // you can only append
bool ret = m_child->RowAppended(); bool ret = m_child->RowAppended();
// report RowInsrted // Do nothing here as the change in the
// child model will be reported back.
return ret; return ret;
} }
@@ -432,7 +607,8 @@ bool wxDataViewSortedListModel::RowPrepended()
// you can only append // you can only append
bool ret = m_child->RowAppended(); bool ret = m_child->RowAppended();
// report RowInsrted // Do nothing here as the change in the
// child model will be reported back.
return ret; return ret;
} }
@@ -442,7 +618,8 @@ bool wxDataViewSortedListModel::RowInserted( size_t WXUNUSED(before) )
// you can only append // you can only append
bool ret = m_child->RowAppended(); bool ret = m_child->RowAppended();
// report different RowInsrted // Do nothing here as the change in the
// child model will be reported back.
return ret; return ret;
} }
@@ -492,8 +669,9 @@ bool wxDataViewSortedListModel::Cleared()
{ {
bool ret = m_child->Cleared(); bool ret = m_child->Cleared();
wxDataViewListModel::Cleared(); // Do nothing here as the change in the
// child model will be reported back.
return ret; return ret;
} }

View File

@@ -783,12 +783,26 @@ bool wxGtkDataViewListModelNotifier::RowPrepended()
bool wxGtkDataViewListModelNotifier::RowInserted( size_t before ) bool wxGtkDataViewListModelNotifier::RowInserted( size_t before )
{ {
return false; GtkTreeIter iter;
iter.stamp = m_gtk_store->stamp;
iter.user_data = (gpointer) before;
GtkTreePath *path = gtk_tree_path_new ();
gtk_tree_path_append_index (path, (gint) before);
gtk_tree_model_row_inserted (GTK_TREE_MODEL (m_gtk_store), path, &iter);
gtk_tree_path_free (path);
return true;
} }
bool wxGtkDataViewListModelNotifier::RowDeleted( size_t row ) bool wxGtkDataViewListModelNotifier::RowDeleted( size_t row )
{ {
return false; GtkTreePath *path = gtk_tree_path_new ();
gtk_tree_path_append_index (path, (gint) row);
gtk_tree_model_row_deleted (GTK_TREE_MODEL (m_gtk_store), path);
gtk_tree_path_free (path);
return true;
} }
bool wxGtkDataViewListModelNotifier::RowChanged( size_t row ) bool wxGtkDataViewListModelNotifier::RowChanged( size_t row )