From: Robert Roebling <robert@roebling.de> Date: Mon, 25 Sep 2006 21:11:14 +0000 (+0000) Subject: Implement most of AppendRow(), PrependRow(), InsertRow(), X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/4627af27d499cd8aca708ca06e8fad19dd61ca26 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 --- diff --git a/include/wx/dataview.h b/include/wx/dataview.h index 195b4f87b2..5e37624e0f 100644 --- a/include/wx/dataview.h +++ b/include/wx/dataview.h @@ -24,7 +24,7 @@ #if defined(__WXGTK20__) // for testing - #define wxUSE_GENERICDATAVIEWCTRL 1 +// #define wxUSE_GENERICDATAVIEWCTRL 1 #elif defined(__WXMAC__) #define wxUSE_GENERICDATAVIEWCTRL 1 #else @@ -168,7 +168,7 @@ public: // set value, call ValueChanged() afterwards! virtual bool SetValue( wxVariant &variant, size_t col, size_t row ); - // delegated notifiers + // called from user virtual bool RowAppended(); virtual bool RowPrepended(); virtual bool RowInserted( size_t before ); @@ -178,7 +178,15 @@ public: virtual bool RowsReordered( size_t *new_order ); 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 ChildRowsReordered( size_t *new_order ); + bool ChildCleared(); virtual void Resort(); diff --git a/samples/dataview/dataview.cpp b/samples/dataview/dataview.cpp index 673fe97b93..d77dabbcc4 100644 --- a/samples/dataview/dataview.cpp +++ b/samples/dataview/dataview.cpp @@ -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; }; @@ -293,6 +317,8 @@ private: wxDataViewCtrl* dataview_left; wxDataViewCtrl* dataview_right; + MyUnsortedTextModel *m_unsorted_model; + DECLARE_EVENT_TABLE() }; @@ -412,6 +438,9 @@ void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event) ) BEGIN_EVENT_TABLE(MySortingFrame,wxFrame) 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() 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 dataview_left = new wxDataViewCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_MULTIPLE ); - MyUnsortedTextModel *model = new MyUnsortedTextModel; - dataview_left->AssociateModel( model ); + m_unsorted_model = new MyUnsortedTextModel; + dataview_left->AssociateModel( m_unsorted_model ); wxDataViewTextCell *text_cell = new wxDataViewTextCell( wxT("string"), wxDATAVIEW_CELL_EDITABLE ); wxDataViewColumn *column = new wxDataViewColumn( wxT("editable"), text_cell, 0 ); 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 dataview_right = new wxDataViewCtrl( this, wxID_ANY ); wxDataViewSortedListModel *sorted_model = - new wxDataViewSortedListModel( model ); + new wxDataViewSortedListModel( m_unsorted_model ); dataview_right->AssociateModel( sorted_model ); text_cell = new wxDataViewTextCell( wxT("string"), wxDATAVIEW_CELL_EDITABLE ); column = new wxDataViewColumn( wxT("editable"), text_cell, 0 ); @@ -504,18 +533,40 @@ void MySortingFrame::OnAbout(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)) { + 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)) { + 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)) { + m_unsorted_model->DeleteRow( 1 ); } void MySortingFrame::OnEditRowLeft(wxCommandEvent& WXUNUSED(event)) diff --git a/src/common/datavcmn.cpp b/src/common/datavcmn.cpp index 106bf563f8..1497379309 100644 --- a/src/common/datavcmn.cpp +++ b/src/common/datavcmn.cpp @@ -216,17 +216,31 @@ class wxDataViewSortedListModelNotifier: public wxDataViewListModelNotifier { public: wxDataViewSortedListModelNotifier( wxDataViewSortedListModel *model ) - { m_model = model; } - - virtual bool RowAppended() { return true; } - virtual bool RowPrepended() { return true; } - virtual bool RowInserted( size_t WXUNUSED(before) ) { return true; } - virtual bool RowDeleted( size_t WXUNUSED(row) ) { return true; } - virtual bool RowChanged( size_t WXUNUSED(row) ) { return true; } + { m_model = model; } + + virtual bool RowAppended() + { return m_model->ChildRowAppended(); } + + virtual bool RowPrepended() + { 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 ) - { return m_model->ChildValueChanged( col, row); } - virtual bool RowsReordered( size_t *WXUNUSED(new_order) ) { return true; } - virtual bool Cleared() { return true; } + { return m_model->ChildValueChanged( col, row); } + + virtual bool RowsReordered( size_t *new_order ) + { return m_model->ChildRowsReordered( new_order ); } + + virtual bool Cleared() + { return m_model->ChildCleared(); } wxDataViewSortedListModel *m_model; }; @@ -332,6 +346,152 @@ static void Dump( wxDataViewListModel *model, size_t col ) } #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 ) { size_t i; @@ -386,6 +546,19 @@ bool wxDataViewSortedListModel::ChildValueChanged( size_t col, size_t row ) 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() { 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]; 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; } @@ -422,7 +596,8 @@ bool wxDataViewSortedListModel::RowAppended() // you can only append bool ret = m_child->RowAppended(); - // report RowInsrted + // Do nothing here as the change in the + // child model will be reported back. return ret; } @@ -432,7 +607,8 @@ bool wxDataViewSortedListModel::RowPrepended() // you can only append bool ret = m_child->RowAppended(); - // report RowInsrted + // Do nothing here as the change in the + // child model will be reported back. return ret; } @@ -442,7 +618,8 @@ bool wxDataViewSortedListModel::RowInserted( size_t WXUNUSED(before) ) // you can only append bool ret = m_child->RowAppended(); - // report different RowInsrted + // Do nothing here as the change in the + // child model will be reported back. return ret; } @@ -492,8 +669,9 @@ bool wxDataViewSortedListModel::Cleared() { bool ret = m_child->Cleared(); - wxDataViewListModel::Cleared(); - + // Do nothing here as the change in the + // child model will be reported back. + return ret; } diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index 9ff06f25be..e4e0890266 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -783,12 +783,26 @@ bool wxGtkDataViewListModelNotifier::RowPrepended() 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 ) { - 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 )