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