Fix for TextCtrl problem as reported by Vegh
[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(void)
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 GtkWidget *item = gtk_menu_item_new_with_label( choices[i] );
73 gtk_menu_append( GTK_MENU(menu), item );
74
75 gtk_widget_realize( item );
76 gtk_widget_realize( GTK_BIN(item)->child );
77
78 gtk_widget_show( item );
79
80 gtk_signal_connect( GTK_OBJECT( item ), "activate",
81 GTK_SIGNAL_FUNC(gtk_choice_clicked_callback), (gpointer*)this );
82 }
83 gtk_option_menu_set_menu( GTK_OPTION_MENU(m_widget), menu );
84
85 m_parent->AddChild( this );
86
87 (m_parent->m_insertCallback)( m_parent, this );
88
89 PostCreation();
90
91 SetBackgroundColour( parent->GetBackgroundColour() );
92 SetForegroundColour( parent->GetForegroundColour() );
93
94 Show( TRUE );
95
96 return TRUE;
97 }
98
99 void wxChoice::Append( const wxString &item )
100 {
101 wxCHECK_RET( m_widget != NULL, "invalid choice" );
102
103 GtkWidget *menu = gtk_option_menu_get_menu( GTK_OPTION_MENU(m_widget) );
104 GtkWidget *menu_item = gtk_menu_item_new_with_label( item );
105
106 gtk_menu_append( GTK_MENU(menu), menu_item );
107
108 gtk_widget_realize( menu_item );
109 gtk_widget_realize( GTK_BIN(menu_item)->child );
110
111 if (m_widgetStyle) ApplyWidgetStyle();
112
113 gtk_signal_connect( GTK_OBJECT( menu_item ), "activate",
114 GTK_SIGNAL_FUNC(gtk_choice_clicked_callback), (gpointer*)this );
115
116 gtk_widget_show( menu_item );
117 }
118
119 void wxChoice::Clear(void)
120 {
121 wxCHECK_RET( m_widget != NULL, "invalid choice" );
122
123 gtk_option_menu_remove_menu( GTK_OPTION_MENU(m_widget) );
124 GtkWidget *menu = gtk_menu_new();
125 gtk_option_menu_set_menu( GTK_OPTION_MENU(m_widget), menu );
126 }
127
128 void wxChoice::Delete( int WXUNUSED(n) )
129 {
130 wxFAIL_MSG( "wxChoice:Delete not implemented" );
131 }
132
133 int wxChoice::FindString( const wxString &string ) const
134 {
135 wxCHECK_MSG( m_widget != NULL, -1, "invalid choice" );
136
137 // If you read this code once and you think you understand
138 // it, then you are very wrong. Robert Roebling.
139
140 GtkMenuShell *menu_shell = GTK_MENU_SHELL( gtk_option_menu_get_menu( GTK_OPTION_MENU(m_widget) ) );
141 int count = 0;
142 GList *child = menu_shell->children;
143 while (child)
144 {
145 GtkBin *bin = GTK_BIN( child->data );
146 GtkLabel *label = (GtkLabel *) NULL;
147 if (bin->child) label = GTK_LABEL(bin->child);
148 if (!label) label = GTK_LABEL( GTK_BUTTON(m_widget)->child );
149
150 wxASSERT_MSG( label != NULL , "wxChoice: invalid label" );
151
152 if (string == label->label) return count;
153 child = child->next;
154 count++;
155 }
156
157 wxFAIL_MSG( "wxChoice: string not found" );
158
159 return -1;
160 }
161
162 int wxChoice::GetColumns(void) const
163 {
164 return 1;
165 }
166
167 int wxChoice::GetSelection(void)
168 {
169 wxCHECK_MSG( m_widget != NULL, -1, "invalid choice" );
170
171 GtkMenuShell *menu_shell = GTK_MENU_SHELL( gtk_option_menu_get_menu( GTK_OPTION_MENU(m_widget) ) );
172 int count = 0;
173 GList *child = menu_shell->children;
174 while (child)
175 {
176 GtkBin *bin = GTK_BIN( child->data );
177 if (!bin->child) return count;
178 child = child->next;
179 count++;
180 }
181
182 wxFAIL_MSG( "wxChoice: no selection" );
183
184 return -1;
185 }
186
187 wxString wxChoice::GetString( int n ) const
188 {
189 wxCHECK_MSG( m_widget != NULL, "", "invalid choice" );
190
191 GtkMenuShell *menu_shell = GTK_MENU_SHELL( gtk_option_menu_get_menu( GTK_OPTION_MENU(m_widget) ) );
192 int count = 0;
193 GList *child = menu_shell->children;
194 while (child)
195 {
196 GtkBin *bin = GTK_BIN( child->data );
197 if (count == n)
198 {
199 GtkLabel *label = (GtkLabel *) NULL;
200 if (bin->child) label = GTK_LABEL(bin->child);
201 if (!label) label = GTK_LABEL( GTK_BUTTON(m_widget)->child );
202
203 wxASSERT_MSG( label != NULL , "wxChoice: invalid label" );
204
205 return label->label;
206 }
207 child = child->next;
208 count++;
209 }
210
211 wxFAIL_MSG( "wxChoice: string not found" );
212
213 return "";
214 }
215
216 wxString wxChoice::GetStringSelection(void) const
217 {
218 wxCHECK_MSG( m_widget != NULL, "", "invalid choice" );
219
220 GtkLabel *label = GTK_LABEL( GTK_BUTTON(m_widget)->child );
221
222 wxASSERT_MSG( label != NULL , "wxChoice: invalid label" );
223
224 return label->label;
225 }
226
227 int wxChoice::Number(void) const
228 {
229 wxCHECK_MSG( m_widget != NULL, 0, "invalid choice" );
230
231 GtkMenuShell *menu_shell = GTK_MENU_SHELL( gtk_option_menu_get_menu( GTK_OPTION_MENU(m_widget) ) );
232 int count = 0;
233 GList *child = menu_shell->children;
234 while (child)
235 {
236 count++;
237 child = child->next;
238 }
239 return count;
240 }
241
242 void wxChoice::SetColumns( int WXUNUSED(n) )
243 {
244 }
245
246 void wxChoice::SetSelection( int n )
247 {
248 wxCHECK_RET( m_widget != NULL, "invalid choice" );
249
250 int tmp = n;
251 gtk_option_menu_set_history( GTK_OPTION_MENU(m_widget), (gint)tmp );
252
253 gtk_choice_clicked_callback( (GtkWidget *) NULL, this );
254 }
255
256 void wxChoice::SetStringSelection( const wxString &string )
257 {
258 wxCHECK_RET( m_widget != NULL, "invalid choice" );
259
260 int n = FindString( string );
261 if (n != -1) SetSelection( n );
262 }
263
264 void wxChoice::ApplyWidgetStyle()
265 {
266 SetWidgetStyle();
267
268 GtkMenuShell *menu_shell = GTK_MENU_SHELL( gtk_option_menu_get_menu( GTK_OPTION_MENU(m_widget) ) );
269
270 gtk_widget_set_style( m_widget, m_widgetStyle );
271 gtk_widget_set_style( GTK_WIDGET( menu_shell ), m_widgetStyle );
272
273 GList *child = menu_shell->children;
274 while (child)
275 {
276 gtk_widget_set_style( GTK_WIDGET( child->data ), m_widgetStyle );
277
278 GtkBin *bin = GTK_BIN( child->data );
279 GtkWidget *label = (GtkWidget *) NULL;
280 if (bin->child) label = bin->child;
281 if (!label) label = GTK_BUTTON(m_widget)->child;
282
283 gtk_widget_set_style( label, m_widgetStyle );
284
285 child = child->next;
286 }
287 }
288