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" 
  16 #include "wx/control.h" 
  17 #include "wx/fontutil.h" 
  18 #include "wx/settings.h" 
  19 #include "wx/gtk/private.h" 
  21 // ============================================================================ 
  22 // wxControl implementation 
  23 // ============================================================================ 
  25 // ---------------------------------------------------------------------------- 
  27 // ---------------------------------------------------------------------------- 
  29 IMPLEMENT_DYNAMIC_CLASS(wxControl
, wxWindow
) 
  31 wxControl::wxControl() 
  36 bool wxControl::Create( wxWindow 
*parent
, 
  41                       const wxValidator
& validator
, 
  42                       const wxString 
&name 
) 
  44     bool ret 
= wxWindow::Create(parent
, id
, pos
, size
, style
, name
); 
  47     SetValidator(validator
); 
  53 wxSize 
wxControl::DoGetBestSize() const 
  55     // Do not return any arbitrary default value... 
  56     wxASSERT_MSG( m_widget
, wxT("DoGetBestSize called before creation") ); 
  61     (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) )->size_request 
) 
  64     wxSize 
best(req
.width
, req
.height
); 
  69 void wxControl::PostCreation(const wxSize
& size
) 
  71     wxWindow::PostCreation(); 
  73     // NB: GetBestSize needs to know the style, otherwise it will assume 
  74     //     default font and if the user uses a different font, determined 
  75     //     best size will be different (typically, smaller) than the desired 
  76     //     size. This call ensure that a style is available at the time 
  77     //     GetBestSize is called. 
  78     gtk_widget_ensure_style(m_widget
); 
  81     SetInitialBestSize(size
); 
  84 // ---------------------------------------------------------------------------- 
  85 // wxControl dealing with labels 
  86 // ---------------------------------------------------------------------------- 
  88 void wxControl::SetLabel( const wxString 
&label 
) 
  90     // keep the original string internally to be able to return it later (for 
  91     // consistency with the other ports) 
  97 wxString 
wxControl::GetLabel() const 
 102 void wxControl::GTKSetLabelForLabel(GtkLabel 
*w
, const wxString
& label
) 
 104     // don't call the virtual function which might call this one back again 
 105     wxControl::SetLabel(label
); 
 107     const wxString labelGTK 
= GTKConvertMnemonics(label
); 
 109     gtk_label_set_text_with_mnemonic(w
, wxGTK_CONV(labelGTK
)); 
 112 // ---------------------------------------------------------------------------- 
 115 // GtkFrames do in fact support mnemonics in GTK2+ but not through 
 116 // gtk_frame_set_label, rather you need to use a custom label widget 
 117 // instead (idea gleaned from the native gtk font dialog code in GTK) 
 118 // ---------------------------------------------------------------------------- 
 120 GtkWidget
* wxControl::GTKCreateFrame(const wxString
& label
) 
 122     const wxString labelGTK 
= GTKConvertMnemonics(label
); 
 123     GtkWidget
* labelwidget 
= gtk_label_new_with_mnemonic(wxGTK_CONV(labelGTK
)); 
 124     gtk_widget_show(labelwidget
); // without this it won't show... 
 126     GtkWidget
* framewidget 
= gtk_frame_new(NULL
); 
 127     gtk_frame_set_label_widget(GTK_FRAME(framewidget
), labelwidget
); 
 129     return framewidget
; //note that the label is already set so you'll  
 130                         //only need to call wxControl::SetLabel afterwards 
 133 void wxControl::GTKSetLabelForFrame(GtkFrame 
*w
, const wxString
& label
) 
 135     GtkLabel
* labelwidget 
= GTK_LABEL(gtk_frame_get_label_widget(w
)); 
 136     GTKSetLabelForLabel(labelwidget
, label
); 
 139 void wxControl::GTKFrameApplyWidgetStyle(GtkFrame
* w
, GtkRcStyle
* style
) 
 141     gtk_widget_modify_style(GTK_WIDGET(w
), style
); 
 142     gtk_widget_modify_style(gtk_frame_get_label_widget (w
), style
); 
 145 void wxControl::GTKFrameSetMnemonicWidget(GtkFrame
* w
, GtkWidget
* widget
) 
 147     GtkLabel
* labelwidget 
= GTK_LABEL(gtk_frame_get_label_widget(w
)); 
 149     gtk_label_set_mnemonic_widget(labelwidget
, widget
); 
 152 // ---------------------------------------------------------------------------- 
 153 // worker function implementing both GTKConvert/RemoveMnemonics() 
 155 // notice that under GTK+ 1 we only really need to support MNEMONICS_REMOVE as 
 156 // it doesn't support mnemonics anyhow but this would make the code so ugly 
 157 // that we do the same thing for GKT+ 1 and 2 
 158 // ---------------------------------------------------------------------------- 
 166 static wxString 
GTKProcessMnemonics(const wxString
& label
, MnemonicsFlag flag
) 
 168     const size_t len 
= label
.length(); 
 170     labelGTK
.reserve(len
); 
 171     for ( size_t i 
= 0; i 
< len
; i
++ ) 
 173         wxChar ch 
= label
[i
]; 
 180                     // "&" at the end of string is an error 
 181                     wxLogDebug(wxT("Invalid label \"%s\"."), label
.c_str()); 
 185                 ch 
= label
[++i
]; // skip '&' itself 
 189                         // special case: "&&" is not a mnemonic at all but just 
 191                         labelGTK 
+= wxT('&'); 
 195                         if ( flag 
== MNEMONICS_CONVERT 
) 
 197                             // '_' can't be a GTK mnemonic apparently so 
 198                             // replace it with something similar 
 199                             labelGTK 
+= wxT("_-"); 
 205                         if ( flag 
== MNEMONICS_CONVERT 
) 
 206                             labelGTK 
+= wxT('_'); 
 212                 if ( flag 
== MNEMONICS_CONVERT 
) 
 214                     // escape any existing underlines in the string so that 
 215                     // they don't become mnemonics accidentally 
 216                     labelGTK 
+= wxT("__"); 
 230 wxString 
wxControl::GTKRemoveMnemonics(const wxString
& label
) 
 232     return GTKProcessMnemonics(label
, MNEMONICS_REMOVE
); 
 236 wxString 
wxControl::GTKConvertMnemonics(const wxString
& label
) 
 238     return GTKProcessMnemonics(label
, MNEMONICS_CONVERT
); 
 241 // ---------------------------------------------------------------------------- 
 242 // wxControl styles (a.k.a. attributes) 
 243 // ---------------------------------------------------------------------------- 
 245 wxVisualAttributes 
wxControl::GetDefaultAttributes() const 
 247     return GetDefaultAttributesFromGTKWidget(m_widget
, 
 252 #define SHIFT (8*(sizeof(short int)-sizeof(char))) 
 256 wxControl::GetDefaultAttributesFromGTKWidget(GtkWidget
* widget
, 
 261     wxVisualAttributes attr
; 
 263     style 
= gtk_rc_get_style(widget
); 
 265         style 
= gtk_widget_get_default_style(); 
 269         return wxWindow::GetClassDefaultAttributes(wxWINDOW_VARIANT_NORMAL
); 
 273         state 
= GTK_STATE_NORMAL
; 
 275     // get the style's colours 
 276     attr
.colFg 
= wxColour(style
->fg
[state
].red   
>> SHIFT
, 
 277                           style
->fg
[state
].green 
>> SHIFT
, 
 278                           style
->fg
[state
].blue  
>> SHIFT
); 
 280         attr
.colBg 
= wxColour(style
->base
[state
].red   
>> SHIFT
, 
 281                               style
->base
[state
].green 
>> SHIFT
, 
 282                               style
->base
[state
].blue  
>> SHIFT
); 
 284         attr
.colBg 
= wxColour(style
->bg
[state
].red   
>> SHIFT
, 
 285                               style
->bg
[state
].green 
>> SHIFT
, 
 286                               style
->bg
[state
].blue  
>> SHIFT
); 
 288     // get the style's font 
 289     if ( !style
->font_desc 
) 
 290         style 
= gtk_widget_get_default_style(); 
 291     if ( style 
&& style
->font_desc 
) 
 293         wxNativeFontInfo info
; 
 294         info
.description 
= pango_font_description_copy(style
->font_desc
); 
 295         attr
.font 
= wxFont(info
); 
 299         GtkSettings 
*settings 
= gtk_settings_get_default(); 
 300         gchar 
*font_name 
= NULL
; 
 301         g_object_get ( settings
, 
 306             attr
.font 
= wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT 
); 
 308             attr
.font 
= wxFont(wxString::FromAscii(font_name
)); 
 318 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNew_t widget_new
, 
 322     wxVisualAttributes attr
; 
 323     // NB: we need toplevel window so that GTK+ can find the right style 
 324     GtkWidget 
*wnd 
= gtk_window_new(GTK_WINDOW_TOPLEVEL
); 
 325     GtkWidget
* widget 
= widget_new(); 
 326     gtk_container_add(GTK_CONTAINER(wnd
), widget
); 
 327     attr 
= GetDefaultAttributesFromGTKWidget(widget
, useBase
, state
); 
 328     gtk_widget_destroy(wnd
); 
 334 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromStr_t widget_new
, 
 338     wxVisualAttributes attr
; 
 339     // NB: we need toplevel window so that GTK+ can find the right style 
 340     GtkWidget 
*wnd 
= gtk_window_new(GTK_WINDOW_TOPLEVEL
); 
 341     GtkWidget
* widget 
= widget_new(""); 
 342     gtk_container_add(GTK_CONTAINER(wnd
), widget
); 
 343     attr 
= GetDefaultAttributesFromGTKWidget(widget
, useBase
, state
); 
 344     gtk_widget_destroy(wnd
); 
 351 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromAdj_t widget_new
, 
 355     wxVisualAttributes attr
; 
 356     // NB: we need toplevel window so that GTK+ can find the right style 
 357     GtkWidget 
*wnd 
= gtk_window_new(GTK_WINDOW_TOPLEVEL
); 
 358     GtkWidget
* widget 
= widget_new(NULL
); 
 359     gtk_container_add(GTK_CONTAINER(wnd
), widget
); 
 360     attr 
= GetDefaultAttributesFromGTKWidget(widget
, useBase
, state
); 
 361     gtk_widget_destroy(wnd
); 
 365 #endif // wxUSE_CONTROLS