]>
Commit | Line | Data |
---|---|---|
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 | |
39 | MyMusicTreeModel::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 | |
63 | wxString 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 | |
72 | int 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 |
81 | void 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 | |
107 | void 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 | |
143 | int 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 | |
170 | void 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 | |
210 | bool 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 | |
237 | wxDataViewItem 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 | |
252 | bool 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 |
263 | unsigned 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 | |
300 | static int my_sort_reverse( int *v1, int *v2 )\r | |
301 | {\r | |
302 | return *v2-*v1;\r | |
303 | }\r | |
304 | \r | |
305 | static 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 |
316 | MyListModel::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 | |
334 | void MyListModel::Prepend( const wxString &text )\r | |
335 | {\r | |
336 | m_array.Insert( text, 0 );\r | |
337 | RowPrepended();\r | |
338 | }\r | |
339 | \r | |
340 | void 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 | |
350 | void 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 | |
382 | void MyListModel::AddMany()\r | |
383 | {\r | |
384 | m_virtualItems += 1000;\r | |
385 | Reset( m_array.GetCount() + m_virtualItems );\r | |
386 | }\r | |
387 | \r | |
388 | void 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 |
412 | bool 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 | |
428 | bool 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 |