This keyword is not expanded by Git which means it's not replaced with the correct revision value in the releases made using git-based scripts and it's confusing to have lines with unexpanded "$Id$" in the released files. As expanding them with Git is not that simple (it could be done with git archive and export-subst attribute) and there are not many benefits in having them in the first place, just remove all these lines. If nothing else, this will make an eventual transition to Git simpler. Closes #14487. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74602 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
301 lines
9.0 KiB
C++
301 lines
9.0 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/common/windowid.cpp
|
|
// Purpose: wxWindowID class - a class for managing window ids
|
|
// Author: Brian Vanderburg II
|
|
// Created: 2007-09-21
|
|
// Copyright: (c) 2007 Brian Vanderburg II
|
|
// Licence: wxWindows licence
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Needed headers
|
|
// ----------------------------------------------------------------------------
|
|
#include "wx/wxprec.h"
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/log.h"
|
|
#include "wx/intl.h"
|
|
#endif //WX_PRECOMP
|
|
|
|
#include "wx/hashmap.h"
|
|
|
|
// Not needed, included in defs.h
|
|
// #include "wx/windowid.h"
|
|
|
|
#define wxTRACE_WINDOWID wxT("windowid")
|
|
|
|
namespace
|
|
{
|
|
|
|
#if wxUSE_AUTOID_MANAGEMENT
|
|
|
|
|
|
// initially no ids are in use and we allocate them consecutively, but after we
|
|
// exhaust the entire range, we wrap around and reuse the ids freed in the
|
|
// meanwhile
|
|
static const wxUint8 ID_FREE = 0;
|
|
static const wxUint8 ID_STARTCOUNT = 1;
|
|
static const wxUint8 ID_COUNTTOOLARGE = 254;
|
|
static const wxUint8 ID_RESERVED = 255;
|
|
|
|
// we use a two level count, most IDs will be used less than ID_COUNTTOOLARGE-1
|
|
// thus we store their count directly in this array, however when the same ID
|
|
// is reused a great number of times (more than or equal to ID_COUNTTOOLARGE),
|
|
// the hash map stores the actual count
|
|
wxUint8 gs_autoIdsRefCount[wxID_AUTO_HIGHEST - wxID_AUTO_LOWEST + 1] = { 0 };
|
|
|
|
// NB: this variable is allocated (again) only when an ID gets at least
|
|
// ID_COUNTTOOLARGE refs, and is freed when the latest entry in the map gets
|
|
// freed. The cell storing the count for an ID is freed only when its count
|
|
// gets to zero (not when it goes below ID_COUNTTOOLARGE, so as to avoid
|
|
// degenerate cases)
|
|
wxLongToLongHashMap *gs_autoIdsLargeRefCount = NULL;
|
|
|
|
// this is an optimization used until we wrap around wxID_AUTO_HIGHEST: if this
|
|
// value is < wxID_AUTO_HIGHEST we know that we haven't wrapped yet and so can
|
|
// allocate the ids simply by incrementing it
|
|
wxWindowID gs_nextAutoId = wxID_AUTO_LOWEST;
|
|
|
|
// Reserve an ID
|
|
void ReserveIdRefCount(wxWindowID winid)
|
|
{
|
|
wxCHECK_RET(winid >= wxID_AUTO_LOWEST && winid <= wxID_AUTO_HIGHEST,
|
|
wxT("invalid id range"));
|
|
|
|
winid -= wxID_AUTO_LOWEST;
|
|
|
|
wxCHECK_RET(gs_autoIdsRefCount[winid] == ID_FREE,
|
|
wxT("id already in use or already reserved"));
|
|
gs_autoIdsRefCount[winid] = ID_RESERVED;
|
|
}
|
|
|
|
// Unreserve and id
|
|
void UnreserveIdRefCount(wxWindowID winid)
|
|
{
|
|
wxCHECK_RET(winid >= wxID_AUTO_LOWEST && winid <= wxID_AUTO_HIGHEST,
|
|
wxT("invalid id range"));
|
|
|
|
winid -= wxID_AUTO_LOWEST;
|
|
|
|
wxCHECK_RET(gs_autoIdsRefCount[winid] == ID_RESERVED,
|
|
wxT("id already in use or not reserved"));
|
|
gs_autoIdsRefCount[winid] = ID_FREE;
|
|
}
|
|
|
|
// Get the usage count of an id
|
|
int GetIdRefCount(wxWindowID winid)
|
|
{
|
|
wxCHECK_MSG(winid >= wxID_AUTO_LOWEST && winid <= wxID_AUTO_HIGHEST, 0,
|
|
wxT("invalid id range"));
|
|
|
|
winid -= wxID_AUTO_LOWEST;
|
|
int refCount = gs_autoIdsRefCount[winid];
|
|
if (refCount == ID_COUNTTOOLARGE)
|
|
refCount = (*gs_autoIdsLargeRefCount)[winid];
|
|
return refCount;
|
|
}
|
|
|
|
// Increase the count for an id
|
|
void IncIdRefCount(wxWindowID winid)
|
|
{
|
|
wxCHECK_RET(winid >= wxID_AUTO_LOWEST && winid <= wxID_AUTO_HIGHEST,
|
|
wxT("invalid id range"));
|
|
|
|
winid -= wxID_AUTO_LOWEST;
|
|
|
|
wxCHECK_RET(gs_autoIdsRefCount[winid] != ID_FREE, wxT("id should first be reserved"));
|
|
|
|
if(gs_autoIdsRefCount[winid] == ID_RESERVED)
|
|
{
|
|
gs_autoIdsRefCount[winid] = ID_STARTCOUNT;
|
|
}
|
|
else if (gs_autoIdsRefCount[winid] >= ID_COUNTTOOLARGE-1)
|
|
{
|
|
if (gs_autoIdsRefCount[winid] == ID_COUNTTOOLARGE-1)
|
|
{
|
|
// we need to allocate a cell, and maybe the hash map itself
|
|
if (!gs_autoIdsLargeRefCount)
|
|
gs_autoIdsLargeRefCount = new wxLongToLongHashMap;
|
|
(*gs_autoIdsLargeRefCount)[winid] = ID_COUNTTOOLARGE-1;
|
|
|
|
gs_autoIdsRefCount[winid] = ID_COUNTTOOLARGE;
|
|
}
|
|
++(*gs_autoIdsLargeRefCount)[winid];
|
|
}
|
|
else
|
|
{
|
|
gs_autoIdsRefCount[winid]++;
|
|
}
|
|
|
|
wxLogTrace(wxTRACE_WINDOWID, wxT("Increasing ref count of ID %d to %d"),
|
|
winid + wxID_AUTO_LOWEST, GetIdRefCount(winid + wxID_AUTO_LOWEST));
|
|
}
|
|
|
|
// Decrease the count for an id
|
|
void DecIdRefCount(wxWindowID winid)
|
|
{
|
|
wxCHECK_RET(winid >= wxID_AUTO_LOWEST && winid <= wxID_AUTO_HIGHEST,
|
|
wxT("invalid id range"));
|
|
|
|
winid -= wxID_AUTO_LOWEST;
|
|
|
|
wxCHECK_RET(gs_autoIdsRefCount[winid] != ID_FREE, wxT("id count already 0"));
|
|
|
|
// DecIdRefCount is only called on an ID that has been IncIdRefCount'ed'
|
|
// so it should never be reserved, but test anyway
|
|
if(gs_autoIdsRefCount[winid] == ID_RESERVED)
|
|
{
|
|
wxFAIL_MSG(wxT("reserve id being decreased"));
|
|
gs_autoIdsRefCount[winid] = ID_FREE;
|
|
}
|
|
else if(gs_autoIdsRefCount[winid] == ID_COUNTTOOLARGE)
|
|
{
|
|
long &largeCount = (*gs_autoIdsLargeRefCount)[winid];
|
|
--largeCount;
|
|
if (largeCount == 0)
|
|
{
|
|
gs_autoIdsLargeRefCount->erase (winid);
|
|
gs_autoIdsRefCount[winid] = ID_FREE;
|
|
|
|
if (gs_autoIdsLargeRefCount->empty())
|
|
wxDELETE (gs_autoIdsLargeRefCount);
|
|
}
|
|
}
|
|
else
|
|
gs_autoIdsRefCount[winid]--;
|
|
|
|
wxLogTrace(wxTRACE_WINDOWID, wxT("Decreasing ref count of ID %d to %d"),
|
|
winid + wxID_AUTO_LOWEST, GetIdRefCount(winid + wxID_AUTO_LOWEST));
|
|
}
|
|
|
|
#else // wxUSE_AUTOID_MANAGEMENT
|
|
|
|
static wxWindowID gs_nextAutoId = wxID_AUTO_HIGHEST;
|
|
|
|
#endif
|
|
|
|
} // anonymous namespace
|
|
|
|
|
|
#if wxUSE_AUTOID_MANAGEMENT
|
|
|
|
void wxWindowIDRef::Assign(wxWindowID winid)
|
|
{
|
|
if ( winid != m_id )
|
|
{
|
|
// decrease count if it is in the managed range
|
|
if ( m_id >= wxID_AUTO_LOWEST && m_id <= wxID_AUTO_HIGHEST )
|
|
DecIdRefCount(m_id);
|
|
|
|
m_id = winid;
|
|
|
|
// increase count if it is in the managed range
|
|
if ( m_id >= wxID_AUTO_LOWEST && m_id <= wxID_AUTO_HIGHEST )
|
|
IncIdRefCount(m_id);
|
|
}
|
|
}
|
|
|
|
#endif // wxUSE_AUTOID_MANAGEMENT
|
|
|
|
|
|
|
|
wxWindowID wxIdManager::ReserveId(int count)
|
|
{
|
|
wxASSERT_MSG(count > 0, wxT("can't allocate less than 1 id"));
|
|
|
|
|
|
#if wxUSE_AUTOID_MANAGEMENT
|
|
if ( gs_nextAutoId + count - 1 <= wxID_AUTO_HIGHEST )
|
|
{
|
|
wxWindowID winid = gs_nextAutoId;
|
|
|
|
while(count--)
|
|
{
|
|
ReserveIdRefCount(gs_nextAutoId++);
|
|
}
|
|
|
|
return winid;
|
|
}
|
|
else
|
|
{
|
|
int found = 0;
|
|
|
|
for(wxWindowID winid = wxID_AUTO_LOWEST; winid <= wxID_AUTO_HIGHEST; winid++)
|
|
{
|
|
if(GetIdRefCount(winid) == 0)
|
|
{
|
|
found++;
|
|
if(found == count)
|
|
{
|
|
// Imagine this: 100 free IDs left. Then NewId(50) takes 50
|
|
// so 50 left. Then, the 25 before that last 50 are freed, but
|
|
// gs_nextAutoId does not decrement and stays where it is at
|
|
// with 50 free. Then NewId(75) gets called, and since there
|
|
// are only 50 left according to gs_nextAutoId, it does a
|
|
// search and finds the 75 at the end. Then NewId(10) gets
|
|
// called, and accorind to gs_nextAutoId, their are still
|
|
// 50 at the end so it returns them without testing the ref
|
|
// To fix this, the next ID is also updated here as needed
|
|
if(winid >= gs_nextAutoId)
|
|
gs_nextAutoId = winid + 1;
|
|
|
|
while(count--)
|
|
ReserveIdRefCount(winid--);
|
|
|
|
return winid + 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
found = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
wxLogError(_("Out of window IDs. Recommend shutting down application."));
|
|
return wxID_NONE;
|
|
#else // !wxUSE_AUTOID_MANAGEMENT
|
|
// Make sure enough in the range
|
|
wxWindowID winid;
|
|
|
|
winid = gs_nextAutoId - count + 1;
|
|
|
|
if ( winid >= wxID_AUTO_LOWEST && winid <= wxID_AUTO_HIGHEST )
|
|
{
|
|
// There is enough, but it may be time to wrap
|
|
if(winid == wxID_AUTO_LOWEST)
|
|
gs_nextAutoId = wxID_AUTO_HIGHEST;
|
|
else
|
|
gs_nextAutoId = winid - 1;
|
|
|
|
return winid;
|
|
}
|
|
else
|
|
{
|
|
// There is not enough at the low end of the range or
|
|
// count was big enough to wrap around to the positive
|
|
// Surely 'count' is not so big to take up much of the range
|
|
gs_nextAutoId = wxID_AUTO_HIGHEST - count;
|
|
return gs_nextAutoId + 1;
|
|
}
|
|
#endif // wxUSE_AUTOID_MANAGEMENT/!wxUSE_AUTOID_MANAGEMENT
|
|
}
|
|
|
|
void wxIdManager::UnreserveId(wxWindowID winid, int count)
|
|
{
|
|
wxASSERT_MSG(count > 0, wxT("can't unreserve less than 1 id"));
|
|
|
|
#if wxUSE_AUTOID_MANAGEMENT
|
|
while (count--)
|
|
UnreserveIdRefCount(winid++);
|
|
#else
|
|
wxUnusedVar(winid);
|
|
wxUnusedVar(count);
|
|
#endif
|
|
}
|
|
|