From c534e69669840e016d9e109356d8839302bb95db Mon Sep 17 00:00:00 2001 From: Robert Roebling Date: Sat, 21 Jul 2007 23:07:03 +0000 Subject: [PATCH] added wxDataViewIndexListModel and sample git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@47630 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/dataview.h | 39 ++++++-- samples/dataview/dataview.cpp | 176 +++++++++++++++++++++++++++++----- src/common/datavcmn.cpp | 125 ++++++++++++++++++++++++ src/gtk/dataview.cpp | 24 +++++ 4 files changed, 332 insertions(+), 32 deletions(-) diff --git a/include/wx/dataview.h b/include/wx/dataview.h index 281141dafb..911727ca24 100644 --- a/include/wx/dataview.h +++ b/include/wx/dataview.h @@ -141,13 +141,16 @@ protected: }; // --------------------------------------------------------- -// wxDataViewVirtualListModel +// wxDataViewIndexListModel // --------------------------------------------------------- +// use hash map later +WX_DEFINE_ARRAY_PTR( void*, wxDataViewItemHash ); + class wxDataViewIndexListModel: public wxDataViewModel { public: - wxDataViewIndexListModel(); + wxDataViewIndexListModel( unsigned int initial_size = 0 ); ~wxDataViewIndexListModel(); virtual unsigned int GetRowCount() = 0; @@ -158,16 +161,36 @@ public: virtual bool SetValue( const wxVariant &variant, unsigned int row, unsigned int col ) = 0; - void ItemPrepended(); - void ItemInserted( unsigned int before ); - void ItemAppended(); - void ItemChanged( unsigned int row ); - void ValueChanged( unsigned int row, unsigned int col ); + void RowPrepended(); + void RowInserted( unsigned int before ); + void RowAppended(); + void RowDeleted( unsigned int row ); + void RowChanged( unsigned int row ); + void RowValueChanged( unsigned int row, unsigned int col ); + + // convert to/from row/wxDataViewItem - wxDataViewItem GetItem( unsigned int row ); + unsigned int GetRow( const wxDataViewItem &item ) const; + wxDataViewItem GetItem( unsigned int row ) const; + + // compare based on index virtual int Compare( const wxDataViewItem &item1, const wxDataViewItem &item2 ); + + // implement base methods + + virtual void GetValue( wxVariant &variant, + const wxDataViewItem &item, unsigned int col ) const; + virtual bool SetValue( const wxVariant &variant, + const wxDataViewItem &item, unsigned int col ); + virtual wxDataViewItem GetParent( const wxDataViewItem &item ) const; + virtual bool IsContainer( const wxDataViewItem &item ) const; + virtual wxDataViewItem GetFirstChild( const wxDataViewItem &parent ) const; + virtual wxDataViewItem GetNextSibling( const wxDataViewItem &item ) const; +private: + wxDataViewItemHash m_hash; + unsigned int m_lastIndex; }; // --------------------------------------------------------- diff --git a/samples/dataview/dataview.cpp b/samples/dataview/dataview.cpp index bd55943730..090bd0c470 100644 --- a/samples/dataview/dataview.cpp +++ b/samples/dataview/dataview.cpp @@ -305,6 +305,83 @@ private: bool m_classicalMusicIsKnownToControl; }; +class MyListModel: public wxDataViewIndexListModel +{ +public: + MyListModel() : + wxDataViewIndexListModel( 100 ) + { + unsigned int i; + for (i = 0; i < 100; i++) + { + wxString str; + str.Printf( "row number %d", i ); + m_array.Add( str ); + } + } + + // helper methods to change the model + + void Prepend( const wxString &text ) + { + m_array.Insert( text, 0 ); + RowPrepended(); + } + + void DeleteItem( const wxDataViewItem &item ) + { + unsigned int row = GetRow( item ); + m_array.RemoveAt( row ); + RowDeleted( row ); + } + + // implementation of base class virtuals to define model + + virtual unsigned int GetColumnCount() const + { + return 2; + } + + virtual wxString GetColumnType( unsigned int col ) const + { + return "string"; + } + + virtual unsigned int GetRowCount() + { + return m_array.GetCount(); + } + + virtual void GetValue( wxVariant &variant, + unsigned int row, unsigned int col ) const + { + if (col==0) + { + variant = m_array[ row ]; + } + else + { + wxString str; + str.Printf( "row %d col %d", row, col ); + variant = str; + } + } + + virtual bool SetValue( const wxVariant &variant, + unsigned int row, unsigned int col ) + { + if (col == 0) + { + m_array[row] = variant.GetString(); + return true; + } + + return false; + } + + wxArrayString m_array; +}; + // ------------------------------------- // MyApp // ------------------------------------- @@ -328,13 +405,21 @@ public: public: void OnQuit(wxCommandEvent& event); void OnAbout(wxCommandEvent& event); - void OnAdd(wxCommandEvent& event); - void OnDelete(wxCommandEvent& event); + + void OnAddMozart(wxCommandEvent& event); + void OnDeleteMusic(wxCommandEvent& event); + + void OnPrependList(wxCommandEvent& event); + void OnDeleteList(wxCommandEvent& event); private: - wxDataViewCtrl* m_dataview; + wxDataViewCtrl* m_musicCtrl; + wxObjectDataPtr m_music_model; + + wxDataViewCtrl* m_listCtrl; + wxObjectDataPtr m_list_model; + wxTextCtrl * m_log; - wxObjectDataPtr m_model; private: DECLARE_EVENT_TABLE() @@ -376,15 +461,20 @@ enum ID_ABOUT = wxID_ABOUT, ID_EXIT = wxID_EXIT, - ID_ADD = 100, - ID_DELETE = 101, + ID_ADD_MOZART = 100, + ID_DELETE_MUSIC = 101, + + ID_PREPEND_LIST = 200, + ID_DELETE_LIST = 201 }; BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU( ID_ABOUT, MyFrame::OnAbout ) EVT_MENU( ID_EXIT, MyFrame::OnQuit ) - EVT_BUTTON( ID_ADD, MyFrame::OnAdd ) - EVT_BUTTON( ID_DELETE, MyFrame::OnDelete ) + EVT_BUTTON( ID_ADD_MOZART, MyFrame::OnAddMozart ) + EVT_BUTTON( ID_DELETE_MUSIC, MyFrame::OnDeleteMusic ) + EVT_BUTTON( ID_PREPEND_LIST, MyFrame::OnPrependList ) + EVT_BUTTON( ID_DELETE_LIST, MyFrame::OnDeleteList ) END_EVENT_TABLE() MyFrame::MyFrame(wxFrame *frame, wxChar *title, int x, int y, int w, int h): @@ -407,27 +497,53 @@ MyFrame::MyFrame(wxFrame *frame, wxChar *title, int x, int y, int w, int h): wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL ); - m_dataview = new wxDataViewCtrl( this, wxID_ANY, wxDefaultPosition, - wxDefaultSize ); + wxBoxSizer *data_sizer = new wxBoxSizer( wxHORIZONTAL ); - m_model = new MyMusicModel; - m_dataview->AssociateModel( m_model.get() ); + // MyMusic - m_dataview->AppendTextColumn( "Title", 0, wxDATAVIEW_CELL_INERT, 200, + m_musicCtrl = new wxDataViewCtrl( this, wxID_ANY, wxDefaultPosition, + wxDefaultSize ); + + m_music_model = new MyMusicModel; + m_musicCtrl->AssociateModel( m_music_model.get() ); + + m_musicCtrl->AppendTextColumn( "Title", 0, wxDATAVIEW_CELL_INERT, 200, DEFAULT_ALIGN, wxDATAVIEW_COL_SORTABLE ); - m_dataview->AppendTextColumn( "Artist", 1, wxDATAVIEW_CELL_EDITABLE, 200, + m_musicCtrl->AppendTextColumn( "Artist", 1, wxDATAVIEW_CELL_EDITABLE, 200, DEFAULT_ALIGN, wxDATAVIEW_COL_SORTABLE ); - m_dataview->AppendTextColumn( "Year", 2, wxDATAVIEW_CELL_INERT, 50, + m_musicCtrl->AppendTextColumn( "Year", 2, wxDATAVIEW_CELL_INERT, 50, DEFAULT_ALIGN ); - main_sizer->Add( m_dataview, 2, wxGROW ); + data_sizer->Add( m_musicCtrl, 3, wxGROW ); + +#if 1 + + // MyList + + m_listCtrl = new wxDataViewCtrl( this, wxID_ANY, wxDefaultPosition, + wxDefaultSize ); + + m_list_model = new MyListModel; + m_listCtrl->AssociateModel( m_list_model.get() ); + + m_listCtrl->AppendTextColumn( "editable string", 0, wxDATAVIEW_CELL_EDITABLE, 120 ); + m_listCtrl->AppendTextColumn( "index", 1, wxDATAVIEW_CELL_INERT, 120 ); + + data_sizer->Add( m_listCtrl, 2, wxGROW ); + +#endif + + main_sizer->Add( data_sizer, 2, wxGROW ); wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL ); - button_sizer->Add( new wxButton( this, ID_ADD, "Add Mozart"), 0, wxALL, 10 ); - button_sizer->Add( new wxButton( this, ID_DELETE, "Delete selected"), 0, wxALL, 10 ); + button_sizer->Add( new wxButton( this, ID_ADD_MOZART, "Add Mozart"), 0, wxALL, 10 ); + button_sizer->Add( new wxButton( this, ID_DELETE_MUSIC, "Delete selected"), 0, wxALL, 10 ); + button_sizer->Add( 10, 10, 1 ); + button_sizer->Add( new wxButton( this, ID_PREPEND_LIST, "Prepend"), 0, wxALL, 10 ); + button_sizer->Add( new wxButton( this, ID_DELETE_LIST, "Delete selected"), 0, wxALL, 10 ); - main_sizer->Add( button_sizer, 0, 0, 0 ); + main_sizer->Add( button_sizer, 0, wxGROW, 0 ); m_log = new wxTextCtrl( this, -1, "", wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE ); @@ -441,16 +557,28 @@ void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) ) Close(true); } -void MyFrame::OnDelete(wxCommandEvent& WXUNUSED(event) ) +void MyFrame::OnAddMozart(wxCommandEvent& WXUNUSED(event) ) +{ + m_music_model->AddToClassical( "Kleine Nachtmusik", "Wolfgang Mozart", "1787" ); +} + +void MyFrame::OnDeleteMusic(wxCommandEvent& WXUNUSED(event) ) { - wxDataViewItem item = m_dataview->GetSelection(); + wxDataViewItem item = m_musicCtrl->GetSelection(); if (item.IsOk()) - m_model->Delete( item ); + m_music_model->Delete( item ); } -void MyFrame::OnAdd(wxCommandEvent& WXUNUSED(event) ) +void MyFrame::OnPrependList( wxCommandEvent& WXUNUSED(event) ) { - m_model->AddToClassical( "Kleine Nachtmusik", "Wolfgang Mozart", "1787" ); + m_list_model->Prepend( "Test" ); +} + +void MyFrame::OnDeleteList( wxCommandEvent& WXUNUSED(event) ) +{ + wxDataViewItem item = m_listCtrl->GetSelection(); + if (item.IsOk()) + m_list_model->DeleteItem( item ); } void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event) ) diff --git a/src/common/datavcmn.cpp b/src/common/datavcmn.cpp index 29c12266a8..11b4e3af1e 100644 --- a/src/common/datavcmn.cpp +++ b/src/common/datavcmn.cpp @@ -205,6 +205,131 @@ int wxDataViewModel::Compare( const wxDataViewItem &item1, const wxDataViewItem return litem1-litem2; } +// --------------------------------------------------------- +// wxDataViewIndexListModel +// --------------------------------------------------------- + +wxDataViewIndexListModel::wxDataViewIndexListModel( unsigned int initial_size ) +{ + // build initial index + unsigned int i; + for (i = 1; i < initial_size+1; i++) + m_hash.Add( (void*) i ); + m_lastIndex = initial_size + 1; +} + +wxDataViewIndexListModel::~wxDataViewIndexListModel() +{ +} + +void wxDataViewIndexListModel::RowPrepended() +{ + unsigned int id = m_lastIndex++; + m_hash.Insert( (void*) id, 0 ); + wxDataViewItem item( (void*) id ); + ItemAdded( wxDataViewItem(0), item ); +} + +void wxDataViewIndexListModel::RowInserted( unsigned int before ) +{ + unsigned int id = m_lastIndex++; + m_hash.Insert( (void*) id, before ); + wxDataViewItem item( (void*) id ); + ItemAdded( wxDataViewItem(0), item ); +} + +void wxDataViewIndexListModel::RowAppended() +{ + unsigned int id = m_lastIndex++; + m_hash.Add( (void*) id ); + wxDataViewItem item( (void*) id ); + ItemAdded( wxDataViewItem(0), item ); +} + +void wxDataViewIndexListModel::RowDeleted( unsigned int row ) +{ + wxDataViewItem item( m_hash[row] ); + m_hash.RemoveAt( row ); + wxDataViewModel::ItemDeleted( item ); +} + +void wxDataViewIndexListModel::RowChanged( unsigned int row ) +{ + wxDataViewModel::ItemChanged( GetItem(row) ); +} + +void wxDataViewIndexListModel::RowValueChanged( unsigned int row, unsigned int col ) +{ + wxDataViewModel::ValueChanged( GetItem(row), col ); +} + +unsigned int wxDataViewIndexListModel::GetRow( const wxDataViewItem &item ) const +{ + // assert for not found + return (unsigned int) m_hash.Index( item.GetID() ); +} + +wxDataViewItem wxDataViewIndexListModel::GetItem( unsigned int row ) const +{ + return wxDataViewItem( m_hash[row] ); +} + +int wxDataViewIndexListModel::Compare( const wxDataViewItem &item1, const wxDataViewItem &item2 ) +{ + return GetRow(item1) - GetRow(item2); +} + +void wxDataViewIndexListModel::GetValue( wxVariant &variant, + const wxDataViewItem &item, unsigned int col ) const +{ + return GetValue( variant, GetRow(item), col ); +} + +bool wxDataViewIndexListModel::SetValue( const wxVariant &variant, + const wxDataViewItem &item, unsigned int col ) +{ + return SetValue( variant, GetRow(item), col ); +} + +wxDataViewItem wxDataViewIndexListModel::GetParent( const wxDataViewItem &item ) const +{ + return wxDataViewItem(0); +} + +bool wxDataViewIndexListModel::IsContainer( const wxDataViewItem &item ) const +{ + // only the invisible root item has children + if (!item.IsOk()) + return true; + + return false; +} + +wxDataViewItem wxDataViewIndexListModel::GetFirstChild( const wxDataViewItem &parent ) const +{ + if (!parent.IsOk()) + { + if (m_hash.GetCount() == 0) + return wxDataViewItem(0); + + return wxDataViewItem( m_hash[0]); + } + + return wxDataViewItem(0); +} + +wxDataViewItem wxDataViewIndexListModel::GetNextSibling( const wxDataViewItem &item ) const +{ + if (!item.IsOk()) + return wxDataViewItem(0); + + int pos = m_hash.Index( item.GetID() ); + if ((pos == wxNOT_FOUND) || (pos == m_hash.GetCount()-1)) + return wxDataViewItem(0); + + return wxDataViewItem( m_hash[pos+1] ); +} + // --------------------------------------------------------- // wxDataViewRendererBase // --------------------------------------------------------- diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index 89a1585145..41ed1b24e8 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -118,6 +118,7 @@ public: ~wxGtkTreeModelNode() { + g_model = m_internal->GetDataViewModel(); size_t count = m_children->GetCount(); size_t i; for (i = 0; i < count; i++) @@ -130,17 +131,20 @@ public: unsigned int AddNode( wxGtkTreeModelNode* child ) { + g_model = m_internal->GetDataViewModel(); m_nodes.Add( child ); return m_children->Add( child->GetItem().GetID() ); } unsigned int AddLeave( void* id ) { + g_model = m_internal->GetDataViewModel(); return m_children->Add( id ); } void DeleteChild( void* id ) { + g_model = m_internal->GetDataViewModel(); size_t pos; size_t count = m_children->GetCount(); for (pos = 0; pos < count; pos++) @@ -2131,6 +2135,8 @@ void wxDataViewColumn::SetWidth( int width ) void wxGtkTreeModelNode::Resort() { + g_model = m_internal->GetDataViewModel(); + size_t child_count = GetChildCount(); if (child_count == 0) return; @@ -2272,6 +2278,8 @@ bool wxDataViewCtrlInternal::ItemDeleted( const wxDataViewItem &item ) gboolean wxDataViewCtrlInternal::get_iter( GtkTreeIter *iter, GtkTreePath *path ) { + g_model = m_wx_model; + int depth = gtk_tree_path_get_depth( path ); wxGtkTreeModelNode *node = m_root; @@ -2312,6 +2320,8 @@ gboolean wxDataViewCtrlInternal::get_iter( GtkTreeIter *iter, GtkTreePath *path GtkTreePath *wxDataViewCtrlInternal::get_path( GtkTreeIter *iter ) { + g_model = m_wx_model; + GtkTreePath *retval = gtk_tree_path_new (); void *id = iter->user_data; @@ -2330,6 +2340,8 @@ GtkTreePath *wxDataViewCtrlInternal::get_path( GtkTreeIter *iter ) GtkTreePath *wxDataViewCtrlInternal::get_path_safe( GtkTreeIter *iter ) { + g_model = m_wx_model; + GtkTreePath *retval = gtk_tree_path_new (); void *id = iter->user_data; @@ -2355,6 +2367,8 @@ GtkTreePath *wxDataViewCtrlInternal::get_path_safe( GtkTreeIter *iter ) gboolean wxDataViewCtrlInternal::iter_next( GtkTreeIter *iter ) { + g_model = m_wx_model; + wxGtkTreeModelNode *parent = FindParentNode( iter ); unsigned int pos = parent->GetChildren().Index( iter->user_data ); @@ -2369,6 +2383,8 @@ gboolean wxDataViewCtrlInternal::iter_next( GtkTreeIter *iter ) gboolean wxDataViewCtrlInternal::iter_children( GtkTreeIter *iter, GtkTreeIter *parent ) { + g_model = m_wx_model; + wxDataViewItem item( (void*) parent->user_data ); if (!m_wx_model->IsContainer( item )) @@ -2388,6 +2404,8 @@ gboolean wxDataViewCtrlInternal::iter_children( GtkTreeIter *iter, GtkTreeIter * gboolean wxDataViewCtrlInternal::iter_has_child( GtkTreeIter *iter ) { + g_model = m_wx_model; + wxDataViewItem item( (void*) iter->user_data ); bool is_container = m_wx_model->IsContainer( item ); @@ -2402,6 +2420,8 @@ gboolean wxDataViewCtrlInternal::iter_has_child( GtkTreeIter *iter ) gint wxDataViewCtrlInternal::iter_n_children( GtkTreeIter *iter ) { + g_model = m_wx_model; + wxDataViewItem item( (void*) iter->user_data ); if (!m_wx_model->IsContainer( item )) @@ -2417,6 +2437,8 @@ gint wxDataViewCtrlInternal::iter_n_children( GtkTreeIter *iter ) gboolean wxDataViewCtrlInternal::iter_nth_child( GtkTreeIter *iter, GtkTreeIter *parent, gint n ) { + g_model = m_wx_model; + void* id = NULL; if (parent) id = (void*) parent->user_data; wxDataViewItem item( id ); @@ -2437,6 +2459,8 @@ gboolean wxDataViewCtrlInternal::iter_nth_child( GtkTreeIter *iter, GtkTreeIter gboolean wxDataViewCtrlInternal::iter_parent( GtkTreeIter *iter, GtkTreeIter *child ) { + g_model = m_wx_model; + wxGtkTreeModelNode *node = FindParentNode( child ); if (!node) return FALSE; -- 2.45.2