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