]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/collpane.cpp
Use generic collapsible pane for wxUniv based builds.
[wxWidgets.git] / src / gtk / collpane.cpp
CommitLineData
3c1f8cb1
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/gtk/collpane.cpp
3// Purpose: wxCollapsiblePane
4// Author: Francesco Montorsi
5// Modified By:
6// Created: 8/10/2006
7// Id: $Id$
8// Copyright: (c) Francesco Montorsi
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12
13// ----------------------------------------------------------------------------
14// headers
15// ----------------------------------------------------------------------------
16
17// For compilers that support precompilation, includes "wx.h".
18#include "wx/wxprec.h"
19
20#ifdef __WXGTK24__
21
22#include "wx/collpane.h"
2cbf7014 23#include "wx/gtk/private.h"
550d433e 24
3c1f8cb1 25#include <gtk/gtkexpander.h>
3c1f8cb1 26
550d433e
VZ
27const wxChar wxCollapsiblePaneNameStr[] = wxT("CollapsiblePane");
28
3c1f8cb1
VZ
29// ============================================================================
30// implementation
31// ============================================================================
32
3c1f8cb1
VZ
33//-----------------------------------------------------------------------------
34// "notify::expanded" signal
35//-----------------------------------------------------------------------------
36
37extern "C" {
38
39static void gtk_collapsiblepane_expanded_callback (GObject *object,
40 GParamSpec *param_spec,
41 wxCollapsiblePane *p)
42{
550d433e
VZ
43 // NB: unlike for the "activate" signal, when this callback is called, if
44 // we try to query the "collapsed" status through p->IsCollapsed(), we
45 // get the right value. I.e. here p->IsCollapsed() will return false if
46 // this callback has been called at the end of a collapsed->expanded
47 // transition and viceversa. Inside the "activate" signal callback
48 // p->IsCollapsed() would return the wrong value!
3c1f8cb1
VZ
49
50 wxSize sz;
550d433e 51 if ( p->IsExpanded() )
3c1f8cb1 52 {
550d433e
VZ
53 // unfortunately there's no clean way to retrieve the minimal size of
54 // the expanded pane in this handler or in other handlers for the
55 // signals generated by user clicks on the GtkExpander button:
56 // p->GetBestSize() or p->GetMinSize() would still return the size for
57 // the collapsed expander even if the collapsed->expanded transition
58 // has already been completed (this because GTK+ queues some resize
59 // calls which still must be processed). So, the only solution to
60 // correctly set the size hints for this window is to calculate the
61 // expanded size ourselves, without relying on p->Get[Best|Min]Size:
3c1f8cb1 62 sz = p->GetMinSize();
550d433e
VZ
63 sz.SetWidth(wxMax(sz.x, p->GetPane()->GetMinSize().x));
64 sz.SetHeight(sz.y + p->GetPane()->GetMinSize().y + 10);
3c1f8cb1 65 }
550d433e 66 else // collapsed
3c1f8cb1 67 {
550d433e
VZ
68 // same problem described above: using p->Get[Best|Min]Size() here we
69 // would get the size of the control when it is expanded even if the
70 // expanded->collapsed transition should be complete now...
3c1f8cb1
VZ
71 // So, we use the size cached at control-creation time...
72 sz = p->m_szCollapsed;
73 }
74
4223cec5 75 p->OnStateChange(sz);
3c1f8cb1 76
550d433e 77 if ( p->m_bIgnoreNextChange )
3c1f8cb1
VZ
78 {
79 // change generated programmatically - do not send an event!
80 p->m_bIgnoreNextChange = false;
81 return;
82 }
83
84 // fire an event
85 wxCollapsiblePaneEvent ev(p, p->GetId(), p->IsCollapsed());
86 p->GetEventHandler()->ProcessEvent(ev);
87}
88}
89
550d433e
VZ
90static void
91gtk_collapsiblepane_insert_callback(wxWindowGTK* parent, wxWindowGTK* child)
3c1f8cb1 92{
550d433e
VZ
93 // this callback should be used only once to insert the "pane" into the
94 // GtkExpander widget. wxGenericCollapsiblePane::DoAddChild() will check if
95 // it has been called only once (and in any case we would get a warning
96 // from the following call as GtkExpander is a GtkBin and can contain only
97 // a single child!).
3c1f8cb1
VZ
98 gtk_container_add (GTK_CONTAINER (parent->m_widget), child->m_widget);
99}
100
3c1f8cb1
VZ
101//-----------------------------------------------------------------------------
102// wxCollapsiblePane
103//-----------------------------------------------------------------------------
104
105IMPLEMENT_DYNAMIC_CLASS(wxCollapsiblePane, wxGenericCollapsiblePane)
106
107BEGIN_EVENT_TABLE(wxCollapsiblePane, wxGenericCollapsiblePane)
108 EVT_SIZE(wxCollapsiblePane::OnSize)
109END_EVENT_TABLE()
110
550d433e
VZ
111bool wxCollapsiblePane::Create(wxWindow *parent,
112 wxWindowID id,
113 const wxString& label,
114 const wxPoint& pos,
115 const wxSize& size,
116 long style,
117 const wxValidator& val,
118 const wxString& name)
3c1f8cb1 119{
550d433e
VZ
120 if (gtk_check_version(2,4,0))
121 return wxGenericCollapsiblePane::Create(parent, id, label,
122 pos, size, style, val, name);
3c1f8cb1
VZ
123
124 m_needParent = true;
125 m_acceptsFocus = true;
126 m_bIgnoreNextChange = false;
127
550d433e
VZ
128 if ( !PreCreation( parent, pos, size ) ||
129 !wxControl::CreateBase(parent, id, pos, size, style, val, name) )
3c1f8cb1
VZ
130 {
131 wxFAIL_MSG( wxT("wxCollapsiblePane creation failed") );
132 return false;
133 }
134
ff928a27
VZ
135 m_widget =
136 gtk_expander_new_with_mnemonic(wxGTK_CONV(GTKConvertMnemonics(label)));
3c1f8cb1 137
550d433e
VZ
138 // see the gtk_collapsiblepane_expanded_callback comments to understand why
139 // we connect to the "notify::expanded" signal instead of the more common
140 // "activate" one
3c1f8cb1
VZ
141 g_signal_connect(m_widget, "notify::expanded",
142 G_CALLBACK(gtk_collapsiblepane_expanded_callback), this);
143
550d433e
VZ
144 // before creating m_pPane, we need to makesure our own insert callback
145 // will be used
3c1f8cb1
VZ
146 m_insertCallback = gtk_collapsiblepane_insert_callback;
147
148 // this the real "pane"
550d433e
VZ
149 m_pPane = new wxWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
150 wxNO_BORDER);
3c1f8cb1
VZ
151
152 gtk_widget_show( GTK_WIDGET(m_widget) );
153 m_parent->DoAddChild( this );
154
155 PostCreation(size);
3c1f8cb1
VZ
156
157 // remember the size of this control when it's collapsed
158 m_szCollapsed = GetBestSize();
159
3c1f8cb1
VZ
160 return true;
161}
162
163wxSize wxCollapsiblePane::DoGetBestSize() const
164{
165 if (!gtk_check_version(2,4,0))
166 {
3c1f8cb1
VZ
167 wxASSERT_MSG( m_widget, wxT("DoGetBestSize called before creation") );
168
169 GtkRequisition req;
170 req.width = 2;
171 req.height = 2;
172 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(m_widget) )->size_request )
173 (m_widget, &req );
174
550d433e
VZ
175 // notice that we do not cache our best size here as it changes
176 return wxSize(req.width, req.height);
3c1f8cb1
VZ
177 }
178
179 return wxGenericCollapsiblePane::DoGetBestSize();
180}
181
182void wxCollapsiblePane::Collapse(bool collapse)
183{
184 if (!gtk_check_version(2,4,0))
185 {
186 // optimization
187 if (IsCollapsed() == collapse)
188 return;
189
190 // do not send event in next signal handler call
191 m_bIgnoreNextChange = true;
192 gtk_expander_set_expanded(GTK_EXPANDER(m_widget), !collapse);
193 }
194 else
195 wxGenericCollapsiblePane::Collapse(collapse);
196}
197
198bool wxCollapsiblePane::IsCollapsed() const
199{
200 if (!gtk_check_version(2,4,0))
201 return !gtk_expander_get_expanded(GTK_EXPANDER(m_widget));
202
203 return wxGenericCollapsiblePane::IsCollapsed();
204}
205
206void wxCollapsiblePane::SetLabel(const wxString &str)
207{
208 if (!gtk_check_version(2,4,0))
209 gtk_expander_set_label(GTK_EXPANDER(m_widget), str.c_str());
210 else
211 wxGenericCollapsiblePane::SetLabel(str);
212}
213
214void wxCollapsiblePane::OnSize(wxSizeEvent &ev)
215{
216#if 0 // for debug only
217 wxClientDC dc(this);
218 dc.SetPen(*wxBLACK_PEN);
219 dc.SetBrush(*wxTRANSPARENT_BRUSH);
220 dc.DrawRectangle(wxPoint(0,0), GetSize());
221 dc.SetPen(*wxRED_PEN);
222 dc.DrawRectangle(wxPoint(0,0), GetBestSize());
223#endif
224
3c1f8cb1
VZ
225 // here we need to resize the pane window otherwise, even if the GtkExpander container
226 // is expanded or shrinked, the pane window won't be updated!
227 m_pPane->SetSize(ev.GetSize());
228
229 // we need to explicitely call m_pPane->Layout() or else it won't correctly relayout
230 // (even if SetAutoLayout(true) has been called on it!)
231 m_pPane->Layout();
232}
233
550d433e 234#endif // __WXGTK24__
3c1f8cb1 235