const wxValidator& validator = wxDefaultValidator,
const wxString& name = wxChoiceNameStr )
{
+ m_strings = (wxSortedArrayString *)NULL;
+
Create(parent, id, pos, size, n, choices, style, validator, name);
}
~wxChoice();
wxString GetString( int n ) const;
// implementation
- wxList m_clientList;
+ wxList m_clientList; // contains the client data for the items
void DisableEvents();
void EnableEvents();
void AppendCommon( const wxString &item );
void ApplyWidgetStyle();
-
+
protected:
virtual int DoAppend(const wxString& item);
{ return(wxWindowBase::DoGetClientObject()); };
private:
+ // common part of Create() and DoAppend()
+ size_t AppendHelper(GtkWidget *menu, const wxString& item);
+
+ // this array is only used for controls with wxCB_SORT style, so only
+ // allocate it if it's needed (hence using pointer)
+ wxSortedArrayString *m_strings;
+
DECLARE_DYNAMIC_CLASS(wxChoice)
};
const wxValidator& validator = wxDefaultValidator,
const wxString& name = wxChoiceNameStr )
{
+ m_strings = (wxSortedArrayString *)NULL;
+
Create(parent, id, pos, size, n, choices, style, validator, name);
}
~wxChoice();
wxString GetString( int n ) const;
// implementation
- wxList m_clientList;
+ wxList m_clientList; // contains the client data for the items
void DisableEvents();
void EnableEvents();
void AppendCommon( const wxString &item );
void ApplyWidgetStyle();
-
+
protected:
virtual int DoAppend(const wxString& item);
{ return(wxWindowBase::DoGetClientObject()); };
private:
+ // common part of Create() and DoAppend()
+ size_t AppendHelper(GtkWidget *menu, const wxString& item);
+
+ // this array is only used for controls with wxCB_SORT style, so only
+ // allocate it if it's needed (hence using pointer)
+ wxSortedArrayString *m_strings;
+
DECLARE_DYNAMIC_CLASS(wxChoice)
};
// sensitive (default). Returns index of the first item matched or
// wxNOT_FOUND
int Index (const wxChar *sz, bool bCase = TRUE, bool bFromEnd = FALSE) const;
- // add new element at the end
- void Add(const wxString& str);
+ // add new element at the end (if the array is not sorted), return its
+ // index
+ size_t Add(const wxString& str);
// add new element at given position
void Insert(const wxString& str, size_t uiIndex);
// remove first item matching this value
}
// add item at the end
-void wxArrayString::Add(const wxString& str)
+size_t wxArrayString::Add(const wxString& str)
{
if ( m_autoSort ) {
// insert the string at the correct position to keep the array sorted
wxASSERT_MSG( lo == hi, wxT("binary search broken") );
Insert(str, lo);
+
+ return (size_t)lo;
}
else {
wxASSERT( str.GetStringData()->IsValid() );
str.GetStringData()->Lock();
// just append
- m_pItems[m_nCount++] = (wxChar *)str.c_str();
+ m_pItems[m_nCount] = (wxChar *)str.c_str(); // const_cast
+
+ return m_nCount++;
}
}
{
wxASSERT( str.GetStringData()->IsValid() );
- wxCHECK_RET( !m_autoSort, wxT("can't use this method with sorted arrays") );
-
wxCHECK_RET( nIndex <= m_nCount, wxT("bad index in wxArrayString::Insert") );
Grow();
static void gtk_choice_clicked_callback( GtkWidget *WXUNUSED(widget), wxChoice *choice )
{
- if (g_isIdle)
+ if (g_isIdle)
wxapp_install_idle_handler();
if (!choice->m_hasVMT) return;
wxChoice::wxChoice()
{
+ m_strings = (wxSortedArrayString *)NULL;
}
bool wxChoice::Create( wxWindow *parent, wxWindowID id,
!CreateBase( parent, id, pos, size, style, validator, name ))
{
wxFAIL_MSG( wxT("wxChoice creation failed") );
- return FALSE;
+ return FALSE;
}
m_widget = gtk_option_menu_new();
newSize.y = 26;
SetSize( newSize.x, newSize.y );
+ if ( style & wxCB_SORT )
+ {
+ // if our m_strings != NULL, DoAppend() will check for it and insert
+ // items in the correct order
+ m_strings = new wxSortedArrayString;
+ }
+
GtkWidget *menu = gtk_menu_new();
for (int i = 0; i < n; i++)
{
- m_clientList.Append( (wxObject*) NULL );
-
- GtkWidget *item = gtk_menu_item_new_with_label( choices[i].mbc_str() );
- gtk_menu_append( GTK_MENU(menu), item );
-
- gtk_widget_show( item );
-
- gtk_signal_connect( GTK_OBJECT( item ), "activate",
- GTK_SIGNAL_FUNC(gtk_choice_clicked_callback), (gpointer*)this );
+ AppendHelper(menu, choices[i]);
}
+
gtk_option_menu_set_menu( GTK_OPTION_MENU(m_widget), menu );
m_parent->DoAddChild( this );
wxChoice::~wxChoice()
{
Clear();
+
+ delete m_strings;
}
int wxChoice::DoAppend( const wxString &item )
wxCHECK_MSG( m_widget != NULL, -1, wxT("invalid choice") );
GtkWidget *menu = gtk_option_menu_get_menu( GTK_OPTION_MENU(m_widget) );
- GtkWidget *menu_item = gtk_menu_item_new_with_label( item.mbc_str() );
-
- gtk_menu_append( GTK_MENU(menu), menu_item );
- if (GTK_WIDGET_REALIZED(m_widget))
- {
- gtk_widget_realize( menu_item );
- gtk_widget_realize( GTK_BIN(menu_item)->child );
-
- if (m_widgetStyle) ApplyWidgetStyle();
- }
-
- gtk_signal_connect( GTK_OBJECT( menu_item ), "activate",
- GTK_SIGNAL_FUNC(gtk_choice_clicked_callback), (gpointer*)this );
-
- gtk_widget_show( menu_item );
-
- m_clientList.Append( (wxObject*) NULL );
-
- // return the index of the item in the control
- return GetCount() - 1;
+ return AppendHelper(menu, item);
}
void wxChoice::DoSetClientData( int n, void* clientData )
if (m_clientDataItemsType == ClientData_Object)
{
- wxNode *node = m_clientList.First();
+ wxNode *node = m_clientList.First();
while (node)
{
wxClientData *cd = (wxClientData*)node->Data();
if (cd) delete cd;
node = node->Next();
- }
+ }
}
m_clientList.Clear();
}
}
}
+size_t wxChoice::AppendHelper(GtkWidget *menu, const wxString& item)
+{
+ GtkWidget *menu_item = gtk_menu_item_new_with_label( item.mbc_str() );
+
+ size_t index;
+ if ( m_strings )
+ {
+ // sorted control, need to insert at the correct index
+ index = m_strings->Add(item);
+
+ gtk_menu_insert( GTK_MENU(menu), menu_item, index );
+
+ if ( index )
+ {
+ m_clientList.Insert( m_clientList.Item(index - 1),
+ (wxObject*) NULL );
+ }
+ else
+ {
+ // can't use Insert() :-(
+ m_clientList.Append( (wxObject*) NULL );
+ }
+ }
+ else
+ {
+ // normal control, just append
+ gtk_menu_append( GTK_MENU(menu), menu_item );
+
+ m_clientList.Append( (wxObject*) NULL );
+
+ // don't call wxChoice::GetCount() from here because it doesn't work
+ // if we're called from ctor (and GtkMenuShell is still NULL)
+ index = m_clientList.GetCount();
+ }
+
+ if (GTK_WIDGET_REALIZED(m_widget))
+ {
+ gtk_widget_realize( menu_item );
+ gtk_widget_realize( GTK_BIN(menu_item)->child );
+
+ if (m_widgetStyle) ApplyWidgetStyle();
+ }
+
+ gtk_signal_connect( GTK_OBJECT( menu_item ), "activate",
+ GTK_SIGNAL_FUNC(gtk_choice_clicked_callback), (gpointer*)this );
+
+ gtk_widget_show( menu_item );
+
+ // return the index of the item in the control
+ return index;
+}
+
#endif
static void gtk_choice_clicked_callback( GtkWidget *WXUNUSED(widget), wxChoice *choice )
{
- if (g_isIdle)
+ if (g_isIdle)
wxapp_install_idle_handler();
if (!choice->m_hasVMT) return;
wxChoice::wxChoice()
{
+ m_strings = (wxSortedArrayString *)NULL;
}
bool wxChoice::Create( wxWindow *parent, wxWindowID id,
!CreateBase( parent, id, pos, size, style, validator, name ))
{
wxFAIL_MSG( wxT("wxChoice creation failed") );
- return FALSE;
+ return FALSE;
}
m_widget = gtk_option_menu_new();
newSize.y = 26;
SetSize( newSize.x, newSize.y );
+ if ( style & wxCB_SORT )
+ {
+ // if our m_strings != NULL, DoAppend() will check for it and insert
+ // items in the correct order
+ m_strings = new wxSortedArrayString;
+ }
+
GtkWidget *menu = gtk_menu_new();
for (int i = 0; i < n; i++)
{
- m_clientList.Append( (wxObject*) NULL );
-
- GtkWidget *item = gtk_menu_item_new_with_label( choices[i].mbc_str() );
- gtk_menu_append( GTK_MENU(menu), item );
-
- gtk_widget_show( item );
-
- gtk_signal_connect( GTK_OBJECT( item ), "activate",
- GTK_SIGNAL_FUNC(gtk_choice_clicked_callback), (gpointer*)this );
+ AppendHelper(menu, choices[i]);
}
+
gtk_option_menu_set_menu( GTK_OPTION_MENU(m_widget), menu );
m_parent->DoAddChild( this );
wxChoice::~wxChoice()
{
Clear();
+
+ delete m_strings;
}
int wxChoice::DoAppend( const wxString &item )
wxCHECK_MSG( m_widget != NULL, -1, wxT("invalid choice") );
GtkWidget *menu = gtk_option_menu_get_menu( GTK_OPTION_MENU(m_widget) );
- GtkWidget *menu_item = gtk_menu_item_new_with_label( item.mbc_str() );
-
- gtk_menu_append( GTK_MENU(menu), menu_item );
- if (GTK_WIDGET_REALIZED(m_widget))
- {
- gtk_widget_realize( menu_item );
- gtk_widget_realize( GTK_BIN(menu_item)->child );
-
- if (m_widgetStyle) ApplyWidgetStyle();
- }
-
- gtk_signal_connect( GTK_OBJECT( menu_item ), "activate",
- GTK_SIGNAL_FUNC(gtk_choice_clicked_callback), (gpointer*)this );
-
- gtk_widget_show( menu_item );
-
- m_clientList.Append( (wxObject*) NULL );
-
- // return the index of the item in the control
- return GetCount() - 1;
+ return AppendHelper(menu, item);
}
void wxChoice::DoSetClientData( int n, void* clientData )
if (m_clientDataItemsType == ClientData_Object)
{
- wxNode *node = m_clientList.First();
+ wxNode *node = m_clientList.First();
while (node)
{
wxClientData *cd = (wxClientData*)node->Data();
if (cd) delete cd;
node = node->Next();
- }
+ }
}
m_clientList.Clear();
}
}
}
+size_t wxChoice::AppendHelper(GtkWidget *menu, const wxString& item)
+{
+ GtkWidget *menu_item = gtk_menu_item_new_with_label( item.mbc_str() );
+
+ size_t index;
+ if ( m_strings )
+ {
+ // sorted control, need to insert at the correct index
+ index = m_strings->Add(item);
+
+ gtk_menu_insert( GTK_MENU(menu), menu_item, index );
+
+ if ( index )
+ {
+ m_clientList.Insert( m_clientList.Item(index - 1),
+ (wxObject*) NULL );
+ }
+ else
+ {
+ // can't use Insert() :-(
+ m_clientList.Append( (wxObject*) NULL );
+ }
+ }
+ else
+ {
+ // normal control, just append
+ gtk_menu_append( GTK_MENU(menu), menu_item );
+
+ m_clientList.Append( (wxObject*) NULL );
+
+ // don't call wxChoice::GetCount() from here because it doesn't work
+ // if we're called from ctor (and GtkMenuShell is still NULL)
+ index = m_clientList.GetCount();
+ }
+
+ if (GTK_WIDGET_REALIZED(m_widget))
+ {
+ gtk_widget_realize( menu_item );
+ gtk_widget_realize( GTK_BIN(menu_item)->child );
+
+ if (m_widgetStyle) ApplyWidgetStyle();
+ }
+
+ gtk_signal_connect( GTK_OBJECT( menu_item ), "activate",
+ GTK_SIGNAL_FUNC(gtk_choice_clicked_callback), (gpointer*)this );
+
+ gtk_widget_show( menu_item );
+
+ // return the index of the item in the control
+ return index;
+}
+
#endif