]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/control.cpp
fixed problems with sometimes processing the events twice introduced in rev 1.170...
[wxWidgets.git] / src / gtk1 / control.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: control.cpp
3 // Purpose:
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 #include "wx/defs.h"
14
15 #if wxUSE_CONTROLS
16
17 #include "wx/control.h"
18 #include "wx/fontutil.h"
19 #include "wx/settings.h"
20
21 #include <gtk/gtk.h>
22
23 //-----------------------------------------------------------------------------
24 // wxControl
25 //-----------------------------------------------------------------------------
26
27 IMPLEMENT_DYNAMIC_CLASS(wxControl, wxWindow)
28
29 wxControl::wxControl()
30 {
31 m_needParent = TRUE;
32 }
33
34 bool wxControl::Create( wxWindow *parent,
35 wxWindowID id,
36 const wxPoint &pos,
37 const wxSize &size,
38 long style,
39 const wxValidator& validator,
40 const wxString &name )
41 {
42 bool ret = wxWindow::Create(parent, id, pos, size, style, name);
43
44 #if wxUSE_VALIDATORS
45 SetValidator(validator);
46 #endif
47
48 return ret;
49 }
50
51 void wxControl::SetLabel( const wxString &label )
52 {
53 m_label.Empty();
54 for ( const wxChar *pc = label; *pc != wxT('\0'); pc++ )
55 {
56 if ( *pc == wxT('&') )
57 {
58 pc++; // skip it
59 #if 0 // it would be unused anyhow for now - kbd interface not done yet
60 if ( *pc != wxT('&') ) m_chAccel = *pc;
61 #endif
62 }
63 m_label << *pc;
64 }
65 InvalidateBestSize();
66 }
67
68 wxString wxControl::GetLabel() const
69 {
70 return m_label;
71 }
72
73
74 wxSize wxControl::DoGetBestSize() const
75 {
76 // Do not return any arbitrary default value...
77 wxASSERT_MSG( m_widget, wxT("DoGetBestSize called before creation") );
78
79 GtkRequisition req;
80 req.width = 2;
81 req.height = 2;
82 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(m_widget) )->size_request )
83 (m_widget, &req );
84
85 wxSize best(req.width, req.height);
86 CacheBestSize(best);
87 return best;
88 }
89
90
91 void wxControl::PostCreation(const wxSize& size)
92 {
93 wxWindow::PostCreation();
94
95 // NB: GetBestSize needs to know the style, otherwise it will assume
96 // default font and if the user uses a different font, determined
97 // best size will be different (typically, smaller) than the desired
98 // size. This call ensure that a style is available at the time
99 // GetBestSize is called.
100 gtk_widget_ensure_style(m_widget);
101
102 ApplyWidgetStyle();
103 SetInitialBestSize(size);
104 }
105
106
107 #ifdef __WXGTK20__
108 wxString wxControl::PrepareLabelMnemonics( const wxString &label ) const
109 {
110 //Format mnemonics properly for GTK2. This can be called from GTK1.x, but
111 //it's not very useful because mnemonics don't exist prior to GTK2.
112 wxString label2;
113 for (size_t i = 0; i < label.Len(); i++)
114 {
115 if (label.GetChar(i) == wxT('&'))
116 {
117 //Mnemonic escape sequence "&&" is a literal "&" in the output.
118 if (label.GetChar(i + 1) == wxT('&'))
119 {
120 label2 << wxT('&');
121 i++;
122 }
123 //Handle special case of "&_" (i.e. "_" is the mnemonic).
124 //FIXME - Is it possible to use "_" as a GTK mnemonic? Just use a
125 //dash for now.
126 else if (label.GetChar(i + 1) == wxT('_'))
127 {
128 label2 << wxT("_-");
129 i++;
130 }
131 //Replace WX mnemonic indicator "&" with GTK indicator "_".
132 else
133 {
134 label2 << wxT('_');
135 }
136 }
137 else if (label.GetChar(i) == wxT('_'))
138 {
139 //Escape any underlines in the string so GTK doesn't use them.
140 label2 << wxT("__");
141 }
142 else
143 {
144 label2 << label.GetChar(i);
145 }
146 }
147 return label2;
148 }
149 #endif
150
151
152 wxVisualAttributes wxControl::GetDefaultAttributes() const
153 {
154 return GetDefaultAttributesFromGTKWidget(m_widget,
155 UseGTKStyleBase());
156 }
157
158
159 #define SHIFT (8*(sizeof(short int)-sizeof(char)))
160
161 // static
162 wxVisualAttributes
163 wxControl::GetDefaultAttributesFromGTKWidget(GtkWidget* widget,
164 bool useBase,
165 int state)
166 {
167 GtkStyle* style;
168 wxVisualAttributes attr;
169
170 style = gtk_rc_get_style(widget);
171 if (!style)
172 style = gtk_widget_get_default_style();
173
174 if (!style)
175 {
176 return wxWindow::GetClassDefaultAttributes(wxWINDOW_VARIANT_NORMAL);
177 }
178
179 if (state == -1)
180 state = GTK_STATE_NORMAL;
181
182 // get the style's colours
183 attr.colFg = wxColour(style->fg[state].red >> SHIFT,
184 style->fg[state].green >> SHIFT,
185 style->fg[state].blue >> SHIFT);
186 if (useBase)
187 attr.colBg = wxColour(style->base[state].red >> SHIFT,
188 style->base[state].green >> SHIFT,
189 style->base[state].blue >> SHIFT);
190 else
191 attr.colBg = wxColour(style->bg[state].red >> SHIFT,
192 style->bg[state].green >> SHIFT,
193 style->bg[state].blue >> SHIFT);
194
195 // get the style's font
196 #ifdef __WXGTK20__
197 if ( !style->font_desc )
198 style = gtk_widget_get_default_style();
199 if ( style && style->font_desc )
200 {
201 wxNativeFontInfo info;
202 info.description = pango_font_description_copy(style->font_desc);
203 attr.font = wxFont(info);
204 }
205 else
206 {
207 GtkSettings *settings = gtk_settings_get_default();
208 gchar *font_name = NULL;
209 g_object_get ( settings,
210 "gtk-font-name",
211 &font_name,
212 NULL);
213 if (!font_name)
214 attr.font = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
215 else
216 attr.font = wxFont(wxString::FromAscii(font_name));
217 g_free (font_name);
218 }
219 #else
220 // TODO: isn't there a way to get a standard gtk 1.2 font?
221 attr.font = wxFont( 12, wxSWISS, wxNORMAL, wxNORMAL );
222 #endif
223
224 return attr;
225 }
226
227
228 //static
229 wxVisualAttributes
230 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNew_t widget_new,
231 bool useBase,
232 int state)
233 {
234 wxVisualAttributes attr;
235 // NB: we need toplevel window so that GTK+ can find the right style
236 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
237 GtkWidget* widget = widget_new();
238 gtk_container_add(GTK_CONTAINER(wnd), widget);
239 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
240 gtk_widget_destroy(wnd);
241 return attr;
242 }
243
244 //static
245 wxVisualAttributes
246 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromStr_t widget_new,
247 bool useBase,
248 int state)
249 {
250 wxVisualAttributes attr;
251 // NB: we need toplevel window so that GTK+ can find the right style
252 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
253 GtkWidget* widget = widget_new("");
254 gtk_container_add(GTK_CONTAINER(wnd), widget);
255 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
256 gtk_widget_destroy(wnd);
257 return attr;
258 }
259
260
261 //static
262 wxVisualAttributes
263 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromAdj_t widget_new,
264 bool useBase,
265 int state)
266 {
267 wxVisualAttributes attr;
268 // NB: we need toplevel window so that GTK+ can find the right style
269 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
270 GtkWidget* widget = widget_new(NULL);
271 gtk_container_add(GTK_CONTAINER(wnd), widget);
272 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
273 gtk_widget_destroy(wnd);
274 return attr;
275 }
276
277 #endif // wxUSE_CONTROLS
278