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