]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/combobox.cpp
Fixed refresh bug on early versions of MacOS X by
[wxWidgets.git] / src / gtk / combobox.cpp
CommitLineData
53010e52
RR
1/////////////////////////////////////////////////////////////////////////////
2// Name: combobox.cpp
3// Purpose:
4// Author: Robert Roebling
dbf858b5 5// Id: $Id$
01111366 6// Copyright: (c) 1998 Robert Roebling
805dd538 7// Licence: wxWindows licence
53010e52
RR
8/////////////////////////////////////////////////////////////////////////////
9
10#ifdef __GNUG__
11#pragma implementation "combobox.h"
12#endif
13
14#include "wx/combobox.h"
dcf924a3
RR
15
16#if wxUSE_COMBOBOX
17
72a16063 18#include "wx/settings.h"
b62c3631 19#include "wx/intl.h"
53010e52 20
78bcfcfc
VZ
21#include "wx/textctrl.h" // for wxEVT_COMMAND_TEXT_UPDATED
22
9e691f46 23#include "wx/gtk/private.h"
83624f79 24
acfd422a
RR
25//-----------------------------------------------------------------------------
26// idle system
27//-----------------------------------------------------------------------------
28
29extern void wxapp_install_idle_handler();
30extern bool g_isIdle;
31
47908e25
RR
32//-----------------------------------------------------------------------------
33// data
34//-----------------------------------------------------------------------------
35
36extern bool g_blockEventsOnDrag;
37
53010e52 38//-----------------------------------------------------------------------------
e1e955e1 39// "select"
47908e25 40//-----------------------------------------------------------------------------
47908e25 41
8a85884a
VZ
42static void
43gtk_combo_clicked_callback( GtkWidget *WXUNUSED(widget), wxComboBox *combo )
53010e52 44{
acfd422a 45 if (g_isIdle) wxapp_install_idle_handler();
8a85884a 46
a2053b27 47 if (!combo->m_hasVMT) return;
acfd422a
RR
48
49 if (g_blockEventsOnDrag) return;
805dd538 50
fd0eed64
RR
51 if (combo->m_alreadySent)
52 {
53 combo->m_alreadySent = FALSE;
54 return;
55 }
47908e25 56
fd0eed64 57 combo->m_alreadySent = TRUE;
805dd538 58
159b66c0
RR
59 int curSelection = combo->GetSelection();
60
61 if (combo->m_prevSelection != curSelection)
62 {
63 GtkWidget *list = GTK_COMBO(combo->m_widget)->list;
64 gtk_list_unselect_item( GTK_LIST(list), combo->m_prevSelection );
65 }
66
67 combo->m_prevSelection = curSelection;
68
8a85884a 69 wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, combo->GetId() );
159b66c0 70 event.SetInt( curSelection );
29006414 71 event.SetString( combo->GetStringSelection() );
8a85884a 72 event.SetEventObject( combo );
31528cd3 73
8a85884a 74 combo->GetEventHandler()->ProcessEvent( event );
6de97a3b 75}
47908e25 76
0c77152e
RR
77//-----------------------------------------------------------------------------
78// "changed"
79//-----------------------------------------------------------------------------
80
eeccd5d9 81static void
0c77152e
RR
82gtk_text_changed_callback( GtkWidget *WXUNUSED(widget), wxComboBox *combo )
83{
acfd422a 84 if (g_isIdle) wxapp_install_idle_handler();
31528cd3 85
a2053b27
RR
86 if (!combo->m_hasVMT) return;
87
8a85884a 88 wxCommandEvent event( wxEVT_COMMAND_TEXT_UPDATED, combo->GetId() );
29006414 89 event.SetString( combo->GetValue() );
0c77152e
RR
90 event.SetEventObject( combo );
91 combo->GetEventHandler()->ProcessEvent( event );
0c77152e
RR
92}
93
e1e955e1
RR
94//-----------------------------------------------------------------------------
95// wxComboBox
53010e52
RR
96//-----------------------------------------------------------------------------
97
98IMPLEMENT_DYNAMIC_CLASS(wxComboBox,wxControl)
99
b4071e91 100BEGIN_EVENT_TABLE(wxComboBox, wxControl)
fd0eed64 101 EVT_SIZE(wxComboBox::OnSize)
8a85884a 102 EVT_CHAR(wxComboBox::OnChar)
b4071e91
RR
103END_EVENT_TABLE()
104
fd0eed64
RR
105bool wxComboBox::Create( wxWindow *parent, wxWindowID id, const wxString& value,
106 const wxPoint& pos, const wxSize& size,
107 int n, const wxString choices[],
805dd538
VZ
108 long style, const wxValidator& validator,
109 const wxString& name )
53010e52 110{
fd0eed64
RR
111 m_alreadySent = FALSE;
112 m_needParent = TRUE;
b292e2f5 113 m_acceptsFocus = TRUE;
159b66c0 114 m_prevSelection = 0;
805dd538 115
db434467 116 if (!PreCreation( parent, pos, size ) ||
4dcaf11a
RR
117 !CreateBase( parent, id, pos, size, style, validator, name ))
118 {
223d09f6 119 wxFAIL_MSG( wxT("wxComboBox creation failed") );
9d9b7755 120 return FALSE;
4dcaf11a 121 }
6de97a3b 122
fd0eed64 123 m_widget = gtk_combo_new();
805dd538 124
8a85884a 125 // make it more useable
3ca6a5f0
BP
126 gtk_combo_set_use_arrows_always( GTK_COMBO(m_widget), TRUE );
127
128 // and case-sensitive
129 gtk_combo_set_case_sensitive( GTK_COMBO(m_widget), TRUE );
130
8a85884a 131
fd0eed64 132 GtkWidget *list = GTK_COMBO(m_widget)->list;
805dd538 133
2e1d7104 134#ifndef __WXGTK20__
81a0614b 135 // gtk_list_set_selection_mode( GTK_LIST(list), GTK_SELECTION_MULTIPLE );
2e1d7104 136#endif
159b66c0 137
fd0eed64
RR
138 for (int i = 0; i < n; i++)
139 {
19da4326 140 /* don't send first event, which GTK sends aways when
9d9b7755 141 inserting the first item */
19da4326 142 m_alreadySent = TRUE;
31528cd3 143
fab591c5 144 GtkWidget *list_item = gtk_list_item_new_with_label( wxGTK_CONV( choices[i] ) );
805dd538 145
fd0eed64 146 m_clientDataList.Append( (wxObject*)NULL );
f5e27805 147 m_clientObjectList.Append( (wxObject*)NULL );
805dd538 148
fd0eed64 149 gtk_container_add( GTK_CONTAINER(list), list_item );
805dd538 150
805dd538 151 gtk_signal_connect( GTK_OBJECT(list_item), "select",
19da4326
RR
152 GTK_SIGNAL_FUNC(gtk_combo_clicked_callback), (gpointer)this );
153
154 gtk_widget_show( list_item );
fd0eed64 155 }
805dd538 156
f03fc89f 157 m_parent->DoAddChild( this );
76fcf0f2
RR
158
159 m_focusWidget = GTK_COMBO(m_widget)->entry;
805dd538 160
fd0eed64 161 PostCreation();
53010e52 162
fd0eed64 163 ConnectWidget( GTK_COMBO(m_widget)->button );
805dd538 164
fd0eed64 165 if (!value.IsNull()) SetValue( value );
805dd538 166
a260fe6a
RR
167 if (style & wxCB_READONLY)
168 gtk_entry_set_editable( GTK_ENTRY( GTK_COMBO(m_widget)->entry ), FALSE );
169
0c77152e
RR
170 gtk_signal_connect( GTK_OBJECT(GTK_COMBO(m_widget)->entry), "changed",
171 GTK_SIGNAL_FUNC(gtk_text_changed_callback), (gpointer)this);
805dd538 172
db434467
RR
173 wxSize size_best( DoGetBestSize() );
174 wxSize new_size( size );
175 if (new_size.x == -1)
176 new_size.x = size_best.x;
177 if (new_size.y == -1)
178 new_size.y = size_best.y;
179 if (new_size.y > size_best.y)
180 new_size.y = size_best.y;
181 if ((new_size.x != size.x) || (new_size.y != size.y))
4494ad58 182 {
db434467 183 SetSize( new_size.x, new_size.y );
4494ad58
RR
184
185 // This is required for tool bar support
186 gtk_widget_set_usize( m_widget, new_size.x, new_size.y );
187 }
188
db434467 189
a756f210 190 SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
fd0eed64 191 SetForegroundColour( parent->GetForegroundColour() );
f96aa4d9 192
fd0eed64 193 Show( TRUE );
805dd538 194
fd0eed64
RR
195 return TRUE;
196}
197
198wxComboBox::~wxComboBox()
199{
b1d4dd7a 200 wxNode *node = m_clientObjectList.GetFirst();
fd0eed64
RR
201 while (node)
202 {
b1d4dd7a 203 wxClientData *cd = (wxClientData*)node->GetData();
fd0eed64 204 if (cd) delete cd;
b1d4dd7a 205 node = node->GetNext();
fd0eed64 206 }
7d6d2cd4
RR
207 m_clientObjectList.Clear();
208
fd0eed64 209 m_clientDataList.Clear();
6de97a3b 210}
53010e52 211
2b5f62a0
VZ
212void wxComboBox::SetFocus()
213{
214 if ( m_hasFocus )
215 {
216 // don't do anything if we already have focus
217 return;
218 }
219
220 gtk_widget_grab_focus( m_focusWidget );
221}
222
fd0eed64 223void wxComboBox::AppendCommon( const wxString &item )
53010e52 224{
223d09f6 225 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 226
fd0eed64 227 GtkWidget *list = GTK_COMBO(m_widget)->list;
805dd538 228
fab591c5 229 GtkWidget *list_item = gtk_list_item_new_with_label( wxGTK_CONV( item ) );
805dd538 230
ec5d85fb
RR
231 gtk_container_add( GTK_CONTAINER(list), list_item );
232
805dd538 233 gtk_signal_connect( GTK_OBJECT(list_item), "select",
fd0eed64 234 GTK_SIGNAL_FUNC(gtk_combo_clicked_callback), (gpointer)this );
805dd538 235
2b07d713
RR
236 if (GTK_WIDGET_REALIZED(m_widget))
237 {
238 gtk_widget_realize( list_item );
239 gtk_widget_realize( GTK_BIN(list_item)->child );
240
241 if (m_widgetStyle) ApplyWidgetStyle();
242 }
805dd538 243
fd0eed64 244 gtk_widget_show( list_item );
6de97a3b 245}
53010e52
RR
246
247void wxComboBox::Append( const wxString &item )
47908e25 248{
f5e27805
RR
249 m_clientDataList.Append( (wxObject*) NULL );
250 m_clientObjectList.Append( (wxObject*) NULL );
805dd538 251
fd0eed64 252 AppendCommon( item );
6de97a3b 253}
47908e25 254
fd0eed64 255void wxComboBox::Append( const wxString &item, void *clientData )
53010e52 256{
f5e27805
RR
257 m_clientDataList.Append( (wxObject*) clientData );
258 m_clientObjectList.Append( (wxObject*)NULL );
805dd538 259
fd0eed64 260 AppendCommon( item );
6de97a3b 261}
53010e52 262
fd0eed64 263void wxComboBox::Append( const wxString &item, wxClientData *clientData )
53010e52 264{
f5e27805
RR
265 m_clientDataList.Append( (wxObject*) NULL );
266 m_clientObjectList.Append( (wxObject*) clientData );
805dd538 267
fd0eed64
RR
268 AppendCommon( item );
269}
270
271void wxComboBox::SetClientData( int n, void* clientData )
272{
223d09f6 273 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 274
b1d4dd7a 275 wxNode *node = m_clientDataList.Item( n );
fd0eed64 276 if (!node) return;
805dd538 277
f5e27805 278 node->SetData( (wxObject*) clientData );
6de97a3b 279}
53010e52 280
fd0eed64 281void* wxComboBox::GetClientData( int n )
53010e52 282{
223d09f6 283 wxCHECK_MSG( m_widget != NULL, NULL, wxT("invalid combobox") );
805dd538 284
b1d4dd7a 285 wxNode *node = m_clientDataList.Item( n );
fd0eed64 286 if (!node) return NULL;
805dd538 287
b1d4dd7a 288 return node->GetData();
fd0eed64
RR
289}
290
291void wxComboBox::SetClientObject( int n, wxClientData* clientData )
292{
223d09f6 293 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 294
b1d4dd7a 295 wxNode *node = m_clientObjectList.Item( n );
fd0eed64 296 if (!node) return;
805dd538 297
b1d4dd7a 298 wxClientData *cd = (wxClientData*) node->GetData();
fd0eed64 299 if (cd) delete cd;
805dd538 300
fd0eed64 301 node->SetData( (wxObject*) clientData );
6de97a3b 302}
53010e52 303
fd0eed64 304wxClientData* wxComboBox::GetClientObject( int n )
53010e52 305{
223d09f6 306 wxCHECK_MSG( m_widget != NULL, (wxClientData*)NULL, wxT("invalid combobox") );
805dd538 307
b1d4dd7a 308 wxNode *node = m_clientObjectList.Item( n );
fd0eed64 309 if (!node) return (wxClientData*) NULL;
805dd538 310
b1d4dd7a 311 return (wxClientData*) node->GetData();
fd0eed64
RR
312}
313
314void wxComboBox::Clear()
315{
223d09f6 316 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 317
fd0eed64
RR
318 GtkWidget *list = GTK_COMBO(m_widget)->list;
319 gtk_list_clear_items( GTK_LIST(list), 0, Number() );
805dd538 320
b1d4dd7a 321 wxNode *node = m_clientObjectList.GetFirst();
fd0eed64
RR
322 while (node)
323 {
b1d4dd7a 324 wxClientData *cd = (wxClientData*)node->GetData();
fd0eed64 325 if (cd) delete cd;
b1d4dd7a 326 node = node->GetNext();
fd0eed64 327 }
f5e27805 328 m_clientObjectList.Clear();
805dd538 329
fd0eed64 330 m_clientDataList.Clear();
6de97a3b 331}
53010e52 332
fd0eed64 333void wxComboBox::Delete( int n )
53010e52 334{
223d09f6 335 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 336
fd0eed64 337 GtkList *listbox = GTK_LIST( GTK_COMBO(m_widget)->list );
805dd538 338
fd0eed64 339 GList *child = g_list_nth( listbox->children, n );
805dd538 340
fd0eed64
RR
341 if (!child)
342 {
223d09f6 343 wxFAIL_MSG(wxT("wrong index"));
fd0eed64
RR
344 return;
345 }
805dd538 346
bbe0af5b 347 GList *list = g_list_append( (GList*) NULL, child->data );
fd0eed64
RR
348 gtk_list_remove_items( listbox, list );
349 g_list_free( list );
805dd538 350
b1d4dd7a 351 wxNode *node = m_clientObjectList.Item( n );
f5e27805 352 if (node)
fd0eed64 353 {
b1d4dd7a 354 wxClientData *cd = (wxClientData*)node->GetData();
fd0eed64 355 if (cd) delete cd;
f5e27805
RR
356 m_clientObjectList.DeleteNode( node );
357 }
805dd538 358
b1d4dd7a 359 node = m_clientDataList.Item( n );
f5e27805
RR
360 if (node)
361 {
fd0eed64
RR
362 m_clientDataList.DeleteNode( node );
363 }
6de97a3b 364}
53010e52 365
fd0eed64 366int wxComboBox::FindString( const wxString &item )
53010e52 367{
223d09f6 368 wxCHECK_MSG( m_widget != NULL, -1, wxT("invalid combobox") );
805dd538 369
fd0eed64 370 GtkWidget *list = GTK_COMBO(m_widget)->list;
805dd538 371
53010e52
RR
372 GList *child = GTK_LIST(list)->children;
373 int count = 0;
374 while (child)
375 {
fd0eed64
RR
376 GtkBin *bin = GTK_BIN( child->data );
377 GtkLabel *label = GTK_LABEL( bin->child );
2b5f62a0
VZ
378#ifdef __WXGTK20__
379 wxString str( wxGTK_CONV_BACK( gtk_label_get_text(label) ) );
380#else
381 wxString str( label->label );
382#endif
383 if (item == str)
7cf8cb48 384 return count;
2b5f62a0 385
fd0eed64
RR
386 count++;
387 child = child->next;
388 }
805dd538 389
7cf8cb48 390 return wxNOT_FOUND;
fd0eed64
RR
391}
392
393int wxComboBox::GetSelection() const
394{
223d09f6 395 wxCHECK_MSG( m_widget != NULL, -1, wxT("invalid combobox") );
805dd538 396
fd0eed64 397 GtkWidget *list = GTK_COMBO(m_widget)->list;
805dd538 398
fd0eed64
RR
399 GList *selection = GTK_LIST(list)->selection;
400 if (selection)
401 {
402 GList *child = GTK_LIST(list)->children;
403 int count = 0;
404 while (child)
405 {
406 if (child->data == selection->data) return count;
407 count++;
408 child = child->next;
409 }
6de97a3b 410 }
805dd538 411
fd0eed64 412 return -1;
6de97a3b 413}
53010e52 414
debe6624 415wxString wxComboBox::GetString( int n ) const
53010e52 416{
223d09f6 417 wxCHECK_MSG( m_widget != NULL, wxT(""), wxT("invalid combobox") );
805dd538 418
fd0eed64 419 GtkWidget *list = GTK_COMBO(m_widget)->list;
805dd538 420
7cf8cb48 421 wxString str;
fd0eed64
RR
422 GList *child = g_list_nth( GTK_LIST(list)->children, n );
423 if (child)
424 {
425 GtkBin *bin = GTK_BIN( child->data );
426 GtkLabel *label = GTK_LABEL( bin->child );
2e1d7104 427#ifdef __WXGTK20__
2b5f62a0 428 str = wxGTK_CONV_BACK( gtk_label_get_text(label) );
2e1d7104
RR
429#else
430 str = wxString( label->label );
431#endif
7cf8cb48
VZ
432 }
433 else
434 {
223d09f6 435 wxFAIL_MSG( wxT("wxComboBox: wrong index") );
fd0eed64 436 }
805dd538 437
7cf8cb48 438 return str;
6de97a3b 439}
53010e52 440
fd0eed64 441wxString wxComboBox::GetStringSelection() const
53010e52 442{
223d09f6 443 wxCHECK_MSG( m_widget != NULL, wxT(""), wxT("invalid combobox") );
805dd538 444
fd0eed64 445 GtkWidget *list = GTK_COMBO(m_widget)->list;
805dd538 446
fd0eed64
RR
447 GList *selection = GTK_LIST(list)->selection;
448 if (selection)
449 {
450 GtkBin *bin = GTK_BIN( selection->data );
2b5f62a0
VZ
451 GtkLabel *label = GTK_LABEL( bin->child );
452#ifdef __WXGTK20__
453 wxString tmp( wxGTK_CONV_BACK( gtk_label_get_text(label) ) );
454#else
455 wxString tmp( label->label );
456#endif
fd0eed64
RR
457 return tmp;
458 }
805dd538 459
223d09f6 460 wxFAIL_MSG( wxT("wxComboBox: no selection") );
805dd538 461
223d09f6 462 return wxT("");
6de97a3b 463}
53010e52 464
fd0eed64 465int wxComboBox::Number() const
53010e52 466{
223d09f6 467 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid combobox") );
805dd538 468
fd0eed64 469 GtkWidget *list = GTK_COMBO(m_widget)->list;
805dd538 470
fd0eed64
RR
471 GList *child = GTK_LIST(list)->children;
472 int count = 0;
473 while (child) { count++; child = child->next; }
474 return count;
6de97a3b 475}
53010e52 476
debe6624 477void wxComboBox::SetSelection( int n )
53010e52 478{
223d09f6 479 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 480
953704c1
RR
481 DisableEvents();
482
fd0eed64 483 GtkWidget *list = GTK_COMBO(m_widget)->list;
159b66c0 484 gtk_list_unselect_item( GTK_LIST(list), m_prevSelection );
fd0eed64 485 gtk_list_select_item( GTK_LIST(list), n );
159b66c0 486 m_prevSelection = n;
953704c1
RR
487
488 EnableEvents();
6de97a3b 489}
53010e52 490
47908e25
RR
491void wxComboBox::SetStringSelection( const wxString &string )
492{
223d09f6 493 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 494
fd0eed64
RR
495 int res = FindString( string );
496 if (res == -1) return;
497 SetSelection( res );
6de97a3b 498}
47908e25 499
fd0eed64 500wxString wxComboBox::GetValue() const
53010e52 501{
2e1d7104
RR
502 GtkEntry *entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry );
503 wxString tmp( wxGTK_CONV_BACK( gtk_entry_get_text( entry ) ) );
504
505#if 0
506 for (int i = 0; i < wxStrlen(tmp.c_str()) +1; i++)
507 {
508 wxChar c = tmp[i];
509 printf( "%d ", (int) (c) );
510 }
511 printf( "\n" );
512#endif
513
fd0eed64 514 return tmp;
6de97a3b 515}
53010e52
RR
516
517void wxComboBox::SetValue( const wxString& value )
518{
223d09f6 519 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 520
fd0eed64 521 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
223d09f6 522 wxString tmp = wxT("");
fd0eed64 523 if (!value.IsNull()) tmp = value;
fab591c5 524 gtk_entry_set_text( GTK_ENTRY(entry), wxGTK_CONV( tmp ) );
6de97a3b 525}
53010e52 526
fd0eed64 527void wxComboBox::Copy()
53010e52 528{
223d09f6 529 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 530
fd0eed64 531 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
9e691f46 532 gtk_editable_copy_clipboard( GTK_EDITABLE(entry) DUMMY_CLIPBOARD_ARG );
6de97a3b 533}
53010e52 534
fd0eed64 535void wxComboBox::Cut()
53010e52 536{
223d09f6 537 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 538
fd0eed64 539 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
9e691f46 540 gtk_editable_cut_clipboard( GTK_EDITABLE(entry) DUMMY_CLIPBOARD_ARG );
6de97a3b 541}
53010e52 542
fd0eed64 543void wxComboBox::Paste()
53010e52 544{
223d09f6 545 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 546
fd0eed64 547 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
9e691f46 548 gtk_editable_paste_clipboard( GTK_EDITABLE(entry) DUMMY_CLIPBOARD_ARG);
6de97a3b 549}
53010e52 550
debe6624 551void wxComboBox::SetInsertionPoint( long pos )
53010e52 552{
223d09f6 553 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 554
fd0eed64 555 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
073c8fe9 556 gtk_entry_set_position( GTK_ENTRY(entry), (int)pos );
6de97a3b 557}
53010e52 558
fd0eed64 559void wxComboBox::SetInsertionPointEnd()
53010e52 560{
223d09f6 561 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538
VZ
562
563 SetInsertionPoint( -1 );
6de97a3b 564}
53010e52 565
fd0eed64 566long wxComboBox::GetInsertionPoint() const
53010e52 567{
9e691f46 568 return (long) GET_EDITABLE_POS( GTK_COMBO(m_widget)->entry );
6de97a3b 569}
53010e52 570
fd0eed64 571long wxComboBox::GetLastPosition() const
53010e52 572{
fd0eed64
RR
573 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
574 int pos = GTK_ENTRY(entry)->text_length;
575 return (long) pos-1;
6de97a3b 576}
53010e52 577
debe6624 578void wxComboBox::Replace( long from, long to, const wxString& value )
53010e52 579{
223d09f6 580 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 581
fd0eed64
RR
582 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
583 gtk_editable_delete_text( GTK_EDITABLE(entry), (gint)from, (gint)to );
584 if (value.IsNull()) return;
585 gint pos = (gint)to;
2e1d7104
RR
586
587#if wxUSE_UNICODE
588 wxCharBuffer buffer = wxConvUTF8.cWX2MB( value );
589 gtk_editable_insert_text( GTK_EDITABLE(entry), (const char*) buffer, strlen( (const char*) buffer ), &pos );
590#else
591 gtk_editable_insert_text( GTK_EDITABLE(entry), value.c_str(), value.Length(), &pos );
592#endif
6de97a3b 593}
53010e52 594
debe6624 595void wxComboBox::Remove(long from, long to)
53010e52 596{
223d09f6 597 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 598
fd0eed64
RR
599 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
600 gtk_editable_delete_text( GTK_EDITABLE(entry), (gint)from, (gint)to );
6de97a3b 601}
53010e52 602
20d10ee1 603void wxComboBox::SetSelection( long from, long to )
53010e52 604{
20d10ee1
VZ
605 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
606 gtk_editable_select_region( GTK_EDITABLE(entry), (gint)from, (gint)to );
6de97a3b 607}
53010e52 608
20d10ee1 609void wxComboBox::SetEditable( bool editable )
53010e52 610{
20d10ee1
VZ
611 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
612 gtk_entry_set_editable( GTK_ENTRY(entry), editable );
b4071e91
RR
613}
614
8a85884a
VZ
615void wxComboBox::OnChar( wxKeyEvent &event )
616{
12a3f227 617 if ( event.GetKeyCode() == WXK_RETURN )
8a85884a 618 {
7cf8cb48 619 wxString value = GetValue();
8a85884a 620
7cf8cb48
VZ
621 if ( Number() == 0 )
622 {
623 // make Enter generate "selected" event if there is only one item
624 // in the combobox - without it, it's impossible to select it at
625 // all!
626 wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, GetId() );
627 event.SetInt( 0 );
29006414 628 event.SetString( value );
7cf8cb48
VZ
629 event.SetEventObject( this );
630 GetEventHandler()->ProcessEvent( event );
631 }
632 else
633 {
634 // add the item to the list if it's not there yet
635 if ( FindString(value) == wxNOT_FOUND )
636 {
637 Append(value);
f6bcfd97 638 SetStringSelection(value);
7cf8cb48
VZ
639
640 // and generate the selected event for it
641 wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, GetId() );
642 event.SetInt( Number() - 1 );
29006414 643 event.SetString( value );
7cf8cb48
VZ
644 event.SetEventObject( this );
645 GetEventHandler()->ProcessEvent( event );
646 }
ea46eba0
RR
647
648 // This will invoke the dialog default action, such
649 // as the clicking the default button.
650
651 wxWindow *top_frame = m_parent;
652 while (top_frame->GetParent() && !(top_frame->IsTopLevel()))
653 top_frame = top_frame->GetParent();
2b328fc9 654
ea46eba0
RR
655 if (top_frame && GTK_IS_WINDOW(top_frame->m_widget))
656 {
657 GtkWindow *window = GTK_WINDOW(top_frame->m_widget);
2b328fc9 658
ea46eba0
RR
659 if (window->default_widget)
660 {
661 gtk_widget_activate (window->default_widget);
662 return;
2b328fc9
RR
663 }
664 }
ea46eba0
RR
665
666 return;
7cf8cb48 667 }
8a85884a 668 }
ea46eba0 669
7cf8cb48 670 event.Skip();
8a85884a
VZ
671}
672
953704c1
RR
673void wxComboBox::DisableEvents()
674{
675 GtkList *list = GTK_LIST( GTK_COMBO(m_widget)->list );
676 GList *child = list->children;
677 while (child)
678 {
31528cd3 679 gtk_signal_disconnect_by_func( GTK_OBJECT(child->data),
953704c1
RR
680 GTK_SIGNAL_FUNC(gtk_combo_clicked_callback), (gpointer)this );
681
682 child = child->next;
683 }
684}
685
686void wxComboBox::EnableEvents()
687{
688 GtkList *list = GTK_LIST( GTK_COMBO(m_widget)->list );
689 GList *child = list->children;
690 while (child)
691 {
692 gtk_signal_connect( GTK_OBJECT(child->data), "select",
693 GTK_SIGNAL_FUNC(gtk_combo_clicked_callback), (gpointer)this );
694
695 child = child->next;
696 }
697}
698
b4071e91
RR
699void wxComboBox::OnSize( wxSizeEvent &event )
700{
f03fc89f 701 event.Skip();
31528cd3 702
b02da6b1 703#if 0
fd0eed64
RR
704 int w = 21;
705 gtk_widget_set_usize( GTK_COMBO(m_widget)->entry, m_width-w-1, m_height );
805dd538 706
fd0eed64
RR
707 gtk_widget_set_uposition( GTK_COMBO(m_widget)->button, m_x+m_width-w, m_y );
708 gtk_widget_set_usize( GTK_COMBO(m_widget)->button, w, m_height );
b02da6b1 709#endif // 0
6de97a3b 710}
53010e52 711
58614078 712void wxComboBox::ApplyWidgetStyle()
868a2826 713{
fd0eed64 714 SetWidgetStyle();
805dd538 715
72a16063 716// gtk_widget_set_style( GTK_COMBO(m_widget)->button, m_widgetStyle );
fd0eed64
RR
717 gtk_widget_set_style( GTK_COMBO(m_widget)->entry, m_widgetStyle );
718 gtk_widget_set_style( GTK_COMBO(m_widget)->list, m_widgetStyle );
805dd538 719
fd0eed64
RR
720 GtkList *list = GTK_LIST( GTK_COMBO(m_widget)->list );
721 GList *child = list->children;
722 while (child)
723 {
724 gtk_widget_set_style( GTK_WIDGET(child->data), m_widgetStyle );
805dd538 725
fd0eed64
RR
726 GtkBin *bin = GTK_BIN(child->data);
727 gtk_widget_set_style( bin->child, m_widgetStyle );
805dd538 728
fd0eed64
RR
729 child = child->next;
730 }
868a2826 731}
b4071e91 732
fd0eed64 733GtkWidget* wxComboBox::GetConnectWidget()
97b3455a 734{
fd0eed64 735 return GTK_COMBO(m_widget)->entry;
97b3455a
RR
736}
737
b4071e91
RR
738bool wxComboBox::IsOwnGtkWindow( GdkWindow *window )
739{
fd0eed64
RR
740 return ( (window == GTK_ENTRY( GTK_COMBO(m_widget)->entry )->text_area) ||
741 (window == GTK_COMBO(m_widget)->button->window ) );
b4071e91 742}
ac57418f 743
f68586e5
VZ
744wxSize wxComboBox::DoGetBestSize() const
745{
db434467 746 wxSize ret( wxControl::DoGetBestSize() );
a6fc8ae3
VZ
747
748 // we know better our horizontal extent: it depends on the longest string
749 // in the combobox
750 ret.x = 0;
751 if ( m_widget )
752 {
60d85ccb
RR
753 int width;
754 size_t count = GetCount();
a6fc8ae3
VZ
755 for ( size_t n = 0; n < count; n++ )
756 {
60d85ccb 757 GetTextExtent( GetString(n), &width, NULL, NULL, NULL, &m_font );
a6fc8ae3
VZ
758 if ( width > ret.x )
759 ret.x = width;
760 }
761 }
762
763 // empty combobox should have some reasonable default size too
764 if ( ret.x < 100 )
765 ret.x = 100;
db434467 766 return ret;
f68586e5
VZ
767}
768
dcf924a3 769#endif