1. changed wxControl::GetLabel() to return the originally provided label and
[wxWidgets.git] / src / gtk / control.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: control.cpp
3 // Purpose:
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 #include "wx/defs.h"
14
15 #if wxUSE_CONTROLS
16
17 #include "wx/control.h"
18 #include "wx/fontutil.h"
19 #include "wx/settings.h"
20 #include "wx/gtk/private.h"
21
22 //-----------------------------------------------------------------------------
23 // wxControl
24 //-----------------------------------------------------------------------------
25
26 IMPLEMENT_DYNAMIC_CLASS(wxControl, wxWindow)
27
28 wxControl::wxControl()
29 {
30 m_needParent = TRUE;
31 }
32
33 bool wxControl::Create( wxWindow *parent,
34 wxWindowID id,
35 const wxPoint &pos,
36 const wxSize &size,
37 long style,
38 const wxValidator& validator,
39 const wxString &name )
40 {
41 bool ret = wxWindow::Create(parent, id, pos, size, style, name);
42
43 #if wxUSE_VALIDATORS
44 SetValidator(validator);
45 #endif
46
47 return ret;
48 }
49
50 wxSize wxControl::DoGetBestSize() const
51 {
52 // Do not return any arbitrary default value...
53 wxASSERT_MSG( m_widget, wxT("DoGetBestSize called before creation") );
54
55 GtkRequisition req;
56 req.width = 2;
57 req.height = 2;
58 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(m_widget) )->size_request )
59 (m_widget, &req );
60
61 wxSize best(req.width, req.height);
62 CacheBestSize(best);
63 return best;
64 }
65
66
67 void wxControl::PostCreation(const wxSize& size)
68 {
69 wxWindow::PostCreation();
70
71 // NB: GetBestSize needs to know the style, otherwise it will assume
72 // default font and if the user uses a different font, determined
73 // best size will be different (typically, smaller) than the desired
74 // size. This call ensure that a style is available at the time
75 // GetBestSize is called.
76 gtk_widget_ensure_style(m_widget);
77
78 ApplyWidgetStyle();
79 SetInitialBestSize(size);
80 }
81
82 // ----------------------------------------------------------------------------
83 // wxControl dealing with labels
84 // ----------------------------------------------------------------------------
85
86 void wxControl::SetLabel( const wxString &label )
87 {
88 // keep the original string internally to be able to return it later (for
89 // consistency with the other ports)
90 m_label = label;
91
92 InvalidateBestSize();
93 }
94
95 wxString wxControl::GetLabel() const
96 {
97 return m_label;
98 }
99
100 void wxControl::GTKSetLabelForLabel(GtkLabel *w, const wxString& label)
101 {
102 // don't call the virtual function which might call this one back again
103 wxControl::SetLabel(label);
104
105 const wxString labelGTK = GTKConvertMnemonics(label);
106
107 #ifdef __WXGTK20__
108 gtk_label_set_text_with_mnemonic(w, wxGTK_CONV(labelGTK));
109 #else
110 gtk_label_set(w, wxGTK_CONV(labelGTK));
111 #endif
112 }
113
114 void wxControl::GTKSetLabelForFrame(GtkFrame *w, const wxString& label)
115 {
116 wxControl::SetLabel(label);
117
118 // frames don't support mnemonics even under GTK+ 2
119 const wxString labelGTK = GTKRemoveMnemonics(label);
120
121 gtk_frame_set_label(w, labelGTK.empty() ? (char *)NULL
122 : wxGTK_CONV(labelGTK));
123 }
124
125 // worker function implementing both GTKConvert/RemoveMnemonics()
126 //
127 // notice that under GTK+ 1 we only really need to support MNEMONICS_REMOVE as
128 // it doesn't support mnemonics anyhow but this would make the code so ugly
129 // that we do the same thing for GKT+ 1 and 2
130 enum MnemonicsFlag
131 {
132 MNEMONICS_REMOVE,
133 MNEMONICS_CONVERT
134 };
135
136 static wxString GTKProcessMnemonics(const wxString& label, MnemonicsFlag flag)
137 {
138 const size_t len = label.length();
139 wxString labelGTK;
140 labelGTK.reserve(len);
141 for ( size_t i = 0; i < len; i++ )
142 {
143 wxChar ch = label[i];
144
145 switch ( ch )
146 {
147 case wxT('&'):
148 if ( i == len - 1 )
149 {
150 // "&" at the end of string is an error
151 wxLogDebug(wxT("Invalid label \"%s\"."), label.c_str());
152 break;
153 }
154
155 ch = label[++i]; // skip '&' itself
156 switch ( ch )
157 {
158 case wxT('&'):
159 // special case: "&&" is not a mnemonic at all but just
160 // an escaped "&"
161 labelGTK += wxT('&');
162 break;
163
164 case wxT('_'):
165 if ( flag == MNEMONICS_CONVERT )
166 {
167 // '_' can't be a GTK mnemonic apparently so
168 // replace it with something similar
169 labelGTK += wxT("_-");
170 break;
171 }
172 //else: fall through
173
174 default:
175 if ( flag == MNEMONICS_CONVERT )
176 labelGTK += wxT('_');
177 labelGTK += ch;
178 }
179 break;
180
181 case wxT('_'):
182 if ( flag == MNEMONICS_CONVERT )
183 {
184 // escape any existing underlines in the string so that
185 // they don't become mnemonics accidentally
186 labelGTK += wxT("__");
187 break;
188 }
189 //else: fall through
190
191 default:
192 labelGTK += ch;
193 }
194 }
195
196 return labelGTK;
197 }
198
199 /* static */
200 wxString wxControl::GTKRemoveMnemonics(const wxString& label)
201 {
202 return GTKProcessMnemonics(label, MNEMONICS_REMOVE);
203 }
204
205 /* static */
206 wxString wxControl::GTKConvertMnemonics(const wxString& label)
207 {
208 return GTKProcessMnemonics(label, MNEMONICS_CONVERT);
209 }
210
211 // ----------------------------------------------------------------------------
212 // wxControl styles (a.k.a. attributes)
213 // ----------------------------------------------------------------------------
214
215 wxVisualAttributes wxControl::GetDefaultAttributes() const
216 {
217 return GetDefaultAttributesFromGTKWidget(m_widget,
218 UseGTKStyleBase());
219 }
220
221
222 #define SHIFT (8*(sizeof(short int)-sizeof(char)))
223
224 // static
225 wxVisualAttributes
226 wxControl::GetDefaultAttributesFromGTKWidget(GtkWidget* widget,
227 bool useBase,
228 int state)
229 {
230 GtkStyle* style;
231 wxVisualAttributes attr;
232
233 style = gtk_rc_get_style(widget);
234 if (!style)
235 style = gtk_widget_get_default_style();
236
237 if (!style)
238 {
239 return wxWindow::GetClassDefaultAttributes(wxWINDOW_VARIANT_NORMAL);
240 }
241
242 if (state == -1)
243 state = GTK_STATE_NORMAL;
244
245 // get the style's colours
246 attr.colFg = wxColour(style->fg[state].red >> SHIFT,
247 style->fg[state].green >> SHIFT,
248 style->fg[state].blue >> SHIFT);
249 if (useBase)
250 attr.colBg = wxColour(style->base[state].red >> SHIFT,
251 style->base[state].green >> SHIFT,
252 style->base[state].blue >> SHIFT);
253 else
254 attr.colBg = wxColour(style->bg[state].red >> SHIFT,
255 style->bg[state].green >> SHIFT,
256 style->bg[state].blue >> SHIFT);
257
258 // get the style's font
259 #ifdef __WXGTK20__
260 if ( !style->font_desc )
261 style = gtk_widget_get_default_style();
262 if ( style && style->font_desc )
263 {
264 wxNativeFontInfo info;
265 info.description = pango_font_description_copy(style->font_desc);
266 attr.font = wxFont(info);
267 }
268 else
269 {
270 GtkSettings *settings = gtk_settings_get_default();
271 gchar *font_name = NULL;
272 g_object_get ( settings,
273 "gtk-font-name",
274 &font_name,
275 NULL);
276 if (!font_name)
277 attr.font = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
278 else
279 attr.font = wxFont(wxString::FromAscii(font_name));
280 g_free (font_name);
281 }
282 #else
283 // TODO: isn't there a way to get a standard gtk 1.2 font?
284 attr.font = wxFont( 12, wxSWISS, wxNORMAL, wxNORMAL );
285 #endif
286
287 return attr;
288 }
289
290
291 //static
292 wxVisualAttributes
293 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNew_t widget_new,
294 bool useBase,
295 int state)
296 {
297 wxVisualAttributes attr;
298 // NB: we need toplevel window so that GTK+ can find the right style
299 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
300 GtkWidget* widget = widget_new();
301 gtk_container_add(GTK_CONTAINER(wnd), widget);
302 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
303 gtk_widget_destroy(wnd);
304 return attr;
305 }
306
307 //static
308 wxVisualAttributes
309 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromStr_t widget_new,
310 bool useBase,
311 int state)
312 {
313 wxVisualAttributes attr;
314 // NB: we need toplevel window so that GTK+ can find the right style
315 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
316 GtkWidget* widget = widget_new("");
317 gtk_container_add(GTK_CONTAINER(wnd), widget);
318 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
319 gtk_widget_destroy(wnd);
320 return attr;
321 }
322
323
324 //static
325 wxVisualAttributes
326 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromAdj_t widget_new,
327 bool useBase,
328 int state)
329 {
330 wxVisualAttributes attr;
331 // NB: we need toplevel window so that GTK+ can find the right style
332 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
333 GtkWidget* widget = widget_new(NULL);
334 gtk_container_add(GTK_CONTAINER(wnd), widget);
335 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
336 gtk_widget_destroy(wnd);
337 return attr;
338 }
339
340 #endif // wxUSE_CONTROLS
341