]> git.saurik.com Git - wxWidgets.git/commitdiff
add support for sorting to grid columns
authorVadim Zeitlin <vadim@wxwidgets.org>
Sun, 14 Dec 2008 00:02:30 +0000 (00:02 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sun, 14 Dec 2008 00:02:30 +0000 (00:02 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@57323 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/generic/grid.h
interface/wx/grid.h
samples/grid/griddemo.cpp
src/generic/grid.cpp

index f38566a86b46839eb84cc7a964834100d7c18bc3..98427527e8dcf2f32e2ae2c357e1cdf110459879 100644 (file)
@@ -1749,6 +1749,31 @@ public:
 #endif // wxUSE_DRAG_AND_DROP
 
 
+    // ------- sorting support
+
+    // wxGrid doesn't support sorting on its own but it can indicate the sort
+    // order in the column header (currently only if native header control is
+    // used though)
+
+    // return the column currently displaying the sort indicator or wxNOT_FOUND
+    // if none
+    int GetSortingColumn() const { return m_sortCol; }
+
+    // return true if this column is currently used for sorting
+    bool IsSortingBy(int col) const { return GetSortingColumn() == col; }
+
+    // return the current sorting order (on GetSortingColumn()): true for
+    // ascending sort and false for descending; it doesn't make sense to call
+    // it if GetSortingColumn() returns wxNOT_FOUND
+    bool IsSortOrderAscending() const { return m_sortIsAscending; }
+
+    // set the sorting column (or unsets any existing one if wxNOT_FOUND) and
+    // the order in which to sort
+    void SetSortingColumn(int col, bool ascending = true);
+
+    // unset any existing sorting column
+    void UnsetSortingColumn() { SetSortingColumn(wxNOT_FOUND); }
+
 #ifdef WXWIN_COMPATIBILITY_2_8
     // ------ For compatibility with previous wxGrid only...
     //
@@ -1998,6 +2023,9 @@ protected:
     wxArrayInt m_colWidths;
     wxArrayInt m_colRights;
 
+    int m_sortCol;
+    bool m_sortIsAscending;
+
     bool m_useNativeHeader,
          m_nativeColumnLabels;
 
@@ -2244,6 +2272,13 @@ private:
     // common part of Clip{Horz,Vert}GridLines
     void DoClipGridLines(bool& var, bool clip);
 
+    // update the sorting indicator shown in the specified column (whose index
+    // must be valid)
+    //
+    // this will use GetSortingColumn() and IsSortOrderAscending() to determine
+    // the sorting indicator to effectively show
+    void UpdateColumnSortingIndicator(int col);
+
 
     // return the position (not index) of the column at the given logical pixel
     // position
@@ -2289,6 +2324,8 @@ private:
     void ProcessColLabelMouseEvent(wxMouseEvent& event);
     void ProcessCornerLabelMouseEvent(wxMouseEvent& event);
 
+    void DoColHeaderClick(int col);
+
     void DoStartResizeCol(int col);
     void DoUpdateResizeCol(int x);
     void DoUpdateResizeColWidth(int w);
@@ -2608,6 +2645,7 @@ extern WXDLLIMPEXP_ADV const wxEventType wxEVT_GRID_EDITOR_HIDDEN;
 extern WXDLLIMPEXP_ADV const wxEventType wxEVT_GRID_EDITOR_CREATED;
 extern WXDLLIMPEXP_ADV const wxEventType wxEVT_GRID_CELL_BEGIN_DRAG;
 extern WXDLLIMPEXP_ADV const wxEventType wxEVT_GRID_COL_MOVE;
+extern WXDLLIMPEXP_ADV const wxEventType wxEVT_GRID_COL_SORT;
 
 
 typedef void (wxEvtHandler::*wxGridEventFunction)(wxGridEvent&);
@@ -2650,6 +2688,7 @@ typedef void (wxEvtHandler::*wxGridEditorCreatedEventFunction)(wxGridEditorCreat
 #define EVT_GRID_CMD_ROW_SIZE(id, fn)            wx__DECLARE_GRIDSIZEEVT(ROW_SIZE, id, fn)
 #define EVT_GRID_CMD_COL_SIZE(id, fn)            wx__DECLARE_GRIDSIZEEVT(COL_SIZE, id, fn)
 #define EVT_GRID_CMD_COL_MOVE(id, fn)            wx__DECLARE_GRIDEVT(COL_MOVE, id, fn)
+#define EVT_GRID_CMD_COL_SORT(id, fn)            wx__DECLARE_GRIDEVT(COL_SORT, id, fn)
 #define EVT_GRID_CMD_RANGE_SELECT(id, fn)        wx__DECLARE_GRIDRANGESELEVT(RANGE_SELECT, id, fn)
 #define EVT_GRID_CMD_CELL_CHANGE(id, fn)         wx__DECLARE_GRIDEVT(CELL_CHANGE, id, fn)
 #define EVT_GRID_CMD_SELECT_CELL(id, fn)         wx__DECLARE_GRIDEVT(SELECT_CELL, id, fn)
@@ -2671,6 +2710,7 @@ typedef void (wxEvtHandler::*wxGridEditorCreatedEventFunction)(wxGridEditorCreat
 #define EVT_GRID_ROW_SIZE(fn)            EVT_GRID_CMD_ROW_SIZE(wxID_ANY, fn)
 #define EVT_GRID_COL_SIZE(fn)            EVT_GRID_CMD_COL_SIZE(wxID_ANY, fn)
 #define EVT_GRID_COL_MOVE(fn)            EVT_GRID_CMD_COL_MOVE(wxID_ANY, fn)
+#define EVT_GRID_COL_SORT(fn)            EVT_GRID_CMD_COL_SORT(wxID_ANY, fn)
 #define EVT_GRID_RANGE_SELECT(fn)        EVT_GRID_CMD_RANGE_SELECT(wxID_ANY, fn)
 #define EVT_GRID_CELL_CHANGE(fn)         EVT_GRID_CMD_CELL_CHANGE(wxID_ANY, fn)
 #define EVT_GRID_SELECT_CELL(fn)         EVT_GRID_CMD_SELECT_CELL(wxID_ANY, fn)
index d41a7d485f8cf304e85a8a2b3ec5a839501de905..bb38bdaeaf31b938269ea6ff1f5e7f9d4324c7f4 100644 (file)
@@ -3056,6 +3056,77 @@ protected:
         called for this row.
     */
     int GetRowMinimalHeight(int col) const;
+
+
+    /**
+        @name Sorting support.
+
+        wxGrid doesn't provide any support for sorting the data but it does
+        generate events allowing the user code to sort it and supports
+        displaying the sort indicator in the column used for sorting.
+
+        To use wxGrid sorting support you need to handle wxEVT_GRID_COL_SORT
+        event (and not veto it) and resort the data displayed in the grid. The
+        grid will automatically update the sorting indicator on the column
+        which was clicked.
+
+        You can also call the functions in this section directly to update the
+        sorting indicator. Once again, they don't do anything with the grid
+        data, it remains your responsibility to actually sort it appropriately.
+     */
+    //@{
+
+    /**
+        Return the column in which the sorting indicator is currently
+        displayed.
+
+        Returns @c wxNOT_FOUND if sorting indicator is not currently displayed
+        at all.
+
+        @see SetSortingColumn()
+     */
+    int GetSortingColumn() const;
+
+    /**
+        Return @true if this column is currently used for sorting.
+
+        @see GetSortingColumn()
+     */
+    bool IsSortingBy(int col) const;
+
+    /**
+        Return @true if the current sorting order is ascending or @false if it
+        is descending.
+
+        It only makes sense to call this function if GetSortingColumn() returns
+        a valid column index and not @c wxNOT_FOUND.
+
+        @see SetSortingColumn()
+     */
+    bool IsSortOrderAscending() const;
+
+    /**
+        Set the column to display the sorting indicator in and its direction.
+
+        @param col
+            The column to display the sorting indicator in or @c wxNOT_FOUND to
+            remove any currently displayed sorting indicator.
+        @param ascending
+            If @true, display the ascending sort indicator, otherwise display
+            the descending sort indicator.
+
+        @see GetSortingColumn(), IsSortOrderAscending()
+     */
+    void SetSortingColumn(int col, bool ascending = true);
+
+    /**
+        Remove any currently shown sorting indicator.
+
+        This is equivalent to calling SetSortingColumn() with @c wxNOT_FOUND
+        first argument.
+     */
+    void UnsetSortingColumn();
+    //@}
 };
 
 
@@ -3183,7 +3254,19 @@ public:
         proceed in which case wxGrid::SetColPos() is used to reorder the
         columns display order without affecting the use of the column indices
         otherwise.
+
         This event macro corresponds to @c wxEVT_GRID_COL_MOVE event type.
+    @event{EVT_GRID_COL_SORT(func)}
+        This event is generated when a column is clicked by the user and its
+        name is explained by the fact that the custom reaction to a click on a
+        column is to sort the grid contents by this column. However the grid
+        itself has no special support for sorting and it's up to the handler of
+        this event to update the associated table. But if the event is handled
+        (and not vetoed) the grid supposes that the table was indeed resorted
+        and updates the column to indicate the new sort order and refreshes
+        itself.
+
+        This event macro corresponds to @c wxEVT_GRID_COL_SORT event type.
     @endEventTable
 
     @library{wxadv}
index f8b6f36895fb79970f99b64880d73bdf7039924f..cff3f3b1fa40b36722458ba9503509bf99dc3ce6 100644 (file)
@@ -1565,22 +1565,34 @@ public:
         ROW_MAX = 3
     };
 
+    TabularGridTable() { m_sortOrder = NULL; }
+
     virtual int GetNumberRows() { return ROW_MAX; }
     virtual int GetNumberCols() { return COL_MAX; }
 
     virtual wxString GetValue(int row, int col)
     {
-        // notice that column parameter here always refers to the internal
-        // column index, independently of its position on the screen
-        static const char *filedata[][COL_MAX] =
+        if ( m_sortOrder )
+            row = m_sortOrder[row];
+
+        switch ( col )
         {
-            { "autoexec", "bat",    "412", "Apr 17  2004" },
-            { "boot",     "ini",    "604", "May 27  2006" },
-            { "io",       "sys",  "40774", "May 31  1994" },
-        };
-        wxCOMPILE_TIME_ASSERT( WXSIZEOF(filedata) == ROW_MAX, Mismatch );
+            case COL_NAME:
+            case COL_EXT:
+                return GetNameOrExt(row, col);
 
-        return filedata[row][col];
+            case COL_SIZE:
+                return wxString::Format("%lu", GetSize(row));
+
+            case COL_DATE:
+                return GetDate(row).FormatDate();
+
+            case COL_MAX:
+            default:
+                wxFAIL_MSG( "unknown column" );
+        }
+
+        return wxString();
     }
 
     virtual void SetValue(int, int, const wxString&)
@@ -1590,8 +1602,10 @@ public:
 
     virtual wxString GetColLabelValue(int col)
     {
+        // notice that column parameter here always refers to the internal
+        // column index, independently of its position on the screen
         static const char *labels[] = { "Name", "Extension", "Size", "Date" };
-        wxCOMPILE_TIME_ASSERT( WXSIZEOF(labels) == COL_MAX, Mismatch );
+        wxCOMPILE_TIME_ASSERT( WXSIZEOF(labels) == COL_MAX, LabelsMismatch );
 
         return labels[col];
     }
@@ -1600,6 +1614,54 @@ public:
     {
         wxFAIL_MSG( "shouldn't be called" );
     }
+
+    void Sort(int col, bool ascending)
+    {
+        // we hardcode all sorting orders for simplicity here
+        static int sortOrders[COL_MAX][2][ROW_MAX] =
+        {
+            // descending   ascending
+            { { 2, 1, 0 }, { 0, 1, 2 } },
+            { { 2, 1, 0 }, { 0, 1, 2 } },
+            { { 2, 1, 0 }, { 0, 1, 2 } },
+            { { 1, 0, 2 }, { 2, 0, 1 } },
+        };
+
+        m_sortOrder = col == wxNOT_FOUND ? NULL : sortOrders[col][ascending];
+    }
+
+private:
+    wxString GetNameOrExt(int row, int col) const
+    {
+        static const char *
+            names[] = { "autoexec.bat", "boot.ini", "io.sys" };
+        wxCOMPILE_TIME_ASSERT( WXSIZEOF(names) == ROW_MAX, NamesMismatch );
+
+        const wxString s(names[row]);
+        return col == COL_NAME ? s.BeforeFirst('.') : s.AfterLast('.');
+    }
+
+    unsigned long GetSize(int row) const
+    {
+        static const unsigned long
+            sizes[] = { 412, 604, 40774 };
+        wxCOMPILE_TIME_ASSERT( WXSIZEOF(sizes) == ROW_MAX, SizesMismatch );
+
+        return sizes[row];
+    }
+
+    wxDateTime GetDate(int row) const
+    {
+        static const char *
+            dates[] = { "2004-04-17", "2006-05-27", "1994-05-31" };
+        wxCOMPILE_TIME_ASSERT( WXSIZEOF(dates) == ROW_MAX, DatesMismatch );
+
+        wxDateTime dt;
+        dt.ParseISODate(dates[row]);
+        return dt;
+    }
+
+    int *m_sortOrder;
 };
 
 // specialized text control for column indexes entry
@@ -1690,6 +1752,13 @@ private:
         UpdateOrder();
     }
 
+    void OnGridColSort(wxGridEvent& event)
+    {
+        const int col = event.GetCol();
+        m_table->Sort(col, !(m_grid->IsSortingBy(col) &&
+                             m_grid->IsSortOrderAscending()));
+    }
+
     void OnGridColMove(wxGridEvent& event)
     {
         // can't update it yet as the order hasn't been changed, so do it a bit
@@ -1721,6 +1790,7 @@ private:
 
     // controls
     wxGrid *m_grid;
+    TabularGridTable *m_table;
     wxCheckBox *m_chkUseNative,
                *m_chkDrawNative,
                *m_chkShowRowLabels,
@@ -1753,6 +1823,7 @@ BEGIN_EVENT_TABLE(TabularGridFrame, wxFrame)
 
     EVT_BUTTON(wxID_APPLY, TabularGridFrame::OnMoveColumn)
 
+    EVT_GRID_COL_SORT(TabularGridFrame::OnGridColSort)
     EVT_GRID_COL_MOVE(TabularGridFrame::OnGridColMove)
 
     EVT_IDLE(TabularGridFrame::OnIdle)
@@ -1766,10 +1837,11 @@ TabularGridFrame::TabularGridFrame()
     wxPanel * const panel = new wxPanel(this);
 
     // create and initialize the grid with the specified data
+    m_table = new TabularGridTable;
     m_grid = new wxGrid(panel, wxID_ANY,
                         wxDefaultPosition, wxDefaultSize,
                         wxBORDER_STATIC | wxWANTS_CHARS);
-    m_grid->SetTable(new TabularGridTable, true, wxGrid::wxGridSelectRows);
+    m_grid->SetTable(m_table, true, wxGrid::wxGridSelectRows);
 
     m_grid->EnableDragColMove();
     m_grid->UseNativeColHeader();
@@ -1841,3 +1913,10 @@ void GridFrame::OnTabularTable(wxCommandEvent&)
 {
     new TabularGridFrame;
 }
+
+bool GridApp::OnInit()
+{
+    new TabularGridFrame();
+
+    return true;
+}
index 3e8c74b0b712211e01a70e379ee596ef95fbf4ed..452a7b6d3f7c9a97d6ec98b98137375f5e82ee94 100644 (file)
@@ -146,6 +146,7 @@ DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_DCLICK)
 DEFINE_EVENT_TYPE(wxEVT_GRID_ROW_SIZE)
 DEFINE_EVENT_TYPE(wxEVT_GRID_COL_SIZE)
 DEFINE_EVENT_TYPE(wxEVT_GRID_COL_MOVE)
+DEFINE_EVENT_TYPE(wxEVT_GRID_COL_SORT)
 DEFINE_EVENT_TYPE(wxEVT_GRID_RANGE_SELECT)
 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_CHANGE)
 DEFINE_EVENT_TYPE(wxEVT_GRID_SELECT_CELL)
@@ -192,9 +193,15 @@ public:
         return flags;
     }
 
-    // TODO: currently there is no support for sorting
-    virtual bool IsSortKey() const { return false; }
-    virtual bool IsSortOrderAscending() const { return false; }
+    virtual bool IsSortKey() const
+    {
+        return m_grid->IsSortingBy(m_col);
+    }
+
+    virtual bool IsSortOrderAscending() const
+    {
+        return m_grid->IsSortOrderAscending();
+    }
 
 private:
     // these really should be const but are not because the column needs to be
@@ -249,6 +256,8 @@ private:
     // override to implement column auto sizing
     virtual bool UpdateColumnWidthToFit(unsigned int idx, int widthTitle)
     {
+        // TODO: currently grid doesn't support computing the column best width
+        //       from its contents so we just use the best label width as is
         GetOwner()->SetColSize(idx, widthTitle);
 
         return true;
@@ -256,6 +265,11 @@ private:
 
 
     // event handlers forwarding wxHeaderCtrl events to wxGrid
+    void OnClick(wxHeaderCtrlEvent& event)
+    {
+        GetOwner()->DoColHeaderClick(event.GetColumn());
+    }
+
     void OnBeginResize(wxHeaderCtrlEvent& event)
     {
         GetOwner()->DoStartResizeCol(event.GetColumn());
@@ -292,6 +306,8 @@ private:
 };
 
 BEGIN_EVENT_TABLE(wxGridHeaderCtrl, wxHeaderCtrl)
+    EVT_HEADER_CLICK(wxID_ANY, wxGridHeaderCtrl::OnClick)
+
     EVT_HEADER_BEGIN_RESIZE(wxID_ANY, wxGridHeaderCtrl::OnBeginResize)
     EVT_HEADER_RESIZING(wxID_ANY, wxGridHeaderCtrl::OnResizing)
     EVT_HEADER_END_RESIZE(wxID_ANY, wxGridHeaderCtrl::OnEndResize)
@@ -4884,6 +4900,9 @@ void wxGrid::Init()
     m_isDragging = false;
     m_startDragPos = wxDefaultPosition;
 
+    m_sortCol = wxNOT_FOUND;
+    m_sortIsAscending = true;
+
     m_useNativeHeader =
     m_nativeColumnLabels = false;
 
@@ -5849,6 +5868,60 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event )
     }
 }
 
+void wxGrid::UpdateColumnSortingIndicator(int col)
+{
+    wxCHECK_RET( col != wxNOT_FOUND, "invalid column index" );
+
+    if ( m_useNativeHeader )
+        GetColHeader()->UpdateColumn(col);
+    else if ( m_nativeColumnLabels )
+        m_colWindow->Refresh();
+    //else: sorting indicator display not yet implemented in grid version
+}
+
+void wxGrid::SetSortingColumn(int col, bool ascending)
+{
+    if ( col == m_sortCol )
+    {
+        // we are already using this column for sorting (or not sorting at all)
+        // but we might still change the sorting order, check for it
+        if ( m_sortCol != wxNOT_FOUND && ascending != m_sortIsAscending )
+        {
+            m_sortIsAscending = ascending;
+
+            UpdateColumnSortingIndicator(m_sortCol);
+        }
+    }
+    else // we're changing the column used for sorting
+    {
+        const int sortColOld = m_sortCol;
+
+        // change it before updating the column as we want GetSortingColumn()
+        // to return the correct new value
+        m_sortCol = col;
+
+        if ( sortColOld != wxNOT_FOUND )
+            UpdateColumnSortingIndicator(sortColOld);
+
+        if ( m_sortCol != wxNOT_FOUND )
+        {
+            m_sortIsAscending = ascending;
+            UpdateColumnSortingIndicator(m_sortCol);
+        }
+    }
+}
+
+void wxGrid::DoColHeaderClick(int col)
+{
+    // we consider that the grid was resorted if this event is processed and
+    // not vetoed
+    if ( SendEvent(wxEVT_GRID_COL_SORT, -1, col) == 1 )
+    {
+        SetSortingColumn(col, IsSortingBy(col) ? !m_sortIsAscending : true);
+        Refresh();
+    }
+}
+
 void wxGrid::DoStartResizeCol(int col)
 {
     m_dragRowOrCol = col;
@@ -5882,10 +5955,11 @@ void wxGrid::DoUpdateResizeColWidth(int w)
 
 void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
 {
-    int x, y, col;
+    int x, y;
     wxPoint pos( event.GetPosition() );
     CalcUnscrolledPosition( pos.x, pos.y, &x, &y );
 
+    int col = XToCol(x);
     if ( event.Dragging() )
     {
         if (!m_isDragging)
@@ -5893,8 +5967,8 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
             m_isDragging = true;
             GetColLabelWindow()->CaptureMouse();
 
-            if ( m_cursorMode == WXGRID_CURSOR_MOVE_COL )
-                DoStartMoveCol(XToCol(x));
+            if ( m_cursorMode == WXGRID_CURSOR_MOVE_COL && col != -1 )
+                DoStartMoveCol(col);
         }
 
         if ( event.LeftIsDown() )
@@ -5907,7 +5981,7 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
 
                 case WXGRID_CURSOR_SELECT_COL:
                 {
-                    if ( (col = XToCol( x )) >= 0 )
+                    if ( col != -1 )
                     {
                         if ( m_selection )
                             m_selection->SelectCol(col, event);
@@ -6005,7 +6079,6 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
         //
         if ( XToEdgeOfCol(x) < 0 )
         {
-            col = XToCol(x);
             if ( col >= 0 &&
                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK, -1, col, event ) )
             {
@@ -6059,10 +6132,9 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
     //
     if ( event.LeftDClick() )
     {
-        col = XToEdgeOfCol(x);
-        if ( col < 0 )
+        const int colEdge = XToEdgeOfCol(x);
+        if ( colEdge == -1 )
         {
-            col = XToCol(x);
             if ( col >= 0 &&
                  ! SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK, -1, col, event ) )
             {
@@ -6072,7 +6144,7 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
         else
         {
             // adjust column width depending on label text
-            AutoSizeColLabelSize( col );
+            AutoSizeColLabelSize( colEdge );
 
             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL, GetColLabelWindow());
             m_dragLastPos = -1;
@@ -6090,9 +6162,11 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
                 break;
 
             case WXGRID_CURSOR_MOVE_COL:
-                if ( m_dragLastPos == -1 )
+                if ( m_dragLastPos == -1 || col == m_dragRowOrCol )
                 {
-                    // The user clicked on the column but didn't actually drag
+                    // the column didn't actually move anywhere
+                    if ( col != -1 )
+                        DoColHeaderClick(col);
                     m_colWindow->Refresh();   // "unpress" the column
                 }
                 else
@@ -6105,7 +6179,8 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
             case WXGRID_CURSOR_SELECT_CELL:
             case WXGRID_CURSOR_RESIZE_ROW:
             case WXGRID_CURSOR_SELECT_ROW:
-                // nothing to do (?)
+                if ( col != -1 )
+                    DoColHeaderClick(col);
                 break;
         }
 
@@ -6117,7 +6192,6 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
     //
     else if ( event.RightDown() )
     {
-        col = XToCol(x);
         if ( col >= 0 &&
              !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK, -1, col, event ) )
         {
@@ -6129,7 +6203,6 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
     //
     else if ( event.RightDClick() )
     {
-        col = XToCol(x);
         if ( col >= 0 &&
              !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK, -1, col, event ) )
         {
@@ -8185,7 +8258,18 @@ void wxGrid::DrawColLabel(wxDC& dc, int col)
 
     if ( m_nativeColumnLabels )
     {
-        wxRendererNative::Get().DrawHeaderButton(GetColLabelWindow(), dc, rect, 0);
+        wxRendererNative::Get().DrawHeaderButton
+                                (
+                                    GetColLabelWindow(),
+                                    dc,
+                                    rect,
+                                    0,
+                                    IsSortingBy(col)
+                                        ? IsSortOrderAscending()
+                                            ? wxHDR_SORT_ICON_UP
+                                            : wxHDR_SORT_ICON_DOWN
+                                        : wxHDR_SORT_ICON_NONE
+                                );
     }
     else
     {