]>
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 | |
32 | \r | |
33 | \r | |
34 | // ----------------------------------------------------------------------------\r | |
35 | // MyMusicTreeModel\r | |
36 | // ----------------------------------------------------------------------------\r | |
37 | \r | |
38 | MyMusicTreeModel::MyMusicTreeModel()\r | |
39 | {\r | |
40 | m_root = new MyMusicTreeModelNode( NULL, wxT("My Music" ));\r | |
41 | m_pop = new MyMusicTreeModelNode( m_root, wxT("Pop music") );\r | |
42 | m_root->Append( m_pop );\r | |
43 | m_pop->Append( new MyMusicTreeModelNode( m_pop,\r | |
44 | wxT("You are not alone"), wxT("Michael Jackson"), 1995 ) );\r | |
45 | m_pop->Append( new MyMusicTreeModelNode( m_pop,\r | |
46 | wxT("Take a bow"), wxT("Madonna"), 1994 ) );\r | |
47 | m_classical = new MyMusicTreeModelNode( m_root, wxT("Classical music") );\r | |
48 | m_root->Append( m_classical );\r | |
49 | m_ninth = new MyMusicTreeModelNode( m_classical,\r | |
50 | wxT("Ninth symphony"), wxT("Ludwig van Beethoven"), 1824 );\r | |
51 | m_classical->Append( m_ninth );\r | |
52 | m_classical->Append( new MyMusicTreeModelNode( m_classical,\r | |
53 | wxT("German Requiem"), wxT("Johannes Brahms"), 1868 ) );\r | |
54 | m_classicalMusicIsKnownToControl = false;\r | |
55 | }\r | |
56 | \r | |
57 | wxString MyMusicTreeModel::GetTitle( const wxDataViewItem &item ) const\r | |
58 | {\r | |
59 | MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();\r | |
60 | if (!node)\r | |
61 | return wxEmptyString;\r | |
62 | \r | |
63 | return node->m_title;\r | |
64 | }\r | |
65 | \r | |
66 | int MyMusicTreeModel::GetYear( const wxDataViewItem &item ) const\r | |
67 | {\r | |
68 | MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();\r | |
69 | if (!node)\r | |
70 | return 2000;\r | |
71 | \r | |
72 | return node->m_year;\r | |
73 | }\r | |
74 | \r | |
75 | void MyMusicTreeModel::AddToClassical( const wxString &title, const wxString &artist, int year )\r | |
76 | {\r | |
77 | // add to data\r | |
78 | MyMusicTreeModelNode *child_node =\r | |
79 | new MyMusicTreeModelNode( m_classical, title, artist, year );\r | |
80 | \r | |
81 | m_classical->Append( child_node );\r | |
82 | \r | |
83 | if (m_classicalMusicIsKnownToControl)\r | |
84 | {\r | |
85 | // notify control\r | |
86 | wxDataViewItem child( (void*) child_node );\r | |
87 | wxDataViewItem parent( (void*) m_classical );\r | |
88 | ItemAdded( parent, child );\r | |
89 | }\r | |
90 | }\r | |
91 | \r | |
92 | void MyMusicTreeModel::Delete( const wxDataViewItem &item )\r | |
93 | {\r | |
94 | MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();\r | |
95 | wxDataViewItem parent( node->GetParent() );\r | |
96 | \r | |
97 | node->GetParent()->GetChildren().Remove( node );\r | |
98 | delete node;\r | |
99 | \r | |
100 | // notify control\r | |
101 | ItemDeleted( parent, item );\r | |
102 | }\r | |
103 | \r | |
104 | int MyMusicTreeModel::Compare( const wxDataViewItem &item1, const wxDataViewItem &item2,\r | |
105 | unsigned int column, bool ascending )\r | |
106 | {\r | |
107 | if (IsContainer(item1) && IsContainer(item2))\r | |
108 | {\r | |
109 | wxVariant value1,value2;\r | |
110 | GetValue( value1, item1, 0 );\r | |
111 | GetValue( value2, item2, 0 );\r | |
112 | \r | |
113 | wxString str1 = value1.GetString();\r | |
114 | wxString str2 = value2.GetString();\r | |
115 | int res = str1.Cmp( str2 );\r | |
116 | if (res) return res;\r | |
117 | \r | |
118 | // items must be different\r | |
119 | wxUIntPtr litem1 = (wxUIntPtr) item1.GetID();\r | |
120 | wxUIntPtr litem2 = (wxUIntPtr) item2.GetID();\r | |
121 | \r | |
122 | return litem1-litem2;\r | |
123 | }\r | |
124 | \r | |
125 | return wxDataViewModel::Compare( item1, item2, column, ascending );\r | |
126 | }\r | |
127 | \r | |
128 | void MyMusicTreeModel::GetValue( wxVariant &variant,\r | |
129 | const wxDataViewItem &item, unsigned int col ) const\r | |
130 | {\r | |
131 | MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();\r | |
132 | switch (col)\r | |
133 | {\r | |
134 | case 0: variant = node->m_title; break;\r | |
135 | case 1: variant = node->m_artist; break;\r | |
136 | case 2: variant = (long) node->m_year; break;\r | |
137 | case 3: variant = node->m_quality; break;\r | |
138 | case 4:\r | |
139 | // wxMac doesn't conceal the popularity progress renderer, return 0 for containers\r | |
140 | if (IsContainer(item))\r | |
141 | variant = (long) 0;\r | |
142 | else\r | |
143 | variant = (long) 80; // all music is very 80% popular\r | |
144 | break;\r | |
145 | case 5:\r | |
146 | // Make size of red square depend on year\r | |
147 | if (GetYear(item) < 1900)\r | |
148 | variant = (long) 35;\r | |
149 | else\r | |
150 | variant = (long) 25;\r | |
151 | break;\r | |
152 | default:\r | |
153 | {\r | |
154 | wxLogError( wxT("MyMusicTreeModel::GetValue: wrong column %d"), col );\r | |
155 | \r | |
156 | // provoke a crash when mouse button down\r | |
157 | wxMouseState state = wxGetMouseState();\r | |
158 | if (state.ShiftDown())\r | |
159 | {\r | |
160 | char *crash = 0;\r | |
161 | *crash = 0;\r | |
162 | }\r | |
163 | }\r | |
164 | }\r | |
165 | }\r | |
166 | \r | |
167 | bool MyMusicTreeModel::SetValue( const wxVariant &variant,\r | |
168 | const wxDataViewItem &item, unsigned int col )\r | |
169 | {\r | |
170 | MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();\r | |
171 | switch (col)\r | |
172 | {\r | |
173 | case 0: node->m_title = variant.GetString(); return true;\r | |
174 | case 1: node->m_artist = variant.GetString(); return true;\r | |
175 | case 2: node->m_year = variant.GetLong(); return true;\r | |
176 | case 3: node->m_quality = variant.GetString(); return true;\r | |
177 | default: wxLogError( wxT("MyMusicTreeModel::SetValue: wrong column") );\r | |
178 | }\r | |
179 | return false;\r | |
180 | }\r | |
181 | \r | |
182 | wxDataViewItem MyMusicTreeModel::GetParent( const wxDataViewItem &item ) const\r | |
183 | {\r | |
184 | // the invisble root node has no parent\r | |
185 | if (!item.IsOk())\r | |
186 | return wxDataViewItem(0);\r | |
187 | \r | |
188 | MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();\r | |
189 | \r | |
190 | // "MyMusic" also has no parent\r | |
191 | if (node == m_root)\r | |
192 | return wxDataViewItem(0);\r | |
193 | \r | |
194 | return wxDataViewItem( (void*) node->GetParent() );\r | |
195 | }\r | |
196 | \r | |
197 | bool MyMusicTreeModel::IsContainer( const wxDataViewItem &item ) const\r | |
198 | {\r | |
199 | // the invisble root node can have children (in\r | |
200 | // our model always "MyMusic")\r | |
201 | if (!item.IsOk())\r | |
202 | return true;\r | |
203 | \r | |
204 | MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();\r | |
205 | return node->IsContainer();\r | |
206 | }\r | |
207 | \r | |
208 | unsigned int MyMusicTreeModel::GetChildren( const wxDataViewItem &parent, wxDataViewItemArray &array ) const\r | |
209 | {\r | |
210 | MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) parent.GetID();\r | |
211 | if (!node)\r | |
212 | {\r | |
213 | array.Add( wxDataViewItem( (void*) m_root ) );\r | |
214 | return 1;\r | |
215 | }\r | |
216 | \r | |
217 | if (node == m_classical)\r | |
218 | {\r | |
219 | MyMusicTreeModel *model = (MyMusicTreeModel*)(const MyMusicTreeModel*) this;\r | |
220 | model->m_classicalMusicIsKnownToControl = true;\r | |
221 | }\r | |
222 | \r | |
223 | if (node->GetChildCount() == 0)\r | |
224 | {\r | |
225 | return 0;\r | |
226 | }\r | |
227 | \r | |
228 | unsigned int count = node->GetChildren().GetCount();\r | |
229 | unsigned int pos;\r | |
230 | for (pos = 0; pos < count; pos++)\r | |
231 | {\r | |
232 | MyMusicTreeModelNode *child = node->GetChildren().Item( pos );\r | |
233 | array.Add( wxDataViewItem( (void*) child ) );\r | |
234 | }\r | |
235 | return count;\r | |
236 | }\r | |
237 | \r | |
238 | \r | |
239 | \r | |
240 | // ----------------------------------------------------------------------------\r | |
241 | // MyListModel\r | |
242 | // ----------------------------------------------------------------------------\r | |
243 | \r | |
244 | static int my_sort_reverse( int *v1, int *v2 )\r | |
245 | {\r | |
246 | return *v2-*v1;\r | |
247 | }\r | |
248 | \r | |
249 | static int my_sort( int *v1, int *v2 )\r | |
250 | {\r | |
251 | return *v1-*v2;\r | |
252 | }\r | |
253 | \r | |
254 | MyListModel::MyListModel() :\r | |
255 | #ifdef __WXMAC__\r | |
256 | wxDataViewVirtualListModel( 1000 + 100 )\r | |
257 | #else\r | |
258 | wxDataViewVirtualListModel( 100000 + 100 )\r | |
259 | #endif\r | |
260 | {\r | |
261 | #ifdef __WXMAC__\r | |
262 | m_virtualItems = 1000;\r | |
263 | #else\r | |
264 | m_virtualItems = 100000;\r | |
265 | #endif\r | |
266 | \r | |
267 | unsigned int i;\r | |
268 | for (i = 0; i < 100; i++)\r | |
269 | {\r | |
270 | wxString str;\r | |
271 | str.Printf( wxT("row number %d"), i );\r | |
272 | m_array.Add( str );\r | |
273 | }\r | |
274 | \r | |
275 | m_icon = wxIcon( null_xpm );\r | |
276 | }\r | |
277 | \r | |
278 | void MyListModel::Prepend( const wxString &text )\r | |
279 | {\r | |
280 | m_array.Insert( text, 0 );\r | |
281 | RowPrepended();\r | |
282 | }\r | |
283 | \r | |
284 | void MyListModel::DeleteItem( const wxDataViewItem &item )\r | |
285 | {\r | |
286 | unsigned int row = GetRow( item );\r | |
287 | if (row >= m_array.GetCount())\r | |
288 | return;\r | |
289 | \r | |
290 | m_array.RemoveAt( row );\r | |
291 | RowDeleted( row );\r | |
292 | }\r | |
293 | \r | |
294 | void MyListModel::DeleteItems( const wxDataViewItemArray &items )\r | |
295 | {\r | |
296 | wxArrayInt rows;\r | |
297 | unsigned int i;\r | |
298 | for (i = 0; i < items.GetCount(); i++)\r | |
299 | {\r | |
300 | unsigned int row = GetRow( items[i] );\r | |
301 | if (row < m_array.GetCount())\r | |
302 | rows.Add( row );\r | |
303 | }\r | |
304 | \r | |
305 | // Sort in descending order so that the last\r | |
306 | // row will be deleted first. Otherwise the\r | |
307 | // remaining indeces would all be wrong.\r | |
308 | rows.Sort( my_sort_reverse );\r | |
309 | for (i = 0; i < rows.GetCount(); i++)\r | |
310 | m_array.RemoveAt( rows[i] );\r | |
311 | \r | |
312 | // This is just to test if wxDataViewCtrl can\r | |
313 | // cope with removing rows not sorted in\r | |
314 | // descending order\r | |
315 | rows.Sort( my_sort );\r | |
316 | RowsDeleted( rows );\r | |
317 | }\r | |
318 | \r | |
319 | void MyListModel::AddMany()\r | |
320 | {\r | |
321 | m_virtualItems += 1000;\r | |
322 | Reset( m_array.GetCount() + m_virtualItems );\r | |
323 | }\r | |
324 | \r | |
325 | void MyListModel::GetValueByRow( wxVariant &variant,\r | |
326 | unsigned int row, unsigned int col ) const\r | |
327 | {\r | |
328 | if (col==0)\r | |
329 | {\r | |
330 | if (row >= m_array.GetCount())\r | |
331 | {\r | |
332 | wxString str;\r | |
333 | str.Printf(wxT("row %d"), row - m_array.GetCount() );\r | |
334 | variant = str;\r | |
335 | }\r | |
336 | else\r | |
337 | {\r | |
338 | variant = m_array[ row ];\r | |
339 | }\r | |
340 | } else\r | |
341 | if (col==1)\r | |
342 | {\r | |
343 | wxDataViewIconText data( wxT("test"), m_icon );\r | |
344 | variant << data;\r | |
345 | } else\r | |
346 | if (col==2)\r | |
347 | {\r | |
348 | if (row >= m_array.GetCount())\r | |
349 | variant = wxT("plain");\r | |
350 | else\r | |
351 | variant = wxT("blue");\r | |
352 | }\r | |
353 | }\r | |
354 | \r | |
355 | bool MyListModel::GetAttrByRow( unsigned int row, unsigned int col, wxDataViewItemAttr &attr )\r | |
356 | {\r | |
357 | if (col != 2)\r | |
358 | return false;\r | |
359 | \r | |
360 | if (row < m_array.GetCount())\r | |
361 | {\r | |
362 | attr.SetColour( *wxBLUE );\r | |
363 | attr.SetItalic( true );\r | |
364 | }\r | |
365 | \r | |
366 | return true;\r | |
367 | }\r | |
368 | \r | |
369 | bool MyListModel::SetValueByRow( const wxVariant &variant,\r | |
370 | unsigned int row, unsigned int col )\r | |
371 | {\r | |
372 | if (col == 0)\r | |
373 | {\r | |
374 | if (row >= m_array.GetCount())\r | |
375 | return false;\r | |
376 | \r | |
377 | m_array[row] = variant.GetString();\r | |
378 | return true;\r | |
379 | }\r | |
380 | \r | |
381 | return false;\r | |
382 | }\r |