]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/choice.cpp
tree ctrl sorting shouldn't crash when items don't have data
[wxWidgets.git] / src / gtk / choice.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: choice.cpp
3// Purpose:
4// Author: Robert Roebling
dbf858b5 5// Id: $Id$
01111366 6// Copyright: (c) 1998 Robert Roebling
29006414 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
10
11#ifdef __GNUG__
12#pragma implementation "choice.h"
13#endif
14
15#include "wx/choice.h"
16
83624f79
RR
17#include "gdk/gdk.h"
18#include "gtk/gtk.h"
19
acfd422a
RR
20//-----------------------------------------------------------------------------
21// idle system
22//-----------------------------------------------------------------------------
23
24extern void wxapp_install_idle_handler();
25extern bool g_isIdle;
26
66bd6b93
RR
27//-----------------------------------------------------------------------------
28// data
29//-----------------------------------------------------------------------------
30
31extern bool g_blockEventsOnDrag;
32
c801d85f 33//-----------------------------------------------------------------------------
e1e955e1 34// "activate"
c801d85f
KB
35//-----------------------------------------------------------------------------
36
66bd6b93 37static void gtk_choice_clicked_callback( GtkWidget *WXUNUSED(widget), wxChoice *choice )
c801d85f 38{
acfd422a
RR
39 if (g_isIdle) wxapp_install_idle_handler();
40
41 if (!choice->HasVMT()) return;
29006414 42
acfd422a 43 if (g_blockEventsOnDrag) return;
29006414 44
acfd422a
RR
45 wxCommandEvent event(wxEVT_COMMAND_CHOICE_SELECTED, choice->GetId() );
46 event.SetInt( choice->GetSelection() );
47 event.SetString( choice->GetStringSelection() );
48 event.SetEventObject(choice);
49 choice->GetEventHandler()->ProcessEvent(event);
6de97a3b 50}
c801d85f 51
e1e955e1
RR
52//-----------------------------------------------------------------------------
53// wxChoice
c801d85f
KB
54//-----------------------------------------------------------------------------
55
7f4dc78d 56IMPLEMENT_DYNAMIC_CLASS(wxChoice,wxControl)
c801d85f 57
fd0eed64 58wxChoice::wxChoice()
c801d85f 59{
6de97a3b 60}
c801d85f 61
debe6624 62bool wxChoice::Create( wxWindow *parent, wxWindowID id,
fd0eed64
RR
63 const wxPoint &pos, const wxSize &size,
64 int n, const wxString choices[],
65 long style, const wxValidator& validator, const wxString &name )
c801d85f 66{
fd0eed64 67 m_needParent = TRUE;
034be888
RR
68#if (GTK_MINOR_VERSION > 0)
69 m_acceptsFocus = TRUE;
70#endif
29006414 71
fd0eed64 72 PreCreation( parent, id, pos, size, style, name );
29006414 73
fd0eed64 74 SetValidator( validator );
6de97a3b 75
fd0eed64 76 m_widget = gtk_option_menu_new();
29006414
VZ
77
78 wxSize newSize(size);
79 if (newSize.x == -1)
80 newSize.x = 80;
81 if (newSize.y == -1)
82 newSize.y = 26;
fd0eed64 83 SetSize( newSize.x, newSize.y );
29006414 84
fd0eed64 85 GtkWidget *menu = gtk_menu_new();
29006414 86
fd0eed64
RR
87 for (int i = 0; i < n; i++)
88 {
89 m_clientDataList.Append( (wxObject*) NULL );
f5e27805 90 m_clientObjectList.Append( (wxObject*) NULL );
29006414 91
93c5dd39 92 GtkWidget *item = gtk_menu_item_new_with_label( choices[i].mbc_str() );
fd0eed64 93 gtk_menu_append( GTK_MENU(menu), item );
29006414 94
fd0eed64 95 gtk_widget_show( item );
29006414
VZ
96
97 gtk_signal_connect( GTK_OBJECT( item ), "activate",
fd0eed64
RR
98 GTK_SIGNAL_FUNC(gtk_choice_clicked_callback), (gpointer*)this );
99 }
100 gtk_option_menu_set_menu( GTK_OPTION_MENU(m_widget), menu );
29006414 101
fd0eed64 102 m_parent->AddChild( this );
6ca41e57 103
fd0eed64 104 (m_parent->m_insertCallback)( m_parent, this );
29006414 105
fd0eed64 106 PostCreation();
29006414 107
fd0eed64
RR
108 SetBackgroundColour( parent->GetBackgroundColour() );
109 SetForegroundColour( parent->GetForegroundColour() );
a7ac4461 110 SetFont( parent->GetFont() );
f96aa4d9 111
fd0eed64 112 Show( TRUE );
29006414 113
fd0eed64 114 return TRUE;
6de97a3b 115}
29006414 116
fd0eed64
RR
117wxChoice::~wxChoice()
118{
f5e27805 119 Clear();
fd0eed64
RR
120}
121
122void wxChoice::AppendCommon( const wxString &item )
123{
93c5dd39 124 wxCHECK_RET( m_widget != NULL, _T("invalid choice") );
29006414 125
fd0eed64 126 GtkWidget *menu = gtk_option_menu_get_menu( GTK_OPTION_MENU(m_widget) );
93c5dd39 127 GtkWidget *menu_item = gtk_menu_item_new_with_label( item.mbc_str() );
29006414 128
fd0eed64 129 gtk_menu_append( GTK_MENU(menu), menu_item );
29006414 130
2b07d713
RR
131 if (GTK_WIDGET_REALIZED(m_widget))
132 {
133 gtk_widget_realize( menu_item );
134 gtk_widget_realize( GTK_BIN(menu_item)->child );
29006414 135
2b07d713
RR
136 if (m_widgetStyle) ApplyWidgetStyle();
137 }
29006414
VZ
138
139 gtk_signal_connect( GTK_OBJECT( menu_item ), "activate",
fd0eed64 140 GTK_SIGNAL_FUNC(gtk_choice_clicked_callback), (gpointer*)this );
29006414 141
fd0eed64
RR
142 gtk_widget_show( menu_item );
143}
144
c801d85f
KB
145void wxChoice::Append( const wxString &item )
146{
f5e27805
RR
147 m_clientDataList.Append( (wxObject*) NULL );
148 m_clientObjectList.Append( (wxObject*) NULL );
29006414 149
fd0eed64
RR
150 AppendCommon( item );
151}
152
153void wxChoice::Append( const wxString &item, void *clientData )
154{
f5e27805
RR
155 m_clientDataList.Append( (wxObject*) clientData );
156 m_clientObjectList.Append( (wxObject*) NULL );
29006414 157
fd0eed64
RR
158 AppendCommon( item );
159}
160
161void wxChoice::Append( const wxString &item, wxClientData *clientData )
162{
f5e27805
RR
163 m_clientObjectList.Append( (wxObject*) clientData );
164 m_clientDataList.Append( (wxObject*) NULL );
29006414 165
fd0eed64
RR
166 AppendCommon( item );
167}
f96aa4d9 168
fd0eed64
RR
169void wxChoice::SetClientData( int n, void* clientData )
170{
93c5dd39 171 wxCHECK_RET( m_widget != NULL, _T("invalid combobox") );
29006414 172
fd0eed64
RR
173 wxNode *node = m_clientDataList.Nth( n );
174 if (!node) return;
29006414 175
f5e27805 176 node->SetData( (wxObject*) clientData );
fd0eed64
RR
177}
178
179void* wxChoice::GetClientData( int n )
180{
93c5dd39 181 wxCHECK_MSG( m_widget != NULL, NULL, _T("invalid combobox") );
29006414 182
fd0eed64
RR
183 wxNode *node = m_clientDataList.Nth( n );
184 if (!node) return NULL;
29006414 185
f5e27805 186 return node->Data();
6de97a3b 187}
fd0eed64
RR
188
189void wxChoice::SetClientObject( int n, wxClientData* clientData )
190{
93c5dd39 191 wxCHECK_RET( m_widget != NULL, _T("invalid combobox") );
29006414 192
f5e27805 193 wxNode *node = m_clientObjectList.Nth( n );
fd0eed64 194 if (!node) return;
29006414 195
fd0eed64
RR
196 wxClientData *cd = (wxClientData*) node->Data();
197 if (cd) delete cd;
29006414 198
fd0eed64
RR
199 node->SetData( (wxObject*) clientData );
200}
201
202wxClientData* wxChoice::GetClientObject( int n )
203{
93c5dd39 204 wxCHECK_MSG( m_widget != NULL, (wxClientData*) NULL, _T("invalid combobox") );
29006414 205
f5e27805 206 wxNode *node = m_clientObjectList.Nth( n );
fd0eed64 207 if (!node) return (wxClientData*) NULL;
29006414 208
fd0eed64
RR
209 return (wxClientData*) node->Data();
210}
29006414 211
fd0eed64 212void wxChoice::Clear()
c801d85f 213{
93c5dd39 214 wxCHECK_RET( m_widget != NULL, _T("invalid choice") );
f96aa4d9 215
fd0eed64
RR
216 gtk_option_menu_remove_menu( GTK_OPTION_MENU(m_widget) );
217 GtkWidget *menu = gtk_menu_new();
218 gtk_option_menu_set_menu( GTK_OPTION_MENU(m_widget), menu );
29006414 219
f5e27805 220 wxNode *node = m_clientObjectList.First();
fd0eed64
RR
221 while (node)
222 {
223 wxClientData *cd = (wxClientData*)node->Data();
224 if (cd) delete cd;
225 node = node->Next();
226 }
f5e27805 227 m_clientObjectList.Clear();
29006414 228
fd0eed64 229 m_clientDataList.Clear();
6de97a3b 230}
c801d85f 231
2f6407b9
RR
232void wxChoice::Delete( int WXUNUSED(n) )
233{
93c5dd39 234 wxFAIL_MSG( _T("wxChoice:Delete not implemented") );
2f6407b9
RR
235}
236
c801d85f
KB
237int wxChoice::FindString( const wxString &string ) const
238{
93c5dd39 239 wxCHECK_MSG( m_widget != NULL, -1, _T("invalid choice") );
fd0eed64
RR
240
241 // If you read this code once and you think you understand
242 // it, then you are very wrong. Robert Roebling.
29006414 243
fd0eed64
RR
244 GtkMenuShell *menu_shell = GTK_MENU_SHELL( gtk_option_menu_get_menu( GTK_OPTION_MENU(m_widget) ) );
245 int count = 0;
246 GList *child = menu_shell->children;
247 while (child)
248 {
249 GtkBin *bin = GTK_BIN( child->data );
250 GtkLabel *label = (GtkLabel *) NULL;
251 if (bin->child) label = GTK_LABEL(bin->child);
252 if (!label) label = GTK_LABEL( GTK_BUTTON(m_widget)->child );
29006414 253
93c5dd39 254 wxASSERT_MSG( label != NULL , _T("wxChoice: invalid label") );
29006414
VZ
255
256 if (string == label->label)
257 return count;
258
fd0eed64
RR
259 child = child->next;
260 count++;
261 }
29006414 262
fd0eed64 263 return -1;
6de97a3b 264}
c801d85f 265
fd0eed64 266int wxChoice::GetColumns() const
c801d85f 267{
fd0eed64 268 return 1;
6de97a3b 269}
c801d85f 270
fd0eed64 271int wxChoice::GetSelection()
c801d85f 272{
93c5dd39 273 wxCHECK_MSG( m_widget != NULL, -1, _T("invalid choice") );
fd0eed64
RR
274
275 GtkMenuShell *menu_shell = GTK_MENU_SHELL( gtk_option_menu_get_menu( GTK_OPTION_MENU(m_widget) ) );
276 int count = 0;
277 GList *child = menu_shell->children;
278 while (child)
279 {
280 GtkBin *bin = GTK_BIN( child->data );
281 if (!bin->child) return count;
282 child = child->next;
283 count++;
284 }
29006414 285
93c5dd39 286 wxFAIL_MSG( _T("wxChoice: no selection") );
29006414 287
fd0eed64 288 return -1;
6de97a3b 289}
c801d85f 290
debe6624 291wxString wxChoice::GetString( int n ) const
c801d85f 292{
93c5dd39 293 wxCHECK_MSG( m_widget != NULL, _T(""), _T("invalid choice") );
fd0eed64
RR
294
295 GtkMenuShell *menu_shell = GTK_MENU_SHELL( gtk_option_menu_get_menu( GTK_OPTION_MENU(m_widget) ) );
296 int count = 0;
297 GList *child = menu_shell->children;
298 while (child)
c801d85f 299 {
fd0eed64
RR
300 GtkBin *bin = GTK_BIN( child->data );
301 if (count == n)
302 {
303 GtkLabel *label = (GtkLabel *) NULL;
304 if (bin->child) label = GTK_LABEL(bin->child);
305 if (!label) label = GTK_LABEL( GTK_BUTTON(m_widget)->child );
29006414 306
93c5dd39 307 wxASSERT_MSG( label != NULL , _T("wxChoice: invalid label") );
29006414 308
fd0eed64
RR
309 return label->label;
310 }
311 child = child->next;
312 count++;
6de97a3b 313 }
29006414 314
93c5dd39 315 wxFAIL_MSG( _T("wxChoice: invalid index in GetString()") );
29006414 316
fd0eed64 317 return "";
6de97a3b 318}
c801d85f 319
fd0eed64 320wxString wxChoice::GetStringSelection() const
c801d85f 321{
93c5dd39 322 wxCHECK_MSG( m_widget != NULL, _T(""), _T("invalid choice") );
f96aa4d9 323
fd0eed64 324 GtkLabel *label = GTK_LABEL( GTK_BUTTON(m_widget)->child );
29006414 325
93c5dd39 326 wxASSERT_MSG( label != NULL , _T("wxChoice: invalid label") );
29006414 327
fd0eed64 328 return label->label;
6de97a3b 329}
c801d85f 330
fd0eed64 331int wxChoice::Number() const
c801d85f 332{
93c5dd39 333 wxCHECK_MSG( m_widget != NULL, 0, _T("invalid choice") );
fd0eed64
RR
334
335 GtkMenuShell *menu_shell = GTK_MENU_SHELL( gtk_option_menu_get_menu( GTK_OPTION_MENU(m_widget) ) );
336 int count = 0;
337 GList *child = menu_shell->children;
338 while (child)
339 {
340 count++;
341 child = child->next;
342 }
343 return count;
6de97a3b 344}
c801d85f 345
debe6624 346void wxChoice::SetColumns( int WXUNUSED(n) )
c801d85f 347{
6de97a3b 348}
c801d85f 349
debe6624 350void wxChoice::SetSelection( int n )
c801d85f 351{
93c5dd39 352 wxCHECK_RET( m_widget != NULL, _T("invalid choice") );
f96aa4d9 353
fd0eed64
RR
354 int tmp = n;
355 gtk_option_menu_set_history( GTK_OPTION_MENU(m_widget), (gint)tmp );
29006414 356
fd0eed64 357 gtk_choice_clicked_callback( (GtkWidget *) NULL, this );
6de97a3b 358}
c801d85f
KB
359
360void wxChoice::SetStringSelection( const wxString &string )
361{
93c5dd39 362 wxCHECK_RET( m_widget != NULL, _T("invalid choice") );
f96aa4d9 363
fd0eed64
RR
364 int n = FindString( string );
365 if (n != -1) SetSelection( n );
6de97a3b 366}
c801d85f 367
58614078 368void wxChoice::ApplyWidgetStyle()
868a2826 369{
fd0eed64 370 SetWidgetStyle();
29006414 371
fd0eed64 372 GtkMenuShell *menu_shell = GTK_MENU_SHELL( gtk_option_menu_get_menu( GTK_OPTION_MENU(m_widget) ) );
29006414 373
fd0eed64
RR
374 gtk_widget_set_style( m_widget, m_widgetStyle );
375 gtk_widget_set_style( GTK_WIDGET( menu_shell ), m_widgetStyle );
29006414 376
fd0eed64
RR
377 GList *child = menu_shell->children;
378 while (child)
379 {
380 gtk_widget_set_style( GTK_WIDGET( child->data ), m_widgetStyle );
29006414 381
fd0eed64
RR
382 GtkBin *bin = GTK_BIN( child->data );
383 GtkWidget *label = (GtkWidget *) NULL;
384 if (bin->child) label = bin->child;
385 if (!label) label = GTK_BUTTON(m_widget)->child;
29006414 386
fd0eed64 387 gtk_widget_set_style( label, m_widgetStyle );
29006414 388
fd0eed64
RR
389 child = child->next;
390 }
f96aa4d9
RR
391}
392