1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wx/headerctrl.h
3 // Purpose: interface of wxHeaderCtrl
4 // Author: Vadim Zeitlin
7 // Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
14 // allow column drag and drop
15 wxHD_ALLOW_REORDER
= 0x0001,
17 // allow hiding (and showing back) the columns using the menu shown by
18 // right clicking the header
19 wxHD_ALLOW_HIDE
= 0x0002,
21 // style used by default when creating the control
22 wxHD_DEFAULT_STYLE
= wxHD_ALLOW_REORDER
30 wxHeaderCtrl is the control containing the column headings which is usually
31 used for display of tabular data.
33 It is used as part of wxGrid, in generic version wxDataViewCtrl and report
34 view of wxListCtrl but can be also used independently. In general this
35 class is meant to be used as part of another control which already stores
36 the column information somewhere as it can't be used directly: instead you
37 need to inherit from it and implement the GetColumn() method to provide
38 column information. See wxHeaderCtrlSimple for a concrete control class
39 which can be used directly.
41 In addition to labeling the columns, the control has the following
43 - Column reordering support, either by explicitly configuring the
44 columns order and calling SetColumnsOrder() or by dragging the
45 columns interactively (if enabled).
46 - Display of the icons in the header: this is often used to display a
47 sort or reverse sort indicator when the column header is clicked.
49 Notice that this control itself doesn't do anything other than displaying
50 the column headers. In particular column reordering and sorting must still
51 be supported by the associated control displaying the real data under the
52 header. Also remember to call ScrollWindow() method of the control if the
53 associated data display window has a horizontal scrollbar, otherwise the
54 headers wouldn't align with the data when the window is scrolled.
56 This control is implemented using the native header control under MSW
57 systems and a generic implementation elsewhere.
60 @section headerctrl_improvements Future Improvements
62 Some features are supported by the native MSW control and so could be
63 easily implemented in this version of wxHeaderCtrl but need to be
64 implemented in the generic version as well to be really useful. Please let
65 us know if you need or, better, plan to work on implementing, any of them:
66 - Displaying bitmaps instead of or together with the text
67 - Custom drawn headers
68 - Filters associated with a column.
72 @style{wxHD_ALLOW_REORDER}
73 If this style is specified (it is by default), the user can reorder
74 the control columns by dragging them.
75 @style{wxHD_ALLOW_HIDE}
76 If this style is specified, the control shows a popup menu allowing the
77 user to change the columns visibility on right mouse click. Notice that
78 the program can always hide or show the columns, this style only
79 affects the users capability to do it.
80 @style{wxHD_DEFAULT_STYLE}
81 Symbolic name for the default control style, currently equal to
82 @c wxHD_ALLOW_REORDER.
85 @beginEventEmissionTable{wxHeaderCtrlEvent}
86 @event{EVT_HEADER_CLICK(id, func)}
87 A column heading was clicked.
88 @event{EVT_HEADER_RIGHT_CLICK(id, func)}
89 A column heading was right clicked.
90 @event{EVT_HEADER_MIDDLE_CLICK(id, func)}
91 A column heading was clicked with the middle mouse button.
92 @event{EVT_HEADER_DCLICK(id, func)}
93 A column heading was double clicked.
94 @event{EVT_HEADER_RIGHT_DCLICK(id, func)}
95 A column heading was right double clicked.
96 @event{EVT_HEADER_MIDDLE_DCLICK(id, func)}
97 A column heading was double clicked with the middle mouse button.
98 @event{EVT_HEADER_SEPARATOR_DCLICK(id, func)}
99 Separator to the right of the specified column was double clicked
100 (this action is commonly used to resize the column to fit its
101 contents width and the control provides UpdateColumnWidthToFit() method
102 to make implementing this easier).
103 @event{EVT_HEADER_BEGIN_RESIZE(id, func)}
104 The user started to drag the separator to the right of the column
105 with the specified index (this can only happen for the columns for
106 which wxHeaderColumn::IsResizeable() returns true). The event can
107 be vetoed to prevent the column from being resized. If it isn't,
108 the resizing and end resize (or dragging cancelled) events will be
110 @event{EVT_HEADER_RESIZING(id, func)}
111 The user is dragging the column with the specified index resizing
112 it and its current width is wxHeaderCtrlEvent::GetWidth().
113 The event can be vetoed to stop the dragging operation completely at
115 @event{EVT_HEADER_END_RESIZE(id, func)}
116 The user stopped dragging the column by releasing the mouse.
117 The column should normally be resized to the value of
118 wxHeaderCtrlEvent::GetWidth().
119 @event{EVT_HEADER_BEGIN_REORDER(id, func)}
120 The user started to drag the column with the specified index (this
121 can only happen for the controls with wxHD_ALLOW_REORDER style).
122 This event can be vetoed to prevent the column from being reordered,
123 otherwise the end reorder message will be generated later.
124 @event{EVT_HEADER_END_REORDER(id, func)}
125 The user dropped the column in its new location. The event can be
126 vetoed to prevent the column from being placed at the new position
127 or handled to update the display of the data in the associated
128 control to match the new column location (available from
129 wxHeaderCtrlEvent::GetNewOrder()).
130 @event{EVT_HEADER_DRAGGING_CANCELLED(id, func)}
131 The resizing or reordering operation currently in progress was
132 cancelled. This can happen if the user pressed Esc key while
133 dragging the mouse or the mouse capture was lost for some other
134 reason. You only need to handle this event if your application
135 entered into some modal mode when resizing or reordering began, in
136 which case it should handle this event in addition to the matching
137 end resizing or reordering ones.
143 @see wxGrid, wxListCtrl, wxDataViewCtrl
145 class wxHeaderCtrl
: public wxControl
149 Default constructor not creating the underlying window.
151 You must use Create() after creating the object using this constructor.
156 Constructor creating the window.
158 Please see Create() for the parameters documentation.
160 wxHeaderCtrl(wxWindow
*parent
,
161 wxWindowID winid
= wxID_ANY
,
162 const wxPoint
& pos
= wxDefaultPosition
,
163 const wxSize
& size
= wxDefaultSize
,
164 long style
= wxHD_DEFAULT_STYLE
,
165 const wxString
& name
= wxHeaderCtrlNameStr
);
168 Create the header control window.
171 The parent window. The header control should be typically
172 positioned along the top edge of this window.
174 Id of the control or @c wxID_ANY if you don't care.
176 The initial position of the control.
178 The initial size of the control (usually not very useful as this
179 control will typically be resized to have the same width as the
180 associated data display control).
182 The control style, @c wxHD_DEFAULT_STYLE by default. Notice that
183 the default style allows the user to reorder the columns by
184 dragging them and you need to explicitly turn this feature off by
185 using @code wxHD_DEFAULT_STYLE & ~wxHD_ALLOW_REORDER @endcode if
188 The name of the control.
190 bool Create(wxWindow
*parent
,
191 wxWindowID winid
= wxID_ANY
,
192 const wxPoint
& pos
= wxDefaultPosition
,
193 const wxSize
& size
= wxDefaultSize
,
194 long style
= wxHD_DEFAULT_STYLE
,
195 const wxString
& name
= wxHeaderCtrlNameStr
);
198 Set the number of columns in the control.
200 The control will use GetColumn() to get information about all the
201 new columns and refresh itself, i.e. this method also has the same
202 effect as calling UpdateColumn() for all columns but it should only be
203 used if the number of columns really changed.
205 void SetColumnCount(unsigned int count
);
208 Return the number of columns in the control.
211 Number of columns as previously set by SetColumnCount().
215 unsigned int GetColumnCount() const;
218 Return whether the control has any columns.
220 @see GetColumnCount()
222 bool IsEmpty() const;
225 Update the column with the given index.
227 When the value returned by GetColumn() changes, this method must be
228 called to notify the control about the change and update the visual
229 display to match the new column data.
232 The column index, must be less than GetColumnCount().
234 void UpdateColumn(unsigned int idx
);
237 Change the columns display order.
239 The display order defines the order in which the columns appear on the
240 screen and does @em not affect the interpretation of indices by all the
243 The @a order array specifies the column indices corresponding to the
247 A permutation of all column indices, i.e. an array of size
248 GetColumnsOrder() containing all column indices exactly once. The
249 n-th element of this array defines the index of the column shown at
250 the n-th position from left (for the default left-to-right writing
253 @see wxListCtrl::SetColumnsOrder()
255 void SetColumnsOrder(const wxArrayInt
& order
);
258 Return the array describing the columns display order.
260 For the controls without wxHD_ALLOW_REORDER style the returned array
261 will be the same as was passed to SetColumnsOrder() previously or
262 define the default order (with n-th element being n) if it hadn't been
263 called. But for the controls with wxHD_ALLOW_REORDER style, the columns
264 can be also reordered by user.
266 wxArrayInt
GetColumnsOrder() const;
269 Return the index of the column displayed at the given position.
272 The display position, e.g. 0 for the left-most column, 1 for the
273 next one and so on until GetColumnCount() - 1.
277 unsigned int GetColumnAt(unsigned int pos
) const;
280 Get the position at which this column is currently displayed.
282 Notice that a valid position is returned even for the hidden columns
286 The column index, must be less than GetColumnCount().
290 unsigned int GetColumnPos(unsigned int idx
) const;
293 Reset the columns order to the natural one.
295 After calling this function, the column with index @c idx appears at
296 position @c idx in the control.
298 void ResetColumnsOrder();
301 Helper function to manipulate the array of column indices.
303 This function reshuffles the array of column indices indexed by
304 positions (i.e. using the same convention as for SetColumnsOrder()) so
305 that the column with the given index is found at the specified
309 Array containing the indices of columns in order of their
312 The index of the column to move.
314 The new position for the column @a idx.
316 static void MoveColumnInOrderArray(wxArrayInt
& order
,
321 Show the popup menu allowing the user to show or hide the columns.
323 This functions shows the popup menu containing all columns with check
324 marks for the ones which are currently shown and allows the user to
325 check or uncheck them to toggle their visibility. It is called from the
326 default EVT_HEADER_RIGHT_CLICK handler for the controls which have
327 wxHD_ALLOW_HIDE style. And if the column has wxHD_ALLOW_REORDER style
328 as well, the menu also contains an item to customize the columns shown
329 using which results in ShowCustomizeDialog() being called, please see
330 its description for more details.
332 If a column was toggled, UpdateColumnVisibility() virtual function is
333 called so it must be implemented for the controls with wxHD_ALLOW_HIDE
334 style or if you call this function explicitly.
337 The position of the menu, in the header window coordinates.
339 The title for the menu if not empty.
341 @true if a column was shown or hidden or @false if nothing was
342 done, e.g. because the menu was cancelled.
344 bool ShowColumnsMenu(const wxPoint
& pt
, const wxString
& title
= wxString());
347 Helper function appending the checkable items corresponding to all the
348 columns to the given menu.
350 This function is used by ShowColumnsMenu() but can also be used if you
351 show your own custom columns menu and still want all the columns shown
352 in it. It appends menu items with column labels as their text and
353 consecutive ids starting from @a idColumnsBase to the menu and checks
354 the items corresponding to the currently visible columns.
359 menu.Append(100, "Some custom command");
360 menu.AppendSeparator();
361 AddColumnsItems(menu, 200);
362 const int rc = GetPopupMenuSelectionFromUser(menu, pt);
364 ... toggle visibility of the column rc-200 ...
368 The menu to append the items to. It may be currently empty or not.
370 The id for the menu item corresponding to the first column, the
371 other ones are consecutive starting from it. It should be positive.
373 void AddColumnsItems(wxMenu
& menu
, int idColumnsBase
= 0);
376 Show the column customization dialog.
378 This function displays a modal dialog containing the list of all
379 columns which the user can use to reorder them as well as show or hide
382 If the user accepts the changes done in the dialog, the virtual
383 methods UpdateColumnVisibility() and UpdateColumnsOrder() will be
384 called so they must be overridden in the derived class if this method
385 is ever called. Please notice that the user will be able to invoke it
386 interactively from the header popup menu if the control has both
387 wxHD_ALLOW_HIDE and wxHD_ALLOW_REORDER styles.
389 @see wxRearrangeDialog
391 bool ShowCustomizeDialog();
394 Returns width needed for given column's title.
398 int GetColumnTitleWidth(const wxHeaderColumn
& col
);
402 Method to be implemented by the derived classes to return the
403 information for the given column.
406 The column index, between 0 and the value last passed to
409 virtual const wxHeaderColumn
& GetColumn(unsigned int idx
) const = 0;
412 Method called when the column visibility is changed by the user.
414 This method is called from ShowColumnsMenu() or ShowCustomizeDialog()
415 when the user interactively hides or shows a column. A typical
416 implementation will simply update the internally stored column state.
417 Notice that there is no need to call UpdateColumn() from this method as
418 it is already done by wxHeaderCtrl itself.
420 The base class version doesn't do anything and must be overridden if
421 this method is called.
424 The index of the column whose visibility was toggled.
426 The new visibility value, @true if the column is now shown or
427 @false if it is not hidden.
429 virtual void UpdateColumnVisibility(unsigned int idx
, bool show
);
432 Method called when the columns order is changed in the customization
435 This method is only called from ShowCustomizeDialog() when the user
436 changes the order of columns. In particular it is @em not called if a
437 single column changes place because the user dragged it to the new
438 location, the EVT_HEADER_END_REORDER event handler should be used to
441 A typical implementation in a derived class will update the display
442 order of the columns in the associated control, if any. Notice that
443 there is no need to call SetColumnsOrder() from it as wxHeaderCtrl does
446 The base class version doesn't do anything and must be overridden if
447 this method is called.
450 The new column order. This array uses the same convention as
453 virtual void UpdateColumnsOrder(const wxArrayInt
& order
);
456 Method which may be implemented by the derived classes to allow double
457 clicking the column separator to resize the column to fit its contents.
459 When a separator is double clicked, the default handler of
460 EVT_HEADER_SEPARATOR_DCLICK event calls this function and refreshes the
461 column if it returns @true so to implement the resizing of the column
462 to fit its width on header double click you need to implement this
463 method using logic similar to this example:
465 class MyHeaderColumn : public wxHeaderColumn
470 void SetWidth(int width) { m_width = width; }
471 virtual int GetWidth() const { return m_width; }
477 class MyHeaderCtrl : public wxHeaderCtrl
481 virtual wxHeaderColumn& GetColumn(unsigned int idx) const
486 virtual bool UpdateColumnWidthToFit(unsigned int idx, int widthTitle)
488 int widthContents = ... compute minimal width for column idx ...
489 m_cols[idx].SetWidth(wxMax(widthContents, widthTitle));
493 wxVector<MyHeaderColumn> m_cols;
497 Base class version simply returns @false.
500 The zero-based index of the column to update.
502 Contains minimal width needed to display the column header itself
503 and will usually be used as a starting point for the fitting width
507 @true to indicate that the column was resized, i.e. GetColumn() now
508 returns the new width value, and so must be refreshed or @false
509 meaning that the control didn't reach to the separator double click.
511 virtual bool UpdateColumnWidthToFit(unsigned int idx
, int widthTitle
);
514 Can be overridden in the derived class to update internal data
515 structures when the number of the columns in the control changes.
517 This method is called by SetColumnCount() before effectively changing
518 the number of columns.
520 The base class version does nothing but it is good practice to still
521 call it from the overridden version in the derived class.
523 virtual void OnColumnCountChanging(unsigned int count
);
528 @class wxHeaderCtrlSimple
530 wxHeaderCtrlSimple is a concrete header control which can be used directly,
531 without inheriting from it as you need to do when using wxHeaderCtrl
534 When using it, you need to use simple AppendColumn(), InsertColumn() and
535 DeleteColumn() methods instead of setting the number of columns with
536 SetColumnCount() and returning the information about them from the
537 overridden GetColumn().
544 class wxHeaderCtrlSimple
: public wxHeaderCtrl
548 Default constructor not creating the underlying window.
550 You must use Create() after creating the object using this constructor.
552 wxHeaderCtrlSimple();
555 Constructor creating the window.
557 Please see the base class wxHeaderCtrl::Create() method for the
558 parameters description.
560 wxHeaderCtrlSimple(wxWindow
*parent
,
561 wxWindowID winid
= wxID_ANY
,
562 const wxPoint
& pos
= wxDefaultPosition
,
563 const wxSize
& size
= wxDefaultSize
,
564 long style
= wxHD_DEFAULT_STYLE
,
565 const wxString
& name
= wxHeaderCtrlNameStr
);
568 Insert the column at the given position.
571 The column to insert. Notice that because of the existence of
572 implicit conversion from wxString to wxHeaderColumn a string
573 can be passed directly here.
575 The position of the new column, from 0 to GetColumnCount(). Using
576 GetColumnCount() means to append the column to the end.
580 void InsertColumn(const wxHeaderColumnSimple
& col
, unsigned int idx
);
583 Append the column to the end of the control.
587 void AppendColumn(const wxHeaderColumnSimple
& col
);
590 Delete the column at the given position.
592 @see InsertColumn(), AppendColumn()
594 void DeleteColumn(unsigned int idx
);
597 Show or hide the column.
599 Initially the column is shown by default or hidden if it was added with
600 wxCOL_HIDDEN flag set.
602 When a column is hidden, it doesn't appear at all on the screen but its
603 index is still taken into account when working with other columns. E.g.
604 if there are three columns 0, 1 and 2 and the column 1 is hidden you
605 still need to use index 2 to refer to the last visible column.
608 The index of the column to show or hide, from 0 to GetColumnCount().
610 Indicates whether the column should be shown (default) or hidden.
612 void ShowColumn(unsigned int idx
, bool show
= true);
615 Hide the column with the given index.
617 This is the same as calling @code ShowColumn(idx, false) @endcode.
620 The index of the column to show or hide, from 0 to GetColumnCount().
622 void HideColumn(unsigned int idx
);
625 Update the column sort indicator.
627 The sort indicator, if shown, is typically an arrow pointing upwards or
628 downwards depending on whether the control contents is sorted in
629 ascending or descending order.
632 The column to set the sort indicator for.
633 If @c -1 is given, then the currently shown sort indicator
636 If @true or @false show the sort indicator corresponding to
637 ascending or descending sort order respectively.
639 void ShowSortIndicator(unsigned int idx
, bool sortOrder
= true);
642 Remove the sort indicator from the column being used as sort key.
644 @see ShowSortIndicator
646 void RemoveSortIndicator();
650 This function can be overridden in the classes deriving from this
651 control instead of overriding UpdateColumnWidthToFit().
653 To implement automatic column resizing to fit its contents width when
654 the column divider is double clicked, you need to simply return the
655 fitting width for the given column @a idx from this method, the control
656 will automatically use the biggest value between the one returned from
657 here and the one needed for the display of the column title itself.
659 The base class version returns -1 indicating that this function is not
662 virtual int GetBestFittingWidth(unsigned int idx
) const;
666 @class wxHeaderCtrlEvent
668 Event class representing the events generated by wxHeaderCtrl.
675 class wxHeaderCtrlEvent
: public wxNotifyEvent
678 wxHeaderCtrlEvent(wxEventType commandType
= wxEVT_NULL
, int winid
= 0);
679 wxHeaderCtrlEvent(const wxHeaderCtrlEvent
& event
);
682 Return the index of the column affected by this event.
684 This method can be called for all header control events.
686 int GetColumn() const;
687 void SetColumn(int col
);
690 Return the current width of the column.
692 This method can only be called for the dragging events.
694 int GetWidth() const;
695 void SetWidth(int width
);
698 Return the new order of the column.
700 This method can only be called for a reorder event for which it
701 indicates the tentative new position for the column GetColumn()
702 selected by the user. If the event is not vetoed, this will become the
703 new column position in wxHeaderCtrl::GetColumnsOrder().
705 unsigned int GetNewOrder() const;
706 void SetNewOrder(unsigned int order
);
711 wxEventType wxEVT_HEADER_CLICK
;
712 wxEventType wxEVT_HEADER_RIGHT_CLICK
;
713 wxEventType wxEVT_HEADER_MIDDLE_CLICK
;
714 wxEventType wxEVT_HEADER_DCLICK
;
715 wxEventType wxEVT_HEADER_RIGHT_DCLICK
;
716 wxEventType wxEVT_HEADER_MIDDLE_DCLICK
;
717 wxEventType wxEVT_HEADER_SEPARATOR_DCLICK
;
718 wxEventType wxEVT_HEADER_BEGIN_RESIZE
;
719 wxEventType wxEVT_HEADER_RESIZING
;
720 wxEventType wxEVT_HEADER_END_RESIZE
;
721 wxEventType wxEVT_HEADER_BEGIN_REORDER
;
722 wxEventType wxEVT_HEADER_END_REORDER
;
723 wxEventType wxEVT_HEADER_DRAGGING_CANCELLED
;