]> git.saurik.com Git - wxWidgets.git/blob - src/generic/collpaneg.cpp
initial draft of wxCollapsiblePane (patch 1577412 by Francesco)
[wxWidgets.git] / src / generic / collpaneg.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/collpaneg.cpp
3 // Purpose: wxGenericCollapsiblePane
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 #include "wx/collpane.h"
20 #include "wx/statline.h"
21
22 // ============================================================================
23 // implementation
24 // ============================================================================
25
26 const wxChar wxGenericCollapsiblePaneNameStr[] = wxT("genericCollapsiblePane");
27
28 //-----------------------------------------------------------------------------
29 // wxGenericCollapsiblePane
30 //-----------------------------------------------------------------------------
31
32 DEFINE_EVENT_TYPE(wxEVT_COMMAND_COLLPANE_CHANGED)
33 IMPLEMENT_DYNAMIC_CLASS(wxGenericCollapsiblePane, wxControl)
34 IMPLEMENT_DYNAMIC_CLASS(wxCollapsiblePaneEvent, wxCommandEvent)
35
36 BEGIN_EVENT_TABLE(wxGenericCollapsiblePane, wxControl)
37 EVT_BUTTON(wxCP_BUTTON_ID, wxGenericCollapsiblePane::OnButton)
38 EVT_SIZE(wxGenericCollapsiblePane::OnSize)
39 END_EVENT_TABLE()
40
41
42 bool wxGenericCollapsiblePane::Create( wxWindow *parent, wxWindowID id,
43 const wxString& label,
44 const wxPoint& pos,
45 const wxSize& size,
46 long style,
47 const wxValidator& val,
48 const wxString& name)
49 {
50 if ( !wxControl::Create(parent, id, pos, size, style, val, name) )
51 return false;
52
53 m_strLabel = label;
54
55 // create children; their size & position is set in OnSize()
56 m_pButton = new wxButton(this, wxCP_BUTTON_ID, GetBtnLabel(), wxPoint(0, 0),
57 wxDefaultSize, wxBU_EXACTFIT);
58 m_pStatLine = new wxStaticLine(this, wxID_ANY);
59 m_pPane = new wxWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNO_BORDER);
60
61 // start as collapsed:
62 m_pPane->Hide();
63
64 //CacheBestSize(GetBestSize());
65 return true;
66 }
67
68 wxSize wxGenericCollapsiblePane::DoGetBestSize() const
69 {
70 wxSize sz = m_pButton->GetBestSize();
71
72 // set width
73 sz.SetWidth( sz.GetWidth() + wxCP_MARGIN + m_pStatLine->GetBestSize().GetWidth() );
74 sz.SetWidth( wxMax(sz.GetWidth(), m_pPane->GetBestSize().GetWidth()) );
75
76 // when expanded, we need more vertical space
77 if (!IsCollapsed())
78 sz.SetHeight( sz.GetHeight() + wxCP_MARGIN + m_pPane->GetBestSize().GetHeight() );
79
80 return sz;
81 }
82
83 wxString wxGenericCollapsiblePane::GetBtnLabel() const
84 {
85 if (IsCollapsed())
86 return m_strLabel + wxT(" >>");
87 return m_strLabel + wxT(" <<");
88 }
89
90 void wxGenericCollapsiblePane::Collapse(bool collapse)
91 {
92 // optimization
93 if (IsCollapsed() == collapse)
94 return;
95
96 // update our state
97 m_pPane->Show(!collapse);
98
99 // update button label
100 // NB: this must be done after updating our "state"
101 m_pButton->SetLabel(GetBtnLabel());
102
103 // minimal size has priority over the best size so set here our min size
104 wxSize sz = GetBestSize();
105 SetMinSize(sz);
106 SetSize(sz);
107
108 wxWindow *top = GetTopLevelParent();
109 if (top)
110 {
111 // we've changed our size, thus our top level parent needs to relayout itself
112 top->Layout();
113
114 // FIXME: this makes wxGenericCollapsiblePane behave as the user expect but
115 // maybe there are cases where this is unwanted!
116 if (top->GetSizer())
117 #ifdef __WXGTK__
118 // FIXME: the SetSizeHints() call would be required also for GTK+ for the
119 // expanded->collapsed transition.
120 // Unfortunately if we enable this line, then the GTK+ top window
121 // won't always be resized by the SetClientSize() call below!
122 // As a side effect of this dirty fix, the minimal size for the
123 // pane window is not set in GTK+ and the user can hide it shrinking
124 // the "top" window...
125 if (IsCollapsed())
126 #endif
127 top->GetSizer()->SetSizeHints(top);
128
129 if (IsCollapsed())
130 {
131 // NB: we need to use SetClientSize() and not SetSize() otherwise the size for
132 // windows like e.g. wxFrames with wxMenubars won't be correctly set
133 top->SetClientSize(sz);
134 }
135 else
136 {
137 // force our parent to "fit", i.e. expand so that it can honour
138 // our minimal size
139 top->Fit();
140 }
141 }
142 }
143
144 wxWindow *wxGenericCollapsiblePane::GetTopLevelParent()
145 {
146 wxWindow *parent = GetParent();
147 while (parent && !parent->IsTopLevel())
148 parent = parent->GetParent();
149
150 return parent;
151 }
152
153 void wxGenericCollapsiblePane::SetLabel(const wxString &label)
154 {
155 m_strLabel = label;
156 m_pButton->SetLabel(GetBtnLabel());
157 m_pButton->SetBestFittingSize();
158
159 LayoutChildren();
160 }
161
162 void wxGenericCollapsiblePane::LayoutChildren()
163 {
164 wxSize btnSz = m_pButton->GetSize();
165
166 // the button position & size are always ok...
167
168 // move & resize the static line
169 m_pStatLine->SetSize(btnSz.GetWidth() + wxCP_MARGIN, btnSz.GetHeight()/2,
170 GetSize().GetWidth() - btnSz.GetWidth() - wxCP_MARGIN, -1,
171 wxSIZE_USE_EXISTING);
172
173 // move & resize the container window
174 m_pPane->SetSize(0, btnSz.GetHeight() + wxCP_MARGIN,
175 GetSize().GetWidth(), GetSize().GetHeight() - btnSz.GetHeight() - wxCP_MARGIN);
176 }
177
178
179
180 //-----------------------------------------------------------------------------
181 // wxGenericCollapsiblePane - event handlers
182 //-----------------------------------------------------------------------------
183
184 void wxGenericCollapsiblePane::OnButton(wxCommandEvent &WXUNUSED(event))
185 {
186 Collapse(!IsCollapsed());
187
188 // this change was generated by the user - send the event
189 wxCollapsiblePaneEvent ev(this, GetId(), IsCollapsed());
190 GetEventHandler()->ProcessEvent(ev);
191 }
192
193 void wxGenericCollapsiblePane::OnSize(wxSizeEvent& WXUNUSED(event))
194 {
195 #if 0 // for debug only
196 wxClientDC dc(this);
197 dc.SetPen(*wxBLACK_PEN);
198 dc.SetBrush(*wxTRANSPARENT_BRUSH);
199 dc.DrawRectangle(wxPoint(0,0), GetSize());
200 dc.SetPen(*wxRED_PEN);
201 dc.DrawRectangle(wxPoint(0,0), GetBestSize());
202 #endif
203
204
205 if (!m_pButton || !m_pStatLine || !m_pPane)
206 return; // we need to complete the creation first!
207
208 LayoutChildren();
209
210 // this is very important to make the pane window layout show correctly
211 m_pPane->Layout();
212 }
213