]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/combobox.cpp
Include wx/gauge.h according to precompiled headers of wx/wx.h (with other minor...
[wxWidgets.git] / src / gtk / combobox.cpp
CommitLineData
53010e52 1/////////////////////////////////////////////////////////////////////////////
11e62fe6 2// Name: src/gtk/combobox.cpp
53010e52
RR
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
VS
10// For compilers that support precompilation, includes "wx.h".
11#include "wx/wxprec.h"
12
dcf924a3
RR
13#if wxUSE_COMBOBOX
14
8228b893
WS
15#include "wx/combobox.h"
16
88a7a4e1
WS
17#ifndef WX_PRECOMP
18 #include "wx/intl.h"
9eddec69 19 #include "wx/settings.h"
fec9cc08 20 #include "wx/textctrl.h" // for wxEVT_COMMAND_TEXT_UPDATED
88a7a4e1
WS
21#endif
22
584ad2a3 23#include "wx/arrstr.h"
53010e52 24
1efb5db8
MR
25// We use GtkCombo which has been deprecated since GTK+ 2.3.0
26// in favour of GtkComboBox for <GTK2.4 runtime
5b008dd7
MR
27// We also use GtkList
28#ifdef GTK_DISABLE_DEPRECATED
1efb5db8
MR
29#undef GTK_DISABLE_DEPRECATED
30#endif
9e691f46 31#include "wx/gtk/private.h"
83624f79 32
47908e25
RR
33//-----------------------------------------------------------------------------
34// data
35//-----------------------------------------------------------------------------
36
37extern bool g_blockEventsOnDrag;
40eb3606
VZ
38static int g_SelectionBeforePopup = wxID_NONE; // this means the popup is hidden
39
78b3b018
RR
40//-----------------------------------------------------------------------------
41// "changed" - typing and list item matches get changed, select-child
42// if it doesn't match an item then just get a single changed
43//-----------------------------------------------------------------------------
44
865bb325 45extern "C" {
78b3b018 46static void
1fb33bdb 47gtkcombo_text_changed_callback( GtkWidget *WXUNUSED(widget), wxComboBox *combo )
78b3b018
RR
48{
49 if (g_isIdle) wxapp_install_idle_handler();
50
51 if (combo->m_ignoreNextUpdate)
150e31d2 52 {
7d8268a1 53 combo->m_ignoreNextUpdate = false;
78b3b018
RR
54 return;
55 }
56
57 if (!combo->m_hasVMT) return;
58
59 wxCommandEvent event( wxEVT_COMMAND_TEXT_UPDATED, combo->GetId() );
60 event.SetString( combo->GetValue() );
61 event.SetEventObject( combo );
62 combo->GetEventHandler()->ProcessEvent( event );
63}
865bb325 64}
78b3b018 65
865bb325 66extern "C" {
78b3b018 67static void
1fb33bdb 68gtkcombo_dummy_callback(GtkEntry *WXUNUSED(entry), GtkCombo *WXUNUSED(combo))
78b3b018
RR
69{
70}
865bb325 71}
78b3b018 72
865bb325 73extern "C" {
9d6a9fdd 74static void
1fb33bdb 75gtkcombo_popup_hide_callback(GtkCombo *WXUNUSED(gtk_combo), wxComboBox *combo)
7d8268a1 76{
9d6a9fdd
RR
77 // when the popup is hidden, throw a SELECTED event only if the combobox
78 // selection changed.
3dbfe8f4
VZ
79 const int curSelection = combo->GetCurrentSelection();
80
81 const bool hasChanged = curSelection != g_SelectionBeforePopup;
82
83 // reset the selection flag to value meaning that it is hidden and do it
84 // now, before generating the events, so that GetSelection() returns the
85 // new value from the event handler
86 g_SelectionBeforePopup = wxID_NONE;
87
88 if ( hasChanged )
9d6a9fdd
RR
89 {
90 wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, combo->GetId() );
91 event.SetInt( curSelection );
92 event.SetString( combo->GetStringSelection() );
93 event.SetEventObject( combo );
94 combo->GetEventHandler()->ProcessEvent( event );
345bdf13
KH
95
96 // for consistency with the other ports, send TEXT event
97 wxCommandEvent event2( wxEVT_COMMAND_TEXT_UPDATED, combo->GetId() );
98 event2.SetString( combo->GetStringSelection() );
99 event2.SetEventObject( combo );
100 combo->GetEventHandler()->ProcessEvent( event2 );
9d6a9fdd 101 }
9d6a9fdd 102}
865bb325 103}
9d6a9fdd 104
865bb325 105extern "C" {
9d6a9fdd 106static void
1fb33bdb 107gtkcombo_popup_show_callback(GtkCombo *WXUNUSED(gtk_combo), wxComboBox *combo)
9d6a9fdd
RR
108{
109 // store the combobox selection value before the popup is shown
40eb3606 110 g_SelectionBeforePopup = combo->GetCurrentSelection();
9d6a9fdd 111}
865bb325 112}
9d6a9fdd 113
53010e52 114//-----------------------------------------------------------------------------
461573cc 115// "select-child" - click/cursor get select-child, changed, select-child
47908e25 116//-----------------------------------------------------------------------------
47908e25 117
865bb325 118extern "C" {
8a85884a 119static void
1fb33bdb 120gtkcombo_combo_select_child_callback( GtkList *WXUNUSED(list), GtkWidget *WXUNUSED(widget), wxComboBox *combo )
53010e52 121{
acfd422a 122 if (g_isIdle) wxapp_install_idle_handler();
8a85884a 123
a2053b27 124 if (!combo->m_hasVMT) return;
30ed6e5c 125
acfd422a 126 if (g_blockEventsOnDrag) return;
805dd538 127
40eb3606 128 int curSelection = combo->GetCurrentSelection();
30ed6e5c 129
3c4e4af6
RR
130 if (combo->m_prevSelection == curSelection) return;
131
132 GtkWidget *list = GTK_COMBO(combo->m_widget)->list;
133 gtk_list_unselect_item( GTK_LIST(list), combo->m_prevSelection );
150e31d2 134
159b66c0
RR
135 combo->m_prevSelection = curSelection;
136
78b3b018
RR
137 // Quickly set the value of the combo box
138 // as GTK+ does that only AFTER the event
139 // is sent.
9fa72bd2 140 g_signal_handlers_disconnect_by_func (GTK_COMBO (combo->GetHandle())->entry,
1fb33bdb 141 (gpointer) gtkcombo_text_changed_callback,
9fa72bd2 142 combo);
78b3b018 143 combo->SetValue( combo->GetStringSelection() );
9fa72bd2 144 g_signal_connect_after (GTK_COMBO (combo->GetHandle())->entry, "changed",
1fb33bdb 145 G_CALLBACK (gtkcombo_text_changed_callback), combo);
78b3b018 146
40eb3606 147 // throw a SELECTED event only if the combobox popup is hidden (wxID_NONE)
1fb33bdb 148 // because when combobox popup is shown, gtkcombo_combo_select_child_callback is
9d6a9fdd
RR
149 // called each times the mouse is over an item with a pressed button so a lot
150 // of SELECTED event could be generated if the user keep the mouse button down
151 // and select other items ...
40eb3606 152 if (g_SelectionBeforePopup == wxID_NONE)
9d6a9fdd
RR
153 {
154 wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, combo->GetId() );
155 event.SetInt( curSelection );
156 event.SetString( combo->GetStringSelection() );
157 event.SetEventObject( combo );
158 combo->GetEventHandler()->ProcessEvent( event );
0c77152e 159
345bdf13 160 // for consistency with the other ports, don't generate text update
40eb3606
VZ
161 // events while the user is browsing the combobox neither
162 wxCommandEvent event2( wxEVT_COMMAND_TEXT_UPDATED, combo->GetId() );
163 event2.SetString( combo->GetValue() );
164 event2.SetEventObject( combo );
165 combo->GetEventHandler()->ProcessEvent( event2 );
166 }
461573cc 167}
865bb325 168}
461573cc 169
590f50d6
RR
170#ifdef __WXGTK24__
171extern "C" {
172static void
173gtkcombobox_text_changed_callback( GtkWidget *WXUNUSED(widget), wxComboBox *combo )
174{
175 if (g_isIdle) wxapp_install_idle_handler();
176
177 if (!combo->m_hasVMT) return;
178
179 wxCommandEvent event( wxEVT_COMMAND_TEXT_UPDATED, combo->GetId() );
180 event.SetString( combo->GetValue() );
181 event.SetEventObject( combo );
182 combo->GetEventHandler()->ProcessEvent( event );
183}
184}
185
186extern "C" {
187static void
188gtkcombobox_changed_callback( GtkWidget *WXUNUSED(widget), wxComboBox *combo )
189{
190 if (g_isIdle) wxapp_install_idle_handler();
191
192 if (!combo->m_hasVMT) return;
193
194 wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, combo->GetId() );
195 event.SetInt( combo->GetSelection() );
196 event.SetString( combo->GetStringSelection() );
197 event.SetEventObject( combo );
198 combo->GetEventHandler()->ProcessEvent( event );
199}
200}
201#endif
202
e1e955e1
RR
203//-----------------------------------------------------------------------------
204// wxComboBox
53010e52
RR
205//-----------------------------------------------------------------------------
206
207IMPLEMENT_DYNAMIC_CLASS(wxComboBox,wxControl)
208
b4071e91 209BEGIN_EVENT_TABLE(wxComboBox, wxControl)
fd0eed64 210 EVT_SIZE(wxComboBox::OnSize)
8a85884a 211 EVT_CHAR(wxComboBox::OnChar)
150e31d2
JS
212
213 EVT_MENU(wxID_CUT, wxComboBox::OnCut)
214 EVT_MENU(wxID_COPY, wxComboBox::OnCopy)
215 EVT_MENU(wxID_PASTE, wxComboBox::OnPaste)
216 EVT_MENU(wxID_UNDO, wxComboBox::OnUndo)
217 EVT_MENU(wxID_REDO, wxComboBox::OnRedo)
218 EVT_MENU(wxID_CLEAR, wxComboBox::OnDelete)
219 EVT_MENU(wxID_SELECTALL, wxComboBox::OnSelectAll)
220
221 EVT_UPDATE_UI(wxID_CUT, wxComboBox::OnUpdateCut)
222 EVT_UPDATE_UI(wxID_COPY, wxComboBox::OnUpdateCopy)
223 EVT_UPDATE_UI(wxID_PASTE, wxComboBox::OnUpdatePaste)
224 EVT_UPDATE_UI(wxID_UNDO, wxComboBox::OnUpdateUndo)
225 EVT_UPDATE_UI(wxID_REDO, wxComboBox::OnUpdateRedo)
226 EVT_UPDATE_UI(wxID_CLEAR, wxComboBox::OnUpdateDelete)
227 EVT_UPDATE_UI(wxID_SELECTALL, wxComboBox::OnUpdateSelectAll)
b4071e91
RR
228END_EVENT_TABLE()
229
584ad2a3
MB
230bool wxComboBox::Create( wxWindow *parent, wxWindowID id,
231 const wxString& value,
232 const wxPoint& pos, const wxSize& size,
233 const wxArrayString& choices,
234 long style, const wxValidator& validator,
235 const wxString& name )
236{
237 wxCArrayString chs(choices);
238
239 return Create( parent, id, value, pos, size, chs.GetCount(),
240 chs.GetStrings(), style, validator, name );
241}
242
fd0eed64
RR
243bool wxComboBox::Create( wxWindow *parent, wxWindowID id, const wxString& value,
244 const wxPoint& pos, const wxSize& size,
245 int n, const wxString choices[],
805dd538
VZ
246 long style, const wxValidator& validator,
247 const wxString& name )
53010e52 248{
7d8268a1
WS
249 m_ignoreNextUpdate = false;
250 m_needParent = true;
251 m_acceptsFocus = true;
159b66c0 252 m_prevSelection = 0;
805dd538 253
db434467 254 if (!PreCreation( parent, pos, size ) ||
4dcaf11a
RR
255 !CreateBase( parent, id, pos, size, style, validator, name ))
256 {
223d09f6 257 wxFAIL_MSG( wxT("wxComboBox creation failed") );
7d8268a1 258 return false;
4dcaf11a 259 }
6de97a3b 260
590f50d6
RR
261#ifdef __WXGTK24__
262 if (!gtk_check_version(2,4,0))
263 {
264 m_widget = gtk_combo_box_entry_new_text();
265 GtkComboBox* combobox = GTK_COMBO_BOX( m_widget );
8228b893 266
590f50d6 267 gtk_entry_set_editable( GTK_ENTRY( GTK_BIN(m_widget)->child ), TRUE );
8228b893 268
590f50d6
RR
269 for (int i = 0; i < n; i++)
270 {
271 gtk_combo_box_append_text( combobox, wxGTK_CONV( choices[i] ) );
30ed6e5c 272
590f50d6
RR
273 m_clientDataList.Append( (wxObject*)NULL );
274 m_clientObjectList.Append( (wxObject*)NULL );
275 }
276 }
277 else
278#endif
279 {
280 m_widget = gtk_combo_new();
281 GtkCombo* combo = GTK_COMBO(m_widget);
8228b893 282
590f50d6
RR
283 // Disable GTK's broken events ...
284 g_signal_handler_disconnect (combo->entry, combo->entry_change_id);
285 // ... and add surrogate handler.
286 combo->entry_change_id = g_signal_connect (combo->entry, "changed",
1fb33bdb 287 G_CALLBACK (gtkcombo_dummy_callback),
9fa72bd2 288 combo);
805dd538 289
590f50d6
RR
290 // make it more useable
291 gtk_combo_set_use_arrows_always( GTK_COMBO(m_widget), TRUE );
30ed6e5c 292
590f50d6
RR
293 // and case-sensitive
294 gtk_combo_set_case_sensitive( GTK_COMBO(m_widget), TRUE );
3ca6a5f0 295
590f50d6 296 if (style & wxNO_BORDER)
7d1fea10 297 g_object_set (combo->entry, "has-frame", FALSE, NULL );
8228b893 298
590f50d6 299 GtkWidget *list = combo->list;
7d8268a1 300
590f50d6
RR
301 for (int i = 0; i < n; i++)
302 {
303 GtkWidget *list_item = gtk_list_item_new_with_label( wxGTK_CONV( choices[i] ) );
805dd538 304
590f50d6
RR
305 m_clientDataList.Append( (wxObject*)NULL );
306 m_clientObjectList.Append( (wxObject*)NULL );
805dd538 307
590f50d6 308 gtk_container_add( GTK_CONTAINER(list), list_item );
805dd538 309
590f50d6
RR
310 gtk_widget_show( list_item );
311 }
fd0eed64 312 }
805dd538 313
590f50d6 314
f03fc89f 315 m_parent->DoAddChild( this );
30ed6e5c 316
590f50d6
RR
317 GtkEntry *entry = NULL;
318#ifdef __WXGTK24__
319 if (!gtk_check_version(2,4,0))
320 entry = GTK_ENTRY( GTK_BIN(m_widget)->child );
321 else
8228b893 322#endif
590f50d6 323 entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry );
8228b893 324
590f50d6 325 m_focusWidget = GTK_WIDGET( entry );
805dd538 326
abdeb9e7 327 PostCreation(size);
53010e52 328
590f50d6
RR
329#ifdef __WXGTK24__
330 if (!gtk_check_version(2,4,0))
331 ConnectWidget( m_widget );
332 else
333#endif
334 ConnectWidget( GTK_COMBO(m_widget)->button );
805dd538 335
590f50d6
RR
336#ifdef __WXGTK24__
337 if (!gtk_check_version(2,4,0))
338 {
339 gtk_entry_set_text( entry, wxGTK_CONV(value) );
8228b893 340
590f50d6
RR
341 if (style & wxCB_READONLY)
342 gtk_entry_set_editable( entry, FALSE );
8228b893 343
590f50d6
RR
344 g_signal_connect_after (entry, "changed",
345 G_CALLBACK (gtkcombobox_text_changed_callback), this);
8228b893 346
590f50d6
RR
347 g_signal_connect_after (m_widget, "changed",
348 G_CALLBACK (gtkcombobox_changed_callback), this);
349 }
350 else
351#endif
352 {
353 GtkCombo *combo = GTK_COMBO(m_widget);
354 // MSW's combo box shows the value and the selection is -1
355 gtk_entry_set_text( entry, wxGTK_CONV(value) );
356 gtk_list_unselect_all( GTK_LIST(combo->list) );
805dd538 357
590f50d6
RR
358 if (style & wxCB_READONLY)
359 gtk_entry_set_editable( entry, FALSE );
a260fe6a 360
590f50d6
RR
361 // "show" and "hide" events are generated when user click on the combobox button which popups a list
362 // this list is the "popwin" gtk widget
363 g_signal_connect (GTK_COMBO(combo)->popwin, "hide",
1fb33bdb 364 G_CALLBACK (gtkcombo_popup_hide_callback), this);
590f50d6 365 g_signal_connect (GTK_COMBO(combo)->popwin, "show",
1fb33bdb 366 G_CALLBACK (gtkcombo_popup_show_callback), this);
590f50d6 367 g_signal_connect_after (combo->list, "select-child",
1fb33bdb 368 G_CALLBACK (gtkcombo_combo_select_child_callback),
9fa72bd2 369 this);
590f50d6
RR
370 g_signal_connect_after (entry, "changed",
371 G_CALLBACK (gtkcombo_text_changed_callback), this);
8228b893 372
590f50d6
RR
373 // This is required for tool bar support
374 // Doesn't currently work
375// wxSize setsize = GetSize();
376// gtk_widget_set_size_request( m_widget, setsize.x, setsize.y );
377 }
805dd538 378
abdeb9e7 379 SetBestSize(size); // need this too because this is a wxControlWithItems
805dd538 380
150e31d2 381
7d8268a1 382 return true;
fd0eed64
RR
383}
384
385wxComboBox::~wxComboBox()
386{
222ed1d6 387 wxList::compatibility_iterator node = m_clientObjectList.GetFirst();
fd0eed64
RR
388 while (node)
389 {
b1d4dd7a 390 wxClientData *cd = (wxClientData*)node->GetData();
fd0eed64 391 if (cd) delete cd;
b1d4dd7a 392 node = node->GetNext();
fd0eed64 393 }
7d6d2cd4
RR
394 m_clientObjectList.Clear();
395
fd0eed64 396 m_clientDataList.Clear();
6de97a3b 397}
53010e52 398
2b5f62a0
VZ
399void wxComboBox::SetFocus()
400{
401 if ( m_hasFocus )
402 {
403 // don't do anything if we already have focus
404 return;
405 }
406
407 gtk_widget_grab_focus( m_focusWidget );
408}
409
6f6f938f 410int wxComboBox::DoAppend( const wxString &item )
53010e52 411{
2a68b7a0 412 wxCHECK_MSG( m_widget != NULL, -1, wxT("invalid combobox") );
805dd538 413
590f50d6
RR
414#ifdef __WXGTK24__
415 if (!gtk_check_version(2,4,0))
416 {
417 GtkComboBox* combobox = GTK_COMBO_BOX( m_widget );
418 gtk_combo_box_append_text( combobox, wxGTK_CONV( item ) );
419 }
420 else
421#endif
422 {
423 DisableEvents();
805dd538 424
590f50d6
RR
425 GtkWidget *list = GTK_COMBO(m_widget)->list;
426 GtkWidget *list_item = gtk_list_item_new_with_label( wxGTK_CONV( item ) );
805dd538 427
590f50d6 428 gtk_container_add( GTK_CONTAINER(list), list_item );
ec5d85fb 429
590f50d6
RR
430 if (GTK_WIDGET_REALIZED(m_widget))
431 {
432 gtk_widget_realize( list_item );
433 gtk_widget_realize( GTK_BIN(list_item)->child );
434 }
2b07d713 435
590f50d6
RR
436 // Apply current widget style to the new list_item
437 GtkRcStyle *style = CreateWidgetStyle();
438 if (style)
439 {
440 gtk_widget_modify_style( GTK_WIDGET( list_item ), style );
441 GtkBin *bin = GTK_BIN( list_item );
442 GtkWidget *label = GTK_WIDGET( bin->child );
443 gtk_widget_modify_style( label, style );
444 gtk_rc_style_unref( style );
445 }
805dd538 446
590f50d6 447 gtk_widget_show( list_item );
30ed6e5c 448
590f50d6
RR
449 EnableEvents();
450 }
53010e52 451
aa61d352 452 const unsigned int count = GetCount();
8228b893
WS
453
454 if ( m_clientDataList.GetCount() < count )
0a164d4c 455 m_clientDataList.Append( (wxObject*) NULL );
8228b893 456 if ( m_clientObjectList.GetCount() < count )
0a164d4c 457 m_clientObjectList.Append( (wxObject*) NULL );
805dd538 458
b0021947
VS
459 InvalidateBestSize();
460
6f6f938f 461 return count - 1;
fd0eed64
RR
462}
463
aa61d352 464int wxComboBox::DoInsert(const wxString &item, unsigned int pos)
243dbf1a 465{
708c45a6
VZ
466 wxCHECK_MSG( !(GetWindowStyle() & wxCB_SORT), -1,
467 wxT("can't insert into sorted list"));
468
469 wxCHECK_MSG( m_widget != NULL, -1, wxT("invalid combobox") );
8228b893 470 wxCHECK_MSG( IsValidInsert(pos), -1, wxT("invalid index") );
243dbf1a 471
aa61d352 472 unsigned int count = GetCount();
6f6f938f 473
aa61d352 474 if (pos == count)
6f6f938f 475 return Append(item);
243dbf1a 476
590f50d6
RR
477#ifdef __WXGTK24__
478 if (!gtk_check_version(2,4,0))
479 {
480 GtkComboBox* combobox = GTK_COMBO_BOX( m_widget );
481 gtk_combo_box_insert_text( combobox, pos, wxGTK_CONV( item ) );
482 }
483 else
484#endif
485 {
486 DisableEvents();
243dbf1a 487
590f50d6
RR
488 GtkWidget *list = GTK_COMBO(m_widget)->list;
489 GtkWidget *list_item = gtk_list_item_new_with_label( wxGTK_CONV( item ) );
243dbf1a 490
590f50d6
RR
491 GList *gitem_list = g_list_alloc ();
492 gitem_list->data = list_item;
493 gtk_list_insert_items( GTK_LIST (list), gitem_list, pos );
243dbf1a 494
590f50d6
RR
495 if (GTK_WIDGET_REALIZED(m_widget))
496 {
497 gtk_widget_realize( list_item );
498 gtk_widget_realize( GTK_BIN(list_item)->child );
243dbf1a 499
590f50d6
RR
500 ApplyWidgetStyle();
501 }
243dbf1a 502
590f50d6 503 gtk_widget_show( list_item );
243dbf1a 504
590f50d6
RR
505 EnableEvents();
506 }
8228b893 507
6f6f938f 508 count = GetCount();
243dbf1a 509
8228b893 510 if ( m_clientDataList.GetCount() < count )
0a164d4c 511 m_clientDataList.Insert( pos, (wxObject*) NULL );
8228b893 512 if ( m_clientObjectList.GetCount() < count )
0a164d4c 513 m_clientObjectList.Insert( pos, (wxObject*) NULL );
243dbf1a 514
b0021947 515 InvalidateBestSize();
243dbf1a 516
6f6f938f 517 return pos;
243dbf1a
VZ
518}
519
aa61d352 520void wxComboBox::DoSetItemClientData(unsigned int n, void* clientData)
fd0eed64 521{
223d09f6 522 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 523
222ed1d6 524 wxList::compatibility_iterator node = m_clientDataList.Item( n );
fd0eed64 525 if (!node) return;
805dd538 526
f5e27805 527 node->SetData( (wxObject*) clientData );
6de97a3b 528}
53010e52 529
aa61d352 530void* wxComboBox::DoGetItemClientData(unsigned int n) const
53010e52 531{
223d09f6 532 wxCHECK_MSG( m_widget != NULL, NULL, wxT("invalid combobox") );
805dd538 533
222ed1d6 534 wxList::compatibility_iterator node = m_clientDataList.Item( n );
805dd538 535
30ed6e5c 536 return node ? node->GetData() : NULL;
fd0eed64
RR
537}
538
aa61d352 539void wxComboBox::DoSetItemClientObject(unsigned int n, wxClientData* clientData)
fd0eed64 540{
223d09f6 541 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 542
222ed1d6 543 wxList::compatibility_iterator node = m_clientObjectList.Item( n );
fd0eed64 544 if (!node) return;
805dd538 545
e94e2e95 546 // wxItemContainer already deletes data for us
805dd538 547
fd0eed64 548 node->SetData( (wxObject*) clientData );
6de97a3b 549}
53010e52 550
aa61d352 551wxClientData* wxComboBox::DoGetItemClientObject(unsigned int n) const
53010e52 552{
223d09f6 553 wxCHECK_MSG( m_widget != NULL, (wxClientData*)NULL, wxT("invalid combobox") );
805dd538 554
222ed1d6 555 wxList::compatibility_iterator node = m_clientObjectList.Item( n );
805dd538 556
30ed6e5c 557 return node ? (wxClientData*) node->GetData() : NULL;
fd0eed64
RR
558}
559
560void wxComboBox::Clear()
561{
223d09f6 562 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 563
461573cc 564 DisableEvents();
30ed6e5c 565
590f50d6
RR
566#ifdef __WXGTK24__
567 if (!gtk_check_version(2,4,0))
568 {
569 GtkComboBox* combobox = GTK_COMBO_BOX( m_widget );
aa61d352
VZ
570 const unsigned int count = GetCount();
571 for (unsigned int i = 0; i < count; i++)
590f50d6
RR
572 gtk_combo_box_remove_text( combobox, 0 );
573 }
c1a3ff25
VZ
574 else // GTK+ < 2.4.0
575#endif // __WXGTK24__
590f50d6
RR
576 {
577 GtkWidget *list = GTK_COMBO(m_widget)->list;
578 gtk_list_clear_items( GTK_LIST(list), 0, GetCount() );
579 }
8228b893 580
222ed1d6 581 wxList::compatibility_iterator node = m_clientObjectList.GetFirst();
fd0eed64
RR
582 while (node)
583 {
b1d4dd7a 584 wxClientData *cd = (wxClientData*)node->GetData();
c1a3ff25 585 delete cd;
b1d4dd7a 586 node = node->GetNext();
fd0eed64 587 }
f5e27805 588 m_clientObjectList.Clear();
805dd538 589
fd0eed64 590 m_clientDataList.Clear();
30ed6e5c 591
461573cc 592 EnableEvents();
b0021947
VS
593
594 InvalidateBestSize();
6de97a3b 595}
53010e52 596
aa61d352 597void wxComboBox::Delete(unsigned int n)
53010e52 598{
223d09f6 599 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 600
590f50d6
RR
601#ifdef __WXGTK24__
602 if (!gtk_check_version(2,4,0))
fd0eed64 603 {
8228b893
WS
604 wxCHECK_RET( IsValid(n), wxT("invalid index") );
605
590f50d6
RR
606 GtkComboBox* combobox = GTK_COMBO_BOX( m_widget );
607 gtk_combo_box_remove_text( combobox, n );
fd0eed64 608 }
590f50d6
RR
609 else
610#endif
611 {
612 GtkList *listbox = GTK_LIST( GTK_COMBO(m_widget)->list );
805dd538 613
590f50d6
RR
614 GList *child = g_list_nth( listbox->children, n );
615
616 if (!child)
617 {
618 wxFAIL_MSG(wxT("wrong index"));
619 return;
620 }
30ed6e5c 621
590f50d6 622 DisableEvents();
805dd538 623
590f50d6
RR
624 GList *list = g_list_append( (GList*) NULL, child->data );
625 gtk_list_remove_items( listbox, list );
626 g_list_free( list );
627
628 EnableEvents();
629 }
8228b893 630
222ed1d6 631 wxList::compatibility_iterator node = m_clientObjectList.Item( n );
f5e27805 632 if (node)
fd0eed64 633 {
b1d4dd7a 634 wxClientData *cd = (wxClientData*)node->GetData();
fd0eed64 635 if (cd) delete cd;
222ed1d6 636 m_clientObjectList.Erase( node );
f5e27805 637 }
805dd538 638
b1d4dd7a 639 node = m_clientDataList.Item( n );
f5e27805 640 if (node)
222ed1d6 641 m_clientDataList.Erase( node );
150e31d2 642
b0021947 643 InvalidateBestSize();
461573cc
RR
644}
645
aa61d352 646void wxComboBox::SetString(unsigned int n, const wxString &text)
461573cc
RR
647{
648 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
649
590f50d6
RR
650#ifdef __WXGTK24__
651 if (!gtk_check_version(2,4,0))
461573cc 652 {
590f50d6 653 GtkComboBox* combobox = GTK_COMBO_BOX( m_widget );
8228b893
WS
654 wxCHECK_RET( IsValid(n), wxT("invalid index") );
655
590f50d6
RR
656 GtkTreeModel *model = gtk_combo_box_get_model( combobox );
657 GtkTreeIter iter;
658 if (gtk_tree_model_iter_nth_child (model, &iter, NULL, n))
659 {
660 GValue value = { 0, };
661 g_value_init( &value, G_TYPE_STRING );
662 g_value_set_string( &value, wxGTK_CONV( text ) );
663 gtk_list_store_set_value( GTK_LIST_STORE(model), &iter, 0, &value );
664 g_value_unset( &value );
665 }
461573cc
RR
666 }
667 else
590f50d6 668#endif
461573cc 669 {
590f50d6 670 GtkWidget *list = GTK_COMBO(m_widget)->list;
150e31d2 671
590f50d6
RR
672 GList *child = g_list_nth( GTK_LIST(list)->children, n );
673 if (child)
674 {
675 GtkBin *bin = GTK_BIN( child->data );
676 GtkLabel *label = GTK_LABEL( bin->child );
677 gtk_label_set_text(label, wxGTK_CONV(text));
678 }
679 else
680 {
681 wxFAIL_MSG( wxT("wxComboBox: wrong index") );
682 }
683 }
8228b893 684
b0021947 685 InvalidateBestSize();
6de97a3b 686}
53010e52 687
11e62fe6 688int wxComboBox::FindString( const wxString &item, bool bCase ) const
53010e52 689{
0a164d4c 690 wxCHECK_MSG( m_widget != NULL, wxNOT_FOUND, wxT("invalid combobox") );
805dd538 691
590f50d6
RR
692#ifdef __WXGTK24__
693 if (!gtk_check_version(2,4,0))
53010e52 694 {
590f50d6
RR
695 GtkComboBox* combobox = GTK_COMBO_BOX( m_widget );
696 GtkTreeModel* model = gtk_combo_box_get_model( combobox );
697 GtkTreeIter iter;
698 gtk_tree_model_get_iter_first( model, &iter );
699 if (!gtk_list_store_iter_is_valid(GTK_LIST_STORE(model), &iter ))
700 return -1;
701 int count = 0;
8228b893 702 do
590f50d6
RR
703 {
704 GValue value = { 0, };
705 gtk_tree_model_get_value( model, &iter, 0, &value );
706 wxString str = wxGTK_CONV_BACK( g_value_get_string( &value ) );
707 g_value_unset( &value );
8228b893 708
590f50d6
RR
709 if (item.IsSameAs( str, bCase ) )
710 return count;
8228b893 711
590f50d6 712 count++;
8228b893 713
590f50d6
RR
714 } while (gtk_tree_model_iter_next( model, &iter ));
715 }
716 else
717#endif
718 {
719 GtkWidget *list = GTK_COMBO(m_widget)->list;
68567a96 720
590f50d6
RR
721 GList *child = GTK_LIST(list)->children;
722 int count = 0;
723 while (child)
724 {
725 GtkBin *bin = GTK_BIN( child->data );
726 GtkLabel *label = GTK_LABEL( bin->child );
727 wxString str( wxGTK_CONV_BACK( gtk_label_get_text(label) ) );
728
729 if (item.IsSameAs( str , bCase ) )
730 return count;
30ed6e5c 731
590f50d6
RR
732 count++;
733 child = child->next;
734 }
fd0eed64 735 }
805dd538 736
7cf8cb48 737 return wxNOT_FOUND;
fd0eed64
RR
738}
739
740int wxComboBox::GetSelection() const
40eb3606 741{
590f50d6
RR
742#ifdef __WXGTK24__
743 if (!gtk_check_version(2,4,0))
744 {
745 GtkComboBox* combobox = GTK_COMBO_BOX( m_widget );
746 return gtk_combo_box_get_active( combobox );
747 }
748 else
749#endif
750 // if the popup is currently opened, use the selection as it had been
751 // before it dropped down
752 return g_SelectionBeforePopup == wxID_NONE ? GetCurrentSelection()
40eb3606
VZ
753 : g_SelectionBeforePopup;
754}
755
756int wxComboBox::GetCurrentSelection() const
fd0eed64 757{
223d09f6 758 wxCHECK_MSG( m_widget != NULL, -1, wxT("invalid combobox") );
805dd538 759
590f50d6
RR
760#ifdef __WXGTK24__
761 if (!gtk_check_version(2,4,0))
fd0eed64 762 {
590f50d6
RR
763 GtkComboBox* combobox = GTK_COMBO_BOX( m_widget );
764 return gtk_combo_box_get_active( combobox );
765 }
766 else
767#endif
768 {
769 GtkWidget *list = GTK_COMBO(m_widget)->list;
770
771 GList *selection = GTK_LIST(list)->selection;
772 if (selection)
fd0eed64 773 {
590f50d6
RR
774 GList *child = GTK_LIST(list)->children;
775 int count = 0;
776 while (child)
777 {
778 if (child->data == selection->data) return count;
779 count++;
780 child = child->next;
781 }
fd0eed64 782 }
6de97a3b 783 }
805dd538 784
fd0eed64 785 return -1;
6de97a3b 786}
53010e52 787
aa61d352 788wxString wxComboBox::GetString(unsigned int n) const
53010e52 789{
0a164d4c 790 wxCHECK_MSG( m_widget != NULL, wxEmptyString, wxT("invalid combobox") );
805dd538 791
7cf8cb48 792 wxString str;
8228b893 793
590f50d6
RR
794#ifdef __WXGTK24__
795 if (!gtk_check_version(2,4,0))
fd0eed64 796 {
590f50d6
RR
797 GtkComboBox* combobox = GTK_COMBO_BOX( m_widget );
798 GtkTreeModel *model = gtk_combo_box_get_model( combobox );
799 GtkTreeIter iter;
800 if (gtk_tree_model_iter_nth_child (model, &iter, NULL, n))
801 {
802 GValue value = { 0, };
803 gtk_tree_model_get_value( model, &iter, 0, &value );
804 wxString tmp = wxGTK_CONV_BACK( g_value_get_string( &value ) );
805 g_value_unset( &value );
806 return tmp;
807 }
7cf8cb48
VZ
808 }
809 else
590f50d6 810#endif
8228b893 811 {
590f50d6
RR
812 GtkWidget *list = GTK_COMBO(m_widget)->list;
813
814 GList *child = g_list_nth( GTK_LIST(list)->children, n );
815 if (child)
816 {
817 GtkBin *bin = GTK_BIN( child->data );
818 GtkLabel *label = GTK_LABEL( bin->child );
819 str = wxGTK_CONV_BACK( gtk_label_get_text(label) );
820 }
821 else
822 {
823 wxFAIL_MSG( wxT("wxComboBox: wrong index") );
824 }
fd0eed64 825 }
805dd538 826
7cf8cb48 827 return str;
6de97a3b 828}
53010e52 829
fd0eed64 830wxString wxComboBox::GetStringSelection() const
53010e52 831{
0a164d4c 832 wxCHECK_MSG( m_widget != NULL, wxEmptyString, wxT("invalid combobox") );
805dd538 833
590f50d6
RR
834#ifdef __WXGTK24__
835 if (!gtk_check_version(2,4,0))
fd0eed64 836 {
590f50d6
RR
837 GtkComboBox* combobox = GTK_COMBO_BOX( m_widget );
838 int sel = gtk_combo_box_get_active( combobox );
839 if (sel == -1)
840 return wxEmptyString;
aa61d352 841 return GetString(sel);
fd0eed64 842 }
590f50d6
RR
843 else
844#endif
8228b893 845 {
590f50d6
RR
846 GtkWidget *list = GTK_COMBO(m_widget)->list;
847
848 GList *selection = GTK_LIST(list)->selection;
849 if (selection)
850 {
851 GtkBin *bin = GTK_BIN( selection->data );
852 GtkLabel *label = GTK_LABEL( bin->child );
853 wxString tmp( wxGTK_CONV_BACK( gtk_label_get_text(label) ) );
854 return tmp;
855 }
805dd538 856
590f50d6
RR
857 wxFAIL_MSG( wxT("wxComboBox: no selection") );
858 }
805dd538 859
0a164d4c 860 return wxEmptyString;
6de97a3b 861}
53010e52 862
aa61d352 863unsigned int wxComboBox::GetCount() const
53010e52 864{
223d09f6 865 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid combobox") );
805dd538 866
590f50d6
RR
867#ifdef __WXGTK24__
868 if (!gtk_check_version(2,4,0))
869 {
870 GtkComboBox* combobox = GTK_COMBO_BOX( m_widget );
871 GtkTreeModel* model = gtk_combo_box_get_model( combobox );
872 GtkTreeIter iter;
873 gtk_tree_model_get_iter_first( model, &iter );
874 if (!gtk_list_store_iter_is_valid(GTK_LIST_STORE(model), &iter ))
875 return 0;
aa61d352 876 unsigned int ret = 1;
590f50d6
RR
877 while (gtk_tree_model_iter_next( model, &iter ))
878 ret++;
879 return ret;
880 }
881 else
882#endif
8228b893 883 {
590f50d6 884 GtkWidget *list = GTK_COMBO(m_widget)->list;
805dd538 885
590f50d6 886 GList *child = GTK_LIST(list)->children;
aa61d352
VZ
887 unsigned int count = 0;
888 while (child)
889 {
890 count++;
891 child = child->next;
892 }
590f50d6
RR
893 return count;
894 }
8228b893 895
590f50d6 896 return 0;
6de97a3b 897}
53010e52 898
debe6624 899void wxComboBox::SetSelection( int n )
53010e52 900{
223d09f6 901 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 902
953704c1
RR
903 DisableEvents();
904
590f50d6
RR
905#ifdef __WXGTK24__
906 if (!gtk_check_version(2,4,0))
907 {
908 GtkComboBox* combobox = GTK_COMBO_BOX( m_widget );
909 gtk_combo_box_set_active( combobox, n );
910 }
911 else
912#endif
913 {
914 GtkWidget *list = GTK_COMBO(m_widget)->list;
915 gtk_list_unselect_item( GTK_LIST(list), m_prevSelection );
916 gtk_list_select_item( GTK_LIST(list), n );
917 m_prevSelection = n;
918 }
8228b893 919
953704c1 920 EnableEvents();
6de97a3b 921}
53010e52 922
fd0eed64 923wxString wxComboBox::GetValue() const
53010e52 924{
590f50d6
RR
925 GtkEntry *entry = NULL;
926#ifdef __WXGTK24__
927 if (!gtk_check_version(2,4,0))
928 entry = GTK_ENTRY( GTK_BIN(m_widget)->child );
929 else
8228b893 930#endif
590f50d6 931 entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry );
8228b893 932
2e1d7104
RR
933 wxString tmp( wxGTK_CONV_BACK( gtk_entry_get_text( entry ) ) );
934
30ed6e5c 935#if 0
2e1d7104
RR
936 for (int i = 0; i < wxStrlen(tmp.c_str()) +1; i++)
937 {
938 wxChar c = tmp[i];
939 printf( "%d ", (int) (c) );
940 }
941 printf( "\n" );
942#endif
30ed6e5c 943
fd0eed64 944 return tmp;
6de97a3b 945}
53010e52
RR
946
947void wxComboBox::SetValue( const wxString& value )
948{
223d09f6 949 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 950
590f50d6
RR
951 GtkEntry *entry = NULL;
952#ifdef __WXGTK24__
953 if (!gtk_check_version(2,4,0))
954 entry = GTK_ENTRY( GTK_BIN(m_widget)->child );
955 else
8228b893 956#endif
590f50d6 957 entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry );
8228b893 958
0a164d4c 959 wxString tmp;
fd0eed64 960 if (!value.IsNull()) tmp = value;
590f50d6 961 gtk_entry_set_text( entry, wxGTK_CONV( tmp ) );
150e31d2 962
b0021947 963 InvalidateBestSize();
6de97a3b 964}
53010e52 965
fd0eed64 966void wxComboBox::Copy()
53010e52 967{
223d09f6 968 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 969
590f50d6
RR
970 GtkEntry *entry = NULL;
971#ifdef __WXGTK24__
972 if (!gtk_check_version(2,4,0))
973 entry = GTK_ENTRY( GTK_BIN(m_widget)->child );
974 else
8228b893 975#endif
590f50d6 976 entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry );
8228b893 977
afa7bd1e 978 gtk_editable_copy_clipboard(GTK_EDITABLE(entry));
6de97a3b 979}
53010e52 980
fd0eed64 981void wxComboBox::Cut()
53010e52 982{
223d09f6 983 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 984
590f50d6
RR
985 GtkEntry *entry = NULL;
986#ifdef __WXGTK24__
987 if (!gtk_check_version(2,4,0))
988 entry = GTK_ENTRY( GTK_BIN(m_widget)->child );
989 else
8228b893 990#endif
590f50d6 991 entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry );
8228b893 992
afa7bd1e 993 gtk_editable_cut_clipboard(GTK_EDITABLE(entry));
6de97a3b 994}
53010e52 995
fd0eed64 996void wxComboBox::Paste()
53010e52 997{
223d09f6 998 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 999
590f50d6
RR
1000 GtkEntry *entry = NULL;
1001#ifdef __WXGTK24__
1002 if (!gtk_check_version(2,4,0))
1003 entry = GTK_ENTRY( GTK_BIN(m_widget)->child );
1004 else
8228b893 1005#endif
590f50d6 1006 entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry );
8228b893 1007
afa7bd1e 1008 gtk_editable_paste_clipboard(GTK_EDITABLE(entry));
6de97a3b 1009}
53010e52 1010
150e31d2
JS
1011void wxComboBox::Undo()
1012{
1013 // TODO
1014}
1015
1016void wxComboBox::Redo()
1017{
1018 // TODO
1019}
1020
1021void wxComboBox::SelectAll()
1022{
4e324a3f 1023 SetSelection(0, GetLastPosition());
150e31d2
JS
1024}
1025
1026bool wxComboBox::CanUndo() const
1027{
1028 // TODO
1029 return false;
1030}
1031
1032bool wxComboBox::CanRedo() const
1033{
1034 // TODO
1035 return false;
1036}
1037
1038bool wxComboBox::HasSelection() const
1039{
1040 long from, to;
1041 GetSelection(&from, &to);
1042 return from != to;
1043}
1044
1045bool wxComboBox::CanCopy() const
1046{
1047 // Can copy if there's a selection
1048 return HasSelection();
1049}
1050
1051bool wxComboBox::CanCut() const
1052{
1053 return CanCopy() && IsEditable();
1054}
1055
1056bool wxComboBox::CanPaste() const
1057{
1058 // TODO: check for text on the clipboard
1059 return IsEditable() ;
1060}
1061
1062bool wxComboBox::IsEditable() const
1063{
1064 return !HasFlag(wxCB_READONLY);
1065}
1066
1067
debe6624 1068void wxComboBox::SetInsertionPoint( long pos )
53010e52 1069{
223d09f6 1070 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 1071
6f6f938f
VZ
1072 if ( pos == GetLastPosition() )
1073 pos = -1;
1074
590f50d6
RR
1075 GtkEntry *entry = NULL;
1076#ifdef __WXGTK24__
1077 if (!gtk_check_version(2,4,0))
1078 entry = GTK_ENTRY( GTK_BIN(m_widget)->child );
1079 else
8228b893 1080#endif
590f50d6 1081 entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry );
8228b893 1082
590f50d6 1083 gtk_entry_set_position( entry, (int)pos );
6de97a3b 1084}
53010e52 1085
fd0eed64 1086long wxComboBox::GetInsertionPoint() const
53010e52 1087{
590f50d6
RR
1088 GtkEntry *entry = NULL;
1089#ifdef __WXGTK24__
1090 if (!gtk_check_version(2,4,0))
1091 entry = GTK_ENTRY( GTK_BIN(m_widget)->child );
1092 else
8228b893 1093#endif
590f50d6 1094 entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry );
8228b893 1095
590f50d6 1096 return (long) gtk_editable_get_position(GTK_EDITABLE(entry));
6de97a3b 1097}
53010e52 1098
7d8268a1 1099wxTextPos wxComboBox::GetLastPosition() const
53010e52 1100{
590f50d6
RR
1101 GtkEntry *entry = NULL;
1102#ifdef __WXGTK24__
1103 if (!gtk_check_version(2,4,0))
1104 entry = GTK_ENTRY( GTK_BIN(m_widget)->child );
1105 else
8228b893 1106#endif
590f50d6 1107 entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry );
8228b893 1108
590f50d6 1109 int pos = entry->text_length;
fd0eed64 1110 return (long) pos-1;
6de97a3b 1111}
53010e52 1112
debe6624 1113void wxComboBox::Replace( long from, long to, const wxString& value )
53010e52 1114{
223d09f6 1115 wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
805dd538 1116
590f50d6
RR
1117 GtkEntry *entry = NULL;
1118#ifdef __WXGTK24__
1119 if (!gtk_check_version(2,4,0))
1120 entry = GTK_ENTRY( GTK_BIN(m_widget)->child );
1121 else
8228b893 1122#endif
590f50d6 1123 entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry );
8228b893 1124
fd0eed64
RR
1125 gtk_editable_delete_text( GTK_EDITABLE(entry), (gint)from, (gint)to );
1126 if (value.IsNull()) return;
1127 gint pos = (gint)to;
30ed6e5c 1128
2e1d7104
RR
1129#if wxUSE_UNICODE
1130 wxCharBuffer buffer = wxConvUTF8.cWX2MB( value );
1131 gtk_editable_insert_text( GTK_EDITABLE(entry), (const char*) buffer, strlen( (const char*) buffer ), &pos );
1132#else
8228b893 1133 gtk_editable_insert_text( GTK_EDITABLE(entry), value.c_str(), value.length(), &pos );
2e1d7104 1134#endif
6de97a3b 1135}
53010e52 1136
20d10ee1 1137void wxComboBox::SetSelection( long from, long to )
53010e52 1138{
590f50d6
RR
1139 GtkEntry *entry = NULL;
1140#ifdef __WXGTK24__
1141 if (!gtk_check_version(2,4,0))
1142 entry = GTK_ENTRY( GTK_BIN(m_widget)->child );
1143 else
8228b893 1144#endif
590f50d6 1145 entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry );
8228b893 1146
20d10ee1 1147 gtk_editable_select_region( GTK_EDITABLE(entry), (gint)from, (gint)to );
6de97a3b 1148}
53010e52 1149
150e31d2
JS
1150void wxComboBox::GetSelection( long* from, long* to ) const
1151{
590f50d6
RR
1152 GtkEntry *entry = NULL;
1153#ifdef __WXGTK24__
1154 if (!gtk_check_version(2,4,0))
1155 entry = GTK_ENTRY( GTK_BIN(m_widget)->child );
1156 else
8228b893 1157#endif
590f50d6 1158 entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry );
8228b893 1159
150e31d2
JS
1160 if (IsEditable())
1161 {
590f50d6 1162 GtkEditable *editable = GTK_EDITABLE(entry);
4e324a3f
JS
1163 gint start, end;
1164 gtk_editable_get_selection_bounds(editable, & start, & end);
1165 *from = start;
1166 *to = end;
150e31d2
JS
1167 }
1168}
1169
20d10ee1 1170void wxComboBox::SetEditable( bool editable )
53010e52 1171{
590f50d6
RR
1172 GtkEntry *entry = NULL;
1173#ifdef __WXGTK24__
1174 if (!gtk_check_version(2,4,0))
1175 entry = GTK_ENTRY( GTK_BIN(m_widget)->child );
1176 else
8228b893 1177#endif
590f50d6 1178 entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry );
8228b893 1179
20d10ee1 1180 gtk_entry_set_editable( GTK_ENTRY(entry), editable );
b4071e91
RR
1181}
1182
8a85884a
VZ
1183void wxComboBox::OnChar( wxKeyEvent &event )
1184{
12a3f227 1185 if ( event.GetKeyCode() == WXK_RETURN )
8a85884a 1186 {
461573cc 1187 // GTK automatically selects an item if its in the list
17a1ebd1
VZ
1188 wxCommandEvent eventEnter(wxEVT_COMMAND_TEXT_ENTER, GetId());
1189 eventEnter.SetString( GetValue() );
1190 eventEnter.SetInt( GetSelection() );
1191 eventEnter.SetEventObject( this );
3352cfff 1192
17a1ebd1 1193 if (!GetEventHandler()->ProcessEvent( eventEnter ))
3352cfff
RR
1194 {
1195 // This will invoke the dialog default action, such
1196 // as the clicking the default button.
1197
1198 wxWindow *top_frame = m_parent;
1199 while (top_frame->GetParent() && !(top_frame->IsTopLevel()))
1200 top_frame = top_frame->GetParent();
1201
1202 if (top_frame && GTK_IS_WINDOW(top_frame->m_widget))
1203 {
1204 GtkWindow *window = GTK_WINDOW(top_frame->m_widget);
1205
1206 if (window->default_widget)
150e31d2 1207 gtk_widget_activate (window->default_widget);
3352cfff
RR
1208 }
1209 }
30ed6e5c 1210
461573cc
RR
1211 // Catch GTK event so that GTK doesn't open the drop
1212 // down list upon RETURN.
0878fb4c 1213 return;
8a85884a 1214 }
30ed6e5c 1215
7cf8cb48 1216 event.Skip();
8a85884a
VZ
1217}
1218
953704c1
RR
1219void wxComboBox::DisableEvents()
1220{
590f50d6
RR
1221#ifdef __WXGTK24__
1222 if (!gtk_check_version(2,4,0))
1223 {
8228b893 1224 g_signal_handlers_disconnect_by_func (GTK_BIN(m_widget)->child,
590f50d6 1225 (gpointer)gtkcombobox_text_changed_callback, this);
8228b893 1226
590f50d6
RR
1227 g_signal_handlers_disconnect_by_func (m_widget,
1228 (gpointer)gtkcombobox_changed_callback, this);
1229 }
1230 else
8228b893 1231#endif
590f50d6
RR
1232 {
1233 g_signal_handlers_disconnect_by_func (GTK_COMBO(m_widget)->list,
1234 (gpointer) gtkcombo_combo_select_child_callback, this);
8228b893 1235
590f50d6
RR
1236 g_signal_handlers_disconnect_by_func (GTK_COMBO(m_widget)->entry,
1237 (gpointer) gtkcombo_text_changed_callback, this);
1238 }
953704c1
RR
1239}
1240
1241void wxComboBox::EnableEvents()
1242{
590f50d6
RR
1243#ifdef __WXGTK24__
1244 if (!gtk_check_version(2,4,0))
1245 {
1246 g_signal_connect_after (GTK_BIN(m_widget)->child, "changed",
1247 G_CALLBACK (gtkcombobox_text_changed_callback), this);
8228b893 1248
590f50d6
RR
1249 g_signal_connect_after (m_widget, "changed",
1250 G_CALLBACK (gtkcombobox_changed_callback), this);
1251 }
1252 else
8228b893 1253#endif
590f50d6
RR
1254 {
1255 g_signal_connect_after (GTK_COMBO(m_widget)->list, "select-child",
1fb33bdb 1256 G_CALLBACK (gtkcombo_combo_select_child_callback),
9fa72bd2 1257 this);
590f50d6 1258 g_signal_connect_after (GTK_COMBO(m_widget)->entry, "changed",
1fb33bdb 1259 G_CALLBACK (gtkcombo_text_changed_callback),
9fa72bd2 1260 this );
590f50d6 1261 }
953704c1
RR
1262}
1263
b4071e91
RR
1264void wxComboBox::OnSize( wxSizeEvent &event )
1265{
590f50d6
RR
1266#ifdef __WXGTK24__
1267 if (!gtk_check_version(2,4,0))
1268 {
1269 // Do nothing
1270 }
1271 else
1272#endif
1273 {
1274 // NB: In some situations (e.g. on non-first page of a wizard, if the
1275 // size used is default size), GtkCombo widget is resized correctly,
1276 // but it's look is not updated, it's rendered as if it was much wider.
1277 // No other widgets are affected, so it looks like a bug in GTK+.
1278 // Manually requesting resize calculation (as gtk_pizza_set_size does)
1279 // fixes it.
1280 if (GTK_WIDGET_VISIBLE(m_widget))
1281 gtk_widget_queue_resize(m_widget);
1282 }
260a67b7 1283
f03fc89f 1284 event.Skip();
6de97a3b 1285}
53010e52 1286
f40fdaa3 1287void wxComboBox::DoApplyWidgetStyle(GtkRcStyle *style)
868a2826 1288{
590f50d6
RR
1289#ifdef __WXGTK24__
1290 if (!gtk_check_version(2,4,0))
1291 {
1292 // Do nothing
1293 }
1294 else
1295#endif
1296 {
f40fdaa3 1297// gtk_widget_modify_style( GTK_COMBO(m_widget)->button, syle );
ea2d542c 1298
590f50d6
RR
1299 gtk_widget_modify_style( GTK_COMBO(m_widget)->entry, style );
1300 gtk_widget_modify_style( GTK_COMBO(m_widget)->list, style );
805dd538 1301
590f50d6
RR
1302 GtkList *list = GTK_LIST( GTK_COMBO(m_widget)->list );
1303 GList *child = list->children;
1304 while (child)
1305 {
1306 gtk_widget_modify_style( GTK_WIDGET(child->data), style );
805dd538 1307
590f50d6
RR
1308 GtkBin *bin = GTK_BIN(child->data);
1309 gtk_widget_modify_style( bin->child, style );
805dd538 1310
590f50d6
RR
1311 child = child->next;
1312 }
fd0eed64 1313 }
868a2826 1314}
b4071e91 1315
fd0eed64 1316GtkWidget* wxComboBox::GetConnectWidget()
97b3455a 1317{
590f50d6
RR
1318 GtkEntry *entry = NULL;
1319#ifdef __WXGTK24__
1320 if (!gtk_check_version(2,4,0))
1321 entry = GTK_ENTRY( GTK_BIN(m_widget)->child );
1322 else
8228b893 1323#endif
590f50d6 1324 entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry );
8228b893 1325
590f50d6 1326 return GTK_WIDGET( entry );
97b3455a
RR
1327}
1328
b4071e91
RR
1329bool wxComboBox::IsOwnGtkWindow( GdkWindow *window )
1330{
590f50d6
RR
1331 GtkEntry *entry = NULL;
1332#ifdef __WXGTK24__
1333 if (!gtk_check_version(2,4,0))
1334 {
1335 entry = GTK_ENTRY( GTK_BIN(m_widget)->child );
1336 return (window == entry->text_area);
1337 }
1338 else
8228b893 1339#endif
590f50d6
RR
1340 {
1341 entry = GTK_ENTRY( GTK_COMBO(m_widget)->entry );
1342 return ( (window == entry->text_area) ||
1343 (window == GTK_COMBO(m_widget)->button->window ) );
1344 }
b4071e91 1345}
ac57418f 1346
f68586e5
VZ
1347wxSize wxComboBox::DoGetBestSize() const
1348{
db434467 1349 wxSize ret( wxControl::DoGetBestSize() );
a6fc8ae3
VZ
1350
1351 // we know better our horizontal extent: it depends on the longest string
1352 // in the combobox
a6fc8ae3
VZ
1353 if ( m_widget )
1354 {
60d85ccb 1355 int width;
aa61d352
VZ
1356 unsigned int count = GetCount();
1357 for ( unsigned int n = 0; n < count; n++ )
a6fc8ae3 1358 {
aa61d352 1359 GetTextExtent(GetString(n), &width, NULL, NULL, NULL );
a6fc8ae3
VZ
1360 if ( width > ret.x )
1361 ret.x = width;
1362 }
1363 }
1364
1365 // empty combobox should have some reasonable default size too
1366 if ( ret.x < 100 )
1367 ret.x = 100;
9f884528
RD
1368
1369 CacheBestSize(ret);
db434467 1370 return ret;
f68586e5
VZ
1371}
1372
9d522606
RD
1373// static
1374wxVisualAttributes
1375wxComboBox::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
1376{
590f50d6
RR
1377#ifdef __WXGTK24__
1378 if (!gtk_check_version(2,4,0))
1379 return GetDefaultAttributesFromGTKWidget(gtk_combo_box_entry_new, true);
1380 else
1381#endif
1382 return GetDefaultAttributesFromGTKWidget(gtk_combo_new, true);
9d522606
RD
1383}
1384
150e31d2
JS
1385// ----------------------------------------------------------------------------
1386// standard event handling
1387// ----------------------------------------------------------------------------
1388
1389void wxComboBox::OnCut(wxCommandEvent& WXUNUSED(event))
1390{
1391 Cut();
1392}
1393
1394void wxComboBox::OnCopy(wxCommandEvent& WXUNUSED(event))
1395{
1396 Copy();
1397}
1398
1399void wxComboBox::OnPaste(wxCommandEvent& WXUNUSED(event))
1400{
1401 Paste();
1402}
1403
1404void wxComboBox::OnUndo(wxCommandEvent& WXUNUSED(event))
1405{
1406 Undo();
1407}
1408
1409void wxComboBox::OnRedo(wxCommandEvent& WXUNUSED(event))
1410{
1411 Redo();
1412}
1413
1414void wxComboBox::OnDelete(wxCommandEvent& WXUNUSED(event))
1415{
1416 long from, to;
1417 GetSelection(& from, & to);
1418 if (from != -1 && to != -1)
1419 Remove(from, to);
1420}
1421
1422void wxComboBox::OnSelectAll(wxCommandEvent& WXUNUSED(event))
1423{
1424 SetSelection(-1, -1);
1425}
1426
1427void wxComboBox::OnUpdateCut(wxUpdateUIEvent& event)
1428{
1429 event.Enable( CanCut() );
1430}
1431
1432void wxComboBox::OnUpdateCopy(wxUpdateUIEvent& event)
1433{
1434 event.Enable( CanCopy() );
1435}
1436
1437void wxComboBox::OnUpdatePaste(wxUpdateUIEvent& event)
1438{
1439 event.Enable( CanPaste() );
1440}
1441
1442void wxComboBox::OnUpdateUndo(wxUpdateUIEvent& event)
1443{
1444 event.Enable( CanUndo() );
1445}
1446
1447void wxComboBox::OnUpdateRedo(wxUpdateUIEvent& event)
1448{
1449 event.Enable( CanRedo() );
1450}
1451
1452void wxComboBox::OnUpdateDelete(wxUpdateUIEvent& event)
1453{
1454 event.Enable(HasSelection() && IsEditable()) ;
1455}
1456
1457void wxComboBox::OnUpdateSelectAll(wxUpdateUIEvent& event)
1458{
1459 event.Enable(GetLastPosition() > 0);
1460}
1461
dcf924a3 1462#endif