+/////////////////////////////////////////////////////////////////////////////\r
+// Name: mymodels.cpp\r
+// Purpose: wxDataViewCtrl wxWidgets sample\r
+// Author: Robert Roebling\r
+// Modified by: Francesco Montorsi, Bo Yang\r
+// Created: 06/01/06\r
+// RCS-ID: $Id$\r
+// Copyright: (c) Robert Roebling\r
+// Licence: wxWindows license\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+// For compilers that support precompilation, includes "wx/wx.h".\r
+#include "wx/wxprec.h"\r
+\r
+#ifdef __BORLANDC__\r
+#pragma hdrstop\r
+#endif\r
+\r
+#ifndef WX_PRECOMP\r
+ #include "wx/wx.h"\r
+#endif\r
+\r
+#include "wx/dataview.h"\r
+#include "mymodels.h"\r
+\r
+// ----------------------------------------------------------------------------\r
+// resources\r
+// ----------------------------------------------------------------------------\r
+\r
+#include "null.xpm"\r
+\r
+\r
+// ----------------------------------------------------------------------------\r
+// MyMusicTreeModel\r
+// ----------------------------------------------------------------------------\r
+\r
+MyMusicTreeModel::MyMusicTreeModel()\r
+{\r
+ m_root = new MyMusicTreeModelNode( NULL, wxT("My Music" ));\r
+ m_pop = new MyMusicTreeModelNode( m_root, wxT("Pop music") );\r
+ m_root->Append( m_pop );\r
+ m_pop->Append( new MyMusicTreeModelNode( m_pop,\r
+ wxT("You are not alone"), wxT("Michael Jackson"), 1995 ) );\r
+ m_pop->Append( new MyMusicTreeModelNode( m_pop,\r
+ wxT("Take a bow"), wxT("Madonna"), 1994 ) );\r
+ m_classical = new MyMusicTreeModelNode( m_root, wxT("Classical music") );\r
+ m_root->Append( m_classical );\r
+ m_ninth = new MyMusicTreeModelNode( m_classical,\r
+ wxT("Ninth symphony"), wxT("Ludwig van Beethoven"), 1824 );\r
+ m_classical->Append( m_ninth );\r
+ m_classical->Append( new MyMusicTreeModelNode( m_classical,\r
+ wxT("German Requiem"), wxT("Johannes Brahms"), 1868 ) );\r
+ m_classicalMusicIsKnownToControl = false;\r
+}\r
+\r
+wxString MyMusicTreeModel::GetTitle( const wxDataViewItem &item ) const\r
+{\r
+ MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();\r
+ if (!node)\r
+ return wxEmptyString;\r
+\r
+ return node->m_title;\r
+}\r
+\r
+int MyMusicTreeModel::GetYear( const wxDataViewItem &item ) const\r
+{\r
+ MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();\r
+ if (!node)\r
+ return 2000;\r
+\r
+ return node->m_year;\r
+}\r
+\r
+void MyMusicTreeModel::AddToClassical( const wxString &title, const wxString &artist, int year )\r
+{\r
+ // add to data\r
+ MyMusicTreeModelNode *child_node =\r
+ new MyMusicTreeModelNode( m_classical, title, artist, year );\r
+\r
+ m_classical->Append( child_node );\r
+\r
+ if (m_classicalMusicIsKnownToControl)\r
+ {\r
+ // notify control\r
+ wxDataViewItem child( (void*) child_node );\r
+ wxDataViewItem parent( (void*) m_classical );\r
+ ItemAdded( parent, child );\r
+ }\r
+}\r
+\r
+void MyMusicTreeModel::Delete( const wxDataViewItem &item )\r
+{\r
+ MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();\r
+ wxDataViewItem parent( node->GetParent() );\r
+\r
+ node->GetParent()->GetChildren().Remove( node );\r
+ delete node;\r
+\r
+ // notify control\r
+ ItemDeleted( parent, item );\r
+}\r
+\r
+int MyMusicTreeModel::Compare( const wxDataViewItem &item1, const wxDataViewItem &item2,\r
+ unsigned int column, bool ascending )\r
+{\r
+ if (IsContainer(item1) && IsContainer(item2))\r
+ {\r
+ wxVariant value1,value2;\r
+ GetValue( value1, item1, 0 );\r
+ GetValue( value2, item2, 0 );\r
+\r
+ wxString str1 = value1.GetString();\r
+ wxString str2 = value2.GetString();\r
+ int res = str1.Cmp( str2 );\r
+ if (res) return res;\r
+\r
+ // items must be different\r
+ wxUIntPtr litem1 = (wxUIntPtr) item1.GetID();\r
+ wxUIntPtr litem2 = (wxUIntPtr) item2.GetID();\r
+\r
+ return litem1-litem2;\r
+ }\r
+\r
+ return wxDataViewModel::Compare( item1, item2, column, ascending );\r
+}\r
+\r
+void MyMusicTreeModel::GetValue( wxVariant &variant,\r
+ const wxDataViewItem &item, unsigned int col ) const\r
+{\r
+ MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();\r
+ switch (col)\r
+ {\r
+ case 0: variant = node->m_title; break;\r
+ case 1: variant = node->m_artist; break;\r
+ case 2: variant = (long) node->m_year; break;\r
+ case 3: variant = node->m_quality; break;\r
+ case 4:\r
+ // wxMac doesn't conceal the popularity progress renderer, return 0 for containers\r
+ if (IsContainer(item))\r
+ variant = (long) 0;\r
+ else\r
+ variant = (long) 80; // all music is very 80% popular\r
+ break;\r
+ case 5:\r
+ // Make size of red square depend on year\r
+ if (GetYear(item) < 1900)\r
+ variant = (long) 35;\r
+ else\r
+ variant = (long) 25;\r
+ break;\r
+ default:\r
+ {\r
+ wxLogError( wxT("MyMusicTreeModel::GetValue: wrong column %d"), col );\r
+\r
+ // provoke a crash when mouse button down\r
+ wxMouseState state = wxGetMouseState();\r
+ if (state.ShiftDown())\r
+ {\r
+ char *crash = 0;\r
+ *crash = 0;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+bool MyMusicTreeModel::SetValue( const wxVariant &variant,\r
+ const wxDataViewItem &item, unsigned int col )\r
+{\r
+ MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();\r
+ switch (col)\r
+ {\r
+ case 0: node->m_title = variant.GetString(); return true;\r
+ case 1: node->m_artist = variant.GetString(); return true;\r
+ case 2: node->m_year = variant.GetLong(); return true;\r
+ case 3: node->m_quality = variant.GetString(); return true;\r
+ default: wxLogError( wxT("MyMusicTreeModel::SetValue: wrong column") );\r
+ }\r
+ return false;\r
+}\r
+\r
+wxDataViewItem MyMusicTreeModel::GetParent( const wxDataViewItem &item ) const\r
+{\r
+ // the invisble root node has no parent\r
+ if (!item.IsOk())\r
+ return wxDataViewItem(0);\r
+\r
+ MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();\r
+\r
+ // "MyMusic" also has no parent\r
+ if (node == m_root)\r
+ return wxDataViewItem(0);\r
+\r
+ return wxDataViewItem( (void*) node->GetParent() );\r
+}\r
+\r
+bool MyMusicTreeModel::IsContainer( const wxDataViewItem &item ) const\r
+{\r
+ // the invisble root node can have children (in\r
+ // our model always "MyMusic")\r
+ if (!item.IsOk())\r
+ return true;\r
+\r
+ MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();\r
+ return node->IsContainer();\r
+}\r
+\r
+unsigned int MyMusicTreeModel::GetChildren( const wxDataViewItem &parent, wxDataViewItemArray &array ) const\r
+{\r
+ MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) parent.GetID();\r
+ if (!node)\r
+ {\r
+ array.Add( wxDataViewItem( (void*) m_root ) );\r
+ return 1;\r
+ }\r
+\r
+ if (node == m_classical)\r
+ {\r
+ MyMusicTreeModel *model = (MyMusicTreeModel*)(const MyMusicTreeModel*) this;\r
+ model->m_classicalMusicIsKnownToControl = true;\r
+ }\r
+\r
+ if (node->GetChildCount() == 0)\r
+ {\r
+ return 0;\r
+ }\r
+\r
+ unsigned int count = node->GetChildren().GetCount();\r
+ unsigned int pos;\r
+ for (pos = 0; pos < count; pos++)\r
+ {\r
+ MyMusicTreeModelNode *child = node->GetChildren().Item( pos );\r
+ array.Add( wxDataViewItem( (void*) child ) );\r
+ }\r
+ return count;\r
+}\r
+\r
+\r
+\r
+// ----------------------------------------------------------------------------\r
+// MyListModel\r
+// ----------------------------------------------------------------------------\r
+\r
+static int my_sort_reverse( int *v1, int *v2 )\r
+{\r
+ return *v2-*v1;\r
+}\r
+\r
+static int my_sort( int *v1, int *v2 )\r
+{\r
+ return *v1-*v2;\r
+}\r
+\r
+MyListModel::MyListModel() :\r
+#ifdef __WXMAC__\r
+ wxDataViewVirtualListModel( 1000 + 100 )\r
+#else\r
+ wxDataViewVirtualListModel( 100000 + 100 )\r
+#endif\r
+{\r
+#ifdef __WXMAC__\r
+ m_virtualItems = 1000;\r
+#else\r
+ m_virtualItems = 100000;\r
+#endif\r
+\r
+ unsigned int i;\r
+ for (i = 0; i < 100; i++)\r
+ {\r
+ wxString str;\r
+ str.Printf( wxT("row number %d"), i );\r
+ m_array.Add( str );\r
+ }\r
+\r
+ m_icon = wxIcon( null_xpm );\r
+}\r
+\r
+void MyListModel::Prepend( const wxString &text )\r
+{\r
+ m_array.Insert( text, 0 );\r
+ RowPrepended();\r
+}\r
+\r
+void MyListModel::DeleteItem( const wxDataViewItem &item )\r
+{\r
+ unsigned int row = GetRow( item );\r
+ if (row >= m_array.GetCount())\r
+ return;\r
+\r
+ m_array.RemoveAt( row );\r
+ RowDeleted( row );\r
+}\r
+\r
+void MyListModel::DeleteItems( const wxDataViewItemArray &items )\r
+{\r
+ wxArrayInt rows;\r
+ unsigned int i;\r
+ for (i = 0; i < items.GetCount(); i++)\r
+ {\r
+ unsigned int row = GetRow( items[i] );\r
+ if (row < m_array.GetCount())\r
+ rows.Add( row );\r
+ }\r
+\r
+ // Sort in descending order so that the last\r
+ // row will be deleted first. Otherwise the\r
+ // remaining indeces would all be wrong.\r
+ rows.Sort( my_sort_reverse );\r
+ for (i = 0; i < rows.GetCount(); i++)\r
+ m_array.RemoveAt( rows[i] );\r
+\r
+ // This is just to test if wxDataViewCtrl can\r
+ // cope with removing rows not sorted in\r
+ // descending order\r
+ rows.Sort( my_sort );\r
+ RowsDeleted( rows );\r
+}\r
+\r
+void MyListModel::AddMany()\r
+{\r
+ m_virtualItems += 1000;\r
+ Reset( m_array.GetCount() + m_virtualItems );\r
+}\r
+\r
+void MyListModel::GetValueByRow( wxVariant &variant,\r
+ unsigned int row, unsigned int col ) const\r
+{\r
+ if (col==0)\r
+ {\r
+ if (row >= m_array.GetCount())\r
+ {\r
+ wxString str;\r
+ str.Printf(wxT("row %d"), row - m_array.GetCount() );\r
+ variant = str;\r
+ }\r
+ else\r
+ {\r
+ variant = m_array[ row ];\r
+ }\r
+ } else\r
+ if (col==1)\r
+ {\r
+ wxDataViewIconText data( wxT("test"), m_icon );\r
+ variant << data;\r
+ } else\r
+ if (col==2)\r
+ {\r
+ if (row >= m_array.GetCount())\r
+ variant = wxT("plain");\r
+ else\r
+ variant = wxT("blue");\r
+ }\r
+}\r
+\r
+bool MyListModel::GetAttrByRow( unsigned int row, unsigned int col, wxDataViewItemAttr &attr )\r
+{\r
+ if (col != 2)\r
+ return false;\r
+\r
+ if (row < m_array.GetCount())\r
+ {\r
+ attr.SetColour( *wxBLUE );\r
+ attr.SetItalic( true );\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+bool MyListModel::SetValueByRow( const wxVariant &variant,\r
+ unsigned int row, unsigned int col )\r
+{\r
+ if (col == 0)\r
+ {\r
+ if (row >= m_array.GetCount())\r
+ return false;\r
+\r
+ m_array[row] = variant.GetString();\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+}\r