]> git.saurik.com Git - wxWidgets.git/blobdiff - interface/wx/headerctrl.h
Convert wxFSW_EVENT_{WARNING,ERROR} to string correctly.
[wxWidgets.git] / interface / wx / headerctrl.h
index f8f23a8aed2fd75926fe305c1b3cabdd7f911eda..0edeb4ba2445ba81b50f26d0e2c5e4b6c189bbac 100644 (file)
@@ -5,22 +5,38 @@
 // Created:     2008-12-01
 // RCS-ID:      $Id$
 // Copyright:   (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
-// 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:
     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
 
         - 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 +182,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 +233,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 +406,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 +462,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 +478,7 @@ protected:
             {
             public:
             protected:
-                virtual wxHeaderColumnBase& GetColumn(unsigned int idx)
+                virtual wxHeaderColumn& GetColumn(unsigned int idx) const
                 {
                     return m_cols[idx];
                 }
@@ -250,16 +496,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 +577,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 +630,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 +668,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_COMMAND_HEADER_CLICK;
+wxEventType wxEVT_COMMAND_HEADER_RIGHT_CLICK;
+wxEventType wxEVT_COMMAND_HEADER_MIDDLE_CLICK;
+wxEventType wxEVT_COMMAND_HEADER_DCLICK;
+wxEventType wxEVT_COMMAND_HEADER_RIGHT_DCLICK;
+wxEventType wxEVT_COMMAND_HEADER_MIDDLE_DCLICK;
+wxEventType wxEVT_COMMAND_HEADER_SEPARATOR_DCLICK;
+wxEventType wxEVT_COMMAND_HEADER_BEGIN_RESIZE;
+wxEventType wxEVT_COMMAND_HEADER_RESIZING;
+wxEventType wxEVT_COMMAND_HEADER_END_RESIZE;
+wxEventType wxEVT_COMMAND_HEADER_BEGIN_REORDER;
+wxEventType wxEVT_COMMAND_HEADER_END_REORDER;
+wxEventType wxEVT_COMMAND_HEADER_DRAGGING_CANCELLED;