]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/combobox.cpp
HP-UX support added
[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() );
a7ac4461 137 SetFont( parent->GetFont() );
f96aa4d9 138
fd0eed64 139 Show( TRUE );
805dd538 140
fd0eed64
RR
141 return TRUE;
142}
143
144wxComboBox::~wxComboBox()
145{
146 wxNode *node = m_clientDataList.First();
147 while (node)
148 {
149 wxClientData *cd = (wxClientData*)node->Data();
150 if (cd) delete cd;
151 node = node->Next();
152 }
153 m_clientDataList.Clear();
6de97a3b 154}
53010e52 155
fd0eed64 156void wxComboBox::AppendCommon( const wxString &item )
53010e52 157{
fd0eed64 158 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
805dd538 159
fd0eed64 160 GtkWidget *list = GTK_COMBO(m_widget)->list;
805dd538
VZ
161
162 GtkWidget *list_item = gtk_list_item_new_with_label( item );
163
164 gtk_signal_connect( GTK_OBJECT(list_item), "select",
fd0eed64 165 GTK_SIGNAL_FUNC(gtk_combo_clicked_callback), (gpointer)this );
805dd538 166
fd0eed64 167 gtk_container_add( GTK_CONTAINER(list), list_item );
805dd538 168
fd0eed64 169 if (m_widgetStyle) ApplyWidgetStyle();
805dd538 170
fd0eed64 171 gtk_widget_show( list_item );
6de97a3b 172}
53010e52
RR
173
174void wxComboBox::Append( const wxString &item )
47908e25 175{
f5e27805
RR
176 m_clientDataList.Append( (wxObject*) NULL );
177 m_clientObjectList.Append( (wxObject*) NULL );
805dd538 178
fd0eed64 179 AppendCommon( item );
6de97a3b 180}
47908e25 181
fd0eed64 182void wxComboBox::Append( const wxString &item, void *clientData )
53010e52 183{
f5e27805
RR
184 m_clientDataList.Append( (wxObject*) clientData );
185 m_clientObjectList.Append( (wxObject*)NULL );
805dd538 186
fd0eed64 187 AppendCommon( item );
6de97a3b 188}
53010e52 189
fd0eed64 190void wxComboBox::Append( const wxString &item, wxClientData *clientData )
53010e52 191{
f5e27805
RR
192 m_clientDataList.Append( (wxObject*) NULL );
193 m_clientObjectList.Append( (wxObject*) clientData );
805dd538 194
fd0eed64
RR
195 AppendCommon( item );
196}
197
198void wxComboBox::SetClientData( int n, void* clientData )
199{
200 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
805dd538 201
fd0eed64
RR
202 wxNode *node = m_clientDataList.Nth( n );
203 if (!node) return;
805dd538 204
f5e27805 205 node->SetData( (wxObject*) clientData );
6de97a3b 206}
53010e52 207
fd0eed64 208void* wxComboBox::GetClientData( int n )
53010e52 209{
fd0eed64 210 wxCHECK_MSG( m_widget != NULL, NULL, "invalid combobox" );
805dd538 211
fd0eed64
RR
212 wxNode *node = m_clientDataList.Nth( n );
213 if (!node) return NULL;
805dd538 214
f5e27805 215 return node->Data();
fd0eed64
RR
216}
217
218void wxComboBox::SetClientObject( int n, wxClientData* clientData )
219{
220 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
805dd538 221
f5e27805 222 wxNode *node = m_clientObjectList.Nth( n );
fd0eed64 223 if (!node) return;
805dd538 224
fd0eed64
RR
225 wxClientData *cd = (wxClientData*) node->Data();
226 if (cd) delete cd;
805dd538 227
fd0eed64 228 node->SetData( (wxObject*) clientData );
6de97a3b 229}
53010e52 230
fd0eed64 231wxClientData* wxComboBox::GetClientObject( int n )
53010e52 232{
fd0eed64 233 wxCHECK_MSG( m_widget != NULL, (wxClientData*)NULL, "invalid combobox" );
805dd538 234
fd0eed64
RR
235 wxNode *node = m_clientDataList.Nth( n );
236 if (!node) return (wxClientData*) NULL;
805dd538 237
fd0eed64
RR
238 return (wxClientData*) node->Data();
239}
240
241void wxComboBox::Clear()
242{
243 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
805dd538 244
fd0eed64
RR
245 GtkWidget *list = GTK_COMBO(m_widget)->list;
246 gtk_list_clear_items( GTK_LIST(list), 0, Number() );
805dd538 247
f5e27805 248 wxNode *node = m_clientObjectList.First();
fd0eed64
RR
249 while (node)
250 {
251 wxClientData *cd = (wxClientData*)node->Data();
252 if (cd) delete cd;
253 node = node->Next();
254 }
f5e27805 255 m_clientObjectList.Clear();
805dd538 256
fd0eed64 257 m_clientDataList.Clear();
6de97a3b 258}
53010e52 259
fd0eed64 260void wxComboBox::Delete( int n )
53010e52 261{
fd0eed64 262 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
805dd538 263
fd0eed64 264 GtkList *listbox = GTK_LIST( GTK_COMBO(m_widget)->list );
805dd538 265
fd0eed64 266 GList *child = g_list_nth( listbox->children, n );
805dd538 267
fd0eed64
RR
268 if (!child)
269 {
270 wxFAIL_MSG("wrong index");
271 return;
272 }
805dd538 273
bbe0af5b 274 GList *list = g_list_append( (GList*) NULL, child->data );
fd0eed64
RR
275 gtk_list_remove_items( listbox, list );
276 g_list_free( list );
805dd538 277
f5e27805
RR
278 wxNode *node = m_clientObjectList.Nth( n );
279 if (node)
fd0eed64
RR
280 {
281 wxClientData *cd = (wxClientData*)node->Data();
282 if (cd) delete cd;
f5e27805
RR
283 m_clientObjectList.DeleteNode( node );
284 }
805dd538 285
f5e27805
RR
286 node = m_clientDataList.Nth( n );
287 if (node)
288 {
fd0eed64
RR
289 m_clientDataList.DeleteNode( node );
290 }
6de97a3b 291}
53010e52 292
fd0eed64 293int wxComboBox::FindString( const wxString &item )
53010e52 294{
fd0eed64 295 wxCHECK_MSG( m_widget != NULL, -1, "invalid combobox" );
805dd538 296
fd0eed64 297 GtkWidget *list = GTK_COMBO(m_widget)->list;
805dd538 298
53010e52
RR
299 GList *child = GTK_LIST(list)->children;
300 int count = 0;
301 while (child)
302 {
fd0eed64
RR
303 GtkBin *bin = GTK_BIN( child->data );
304 GtkLabel *label = GTK_LABEL( bin->child );
305 if (item == label->label) return count;
306 count++;
307 child = child->next;
308 }
805dd538 309
fd0eed64 310 wxFAIL_MSG( "wxComboBox: string not found" );
805dd538 311
fd0eed64
RR
312 return -1;
313}
314
315int wxComboBox::GetSelection() const
316{
317 wxCHECK_MSG( m_widget != NULL, -1, "invalid combobox" );
805dd538 318
fd0eed64 319 GtkWidget *list = GTK_COMBO(m_widget)->list;
805dd538 320
fd0eed64
RR
321 GList *selection = GTK_LIST(list)->selection;
322 if (selection)
323 {
324 GList *child = GTK_LIST(list)->children;
325 int count = 0;
326 while (child)
327 {
328 if (child->data == selection->data) return count;
329 count++;
330 child = child->next;
331 }
6de97a3b 332 }
805dd538 333
fd0eed64 334 wxFAIL_MSG( "wxComboBox: no selection" );
805dd538 335
fd0eed64 336 return -1;
6de97a3b 337}
53010e52 338
debe6624 339wxString wxComboBox::GetString( int n ) const
53010e52 340{
fd0eed64 341 wxCHECK_MSG( m_widget != NULL, "", "invalid combobox" );
805dd538 342
fd0eed64 343 GtkWidget *list = GTK_COMBO(m_widget)->list;
805dd538 344
fd0eed64
RR
345 GList *child = g_list_nth( GTK_LIST(list)->children, n );
346 if (child)
347 {
348 GtkBin *bin = GTK_BIN( child->data );
349 GtkLabel *label = GTK_LABEL( bin->child );
350 return label->label;
351 }
805dd538 352
fd0eed64 353 wxFAIL_MSG( "wxComboBox: wrong index" );
805dd538 354
fd0eed64 355 return "";
6de97a3b 356}
53010e52 357
fd0eed64 358wxString wxComboBox::GetStringSelection() const
53010e52 359{
fd0eed64 360 wxCHECK_MSG( m_widget != NULL, "", "invalid combobox" );
805dd538 361
fd0eed64 362 GtkWidget *list = GTK_COMBO(m_widget)->list;
805dd538 363
fd0eed64
RR
364 GList *selection = GTK_LIST(list)->selection;
365 if (selection)
366 {
367 GtkBin *bin = GTK_BIN( selection->data );
368 wxString tmp = GTK_LABEL( bin->child )->label;
369 return tmp;
370 }
805dd538 371
fd0eed64 372 wxFAIL_MSG( "wxComboBox: no selection" );
805dd538 373
fd0eed64 374 return "";
6de97a3b 375}
53010e52 376
fd0eed64 377int wxComboBox::Number() const
53010e52 378{
fd0eed64 379 wxCHECK_MSG( m_widget != NULL, 0, "invalid combobox" );
805dd538 380
fd0eed64 381 GtkWidget *list = GTK_COMBO(m_widget)->list;
805dd538 382
fd0eed64
RR
383 GList *child = GTK_LIST(list)->children;
384 int count = 0;
385 while (child) { count++; child = child->next; }
386 return count;
6de97a3b 387}
53010e52 388
debe6624 389void wxComboBox::SetSelection( int n )
53010e52 390{
fd0eed64 391 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
805dd538 392
fd0eed64
RR
393 GtkWidget *list = GTK_COMBO(m_widget)->list;
394 gtk_list_select_item( GTK_LIST(list), n );
6de97a3b 395}
53010e52 396
47908e25
RR
397void wxComboBox::SetStringSelection( const wxString &string )
398{
fd0eed64 399 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
805dd538 400
fd0eed64
RR
401 int res = FindString( string );
402 if (res == -1) return;
403 SetSelection( res );
6de97a3b 404}
47908e25 405
fd0eed64 406wxString wxComboBox::GetValue() const
53010e52 407{
fd0eed64
RR
408 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
409 wxString tmp = gtk_entry_get_text( GTK_ENTRY(entry) );
410 return tmp;
6de97a3b 411}
53010e52
RR
412
413void wxComboBox::SetValue( const wxString& value )
414{
fd0eed64 415 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
805dd538 416
fd0eed64
RR
417 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
418 wxString tmp = "";
419 if (!value.IsNull()) tmp = value;
420 gtk_entry_set_text( GTK_ENTRY(entry), tmp );
6de97a3b 421}
53010e52 422
fd0eed64 423void wxComboBox::Copy()
53010e52 424{
fd0eed64 425 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
805dd538 426
fd0eed64 427 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
75ed1d15 428#if (GTK_MINOR_VERSION == 1)
fd0eed64 429 gtk_editable_copy_clipboard( GTK_EDITABLE(entry) );
75ed1d15 430#else
fd0eed64 431 gtk_editable_copy_clipboard( GTK_EDITABLE(entry), 0 );
75ed1d15 432#endif
6de97a3b 433}
53010e52 434
fd0eed64 435void wxComboBox::Cut()
53010e52 436{
fd0eed64 437 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
805dd538 438
fd0eed64 439 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
75ed1d15 440#if (GTK_MINOR_VERSION == 1)
fd0eed64 441 gtk_editable_cut_clipboard( GTK_EDITABLE(entry) );
75ed1d15 442#else
fd0eed64 443 gtk_editable_cut_clipboard( GTK_EDITABLE(entry), 0 );
75ed1d15 444#endif
6de97a3b 445}
53010e52 446
fd0eed64 447void wxComboBox::Paste()
53010e52 448{
fd0eed64 449 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
805dd538 450
fd0eed64 451 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
75ed1d15 452#if (GTK_MINOR_VERSION == 1)
fd0eed64 453 gtk_editable_paste_clipboard( GTK_EDITABLE(entry) );
75ed1d15 454#else
fd0eed64 455 gtk_editable_paste_clipboard( GTK_EDITABLE(entry), 0 );
75ed1d15 456#endif
6de97a3b 457}
53010e52 458
debe6624 459void wxComboBox::SetInsertionPoint( long pos )
53010e52 460{
fd0eed64 461 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
805dd538 462
fd0eed64 463 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
073c8fe9 464 gtk_entry_set_position( GTK_ENTRY(entry), (int)pos );
6de97a3b 465}
53010e52 466
fd0eed64 467void wxComboBox::SetInsertionPointEnd()
53010e52 468{
fd0eed64 469 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
805dd538
VZ
470
471 SetInsertionPoint( -1 );
6de97a3b 472}
53010e52 473
fd0eed64 474long wxComboBox::GetInsertionPoint() const
53010e52 475{
fd0eed64
RR
476 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
477 return (long) GTK_EDITABLE(entry)->current_pos;
6de97a3b 478}
53010e52 479
fd0eed64 480long wxComboBox::GetLastPosition() const
53010e52 481{
fd0eed64
RR
482 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
483 int pos = GTK_ENTRY(entry)->text_length;
484 return (long) pos-1;
6de97a3b 485}
53010e52 486
debe6624 487void wxComboBox::Replace( long from, long to, const wxString& value )
53010e52 488{
fd0eed64 489 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
805dd538 490
fd0eed64
RR
491 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
492 gtk_editable_delete_text( GTK_EDITABLE(entry), (gint)from, (gint)to );
493 if (value.IsNull()) return;
494 gint pos = (gint)to;
495 gtk_editable_insert_text( GTK_EDITABLE(entry), value, value.Length(), &pos );
6de97a3b 496}
53010e52 497
debe6624 498void wxComboBox::Remove(long from, long to)
53010e52 499{
fd0eed64 500 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
805dd538 501
fd0eed64
RR
502 GtkWidget *entry = GTK_COMBO(m_widget)->entry;
503 gtk_editable_delete_text( GTK_EDITABLE(entry), (gint)from, (gint)to );
6de97a3b 504}
53010e52 505
debe6624 506void wxComboBox::SetSelection( long WXUNUSED(from), long WXUNUSED(to) )
53010e52 507{
fd0eed64 508 wxFAIL_MSG( "wxComboBox::SetSelection not implemented" );
6de97a3b 509}
53010e52 510
debe6624 511void wxComboBox::SetEditable( bool WXUNUSED(editable) )
53010e52 512{
fd0eed64 513 wxFAIL_MSG( "wxComboBox::SetEditable not implemented" );
b4071e91
RR
514}
515
516void wxComboBox::OnSize( wxSizeEvent &event )
517{
fd0eed64 518 wxControl::OnSize( event );
805dd538 519
fd0eed64
RR
520 int w = 21;
521 gtk_widget_set_usize( GTK_COMBO(m_widget)->entry, m_width-w-1, m_height );
805dd538 522
fd0eed64
RR
523 gtk_widget_set_uposition( GTK_COMBO(m_widget)->button, m_x+m_width-w, m_y );
524 gtk_widget_set_usize( GTK_COMBO(m_widget)->button, w, m_height );
6de97a3b 525}
53010e52 526
58614078 527void wxComboBox::ApplyWidgetStyle()
868a2826 528{
fd0eed64 529 SetWidgetStyle();
805dd538 530
fd0eed64
RR
531 gtk_widget_set_style( GTK_COMBO(m_widget)->button, m_widgetStyle );
532 gtk_widget_set_style( GTK_COMBO(m_widget)->entry, m_widgetStyle );
533 gtk_widget_set_style( GTK_COMBO(m_widget)->list, m_widgetStyle );
805dd538 534
fd0eed64
RR
535 GtkList *list = GTK_LIST( GTK_COMBO(m_widget)->list );
536 GList *child = list->children;
537 while (child)
538 {
539 gtk_widget_set_style( GTK_WIDGET(child->data), m_widgetStyle );
805dd538 540
fd0eed64
RR
541 GtkBin *bin = GTK_BIN(child->data);
542 gtk_widget_set_style( bin->child, m_widgetStyle );
805dd538 543
fd0eed64
RR
544 child = child->next;
545 }
868a2826 546}
b4071e91 547
fd0eed64 548GtkWidget* wxComboBox::GetConnectWidget()
97b3455a 549{
fd0eed64 550 return GTK_COMBO(m_widget)->entry;
97b3455a
RR
551}
552
b4071e91
RR
553bool wxComboBox::IsOwnGtkWindow( GdkWindow *window )
554{
fd0eed64
RR
555 return ( (window == GTK_ENTRY( GTK_COMBO(m_widget)->entry )->text_area) ||
556 (window == GTK_COMBO(m_widget)->button->window ) );
b4071e91 557}
ac57418f 558