Commit Graph

808 Commits

Author SHA1 Message Date
Dimitri Schoolwerth
1f5b77bad3 Make use of grid helper function GetCellSpan()
Also gets rid of an additional attribute lookup that was recently
added in 00c497125e containing a minimal fix.
2021-01-19 22:30:33 +01:00
Dimitri Schoolwerth
860d9d09bc Refactor code deciding the kind of span of a grid cell
Move wxGrid's GetCellSize() cell span logic into GetCellSpan() for
future usage.
2021-01-19 22:26:03 +01:00
Dimitri Schoolwerth
00c497125e Fix drawing of grid cells appearing inside a multicell
Grid cells are considered for redrawing solely based on having
a (text) value. This can lead to infinite recursion with overflowing
inside cells if wxGridCellStringRenderer::Draw() wants to draw cells
appearing after this one but instead visits the same cell again (because
of a negative cell size as opposed to expected default cell size of 1x1
or a larger spanning size) and calls DrawCell() again for this cell
which will call the renderer's Draw() again etc...

Fix by not taking inside cells into consideration for redrawing. This
is the right thing to do as earlier on in the same function a cell is
not drawn for the same reason. Also the aforementioned Draw() mentions
it shouldn't be called for cell sizes <= 0.

Also fixes the crashing grid test just introduced in 6d3dbc3fe5.
2021-01-19 22:17:41 +01:00
Daniel Kulp
3c28244806 Improve wxGrid appearance in dark mode under macOS
Use more appropriate colours for the row/column cell headers and don't
hardcode black (i.e. at least use white instead in dark mode) for the
frozen border.

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

See #18941.
2021-01-18 00:03:10 +01:00
Paul Cornett
dd864cffe0 Fix border drawing glitch in wxGrid column header
See #18980
2020-11-20 21:46:09 -08:00
Vadim Zeitlin
bd8c74f368 Fix positioning of bottom-aligned checkboxes in wxGrid
This fixes a bug due to a typo in ab02d36e10 (Account for vertical
alignment in wxGetGridCheckBoxRect() too, 2019-11-22) which used the
vertical component of a wrong object and so didn't actually offset the
checkbox by its size from the bottom of the cell rectangle, as it should
have done.

Closes #18907.
2020-11-02 00:55:47 +01:00
Gary Allen
095d1e317c Add wxGridSelectNone selection mode
In this mode the user can't select any cells at all in wxGrid.
2020-10-31 17:01:36 +01:00
PB
f57f214122 Remove BCC-specific hdrstop pragma from everywhere 2020-10-12 21:58:37 +02:00
Vadim Zeitlin
be2a61519b Merge branch 'grid-selected'
Split the wxGrid RANGE_SELECT event into separate SELECTING and SELECTED
events.

See https://github.com/wxWidgets/wxWidgets/pull/2028
2020-08-31 14:55:56 +02:00
Vadim Zeitlin
d41539ef05 Merge branch 'fix-grid-resizing'
Fix bugs in wxGrid mouse handling and simplify the code.

See https://github.com/wxWidgets/wxWidgets/pull/2018
2020-08-31 14:53:37 +02:00
Ilya Sinitsyn
0e8ca0c8f9 Fix the cursor mode switching in wxGrid mouse move event handler
Allow switching between row and column resizing modes in mouse move event
handler.
2020-08-24 02:09:01 +02:00
Ilya Sinitsyn
d6aec06150 Process the wxGrid mouse click depending on the current mode
Simplify the code of wxGrid::DoGridCellLeftDown() and make it more
correct by using m_cursorMode instead of duplicating (not 100%
correctly) the logic used to set it in DoGridMouseMoveEvent().

If the assumption that m_cursorMode is already set by the time
DoGridCellLeftDown() is called turns out to be wrong, e.g. when wxGrid
is used on touch screens, we would need to refactor these functions to
extract the code determining m_cursorMode from the mouse location into a
separate function that would be called from both.

Note that this commit is best viewed with "git diff -w" to see how little
has really changed.
2020-08-24 02:08:54 +02:00
Vadim Zeitlin
9765b6d58e Send SELECTING events while selecting rows/columns too
Generalize the changes of 415f080c80 (Split wxGrid RANGE_SELECT event
into SELECTING and SELECTED, 2020-07-27) to the case when the mouse is
dragged over row or column headers: also send SELECTING events while
dragging and a SELECTED event at the end, whether it's due to releasing
the mouse button or losing mouse capture.
2020-08-21 16:10:40 +02:00
Vadim Zeitlin
408ebfd253 Capture mouse while selecting rows/columns too
Change the logic in ChangeCursorMode() to explicitly exclude the modes
for which the mouse should not be captured, as CaptureMouse() should be
called in most cases (and ideally for all of them in the future) and do
capture it for WXGRID_CURSOR_SELECT_{ROW,COL} too, if only to be
notified about mouse capture loss.
2020-08-21 15:54:47 +02:00
Ilya Sinitsyn
39725cabd4 Fix wxGrid selecting mode ending condition 2020-08-20 16:56:03 +02:00
Ilya Sinitsyn
0a2c62fc5c Remove the selecting mode flag from wxGridSelection
Remove m_isSelecting and StartSelecting() from wxGridSelection to avoid
inconsistency of wxGridSelection selecting mode state with wxGrid state,
as wxGrid already has m_isDragging field which tells it if the selection
state is final or not.

Instead, just allow wxGrid to specify the event to send from
ExtendCurrentBlock().

We still need a separate EndSelecting() for sending the final
wxEVT_GRID_RANGE_SELECTED event, but send it only for the last selection
block, and not all the selected blocks, as this makes more sense (there
should be one SELECTED event for each block and it was already sent for
the other blocks before) and is consistent with the events generated
when performing the same actions from keyboard.
2020-08-20 16:56:03 +02:00
Daniel Kulp
415f080c80 Split wxGrid RANGE_SELECT event into SELECTING and SELECTED
This will allow the applications that are only interested in the final
selection to ignore the intermediate SELECTING events, which are now
sent as soon as the selection changes while dragging the mouse, and only
handle the final SELECTED ones, when the drag is over.
2020-08-20 16:56:03 +02:00
Scott Talbert
9be1f86ca0 Fix regression in wxGrid::DeselectRow() and wxGrid::DeselectCol() 2020-08-13 20:01:45 -04:00
Vadim Zeitlin
8e126d2cd6 Don't call RefreshRect() with negative size in wxGrid code
Don't bother trying to refresh areas beyond the visible part of the
window: not only it's useless, but it also results in debug warnings
from Cairo/pixman due to the use of negative rectangle width/height.

Closes #18848.
2020-07-23 16:21:42 +02:00
Ian McInerney
b256aa6956 Replace wxEVT_GRID_HIDE_EDITOR usage with CallAfter
This simplifies the code by removing the need for a special event,
and also means the combox popup handler is no longer needed to reset
the inSetFocus flag for the closing handler.
2020-07-14 12:28:13 +01:00
Vadim Zeitlin
a9b419af51 Fix code determining the rows to refresh in wxGrid::SetColSize()
The changes in 15de1a4cf4 (Optimize refresh when resizing grid rows or
columns, 2020-02-18) incorrectly translated XToPos() used in
SetRowSize() to YToRow(), which compiled due to an implicit conversion
of m_gridWin pointer to bool, but did the wrong thing, as the wrong grid
window could be used for a frozen grid.

Fix this by switching to internalYToRow() which actually does what the
original code tried to do.

Co-authored-by: Artur Wieczorek <artwik@wp.pl>
2020-07-05 15:04:00 +02:00
Vadim Zeitlin
97924a3b81 Use internalYToRow() instead of YToRow(true)
No real changes, just be consistent: as we have internalYToRow() macro
which passes true as "clipToMinMax" YToRow() parameter instead of the
default false, use it everywhere instead of using it almost everywhere
and still using YToRow(true) and XToCol(true) explicitly just once each.

Also add a comment explaining the difference between internalAToB() and
public AToB() functions.
2020-07-05 14:58:02 +02:00
Vadim Zeitlin
13e1b384e7 Fix another possible bug in wxEVT_GRID_CELL_CHANGED handling
Even when wxEVT_GRID_CELL_CHANGED is really vetoed, it's still possible
that m_currentCellCoords was changed by the handler, so use the row/col
coordinates of the cell that was really changed instead of the possibly
different m_currentCellCoords value to avoid a bug similar to the one
fixed by the previous commit.
2020-06-30 19:15:15 +02:00
Vadim Zeitlin
8445d1993e Fix bug in workaround for event handlers deleting wxGrid cells
The changes of e6e6dbe077 (Fix problems due to deleting grid cells in
the event handlers, 2020-05-02) fixed the bug (see #18731), but
introduced another one in place: if wxEVT_GRID_CELL_CHANGED handler
deleted any cells, wxGrid code could mistakenly restore the "old" cell
value (actually it restored the value for a different cell, as the
current cell coordinates necessarily changed too in this case).

This bug became more visible after the addition of activatable editors
as the new code asserts, instead of trying to restore the old value, if
wxEVT_GRID_CELL_CHANGED is vetoed, which also resulted in asserts if the
handler deleted the current cell instead.

Fix this by separating the cases of event being really vetoed and of the
event handler deleting the cell for which the event was generated and
handle the latter separately from the former where it matters.

This commit is best viewed ignoring whitespace changes.
2020-06-30 19:04:52 +02:00
Vadim Zeitlin
f877106663 Use EventResult enum instead of magic numbers in wxGrid code
This is more verbose, but also much more clear (and so allows to remove
some previously necessary comments).

No real changes, even keep the same values for the enum elements as were
previously used: this is probably unnecessary but do it just to minimize
changes.
2020-06-30 18:51:13 +02:00
Vadim Zeitlin
3cc3236f10 Add support for "activatable" editors to wxGrid
This is useful for editors which don't really need to show any control
as they can change their value directly and will be used to reimplement
wxGridCellBoolEditor in the upcoming commits.
2020-06-30 02:25:14 +02:00
Vadim Zeitlin
4e62b24042 Fix bug with Shift-Enter selecting cells while editing
It was unexpected that pressing Shift-Enter while an editor was active
didn't close it, but just selected the cell below (and then the one
below it if pressed again and so on), so now always finish editing when
it's pressed.

It could be argued that it's still unexpected for Shift-Enter to select
the cell below after closing the editor, but this is consistent with how
Tab works, and so shouldn't be as confusing as the old behaviour.
2020-06-28 23:14:32 +02:00
Vadim Zeitlin
3747169660 Remove apparently unnecessary wxGrid::m_inOnKeyDown
Although this variable, and a check for it in OnKeyDown(), was present
since the first version of this code added back in f85afd4e46 (Added new
wxGrid classes[...], 1999-10-06), there doesn't seem to be any
indication that it has ever been needed, so remove it to simplify the
code and make it possible to add early returns to this function easily.

No real changes yet.
2020-06-28 22:53:10 +02:00
Vadim Zeitlin
a5f172bacb Fix hiding the editor when the mouse simply moved around
Since the changes done in 8b2237cd2d (Make row/column drag-resizing in
wxGrid "live", 2020-03-01) the grid editor was dismissed whenever the
mouse crossed any row/column separator, which was, of course, wrong, as
it was only supposed to be hidden when row/column was actually resized,
i.e. when the separator was dragged by the mouse.

Fix this by moving calls to DoStartResizeRowOrCol() to more appropriate
places and do it only when the button is pressed now.

Note that it might actually be better to just disable column/row
resizing while a cell is being edited, but for now keep things working
as they did before and at least fix the latest regression which is
definitely unwanted.
2020-06-28 18:54:45 +02:00
Vadim Zeitlin
7235c77f81 Use GetCellSize() return value instead of checking rows/columns
No real changes, just use the value returned by the function to
determine if the cell is inside a multi-cell, instead of comparing
rows/columns with 0 to make code slightly more readable and self
explanatory.
2020-06-28 01:55:17 +02:00
Vadim Zeitlin
a400a380f2 Add wxGrid::DoEnableCellEditControl() with bool return value
Checking the new function return value is simpler than checking the
value of m_cellEditCtrlEnabled after calling EnableCellEditControl().

Do this now also when starting editing using the mouse, as it was simply
forgotten before and so StartingClick() was still called even if editing
was vetoed.

Also add DoDisableCellEditControl(), but this one exists purely for the
symmetry.
2020-06-28 01:47:06 +02:00
Vadim Zeitlin
2d9112bd9b Add DoHideCellEditControl() for symmetry
This also allows to reset m_cellEditCtrlEnabled earlier, as we don't
have to keep it true for the duration of HideCellEditControl()
execution.

No real changes, as with the previous commit, this one is best viewed
ignoring whitespace changes.
2020-06-28 00:40:09 +02:00
Vadim Zeitlin
c73634c520 Add DoShowCellEditControl() showing the editor unconditionally
It doesn't make sense to perform the checks in ShowCellEditControl()
when it's called from EnableCellEditControl() and this makes the code
unnecessarily fragile as m_cellEditCtrlEnabled needs to be set at just
the right moment for it to work correctly.

Call the new DoShowCellEditControl() instead and perform the checks only
in the public function, for compatibility.

Also note in a comment and the documentation that ShowCellEditControl()
is not very useful anyhow and that EnableCellEditControl() should most
often be used instead.

No real changes (the commit is best viewed ignoring whitespace changes).
2020-06-28 00:30:57 +02:00
Vadim Zeitlin
181747f462 Remove useless IsCellEditControlEnabled() checks
There is no need to do this before calling DisableCellEditControl() as
it won't do anything if the cell edit control is already disabled.
2020-06-28 00:21:23 +02:00
Vadim Zeitlin
45bc2e648b Remove check for read only cells from IsCellEditControlEnabled()
This check was introduced back in 283b7808d8 (added support for readonly
cells and 3d border drawing, 2000-02-16), but was wrong even then and
remained wrong ever since: we must not set m_cellEditCtrlEnabled to true
when the current cell is read-only, so there is no need to check for the
latter condition if m_cellEditCtrlEnabled is indeed true.

Ensure that we really never erroneously set m_cellEditCtrlEnabled for
the read-only cells by replacing an wxASSERT_MSG checking for this in
EnableCellEditControl() with wxCHECK_RET().

Also explicitly document this function precondition, also added back in
b54ba67107 ([...] added CanEnableCellControl() and use it before calling
EnableEC, 2000-02-17) but never documented so far.
2020-06-28 00:02:29 +02:00
Vadim Zeitlin
1a330bb43e Remove apparently useless call to ShowCellEditControl()
This code seems to have been there ever since da6af900f1 (Added
drag-shrinking, 2000-02-04), but while it probably made sense back then,
it lost its purpose a long time ago as the cell editor is now not only
hidden, but also disabled when drag-resizing starts, so it doesn't make
sense to attempt showing it back when the mouse button is released: it's
never going to do anything (and didn't).

Just remove this code, as hiding the editor while drag-resizing is not
the behaviour we want from the UI point of view anyhow. And, again,
removing it doesn't actually change anything in the current version of
the code.
2020-06-27 23:34:11 +02:00
Vadim Zeitlin
4b1f057d74 Factor out DoAcceptCellEditControl() into a separate function
This allows to fold the last DoSaveEditControlValue() call into this
function, so that it's only called from DoAcceptCellEditControl() or
from SaveEditControlValue() (which is public, and hence can't be
changed, even if its behaviour doesn't make much sense).

This commit means that m_cellEditCtrlEnabled is now reset to false when
AcceptCellEditControlIfShown() is called, which was not the case before,
but this seems to make sense, as we shouldn't be just hiding the editor
while leaving it enabled, and, also, doesn't really seem to change
anything as hiding the editor indirectly results in a call to
DisableCellEditControl(), via wxGrid::OnHideEditor(), and so it was
actually already reset before -- but now this happens slightly earlier
and more explicitly.
2020-06-27 17:13:04 +02:00
Vadim Zeitlin
3a874471c3 Add helper AcceptCellEditControlIfShown() function
This is just another refactoring in order to avoid duplicating calls to
HideCellEditControl() and SaveEditControlValue() in several different
places.

Also call DoSaveEditControlValue() because if the editor is shown, it is
also necessarily enabled and there is no need to check for this.
2020-06-27 16:57:40 +02:00
Vadim Zeitlin
0fb153a2bd Use ProcessWindowEvent() in wxGrid code
No real changes, just replace multiple calls to ProcessEvent() on
GetEventHandler() with a simpler call to ProcessWindowEvent().
2020-06-27 16:46:52 +02:00
Vadim Zeitlin
ed0f58c2dd Add helper wxGrid::GetCurrentCellEditorPtr() and use it
No real changes, just simplify the code by using a single function to
retrieve the editor to use for the current cell.

This also allows to get rid of a few temporary variables, further
amplifying the simplification.
2020-06-27 16:00:02 +02:00
Vadim Zeitlin
b7e7bb763a Fix rare crash when using native header in wxGrid under MSW
Pressing Esc while double clicking on the column separator in the native
header in wxGrid could result in a crash due to using invalid index when
calling GetColLeft(m_dragRowOrCol) in GetPositionForResizeEvent() called
from DoHeaderEndDragResizeCol() because m_dragRowOrCol had been already
reset to -1.

Guard against the crash with a check in GetPositionForResizeEvent()
itself and also add a check to DoHeaderDragResizeCol() to avoid calling
the former function in this case.

Reproducing the original problem is relatively simple as it's enough to
just keep double clicking a column separator while also pressing Esc,
but catching it under debugger is much more complicated and so it's not
really clear how exactly does this happen, but tracing shows that the
native control just decides to generate two HDN_ENDTRACK messages
without any intervening HDN_BEGINTRACK, so it doesn't seem like we can
do anything else than just silently ignore the unwanted HDN_ENDTRACK, as
it's done in this commit.
2020-06-27 01:42:57 +02:00
Vadim Zeitlin
c4fef08d39 Disallow resizing rows by dragging cell corners if disabled
Even when resizing rows by dragging their edges was disabled via
DisableDragRowSize(), it was still possible to try to resize them when
the mouse was over the cell corner.

Fix this and remove the special case for the corners entirely, it's not
necessary as the existing cases cover this one already.

Just rearrange them in the right order to prefer column resizing, as
this seems to be a much more commonly used operation than row resizing.
2020-06-26 22:19:49 +02:00
Vadim Zeitlin
7e79925fb7 Do erase background even in wxGridCellTextEditor
It is necessary to do it since the switch to double buffering wxGrid
painting in ebbadae09a (Double buffer wxGridWindow drawing, 2020-01-28)
as even a "full cell" editor such as wxGridCellTextEditor still doesn't
fill the entire cell, as there are margins around it, and the backing
bitmap could keep whatever junk happened to be there if we didn't erase
it, so do erase it now.

Remove the code doing the same thing from ShowCellEditControl(),
however, as it's redundant and doesn't do anything except creating some
flicker, and also doesn't work on the platforms not supporting the use
of wxClientDC anyhow.
2020-06-26 22:19:49 +02:00
Vadim Zeitlin
097f1a17cb Fix positioning of grid editor inside the grid client area
The existing logic for adjusting the editor window position by moving it
was flawed as it didn't take into account the fact that the editor could
decide to use a different (and usually bigger) rectangle than the one we
provided it with, if it doesn't fit into the given one. Fix it to ensure
that the editor window is fully inside the grid client area by moving it
only after letting it choose its own size.

The existing code was also inconsistent as CalcDimensions() didn't take
any adjustment to the cell rectangle done in ShowCellEditControl() into
account at all and always just blithely assumed it was positioned at the
cell top left corner, which resulted in wrong virtual size calculation
and could make scrollbars appear when starting editing, as happened in
the "Bugs table" example of the grid sample when showing any comboboxes
in the last grid row. Fix this code to use the actual editor rectangle
instead.
2020-06-22 01:53:59 +02:00
Vadim Zeitlin
f8a0438385 Also avoid updating wxHeaderCtrl column when resizing in wxGrid
This is another attempt to get rid of the flicker when using the native
header control with wxGrid under MSW and avoid calling UpdateColumn(),
which is currently implemented in a very inefficient way in wxHeaderCtrl
under MSW, during interactive resizing.

See #18794.
2020-06-21 23:46:59 +02:00
Vadim Zeitlin
bf266ca348 Avoid unnecessarily refreshing native header in wxGrid
We don't need to refresh it after resizing, it takes care of itself and
calling Refresh() just results in extra flicker.

See #18794.
2020-06-21 19:29:37 +02:00
Vadim Zeitlin
867cc2a3eb Handle clicks on grid edges normally when not using drag-resizing
Clicking on (or near) the grid column or row edges was handled specially
to allow dragging them in order to resize the column or row, but this
doesn't need to be done if drag-resizing the columns or rows is not
allowed in the first place and resulted in surprising user-visible
behaviour: e.g. when using row selection, clicking mostly anywhere in
the row selected it, except if the click happened to be between the two
columns, in which case it didn't.

Fix this and always select the row in such scenario now.

Unfortunately, doing this required adding yet more CanDragXXX()
functions in addition to the already impressive panoply of them in
wxGrid, but we need CanDragGridColEdges() as none of the existing
functions checked for m_useNativeHeader (there was instead an ad hoc
check for it directly in the mouse handling code) and the row version
had to be added for symmetry.
2020-06-21 19:29:37 +02:00
Vadim Zeitlin
96de24d1bb Add wxGridCellChoiceRenderer to optimize column size calculation
Previously columns using a set of predetermined values used plain
wxGridCellStringRenderer, which didn't allow to determine their best
size efficiently, as wxGrid had to iterate over all the rows of the
table, even if they only took a couple of possible values.

Add wxGridCellChoiceRenderer (refactoring wxGridCellEnumRenderer to
extract the common code from it in the process) which implements
GetMaxBestSize() by just finding the best size of all of these values,
which is much faster for large grids.

This does result in a change in behaviour, as the column now adapts to
its "theoretical" best size and not just the size of the values actually
shown in it, but this seems to be a worthwhile trade-off and could even
be seen as an advantage, as editing a cell won't make its value overflow
the auto-sized column width any more, as it is wide enough to show any
of the column values.
2020-06-13 16:10:14 +02:00
Vadim Zeitlin
71d42a8290 Add wxGridCellRenderer::GetMaxBestSize()
This is another optimization, useful for the renderers that are used
with the values of a fixed form or part of a limited set, as it is much
faster to compute the best size for all values of the set rather than
computing them for all the cells in the column.
2020-06-13 15:51:20 +02:00
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