]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/control.cpp
fixed compilation of STL non-UTF8 builds
[wxWidgets.git] / src / gtk / control.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
634fb750
VZ
2// Name: src/gtk/control.cpp
3// Purpose: wxControl implementation for wxGTK
c801d85f 4// Author: Robert Roebling
dbf858b5 5// Id: $Id$
01111366 6// Copyright: (c) 1998 Robert Roebling, Julian Smart and Vadim Zeitlin
65571936 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
14f355c2
VS
10// For compilers that support precompilation, includes "wx.h".
11#include "wx/wxprec.h"
12
1e6feb95
VZ
13#if wxUSE_CONTROLS
14
c801d85f 15#include "wx/control.h"
e4db172a
WS
16
17#ifndef WX_PRECOMP
18 #include "wx/log.h"
9eddec69 19 #include "wx/settings.h"
e4db172a
WS
20#endif
21
9d522606 22#include "wx/fontutil.h"
b2ff89d6 23#include "wx/gtk/private.h"
034be888 24
39bc0347
VZ
25#include "wx/private/stattext.h"
26
27
634fb750
VZ
28// ============================================================================
29// wxControl implementation
30// ============================================================================
31
32// ----------------------------------------------------------------------------
33// wxControl creation
34// ----------------------------------------------------------------------------
c801d85f 35
9abe166a 36IMPLEMENT_DYNAMIC_CLASS(wxControl, wxWindow)
c801d85f 37
31528cd3 38wxControl::wxControl()
c801d85f 39{
9eddec69 40 m_needParent = true;
6de97a3b 41}
c801d85f 42
04165bec 43bool wxControl::Create( wxWindow *parent,
31528cd3
VZ
44 wxWindowID id,
45 const wxPoint &pos,
46 const wxSize &size,
47 long style,
8d772832 48 const wxValidator& validator,
04165bec 49 const wxString &name )
8d772832 50{
04165bec 51 bool ret = wxWindow::Create(parent, id, pos, size, style, name);
b2ff89d6 52
04165bec 53#if wxUSE_VALIDATORS
8d772832 54 SetValidator(validator);
8d772832
RD
55#endif
56
04165bec
RR
57 return ret;
58}
59
f68586e5
VZ
60wxSize wxControl::DoGetBestSize() const
61{
0279e844
RR
62 // Do not return any arbitrary default value...
63 wxASSERT_MSG( m_widget, wxT("DoGetBestSize called before creation") );
64
f68586e5 65 GtkRequisition req;
33720b2d
RR
66 req.width = 2;
67 req.height = 2;
2afa14f2 68 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(m_widget) )->size_request )
f68586e5
VZ
69 (m_widget, &req );
70
9f884528
RD
71 wxSize best(req.width, req.height);
72 CacheBestSize(best);
73 return best;
f68586e5
VZ
74}
75
abdeb9e7
RD
76void wxControl::PostCreation(const wxSize& size)
77{
78 wxWindow::PostCreation();
f40fdaa3
VS
79
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);
b2ff89d6 86
abdeb9e7 87 ApplyWidgetStyle();
170acdc9 88 SetInitialSize(size);
abdeb9e7
RD
89}
90
b2ff89d6
VZ
91// ----------------------------------------------------------------------------
92// wxControl dealing with labels
93// ----------------------------------------------------------------------------
94
39bc0347 95void wxControl::GTKSetLabelForLabel(GtkLabel *w, const wxString& label)
b2ff89d6 96{
39bc0347
VZ
97 // save the original label
98 wxControlBase::SetLabel(label);
b2ff89d6 99
39bc0347
VZ
100 const wxString labelGTK = GTKConvertMnemonics(label);
101 gtk_label_set_text_with_mnemonic(w, wxGTK_CONV(labelGTK));
b2ff89d6
VZ
102}
103
39bc0347 104void wxControl::GTKSetLabelWithMarkupForLabel(GtkLabel *w, const wxString& label)
b2ff89d6 105{
39bc0347
VZ
106 const wxString labelGTK = GTKConvertMnemonicsWithMarkup(label);
107 gtk_label_set_markup_with_mnemonic(w, wxGTK_CONV(labelGTK));
b2ff89d6
VZ
108}
109
b2ff89d6 110
2e1f5012
VZ
111// ----------------------------------------------------------------------------
112// GtkFrame helpers
113//
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// ----------------------------------------------------------------------------
118
119GtkWidget* wxControl::GTKCreateFrame(const wxString& label)
120{
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...
124
125 GtkWidget* framewidget = gtk_frame_new(NULL);
126 gtk_frame_set_label_widget(GTK_FRAME(framewidget), labelwidget);
127
39bc0347
VZ
128 return framewidget; // note that the label is already set so you'll
129 // only need to call wxControl::SetLabel afterwards
2e1f5012
VZ
130}
131
b2ff89d6
VZ
132void wxControl::GTKSetLabelForFrame(GtkFrame *w, const wxString& label)
133{
2e1f5012
VZ
134 GtkLabel* labelwidget = GTK_LABEL(gtk_frame_get_label_widget(w));
135 GTKSetLabelForLabel(labelwidget, label);
136}
137
138void wxControl::GTKFrameApplyWidgetStyle(GtkFrame* w, GtkRcStyle* style)
139{
140 gtk_widget_modify_style(GTK_WIDGET(w), style);
141 gtk_widget_modify_style(gtk_frame_get_label_widget (w), style);
142}
b2ff89d6 143
2e1f5012
VZ
144void wxControl::GTKFrameSetMnemonicWidget(GtkFrame* w, GtkWidget* widget)
145{
146 GtkLabel* labelwidget = GTK_LABEL(gtk_frame_get_label_widget(w));
b2ff89d6 147
2e1f5012 148 gtk_label_set_mnemonic_widget(labelwidget, widget);
b2ff89d6
VZ
149}
150
2e1f5012 151// ----------------------------------------------------------------------------
39bc0347 152// worker function implementing GTK*Mnemonics() functions
2e1f5012
VZ
153// ----------------------------------------------------------------------------
154
b2ff89d6 155enum MnemonicsFlag
eaafd2f8 156{
b2ff89d6 157 MNEMONICS_REMOVE,
39bc0347
VZ
158 MNEMONICS_CONVERT,
159 MNEMONICS_CONVERT_MARKUP
b2ff89d6
VZ
160};
161
39bc0347 162static wxString GTKProcessMnemonics(const wxChar* label, MnemonicsFlag flag)
b2ff89d6 163{
39bc0347 164 const size_t len = wxStrlen(label);
b2ff89d6
VZ
165 wxString labelGTK;
166 labelGTK.reserve(len);
167 for ( size_t i = 0; i < len; i++ )
eaafd2f8 168 {
b2ff89d6
VZ
169 wxChar ch = label[i];
170
171 switch ( ch )
eaafd2f8 172 {
b2ff89d6
VZ
173 case wxT('&'):
174 if ( i == len - 1 )
175 {
176 // "&" at the end of string is an error
39bc0347 177 wxLogDebug(wxT("Invalid label \"%s\"."), label);
b2ff89d6
VZ
178 break;
179 }
180
39bc0347
VZ
181 if ( flag == MNEMONICS_CONVERT_MARKUP )
182 {
183 bool isMnemonic = true;
184
185 // is this ampersand introducing a mnemonic or rather an entity?
186 for (size_t j=0; j < wxMARKUP_ENTITY_MAX; j++)
187 {
188 const wxChar *entity = wxMarkupEntities[wxMARKUP_ELEMENT_NAME][j];
189 size_t entityLen = wxStrlen(entity);
190
191 if (len - i >= entityLen &&
192 wxStrncmp(entity, &label[i], entityLen) == 0)
193 {
194 labelGTK << entity;
195 i += entityLen - 1; // the -1 is because main for()
196 // loop already increments i
197 isMnemonic = false;
198
199 break;
200 }
201 }
202
203 if (!isMnemonic)
204 continue;
205 }
206
b2ff89d6
VZ
207 ch = label[++i]; // skip '&' itself
208 switch ( ch )
209 {
210 case wxT('&'):
211 // special case: "&&" is not a mnemonic at all but just
212 // an escaped "&"
39bc0347
VZ
213 if ( flag == MNEMONICS_CONVERT_MARKUP )
214 labelGTK += wxT("&amp;");
215 else
216 labelGTK += wxT('&');
b2ff89d6
VZ
217 break;
218
219 case wxT('_'):
39bc0347 220 if ( flag != MNEMONICS_REMOVE )
b2ff89d6
VZ
221 {
222 // '_' can't be a GTK mnemonic apparently so
223 // replace it with something similar
224 labelGTK += wxT("_-");
225 break;
226 }
227 //else: fall through
228
229 default:
39bc0347 230 if ( flag != MNEMONICS_REMOVE )
b2ff89d6
VZ
231 labelGTK += wxT('_');
232 labelGTK += ch;
233 }
234 break;
235
236 case wxT('_'):
39bc0347 237 if ( flag != MNEMONICS_REMOVE )
b2ff89d6
VZ
238 {
239 // escape any existing underlines in the string so that
240 // they don't become mnemonics accidentally
241 labelGTK += wxT("__");
242 break;
243 }
244 //else: fall through
245
246 default:
247 labelGTK += ch;
eaafd2f8
VS
248 }
249 }
b2ff89d6
VZ
250
251 return labelGTK;
252}
253
254/* static */
255wxString wxControl::GTKRemoveMnemonics(const wxString& label)
256{
257 return GTKProcessMnemonics(label, MNEMONICS_REMOVE);
258}
259
260/* static */
261wxString wxControl::GTKConvertMnemonics(const wxString& label)
262{
263 return GTKProcessMnemonics(label, MNEMONICS_CONVERT);
eaafd2f8
VS
264}
265
39bc0347
VZ
266/* static */
267wxString wxControl::GTKConvertMnemonicsWithMarkup(const wxString& label)
268{
269 return GTKProcessMnemonics(label, MNEMONICS_CONVERT_MARKUP);
270}
271
b2ff89d6
VZ
272// ----------------------------------------------------------------------------
273// wxControl styles (a.k.a. attributes)
274// ----------------------------------------------------------------------------
9d522606
RD
275
276wxVisualAttributes wxControl::GetDefaultAttributes() const
277{
278 return GetDefaultAttributesFromGTKWidget(m_widget,
279 UseGTKStyleBase());
280}
281
9d522606
RD
282// static
283wxVisualAttributes
284wxControl::GetDefaultAttributesFromGTKWidget(GtkWidget* widget,
285 bool useBase,
286 int state)
287{
288 GtkStyle* style;
289 wxVisualAttributes attr;
290
291 style = gtk_rc_get_style(widget);
292 if (!style)
293 style = gtk_widget_get_default_style();
294
295 if (!style)
296 {
297 return wxWindow::GetClassDefaultAttributes(wxWINDOW_VARIANT_NORMAL);
298 }
299
300 if (state == -1)
301 state = GTK_STATE_NORMAL;
b2ff89d6 302
9d522606 303 // get the style's colours
cdf068a4 304 attr.colFg = wxColour(style->fg[state]);
9d522606 305 if (useBase)
cdf068a4 306 attr.colBg = wxColour(style->base[state]);
9d522606 307 else
cdf068a4 308 attr.colBg = wxColour(style->bg[state]);
9d522606
RD
309
310 // get the style's font
9d522606 311 if ( !style->font_desc )
b2ff89d6 312 style = gtk_widget_get_default_style();
9d522606 313 if ( style && style->font_desc )
b2ff89d6
VZ
314 {
315 wxNativeFontInfo info;
fdf7514a 316 info.description = pango_font_description_copy(style->font_desc);
b2ff89d6
VZ
317 attr.font = wxFont(info);
318 }
319 else
320 {
9d522606
RD
321 GtkSettings *settings = gtk_settings_get_default();
322 gchar *font_name = NULL;
323 g_object_get ( settings,
b2ff89d6 324 "gtk-font-name",
9d522606
RD
325 &font_name,
326 NULL);
327 if (!font_name)
328 attr.font = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
329 else
330 attr.font = wxFont(wxString::FromAscii(font_name));
331 g_free (font_name);
b2ff89d6 332 }
b2ff89d6 333
9d522606
RD
334 return attr;
335}
336
337
338//static
339wxVisualAttributes
865bb325 340wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNew_t widget_new,
9d522606
RD
341 bool useBase,
342 int state)
343{
344 wxVisualAttributes attr;
66d8fe77
VS
345 // NB: we need toplevel window so that GTK+ can find the right style
346 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
9d522606 347 GtkWidget* widget = widget_new();
66d8fe77 348 gtk_container_add(GTK_CONTAINER(wnd), widget);
9d522606 349 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
66d8fe77 350 gtk_widget_destroy(wnd);
9d522606
RD
351 return attr;
352}
353
354//static
355wxVisualAttributes
865bb325 356wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromStr_t widget_new,
9d522606
RD
357 bool useBase,
358 int state)
359{
360 wxVisualAttributes attr;
66d8fe77
VS
361 // NB: we need toplevel window so that GTK+ can find the right style
362 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
9d522606 363 GtkWidget* widget = widget_new("");
66d8fe77 364 gtk_container_add(GTK_CONTAINER(wnd), widget);
9d522606 365 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
66d8fe77 366 gtk_widget_destroy(wnd);
9d522606
RD
367 return attr;
368}
369
370
371//static
372wxVisualAttributes
865bb325 373wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromAdj_t widget_new,
9d522606
RD
374 bool useBase,
375 int state)
376{
377 wxVisualAttributes attr;
66d8fe77
VS
378 // NB: we need toplevel window so that GTK+ can find the right style
379 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
9d522606 380 GtkWidget* widget = widget_new(NULL);
66d8fe77 381 gtk_container_add(GTK_CONTAINER(wnd), widget);
9d522606 382 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
66d8fe77 383 gtk_widget_destroy(wnd);
9d522606
RD
384 return attr;
385}
386
ef5c70f9
VZ
387// ----------------------------------------------------------------------------
388// idle handling
389// ----------------------------------------------------------------------------
390
391void wxControl::OnInternalIdle()
392{
393 if ( GtkShowFromOnIdle() )
394 return;
ef5c70f9 395
1f5cf9cc 396 if ( GTK_WIDGET_REALIZED(m_widget) )
6c6a3e8a
VZ
397 {
398 GTKUpdateCursor();
399
400 GTKSetDelayedFocusIfNeeded();
401 }
06a7419e 402
ef5c70f9
VZ
403 if ( wxUpdateUIEvent::CanUpdate(this) )
404 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
405}
406
1e6feb95 407#endif // wxUSE_CONTROLS