]> git.saurik.com Git - wxWidgets.git/blobdiff - include/wx/generic/grid.h
add support for sorting to grid columns
[wxWidgets.git] / include / wx / generic / grid.h
index 546bf7ea26b2603cce1883ff69854f1f86634a13..98427527e8dcf2f32e2ae2c357e1cdf110459879 100644 (file)
@@ -22,7 +22,7 @@
 // constants
 // ----------------------------------------------------------------------------
 
-extern WXDLLIMPEXP_DATA_ADV(const wxChar) wxGridNameStr[];
+extern WXDLLIMPEXP_DATA_ADV(const char) wxGridNameStr[];
 
 // Default parameters for wxGrid
 //
@@ -77,6 +77,7 @@ class WXDLLIMPEXP_FWD_ADV wxGridWindow;
 class WXDLLIMPEXP_FWD_ADV wxGridTypeRegistry;
 class WXDLLIMPEXP_FWD_ADV wxGridSelection;
 
+class WXDLLIMPEXP_FWD_CORE wxHeaderCtrl;
 class WXDLLIMPEXP_FWD_CORE wxCheckBox;
 class WXDLLIMPEXP_FWD_CORE wxComboBox;
 class WXDLLIMPEXP_FWD_CORE wxTextCtrl;
@@ -913,12 +914,15 @@ public:
     // would break the existing code overriding them, so instead we provide
     // these const synonyms which can be used from const-correct code
     int GetRowsCount() const
-        { return wx_const_cast(wxGridTableBase *, this)->GetNumberRows(); }
+        { return const_cast<wxGridTableBase *>(this)->GetNumberRows(); }
     int GetColsCount() const
-        { return wx_const_cast(wxGridTableBase *, this)->GetNumberCols(); }
+        { return const_cast<wxGridTableBase *>(this)->GetNumberCols(); }
 
 
-    virtual bool IsEmptyCell( int row, int col ) = 0;
+    virtual bool IsEmptyCell( int row, int col )
+    {
+        return GetValue(row, col).empty();
+    }
 
     bool IsEmpty(const wxGridCellCoords& coord)
     {
@@ -1071,7 +1075,6 @@ public:
     int GetNumberCols();
     wxString GetValue( int row, int col );
     void SetValue( int row, int col, const wxString& s );
-    bool IsEmptyCell( int row, int col );
 
     // overridden functions from wxGridTableBase
     //
@@ -1126,14 +1129,19 @@ public:
     // ------------------------
 
     // ctor and Create() create the grid window, as with the other controls
-    wxGrid();
+    wxGrid() { Init(); }
 
     wxGrid(wxWindow *parent,
             wxWindowID id,
             const wxPoint& pos = wxDefaultPosition,
             const wxSize& size = wxDefaultSize,
             long style = wxWANTS_CHARS,
-            const wxString& name = wxGridNameStr);
+            const wxString& name = wxGridNameStr)
+    {
+        Init();
+
+        Create(parent, id, pos, size, style, name);
+    }
 
     bool Create(wxWindow *parent,
                 wxWindowID id,
@@ -1305,6 +1313,12 @@ public:
     wxGridCellCoords XYToCell(const wxPoint& pos) const
         { return XYToCell(pos.x, pos.y); }
 
+    // these functions return the index of the row/columns corresponding to the
+    // given logical position in pixels
+    //
+    // if clipToMinMax is false (default, wxNOT_FOUND is returned if the
+    // position is outside any row/column, otherwise the first/last element is
+    // returned in this case
     int  YToRow( int y, bool clipToMinMax = false ) const;
     int  XToCol( int x, bool clipToMinMax = false ) const;
 
@@ -1377,7 +1391,13 @@ public:
     int      GetCellHighlightPenWidth() const { return m_cellHighlightPenWidth; }
     int      GetCellHighlightROPenWidth() const { return m_cellHighlightROPenWidth; }
 
-    void     SetUseNativeColLabels( bool native = true );
+    // this one will use wxHeaderCtrl for the column labels
+    void UseNativeColHeader(bool native = true);
+
+    // this one will still draw them manually but using the native renderer
+    // instead of using the same appearance as for the row labels
+    void SetUseNativeColLabels( bool native = true );
+
     void     SetRowLabelSize( int width );
     void     SetColLabelSize( int height );
     void     HideRowLabels() { SetRowLabelSize( 0 ); }
@@ -1491,33 +1511,48 @@ public:
 
     void     SetColSize( int col, int width );
 
-    //Column positions
-    int GetColAt( int colPos ) const
+    // columns index <-> positions mapping: by default, the position of the
+    // column is the same as its index, but the columns can also be reordered
+    // (either by calling SetColPos() explicitly or by the user dragging the
+    // columns around) in which case their indices don't correspond to their
+    // positions on display any longer
+    //
+    // internally we always work with indices except for the functions which
+    // have "Pos" in their names (and which work with columns, not pixels) and
+    // only the display and hit testing code really cares about display
+    // positions at all
+
+    // return the column index corresponding to the given (valid) position
+    int GetColAt(int pos) const
     {
-        if ( m_colAt.IsEmpty() )
-            return colPos;
-        else
-            return m_colAt[colPos];
+        return m_colAt.empty() ? pos : m_colAt[pos];
     }
 
-    void SetColPos( int colID, int newPos );
+    // reorder the columns so that the column with the given index is now shown
+    // as the position pos
+    void SetColPos(int idx, int pos);
 
-    int GetColPos( int colID ) const
+    // return the position at which the column with the given index is
+    // displayed: notice that this is a slow operation as we don't maintain the
+    // reverse mapping currently
+    int GetColPos(int idx) const
     {
         if ( m_colAt.IsEmpty() )
-            return colID;
-        else
+            return idx;
+
+        for ( int i = 0; i < m_numCols; i++ )
         {
-            for ( int i = 0; i < m_numCols; i++ )
-            {
-                if ( m_colAt[i] == colID )
-                    return i;
-            }
+            if ( m_colAt[i] == idx )
+                return i;
         }
 
-        return -1;
+        wxFAIL_MSG( "invalid column index" );
+
+        return wxNOT_FOUND;
     }
 
+
+
     // automatically size the column or row to fit to its contents, if
     // setAsMin is true, this optimal width will also be set as minimal width
     // for this column
@@ -1699,7 +1734,7 @@ public:
     // Accessors for component windows
     wxWindow* GetGridWindow() const            { return (wxWindow*)m_gridWin; }
     wxWindow* GetGridRowLabelWindow() const    { return (wxWindow*)m_rowLabelWin; }
-    wxWindow* GetGridColLabelWindow() const    { return (wxWindow*)m_colLabelWin; }
+    wxWindow* GetGridColLabelWindow() const    { return m_colWindow; }
     wxWindow* GetGridCornerLabelWindow() const { return (wxWindow*)m_cornerLabelWin; }
 
     // Allow adjustment of scroll increment. The default is (15, 15).
@@ -1714,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...
     //
@@ -1728,12 +1788,10 @@ public:
             int x, int y, int w = wxDefaultCoord, int h = wxDefaultCoord,
             long style = wxWANTS_CHARS,
             const wxString& name = wxPanelNameStr )
-        : wxScrolledWindow( parent, wxID_ANY, wxPoint(x,y), wxSize(w,h),
-                            (style|wxWANTS_CHARS), name )
-        {
-            InitVars();
-            Create();
-        }
+    {
+        Init();
+        Create(parent, wxID_ANY, wxPoint(x, y), wxSize(w, h), style, name);
+    }
 
     void SetCellValue( const wxString& val, int row, int col )
         { SetCellValue( row, col, val ); }
@@ -1894,9 +1952,30 @@ protected:
     bool m_created;
 
     wxGridWindow             *m_gridWin;
-    wxGridRowLabelWindow     *m_rowLabelWin;
-    wxGridColLabelWindow     *m_colLabelWin;
     wxGridCornerLabelWindow  *m_cornerLabelWin;
+    wxGridRowLabelWindow     *m_rowLabelWin;
+
+    // the real type of the column window depends on m_useNativeHeader value:
+    // if it is true, its dynamic type is wxHeaderCtrl, otherwise it is
+    // wxGridColLabelWindow, use accessors below when the real type matters
+    wxWindow *m_colWindow;
+
+    wxHeaderCtrl *GetColHeader() const
+    {
+        wxASSERT_MSG( m_useNativeHeader, "no column header window" );
+
+        // static_cast<> doesn't work without the full class declaration in
+        // view and we prefer to avoid adding more compile-time dependencies
+        // even at the cost of using reinterpret_cast<>
+        return reinterpret_cast<wxHeaderCtrl *>(m_colWindow);
+    }
+
+    wxGridColLabelWindow *GetColLabelWindow() const
+    {
+        wxASSERT_MSG( !m_useNativeHeader, "no column label window" );
+
+        return reinterpret_cast<wxGridColLabelWindow *>(m_colWindow);
+    }
 
     wxGridTableBase          *m_table;
     bool                      m_ownTable;
@@ -1944,7 +2023,11 @@ protected:
     wxArrayInt m_colWidths;
     wxArrayInt m_colRights;
 
-    bool m_nativeColumnLabels;
+    int m_sortCol;
+    bool m_sortIsAscending;
+
+    bool m_useNativeHeader,
+         m_nativeColumnLabels;
 
     // get the col/row coords
     int GetColWidth(int col) const;
@@ -2078,7 +2161,6 @@ protected:
 
     //Column positions
     wxArrayInt m_colAt;
-    int m_moveToCol;
 
     bool    m_canDragRowSize;
     bool    m_canDragColSize;
@@ -2117,9 +2199,9 @@ protected:
     int m_scrollLineX; // X scroll increment
     int m_scrollLineY; // Y scroll increment
 
+    void Init();        // common part of all ctors
     void Create();
-    void Init();
-    void InitVars();
+    void CreateColumnWindow();
     void CalcDimensions();
     void CalcWindowSizes();
     bool Redimension( wxGridTableMessage& );
@@ -2178,6 +2260,8 @@ protected:
     friend class wxGridRowLabelWindow;
     friend class wxGridWindow;
 
+    friend class wxGridHeaderCtrl;
+
 private:
     // implement wxScrolledWindow method to return m_gridWin size
     virtual wxSize GetSizeAvailableForScrollTarget(const wxSize& size);
@@ -2188,6 +2272,21 @@ 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
+    //
+    // this always returns a valid position, even if the coordinate is out of
+    // bounds (in which case first/last column is returned)
+    int XToPos(int x) const;
+
 
     // event handlers and their helpers
     // --------------------------------
@@ -2225,16 +2324,25 @@ 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);
+    void DoStartMoveCol(int col);
+
     void DoEndDragResizeRow();
-    void DoEndDragResizeCol();
-    void DoEndDragMoveCol();
+    void DoEndDragResizeCol(wxMouseEvent *event = NULL);
+    void DoEndMoveCol(int pos);
 
 
     // common implementations of methods defined for both rows and columns
     void DeselectLine(int line, const wxGridOperations& oper);
     void DoEndDragResizeLine(const wxGridOperations& oper);
-    int  PosToLine(int pos, bool clipToMinMax,
-                   const wxGridOperations& oper) const;
+    int PosToLinePos(int pos, bool clipToMinMax,
+                     const wxGridOperations& oper) const;
+    int PosToLine(int pos, bool clipToMinMax,
+                  const wxGridOperations& oper) const;
     int PosToEdgeOfLine(int pos, const wxGridOperations& oper) const;
 
     bool DoMoveCursor(bool expandSelection,
@@ -2326,7 +2434,9 @@ public:
         SetEventObject(obj);
     }
 
-    wxDEPRECATED(
+    // explicitly specifying inline allows gcc < 3.4 to
+    // handle the deprecation attribute even in the constructor.
+    wxDEPRECATED( inline
     wxGridEvent(int id,
                 wxEventType type,
                 wxObject* obj,
@@ -2387,7 +2497,7 @@ public:
         SetEventObject(obj);
     }
 
-    wxDEPRECATED(
+    wxDEPRECATED( inline
     wxGridSizeEvent(int id,
                     wxEventType type,
                     wxObject* obj,
@@ -2445,7 +2555,7 @@ public:
         SetEventObject(obj);
     }
 
-    wxDEPRECATED(
+    wxDEPRECATED( inline
     wxGridRangeSelectEvent(int id,
                            wxEventType type,
                            wxObject* obj,
@@ -2535,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&);
@@ -2577,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)
@@ -2598,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)