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