]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/control.cpp
Fix crash in wxDC::GetMultiLineTextExtent() after last commit.
[wxWidgets.git] / src / gtk / control.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
634fb750
VZ
2// Name: src/gtk/control.cpp
3// Purpose: wxControl implementation for wxGTK
c801d85f 4// Author: Robert Roebling
dbf858b5 5// Id: $Id$
01111366 6// Copyright: (c) 1998 Robert Roebling, Julian Smart and Vadim Zeitlin
65571936 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
14f355c2
VS
10// For compilers that support precompilation, includes "wx.h".
11#include "wx/wxprec.h"
12
1e6feb95
VZ
13#if wxUSE_CONTROLS
14
c801d85f 15#include "wx/control.h"
e4db172a
WS
16
17#ifndef WX_PRECOMP
18 #include "wx/log.h"
9eddec69 19 #include "wx/settings.h"
e4db172a
WS
20#endif
21
9d522606 22#include "wx/fontutil.h"
ad60f9e7
JS
23#include "wx/utils.h"
24#include "wx/sysopt.h"
034be888 25
9dc44eff
PC
26#include <gtk/gtk.h>
27#include "wx/gtk/private.h"
b1f17bf0 28#include "wx/gtk/private/mnemonics.h"
39bc0347 29
634fb750
VZ
30// ============================================================================
31// wxControl implementation
32// ============================================================================
33
34// ----------------------------------------------------------------------------
35// wxControl creation
36// ----------------------------------------------------------------------------
c801d85f 37
9abe166a 38IMPLEMENT_DYNAMIC_CLASS(wxControl, wxWindow)
c801d85f 39
31528cd3 40wxControl::wxControl()
c801d85f 41{
6de97a3b 42}
c801d85f 43
04165bec 44bool wxControl::Create( wxWindow *parent,
31528cd3
VZ
45 wxWindowID id,
46 const wxPoint &pos,
47 const wxSize &size,
48 long style,
8d772832 49 const wxValidator& validator,
04165bec 50 const wxString &name )
8d772832 51{
04165bec 52 bool ret = wxWindow::Create(parent, id, pos, size, style, name);
b2ff89d6 53
04165bec 54#if wxUSE_VALIDATORS
8d772832 55 SetValidator(validator);
8d772832
RD
56#endif
57
04165bec
RR
58 return ret;
59}
60
9dc44eff
PC
61#ifdef __WXGTK3__
62bool wxControl::SetFont(const wxFont& font)
63{
64 const bool changed = base_type::SetFont(font);
65 if (changed && !gtk_widget_get_realized(m_widget))
66 {
67 // GTK defers sending "style-updated" until widget is realized, but
68 // GetBestSize() won't compute correct result until the signal is sent,
69 // so we have to do it now
70 g_signal_emit_by_name(m_widget, "style-updated");
71 }
72 return changed;
73}
74#endif
75
f68586e5
VZ
76wxSize wxControl::DoGetBestSize() const
77{
0279e844
RR
78 // Do not return any arbitrary default value...
79 wxASSERT_MSG( m_widget, wxT("DoGetBestSize called before creation") );
80
50bedb7b
PC
81 wxSize best;
82 if (m_wxwindow)
83 {
84 // this is not a native control, size_request is likely to be (0,0)
85 best = wxControlBase::DoGetBestSize();
86 }
87 else
88 {
89 GtkRequisition req;
9dc44eff
PC
90#ifdef __WXGTK3__
91 if (gtk_widget_get_request_mode(m_widget) != GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH)
92 {
93 gtk_widget_get_preferred_height(m_widget, NULL, &req.height);
94 gtk_widget_get_preferred_width_for_height(m_widget, req.height, NULL, &req.width);
95 }
96 else
97 {
98 gtk_widget_get_preferred_width(m_widget, NULL, &req.width);
99 gtk_widget_get_preferred_height_for_width(m_widget, req.width, NULL, &req.height);
100 }
101#else
50bedb7b 102 GTK_WIDGET_GET_CLASS(m_widget)->size_request(m_widget, &req);
9dc44eff 103#endif
50bedb7b
PC
104 best.Set(req.width, req.height);
105 }
9f884528
RD
106 CacheBestSize(best);
107 return best;
f68586e5
VZ
108}
109
abdeb9e7
RD
110void wxControl::PostCreation(const wxSize& size)
111{
112 wxWindow::PostCreation();
f40fdaa3 113
9dc44eff 114#ifndef __WXGTK3__
f40fdaa3
VS
115 // NB: GetBestSize needs to know the style, otherwise it will assume
116 // default font and if the user uses a different font, determined
117 // best size will be different (typically, smaller) than the desired
118 // size. This call ensure that a style is available at the time
119 // GetBestSize is called.
120 gtk_widget_ensure_style(m_widget);
9dc44eff 121#endif
b2ff89d6 122
496e7ec6 123 GTKApplyWidgetStyle();
170acdc9 124 SetInitialSize(size);
abdeb9e7
RD
125}
126
ad60f9e7
JS
127// ----------------------------------------------------------------------------
128// Work around a GTK+ bug whereby button is insensitive after being
129// enabled
130// ----------------------------------------------------------------------------
131
132// Fix sensitivity due to bug in GTK+ < 2.14
9dc44eff 133void wxControl::GTKFixSensitivity(bool WXUNUSED_IN_GTK3(onlyIfUnderMouse))
ad60f9e7 134{
9dc44eff 135#ifndef __WXGTK3__
ad60f9e7
JS
136 if (gtk_check_version(2,14,0)
137#if wxUSE_SYSTEM_OPTIONS
138 && (wxSystemOptions::GetOptionInt(wxT("gtk.control.disable-sensitivity-fix")) != 1)
139#endif
140 )
141 {
8ab75332 142 if (!onlyIfUnderMouse || GetScreenRect().Contains(wxGetMousePosition()))
ad60f9e7
JS
143 {
144 Hide();
145 Show();
146 }
147 }
9dc44eff 148#endif
ad60f9e7
JS
149}
150
b2ff89d6
VZ
151// ----------------------------------------------------------------------------
152// wxControl dealing with labels
153// ----------------------------------------------------------------------------
154
39bc0347 155void wxControl::GTKSetLabelForLabel(GtkLabel *w, const wxString& label)
b2ff89d6 156{
39bc0347
VZ
157 const wxString labelGTK = GTKConvertMnemonics(label);
158 gtk_label_set_text_with_mnemonic(w, wxGTK_CONV(labelGTK));
b2ff89d6
VZ
159}
160
f5bdfc69
VZ
161#if wxUSE_MARKUP
162
39bc0347 163void wxControl::GTKSetLabelWithMarkupForLabel(GtkLabel *w, const wxString& label)
b2ff89d6 164{
39bc0347
VZ
165 const wxString labelGTK = GTKConvertMnemonicsWithMarkup(label);
166 gtk_label_set_markup_with_mnemonic(w, wxGTK_CONV(labelGTK));
b2ff89d6
VZ
167}
168
f5bdfc69 169#endif // wxUSE_MARKUP
b2ff89d6 170
2e1f5012
VZ
171// ----------------------------------------------------------------------------
172// GtkFrame helpers
173//
174// GtkFrames do in fact support mnemonics in GTK2+ but not through
175// gtk_frame_set_label, rather you need to use a custom label widget
176// instead (idea gleaned from the native gtk font dialog code in GTK)
177// ----------------------------------------------------------------------------
178
179GtkWidget* wxControl::GTKCreateFrame(const wxString& label)
180{
181 const wxString labelGTK = GTKConvertMnemonics(label);
182 GtkWidget* labelwidget = gtk_label_new_with_mnemonic(wxGTK_CONV(labelGTK));
183 gtk_widget_show(labelwidget); // without this it won't show...
184
185 GtkWidget* framewidget = gtk_frame_new(NULL);
186 gtk_frame_set_label_widget(GTK_FRAME(framewidget), labelwidget);
187
39bc0347
VZ
188 return framewidget; // note that the label is already set so you'll
189 // only need to call wxControl::SetLabel afterwards
2e1f5012
VZ
190}
191
b2ff89d6
VZ
192void wxControl::GTKSetLabelForFrame(GtkFrame *w, const wxString& label)
193{
6ea2bc50
VZ
194 wxControlBase::SetLabel(label);
195
2e1f5012
VZ
196 GtkLabel* labelwidget = GTK_LABEL(gtk_frame_get_label_widget(w));
197 GTKSetLabelForLabel(labelwidget, label);
198}
199
200void wxControl::GTKFrameApplyWidgetStyle(GtkFrame* w, GtkRcStyle* style)
201{
9dc44eff
PC
202 GTKApplyStyle(GTK_WIDGET(w), style);
203 GTKApplyStyle(gtk_frame_get_label_widget(w), style);
2e1f5012 204}
b2ff89d6 205
2e1f5012
VZ
206void wxControl::GTKFrameSetMnemonicWidget(GtkFrame* w, GtkWidget* widget)
207{
208 GtkLabel* labelwidget = GTK_LABEL(gtk_frame_get_label_widget(w));
b2ff89d6 209
2e1f5012 210 gtk_label_set_mnemonic_widget(labelwidget, widget);
b2ff89d6
VZ
211}
212
2e1f5012 213// ----------------------------------------------------------------------------
39bc0347 214// worker function implementing GTK*Mnemonics() functions
2e1f5012
VZ
215// ----------------------------------------------------------------------------
216
b2ff89d6
VZ
217/* static */
218wxString wxControl::GTKRemoveMnemonics(const wxString& label)
219{
b1f17bf0 220 return wxGTKRemoveMnemonics(label);
b2ff89d6
VZ
221}
222
223/* static */
224wxString wxControl::GTKConvertMnemonics(const wxString& label)
225{
b1f17bf0 226 return wxConvertMnemonicsToGTK(label);
eaafd2f8
VS
227}
228
39bc0347
VZ
229/* static */
230wxString wxControl::GTKConvertMnemonicsWithMarkup(const wxString& label)
231{
b1f17bf0 232 return wxConvertMnemonicsToGTKMarkup(label);
39bc0347
VZ
233}
234
b2ff89d6
VZ
235// ----------------------------------------------------------------------------
236// wxControl styles (a.k.a. attributes)
237// ----------------------------------------------------------------------------
9d522606
RD
238
239wxVisualAttributes wxControl::GetDefaultAttributes() const
240{
241 return GetDefaultAttributesFromGTKWidget(m_widget,
242 UseGTKStyleBase());
243}
244
9d522606
RD
245// static
246wxVisualAttributes
247wxControl::GetDefaultAttributesFromGTKWidget(GtkWidget* widget,
9dc44eff 248 bool WXUNUSED_IN_GTK3(useBase),
9d522606
RD
249 int state)
250{
9d522606 251 wxVisualAttributes attr;
9dc44eff
PC
252#ifdef __WXGTK3__
253 GtkStateFlags stateFlag = GTK_STATE_FLAG_NORMAL;
254 if (state)
255 {
256 wxASSERT(state == GTK_STATE_ACTIVE);
257 stateFlag = GTK_STATE_FLAG_ACTIVE;
258 }
259 GtkStyleContext* sc = gtk_widget_get_style_context(widget);
260 GdkRGBA c;
261 gtk_style_context_get_color(sc, stateFlag, &c);
262 attr.colFg = wxColour(c);
263 gtk_style_context_get_background_color(sc, stateFlag, &c);
264 attr.colBg = wxColour(c);
265 wxNativeFontInfo info;
266 info.description = const_cast<PangoFontDescription*>(gtk_style_context_get_font(sc, stateFlag));
267 attr.font = wxFont(info);
268 info.description = NULL;
269#else
270 GtkStyle* style;
9d522606
RD
271
272 style = gtk_rc_get_style(widget);
273 if (!style)
274 style = gtk_widget_get_default_style();
275
276 if (!style)
277 {
278 return wxWindow::GetClassDefaultAttributes(wxWINDOW_VARIANT_NORMAL);
279 }
280
9d522606 281 // get the style's colours
cdf068a4 282 attr.colFg = wxColour(style->fg[state]);
9d522606 283 if (useBase)
cdf068a4 284 attr.colBg = wxColour(style->base[state]);
9d522606 285 else
cdf068a4 286 attr.colBg = wxColour(style->bg[state]);
9d522606
RD
287
288 // get the style's font
9d522606 289 if ( !style->font_desc )
b2ff89d6 290 style = gtk_widget_get_default_style();
9d522606 291 if ( style && style->font_desc )
b2ff89d6
VZ
292 {
293 wxNativeFontInfo info;
622226dc 294 info.description = style->font_desc;
b2ff89d6 295 attr.font = wxFont(info);
622226dc 296 info.description = NULL;
b2ff89d6 297 }
9dc44eff
PC
298#endif
299 if (!attr.font.IsOk())
b2ff89d6 300 {
9d522606
RD
301 GtkSettings *settings = gtk_settings_get_default();
302 gchar *font_name = NULL;
303 g_object_get ( settings,
b2ff89d6 304 "gtk-font-name",
9d522606
RD
305 &font_name,
306 NULL);
307 if (!font_name)
308 attr.font = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
309 else
310 attr.font = wxFont(wxString::FromAscii(font_name));
311 g_free (font_name);
b2ff89d6 312 }
b2ff89d6 313
9d522606
RD
314 return attr;
315}
316
317
318//static
319wxVisualAttributes
865bb325 320wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNew_t widget_new,
9d522606
RD
321 bool useBase,
322 int state)
323{
324 wxVisualAttributes attr;
66d8fe77
VS
325 // NB: we need toplevel window so that GTK+ can find the right style
326 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
9d522606 327 GtkWidget* widget = widget_new();
66d8fe77 328 gtk_container_add(GTK_CONTAINER(wnd), widget);
9d522606 329 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
66d8fe77 330 gtk_widget_destroy(wnd);
9d522606
RD
331 return attr;
332}
333
334//static
335wxVisualAttributes
865bb325 336wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromStr_t widget_new,
9d522606
RD
337 bool useBase,
338 int state)
339{
340 wxVisualAttributes attr;
66d8fe77
VS
341 // NB: we need toplevel window so that GTK+ can find the right style
342 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
9d522606 343 GtkWidget* widget = widget_new("");
66d8fe77 344 gtk_container_add(GTK_CONTAINER(wnd), widget);
9d522606 345 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
66d8fe77 346 gtk_widget_destroy(wnd);
9d522606
RD
347 return attr;
348}
349
350
351//static
352wxVisualAttributes
865bb325 353wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromAdj_t widget_new,
9d522606
RD
354 bool useBase,
355 int state)
356{
357 wxVisualAttributes attr;
66d8fe77
VS
358 // NB: we need toplevel window so that GTK+ can find the right style
359 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
9d522606 360 GtkWidget* widget = widget_new(NULL);
66d8fe77 361 gtk_container_add(GTK_CONTAINER(wnd), widget);
9d522606 362 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
66d8fe77 363 gtk_widget_destroy(wnd);
9d522606
RD
364 return attr;
365}
366
1e6feb95 367#endif // wxUSE_CONTROLS