1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/collpaneg.cpp
3 // Purpose: wxGenericCollapsiblePane
4 // Author: Francesco Montorsi
8 // Copyright: (c) Francesco Montorsi
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 // ----------------------------------------------------------------------------
15 // ----------------------------------------------------------------------------
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
20 #include "wx/collpane.h"
22 #if wxUSE_BUTTON && wxUSE_STATLINE
25 #include "wx/toplevel.h"
26 #include "wx/button.h"
30 #include "wx/statline.h"
32 // ----------------------------------------------------------------------------
34 // ----------------------------------------------------------------------------
36 // the number of pixels to leave between the button and the static line and
37 // between the button and the pane
38 #define wxCP_MARGIN 10
40 // ============================================================================
42 // ============================================================================
44 const wxChar wxGenericCollapsiblePaneNameStr
[] = wxT("genericCollapsiblePane");
46 //-----------------------------------------------------------------------------
47 // wxGenericCollapsiblePane
48 //-----------------------------------------------------------------------------
50 DEFINE_EVENT_TYPE(wxEVT_COMMAND_COLLPANE_CHANGED
)
51 IMPLEMENT_DYNAMIC_CLASS(wxGenericCollapsiblePane
, wxControl
)
52 IMPLEMENT_DYNAMIC_CLASS(wxCollapsiblePaneEvent
, wxCommandEvent
)
54 BEGIN_EVENT_TABLE(wxGenericCollapsiblePane
, wxControl
)
55 EVT_BUTTON(wxID_ANY
, wxGenericCollapsiblePane::OnButton
)
56 EVT_SIZE(wxGenericCollapsiblePane::OnSize
)
60 bool wxGenericCollapsiblePane::Create(wxWindow
*parent
,
62 const wxString
& label
,
66 const wxValidator
& val
,
69 if ( !wxControl::Create(parent
, id
, pos
, size
, style
, val
, name
) )
74 // create children; their size & position is set in OnSize()
75 m_pButton
= new wxButton(this, wxID_ANY
, GetBtnLabel(), wxPoint(0, 0),
76 wxDefaultSize
, wxBU_EXACTFIT
);
77 m_pStatLine
= new wxStaticLine(this, wxID_ANY
);
78 m_pPane
= new wxWindow(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
,
81 // start as collapsed:
84 //CacheBestSize(GetBestSize());
88 wxSize
wxGenericCollapsiblePane::DoGetBestSize() const
90 wxSize sz
= m_pButton
->GetBestSize();
93 sz
.SetWidth(sz
.x
+ wxCP_MARGIN
+ m_pStatLine
->GetBestSize().x
);
94 const wxCoord paneWidth
= m_pPane
->GetBestSize().x
;
95 if ( sz
.x
< paneWidth
)
98 // when expanded, we need more vertical space
100 sz
.SetHeight(sz
.y
+ wxCP_MARGIN
+ m_pPane
->GetBestSize().y
);
105 wxString
wxGenericCollapsiblePane::GetBtnLabel() const
107 return m_strLabel
+ (IsCollapsed() ? wxT(" >>") : wxT(" <<"));
110 void wxGenericCollapsiblePane::OnStateChange(const wxSize
& sz
)
112 // minimal size has priority over the best size so set here our min size
117 top
= wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow
);
120 // we've changed our size, thus our top level parent needs to relayout
124 // FIXME: this makes wxGenericCollapsiblePane behave as the user expect
125 // but maybe there are cases where this is unwanted!
128 // FIXME: the SetSizeHints() call would be required also for GTK+ for
129 // the expanded->collapsed transition. Unfortunately if we
130 // enable this line, then the GTK+ top window won't always be
131 // resized by the SetClientSize() call below! As a side effect
132 // of this dirty fix, the minimal size for the pane window is
133 // not set in GTK+ and the user can hide it shrinking the "top"
137 top
->GetSizer()->SetSizeHints(top
);
140 // we shouldn't attempt to resize a maximized window, whatever happens
141 if ( !top
->IsMaximized() )
145 // use SetClientSize() and not SetSize() otherwise the size for
146 // e.g. a wxFrame with a menubar wouldn't be correctly set
147 top
->SetClientSize(sz
);
151 // force our parent to "fit", i.e. expand so that it can honour
159 void wxGenericCollapsiblePane::Collapse(bool collapse
)
162 if ( IsCollapsed() == collapse
)
166 m_pPane
->Show(!collapse
);
168 // update button label
169 // NB: this must be done after updating our "state"
170 m_pButton
->SetLabel(GetBtnLabel());
172 OnStateChange(GetBestSize());
175 void wxGenericCollapsiblePane::SetLabel(const wxString
&label
)
178 m_pButton
->SetLabel(GetBtnLabel());
179 m_pButton
->SetBestFittingSize();
184 void wxGenericCollapsiblePane::LayoutChildren()
186 wxSize btnSz
= m_pButton
->GetSize();
188 // the button position & size are always ok...
190 // move & resize the static line
191 m_pStatLine
->SetSize(btnSz
.x
+ wxCP_MARGIN
, btnSz
.y
/2,
192 GetSize().x
- btnSz
.x
- wxCP_MARGIN
, -1,
193 wxSIZE_USE_EXISTING
);
195 // move & resize the container window
196 m_pPane
->SetSize(0, btnSz
.y
+ wxCP_MARGIN
,
197 GetSize().x
, GetSize().y
- btnSz
.y
- wxCP_MARGIN
);
202 //-----------------------------------------------------------------------------
203 // wxGenericCollapsiblePane - event handlers
204 //-----------------------------------------------------------------------------
206 void wxGenericCollapsiblePane::OnButton(wxCommandEvent
& event
)
208 if ( event
.GetEventObject() != m_pButton
)
214 Collapse(!IsCollapsed());
216 // this change was generated by the user - send the event
217 wxCollapsiblePaneEvent
ev(this, GetId(), IsCollapsed());
218 GetEventHandler()->ProcessEvent(ev
);
221 void wxGenericCollapsiblePane::OnSize(wxSizeEvent
& WXUNUSED(event
))
223 #if 0 // for debug only
225 dc
.SetPen(*wxBLACK_PEN
);
226 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
227 dc
.DrawRectangle(wxPoint(0,0), GetSize());
228 dc
.SetPen(*wxRED_PEN
);
229 dc
.DrawRectangle(wxPoint(0,0), GetBestSize());
233 if (!m_pButton
|| !m_pStatLine
|| !m_pPane
)
234 return; // we need to complete the creation first!
238 // this is very important to make the pane window layout show correctly
242 #endif // wxUSE_BUTTON && wxUSE_STATLINE