1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/statbox.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Copyright: (c) 1998 Robert Roebling
6 // Licence: wxWindows licence
7 /////////////////////////////////////////////////////////////////////////////
8
9 // For compilers that support precompilation, includes "wx.h".
10 #include "wx/wxprec.h"
11
12 #if wxUSE_STATBOX
13
14 #include "wx/statbox.h"
15
16 #include "wx/gtk/private/wrapgtk.h"
17 #include "wx/gtk/private/win_gtk.h"
18
19 // constants taken from GTK sources
20 #define LABEL_PAD 1
21 #define LABEL_SIDE_PAD 2
22
23 //-----------------------------------------------------------------------------
24 // "size_allocate" from m_widget
25 //-----------------------------------------------------------------------------
26
27 #ifndef __WXGTK3__
28 extern "C" {
size_allocate(GtkWidget * widget,GtkAllocation * alloc,void *)29 static void size_allocate(GtkWidget* widget, GtkAllocation* alloc, void*)
30 {
31 // clip label as GTK >= 2.12 does
32 GtkWidget* label_widget = gtk_frame_get_label_widget(GTK_FRAME(widget));
33 int w = alloc->width -
34 2 * gtk_widget_get_style(widget)->xthickness - 2 * LABEL_PAD - 2 * LABEL_SIDE_PAD;
35 if (w < 0)
36 w = 0;
37
38 GtkAllocation a;
39 gtk_widget_get_allocation(label_widget, &a);
40 if (a.width > w)
41 {
42 a.width = w;
43 gtk_widget_size_allocate(label_widget, &a);
44 }
45 }
46
expose_event(GtkWidget * widget,GdkEventExpose *,wxWindow *)47 static gboolean expose_event(GtkWidget* widget, GdkEventExpose*, wxWindow*)
48 {
49 const GtkAllocation& a = widget->allocation;
50 gtk_paint_flat_box(gtk_widget_get_style(widget), gtk_widget_get_window(widget),
51 GTK_STATE_NORMAL, GTK_SHADOW_NONE, NULL, widget, "", a.x, a.y, a.width, a.height);
52 return false;
53 }
54 }
55 #endif
56
57 //-----------------------------------------------------------------------------
58 // wxStaticBox
59 //-----------------------------------------------------------------------------
60
DoCreate(wxWindow * parent,wxWindowID id,const wxString * labelStr,wxWindow * labelWin,const wxPoint & pos,const wxSize & size,long style,const wxString & name)61 bool wxStaticBox::DoCreate(wxWindow *parent,
62 wxWindowID id,
63 const wxString* labelStr,
64 wxWindow* labelWin,
65 const wxPoint& pos,
66 const wxSize& size,
67 long style,
68 const wxString& name)
69 {
70 if (!PreCreation( parent, pos, size ) ||
71 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
72 {
73 wxFAIL_MSG( wxT("wxStaticBox creation failed") );
74 return false;
75 }
76
77 if ( labelStr )
78 {
79 m_widget = GTKCreateFrame(*labelStr);
80
81 // only base SetLabel needs to be called after GTKCreateFrame
82 wxControl::SetLabel(*labelStr);
83 }
84 else // Use the given window as the label.
85 {
86 wxCHECK_MSG( labelWin, false, wxS("Label window can't be null") );
87
88 GtkWidget* const labelWidget = labelWin->m_widget;
89 wxCHECK_MSG( labelWidget, false, wxS("Label window must be created") );
90
91 // The widget must not have any parent at GTK+ level or setting it as
92 // label widget would fail.
93 GtkWidget* const oldParent = gtk_widget_get_parent(labelWidget);
94 gtk_container_remove(GTK_CONTAINER(oldParent), labelWidget);
95 gtk_widget_unparent(labelWidget);
96
97 // It also should be our child at wx API level, but without being our
98 // child in wxGTK, i.e. it must not be added to the GtkFrame container,
99 // so we can't call Reparent() here (not even wxWindowBase version, as
100 // it still would end up in our overridden AddChild()), nor the normal
101 // AddChild() for the same reason.
102 labelWin->GetParent()->RemoveChild(labelWin);
103 wxWindowBase::AddChild(labelWin);
104
105 m_labelWin = labelWin;
106
107 m_widget = gtk_frame_new(NULL);
108 gtk_frame_set_label_widget(GTK_FRAME(m_widget), labelWidget);
109 }
110
111 g_object_ref(m_widget);
112
113 m_parent->DoAddChild( this );
114
115 PostCreation(size);
116
117 // need to set non default alignment?
118 gfloat xalign = 0;
119 if ( style & wxALIGN_CENTER )
120 xalign = 0.5;
121 else if ( style & wxALIGN_RIGHT )
122 xalign = 1.0;
123
124 gtk_frame_set_label_align(GTK_FRAME(m_widget), xalign, 0.5);
125
126 #ifndef __WXGTK3__
127 if (!wx_is_at_least_gtk2(12))
128 {
129 // we connect this signal to perform label-clipping as GTK >= 2.12 does
130 g_signal_connect(m_widget, "size_allocate", G_CALLBACK(size_allocate), NULL);
131 }
132 #endif
133
134 m_container.DisableSelfFocus();
135
136 return true;
137 }
138
AddChild(wxWindowBase * child)139 void wxStaticBox::AddChild( wxWindowBase *child )
140 {
141 if (!m_wxwindow)
142 {
143 // make this window a container of other wxWindows by instancing a wxPizza
144 // and packing it into the GtkFrame:
145 m_wxwindow = wxPizza::New();
146 gtk_widget_show( m_wxwindow );
147 gtk_container_add( GTK_CONTAINER (m_widget), m_wxwindow );
148 GTKApplyWidgetStyle();
149 }
150
151 wxStaticBoxBase::AddChild(child);
152 }
153
SetLabel(const wxString & label)154 void wxStaticBox::SetLabel( const wxString& label )
155 {
156 wxCHECK_RET( m_widget != NULL, wxT("invalid staticbox") );
157
158 wxCHECK_RET( !m_labelWin, wxS("Doesn't make sense when using label window") );
159
160 GTKSetLabelForFrame(GTK_FRAME(m_widget), label);
161 }
162
DoApplyWidgetStyle(GtkRcStyle * style)163 void wxStaticBox::DoApplyWidgetStyle(GtkRcStyle *style)
164 {
165 GTKFrameApplyWidgetStyle(GTK_FRAME(m_widget), style);
166 if ( m_labelWin )
167 GTKDoApplyWidgetStyle(m_labelWin, style);
168 if (m_wxwindow)
169 GTKApplyStyle(m_wxwindow, style);
170
171 #ifndef __WXGTK3__
172 g_signal_handlers_disconnect_by_func(m_widget, (void*)expose_event, this);
173 if (m_backgroundColour.IsOk())
174 g_signal_connect(m_widget, "expose-event", G_CALLBACK(expose_event), this);
175 #endif
176 }
177
GTKWidgetNeedsMnemonic() const178 bool wxStaticBox::GTKWidgetNeedsMnemonic() const
179 {
180 return true;
181 }
182
GTKWidgetDoSetMnemonic(GtkWidget * w)183 void wxStaticBox::GTKWidgetDoSetMnemonic(GtkWidget* w)
184 {
185 GTKFrameSetMnemonicWidget(GTK_FRAME(m_widget), w);
186 }
187
188 // static
189 wxVisualAttributes
GetClassDefaultAttributes(wxWindowVariant WXUNUSED (variant))190 wxStaticBox::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
191 {
192 return GetDefaultAttributesFromGTKWidget(gtk_frame_new(""));
193 }
194
GetBordersForSizer(int * borderTop,int * borderOther) const195 void wxStaticBox::GetBordersForSizer(int *borderTop, int *borderOther) const
196 {
197 GtkWidget* label = gtk_frame_get_label_widget(GTK_FRAME(m_widget));
198 #ifdef __WXGTK3__
199 *borderOther = 0;
200 *borderTop = 0;
201 if (label)
202 {
203 int nat_width;
204 gtk_widget_get_preferred_width(label, NULL, &nat_width);
205 gtk_widget_get_preferred_height_for_width(label, nat_width, borderTop, NULL);
206 }
207 #else
208 gtk_widget_ensure_style(m_widget);
209 const int border_width = GTK_CONTAINER(m_widget)->border_width;
210 *borderOther = border_width + m_widget->style->xthickness;
211 *borderTop = border_width;
212 if (label)
213 {
214 GtkRequisition req;
215 gtk_widget_size_request(label, &req);
216 *borderTop += req.height;
217 }
218 else
219 *borderTop += m_widget->style->ythickness;
220 #endif
221 }
222
223 #endif // wxUSE_STATBOX
224