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 #include "wx/private/stattext.h"
28 // ============================================================================
29 // wxControl implementation
30 // ============================================================================
32 // ----------------------------------------------------------------------------
34 // ----------------------------------------------------------------------------
36 IMPLEMENT_DYNAMIC_CLASS(wxControl
, wxWindow
)
38 wxControl::wxControl()
43 bool wxControl::Create( wxWindow
*parent
,
48 const wxValidator
& validator
,
49 const wxString
&name
)
51 bool ret
= wxWindow::Create(parent
, id
, pos
, size
, style
, name
);
54 SetValidator(validator
);
60 wxSize
wxControl::DoGetBestSize() const
62 // Do not return any arbitrary default value...
63 wxASSERT_MSG( m_widget
, wxT("DoGetBestSize called before creation") );
68 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) )->size_request
)
71 wxSize
best(req
.width
, req
.height
);
76 void wxControl::PostCreation(const wxSize
& size
)
78 wxWindow::PostCreation();
80 // NB: GetBestSize needs to know the style, otherwise it will assume
81 // default font and if the user uses a different font, determined
82 // best size will be different (typically, smaller) than the desired
83 // size. This call ensure that a style is available at the time
84 // GetBestSize is called.
85 gtk_widget_ensure_style(m_widget
);
91 // ----------------------------------------------------------------------------
92 // wxControl dealing with labels
93 // ----------------------------------------------------------------------------
95 void wxControl::GTKSetLabelForLabel(GtkLabel
*w
, const wxString
& label
)
97 // save the original label
98 wxControlBase::SetLabel(label
);
100 const wxString labelGTK
= GTKConvertMnemonics(label
);
101 gtk_label_set_text_with_mnemonic(w
, wxGTK_CONV(labelGTK
));
104 void wxControl::GTKSetLabelWithMarkupForLabel(GtkLabel
*w
, const wxString
& label
)
106 const wxString labelGTK
= GTKConvertMnemonicsWithMarkup(label
);
107 gtk_label_set_markup_with_mnemonic(w
, wxGTK_CONV(labelGTK
));
111 // ----------------------------------------------------------------------------
114 // GtkFrames do in fact support mnemonics in GTK2+ but not through
115 // gtk_frame_set_label, rather you need to use a custom label widget
116 // instead (idea gleaned from the native gtk font dialog code in GTK)
117 // ----------------------------------------------------------------------------
119 GtkWidget
* wxControl::GTKCreateFrame(const wxString
& label
)
121 const wxString labelGTK
= GTKConvertMnemonics(label
);
122 GtkWidget
* labelwidget
= gtk_label_new_with_mnemonic(wxGTK_CONV(labelGTK
));
123 gtk_widget_show(labelwidget
); // without this it won't show...
125 GtkWidget
* framewidget
= gtk_frame_new(NULL
);
126 gtk_frame_set_label_widget(GTK_FRAME(framewidget
), labelwidget
);
128 return framewidget
; // note that the label is already set so you'll
129 // only need to call wxControl::SetLabel afterwards
132 void wxControl::GTKSetLabelForFrame(GtkFrame
*w
, const wxString
& label
)
134 GtkLabel
* labelwidget
= GTK_LABEL(gtk_frame_get_label_widget(w
));
135 GTKSetLabelForLabel(labelwidget
, label
);
138 void wxControl::GTKFrameApplyWidgetStyle(GtkFrame
* w
, GtkRcStyle
* style
)
140 gtk_widget_modify_style(GTK_WIDGET(w
), style
);
141 gtk_widget_modify_style(gtk_frame_get_label_widget (w
), style
);
144 void wxControl::GTKFrameSetMnemonicWidget(GtkFrame
* w
, GtkWidget
* widget
)
146 GtkLabel
* labelwidget
= GTK_LABEL(gtk_frame_get_label_widget(w
));
148 gtk_label_set_mnemonic_widget(labelwidget
, widget
);
151 // ----------------------------------------------------------------------------
152 // worker function implementing GTK*Mnemonics() functions
153 // ----------------------------------------------------------------------------
159 MNEMONICS_CONVERT_MARKUP
162 static wxString
GTKProcessMnemonics(const wxChar
* label
, MnemonicsFlag flag
)
164 const size_t len
= wxStrlen(label
);
166 labelGTK
.reserve(len
);
167 for ( size_t i
= 0; i
< len
; i
++ )
169 wxChar ch
= label
[i
];
176 // "&" at the end of string is an error
177 wxLogDebug(wxT("Invalid label \"%s\"."), label
);
181 if ( flag
== MNEMONICS_CONVERT_MARKUP
)
183 bool isMnemonic
= true;
185 // is this ampersand introducing a mnemonic or rather an entity?
186 for (size_t j
=0; j
< wxMARKUP_ENTITY_MAX
; j
++)
188 const wxChar
*entity
= wxMarkupEntities
[wxMARKUP_ELEMENT_NAME
][j
];
189 size_t entityLen
= wxStrlen(entity
);
191 if (len
- i
>= entityLen
&&
192 wxStrncmp(entity
, &label
[i
], entityLen
) == 0)
195 i
+= entityLen
- 1; // the -1 is because main for()
196 // loop already increments i
207 ch
= label
[++i
]; // skip '&' itself
211 // special case: "&&" is not a mnemonic at all but just
213 if ( flag
== MNEMONICS_CONVERT_MARKUP
)
214 labelGTK
+= wxT("&");
216 labelGTK
+= wxT('&');
220 if ( flag
!= MNEMONICS_REMOVE
)
222 // '_' can't be a GTK mnemonic apparently so
223 // replace it with something similar
224 labelGTK
+= wxT("_-");
230 if ( flag
!= MNEMONICS_REMOVE
)
231 labelGTK
+= wxT('_');
237 if ( flag
!= MNEMONICS_REMOVE
)
239 // escape any existing underlines in the string so that
240 // they don't become mnemonics accidentally
241 labelGTK
+= wxT("__");
255 wxString
wxControl::GTKRemoveMnemonics(const wxString
& label
)
257 return GTKProcessMnemonics(label
, MNEMONICS_REMOVE
);
261 wxString
wxControl::GTKConvertMnemonics(const wxString
& label
)
263 return GTKProcessMnemonics(label
, MNEMONICS_CONVERT
);
267 wxString
wxControl::GTKConvertMnemonicsWithMarkup(const wxString
& label
)
269 return GTKProcessMnemonics(label
, MNEMONICS_CONVERT_MARKUP
);
272 // ----------------------------------------------------------------------------
273 // wxControl styles (a.k.a. attributes)
274 // ----------------------------------------------------------------------------
276 wxVisualAttributes
wxControl::GetDefaultAttributes() const
278 return GetDefaultAttributesFromGTKWidget(m_widget
,
284 wxControl::GetDefaultAttributesFromGTKWidget(GtkWidget
* widget
,
289 wxVisualAttributes attr
;
291 style
= gtk_rc_get_style(widget
);
293 style
= gtk_widget_get_default_style();
297 return wxWindow::GetClassDefaultAttributes(wxWINDOW_VARIANT_NORMAL
);
301 state
= GTK_STATE_NORMAL
;
303 // get the style's colours
304 attr
.colFg
= wxColour(style
->fg
[state
]);
306 attr
.colBg
= wxColour(style
->base
[state
]);
308 attr
.colBg
= wxColour(style
->bg
[state
]);
310 // get the style's font
311 if ( !style
->font_desc
)
312 style
= gtk_widget_get_default_style();
313 if ( style
&& style
->font_desc
)
315 wxNativeFontInfo info
;
316 info
.description
= pango_font_description_copy(style
->font_desc
);
317 attr
.font
= wxFont(info
);
321 GtkSettings
*settings
= gtk_settings_get_default();
322 gchar
*font_name
= NULL
;
323 g_object_get ( settings
,
328 attr
.font
= wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT
);
330 attr
.font
= wxFont(wxString::FromAscii(font_name
));
340 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNew_t widget_new
,
344 wxVisualAttributes attr
;
345 // NB: we need toplevel window so that GTK+ can find the right style
346 GtkWidget
*wnd
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
347 GtkWidget
* widget
= widget_new();
348 gtk_container_add(GTK_CONTAINER(wnd
), widget
);
349 attr
= GetDefaultAttributesFromGTKWidget(widget
, useBase
, state
);
350 gtk_widget_destroy(wnd
);
356 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromStr_t widget_new
,
360 wxVisualAttributes attr
;
361 // NB: we need toplevel window so that GTK+ can find the right style
362 GtkWidget
*wnd
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
363 GtkWidget
* widget
= widget_new("");
364 gtk_container_add(GTK_CONTAINER(wnd
), widget
);
365 attr
= GetDefaultAttributesFromGTKWidget(widget
, useBase
, state
);
366 gtk_widget_destroy(wnd
);
373 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromAdj_t widget_new
,
377 wxVisualAttributes attr
;
378 // NB: we need toplevel window so that GTK+ can find the right style
379 GtkWidget
*wnd
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
380 GtkWidget
* widget
= widget_new(NULL
);
381 gtk_container_add(GTK_CONTAINER(wnd
), widget
);
382 attr
= GetDefaultAttributesFromGTKWidget(widget
, useBase
, state
);
383 gtk_widget_destroy(wnd
);
387 // ----------------------------------------------------------------------------
389 // ----------------------------------------------------------------------------
391 void wxControl::OnInternalIdle()
393 if ( GtkShowFromOnIdle() )
396 if ( GTK_WIDGET_REALIZED(m_widget
) )
400 GTKSetDelayedFocusIfNeeded();
403 if ( wxUpdateUIEvent::CanUpdate(this) )
404 UpdateWindowUI(wxUPDATE_UI_FROMIDLE
);
407 #endif // wxUSE_CONTROLS