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