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