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