X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e2bfe6731edfca732418012b03438db85b4aa0dd..72dc02c6a7fe7d02b1876b6cd466e92614bccfd4:/interface/wx/headerctrl.h diff --git a/interface/wx/headerctrl.h b/interface/wx/headerctrl.h index 76b76e746f..a5358665c1 100644 --- a/interface/wx/headerctrl.h +++ b/interface/wx/headerctrl.h @@ -40,35 +40,86 @@ This control is implemented using the native header control under MSW systems and a generic implementation elsewhere. + + @section headerctrl_improvements Future Improvements + + Some features are supported by the native MSW control and so could be + easily implemented in this version of wxHeaderCtrl but need to be + implemented in the generic version as well to be really useful. Please let + us know if you need or, better, plan to work on implementing, any of them: + - Displaying bitmaps instead of or together with the text + - Custom drawn headers + - Filters associated with a column. + + @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. + @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{wxHeaderEvent} + @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 (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_DRAGDROP 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 - - - @section headerctrl_improvements Future Improvements - - Some features are supported by the native MSW control and so could be - easily implemented in this version of wxHeaderCtrl but need to be - implemented in the generic version as well to be really useful. Please let - us know if you need or, better, plan to work on implementing, any of them: - - Displaying bitmaps instead of or together with the text - - Custom drawn headers - - Filters associated with a column. */ class wxHeaderCtrl { @@ -149,6 +200,94 @@ public: */ bool IsEmpty() const; + /** + Update the column with the given index. + + When the value returned by GetColumn() changes, this method must be + called to notify the control about the change and update the visual + display to match the new column data. + + @param idx + The column index, must be less than GetColumnCount(). + */ + 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_DRAGDROP 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_DRAGDROP 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; + + /** + 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); + protected: /** Method to be implemented by the derived classes to return the @@ -159,6 +298,76 @@ protected: SetColumnCount(). */ virtual wxHeaderColumnBase& GetColumn(unsigned int idx) = 0; + + /** + Method which may be implemented by the derived classes to allow double + clicking the column separator to resize the column to fit its contents. + + When a separator is double clicked, the default handler of + EVT_HEADER_SEPARATOR_DCLICK event calls this function and refreshes the + column if it returns @true so to implement the resizing of the column + 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 + { + public: + ... + + void SetWidth(int width) { m_width = width; } + virtual int GetWidth() const { return m_width; } + + private: + int m_width; + }; + + class MyHeaderCtrl : public wxHeaderCtrl + { + public: + protected: + virtual wxHeaderColumnBase& GetColumn(unsigned int idx) + { + return m_cols[idx]; + } + + virtual bool UpdateColumnWidthToFit(unsigned int idx, int widthTitle) + { + int widthContents = ... compute minimal width for column idx ... + m_cols[idx].SetWidth(wxMax(widthContents, widthTitle)); + return true; + } + + wxVector m_cols; + }; + @endcode + + Base class version simply returns @false. + + @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); }; @@ -284,4 +493,58 @@ public: The column to remove sort indicator for. */ void RemoveSortIndicator(unsigned int idx); + +protected: + /** + This function can be overridden in the classes deriving from this + control instead of overriding UpdateColumnWidthToFit(). + + To implement automatic column resizing to fit its contents width when + the column divider is double clicked, you need to simply return the + fitting width for the given column @a idx from this method, the control + will automatically use the biggest value between the one returned from + here and the one needed for the display of the column title itself. + + The base class version returns -1 indicating that this function is not + implemented. + */ + virtual int GetBestFittingWidth(unsigned int idx) const; +}; + +/** + @class wxHeaderCtrlEvent + + Event class representing the events generated by wxHeaderCtrl. + + @library{wxcore} + @category{ctrl} + + @see wxHeaderCtrl +*/ +class wxHeaderCtrlEvent : public wxNotifyEvent +{ +public: + /** + Return the index of the column affected by this event. + + This method can be called for all header control events. + */ + int GetColumn() const; + + /** + Return the current width of the column. + + This method can only be called for the dragging events. + */ + int GetWidth() const; + + /** + Return the new order of the column. + + This method can only be called for end 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(). + */ + unsigned int GetNewOrder() const; };