--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: classlist.cpp
+// Purpose: ClassListDialog implementation
+// Author: Francesco Montorsi
+// Modified by:
+// Created: 03/06/2007 14:49:55
+// RCS-ID: $Id: classlist.cpp 48186 2007-08-19 19:59:54Z FM $
+// Copyright: (c) 2007 Francesco Montorsi
+// Licence: wxWidgets license
+/////////////////////////////////////////////////////////////////////////////
+
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+#include "classlist.h"
+
+#if !wxUSE_EXTENDED_RTTI
+ #error This sample requires XTI (eXtended RTTI) enabled
+#endif
+
+// IMPLEMENT_DYNAMIC_CLASS( ClassListDialog, wxDialog ) -- see the header
+BEGIN_EVENT_TABLE( ClassListDialog, wxDialog )
+ EVT_LISTBOX( ID_LISTBOX, ClassListDialog::OnListboxSelected )
+ EVT_TREE_SEL_CHANGED( ID_TREECTRL, ClassListDialog::OnTreectrlSelChanged )
+ EVT_CHOICEBOOK_PAGE_CHANGED( ID_LISTMODE, ClassListDialog::OnChoiceBookPageChange )
+
+ EVT_CHECKBOX( ID_SHOW_ONLY_XTI, ClassListDialog::OnShowOnlyXTICheckbox )
+ EVT_CHECKBOX( ID_SHOW_PROPERTIES_RECURSIVELY, ClassListDialog::OnShowRecursiveInfoCheckbox )
+END_EVENT_TABLE()
+
+// defined later
+wxString DumpClassInfo(const wxClassInfo*, bool recursive);
+
+
+// ----------------------------------------------------------------------------
+// ClassListDialog
+// ----------------------------------------------------------------------------
+
+ClassListDialog::ClassListDialog()
+{
+ Init();
+}
+
+ClassListDialog::ClassListDialog( wxWindow* parent, wxWindowID id,
+ const wxString& caption, const wxPoint& pos,
+ const wxSize& size, long style )
+{
+ Init();
+ Create(parent, id, caption, pos, size, style);
+}
+
+bool ClassListDialog::Create( wxWindow* parent, wxWindowID id, const wxString& caption,
+ const wxPoint& pos, const wxSize& size, long style )
+{
+ SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
+ wxDialog::Create( parent, id, caption, pos, size, style );
+
+ CreateControls();
+ if (GetSizer())
+ {
+ GetSizer()->SetSizeHints(this);
+ }
+ Centre();
+
+ return true;
+}
+
+ClassListDialog::~ClassListDialog()
+{
+}
+
+void ClassListDialog::Init()
+{
+ m_pClassCountText = NULL;
+ m_pRawListBox = NULL;
+ m_pParentTreeCtrl = NULL;
+ m_pSizeListBox = NULL;
+ m_pTextCtrl = NULL;
+}
+
+void ClassListDialog::CreateControls()
+{
+ wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
+ this->SetSizer(itemBoxSizer2);
+
+ 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 );
+ itemBoxSizer2->Add(itemStaticText3, 0, wxALIGN_LEFT|wxALL, 5);
+
+ // filters
+ wxBoxSizer* filters = new wxBoxSizer(wxHORIZONTAL);
+ itemBoxSizer2->Add(filters, 0, wxGROW|wxLEFT|wxRIGHT|wxBOTTOM, 5);
+ filters->Add(new wxCheckBox(this, ID_SHOW_ONLY_XTI,
+ wxT("Show only classes with eXtended infos")));
+ filters->AddSpacer(10);
+ filters->Add(new wxCheckBox(this, ID_SHOW_PROPERTIES_RECURSIVELY,
+ wxT("Show properties of parent classes")));
+
+ // show how many have we filtered out
+ m_pClassCountText = new wxStaticText( this, wxID_STATIC,
+ wxT("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"),
+ wxDefaultPosition, wxDefaultSize, 0 );
+ m_pClassCountText->SetFont(wxFont(8, wxSWISS, wxNORMAL, wxBOLD, false, wxT("Tahoma")));
+ itemBoxSizer2->Add(m_pClassCountText, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxBOTTOM, 5);
+
+ wxBoxSizer* itemBoxSizer5 = new wxBoxSizer(wxHORIZONTAL);
+ itemBoxSizer2->Add(itemBoxSizer5, 1, wxGROW, 5);
+
+ m_pChoiceBook = new wxChoicebook( this, ID_LISTMODE, wxDefaultPosition, wxDefaultSize, wxCHB_DEFAULT );
+
+ // raw-list page
+ wxPanel* itemPanel7 = new wxPanel( m_pChoiceBook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
+ wxBoxSizer* itemBoxSizer8 = new wxBoxSizer(wxHORIZONTAL);
+ itemPanel7->SetSizer(itemBoxSizer8);
+
+ wxArrayString m_pRawListBoxStrings;
+ m_pRawListBox = new wxListBox( itemPanel7, ID_LISTBOX, wxDefaultPosition, wxDefaultSize, m_pRawListBoxStrings, wxLB_SINGLE );
+ itemBoxSizer8->Add(m_pRawListBox, 1, wxGROW, 5);
+
+ m_pChoiceBook->AddPage(itemPanel7, _("Raw list"));
+
+ // by-size page
+ wxPanel* itemPanel13 = new wxPanel( m_pChoiceBook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER|wxTAB_TRAVERSAL );
+ wxBoxSizer* itemBoxSizer14 = new wxBoxSizer(wxHORIZONTAL);
+ itemPanel13->SetSizer(itemBoxSizer14);
+
+ wxArrayString m_pSizeListBoxStrings;
+ m_pSizeListBox = new wxListBox( itemPanel13, ID_LISTBOX, wxDefaultPosition, wxDefaultSize, m_pSizeListBoxStrings, wxLB_SINGLE );
+ itemBoxSizer14->Add(m_pSizeListBox, 1, wxGROW, 5);
+
+ m_pChoiceBook->AddPage(itemPanel13, _("Classes by size"));
+
+ // tree page
+ wxPanel* itemPanel10 = new wxPanel( m_pChoiceBook, ID_PANEL, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
+ wxBoxSizer* itemBoxSizer11 = new wxBoxSizer(wxVERTICAL);
+ itemPanel10->SetSizer(itemBoxSizer11);
+
+ m_pParentTreeCtrl = new wxTreeCtrl( itemPanel10, ID_TREECTRL, wxDefaultPosition, wxSize(100, 100), wxTR_HAS_BUTTONS |wxTR_SINGLE );
+ itemBoxSizer11->Add(m_pParentTreeCtrl, 1, wxGROW, 5);
+
+ m_pChoiceBook->AddPage(itemPanel10, _("Classes by parent"));
+
+
+ itemBoxSizer5->Add(m_pChoiceBook, 0, wxGROW|wxALL, 5);
+
+ m_pTextCtrl = new wxTextCtrl( this, ID_TEXTCTRL, _T(""), wxDefaultPosition, wxSize(500, -1), wxTE_MULTILINE|wxTE_READONLY );
+ itemBoxSizer5->Add(m_pTextCtrl, 3, wxGROW|wxALL, 5);
+
+ wxStdDialogButtonSizer* itemStdDialogButtonSizer17 = new wxStdDialogButtonSizer;
+
+ itemBoxSizer2->Add(itemStdDialogButtonSizer17, 0, wxGROW|wxALL, 5);
+ wxButton* itemButton18 = new wxButton( this, wxID_OK, _("&OK"), wxDefaultPosition, wxDefaultSize, 0 );
+ itemStdDialogButtonSizer17->AddButton(itemButton18);
+
+ wxButton* itemButton19 = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
+ itemStdDialogButtonSizer17->AddButton(itemButton19);
+
+ itemStdDialogButtonSizer17->Realize();
+
+ InitControls();
+}
+
+int ClassListDialog::AddClassesWithParent(const wxClassInfo *parent, const wxTreeItemId &id)
+{
+ const wxClassInfo *ci = wxClassInfo::GetFirst();
+ int count = 0;
+ while (ci)
+ {
+ // is this class derived from the given parent?
+ if (wxString(ci->GetBaseClassName1()) == parent->GetClassName() ||
+ wxString(ci->GetBaseClassName2()) == parent->GetClassName())
+ {
+ wxTreeItemId child = m_pParentTreeCtrl->AppendItem(id, ci->GetClassName());
+
+ // update the name of this child with the count of the children classes
+ int ret = AddClassesWithParent(ci, child);
+ m_pParentTreeCtrl->SetItemText(child,
+ m_pParentTreeCtrl->GetItemText(child) +
+ wxString::Format(wxT(" [%d]"), ret));
+ count += ret+1;
+ }
+
+ ci = ci->GetNext();
+ }
+
+ // reorder all the children we've just added
+ m_pParentTreeCtrl->SortChildren(id);
+
+ return count;
+}
+
+int GetSizeOfClass(const wxString &cn)
+{
+ const wxClassInfo *ci = wxClassInfo::FindClass(cn);
+ if (ci)
+ return ci->GetSize();
+ return 0;
+}
+
+int CompareClassSizes(const wxString &class1, const wxString &class2)
+{
+ return GetSizeOfClass(class1) - GetSizeOfClass(class2);
+}
+
+void ClassListDialog::InitControls()
+{
+ // create a wxArrayString with the names of all classes:
+ const wxClassInfo *ci = wxClassInfo::GetFirst();
+ wxArrayString arr;
+ while (ci)
+ {
+ arr.Add(ci->GetClassName());
+ ci = ci->GetNext();
+ }
+
+ arr.Sort(); // sort alphabetically
+
+ // now add it to the raw-mode listbox
+ for (unsigned int i=0; i<arr.GetCount(); i++)
+ if (!IsToDiscard(arr[i]))
+ m_pRawListBox->Append(arr[i]);
+ m_nCount = m_pRawListBox->GetCount();
+
+ // sort again using size as sortkey
+ arr.Sort((wxArrayString::CompareFunction)CompareClassSizes);
+
+ // now add it to the size-mode listbox
+ for (unsigned int i=0; i<arr.GetCount(); i++)
+ if (!IsToDiscard(arr[i]))
+ m_pSizeListBox->Append(arr[i]);
+
+ // add root item to parent-mode treectrl
+ wxTreeItemId id = m_pParentTreeCtrl->AddRoot(_T("wxObject"));
+
+ // recursively add all leaves to the treectrl
+ int count = AddClassesWithParent(CLASSINFO(wxObject), id);
+ m_pParentTreeCtrl->SetItemText(id, m_pParentTreeCtrl->GetItemText(id) +
+ wxString::Format(wxT(" [%d]"), count));
+
+ // initially expand the root item
+ m_pParentTreeCtrl->Expand(id);
+
+ m_nTotalCount = arr.GetCount();
+ UpdateFilterText();
+
+ // don't leave blank the XTI info display
+ m_pChoiceBook->ChangeSelection(0);
+ m_pRawListBox->Select(0);
+ UpdateClassInfo(m_pRawListBox->GetStringSelection());
+}
+
+bool ClassListDialog::IsToDiscard(const wxString &classname) const
+{
+ wxCheckBox *cb = wx_static_cast(wxCheckBox*, FindWindow(ID_SHOW_ONLY_XTI));
+ if (!cb || !cb->IsChecked())
+ return false;
+
+ // check if this class has XTI infos
+ wxClassInfo *info = wxClassInfo::FindClass(classname);
+ if (!info)
+ return false;
+ if (info->GetFirstProperty() != NULL || info->GetFirstHandler() != NULL)
+ return false; // has XTI info
+ return true; // no XTI info
+}
+
+void ClassListDialog::UpdateFilterText()
+{
+ // tell the user how many registered classes are present and
+ // how many are we showing
+ m_pClassCountText->SetLabel(
+ wxString::Format(
+ wxT("Showing %d classes on a total of %d registered classes in wxXTI."),
+ m_nCount, m_nTotalCount));
+}
+
+void ClassListDialog::UpdateClassInfo(const wxString &itemName)
+{
+ wxString classname = itemName.BeforeFirst(_T(' '));
+ wxCheckBox *cb = wx_static_cast(wxCheckBox*, FindWindow(ID_SHOW_PROPERTIES_RECURSIVELY));
+
+ m_pTextCtrl->SetValue(
+ DumpClassInfo(wxClassInfo::FindClass(classname), cb->IsChecked()));
+}
+
+
+// ----------------------------------------------------------------------------
+// ClassListDialog - event handlers
+// ----------------------------------------------------------------------------
+
+void ClassListDialog::OnShowOnlyXTICheckbox( wxCommandEvent& WXUNUSED(event) )
+{
+ m_pRawListBox->Clear();
+ m_pParentTreeCtrl->DeleteAllItems();
+ m_pSizeListBox->Clear();
+
+ InitControls();
+}
+
+void ClassListDialog::OnShowRecursiveInfoCheckbox( wxCommandEvent& WXUNUSED(event) )
+{
+ m_pRawListBox->Clear();
+ m_pParentTreeCtrl->DeleteAllItems();
+ m_pSizeListBox->Clear();
+
+ InitControls();
+}
+
+void ClassListDialog::OnListboxSelected( wxCommandEvent& event )
+{
+ UpdateClassInfo(event.GetString());
+}
+
+void ClassListDialog::OnTreectrlSelChanged( wxTreeEvent& event )
+{
+ UpdateClassInfo(m_pParentTreeCtrl->GetItemText(event.GetItem()));
+}
+
+void ClassListDialog::OnChoiceBookPageChange( wxChoicebookEvent& event )
+{
+ switch (event.GetSelection())
+ {
+ case 0:
+ if (m_pRawListBox->GetCount())
+ {
+ m_pRawListBox->Select(0);
+ UpdateClassInfo(m_pRawListBox->GetStringSelection());
+ }
+ break;
+ case 1:
+ if (m_pSizeListBox->GetCount())
+ {
+ m_pSizeListBox->Select(0);
+ UpdateClassInfo(m_pSizeListBox->GetStringSelection());
+ }
+ break;
+ case 2:
+ {
+ wxTreeItemId root = m_pParentTreeCtrl->GetRootItem();
+ if (root.IsOk())
+ {
+ m_pParentTreeCtrl->SelectItem(root);
+ UpdateClassInfo(m_pParentTreeCtrl->GetItemText(root));
+ }
+ }
+ break;
+ }
+}
+
+
+
+// ----------------------------------------------------------------------------
+// dump functions
+// ----------------------------------------------------------------------------
+
+wxString DumpStr(const wxString &str)
+{
+ if (str.empty())
+ return wxT("none");
+ return str;
+}
+
+wxString DumpTypeInfo(const wxTypeInfo *ti)
+{
+ if (!ti)
+ return _T("none");
+
+ return DumpStr(ti->GetTypeName());
+}
+
+wxString DumpPropertyAccessor(const wxPropertyAccessor *acc, int indent)
+{
+ wxString ind = _T("\n") + wxString(indent, wxT(' '));
+ wxString infostr;
+
+ if (!acc)
+ return ind + _T("no property accessors");
+
+ if (acc->HasSetter())
+ infostr << ind << _T("setter name: ") << acc->GetSetterName();
+ if (acc->HasCollectionGetter())
+ infostr << ind << _T("collection getter name: ") << acc->GetCollectionGetterName();
+ if (acc->HasGetter())
+ infostr << ind << _T("getter name: ") << acc->GetGetterName();
+ if (acc->HasAdder())
+ infostr << ind << _T("adder name: ") << acc->GetAdderName();
+
+ return infostr;
+}
+
+wxString DumpPropertyInfo(const wxPropertyInfo *prop, int indent)
+{
+ wxString ind = _T("\n") + wxString(indent, wxT(' '));
+ wxString infostr;
+
+ if (!prop)
+ return ind + _T("none");
+
+ infostr << ind << _T("flags: ");
+ if (prop->GetFlags() & wxPROP_DEPRECATED)
+ infostr << _T("wxPROP_DEPRECATED,");
+ if (prop->GetFlags() & wxPROP_OBJECT_GRAPH)
+ infostr << _T("wxPROP_OBJECT_GRAPH,");
+ if (prop->GetFlags() & wxPROP_ENUM_STORE_LONG)
+ infostr << _T("wxPROP_ENUM_STORE_LONG,");
+ if (prop->GetFlags() & wxPROP_DONT_STREAM)
+ infostr << _T("wxPROP_DONT_STREAM,");
+
+ if (prop->GetFlags() == 0)
+ infostr << _T("none");
+ else
+ infostr.RemoveLast(); // remove last comma
+
+ infostr << ind << _T("help string: ") << DumpStr(prop->GetHelpString());
+ infostr << ind << _T("group string: ") << DumpStr(prop->GetGroupString());
+
+ infostr << ind << _T("collection element type: ") << DumpTypeInfo(prop->GetCollectionElementTypeInfo());
+ infostr << ind << _T("type: ") << DumpTypeInfo(prop->GetTypeInfo());
+
+ infostr << ind << _T("default value: ") << DumpStr(prop->GetDefaultValue().GetAsString());
+ infostr << DumpPropertyAccessor(prop->GetAccessor(), indent+1);
+
+ return infostr;
+}
+
+wxString DumpHandlerInfo(const wxHandlerInfo *phdlr, int indent)
+{
+ wxString ind = _T("\n") + wxString(indent, wxT(' '));
+ wxString infostr;
+
+ if (!phdlr)
+ return ind + _T("none");
+
+ infostr << ind << _T("event class: ") <<
+ (phdlr->GetEventClassInfo() ? phdlr->GetEventClassInfo()->GetClassName() : wxT("none"));
+
+ return infostr;
+}
+
+int DumpProperties(const wxClassInfo *info, wxString& infostr, bool recursive)
+{
+ const wxPropertyInfo *prop;
+ int pcount;
+ for (prop = info->GetFirstProperty(), pcount = 0;
+ prop;
+ prop = prop->GetNext(), pcount++)
+ {
+ infostr << _T("\n\n [") << pcount+1 << _T("] Property: ") << prop->GetName();
+ infostr << DumpPropertyInfo(prop, 4);
+ }
+
+ if (pcount == 0)
+ infostr << _T("\n None");
+
+ if (recursive)
+ {
+ const wxClassInfo **parent = info->GetParents();
+ wxString str;
+
+ for (int i=0; parent[i] != NULL; i++)
+ {
+ int ppcount = DumpProperties(parent[i], str, recursive);
+ if (ppcount)
+ {
+ pcount += ppcount;
+ infostr << _T("\n\n ") << parent[i]->GetClassName() << _T(" PARENT'S PROPERTIES:");
+ infostr << str;
+ }
+ }
+ }
+
+ return pcount;
+}
+
+int DumpHandlers(const wxClassInfo *info, wxString& infostr, bool recursive)
+{
+ const wxHandlerInfo *h;
+ int hcount;
+ for (h = info->GetFirstHandler(), hcount = 0;
+ h;
+ h = h->GetNext(), hcount++)
+ {
+ infostr << _T("\n\n [") << hcount+1 << _T("] Handler: ") << h->GetName();
+ infostr << DumpHandlerInfo(h, 4);
+ }
+
+ if (hcount == 0)
+ infostr << _T("\n None");
+
+ if (recursive)
+ {
+ const wxClassInfo **parent = info->GetParents();
+ wxString str;
+
+ for (int i=0; parent[i] != NULL; i++)
+ {
+ int hhcount = DumpHandlers(parent[i], str, recursive);
+ if (hhcount)
+ {
+ hcount += hhcount;
+ infostr << _T("\n\n ") << parent[i]->GetClassName() << _T(" PARENT'S HANDLERS:");
+ infostr << str;
+ }
+ }
+ }
+
+ return hcount;
+}
+
+wxString DumpClassInfo(const wxClassInfo *info, bool recursive)
+{
+ wxString infostr;
+
+ if (!info)
+ return wxEmptyString;
+
+ // basic stuff:
+
+ infostr << _T("\n BASIC RTTI INFO ABOUT ") << info->GetClassName();
+ infostr << _T("\n =================================================");
+ infostr << _T("\n Base class #1: ") << DumpStr(info->GetBaseClassName1());
+ infostr << _T("\n Base class #2: ") << DumpStr(info->GetBaseClassName2());
+ infostr << _T("\n Include file: ") << DumpStr(info->GetIncludeName());
+ infostr << _T("\n Size: ") << info->GetSize();
+ infostr << _T("\n Dynamic: ") << (info->IsDynamic() ? _T("true") : _T("false"));
+
+
+ // advanced stuff:
+
+ infostr << _T("\n\n\n ADVANCED RTTI INFO ABOUT ") << info->GetClassName();
+ infostr << _T("\n =================================================\n");
+ infostr << _T("\n PROPERTIES");
+ infostr << _T("\n -----------------------------------------");
+ int pcount = DumpProperties(info, infostr, recursive);
+ infostr << _T("\n\n HANDLERS");
+ infostr << _T("\n -----------------------------------------");
+ int hcount = DumpHandlers(info, infostr, recursive);
+
+ if (pcount+hcount == 0)
+ infostr << _T("\n\n no advanced info\n");
+ else
+ {
+ infostr << _T("\n\n Total count of properties: ") << pcount;
+ infostr << _T("\n Total count of handlers: ") << hcount << _T("\n");
+ }
+
+ return infostr;
+}