1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxList, wxStringList classes
4 // Author: Julian Smart
5 // Modified by: VZ at 16/11/98: WX_DECLARE_LIST() and typesafe lists added
8 // Copyright: (c) 1998 Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 All this is quite ugly but serves two purposes:
14 1. Be almost 100% compatible with old, untyped, wxList class
15 2. Ensure compile-time type checking for the linked lists
17 The idea is to have one base class (wxListBase) working with "void *" data,
18 but to hide these untyped functions - i.e. make them protected, so they
19 can only be used from derived classes which have inline member functions
20 working with right types. This achieves the 2nd goal. As for the first one,
21 we provide a special derivation of wxListBase called wxList which looks just
28 // -----------------------------------------------------------------------------
30 // -----------------------------------------------------------------------------
33 #include "wx/object.h"
34 #include "wx/string.h"
37 #include "wx/beforestd.h"
41 #include "wx/afterstd.h"
44 // ----------------------------------------------------------------------------
46 // ----------------------------------------------------------------------------
48 // type of compare function for list sort operation (as in 'qsort'): it should
49 // return a negative value, 0 or positive value if the first element is less
50 // than, equal or greater than the second
54 typedef int (* LINKAGEMODE wxSortCompareFunction
)(const void *elem1
, const void *elem2
);
57 class WXDLLIMPEXP_BASE wxObjectListNode
;
58 typedef wxObjectListNode wxNode
;
61 typedef int (* LINKAGEMODE wxListIterateFunction
)(void *current
);
63 // ----------------------------------------------------------------------------
65 // ----------------------------------------------------------------------------
67 #if !defined(wxENUM_KEY_TYPE_DEFINED)
68 #define wxENUM_KEY_TYPE_DEFINED
81 #define wxLIST_COMPATIBILITY
83 #define WX_DECLARE_LIST_3(elT, dummy1, liT, dummy2, decl) \
84 WX_DECLARE_LIST_WITH_DECL(elT, liT, decl)
85 #define WX_DECLARE_LIST_PTR_3(elT, dummy1, liT, dummy2, decl) \
86 WX_DECLARE_LIST_3(elT, dummy1, liT, dummy2, decl)
88 #define WX_DECLARE_LIST_2(elT, liT, dummy, decl) \
89 WX_DECLARE_LIST_WITH_DECL(elT, liT, decl)
90 #define WX_DECLARE_LIST_PTR_2(elT, liT, dummy, decl) \
91 WX_DECLARE_LIST_2(elT, liT, dummy, decl) \
93 #define WX_DECLARE_LIST_WITH_DECL(elT, liT, decl) \
94 WX_DECLARE_LIST_XO(elT*, liT, decl)
96 #if !defined( __VISUALC__ )
99 class WXDLLIMPEXP_BASE wxList_SortFunction
102 wxList_SortFunction(wxSortCompareFunction f
) : m_f(f
) { }
103 bool operator()(const T
& i1
, const T
& i2
)
104 { return m_f((T
*)&i1
, (T
*)&i2
) < 0; }
106 wxSortCompareFunction m_f
;
109 #define WX_LIST_SORTFUNCTION( elT, f ) wxList_SortFunction<elT>(f)
110 #define VC6_WORKAROUND(elT, liT, decl)
112 #else // if defined( __VISUALC__ )
114 #define WX_LIST_SORTFUNCTION( elT, f ) std::greater<elT>( f )
115 #define VC6_WORKAROUND(elT, liT, decl) \
118 /* Workaround for broken VC6 STL incorrectly requires a std::greater<> */ \
119 /* to be passed into std::list::sort() */ \
121 struct std::greater<elT> \
124 wxSortCompareFunction m_CompFunc; \
126 greater( wxSortCompareFunction compfunc = NULL ) \
127 : m_CompFunc( compfunc ) {} \
128 bool operator()(const elT X, const elT Y) const \
130 return m_CompFunc ? \
131 ( m_CompFunc( X, Y ) < 0 ) : \
136 #endif // defined( __VISUALC__ )
138 #define WX_DECLARE_LIST_XO(elT, liT, decl) \
139 VC6_WORKAROUND(elT, liT, decl) \
140 decl liT : public std::list<elT> \
145 typedef elT _WX_LIST_ITEM_TYPE_##liT; \
146 static void DeleteFunction( _WX_LIST_ITEM_TYPE_##liT X ); \
148 class compatibility_iterator \
151 /* Workaround for broken VC6 nested class name resolution */ \
152 typedef std::list<elT>::iterator iterator; \
158 compatibility_iterator() \
159 : m_iter(), m_list( NULL ) {} \
160 compatibility_iterator( liT* li, iterator i ) \
161 : m_iter( i ), m_list( li ) {} \
162 compatibility_iterator( const liT* li, iterator i ) \
163 : m_iter( i ), m_list( const_cast< liT* >( li ) ) {} \
165 compatibility_iterator* operator->() { return this; } \
166 const compatibility_iterator* operator->() const { return this; } \
168 bool operator==(const compatibility_iterator& i) const \
170 wxASSERT_MSG( m_list && i.m_list, \
171 _T("comparing invalid iterators is illegal") ); \
172 return (m_list == i.m_list) && (m_iter == i.m_iter); \
174 bool operator!=(const compatibility_iterator& i) const \
175 { return !( operator==( i ) ); } \
176 operator bool() const \
177 { return m_list ? m_iter != m_list->end() : false; } \
178 bool operator !() const \
179 { return !( operator bool() ); } \
181 elT GetData() const \
182 { return *m_iter; } \
183 void SetData( elT e ) \
186 compatibility_iterator GetNext() const \
188 iterator i = m_iter; \
189 return compatibility_iterator( m_list, ++i ); \
191 compatibility_iterator GetPrevious() const \
193 if ( m_iter == m_list->begin() ) \
194 return compatibility_iterator(); \
196 iterator i = m_iter; \
197 return compatibility_iterator( m_list, --i ); \
199 int IndexOf() const \
201 return *this ? std::distance( m_list->begin(), m_iter ) \
206 liT() : m_destroy( false ) {} \
208 compatibility_iterator Find( const elT e ) const \
210 liT* _this = const_cast< liT* >( this ); \
211 return compatibility_iterator( _this, \
212 std::find( _this->begin(), _this->end(), e ) ); \
215 bool IsEmpty() const \
216 { return empty(); } \
217 size_t GetCount() const \
220 { return static_cast< int >( GetCount() ); } \
222 compatibility_iterator Item( size_t idx ) const \
224 iterator i = const_cast< liT* >(this)->begin(); \
225 std::advance( i, idx ); \
226 return compatibility_iterator( this, i ); \
228 compatibility_iterator GetFirst() const \
230 return compatibility_iterator( this, \
231 const_cast< liT* >(this)->begin() ); \
233 compatibility_iterator GetLast() const \
235 iterator i = const_cast< liT* >(this)->end(); \
236 return compatibility_iterator( this, !empty() ? --i : i ); \
238 compatibility_iterator Member( elT e ) const \
239 { return Find( e ); } \
240 compatibility_iterator Nth( int n ) const \
241 { return Item( n ); } \
242 int IndexOf( elT e ) const \
243 { return Find( e ).IndexOf(); } \
245 compatibility_iterator Append( elT e ) \
250 compatibility_iterator Insert( elT e ) \
253 return compatibility_iterator( this, begin() ); \
255 compatibility_iterator Insert( compatibility_iterator & i, elT e ) \
257 return compatibility_iterator( this, insert( i.m_iter, e ) ); \
259 compatibility_iterator Insert( size_t idx, elT e ) \
261 return compatibility_iterator( this, \
262 insert( Item( idx ).m_iter, e ) ); \
265 void DeleteContents( bool destroy ) \
266 { m_destroy = destroy; } \
267 bool GetDeleteContents() const \
268 { return m_destroy; } \
269 void Erase( const compatibility_iterator& i ) \
272 DeleteFunction( i->GetData() ); \
275 bool DeleteNode( const compatibility_iterator& i ) \
284 bool DeleteObject( elT e ) \
286 return DeleteNode( Find( e ) ); \
291 std::for_each( begin(), end(), DeleteFunction ); \
294 /* Workaround for broken VC6 std::list::sort() see above */ \
295 void Sort( wxSortCompareFunction compfunc ) \
296 { sort( WX_LIST_SORTFUNCTION( elT, compfunc ) ); } \
297 ~liT() { Clear(); } \
300 #define WX_DECLARE_LIST(elementtype, listname) \
301 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class)
302 #define WX_DECLARE_LIST_PTR(elementtype, listname) \
303 WX_DECLARE_LIST(elementtype, listname)
305 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
306 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLEXPORT)
307 #define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
308 WX_DECLARE_EXPORTED_LIST(elementtype, listname)
310 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
311 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class usergoo)
312 #define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
313 WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo)
315 // this macro must be inserted in your program after
316 // #include "wx/listimpl.cpp"
317 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
319 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
320 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
322 #else // if !wxUSE_STL
324 // due to circular header dependencies this function has to be declared here
325 // (normally it's found in utils.h which includes itself list.h...)
326 #if WXWIN_COMPATIBILITY_2_4
327 extern WXDLLIMPEXP_BASE wxChar
* copystring(const wxChar
*s
);
330 // undef it to get rid of old, deprecated functions
331 #define wxLIST_COMPATIBILITY
333 // -----------------------------------------------------------------------------
334 // key stuff: a list may be optionally keyed on integer or string key
335 // -----------------------------------------------------------------------------
343 // a struct which may contain both types of keys
345 // implementation note: on one hand, this class allows to have only one function
346 // for any keyed operation instead of 2 almost equivalent. OTOH, it's needed to
347 // resolve ambiguity which we would otherwise have with wxStringList::Find() and
348 // wxList::Find(const char *).
349 class WXDLLIMPEXP_BASE wxListKey
353 wxListKey() : m_keyType(wxKEY_NONE
)
355 wxListKey(long i
) : m_keyType(wxKEY_INTEGER
)
356 { m_key
.integer
= i
; }
357 wxListKey(const wxChar
*s
) : m_keyType(wxKEY_STRING
)
358 { m_key
.string
= wxStrdup(s
); }
359 wxListKey(const wxString
& s
) : m_keyType(wxKEY_STRING
)
360 { m_key
.string
= wxStrdup(s
.c_str()); }
363 wxKeyType
GetKeyType() const { return m_keyType
; }
364 const wxChar
*GetString() const
365 { wxASSERT( m_keyType
== wxKEY_STRING
); return m_key
.string
; }
366 long GetNumber() const
367 { wxASSERT( m_keyType
== wxKEY_INTEGER
); return m_key
.integer
; }
370 // Note: implementation moved to list.cpp to prevent BC++ inline
371 // expansion warning.
372 bool operator==(wxListKeyValue value
) const ;
377 if ( m_keyType
== wxKEY_STRING
)
383 wxListKeyValue m_key
;
386 // -----------------------------------------------------------------------------
387 // wxNodeBase class is a (base for) node in a double linked list
388 // -----------------------------------------------------------------------------
390 extern WXDLLIMPEXP_DATA_BASE(wxListKey
) wxDefaultListKey
;
392 class WXDLLIMPEXP_BASE wxListBase
;
394 class WXDLLIMPEXP_BASE wxNodeBase
396 friend class wxListBase
;
399 wxNodeBase(wxListBase
*list
= (wxListBase
*)NULL
,
400 wxNodeBase
*previous
= (wxNodeBase
*)NULL
,
401 wxNodeBase
*next
= (wxNodeBase
*)NULL
,
403 const wxListKey
& key
= wxDefaultListKey
);
405 virtual ~wxNodeBase();
407 // FIXME no check is done that the list is really keyed on strings
408 const wxChar
*GetKeyString() const { return m_key
.string
; }
409 long GetKeyInteger() const { return m_key
.integer
; }
411 // Necessary for some existing code
412 void SetKeyString(wxChar
* s
) { m_key
.string
= s
; }
413 void SetKeyInteger(long i
) { m_key
.integer
= i
; }
415 #ifdef wxLIST_COMPATIBILITY
416 // compatibility methods, use Get* instead.
417 wxDEPRECATED( wxNode
*Next() const );
418 wxDEPRECATED( wxNode
*Previous() const );
419 wxDEPRECATED( wxObject
*Data() const );
420 #endif // wxLIST_COMPATIBILITY
423 // all these are going to be "overloaded" in the derived classes
424 wxNodeBase
*GetNext() const { return m_next
; }
425 wxNodeBase
*GetPrevious() const { return m_previous
; }
427 void *GetData() const { return m_data
; }
428 void SetData(void *data
) { m_data
= data
; }
430 // get 0-based index of this node within the list or wxNOT_FOUND
433 virtual void DeleteData() { }
435 // for wxList::iterator
436 void** GetDataPtr() const { return &(((wxNodeBase
*)this)->m_data
); }
438 // optional key stuff
439 wxListKeyValue m_key
;
441 void *m_data
; // user data
442 wxNodeBase
*m_next
, // next and previous nodes in the list
445 wxListBase
*m_list
; // list we belong to
447 DECLARE_NO_COPY_CLASS(wxNodeBase
)
450 // -----------------------------------------------------------------------------
451 // a double-linked list class
452 // -----------------------------------------------------------------------------
454 class WXDLLIMPEXP_BASE wxList
;
456 class WXDLLIMPEXP_BASE wxListBase
: public wxObject
458 friend class WXDLLIMPEXP_BASE wxNodeBase
; // should be able to call DetachNode()
459 friend class wxHashTableBase
; // should be able to call untyped Find()
462 // default ctor & dtor
463 wxListBase(wxKeyType keyType
= wxKEY_NONE
)
465 virtual ~wxListBase();
468 // count of items in the list
469 size_t GetCount() const { return m_count
; }
471 // return true if this list is empty
472 bool IsEmpty() const { return m_count
== 0; }
479 // instruct it to destroy user data when deleting nodes
480 void DeleteContents(bool destroy
) { m_destroy
= destroy
; }
482 // query if to delete
483 bool GetDeleteContents() const
484 { return m_destroy
; }
487 wxKeyType
GetKeyType() const
488 { return m_keyType
; }
490 // set the keytype (required by the serial code)
491 void SetKeyType(wxKeyType keyType
)
492 { wxASSERT( m_count
==0 ); m_keyType
= keyType
; }
494 #ifdef wxLIST_COMPATIBILITY
495 // compatibility methods from old wxList
496 wxDEPRECATED( int Number() const ); // use GetCount instead.
497 wxDEPRECATED( wxNode
*First() const ); // use GetFirst
498 wxDEPRECATED( wxNode
*Last() const ); // use GetLast
499 wxDEPRECATED( wxNode
*Nth(size_t n
) const ); // use Item
501 // kludge for typesafe list migration in core classes.
502 wxDEPRECATED( operator wxList
&() const );
503 #endif // wxLIST_COMPATIBILITY
507 // all methods here are "overloaded" in derived classes to provide compile
508 // time type checking
510 // create a node for the list of this type
511 virtual wxNodeBase
*CreateNode(wxNodeBase
*prev
, wxNodeBase
*next
,
513 const wxListKey
& key
= wxDefaultListKey
) = 0;
515 // Can't access these from derived classes otherwise (bug in Salford C++?)
522 wxListBase(size_t count
, void *elements
[]);
523 // from a sequence of objects
524 wxListBase(void *object
, ... /* terminate with NULL */);
527 void Assign(const wxListBase
& list
)
528 { Clear(); DoCopy(list
); }
530 // get list head/tail
531 wxNodeBase
*GetFirst() const { return m_nodeFirst
; }
532 wxNodeBase
*GetLast() const { return m_nodeLast
; }
534 // by (0-based) index
535 wxNodeBase
*Item(size_t index
) const;
537 // get the list item's data
538 void *operator[](size_t n
) const
540 wxNodeBase
*node
= Item(n
);
542 return node
? node
->GetData() : (wxNodeBase
*)NULL
;
546 // append to end of list
547 wxNodeBase
*Prepend(void *object
)
548 { return (wxNodeBase
*)wxListBase::Insert(object
); }
549 // append to beginning of list
550 wxNodeBase
*Append(void *object
);
551 // insert a new item at the beginning of the list
552 wxNodeBase
*Insert(void *object
) { return Insert( (wxNodeBase
*)NULL
, object
); }
553 // insert a new item at the given position
554 wxNodeBase
*Insert(size_t pos
, void *object
)
555 { return pos
== GetCount() ? Append(object
)
556 : Insert(Item(pos
), object
); }
557 // insert before given node or at front of list if prev == NULL
558 wxNodeBase
*Insert(wxNodeBase
*prev
, void *object
);
561 wxNodeBase
*Append(long key
, void *object
);
562 wxNodeBase
*Append(const wxChar
*key
, void *object
);
564 // removes node from the list but doesn't delete it (returns pointer
565 // to the node or NULL if it wasn't found in the list)
566 wxNodeBase
*DetachNode(wxNodeBase
*node
);
567 // delete element from list, returns false if node not found
568 bool DeleteNode(wxNodeBase
*node
);
569 // finds object pointer and deletes node (and object if DeleteContents
570 // is on), returns false if object not found
571 bool DeleteObject(void *object
);
573 // search (all return NULL if item not found)
575 wxNodeBase
*Find(const void *object
) const;
578 wxNodeBase
*Find(const wxListKey
& key
) const;
580 // get 0-based index of object or wxNOT_FOUND
581 int IndexOf( void *object
) const;
583 // this function allows the sorting of arbitrary lists by giving
584 // a function to compare two list elements. The list is sorted in place.
585 void Sort(const wxSortCompareFunction compfunc
);
587 // functions for iterating over the list
588 void *FirstThat(wxListIterateFunction func
);
589 void ForEach(wxListIterateFunction func
);
590 void *LastThat(wxListIterateFunction func
);
592 // for STL interface, "last" points to one after the last node
593 // of the controlled sequence (NULL for the end of the list)
595 void DeleteNodes(wxNodeBase
* first
, wxNodeBase
* last
);
598 // common part of all ctors
599 void Init(wxKeyType keyType
= wxKEY_NONE
);
602 // common part of copy ctor and assignment operator
603 void DoCopy(const wxListBase
& list
);
604 // common part of all Append()s
605 wxNodeBase
*AppendCommon(wxNodeBase
*node
);
606 // free node's data and node itself
607 void DoDeleteNode(wxNodeBase
*node
);
609 size_t m_count
; // number of elements in the list
610 bool m_destroy
; // destroy user data when deleting list items?
611 wxNodeBase
*m_nodeFirst
, // pointers to the head and tail of the list
614 wxKeyType m_keyType
; // type of our keys (may be wxKEY_NONE)
617 // -----------------------------------------------------------------------------
618 // macros for definition of "template" list type
619 // -----------------------------------------------------------------------------
621 // and now some heavy magic...
623 // declare a list type named 'name' and containing elements of type 'T *'
624 // (as a by product of macro expansion you also get wx##name##Node
625 // wxNode-derived type)
627 // implementation details:
628 // 1. We define _WX_LIST_ITEM_TYPE_##name typedef to save in it the item type
629 // for the list of given type - this allows us to pass only the list name
630 // to WX_DEFINE_LIST() even if it needs both the name and the type
632 // 2. We redefine all non-type-safe wxList functions with type-safe versions
633 // which don't take any space (everything is inline), but bring compile
634 // time error checking.
636 // 3. The macro which is usually used (WX_DECLARE_LIST) is defined in terms of
637 // a more generic WX_DECLARE_LIST_2 macro which, in turn, uses the most
638 // generic WX_DECLARE_LIST_3 one. The last macro adds a sometimes
639 // interesting capability to store polymorphic objects in the list and is
640 // particularly useful with, for example, "wxWindow *" list where the
641 // wxWindowBase pointers are put into the list, but wxWindow pointers are
642 // retrieved from it.
644 // 4. final hack is that WX_DECLARE_LIST_3 is defined in terms of
645 // WX_DECLARE_LIST_4 to allow defining classes without operator->() as
646 // it results in compiler warnings when this operator doesn't make sense
647 // (i.e. stored elements are not pointers)
649 // common part of WX_DECLARE_LIST_3 and WX_DECLARE_LIST_PTR_3
650 #define WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, ptrop) \
651 typedef int (*wxSortFuncFor_##name)(const T **, const T **); \
653 classexp nodetype : public wxNodeBase \
656 nodetype(wxListBase *list = (wxListBase *)NULL, \
657 nodetype *previous = (nodetype *)NULL, \
658 nodetype *next = (nodetype *)NULL, \
659 T *data = (T *)NULL, \
660 const wxListKey& key = wxDefaultListKey) \
661 : wxNodeBase(list, previous, next, data, key) { } \
663 nodetype *GetNext() const \
664 { return (nodetype *)wxNodeBase::GetNext(); } \
665 nodetype *GetPrevious() const \
666 { return (nodetype *)wxNodeBase::GetPrevious(); } \
669 { return (T *)wxNodeBase::GetData(); } \
670 void SetData(T *data) \
671 { wxNodeBase::SetData(data); } \
674 virtual void DeleteData(); \
676 DECLARE_NO_COPY_CLASS(nodetype) \
679 classexp name : public wxListBase \
682 typedef nodetype Node; \
683 class compatibility_iterator \
686 compatibility_iterator(Node *ptr = NULL) : m_ptr(ptr) { } \
688 Node *operator->() const { return m_ptr; } \
689 operator Node *() const { return m_ptr; } \
695 name(wxKeyType keyType = wxKEY_NONE) : wxListBase(keyType) \
697 name(const name& list) : wxListBase(list.GetKeyType()) \
699 name(size_t count, T *elements[]) \
700 : wxListBase(count, (void **)elements) { } \
702 name& operator=(const name& list) \
703 { Assign(list); return *this; } \
705 nodetype *GetFirst() const \
706 { return (nodetype *)wxListBase::GetFirst(); } \
707 nodetype *GetLast() const \
708 { return (nodetype *)wxListBase::GetLast(); } \
710 nodetype *Item(size_t index) const \
711 { return (nodetype *)wxListBase::Item(index); } \
713 T *operator[](size_t index) const \
715 nodetype *node = Item(index); \
716 return node ? (T*)(node->GetData()) : (T*)NULL; \
719 nodetype *Append(Tbase *object) \
720 { return (nodetype *)wxListBase::Append(object); } \
721 nodetype *Insert(Tbase *object) \
722 { return (nodetype *)Insert((nodetype*)NULL, object); } \
723 nodetype *Insert(size_t pos, Tbase *object) \
724 { return (nodetype *)wxListBase::Insert(pos, object); } \
725 nodetype *Insert(nodetype *prev, Tbase *object) \
726 { return (nodetype *)wxListBase::Insert(prev, object); } \
728 nodetype *Append(long key, void *object) \
729 { return (nodetype *)wxListBase::Append(key, object); } \
730 nodetype *Append(const wxChar *key, void *object) \
731 { return (nodetype *)wxListBase::Append(key, object); } \
733 nodetype *DetachNode(nodetype *node) \
734 { return (nodetype *)wxListBase::DetachNode(node); } \
735 bool DeleteNode(nodetype *node) \
736 { return wxListBase::DeleteNode(node); } \
737 bool DeleteObject(Tbase *object) \
738 { return wxListBase::DeleteObject(object); } \
739 void Erase(compatibility_iterator it) \
740 { DeleteNode(it); } \
742 nodetype *Find(const Tbase *object) const \
743 { return (nodetype *)wxListBase::Find(object); } \
745 virtual nodetype *Find(const wxListKey& key) const \
746 { return (nodetype *)wxListBase::Find(key); } \
748 int IndexOf(Tbase *object) const \
749 { return wxListBase::IndexOf(object); } \
751 void Sort(wxSortCompareFunction func) \
752 { wxListBase::Sort(func); } \
753 void Sort(wxSortFuncFor_##name func) \
754 { Sort((wxSortCompareFunction)func); } \
757 virtual wxNodeBase *CreateNode(wxNodeBase *prev, wxNodeBase *next, \
759 const wxListKey& key = wxDefaultListKey) \
761 return new nodetype(this, \
762 (nodetype *)prev, (nodetype *)next, \
765 /* STL interface */ \
767 typedef size_t size_type; \
768 typedef int difference_type; \
769 typedef T* value_type; \
770 typedef Tbase* base_value_type; \
771 typedef value_type& reference; \
772 typedef const value_type& const_reference; \
773 typedef base_value_type& base_reference; \
774 typedef const base_value_type& const_base_reference; \
780 typedef nodetype Node; \
781 typedef iterator itor; \
782 typedef T* value_type; \
783 typedef value_type* ptr_type; \
784 typedef value_type& reference; \
789 typedef reference reference_type; \
790 typedef ptr_type pointer_type; \
792 iterator(Node* node, Node* init) : m_node(node), m_init(init) {}\
793 iterator() : m_node(NULL), m_init(NULL) { } \
794 reference_type operator*() const \
795 { return *(pointer_type)m_node->GetDataPtr(); } \
797 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
798 const itor operator++(int) \
799 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
802 m_node = m_node ? m_node->GetPrevious() : m_init; \
805 const itor operator--(int) \
808 m_node = m_node ? m_node->GetPrevious() : m_init; \
811 bool operator!=(const itor& it) const \
812 { return it.m_node != m_node; } \
813 bool operator==(const itor& it) const \
814 { return it.m_node == m_node; } \
816 class const_iterator \
820 typedef nodetype Node; \
821 typedef T* value_type; \
822 typedef const value_type& const_reference; \
823 typedef const_iterator itor; \
824 typedef value_type* ptr_type; \
829 typedef const_reference reference_type; \
830 typedef const ptr_type pointer_type; \
832 const_iterator(Node* node, Node* init) \
833 : m_node(node), m_init(init) { } \
834 const_iterator() : m_node(NULL), m_init(NULL) { } \
835 const_iterator(const iterator& it) \
836 : m_node(it.m_node), m_init(it.m_init) { } \
837 reference_type operator*() const \
838 { return *(pointer_type)m_node->GetDataPtr(); } \
840 itor& operator++() { m_node = m_node->GetNext(); return *this; }\
841 const itor operator++(int) \
842 { itor tmp = *this; m_node = m_node->GetNext(); return tmp; }\
845 m_node = m_node ? m_node->GetPrevious() : m_init; \
848 const itor operator--(int) \
851 m_node = m_node ? m_node->GetPrevious() : m_init; \
854 bool operator!=(const itor& it) const \
855 { return it.m_node != m_node; } \
856 bool operator==(const itor& it) const \
857 { return it.m_node == m_node; } \
859 class reverse_iterator \
863 typedef nodetype Node; \
864 typedef T* value_type; \
865 typedef reverse_iterator itor; \
866 typedef value_type* ptr_type; \
867 typedef value_type& reference; \
872 typedef reference reference_type; \
873 typedef ptr_type pointer_type; \
875 reverse_iterator(Node* node, Node* init) \
876 : m_node(node), m_init(init) { } \
877 reverse_iterator() : m_node(NULL), m_init(NULL) { } \
878 reference_type operator*() const \
879 { return *(pointer_type)m_node->GetDataPtr(); } \
882 { m_node = m_node->GetPrevious(); return *this; } \
883 const itor operator++(int) \
884 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
886 { m_node = m_node ? m_node->GetNext() : m_init; return *this; } \
887 const itor operator--(int) \
890 m_node = m_node ? m_node->GetNext() : m_init; \
893 bool operator!=(const itor& it) const \
894 { return it.m_node != m_node; } \
895 bool operator==(const itor& it) const \
896 { return it.m_node == m_node; } \
898 class const_reverse_iterator \
902 typedef nodetype Node; \
903 typedef T* value_type; \
904 typedef const_reverse_iterator itor; \
905 typedef value_type* ptr_type; \
906 typedef const value_type& const_reference; \
911 typedef const_reference reference_type; \
912 typedef const ptr_type pointer_type; \
914 const_reverse_iterator(Node* node, Node* init) \
915 : m_node(node), m_init(init) { } \
916 const_reverse_iterator() : m_node(NULL), m_init(NULL) { } \
917 const_reverse_iterator(const reverse_iterator& it) \
918 : m_node(it.m_node), m_init(it.m_init) { } \
919 reference_type operator*() const \
920 { return *(pointer_type)m_node->GetDataPtr(); } \
923 { m_node = m_node->GetPrevious(); return *this; } \
924 const itor operator++(int) \
925 { itor tmp = *this; m_node = m_node->GetPrevious(); return tmp; }\
927 { m_node = m_node ? m_node->GetNext() : m_init; return *this;}\
928 const itor operator--(int) \
931 m_node = m_node ? m_node->GetNext() : m_init; \
934 bool operator!=(const itor& it) const \
935 { return it.m_node != m_node; } \
936 bool operator==(const itor& it) const \
937 { return it.m_node == m_node; } \
940 wxEXPLICIT name(size_type n, const_reference v = value_type()) \
942 name(const const_iterator& first, const const_iterator& last) \
943 { assign(first, last); } \
944 iterator begin() { return iterator(GetFirst(), GetLast()); } \
945 const_iterator begin() const \
946 { return const_iterator(GetFirst(), GetLast()); } \
947 iterator end() { return iterator(NULL, GetLast()); } \
948 const_iterator end() const { return const_iterator(NULL, GetLast()); }\
949 reverse_iterator rbegin() \
950 { return reverse_iterator(GetLast(), GetFirst()); } \
951 const_reverse_iterator rbegin() const \
952 { return const_reverse_iterator(GetLast(), GetFirst()); } \
953 reverse_iterator rend() { return reverse_iterator(NULL, GetFirst()); }\
954 const_reverse_iterator rend() const \
955 { return const_reverse_iterator(NULL, GetFirst()); } \
956 void resize(size_type n, value_type v = value_type()) \
963 size_type size() const { return GetCount(); } \
964 size_type max_size() const { return INT_MAX; } \
965 bool empty() const { return IsEmpty(); } \
966 reference front() { return *begin(); } \
967 const_reference front() const { return *begin(); } \
968 reference back() { iterator tmp = end(); return *--tmp; } \
969 const_reference back() const { const_iterator tmp = end(); return *--tmp; }\
970 void push_front(const_reference v = value_type()) \
971 { Insert(GetFirst(), (const_base_reference)v); } \
972 void pop_front() { DeleteNode(GetFirst()); } \
973 void push_back(const_reference v = value_type()) \
974 { Append((const_base_reference)v); } \
975 void pop_back() { DeleteNode(GetLast()); } \
976 void assign(const_iterator first, const const_iterator& last) \
979 for(; first != last; ++first) \
980 Append((const_base_reference)*first); \
982 void assign(size_type n, const_reference v = value_type()) \
985 for(size_type i = 0; i < n; ++i) \
986 Append((const_base_reference)v); \
988 iterator insert(const iterator& it, const_reference v = value_type())\
990 Insert(it.m_node, (const_base_reference)v); \
991 return iterator(it.m_node->GetPrevious(), GetLast()); \
993 void insert(const iterator& it, size_type n, const_reference v = value_type())\
995 for(size_type i = 0; i < n; ++i) \
996 Insert(it.m_node, (const_base_reference)v); \
998 void insert(const iterator& it, const_iterator first, const const_iterator& last)\
1000 for(; first != last; ++first) \
1001 Insert(it.m_node, (const_base_reference)*first); \
1003 iterator erase(const iterator& it) \
1005 iterator next = iterator(it.m_node->GetNext(), GetLast()); \
1006 DeleteNode(it.m_node); return next; \
1008 iterator erase(const iterator& first, const iterator& last) \
1010 iterator next = last; ++next; \
1011 DeleteNodes(first.m_node, last.m_node); \
1014 void clear() { Clear(); } \
1015 void splice(const iterator& it, name& l, const iterator& first, const iterator& last)\
1016 { insert(it, first, last); l.erase(first, last); } \
1017 void splice(const iterator& it, name& l) \
1018 { splice(it, l, l.begin(), l.end() ); } \
1019 void splice(const iterator& it, name& l, const iterator& first) \
1021 iterator tmp = first; ++tmp; \
1022 if(it == first || it == tmp) return; \
1023 insert(it, *first); \
1026 void remove(const_reference v) \
1027 { DeleteObject((const_base_reference)v); } \
1030 /* void swap(name& l) \
1032 { size_t t = m_count; m_count = l.m_count; l.m_count = t; } \
1033 { bool t = m_destroy; m_destroy = l.m_destroy; l.m_destroy = t; }\
1034 { wxNodeBase* t = m_nodeFirst; m_nodeFirst = l.m_nodeFirst; l.m_nodeFirst = t; }\
1035 { wxNodeBase* t = m_nodeLast; m_nodeLast = l.m_nodeLast; l.m_nodeLast = t; }\
1036 { wxKeyType t = m_keyType; m_keyType = l.m_keyType; l.m_keyType = t; }\
1040 #define WX_LIST_PTROP \
1041 pointer_type operator->() const \
1042 { return (pointer_type)m_node->GetDataPtr(); }
1043 #define WX_LIST_PTROP_NONE
1045 #define WX_DECLARE_LIST_3(T, Tbase, name, nodetype, classexp) \
1046 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP_NONE)
1047 #define WX_DECLARE_LIST_PTR_3(T, Tbase, name, nodetype, classexp) \
1048 WX_DECLARE_LIST_4(T, Tbase, name, nodetype, classexp, WX_LIST_PTROP)
1050 #define WX_DECLARE_LIST_2(elementtype, listname, nodename, classexp) \
1051 WX_DECLARE_LIST_3(elementtype, elementtype, listname, nodename, classexp)
1052 #define WX_DECLARE_LIST_PTR_2(elementtype, listname, nodename, classexp) \
1053 WX_DECLARE_LIST_PTR_3(elementtype, elementtype, listname, nodename, classexp)
1055 #define WX_DECLARE_LIST(elementtype, listname) \
1056 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1057 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class)
1058 #define WX_DECLARE_LIST_PTR(elementtype, listname) \
1059 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1060 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class)
1062 #define WX_DECLARE_LIST_WITH_DECL(elementtype, listname, decl) \
1063 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1064 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, decl)
1066 #define WX_DECLARE_EXPORTED_LIST(elementtype, listname) \
1067 WX_DECLARE_LIST_WITH_DECL(elementtype, listname, class WXDLLEXPORT)
1069 #define WX_DECLARE_EXPORTED_LIST_PTR(elementtype, listname) \
1070 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1071 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class WXDLLEXPORT)
1073 #define WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) \
1074 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1075 WX_DECLARE_LIST_2(elementtype, listname, wx##listname##Node, class usergoo)
1076 #define WX_DECLARE_USER_EXPORTED_LIST_PTR(elementtype, listname, usergoo) \
1077 typedef elementtype _WX_LIST_ITEM_TYPE_##listname; \
1078 WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class usergoo)
1080 // this macro must be inserted in your program after
1081 // #include "wx/listimpl.cpp"
1082 #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!"
1084 #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1085 #define WX_DEFINE_USER_EXPORTED_LIST(name) WX_DEFINE_LIST(name)
1087 #endif // !wxUSE_STL
1089 // ============================================================================
1090 // now we can define classes 100% compatible with the old ones
1091 // ============================================================================
1093 // ----------------------------------------------------------------------------
1094 // commonly used list classes
1095 // ----------------------------------------------------------------------------
1097 #if defined(wxLIST_COMPATIBILITY)
1099 // inline compatibility functions
1103 // ----------------------------------------------------------------------------
1104 // wxNodeBase deprecated methods
1105 // ----------------------------------------------------------------------------
1107 inline wxNode
*wxNodeBase::Next() const { return (wxNode
*)GetNext(); }
1108 inline wxNode
*wxNodeBase::Previous() const { return (wxNode
*)GetPrevious(); }
1109 inline wxObject
*wxNodeBase::Data() const { return (wxObject
*)GetData(); }
1111 // ----------------------------------------------------------------------------
1112 // wxListBase deprecated methods
1113 // ----------------------------------------------------------------------------
1115 inline int wxListBase::Number() const { return (int)GetCount(); }
1116 inline wxNode
*wxListBase::First() const { return (wxNode
*)GetFirst(); }
1117 inline wxNode
*wxListBase::Last() const { return (wxNode
*)GetLast(); }
1118 inline wxNode
*wxListBase::Nth(size_t n
) const { return (wxNode
*)Item(n
); }
1119 inline wxListBase::operator wxList
&() const { return *(wxList
*)this; }
1123 // define this to make a lot of noise about use of the old wxList classes.
1124 //#define wxWARN_COMPAT_LIST_USE
1126 // ----------------------------------------------------------------------------
1127 // wxList compatibility class: in fact, it's a list of wxObjects
1128 // ----------------------------------------------------------------------------
1130 WX_DECLARE_LIST_2(wxObject
, wxObjectList
, wxObjectListNode
,
1131 class WXDLLIMPEXP_BASE
);
1133 class WXDLLIMPEXP_BASE wxList
: public wxObjectList
1136 #if defined(wxWARN_COMPAT_LIST_USE) && !wxUSE_STL
1138 wxDEPRECATED( wxList(int key_type
) );
1140 wxList(int key_type
= wxKEY_NONE
);
1143 // this destructor is required for Darwin
1147 wxList
& operator=(const wxList
& list
)
1148 { (void) wxListBase::operator=(list
); return *this; }
1150 // compatibility methods
1151 void Sort(wxSortCompareFunction compfunc
) { wxListBase::Sort(compfunc
); }
1156 wxNode
*Member(wxObject
*object
) const { return (wxNode
*)Find(object
); }
1161 DECLARE_DYNAMIC_CLASS(wxList
)
1167 // -----------------------------------------------------------------------------
1168 // wxStringList class for compatibility with the old code
1169 // -----------------------------------------------------------------------------
1170 WX_DECLARE_LIST_2(wxChar
, wxStringListBase
, wxStringListNode
, class WXDLLIMPEXP_BASE
);
1172 class WXDLLIMPEXP_BASE wxStringList
: public wxStringListBase
1177 #ifdef wxWARN_COMPAT_LIST_USE
1179 wxDEPRECATED( wxStringList(const wxChar
*first
...) );
1182 wxStringList(const wxChar
*first
...);
1185 // copying the string list: the strings are copied, too (extremely
1187 wxStringList(const wxStringList
& other
) : wxStringListBase() { DeleteContents(true); DoCopy(other
); }
1188 wxStringList
& operator=(const wxStringList
& other
)
1189 { Clear(); DoCopy(other
); return *this; }
1192 // makes a copy of the string
1193 wxNode
*Add(const wxChar
*s
);
1195 // Append to beginning of list
1196 wxNode
*Prepend(const wxChar
*s
);
1198 bool Delete(const wxChar
*s
);
1200 wxChar
**ListToArray(bool new_copies
= false) const;
1201 bool Member(const wxChar
*s
) const;
1207 void DoCopy(const wxStringList
&); // common part of copy ctor and operator=
1209 DECLARE_DYNAMIC_CLASS(wxStringList
)
1212 #else // if wxUSE_STL
1214 WX_DECLARE_LIST_XO(wxString
, wxStringListBase
, class WXDLLIMPEXP_BASE
);
1216 class WXDLLIMPEXP_BASE wxStringList
: public wxStringListBase
1219 compatibility_iterator
Append(wxChar
* s
)
1220 { wxString tmp
= s
; delete[] s
; return wxStringListBase::Append(tmp
); }
1221 compatibility_iterator
Insert(wxChar
* s
)
1222 { wxString tmp
= s
; delete[] s
; return wxStringListBase::Insert(tmp
); }
1223 compatibility_iterator
Insert(size_t pos
, wxChar
* s
)
1227 return wxStringListBase::Insert(pos
, tmp
);
1229 compatibility_iterator
Add(const wxChar
* s
)
1230 { push_back(s
); return GetLast(); }
1231 compatibility_iterator
Prepend(const wxChar
* s
)
1232 { push_front(s
); return GetFirst(); }
1237 #endif // wxLIST_COMPATIBILITY
1239 // delete all list elements
1241 // NB: the class declaration of the list elements must be visible from the
1242 // place where you use this macro, otherwise the proper destructor may not
1243 // be called (a decent compiler should give a warning about it, but don't
1245 #define WX_CLEAR_LIST(type, list) \
1247 type::iterator it, en; \
1248 for( it = (list).begin(), en = (list).end(); it != en; ++it ) \
1253 #endif // _WX_LISTH__