]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/combobox.cpp
bug in wxString::Printf() corrected (the length of the string wasn't updated
[wxWidgets.git] / src / gtk / combobox.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: combobox.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "combobox.h"
12 #endif
13
14
15 #include "wx/combobox.h"
16
17 #ifdef wxUSE_COMBOBOX
18
19 #include <wx/intl.h>
20
21 #include "gdk/gdk.h"
22 #include "gtk/gtk.h"
23
24 //-----------------------------------------------------------------------------
25 // data
26 //-----------------------------------------------------------------------------
27
28 extern bool g_blockEventsOnDrag;
29
30 //-----------------------------------------------------------------------------
31 // "select"
32 //-----------------------------------------------------------------------------
33
34 static void gtk_combo_clicked_callback( GtkWidget *WXUNUSED(widget), wxComboBox *combo )
35 {
36 if (!combo->HasVMT()) return;
37 if (g_blockEventsOnDrag) return;
38
39 if (combo->m_alreadySent)
40 {
41 combo->m_alreadySent = FALSE;
42 return;
43 }
44
45 combo->m_alreadySent = TRUE;
46
47 wxCommandEvent event(wxEVT_COMMAND_CHOICE_SELECTED, combo->GetId());
48 event.SetInt( combo->GetSelection() );
49 wxString tmp( combo->GetStringSelection() );
50 event.SetString( WXSTRINGCAST(tmp) );
51 event.SetEventObject(combo);
52 combo->GetEventHandler()->ProcessEvent(event);
53 }
54
55 //-----------------------------------------------------------------------------
56 // wxComboBox
57 //-----------------------------------------------------------------------------
58
59 IMPLEMENT_DYNAMIC_CLASS(wxComboBox,wxControl)
60
61 BEGIN_EVENT_TABLE(wxComboBox, wxControl)
62 EVT_SIZE(wxComboBox::OnSize)
63 END_EVENT_TABLE()
64
65 bool wxComboBox::Create( wxWindow *parent, wxWindowID id, const wxString& value,
66 const wxPoint& pos, const wxSize& size,
67 int n, const wxString choices[],
68 long style, const wxValidator& validator,
69 const wxString& name )
70 {
71 m_alreadySent = FALSE;
72 m_needParent = TRUE;
73 m_acceptsFocus = TRUE;
74
75 PreCreation( parent, id, pos, size, style, name );
76
77 SetValidator( validator );
78
79 m_widget = gtk_combo_new();
80
81 wxSize newSize = size;
82 if (newSize.x == -1) newSize.x = 100;
83 if (newSize.y == -1) newSize.y = 26;
84 SetSize( newSize.x, newSize.y );
85
86 GtkWidget *list = GTK_COMBO(m_widget)->list;
87
88 for (int i = 0; i < n; i++)
89 {
90 GtkWidget *list_item = gtk_list_item_new_with_label( choices[i] );
91
92 m_clientDataList.Append( (wxObject*)NULL );
93 m_clientObjectList.Append( (wxObject*)NULL );
94
95 gtk_container_add( GTK_CONTAINER(list), list_item );
96
97 gtk_widget_realize( list_item );
98 gtk_widget_realize( GTK_BIN(list_item)->child );
99
100 gtk_widget_show( list_item );
101
102 gtk_signal_connect( GTK_OBJECT(list_item), "select",
103 GTK_SIGNAL_FUNC(gtk_combo_clicked_callback), (gpointer)this );
104 }
105
106 m_parent->AddChild( this );
107
108 (m_parent->m_insertCallback)( m_parent, this );
109
110 PostCreation();
111
112 ConnectWidget( GTK_COMBO(m_widget)->button );
113
114 if (!value.IsNull()) SetValue( value );
115
116 gtk_widget_realize( GTK_COMBO(m_widget)->list );
117 gtk_widget_realize( GTK_COMBO(m_widget)->entry );
118 gtk_widget_realize( GTK_COMBO(m_widget)->button );
119
120 SetBackgroundColour( parent->GetBackgroundColour() );
121 SetForegroundColour( parent->GetForegroundColour() );
122
123 Show( TRUE );
124
125 return TRUE;
126 }
127
128 wxComboBox::~wxComboBox()
129 {
130 wxNode *node = m_clientDataList.First();
131 while (node)
132 {
133 wxClientData *cd = (wxClientData*)node->Data();
134 if (cd) delete cd;
135 node = node->Next();
136 }
137 m_clientDataList.Clear();
138 }
139
140 void wxComboBox::AppendCommon( const wxString &item )
141 {
142 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
143
144 GtkWidget *list = GTK_COMBO(m_widget)->list;
145
146 GtkWidget *list_item = gtk_list_item_new_with_label( item );
147
148 gtk_signal_connect( GTK_OBJECT(list_item), "select",
149 GTK_SIGNAL_FUNC(gtk_combo_clicked_callback), (gpointer)this );
150
151 gtk_container_add( GTK_CONTAINER(list), list_item );
152
153 if (m_widgetStyle) ApplyWidgetStyle();
154
155 gtk_widget_show( list_item );
156 }
157
158 void wxComboBox::Append( const wxString &item )
159 {
160 m_clientDataList.Append( (wxObject*) NULL );
161 m_clientObjectList.Append( (wxObject*) NULL );
162
163 AppendCommon( item );
164 }
165
166 void wxComboBox::Append( const wxString &item, void *clientData )
167 {
168 m_clientDataList.Append( (wxObject*) clientData );
169 m_clientObjectList.Append( (wxObject*)NULL );
170
171 AppendCommon( item );
172 }
173
174 void wxComboBox::Append( const wxString &item, wxClientData *clientData )
175 {
176 m_clientDataList.Append( (wxObject*) NULL );
177 m_clientObjectList.Append( (wxObject*) clientData );
178
179 AppendCommon( item );
180 }
181
182 void wxComboBox::SetClientData( int n, void* clientData )
183 {
184 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
185
186 wxNode *node = m_clientDataList.Nth( n );
187 if (!node) return;
188
189 node->SetData( (wxObject*) clientData );
190 }
191
192 void* wxComboBox::GetClientData( int n )
193 {
194 wxCHECK_MSG( m_widget != NULL, NULL, "invalid combobox" );
195
196 wxNode *node = m_clientDataList.Nth( n );
197 if (!node) return NULL;
198
199 return node->Data();
200 }
201
202 void wxComboBox::SetClientObject( int n, wxClientData* clientData )
203 {
204 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
205
206 wxNode *node = m_clientObjectList.Nth( n );
207 if (!node) return;
208
209 wxClientData *cd = (wxClientData*) node->Data();
210 if (cd) delete cd;
211
212 node->SetData( (wxObject*) clientData );
213 }
214
215 wxClientData* wxComboBox::GetClientObject( int n )
216 {
217 wxCHECK_MSG( m_widget != NULL, (wxClientData*)NULL, "invalid combobox" );
218
219 wxNode *node = m_clientDataList.Nth( n );
220 if (!node) return (wxClientData*) NULL;
221
222 return (wxClientData*) node->Data();
223 }
224
225 void wxComboBox::Clear()
226 {
227 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
228
229 GtkWidget *list = GTK_COMBO(m_widget)->list;
230 gtk_list_clear_items( GTK_LIST(list), 0, Number() );
231
232 wxNode *node = m_clientObjectList.First();
233 while (node)
234 {
235 wxClientData *cd = (wxClientData*)node->Data();
236 if (cd) delete cd;
237 node = node->Next();
238 }
239 m_clientObjectList.Clear();
240
241 m_clientDataList.Clear();
242 }
243
244 void wxComboBox::Delete( int n )
245 {
246 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
247
248 GtkList *listbox = GTK_LIST( GTK_COMBO(m_widget)->list );
249
250 GList *child = g_list_nth( listbox->children, n );
251
252 if (!child)
253 {
254 wxFAIL_MSG("wrong index");
255 return;
256 }
257
258 GList *list = g_list_append( NULL, child->data );
259 gtk_list_remove_items( listbox, list );
260 g_list_free( list );
261
262 wxNode *node = m_clientObjectList.Nth( n );
263 if (node)
264 {
265 wxClientData *cd = (wxClientData*)node->Data();
266 if (cd) delete cd;
267 m_clientObjectList.DeleteNode( node );
268 }
269
270 node = m_clientDataList.Nth( n );
271 if (node)
272 {
273 m_clientDataList.DeleteNode( node );
274 }
275 }
276
277 int wxComboBox::FindString( const wxString &item )
278 {
279 wxCHECK_MSG( m_widget != NULL, -1, "invalid combobox" );
280
281 GtkWidget *list = GTK_COMBO(m_widget)->list;
282
283 GList *child = GTK_LIST(list)->children;
284 int count = 0;
285 while (child)
286 {
287 GtkBin *bin = GTK_BIN( child->data );
288 GtkLabel *label = GTK_LABEL( bin->child );
289 if (item == label->label) return count;
290 count++;
291 child = child->next;
292 }
293
294 wxFAIL_MSG( "wxComboBox: string not found" );
295
296 return -1;
297 }
298
299 int wxComboBox::GetSelection() const
300 {
301 wxCHECK_MSG( m_widget != NULL, -1, "invalid combobox" );
302
303 GtkWidget *list = GTK_COMBO(m_widget)->list;
304
305 GList *selection = GTK_LIST(list)->selection;
306 if (selection)
307 {
308 GList *child = GTK_LIST(list)->children;
309 int count = 0;
310 while (child)
311 {
312 if (child->data == selection->data) return count;
313 count++;
314 child = child->next;
315 }
316 }
317
318 wxFAIL_MSG( "wxComboBox: no selection" );
319
320 return -1;
321 }
322
323 wxString wxComboBox::GetString( int n ) const
324 {
325 wxCHECK_MSG( m_widget != NULL, "", "invalid combobox" );
326
327 GtkWidget *list = GTK_COMBO(m_widget)->list;
328
329 GList *child = g_list_nth( GTK_LIST(list)->children, n );
330 if (child)
331 {
332 GtkBin *bin = GTK_BIN( child->data );
333 GtkLabel *label = GTK_LABEL( bin->child );
334 return label->label;
335 }
336
337 wxFAIL_MSG( "wxComboBox: wrong index" );
338
339 return "";
340 }
341
342 wxString wxComboBox::GetStringSelection() const
343 {
344 wxCHECK_MSG( m_widget != NULL, "", "invalid combobox" );
345
346 GtkWidget *list = GTK_COMBO(m_widget)->list;
347
348 GList *selection = GTK_LIST(list)->selection;
349 if (selection)
350 {
351 GtkBin *bin = GTK_BIN( selection->data );
352 wxString tmp = GTK_LABEL( bin->child )->label;
353 return tmp;
354 }
355
356 wxFAIL_MSG( "wxComboBox: no selection" );
357
358 return "";
359 }
360
361 int wxComboBox::Number() const
362 {
363 wxCHECK_MSG( m_widget != NULL, 0, "invalid combobox" );
364
365 GtkWidget *list = GTK_COMBO(m_widget)->list;
366
367 GList *child = GTK_LIST(list)->children;
368 int count = 0;
369 while (child) { count++; child = child->next; }
370 return count;
371 }
372
373 void wxComboBox::SetSelection( int n )
374 {
375 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
376
377 GtkWidget *list = GTK_COMBO(m_widget)->list;
378 gtk_list_select_item( GTK_LIST(list), n );
379 }
380
381 void wxComboBox::SetStringSelection( const wxString &string )
382 {
383 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
384
385 int res = FindString( string );
386 if (res == -1) return;
387 SetSelection( res );
388 }
389
390 wxString wxComboBox::GetValue() const
391 {
392 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
393 wxString tmp = gtk_entry_get_text( GTK_ENTRY(entry) );
394 return tmp;
395 }
396
397 void wxComboBox::SetValue( const wxString& value )
398 {
399 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
400
401 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
402 wxString tmp = "";
403 if (!value.IsNull()) tmp = value;
404 gtk_entry_set_text( GTK_ENTRY(entry), tmp );
405 }
406
407 void wxComboBox::Copy()
408 {
409 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
410
411 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
412 #if (GTK_MINOR_VERSION == 1)
413 gtk_editable_copy_clipboard( GTK_EDITABLE(entry) );
414 #else
415 gtk_editable_copy_clipboard( GTK_EDITABLE(entry), 0 );
416 #endif
417 }
418
419 void wxComboBox::Cut()
420 {
421 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
422
423 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
424 #if (GTK_MINOR_VERSION == 1)
425 gtk_editable_cut_clipboard( GTK_EDITABLE(entry) );
426 #else
427 gtk_editable_cut_clipboard( GTK_EDITABLE(entry), 0 );
428 #endif
429 }
430
431 void wxComboBox::Paste()
432 {
433 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
434
435 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
436 #if (GTK_MINOR_VERSION == 1)
437 gtk_editable_paste_clipboard( GTK_EDITABLE(entry) );
438 #else
439 gtk_editable_paste_clipboard( GTK_EDITABLE(entry), 0 );
440 #endif
441 }
442
443 void wxComboBox::SetInsertionPoint( long pos )
444 {
445 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
446
447 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
448 int tmp = (int) pos;
449 gtk_entry_set_position( GTK_ENTRY(entry), tmp );
450 }
451
452 void wxComboBox::SetInsertionPointEnd()
453 {
454 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
455
456 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
457 int pos = GTK_ENTRY(entry)->text_length;
458 SetInsertionPoint( pos-1 );
459 }
460
461 long wxComboBox::GetInsertionPoint() const
462 {
463 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
464 return (long) GTK_EDITABLE(entry)->current_pos;
465 }
466
467 long wxComboBox::GetLastPosition() const
468 {
469 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
470 int pos = GTK_ENTRY(entry)->text_length;
471 return (long) pos-1;
472 }
473
474 void wxComboBox::Replace( long from, long to, const wxString& value )
475 {
476 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
477
478 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
479 gtk_editable_delete_text( GTK_EDITABLE(entry), (gint)from, (gint)to );
480 if (value.IsNull()) return;
481 gint pos = (gint)to;
482 gtk_editable_insert_text( GTK_EDITABLE(entry), value, value.Length(), &pos );
483 }
484
485 void wxComboBox::Remove(long from, long to)
486 {
487 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
488
489 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
490 gtk_editable_delete_text( GTK_EDITABLE(entry), (gint)from, (gint)to );
491 }
492
493 void wxComboBox::SetSelection( long WXUNUSED(from), long WXUNUSED(to) )
494 {
495 wxFAIL_MSG( "wxComboBox::SetSelection not implemented" );
496 }
497
498 void wxComboBox::SetEditable( bool WXUNUSED(editable) )
499 {
500 wxFAIL_MSG( "wxComboBox::SetEditable not implemented" );
501 }
502
503 void wxComboBox::OnSize( wxSizeEvent &event )
504 {
505 wxControl::OnSize( event );
506
507 int w = 21;
508 gtk_widget_set_usize( GTK_COMBO(m_widget)->entry, m_width-w-1, m_height );
509
510 gtk_widget_set_uposition( GTK_COMBO(m_widget)->button, m_x+m_width-w, m_y );
511 gtk_widget_set_usize( GTK_COMBO(m_widget)->button, w, m_height );
512 }
513
514 void wxComboBox::ApplyWidgetStyle()
515 {
516 SetWidgetStyle();
517
518 gtk_widget_set_style( GTK_COMBO(m_widget)->button, m_widgetStyle );
519 gtk_widget_set_style( GTK_COMBO(m_widget)->entry, m_widgetStyle );
520 gtk_widget_set_style( GTK_COMBO(m_widget)->list, m_widgetStyle );
521
522 GtkList *list = GTK_LIST( GTK_COMBO(m_widget)->list );
523 GList *child = list->children;
524 while (child)
525 {
526 gtk_widget_set_style( GTK_WIDGET(child->data), m_widgetStyle );
527
528 GtkBin *bin = GTK_BIN(child->data);
529 gtk_widget_set_style( bin->child, m_widgetStyle );
530
531 child = child->next;
532 }
533 }
534
535 GtkWidget* wxComboBox::GetConnectWidget()
536 {
537 return GTK_COMBO(m_widget)->entry;
538 }
539
540 bool wxComboBox::IsOwnGtkWindow( GdkWindow *window )
541 {
542 return ( (window == GTK_ENTRY( GTK_COMBO(m_widget)->entry )->text_area) ||
543 (window == GTK_COMBO(m_widget)->button->window ) );
544 }
545
546 #endif
547
548 // wxUSE_COMBOBOX