Add support for freezing columns and/or rows of wxGrid

Add wxGrid::FreezeTo() method which allows to freeze the given number of
columns and/or rows at the beginning of the grid, i.e. keep them pinned
in place while the rest of the grid is scrolled.

The main wxGridWindow (m_gridWin) now corresponds to the non-frozen part
of the grid, with up to 3 new similar windows for the frozen
rows/columns and the frozen corner cells (which only exist if both rows
and columns are frozen) being additionally used.

Doing this involved adding "wxGridWindow*" parameter to many functions
that previously only worked with m_gridWin itself and addressing
additional complications, such as mouse events that can now cross
different windows.

See https://github.com/wxWidgets/wxWidgets/pull/952 for the original
version of the changes.
This commit is contained in:
lucian-rotariu
2019-07-03 23:07:30 +03:00
committed by Vadim Zeitlin
parent f61b58bba3
commit 04f7f1fd32
6 changed files with 1477 additions and 409 deletions

View File

@@ -2687,8 +2687,13 @@ public:
Also note that currently @c wxEVT_GRID_LABEL_RIGHT_DCLICK event is not
generated for the column labels if the native columns header is used
(but this limitation could possibly be lifted in the future).
Finally, please note that using the native control is currently
incompatible with freezing columns in the grid (see FreezeTo()) and
this function will return @false, without doing anything, if it's
called on a grid in which any columns are frozen.
*/
void UseNativeColHeader(bool native = true);
bool UseNativeColHeader(bool native = true);
//@}
@@ -3767,8 +3772,14 @@ public:
/**
Enables or disables column moving by dragging with the mouse.
Note that reordering columns by dragging them is currently not
supported when the grid has any frozen columns (see FreezeTo()) and if
this method is called with @a enable equal to @true in this situation,
it returns @false without doing anything. Otherwise it returns @true to
indicate that it was successful.
*/
void EnableDragColMove(bool enable = true);
bool EnableDragColMove(bool enable = true);
/**
Enables or disables column sizing by dragging with the mouse.
@@ -4280,10 +4291,13 @@ public:
limited by @a topLeft and @a bottomRight cell in device coords and
clipped to the client size of the grid window.
@since 3.1.3 Parameter @a gridWindow has been added.
@see CellToRect()
*/
wxRect BlockToDeviceRect(const wxGridCellCoords& topLeft,
const wxGridCellCoords& bottomRight) const;
const wxGridCellCoords& bottomRight,
const wxGridWindow *gridWindow = NULL) const;
/**
Return the rectangle corresponding to the grid cell's size and position
@@ -4301,7 +4315,78 @@ public:
wxRect CellToRect(const wxGridCellCoords& coords) const;
/**
Returns the column at the given pixel position.
Returns the grid window that contains the cell.
In a grid without frozen rows or columns (see FreezeTo()), this will
always return the same window as GetGridWindow(), however if some parts
of the grid are frozen, this function returns the window containing the
given cell.
@since 3.1.3
*/
wxGridWindow* CellToGridWindow( int row, int col ) const;
/// @overload
wxGridWindow* CellToGridWindow( const wxGridCellCoords& coords ) const
/**
Returns the grid window that includes the input coordinates.
@since 3.1.3
*/
wxGridWindow* DevicePosToGridWindow(wxPoint pos) const;
/// @overload
wxGridWindow* DevicePosToGridWindow(int x, int y) const;
/**
Returns the grid window's offset from the grid starting position taking
into account the frozen cells.
If there are no frozen cells, returns (0, 0).
@since 3.1.3
@see FreezeTo()
*/
void GetGridWindowOffset(const wxGridWindow *gridWindow, int &x, int &y) const;
/// @overload
wxPoint GetGridWindowOffset(const wxGridWindow *gridWindow) const;
/**
Translates the device coordinates to the logical ones, taking into
account the grid window type.
@since 3.1.3
@see wxScrolled::CalcUnscrolledPosition()
*/
void CalcGridWindowUnscrolledPosition(int x, int y,
int *xx, int *yy,
const wxGridWindow *gridWindow) const;
/// @overload
wxPoint CalcGridWindowUnscrolledPosition(const wxPoint& pt,
const wxGridWindow *gridWindow) const;
/**
Translates the logical coordinates to the device ones, taking into
account the grid window type.
@since 3.1.3
@see wxScrolled::CalcScrolledPosition()
*/
void CalcGridWindowScrolledPosition(int x, int y,
int *xx, int *yy,
const wxGridWindow *gridWindow) const;
/// @overload
wxPoint CalcGridWindowScrolledPosition(const wxPoint& pt,
const wxGridWindow *gridWindow) const;
/**
Returns the column at the given pixel position depending on the window.
@param x
The x position to evaluate.
@@ -4309,10 +4394,15 @@ public:
If @true, rather than returning @c wxNOT_FOUND, it returns either
the first or last column depending on whether @a x is too far to
the left or right respectively.
@param gridWindow
The associated grid window that limits the search (note that this
parameter is only available since wxWidgets 3.1.3).
If @a gridWindow is @NULL, it will consider all the cells, no matter
which grid they belong to.
@return
The column index or @c wxNOT_FOUND.
*/
int XToCol(int x, bool clipToMinMax = false) const;
int XToCol(int x, bool clipToMinMax = false, wxGridWindow *gridWindow = NULL) const;
/**
Returns the column whose right hand edge is close to the given logical
@@ -4330,20 +4420,22 @@ public:
the mouse position, which is expressed in device coordinates, to
logical ones.
@see XToCol(), YToRow()
*/
wxGridCellCoords XYToCell(int x, int y) const;
/**
Translates logical pixel coordinates to the grid cell coordinates.
The parameter @a gridWindow is new since wxWidgets 3.1.3. If it is
specified, i.e. non-@NULL, the coordinates must be in this window
coordinate system and only the cells of this window are considered,
i.e. the function returns @c wxNOT_FOUND if the coordinates are out of
bounds.
Notice that this function expects logical coordinates on input so if
you use this function in a mouse event handler you need to translate
the mouse position, which is expressed in device coordinates, to
logical ones.
If @a gridWindow is @NULL, coordinates are relative to the main grid
window and all cells are considered.
@see XToCol(), YToRow()
*/
wxGridCellCoords XYToCell(const wxPoint& pos) const;
wxGridCellCoords XYToCell(int x, int y, wxGridWindow *gridWindow = NULL) const;
/// @overload
wxGridCellCoords XYToCell(const wxPoint& pos, wxGridWindow *gridWindow = NULL) const;
// XYToCell(int, int, wxGridCellCoords&) overload is intentionally
// undocumented, using it is ugly and non-const reference parameters are
// not used in wxWidgets API
@@ -4359,9 +4451,16 @@ public:
/**
Returns the grid row that corresponds to the logical @a y coordinate.
Returns @c wxNOT_FOUND if there is no row at the @a y position.
The parameter @a gridWindow is new since wxWidgets 3.1.3. If it is
specified, i.e. non-@NULL, only the cells of this window are
considered, i.e. the function returns @c wxNOT_FOUND if @a y is out of
bounds.
If @a gridWindow is @NULL, the function returns @c wxNOT_FOUND only if
there is no row at all at the @a y position.
*/
int YToRow(int y, bool clipToMinMax = false) const;
int YToRow(int y, bool clipToMinMax = false, wxGridWindow *gridWindow = NULL) const;
//@}
@@ -4489,6 +4588,31 @@ public:
*/
bool DeleteRows(int pos = 0, int numRows = 1, bool updateLabels = true);
/**
Sets or resets the frozen columns and rows.
@param row
The number of rows to freeze, 0 means to unfreeze all rows.
@param col
The number of columns to freeze, 0 means to unfreeze all columns.
@return @true on success or @false if it failed.
Note that this method doesn't do anything, and returns @false, if any
of the following conditions are true:
- Either @a row or @a col are out of range
- Size of the frozen area would be bigger than the current viewing area
- There are any merged cells in the area to be frozen
- Grid uses a native header control (see UseNativeColHeader())
(some of these limitations could be lifted in the future).
@since 3.1.3
*/
bool FreezeTo(unsigned row, unsigned col);
/// @overload
bool FreezeTo(const wxGridCellCoords& coords);
/**
Decrements the grid's batch count.
@@ -4535,6 +4659,28 @@ public:
*/
int GetNumberRows() const;
/**
Returns the number of frozen grid columns.
If there are no frozen columns, returns 0.
@since 3.1.3
@see FreezeTo()
*/
int GetNumberFrozenCols() const;
/**
Returns the number of frozen grid rows.
If there are no frozen rows, returns 0.
@since 3.1.3
@see FreezeTo()
*/
int GetNumberFrozenRows() const;
/**
Returns the attribute for the given cell creating one if necessary.
@@ -4693,9 +4839,12 @@ public:
void SetRowAttr(int row, wxGridCellAttr* attr);
wxArrayInt CalcRowLabelsExposed( const wxRegion& reg );
wxArrayInt CalcColLabelsExposed( const wxRegion& reg );
wxGridCellCoordsArray CalcCellsExposed( const wxRegion& reg );
wxArrayInt CalcRowLabelsExposed( const wxRegion& reg,
wxGridWindow *gridWindow = NULL) const;
wxArrayInt CalcColLabelsExposed( const wxRegion& reg,
wxGridWindow *gridWindow = NULL) const;
wxGridCellCoordsArray CalcCellsExposed( const wxRegion& reg,
wxGridWindow *gridWindow = NULL) const;
//@}
@@ -4776,15 +4925,19 @@ public:
Return the various child windows of wxGrid.
wxGrid is an empty parent window for 4 children representing the column
labels window (top), the row labels window (left), the corner window
(top left) and the main grid window. It may be necessary to use these
individual windows and not the wxGrid window itself if you need to
handle events for them (this can be done using wxEvtHandler::Connect()
or wxWindow::PushEventHandler()) or do something else requiring the use
of the correct window pointer. Notice that you should not, however,
change these windows (e.g. reposition them or draw over them) because
they are managed by wxGrid itself.
wxGrid is an empty parent window for at least 4 children representing
the column labels window (top), the row labels window (left), the
corner window (top left) and the main grid window. It may be necessary
to use these individual windows and not the wxGrid window itself if you
need to handle events for them (using wxEvtHandler::Bind()) or do
something else requiring the use of the correct window pointer. Notice
that you should not, however, change these windows (e.g. reposition
them or draw over them) because they are managed by wxGrid itself.
When parts of the grid are frozen using FreezeTo() function, the main
grid window contains only the unfrozen part and additional windows are
used for the parts containing frozen rows and/or columns and the corner
window if both some rows and some columns are frozen.
*/
//@{
@@ -4795,6 +4948,33 @@ public:
*/
wxWindow *GetGridWindow() const;
/**
Return the corner grid window containing frozen cells.
This window is shown only when there are frozen rows and columns.
@since 3.1.3
*/
wxWindow* GetFrozenCornerGridWindow() const;
/**
Return the rows grid window containing row frozen cells.
This window is shown only when there are frozen rows.
@since 3.1.3
*/
wxWindow* GetFrozenRowGridWindow() const;
/**
Return the columns grid window containing column frozen cells.
This window is shown only when there are frozen columns.
@since 3.1.3
*/
wxWindow* GetFrozenColGridWindow() const;
/**
Return the row labels window.
@@ -4864,6 +5044,8 @@ public:
void SetCellHighlightColour( const wxColour& );
void SetCellHighlightPenWidth(int width);
void SetCellHighlightROPenWidth(int width);
void SetGridFrozenBorderColour( const wxColour& );
void SetGridFrozenBorderPenWidth( int width );
protected: