]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/listbox.cpp
check for empty data pointer in Len() and Empty()
[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;
35
c801d85f
KB
36 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, listbox->GetId() );
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
KB
70
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;
77
78 PreCreation( parent, id, pos, size, style, name );
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 );
85
86 m_list = GTK_LIST( gtk_list_new() );
6a6d4eed 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 );
c801d85f
KB
95
96 gtk_container_add (GTK_CONTAINER(m_widget), GTK_WIDGET(m_list) );
97 gtk_widget_show( GTK_WIDGET(m_list) );
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 );
103
c801d85f
KB
104 for (int i = 0; i < n; i++)
105 {
106 GtkWidget *list_item;
107 list_item = gtk_list_item_new_with_label( choices[i] );
108
66bd6b93
RR
109 gtk_container_add( GTK_CONTAINER(m_list), list_item );
110
c801d85f
KB
111 gtk_signal_connect( GTK_OBJECT(list_item), "select",
112 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
113
a60c99e6 114 if (style & wxLB_MULTIPLE)
09cf7c58
RR
115 gtk_signal_connect( GTK_OBJECT(list_item), "deselect",
116 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
117
e2414cbe
RR
118 m_clientData.Append( (wxObject*)NULL );
119
c801d85f 120 gtk_widget_show( list_item );
6de97a3b 121 }
c801d85f
KB
122
123 PostCreation();
124
e3e65dac
RR
125 gtk_widget_realize( GTK_WIDGET(m_list) );
126
c801d85f
KB
127 Show( TRUE );
128
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{
868a2826
RR
139 GtkWidget *list_item = gtk_list_item_new_with_label( item );
140
141 if (m_hasOwnStyle)
142 {
143 GtkBin *bin = GTK_BIN( list_item );
144 gtk_widget_set_style( bin->child,
145 gtk_style_ref(
146 gtk_widget_get_style( m_widget ) ) );
147 }
e2414cbe 148
09cf7c58 149 gtk_signal_connect( GTK_OBJECT(list_item), "select",
e2414cbe
RR
150 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
151
a60c99e6 152 if (GetWindowStyleFlag() & wxLB_MULTIPLE)
09cf7c58
RR
153 gtk_signal_connect( GTK_OBJECT(list_item), "deselect",
154 GTK_SIGNAL_FUNC(gtk_listitem_select_callback), (gpointer)this );
155
e2414cbe
RR
156 m_clientData.Append( (wxObject*)clientData );
157
2f6407b9
RR
158 gtk_container_add( GTK_CONTAINER(m_list), list_item );
159
e2414cbe 160 gtk_widget_show( list_item );
a60c99e6
RR
161
162 ConnectWidget( list_item );
163
164 ConnectDnDWidget( list_item );
165
6de97a3b 166}
c801d85f
KB
167
168void wxListBox::Clear(void)
169{
170 gtk_list_clear_items( m_list, 0, Number() );
e2414cbe
RR
171
172 m_clientData.Clear();
6de97a3b 173}
c801d85f
KB
174
175void wxListBox::Delete( int n )
176{
30f82ea4
RR
177 GList *child = g_list_nth( m_list->children, n );
178
179 if (!child)
180 {
181 wxFAIL_MSG("wrong listbox index");
182 return;
183 }
184
185 GList *list = g_list_append( NULL, child->data );
186 gtk_list_remove_items( m_list, list );
187 g_list_free( list );
e2414cbe
RR
188
189 wxNode *node = m_clientData.Nth( n );
190 if (!node)
191 {
30f82ea4 192 wxFAIL_MSG("wrong listbox index");
e2414cbe
RR
193 }
194 else
195 m_clientData.DeleteNode( node );
6de97a3b 196}
c801d85f
KB
197
198void wxListBox::Deselect( int n )
199{
200 gtk_list_unselect_item( m_list, n );
6de97a3b 201}
c801d85f
KB
202
203int wxListBox::FindString( const wxString &item ) const
204{
205 GList *child = m_list->children;
206 int count = 0;
207 while (child)
208 {
209 GtkBin *bin = GTK_BIN( child->data );
210 GtkLabel *label = GTK_LABEL( bin->child );
211 if (item == label->label) return count;
212 count++;
213 child = child->next;
6de97a3b 214 }
30f82ea4 215 wxFAIL_MSG("wrong listbox index");
c801d85f 216 return -1;
6de97a3b 217}
c801d85f 218
e2414cbe 219char *wxListBox::GetClientData( int n ) const
c801d85f 220{
e2414cbe
RR
221 wxNode *node = m_clientData.Nth( n );
222 if (node) return ((char*)node->Data());
30f82ea4
RR
223
224 wxFAIL_MSG("wrong listbox index");
c67daf87 225 return (char *) NULL;
6de97a3b 226}
c801d85f
KB
227
228int wxListBox::GetSelection(void) const
229{
d84eb083
RR
230 GList *child = m_list->children;
231 int count = 0;
232 while (child)
c801d85f 233 {
d84eb083
RR
234 if (GTK_WIDGET(child->data)->state == GTK_STATE_SELECTED) return count;
235 count++;
236 child = child->next;
6de97a3b 237 }
c801d85f 238 return -1;
6de97a3b 239}
c801d85f 240
6a6d4eed 241int wxListBox::GetSelections(wxArrayInt& aSelections) const
c801d85f 242{
6a6d4eed
VZ
243 // get the number of selected items first
244 GList *child = m_list->children;
245 int count = 0;
868a2826
RR
246 for ( child = m_list->children; child != NULL; child = child->next )
247 {
6a6d4eed
VZ
248 if ( GTK_WIDGET(child->data)->state == GTK_STATE_SELECTED )
249 count++;
250 }
251
252 aSelections.Empty();
253
254 if ( count > 0 ) {
255 // now fill the list
256 aSelections.Alloc(count); // optimization attempt
257 int i = 0;
868a2826
RR
258 for ( child = m_list->children; child != NULL; child = child->next, i++ )
259 {
6a6d4eed
VZ
260 if ( GTK_WIDGET(child->data)->state == GTK_STATE_SELECTED )
261 aSelections.Add(i);
262 }
263 }
264
265 return count;
6de97a3b 266}
c801d85f
KB
267
268wxString wxListBox::GetString( int n ) const
269{
270 GList *child = g_list_nth( m_list->children, n );
271 if (child)
272 {
273 GtkBin *bin = GTK_BIN( child->data );
274 GtkLabel *label = GTK_LABEL( bin->child );
275 return label->label;
6de97a3b 276 }
30f82ea4 277 wxFAIL_MSG("wrong listbox index");
c801d85f 278 return "";
6de97a3b 279}
c801d85f
KB
280
281wxString wxListBox::GetStringSelection(void) const
282{
283 GList *selection = m_list->selection;
284 if (selection)
285 {
286 GtkBin *bin = GTK_BIN( selection->data );
287 wxString tmp = GTK_LABEL( bin->child )->label;
288 return tmp;
6de97a3b 289 }
30f82ea4 290 wxFAIL_MSG("no listbox selection available");
c801d85f 291 return "";
6de97a3b 292}
c801d85f
KB
293
294int wxListBox::Number(void)
295{
296 GList *child = m_list->children;
297 int count = 0;
6de97a3b 298 while (child) { count++; child = child->next; }
c801d85f 299 return count;
6de97a3b 300}
c801d85f 301
debe6624 302bool wxListBox::Selected( int n )
c801d85f
KB
303{
304 GList *target = g_list_nth( m_list->children, n );
305 if (target)
306 {
307 GList *child = m_list->selection;
308 while (child)
309 {
310 if (child->data == target->data) return TRUE;
311 child = child->next;
6de97a3b
RR
312 }
313 }
30f82ea4 314 wxFAIL_MSG("wrong listbox index");
c801d85f 315 return FALSE;
6de97a3b 316}
c801d85f 317
debe6624 318void wxListBox::Set( int WXUNUSED(n), const wxString *WXUNUSED(choices) )
c801d85f 319{
30f82ea4 320 wxFAIL_MSG("wxListBox::Set not implemented");
6de97a3b 321}
c801d85f 322
e2414cbe 323void wxListBox::SetClientData( int n, char *clientData )
c801d85f 324{
e2414cbe 325 wxNode *node = m_clientData.Nth( n );
30f82ea4
RR
326 if (node)
327 {
328 node->SetData( (wxObject*)clientData );
329 }
330 else
331 {
332 wxFAIL_MSG("wrong listbox index");
333 }
6de97a3b 334}
c801d85f
KB
335
336void wxListBox::SetFirstItem( int WXUNUSED(n) )
337{
30f82ea4 338 wxFAIL_MSG("wxListBox::SetFirstItem not implemented");
6de97a3b 339}
c801d85f
KB
340
341void wxListBox::SetFirstItem( const wxString &WXUNUSED(item) )
342{
30f82ea4 343 wxFAIL_MSG("wxListBox::SetFirstItem not implemented");
6de97a3b 344}
c801d85f 345
debe6624 346void wxListBox::SetSelection( int n, bool select )
c801d85f
KB
347{
348 if (select)
349 gtk_list_select_item( m_list, n );
350 else
351 gtk_list_unselect_item( m_list, n );
6de97a3b 352}
c801d85f 353
09cf7c58 354void wxListBox::SetString( int n, const wxString &string )
c801d85f 355{
09cf7c58
RR
356 GList *child = g_list_nth( m_list->children, n );
357 if (child)
358 {
359 GtkBin *bin = GTK_BIN( child->data );
360 GtkLabel *label = GTK_LABEL( bin->child );
361 gtk_label_set( label, string );
6de97a3b 362 }
30f82ea4
RR
363 else
364 {
365 wxFAIL_MSG("wrong listbox index");
366 }
6de97a3b 367}
c801d85f 368
debe6624 369void wxListBox::SetStringSelection( const wxString &string, bool select )
c801d85f
KB
370{
371 SetSelection( FindString(string), select );
6de97a3b 372}
c801d85f
KB
373
374int wxListBox::GetIndex( GtkWidget *item ) const
375{
376 if (item)
377 {
378 GList *child = m_list->children;
379 int count = 0;
380 while (child)
381 {
382 if (GTK_WIDGET(child->data) == item) return count;
383 count++;
384 child = child->next;
6de97a3b
RR
385 }
386 }
c801d85f 387 return -1;
6de97a3b 388}
c801d85f 389
a60c99e6
RR
390void wxListBox::SetDropTarget( wxDropTarget *dropTarget )
391{
392 GList *child = m_list->children;
393 while (child)
394 {
395 DisconnectDnDWidget( GTK_WIDGET( child->data ) );
396 child = child->next;
397 }
398
399 wxWindow::SetDropTarget( dropTarget );
400
401 child = m_list->children;
402 while (child)
403 {
404 ConnectDnDWidget( GTK_WIDGET( child->data ) );
405 child = child->next;
406 }
407}
408
30dea054 409GtkWidget *wxListBox::GetConnectWidget(void)
e3e65dac
RR
410{
411 return GTK_WIDGET(m_list);
6de97a3b 412}
e3e65dac 413
868a2826
RR
414void wxListBox::SetFont( const wxFont &font )
415{
416 wxWindow::SetFont( font );
a60c99e6 417
868a2826
RR
418 GList *child = m_list->children;
419 while (child)
420 {
421 GtkBin *bin = (GtkBin*) child->data;
422 gtk_widget_set_style( bin->child,
423 gtk_style_ref(
424 gtk_widget_get_style( m_widget ) ) );
425 child = child->next;
426 }
427}
e3e65dac 428
c058d771
RR
429bool wxListBox::IsOwnGtkWindow( GdkWindow *window )
430{
431 if (wxWindow::IsOwnGtkWindow( window )) return TRUE;
432
433 GList *child = m_list->children;
434 while (child)
435 {
436 GtkBin *bin = (GtkBin*) child->data;
437 if (bin->child->window == window) return TRUE;
438 child = child->next;
439 }
440
441 return FALSE;
442}
443
c801d85f 444