]> git.saurik.com Git - wxWidgets.git/blame - src/common/windowid.cpp
Merge in from trunk r64802 - r68625
[wxWidgets.git] / src / common / windowid.cpp
CommitLineData
cf2810aa
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/common/windowid.cpp
3// Purpose: wxWindowID class - a class for managing window ids
4// Author: Brian Vanderburg II
5// Created: 2007-09-21
6// RCS-ID: $Id$
7// Copyright: (c) 2007 Brian Vanderburg II
8// Licence: wxWindows licence
9///////////////////////////////////////////////////////////////////////////////
10
11// ----------------------------------------------------------------------------
12// Needed headers
13// ----------------------------------------------------------------------------
14#include "wx/wxprec.h"
15
16#ifdef __BORLANDC__
17 #pragma hdrstop
18#endif
19
20#ifndef WX_PRECOMP
21 #include "wx/log.h"
22 #include "wx/intl.h"
23#endif //WX_PRECOMP
24
25// Not needed, included in defs.h
26// #include "wx/windowid.h"
27
9a83f860 28#define wxTRACE_WINDOWID wxT("windowid")
cf2810aa
VZ
29
30namespace
31{
32
33#if wxUSE_AUTOID_MANAGEMENT
34
35
36// initially no ids are in use and we allocate them consecutively, but after we
37// exhaust the entire range, we wrap around and reuse the ids freed in the
38// meanwhile
39static const wxUint8 ID_FREE = 0;
40static const wxUint8 ID_STARTCOUNT = 1;
41static const wxUint8 ID_MAXCOUNT = 254;
42static const wxUint8 ID_RESERVED = 255;
43
44wxUint8 gs_autoIdsRefCount[wxID_AUTO_HIGHEST - wxID_AUTO_LOWEST + 1] = { 0 };
45
46// this is an optimization used until we wrap around wxID_AUTO_HIGHEST: if this
47// value is < wxID_AUTO_HIGHEST we know that we haven't wrapped yet and so can
48// allocate the ids simply by incrementing it
49wxWindowID gs_nextAutoId = wxID_AUTO_LOWEST;
50
51// Reserve an ID
e3b2f973 52void ReserveIdRefCount(wxWindowID winid)
cf2810aa 53{
e3b2f973 54 wxCHECK_RET(winid >= wxID_AUTO_LOWEST && winid <= wxID_AUTO_HIGHEST,
cf2810aa
VZ
55 wxT("invalid id range"));
56
e3b2f973 57 winid -= wxID_AUTO_LOWEST;
cf2810aa 58
e3b2f973 59 wxCHECK_RET(gs_autoIdsRefCount[winid] == ID_FREE,
cf2810aa 60 wxT("id already in use or already reserved"));
e3b2f973 61 gs_autoIdsRefCount[winid] = ID_RESERVED;
cf2810aa
VZ
62}
63
64// Unreserve and id
e3b2f973 65void UnreserveIdRefCount(wxWindowID winid)
cf2810aa 66{
e3b2f973 67 wxCHECK_RET(winid >= wxID_AUTO_LOWEST && winid <= wxID_AUTO_HIGHEST,
cf2810aa
VZ
68 wxT("invalid id range"));
69
e3b2f973 70 winid -= wxID_AUTO_LOWEST;
cf2810aa 71
e3b2f973 72 wxCHECK_RET(gs_autoIdsRefCount[winid] == ID_RESERVED,
cf2810aa 73 wxT("id already in use or not reserved"));
e3b2f973 74 gs_autoIdsRefCount[winid] = ID_FREE;
cf2810aa
VZ
75}
76
77// Get the usage count of an id
e3b2f973 78int GetIdRefCount(wxWindowID winid)
cf2810aa 79{
e3b2f973 80 wxCHECK_MSG(winid >= wxID_AUTO_LOWEST && winid <= wxID_AUTO_HIGHEST, 0,
cf2810aa
VZ
81 wxT("invalid id range"));
82
e3b2f973
SC
83 winid -= wxID_AUTO_LOWEST;
84 return gs_autoIdsRefCount[winid];
cf2810aa
VZ
85}
86
87// Increase the count for an id
e3b2f973 88void IncIdRefCount(wxWindowID winid)
cf2810aa 89{
e3b2f973 90 wxCHECK_RET(winid >= wxID_AUTO_LOWEST && winid <= wxID_AUTO_HIGHEST,
cf2810aa
VZ
91 wxT("invalid id range"));
92
e3b2f973 93 winid -= wxID_AUTO_LOWEST;
cf2810aa 94
e3b2f973
SC
95 wxCHECK_RET(gs_autoIdsRefCount[winid] != ID_MAXCOUNT, wxT("id count at max"));
96 wxCHECK_RET(gs_autoIdsRefCount[winid] != ID_FREE, wxT("id should first be reserved"));
cf2810aa 97
e3b2f973
SC
98 if(gs_autoIdsRefCount[winid] == ID_RESERVED)
99 gs_autoIdsRefCount[winid] = ID_STARTCOUNT;
cf2810aa 100 else
e3b2f973 101 gs_autoIdsRefCount[winid]++;
cf2810aa
VZ
102
103 wxLogTrace(wxTRACE_WINDOWID, wxT("Increasing ref count of ID %d to %d"),
e3b2f973 104 winid + wxID_AUTO_LOWEST, gs_autoIdsRefCount[winid]);
cf2810aa
VZ
105}
106
107// Decrease the count for an id
e3b2f973 108void DecIdRefCount(wxWindowID winid)
cf2810aa 109{
e3b2f973 110 wxCHECK_RET(winid >= wxID_AUTO_LOWEST && winid <= wxID_AUTO_HIGHEST,
cf2810aa
VZ
111 wxT("invalid id range"));
112
e3b2f973 113 winid -= wxID_AUTO_LOWEST;
cf2810aa 114
e3b2f973 115 wxCHECK_RET(gs_autoIdsRefCount[winid] != ID_FREE, wxT("id count already 0"));
cf2810aa
VZ
116
117 // DecIdRefCount is only called on an ID that has been IncIdRefCount'ed'
118 // so it should never be reserved, but test anyway
e3b2f973 119 if(gs_autoIdsRefCount[winid] == ID_RESERVED)
cf2810aa 120 {
e54266ad 121 wxFAIL_MSG(wxT("reserve id being decreased"));
e3b2f973 122 gs_autoIdsRefCount[winid] = ID_FREE;
cf2810aa
VZ
123 }
124 else
e3b2f973 125 gs_autoIdsRefCount[winid]--;
cf2810aa
VZ
126
127 wxLogTrace(wxTRACE_WINDOWID, wxT("Decreasing ref count of ID %d to %d"),
e3b2f973 128 winid + wxID_AUTO_LOWEST, gs_autoIdsRefCount[winid]);
cf2810aa
VZ
129}
130
131#else // wxUSE_AUTOID_MANAGEMENT
132
133static wxWindowID gs_nextAutoId = wxID_AUTO_HIGHEST;
134
135#endif
136
137} // anonymous namespace
138
139
140#if wxUSE_AUTOID_MANAGEMENT
141
e3b2f973 142void wxWindowIDRef::Assign(wxWindowID winid)
cf2810aa 143{
e3b2f973 144 if ( winid != m_id )
cf2810aa
VZ
145 {
146 // decrease count if it is in the managed range
147 if ( m_id >= wxID_AUTO_LOWEST && m_id <= wxID_AUTO_HIGHEST )
148 DecIdRefCount(m_id);
149
e3b2f973 150 m_id = winid;
cf2810aa
VZ
151
152 // increase count if it is in the managed range
153 if ( m_id >= wxID_AUTO_LOWEST && m_id <= wxID_AUTO_HIGHEST )
154 IncIdRefCount(m_id);
155 }
156}
157
158#endif // wxUSE_AUTOID_MANAGEMENT
159
160
161
162wxWindowID wxIdManager::ReserveId(int count)
163{
164 wxASSERT_MSG(count > 0, wxT("can't allocate less than 1 id"));
165
166
167#if wxUSE_AUTOID_MANAGEMENT
168 if ( gs_nextAutoId + count - 1 <= wxID_AUTO_HIGHEST )
169 {
e3b2f973 170 wxWindowID winid = gs_nextAutoId;
cf2810aa
VZ
171
172 while(count--)
173 {
174 ReserveIdRefCount(gs_nextAutoId++);
175 }
176
e3b2f973 177 return winid;
cf2810aa
VZ
178 }
179 else
180 {
181 int found = 0;
182
e3b2f973 183 for(wxWindowID winid = wxID_AUTO_LOWEST; winid <= wxID_AUTO_HIGHEST; winid++)
cf2810aa 184 {
e3b2f973 185 if(GetIdRefCount(winid) == 0)
cf2810aa
VZ
186 {
187 found++;
188 if(found == count)
189 {
190 // Imagine this: 100 free IDs left. Then NewId(50) takes 50
191 // so 50 left. Then, the 25 before that last 50 are freed, but
192 // gs_nextAutoId does not decrement and stays where it is at
193 // with 50 free. Then NewId(75) gets called, and since there
194 // are only 50 left according to gs_nextAutoId, it does a
195 // search and finds the 75 at the end. Then NewId(10) gets
196 // called, and accorind to gs_nextAutoId, their are still
197 // 50 at the end so it returns them without testing the ref
198 // To fix this, the next ID is also updated here as needed
e3b2f973
SC
199 if(winid >= gs_nextAutoId)
200 gs_nextAutoId = winid + 1;
cf2810aa
VZ
201
202 while(count--)
e3b2f973 203 ReserveIdRefCount(winid--);
cf2810aa 204
e3b2f973 205 return winid + 1;
cf2810aa
VZ
206 }
207 }
208 else
209 {
210 found = 0;
211 }
212 }
213 }
214
34a083c9 215 wxLogError(_("Out of window IDs. Recommend shutting down application."));
cf2810aa
VZ
216 return wxID_NONE;
217#else // !wxUSE_AUTOID_MANAGEMENT
218 // Make sure enough in the range
e3b2f973 219 wxWindowID winid;
cf2810aa 220
e3b2f973 221 winid = gs_nextAutoId - count + 1;
cf2810aa 222
e3b2f973 223 if ( winid >= wxID_AUTO_LOWEST && winid <= wxID_AUTO_HIGHEST )
cf2810aa
VZ
224 {
225 // There is enough, but it may be time to wrap
e3b2f973 226 if(winid == wxID_AUTO_LOWEST)
cf2810aa
VZ
227 gs_nextAutoId = wxID_AUTO_HIGHEST;
228 else
e3b2f973 229 gs_nextAutoId = winid - 1;
cf2810aa 230
e3b2f973 231 return winid;
cf2810aa
VZ
232 }
233 else
234 {
235 // There is not enough at the low end of the range or
236 // count was big enough to wrap around to the positive
237 // Surely 'count' is not so big to take up much of the range
238 gs_nextAutoId = wxID_AUTO_HIGHEST - count;
239 return gs_nextAutoId + 1;
240 }
241#endif // wxUSE_AUTOID_MANAGEMENT/!wxUSE_AUTOID_MANAGEMENT
242}
243
e3b2f973 244void wxIdManager::UnreserveId(wxWindowID winid, int count)
cf2810aa
VZ
245{
246 wxASSERT_MSG(count > 0, wxT("can't unreserve less than 1 id"));
247
248#if wxUSE_AUTOID_MANAGEMENT
249 while (count--)
e3b2f973 250 UnreserveIdRefCount(winid++);
cf2810aa 251#else
e3b2f973 252 wxUnusedVar(winid);
cf2810aa
VZ
253 wxUnusedVar(count);
254#endif
255}
256