]> git.saurik.com Git - wxWidgets.git/blob - samples/dataview/dataview.cpp
Made wxDataViewCtrl sample use a real, expandabl data tree
[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 MyMusicModel()
126 {
127 m_idCounter = 0;
128 m_root = new MyMusicModelNode( NULL, GetNewId(), "My Music" );
129 m_pop = new MyMusicModelNode( m_root, GetNewId(), "Pop music" );
130 m_root->Append( m_pop );
131 m_pop->Append( new MyMusicModelNode( m_pop, GetNewId(),
132 "You are not alone", "Michael Jackson", "1995" ) );
133 m_pop->Append( new MyMusicModelNode( m_pop, GetNewId(),
134 "Take a bow", "Madonna", "1994" ) );
135 m_classical = new MyMusicModelNode( m_root, GetNewId(), "Classical music" );
136 m_root->Append( m_classical );
137 m_classical->Append( new MyMusicModelNode( m_classical, GetNewId(),
138 "Ninth symphony", "Ludwig van Beethoven", "1824" ) );
139 m_classical->Append( new MyMusicModelNode( m_classical, GetNewId(),
140 "German Requiem", "Johannes Brahms", "1868" ) );
141 }
142
143 void AddToClassical( const wxString &title, const wxString &artist, const wxString &year )
144 {
145 // add to data
146 MyMusicModelNode *child_node =
147 new MyMusicModelNode( m_classical, GetNewId(), title, artist, year );
148 m_classical->Append( child_node );
149
150 // notify control
151 wxDataViewItem child( child_node->GetID() );
152 wxDataViewItem parent( m_classical->GetID() );
153 wxPrintf( "parent id %d\n", m_classical->GetID() );
154 ItemAdded( parent, child );
155 }
156
157 virtual unsigned int GetColumnCount() const
158 {
159 return 3;
160 }
161
162 virtual wxString GetColumnType( unsigned int col ) const
163 {
164 return "string";
165 }
166
167 virtual void GetValue( wxVariant &variant,
168 const wxDataViewItem &item, unsigned int col ) const
169 {
170 MyMusicModelNode *node = FindNode( item );
171 switch (col)
172 {
173 case 0: variant = node->m_title; break;
174 case 1: variant = node->m_artist; break;
175 case 2: variant = node->m_year; break;
176 default: wxLogError( "MyMusicModel::GetValue: wrong column" );
177 }
178 }
179
180 virtual bool SetValue( const wxVariant &variant,
181 const wxDataViewItem &item, unsigned int col )
182 {
183 MyMusicModelNode *node = FindNode( item );
184 switch (col)
185 {
186 case 0: node->m_title = variant.GetString(); break;
187 case 1: node->m_artist = variant.GetString(); break;
188 case 2: node->m_year = variant.GetString(); break;
189 default: wxLogError( "MyMusicModel::SetValue: wrong column" );
190 }
191 }
192
193 virtual bool HasChildren( const wxDataViewItem &item ) const
194 {
195 if (item.GetID() == 0)
196 return true;
197
198 MyMusicModelNode *node = FindNode( item );
199 return node->IsContainer();
200 }
201
202 virtual wxDataViewItem GetFirstChild( const wxDataViewItem &parent ) const
203 {
204 if (parent.GetID() == 0)
205 return wxDataViewItem( m_root->GetID() );
206
207 MyMusicModelNode *node = FindNode( parent );
208
209 if (node->GetChildCount() == 0)
210 return wxDataViewItem( 0 );
211
212 MyMusicModelNode *first_child = node->GetChildren().Item( 0 );
213 return wxDataViewItem( first_child->GetID() );
214 }
215
216 virtual wxDataViewItem GetNextSibling( const wxDataViewItem &item ) const
217 {
218 MyMusicModelNode *node = FindNode( item );
219 MyMusicModelNode *parent = node->GetParent();
220 if (!parent)
221 return wxDataViewItem(0);
222
223 int pos = parent->GetChildren().Index( node );
224 if (pos == wxNOT_FOUND)
225 return wxDataViewItem(0);
226
227 if (pos == parent->GetChildCount()-1)
228 return wxDataViewItem(0);
229
230 node = parent->GetChildren().Item( pos+1 );
231 return wxDataViewItem( node->GetID() );
232 }
233
234 private:
235 wxUint32 GetNewId() { m_idCounter++; return m_idCounter; }
236
237 MyMusicModelNode *FindNodeRec( MyMusicModelNode *node, const wxDataViewItem &item ) const
238 {
239 if (node->GetID() == item.GetID())
240 return node;
241
242 size_t count = node->GetChildCount();
243 size_t i;
244 for (i = 0; i < count; i++)
245 {
246 MyMusicModelNode *child = node->GetChildren().Item( i );
247 MyMusicModelNode *node2 = FindNodeRec( child, item );
248 if (node2)
249 return node2;
250 }
251 return NULL;
252 }
253
254 MyMusicModelNode *FindNode( const wxDataViewItem &item ) const
255 {
256 if (item.GetID() == 0)
257 return NULL;
258
259 if (!m_root)
260 return NULL;
261
262 return FindNodeRec( m_root, item );
263 }
264
265 MyMusicModelNode* m_root;
266 MyMusicModelNode* m_pop;
267 MyMusicModelNode* m_classical;
268 wxUint32 m_idCounter;
269 };
270
271 // -------------------------------------
272 // MyApp
273 // -------------------------------------
274
275 class MyApp: public wxApp
276 {
277 public:
278 bool OnInit(void);
279 int OnExit();
280 };
281
282 // -------------------------------------
283 // MyFrame
284 // -------------------------------------
285
286 class MyFrame : public wxFrame
287 {
288 public:
289 MyFrame(wxFrame *frame, wxChar *title, int x, int y, int w, int h);
290
291 public:
292 void OnQuit(wxCommandEvent& event);
293 void OnAbout(wxCommandEvent& event);
294 void OnAdd(wxCommandEvent& event);
295
296 private:
297 wxDataViewCtrl* m_dataview;
298 wxTextCtrl * m_log;
299 wxObjectDataPtr<MyMusicModel> m_model;
300
301 private:
302 DECLARE_EVENT_TABLE()
303 };
304
305 // -------------------------------------
306 // MyApp
307 // -------------------------------------
308
309 IMPLEMENT_APP(MyApp)
310
311 bool MyApp::OnInit(void)
312 {
313 if ( !wxApp::OnInit() )
314 return false;
315
316 // build the first frame
317 MyFrame *frame =
318 new MyFrame(NULL, wxT("wxDataViewCtrl feature test"), 10, 10, 700, 440);
319 frame->Show(true);
320
321 SetTopWindow(frame);
322 return true;
323 }
324
325 int MyApp::OnExit()
326 {
327 return 0;
328 }
329
330
331 // -------------------------------------
332 // MyFrame
333 // -------------------------------------
334
335 enum
336 {
337 // file menu
338 ID_ABOUT = wxID_ABOUT,
339 ID_EXIT = wxID_EXIT,
340
341 ID_ADD = 100,
342 };
343
344 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
345 EVT_MENU( ID_ABOUT, MyFrame::OnAbout )
346 EVT_MENU( ID_EXIT, MyFrame::OnQuit )
347 EVT_BUTTON( ID_ADD, MyFrame::OnAdd )
348 END_EVENT_TABLE()
349
350 MyFrame::MyFrame(wxFrame *frame, wxChar *title, int x, int y, int w, int h):
351 wxFrame(frame, wxID_ANY, title, wxPoint(x, y), wxSize(w, h))
352 {
353 SetIcon(wxICON(sample));
354
355 // build the menus:
356
357 wxMenu *file_menu = new wxMenu;
358 file_menu->Append(ID_ABOUT, "&About");
359 file_menu->AppendSeparator();
360 file_menu->Append(ID_EXIT, "E&xit");
361
362 wxMenuBar *menu_bar = new wxMenuBar;
363 menu_bar->Append(file_menu, "&File");
364
365 SetMenuBar(menu_bar);
366 CreateStatusBar();
367
368 wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
369
370 m_dataview = new wxDataViewCtrl( this, wxID_ANY, wxDefaultPosition,
371 wxDefaultSize );
372
373 m_model = new MyMusicModel;
374 m_dataview->AssociateModel( m_model.get() );
375
376 m_dataview->AppendTextColumn( "Title", 0, wxDATAVIEW_CELL_INERT, 200,
377 DEFAULT_ALIGN, wxDATAVIEW_COL_SORTABLE );
378 m_dataview->AppendTextColumn( "Artist", 1, wxDATAVIEW_CELL_INERT, 200,
379 DEFAULT_ALIGN, wxDATAVIEW_COL_SORTABLE );
380 m_dataview->AppendTextColumn( "Year", 2, wxDATAVIEW_CELL_INERT, 50,
381 DEFAULT_ALIGN );
382
383 main_sizer->Add( m_dataview, 2, wxGROW );
384
385 wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
386
387 button_sizer->Add( new wxButton( this, ID_ADD, "Add Mozart"), 0, wxALL, 10 );
388
389 main_sizer->Add( button_sizer, 0, 0, 0 );
390
391 m_log = new wxTextCtrl( this, -1, "", wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE );
392
393 main_sizer->Add( m_log, 1, wxGROW );
394
395 SetSizer( main_sizer );
396 }
397
398 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) )
399 {
400 Close(true);
401 }
402
403 void MyFrame::OnAdd(wxCommandEvent& WXUNUSED(event) )
404 {
405 #if 0
406 // ignore selection, do something better later
407 wxDataViewItem item = m_dataview->GetSelection();
408 if (item.IsOk())
409 {
410 if (m_model->HasChildren(item))
411 {
412 }
413 else
414 {
415 }
416 }
417 #endif
418
419 m_model->AddToClassical( "Kleine Nachtmusik", "Wolfgang Mozart", "1787" );
420 }
421
422 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event) )
423 {
424 wxAboutDialogInfo info;
425 info.SetName(_("DataView sample"));
426 info.SetDescription(_("This sample demonstrates the dataview control handling"));
427 info.SetCopyright(_T("(C) 2007 Robert Roebling"));
428
429 wxAboutBox(info);
430 }
431