]> git.saurik.com Git - wxWidgets.git/blame - samples/dataview/mymodels.cpp
Fix comparison operator for functions keys (fixes #10547).
[wxWidgets.git] / samples / dataview / mymodels.cpp
CommitLineData
bf19b714
FM
1/////////////////////////////////////////////////////////////////////////////\r
2// Name: mymodels.cpp\r
3// Purpose: wxDataViewCtrl wxWidgets sample\r
4// Author: Robert Roebling\r
5// Modified by: Francesco Montorsi, Bo Yang\r
6// Created: 06/01/06\r
7// RCS-ID: $Id$\r
8// Copyright: (c) Robert Roebling\r
9// Licence: wxWindows license\r
10/////////////////////////////////////////////////////////////////////////////\r
11\r
12\r
13// For compilers that support precompilation, includes "wx/wx.h".\r
14#include "wx/wxprec.h"\r
15\r
16#ifdef __BORLANDC__\r
17#pragma hdrstop\r
18#endif\r
19\r
20#ifndef WX_PRECOMP\r
21 #include "wx/wx.h"\r
22#endif\r
23\r
24#include "wx/dataview.h"\r
25#include "mymodels.h"\r
26\r
27// ----------------------------------------------------------------------------\r
28// resources\r
29// ----------------------------------------------------------------------------\r
30\r
31#include "null.xpm"\r
81c3f0fc 32#include "wx_small.xpm"\r
bf19b714
FM
33\r
34\r
35// ----------------------------------------------------------------------------\r
36// MyMusicTreeModel\r
37// ----------------------------------------------------------------------------\r
38\r
39MyMusicTreeModel::MyMusicTreeModel()\r
40{\r
41 m_root = new MyMusicTreeModelNode( NULL, wxT("My Music" ));\r
81c3f0fc
FM
42\r
43 // setup pop music\r
bf19b714 44 m_pop = new MyMusicTreeModelNode( m_root, wxT("Pop music") );\r
81c3f0fc
FM
45 m_pop->Append( \r
46 new MyMusicTreeModelNode( m_pop, wxT("You are not alone"), wxT("Michael Jackson"), 1995 ) );\r
47 m_pop->Append( \r
48 new MyMusicTreeModelNode( m_pop, wxT("Take a bow"), wxT("Madonna"), 1994 ) );\r
bf19b714 49 m_root->Append( m_pop );\r
81c3f0fc
FM
50\r
51 // setup classical music\r
bf19b714 52 m_classical = new MyMusicTreeModelNode( m_root, wxT("Classical music") );\r
81c3f0fc
FM
53 m_ninth = new MyMusicTreeModelNode( m_classical, wxT("Ninth symphony"), \r
54 wxT("Ludwig van Beethoven"), 1824 );\r
bf19b714 55 m_classical->Append( m_ninth );\r
81c3f0fc
FM
56 m_classical->Append( new MyMusicTreeModelNode( m_classical, wxT("German Requiem"), \r
57 wxT("Johannes Brahms"), 1868 ) );\r
58 m_root->Append( m_classical );\r
59\r
bf19b714
FM
60 m_classicalMusicIsKnownToControl = false;\r
61}\r
62\r
63wxString MyMusicTreeModel::GetTitle( const wxDataViewItem &item ) const\r
64{\r
65 MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();\r
81c3f0fc 66 if (!node) // happens if item.IsOk()==false\r
bf19b714
FM
67 return wxEmptyString;\r
68\r
69 return node->m_title;\r
70}\r
71\r
72int MyMusicTreeModel::GetYear( const wxDataViewItem &item ) const\r
73{\r
74 MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();\r
81c3f0fc 75 if (!node) // happens if item.IsOk()==false\r
bf19b714
FM
76 return 2000;\r
77\r
78 return node->m_year;\r
79}\r
80\r
81c3f0fc
FM
81void MyMusicTreeModel::AddToClassical( const wxString &title, const wxString &artist, \r
82 unsigned int year )\r
bf19b714 83{\r
81c3f0fc
FM
84 if (!m_classical)\r
85 {\r
86 wxASSERT(m_root);\r
87\r
88 // it was removed: restore it\r
89 m_classical = new MyMusicTreeModelNode( m_root, wxT("Classical music") );\r
90 m_root->Append( m_classical );\r
91 }\r
92\r
93 // add to the classical music node a new node:\r
bf19b714
FM
94 MyMusicTreeModelNode *child_node =\r
95 new MyMusicTreeModelNode( m_classical, title, artist, year );\r
bf19b714
FM
96 m_classical->Append( child_node );\r
97\r
98 if (m_classicalMusicIsKnownToControl)\r
99 {\r
100 // notify control\r
101 wxDataViewItem child( (void*) child_node );\r
102 wxDataViewItem parent( (void*) m_classical );\r
103 ItemAdded( parent, child );\r
104 }\r
105}\r
106\r
107void MyMusicTreeModel::Delete( const wxDataViewItem &item )\r
108{\r
109 MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();\r
81c3f0fc
FM
110 if (!node) // happens if item.IsOk()==false\r
111 return;\r
112\r
bf19b714 113 wxDataViewItem parent( node->GetParent() );\r
81c3f0fc
FM
114 if (!parent.IsOk())\r
115 {\r
116 wxASSERT(node == m_root);\r
bf19b714 117\r
81c3f0fc
FM
118 // don't make the control completely empty: \r
119 wxLogError("Cannot remove the root item!");\r
120 return;\r
121 }\r
122\r
123 // is the node one of those we keep stored in special pointers?\r
124 if (node == m_pop)\r
125 m_pop = NULL;\r
126 else if (node == m_classical)\r
127 m_classical = NULL;\r
128 else if (node == m_ninth)\r
129 m_ninth = NULL;\r
130\r
131 // first remove the node from the parent's array of children;\r
132 // NOTE: MyMusicTreeModelNodePtrArray is only an array of _pointers_\r
133 // thus removing the node from it doesn't result in freeing it\r
bf19b714 134 node->GetParent()->GetChildren().Remove( node );\r
81c3f0fc
FM
135\r
136 // free the node\r
bf19b714
FM
137 delete node;\r
138\r
139 // notify control\r
140 ItemDeleted( parent, item );\r
141}\r
142\r
143int MyMusicTreeModel::Compare( const wxDataViewItem &item1, const wxDataViewItem &item2,\r
144 unsigned int column, bool ascending )\r
145{\r
81c3f0fc
FM
146 wxASSERT(item1.IsOk() && item2.IsOk());\r
147 // should never happen\r
148\r
bf19b714
FM
149 if (IsContainer(item1) && IsContainer(item2))\r
150 {\r
81c3f0fc 151 wxVariant value1, value2;\r
bf19b714
FM
152 GetValue( value1, item1, 0 );\r
153 GetValue( value2, item2, 0 );\r
154\r
155 wxString str1 = value1.GetString();\r
156 wxString str2 = value2.GetString();\r
157 int res = str1.Cmp( str2 );\r
158 if (res) return res;\r
159\r
160 // items must be different\r
161 wxUIntPtr litem1 = (wxUIntPtr) item1.GetID();\r
162 wxUIntPtr litem2 = (wxUIntPtr) item2.GetID();\r
163\r
164 return litem1-litem2;\r
165 }\r
166\r
167 return wxDataViewModel::Compare( item1, item2, column, ascending );\r
168}\r
169\r
170void MyMusicTreeModel::GetValue( wxVariant &variant,\r
171 const wxDataViewItem &item, unsigned int col ) const\r
172{\r
81c3f0fc
FM
173 wxASSERT(item.IsOk());\r
174\r
bf19b714
FM
175 MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();\r
176 switch (col)\r
177 {\r
81c3f0fc
FM
178 case 0:\r
179 variant = node->m_title; \r
180 break;\r
181 case 1: \r
182 variant = node->m_artist; \r
183 break;\r
184 case 2: \r
185 variant = (long) node->m_year; \r
186 break;\r
187 case 3: \r
188 variant = node->m_quality; \r
189 break;\r
190 case 4:\r
191 // wxMac doesn't conceal the popularity progress renderer, return 0 for containers\r
192 if (IsContainer(item))\r
193 variant = (long) 0;\r
194 else\r
195 variant = (long) 80; // all music is very 80% popular\r
196 break;\r
197 case 5:\r
198 // Make size of red square depend on year\r
199 if (GetYear(item) < 1900)\r
200 variant = (long) 35;\r
201 else\r
202 variant = (long) 25;\r
203 break;\r
204\r
205 default:\r
206 wxLogError( wxT("MyMusicTreeModel::GetValue: wrong column %d"), col );\r
bf19b714
FM
207 }\r
208}\r
209\r
210bool MyMusicTreeModel::SetValue( const wxVariant &variant,\r
211 const wxDataViewItem &item, unsigned int col )\r
212{\r
81c3f0fc
FM
213 wxASSERT(item.IsOk());\r
214\r
bf19b714
FM
215 MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();\r
216 switch (col)\r
217 {\r
81c3f0fc
FM
218 case 0: \r
219 node->m_title = variant.GetString(); \r
220 return true;\r
221 case 1: \r
222 node->m_artist = variant.GetString(); \r
223 return true;\r
224 case 2: \r
225 node->m_year = variant.GetLong(); \r
226 return true;\r
227 case 3: \r
228 node->m_quality = variant.GetString(); \r
229 return true;\r
230\r
231 default: \r
232 wxLogError( wxT("MyMusicTreeModel::SetValue: wrong column") );\r
bf19b714
FM
233 }\r
234 return false;\r
235}\r
236\r
237wxDataViewItem MyMusicTreeModel::GetParent( const wxDataViewItem &item ) const\r
238{\r
81c3f0fc 239 // the invisible root node has no parent\r
bf19b714
FM
240 if (!item.IsOk())\r
241 return wxDataViewItem(0);\r
242\r
243 MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();\r
244\r
245 // "MyMusic" also has no parent\r
246 if (node == m_root)\r
247 return wxDataViewItem(0);\r
248\r
249 return wxDataViewItem( (void*) node->GetParent() );\r
250}\r
251\r
252bool MyMusicTreeModel::IsContainer( const wxDataViewItem &item ) const\r
253{\r
81c3f0fc
FM
254 // the invisble root node can have children\r
255 // (in our model always "MyMusic")\r
bf19b714
FM
256 if (!item.IsOk())\r
257 return true;\r
258\r
259 MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();\r
260 return node->IsContainer();\r
261}\r
262\r
81c3f0fc
FM
263unsigned int MyMusicTreeModel::GetChildren( const wxDataViewItem &parent, \r
264 wxDataViewItemArray &array ) const\r
bf19b714
FM
265{\r
266 MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) parent.GetID();\r
267 if (!node)\r
268 {\r
269 array.Add( wxDataViewItem( (void*) m_root ) );\r
270 return 1;\r
271 }\r
272\r
273 if (node == m_classical)\r
274 {\r
275 MyMusicTreeModel *model = (MyMusicTreeModel*)(const MyMusicTreeModel*) this;\r
276 model->m_classicalMusicIsKnownToControl = true;\r
277 }\r
278\r
279 if (node->GetChildCount() == 0)\r
280 {\r
281 return 0;\r
282 }\r
283\r
284 unsigned int count = node->GetChildren().GetCount();\r
81c3f0fc 285 for (unsigned int pos = 0; pos < count; pos++)\r
bf19b714
FM
286 {\r
287 MyMusicTreeModelNode *child = node->GetChildren().Item( pos );\r
288 array.Add( wxDataViewItem( (void*) child ) );\r
289 }\r
81c3f0fc 290\r
bf19b714
FM
291 return count;\r
292}\r
293\r
294\r
295\r
296// ----------------------------------------------------------------------------\r
297// MyListModel\r
298// ----------------------------------------------------------------------------\r
299\r
300static int my_sort_reverse( int *v1, int *v2 )\r
301{\r
302 return *v2-*v1;\r
303}\r
304\r
305static int my_sort( int *v1, int *v2 )\r
306{\r
307 return *v1-*v2;\r
308}\r
309\r
bf19b714 310#ifdef __WXMAC__\r
81c3f0fc 311 #define INITIAL_NUMBER_OF_ITEMS 100\r
bf19b714 312#else\r
81c3f0fc 313 #define INITIAL_NUMBER_OF_ITEMS 100000\r
bf19b714 314#endif\r
81c3f0fc
FM
315\r
316MyListModel::MyListModel() :\r
317 wxDataViewVirtualListModel( INITIAL_NUMBER_OF_ITEMS )\r
bf19b714 318{\r
81c3f0fc 319 m_virtualItems = INITIAL_NUMBER_OF_ITEMS;\r
bf19b714 320\r
81c3f0fc
FM
321 // the first 100 items are really stored in this model;\r
322 // all the others are synthetized on request \r
323 for (unsigned int i = 0; i < 100; i++)\r
bf19b714
FM
324 {\r
325 wxString str;\r
81c3f0fc 326 str.Printf( wxT("real row %d"), i );\r
bf19b714
FM
327 m_array.Add( str );\r
328 }\r
329\r
81c3f0fc
FM
330 m_icon[0] = wxIcon( null_xpm );\r
331 m_icon[1] = wxIcon( wx_small_xpm );\r
bf19b714
FM
332}\r
333\r
334void MyListModel::Prepend( const wxString &text )\r
335{\r
336 m_array.Insert( text, 0 );\r
337 RowPrepended();\r
338}\r
339\r
340void MyListModel::DeleteItem( const wxDataViewItem &item )\r
341{\r
342 unsigned int row = GetRow( item );\r
343 if (row >= m_array.GetCount())\r
344 return;\r
345\r
346 m_array.RemoveAt( row );\r
347 RowDeleted( row );\r
348}\r
349\r
350void MyListModel::DeleteItems( const wxDataViewItemArray &items )\r
351{\r
352 wxArrayInt rows;\r
81c3f0fc 353 for (unsigned int i = 0; i < items.GetCount(); i++)\r
bf19b714
FM
354 {\r
355 unsigned int row = GetRow( items[i] );\r
356 if (row < m_array.GetCount())\r
357 rows.Add( row );\r
358 }\r
359\r
81c3f0fc
FM
360 if (rows.GetCount() == 0)\r
361 {\r
362 // none of the selected items were in the range of the items\r
363 // which we store... for simplicity, don't allow removing them\r
364 wxLogError("Cannot remove rows with an index greater than %d", m_array.GetCount());\r
365 return;\r
366 }\r
367\r
bf19b714
FM
368 // Sort in descending order so that the last\r
369 // row will be deleted first. Otherwise the\r
370 // remaining indeces would all be wrong.\r
371 rows.Sort( my_sort_reverse );\r
8bf6f044 372 for (unsigned int i = 0; i < rows.GetCount(); i++)\r
bf19b714
FM
373 m_array.RemoveAt( rows[i] );\r
374\r
375 // This is just to test if wxDataViewCtrl can\r
376 // cope with removing rows not sorted in\r
377 // descending order\r
378 rows.Sort( my_sort );\r
379 RowsDeleted( rows );\r
380}\r
381\r
382void MyListModel::AddMany()\r
383{\r
384 m_virtualItems += 1000;\r
385 Reset( m_array.GetCount() + m_virtualItems );\r
386}\r
387\r
388void MyListModel::GetValueByRow( wxVariant &variant,\r
389 unsigned int row, unsigned int col ) const\r
390{\r
391 if (col==0)\r
392 {\r
393 if (row >= m_array.GetCount())\r
81c3f0fc 394 variant = wxString::Format( wxT("virtual row %d"), row );\r
bf19b714 395 else\r
bf19b714 396 variant = m_array[ row ];\r
81c3f0fc
FM
397 } \r
398 else if (col==1)\r
bf19b714 399 {\r
81c3f0fc 400 wxDataViewIconText data( wxT("test"), m_icon[ row%2 ] );\r
bf19b714 401 variant << data;\r
81c3f0fc
FM
402 } \r
403 else if (col==2)\r
bf19b714
FM
404 {\r
405 if (row >= m_array.GetCount())\r
406 variant = wxT("plain");\r
407 else\r
81c3f0fc 408 variant = wxT("blue/green/red");\r
bf19b714
FM
409 }\r
410}\r
411\r
81c3f0fc
FM
412bool MyListModel::GetAttrByRow( unsigned int row, unsigned int col, \r
413 wxDataViewItemAttr &attr )\r
bf19b714
FM
414{\r
415 if (col != 2)\r
416 return false;\r
417\r
418 if (row < m_array.GetCount())\r
419 {\r
81c3f0fc
FM
420 attr.SetColour( (row%2) == 0 ? *wxBLUE :\r
421 ((row%3) == 0 ? *wxGREEN : *wxRED) );\r
422 attr.SetItalic( (row%2) == 5 );\r
bf19b714
FM
423 }\r
424\r
425 return true;\r
426}\r
427\r
428bool MyListModel::SetValueByRow( const wxVariant &variant,\r
429 unsigned int row, unsigned int col )\r
430{\r
431 if (col == 0)\r
432 {\r
433 if (row >= m_array.GetCount())\r
81c3f0fc
FM
434 {\r
435 // the item is not in the range of the items\r
436 // which we store... for simplicity, don't allow editing it\r
437 wxLogError("Cannot edit rows with an index greater than %d", m_array.GetCount());\r
bf19b714 438 return false;\r
81c3f0fc 439 }\r
bf19b714
FM
440\r
441 m_array[row] = variant.GetString();\r
442 return true;\r
443 }\r
444\r
445 return false;\r
446}\r