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