]> git.saurik.com Git - wxWidgets.git/commitdiff
1. some fixes for wxSortedArrayString
authorVadim Zeitlin <vadim@wxwidgets.org>
Fri, 22 Oct 1999 13:12:04 +0000 (13:12 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Fri, 22 Oct 1999 13:12:04 +0000 (13:12 +0000)
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
include/wx/gtk1/choice.h
include/wx/string.h
src/common/string.cpp
src/gtk/choice.cpp
src/gtk1/choice.cpp

index b7dd865d98a4151ca9086c2c0a37b275f81248d8..ba5528bbfc8f0f69cc110ff12fcbcec5e9939557 100644 (file)
@@ -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)
 };
 
index b7dd865d98a4151ca9086c2c0a37b275f81248d8..ba5528bbfc8f0f69cc110ff12fcbcec5e9939557 100644 (file)
@@ -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)
 };
 
index 3c642cc6be19944a4cc0714b820dd0fae04c419b..576d9661663cd54ed4e95b8d2a7015b671a398e7 100644 (file)
@@ -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
index 4a667a59cc4fab8883dca6432edb1ebd83218dba..423bb6a7e31d2f71a4d053782e00c2496b182c4a 100644 (file)
@@ -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();
index 81d2380a015c987ef026d3f4df0196a324d7452c..44c8f53503bd68b31ebaa669f21fef8722c1793a 100644 (file)
@@ -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
index 81d2380a015c987ef026d3f4df0196a324d7452c..44c8f53503bd68b31ebaa669f21fef8722c1793a 100644 (file)
@@ -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