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