1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/gtk1/control.cpp
3 // Purpose:     wxControl implementation for wxGTK
4 // Author:      Robert Roebling
5 // Copyright:   (c) 1998 Robert Roebling, Julian Smart and Vadim Zeitlin
6 // Licence:     wxWindows licence
7 /////////////////////////////////////////////////////////////////////////////
8 
9 // For compilers that support precompilation, includes "wx.h".
10 #include "wx/wxprec.h"
11 
12 #if wxUSE_CONTROLS
13 
14 #include "wx/control.h"
15 
16 #ifndef WX_PRECOMP
17     #include "wx/log.h"
18     #include "wx/settings.h"
19 #endif
20 
21 #include "wx/fontutil.h"
22 #include "wx/gtk1/private.h"
23 
24 // ============================================================================
25 // wxControl implementation
26 // ============================================================================
27 
28 // ----------------------------------------------------------------------------
29 // wxControl creation
30 // ----------------------------------------------------------------------------
31 
IMPLEMENT_DYNAMIC_CLASS(wxControl,wxWindow)32 IMPLEMENT_DYNAMIC_CLASS(wxControl, wxWindow)
33 
34 wxControl::wxControl()
35 {
36     m_needParent = true;
37 }
38 
Create(wxWindow * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxValidator & validator,const wxString & name)39 bool wxControl::Create( wxWindow *parent,
40                       wxWindowID id,
41                       const wxPoint &pos,
42                       const wxSize &size,
43                       long style,
44                       const wxValidator& validator,
45                       const wxString &name )
46 {
47     bool ret = wxWindow::Create(parent, id, pos, size, style, name);
48 
49 #if wxUSE_VALIDATORS
50     SetValidator(validator);
51 #endif
52 
53     return ret;
54 }
55 
DoGetBestSize() const56 wxSize wxControl::DoGetBestSize() const
57 {
58     // Do not return any arbitrary default value...
59     wxASSERT_MSG( m_widget, wxT("DoGetBestSize called before creation") );
60 
61     GtkRequisition req;
62     req.width = 2;
63     req.height = 2;
64     (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(m_widget) )->size_request )
65         (m_widget, &req );
66 
67     wxSize best(req.width, req.height);
68     CacheBestSize(best);
69     return best;
70 }
71 
72 
PostCreation(const wxSize & size)73 void wxControl::PostCreation(const wxSize& size)
74 {
75     wxWindow::PostCreation();
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);
83 
84     ApplyWidgetStyle();
85     SetInitialSize(size);
86 }
87 
88 // ----------------------------------------------------------------------------
89 // wxControl dealing with labels
90 // ----------------------------------------------------------------------------
91 
SetLabel(const wxString & label)92 void 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 
GetLabel() const101 wxString wxControl::GetLabel() const
102 {
103     return m_label;
104 }
105 
GTKSetLabelForLabel(GtkLabel * w,const wxString & label)106 void 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 = GTKRemoveMnemonics(label);
112 
113     gtk_label_set(w, wxGTK_CONV(labelGTK));
114 }
115 
GTKSetLabelForFrame(GtkFrame * w,const wxString & label)116 void wxControl::GTKSetLabelForFrame(GtkFrame *w, const wxString& label)
117 {
118     wxControl::SetLabel(label);
119 
120     const wxString labelGTK = GTKRemoveMnemonics(label);
121 
122     gtk_frame_set_label(w, labelGTK.empty() ? (const char *)NULL
123                                             : wxGTK_CONV(labelGTK));
124 }
125 
126 /* static */
GTKRemoveMnemonics(const wxString & label)127 wxString wxControl::GTKRemoveMnemonics(const wxString& label)
128 {
129     const size_t len = label.length();
130     wxString labelGTK;
131     labelGTK.reserve(len);
132     for ( size_t i = 0; i < len; i++ )
133     {
134         wxChar ch = label[i];
135 
136         if ( ch == wxT('&') )
137         {
138             if ( i == len - 1 )
139             {
140                 // "&" at the end of string is an error
141                 wxLogDebug(wxT("Invalid label \"%s\"."), label.c_str());
142                 break;
143             }
144 
145             ch = label[++i]; // skip '&' itself
146             if ( ch == wxT('&') )
147             {
148                 // special case: "&&" is not a mnemonic at all but just an
149                 // escaped "&"
150                 labelGTK += wxT('&');
151                 continue;
152             }
153         }
154 
155         labelGTK += ch;
156     }
157 
158     return labelGTK;
159 }
160 
161 // ----------------------------------------------------------------------------
162 // wxControl styles (a.k.a. attributes)
163 // ----------------------------------------------------------------------------
164 
GetDefaultAttributes() const165 wxVisualAttributes wxControl::GetDefaultAttributes() const
166 {
167     return GetDefaultAttributesFromGTKWidget(m_widget,
168                                              UseGTKStyleBase());
169 }
170 
171 
172 #define SHIFT (8*(sizeof(short int)-sizeof(char)))
173 
174 // static
175 wxVisualAttributes
GetDefaultAttributesFromGTKWidget(GtkWidget * widget,bool useBase,int state)176 wxControl::GetDefaultAttributesFromGTKWidget(GtkWidget* widget,
177                                              bool useBase,
178                                              int state)
179 {
180     GtkStyle* style;
181     wxVisualAttributes attr;
182 
183     style = gtk_rc_get_style(widget);
184     if (!style)
185         style = gtk_widget_get_default_style();
186 
187     if (!style)
188     {
189         return wxWindow::GetClassDefaultAttributes(wxWINDOW_VARIANT_NORMAL);
190     }
191 
192     if (state == -1)
193         state = GTK_STATE_NORMAL;
194 
195     // get the style's colours
196     attr.colFg = wxColour(style->fg[state].red   >> SHIFT,
197                           style->fg[state].green >> SHIFT,
198                           style->fg[state].blue  >> SHIFT);
199     if (useBase)
200         attr.colBg = wxColour(style->base[state].red   >> SHIFT,
201                               style->base[state].green >> SHIFT,
202                               style->base[state].blue  >> SHIFT);
203     else
204         attr.colBg = wxColour(style->bg[state].red   >> SHIFT,
205                               style->bg[state].green >> SHIFT,
206                               style->bg[state].blue  >> SHIFT);
207 
208     // get the style's font
209     // TODO: isn't there a way to get a standard gtk 1.2 font?
210     attr.font = wxFont( 12, wxSWISS, wxNORMAL, wxNORMAL );
211 
212     return attr;
213 }
214 
215 
216 //static
217 wxVisualAttributes
GetDefaultAttributesFromGTKWidget(wxGtkWidgetNew_t widget_new,bool useBase,int state)218 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNew_t widget_new,
219                                              bool useBase,
220                                              int state)
221 {
222     wxVisualAttributes attr;
223     // NB: we need toplevel window so that GTK+ can find the right style
224     GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
225     GtkWidget* widget = widget_new();
226     gtk_container_add(GTK_CONTAINER(wnd), widget);
227     attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
228     gtk_widget_destroy(wnd);
229     return attr;
230 }
231 
232 //static
233 wxVisualAttributes
GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromStr_t widget_new,bool useBase,int state)234 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromStr_t widget_new,
235                                              bool useBase,
236                                              int state)
237 {
238     wxVisualAttributes attr;
239     // NB: we need toplevel window so that GTK+ can find the right style
240     GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
241     GtkWidget* widget = widget_new("");
242     gtk_container_add(GTK_CONTAINER(wnd), widget);
243     attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
244     gtk_widget_destroy(wnd);
245     return attr;
246 }
247 
248 
249 //static
250 wxVisualAttributes
GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromAdj_t widget_new,bool useBase,int state)251 wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromAdj_t widget_new,
252                                              bool useBase,
253                                              int state)
254 {
255     wxVisualAttributes attr;
256     // NB: we need toplevel window so that GTK+ can find the right style
257     GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
258     GtkWidget* widget = widget_new(NULL);
259     gtk_container_add(GTK_CONTAINER(wnd), widget);
260     attr = GetDefaultAttributesFromGTKWidget(widget, useBase, state);
261     gtk_widget_destroy(wnd);
262     return attr;
263 }
264 
265 #endif // wxUSE_CONTROLS
266