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