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