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