itemcontainer.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Program: wxWidgets Widgets Sample
  3. // Name: itemcontainer.cpp
  4. // Purpose: Part of the widgets sample showing wxComboBox
  5. // Created: 20.07.07
  6. // Licence: wxWindows licence
  7. /////////////////////////////////////////////////////////////////////////////
  8. // ============================================================================
  9. // declarations
  10. // ============================================================================
  11. // ----------------------------------------------------------------------------
  12. // headers
  13. // ----------------------------------------------------------------------------
  14. // for compilers that support precompilation, includes "wx/wx.h".
  15. #include "wx/wxprec.h"
  16. #ifdef __BORLANDC__
  17. #pragma hdrstop
  18. #endif
  19. // for all others, include the necessary headers
  20. #ifndef WX_PRECOMP
  21. #include "wx/log.h"
  22. #include "wx/event.h"
  23. #endif
  24. #include "wx/ctrlsub.h"
  25. #include "itemcontainer.h"
  26. // Help track client data objects in wxItemContainer instances.
  27. class TrackedClientData : public wxClientData
  28. {
  29. public:
  30. TrackedClientData(ItemContainerWidgetsPage* tracker, int value)
  31. : m_tracker(tracker),
  32. m_value(value)
  33. {
  34. m_tracker->StartTrackingData();
  35. }
  36. virtual ~TrackedClientData()
  37. {
  38. m_tracker->StopTrackingData();
  39. }
  40. int GetValue() const
  41. {
  42. return m_value;
  43. }
  44. private:
  45. ItemContainerWidgetsPage *m_tracker;
  46. int m_value;
  47. wxDECLARE_NO_COPY_CLASS(TrackedClientData);
  48. };
  49. // ============================================================================
  50. // implementation
  51. // ============================================================================
  52. ItemContainerWidgetsPage::ItemContainerWidgetsPage(WidgetsBookCtrl *book,
  53. wxImageList *image_list,
  54. const char *const icon[])
  55. : WidgetsPage(book, image_list, icon), m_trackedDataObjects(0)
  56. {
  57. m_items.Add(wxT("This"));
  58. m_items.Add(wxT("is"));
  59. m_items.Add(wxT("a"));
  60. m_items.Add(wxT("List"));
  61. m_items.Add(wxT("of"));
  62. m_items.Add(wxT("strings"));
  63. m_itemsSorted = m_items;
  64. }
  65. ItemContainerWidgetsPage::~ItemContainerWidgetsPage()
  66. {
  67. }
  68. wxClientData* ItemContainerWidgetsPage::CreateClientData(int value)
  69. {
  70. return new TrackedClientData(this, value);
  71. }
  72. void ItemContainerWidgetsPage::StartTrackingData()
  73. {
  74. ++m_trackedDataObjects;
  75. }
  76. void ItemContainerWidgetsPage::StopTrackingData()
  77. {
  78. --m_trackedDataObjects;
  79. }
  80. bool ItemContainerWidgetsPage::VerifyAllClientDataDestroyed()
  81. {
  82. if ( m_trackedDataObjects )
  83. {
  84. wxString message = wxT("Bug in managing wxClientData: ");
  85. if ( m_trackedDataObjects > 0 )
  86. message << m_trackedDataObjects << wxT(" lost objects");
  87. else
  88. message << (-m_trackedDataObjects) << wxT(" extra deletes");
  89. wxFAIL_MSG(message);
  90. return false;
  91. }
  92. return true;
  93. }
  94. void ItemContainerWidgetsPage::StartTest(const wxString& label)
  95. {
  96. m_container->Clear();
  97. wxLogMessage(wxT("Test - %s:"), label.c_str());
  98. }
  99. void ItemContainerWidgetsPage::EndTest(const wxArrayString& items)
  100. {
  101. const unsigned count = m_container->GetCount();
  102. bool ok = count == items.GetCount();
  103. if ( !ok )
  104. {
  105. wxFAIL_MSG(wxT("Item count does not match."));
  106. }
  107. else
  108. {
  109. for ( unsigned i = 0; i < count; ++i )
  110. {
  111. wxString str = m_container->GetString(i);
  112. if ( str != items[i] )
  113. {
  114. wxFAIL_MSG(wxString::Format(
  115. wxT("Wrong string \"%s\" at position %d (expected \"%s\")"),
  116. str.c_str(), i, items[i].c_str()));
  117. ok = false;
  118. break;
  119. }
  120. if ( m_container->HasClientUntypedData() )
  121. {
  122. void *data = m_container->GetClientData(i);
  123. if ( data && !VerifyClientData((wxUIntPtr)data, str) )
  124. {
  125. ok = false;
  126. break;
  127. }
  128. }
  129. else if ( m_container->HasClientObjectData() )
  130. {
  131. TrackedClientData* obj = (TrackedClientData*)m_container->GetClientObject(i);
  132. if ( obj && !VerifyClientData(obj->GetValue(), str) )
  133. {
  134. ok = false;
  135. break;
  136. }
  137. }
  138. }
  139. if ( !ok )
  140. {
  141. wxLogMessage(DumpContainerData(items));
  142. }
  143. }
  144. m_container->Clear();
  145. ok &= VerifyAllClientDataDestroyed();
  146. wxLogMessage(wxT("...%s"), ok ? wxT("passed") : wxT("failed"));
  147. }
  148. wxString
  149. ItemContainerWidgetsPage::DumpContainerData(const wxArrayString& expected) const
  150. {
  151. wxString str;
  152. str << wxT("Current content:\n");
  153. unsigned i;
  154. for ( i = 0; i < m_container->GetCount(); ++i )
  155. {
  156. str << wxT(" - ") << m_container->GetString(i) << wxT(" [");
  157. if ( m_container->HasClientObjectData() )
  158. {
  159. TrackedClientData *
  160. obj = (TrackedClientData*)m_container->GetClientObject(i);
  161. if ( obj )
  162. str << obj->GetValue();
  163. }
  164. else if ( m_container->HasClientUntypedData() )
  165. {
  166. void *data = m_container->GetClientData(i);
  167. if ( data )
  168. str << (wxUIntPtr)data;
  169. }
  170. str << wxT("]\n");
  171. }
  172. str << wxT("Expected content:\n");
  173. for ( i = 0; i < expected.GetCount(); ++i )
  174. {
  175. const wxString& item = expected[i];
  176. str << wxT(" - ") << item << wxT("[");
  177. for( unsigned j = 0; j < m_items.GetCount(); ++j )
  178. {
  179. if ( m_items[j] == item )
  180. str << j;
  181. }
  182. str << wxT("]\n");
  183. }
  184. return str;
  185. }
  186. bool ItemContainerWidgetsPage::VerifyClientData(wxUIntPtr i, const wxString& str)
  187. {
  188. if ( i > m_items.GetCount() || m_items[i] != str )
  189. {
  190. wxLogMessage(wxT("Client data for '%s' does not match."), str.c_str());
  191. return false;
  192. }
  193. return true;
  194. }
  195. /* static */
  196. wxArrayString
  197. ItemContainerWidgetsPage::MakeArray(const wxSortedArrayString& sorted)
  198. {
  199. wxArrayString a;
  200. const size_t count = sorted.size();
  201. a.reserve(count);
  202. for ( size_t n = 0; n < count; n++ )
  203. a.push_back(sorted[n]);
  204. return a;
  205. }
  206. void ItemContainerWidgetsPage::OnButtonTestItemContainer(wxCommandEvent&)
  207. {
  208. m_container = GetContainer();
  209. wxASSERT_MSG(m_container, wxT("Widget must have a test widget"));
  210. wxLogMessage(wxT("wxItemContainer test for %s, %s:"),
  211. GetWidget()->GetClassInfo()->GetClassName(),
  212. (m_container->IsSorted() ? "Sorted" : "Unsorted"));
  213. const wxArrayString
  214. expected_result = m_container->IsSorted() ? MakeArray(m_itemsSorted)
  215. : m_items;
  216. StartTest(wxT("Append one item"));
  217. wxString item = m_items[0];
  218. m_container->Append(item);
  219. EndTest(wxArrayString(1, &item));
  220. StartTest(wxT("Append some items"));
  221. m_container->Append(m_items);
  222. EndTest(expected_result);
  223. StartTest(wxT("Append some items with data objects"));
  224. wxClientData **objects = new wxClientData *[m_items.GetCount()];
  225. unsigned i;
  226. for ( i = 0; i < m_items.GetCount(); ++i )
  227. objects[i] = CreateClientData(i);
  228. m_container->Append(m_items, objects);
  229. EndTest(expected_result);
  230. delete[] objects;
  231. StartTest(wxT("Append some items with data"));
  232. void **data = new void *[m_items.GetCount()];
  233. for ( i = 0; i < m_items.GetCount(); ++i )
  234. data[i] = wxUIntToPtr(i);
  235. m_container->Append(m_items, data);
  236. EndTest(expected_result);
  237. delete[] data;
  238. StartTest(wxT("Append some items with data, one by one"));
  239. for ( i = 0; i < m_items.GetCount(); ++i )
  240. m_container->Append(m_items[i], wxUIntToPtr(i));
  241. EndTest(expected_result);
  242. StartTest(wxT("Append some items with data objects, one by one"));
  243. for ( i = 0; i < m_items.GetCount(); ++i )
  244. m_container->Append(m_items[i], CreateClientData(i));
  245. EndTest(expected_result);
  246. if ( !m_container->IsSorted() )
  247. {
  248. StartTest(wxT("Insert in reverse order with data, one by one"));
  249. for ( unsigned i = m_items.GetCount(); i; --i )
  250. m_container->Insert(m_items[i - 1], 0, wxUIntToPtr(i - 1));
  251. EndTest(expected_result);
  252. }
  253. }