New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
wxGrid: allow drag-resizing row and col labels #24362
base: master
Are you sure you want to change the base?
wxGrid: allow drag-resizing row and col labels #24362
Conversation
OK, dragging the edge towards the grid is now working as well. |
Dragging the label edges is now working also when inside the grid cell window. I have removed this line from This seems in line with the current implementation on relying that the cursor mode was set in To be done:
|
The documentation is now updated.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First of all, thanks for implementing this!
The documentation is now updated.
Thanks!
To be decided:
* leave drag-resizing on by default?
I'm not sure but AFAIK this is typically not something allowed by default. Personally, I think it's most useful for the row labels and not so much for the column ones, but it wouldn't make much sense to only allow one and not the other, which is another argument in favour of not allowing this by default and telling people to enable it in the directions they need it.
* leave minimum size at 0 by default?
If we enable it by default, it definitely shouldn't be 0 because this would result in complains from users hiding the labels entirely when this was never intended by the developer. If we don't, we could make it 0 by default but mention that you may want to change this when enabling it.
* where is `event.Skip()` required?
It should definitely be used in the leaving/entering events, there is no reason to stop handling them.
src/generic/grid.cpp
Outdated
bool atBottomEdge = false, atRightEdge = false, atLabelEdge = false; | ||
const wxPoint posEvent = event.GetPosition(); | ||
int edge = FromDIP(WXGRID_LABEL_EDGE_ZONE); | ||
const wxGridOperations* oper = nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a memory leak AFAICS because oper
is never deleted. Please use
const wxGridOperations* oper = nullptr; | |
std::unique_ptr<wxGridOperations> oper; |
instead.
src/generic/grid.cpp
Outdated
: static_cast<const wxGridOperations&>(wxGridColumnOperations()) | ||
).SetLineSize(this, m_dragRowOrCol, m_dragRowOrColOldSize); | ||
if ( m_dragRowOrCol == -2 ) | ||
{ if ( m_cursorMode == WXGRID_CURSOR_RESIZE_ROW ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some strange indentation here
{ if ( m_cursorMode == WXGRID_CURSOR_RESIZE_ROW ) | |
{ | |
if ( m_cursorMode == WXGRID_CURSOR_RESIZE_ROW ) |
src/generic/grid.cpp
Outdated
@@ -8726,6 +8885,19 @@ void wxGrid::SetColLabelSize( int height ) | |||
} | |||
} | |||
|
|||
void wxGrid::SetRowLabelMinimalSize(int width) | |||
{ | |||
if ( width >= 0 ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it really make sense to pass negative width here? If not, we should replace this with
if ( width >= 0 ) | |
wxCHECK_RET( width >= 0, "invalid min row label width" ); |
include/wx/generic/grid.h
Outdated
@@ -2659,6 +2680,7 @@ class WXDLLIMPEXP_CORE wxGrid : public wxScrolledCanvas | |||
const wxColour *m_dragLastColour; | |||
|
|||
// Row or column (depending on m_cursorMode value) currently being resized | |||
// or -2 if row or col label is being resized |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We really ought to have a symbolic constant for this instead of repeating this -2
many times.
But, to be honest, I rather dislike having such multiple-state variable. Having an int which can be invalid is not too bad, but having an int with 3 different kinds of values is not great. Could things become clearer if we introduced a separate bool m_dragLabel
?
Thanks for the review. I will apply the suggested modifications and also try the variant with a separate I hope this is correct - at least it compiles: std::unique_ptr<wxGridOperations> oper;
...
oper = (std::unique_ptr<wxGridOperations>) (new wxGridRowOperations()); |
This is actually correct but very strange. Please use either oper = std::unique_ptr<wxGridOperations>(new wxGridRowOperations()); which does exactly the same thing but looks better or, to avoid creation of another temporary pointer, oper.reset(new wxGridRowOperations()); TIA! |
Thanks. The |
The advantage of using |
With 324430b now
|
The last two commits do simplify grid again a bit, but complicate What do you think? Still open: for which events to call |
The last commits somewhat reduce complexity. At many points there is code like
I think a helper function |
OK, a helper like this could be used at four points: wxGridOperations* wxGrid::DoGetOperationsFromCursorMode()
{
if ( m_cursorMode == WXGRID_CURSOR_RESIZE_ROW )
return new wxGridRowOperations();
if ( m_cursorMode == WXGRID_CURSOR_RESIZE_COL )
return new wxGridColumnOperations();
return nullptr;
} The number of lines is not really reduced due to declaration and implementation of the helper, but still I prefer the simpler code. I don't like either of these usage options, though: {
const wxGridOperations* oper = DoGetOperationsFromCursorMode();
...
delete oper;
} {
std::unique_ptr<wxGridOperations> oper(DoGetOperationsFromCursorMode());
...
} Do you see a better option? The |
Sorry, didn't have time to look at the new code yet, but just 2 comments:
Sorry, which events are we speaking about here? I saw the question about the mouse ones and I answered it (you should call
Yes, I definitely do: const auto oper(DoGetOperationsFromCursorMode());
...
// no need for deleting anything and no danger of memory leaks |
Thanks. I think I have now all infos and will modify accordingly. |
About event handling and
The old implementation of if ( event.LeftDown() )
if ( SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK, -1, -1, event ) == Event_Unhandled )
SelectAll();
else if ( event.LeftDClick() )
SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK, -1, -1, event );
else if ( event.RightDown() )
if ( SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK, -1, -1, event ) == Event_Unhandled )
event.Skip(); // no default action at the moment
else if ( event.RightDClick() )
if ( SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK, -1, -1, event ) == Event_Unhandled )
event.Skip(); // no default action at the moment
else
event.Skip(); So, I have checked |
This is a first version to add a feature that has been on my wish list for years.
This first version only allows dragging the edges of the corner label.
I'm not sure whether this is good enough or it should also be possible to drag the edges of the whole label windows.
When you look at the modifications, you can see that the modifications in
ProcessRowColLabelMouseEvent
are rather simple compared toProcessCornerLabelMouseEvent
where both directions have to be handled.The new methods and events are not yet in the interface header files. I will add them as soon as the API modifications are agreed:
Internally, a
m_dragRowOrCol
value-2
is used:To be decided:
event.Skip()
calls. I have added it to the case ofevent.Moving()
insideProcessCornerLabelMouseEvent
.Inside
ProcessRowColLabelMouseEvent
this is not done now. I'm wondering what is the correct way and whetherevent.Skip()
should also be added to e.g.event.Leaving()
.