From e01c8145b13461ab46a1d24ce51f0ec60420d4d9 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 22 Oct 1999 13:12:04 +0000 Subject: [PATCH] 1. some fixes for wxSortedArrayString 2. wxChoice understands wxCB_SORT under GTK git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@4135 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/gtk/choice.h | 13 ++++- include/wx/gtk1/choice.h | 13 ++++- include/wx/string.h | 5 +- src/common/string.cpp | 10 ++-- src/gtk/choice.cpp | 102 ++++++++++++++++++++++++++------------- src/gtk1/choice.cpp | 102 ++++++++++++++++++++++++++------------- 6 files changed, 169 insertions(+), 76 deletions(-) diff --git a/include/wx/gtk/choice.h b/include/wx/gtk/choice.h index b7dd865d98..ba5528bbfc 100644 --- a/include/wx/gtk/choice.h +++ b/include/wx/gtk/choice.h @@ -30,6 +30,8 @@ public: const wxValidator& validator = wxDefaultValidator, const wxString& name = wxChoiceNameStr ) { + m_strings = (wxSortedArrayString *)NULL; + Create(parent, id, pos, size, n, choices, style, validator, name); } ~wxChoice(); @@ -53,13 +55,13 @@ public: 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); @@ -79,6 +81,13 @@ protected: { 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) }; diff --git a/include/wx/gtk1/choice.h b/include/wx/gtk1/choice.h index b7dd865d98..ba5528bbfc 100644 --- a/include/wx/gtk1/choice.h +++ b/include/wx/gtk1/choice.h @@ -30,6 +30,8 @@ public: const wxValidator& validator = wxDefaultValidator, const wxString& name = wxChoiceNameStr ) { + m_strings = (wxSortedArrayString *)NULL; + Create(parent, id, pos, size, n, choices, style, validator, name); } ~wxChoice(); @@ -53,13 +55,13 @@ public: 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); @@ -79,6 +81,13 @@ protected: { 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) }; diff --git a/include/wx/string.h b/include/wx/string.h index 3c642cc6be..576d966166 100644 --- a/include/wx/string.h +++ b/include/wx/string.h @@ -912,8 +912,9 @@ public: // 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 diff --git a/src/common/string.cpp b/src/common/string.cpp index 4a667a59cc..423bb6a7e3 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -1844,7 +1844,7 @@ int wxArrayString::Index(const wxChar *sz, bool bCase, bool bFromEnd) const } // 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 @@ -1869,6 +1869,8 @@ void wxArrayString::Add(const wxString& str) wxASSERT_MSG( lo == hi, wxT("binary search broken") ); Insert(str, lo); + + return (size_t)lo; } else { wxASSERT( str.GetStringData()->IsValid() ); @@ -1879,7 +1881,9 @@ void wxArrayString::Add(const wxString& str) 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++; } } @@ -1888,8 +1892,6 @@ void wxArrayString::Insert(const wxString& str, size_t nIndex) { 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(); diff --git a/src/gtk/choice.cpp b/src/gtk/choice.cpp index 81d2380a01..44c8f53503 100644 --- a/src/gtk/choice.cpp +++ b/src/gtk/choice.cpp @@ -38,7 +38,7 @@ extern bool g_blockEventsOnDrag; 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; @@ -60,6 +60,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxChoice,wxControl) wxChoice::wxChoice() { + m_strings = (wxSortedArrayString *)NULL; } bool wxChoice::Create( wxWindow *parent, wxWindowID id, @@ -76,7 +77,7 @@ 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(); @@ -88,20 +89,20 @@ bool wxChoice::Create( wxWindow *parent, wxWindowID id, 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 ); @@ -120,6 +121,8 @@ bool wxChoice::Create( wxWindow *parent, wxWindowID id, wxChoice::~wxChoice() { Clear(); + + delete m_strings; } int wxChoice::DoAppend( const wxString &item ) @@ -127,27 +130,8 @@ 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 ) @@ -204,13 +188,13 @@ void wxChoice::Clear() 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(); } @@ -374,4 +358,56 @@ void wxChoice::ApplyWidgetStyle() } } +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 diff --git a/src/gtk1/choice.cpp b/src/gtk1/choice.cpp index 81d2380a01..44c8f53503 100644 --- a/src/gtk1/choice.cpp +++ b/src/gtk1/choice.cpp @@ -38,7 +38,7 @@ extern bool g_blockEventsOnDrag; 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; @@ -60,6 +60,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxChoice,wxControl) wxChoice::wxChoice() { + m_strings = (wxSortedArrayString *)NULL; } bool wxChoice::Create( wxWindow *parent, wxWindowID id, @@ -76,7 +77,7 @@ 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(); @@ -88,20 +89,20 @@ bool wxChoice::Create( wxWindow *parent, wxWindowID id, 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 ); @@ -120,6 +121,8 @@ bool wxChoice::Create( wxWindow *parent, wxWindowID id, wxChoice::~wxChoice() { Clear(); + + delete m_strings; } int wxChoice::DoAppend( const wxString &item ) @@ -127,27 +130,8 @@ 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 ) @@ -204,13 +188,13 @@ void wxChoice::Clear() 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(); } @@ -374,4 +358,56 @@ void wxChoice::ApplyWidgetStyle() } } +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 -- 2.45.2