dolphin/Externals/wxWidgets3/src/generic/selstore.cpp

232 lines
7.2 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// Name: src/generic/selstore.cpp
// Purpose: wxSelectionStore implementation
// Author: Vadim Zeitlin
// Modified by:
// Created: 08.06.03 (extracted from src/generic/listctrl.cpp)
// Copyright: (c) 2000-2003 Vadim Zeitlin <vadim@wxwindows.org>
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "wx/selstore.h"
// ============================================================================
// wxSelectionStore
// ============================================================================
// ----------------------------------------------------------------------------
// tests
// ----------------------------------------------------------------------------
bool wxSelectionStore::IsSelected(unsigned item) const
{
bool isSel = m_itemsSel.Index(item) != wxNOT_FOUND;
// if the default state is to be selected, being in m_itemsSel means that
// the item is not selected, so we have to inverse the logic
return m_defaultState ? !isSel : isSel;
}
// ----------------------------------------------------------------------------
// Select*()
// ----------------------------------------------------------------------------
bool wxSelectionStore::SelectItem(unsigned item, bool select)
{
// search for the item ourselves as like this we get the index where to
// insert it later if needed, so we do only one search in the array instead
// of two (adding item to a sorted array requires a search)
size_t index = m_itemsSel.IndexForInsert(item);
bool isSel = index < m_itemsSel.GetCount() && m_itemsSel[index] == item;
if ( select != m_defaultState )
{
if ( !isSel )
{
m_itemsSel.AddAt(item, index);
return true;
}
}
else // reset to default state
{
if ( isSel )
{
m_itemsSel.RemoveAt(index);
return true;
}
}
return false;
}
bool wxSelectionStore::SelectRange(unsigned itemFrom, unsigned itemTo,
bool select,
wxArrayInt *itemsChanged)
{
// 100 is hardcoded but it shouldn't matter much: the important thing is
// that we don't refresh everything when really few (e.g. 1 or 2) items
// change state
static const unsigned MANY_ITEMS = 100;
wxASSERT_MSG( itemFrom <= itemTo, wxT("should be in order") );
// are we going to have more [un]selected items than the other ones?
if ( itemTo - itemFrom > m_count/2 )
{
if ( select != m_defaultState )
{
// the default state now becomes the same as 'select'
m_defaultState = select;
// so all the old selections (which had state select) shouldn't be
// selected any more, but all the other ones should
wxSelectedIndices selOld = m_itemsSel;
m_itemsSel.Empty();
// TODO: it should be possible to optimize the searches a bit
// knowing the possible range
unsigned item;
for ( item = 0; item < itemFrom; item++ )
{
if ( selOld.Index(item) == wxNOT_FOUND )
m_itemsSel.Add(item);
}
for ( item = itemTo + 1; item < m_count; item++ )
{
if ( selOld.Index(item) == wxNOT_FOUND )
m_itemsSel.Add(item);
}
// many items (> half) changed state
itemsChanged = NULL;
}
else // select == m_defaultState
{
// get the inclusive range of items between itemFrom and itemTo
size_t count = m_itemsSel.GetCount(),
start = m_itemsSel.IndexForInsert(itemFrom),
end = m_itemsSel.IndexForInsert(itemTo);
if ( start == count || m_itemsSel[start] < itemFrom )
{
start++;
}
if ( end == count || m_itemsSel[end] > itemTo )
{
end--;
}
if ( start <= end )
{
// delete all of them (from end to avoid changing indices)
for ( int i = end; i >= (int)start; i-- )
{
if ( itemsChanged )
{
if ( itemsChanged->GetCount() > MANY_ITEMS )
{
// stop counting (see comment below)
itemsChanged = NULL;
}
else
{
itemsChanged->Add(m_itemsSel[i]);
}
}
m_itemsSel.RemoveAt(i);
}
}
}
}
else // "few" items change state
{
if ( itemsChanged )
{
itemsChanged->Empty();
}
// just add the items to the selection
for ( unsigned item = itemFrom; item <= itemTo; item++ )
{
if ( SelectItem(item, select) && itemsChanged )
{
itemsChanged->Add(item);
if ( itemsChanged->GetCount() > MANY_ITEMS )
{
// stop counting them, we'll just eat gobs of memory
// for nothing at all - faster to refresh everything in
// this case
itemsChanged = NULL;
}
}
}
}
// we set it to NULL if there are many items changing state
return itemsChanged != NULL;
}
// ----------------------------------------------------------------------------
// callbacks
// ----------------------------------------------------------------------------
void wxSelectionStore::OnItemDelete(unsigned item)
{
size_t count = m_itemsSel.GetCount(),
i = m_itemsSel.IndexForInsert(item);
if ( i < count && m_itemsSel[i] == item )
{
// this item itself was in m_itemsSel, remove it from there
m_itemsSel.RemoveAt(i);
count--;
}
// and adjust the index of all which follow it
while ( i < count )
{
// all following elements must be greater than the one we deleted
wxASSERT_MSG( m_itemsSel[i] > item, wxT("logic error") );
m_itemsSel[i++]--;
}
}
void wxSelectionStore::SetItemCount(unsigned count)
{
// forget about all items whose indices are now invalid if the size
// decreased
if ( count < m_count )
{
for ( size_t i = m_itemsSel.GetCount(); i > 0; i-- )
{
if ( m_itemsSel[i - 1] >= count )
m_itemsSel.RemoveAt(i - 1);
}
}
// remember the new number of items
m_count = count;
}