+wxClientData* wxChoice::DoGetItemClientObject( int n ) const
+{
+ wxCHECK_MSG( m_widget != NULL, (wxClientData*) NULL, wxT("invalid choice control") );
+
+ wxList::compatibility_iterator node = m_clientList.Item( n );
+ wxCHECK_MSG( node, (wxClientData *)NULL,
+ wxT("invalid index in wxChoice::DoGetItemClientObject") );
+
+ return (wxClientData*) node->GetData();
+}
+
+void wxChoice::Clear()
+{
+ wxCHECK_RET( m_widget != NULL, wxT("invalid choice") );
+
+ gtk_option_menu_remove_menu( GTK_OPTION_MENU(m_widget) );
+ GtkWidget *menu = gtk_menu_new();
+ gtk_option_menu_set_menu( GTK_OPTION_MENU(m_widget), menu );
+
+ if ( HasClientObjectData() )
+ {
+ // destroy the data (due to Robert's idea of using wxList<wxObject>
+ // and not wxList<wxClientData> we can't just say
+ // m_clientList.DeleteContents(TRUE) - this would crash!
+ wxList::compatibility_iterator node = m_clientList.GetFirst();
+ while ( node )
+ {
+ delete (wxClientData *)node->GetData();
+ node = node->GetNext();
+ }
+ }
+ m_clientList.Clear();
+
+ if ( m_strings )
+ m_strings->Clear();
+}
+
+void wxChoice::Delete( int n )
+{
+ wxCHECK_RET( m_widget != NULL, wxT("invalid choice") );
+
+ // VZ: apparently GTK+ doesn't have a built-in function to do it (not even
+ // in 2.0), hence this dumb implementation -- still better than nothing
+ int i,
+ count = GetCount();
+
+ wxCHECK_RET( n >= 0 && n < count, _T("invalid index in wxChoice::Delete") );
+
+ const bool hasClientData = m_clientDataItemsType != wxClientData_None;
+ const bool hasObjectData = m_clientDataItemsType == wxClientData_Object;
+
+ wxList::compatibility_iterator node = m_clientList.GetFirst();
+
+ wxArrayString items;
+ wxArrayPtrVoid itemsData;
+ items.Alloc(count);
+ for ( i = 0; i < count; i++ )
+ {
+ if ( i != n )
+ {
+ items.Add(GetString(i));
+ if ( hasClientData )
+ {
+ // also save the client data
+ itemsData.Add(node->GetData());
+ }
+ }
+ else // need to delete the client object too
+ {
+ if ( hasObjectData )
+ {
+ delete (wxClientData *)node->GetData();
+ }
+ }
+
+ if ( hasClientData )
+ {
+ node = node->GetNext();
+ }
+ }
+
+ if ( hasObjectData )
+ {
+ // prevent Clear() from destroying all client data
+ m_clientDataItemsType = wxClientData_None;
+ }
+
+ Clear();
+
+ for ( i = 0; i < count - 1; i++ )
+ {
+ Append(items[i]);
+
+ if ( hasObjectData )
+ SetClientObject(i, (wxClientData *)itemsData[i]);
+ else if ( hasClientData )
+ SetClientData(i, itemsData[i]);
+ }
+}
+
+int wxChoice::FindString( const wxString &string ) const
+{
+ wxCHECK_MSG( m_widget != NULL, -1, wxT("invalid choice") );
+
+ // If you read this code once and you think you understand
+ // it, then you are very wrong. Robert Roebling.
+
+ GtkMenuShell *menu_shell = GTK_MENU_SHELL( gtk_option_menu_get_menu( GTK_OPTION_MENU(m_widget) ) );
+ int count = 0;
+ GList *child = menu_shell->children;
+ while (child)
+ {
+ GtkBin *bin = GTK_BIN( child->data );
+ GtkLabel *label = (GtkLabel *) NULL;
+ if (bin->child)
+ label = GTK_LABEL(bin->child);
+ if (!label)
+ label = GTK_LABEL( BUTTON_CHILD(m_widget) );
+
+ wxASSERT_MSG( label != NULL , wxT("wxChoice: invalid label") );
+
+#ifdef __WXGTK20__
+ wxString tmp( wxGTK_CONV_BACK( gtk_label_get_text( label) ) );
+#else
+ wxString tmp( label->label );
+#endif
+ if (string == tmp)
+ return count;
+
+ child = child->next;
+ count++;
+ }
+
+ return -1;
+}
+
+int wxChoice::GetSelection() const