]>
Commit | Line | Data |
---|---|---|
56873923 VZ |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // Name: src/common/headerctrlcmn.cpp | |
3 | // Purpose: implementation of wxHeaderCtrlBase | |
4 | // Author: Vadim Zeitlin | |
5 | // Created: 2008-12-02 | |
6 | // RCS-ID: $Id$ | |
7 | // Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org> | |
8 | // Licence: wxWindows licence | |
9 | /////////////////////////////////////////////////////////////////////////////// | |
10 | ||
11 | // ============================================================================ | |
12 | // declarations | |
13 | // ============================================================================ | |
14 | ||
15 | // ---------------------------------------------------------------------------- | |
16 | // headers | |
17 | // ---------------------------------------------------------------------------- | |
18 | ||
19 | // for compilers that support precompilation, includes "wx.h". | |
20 | #include "wx/wxprec.h" | |
21 | ||
22 | #ifdef __BORLANDC__ | |
23 | #pragma hdrstop | |
24 | #endif | |
25 | ||
26 | #ifndef WX_PRECOMP | |
27 | #endif // WX_PRECOMP | |
28 | ||
29 | #include "wx/headerctrl.h" | |
30 | ||
e2bfe673 VZ |
31 | // ---------------------------------------------------------------------------- |
32 | // constants | |
33 | // ---------------------------------------------------------------------------- | |
34 | ||
35 | namespace | |
36 | { | |
37 | ||
38 | const unsigned int wxNO_COLUMN = static_cast<unsigned>(-1); | |
39 | ||
40 | } // anonymous namespace | |
41 | ||
56873923 VZ |
42 | // ============================================================================ |
43 | // wxHeaderCtrlBase implementation | |
44 | // ============================================================================ | |
45 | ||
9a382f1f | 46 | extern WXDLLIMPEXP_DATA_CORE(const char) wxHeaderCtrlNameStr[] = "wxHeaderCtrl"; |
56873923 | 47 | |
3bfaa5a7 VZ |
48 | BEGIN_EVENT_TABLE(wxHeaderCtrlBase, wxControl) |
49 | EVT_HEADER_SEPARATOR_DCLICK(wxID_ANY, wxHeaderCtrlBase::OnSeparatorDClick) | |
50 | END_EVENT_TABLE() | |
51 | ||
d8fc3398 VZ |
52 | void wxHeaderCtrlBase::ScrollWindow(int dx, |
53 | int WXUNUSED_UNLESS_DEBUG(dy), | |
54 | const wxRect * WXUNUSED_UNLESS_DEBUG(rect)) | |
55 | ||
56 | { | |
57 | // this doesn't make sense at all | |
58 | wxASSERT_MSG( !dy, "header window can't be scrolled vertically" ); | |
59 | ||
60 | // this would actually be nice to support for "frozen" headers but it isn't | |
61 | // supported currently | |
62 | wxASSERT_MSG( !rect, "header window can't be scrolled partially" ); | |
63 | ||
64 | DoScrollHorz(dx); | |
65 | } | |
66 | ||
4635abac VZ |
67 | void wxHeaderCtrlBase::SetColumnCount(unsigned int count) |
68 | { | |
69 | OnColumnCountChanging(count); | |
70 | ||
71 | DoSetCount(count); | |
72 | } | |
73 | ||
702f5349 VZ |
74 | // ---------------------------------------------------------------------------- |
75 | // wxHeaderCtrlBase event handling | |
76 | // ---------------------------------------------------------------------------- | |
77 | ||
3bfaa5a7 VZ |
78 | void wxHeaderCtrlBase::OnSeparatorDClick(wxHeaderCtrlEvent& event) |
79 | { | |
80 | const unsigned col = event.GetColumn(); | |
81 | ||
82 | int w = wxWindowBase::GetTextExtent(GetColumn(col).GetTitle()).x; | |
f458d4dd | 83 | w += 4*GetCharWidth(); // add some arbitrary margins around text |
3bfaa5a7 VZ |
84 | |
85 | if ( !UpdateColumnWidthToFit(col, w) ) | |
86 | event.Skip(); | |
87 | else | |
88 | UpdateColumn(col); | |
89 | } | |
90 | ||
702f5349 VZ |
91 | // ---------------------------------------------------------------------------- |
92 | // wxHeaderCtrlBase column reordering | |
93 | // ---------------------------------------------------------------------------- | |
94 | ||
95 | void wxHeaderCtrlBase::SetColumnsOrder(const wxArrayInt& order) | |
96 | { | |
97 | const unsigned count = GetColumnCount(); | |
98 | wxCHECK_RET( order.size() == count, "wrong number of columns" ); | |
99 | ||
100 | // check the array validity | |
101 | wxArrayInt seen(count, 0); | |
102 | for ( unsigned n = 0; n < count; n++ ) | |
103 | { | |
104 | const unsigned idx = order[n]; | |
105 | wxCHECK_RET( idx < count, "invalid column index" ); | |
106 | wxCHECK_RET( !seen[idx], "duplicate column index" ); | |
107 | ||
108 | seen[idx] = 1; | |
109 | } | |
110 | ||
111 | DoSetColumnsOrder(order); | |
112 | ||
113 | // TODO-RTL: do we need to reverse the array? | |
114 | } | |
115 | ||
116 | wxArrayInt wxHeaderCtrlBase::GetColumnsOrder() const | |
117 | { | |
118 | const wxArrayInt order = DoGetColumnsOrder(); | |
119 | ||
120 | wxASSERT_MSG( order.size() == GetColumnCount(), "invalid order array" ); | |
121 | ||
122 | return order; | |
123 | } | |
124 | ||
125 | unsigned int wxHeaderCtrlBase::GetColumnAt(unsigned int pos) const | |
126 | { | |
127 | wxCHECK_MSG( pos < GetColumnCount(), wxNO_COLUMN, "invalid position" ); | |
128 | ||
129 | return GetColumnsOrder()[pos]; | |
130 | } | |
131 | ||
132 | unsigned int wxHeaderCtrlBase::GetColumnPos(unsigned int idx) const | |
133 | { | |
134 | const unsigned count = GetColumnCount(); | |
135 | ||
136 | wxCHECK_MSG( idx < count, wxNO_COLUMN, "invalid index" ); | |
137 | ||
138 | const wxArrayInt order = GetColumnsOrder(); | |
139 | for ( unsigned n = 0; n < count; n++ ) | |
140 | { | |
141 | if ( (unsigned)order[n] == idx ) | |
142 | return n; | |
143 | } | |
144 | ||
145 | wxFAIL_MSG( "column unexpectedly not displayed at all" ); | |
146 | ||
147 | return wxNO_COLUMN; | |
148 | } | |
149 | ||
1bb74626 VZ |
150 | /* static */ |
151 | void wxHeaderCtrlBase::MoveColumnInOrderArray(wxArrayInt& order, | |
152 | unsigned int idx, | |
153 | unsigned int pos) | |
154 | { | |
155 | const unsigned count = order.size(); | |
156 | ||
157 | wxArrayInt orderNew; | |
158 | orderNew.reserve(count); | |
159 | for ( unsigned n = 0; ; n++ ) | |
160 | { | |
161 | // NB: order of checks is important for this to work when the new | |
162 | // column position is the same as the old one | |
163 | ||
164 | // insert the column at its new position | |
165 | if ( orderNew.size() == pos ) | |
166 | orderNew.push_back(idx); | |
167 | ||
168 | if ( n == count ) | |
169 | break; | |
170 | ||
171 | // delete the column from its old position | |
172 | const unsigned idxOld = order[n]; | |
173 | if ( idxOld == idx ) | |
174 | continue; | |
175 | ||
176 | orderNew.push_back(idxOld); | |
177 | } | |
178 | ||
179 | order.swap(orderNew); | |
180 | } | |
181 | ||
e2bfe673 VZ |
182 | // ============================================================================ |
183 | // wxHeaderCtrlSimple implementation | |
184 | // ============================================================================ | |
185 | ||
186 | void wxHeaderCtrlSimple::Init() | |
187 | { | |
188 | m_sortKey = wxNO_COLUMN; | |
189 | } | |
190 | ||
dcb6cbec | 191 | wxHeaderColumn& wxHeaderCtrlSimple::GetColumn(unsigned int idx) |
e2bfe673 VZ |
192 | { |
193 | return m_cols[idx]; | |
194 | } | |
195 | ||
196 | void wxHeaderCtrlSimple::DoInsert(const wxHeaderColumnSimple& col, unsigned int idx) | |
197 | { | |
198 | m_cols.insert(m_cols.begin() + idx, col); | |
199 | ||
200 | UpdateColumnCount(); | |
201 | } | |
202 | ||
203 | void wxHeaderCtrlSimple::DoDelete(unsigned int idx) | |
204 | { | |
205 | m_cols.erase(m_cols.begin() + idx); | |
206 | if ( idx == m_sortKey ) | |
207 | m_sortKey = wxNO_COLUMN; | |
208 | ||
209 | UpdateColumnCount(); | |
210 | } | |
211 | ||
212 | void wxHeaderCtrlSimple::DeleteAllColumns() | |
213 | { | |
214 | m_cols.clear(); | |
215 | m_sortKey = wxNO_COLUMN; | |
216 | ||
217 | UpdateColumnCount(); | |
218 | } | |
219 | ||
220 | ||
221 | void wxHeaderCtrlSimple::DoShowColumn(unsigned int idx, bool show) | |
222 | { | |
223 | if ( show != m_cols[idx].IsShown() ) | |
224 | { | |
225 | m_cols[idx].SetHidden(!show); | |
226 | ||
227 | UpdateColumn(idx); | |
228 | } | |
229 | } | |
230 | ||
231 | void wxHeaderCtrlSimple::DoShowSortIndicator(unsigned int idx, bool ascending) | |
232 | { | |
233 | RemoveSortIndicator(); | |
234 | ||
235 | m_cols[idx].SetAsSortKey(ascending); | |
236 | m_sortKey = idx; | |
237 | ||
238 | UpdateColumn(idx); | |
239 | } | |
240 | ||
241 | void wxHeaderCtrlSimple::RemoveSortIndicator() | |
242 | { | |
243 | if ( m_sortKey != wxNO_COLUMN ) | |
244 | { | |
245 | const unsigned sortOld = m_sortKey; | |
246 | m_sortKey = wxNO_COLUMN; | |
247 | ||
248 | m_cols[sortOld].UnsetAsSortKey(); | |
249 | ||
250 | UpdateColumn(sortOld); | |
251 | } | |
252 | } | |
253 | ||
e5a16353 VZ |
254 | bool |
255 | wxHeaderCtrlSimple::UpdateColumnWidthToFit(unsigned int idx, int widthTitle) | |
256 | { | |
257 | const int widthContents = GetBestFittingWidth(idx); | |
258 | if ( widthContents == -1 ) | |
259 | return false; | |
260 | ||
261 | m_cols[idx].SetWidth(wxMax(widthContents, widthTitle)); | |
e5a16353 VZ |
262 | |
263 | return true; | |
264 | } | |
265 | ||
fa3d4aaf VZ |
266 | // ============================================================================ |
267 | // wxHeaderCtrlEvent implementation | |
268 | // ============================================================================ | |
269 | ||
270 | IMPLEMENT_DYNAMIC_CLASS(wxHeaderCtrlEvent, wxNotifyEvent) | |
271 | ||
272 | const wxEventType wxEVT_COMMAND_HEADER_CLICK = wxNewEventType(); | |
273 | const wxEventType wxEVT_COMMAND_HEADER_RIGHT_CLICK = wxNewEventType(); | |
274 | const wxEventType wxEVT_COMMAND_HEADER_MIDDLE_CLICK = wxNewEventType(); | |
275 | ||
276 | const wxEventType wxEVT_COMMAND_HEADER_DCLICK = wxNewEventType(); | |
277 | const wxEventType wxEVT_COMMAND_HEADER_RIGHT_DCLICK = wxNewEventType(); | |
278 | const wxEventType wxEVT_COMMAND_HEADER_MIDDLE_DCLICK = wxNewEventType(); | |
3bfaa5a7 VZ |
279 | |
280 | const wxEventType wxEVT_COMMAND_HEADER_SEPARATOR_DCLICK = wxNewEventType(); | |
aef252d9 | 281 | |
396825dc VZ |
282 | const wxEventType wxEVT_COMMAND_HEADER_BEGIN_RESIZE = wxNewEventType(); |
283 | const wxEventType wxEVT_COMMAND_HEADER_RESIZING = wxNewEventType(); | |
284 | const wxEventType wxEVT_COMMAND_HEADER_END_RESIZE = wxNewEventType(); | |
702f5349 VZ |
285 | |
286 | const wxEventType wxEVT_COMMAND_HEADER_BEGIN_REORDER = wxNewEventType(); | |
287 | const wxEventType wxEVT_COMMAND_HEADER_END_REORDER = wxNewEventType(); | |
565804f2 VZ |
288 | |
289 | const wxEventType wxEVT_COMMAND_HEADER_DRAGGING_CANCELLED = wxNewEventType(); |