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