]> git.saurik.com Git - wxWidgets.git/blob - samples/xti/classlist.cpp
Make storing non-trivial data in wxThreadSpecificInfo possible.
[wxWidgets.git] / samples / xti / classlist.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: classlist.cpp
3 // Purpose: ClassListDialog implementation
4 // Author: Francesco Montorsi
5 // Modified by:
6 // Created: 03/06/2007 14:49:55
7 // Copyright: (c) 2007 Francesco Montorsi
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11
12 // ----------------------------------------------------------------------------
13 // headers
14 // ----------------------------------------------------------------------------
15
16 // For compilers that support precompilation, includes "wx/wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/wx.h"
25 #endif
26
27 #include "classlist.h"
28
29 #if !wxUSE_EXTENDED_RTTI
30 #error This sample requires XTI (eXtended RTTI) enabled
31 #endif
32
33 // IMPLEMENT_DYNAMIC_CLASS( ClassListDialog, wxDialog ) -- see the header
34 BEGIN_EVENT_TABLE( ClassListDialog, wxDialog )
35 EVT_LISTBOX( ID_LISTBOX, ClassListDialog::OnListboxSelected )
36 EVT_TREE_SEL_CHANGED( ID_TREECTRL, ClassListDialog::OnTreectrlSelChanged )
37 EVT_CHOICEBOOK_PAGE_CHANGED( ID_LISTMODE, ClassListDialog::OnChoiceBookPageChange )
38
39 EVT_CHECKBOX( ID_SHOW_ONLY_XTI, ClassListDialog::OnShowOnlyXTICheckbox )
40 EVT_CHECKBOX( ID_SHOW_PROPERTIES_RECURSIVELY, ClassListDialog::OnShowRecursiveInfoCheckbox )
41 END_EVENT_TABLE()
42
43 // defined later
44 wxString DumpClassInfo(const wxClassInfo*, bool recursive);
45
46
47 // ----------------------------------------------------------------------------
48 // ClassListDialog
49 // ----------------------------------------------------------------------------
50
51 ClassListDialog::ClassListDialog()
52 {
53 Init();
54 }
55
56 ClassListDialog::ClassListDialog( wxWindow* parent, wxWindowID id,
57 const wxString& caption, const wxPoint& pos,
58 const wxSize& size, long style )
59 {
60 Init();
61 Create(parent, id, caption, pos, size, style);
62 }
63
64 bool ClassListDialog::Create( wxWindow* parent, wxWindowID id, const wxString& caption,
65 const wxPoint& pos, const wxSize& size, long style )
66 {
67 SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
68 wxDialog::Create( parent, id, caption, pos, size, style );
69
70 CreateControls();
71 if (GetSizer())
72 {
73 GetSizer()->SetSizeHints(this);
74 }
75 Centre();
76
77 return true;
78 }
79
80 ClassListDialog::~ClassListDialog()
81 {
82 }
83
84 void ClassListDialog::Init()
85 {
86 m_pClassCountText = NULL;
87 m_pRawListBox = NULL;
88 m_pParentTreeCtrl = NULL;
89 m_pSizeListBox = NULL;
90 m_pTextCtrl = NULL;
91 }
92
93 void ClassListDialog::CreateControls()
94 {
95 wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
96 this->SetSizer(itemBoxSizer2);
97
98 wxStaticText* itemStaticText3 = new wxStaticText( this, wxID_STATIC, _("This is the list of wxWidgets classes registered in the XTI system.\nNote that not all wxWidgets classes are registered nor all registered classes are completely _described_ using XTI metadata."), wxDefaultPosition, wxDefaultSize, 0 );
99 itemBoxSizer2->Add(itemStaticText3, 0, wxALIGN_LEFT|wxALL, 5);
100
101 // filters
102 wxBoxSizer* filters = new wxBoxSizer(wxHORIZONTAL);
103 itemBoxSizer2->Add(filters, 0, wxGROW|wxLEFT|wxRIGHT|wxBOTTOM, 5);
104 filters->Add(new wxCheckBox(this, ID_SHOW_ONLY_XTI,
105 wxT("Show only classes with eXtended infos")));
106 filters->AddSpacer(10);
107 filters->Add(new wxCheckBox(this, ID_SHOW_PROPERTIES_RECURSIVELY,
108 wxT("Show properties of parent classes")));
109
110 // show how many have we filtered out
111 m_pClassCountText = new wxStaticText( this, wxID_STATIC,
112 wxT("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"),
113 wxDefaultPosition, wxDefaultSize, 0 );
114 m_pClassCountText->SetFont(wxFont(8, wxSWISS, wxNORMAL, wxBOLD, false, wxT("Tahoma")));
115 itemBoxSizer2->Add(m_pClassCountText, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxBOTTOM, 5);
116
117 wxBoxSizer* itemBoxSizer5 = new wxBoxSizer(wxHORIZONTAL);
118 itemBoxSizer2->Add(itemBoxSizer5, 1, wxGROW, 5);
119
120 m_pChoiceBook = new wxChoicebook( this, ID_LISTMODE, wxDefaultPosition, wxDefaultSize, wxCHB_DEFAULT );
121
122 // raw-list page
123 wxPanel* itemPanel7 = new wxPanel( m_pChoiceBook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
124 wxBoxSizer* itemBoxSizer8 = new wxBoxSizer(wxHORIZONTAL);
125 itemPanel7->SetSizer(itemBoxSizer8);
126
127 wxArrayString m_pRawListBoxStrings;
128 m_pRawListBox = new wxListBox( itemPanel7, ID_LISTBOX, wxDefaultPosition, wxDefaultSize, m_pRawListBoxStrings, wxLB_SINGLE );
129 itemBoxSizer8->Add(m_pRawListBox, 1, wxGROW, 5);
130
131 m_pChoiceBook->AddPage(itemPanel7, _("Raw list"));
132
133 // by-size page
134 wxPanel* itemPanel13 = new wxPanel( m_pChoiceBook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER|wxTAB_TRAVERSAL );
135 wxBoxSizer* itemBoxSizer14 = new wxBoxSizer(wxHORIZONTAL);
136 itemPanel13->SetSizer(itemBoxSizer14);
137
138 wxArrayString m_pSizeListBoxStrings;
139 m_pSizeListBox = new wxListBox( itemPanel13, ID_LISTBOX, wxDefaultPosition, wxDefaultSize, m_pSizeListBoxStrings, wxLB_SINGLE );
140 itemBoxSizer14->Add(m_pSizeListBox, 1, wxGROW, 5);
141
142 m_pChoiceBook->AddPage(itemPanel13, _("Classes by size"));
143
144 // tree page
145 wxPanel* itemPanel10 = new wxPanel( m_pChoiceBook, ID_PANEL, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
146 wxBoxSizer* itemBoxSizer11 = new wxBoxSizer(wxVERTICAL);
147 itemPanel10->SetSizer(itemBoxSizer11);
148
149 m_pParentTreeCtrl = new wxTreeCtrl( itemPanel10, ID_TREECTRL, wxDefaultPosition, wxSize(100, 100), wxTR_HAS_BUTTONS |wxTR_SINGLE );
150 itemBoxSizer11->Add(m_pParentTreeCtrl, 1, wxGROW, 5);
151
152 m_pChoiceBook->AddPage(itemPanel10, _("Classes by parent"));
153
154
155 itemBoxSizer5->Add(m_pChoiceBook, 0, wxGROW|wxALL, 5);
156
157 m_pTextCtrl = new wxTextCtrl( this, ID_TEXTCTRL, wxT(""), wxDefaultPosition, wxSize(500, -1), wxTE_MULTILINE|wxTE_READONLY );
158 itemBoxSizer5->Add(m_pTextCtrl, 3, wxGROW|wxALL, 5);
159
160 wxStdDialogButtonSizer* itemStdDialogButtonSizer17 = new wxStdDialogButtonSizer;
161
162 itemBoxSizer2->Add(itemStdDialogButtonSizer17, 0, wxGROW|wxALL, 5);
163 wxButton* itemButton18 = new wxButton( this, wxID_OK, _("&OK"), wxDefaultPosition, wxDefaultSize, 0 );
164 itemStdDialogButtonSizer17->AddButton(itemButton18);
165
166 wxButton* itemButton19 = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
167 itemStdDialogButtonSizer17->AddButton(itemButton19);
168
169 itemStdDialogButtonSizer17->Realize();
170
171 InitControls();
172 }
173
174 int ClassListDialog::AddClassesWithParent(const wxClassInfo *parent, const wxTreeItemId &id)
175 {
176 const wxClassInfo *ci = wxClassInfo::GetFirst();
177 int count = 0;
178 while (ci)
179 {
180 // is this class derived from the given parent?
181 if (wxString(ci->GetBaseClassName1()) == parent->GetClassName() ||
182 wxString(ci->GetBaseClassName2()) == parent->GetClassName())
183 {
184 wxTreeItemId child = m_pParentTreeCtrl->AppendItem(id, ci->GetClassName());
185
186 // update the name of this child with the count of the children classes
187 int ret = AddClassesWithParent(ci, child);
188 m_pParentTreeCtrl->SetItemText(child,
189 m_pParentTreeCtrl->GetItemText(child) +
190 wxString::Format(wxT(" [%d]"), ret));
191 count += ret+1;
192 }
193
194 ci = ci->GetNext();
195 }
196
197 // reorder all the children we've just added
198 m_pParentTreeCtrl->SortChildren(id);
199
200 return count;
201 }
202
203 int GetSizeOfClass(const wxString &cn)
204 {
205 const wxClassInfo *ci = wxClassInfo::FindClass(cn);
206 if (ci)
207 return ci->GetSize();
208 return 0;
209 }
210
211 int CompareClassSizes(const wxString &class1, const wxString &class2)
212 {
213 return GetSizeOfClass(class1) - GetSizeOfClass(class2);
214 }
215
216 void ClassListDialog::InitControls()
217 {
218 // create a wxArrayString with the names of all classes:
219 const wxClassInfo *ci = wxClassInfo::GetFirst();
220 wxArrayString arr;
221 while (ci)
222 {
223 arr.Add(ci->GetClassName());
224 ci = ci->GetNext();
225 }
226
227 arr.Sort(); // sort alphabetically
228
229 // now add it to the raw-mode listbox
230 for (unsigned int i=0; i<arr.GetCount(); i++)
231 if (!IsToDiscard(arr[i]))
232 m_pRawListBox->Append(arr[i]);
233 m_nCount = m_pRawListBox->GetCount();
234
235 // sort again using size as sortkey
236 arr.Sort((wxArrayString::CompareFunction)CompareClassSizes);
237
238 // now add it to the size-mode listbox
239 for (unsigned int i=0; i<arr.GetCount(); i++)
240 if (!IsToDiscard(arr[i]))
241 m_pSizeListBox->Append(arr[i]);
242
243 // add root item to parent-mode treectrl
244 wxTreeItemId id = m_pParentTreeCtrl->AddRoot(wxT("wxObject"));
245
246 // recursively add all leaves to the treectrl
247 int count = AddClassesWithParent(CLASSINFO(wxObject), id);
248 m_pParentTreeCtrl->SetItemText(id, m_pParentTreeCtrl->GetItemText(id) +
249 wxString::Format(wxT(" [%d]"), count));
250
251 // initially expand the root item
252 m_pParentTreeCtrl->Expand(id);
253
254 m_nTotalCount = arr.GetCount();
255 UpdateFilterText();
256
257 // don't leave blank the XTI info display
258 m_pChoiceBook->ChangeSelection(0);
259 m_pRawListBox->Select(0);
260 UpdateClassInfo(m_pRawListBox->GetStringSelection());
261 }
262
263 bool ClassListDialog::IsToDiscard(const wxString &classname) const
264 {
265 wxCheckBox *cb = wx_static_cast(wxCheckBox*, FindWindow(ID_SHOW_ONLY_XTI));
266 if (!cb || !cb->IsChecked())
267 return false;
268
269 // check if this class has XTI infos
270 wxClassInfo *info = wxClassInfo::FindClass(classname);
271 if (!info)
272 return false;
273 if (info->GetFirstProperty() != NULL || info->GetFirstHandler() != NULL)
274 return false; // has XTI info
275 return true; // no XTI info
276 }
277
278 void ClassListDialog::UpdateFilterText()
279 {
280 // tell the user how many registered classes are present and
281 // how many are we showing
282 m_pClassCountText->SetLabel(
283 wxString::Format(
284 wxT("Showing %d classes on a total of %d registered classes in wxXTI."),
285 m_nCount, m_nTotalCount));
286 }
287
288 void ClassListDialog::UpdateClassInfo(const wxString &itemName)
289 {
290 wxString classname = itemName.BeforeFirst(wxT(' '));
291 wxCheckBox *cb = wx_static_cast(wxCheckBox*, FindWindow(ID_SHOW_PROPERTIES_RECURSIVELY));
292
293 m_pTextCtrl->SetValue(
294 DumpClassInfo(wxClassInfo::FindClass(classname), cb->IsChecked()));
295 }
296
297
298 // ----------------------------------------------------------------------------
299 // ClassListDialog - event handlers
300 // ----------------------------------------------------------------------------
301
302 void ClassListDialog::OnShowOnlyXTICheckbox( wxCommandEvent& WXUNUSED(event) )
303 {
304 m_pRawListBox->Clear();
305 m_pParentTreeCtrl->DeleteAllItems();
306 m_pSizeListBox->Clear();
307
308 InitControls();
309 }
310
311 void ClassListDialog::OnShowRecursiveInfoCheckbox( wxCommandEvent& WXUNUSED(event) )
312 {
313 m_pRawListBox->Clear();
314 m_pParentTreeCtrl->DeleteAllItems();
315 m_pSizeListBox->Clear();
316
317 InitControls();
318 }
319
320 void ClassListDialog::OnListboxSelected( wxCommandEvent& event )
321 {
322 UpdateClassInfo(event.GetString());
323 }
324
325 void ClassListDialog::OnTreectrlSelChanged( wxTreeEvent& event )
326 {
327 UpdateClassInfo(m_pParentTreeCtrl->GetItemText(event.GetItem()));
328 }
329
330 void ClassListDialog::OnChoiceBookPageChange( wxChoicebookEvent& event )
331 {
332 switch (event.GetSelection())
333 {
334 case 0:
335 if (m_pRawListBox->GetCount())
336 {
337 m_pRawListBox->Select(0);
338 UpdateClassInfo(m_pRawListBox->GetStringSelection());
339 }
340 break;
341 case 1:
342 if (m_pSizeListBox->GetCount())
343 {
344 m_pSizeListBox->Select(0);
345 UpdateClassInfo(m_pSizeListBox->GetStringSelection());
346 }
347 break;
348 case 2:
349 {
350 wxTreeItemId root = m_pParentTreeCtrl->GetRootItem();
351 if (root.IsOk())
352 {
353 m_pParentTreeCtrl->SelectItem(root);
354 UpdateClassInfo(m_pParentTreeCtrl->GetItemText(root));
355 }
356 }
357 break;
358 }
359 }
360
361
362
363 // ----------------------------------------------------------------------------
364 // dump functions
365 // ----------------------------------------------------------------------------
366
367 wxString DumpStr(const wxString &str)
368 {
369 if (str.empty())
370 return wxT("none");
371 return str;
372 }
373
374 wxString DumpTypeInfo(const wxTypeInfo *ti)
375 {
376 if (!ti)
377 return wxT("none");
378
379 return DumpStr(ti->GetTypeName());
380 }
381
382 wxString DumpPropertyAccessor(const wxPropertyAccessor *acc, int indent)
383 {
384 wxString ind = wxT("\n") + wxString(indent, wxT(' '));
385 wxString infostr;
386
387 if (!acc)
388 return ind + wxT("no property accessors");
389
390 if (acc->HasSetter())
391 infostr << ind << wxT("setter name: ") << acc->GetSetterName();
392 if (acc->HasCollectionGetter())
393 infostr << ind << wxT("collection getter name: ") << acc->GetCollectionGetterName();
394 if (acc->HasGetter())
395 infostr << ind << wxT("getter name: ") << acc->GetGetterName();
396 if (acc->HasAdder())
397 infostr << ind << wxT("adder name: ") << acc->GetAdderName();
398
399 return infostr;
400 }
401
402 wxString DumpPropertyInfo(const wxPropertyInfo *prop, int indent)
403 {
404 wxString ind = wxT("\n") + wxString(indent, wxT(' '));
405 wxString infostr;
406
407 if (!prop)
408 return ind + wxT("none");
409
410 infostr << ind << wxT("flags: ");
411 if (prop->GetFlags() & wxPROP_DEPRECATED)
412 infostr << wxT("wxPROP_DEPRECATED,");
413 if (prop->GetFlags() & wxPROP_OBJECT_GRAPH)
414 infostr << wxT("wxPROP_OBJECT_GRAPH,");
415 if (prop->GetFlags() & wxPROP_ENUM_STORE_LONG)
416 infostr << wxT("wxPROP_ENUM_STORE_LONG,");
417 if (prop->GetFlags() & wxPROP_DONT_STREAM)
418 infostr << wxT("wxPROP_DONT_STREAM,");
419
420 if (prop->GetFlags() == 0)
421 infostr << wxT("none");
422 else
423 infostr.RemoveLast(); // remove last comma
424
425 infostr << ind << wxT("help string: ") << DumpStr(prop->GetHelpString());
426 infostr << ind << wxT("group string: ") << DumpStr(prop->GetGroupString());
427
428 infostr << ind << wxT("collection element type: ") << DumpTypeInfo(prop->GetCollectionElementTypeInfo());
429 infostr << ind << wxT("type: ") << DumpTypeInfo(prop->GetTypeInfo());
430
431 infostr << ind << wxT("default value: ") << DumpStr(wxAnyGetAsString(prop->GetDefaultValue()));
432 infostr << DumpPropertyAccessor(prop->GetAccessor(), indent+1);
433
434 return infostr;
435 }
436
437 wxString DumpHandlerInfo(const wxHandlerInfo *phdlr, int indent)
438 {
439 wxString ind = wxT("\n") + wxString(indent, wxT(' '));
440 wxString infostr;
441
442 if (!phdlr)
443 return ind + wxT("none");
444
445 infostr << ind << wxT("event class: ") <<
446 (phdlr->GetEventClassInfo() ? phdlr->GetEventClassInfo()->GetClassName() : wxT("none"));
447
448 return infostr;
449 }
450
451 int DumpProperties(const wxClassInfo *info, wxString& infostr, bool recursive)
452 {
453 const wxPropertyInfo *prop;
454 int pcount;
455 for (prop = info->GetFirstProperty(), pcount = 0;
456 prop;
457 prop = prop->GetNext(), pcount++)
458 {
459 infostr << wxT("\n\n [") << pcount+1 << wxT("] Property: ") << prop->GetName();
460 infostr << DumpPropertyInfo(prop, 4);
461 }
462
463 if (pcount == 0)
464 infostr << wxT("\n None");
465
466 if (recursive)
467 {
468 const wxClassInfo **parent = info->GetParents();
469 wxString str;
470
471 for (int i=0; parent[i] != NULL; i++)
472 {
473 int ppcount = DumpProperties(parent[i], str, recursive);
474 if (ppcount)
475 {
476 pcount += ppcount;
477 infostr << wxT("\n\n ") << parent[i]->GetClassName() << wxT(" PARENT'S PROPERTIES:");
478 infostr << str;
479 }
480 }
481 }
482
483 return pcount;
484 }
485
486 int DumpHandlers(const wxClassInfo *info, wxString& infostr, bool recursive)
487 {
488 const wxHandlerInfo *h;
489 int hcount;
490 for (h = info->GetFirstHandler(), hcount = 0;
491 h;
492 h = h->GetNext(), hcount++)
493 {
494 infostr << wxT("\n\n [") << hcount+1 << wxT("] Handler: ") << h->GetName();
495 infostr << DumpHandlerInfo(h, 4);
496 }
497
498 if (hcount == 0)
499 infostr << wxT("\n None");
500
501 if (recursive)
502 {
503 const wxClassInfo **parent = info->GetParents();
504 wxString str;
505
506 for (int i=0; parent[i] != NULL; i++)
507 {
508 int hhcount = DumpHandlers(parent[i], str, recursive);
509 if (hhcount)
510 {
511 hcount += hhcount;
512 infostr << wxT("\n\n ") << parent[i]->GetClassName() << wxT(" PARENT'S HANDLERS:");
513 infostr << str;
514 }
515 }
516 }
517
518 return hcount;
519 }
520
521 wxString DumpClassInfo(const wxClassInfo *info, bool recursive)
522 {
523 wxString infostr;
524
525 if (!info)
526 return wxEmptyString;
527
528 // basic stuff:
529
530 infostr << wxT("\n BASIC RTTI INFO ABOUT ") << info->GetClassName();
531 infostr << wxT("\n =================================================");
532 infostr << wxT("\n Base class #1: ") << DumpStr(info->GetBaseClassName1());
533 infostr << wxT("\n Base class #2: ") << DumpStr(info->GetBaseClassName2());
534 infostr << wxT("\n Include file: ") << DumpStr(info->GetIncludeName());
535 infostr << wxT("\n Size: ") << info->GetSize();
536 infostr << wxT("\n Dynamic: ") << (info->IsDynamic() ? wxT("true") : wxT("false"));
537
538
539 // advanced stuff:
540
541 infostr << wxT("\n\n\n ADVANCED RTTI INFO ABOUT ") << info->GetClassName();
542 infostr << wxT("\n =================================================\n");
543 infostr << wxT("\n PROPERTIES");
544 infostr << wxT("\n -----------------------------------------");
545 int pcount = DumpProperties(info, infostr, recursive);
546 infostr << wxT("\n\n HANDLERS");
547 infostr << wxT("\n -----------------------------------------");
548 int hcount = DumpHandlers(info, infostr, recursive);
549
550 if (pcount+hcount == 0)
551 infostr << wxT("\n\n no advanced info\n");
552 else
553 {
554 infostr << wxT("\n\n Total count of properties: ") << pcount;
555 infostr << wxT("\n Total count of handlers: ") << hcount << wxT("\n");
556 }
557
558 return infostr;
559 }