Don't call base class SetLabel() from GTKSetLabelForLabel().
[wxWidgets.git] / src / gtk / control.cpp
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 #include "wx/utils.h"
25 #include "wx/sysopt.h"
26
27 #include "wx/gtk/private/mnemonics.h"
28
29 // ============================================================================
30 // wxControl implementation
31 // ============================================================================
32
33 // ----------------------------------------------------------------------------
34 // wxControl creation
35 // ----------------------------------------------------------------------------
36
37 IMPLEMENT_DYNAMIC_CLASS(wxControl, wxWindow)
38
39 wxControl::wxControl()
40 {
41 }
42
43 bool wxControl::Create( wxWindow *parent,
44 wxWindowID id,
45 const wxPoint &pos,
46 const wxSize &size,
47 long style,
48 const wxValidator& validator,
49 const wxString &name )
50 {
51 bool ret = wxWindow::Create(parent, id, pos, size, style, name);
52
53 #if wxUSE_VALIDATORS
54 SetValidator(validator);
55 #endif
56
57 return ret;
58 }
59
60 wxSize wxControl::DoGetBestSize() const
61 {
62 // Do not return any arbitrary default value...
63 wxASSERT_MSG( m_widget, wxT("DoGetBestSize called before creation") );
64
65 wxSize best;
66 if (m_wxwindow)
67 {
68 // this is not a native control, size_request is likely to be (0,0)
69 best = wxControlBase::DoGetBestSize();
70 }
71 else
72 {
73 GtkRequisition req;
74 GTK_WIDGET_GET_CLASS(m_widget)->size_request(m_widget, &req);
75 best.Set(req.width, req.height);
76 }
77 CacheBestSize(best);
78 return best;
79 }
80
81 void wxControl::PostCreation(const wxSize& size)
82 {
83 wxWindow::PostCreation();
84
85 // NB: GetBestSize needs to know the style, otherwise it will assume
86 // default font and if the user uses a different font, determined
87 // best size will be different (typically, smaller) than the desired
88 // size. This call ensure that a style is available at the time
89 // GetBestSize is called.
90 gtk_widget_ensure_style(m_widget);
91
92 GTKApplyWidgetStyle();
93 SetInitialSize(size);
94 }
95
96 // ----------------------------------------------------------------------------
97 // Work around a GTK+ bug whereby button is insensitive after being
98 // enabled
99 // ----------------------------------------------------------------------------
100
101 // Fix sensitivity due to bug in GTK+ < 2.14
102 void wxControl::GTKFixSensitivity(bool onlyIfUnderMouse)
103 {
104 if (gtk_check_version(2,14,0)
105 #if wxUSE_SYSTEM_OPTIONS
106 && (wxSystemOptions::GetOptionInt(wxT("gtk.control.disable-sensitivity-fix")) != 1)
107 #endif
108 )
109 {
110 wxPoint pt = wxGetMousePosition();
111 wxRect rect(ClientToScreen(wxPoint(0, 0)), GetSize());
112 if (!onlyIfUnderMouse || rect.Contains(pt))
113 {
114 Hide();
115 Show();
116 }
117 }
118 }
119
120 // ----------------------------------------------------------------------------
121 // wxControl dealing with labels
122 // ----------------------------------------------------------------------------
123
124 void wxControl::GTKSetLabelForLabel(GtkLabel *w, const wxString& label)
125 {
126 const wxString labelGTK = GTKConvertMnemonics(label);
127 gtk_label_set_text_with_mnemonic(w, wxGTK_CONV(labelGTK));
128 }
129
130 void wxControl::GTKSetLabelWithMarkupForLabel(GtkLabel *w, const wxString& label)
131 {
132 const wxString labelGTK = GTKConvertMnemonicsWithMarkup(label);
133 gtk_label_set_markup_with_mnemonic(w, wxGTK_CONV(labelGTK));
134 }
135
136
137 // ----------------------------------------------------------------------------
138 // GtkFrame helpers
139 //
140 // GtkFrames do in fact support mnemonics in GTK2+ but not through
141 // gtk_frame_set_label, rather you need to use a custom label widget
142 // instead (idea gleaned from the native gtk font dialog code in GTK)
143 // ----------------------------------------------------------------------------
144
145 GtkWidget* wxControl::GTKCreateFrame(const wxString& label)
146 {
147 const wxString labelGTK = GTKConvertMnemonics(label);
148 GtkWidget* labelwidget = gtk_label_new_with_mnemonic(wxGTK_CONV(labelGTK));
149 gtk_widget_show(labelwidget); // without this it won't show...
150
151 GtkWidget* framewidget = gtk_frame_new(NULL);
152 gtk_frame_set_label_widget(GTK_FRAME(framewidget), labelwidget);
153
154 return framewidget; // note that the label is already set so you'll
155 // only need to call wxControl::SetLabel afterwards
156 }
157
158 void wxControl::GTKSetLabelForFrame(GtkFrame *w, const wxString& label)
159 {
160 wxControlBase::SetLabel(label);
161
162 GtkLabel* labelwidget = GTK_LABEL(gtk_frame_get_label_widget(w));
163 GTKSetLabelForLabel(labelwidget, label);
164 }
165
166 void wxControl::GTKFrameApplyWidgetStyle(GtkFrame* w, GtkRcStyle* style)
167 {
168 gtk_widget_modify_style(GTK_WIDGET(w), style);
169 gtk_widget_modify_style(gtk_frame_get_label_widget (w), style);
170 }
171
172 void wxControl::GTKFrameSetMnemonicWidget(GtkFrame* w, GtkWidget* widget)
173 {
174 GtkLabel* labelwidget = GTK_LABEL(gtk_frame_get_label_widget(w));
175
176 gtk_label_set_mnemonic_widget(labelwidget, widget);
177 }
178
179 // ----------------------------------------------------------------------------
180 // worker function implementing GTK*Mnemonics() functions
181 // ----------------------------------------------------------------------------
182
183 /* static */
184 wxString wxControl::GTKRemoveMnemonics(const wxString& label)
185 {
186 return wxGTKRemoveMnemonics(label);
187 }
188
189 /* static */
190 wxString wxControl::GTKConvertMnemonics(const wxString& label)
191 {
192 return wxConvertMnemonicsToGTK(label);
193 }
194
195 /* static */
196 wxString wxControl::GTKConvertMnemonicsWithMarkup(const wxString& label)
197 {
198 return wxConvertMnemonicsToGTKMarkup(label);
199 }
200
201 // ----------------------------------------------------------------------------
202 // wxControl styles (a.k.a. attributes)
203 // ----------------------------------------------------------------------------
204
205 wxVisualAttributes wxControl::GetDefaultAttributes() const
206 {
207 return GetDefaultAttributesFromGTKWidget(m_widget,
208 UseGTKStyleBase());
209 }
210
211 // static
212 wxVisualAttributes
213 wxControl::GetDefaultAttributesFromGTKWidget(GtkWidget* widget,
214 bool useBase,
215 int state)
216 {
217 GtkStyle* style;
218 wxVisualAttributes attr;
219
220 style = gtk_rc_get_style(widget);
221 if (!style)
222 style = gtk_widget_get_default_style();
223
224 if (!style)
225 {
226 return wxWindow::GetClassDefaultAttributes(wxWINDOW_VARIANT_NORMAL);
227 }
228
229 if (state == -1)
230 state = GTK_STATE_NORMAL;
231
232 // get the style's colours
233 attr.colFg = wxColour(style->fg[state]);
234 if (useBase)
235 attr.colBg = wxColour(style->base[state]);
236 else
237 attr.colBg = wxColour(style->bg[state]);
238
239 // get the style's font
240 if ( !style->font_desc )
241 style = gtk_widget_get_default_style();
242 if ( style && style->font_desc )
243 {
244 wxNativeFontInfo info;
245 info.description = pango_font_description_copy(style->font_desc);
246 attr.font = wxFont(info);
247 }
248 else
249 {
250 GtkSettings *settings = gtk_settings_get_default();
251 gchar *font_name = NULL;
252 g_object_get ( settings,
253 "gtk-font-name",
254 &font_name,
255 NULL);
256 if (!font_name)
257 attr.font = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
258 else
259 attr.font = wxFont(wxString::FromAscii(font_name));
260 g_free (font_name);
261 }
262
263 return attr;
264 }
265
266
267 //static
268 wxVisualAttributes
269 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNew_t widget_new,
270 bool useBase,
271 int state)
272 {
273 wxVisualAttributes attr;
274 // NB: we need toplevel window so that GTK+ can find the right style
275 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
276 GtkWidget* widget = widget_new();
277 gtk_container_add(GTK_CONTAINER(wnd), widget);
278 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
279 gtk_widget_destroy(wnd);
280 return attr;
281 }
282
283 //static
284 wxVisualAttributes
285 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromStr_t widget_new,
286 bool useBase,
287 int state)
288 {
289 wxVisualAttributes attr;
290 // NB: we need toplevel window so that GTK+ can find the right style
291 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
292 GtkWidget* widget = widget_new("");
293 gtk_container_add(GTK_CONTAINER(wnd), widget);
294 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
295 gtk_widget_destroy(wnd);
296 return attr;
297 }
298
299
300 //static
301 wxVisualAttributes
302 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromAdj_t widget_new,
303 bool useBase,
304 int state)
305 {
306 wxVisualAttributes attr;
307 // NB: we need toplevel window so that GTK+ can find the right style
308 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
309 GtkWidget* widget = widget_new(NULL);
310 gtk_container_add(GTK_CONTAINER(wnd), widget);
311 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
312 gtk_widget_destroy(wnd);
313 return attr;
314 }
315
316 #endif // wxUSE_CONTROLS