1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "listbox.h"
15 #include "wx/dynarray.h"
16 #include "wx/listbox.h"
20 //-------------------------------------------------------------------------
21 // conditional compilation
22 //-------------------------------------------------------------------------
24 #if (GTK_MINOR_VERSION == 1)
25 #if (GTK_MICRO_VERSION >= 5)
26 #define NEW_GTK_SCROLL_CODE
30 //-----------------------------------------------------------------------------
32 //-----------------------------------------------------------------------------
34 extern bool g_blockEventsOnDrag
;
36 //-----------------------------------------------------------------------------
37 // "select" and "deselect"
38 //-----------------------------------------------------------------------------
40 static void gtk_listitem_select_callback( GtkWidget
*WXUNUSED(widget
), wxListBox
*listbox
)
42 if (!listbox
->HasVMT()) return;
43 if (g_blockEventsOnDrag
) return;
45 wxCommandEvent
event(wxEVT_COMMAND_LISTBOX_SELECTED
, listbox
->GetId() );
47 wxArrayInt aSelections
;
48 int count
= listbox
->GetSelections(aSelections
);
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
);
58 event
.m_commandInt
= -1 ;
59 event
.m_commandString
= copystring("") ;
62 event
.SetEventObject( listbox
);
64 listbox
->GetEventHandler()->ProcessEvent( event
);
65 if (event
.m_commandString
) delete[] event
.m_commandString
;
68 //-----------------------------------------------------------------------------
70 //-----------------------------------------------------------------------------
72 IMPLEMENT_DYNAMIC_CLASS(wxListBox
,wxControl
)
74 wxListBox::wxListBox()
76 m_list
= (GtkList
*) NULL
;
79 bool wxListBox::Create( wxWindow
*parent
, wxWindowID id
,
80 const wxPoint
&pos
, const wxSize
&size
,
81 int n
, const wxString choices
[],
82 long style
, const wxValidator
& validator
, const wxString
&name
)
86 PreCreation( parent
, id
, pos
, size
, style
, name
);
88 SetValidator( validator
);
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
);
94 m_list
= GTK_LIST( gtk_list_new() );
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
;
102 gtk_list_set_selection_mode( GTK_LIST(m_list
), mode
);
104 #ifdef NEW_GTK_SCROLL_CODE
105 gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(m_widget
), GTK_WIDGET(m_list
) );
107 gtk_container_add( GTK_CONTAINER(m_widget
), GTK_WIDGET(m_list
) );
110 gtk_widget_show( GTK_WIDGET(m_list
) );
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
);
117 for (int i
= 0; i
< n
; i
++)
119 m_clientDataList
.Append( (wxObject
*) NULL
);
120 m_clientObjectList
.Append( (wxObject
*) NULL
);
122 GtkWidget
*list_item
;
123 list_item
= gtk_list_item_new_with_label( choices
[i
] );
125 gtk_container_add( GTK_CONTAINER(m_list
), list_item
);
127 gtk_signal_connect( GTK_OBJECT(list_item
), "select",
128 GTK_SIGNAL_FUNC(gtk_listitem_select_callback
), (gpointer
)this );
130 if (style
& wxLB_MULTIPLE
)
131 gtk_signal_connect( GTK_OBJECT(list_item
), "deselect",
132 GTK_SIGNAL_FUNC(gtk_listitem_select_callback
), (gpointer
)this );
134 ConnectWidget( list_item
);
136 gtk_widget_show( list_item
);
139 m_parent
->AddChild( this );
141 (m_parent
->m_insertCallback
)( m_parent
, this );
145 gtk_widget_realize( GTK_WIDGET(m_list
) );
147 SetBackgroundColour( parent
->GetBackgroundColour() );
148 SetForegroundColour( parent
->GetForegroundColour() );
155 wxListBox::~wxListBox()
160 void wxListBox::AppendCommon( const wxString
&item
)
162 wxCHECK_RET( m_list
!= NULL
, "invalid listbox" );
164 GtkWidget
*list_item
= gtk_list_item_new_with_label( item
);
166 gtk_signal_connect( GTK_OBJECT(list_item
), "select",
167 GTK_SIGNAL_FUNC(gtk_listitem_select_callback
), (gpointer
)this );
169 if (GetWindowStyleFlag() & wxLB_MULTIPLE
)
170 gtk_signal_connect( GTK_OBJECT(list_item
), "deselect",
171 GTK_SIGNAL_FUNC(gtk_listitem_select_callback
), (gpointer
)this );
173 gtk_container_add( GTK_CONTAINER(m_list
), list_item
);
175 if (m_widgetStyle
) ApplyWidgetStyle();
177 gtk_widget_show( list_item
);
179 ConnectWidget( list_item
);
181 #ifndef NEW_GTK_DND_CODE
182 if (m_dropTarget
) m_dropTarget
->RegisterWidget( list_item
);
186 void wxListBox::Append( const wxString
&item
)
188 m_clientDataList
.Append( (wxObject
*) NULL
);
189 m_clientObjectList
.Append( (wxObject
*) NULL
);
191 AppendCommon( item
);
194 void wxListBox::Append( const wxString
&item
, void *clientData
)
196 m_clientDataList
.Append( (wxObject
*) clientData
);
197 m_clientObjectList
.Append( (wxObject
*) NULL
);
199 AppendCommon( item
);
202 void wxListBox::Append( const wxString
&item
, wxClientData
*clientData
)
204 m_clientObjectList
.Append( (wxObject
*) clientData
);
205 m_clientDataList
.Append( (wxObject
*) NULL
);
207 AppendCommon( item
);
210 void wxListBox::SetClientData( int n
, void* clientData
)
212 wxCHECK_RET( m_widget
!= NULL
, "invalid combobox" );
214 wxNode
*node
= m_clientDataList
.Nth( n
);
217 node
->SetData( (wxObject
*) clientData
);
220 void* wxListBox::GetClientData( int n
)
222 wxCHECK_MSG( m_widget
!= NULL
, NULL
, "invalid combobox" );
224 wxNode
*node
= m_clientDataList
.Nth( n
);
225 if (!node
) return NULL
;
230 void wxListBox::SetClientObject( int n
, wxClientData
* clientData
)
232 wxCHECK_RET( m_widget
!= NULL
, "invalid combobox" );
234 wxNode
*node
= m_clientObjectList
.Nth( n
);
237 wxClientData
*cd
= (wxClientData
*) node
->Data();
240 node
->SetData( (wxObject
*) clientData
);
243 wxClientData
* wxListBox::GetClientObject( int n
)
245 wxCHECK_MSG( m_widget
!= NULL
, (wxClientData
*)NULL
, "invalid combobox" );
247 wxNode
*node
= m_clientObjectList
.Nth( n
);
248 if (!node
) return (wxClientData
*) NULL
;
250 return (wxClientData
*) node
->Data();
253 void wxListBox::Clear()
255 wxCHECK_RET( m_list
!= NULL
, "invalid listbox" );
257 gtk_list_clear_items( m_list
, 0, Number() );
259 wxNode
*node
= m_clientObjectList
.First();
262 wxClientData
*cd
= (wxClientData
*)node
->Data();
266 m_clientObjectList
.Clear();
268 m_clientDataList
.Clear();
271 void wxListBox::Delete( int n
)
273 wxCHECK_RET( m_list
!= NULL
, "invalid listbox" );
275 GList
*child
= g_list_nth( m_list
->children
, n
);
279 wxFAIL_MSG("wrong listbox index");
283 GList
*list
= g_list_append( NULL
, child
->data
);
284 gtk_list_remove_items( m_list
, list
);
287 wxNode
*node
= m_clientObjectList
.Nth( n
);
290 wxClientData
*cd
= (wxClientData
*)node
->Data();
292 m_clientObjectList
.DeleteNode( node
);
295 node
= m_clientDataList
.Nth( n
);
298 m_clientDataList
.DeleteNode( node
);
302 void wxListBox::Deselect( int n
)
304 wxCHECK_RET( m_list
!= NULL
, "invalid listbox" );
306 gtk_list_unselect_item( m_list
, n
);
309 int wxListBox::FindString( const wxString
&item
) const
311 wxCHECK_MSG( m_list
!= NULL
, -1, "invalid listbox" );
313 GList
*child
= m_list
->children
;
317 GtkBin
*bin
= GTK_BIN( child
->data
);
318 GtkLabel
*label
= GTK_LABEL( bin
->child
);
319 if (item
== label
->label
) return count
;
324 // it's not an error if the string is not found -> no wxCHECK
329 int wxListBox::GetSelection() const
331 wxCHECK_MSG( m_list
!= NULL
, -1, "invalid listbox" );
333 GList
*child
= m_list
->children
;
337 if (GTK_WIDGET(child
->data
)->state
== GTK_STATE_SELECTED
) return count
;
344 int wxListBox::GetSelections( wxArrayInt
& aSelections
) const
346 wxCHECK_MSG( m_list
!= NULL
, -1, "invalid listbox" );
348 // get the number of selected items first
349 GList
*child
= m_list
->children
;
351 for (child
= m_list
->children
; child
!= NULL
; child
= child
->next
)
353 if (GTK_WIDGET(child
->data
)->state
== GTK_STATE_SELECTED
)
362 aSelections
.Alloc(count
); // optimization attempt
364 for (child
= m_list
->children
; child
!= NULL
; child
= child
->next
, i
++)
366 if (GTK_WIDGET(child
->data
)->state
== GTK_STATE_SELECTED
)
374 wxString
wxListBox::GetString( int n
) const
376 wxCHECK_MSG( m_list
!= NULL
, "", "invalid listbox" );
378 GList
*child
= g_list_nth( m_list
->children
, n
);
381 GtkBin
*bin
= GTK_BIN( child
->data
);
382 GtkLabel
*label
= GTK_LABEL( bin
->child
);
385 wxFAIL_MSG("wrong listbox index");
389 wxString
wxListBox::GetStringSelection() const
391 wxCHECK_MSG( m_list
!= NULL
, "", "invalid listbox" );
393 GList
*selection
= m_list
->selection
;
396 GtkBin
*bin
= GTK_BIN( selection
->data
);
397 wxString tmp
= GTK_LABEL( bin
->child
)->label
;
400 wxFAIL_MSG("no listbox selection available");
404 int wxListBox::Number()
406 wxCHECK_MSG( m_list
!= NULL
, -1, "invalid listbox" );
408 GList
*child
= m_list
->children
;
410 while (child
) { count
++; child
= child
->next
; }
414 bool wxListBox::Selected( int n
)
416 wxCHECK_MSG( m_list
!= NULL
, FALSE
, "invalid listbox" );
418 GList
*target
= g_list_nth( m_list
->children
, n
);
421 GList
*child
= m_list
->selection
;
424 if (child
->data
== target
->data
) return TRUE
;
428 wxFAIL_MSG("wrong listbox index");
432 void wxListBox::Set( int WXUNUSED(n
), const wxString
*WXUNUSED(choices
) )
434 wxFAIL_MSG("wxListBox::Set not implemented");
437 void wxListBox::SetFirstItem( int WXUNUSED(n
) )
439 wxFAIL_MSG("wxListBox::SetFirstItem not implemented");
442 void wxListBox::SetFirstItem( const wxString
&WXUNUSED(item
) )
444 wxFAIL_MSG("wxListBox::SetFirstItem not implemented");
447 void wxListBox::SetSelection( int n
, bool select
)
449 wxCHECK_RET( m_list
!= NULL
, "invalid listbox" );
452 gtk_list_select_item( m_list
, n
);
454 gtk_list_unselect_item( m_list
, n
);
457 void wxListBox::SetString( int n
, const wxString
&string
)
459 wxCHECK_RET( m_list
!= NULL
, "invalid listbox" );
461 GList
*child
= g_list_nth( m_list
->children
, n
);
464 GtkBin
*bin
= GTK_BIN( child
->data
);
465 GtkLabel
*label
= GTK_LABEL( bin
->child
);
466 gtk_label_set( label
, string
);
470 wxFAIL_MSG("wrong listbox index");
474 void wxListBox::SetStringSelection( const wxString
&string
, bool select
)
476 wxCHECK_RET( m_list
!= NULL
, "invalid listbox" );
478 SetSelection( FindString(string
), select
);
481 int wxListBox::GetIndex( GtkWidget
*item
) const
485 GList
*child
= m_list
->children
;
489 if (GTK_WIDGET(child
->data
) == item
) return count
;
497 void wxListBox::SetDropTarget( wxDropTarget
*dropTarget
)
499 wxCHECK_RET( m_list
!= NULL
, "invalid listbox" );
501 #ifndef NEW_GTK_DND_CODE
504 GList
*child
= m_list
->children
;
507 m_dropTarget
->UnregisterWidget( GTK_WIDGET( child
->data
) );
513 wxWindow::SetDropTarget( dropTarget
);
515 #ifndef NEW_GTK_DND_CODE
518 GList
*child
= m_list
->children
;
521 m_dropTarget
->RegisterWidget( GTK_WIDGET( child
->data
) );
528 GtkWidget
*wxListBox::GetConnectWidget()
530 return GTK_WIDGET(m_list
);
533 bool wxListBox::IsOwnGtkWindow( GdkWindow
*window
)
535 if (wxWindow::IsOwnGtkWindow( window
)) return TRUE
;
537 GList
*child
= m_list
->children
;
540 GtkWidget
*bin
= GTK_WIDGET( child
->data
);
541 if (bin
->window
== window
) return TRUE
;
548 void wxListBox::ApplyWidgetStyle()
552 if (m_backgroundColour
.Ok())
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
);
560 GList
*child
= m_list
->children
;
563 gtk_widget_set_style( GTK_BIN(child
->data
)->child
, m_widgetStyle
);
564 gtk_widget_set_style( GTK_WIDGET(child
->data
), m_widgetStyle
);