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