many wxItemContainer-related changes:

1. the main function for item insertion is now DoInsertItems() which allows
   for much more efficient addition of many new items at once
2. the items client data management is done entirely in wxItemContainer
   itself, the derived classes don't have to distinguish between void and
   object client data
3. many fixes for sorted controls, in particular implemented wxCB_SORT support
   in wxGTK combobox


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@47730 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2007-07-26 13:54:14 +00:00
parent 7f73c398d5
commit a236aa2058
98 changed files with 2825 additions and 2678 deletions

View File

@@ -51,15 +51,6 @@ static inline const wxString& Prefix(bool checked)
static inline bool IsChecked(const wxString& s)
{ wxASSERT(s.length() >=4); return s[1] == checkChar; }
static void CopyStringsAddingPrefix(const wxArrayString& orig,
wxArrayString& copy)
{
copy.Clear();
for(size_t i = 0; i < orig.GetCount(); ++i )
copy.Add( Prefix(false) + orig[i] );
}
// def ctor: use Create() to really create the control
wxCheckListBox::wxCheckListBox() : wxCheckListBoxBase()
{
@@ -154,11 +145,6 @@ void wxCheckListBox::DoToggleItem( int n, int x )
}
}
int wxCheckListBox::DoAppend(const wxString& item)
{
return wxListBox::DoAppend( Prefix(false) + item );
}
int wxCheckListBox::FindString(const wxString& s, bool bCase) const
{
int n1 = wxListBox::FindString(Prefix(false) + s, bCase);
@@ -183,18 +169,16 @@ wxString wxCheckListBox::GetString(unsigned int n) const
return wxListBox::GetString(n).substr(4);
}
void wxCheckListBox::DoInsertItems(const wxArrayString& items, unsigned int pos)
int wxCheckListBox::DoInsertItems(const wxArrayStringsAdapter& items,
unsigned int pos,
void **clientData, wxClientDataType type)
{
wxArrayString copy;
CopyStringsAddingPrefix(items, copy);
wxListBox::DoInsertItems(copy, pos);
}
copy.reserve(pos);
for ( size_t i = 0; i < items.GetCount(); ++i )
copy.push_back( Prefix(false) + items[i] );
void wxCheckListBox::DoSetItems(const wxArrayString& items, void **clientData)
{
wxArrayString copy;
CopyStringsAddingPrefix(items, copy);
wxListBox::DoSetItems(copy, clientData);
return wxListBox::DoInsertItems(copy, pos, clientData, type);
}
#endif // wxUSE_CHECKLISTBOX

View File

@@ -179,8 +179,6 @@ wxChoice::~wxChoice()
m_mainWidget = (WXWidget) 0;
m_buttonWidget = (WXWidget) 0;
}
if ( HasClientObjectData() )
m_clientDataDict.DestroyData();
}
static inline wxChar* MYcopystring(const wxChar* s)
@@ -189,72 +187,78 @@ static inline wxChar* MYcopystring(const wxChar* s)
return wxStrcpy(copy, s);
}
int wxChoice::DoInsert(const wxString& item, unsigned int pos)
// TODO auto-sorting is not supported by the code
int wxChoice::DoInsertItems(const wxArrayStringsAdapter& items,
unsigned int pos,
void **clientData, wxClientDataType type)
{
#ifndef XmNpositionIndex
wxCHECK_MSG( pos == GetCount(), -1, wxT("insert not implemented"));
#endif
Widget w = XtVaCreateManagedWidget (GetLabelText(item),
const unsigned int numItems = items.GetCount();
AllocClientData(numItems);
for( unsigned int i = 0; i < numItems; ++i, ++pos )
{
Widget w = XtVaCreateManagedWidget (GetLabelText(items[i]),
#if wxUSE_GADGETS
xmPushButtonGadgetClass, (Widget) m_menuWidget,
xmPushButtonGadgetClass, (Widget) m_menuWidget,
#else
xmPushButtonWidgetClass, (Widget) m_menuWidget,
xmPushButtonWidgetClass, (Widget) m_menuWidget,
#endif
#ifdef XmNpositionIndex
XmNpositionIndex, pos,
XmNpositionIndex, pos,
#endif
NULL);
wxDoChangeBackgroundColour((WXWidget) w, m_backgroundColour);
if( m_font.Ok() )
wxDoChangeFont( w, m_font );
m_widgetArray.Insert(w, pos);
char mnem = wxFindMnemonic (item);
if (mnem != 0)
XtVaSetValues (w, XmNmnemonic, mnem, NULL);
XtAddCallback (w, XmNactivateCallback,
(XtCallbackProc) wxChoiceCallback,
(XtPointer) this);
if (m_noStrings == 0 && m_buttonWidget)
{
XtVaSetValues ((Widget) m_buttonWidget, XmNmenuHistory, w, NULL);
Widget label = XmOptionButtonGadget ((Widget) m_buttonWidget);
wxXmString text( item );
XtVaSetValues (label,
XmNlabelString, text(),
NULL);
wxDoChangeBackgroundColour((WXWidget) w, m_backgroundColour);
if( m_font.Ok() )
wxDoChangeFont( w, m_font );
m_widgetArray.Insert(w, pos);
char mnem = wxFindMnemonic (items[i]);
if (mnem != 0)
XtVaSetValues (w, XmNmnemonic, mnem, NULL);
XtAddCallback (w, XmNactivateCallback,
(XtCallbackProc) wxChoiceCallback,
(XtPointer) this);
if (m_noStrings == 0 && m_buttonWidget)
{
XtVaSetValues ((Widget) m_buttonWidget, XmNmenuHistory, w, NULL);
Widget label = XmOptionButtonGadget ((Widget) m_buttonWidget);
wxXmString text( items[i] );
XtVaSetValues (label,
XmNlabelString, text(),
NULL);
}
// need to ditch wxStringList for wxArrayString
m_stringList.Insert(pos, MYcopystring(items[i]));
m_noStrings ++;
InsertNewItemClientData(pos, clientData, i, type);
}
// need to ditch wxStringList for wxArrayString
m_stringList.Insert(pos, MYcopystring(item));
m_noStrings ++;
return pos;
return pos - 1;
}
int wxChoice::DoAppend(const wxString& item)
{
return DoInsert(item, GetCount());
}
void wxChoice::Delete(unsigned int n)
void wxChoice::DoDeleteOneItem(unsigned int n)
{
Widget w = (Widget)m_widgetArray[n];
XtRemoveCallback(w, XmNactivateCallback, (XtCallbackProc)wxChoiceCallback,
(XtPointer)this);
m_stringList.Erase(m_stringList.Item(n));
m_widgetArray.RemoveAt(size_t(n));
m_clientDataDict.Delete(n, HasClientObjectData());
wxChoiceBase::DoDeleteOneItem(n);
XtDestroyWidget(w);
m_noStrings--;
}
void wxChoice::Clear()
void wxChoice::DoClear()
{
m_stringList.Clear ();
unsigned int i;
@@ -272,8 +276,7 @@ void wxChoice::Clear()
XmNmenuHistory, (Widget) NULL,
NULL);
if ( HasClientObjectData() )
m_clientDataDict.DestroyData();
wxChoiceBase::DoClear();
m_noStrings = 0;
}
@@ -502,27 +505,6 @@ unsigned int wxChoice::GetCount() const
return m_noStrings;
}
void wxChoice::DoSetItemClientData(unsigned int n, void* clientData)
{
m_clientDataDict.Set(n, (wxClientData*)clientData, false);
}
void* wxChoice::DoGetItemClientData(unsigned int n) const
{
return (void*)m_clientDataDict.Get(n);
}
void wxChoice::DoSetItemClientObject(unsigned int n, wxClientData* clientData)
{
// don't delete, wxItemContainer does that for us
m_clientDataDict.Set(n, clientData, false);
}
wxClientData* wxChoice::DoGetItemClientObject(unsigned int n) const
{
return m_clientDataDict.Get(n);
}
void wxChoice::SetString(unsigned int WXUNUSED(n), const wxString& WXUNUSED(s))
{
wxFAIL_MSG( wxT("wxChoice::SetString not implemented") );

View File

@@ -111,8 +111,6 @@ wxComboBox::~wxComboBox()
DetachWidget((Widget) m_mainWidget); // Removes event handlers
XtDestroyWidget((Widget) m_mainWidget);
m_mainWidget = (WXWidget) 0;
if ( HasClientObjectData() )
m_clientDataDict.DestroyData();
}
void wxComboBox::DoSetSize(int x, int y,
@@ -151,34 +149,29 @@ void wxComboBox::SetString(unsigned int WXUNUSED(n), const wxString& WXUNUSED(s)
wxFAIL_MSG( wxT("wxComboBox::SetString only implemented for Motif 2.0") );
}
int wxComboBox::DoAppend(const wxString& item)
// TODO auto-sorting is not supported by the code
int wxComboBox::DoInsertItems(const wxArrayStringsAdapter& items,
unsigned int pos,
void **clientData,
wxClientDataType type)
{
wxXmString str( item.c_str() );
XmComboBoxAddItem((Widget) m_mainWidget, str(), 0);
m_stringList.Add(item);
m_noStrings ++;
const unsigned int numItems = items.GetCount();
return GetCount() - 1;
AllocClientData(numItems);
for( unsigned int i = 0; i < numItems; ++i, ++pos )
{
wxXmString str( items[i].c_str() );
XmComboBoxAddItem((Widget) m_mainWidget, str(), GetMotifPosition(pos));
wxChar* copy = wxStrcpy(new wxChar[items[i].length() + 1], items[i].c_str());
m_stringList.Insert(pos, copy);
m_noStrings ++;
InsertNewItemClientData(pos, clientData, i, type);
}
return pos - 1;
}
int wxComboBox::DoInsert(const wxString& item, unsigned int pos)
{
wxCHECK_MSG(!(GetWindowStyle() & wxCB_SORT), -1, wxT("can't insert into sorted list"));
wxCHECK_MSG(IsValidInsert(pos), -1, wxT("invalid index"));
if (pos == GetCount())
return DoAppend(item);
wxXmString str( item.c_str() );
XmComboBoxAddItem((Widget) m_mainWidget, str(), pos+1);
wxChar* copy = wxStrcpy(new wxChar[item.length() + 1], item.c_str());
m_stringList.Insert(pos, copy);
m_noStrings ++;
return pos;
}
void wxComboBox::Delete(unsigned int n)
void wxComboBox::DoDeleteOneItem(unsigned int n)
{
XmComboBoxDeletePos((Widget) m_mainWidget, n+1);
wxStringList::Node *node = m_stringList.Item(n);
@@ -187,17 +180,16 @@ void wxComboBox::Delete(unsigned int n)
delete[] node->GetData();
delete node;
}
m_clientDataDict.Delete(n, HasClientObjectData());
wxControlWithItems::DoDeleteOneItem(n);
m_noStrings--;
}
void wxComboBox::Clear()
void wxComboBox::DoClear()
{
XmComboBoxDeleteAllItems((Widget) m_mainWidget);
m_stringList.Clear();
if ( HasClientObjectData() )
m_clientDataDict.DestroyData();
wxControlWithItems::DoClear();
m_noStrings = 0;
}

View File

@@ -161,8 +161,6 @@ wxComboBox::~wxComboBox()
DetachWidget((Widget) m_mainWidget); // Removes event handlers
XtDestroyWidget((Widget) m_mainWidget);
m_mainWidget = (WXWidget) 0;
if ( HasClientObjectData() )
m_clientDataDict.DestroyData();
}
void wxComboBox::DoSetSize(int x, int y, int width, int WXUNUSED(height), int sizeFlags)
@@ -202,33 +200,28 @@ void wxComboBox::SetValue(const wxString& value)
m_inSetValue = false;
}
int wxComboBox::DoAppend(const wxString& item)
int wxComboBox::DoInsertItems(const wxArrayStringsAdapter & items,
unsigned int pos,
void **clientData, wxClientDataType type)
{
wxXmString str( item.c_str() );
XmComboBoxAddItem((Widget) m_mainWidget, str(), 0, False);
m_noStrings ++;
const unsigned int numItems = items.GetCount();
AllocClientData(numItems);
for ( unsigned int i = 0; i < numItems; ++i, ++pos )
{
wxXmString str( items[i].c_str() );
XmComboBoxAddItem((Widget) m_mainWidget, str(),
GetMotifPosition(pos), False);
m_noStrings ++;
InsertNewItemClientData(pos, clientData, i, type);
}
AdjustDropDownListSize();
return GetCount() - 1;
return pos - 1;
}
int wxComboBox::DoInsert(const wxString& item, unsigned int pos)
{
wxCHECK_MSG(!(GetWindowStyle() & wxCB_SORT), -1, wxT("can't insert into sorted list"));
wxCHECK_MSG(IsValidInsert(pos), -1, wxT("invalid index"));
if (pos == GetCount())
return DoAppend(item);
wxXmString str( item.c_str() );
XmComboBoxAddItem((Widget) m_mainWidget, str(), pos+1, False);
m_noStrings ++;
AdjustDropDownListSize();
return GetCount() - 1;
}
void wxComboBox::Delete(unsigned int n)
void wxComboBox::DoDeleteOneItem(unsigned int n)
{
#ifdef LESSTIF_VERSION
XmListDeletePos (GetXmList(this), n + 1);
@@ -236,13 +229,13 @@ void wxComboBox::Delete(unsigned int n)
XmComboBoxDeletePos((Widget) m_mainWidget, n+1);
#endif
m_clientDataDict.Delete(n, HasClientObjectData());
wxControlWithItems::DoDeleteOneItem(n);
m_noStrings--;
AdjustDropDownListSize();
}
void wxComboBox::Clear()
void wxComboBox::DoClear()
{
#ifdef LESSTIF_VERSION
XmListDeleteAllItems (GetXmList(this));
@@ -253,8 +246,7 @@ void wxComboBox::Clear()
}
#endif
if ( HasClientObjectData() )
m_clientDataDict.DestroyData();
wxControlWithItems::DoClear();
m_noStrings = 0;
AdjustDropDownListSize();
}

View File

@@ -171,12 +171,6 @@ bool wxListBox::Create(wxWindow *parent, wxWindowID id,
style, validator, name);
}
wxListBox::~wxListBox()
{
if( HasClientObjectData() )
m_clientDataDict.DestroyData();
}
void wxListBox::SetSelectionPolicy()
{
Widget listBox = (Widget)m_mainWidget;
@@ -208,63 +202,16 @@ void wxListBox::DoSetFirstItem( int N )
XmListSetPos ((Widget) m_mainWidget, N + 1);
}
void wxListBox::Delete(unsigned int n)
void wxListBox::DoDeleteOneItem(unsigned int n)
{
Widget listBox = (Widget) m_mainWidget;
XmListDeletePos (listBox, n + 1);
m_clientDataDict.Delete(n, HasClientObjectData());
wxListBoxBase::DoDeleteOneItem(n);
m_noItems --;
}
int wxListBox::DoAppend(const wxString& item)
{
Widget listBox = (Widget) m_mainWidget;
int n;
XtVaGetValues (listBox, XmNitemCount, &n, NULL);
wxXmString text( item );
// XmListAddItem(listBox, text, n + 1);
XmListAddItemUnselected (listBox, text(), 0);
// It seems that if the list is cleared, we must re-ask for
// selection policy!!
SetSelectionPolicy();
m_noItems ++;
return GetCount() - 1;
}
void wxListBox::DoSetItems(const wxArrayString& items, void** clientData)
{
Widget listBox = (Widget) m_mainWidget;
if( HasClientObjectData() )
m_clientDataDict.DestroyData();
XmString *text = new XmString[items.GetCount()];
unsigned int i;
for (i = 0; i < items.GetCount(); ++i)
text[i] = wxStringToXmString (items[i]);
if ( clientData )
for (i = 0; i < items.GetCount(); ++i)
m_clientDataDict.Set(i, (wxClientData*)clientData[i], false);
XmListAddItems (listBox, text, items.GetCount(), 0);
for (i = 0; i < items.GetCount(); i++)
XmStringFree (text[i]);
delete[] text;
// It seems that if the list is cleared, we must re-ask for
// selection policy!!
SetSelectionPolicy();
m_noItems = items.GetCount();
}
int wxDoFindStringInList(Widget w, const wxString& s)
{
wxXmString str( s );
@@ -290,20 +237,19 @@ int wxListBox::FindString(const wxString& s, bool WXUNUSED(bCase)) const
return wxDoFindStringInList( (Widget)m_mainWidget, s );
}
void wxListBox::Clear()
void wxListBox::DoClear()
{
if (m_noItems <= 0)
if (!m_noItems)
return;
wxSizeKeeper sk( this );
Widget listBox = (Widget) m_mainWidget;
XmListDeleteAllItems (listBox);
if( HasClientObjectData() )
m_clientDataDict.DestroyData();
sk.Restore();
wxListBoxBase::DoClear();
m_noItems = 0;
}
@@ -364,26 +310,6 @@ bool wxListBox::IsSelected(int N) const
return false;
}
void wxListBox::DoSetItemClientObject(unsigned int n, wxClientData* clientData)
{
m_clientDataDict.Set(n, clientData, false);
}
wxClientData* wxListBox::DoGetItemClientObject(unsigned int n) const
{
return m_clientDataDict.Get(n);
}
void *wxListBox::DoGetItemClientData(unsigned int n) const
{
return (void*)m_clientDataDict.Get(n);
}
void wxListBox::DoSetItemClientData(unsigned int n, void *Client_data)
{
m_clientDataDict.Set(n, (wxClientData*)Client_data, false);
}
// Return number of selections and an array of selected integers
int wxListBox::GetSelections(wxArrayInt& aSelections) const
{
@@ -456,36 +382,43 @@ wxString wxListBox::GetString(unsigned int n) const
return wxDoGetStringInList( (Widget)m_mainWidget, n );
}
void wxListBox::DoInsertItems(const wxArrayString& items, unsigned int pos)
int wxListBox::DoInsertItems(const wxArrayStringsAdapter & items,
unsigned int pos,
void **clientData, wxClientDataType type)
{
Widget listBox = (Widget) m_mainWidget;
XmString *text = new XmString[items.GetCount()];
const unsigned int numItems = items.GetCount();
XmString *text = new XmString[numItems];
unsigned int i;
// Steve Hammes: Motif 1.1 compatibility
// #if XmVersion > 1100
// Corrected by Sergey Krasnov from Steve Hammes' code
#if XmVersion > 1001
for (i = 0; i < items.GetCount(); i++)
text[i] = wxStringToXmString(items[i]);
XmListAddItemsUnselected(listBox, text, items.GetCount(), pos+1);
#else
for (i = 0; i < items.GetCount(); i++)
for (i = 0; i < numItems; i++)
{
text[i] = wxStringToXmString(items[i]);
// Another Sergey correction
XmListAddItemUnselected(listBox, text[i], pos+i+1);
}
XmListAddItemsUnselected(listBox, text, numItems, GetMotifPosition(pos));
InsertNewItemsClientData(pos, numItems, clientData, type);
#else
AllocClientData(numItems);
unsigned int idx = pos;
for ( i = 0; i < numItems; i++, idx++ )
{
text[i] = wxStringToXmString(items[i]);
XmListAddItemUnselected(listBox, text[i], GetMotifPosition(idx));
InsertNewItemClientData(idx, clientData, i, type);
}
#endif
for (i = 0; i < items.GetCount(); i++)
for (i = 0; i < numItems; i++)
XmStringFree(text[i]);
delete[] text;
// It seems that if the list is cleared, we must re-ask for
// selection policy!!
m_noItems += numItems;
SetSelectionPolicy();
m_noItems += items.GetCount();
return pos + numItems - 1;
}
void wxListBox::SetString(unsigned int n, const wxString& s)