X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e8375af8ff97a3649361b988a40b991a8cdaab09..06d7ed27a19281549a8293d26cb44dd2d45055ea:/src/gtk/combobox.cpp diff --git a/src/gtk/combobox.cpp b/src/gtk/combobox.cpp index 10f20fbd1a..0caf6df81f 100644 --- a/src/gtk/combobox.cpp +++ b/src/gtk/combobox.cpp @@ -132,12 +132,12 @@ gtkcombo_combo_select_child_callback( GtkList *WXUNUSED(list), GtkWidget *WXUNUS // Quickly set the value of the combo box // as GTK+ does that only AFTER the event // is sent. - g_signal_handlers_disconnect_by_func (GTK_COMBO (combo->GetHandle())->entry, - (gpointer) gtkcombo_text_changed_callback, - combo); + GtkWidget* entry = GTK_COMBO(combo->GetHandle())->entry; + g_signal_handlers_block_by_func( + entry, (gpointer)gtkcombo_text_changed_callback, combo); combo->SetValue( combo->GetStringSelection() ); - g_signal_connect_after (GTK_COMBO (combo->GetHandle())->entry, "changed", - G_CALLBACK (gtkcombo_text_changed_callback), combo); + g_signal_handlers_unblock_by_func( + entry, (gpointer)gtkcombo_text_changed_callback, combo); // throw a SELECTED event only if the combobox popup is hidden (wxID_NONE) // because when combobox popup is shown, gtkcombo_combo_select_child_callback is @@ -241,6 +241,7 @@ bool wxComboBox::Create( wxWindow *parent, wxWindowID id, const wxString& value, long style, const wxValidator& validator, const wxString& name ) { + m_strings = NULL; m_ignoreNextUpdate = false; m_prevSelection = 0; @@ -251,21 +252,15 @@ bool wxComboBox::Create( wxWindow *parent, wxWindowID id, const wxString& value, return false; } + if(HasFlag(wxCB_SORT)) + m_strings = new wxSortedArrayString(); + #ifdef __WXGTK24__ if (!gtk_check_version(2,4,0)) { m_widget = gtk_combo_box_entry_new_text(); - GtkComboBox* combobox = GTK_COMBO_BOX( m_widget ); gtk_entry_set_editable( GTK_ENTRY( GTK_BIN(m_widget)->child ), TRUE ); - - for (int i = 0; i < n; i++) - { - gtk_combo_box_append_text( combobox, wxGTK_CONV( choices[i] ) ); - - m_clientDataList.Append( (wxObject*)NULL ); - m_clientObjectList.Append( (wxObject*)NULL ); - } } else #endif @@ -288,22 +283,9 @@ bool wxComboBox::Create( wxWindow *parent, wxWindowID id, const wxString& value, if (style & wxNO_BORDER) g_object_set (combo->entry, "has-frame", FALSE, NULL ); - - GtkWidget *list = combo->list; - - for (int i = 0; i < n; i++) - { - GtkWidget *list_item = gtk_list_item_new_with_label( wxGTK_CONV( choices[i] ) ); - - m_clientDataList.Append( (wxObject*)NULL ); - m_clientObjectList.Append( (wxObject*)NULL ); - - gtk_container_add( GTK_CONTAINER(list), list_item ); - - gtk_widget_show( list_item ); - } } + Append(n, choices); m_parent->DoAddChild( this ); @@ -370,18 +352,21 @@ bool wxComboBox::Create( wxWindow *parent, wxWindowID id, const wxString& value, return true; } +GtkEditable *wxComboBox::GetEditable() const +{ +#ifdef __WXGTK24__ + if ( !gtk_check_version(2,4,0) ) + return GTK_EDITABLE( GTK_BIN(m_widget)->child ); + else +#endif + return GTK_EDITABLE( GTK_COMBO(m_widget)->entry ); +} + wxComboBox::~wxComboBox() { - wxList::compatibility_iterator node = m_clientObjectList.GetFirst(); - while (node) - { - wxClientData *cd = (wxClientData*)node->GetData(); - if (cd) delete cd; - node = node->GetNext(); - } - m_clientObjectList.Clear(); + Clear(); - m_clientDataList.Clear(); + delete m_strings; } void wxComboBox::SetFocus() @@ -395,15 +380,36 @@ void wxComboBox::SetFocus() gtk_widget_grab_focus( m_focusWidget ); } -int wxComboBox::DoAppend( const wxString &item ) +int wxComboBox::DoInsertItems(const wxArrayStringsAdapter & items, + unsigned int pos, + void **clientData, wxClientDataType type) { wxCHECK_MSG( m_widget != NULL, -1, wxT("invalid combobox") ); + wxASSERT_MSG( !IsSorted() || (pos == GetCount()), + _T("In a sorted combobox data could only be appended")); + + const int count = items.GetCount(); + + int n = wxNOT_FOUND; + #ifdef __WXGTK24__ if (!gtk_check_version(2,4,0)) { GtkComboBox* combobox = GTK_COMBO_BOX( m_widget ); - gtk_combo_box_append_text( combobox, wxGTK_CONV( item ) ); + for( int i = 0; i < count; ++i ) + { + n = pos + i; + // If sorted, use this wxSortedArrayStrings to determine + // the right insertion point + if(m_strings) + n = m_strings->Add(items[i]); + + gtk_combo_box_insert_text( combobox, n, wxGTK_CONV( items[i] ) ); + + m_clientData.Insert( NULL, n ); + AssignNewItemClientData(n, clientData, i, type); + } } else #endif @@ -411,141 +417,54 @@ int wxComboBox::DoAppend( const wxString &item ) DisableEvents(); GtkWidget *list = GTK_COMBO(m_widget)->list; - GtkWidget *list_item = gtk_list_item_new_with_label( wxGTK_CONV( item ) ); - - gtk_container_add( GTK_CONTAINER(list), list_item ); - - if (GTK_WIDGET_REALIZED(m_widget)) + for( int i = 0; i < count; ++i ) { - gtk_widget_realize( list_item ); - gtk_widget_realize( GTK_BIN(list_item)->child ); - } - - // Apply current widget style to the new list_item - GtkRcStyle *style = CreateWidgetStyle(); - if (style) - { - gtk_widget_modify_style(list_item, style); - GtkBin *bin = GTK_BIN( list_item ); - GtkWidget *label = bin->child; - gtk_widget_modify_style( label, style ); - gtk_rc_style_unref( style ); - } - - gtk_widget_show( list_item ); - - EnableEvents(); - } + n = pos + i; + // If sorted, use this wxSortedArrayStrings to determine + // the right insertion point + if(m_strings) + n = m_strings->Add(items[i]); - const unsigned int count = GetCount(); + GtkWidget *list_item = gtk_list_item_new_with_label( wxGTK_CONV( items[i] ) ); - if ( m_clientDataList.GetCount() < count ) - m_clientDataList.Append( (wxObject*) NULL ); - if ( m_clientObjectList.GetCount() < count ) - m_clientObjectList.Append( (wxObject*) NULL ); + // TODO construct a list with all items and call gtk_list_insert_items once? + GList *gitem_list = g_list_alloc (); + gitem_list->data = list_item; + gtk_list_insert_items( GTK_LIST (list), gitem_list, n ); - InvalidateBestSize(); - - return count - 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( m_widget != NULL, -1, wxT("invalid combobox") ); - wxCHECK_MSG( IsValidInsert(pos), -1, wxT("invalid index") ); - - unsigned int count = GetCount(); - - if (pos == count) - return Append(item); - -#ifdef __WXGTK24__ - if (!gtk_check_version(2,4,0)) - { - GtkComboBox* combobox = GTK_COMBO_BOX( m_widget ); - gtk_combo_box_insert_text( combobox, pos, wxGTK_CONV( item ) ); - } - else -#endif - { - DisableEvents(); + m_clientData.Insert( NULL, n ); + AssignNewItemClientData(n, clientData, i, type); - GtkWidget *list = GTK_COMBO(m_widget)->list; - GtkWidget *list_item = gtk_list_item_new_with_label( wxGTK_CONV( item ) ); - - GList *gitem_list = g_list_alloc (); - gitem_list->data = list_item; - gtk_list_insert_items( GTK_LIST (list), gitem_list, pos ); + if (GTK_WIDGET_REALIZED(m_widget)) + { + gtk_widget_realize( list_item ); + gtk_widget_realize( GTK_BIN(list_item)->child ); - if (GTK_WIDGET_REALIZED(m_widget)) - { - gtk_widget_realize( list_item ); - gtk_widget_realize( GTK_BIN(list_item)->child ); + ApplyWidgetStyle(); + } - ApplyWidgetStyle(); + gtk_widget_show( list_item ); } - gtk_widget_show( list_item ); - EnableEvents(); } - count = GetCount(); - - if ( m_clientDataList.GetCount() < count ) - m_clientDataList.Insert( pos, (wxObject*) NULL ); - if ( m_clientObjectList.GetCount() < count ) - m_clientObjectList.Insert( pos, (wxObject*) NULL ); - InvalidateBestSize(); - return pos; + return n; } void wxComboBox::DoSetItemClientData(unsigned int n, void* clientData) { - wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") ); - - wxList::compatibility_iterator node = m_clientDataList.Item( n ); - if (!node) return; - - node->SetData( (wxObject*) clientData ); + m_clientData[n] = clientData; } void* wxComboBox::DoGetItemClientData(unsigned int n) const { - wxCHECK_MSG( m_widget != NULL, NULL, wxT("invalid combobox") ); - - wxList::compatibility_iterator node = m_clientDataList.Item( n ); - - return node ? node->GetData() : NULL; + return m_clientData[n]; } -void wxComboBox::DoSetItemClientObject(unsigned int n, wxClientData* clientData) -{ - wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") ); - - wxList::compatibility_iterator node = m_clientObjectList.Item( n ); - if (!node) return; - - // wxItemContainer already deletes data for us - - node->SetData( (wxObject*) clientData ); -} - -wxClientData* wxComboBox::DoGetItemClientObject(unsigned int n) const -{ - wxCHECK_MSG( m_widget != NULL, (wxClientData*)NULL, wxT("invalid combobox") ); - - wxList::compatibility_iterator node = m_clientObjectList.Item( n ); - - return node ? (wxClientData*) node->GetData() : NULL; -} - -void wxComboBox::Clear() +void wxComboBox::DoClear() { wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") ); @@ -566,23 +485,17 @@ void wxComboBox::Clear() gtk_list_clear_items( GTK_LIST(list), 0, GetCount() ); } - wxList::compatibility_iterator node = m_clientObjectList.GetFirst(); - while (node) - { - wxClientData *cd = (wxClientData*)node->GetData(); - delete cd; - node = node->GetNext(); - } - m_clientObjectList.Clear(); + m_clientData.Clear(); - m_clientDataList.Clear(); + if(m_strings) + m_strings->Clear(); EnableEvents(); InvalidateBestSize(); } -void wxComboBox::Delete(unsigned int n) +void wxComboBox::DoDeleteOneItem(unsigned int n) { wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") ); @@ -616,17 +529,9 @@ void wxComboBox::Delete(unsigned int n) EnableEvents(); } - wxList::compatibility_iterator node = m_clientObjectList.Item( n ); - if (node) - { - wxClientData *cd = (wxClientData*)node->GetData(); - if (cd) delete cd; - m_clientObjectList.Erase( node ); - } - - node = m_clientDataList.Item( n ); - if (node) - m_clientDataList.Erase( node ); + m_clientData.RemoveAt( n ); + if(m_strings) + m_strings->RemoveAt( n ); InvalidateBestSize(); } @@ -815,39 +720,6 @@ wxString wxComboBox::GetString(unsigned int n) const return str; } -wxString wxComboBox::GetStringSelection() const -{ - wxCHECK_MSG( m_widget != NULL, wxEmptyString, wxT("invalid combobox") ); - -#ifdef __WXGTK24__ - if (!gtk_check_version(2,4,0)) - { - GtkComboBox* combobox = GTK_COMBO_BOX( m_widget ); - int sel = gtk_combo_box_get_active( combobox ); - if (sel == -1) - return wxEmptyString; - return GetString(sel); - } - else -#endif - { - GtkWidget *list = GTK_COMBO(m_widget)->list; - - GList *selection = GTK_LIST(list)->selection; - if (selection) - { - GtkBin *bin = GTK_BIN( selection->data ); - GtkLabel *label = GTK_LABEL( bin->child ); - wxString tmp( wxGTK_CONV_BACK( gtk_label_get_text(label) ) ); - return tmp; - } - - wxFAIL_MSG( wxT("wxComboBox: no selection") ); - } - - return wxEmptyString; -} - unsigned int wxComboBox::GetCount() const { wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid combobox") ); @@ -880,8 +752,6 @@ unsigned int wxComboBox::GetCount() const } return count; } - - return 0; } void wxComboBox::SetSelection( int n ) @@ -908,266 +778,6 @@ void wxComboBox::SetSelection( int n ) EnableEvents(); } -wxString wxComboBox::GetValue() const -{ - GtkEntry *entry = NULL; -#ifdef __WXGTK24__ - if (!gtk_check_version(2,4,0)) - entry = GTK_ENTRY( GTK_BIN(m_widget)->child ); - else -#endif - entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry ); - - wxString tmp( wxGTK_CONV_BACK( gtk_entry_get_text( entry ) ) ); - -#if 0 - for (int i = 0; i < wxStrlen(tmp.c_str()) +1; i++) - { - wxChar c = tmp[i]; - printf( "%d ", (int) (c) ); - } - printf( "\n" ); -#endif - - return tmp; -} - -void wxComboBox::SetValue( const wxString& value ) -{ - wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") ); - - GtkEntry *entry = NULL; -#ifdef __WXGTK24__ - if (!gtk_check_version(2,4,0)) - entry = GTK_ENTRY( GTK_BIN(m_widget)->child ); - else -#endif - entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry ); - - wxString tmp; - if (!value.IsNull()) tmp = value; - gtk_entry_set_text( entry, wxGTK_CONV( tmp ) ); - - InvalidateBestSize(); -} - -void wxComboBox::Copy() -{ - wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") ); - - GtkEntry *entry = NULL; -#ifdef __WXGTK24__ - if (!gtk_check_version(2,4,0)) - entry = GTK_ENTRY( GTK_BIN(m_widget)->child ); - else -#endif - entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry ); - - gtk_editable_copy_clipboard(GTK_EDITABLE(entry)); -} - -void wxComboBox::Cut() -{ - wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") ); - - GtkEntry *entry = NULL; -#ifdef __WXGTK24__ - if (!gtk_check_version(2,4,0)) - entry = GTK_ENTRY( GTK_BIN(m_widget)->child ); - else -#endif - entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry ); - - gtk_editable_cut_clipboard(GTK_EDITABLE(entry)); -} - -void wxComboBox::Paste() -{ - wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") ); - - GtkEntry *entry = NULL; -#ifdef __WXGTK24__ - if (!gtk_check_version(2,4,0)) - entry = GTK_ENTRY( GTK_BIN(m_widget)->child ); - else -#endif - entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry ); - - gtk_editable_paste_clipboard(GTK_EDITABLE(entry)); -} - -void wxComboBox::Undo() -{ - // TODO -} - -void wxComboBox::Redo() -{ - // TODO -} - -void wxComboBox::SelectAll() -{ - SetSelection(0, GetLastPosition()); -} - -bool wxComboBox::CanUndo() const -{ - // TODO - return false; -} - -bool wxComboBox::CanRedo() const -{ - // TODO - return false; -} - -bool wxComboBox::HasSelection() const -{ - long from, to; - GetSelection(&from, &to); - return from != to; -} - -bool wxComboBox::CanCopy() const -{ - // Can copy if there's a selection - return HasSelection(); -} - -bool wxComboBox::CanCut() const -{ - return CanCopy() && IsEditable(); -} - -bool wxComboBox::CanPaste() const -{ - // TODO: check for text on the clipboard - return IsEditable() ; -} - -bool wxComboBox::IsEditable() const -{ - return !HasFlag(wxCB_READONLY); -} - - -void wxComboBox::SetInsertionPoint( long pos ) -{ - wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") ); - - if ( pos == GetLastPosition() ) - pos = -1; - - GtkEntry *entry = NULL; -#ifdef __WXGTK24__ - if (!gtk_check_version(2,4,0)) - entry = GTK_ENTRY( GTK_BIN(m_widget)->child ); - else -#endif - entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry ); - - gtk_entry_set_position( entry, (int)pos ); -} - -long wxComboBox::GetInsertionPoint() const -{ - GtkEntry *entry = NULL; -#ifdef __WXGTK24__ - if (!gtk_check_version(2,4,0)) - entry = GTK_ENTRY( GTK_BIN(m_widget)->child ); - else -#endif - entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry ); - - return (long) gtk_editable_get_position(GTK_EDITABLE(entry)); -} - -wxTextPos wxComboBox::GetLastPosition() const -{ - GtkEntry *entry = NULL; -#ifdef __WXGTK24__ - if (!gtk_check_version(2,4,0)) - entry = GTK_ENTRY( GTK_BIN(m_widget)->child ); - else -#endif - entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry ); - - int pos = entry->text_length; - return (long) pos-1; -} - -void wxComboBox::Replace( long from, long to, const wxString& value ) -{ - wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") ); - - GtkEntry *entry = NULL; -#ifdef __WXGTK24__ - if (!gtk_check_version(2,4,0)) - entry = GTK_ENTRY( GTK_BIN(m_widget)->child ); - else -#endif - entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry ); - - gtk_editable_delete_text( GTK_EDITABLE(entry), (gint)from, (gint)to ); - if (value.IsNull()) return; - gint pos = (gint)to; - -#if wxUSE_UNICODE - wxCharBuffer buffer = wxConvUTF8.cWX2MB( value ); - gtk_editable_insert_text( GTK_EDITABLE(entry), (const char*) buffer, strlen( (const char*) buffer ), &pos ); -#else - gtk_editable_insert_text( GTK_EDITABLE(entry), value.c_str(), value.length(), &pos ); -#endif -} - -void wxComboBox::SetSelection( long from, long to ) -{ - GtkEntry *entry = NULL; -#ifdef __WXGTK24__ - if (!gtk_check_version(2,4,0)) - entry = GTK_ENTRY( GTK_BIN(m_widget)->child ); - else -#endif - entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry ); - - gtk_editable_select_region( GTK_EDITABLE(entry), (gint)from, (gint)to ); -} - -void wxComboBox::GetSelection( long* from, long* to ) const -{ - GtkEntry *entry = NULL; -#ifdef __WXGTK24__ - if (!gtk_check_version(2,4,0)) - entry = GTK_ENTRY( GTK_BIN(m_widget)->child ); - else -#endif - entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry ); - - if (IsEditable()) - { - GtkEditable *editable = GTK_EDITABLE(entry); - gint start, end; - gtk_editable_get_selection_bounds(editable, & start, & end); - *from = start; - *to = end; - } -} - -void wxComboBox::SetEditable( bool editable ) -{ - GtkEntry *entry = NULL; -#ifdef __WXGTK24__ - if (!gtk_check_version(2,4,0)) - entry = GTK_ENTRY( GTK_BIN(m_widget)->child ); - else -#endif - entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry ); - - gtk_entry_set_editable( GTK_ENTRY(entry), editable ); -} - void wxComboBox::OnChar( wxKeyEvent &event ) { if ( event.GetKeyCode() == WXK_RETURN ) @@ -1209,20 +819,20 @@ void wxComboBox::DisableEvents() #ifdef __WXGTK24__ if (!gtk_check_version(2,4,0)) { - g_signal_handlers_disconnect_by_func (GTK_BIN(m_widget)->child, - (gpointer)gtkcombobox_text_changed_callback, this); + g_signal_handlers_block_by_func(GTK_BIN(m_widget)->child, + (gpointer)gtkcombobox_text_changed_callback, this); - g_signal_handlers_disconnect_by_func (m_widget, - (gpointer)gtkcombobox_changed_callback, this); + g_signal_handlers_block_by_func(m_widget, + (gpointer)gtkcombobox_changed_callback, this); } else #endif { - g_signal_handlers_disconnect_by_func (GTK_COMBO(m_widget)->list, - (gpointer) gtkcombo_combo_select_child_callback, this); + g_signal_handlers_block_by_func(GTK_COMBO(m_widget)->list, + (gpointer) gtkcombo_combo_select_child_callback, this); - g_signal_handlers_disconnect_by_func (GTK_COMBO(m_widget)->entry, - (gpointer) gtkcombo_text_changed_callback, this); + g_signal_handlers_block_by_func(GTK_COMBO(m_widget)->entry, + (gpointer) gtkcombo_text_changed_callback, this); } } @@ -1231,21 +841,20 @@ void wxComboBox::EnableEvents() #ifdef __WXGTK24__ if (!gtk_check_version(2,4,0)) { - g_signal_connect_after (GTK_BIN(m_widget)->child, "changed", - G_CALLBACK (gtkcombobox_text_changed_callback), this); + g_signal_handlers_unblock_by_func(GTK_BIN(m_widget)->child, + (gpointer)gtkcombobox_text_changed_callback, this); - g_signal_connect_after (m_widget, "changed", - G_CALLBACK (gtkcombobox_changed_callback), this); + g_signal_handlers_unblock_by_func(m_widget, + (gpointer)gtkcombobox_changed_callback, this); } else #endif { - g_signal_connect_after (GTK_COMBO(m_widget)->list, "select-child", - G_CALLBACK (gtkcombo_combo_select_child_callback), - this); - g_signal_connect_after (GTK_COMBO(m_widget)->entry, "changed", - G_CALLBACK (gtkcombo_text_changed_callback), - this ); + g_signal_handlers_unblock_by_func(GTK_COMBO(m_widget)->list, + (gpointer) gtkcombo_combo_select_child_callback, this); + + g_signal_handlers_unblock_by_func(GTK_COMBO(m_widget)->entry, + (gpointer) gtkcombo_text_changed_callback, this); } } @@ -1449,4 +1058,4 @@ void wxComboBox::OnUpdateSelectAll(wxUpdateUIEvent& event) event.Enable(GetLastPosition() > 0); } -#endif +#endif // wxUSE_COMBOBOX