]> git.saurik.com Git - wxWidgets.git/blob - samples/dataview/dataview.cpp
7cdd1ed6054d3a4204abce7fdb3b3cc5d0f2fa5d
[wxWidgets.git] / samples / dataview / dataview.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: dataview.cpp
3 // Purpose: wxDataViewCtrl wxWidgets sample
4 // Author: Robert Roebling
5 // Modified by: Francesco Montorsi
6 // Created: 06/01/06
7 // RCS-ID: $Id$
8 // Copyright: (c) Robert Roebling
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #ifndef WX_PRECOMP
20 #include "wx/wx.h"
21 #endif
22
23 #include "wx/datetime.h"
24 #include "wx/splitter.h"
25 #include "wx/aboutdlg.h"
26 #include "wx/choicdlg.h"
27 #include "wx/numdlg.h"
28 #include "wx/dataview.h"
29 #include "wx/spinctrl.h"
30
31 #ifndef __WXMSW__
32 #include "../sample.xpm"
33 #endif
34
35 #include "null.xpm"
36
37
38 #define DEFAULT_ALIGN wxALIGN_LEFT
39 #define DATAVIEW_DEFAULT_STYLE (wxDV_MULTIPLE|wxDV_HORIZ_RULES|wxDV_VERT_RULES)
40
41
42
43 // -------------------------------------
44 // MyMusicModel
45 // -------------------------------------
46
47 /*
48 Implement this data model
49 Title Artist Year
50 -------------------------------------------------------------
51 1: My Music:
52 2: Pop music
53 3: You are not alone Michael Jackson 1995
54 4: Take a bow Madonna 1994
55 5: Classical music
56 6: Ninth Symphony Ludwig v. Beethoven 1824
57 7: German Requiem Johannes Brahms 1868
58 */
59
60
61
62 class MyMusicModelNode;
63 WX_DEFINE_ARRAY_PTR( MyMusicModelNode*, MyMusicModelNodes );
64
65 class MyMusicModelNode
66 {
67 public:
68 MyMusicModelNode( MyMusicModelNode* parent, const wxUint32 id,
69 const wxString &title, const wxString &artist, const wxString &year )
70 {
71 m_parent = parent;
72 m_id = id;
73 m_title = title;
74 m_artist = artist;
75 m_year = year;
76 m_isContainer = false;
77 }
78
79 MyMusicModelNode( MyMusicModelNode* parent, const wxUint32 id,
80 const wxString &branch )
81 {
82 m_parent = parent;
83 m_id = id;
84 m_title = branch;
85 m_isContainer = true;
86 }
87
88 ~MyMusicModelNode()
89 {
90 size_t count = m_children.GetCount();
91 size_t i;
92 for (i = 0; i < count; i++)
93 {
94 MyMusicModelNode *child = m_children[i];
95 delete child;
96 }
97 }
98
99 wxUint32 GetID() { return m_id; }
100 bool IsContainer() { return m_isContainer; }
101
102 MyMusicModelNode* GetParent() { return m_parent; }
103 MyMusicModelNodes &GetChildren() { return m_children; }
104 MyMusicModelNode* GetNthChild( unsigned int n ) { return m_children.Item( n ); }
105 void Insert( MyMusicModelNode* child, unsigned int n) { m_children.Insert( child, n); }
106 void Append( MyMusicModelNode* child ) { m_children.Add( child ); }
107 unsigned int GetChildCount() { return m_children.GetCount(); }
108
109 public:
110 wxString m_title;
111 wxString m_artist;
112 wxString m_year;
113
114 private:
115 MyMusicModelNode *m_parent;
116 MyMusicModelNodes m_children;
117 wxUint32 m_id;
118 bool m_isContainer;
119 };
120
121
122 class MyMusicModel: public wxDataViewModel
123 {
124 public:
125
126 // constructor
127
128 MyMusicModel()
129 {
130 m_idCounter = 0;
131 m_root = new MyMusicModelNode( NULL, GetNewId(), "My Music" );
132 m_pop = new MyMusicModelNode( m_root, GetNewId(), "Pop music" );
133 m_root->Append( m_pop );
134 m_pop->Append( new MyMusicModelNode( m_pop, GetNewId(),
135 "You are not alone", "Michael Jackson", "1995" ) );
136 m_pop->Append( new MyMusicModelNode( m_pop, GetNewId(),
137 "Take a bow", "Madonna", "1994" ) );
138 m_classical = new MyMusicModelNode( m_root, GetNewId(), "Classical music" );
139 m_root->Append( m_classical );
140 m_classical->Append( new MyMusicModelNode( m_classical, GetNewId(),
141 "Ninth symphony", "Ludwig van Beethoven", "1824" ) );
142 m_classical->Append( new MyMusicModelNode( m_classical, GetNewId(),
143 "German Requiem", "Johannes Brahms", "1868" ) );
144 m_classicalMusicIsKnownToControl = false;
145 }
146
147 // helper methods to change the model
148
149 void AddToClassical( const wxString &title, const wxString &artist, const wxString &year )
150 {
151 // add to data
152 MyMusicModelNode *child_node =
153 new MyMusicModelNode( m_classical, GetNewId(), title, artist, year );
154 m_classical->Append( child_node );
155
156 if (m_classicalMusicIsKnownToControl)
157 {
158 // notify control
159 wxDataViewItem child( child_node->GetID() );
160 wxDataViewItem parent( m_classical->GetID() );
161 ItemAdded( parent, child );
162 }
163 }
164
165 void Delete( const wxDataViewItem &item )
166 {
167 MyMusicModelNode *node = FindNode( item );
168 node->GetParent()->GetChildren().Remove( node );
169 delete node;
170
171 // notify control
172 ItemDeleted( item );
173 }
174
175 // implementation of base class virtuals to define model
176
177 virtual unsigned int GetColumnCount() const
178 {
179 return 3;
180 }
181
182 virtual wxString GetColumnType( unsigned int col ) const
183 {
184 return "string";
185 }
186
187 virtual void GetValue( wxVariant &variant,
188 const wxDataViewItem &item, unsigned int col ) const
189 {
190 MyMusicModelNode *node = FindNode( item );
191 switch (col)
192 {
193 case 0: variant = node->m_title; break;
194 case 1: variant = node->m_artist; break;
195 case 2: variant = node->m_year; break;
196 default: wxLogError( "MyMusicModel::GetValue: wrong column" );
197 }
198 }
199
200 virtual bool SetValue( const wxVariant &variant,
201 const wxDataViewItem &item, unsigned int col )
202 {
203 MyMusicModelNode *node = FindNode( item );
204 switch (col)
205 {
206 case 0: node->m_title = variant.GetString(); break;
207 case 1: node->m_artist = variant.GetString(); break;
208 case 2: node->m_year = variant.GetString(); break;
209 default: wxLogError( "MyMusicModel::SetValue: wrong column" );
210 }
211 }
212
213 virtual bool HasChildren( const wxDataViewItem &item ) const
214 {
215 if (item.GetID() == 0)
216 return true;
217
218 MyMusicModelNode *node = FindNode( item );
219 return node->IsContainer();
220 }
221
222 virtual wxDataViewItem GetFirstChild( const wxDataViewItem &parent ) const
223 {
224 if (parent.GetID() == 0)
225 return wxDataViewItem( m_root->GetID() );
226
227 MyMusicModelNode *node = FindNode( parent );
228
229 if (node->GetChildCount() == 0)
230 return wxDataViewItem( 0 );
231
232 if (node == m_classical)
233 {
234 MyMusicModel *model = (MyMusicModel*)(const MyMusicModel*) this;
235 model->m_classicalMusicIsKnownToControl = true;
236 }
237
238 MyMusicModelNode *first_child = node->GetChildren().Item( 0 );
239 return wxDataViewItem( first_child->GetID() );
240 }
241
242 virtual wxDataViewItem GetNextSibling( const wxDataViewItem &item ) const
243 {
244 MyMusicModelNode *node = FindNode( item );
245 MyMusicModelNode *parent = node->GetParent();
246 if (!parent)
247 return wxDataViewItem(0);
248
249 int pos = parent->GetChildren().Index( node );
250 if (pos == wxNOT_FOUND)
251 return wxDataViewItem(0);
252
253 if (pos == parent->GetChildCount()-1)
254 return wxDataViewItem(0);
255
256 node = parent->GetChildren().Item( pos+1 );
257 return wxDataViewItem( node->GetID() );
258 }
259
260 private:
261 wxUint32 GetNewId() { m_idCounter++; return m_idCounter; }
262
263 MyMusicModelNode *FindNodeRec( MyMusicModelNode *node, const wxDataViewItem &item ) const
264 {
265 if (node->GetID() == item.GetID())
266 return node;
267
268 size_t count = node->GetChildCount();
269 size_t i;
270 for (i = 0; i < count; i++)
271 {
272 MyMusicModelNode *child = node->GetChildren().Item( i );
273 MyMusicModelNode *node2 = FindNodeRec( child, item );
274 if (node2)
275 return node2;
276 }
277 return NULL;
278 }
279
280 MyMusicModelNode *FindNode( const wxDataViewItem &item ) const
281 {
282 if (item.GetID() == 0)
283 return NULL;
284
285 if (!m_root)
286 return NULL;
287
288 return FindNodeRec( m_root, item );
289 }
290
291 MyMusicModelNode* m_root;
292 MyMusicModelNode* m_pop;
293 MyMusicModelNode* m_classical;
294 bool m_classicalMusicIsKnownToControl;
295 wxUint32 m_idCounter;
296 };
297
298 // -------------------------------------
299 // MyApp
300 // -------------------------------------
301
302 class MyApp: public wxApp
303 {
304 public:
305 bool OnInit(void);
306 int OnExit();
307 };
308
309 // -------------------------------------
310 // MyFrame
311 // -------------------------------------
312
313 class MyFrame : public wxFrame
314 {
315 public:
316 MyFrame(wxFrame *frame, wxChar *title, int x, int y, int w, int h);
317
318 public:
319 void OnQuit(wxCommandEvent& event);
320 void OnAbout(wxCommandEvent& event);
321 void OnAdd(wxCommandEvent& event);
322 void OnDelete(wxCommandEvent& event);
323
324 private:
325 wxDataViewCtrl* m_dataview;
326 wxTextCtrl * m_log;
327 wxObjectDataPtr<MyMusicModel> m_model;
328
329 private:
330 DECLARE_EVENT_TABLE()
331 };
332
333 // -------------------------------------
334 // MyApp
335 // -------------------------------------
336
337 IMPLEMENT_APP(MyApp)
338
339 bool MyApp::OnInit(void)
340 {
341 if ( !wxApp::OnInit() )
342 return false;
343
344 // build the first frame
345 MyFrame *frame =
346 new MyFrame(NULL, wxT("wxDataViewCtrl feature test"), 10, 10, 700, 440);
347 frame->Show(true);
348
349 SetTopWindow(frame);
350 return true;
351 }
352
353 int MyApp::OnExit()
354 {
355 return 0;
356 }
357
358
359 // -------------------------------------
360 // MyFrame
361 // -------------------------------------
362
363 enum
364 {
365 // file menu
366 ID_ABOUT = wxID_ABOUT,
367 ID_EXIT = wxID_EXIT,
368
369 ID_ADD = 100,
370 ID_DELETE = 101,
371 };
372
373 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
374 EVT_MENU( ID_ABOUT, MyFrame::OnAbout )
375 EVT_MENU( ID_EXIT, MyFrame::OnQuit )
376 EVT_BUTTON( ID_ADD, MyFrame::OnAdd )
377 EVT_BUTTON( ID_DELETE, MyFrame::OnDelete )
378 END_EVENT_TABLE()
379
380 MyFrame::MyFrame(wxFrame *frame, wxChar *title, int x, int y, int w, int h):
381 wxFrame(frame, wxID_ANY, title, wxPoint(x, y), wxSize(w, h))
382 {
383 SetIcon(wxICON(sample));
384
385 // build the menus:
386
387 wxMenu *file_menu = new wxMenu;
388 file_menu->Append(ID_ABOUT, "&About");
389 file_menu->AppendSeparator();
390 file_menu->Append(ID_EXIT, "E&xit");
391
392 wxMenuBar *menu_bar = new wxMenuBar;
393 menu_bar->Append(file_menu, "&File");
394
395 SetMenuBar(menu_bar);
396 CreateStatusBar();
397
398 wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
399
400 m_dataview = new wxDataViewCtrl( this, wxID_ANY, wxDefaultPosition,
401 wxDefaultSize );
402
403 m_model = new MyMusicModel;
404 m_dataview->AssociateModel( m_model.get() );
405
406 m_dataview->AppendTextColumn( "Title", 0, wxDATAVIEW_CELL_INERT, 200,
407 DEFAULT_ALIGN, wxDATAVIEW_COL_SORTABLE );
408 m_dataview->AppendTextColumn( "Artist", 1, wxDATAVIEW_CELL_INERT, 200,
409 DEFAULT_ALIGN, wxDATAVIEW_COL_SORTABLE );
410 m_dataview->AppendTextColumn( "Year", 2, wxDATAVIEW_CELL_INERT, 50,
411 DEFAULT_ALIGN );
412
413 main_sizer->Add( m_dataview, 2, wxGROW );
414
415 wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
416
417 button_sizer->Add( new wxButton( this, ID_ADD, "Add Mozart"), 0, wxALL, 10 );
418 button_sizer->Add( new wxButton( this, ID_DELETE, "Delete selected"), 0, wxALL, 10 );
419
420 main_sizer->Add( button_sizer, 0, 0, 0 );
421
422 m_log = new wxTextCtrl( this, -1, "", wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE );
423
424 main_sizer->Add( m_log, 1, wxGROW );
425
426 SetSizer( main_sizer );
427 }
428
429 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) )
430 {
431 Close(true);
432 }
433
434 void MyFrame::OnDelete(wxCommandEvent& WXUNUSED(event) )
435 {
436 wxDataViewItem item = m_dataview->GetSelection();
437 if (item.IsOk())
438 m_model->Delete( item );
439 }
440
441 void MyFrame::OnAdd(wxCommandEvent& WXUNUSED(event) )
442 {
443 m_model->AddToClassical( "Kleine Nachtmusik", "Wolfgang Mozart", "1787" );
444 }
445
446 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event) )
447 {
448 wxAboutDialogInfo info;
449 info.SetName(_("DataView sample"));
450 info.SetDescription(_("This sample demonstrates the dataview control handling"));
451 info.SetCopyright(_T("(C) 2007 Robert Roebling"));
452
453 wxAboutBox(info);
454 }
455