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