1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk/control.cpp 
   3 // Purpose:     wxControl implementation for wxGTK 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling, Julian Smart and Vadim Zeitlin 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 // For compilers that support precompilation, includes "wx.h". 
  11 #include "wx/wxprec.h" 
  15 #include "wx/control.h" 
  19     #include "wx/settings.h" 
  22 #include "wx/fontutil.h" 
  23 #include "wx/gtk/private.h" 
  25 // ============================================================================ 
  26 // wxControl implementation 
  27 // ============================================================================ 
  29 // ---------------------------------------------------------------------------- 
  31 // ---------------------------------------------------------------------------- 
  33 IMPLEMENT_DYNAMIC_CLASS(wxControl
, wxWindow
) 
  35 wxControl::wxControl() 
  40 bool wxControl::Create( wxWindow 
*parent
, 
  45                       const wxValidator
& validator
, 
  46                       const wxString 
&name 
) 
  48     bool ret 
= wxWindow::Create(parent
, id
, pos
, size
, style
, name
); 
  51     SetValidator(validator
); 
  57 wxSize 
wxControl::DoGetBestSize() const 
  59     // Do not return any arbitrary default value... 
  60     wxASSERT_MSG( m_widget
, wxT("DoGetBestSize called before creation") ); 
  65     (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) )->size_request 
) 
  68     wxSize 
best(req
.width
, req
.height
); 
  73 void wxControl::PostCreation(const wxSize
& size
) 
  75     wxWindow::PostCreation(); 
  77     // NB: GetBestSize needs to know the style, otherwise it will assume 
  78     //     default font and if the user uses a different font, determined 
  79     //     best size will be different (typically, smaller) than the desired 
  80     //     size. This call ensure that a style is available at the time 
  81     //     GetBestSize is called. 
  82     gtk_widget_ensure_style(m_widget
); 
  85     SetInitialBestSize(size
); 
  88 // ---------------------------------------------------------------------------- 
  89 // wxControl dealing with labels 
  90 // ---------------------------------------------------------------------------- 
  92 void wxControl::SetLabel( const wxString 
&label 
) 
  94     // keep the original string internally to be able to return it later (for 
  95     // consistency with the other ports) 
 101 wxString 
wxControl::GetLabel() const 
 106 void wxControl::GTKSetLabelForLabel(GtkLabel 
*w
, const wxString
& label
) 
 108     // don't call the virtual function which might call this one back again 
 109     wxControl::SetLabel(label
); 
 111     const wxString labelGTK 
= GTKConvertMnemonics(label
); 
 113     gtk_label_set_text_with_mnemonic(w
, wxGTK_CONV(labelGTK
)); 
 116 // ---------------------------------------------------------------------------- 
 119 // GtkFrames do in fact support mnemonics in GTK2+ but not through 
 120 // gtk_frame_set_label, rather you need to use a custom label widget 
 121 // instead (idea gleaned from the native gtk font dialog code in GTK) 
 122 // ---------------------------------------------------------------------------- 
 124 GtkWidget
* wxControl::GTKCreateFrame(const wxString
& label
) 
 126     const wxString labelGTK 
= GTKConvertMnemonics(label
); 
 127     GtkWidget
* labelwidget 
= gtk_label_new_with_mnemonic(wxGTK_CONV(labelGTK
)); 
 128     gtk_widget_show(labelwidget
); // without this it won't show... 
 130     GtkWidget
* framewidget 
= gtk_frame_new(NULL
); 
 131     gtk_frame_set_label_widget(GTK_FRAME(framewidget
), labelwidget
); 
 133     return framewidget
; //note that the label is already set so you'll 
 134                         //only need to call wxControl::SetLabel afterwards 
 137 void wxControl::GTKSetLabelForFrame(GtkFrame 
*w
, const wxString
& label
) 
 139     GtkLabel
* labelwidget 
= GTK_LABEL(gtk_frame_get_label_widget(w
)); 
 140     GTKSetLabelForLabel(labelwidget
, label
); 
 143 void wxControl::GTKFrameApplyWidgetStyle(GtkFrame
* w
, GtkRcStyle
* style
) 
 145     gtk_widget_modify_style(GTK_WIDGET(w
), style
); 
 146     gtk_widget_modify_style(gtk_frame_get_label_widget (w
), style
); 
 149 void wxControl::GTKFrameSetMnemonicWidget(GtkFrame
* w
, GtkWidget
* widget
) 
 151     GtkLabel
* labelwidget 
= GTK_LABEL(gtk_frame_get_label_widget(w
)); 
 153     gtk_label_set_mnemonic_widget(labelwidget
, widget
); 
 156 // ---------------------------------------------------------------------------- 
 157 // worker function implementing both GTKConvert/RemoveMnemonics() 
 159 // notice that under GTK+ 1 we only really need to support MNEMONICS_REMOVE as 
 160 // it doesn't support mnemonics anyhow but this would make the code so ugly 
 161 // that we do the same thing for GKT+ 1 and 2 
 162 // ---------------------------------------------------------------------------- 
 170 static wxString 
GTKProcessMnemonics(const wxString
& label
, MnemonicsFlag flag
) 
 172     const size_t len 
= label
.length(); 
 174     labelGTK
.reserve(len
); 
 175     for ( size_t i 
= 0; i 
< len
; i
++ ) 
 177         wxChar ch 
= label
[i
]; 
 184                     // "&" at the end of string is an error 
 185                     wxLogDebug(wxT("Invalid label \"%s\"."), label
.c_str()); 
 189                 ch 
= label
[++i
]; // skip '&' itself 
 193                         // special case: "&&" is not a mnemonic at all but just 
 195                         labelGTK 
+= wxT('&'); 
 199                         if ( flag 
== MNEMONICS_CONVERT 
) 
 201                             // '_' can't be a GTK mnemonic apparently so 
 202                             // replace it with something similar 
 203                             labelGTK 
+= wxT("_-"); 
 209                         if ( flag 
== MNEMONICS_CONVERT 
) 
 210                             labelGTK 
+= wxT('_'); 
 216                 if ( flag 
== MNEMONICS_CONVERT 
) 
 218                     // escape any existing underlines in the string so that 
 219                     // they don't become mnemonics accidentally 
 220                     labelGTK 
+= wxT("__"); 
 234 wxString 
wxControl::GTKRemoveMnemonics(const wxString
& label
) 
 236     return GTKProcessMnemonics(label
, MNEMONICS_REMOVE
); 
 240 wxString 
wxControl::GTKConvertMnemonics(const wxString
& label
) 
 242     return GTKProcessMnemonics(label
, MNEMONICS_CONVERT
); 
 245 // ---------------------------------------------------------------------------- 
 246 // wxControl styles (a.k.a. attributes) 
 247 // ---------------------------------------------------------------------------- 
 249 wxVisualAttributes 
wxControl::GetDefaultAttributes() const 
 251     return GetDefaultAttributesFromGTKWidget(m_widget
, 
 256 #define SHIFT (8*(sizeof(short int)-sizeof(char))) 
 260 wxControl::GetDefaultAttributesFromGTKWidget(GtkWidget
* widget
, 
 265     wxVisualAttributes attr
; 
 267     style 
= gtk_rc_get_style(widget
); 
 269         style 
= gtk_widget_get_default_style(); 
 273         return wxWindow::GetClassDefaultAttributes(wxWINDOW_VARIANT_NORMAL
); 
 277         state 
= GTK_STATE_NORMAL
; 
 279     // get the style's colours 
 280     attr
.colFg 
= wxColour(style
->fg
[state
].red   
>> SHIFT
, 
 281                           style
->fg
[state
].green 
>> SHIFT
, 
 282                           style
->fg
[state
].blue  
>> SHIFT
); 
 284         attr
.colBg 
= wxColour(style
->base
[state
].red   
>> SHIFT
, 
 285                               style
->base
[state
].green 
>> SHIFT
, 
 286                               style
->base
[state
].blue  
>> SHIFT
); 
 288         attr
.colBg 
= wxColour(style
->bg
[state
].red   
>> SHIFT
, 
 289                               style
->bg
[state
].green 
>> SHIFT
, 
 290                               style
->bg
[state
].blue  
>> SHIFT
); 
 292     // get the style's font 
 293     if ( !style
->font_desc 
) 
 294         style 
= gtk_widget_get_default_style(); 
 295     if ( style 
&& style
->font_desc 
) 
 297         wxNativeFontInfo info
; 
 298         info
.description 
= pango_font_description_copy(style
->font_desc
); 
 299         attr
.font 
= wxFont(info
); 
 303         GtkSettings 
*settings 
= gtk_settings_get_default(); 
 304         gchar 
*font_name 
= NULL
; 
 305         g_object_get ( settings
, 
 310             attr
.font 
= wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT 
); 
 312             attr
.font 
= wxFont(wxString::FromAscii(font_name
)); 
 322 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNew_t widget_new
, 
 326     wxVisualAttributes attr
; 
 327     // NB: we need toplevel window so that GTK+ can find the right style 
 328     GtkWidget 
*wnd 
= gtk_window_new(GTK_WINDOW_TOPLEVEL
); 
 329     GtkWidget
* widget 
= widget_new(); 
 330     gtk_container_add(GTK_CONTAINER(wnd
), widget
); 
 331     attr 
= GetDefaultAttributesFromGTKWidget(widget
, useBase
, state
); 
 332     gtk_widget_destroy(wnd
); 
 338 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromStr_t widget_new
, 
 342     wxVisualAttributes attr
; 
 343     // NB: we need toplevel window so that GTK+ can find the right style 
 344     GtkWidget 
*wnd 
= gtk_window_new(GTK_WINDOW_TOPLEVEL
); 
 345     GtkWidget
* widget 
= widget_new(""); 
 346     gtk_container_add(GTK_CONTAINER(wnd
), widget
); 
 347     attr 
= GetDefaultAttributesFromGTKWidget(widget
, useBase
, state
); 
 348     gtk_widget_destroy(wnd
); 
 355 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromAdj_t widget_new
, 
 359     wxVisualAttributes attr
; 
 360     // NB: we need toplevel window so that GTK+ can find the right style 
 361     GtkWidget 
*wnd 
= gtk_window_new(GTK_WINDOW_TOPLEVEL
); 
 362     GtkWidget
* widget 
= widget_new(NULL
); 
 363     gtk_container_add(GTK_CONTAINER(wnd
), widget
); 
 364     attr 
= GetDefaultAttributesFromGTKWidget(widget
, useBase
, state
); 
 365     gtk_widget_destroy(wnd
); 
 369 #endif // wxUSE_CONTROLS