All (GUI):
+- wxGrid: add possibility to prevent resizing of individual rows/columns.
- wxHTML: add support for table borders width (Laurent Humbertclaude).
i18n:
with wxGrid::AutoSizeRows().
Additionally, by default the user can also drag the row separator lines to
-resize the rows interactively. This can be forbidden by calling
-wxGrid::DisableDragRowSize(). If you do allow the user to resize the grid rows,
-it may be a good idea to save their heights and restore it when the grid is
-recreated the next time (possibly during a next program execution): the
-functions wxGrid::GetRowSizes() and wxGrid::SetRowSizes() can help with this,
-you will just need to serialize wxGridSizesInfo structure returned by the
-former in some way and deserialize it back before calling the latter.
+resize the rows interactively. This can be forbidden completely by calling
+wxGrid::DisableDragRowSize() or just for the individual rows using
+wxGrid::DisableRowResize().
+
+If you do allow the user to resize the grid rows, it may be a good idea to save
+their heights and restore it when the grid is recreated the next time (possibly
+during a next program execution): the functions wxGrid::GetRowSizes() and
+wxGrid::SetRowSizes() can help with this, you will just need to serialize
+wxGridSizesInfo structure returned by the former in some way and deserialize it
+back before calling the latter.
*/
#if wxUSE_GRID
+#include "wx/hashmap.h"
+
#include "wx/scrolwin.h"
// ----------------------------------------------------------------------------
class WXDLLIMPEXP_FWD_CORE wxSpinCtrl;
#endif
+class wxGridFixedIndicesSet;
+
class wxGridOperations;
class wxGridRowOperations;
class wxGridColumnOperations;
// their non default size for those which don't have the default size.
// ----------------------------------------------------------------------------
-// Hashmap to store postions as the keys and sizes as the values
+// hash map to store positions as the keys and sizes as the values
WX_DECLARE_HASH_MAP_WITH_DECL( unsigned, int, wxIntegerHash, wxIntegerEqual,
wxUnsignedToIntHashMap, class WXDLLIMPEXP_ADV );
void SetCellHighlightPenWidth(int width);
void SetCellHighlightROPenWidth(int width);
+
+ // interactive grid mouse operations control
+ // -----------------------------------------
+
+ // functions globally enabling row/column interactive resizing (enabled by
+ // default)
void EnableDragRowSize( bool enable = true );
void DisableDragRowSize() { EnableDragRowSize( false ); }
- bool CanDragRowSize() const { return m_canDragRowSize; }
+
void EnableDragColSize( bool enable = true );
void DisableDragColSize() { EnableDragColSize( false ); }
- bool CanDragColSize() const { return m_canDragColSize; }
+
+ // if interactive resizing is enabled, some rows/columns can still have
+ // fixed size
+ void DisableRowResize(int row) { DoDisableLineResize(row, m_setFixedRows); }
+ void DisableColResize(int col) { DoDisableLineResize(col, m_setFixedCols); }
+
+ // these functions return whether the given row/column can be
+ // effectively resized: for this interactive resizing must be enabled
+ // and this index must not have been passed to DisableRow/ColResize()
+ bool CanDragRowSize(int row) const
+ { return m_canDragRowSize && DoCanResizeLine(row, m_setFixedRows); }
+ bool CanDragColSize(int col) const
+ { return m_canDragColSize && DoCanResizeLine(col, m_setFixedCols); }
+
+ // interactive column reordering (disabled by default)
void EnableDragColMove( bool enable = true );
void DisableDragColMove() { EnableDragColMove( false ); }
bool CanDragColMove() const { return m_canDragColMove; }
+
+ // interactive resizing of grid cells (enabled by default)
void EnableDragGridSize(bool enable = true);
void DisableDragGridSize() { EnableDragGridSize(false); }
bool CanDragGridSize() const { return m_canDragGridSize; }
+ // interactive dragging of cells (disabled by default)
void EnableDragCell( bool enable = true );
void DisableDragCell() { EnableDragCell( false ); }
bool CanDragCell() const { return m_canDragCell; }
wxGRID_CHECKBOX,
wxGRID_CHOICE,
wxGRID_COMBOBOX };
+
+ wxDEPRECATED_INLINE(bool CanDragRowSize() const, return m_canDragRowSize; )
+ wxDEPRECATED_INLINE(bool CanDragColSize() const, return m_canDragColSize; )
#endif // WXWIN_COMPATIBILITY_2_8
bool DoAppendLines(bool (wxGridTableBase::*funcAppend)(size_t),
int num, bool updateLabels);
- // Common part of Set{Col,Row}Sizes
+ // common part of Set{Col,Row}Sizes
void DoSetSizes(const wxGridSizesInfo& sizeInfo,
const wxGridOperations& oper);
+ // common part of Disable{Row,Col}Resize and CanDrag{Row,Col}Size
+ void DoDisableLineResize(int line, wxGridFixedIndicesSet *& setFixed);
+ bool DoCanResizeLine(int line, const wxGridFixedIndicesSet *setFixed) const;
+
+
+
+ // these sets contain the indices of fixed, i.e. non-resizable
+ // interactively, grid rows or columns and are NULL if there are no fixed
+ // elements (which is the default)
+ wxGridFixedIndicesSet *m_setFixedRows,
+ *m_setFixedCols;
+
DECLARE_DYNAMIC_CLASS( wxGrid )
DECLARE_EVENT_TABLE()
wxDECLARE_NO_COPY_CLASS(wxGrid);
// we can't know in advance whether we can sort by this column or not
// with wxGrid API so suppose we can by default
int flags = wxCOL_SORTABLE;
- if ( m_grid->CanDragColSize() )
+ if ( m_grid->CanDragColSize(m_col) )
flags |= wxCOL_RESIZABLE;
if ( m_grid->CanDragColMove() )
flags |= wxCOL_REORDERABLE;
// Set the row default height or column default width
virtual void SetDefaultLineSize(wxGrid *grid, int size, bool resizeExisting) const = 0;
- // True if rows/columns can be resized by user
- virtual bool CanResizeLines(const wxGrid *grid) const = 0;
-
// Return the index of the line at the given position
//
{ return grid->GetRowMinimalHeight(line); }
virtual void SetLineSize(wxGrid *grid, int line, int size) const
{ grid->SetRowSize(line, size); }
- virtual bool CanResizeLines(const wxGrid *grid) const
- { return grid->CanDragRowSize(); }
virtual void SetDefaultLineSize(wxGrid *grid, int size, bool resizeExisting) const
- { grid->SetDefaultRowSize(size, resizeExisting); }
+ { grid->SetDefaultRowSize(size, resizeExisting); }
virtual int GetLineAt(const wxGrid * WXUNUSED(grid), int line) const
{ return line; } // TODO: implement row reordering
{ return grid->GetColMinimalWidth(line); }
virtual void SetLineSize(wxGrid *grid, int line, int size) const
{ grid->SetColSize(line, size); }
- virtual bool CanResizeLines(const wxGrid *grid) const
- { return grid->CanDragColSize(); }
virtual void SetDefaultLineSize(wxGrid *grid, int size, bool resizeExisting) const
- { grid->SetDefaultColSize(size, resizeExisting); }
+ { grid->SetDefaultColSize(size, resizeExisting); }
virtual int GetLineAt(const wxGrid *grid, int line) const
{ return grid->GetColAt(line); }
/**
@name Column and Row Sizes
+
+ @see overview_grid_resizing
*/
//@{
/**
@name User-Resizing and Dragging
+
+ Functions controlling various interactive mouse operations.
+
+ By default, columns and rows can be resized by dragging the edges of
+ their labels (this can be disabled using DisableDragColSize() and
+ DisableDragRowSize() methods). And if grid line dragging is enabled with
+ EnableDragGridSize() they can also be resized by dragging the right or
+ bottom edge of the grid cells.
+
+ Columns can also be moved to interactively change their order but this
+ needs to be explicitly enabled with EnableDragColMove().
*/
//@{
bool CanDragColMove() const;
/**
- Returns @true if columns can be resized by dragging with the mouse.
+ Returns @true if the given column can be resized by dragging with the
+ mouse.
- Columns can be resized by dragging the edges of their labels. If grid
- line dragging is enabled they can also be resized by dragging the right
- edge of the column in the grid cell area (see EnableDragGridSize()).
+ This function returns @true if resizing the columns interactively is
+ globally enabled, i.e. if DisableDragColSize() hadn't been called, and
+ if this column wasn't explicitly marked as non-resizable with
+ DisableColResize().
*/
- bool CanDragColSize() const;
+ bool CanDragColSize(int col) const;
/**
Return @true if the dragging of grid lines to resize rows and columns
bool CanDragGridSize() const;
/**
- Returns @true if rows can be resized by dragging with the mouse.
+ Returns @true if the given row can be resized by dragging with the
+ mouse.
- Rows can be resized by dragging the edges of their labels. If grid line
- dragging is enabled they can also be resized by dragging the lower edge
- of the row in the grid cell area (see EnableDragGridSize()).
+ This is the same as CanDragColSize() but for rows.
*/
- bool CanDragRowSize() const;
+ bool CanDragRowSize(int row) const;
+
+ /**
+ Disable interactive resizing of the specified column.
+
+ This method allows to disable resizing of an individual column in a
+ grid where the columns are otherwise resizable (which is the case by
+ default).
+
+ Notice that currently there is no way to make some columns resizable in
+ a grid where columns can't be resized by default as there doesn't seem
+ to be any need for this in practice. There is also no way to make the
+ column marked as fixed using this method resizeable again because it is
+ supposed that fixed columns are used for static parts of the grid and
+ so should remain fixed during the entire grid lifetime.
+
+ Also notice that disabling interactive column resizing will not prevent
+ the program from changing the column size.
+
+ @see EnableDragColSize()
+ */
+ void DisableColResize(int col);
+
+ /**
+ Disable interactive resizing of the specified row.
+
+ This is the same as DisableColResize() but for rows.
+
+ @see EnableDragRowSize()
+ */
+ void DisableRowResize(int row);
/**
Disables column moving by dragging with the mouse.
/**
Enables or disables column sizing by dragging with the mouse.
+
+ @see DisableColResize()
*/
void EnableDragColSize(bool enable = true);
/**
Enables or disables row sizing by dragging with the mouse.
+
+ @see DisableRowResize()
*/
void EnableDragRowSize(bool enable = true);
grid->SetCellAlignment(7, 1, wxALIGN_CENTRE, wxALIGN_CENTRE);
grid->SetCellValue(7, 1, _T("Big box!"));
+ // create a separator-like row: it's grey and it's non-resizeable
+ grid->DisableRowResize(10);
+ grid->SetRowSize(10, 30);
+ attr = new wxGridCellAttr;
+ attr->SetBackgroundColour(*wxLIGHT_GREY);
+ grid->SetRowAttr(10, attr);
+ grid->SetCellValue(10, 0, "You can't resize this row interactively -- try it");
+
// this does exactly nothing except testing that SetAttr() handles NULL
// attributes and does reference counting correctly
grid->SetAttr(11, 11, NULL);
#include "wx/tokenzr.h"
#include "wx/renderer.h"
#include "wx/headerctrl.h"
+#include "wx/hashset.h"
#include "wx/generic/gridsel.h"
#include "wx/generic/gridctrl.h"
// Required for wxIs... functions
#include <ctype.h>
+WX_DECLARE_HASH_SET_WITH_DECL(int, wxIntegerHash, wxIntegerEqual,
+ wxGridFixedIndicesSet, class WXDLLIMPEXP_ADV);
+
// ----------------------------------------------------------------------------
// globals
delete m_typeRegistry;
delete m_selection;
+
+ delete m_setFixedRows;
+ delete m_setFixedCols;
}
//
m_rowLabelWidth = WXGRID_DEFAULT_ROW_LABEL_WIDTH;
m_colLabelHeight = WXGRID_DEFAULT_COL_LABEL_HEIGHT;
+ m_setFixedRows =
+ m_setFixedCols = NULL;
+
// init attr cache
m_attrCache.row = -1;
m_attrCache.col = -1;
//
else if ( event.LeftDown() )
{
- // don't send a label click event for a hit on the
- // edge of the row label - this is probably the user
- // wanting to resize the row
- //
- if ( YToEdgeOfRow(y) < 0 )
+ row = YToEdgeOfRow(y);
+ if ( row != wxNOT_FOUND && CanDragRowSize(row) )
+ {
+ ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW, m_rowLabelWin);
+ }
+ else // not a request to start resizing
{
row = YToRow(y);
if ( row >= 0 &&
ChangeCursorMode(WXGRID_CURSOR_SELECT_ROW, m_rowLabelWin);
}
}
- else
- {
- // starting to drag-resize a row
- if ( CanDragRowSize() )
- ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW, m_rowLabelWin);
- }
}
// ------------ Left double click
else if (event.LeftDClick() )
{
row = YToEdgeOfRow(y);
- if ( row < 0 )
+ if ( row != wxNOT_FOUND && CanDragRowSize(row) )
+ {
+ // adjust row height depending on label text
+ AutoSizeRowLabelSize( row );
+
+ ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL, GetColLabelWindow());
+ m_dragLastPos = -1;
+ }
+ else // not on row separator or it's not resizeable
{
row = YToRow(y);
if ( row >=0 &&
// no default action at the moment
}
}
- else
- {
- // adjust row height depending on label text
- AutoSizeRowLabelSize( row );
-
- ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL, GetColLabelWindow());
- m_dragLastPos = -1;
- }
}
// ------------ Left button released
else if ( event.Moving() )
{
m_dragRowOrCol = YToEdgeOfRow( y );
- if ( m_dragRowOrCol >= 0 )
+ if ( m_dragRowOrCol != wxNOT_FOUND )
{
if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
{
- // don't capture the mouse yet
- if ( CanDragRowSize() )
+ if ( CanDragRowSize(m_dragRowOrCol) )
ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW, m_rowLabelWin, false);
}
}
//
else if ( event.LeftDown() )
{
- // don't send a label click event for a hit on the
- // edge of the col label - this is probably the user
- // wanting to resize the col
- //
- if ( XToEdgeOfCol(x) < 0 )
+ int col = XToEdgeOfCol(x);
+ if ( col != wxNOT_FOUND && CanDragColSize(col) )
{
+ ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL, GetColLabelWindow());
+ }
+ else // not a request to start resizing
+ {
+ col = XToCol(x);
if ( col >= 0 &&
!SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK, -1, col, event ) )
{
}
}
}
- else
- {
- // starting to drag-resize a col
- //
- if ( CanDragColSize() )
- ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL, GetColLabelWindow());
- }
}
// ------------ Left double click
{
if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
{
- // don't capture the cursor yet
- if ( CanDragColSize() )
+ if ( CanDragColSize(m_dragRowOrCol) )
ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL, GetColLabelWindow(), false);
}
}
return;
}
- if ( dragRow >= 0 )
+ if ( dragRow >= 0 && CanDragGridSize() && CanDragRowSize(dragRow) )
{
- m_dragRowOrCol = dragRow;
-
if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
{
- if ( CanDragRowSize() && CanDragGridSize() )
- ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW, NULL, false);
+ m_dragRowOrCol = dragRow;
+ ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW, NULL, false);
}
}
// When using the native header window we can only resize the columns by
// dragging the dividers in it because we can't make it enter into the
// column resizing mode programmatically
- else if ( dragCol >= 0 && !m_useNativeHeader )
+ else if ( dragCol >= 0 && !m_useNativeHeader &&
+ CanDragGridSize() && CanDragColSize(dragCol) )
{
- m_dragRowOrCol = dragCol;
-
if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
{
- if ( CanDragColSize() && CanDragGridSize() )
- ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL, NULL, false);
+ m_dragRowOrCol = dragCol;
+ ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL, NULL, false);
}
}
else // Neither on a row or col edge
return PosToLinePos(x, true /* clip */, wxGridColumnOperations());
}
-// return the row number that that the y coord is near the edge of, or -1 if
+// return the row number such that the y coord is near the edge of, or -1 if
// not near an edge.
//
-// coords can only possibly be near an edge if
-// (a) the row/column is large enough to still allow for an "inner" area
-// that is _not_ near the edge (i.e., if the height/width is smaller
-// than WXGRID_LABEL_EDGE_ZONE, coords are _never_ considered to be
-// near the edge).
-// and
-// (b) resizing rows/columns (the thing for which edge detection is
-// relevant at all) is enabled.
-//
+// notice that position can only possibly be near an edge if the row/column is
+// large enough to still allow for an "inner" area that is _not_ near the edge
+// (i.e., if the height/width is smaller than WXGRID_LABEL_EDGE_ZONE, pos will
+// _never_ be considered to be near the edge).
int wxGrid::PosToEdgeOfLine(int pos, const wxGridOperations& oper) const
{
- if ( !oper.CanResizeLines(this) )
- return -1;
-
const int line = oper.PosToLine(this, pos, true);
if ( oper.GetLineSize(this, line) > WXGRID_LABEL_EDGE_ZONE )
// row/col size
// ----------------------------------------------------------------------------
+void wxGrid::DoDisableLineResize(int line, wxGridFixedIndicesSet *& setFixed)
+{
+ if ( !setFixed )
+ {
+ setFixed = new wxGridFixedIndicesSet;
+ }
+
+ setFixed->insert(line);
+}
+
+bool
+wxGrid::DoCanResizeLine(int line, const wxGridFixedIndicesSet *setFixed) const
+{
+ return !setFixed || !setFixed->count(line);
+}
+
void wxGrid::EnableDragRowSize( bool enable )
{
m_canDragRowSize = enable;