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