X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1efd7bc655b04d424ba5fb42d1f281edceff7b2a..e4097f77c440b1f31a80fe273cc732c14d606096:/interface/wx/headerctrl.h diff --git a/interface/wx/headerctrl.h b/interface/wx/headerctrl.h index f8f23a8aed..662d20df0e 100644 --- a/interface/wx/headerctrl.h +++ b/interface/wx/headerctrl.h @@ -3,24 +3,39 @@ // Purpose: interface of wxHeaderCtrl // Author: Vadim Zeitlin // Created: 2008-12-01 -// RCS-ID: $Id$ // Copyright: (c) 2008 Vadim Zeitlin -// Licence: wxWindows license +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// + +enum +{ + // allow column drag and drop + wxHD_ALLOW_REORDER = 0x0001, + + // allow hiding (and showing back) the columns using the menu shown by + // right clicking the header + wxHD_ALLOW_HIDE = 0x0002, + + // style used by default when creating the control + wxHD_DEFAULT_STYLE = wxHD_ALLOW_REORDER +}; + + + /** @class wxHeaderCtrl wxHeaderCtrl is the control containing the column headings which is usually used for display of tabular data. - It is used as part of wxGrid and (will be used in the near future) in - in wxDataViewCtrl and report view of wxListCtrl but can be also used - independently. In general this class is meant to be used as part of another - control which already stores the column information somewhere as it can't - be used directly: instead you need to inherit from it and implement the - GetColumn() method to provide column information. See wxHeaderCtrlSimple - for a concrete control class which can be used directly. + It is used as part of wxGrid, in generic version wxDataViewCtrl and report + view of wxListCtrl but can be also used independently. In general this + class is meant to be used as part of another control which already stores + the column information somewhere as it can't be used directly: instead you + need to inherit from it and implement the GetColumn() method to provide + column information. See wxHeaderCtrlSimple for a concrete control class + which can be used directly. In addition to labeling the columns, the control has the following features: @@ -40,59 +55,6 @@ This control is implemented using the native header control under MSW systems and a generic implementation elsewhere. - @beginStyleTable - @style{wxHD_DRAGDROP} - If this style is specified (it is by default), the user can reorder - the control columns by dragging them. - @style{wxHD_DEFAULT_STYLE} - Symbolic name for the default control style, currently equal to @c - wxHD_DRAGDROP. - @endStyleTable - - @beginEventTable{wxHeaderCtrlEvent} - @event{EVT_HEADER_CLICK(id, func)} - A column heading was clicked. - @event{EVT_HEADER_RIGHT_CLICK(id, func)} - A column heading was right clicked. - @event{EVT_HEADER_MIDDLE_CLICK(id, func)} - A column heading was clicked with the middle mouse button. - - @event{EVT_HEADER_DCLICK(id, func)} - A column heading was double clicked. - @event{EVT_HEADER_RIGHT_DCLICK(id, func)} - A column heading was right double clicked. - @event{EVT_HEADER_MIDDLE_DCLICK(id, func)} - A column heading was double clicked with the middle mouse button. - - @event{EVT_HEADER_SEPARATOR_DCLICK(id, func)} - Separator to the right of the specified column was double clicked - (this action is commonly used to resize the column to fit its - contents width and the control provides UpdateColumnWidthToFit() method - to make implementing this easier). - - @event{EVT_HEADER_BEGIN_RESIZE(id, func)} - The user started to drag the separator to the right of the column - with the specified index (this can only happen for the columns for - which wxHeaderColumn::IsResizeable() returns true). The event can - be vetoed to prevent the column from being resized. If it isn't, - the resizing and end resize events will be generated later. - @event{EVT_HEADER_RESIZING(id, func)} - The user is dragging the column with the specified index resizing - it and its current width is wxHeaderCtrlEvent::GetWidth(). The - event can be vetoed to stop the dragging operation completely at - any time. - @event{EVT_HEADER_END_RESIZE(id, func)} - Either the user stopped dragging the column by releasing the mouse - or the resizing was cancelled. If wxHeaderCtrlEvent::IsCancelled() - returns @true, nothing should be done, otherwise the column should - normally be resized to the value of wxHeaderCtrlEvent::GetWidth(). - @endEventTable - - @library{wxcore} - @category{ctrl} - - @see wxGrid, wxListCtrl, wxDataViewCtrl - @section headerctrl_improvements Future Improvements @@ -103,8 +65,83 @@ - Displaying bitmaps instead of or together with the text - Custom drawn headers - Filters associated with a column. + + + @beginStyleTable + @style{wxHD_ALLOW_REORDER} + If this style is specified (it is by default), the user can reorder + the control columns by dragging them. + @style{wxHD_ALLOW_HIDE} + If this style is specified, the control shows a popup menu allowing the + user to change the columns visibility on right mouse click. Notice that + the program can always hide or show the columns, this style only + affects the users capability to do it. + @style{wxHD_DEFAULT_STYLE} + Symbolic name for the default control style, currently equal to + @c wxHD_ALLOW_REORDER. + @endStyleTable + + @beginEventEmissionTable{wxHeaderCtrlEvent} + @event{EVT_HEADER_CLICK(id, func)} + A column heading was clicked. + @event{EVT_HEADER_RIGHT_CLICK(id, func)} + A column heading was right clicked. + @event{EVT_HEADER_MIDDLE_CLICK(id, func)} + A column heading was clicked with the middle mouse button. + @event{EVT_HEADER_DCLICK(id, func)} + A column heading was double clicked. + @event{EVT_HEADER_RIGHT_DCLICK(id, func)} + A column heading was right double clicked. + @event{EVT_HEADER_MIDDLE_DCLICK(id, func)} + A column heading was double clicked with the middle mouse button. + @event{EVT_HEADER_SEPARATOR_DCLICK(id, func)} + Separator to the right of the specified column was double clicked + (this action is commonly used to resize the column to fit its + contents width and the control provides UpdateColumnWidthToFit() method + to make implementing this easier). + @event{EVT_HEADER_BEGIN_RESIZE(id, func)} + The user started to drag the separator to the right of the column + with the specified index (this can only happen for the columns for + which wxHeaderColumn::IsResizeable() returns true). The event can + be vetoed to prevent the column from being resized. If it isn't, + the resizing and end resize (or dragging cancelled) events will be + generated later. + @event{EVT_HEADER_RESIZING(id, func)} + The user is dragging the column with the specified index resizing + it and its current width is wxHeaderCtrlEvent::GetWidth(). + The event can be vetoed to stop the dragging operation completely at + any time. + @event{EVT_HEADER_END_RESIZE(id, func)} + The user stopped dragging the column by releasing the mouse. + The column should normally be resized to the value of + wxHeaderCtrlEvent::GetWidth(). + @event{EVT_HEADER_BEGIN_REORDER(id, func)} + The user started to drag the column with the specified index (this + can only happen for the controls with wxHD_ALLOW_REORDER style). + This event can be vetoed to prevent the column from being reordered, + otherwise the end reorder message will be generated later. + @event{EVT_HEADER_END_REORDER(id, func)} + The user dropped the column in its new location. The event can be + vetoed to prevent the column from being placed at the new position + or handled to update the display of the data in the associated + control to match the new column location (available from + wxHeaderCtrlEvent::GetNewOrder()). + @event{EVT_HEADER_DRAGGING_CANCELLED(id, func)} + The resizing or reordering operation currently in progress was + cancelled. This can happen if the user pressed Esc key while + dragging the mouse or the mouse capture was lost for some other + reason. You only need to handle this event if your application + entered into some modal mode when resizing or reordering began, in + which case it should handle this event in addition to the matching + end resizing or reordering ones. + @endEventTable + + @library{wxcore} + @category{ctrl} + + @see wxGrid, wxListCtrl, wxDataViewCtrl */ -class wxHeaderCtrl +class wxHeaderCtrl : public wxControl { public: /** @@ -144,8 +181,8 @@ public: The control style, @c wxHD_DEFAULT_STYLE by default. Notice that the default style allows the user to reorder the columns by dragging them and you need to explicitly turn this feature off by - using @code wxHD_DEFAULT_STYLE & ~wxHD_DRAGDROP @endcode if this is - undesirable. + using @code wxHD_DEFAULT_STYLE & ~wxHD_ALLOW_REORDER @endcode if + this is undesirable. @param name The name of the control. */ @@ -195,6 +232,170 @@ public: */ void UpdateColumn(unsigned int idx); + /** + Change the columns display order. + + The display order defines the order in which the columns appear on the + screen and does @em not affect the interpretation of indices by all the + other class methods. + + The @a order array specifies the column indices corresponding to the + display positions. + + @param order + A permutation of all column indices, i.e. an array of size + GetColumnsOrder() containing all column indices exactly once. The + n-th element of this array defines the index of the column shown at + the n-th position from left (for the default left-to-right writing + direction). + + @see wxListCtrl::SetColumnsOrder() + */ + void SetColumnsOrder(const wxArrayInt& order); + + /** + Return the array describing the columns display order. + + For the controls without wxHD_ALLOW_REORDER style the returned array + will be the same as was passed to SetColumnsOrder() previously or + define the default order (with n-th element being n) if it hadn't been + called. But for the controls with wxHD_ALLOW_REORDER style, the columns + can be also reordered by user. + */ + wxArrayInt GetColumnsOrder() const; + + /** + Return the index of the column displayed at the given position. + + @param pos + The display position, e.g. 0 for the left-most column, 1 for the + next one and so on until GetColumnCount() - 1. + + @see GetColumnPos() + */ + unsigned int GetColumnAt(unsigned int pos) const; + + /** + Get the position at which this column is currently displayed. + + Notice that a valid position is returned even for the hidden columns + currently. + + @param idx + The column index, must be less than GetColumnCount(). + + @see GetColumnAt() + */ + unsigned int GetColumnPos(unsigned int idx) const; + + /** + Reset the columns order to the natural one. + + After calling this function, the column with index @c idx appears at + position @c idx in the control. + */ + void ResetColumnsOrder(); + + /** + Helper function to manipulate the array of column indices. + + This function reshuffles the array of column indices indexed by + positions (i.e. using the same convention as for SetColumnsOrder()) so + that the column with the given index is found at the specified + position. + + @param order + Array containing the indices of columns in order of their + positions. + @param idx + The index of the column to move. + @param pos + The new position for the column @a idx. + */ + static void MoveColumnInOrderArray(wxArrayInt& order, + unsigned int idx, + unsigned int pos); + + /** + Show the popup menu allowing the user to show or hide the columns. + + This functions shows the popup menu containing all columns with check + marks for the ones which are currently shown and allows the user to + check or uncheck them to toggle their visibility. It is called from the + default EVT_HEADER_RIGHT_CLICK handler for the controls which have + wxHD_ALLOW_HIDE style. And if the column has wxHD_ALLOW_REORDER style + as well, the menu also contains an item to customize the columns shown + using which results in ShowCustomizeDialog() being called, please see + its description for more details. + + If a column was toggled, UpdateColumnVisibility() virtual function is + called so it must be implemented for the controls with wxHD_ALLOW_HIDE + style or if you call this function explicitly. + + @param pt + The position of the menu, in the header window coordinates. + @param title + The title for the menu if not empty. + @return + @true if a column was shown or hidden or @false if nothing was + done, e.g. because the menu was cancelled. + */ + bool ShowColumnsMenu(const wxPoint& pt, const wxString& title = wxString()); + + /** + Helper function appending the checkable items corresponding to all the + columns to the given menu. + + This function is used by ShowColumnsMenu() but can also be used if you + show your own custom columns menu and still want all the columns shown + in it. It appends menu items with column labels as their text and + consecutive ids starting from @a idColumnsBase to the menu and checks + the items corresponding to the currently visible columns. + + Example of use: + @code + wxMenu menu; + menu.Append(100, "Some custom command"); + menu.AppendSeparator(); + AddColumnsItems(menu, 200); + const int rc = GetPopupMenuSelectionFromUser(menu, pt); + if ( rc >= 200 ) + ... toggle visibility of the column rc-200 ... + @endcode + + @param menu + The menu to append the items to. It may be currently empty or not. + @param idColumnsBase + The id for the menu item corresponding to the first column, the + other ones are consecutive starting from it. It should be positive. + */ + void AddColumnsItems(wxMenu& menu, int idColumnsBase = 0); + + /** + Show the column customization dialog. + + This function displays a modal dialog containing the list of all + columns which the user can use to reorder them as well as show or hide + individual columns. + + If the user accepts the changes done in the dialog, the virtual + methods UpdateColumnVisibility() and UpdateColumnsOrder() will be + called so they must be overridden in the derived class if this method + is ever called. Please notice that the user will be able to invoke it + interactively from the header popup menu if the control has both + wxHD_ALLOW_HIDE and wxHD_ALLOW_REORDER styles. + + @see wxRearrangeDialog + */ + bool ShowCustomizeDialog(); + + /** + Returns width needed for given column's title. + + @since 2.9.4 + */ + int GetColumnTitleWidth(const wxHeaderColumn& col); + protected: /** Method to be implemented by the derived classes to return the @@ -204,7 +405,51 @@ protected: The column index, between 0 and the value last passed to SetColumnCount(). */ - virtual wxHeaderColumnBase& GetColumn(unsigned int idx) = 0; + virtual const wxHeaderColumn& GetColumn(unsigned int idx) const = 0; + + /** + Method called when the column visibility is changed by the user. + + This method is called from ShowColumnsMenu() or ShowCustomizeDialog() + when the user interactively hides or shows a column. A typical + implementation will simply update the internally stored column state. + Notice that there is no need to call UpdateColumn() from this method as + it is already done by wxHeaderCtrl itself. + + The base class version doesn't do anything and must be overridden if + this method is called. + + @param idx + The index of the column whose visibility was toggled. + @param show + The new visibility value, @true if the column is now shown or + @false if it is not hidden. + */ + virtual void UpdateColumnVisibility(unsigned int idx, bool show); + + /** + Method called when the columns order is changed in the customization + dialog. + + This method is only called from ShowCustomizeDialog() when the user + changes the order of columns. In particular it is @em not called if a + single column changes place because the user dragged it to the new + location, the EVT_HEADER_END_REORDER event handler should be used to + react to this. + + A typical implementation in a derived class will update the display + order of the columns in the associated control, if any. Notice that + there is no need to call SetColumnsOrder() from it as wxHeaderCtrl does + it itself. + + The base class version doesn't do anything and must be overridden if + this method is called. + + @param order + The new column order. This array uses the same convention as + SetColumnsOrder(). + */ + virtual void UpdateColumnsOrder(const wxArrayInt& order); /** Method which may be implemented by the derived classes to allow double @@ -216,7 +461,7 @@ protected: to fit its width on header double click you need to implement this method using logic similar to this example: @code - class MyHeaderCtrl : public wxHeaderColumnBase + class MyHeaderColumn : public wxHeaderColumn { public: ... @@ -232,7 +477,7 @@ protected: { public: protected: - virtual wxHeaderColumnBase& GetColumn(unsigned int idx) + virtual wxHeaderColumn& GetColumn(unsigned int idx) const { return m_cols[idx]; } @@ -250,16 +495,31 @@ protected: Base class version simply returns @false. - @param width + @param idx + The zero-based index of the column to update. + @param widthTitle Contains minimal width needed to display the column header itself and will usually be used as a starting point for the fitting width calculation. + @return @true to indicate that the column was resized, i.e. GetColumn() now returns the new width value, and so must be refreshed or @false meaning that the control didn't reach to the separator double click. */ virtual bool UpdateColumnWidthToFit(unsigned int idx, int widthTitle); + + /** + Can be overridden in the derived class to update internal data + structures when the number of the columns in the control changes. + + This method is called by SetColumnCount() before effectively changing + the number of columns. + + The base class version does nothing but it is good practice to still + call it from the overridden version in the derived class. + */ + virtual void OnColumnCountChanging(unsigned int count); }; @@ -316,14 +576,14 @@ public: @see AppendColumn() */ - void InsertColumn(const wxHeaderColumn& col, unsigned int idx); + void InsertColumn(const wxHeaderColumnSimple& col, unsigned int idx); /** Append the column to the end of the control. @see InsertColumn() */ - void AppendColumn(const wxHeaderColumn& col); + void AppendColumn(const wxHeaderColumnSimple& col); /** Delete the column at the given position. @@ -369,22 +629,20 @@ public: @param idx The column to set the sort indicator for. + If @c -1 is given, then the currently shown sort indicator + will be removed. @param sortOrder If @true or @false show the sort indicator corresponding to - ascending or descending sort order respectively, if @c -1 remove - the currently shown sort indicator. + ascending or descending sort order respectively. */ - virtual void ShowSortIndicator(unsigned int idx, int sortOrder); + void ShowSortIndicator(unsigned int idx, bool sortOrder = true); /** - Remove the sort indicator from the given column. - - This is the same as calling ShowSortIndicator() with @c -1 argument. + Remove the sort indicator from the column being used as sort key. - @param idx - The column to remove sort indicator for. + @see ShowSortIndicator */ - void RemoveSortIndicator(unsigned int idx); + void RemoveSortIndicator(); protected: /** @@ -409,31 +667,56 @@ protected: Event class representing the events generated by wxHeaderCtrl. @library{wxcore} - @category{ctrl} + @category{events} @see wxHeaderCtrl */ class wxHeaderCtrlEvent : public wxNotifyEvent { public: + wxHeaderCtrlEvent(wxEventType commandType = wxEVT_NULL, int winid = 0); + wxHeaderCtrlEvent(const wxHeaderCtrlEvent& event); + /** Return the index of the column affected by this event. This method can be called for all header control events. */ int GetColumn() const; - + void SetColumn(int col); + /** Return the current width of the column. This method can only be called for the dragging events. */ int GetWidth() const; - + void SetWidth(int width); + /** - Return @true if the drag operation was cancelled. + Return the new order of the column. - This method can only be called for the end drag event. + This method can only be called for a reorder event for which it + indicates the tentative new position for the column GetColumn() + selected by the user. If the event is not vetoed, this will become the + new column position in wxHeaderCtrl::GetColumnsOrder(). */ - bool IsCancelled() const; + unsigned int GetNewOrder() const; + void SetNewOrder(unsigned int order); }; + + + +wxEventType wxEVT_HEADER_CLICK; +wxEventType wxEVT_HEADER_RIGHT_CLICK; +wxEventType wxEVT_HEADER_MIDDLE_CLICK; +wxEventType wxEVT_HEADER_DCLICK; +wxEventType wxEVT_HEADER_RIGHT_DCLICK; +wxEventType wxEVT_HEADER_MIDDLE_DCLICK; +wxEventType wxEVT_HEADER_SEPARATOR_DCLICK; +wxEventType wxEVT_HEADER_BEGIN_RESIZE; +wxEventType wxEVT_HEADER_RESIZING; +wxEventType wxEVT_HEADER_END_RESIZE; +wxEventType wxEVT_HEADER_BEGIN_REORDER; +wxEventType wxEVT_HEADER_END_REORDER; +wxEventType wxEVT_HEADER_DRAGGING_CANCELLED;