Commit Graph

759 Commits

Author SHA1 Message Date
Vadim Zeitlin
249db04dd3 Add wxGridTableBase::CanMeasureColUsingSameAttr()
This allows to optimize AutoSizeColumns() in the common case when all
cells in the same column can be measured using the same attribute.
2020-06-11 10:03:13 +02:00
Vadim Zeitlin
79d25664eb Optimize wxGrid::GetBestSize() when using uniform row/column size
There is no need to iterate over all rows or columns if all of them have
the same size anyhow.
2020-06-07 17:04:49 +02:00
Vadim Zeitlin
123e21c181 Refactor wxGrid::SetOrCalcColumnSizes() and SetOrCalcRowSizes()
Get rid of the unnecessarily complicated functions doing two quite
different things depending on whether their first boolean parameter was
true of false.

Instead, split their body between AutoSize{Columns,Rows}() (which used
to call them) and DoGetBestSize(), keeping just the part needed in each
case.

This is much simpler and even more efficient, as it avoids a completely
unnecessary call to CalcDimensions() and Refresh() from DoGetBestSize(),
which doesn't change the current size at all and so doesn't need to
refresh anything, but previously did it and not only once, but twice,
because both of SetOrCalc{Column,Row}Sizes() did it.
2020-05-31 17:51:12 +02:00
Vadim Zeitlin
eac58e7f87 Simplify wxGrid best size computations
Remove needless subtraction of row/column label size before adding it
back again, as this seems completely unnecessary.

No real changes, this is just a simplification.
2020-05-31 16:12:26 +02:00
Vadim Zeitlin
3307000baa Add wxGrid::GetSelectedRowBlocks() and GetSelectedColBlocks()
These functions are much simpler to use in the application code using
wxGrid in row- or column-only selection mode than GetSelectedBlocks()
itself because they take care of deduplicating, ordering and squashing
together the adjacent ranges, so that the application can use their
results directly, unlike with GetSelectedBlocks().
2020-05-27 03:19:34 +02:00
Vadim Zeitlin
f1425dad13 Don't hard code grid lines colour in wxGrid
Use wxSYS_COLOUR_BTNFACE instead of the hardcoded value of this colour
in "Windows Classic" theme, which was probably used back when the commit
73145b0ed1 (Applied patches by Scott Pleiter:, 2002-12-09), which was
supposed to change wxGrid to use system colours (among other things),
was done.

Nowadays wxSYS_COLOUR_BTNFACE is 0xF0F0F0 rather than 0xC0C0C0, which is
quite different visually, but it still seems better to use the system
colour rather than the fixed value, especially for platforms with dark
mode support.

Closes https://github.com/wxWidgets/wxWidgets/pull/1866
2020-05-26 15:11:02 +02:00
Vadim Zeitlin
37b2918c9c Don't consume all 'C'/Insert key presses in wxGrid
Skip the key events other than Ctrl-C/Ins which are used for copying
grid contents to the clipboard, notably Alt-C which should still be
usable for opening the menus.

This fixes a problems introduced in 67c1c412c6 (Implement support for
copying wxGrid cells to clipboard, 2020-04-26), see #13562.
2020-05-26 02:00:18 +02:00
Vadim Zeitlin
7466681607 Merge branch 'grid-event-delete'
Handle deleting grid rows/columns in event handlers gracefully.

See https://github.com/wxWidgets/wxWidgets/pull/1834
2020-05-06 18:45:16 +02:00
Kvaz1r
67c1c412c6 Implement support for copying wxGrid cells to clipboard
This is useful for read-only grids, in which an editor can't be shown to
copy the value of a cell, and also for copying an entire selection block
and not just a single cell.

Closes https://github.com/wxWidgets/wxWidgets/pull/1824

Closes #13562.
2020-05-02 19:20:48 +02:00
Vadim Zeitlin
ebe7816516 Finish editing on Enter in cells in the last shown row of wxGrid
Previously, pressing Enter in a cell of a row which wasn't the last one,
but was the last shown one, didn't do anything because we explicitly
checked whether the cell was in the last row and not in the last visible
row, but MoveCursorDown() doesn't move the cursor for the latter, and
not just for the former.

Fix this by avoiding any row checks at all and just calling
MoveCursorDown() in any case and DisableCellEditControl() if it didn't
do anything.

Closes #18754.
2020-05-02 17:45:51 +02:00
Vadim Zeitlin
e6e6dbe077 Fix problems due to deleting grid cells in the event handlers
Deleting last grid rows or column in a few event handlers could result
in asserts/crashes in wxGrid code if the event handler also called
event.Skip(), as wxGrid still tried to perform the default action using
the deleted cell, when these events happened in the last row or column.

It's not totally clear whether calling event.Skip() after performing an
action modifying the grid should be allowed at all, but, in doubt, at
least avoid crashing if it does happen, by considering the event as
being handled (and even vetoed) if its handler deleted the cell in which
it was generated.

Closes #18731.
2020-05-02 00:53:59 +02:00
Vadim Zeitlin
5cdcfddc61 Refactor event sending code in wxGrid to use even more functions
Move the logic determining the return value of SendEvent() into its own
function instead of repeating it twice.

No real changes, this is a pure refactoring.
2020-05-02 00:49:08 +02:00
Vadim Zeitlin
44c3e626b3 Extend current selection on {Ctrl,Shift}-Space
Extend the existing selection instead of adding a new block, as there is
no reason to keep the old selection as a separate block, when it's
always a subblock of the new one, and doing it resulted in wrong
behaviour when selecting 2 horizontally adjacent cells, pressing
Ctrl-Space and then pressing Shift-Left deselected the rightmost
selected column but still left its single cell, which was part of the
originally selected block, selected, which was surprising and looked
wrong.
2020-04-15 16:16:00 +02:00
Vadim Zeitlin
ed767ed324 Make Ctrl/Shift-Space apply to all cells of the current selection
This provides a convenient way to select multiple lines and is
consistent with the operation of these keys in spreadsheet programs.
2020-04-13 21:59:44 +02:00
Vadim Zeitlin
4cde93cc82 Optimize test for the row/column selection
Use wxGridSelection::IsInSelection() instead of GetSelectedRows/Cols()
which can be much slower as they need to produce an array containing
indices of all the selected rows/columns.
2020-04-13 21:45:54 +02:00
Vadim Zeitlin
ee0b70a3a9 Disable extending selection with Ctrl-drag for rows/columns too
Don't extend the selection if the anchor line is not selected, as this
doesn't work correctly because the entire selection logic supposes the
anchor itself is selected and, moreover, it's not really clear how could
it would otherwise.

This commit does the same thing for rows/columns as the grandparent
commit did to the cells. Unfortunately a somewhat cleaner solution of
the parent commit can't be easily applied to the existing rows/columns
code and it's arguably not worth changing it in depth just for this.
2020-04-13 21:41:40 +02:00
Vadim Zeitlin
e6186f73a6 Implement alternative solution to Ctrl-drag problem
This commit doesn't change the behaviour compared to the previous one,
but provides an alternative implementation of the same goal, which seems
preferable: instead of not extending the selection while Ctrl-dragging,
just don't enter dragging mode, i.e. don't capture the mouse and don't
set m_isDragging to true, if we start it from a previously selected, and
hence currently deselected, cell.
2020-04-13 21:33:55 +02:00
Vadim Zeitlin
52d1b86bbd Don't allow drag-extending selection from deselected cell
Dragging in a grid with Ctrl key pressed starting from a previously
selected cell behaved very counterintuitively if not downright wrongly,
as the selection logic assumes that the selection anchor itself is
always selected, which wasn't true in this case.

Solve the problem by just not extending the selection at all when
starting to drag from a deselected cell. This means that Ctrl-dragging
doesn't do anything any more, but it's not a huge loss and to make it
work well while still allowing to use Ctrl-click to toggle the cell
selection, we'd need to implement a whole new and different
drag-deselect mode, as is done in Microsoft Excel 2016 (note that the
previous versions of Excel don't implement Ctrl-dragging neither).
2020-04-13 18:46:54 +02:00
Vadim Zeitlin
6d4df74a03 Simplify and improve wxGrid::DoGridCellDrag() return value logic
Remove the "performDefault" variable which didn't really seem to help,
as the actual meaning of the return value is whether we should start
drag-selecting or not and the name of this variable didn't reflect this
anyhow.

Return false if we are over an invalid cell: this shouldn't change
anything when we're already dragging, but would prevent us from starting
to drag from an invalid cell which seems more correct, even if it's not
clear if this can happen in practice.

Also move hiding the edit control inside "isFirstDrag" check, there is
no reason to do it on every drag.
2020-04-13 18:37:47 +02:00
Vadim Zeitlin
abd9aaa431 Stop setting current cell on first Ctrl-drag event
This is not necessary any longer as the current cell is changed on
Ctrl-click since the previous commit.

This commit is best viewed ignoring whitespace.
2020-04-13 17:53:41 +02:00
Vadim Zeitlin
39d0c21a81 Do make Ctrl-clicked cell current
There isn't really any valid reason to ever set the current cell to the
corner of a block remaining after breaking up the currently selected
block after the deselection of the just clicked cell, so don't do it.

Just set the current cell to the clicked cell, whether it's selected or
not.
2020-04-13 17:48:15 +02:00
Vadim Zeitlin
da84a25311 Make the line whose header was Ctrl-clicked current
This is more consistent with Ctrl-clicking cells.

It also slightly improves behaviour when Ctrl-dragging mouse over the
range of selected lines, although it's still somewhat surprising.
2020-04-13 14:47:44 +02:00
Vadim Zeitlin
62cb90b455 Avoid horizontal scrolling when pressing Shift-Page Up/Down
Scroll the new end of selection into view only vertically, it would be
unexpected for the vertical Page Up/Down movement to scroll the grid
horizontally.
2020-04-13 14:21:07 +02:00
Vadim Zeitlin
b8c3c60316 Allow extending selection using Shift-Page Up/Down keys
Also make Page Up/Down themselves work consistently with the other
cursor movement keys and clear current selection if they move the
cursor.

Even though DoMoveCursorByPage() is simpler than DoMoveCursorByBlock(),
still factor out AdvanceByPage() for consistency with AdvanceByBlock()
and because it still makes the code more clear.
2020-04-13 01:23:25 +02:00
Vadim Zeitlin
bc3c6fea70 Fix Shift-Ctrl-arrows handling
Extending the selection with Ctrl-arrows is different from all the other
cases, as we need to combine both the selection anchor and the current
cell coordinates when doing it.

This means that we can't reuse the same PrepareForSelectionExpansion()
helper for this case, so this function is not useful finally and this
commit removes it entirely. It also replaces GetCurrentBlockCornerRow()
and GetCurrentBlockCornerCol() functions with GetExtensionAnchor() which
combines both of them.

Finally, it adds wxGridDirectionOperations::TryToAdvance() helper to
avoid repeating the IsAtBoundary() check which was previously part of
PrepareForSelectionExpansion() in multiple places.

And because the "extending" and normal parts of DoMoveCursorByBlock()
are so different now, it also factors out AdvanceByBlock() helper which
can be used to keep these parts well separate from each other instead of
intermixing them together.

With all these preparatory changes, it's finally possible to implement
the "extending selection by block" logic relatively easily, with the
bulk of this branch actually taken by comments explaining why do we have
to do what we do.

Add unit tests verifying that the functions used by Shift-Ctrl-arrow
work as expected.
2020-04-13 00:49:22 +02:00
Vadim Zeitlin
4f7ed07f5e Don't use row/column headers for selection incompatible with mode
Mouse events in row/column headers should be just ignored when the
current selection mode disallows row/column selection.

This wasn't the case before, and while actually selecting the line
corresponding to the header was disallowed further down the call chain,
clicking it still unexpectedly cleared the existing selection and
dragging mouse in the header window selected the entire grid.

Fix this by just never entering the corresponding cursor mode in the
first place if it's incompatible with the current selection mode.
2020-04-12 18:39:34 +02:00
Vadim Zeitlin
4cabffb983 Fix test for "almost visible" row in GetFirstFullyVisibleRow()
The test didn't correspond to the comment and resulted in always
considering the first row not visible instead of the intended effect.
2020-04-12 18:29:26 +02:00
Vadim Zeitlin
b98f439686 Also rename wxGridSelection::ExtendOrCreateCurrentBlock()
This function finally doesn't ever create a new block, except for the
trivial case when there is no current block, so rename it to a simpler
and more clear name.

No real changes.
2020-04-12 02:43:42 +02:00
Vadim Zeitlin
30eaa28de5 Rename wxGrid::GetSelectionRange() to GetSelectedBlocks()
This seems to be more consistent with the existing functions and doesn't
create ambiguity with a grid range.

Also rename wxGridSelectionRange to just wxGridBlocks as, in principle,
this class could be used for iterating over any blocks, not just the
selected ones.

No changes in functionality, this is just a renaming.
2020-04-12 02:38:37 +02:00
Vadim Zeitlin
c90bed6f8e Stop passing invalid coordinates to ExtendOrCreateCurrentBlock()
This made the logic of this function unnecessarily more complicated.
Instead, just fall back to the current cell coordinates in the only
place where this could happen before.

Doing this still preserves the correct behaviour of Shift-arrow
selection when entire rows/columns are selected and the current cell is
not the leftmost/topmost cell (due to scrolling), but the code is
simpler.

Remove the now always true condition check and assert that it's indeed
always true.

Note that the changes to gridsel.cpp in this commit are best viewed
ignoring whitespace changes.
2020-04-12 02:38:37 +02:00
Vadim Zeitlin
415bab551c Add wxGridSelection::SelectAll() and use it in wxGrid
The difference between calling SelectAll() and SelectBlock() with a
block covering the entire grid is that the former discards any
previously selected blocks, which become clearly redundant.

As a consequence, clicking on the grid corner 10 times in a row still
results in a selection with a single block, not 10 (identical) blocks.
2020-04-12 02:38:37 +02:00
Vadim Zeitlin
1cb2ec06ee Fix off-by-1 bugs in wxGrid::GetFirstFullyVisible{Row,Column}()
These functions always returned the first partially visible line, not
the first fully visible one as intended because IsXXXShown() always
returned true when it applied to that line and we need to increment the
index first, before calling it -- even if this requires writing the loop
in a slightly uglier way.

This fixes bugs in commits 0920a1646b (Make wxGrid row selecting more
user friendly, 2020-03-04) and 89dd47edee (Make wxGrid column selecting
more user friendly, 2020-03-04).
2020-04-12 02:38:37 +02:00
Vadim Zeitlin
69a05b0340 Use the same selection expansion logic for Shift-Ctrl-cursor
Expanding the selection from keyboard with Ctrl pressed should move in
the same way Ctrl-cursor does, but use the same selection anchor as
Shift-cursor does instead of always using the current cell.

This makes the expansion work much more intuitively in the grid, e.g.
pressing Shift-Ctrl-Down in

    1 2
    3 4

grid when 1 and 2 are selected now selects all the cells instead of
selecting 1 and 3 as it did before.
2020-04-06 02:39:21 +02:00
Vadim Zeitlin
1d43ae7dc6 Refactor selection expansion code to use actual wxKeyboardState
Switch from using just "bool expandSelection" in the grid functions
(possibly) extending the current selection to using the full
wxKeyboardState.

This allows to pass it to ExtendOrCreateCurrentBlock() and slightly
simplify the code by using DoMoveCursorFromKeyboard().
2020-04-05 15:56:45 +02:00
Vadim Zeitlin
791a9e68ae Rename and simplify wxGridBlockCoords::ContainsBlock()
Change the return type of this function to a simple and clear bool
instead of 3-valued int requiring a special explanation. This is simpler
and not any less efficient as checking for whether one block contains
another or the other one contains this one are separate operations
anyhow.

Rename the function to a more grammatically correct name.

Also move it inline as it's now trivial enough for this to be worth it.
2020-04-05 01:37:56 +02:00
Vadim Zeitlin
a5952ee087 Rename wxGridBlockCoords::ContainsCell() and move it inline
Make the function name more grammatically correct.

No real changes.
2020-04-04 19:45:19 +02:00
Vadim Zeitlin
7231a6a855 Make temporary variable in GetSelectionRange() const
We don't need to modify the selection blocks here.

No real changes.
2020-04-04 19:04:33 +02:00
Ilya Sinitsyn
bfca68c74a Move the wxGrid cursor to the corner of the last selection
Move the wxGrid cursor to the corner of the last selection when splitting
the selection block on click with Ctrl.
2020-04-04 18:50:37 +02:00
Ilya Sinitsyn
f8015b13b1 Implement wxGrid selection blocks iterating interface 2020-04-04 18:50:37 +02:00
Ilya Sinitsyn
8ebdf101b8 Make wxGrid cells selecting by mouse more user friendly 2020-04-04 18:50:37 +02:00
Ilya Sinitsyn
0920a1646b Make wxGrid row selecting more user friendly 2020-04-04 18:50:37 +02:00
Ilya Sinitsyn
89dd47edee Make wxGrid column selecting more user friendly 2020-04-04 18:50:37 +02:00
Ilya Sinitsyn
e1b9ece9a4 Edit the current wxGrid selection block
Really edit the current selection block instead of storing the temporary
information about the current selection and applying it on releasing Shift
key or LKM.
2020-04-04 18:50:37 +02:00
Ilya Sinitsyn
72e7bde306 Refactor wxGrid::MakeCellVisible() to scroll in only one direction
Allow -1 for a row or a column single parameter.
2020-04-04 18:50:37 +02:00
Ilya Sinitsyn
206bad9ba0 Remove wxEVT_GRID_RANGE_SELECT handling by wxGrid::SendEvent()
VZ: [...] this is not used by wxGrid itself and SendEvent() is not part
of the public API, so we never made any promises about being able to call
it with wxEVT_GRID_RANGE_SELECT.
2020-04-04 18:50:37 +02:00
Ilya Sinitsyn
779d3f7f17 Clear the selection in wxGrid::SetTable
The selection in m_selection was not considered at all so it was worked not
correctly any way.
2020-04-04 18:50:37 +02:00
Ilya Sinitsyn
d4919d3334 Remove wxGridSelection::ToggleCellSelection()
Remove the function because it's not usefull anymore and used only in one
place.
2020-04-04 18:50:36 +02:00
Ilya Sinitsyn
cdf3187fe5 Improve rows, columns and cells deselection in wxGrid
Use DeselectBlock() instead of ToggleCellSelection() to improve execution
speed and make the code more clean.
2020-04-04 18:50:36 +02:00
Ilya Sinitsyn
acd72efbf1 Implement wxGridBlockCoords class
wxGridBlockCoords represents a location of a block of cells in the grid.
2020-04-04 18:50:36 +02:00
Ilya Sinitsyn
673ed29d7b Make wxGridSelection to be non-friend to wxGrid
Improve integrity of the wxGridSelection internal data by removing `friend`
declaration.
2020-04-04 18:50:36 +02:00