1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wx/ctrlsub.h (read: "wxConTRoL with SUBitems")
3 // Purpose: wxControlWithItems interface
4 // Author: Vadim Zeitlin
8 // Copyright: (c) wxWidgets team
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #ifndef _WX_CTRLSUB_H_BASE_
13 #define _WX_CTRLSUB_H_BASE_
19 #include "wx/arrstr.h"
20 #include "wx/control.h" // base class
22 // ----------------------------------------------------------------------------
23 // wxItemContainer defines an interface which is implemented by all controls
24 // which have string subitems each of which may be selected.
26 // It is decomposed in wxItemContainerImmutable which omits all methods
27 // adding/removing items and is used by wxRadioBox and wxItemContainer itself.
29 // Examples: wxListBox, wxCheckListBox, wxChoice and wxComboBox (which
30 // implements an extended interface deriving from this one)
31 // ----------------------------------------------------------------------------
33 class WXDLLIMPEXP_CORE wxItemContainerImmutable
36 wxItemContainerImmutable() { }
37 virtual ~wxItemContainerImmutable();
42 virtual unsigned int GetCount() const = 0;
43 bool IsEmpty() const { return GetCount() == 0; }
45 virtual wxString
GetString(unsigned int n
) const = 0;
46 wxArrayString
GetStrings() const;
47 virtual void SetString(unsigned int n
, const wxString
& s
) = 0;
49 // finding string natively is either case sensitive or insensitive
50 // but never both so fall back to this base version for not
51 // supported search type
52 virtual int FindString(const wxString
& s
, bool bCase
= false) const
54 unsigned int count
= GetCount();
56 for ( unsigned int i
= 0; i
< count
; ++i
)
58 if (GetString(i
).IsSameAs( s
, bCase
))
69 virtual void SetSelection(int n
) = 0;
70 virtual int GetSelection() const = 0;
72 // set selection to the specified string, return false if not found
73 bool SetStringSelection(const wxString
& s
);
75 // return the selected string or empty string if none
76 virtual wxString
GetStringSelection() const;
78 // this is the same as SetSelection( for single-selection controls but
79 // reads better for multi-selection ones
80 void Select(int n
) { SetSelection(n
); }
84 // check that the index is valid
85 bool IsValid(unsigned int n
) const { return n
< GetCount(); }
86 bool IsValidInsert(unsigned int n
) const { return n
<= GetCount(); }
89 // ----------------------------------------------------------------------------
90 // wxItemContainer extends wxItemContainerImmutable interface with methods
91 // for adding/removing items.
93 // Classes deriving from this one must override DoInsertItems() to implement
94 // adding items to the control. This can often be implemented more efficiently
95 // than simply looping over the elements and inserting them but if this is not
96 // the case, the generic DoInsertItemsInLoop can be used in implementation, but
97 // in this case DoInsertItem() needs to be overridden.
98 // ----------------------------------------------------------------------------
100 class WXDLLIMPEXP_CORE wxItemContainer
: public wxItemContainerImmutable
103 // AppendItems() and InsertItems() helpers just call DoAppend/InsertItems()
104 // after doing some checks
106 // NB: they're defined here so that they're inlined when used in public part
107 int AppendItems(const wxArrayStringsAdapter
& items
,
109 wxClientDataType type
)
111 if ( items
.IsEmpty() )
114 return DoAppendItems(items
, clientData
, type
);
117 int AppendItems(const wxArrayStringsAdapter
& items
)
119 return AppendItems(items
, NULL
, wxClientData_None
);
122 int AppendItems(const wxArrayStringsAdapter
& items
, void **clientData
)
124 wxASSERT_MSG( GetClientDataType() != wxClientData_Object
,
125 wxT("can't mix different types of client data") );
127 return AppendItems(items
, clientData
, wxClientData_Void
);
130 int AppendItems(const wxArrayStringsAdapter
& items
,
131 wxClientData
**clientData
)
133 wxASSERT_MSG( GetClientDataType() != wxClientData_Void
,
134 wxT("can't mix different types of client data") );
136 return AppendItems(items
, reinterpret_cast<void **>(clientData
),
137 wxClientData_Object
);
140 int InsertItems(const wxArrayStringsAdapter
& items
,
143 wxClientDataType type
)
145 wxASSERT_MSG( !IsSorted(), wxT("can't insert items in sorted control") );
147 wxCHECK_MSG( pos
<= GetCount(), wxNOT_FOUND
,
148 wxT("position out of range") );
150 // not all derived classes handle empty arrays correctly in
151 // DoInsertItems() and besides it really doesn't make much sense to do
152 // this (for append it could correspond to creating an initially empty
153 // control but why would anybody need to insert 0 items?)
154 wxCHECK_MSG( !items
.IsEmpty(), wxNOT_FOUND
,
155 wxT("need something to insert") );
157 return DoInsertItems(items
, pos
, clientData
, type
);
160 int InsertItems(const wxArrayStringsAdapter
& items
, unsigned int pos
)
162 return InsertItems(items
, pos
, NULL
, wxClientData_None
);
165 int InsertItems(const wxArrayStringsAdapter
& items
,
169 wxASSERT_MSG( GetClientDataType() != wxClientData_Object
,
170 wxT("can't mix different types of client data") );
172 return InsertItems(items
, pos
, clientData
, wxClientData_Void
);
175 int InsertItems(const wxArrayStringsAdapter
& items
,
177 wxClientData
**clientData
)
179 wxASSERT_MSG( GetClientDataType() != wxClientData_Void
,
180 wxT("can't mix different types of client data") );
182 return InsertItems(items
, pos
,
183 reinterpret_cast<void **>(clientData
),
184 wxClientData_Object
);
188 wxItemContainer() { m_clientDataItemsType
= wxClientData_None
; }
189 virtual ~wxItemContainer();
194 // append single item, return its position in the control (which can be
195 // different from the last one if the control is sorted)
196 int Append(const wxString
& item
)
197 { return AppendItems(item
); }
198 int Append(const wxString
& item
, void *clientData
)
199 { return AppendItems(item
, &clientData
); }
200 int Append(const wxString
& item
, wxClientData
*clientData
)
201 { return AppendItems(item
, &clientData
); }
203 // append several items at once to the control, return the position of the
204 // last item appended
205 int Append(const wxArrayString
& items
)
206 { return AppendItems(items
); }
207 int Append(const wxArrayString
& items
, void **clientData
)
208 { return AppendItems(items
, clientData
); }
209 int Append(const wxArrayString
& items
, wxClientData
**clientData
)
210 { return AppendItems(items
, clientData
); }
211 int Append(unsigned int n
, const wxString
*items
)
212 { return AppendItems(wxArrayStringsAdapter(n
, items
)); }
213 int Append(unsigned int n
, const wxString
*items
, void **clientData
)
214 { return AppendItems(wxArrayStringsAdapter(n
, items
), clientData
); }
215 int Append(unsigned int n
,
216 const wxString
*items
,
217 wxClientData
**clientData
)
218 { return AppendItems(wxArrayStringsAdapter(n
, items
), clientData
); }
220 // only for RTTI needs (separate name)
221 void AppendString(const wxString
& item
)
225 // inserting items: not for sorted controls!
226 // -----------------------------------------
228 // insert single item at the given position, return its effective position
229 int Insert(const wxString
& item
, unsigned int pos
)
230 { return InsertItems(item
, pos
); }
231 int Insert(const wxString
& item
, unsigned int pos
, void *clientData
)
232 { return InsertItems(item
, pos
, &clientData
); }
233 int Insert(const wxString
& item
, unsigned int pos
, wxClientData
*clientData
)
234 { return InsertItems(item
, pos
, &clientData
); }
236 // insert several items at once into the control, return the index of the
237 // last item inserted
238 int Insert(const wxArrayString
& items
, unsigned int pos
)
239 { return InsertItems(items
, pos
); }
240 int Insert(const wxArrayString
& items
, unsigned int pos
, void **clientData
)
241 { return InsertItems(items
, pos
, clientData
); }
242 int Insert(const wxArrayString
& items
,
244 wxClientData
**clientData
)
245 { return InsertItems(items
, pos
, clientData
); }
246 int Insert(unsigned int n
, const wxString
*items
, unsigned int pos
)
247 { return InsertItems(wxArrayStringsAdapter(n
, items
), pos
); }
248 int Insert(unsigned int n
,
249 const wxString
*items
,
252 { return InsertItems(wxArrayStringsAdapter(n
, items
), pos
, clientData
); }
253 int Insert(unsigned int n
,
254 const wxString
*items
,
256 wxClientData
**clientData
)
257 { return InsertItems(wxArrayStringsAdapter(n
, items
), pos
, clientData
); }
263 void Set(const wxArrayString
& items
)
264 { Clear(); Append(items
); }
265 void Set(const wxArrayString
& items
, void **clientData
)
266 { Clear(); Append(items
, clientData
); }
267 void Set(const wxArrayString
& items
, wxClientData
**clientData
)
268 { Clear(); Append(items
, clientData
); }
269 void Set(unsigned int n
, const wxString
*items
)
270 { Clear(); Append(n
, items
); }
271 void Set(unsigned int n
, const wxString
*items
, void **clientData
)
272 { Clear(); Append(n
, items
, clientData
); }
273 void Set(unsigned int n
, const wxString
*items
, wxClientData
**clientData
)
274 { Clear(); Append(n
, items
, clientData
); }
280 void Delete(unsigned int pos
);
286 // The control may maintain its items in a sorted order in which case
287 // items are automatically inserted at the right position when they are
288 // inserted or appended. Derived classes have to override this method if
289 // they implement sorting, typically by returning HasFlag(wxXX_SORT)
290 virtual bool IsSorted() const { return false; }
296 void SetClientData(unsigned int n
, void* clientData
);
297 void* GetClientData(unsigned int n
) const;
299 // SetClientObject() takes ownership of the pointer, GetClientObject()
300 // returns it but keeps the ownership while DetachClientObject() expects
301 // the caller to delete the pointer and also resets the internally stored
302 // one to NULL for this item
303 void SetClientObject(unsigned int n
, wxClientData
* clientData
);
304 wxClientData
* GetClientObject(unsigned int n
) const;
305 wxClientData
* DetachClientObject(unsigned int n
);
307 // return the type of client data stored in this control: usually it just
308 // returns m_clientDataItemsType but must be overridden in the controls
309 // which delegate their client data storage to another one (e.g. wxChoice
310 // in wxUniv which stores data in wxListBox which it uses anyhow); don't
311 // forget to override SetClientDataType() if you override this one
313 // NB: for this to work no code should ever access m_clientDataItemsType
314 // directly but only via this function!
315 virtual wxClientDataType
GetClientDataType() const
316 { return m_clientDataItemsType
; }
318 bool HasClientData() const
319 { return GetClientDataType() != wxClientData_None
; }
320 bool HasClientObjectData() const
321 { return GetClientDataType() == wxClientData_Object
; }
322 bool HasClientUntypedData() const
323 { return GetClientDataType() == wxClientData_Void
; }
326 // there is usually no need to override this method but you can do it if it
327 // is more convenient to only do "real" insertions in DoInsertItems() and
328 // to implement items appending here (in which case DoInsertItems() should
329 // call this method if pos == GetCount() as it can still be called in this
330 // case if public Insert() is called with such position)
331 virtual int DoAppendItems(const wxArrayStringsAdapter
& items
,
333 wxClientDataType type
)
335 return DoInsertItems(items
, GetCount(), clientData
, type
);
338 // this method must be implemented to insert the items into the control at
339 // position pos which can be GetCount() meaning that the items should be
340 // appended; for the sorted controls the position can be ignored
342 // the derived classes typically use AssignNewItemClientData() to
343 // associate the data with the items as they're being inserted
345 // the method should return the index of the position the last item was
346 // inserted into or wxNOT_FOUND if an error occurred
347 virtual int DoInsertItems(const wxArrayStringsAdapter
& items
,
350 wxClientDataType type
) = 0;
352 // before the client data is set for the first time for the control which
353 // hadn't had it before, DoInitItemClientData() is called which gives the
354 // derived class the possibility to initialize its client data storage only
355 // when client data is really used
356 virtual void DoInitItemClientData() { }
357 virtual void DoSetItemClientData(unsigned int n
, void *clientData
) = 0;
358 virtual void *DoGetItemClientData(unsigned int n
) const = 0;
360 virtual void DoClear() = 0;
361 virtual void DoDeleteOneItem(unsigned int pos
) = 0;
364 // methods useful for the derived classes which don't have any better way
365 // of adding multiple items to the control than doing it one by one: such
366 // classes should call DoInsertItemsInLoop() from their DoInsert() and
367 // override DoInsertOneItem() to perform the real insertion
368 virtual int DoInsertOneItem(const wxString
& item
, unsigned int pos
);
369 int DoInsertItemsInLoop(const wxArrayStringsAdapter
& items
,
372 wxClientDataType type
);
375 // helper for DoInsertItems(): n is the index into clientData, pos is the
376 // position of the item in the control
377 void AssignNewItemClientData(unsigned int pos
,
380 wxClientDataType type
);
382 // free the client object associated with the item at given position and
383 // set it to NULL (must only be called if HasClientObjectData())
384 void ResetItemClientObject(unsigned int n
);
386 // set the type of the client data stored in this control: override this if
387 // you override GetClientDataType()
388 virtual void SetClientDataType(wxClientDataType clientDataItemsType
)
390 m_clientDataItemsType
= clientDataItemsType
;
394 // the type of the client data for the items
395 wxClientDataType m_clientDataItemsType
;
398 // Inheriting directly from a wxWindow-derived class and wxItemContainer
399 // unfortunately introduces an ambiguity for all GetClientXXX() methods as they
400 // are inherited twice: the "global" versions from wxWindow and the per-item
401 // versions taking the index from wxItemContainer.
403 // So we need to explicitly resolve them and this helper template class is
404 // provided to do it. To use it, simply inherit from wxWindowWithItems<Window,
405 // Container> instead of Window and Container interface directly.
406 template <class W
, class C
>
407 class wxWindowWithItems
: public W
, public C
410 typedef W BaseWindowClass
;
411 typedef C BaseContainerInterface
;
413 wxWindowWithItems() { }
415 void SetClientData(void *data
)
416 { BaseWindowClass::SetClientData(data
); }
417 void *GetClientData() const
418 { return BaseWindowClass::GetClientData(); }
419 void SetClientObject(wxClientData
*data
)
420 { BaseWindowClass::SetClientObject(data
); }
421 wxClientData
*GetClientObject() const
422 { return BaseWindowClass::GetClientObject(); }
424 void SetClientData(unsigned int n
, void* clientData
)
425 { wxItemContainer::SetClientData(n
, clientData
); }
426 void* GetClientData(unsigned int n
) const
427 { return wxItemContainer::GetClientData(n
); }
428 void SetClientObject(unsigned int n
, wxClientData
* clientData
)
429 { wxItemContainer::SetClientObject(n
, clientData
); }
430 wxClientData
* GetClientObject(unsigned int n
) const
431 { return wxItemContainer::GetClientObject(n
); }
434 class WXDLLIMPEXP_CORE wxControlWithItemsBase
:
435 public wxWindowWithItems
<wxControl
, wxItemContainer
>
438 wxControlWithItemsBase() { }
440 // usually the controls like list/combo boxes have their own background
442 virtual bool ShouldInheritColours() const { return false; }
445 // Implementation only from now on.
447 // Generate an event of the given type for the selection change.
448 void SendSelectionChangedEvent(wxEventType eventType
);
451 // fill in the client object or data field of the event as appropriate
453 // calls InitCommandEvent() and, if n != wxNOT_FOUND, also sets the per
455 void InitCommandEventWithItems(wxCommandEvent
& event
, int n
);
458 wxDECLARE_NO_COPY_CLASS(wxControlWithItemsBase
);
461 // define the platform-specific wxControlWithItems class
462 #if defined(__WXMSW__)
463 #include "wx/msw/ctrlsub.h"
464 #elif defined(__WXMOTIF__)
465 #include "wx/motif/ctrlsub.h"
467 class WXDLLIMPEXP_CORE wxControlWithItems
: public wxControlWithItemsBase
470 wxControlWithItems() { }
473 DECLARE_ABSTRACT_CLASS(wxControlWithItems
)
474 wxDECLARE_NO_COPY_CLASS(wxControlWithItems
);
478 #endif // wxUSE_CONTROLS
480 #endif // _WX_CTRLSUB_H_BASE_