1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/generic/collheaderctrlg.cpp
3 // Purpose:     Generic wxCollapsibleHeaderCtrl implementation
4 // Author:      Tobias Taschner
5 // Created:     2015-09-19
6 // Copyright:   (c) 2015 wxWidgets development team
7 // Licence:     wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9 
10 // ----------------------------------------------------------------------------
11 // headers
12 // ----------------------------------------------------------------------------
13 
14 #include "wx/wxprec.h"
15 
16 #include "wx/defs.h"
17 
18 #if wxUSE_COLLPANE
19 
20 #include "wx/collheaderctrl.h"
21 
22 #ifndef WX_PRECOMP
23     #include "wx/dcclient.h"
24     #include "wx/sizer.h"
25 #endif // !WX_PRECOMP
26 
27 #include "wx/renderer.h"
28 
29 #ifdef __WXMSW__
30     #include "wx/msw/private.h"
31 #endif // __WXMSW__
32 
33 // if we have another implementation of this class we should extract
34 // the lines below to a common file
35 
36 const char wxCollapsibleHeaderCtrlNameStr[] = "collapsibleHeader";
37 
38 wxDEFINE_EVENT(wxEVT_COLLAPSIBLEHEADER_CHANGED, wxCommandEvent);
39 
40 // ============================================================================
41 // implementation
42 // ============================================================================
43 
Init()44 void wxGenericCollapsibleHeaderCtrl::Init()
45 {
46     m_collapsed = true;
47     m_inWindow = false;
48     m_mouseDown = false;
49 }
50 
Create(wxWindow * parent,wxWindowID id,const wxString & label,const wxPoint & pos,const wxSize & size,long style,const wxValidator & validator,const wxString & name)51 bool wxGenericCollapsibleHeaderCtrl::Create(wxWindow *parent,
52     wxWindowID id,
53     const wxString& label,
54     const wxPoint& pos,
55     const wxSize& size,
56     long style,
57     const wxValidator& validator,
58     const wxString& name)
59 {
60     if ( !wxCollapsibleHeaderCtrlBase::Create(parent, id, label, pos, size,
61                                               style, validator, name) )
62     {
63         return false;
64     }
65 
66     Bind(wxEVT_PAINT, &wxGenericCollapsibleHeaderCtrl::OnPaint, this);
67     Bind(wxEVT_LEFT_DOWN, &wxGenericCollapsibleHeaderCtrl::OnLeftDown, this);
68     Bind(wxEVT_LEFT_UP, &wxGenericCollapsibleHeaderCtrl::OnLeftUp, this);
69     Bind(wxEVT_ENTER_WINDOW, &wxGenericCollapsibleHeaderCtrl::OnEnterWindow, this);
70     Bind(wxEVT_LEAVE_WINDOW, &wxGenericCollapsibleHeaderCtrl::OnLeaveWindow, this);
71     Bind(wxEVT_CHAR, &wxGenericCollapsibleHeaderCtrl::OnChar, this);
72     Bind(wxEVT_SET_FOCUS, &wxGenericCollapsibleHeaderCtrl::OnFocus, this);
73     Bind(wxEVT_KILL_FOCUS, &wxGenericCollapsibleHeaderCtrl::OnFocus, this);
74 
75     return true;
76 }
77 
DoGetBestClientSize() const78 wxSize wxGenericCollapsibleHeaderCtrl::DoGetBestClientSize() const
79 {
80     wxGenericCollapsibleHeaderCtrl* const
81         self = const_cast<wxGenericCollapsibleHeaderCtrl*>(this);
82 
83     // The code here parallels that of OnPaint() -- except without drawing.
84     wxClientDC dc(self);
85 
86     wxSize size = wxRendererNative::Get().GetCollapseButtonSize(self, dc);
87 
88     wxString text;
89     wxControl::FindAccelIndex(GetLabel(), &text);
90 
91     const wxSize textSize = dc.GetTextExtent(text);
92 
93     size.x += FromDIP(2) + textSize.x;
94     if ( textSize.y > size.y )
95         size.y = textSize.y;
96 
97 #ifdef __WXMSW__
98     size.IncBy(wxGetSystemMetrics(SM_CXFOCUSBORDER, this),
99                wxGetSystemMetrics(SM_CYFOCUSBORDER, this));
100 #endif // __WXMSW__
101 
102     return size;
103 }
104 
SetCollapsed(bool collapsed)105 void wxGenericCollapsibleHeaderCtrl::SetCollapsed(bool collapsed)
106 {
107     m_collapsed = collapsed;
108     Refresh();
109 }
110 
DoSetCollapsed(bool collapsed)111 void wxGenericCollapsibleHeaderCtrl::DoSetCollapsed(bool collapsed)
112 {
113     SetCollapsed(collapsed);
114 
115     wxCommandEvent evt(wxEVT_COLLAPSIBLEHEADER_CHANGED, GetId());
116     evt.SetEventObject(this);
117     ProcessEvent(evt);
118 }
119 
OnFocus(wxFocusEvent & event)120 void wxGenericCollapsibleHeaderCtrl::OnFocus(wxFocusEvent& event)
121 {
122     Refresh();
123     event.Skip();
124 }
125 
OnChar(wxKeyEvent & event)126 void wxGenericCollapsibleHeaderCtrl::OnChar(wxKeyEvent& event)
127 {
128     switch (event.GetKeyCode())
129     {
130     case WXK_SPACE:
131     case WXK_RETURN:
132         DoSetCollapsed(!m_collapsed);
133         break;
134     default:
135         event.Skip();
136         break;
137     }
138 }
139 
OnEnterWindow(wxMouseEvent & event)140 void wxGenericCollapsibleHeaderCtrl::OnEnterWindow(wxMouseEvent& event)
141 {
142     m_inWindow = true;
143     Refresh();
144     event.Skip();
145 }
146 
OnLeaveWindow(wxMouseEvent & event)147 void wxGenericCollapsibleHeaderCtrl::OnLeaveWindow(wxMouseEvent& event)
148 {
149     m_inWindow = false;
150     Refresh();
151     event.Skip();
152 }
153 
OnLeftUp(wxMouseEvent & event)154 void wxGenericCollapsibleHeaderCtrl::OnLeftUp(wxMouseEvent& event)
155 {
156     m_mouseDown = false;
157     DoSetCollapsed(!m_collapsed);
158     event.Skip();
159 }
160 
OnLeftDown(wxMouseEvent & event)161 void wxGenericCollapsibleHeaderCtrl::OnLeftDown(wxMouseEvent& event)
162 {
163     m_mouseDown = true;
164     Refresh();
165     event.Skip();
166 }
167 
OnPaint(wxPaintEvent & WXUNUSED (event))168 void wxGenericCollapsibleHeaderCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
169 {
170     wxPaintDC dc(this);
171 
172     wxRect rect(wxPoint(0, 0), GetClientSize());
173 
174     wxSize btnSize = wxRendererNative::Get().GetCollapseButtonSize(this, dc);
175 
176     wxRect btnRect(wxPoint(0, 0), btnSize);
177     btnRect = btnRect.CenterIn(rect, wxVERTICAL);
178 
179     int flags = 0;
180 
181     if ( m_inWindow )
182         flags |= wxCONTROL_CURRENT;
183 
184     if ( m_mouseDown )
185         flags |= wxCONTROL_PRESSED;
186 
187     if ( !m_collapsed )
188         flags |= wxCONTROL_EXPANDED;
189 
190     wxRendererNative::Get().DrawCollapseButton(this, dc, btnRect, flags);
191 
192     wxString text;
193     int indexAccel = wxControl::FindAccelIndex(GetLabel(), &text);
194 
195     wxSize textSize = dc.GetTextExtent(text);
196 
197     wxRect textRect(wxPoint(btnSize.x + FromDIP(2), 0), textSize);
198     textRect = textRect.CenterIn(rect, wxVERTICAL);
199 
200     dc.DrawLabel(text, textRect, wxALIGN_CENTRE_VERTICAL, indexAccel);
201 
202 #ifdef __WXMSW__
203     if ( HasFocus() )
204         wxRendererNative::Get().DrawFocusRect(this, dc, textRect.Inflate(1), flags);
205 #endif
206 }
207 
208 
209 #endif // wxUSE_COLLPANE
210