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