1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxDataViewCtrl wxWidgets sample
4 // Author: Robert Roebling
5 // Modified by: Francesco Montorsi, Bo Yang
8 // Copyright: (c) Robert Roebling
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 // For compilers that support precompilation, includes "wx/wx.h".
14 #include "wx/wxprec.h"
24 #include "wx/dataview.h"
27 // ----------------------------------------------------------------------------
29 // ----------------------------------------------------------------------------
32 #include "wx_small.xpm"
35 // ----------------------------------------------------------------------------
37 // ----------------------------------------------------------------------------
39 MyMusicTreeModel::MyMusicTreeModel()
41 m_root
= new MyMusicTreeModelNode( NULL
, wxT("My Music" ));
44 m_pop
= new MyMusicTreeModelNode( m_root
, wxT("Pop music") );
46 new MyMusicTreeModelNode( m_pop
, wxT("You are not alone"), wxT("Michael Jackson"), 1995 ) );
48 new MyMusicTreeModelNode( m_pop
, wxT("Take a bow"), wxT("Madonna"), 1994 ) );
49 m_root
->Append( m_pop
);
51 // setup classical music
52 m_classical
= new MyMusicTreeModelNode( m_root
, wxT("Classical music") );
53 m_ninth
= new MyMusicTreeModelNode( m_classical
, wxT("Ninth symphony"),
54 wxT("Ludwig van Beethoven"), 1824 );
55 m_classical
->Append( m_ninth
);
56 m_classical
->Append( new MyMusicTreeModelNode( m_classical
, wxT("German Requiem"),
57 wxT("Johannes Brahms"), 1868 ) );
58 m_root
->Append( m_classical
);
60 m_classicalMusicIsKnownToControl
= false;
63 wxString
MyMusicTreeModel::GetTitle( const wxDataViewItem
&item
) const
65 MyMusicTreeModelNode
*node
= (MyMusicTreeModelNode
*) item
.GetID();
66 if (!node
) // happens if item.IsOk()==false
72 int MyMusicTreeModel::GetYear( const wxDataViewItem
&item
) const
74 MyMusicTreeModelNode
*node
= (MyMusicTreeModelNode
*) item
.GetID();
75 if (!node
) // happens if item.IsOk()==false
81 void MyMusicTreeModel::AddToClassical( const wxString
&title
, const wxString
&artist
,
88 // it was removed: restore it
89 m_classical
= new MyMusicTreeModelNode( m_root
, wxT("Classical music") );
90 m_root
->Append( m_classical
);
93 // add to the classical music node a new node:
94 MyMusicTreeModelNode
*child_node
=
95 new MyMusicTreeModelNode( m_classical
, title
, artist
, year
);
96 m_classical
->Append( child_node
);
98 if (m_classicalMusicIsKnownToControl
)
101 wxDataViewItem
child( (void*) child_node
);
102 wxDataViewItem
parent( (void*) m_classical
);
103 ItemAdded( parent
, child
);
107 void MyMusicTreeModel::Delete( const wxDataViewItem
&item
)
109 MyMusicTreeModelNode
*node
= (MyMusicTreeModelNode
*) item
.GetID();
110 if (!node
) // happens if item.IsOk()==false
113 wxDataViewItem
parent( node
->GetParent() );
116 wxASSERT(node
== m_root
);
118 // don't make the control completely empty:
119 wxLogError("Cannot remove the root item!");
123 // is the node one of those we keep stored in special pointers?
126 else if (node
== m_classical
)
128 else if (node
== m_ninth
)
131 // first remove the node from the parent's array of children;
132 // NOTE: MyMusicTreeModelNodePtrArray is only an array of _pointers_
133 // thus removing the node from it doesn't result in freeing it
134 node
->GetParent()->GetChildren().Remove( node
);
140 ItemDeleted( parent
, item
);
143 int MyMusicTreeModel::Compare( const wxDataViewItem
&item1
, const wxDataViewItem
&item2
,
144 unsigned int column
, bool ascending
)
146 wxASSERT(item1
.IsOk() && item2
.IsOk());
147 // should never happen
149 if (IsContainer(item1
) && IsContainer(item2
))
151 wxVariant value1
, value2
;
152 GetValue( value1
, item1
, 0 );
153 GetValue( value2
, item2
, 0 );
155 wxString str1
= value1
.GetString();
156 wxString str2
= value2
.GetString();
157 int res
= str1
.Cmp( str2
);
160 // items must be different
161 wxUIntPtr litem1
= (wxUIntPtr
) item1
.GetID();
162 wxUIntPtr litem2
= (wxUIntPtr
) item2
.GetID();
164 return litem1
-litem2
;
167 return wxDataViewModel::Compare( item1
, item2
, column
, ascending
);
170 void MyMusicTreeModel::GetValue( wxVariant
&variant
,
171 const wxDataViewItem
&item
, unsigned int col
) const
173 wxASSERT(item
.IsOk());
175 MyMusicTreeModelNode
*node
= (MyMusicTreeModelNode
*) item
.GetID();
179 variant
= node
->m_title
;
182 variant
= node
->m_artist
;
185 variant
= (long) node
->m_year
;
188 variant
= node
->m_quality
;
191 // wxMac doesn't conceal the popularity progress renderer, return 0 for containers
192 if (IsContainer(item
))
195 variant
= (long) 80; // all music is very 80% popular
198 // Make size of red square depend on year
199 if (GetYear(item
) < 1900)
206 wxLogError( wxT("MyMusicTreeModel::GetValue: wrong column %d"), col
);
210 bool MyMusicTreeModel::SetValue( const wxVariant
&variant
,
211 const wxDataViewItem
&item
, unsigned int col
)
213 wxASSERT(item
.IsOk());
215 MyMusicTreeModelNode
*node
= (MyMusicTreeModelNode
*) item
.GetID();
219 node
->m_title
= variant
.GetString();
222 node
->m_artist
= variant
.GetString();
225 node
->m_year
= variant
.GetLong();
228 node
->m_quality
= variant
.GetString();
232 wxLogError( wxT("MyMusicTreeModel::SetValue: wrong column") );
237 wxDataViewItem
MyMusicTreeModel::GetParent( const wxDataViewItem
&item
) const
239 // the invisible root node has no parent
241 return wxDataViewItem(0);
243 MyMusicTreeModelNode
*node
= (MyMusicTreeModelNode
*) item
.GetID();
245 // "MyMusic" also has no parent
247 return wxDataViewItem(0);
249 return wxDataViewItem( (void*) node
->GetParent() );
252 bool MyMusicTreeModel::IsContainer( const wxDataViewItem
&item
) const
254 // the invisble root node can have children
255 // (in our model always "MyMusic")
259 MyMusicTreeModelNode
*node
= (MyMusicTreeModelNode
*) item
.GetID();
260 return node
->IsContainer();
263 unsigned int MyMusicTreeModel::GetChildren( const wxDataViewItem
&parent
,
264 wxDataViewItemArray
&array
) const
266 MyMusicTreeModelNode
*node
= (MyMusicTreeModelNode
*) parent
.GetID();
269 array
.Add( wxDataViewItem( (void*) m_root
) );
273 if (node
== m_classical
)
275 MyMusicTreeModel
*model
= (MyMusicTreeModel
*)(const MyMusicTreeModel
*) this;
276 model
->m_classicalMusicIsKnownToControl
= true;
279 if (node
->GetChildCount() == 0)
284 unsigned int count
= node
->GetChildren().GetCount();
285 for (unsigned int pos
= 0; pos
< count
; pos
++)
287 MyMusicTreeModelNode
*child
= node
->GetChildren().Item( pos
);
288 array
.Add( wxDataViewItem( (void*) child
) );
296 // ----------------------------------------------------------------------------
298 // ----------------------------------------------------------------------------
300 static int my_sort_reverse( int *v1
, int *v2
)
305 static int my_sort( int *v1
, int *v2
)
311 #define INITIAL_NUMBER_OF_ITEMS 100
313 #define INITIAL_NUMBER_OF_ITEMS 100000
316 MyListModel::MyListModel() :
317 wxDataViewVirtualListModel( INITIAL_NUMBER_OF_ITEMS
)
319 m_virtualItems
= INITIAL_NUMBER_OF_ITEMS
;
321 // the first 100 items are really stored in this model;
322 // all the others are synthetized on request
323 for (unsigned int i
= 0; i
< 100; i
++)
326 str
.Printf( wxT("real row %d"), i
);
330 m_icon
[0] = wxIcon( null_xpm
);
331 m_icon
[1] = wxIcon( wx_small_xpm
);
334 void MyListModel::Prepend( const wxString
&text
)
336 m_array
.Insert( text
, 0 );
340 void MyListModel::DeleteItem( const wxDataViewItem
&item
)
342 unsigned int row
= GetRow( item
);
343 if (row
>= m_array
.GetCount())
346 m_array
.RemoveAt( row
);
350 void MyListModel::DeleteItems( const wxDataViewItemArray
&items
)
354 for (i
= 0; i
< items
.GetCount(); i
++)
356 unsigned int row
= GetRow( items
[i
] );
357 if (row
< m_array
.GetCount())
361 if (rows
.GetCount() == 0)
363 // none of the selected items were in the range of the items
364 // which we store... for simplicity, don't allow removing them
365 wxLogError("Cannot remove rows with an index greater than %d", m_array
.GetCount());
369 // Sort in descending order so that the last
370 // row will be deleted first. Otherwise the
371 // remaining indeces would all be wrong.
372 rows
.Sort( my_sort_reverse
);
373 for (i
= 0; i
< rows
.GetCount(); i
++)
374 m_array
.RemoveAt( rows
[i
] );
376 // This is just to test if wxDataViewCtrl can
377 // cope with removing rows not sorted in
379 rows
.Sort( my_sort
);
383 void MyListModel::AddMany()
385 m_virtualItems
+= 1000;
386 Reset( m_array
.GetCount() + m_virtualItems
);
389 void MyListModel::GetValueByRow( wxVariant
&variant
,
390 unsigned int row
, unsigned int col
) const
394 if (row
>= m_array
.GetCount())
395 variant
= wxString::Format( wxT("virtual row %d"), row
);
397 variant
= m_array
[ row
];
401 wxDataViewIconText
data( wxT("test"), m_icon
[ row%2
] );
406 if (row
>= m_array
.GetCount())
407 variant
= wxT("plain");
409 variant
= wxT("blue/green/red");
413 bool MyListModel::GetAttrByRow( unsigned int row
, unsigned int col
,
414 wxDataViewItemAttr
&attr
)
419 if (row
< m_array
.GetCount())
421 attr
.SetColour( (row%2
) == 0 ? *wxBLUE
:
422 ((row%3
) == 0 ? *wxGREEN
: *wxRED
) );
423 attr
.SetItalic( (row%2
) == 5 );
429 bool MyListModel::SetValueByRow( const wxVariant
&variant
,
430 unsigned int row
, unsigned int col
)
434 if (row
>= m_array
.GetCount())
436 // the item is not in the range of the items
437 // which we store... for simplicity, don't allow editing it
438 wxLogError("Cannot edit rows with an index greater than %d", m_array
.GetCount());
442 m_array
[row
] = variant
.GetString();