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