]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/listbox.cpp
correct a bug in the MSW code using wxMask
[wxWidgets.git] / src / gtk / listbox.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: listbox.cpp
3// Purpose:
4// Author: Robert Roebling
f96aa4d9
RR
5// Id: $Id$
6// Copyright: (c) 1998 Robert Roebling
a3622daa 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
10
11#ifdef __GNUG__
12#pragma implementation "listbox.h"
13#endif
14
6a6d4eed 15#include "wx/dynarray.h"
c801d85f 16#include "wx/listbox.h"
09cf7c58 17#include "wx/utils.h"
1a5a8367 18#include <wx/intl.h>
c801d85f 19
38c7b3d3
RR
20//-------------------------------------------------------------------------
21// conditional compilation
22//-------------------------------------------------------------------------
23
24#if (GTK_MINOR_VERSION == 1)
25#if (GTK_MICRO_VERSION >= 5)
26#define NEW_GTK_SCROLL_CODE
27#endif
28#endif
29
66bd6b93
RR
30//-----------------------------------------------------------------------------
31// data
32//-----------------------------------------------------------------------------
33
34extern bool g_blockEventsOnDrag;
35
c801d85f 36//-----------------------------------------------------------------------------
a60c99e6 37// "select" and "deselect"
c801d85f
KB
38//-----------------------------------------------------------------------------
39
09cf7c58 40static void gtk_listitem_select_callback( GtkWidget *WXUNUSED(widget), wxListBox *listbox )
c801d85f 41{
fd0eed64
RR
42 if (!listbox->HasVMT()) return;
43 if (g_blockEventsOnDrag) return;
dcf40a56 44
fd0eed64 45 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, listbox->GetId() );
dcf40a56 46
09cf7c58
RR
47 wxArrayInt aSelections;
48 int count = listbox->GetSelections(aSelections);
49 if ( count > 0 )
50 {
fd0eed64
RR
51 event.m_commandInt = aSelections[0] ;
52 event.m_clientData = listbox->GetClientData( event.m_commandInt );
53 wxString str(listbox->GetString(event.m_commandInt));
54 if (str != "") event.m_commandString = copystring((char *)(const char *)str);
09cf7c58
RR
55 }
56 else
57 {
fd0eed64
RR
58 event.m_commandInt = -1 ;
59 event.m_commandString = copystring("") ;
09cf7c58
RR
60 }
61
fd0eed64 62 event.SetEventObject( listbox );
a3622daa 63
fd0eed64
RR
64 listbox->GetEventHandler()->ProcessEvent( event );
65 if (event.m_commandString) delete[] event.m_commandString ;
6de97a3b 66}
c801d85f 67
a60c99e6
RR
68//-----------------------------------------------------------------------------
69// wxListBox
c801d85f
KB
70//-----------------------------------------------------------------------------
71
72IMPLEMENT_DYNAMIC_CLASS(wxListBox,wxControl)
73
fd0eed64 74wxListBox::wxListBox()
c801d85f 75{
fd0eed64 76 m_list = (GtkList *) NULL;
6de97a3b 77}
c801d85f 78
dcf40a56 79bool wxListBox::Create( wxWindow *parent, wxWindowID id,
fd0eed64
RR
80 const wxPoint &pos, const wxSize &size,
81 int n, const wxString choices[],
82 long style, const wxValidator& validator, const wxString &name )
c801d85f 83{
fd0eed64 84 m_needParent = TRUE;
dcf40a56 85
fd0eed64 86 PreCreation( parent, id, pos, size, style, name );
dcf40a56 87
fd0eed64 88 SetValidator( validator );
6de97a3b 89
fd0eed64
RR
90 m_widget = gtk_scrolled_window_new( (GtkAdjustment*) NULL, (GtkAdjustment*) NULL );
91 gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(m_widget),
92 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
dcf40a56 93
fd0eed64 94 m_list = GTK_LIST( gtk_list_new() );
dcf40a56 95
fd0eed64
RR
96 GtkSelectionMode mode = GTK_SELECTION_BROWSE;
97 if (style & wxLB_MULTIPLE)
98 mode = GTK_SELECTION_MULTIPLE;
99 else if (style & wxLB_EXTENDED)
100 mode = GTK_SELECTION_EXTENDED;
6a6d4eed 101
fd0eed64 102 gtk_list_set_selection_mode( GTK_LIST(m_list), mode );
dcf40a56 103
38c7b3d3
RR
104#ifdef NEW_GTK_SCROLL_CODE
105 gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(m_widget), GTK_WIDGET(m_list) );
106#else
fd0eed64 107 gtk_container_add( GTK_CONTAINER(m_widget), GTK_WIDGET(m_list) );
38c7b3d3
RR
108#endif
109
fd0eed64 110 gtk_widget_show( GTK_WIDGET(m_list) );
dcf40a56 111
fd0eed64
RR
112 wxSize newSize = size;
113 if (newSize.x == -1) newSize.x = 100;
114 if (newSize.y == -1) newSize.y = 110;
115 SetSize( newSize.x, newSize.y );
dcf40a56 116
fd0eed64
RR
117 for (int i = 0; i < n; i++)
118 {
f5e27805
RR
119 m_clientDataList.Append( (wxObject*) NULL );
120 m_clientObjectList.Append( (wxObject*) NULL );
121
fd0eed64
RR
122 GtkWidget *list_item;
123 list_item = gtk_list_item_new_with_label( choices[i] );
dcf40a56 124
fd0eed64 125 gtk_container_add( GTK_CONTAINER(m_list), list_item );
dcf40a56 126
fd0eed64
RR
127 gtk_signal_connect( GTK_OBJECT(list_item), "select",
128 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
dcf40a56 129
fd0eed64
RR
130 if (style & wxLB_MULTIPLE)
131 gtk_signal_connect( GTK_OBJECT(list_item), "deselect",
132 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
dcf40a56 133
fd0eed64 134 ConnectWidget( list_item );
c67d8618 135
fd0eed64
RR
136 gtk_widget_show( list_item );
137 }
dcf40a56 138
fd0eed64 139 m_parent->AddChild( this );
6ca41e57 140
fd0eed64 141 (m_parent->m_insertCallback)( m_parent, this );
6ca41e57 142
fd0eed64 143 PostCreation();
dcf40a56 144
fd0eed64 145 gtk_widget_realize( GTK_WIDGET(m_list) );
dcf40a56 146
fd0eed64
RR
147 SetBackgroundColour( parent->GetBackgroundColour() );
148 SetForegroundColour( parent->GetForegroundColour() );
f96aa4d9 149
fd0eed64 150 Show( TRUE );
dcf40a56 151
fd0eed64 152 return TRUE;
6de97a3b 153}
c801d85f 154
fd0eed64 155wxListBox::~wxListBox()
c801d85f 156{
f5e27805 157 Clear();
6de97a3b 158}
c801d85f 159
fd0eed64 160void wxListBox::AppendCommon( const wxString &item )
c801d85f 161{
fd0eed64
RR
162 wxCHECK_RET( m_list != NULL, "invalid listbox" );
163
164 GtkWidget *list_item = gtk_list_item_new_with_label( item );
fc54776e 165
fd0eed64
RR
166 gtk_signal_connect( GTK_OBJECT(list_item), "select",
167 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
dcf40a56 168
fd0eed64
RR
169 if (GetWindowStyleFlag() & wxLB_MULTIPLE)
170 gtk_signal_connect( GTK_OBJECT(list_item), "deselect",
171 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
dcf40a56 172
fd0eed64 173 gtk_container_add( GTK_CONTAINER(m_list), list_item );
dcf40a56 174
fd0eed64
RR
175 if (m_widgetStyle) ApplyWidgetStyle();
176
177 gtk_widget_show( list_item );
178
179 ConnectWidget( list_item );
180
38c7b3d3 181#ifndef NEW_GTK_DND_CODE
33a5bc52 182 if (m_dropTarget) m_dropTarget->RegisterWidget( list_item );
38c7b3d3 183#endif
fd0eed64
RR
184}
185
186void wxListBox::Append( const wxString &item )
187{
f5e27805
RR
188 m_clientDataList.Append( (wxObject*) NULL );
189 m_clientObjectList.Append( (wxObject*) NULL );
fd0eed64
RR
190
191 AppendCommon( item );
192}
193
194void wxListBox::Append( const wxString &item, void *clientData )
195{
f5e27805
RR
196 m_clientDataList.Append( (wxObject*) clientData );
197 m_clientObjectList.Append( (wxObject*) NULL );
fd0eed64
RR
198
199 AppendCommon( item );
200}
dcf40a56 201
fd0eed64
RR
202void wxListBox::Append( const wxString &item, wxClientData *clientData )
203{
f5e27805
RR
204 m_clientObjectList.Append( (wxObject*) clientData );
205 m_clientDataList.Append( (wxObject*) NULL );
fd0eed64
RR
206
207 AppendCommon( item );
208}
dcf40a56 209
fd0eed64
RR
210void wxListBox::SetClientData( int n, void* clientData )
211{
212 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
213
214 wxNode *node = m_clientDataList.Nth( n );
215 if (!node) return;
7bce6aec 216
f5e27805 217 node->SetData( (wxObject*) clientData );
fd0eed64 218}
dcf40a56 219
fd0eed64
RR
220void* wxListBox::GetClientData( int n )
221{
222 wxCHECK_MSG( m_widget != NULL, NULL, "invalid combobox" );
223
224 wxNode *node = m_clientDataList.Nth( n );
225 if (!node) return NULL;
226
f5e27805 227 return node->Data();
fd0eed64 228}
dcf40a56 229
fd0eed64
RR
230void wxListBox::SetClientObject( int n, wxClientData* clientData )
231{
232 wxCHECK_RET( m_widget != NULL, "invalid combobox" );
233
f5e27805 234 wxNode *node = m_clientObjectList.Nth( n );
fd0eed64
RR
235 if (!node) return;
236
237 wxClientData *cd = (wxClientData*) node->Data();
238 if (cd) delete cd;
239
240 node->SetData( (wxObject*) clientData );
6de97a3b 241}
c801d85f 242
fd0eed64 243wxClientData* wxListBox::GetClientObject( int n )
c801d85f 244{
fd0eed64
RR
245 wxCHECK_MSG( m_widget != NULL, (wxClientData*)NULL, "invalid combobox" );
246
f5e27805 247 wxNode *node = m_clientObjectList.Nth( n );
fd0eed64
RR
248 if (!node) return (wxClientData*) NULL;
249
250 return (wxClientData*) node->Data();
251}
252
253void wxListBox::Clear()
254{
255 wxCHECK_RET( m_list != NULL, "invalid listbox" );
fc54776e 256
fd0eed64 257 gtk_list_clear_items( m_list, 0, Number() );
dcf40a56 258
f5e27805 259 wxNode *node = m_clientObjectList.First();
fd0eed64
RR
260 while (node)
261 {
262 wxClientData *cd = (wxClientData*)node->Data();
263 if (cd) delete cd;
264 node = node->Next();
265 }
f5e27805
RR
266 m_clientObjectList.Clear();
267
fd0eed64 268 m_clientDataList.Clear();
6de97a3b 269}
c801d85f
KB
270
271void wxListBox::Delete( int n )
272{
fd0eed64 273 wxCHECK_RET( m_list != NULL, "invalid listbox" );
fc54776e 274
fd0eed64 275 GList *child = g_list_nth( m_list->children, n );
dcf40a56 276
fd0eed64
RR
277 if (!child)
278 {
279 wxFAIL_MSG("wrong listbox index");
280 return;
281 }
dcf40a56 282
fd0eed64
RR
283 GList *list = g_list_append( NULL, child->data );
284 gtk_list_remove_items( m_list, list );
285 g_list_free( list );
dcf40a56 286
f5e27805
RR
287 wxNode *node = m_clientObjectList.Nth( n );
288 if (node)
fd0eed64
RR
289 {
290 wxClientData *cd = (wxClientData*)node->Data();
291 if (cd) delete cd;
f5e27805
RR
292 m_clientObjectList.DeleteNode( node );
293 }
294
295 node = m_clientDataList.Nth( n );
296 if (node)
297 {
fd0eed64
RR
298 m_clientDataList.DeleteNode( node );
299 }
6de97a3b 300}
c801d85f
KB
301
302void wxListBox::Deselect( int n )
303{
fd0eed64 304 wxCHECK_RET( m_list != NULL, "invalid listbox" );
fc54776e 305
fd0eed64 306 gtk_list_unselect_item( m_list, n );
6de97a3b 307}
c801d85f
KB
308
309int wxListBox::FindString( const wxString &item ) const
310{
fd0eed64 311 wxCHECK_MSG( m_list != NULL, -1, "invalid listbox" );
fc54776e 312
fd0eed64
RR
313 GList *child = m_list->children;
314 int count = 0;
315 while (child)
316 {
317 GtkBin *bin = GTK_BIN( child->data );
318 GtkLabel *label = GTK_LABEL( bin->child );
319 if (item == label->label) return count;
320 count++;
321 child = child->next;
322 }
323
324 // it's not an error if the string is not found -> no wxCHECK
dcf40a56 325
c801d85f 326 return -1;
6de97a3b 327}
c801d85f 328
fd0eed64 329int wxListBox::GetSelection() const
c801d85f 330{
fd0eed64 331 wxCHECK_MSG( m_list != NULL, -1, "invalid listbox" );
fc54776e 332
fd0eed64
RR
333 GList *child = m_list->children;
334 int count = 0;
335 while (child)
336 {
337 if (GTK_WIDGET(child->data)->state == GTK_STATE_SELECTED) return count;
338 count++;
339 child = child->next;
340 }
341 return -1;
6de97a3b 342}
c801d85f 343
fd0eed64 344int wxListBox::GetSelections( wxArrayInt& aSelections ) const
c801d85f 345{
fd0eed64 346 wxCHECK_MSG( m_list != NULL, -1, "invalid listbox" );
fc54776e 347
fd0eed64
RR
348 // get the number of selected items first
349 GList *child = m_list->children;
350 int count = 0;
351 for (child = m_list->children; child != NULL; child = child->next)
352 {
353 if (GTK_WIDGET(child->data)->state == GTK_STATE_SELECTED)
354 count++;
355 }
c801d85f 356
fd0eed64
RR
357 aSelections.Empty();
358
359 if (count > 0)
868a2826 360 {
fd0eed64
RR
361 // now fill the list
362 aSelections.Alloc(count); // optimization attempt
363 int i = 0;
364 for (child = m_list->children; child != NULL; child = child->next, i++)
365 {
366 if (GTK_WIDGET(child->data)->state == GTK_STATE_SELECTED)
367 aSelections.Add(i);
368 }
6a6d4eed 369 }
dcf40a56 370
fd0eed64 371 return count;
6de97a3b 372}
c801d85f
KB
373
374wxString wxListBox::GetString( int n ) const
375{
fd0eed64 376 wxCHECK_MSG( m_list != NULL, "", "invalid listbox" );
fc54776e 377
fd0eed64
RR
378 GList *child = g_list_nth( m_list->children, n );
379 if (child)
380 {
381 GtkBin *bin = GTK_BIN( child->data );
382 GtkLabel *label = GTK_LABEL( bin->child );
383 return label->label;
384 }
385 wxFAIL_MSG("wrong listbox index");
386 return "";
6de97a3b 387}
c801d85f 388
fd0eed64 389wxString wxListBox::GetStringSelection() const
c801d85f 390{
fd0eed64 391 wxCHECK_MSG( m_list != NULL, "", "invalid listbox" );
fc54776e 392
fd0eed64
RR
393 GList *selection = m_list->selection;
394 if (selection)
395 {
396 GtkBin *bin = GTK_BIN( selection->data );
397 wxString tmp = GTK_LABEL( bin->child )->label;
398 return tmp;
399 }
400 wxFAIL_MSG("no listbox selection available");
401 return "";
6de97a3b 402}
c801d85f 403
fd0eed64 404int wxListBox::Number()
c801d85f 405{
fd0eed64 406 wxCHECK_MSG( m_list != NULL, -1, "invalid listbox" );
fc54776e 407
fd0eed64
RR
408 GList *child = m_list->children;
409 int count = 0;
410 while (child) { count++; child = child->next; }
411 return count;
6de97a3b 412}
c801d85f 413
debe6624 414bool wxListBox::Selected( int n )
c801d85f 415{
fd0eed64 416 wxCHECK_MSG( m_list != NULL, FALSE, "invalid listbox" );
fc54776e 417
fd0eed64
RR
418 GList *target = g_list_nth( m_list->children, n );
419 if (target)
c801d85f 420 {
fd0eed64
RR
421 GList *child = m_list->selection;
422 while (child)
423 {
424 if (child->data == target->data) return TRUE;
425 child = child->next;
426 }
6de97a3b 427 }
fd0eed64
RR
428 wxFAIL_MSG("wrong listbox index");
429 return FALSE;
6de97a3b 430}
c801d85f 431
debe6624 432void wxListBox::Set( int WXUNUSED(n), const wxString *WXUNUSED(choices) )
c801d85f 433{
fd0eed64 434 wxFAIL_MSG("wxListBox::Set not implemented");
6de97a3b 435}
c801d85f
KB
436
437void wxListBox::SetFirstItem( int WXUNUSED(n) )
438{
fd0eed64 439 wxFAIL_MSG("wxListBox::SetFirstItem not implemented");
6de97a3b 440}
c801d85f
KB
441
442void wxListBox::SetFirstItem( const wxString &WXUNUSED(item) )
443{
fd0eed64 444 wxFAIL_MSG("wxListBox::SetFirstItem not implemented");
6de97a3b 445}
c801d85f 446
debe6624 447void wxListBox::SetSelection( int n, bool select )
c801d85f 448{
fd0eed64 449 wxCHECK_RET( m_list != NULL, "invalid listbox" );
fc54776e 450
fd0eed64
RR
451 if (select)
452 gtk_list_select_item( m_list, n );
453 else
454 gtk_list_unselect_item( m_list, n );
6de97a3b 455}
c801d85f 456
09cf7c58 457void wxListBox::SetString( int n, const wxString &string )
c801d85f 458{
fd0eed64 459 wxCHECK_RET( m_list != NULL, "invalid listbox" );
fc54776e 460
fd0eed64
RR
461 GList *child = g_list_nth( m_list->children, n );
462 if (child)
463 {
464 GtkBin *bin = GTK_BIN( child->data );
465 GtkLabel *label = GTK_LABEL( bin->child );
466 gtk_label_set( label, string );
467 }
468 else
469 {
470 wxFAIL_MSG("wrong listbox index");
471 }
6de97a3b 472}
c801d85f 473
debe6624 474void wxListBox::SetStringSelection( const wxString &string, bool select )
c801d85f 475{
fd0eed64 476 wxCHECK_RET( m_list != NULL, "invalid listbox" );
fc54776e 477
fd0eed64 478 SetSelection( FindString(string), select );
6de97a3b 479}
c801d85f
KB
480
481int wxListBox::GetIndex( GtkWidget *item ) const
482{
fd0eed64 483 if (item)
c801d85f 484 {
fd0eed64
RR
485 GList *child = m_list->children;
486 int count = 0;
487 while (child)
488 {
489 if (GTK_WIDGET(child->data) == item) return count;
490 count++;
491 child = child->next;
492 }
6de97a3b 493 }
fd0eed64 494 return -1;
6de97a3b 495}
c801d85f 496
a60c99e6
RR
497void wxListBox::SetDropTarget( wxDropTarget *dropTarget )
498{
fd0eed64 499 wxCHECK_RET( m_list != NULL, "invalid listbox" );
fc54776e 500
38c7b3d3 501#ifndef NEW_GTK_DND_CODE
33a5bc52 502 if (m_dropTarget)
fd0eed64 503 {
33a5bc52
RR
504 GList *child = m_list->children;
505 while (child)
506 {
507 m_dropTarget->UnregisterWidget( GTK_WIDGET( child->data ) );
508 child = child->next;
509 }
fd0eed64 510 }
fed46e72 511#endif
38c7b3d3
RR
512
513 wxWindow::SetDropTarget( dropTarget );
fed46e72
RR
514
515#ifndef NEW_GTK_DND_CODE
33a5bc52 516 if (m_dropTarget)
fd0eed64 517 {
33a5bc52
RR
518 GList *child = m_list->children;
519 while (child)
520 {
521 m_dropTarget->RegisterWidget( GTK_WIDGET( child->data ) );
522 child = child->next;
523 }
fd0eed64 524 }
38c7b3d3 525#endif
a60c99e6
RR
526}
527
fd0eed64 528GtkWidget *wxListBox::GetConnectWidget()
e3e65dac 529{
fd0eed64 530 return GTK_WIDGET(m_list);
6de97a3b 531}
e3e65dac 532
f96aa4d9 533bool wxListBox::IsOwnGtkWindow( GdkWindow *window )
868a2826 534{
fd0eed64 535 if (wxWindow::IsOwnGtkWindow( window )) return TRUE;
a60c99e6 536
fd0eed64
RR
537 GList *child = m_list->children;
538 while (child)
539 {
540 GtkWidget *bin = GTK_WIDGET( child->data );
541 if (bin->window == window) return TRUE;
542 child = child->next;
543 }
f96aa4d9 544
fd0eed64 545 return FALSE;
868a2826 546}
e3e65dac 547
58614078 548void wxListBox::ApplyWidgetStyle()
c058d771 549{
fd0eed64 550 SetWidgetStyle();
fc54776e 551
e380f72b
RR
552 if (m_backgroundColour.Ok())
553 {
554 GdkWindow *window = GTK_WIDGET(m_list)->window;
555 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
556 gdk_window_set_background( window, m_backgroundColour.GetColor() );
557 gdk_window_clear( window );
558 }
f96aa4d9 559
fd0eed64
RR
560 GList *child = m_list->children;
561 while (child)
562 {
563 gtk_widget_set_style( GTK_BIN(child->data)->child, m_widgetStyle );
564 gtk_widget_set_style( GTK_WIDGET(child->data), m_widgetStyle );
565 child = child->next;
566 }
68dda785 567}