1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk1/control.cpp
3 // Purpose: wxControl implementation for wxGTK
4 // Author: Robert Roebling
5 // Id: $Id: control.cpp 42816 2006-10-31 08:50:17Z RD $
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/gtk1/private.h"
24
25 // ============================================================================
26 // wxControl implementation
27 // ============================================================================
28
29 // ----------------------------------------------------------------------------
30 // wxControl creation
31 // ----------------------------------------------------------------------------
32
IMPLEMENT_DYNAMIC_CLASS(wxControl,wxWindow)33 IMPLEMENT_DYNAMIC_CLASS(wxControl, wxWindow)
34
35 wxControl::wxControl()
36 {
37 m_needParent = true;
38 }
39
Create(wxWindow * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxValidator & validator,const wxString & name)40 bool 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
DoGetBestSize() const57 wxSize 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
73
PostCreation(const wxSize & size)74 void wxControl::PostCreation(const wxSize& size)
75 {
76 wxWindow::PostCreation();
77
78 // NB: GetBestSize needs to know the style, otherwise it will assume
79 // default font and if the user uses a different font, determined
80 // best size will be different (typically, smaller) than the desired
81 // size. This call ensure that a style is available at the time
82 // GetBestSize is called.
83 gtk_widget_ensure_style(m_widget);
84
85 ApplyWidgetStyle();
86 SetInitialSize(size);
87 }
88
89 // ----------------------------------------------------------------------------
90 // wxControl dealing with labels
91 // ----------------------------------------------------------------------------
92
SetLabel(const wxString & label)93 void wxControl::SetLabel( const wxString &label )
94 {
95 // keep the original string internally to be able to return it later (for
96 // consistency with the other ports)
97 m_label = label;
98
99 InvalidateBestSize();
100 }
101
GetLabel() const102 wxString wxControl::GetLabel() const
103 {
104 return m_label;
105 }
106
GTKSetLabelForLabel(GtkLabel * w,const wxString & label)107 void wxControl::GTKSetLabelForLabel(GtkLabel *w, const wxString& label)
108 {
109 // don't call the virtual function which might call this one back again
110 wxControl::SetLabel(label);
111
112 const wxString labelGTK = GTKRemoveMnemonics(label);
113
114 gtk_label_set(w, wxGTK_CONV(labelGTK));
115 }
116
GTKSetLabelForFrame(GtkFrame * w,const wxString & label)117 void wxControl::GTKSetLabelForFrame(GtkFrame *w, const wxString& label)
118 {
119 wxControl::SetLabel(label);
120
121 const wxString labelGTK = GTKRemoveMnemonics(label);
122
123 gtk_frame_set_label(w, labelGTK.empty() ? (char *)NULL
124 : wxGTK_CONV(labelGTK));
125 }
126
127 /* static */
GTKRemoveMnemonics(const wxString & label)128 wxString wxControl::GTKRemoveMnemonics(const wxString& label)
129 {
130 const size_t len = label.length();
131 wxString labelGTK;
132 labelGTK.reserve(len);
133 for ( size_t i = 0; i < len; i++ )
134 {
135 wxChar ch = label[i];
136
137 if ( ch == _T('&') )
138 {
139 if ( i == len - 1 )
140 {
141 // "&" at the end of string is an error
142 wxLogDebug(wxT("Invalid label \"%s\"."), label.c_str());
143 break;
144 }
145
146 ch = label[++i]; // skip '&' itself
147 if ( ch == _T('&') )
148 {
149 // special case: "&&" is not a mnemonic at all but just an
150 // escaped "&"
151 labelGTK += wxT('&');
152 continue;
153 }
154 }
155
156 labelGTK += ch;
157 }
158
159 return labelGTK;
160 }
161
162 // ----------------------------------------------------------------------------
163 // wxControl styles (a.k.a. attributes)
164 // ----------------------------------------------------------------------------
165
GetDefaultAttributes() const166 wxVisualAttributes wxControl::GetDefaultAttributes() const
167 {
168 return GetDefaultAttributesFromGTKWidget(m_widget,
169 UseGTKStyleBase());
170 }
171
172
173 #define SHIFT (8*(sizeof(short int)-sizeof(char)))
174
175 // static
176 wxVisualAttributes
GetDefaultAttributesFromGTKWidget(GtkWidget * widget,bool useBase,int state)177 wxControl::GetDefaultAttributesFromGTKWidget(GtkWidget* widget,
178 bool useBase,
179 int state)
180 {
181 GtkStyle* style;
182 wxVisualAttributes attr;
183
184 style = gtk_rc_get_style(widget);
185 if (!style)
186 style = gtk_widget_get_default_style();
187
188 if (!style)
189 {
190 return wxWindow::GetClassDefaultAttributes(wxWINDOW_VARIANT_NORMAL);
191 }
192
193 if (state == -1)
194 state = GTK_STATE_NORMAL;
195
196 // get the style's colours
197 attr.colFg = wxColour(style->fg[state].red >> SHIFT,
198 style->fg[state].green >> SHIFT,
199 style->fg[state].blue >> SHIFT);
200 if (useBase)
201 attr.colBg = wxColour(style->base[state].red >> SHIFT,
202 style->base[state].green >> SHIFT,
203 style->base[state].blue >> SHIFT);
204 else
205 attr.colBg = wxColour(style->bg[state].red >> SHIFT,
206 style->bg[state].green >> SHIFT,
207 style->bg[state].blue >> SHIFT);
208
209 // get the style's font
210 // TODO: isn't there a way to get a standard gtk 1.2 font?
211 attr.font = wxFont( 12, wxSWISS, wxNORMAL, wxNORMAL );
212
213 return attr;
214 }
215
216
217 //static
218 wxVisualAttributes
GetDefaultAttributesFromGTKWidget(wxGtkWidgetNew_t widget_new,bool useBase,int state)219 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNew_t widget_new,
220 bool useBase,
221 int state)
222 {
223 wxVisualAttributes attr;
224 // NB: we need toplevel window so that GTK+ can find the right style
225 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
226 GtkWidget* widget = widget_new();
227 gtk_container_add(GTK_CONTAINER(wnd), widget);
228 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
229 gtk_widget_destroy(wnd);
230 return attr;
231 }
232
233 //static
234 wxVisualAttributes
GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromStr_t widget_new,bool useBase,int state)235 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromStr_t widget_new,
236 bool useBase,
237 int state)
238 {
239 wxVisualAttributes attr;
240 // NB: we need toplevel window so that GTK+ can find the right style
241 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
242 GtkWidget* widget = widget_new("");
243 gtk_container_add(GTK_CONTAINER(wnd), widget);
244 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
245 gtk_widget_destroy(wnd);
246 return attr;
247 }
248
249
250 //static
251 wxVisualAttributes
GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromAdj_t widget_new,bool useBase,int state)252 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromAdj_t widget_new,
253 bool useBase,
254 int state)
255 {
256 wxVisualAttributes attr;
257 // NB: we need toplevel window so that GTK+ can find the right style
258 GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
259 GtkWidget* widget = widget_new(NULL);
260 gtk_container_add(GTK_CONTAINER(wnd), widget);
261 attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
262 gtk_widget_destroy(wnd);
263 return attr;
264 }
265
266 #endif // wxUSE_CONTROLS
267