+ mode = GTK_SELECTION_MULTIPLE;
+ }
+ else if (style & wxLB_EXTENDED)
+ {
+ mode = GTK_SELECTION_EXTENDED;
+ }
+ else
+ {
+ // if style was 0 set single mode
+ m_windowStyle |= wxLB_SINGLE;
+ mode = GTK_SELECTION_SINGLE;
+ }
+
+ gtk_tree_selection_set_mode( selection, mode );
+
+ // Handle sortable stuff
+ if(style & wxLB_SORT)
+ {
+ // Setup sorting in ascending (wx) order
+ gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(m_liststore),
+ WXLISTBOX_DATACOLUMN,
+ GTK_SORT_ASCENDING);
+
+ // Set the sort callback
+ gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(m_liststore),
+ WXLISTBOX_DATACOLUMN,
+ (GtkTreeIterCompareFunc) gtk_listbox_sort_callback,
+ this, //userdata
+ NULL //"destroy notifier"
+ );
+ }
+
+
+ gtk_container_add (GTK_CONTAINER (m_widget), GTK_WIDGET(m_treeview) );
+
+ gtk_widget_show( GTK_WIDGET(m_treeview) );
+ m_focusWidget = GTK_WIDGET(m_treeview);
+
+ wxListBox::DoInsertItems(wxArrayString(n, choices), 0); // insert initial items
+
+ // generate dclick events
+ g_signal_connect_after(m_treeview, "row-activated",
+ G_CALLBACK(gtk_listbox_row_activated_callback), this);
+
+ m_parent->DoAddChild( this );
+
+ PostCreation(size);
+ SetInitialSize(size); // need this too because this is a wxControlWithItems
+
+ return true;
+}
+
+wxListBox::~wxListBox()
+{
+ m_hasVMT = false;
+
+ Clear();
+}
+
+// ----------------------------------------------------------------------------
+// adding items
+// ----------------------------------------------------------------------------
+
+void wxListBox::GtkInsertItems(const wxArrayString& items,
+ void** clientData, unsigned int pos)
+{
+ wxCHECK_RET( m_treeview != NULL, wxT("invalid listbox") );
+
+ InvalidateBestSize();
+
+ // Create and set column ids and GValues
+
+ unsigned int nNum = items.GetCount();
+ unsigned int nCurCount = wxListBox::GetCount();
+ wxASSERT_MSG(pos <= nCurCount, wxT("Invalid index passed to wxListBox"));
+
+ GtkTreeIter* pIter = NULL; // append by default
+ GtkTreeIter iter;
+ if (pos != nCurCount)
+ {
+ wxCHECK_RET( GtkGetIteratorFor(pos, &iter),
+ wxT("internal wxListBox error in insertion") );
+
+ pIter = &iter;
+ }
+
+ for (unsigned int i = 0; i < nNum; ++i)
+ {
+ wxString label = items[i];
+
+ GtkTreeEntry* entry = gtk_tree_entry_new();
+ gtk_tree_entry_set_label(entry, wxGTK_CONV(label));
+ gtk_tree_entry_set_destroy_func(entry,
+ (GtkTreeEntryDestroy)gtk_tree_entry_destroy_cb,
+ this);
+
+ if (clientData)
+ gtk_tree_entry_set_userdata(entry, clientData[i]);
+
+ GtkTreeIter itercur;
+ gtk_list_store_insert_before(m_liststore, &itercur, pIter);
+
+ GtkSetItem(itercur, entry);
+
+ g_object_unref (entry);
+ }
+}
+
+void wxListBox::DoInsertItems(const wxArrayString& items, unsigned int pos)
+{
+ wxCHECK_RET( IsValidInsert(pos), wxT("invalid index in wxListBox::InsertItems") );
+
+ GtkInsertItems(items, NULL, pos);
+}
+
+int wxListBox::DoAppend( const wxString& item )
+{
+ wxCHECK_MSG( m_treeview != NULL, -1, wxT("invalid listbox") );
+
+ InvalidateBestSize();
+
+ GtkTreeEntry* entry = gtk_tree_entry_new();
+ gtk_tree_entry_set_label( entry, wxGTK_CONV(item) );
+ gtk_tree_entry_set_destroy_func(entry,
+ (GtkTreeEntryDestroy)gtk_tree_entry_destroy_cb,
+ this);
+
+ GtkTreeIter itercur;
+ gtk_list_store_insert_before( m_liststore, &itercur, NULL );
+
+ GtkSetItem(itercur, entry);
+
+ g_object_unref (entry);
+
+ return GtkGetIndexFor(itercur);
+}
+
+void wxListBox::DoSetItems( const wxArrayString& items,
+ void **clientData)
+{
+ Clear();
+ GtkInsertItems(items, clientData, 0);
+}
+
+// ----------------------------------------------------------------------------
+// deleting items
+// ----------------------------------------------------------------------------
+
+void wxListBox::Clear()
+{
+ wxCHECK_RET( m_treeview != NULL, wxT("invalid listbox") );
+
+ InvalidateBestSize();
+
+ gtk_list_store_clear( m_liststore ); /* well, THAT was easy :) */
+}
+
+void wxListBox::Delete(unsigned int n)
+{
+ wxCHECK_RET( m_treeview != NULL, wxT("invalid listbox") );
+
+ InvalidateBestSize();
+
+ GtkTreeIter iter;
+ wxCHECK_RET( GtkGetIteratorFor(n, &iter), wxT("wrong listbox index") );
+
+ // this returns false if iter is invalid (e.g. deleting item at end) but
+ // since we don't use iter, we ignore the return value
+ gtk_list_store_remove(m_liststore, &iter);
+}
+
+// ----------------------------------------------------------------------------
+// helper functions for working with iterators
+// ----------------------------------------------------------------------------
+
+bool wxListBox::GtkGetIteratorFor(unsigned pos, GtkTreeIter *iter) const
+{
+ if ( !gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(m_liststore),
+ iter, NULL, pos) )
+ {
+ wxLogDebug(wxT("gtk_tree_model_iter_nth_child(%u) failed"), pos);
+ return false;