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