]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/gtk/control.cpp
[ 1509599 ] 'Split pickers page in widgets sample' with more icons and rebaking.
[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 SetInitialBestSize(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
256#define SHIFT (8*(sizeof(short int)-sizeof(char)))
257
258// static
259wxVisualAttributes
260wxControl::GetDefaultAttributesFromGTKWidget(GtkWidget* widget,
261 bool useBase,
262 int state)
263{
264 GtkStyle* style;
265 wxVisualAttributes attr;
266
267 style = gtk_rc_get_style(widget);
268 if (!style)
269 style = gtk_widget_get_default_style();
270
271 if (!style)
272 {
273 return wxWindow::GetClassDefaultAttributes(wxWINDOW_VARIANT_NORMAL);
274 }
275
276 if (state == -1)
277 state = GTK_STATE_NORMAL;
278
279 // get the style's colours
280 attr.colFg = wxColour(style->fg[state].red >> SHIFT,
281 style->fg[state].green >> SHIFT,
282 style->fg[state].blue >> SHIFT);
283 if (useBase)
284 attr.colBg = wxColour(style->base[state].red >> SHIFT,
285 style->base[state].green >> SHIFT,
286 style->base[state].blue >> SHIFT);
287 else
288 attr.colBg = wxColour(style->bg[state].red >> SHIFT,
289 style->bg[state].green >> SHIFT,
290 style->bg[state].blue >> SHIFT);
291
292 // get the style's font
293 if ( !style->font_desc )
294 style = gtk_widget_get_default_style();
295 if ( style && style->font_desc )
296 {
297 wxNativeFontInfo info;
298 info.description = pango_font_description_copy(style->font_desc);
299 attr.font = wxFont(info);
300 }
301 else
302 {
303 GtkSettings *settings = gtk_settings_get_default();
304 gchar *font_name = NULL;
305 g_object_get ( settings,
306 "gtk-font-name",
307 &font_name,
308 NULL);
309 if (!font_name)
310 attr.font = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
311 else
312 attr.font = wxFont(wxString::FromAscii(font_name));
313 g_free (font_name);
314 }
315
316 return attr;
317}
318
319
320//static
321wxVisualAttributes
322wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNew_t widget_new,
323 bool useBase,
324 int state)
325{
326 wxVisualAttributes attr;
327 // NB: we need toplevel window so that GTK+ can find the right style
328 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
329 GtkWidget* widget = widget_new();
330 gtk_container_add(GTK_CONTAINER(wnd), widget);
331 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
332 gtk_widget_destroy(wnd);
333 return attr;
334}
335
336//static
337wxVisualAttributes
338wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromStr_t widget_new,
339 bool useBase,
340 int state)
341{
342 wxVisualAttributes attr;
343 // NB: we need toplevel window so that GTK+ can find the right style
344 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
345 GtkWidget* widget = widget_new("");
346 gtk_container_add(GTK_CONTAINER(wnd), widget);
347 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
348 gtk_widget_destroy(wnd);
349 return attr;
350}
351
352
353//static
354wxVisualAttributes
355wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromAdj_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(NULL);
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#endif // wxUSE_CONTROLS