1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        src/common/ctrlsub.cpp
3 // Purpose:     wxItemContainer implementation
4 // Author:      Vadim Zeitlin
5 // Modified by:
6 // Created:     22.10.99
7 // Copyright:   (c) wxWidgets team
8 // Licence:     wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10 
11 // ============================================================================
12 // declarations
13 // ============================================================================
14 
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18 
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21 
22 #ifdef __BORLANDC__
23     #pragma hdrstop
24 #endif
25 
26 #if wxUSE_CONTROLS
27 
28 #ifndef WX_PRECOMP
29     #include "wx/ctrlsub.h"
30     #include "wx/arrstr.h"
31 #endif
32 
IMPLEMENT_ABSTRACT_CLASS(wxControlWithItems,wxControl)33 IMPLEMENT_ABSTRACT_CLASS(wxControlWithItems, wxControl)
34 
35 // ============================================================================
36 // wxItemContainerImmutable implementation
37 // ============================================================================
38 
39 wxItemContainerImmutable::~wxItemContainerImmutable()
40 {
41     // this destructor is required for Darwin
42 }
43 
44 // ----------------------------------------------------------------------------
45 // selection
46 // ----------------------------------------------------------------------------
47 
GetStringSelection() const48 wxString wxItemContainerImmutable::GetStringSelection() const
49 {
50     wxString s;
51 
52     int sel = GetSelection();
53     if ( sel != wxNOT_FOUND )
54         s = GetString((unsigned int)sel);
55 
56     return s;
57 }
58 
SetStringSelection(const wxString & s)59 bool wxItemContainerImmutable::SetStringSelection(const wxString& s)
60 {
61     const int sel = FindString(s);
62     if ( sel == wxNOT_FOUND )
63         return false;
64 
65     SetSelection(sel);
66 
67     return true;
68 }
69 
GetStrings() const70 wxArrayString wxItemContainerImmutable::GetStrings() const
71 {
72     wxArrayString result;
73 
74     const unsigned int count = GetCount();
75     result.Alloc(count);
76     for ( unsigned int n = 0; n < count; n++ )
77         result.Add(GetString(n));
78 
79     return result;
80 }
81 
82 // ============================================================================
83 // wxItemContainer implementation
84 // ============================================================================
85 
~wxItemContainer()86 wxItemContainer::~wxItemContainer()
87 {
88     // this destructor is required for Darwin
89 }
90 
91 // ----------------------------------------------------------------------------
92 // deleting items
93 // ----------------------------------------------------------------------------
94 
Clear()95 void wxItemContainer::Clear()
96 {
97     if ( HasClientObjectData() )
98     {
99         const unsigned count = GetCount();
100         for ( unsigned i = 0; i < count; ++i )
101             ResetItemClientObject(i);
102     }
103 
104     SetClientDataType(wxClientData_None);
105 
106     DoClear();
107 }
108 
Delete(unsigned int pos)109 void wxItemContainer::Delete(unsigned int pos)
110 {
111     wxCHECK_RET( pos < GetCount(), wxT("invalid index") );
112 
113     if ( HasClientObjectData() )
114         ResetItemClientObject(pos);
115 
116     DoDeleteOneItem(pos);
117 
118     if ( IsEmpty() )
119     {
120         SetClientDataType(wxClientData_None);
121     }
122 }
123 
124 // ----------------------------------------------------------------------------
125 //
126 // ----------------------------------------------------------------------------
127 
DoInsertItemsInLoop(const wxArrayStringsAdapter & items,unsigned int pos,void ** clientData,wxClientDataType type)128 int wxItemContainer::DoInsertItemsInLoop(const wxArrayStringsAdapter& items,
129                                          unsigned int pos,
130                                          void **clientData,
131                                          wxClientDataType type)
132 {
133     int n = wxNOT_FOUND;
134 
135     const unsigned int count = items.GetCount();
136     for ( unsigned int i = 0; i < count; ++i )
137     {
138         n = DoInsertOneItem(items[i], pos++);
139         if ( n == wxNOT_FOUND )
140             break;
141 
142         AssignNewItemClientData(n, clientData, i, type);
143     }
144 
145     return n;
146 }
147 
148 int
DoInsertOneItem(const wxString & WXUNUSED (item),unsigned int WXUNUSED (pos))149 wxItemContainer::DoInsertOneItem(const wxString& WXUNUSED(item),
150                                  unsigned int WXUNUSED(pos))
151 {
152     wxFAIL_MSG( wxT("Must be overridden if DoInsertItemsInLoop() is used") );
153 
154     return wxNOT_FOUND;
155 }
156 
157 
158 // ----------------------------------------------------------------------------
159 // client data
160 // ----------------------------------------------------------------------------
161 
SetClientObject(unsigned int n,wxClientData * data)162 void wxItemContainer::SetClientObject(unsigned int n, wxClientData *data)
163 {
164     wxASSERT_MSG( !HasClientUntypedData(),
165                   wxT("can't have both object and void client data") );
166 
167     wxCHECK_RET( IsValid(n), "Invalid index passed to SetClientObject()" );
168 
169     if ( HasClientObjectData() )
170     {
171         wxClientData * clientDataOld
172             = static_cast<wxClientData *>(DoGetItemClientData(n));
173         if ( clientDataOld )
174             delete clientDataOld;
175     }
176     else // didn't have any client data so far
177     {
178         // now we have object client data
179         DoInitItemClientData();
180 
181         SetClientDataType(wxClientData_Object);
182     }
183 
184     DoSetItemClientData(n, data);
185 }
186 
GetClientObject(unsigned int n) const187 wxClientData *wxItemContainer::GetClientObject(unsigned int n) const
188 {
189     wxCHECK_MSG( HasClientObjectData(), NULL,
190                   wxT("this window doesn't have object client data") );
191 
192     wxCHECK_MSG( IsValid(n), NULL,
193                  "Invalid index passed to GetClientObject()" );
194 
195     return static_cast<wxClientData *>(DoGetItemClientData(n));
196 }
197 
DetachClientObject(unsigned int n)198 wxClientData *wxItemContainer::DetachClientObject(unsigned int n)
199 {
200     wxClientData * const data = GetClientObject(n);
201     if ( data )
202     {
203         // reset the pointer as we don't own it any more
204         DoSetItemClientData(n, NULL);
205     }
206 
207     return data;
208 }
209 
SetClientData(unsigned int n,void * data)210 void wxItemContainer::SetClientData(unsigned int n, void *data)
211 {
212     if ( !HasClientData() )
213     {
214         DoInitItemClientData();
215         SetClientDataType(wxClientData_Void);
216     }
217 
218     wxASSERT_MSG( HasClientUntypedData(),
219                   wxT("can't have both object and void client data") );
220 
221     wxCHECK_RET( IsValid(n), "Invalid index passed to SetClientData()" );
222 
223     DoSetItemClientData(n, data);
224 }
225 
GetClientData(unsigned int n) const226 void *wxItemContainer::GetClientData(unsigned int n) const
227 {
228     wxCHECK_MSG( HasClientUntypedData(), NULL,
229                   wxT("this window doesn't have void client data") );
230 
231     wxCHECK_MSG( IsValid(n), NULL,
232                  "Invalid index passed to GetClientData()" );
233 
234     return DoGetItemClientData(n);
235 }
236 
AssignNewItemClientData(unsigned int pos,void ** clientData,unsigned int n,wxClientDataType type)237 void wxItemContainer::AssignNewItemClientData(unsigned int pos,
238                                               void **clientData,
239                                               unsigned int n,
240                                               wxClientDataType type)
241 {
242     switch ( type )
243     {
244         case wxClientData_Object:
245             SetClientObject
246             (
247                 pos,
248                 (reinterpret_cast<wxClientData **>(clientData))[n]
249             );
250             break;
251 
252         case wxClientData_Void:
253             SetClientData(pos, clientData[n]);
254             break;
255 
256         default:
257             wxFAIL_MSG( wxT("unknown client data type") );
258             // fall through
259 
260         case wxClientData_None:
261             // nothing to do
262             break;
263     }
264 }
265 
ResetItemClientObject(unsigned int n)266 void wxItemContainer::ResetItemClientObject(unsigned int n)
267 {
268     wxClientData * const data = GetClientObject(n);
269     if ( data )
270     {
271         delete data;
272         DoSetItemClientData(n, NULL);
273     }
274 }
275 
276 // ============================================================================
277 // wxControlWithItems implementation
278 // ============================================================================
279 
280 void
InitCommandEventWithItems(wxCommandEvent & event,int n)281 wxControlWithItemsBase::InitCommandEventWithItems(wxCommandEvent& event, int n)
282 {
283     InitCommandEvent(event);
284 
285     if ( n != wxNOT_FOUND )
286     {
287         if ( HasClientObjectData() )
288             event.SetClientObject(GetClientObject(n));
289         else if ( HasClientUntypedData() )
290             event.SetClientData(GetClientData(n));
291     }
292 }
293 
SendSelectionChangedEvent(wxEventType eventType)294 void wxControlWithItemsBase::SendSelectionChangedEvent(wxEventType eventType)
295 {
296     const int n = GetSelection();
297     if ( n == wxNOT_FOUND )
298         return;
299 
300     wxCommandEvent event(eventType, m_windowId);
301     event.SetInt(n);
302     event.SetEventObject(this);
303     event.SetString(GetStringSelection());
304     InitCommandEventWithItems(event, n);
305 
306     HandleWindowEvent(event);
307 }
308 
309 #endif // wxUSE_CONTROLS
310