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