]> git.saurik.com Git - wxWidgets.git/blame - src/generic/selstore.cpp
Ticket #1032 wxVariant::operator==(wxVariant& variant) has bad bug
[wxWidgets.git] / src / generic / selstore.cpp
CommitLineData
c71d3313
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: generic/selstore.cpp
3// Purpose: wxSelectionStore implementation
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 08.06.03 (extracted from src/generic/listctrl.cpp)
7// RCS-ID: $Id$
8// Copyright: (c) 2000-2003 Vadim Zeitlin <vadim@wxwindows.org>
65571936 9// Licence: wxWindows licence
c71d3313
VZ
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
14b6653c
VZ
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
c71d3313
VZ
26#include "wx/selstore.h"
27
28// ============================================================================
29// wxSelectionStore
30// ============================================================================
31
32// ----------------------------------------------------------------------------
33// tests
34// ----------------------------------------------------------------------------
35
4cfcb00f 36bool wxSelectionStore::IsSelected(unsigned item) const
c71d3313
VZ
37{
38 bool isSel = m_itemsSel.Index(item) != wxNOT_FOUND;
39
40 // if the default state is to be selected, being in m_itemsSel means that
41 // the item is not selected, so we have to inverse the logic
42 return m_defaultState ? !isSel : isSel;
43}
44
45// ----------------------------------------------------------------------------
46// Select*()
47// ----------------------------------------------------------------------------
48
4cfcb00f 49bool wxSelectionStore::SelectItem(unsigned item, bool select)
c71d3313
VZ
50{
51 // search for the item ourselves as like this we get the index where to
52 // insert it later if needed, so we do only one search in the array instead
53 // of two (adding item to a sorted array requires a search)
54 size_t index = m_itemsSel.IndexForInsert(item);
55 bool isSel = index < m_itemsSel.GetCount() && m_itemsSel[index] == item;
56
57 if ( select != m_defaultState )
58 {
59 if ( !isSel )
60 {
61 m_itemsSel.AddAt(item, index);
62
ca65c044 63 return true;
c71d3313
VZ
64 }
65 }
66 else // reset to default state
67 {
68 if ( isSel )
69 {
70 m_itemsSel.RemoveAt(index);
ca65c044 71 return true;
c71d3313
VZ
72 }
73 }
74
ca65c044 75 return false;
c71d3313
VZ
76}
77
4cfcb00f 78bool wxSelectionStore::SelectRange(unsigned itemFrom, unsigned itemTo,
c71d3313
VZ
79 bool select,
80 wxArrayInt *itemsChanged)
81{
82 // 100 is hardcoded but it shouldn't matter much: the important thing is
83 // that we don't refresh everything when really few (e.g. 1 or 2) items
84 // change state
4cfcb00f 85 static const unsigned MANY_ITEMS = 100;
c71d3313
VZ
86
87 wxASSERT_MSG( itemFrom <= itemTo, _T("should be in order") );
88
89 // are we going to have more [un]selected items than the other ones?
90 if ( itemTo - itemFrom > m_count/2 )
91 {
92 if ( select != m_defaultState )
93 {
94 // the default state now becomes the same as 'select'
95 m_defaultState = select;
96
97 // so all the old selections (which had state select) shouldn't be
98 // selected any more, but all the other ones should
99 wxSelectedIndices selOld = m_itemsSel;
100 m_itemsSel.Empty();
101
102 // TODO: it should be possible to optimize the searches a bit
103 // knowing the possible range
104
4cfcb00f 105 unsigned item;
c71d3313
VZ
106 for ( item = 0; item < itemFrom; item++ )
107 {
108 if ( selOld.Index(item) == wxNOT_FOUND )
109 m_itemsSel.Add(item);
110 }
111
112 for ( item = itemTo + 1; item < m_count; item++ )
113 {
114 if ( selOld.Index(item) == wxNOT_FOUND )
115 m_itemsSel.Add(item);
116 }
117
118 // many items (> half) changed state
119 itemsChanged = NULL;
120 }
121 else // select == m_defaultState
122 {
123 // get the inclusive range of items between itemFrom and itemTo
124 size_t count = m_itemsSel.GetCount(),
125 start = m_itemsSel.IndexForInsert(itemFrom),
126 end = m_itemsSel.IndexForInsert(itemTo);
127
128 if ( start == count || m_itemsSel[start] < itemFrom )
129 {
130 start++;
131 }
132
133 if ( end == count || m_itemsSel[end] > itemTo )
134 {
135 end--;
136 }
137
138 if ( start <= end )
139 {
140 // delete all of them (from end to avoid changing indices)
141 for ( int i = end; i >= (int)start; i-- )
142 {
143 if ( itemsChanged )
144 {
145 if ( itemsChanged->GetCount() > MANY_ITEMS )
146 {
147 // stop counting (see comment below)
148 itemsChanged = NULL;
149 }
150 else
151 {
152 itemsChanged->Add(m_itemsSel[i]);
153 }
154 }
155
156 m_itemsSel.RemoveAt(i);
157 }
158 }
159 }
160 }
161 else // "few" items change state
162 {
163 if ( itemsChanged )
164 {
165 itemsChanged->Empty();
166 }
167
168 // just add the items to the selection
4cfcb00f 169 for ( unsigned item = itemFrom; item <= itemTo; item++ )
c71d3313
VZ
170 {
171 if ( SelectItem(item, select) && itemsChanged )
172 {
173 itemsChanged->Add(item);
174
175 if ( itemsChanged->GetCount() > MANY_ITEMS )
176 {
177 // stop counting them, we'll just eat gobs of memory
178 // for nothing at all - faster to refresh everything in
179 // this case
180 itemsChanged = NULL;
181 }
182 }
183 }
184 }
185
186 // we set it to NULL if there are many items changing state
187 return itemsChanged != NULL;
188}
189
190// ----------------------------------------------------------------------------
191// callbacks
192// ----------------------------------------------------------------------------
193
4cfcb00f 194void wxSelectionStore::OnItemDelete(unsigned item)
c71d3313
VZ
195{
196 size_t count = m_itemsSel.GetCount(),
197 i = m_itemsSel.IndexForInsert(item);
198
199 if ( i < count && m_itemsSel[i] == item )
200 {
201 // this item itself was in m_itemsSel, remove it from there
202 m_itemsSel.RemoveAt(i);
203
204 count--;
205 }
206
207 // and adjust the index of all which follow it
208 while ( i < count )
209 {
210 // all following elements must be greater than the one we deleted
211 wxASSERT_MSG( m_itemsSel[i] > item, _T("logic error") );
212
213 m_itemsSel[i++]--;
214 }
215}
216
c8f80d27
VZ
217void wxSelectionStore::SetItemCount(unsigned count)
218{
219 // forget about all items whose indices are now invalid if the size
220 // decreased
221 if ( count < m_count )
222 {
223 for ( size_t i = m_itemsSel.GetCount(); i > 0; i-- )
224 {
225 if ( m_itemsSel[i - 1] >= count )
226 m_itemsSel.RemoveAt(i - 1);
227 }
228 }
229
230 // remember the new number of items
231 m_count = count;
232}