1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  12 #pragma implementation "choice.h" 
  15 #include "wx/choice.h" 
  20 //----------------------------------------------------------------------------- 
  22 //----------------------------------------------------------------------------- 
  24 extern void wxapp_install_idle_handler(); 
  27 //----------------------------------------------------------------------------- 
  29 //----------------------------------------------------------------------------- 
  31 extern bool   g_blockEventsOnDrag
; 
  33 //----------------------------------------------------------------------------- 
  35 //----------------------------------------------------------------------------- 
  37 static void gtk_choice_clicked_callback( GtkWidget 
*WXUNUSED(widget
), wxChoice 
*choice 
) 
  39     if (g_isIdle
) wxapp_install_idle_handler(); 
  41     if (!choice
->m_hasVMT
) return; 
  43     if (g_blockEventsOnDrag
) return; 
  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
); 
  52 //----------------------------------------------------------------------------- 
  54 //----------------------------------------------------------------------------- 
  56 IMPLEMENT_DYNAMIC_CLASS(wxChoice
,wxControl
) 
  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 
) 
  68 #if (GTK_MINOR_VERSION > 0) 
  69     m_acceptsFocus 
= TRUE
; 
  72     PreCreation( parent
, id
, pos
, size
, style
, name 
); 
  74     SetValidator( validator 
); 
  76     m_widget 
= gtk_option_menu_new(); 
  83     SetSize( newSize
.x
, newSize
.y 
); 
  85     GtkWidget 
*menu 
= gtk_menu_new(); 
  87     for (int i 
= 0; i 
< n
; i
++) 
  89         m_clientDataList
.Append( (wxObject
*) NULL 
); 
  90         m_clientObjectList
.Append( (wxObject
*) NULL 
); 
  92         GtkWidget 
*item 
= gtk_menu_item_new_with_label( choices
[i
].mbc_str() ); 
  93         gtk_menu_append( GTK_MENU(menu
), item 
); 
  95         gtk_widget_show( item 
); 
  97         gtk_signal_connect( GTK_OBJECT( item 
), "activate", 
  98           GTK_SIGNAL_FUNC(gtk_choice_clicked_callback
), (gpointer
*)this ); 
 100     gtk_option_menu_set_menu( GTK_OPTION_MENU(m_widget
), menu 
); 
 102     m_parent
->DoAddChild( this ); 
 106     SetBackgroundColour( parent
->GetBackgroundColour() ); 
 107     SetForegroundColour( parent
->GetForegroundColour() ); 
 108     SetFont( parent
->GetFont() ); 
 115 wxChoice::~wxChoice() 
 120 void wxChoice::AppendCommon( const wxString 
&item 
) 
 122     wxCHECK_RET( m_widget 
!= NULL
, _T("invalid choice") ); 
 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() ); 
 127     gtk_menu_append( GTK_MENU(menu
), menu_item 
); 
 129     if (GTK_WIDGET_REALIZED(m_widget
)) 
 131         gtk_widget_realize( menu_item 
); 
 132         gtk_widget_realize( GTK_BIN(menu_item
)->child 
); 
 134         if (m_widgetStyle
) ApplyWidgetStyle(); 
 137     gtk_signal_connect( GTK_OBJECT( menu_item 
), "activate", 
 138       GTK_SIGNAL_FUNC(gtk_choice_clicked_callback
), (gpointer
*)this ); 
 140     gtk_widget_show( menu_item 
); 
 143 void wxChoice::Append( const wxString 
&item 
) 
 145     m_clientDataList
.Append( (wxObject
*) NULL 
); 
 146     m_clientObjectList
.Append( (wxObject
*) NULL 
); 
 148     AppendCommon( item 
); 
 151 void wxChoice::Append( const wxString 
&item
, void *clientData 
) 
 153     m_clientDataList
.Append( (wxObject
*) clientData 
); 
 154     m_clientObjectList
.Append( (wxObject
*) NULL 
); 
 156     AppendCommon( item 
); 
 159 void wxChoice::Append( const wxString 
&item
, wxClientData 
*clientData 
) 
 161     m_clientObjectList
.Append( (wxObject
*) clientData 
); 
 162     m_clientDataList
.Append( (wxObject
*) NULL 
); 
 164     AppendCommon( item 
); 
 167 void wxChoice::SetClientData( int n
, void* clientData 
) 
 169     wxCHECK_RET( m_widget 
!= NULL
, _T("invalid combobox") ); 
 171     wxNode 
*node 
= m_clientDataList
.Nth( n 
); 
 174     node
->SetData( (wxObject
*) clientData 
); 
 177 void* wxChoice::GetClientData( int n 
) 
 179     wxCHECK_MSG( m_widget 
!= NULL
, NULL
, _T("invalid combobox") ); 
 181     wxNode 
*node 
= m_clientDataList
.Nth( n 
); 
 182     if (!node
) return NULL
; 
 187 void wxChoice::SetClientObject( int n
, wxClientData
* clientData 
) 
 189     wxCHECK_RET( m_widget 
!= NULL
, _T("invalid combobox") ); 
 191     wxNode 
*node 
= m_clientObjectList
.Nth( n 
); 
 194     wxClientData 
*cd 
= (wxClientData
*) node
->Data(); 
 197     node
->SetData( (wxObject
*) clientData 
); 
 200 wxClientData
* wxChoice::GetClientObject( int n 
) 
 202     wxCHECK_MSG( m_widget 
!= NULL
, (wxClientData
*) NULL
, _T("invalid combobox") ); 
 204     wxNode 
*node 
= m_clientObjectList
.Nth( n 
); 
 205     if (!node
) return (wxClientData
*) NULL
; 
 207     return (wxClientData
*) node
->Data(); 
 210 void wxChoice::Clear() 
 212     wxCHECK_RET( m_widget 
!= NULL
, _T("invalid choice") ); 
 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 
); 
 218     wxNode 
*node 
= m_clientObjectList
.First(); 
 221         wxClientData 
*cd 
= (wxClientData
*)node
->Data(); 
 225     m_clientObjectList
.Clear(); 
 227     m_clientDataList
.Clear(); 
 230 void wxChoice::Delete( int WXUNUSED(n
) ) 
 232     wxFAIL_MSG( _T("wxChoice:Delete not implemented") ); 
 235 int wxChoice::FindString( const wxString 
&string 
) const 
 237     wxCHECK_MSG( m_widget 
!= NULL
, -1, _T("invalid choice") ); 
 239     // If you read this code once and you think you understand 
 240     // it, then you are very wrong. Robert Roebling. 
 242     GtkMenuShell 
*menu_shell 
= GTK_MENU_SHELL( gtk_option_menu_get_menu( GTK_OPTION_MENU(m_widget
) ) ); 
 244     GList 
*child 
= menu_shell
->children
; 
 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 
); 
 252         wxASSERT_MSG( label 
!= NULL 
, _T("wxChoice: invalid label") ); 
 254        if (string 
== wxString(label
->label
,*wxConvCurrent
)) 
 264 int wxChoice::GetColumns() const 
 269 int wxChoice::GetSelection() 
 271     wxCHECK_MSG( m_widget 
!= NULL
, -1, _T("invalid choice") ); 
 273     GtkMenuShell 
*menu_shell 
= GTK_MENU_SHELL( gtk_option_menu_get_menu( GTK_OPTION_MENU(m_widget
) ) ); 
 275     GList 
*child 
= menu_shell
->children
; 
 278         GtkBin 
*bin 
= GTK_BIN( child
->data 
); 
 279         if (!bin
->child
) return count
; 
 284     wxFAIL_MSG( _T("wxChoice: no selection") ); 
 289 wxString 
wxChoice::GetString( int n 
) const 
 291     wxCHECK_MSG( m_widget 
!= NULL
, _T(""), _T("invalid choice") ); 
 293     GtkMenuShell 
*menu_shell 
= GTK_MENU_SHELL( gtk_option_menu_get_menu( GTK_OPTION_MENU(m_widget
) ) ); 
 295     GList 
*child 
= menu_shell
->children
; 
 298         GtkBin 
*bin 
= GTK_BIN( child
->data 
); 
 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 
); 
 305             wxASSERT_MSG( label 
!= NULL 
, _T("wxChoice: invalid label") ); 
 307             return wxString(label
->label
,*wxConvCurrent
); 
 313     wxFAIL_MSG( _T("wxChoice: invalid index in GetString()") ); 
 318 wxString 
wxChoice::GetStringSelection() const 
 320     wxCHECK_MSG( m_widget 
!= NULL
, _T(""), _T("invalid choice") ); 
 322     GtkLabel 
*label 
= GTK_LABEL( GTK_BUTTON(m_widget
)->child 
); 
 324     wxASSERT_MSG( label 
!= NULL 
, _T("wxChoice: invalid label") ); 
 326     return wxString(label
->label
,*wxConvCurrent
); 
 329 int wxChoice::Number() const 
 331     wxCHECK_MSG( m_widget 
!= NULL
, 0, _T("invalid choice") ); 
 333     GtkMenuShell 
*menu_shell 
= GTK_MENU_SHELL( gtk_option_menu_get_menu( GTK_OPTION_MENU(m_widget
) ) ); 
 335     GList 
*child 
= menu_shell
->children
; 
 344 void wxChoice::SetColumns( int WXUNUSED(n
) ) 
 348 void wxChoice::SetSelection( int n 
) 
 350     wxCHECK_RET( m_widget 
!= NULL
, _T("invalid choice") ); 
 353     gtk_option_menu_set_history( GTK_OPTION_MENU(m_widget
), (gint
)tmp 
); 
 355     gtk_choice_clicked_callback( (GtkWidget 
*) NULL
, this ); 
 358 void wxChoice::SetStringSelection( const wxString 
&string 
) 
 360     wxCHECK_RET( m_widget 
!= NULL
, _T("invalid choice") ); 
 362     int n 
= FindString( string 
); 
 363     if (n 
!= -1) SetSelection( n 
); 
 366 void wxChoice::ApplyWidgetStyle() 
 370     GtkMenuShell 
*menu_shell 
= GTK_MENU_SHELL( gtk_option_menu_get_menu( GTK_OPTION_MENU(m_widget
) ) ); 
 372     gtk_widget_set_style( m_widget
, m_widgetStyle 
); 
 373     gtk_widget_set_style( GTK_WIDGET( menu_shell 
), m_widgetStyle 
); 
 375     GList 
*child 
= menu_shell
->children
; 
 378         gtk_widget_set_style( GTK_WIDGET( child
->data 
), m_widgetStyle 
); 
 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
; 
 385         gtk_widget_set_style( label
, m_widgetStyle 
);