]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/control.cpp
explicitly call OnExit() in the ports which don't use wxEventLoopManual
[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"
b2ff89d6 23#include "wx/gtk/private.h"
034be888 24
634fb750
VZ
25// ============================================================================
26// wxControl implementation
27// ============================================================================
28
29// ----------------------------------------------------------------------------
30// wxControl creation
31// ----------------------------------------------------------------------------
c801d85f 32
9abe166a 33IMPLEMENT_DYNAMIC_CLASS(wxControl, wxWindow)
c801d85f 34
31528cd3 35wxControl::wxControl()
c801d85f 36{
9eddec69 37 m_needParent = true;
6de97a3b 38}
c801d85f 39
04165bec 40bool wxControl::Create( wxWindow *parent,
31528cd3
VZ
41 wxWindowID id,
42 const wxPoint &pos,
43 const wxSize &size,
44 long style,
8d772832 45 const wxValidator& validator,
04165bec 46 const wxString &name )
8d772832 47{
04165bec 48 bool ret = wxWindow::Create(parent, id, pos, size, style, name);
b2ff89d6 49
04165bec 50#if wxUSE_VALIDATORS
8d772832 51 SetValidator(validator);
8d772832
RD
52#endif
53
04165bec
RR
54 return ret;
55}
56
f68586e5
VZ
57wxSize wxControl::DoGetBestSize() const
58{
0279e844
RR
59 // Do not return any arbitrary default value...
60 wxASSERT_MSG( m_widget, wxT("DoGetBestSize called before creation") );
61
f68586e5 62 GtkRequisition req;
33720b2d
RR
63 req.width = 2;
64 req.height = 2;
2afa14f2 65 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(m_widget) )->size_request )
f68586e5
VZ
66 (m_widget, &req );
67
9f884528
RD
68 wxSize best(req.width, req.height);
69 CacheBestSize(best);
70 return best;
f68586e5
VZ
71}
72
abdeb9e7
RD
73void wxControl::PostCreation(const wxSize& size)
74{
75 wxWindow::PostCreation();
f40fdaa3
VS
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);
b2ff89d6 83
abdeb9e7 84 ApplyWidgetStyle();
170acdc9 85 SetInitialSize(size);
abdeb9e7
RD
86}
87
b2ff89d6
VZ
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);
abdeb9e7 112
b2ff89d6 113 gtk_label_set_text_with_mnemonic(w, wxGTK_CONV(labelGTK));
b2ff89d6
VZ
114}
115
2e1f5012
VZ
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
e4db172a 133 return framewidget; //note that the label is already set so you'll
2e1f5012
VZ
134 //only need to call wxControl::SetLabel afterwards
135}
136
b2ff89d6
VZ
137void wxControl::GTKSetLabelForFrame(GtkFrame *w, const wxString& label)
138{
2e1f5012
VZ
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}
b2ff89d6 148
2e1f5012
VZ
149void wxControl::GTKFrameSetMnemonicWidget(GtkFrame* w, GtkWidget* widget)
150{
151 GtkLabel* labelwidget = GTK_LABEL(gtk_frame_get_label_widget(w));
b2ff89d6 152
2e1f5012 153 gtk_label_set_mnemonic_widget(labelwidget, widget);
b2ff89d6
VZ
154}
155
2e1f5012 156// ----------------------------------------------------------------------------
b2ff89d6
VZ
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
2e1f5012
VZ
162// ----------------------------------------------------------------------------
163
b2ff89d6 164enum MnemonicsFlag
eaafd2f8 165{
b2ff89d6
VZ
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++ )
eaafd2f8 176 {
b2ff89d6
VZ
177 wxChar ch = label[i];
178
179 switch ( ch )
eaafd2f8 180 {
b2ff89d6
VZ
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;
eaafd2f8
VS
227 }
228 }
b2ff89d6
VZ
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);
eaafd2f8
VS
243}
244
b2ff89d6
VZ
245// ----------------------------------------------------------------------------
246// wxControl styles (a.k.a. attributes)
247// ----------------------------------------------------------------------------
9d522606
RD
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;
b2ff89d6 278
9d522606
RD
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
9d522606 293 if ( !style->font_desc )
b2ff89d6 294 style = gtk_widget_get_default_style();
9d522606 295 if ( style && style->font_desc )
b2ff89d6
VZ
296 {
297 wxNativeFontInfo info;
fdf7514a 298 info.description = pango_font_description_copy(style->font_desc);
b2ff89d6
VZ
299 attr.font = wxFont(info);
300 }
301 else
302 {
9d522606
RD
303 GtkSettings *settings = gtk_settings_get_default();
304 gchar *font_name = NULL;
305 g_object_get ( settings,
b2ff89d6 306 "gtk-font-name",
9d522606
RD
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);
b2ff89d6 314 }
b2ff89d6 315
9d522606
RD
316 return attr;
317}
318
319
320//static
321wxVisualAttributes
865bb325 322wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNew_t widget_new,
9d522606
RD
323 bool useBase,
324 int state)
325{
326 wxVisualAttributes attr;
66d8fe77
VS
327 // NB: we need toplevel window so that GTK+ can find the right style
328 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
9d522606 329 GtkWidget* widget = widget_new();
66d8fe77 330 gtk_container_add(GTK_CONTAINER(wnd), widget);
9d522606 331 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
66d8fe77 332 gtk_widget_destroy(wnd);
9d522606
RD
333 return attr;
334}
335
336//static
337wxVisualAttributes
865bb325 338wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromStr_t widget_new,
9d522606
RD
339 bool useBase,
340 int state)
341{
342 wxVisualAttributes attr;
66d8fe77
VS
343 // NB: we need toplevel window so that GTK+ can find the right style
344 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
9d522606 345 GtkWidget* widget = widget_new("");
66d8fe77 346 gtk_container_add(GTK_CONTAINER(wnd), widget);
9d522606 347 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
66d8fe77 348 gtk_widget_destroy(wnd);
9d522606
RD
349 return attr;
350}
351
352
353//static
354wxVisualAttributes
865bb325 355wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromAdj_t widget_new,
9d522606
RD
356 bool useBase,
357 int state)
358{
359 wxVisualAttributes attr;
66d8fe77
VS
360 // NB: we need toplevel window so that GTK+ can find the right style
361 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
9d522606 362 GtkWidget* widget = widget_new(NULL);
66d8fe77 363 gtk_container_add(GTK_CONTAINER(wnd), widget);
9d522606 364 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
66d8fe77 365 gtk_widget_destroy(wnd);
9d522606
RD
366 return attr;
367}
368
ef5c70f9
VZ
369// ----------------------------------------------------------------------------
370// idle handling
371// ----------------------------------------------------------------------------
372
373void wxControl::OnInternalIdle()
374{
375 if ( GtkShowFromOnIdle() )
376 return;
ef5c70f9 377
1f5cf9cc 378 if ( GTK_WIDGET_REALIZED(m_widget) )
6c6a3e8a
VZ
379 {
380 GTKUpdateCursor();
381
382 GTKSetDelayedFocusIfNeeded();
383 }
06a7419e 384
ef5c70f9
VZ
385 if ( wxUpdateUIEvent::CanUpdate(this) )
386 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
387}
388
1e6feb95 389#endif // wxUSE_CONTROLS