Add single-click editing to grid cells. (Experimental.)

This commit is contained in:
Jeff Young 2018-08-19 17:10:42 +01:00
parent b90a261d5c
commit 45bc1b1aff
4 changed files with 117 additions and 16 deletions

View File

@ -43,12 +43,16 @@ GRID_TRICKS::GRID_TRICKS( wxGrid* aGrid ):
m_sel_row_count = 0; m_sel_row_count = 0;
m_sel_col_count = 0; m_sel_col_count = 0;
m_showEditorOnMouseUp = false;
aGrid->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( GRID_TRICKS::onGridCellLeftClick ), NULL, this ); aGrid->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( GRID_TRICKS::onGridCellLeftClick ), NULL, this );
aGrid->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( GRID_TRICKS::onGridCellLeftDClick ), NULL, this ); aGrid->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( GRID_TRICKS::onGridCellLeftDClick ), NULL, this );
aGrid->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( GRID_TRICKS::onGridCellRightClick ), NULL, this ); aGrid->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( GRID_TRICKS::onGridCellRightClick ), NULL, this );
aGrid->Connect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( GRID_TRICKS::onGridLabelRightClick ), NULL, this ); aGrid->Connect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( GRID_TRICKS::onGridLabelRightClick ), NULL, this );
aGrid->Connect( GRIDTRICKS_FIRST_ID, GRIDTRICKS_LAST_ID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( GRID_TRICKS::onPopupSelection ), NULL, this ); aGrid->Connect( GRIDTRICKS_FIRST_ID, GRIDTRICKS_LAST_ID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( GRID_TRICKS::onPopupSelection ), NULL, this );
aGrid->Connect( wxEVT_KEY_DOWN, wxKeyEventHandler( GRID_TRICKS::onKeyDown ), NULL, this ); aGrid->Connect( wxEVT_KEY_DOWN, wxKeyEventHandler( GRID_TRICKS::onKeyDown ), NULL, this );
aGrid->GetGridWindow()->Connect( wxEVT_LEFT_UP, wxMouseEventHandler( GRID_TRICKS::onMouseUp ), NULL, this );
aGrid->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( GRID_TRICKS::onUpdateUI ), NULL, this );
} }
@ -90,16 +94,44 @@ bool GRID_TRICKS::toggleCell( int aRow, int aCol )
} }
bool GRID_TRICKS::showEditor( int aRow, int aCol )
{
if( m_grid->IsEditable() && !m_grid->IsReadOnly( aRow, aCol ) )
{
if( m_grid->GetSelectionMode() == wxGrid::wxGridSelectionModes::wxGridSelectRows )
m_grid->SelectRow( aRow );
m_grid->SetGridCursor( aRow, aCol );
// For several reasons we can't enable the control here. There's the whole
// SetInSetFocus() issue/hack in wxWidgets, and there's also wxGrid's MouseUp
// handler which doesn't notice it's processing a MouseUp until after it has
// disabled the editor yet again. So we wait for the MouseUp.
m_showEditorOnMouseUp = true;
return true;
}
return false;
}
void GRID_TRICKS::onGridCellLeftClick( wxGridEvent& aEvent ) void GRID_TRICKS::onGridCellLeftClick( wxGridEvent& aEvent )
{ {
int row = aEvent.GetRow(); int row = aEvent.GetRow();
int col = aEvent.GetCol(); int col = aEvent.GetCol();
// Don't make users click twice to toggle a checkbox // Don't make users click twice to toggle a checkbox or edit a text cell
if( !aEvent.GetModifiers() )
{
if( toggleCell( row, col ) )
return;
if( showEditor( row, col ) )
return;
}
if( !aEvent.GetModifiers() && toggleCell( row, col ) )
/* eat event */ ;
else
aEvent.Skip(); aEvent.Skip();
} }
@ -111,6 +143,24 @@ void GRID_TRICKS::onGridCellLeftDClick( wxGridEvent& aEvent )
} }
void GRID_TRICKS::onMouseUp( wxMouseEvent& aEvent )
{
if( m_showEditorOnMouseUp )
{
// Some wxGridCellEditors don't have the SetInSetFocus() hack. Even when they do,
// it sometimes fails. Activating the control here seems to avoid those issues.
if( m_grid->CanEnableCellControl() )
{
m_grid->EnableCellEditControl();
m_grid->ShowCellEditControl();
}
m_showEditorOnMouseUp = false;
}
else
aEvent.Skip();
}
bool GRID_TRICKS::handleDoubleClick( wxGridEvent& aEvent ) bool GRID_TRICKS::handleDoubleClick( wxGridEvent& aEvent )
{ {
// Double-click processing must be handled by specific sub-classes // Double-click processing must be handled by specific sub-classes
@ -387,3 +437,27 @@ void GRID_TRICKS::cutcopy( bool doCut )
m_grid->ForceRefresh(); m_grid->ForceRefresh();
} }
} }
void GRID_TRICKS::onUpdateUI( wxUpdateUIEvent& event )
{
// Respect ROW selectionMode when moving cursor
if( m_grid->GetSelectionMode() == wxGrid::wxGridSelectionModes::wxGridSelectRows )
{
int cursorRow = m_grid->GetCursorRow();
bool cursorInSelectedRow = false;
for( int row : m_grid->GetSelectedRows() )
{
if( row == cursorRow )
{
cursorInSelectedRow = true;
break;
}
}
if( !cursorInSelectedRow )
m_grid->SelectRow( cursorRow );
}
}

View File

@ -169,6 +169,9 @@ PANEL_SYM_LIB_TABLE::PANEL_SYM_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent,
m_global_grid->PushEventHandler( new SYMBOL_GRID_TRICKS( m_parent, m_global_grid ) ); m_global_grid->PushEventHandler( new SYMBOL_GRID_TRICKS( m_parent, m_global_grid ) );
m_project_grid->PushEventHandler( new SYMBOL_GRID_TRICKS( m_parent, m_project_grid ) ); m_project_grid->PushEventHandler( new SYMBOL_GRID_TRICKS( m_parent, m_project_grid ) );
m_global_grid->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
m_project_grid->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
m_global_grid->AutoSizeColumns( false ); m_global_grid->AutoSizeColumns( false );
m_project_grid->AutoSizeColumns( false ); m_project_grid->AutoSizeColumns( false );
@ -213,17 +216,20 @@ PANEL_SYM_LIB_TABLE::PANEL_SYM_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent,
// for ALT+A handling, we want the initial focus to be on the first selected grid. // for ALT+A handling, we want the initial focus to be on the first selected grid.
m_parent->SetInitialFocus( m_cur_grid ); m_parent->SetInitialFocus( m_cur_grid );
// Gives a selection for each grid, mainly for delete lib button.
// Without that, we do not see what lib will be deleted
m_global_grid->SelectRow( 0 );
m_project_grid->SelectRow( 0 );
// Configure button logos // Configure button logos
m_append_button->SetBitmap( KiBitmap( small_plus_xpm ) ); m_append_button->SetBitmap( KiBitmap( small_plus_xpm ) );
m_delete_button->SetBitmap( KiBitmap( trash_xpm ) ); m_delete_button->SetBitmap( KiBitmap( trash_xpm ) );
m_move_up_button->SetBitmap( KiBitmap( small_up_xpm ) ); m_move_up_button->SetBitmap( KiBitmap( small_up_xpm ) );
m_move_down_button->SetBitmap( KiBitmap( small_down_xpm ) ); m_move_down_button->SetBitmap( KiBitmap( small_down_xpm ) );
m_browse_button->SetBitmap( KiBitmap( folder_xpm ) ); m_browse_button->SetBitmap( KiBitmap( folder_xpm ) );
// Gives a selection to each grid, mainly for delete button. wxGrid's wake up with
// a currentCell which is sometimes not highlighted.
if( m_global_grid->GetNumberRows() > 0 )
m_global_grid->SelectRow( 0 );
if( m_project_grid->GetNumberRows() > 0 )
m_project_grid->SelectRow( 0 );
} }
@ -470,6 +476,12 @@ void PANEL_SYM_LIB_TABLE::deleteRowHandler( wxCommandEvent& event )
if( selectedRows.size() == 0 && m_cur_grid->GetGridCursorRow() >= 0 ) if( selectedRows.size() == 0 && m_cur_grid->GetGridCursorRow() >= 0 )
selectedRows.Add( m_cur_grid->GetGridCursorRow() ); selectedRows.Add( m_cur_grid->GetGridCursorRow() );
if( selectedRows.size() == 0 )
{
wxBell();
return;
}
std::sort( selectedRows.begin(), selectedRows.end() ); std::sort( selectedRows.begin(), selectedRows.end() );
// Remove selected rows (note: a row can be stored more than once in list) // Remove selected rows (note: a row can be stored more than once in list)

View File

@ -64,6 +64,8 @@ protected:
int m_sel_row_count; int m_sel_row_count;
int m_sel_col_count; int m_sel_col_count;
bool m_showEditorOnMouseUp;
/// Puts the selected area into a sensible rectangle of m_sel_{row,col}_{start,count} above. /// Puts the selected area into a sensible rectangle of m_sel_{row,col}_{start,count} above.
void getSelectedArea(); void getSelectedArea();
@ -78,12 +80,15 @@ protected:
void onGridLabelRightClick( wxGridEvent& event ); void onGridLabelRightClick( wxGridEvent& event );
void onPopupSelection( wxCommandEvent& event ); void onPopupSelection( wxCommandEvent& event );
void onKeyDown( wxKeyEvent& ev ); void onKeyDown( wxKeyEvent& ev );
void onMouseUp( wxMouseEvent& aEvent );
void onUpdateUI( wxUpdateUIEvent& event );
virtual bool handleDoubleClick( wxGridEvent& aEvent ); virtual bool handleDoubleClick( wxGridEvent& aEvent );
virtual void showPopupMenu( wxMenu& menu ); virtual void showPopupMenu( wxMenu& menu );
virtual void doPopupSelection( wxCommandEvent& event ); virtual void doPopupSelection( wxCommandEvent& event );
bool toggleCell( int aRow, int aCol ); bool toggleCell( int aRow, int aCol );
bool showEditor( int aRow, int aCol );
virtual void paste_clipboard(); virtual void paste_clipboard();
virtual void paste_text( const wxString& cb_text ); virtual void paste_text( const wxString& cb_text );

View File

@ -277,8 +277,6 @@ PANEL_FP_LIB_TABLE::PANEL_FP_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent,
m_GblTableFilename->SetLabel( aGlobalTblPath ); m_GblTableFilename->SetLabel( aGlobalTblPath );
m_PrjTableFilename->SetLabel( aProjectTblPath ); m_PrjTableFilename->SetLabel( aProjectTblPath );
// wxGrid only supports user owned tables if they exist past end of ~wxGrid(),
// so make it a grid owned table.
m_global_grid->SetTable( new FP_LIB_TABLE_GRID( *aGlobal ), true ); m_global_grid->SetTable( new FP_LIB_TABLE_GRID( *aGlobal ), true );
m_project_grid->SetTable( new FP_LIB_TABLE_GRID( *aProject ), true ); m_project_grid->SetTable( new FP_LIB_TABLE_GRID( *aProject ), true );
@ -290,6 +288,9 @@ PANEL_FP_LIB_TABLE::PANEL_FP_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent,
m_global_grid->PushEventHandler( new FP_GRID_TRICKS( m_parent, m_global_grid ) ); m_global_grid->PushEventHandler( new FP_GRID_TRICKS( m_parent, m_global_grid ) );
m_project_grid->PushEventHandler( new FP_GRID_TRICKS( m_parent, m_project_grid ) ); m_project_grid->PushEventHandler( new FP_GRID_TRICKS( m_parent, m_project_grid ) );
m_global_grid->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
m_project_grid->SetSelectionMode( wxGrid::wxGridSelectionModes::wxGridSelectRows );
m_global_grid->AutoSizeColumns( false ); m_global_grid->AutoSizeColumns( false );
m_project_grid->AutoSizeColumns( false ); m_project_grid->AutoSizeColumns( false );
@ -346,10 +347,13 @@ PANEL_FP_LIB_TABLE::PANEL_FP_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent,
m_move_up_button->SetBitmap( KiBitmap( small_up_xpm ) ); m_move_up_button->SetBitmap( KiBitmap( small_up_xpm ) );
m_move_down_button->SetBitmap( KiBitmap( small_down_xpm ) ); m_move_down_button->SetBitmap( KiBitmap( small_down_xpm ) );
// Gives a selection for each grid, mainly for delete lib button. // Gives a selection to each grid, mainly for delete button. wxGrid's wake up with
// Without that, we do not see what lib will be deleted // a currentCell which is sometimes not highlighted.
m_global_grid->SetGridCursor( 0, 1 ); if( m_global_grid->GetNumberRows() > 0 )
m_project_grid->SetGridCursor( 0, 1 ); m_global_grid->SelectRow( 0 );
if( m_project_grid->GetNumberRows() > 0 )
m_project_grid->SelectRow( 0 );
} }
@ -511,6 +515,12 @@ void PANEL_FP_LIB_TABLE::deleteRowHandler( wxCommandEvent& event )
if( selectedRows.size() == 0 && m_cur_grid->GetGridCursorRow() >= 0 ) if( selectedRows.size() == 0 && m_cur_grid->GetGridCursorRow() >= 0 )
selectedRows.Add( m_cur_grid->GetGridCursorRow() ); selectedRows.Add( m_cur_grid->GetGridCursorRow() );
if( selectedRows.size() == 0 )
{
wxBell();
return;
}
std::sort( selectedRows.begin(), selectedRows.end() ); std::sort( selectedRows.begin(), selectedRows.end() );
// Remove selected rows (note: a row can be stored more than once in list) // Remove selected rows (note: a row can be stored more than once in list)