diff --git a/common/grid_tricks.cpp b/common/grid_tricks.cpp index 37827863e1..a1c23bb4d1 100644 --- a/common/grid_tricks.cpp +++ b/common/grid_tricks.cpp @@ -57,6 +57,8 @@ GRID_TRICKS::GRID_TRICKS( wxGrid* aGrid ): m_sel_row_count = 0; m_sel_col_count = 0; + aGrid->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( GRID_TRICKS::onGridCellLeftClick ), NULL, this ); + aGrid->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( GRID_TRICKS::onGridCellLeftClick ), NULL, this ); aGrid->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( GRID_TRICKS::onGridCellRightClick ), NULL, this ); aGrid->Connect( MYID_FIRST, MYID_LAST, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( GRID_TRICKS::onPopupSelection ), NULL, this ); aGrid->Connect( wxEVT_KEY_DOWN, wxKeyEventHandler( GRID_TRICKS::onKeyDown ), NULL, this ); @@ -64,6 +66,57 @@ GRID_TRICKS::GRID_TRICKS( wxGrid* aGrid ): } +bool GRID_TRICKS::toggleCell( int aRow, int aCol ) +{ + auto renderer = m_grid->GetCellRenderer( aRow, aCol ); + bool isCheckbox = ( dynamic_cast( renderer ) != nullptr ); + renderer->DecRef(); + + if( isCheckbox ) + { + wxGridTableBase* model = m_grid->GetTable(); + + if( model->CanGetValueAs( aRow, aCol, wxGRID_VALUE_BOOL ) + && model->CanSetValueAs( aRow, aCol, wxGRID_VALUE_BOOL )) + { + model->SetValueAsBool( aRow, aCol, !model->GetValueAsBool( aRow, aCol )); + } + else // fall back to string processing + { + if( model->GetValue( aRow, aCol ) == wxT( "1" ) ) + model->SetValue( aRow, aCol, wxT( "0" ) ); + else + model->SetValue( aRow, aCol, wxT( "1" ) ); + } + + return true; + } + + return false; +} + + +void GRID_TRICKS::onGridCellLeftClick( wxGridEvent& aEvent ) +{ + int row = aEvent.GetRow(); + int col = aEvent.GetCol(); + + // Don't make users click twice to toggle a checkbox + + if( !aEvent.GetModifiers() && toggleCell( row, col ) ) + { + m_grid->ClearSelection(); + m_grid->SetGridCursor( row, col ); + + // eat event + } + else + { + aEvent.Skip(); + } +} + + void GRID_TRICKS::getSelectedArea() { wxGridCellCoordsArray topLeft = m_grid->GetSelectionBlockTopLeft(); @@ -178,26 +231,39 @@ void GRID_TRICKS::onKeyDown( wxKeyEvent& ev ) if( isCtl( 'A', ev ) ) { m_grid->SelectAll(); + return; } else if( isCtl( 'C', ev ) ) { getSelectedArea(); cutcopy( false ); + return; } else if( isCtl( 'V', ev ) ) { getSelectedArea(); paste_clipboard(); + return; } else if( isCtl( 'X', ev ) ) { getSelectedArea(); cutcopy( true ); + return; } - else + else if( ev.GetKeyCode() == ' ' ) { - ev.Skip( true ); + int row = m_grid->GetCursorRow(); + int col = m_grid->GetCursorColumn(); + + if( m_grid->IsVisible( row, col ) && toggleCell( row, col ) ) + { + m_grid->ForceRefresh(); + return; + } } + + ev.Skip( true ); } diff --git a/eeschema/dialogs/dialog_sym_lib_table.cpp b/eeschema/dialogs/dialog_sym_lib_table.cpp index 39303ec1e0..6e2b0509e4 100644 --- a/eeschema/dialogs/dialog_sym_lib_table.cpp +++ b/eeschema/dialogs/dialog_sym_lib_table.cpp @@ -182,8 +182,8 @@ DIALOG_SYMBOL_LIB_TABLE::DIALOG_SYMBOL_LIB_TABLE( wxTopLevelWindow* aParent, g->SetColAttr( COL_TYPE, attr ); attr = new wxGridCellAttr; - attr->SetEditor( new wxGridCellBoolEditor() ); attr->SetRenderer( new wxGridCellBoolRenderer() ); + attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS g->SetColAttr( COL_ENABLED, attr ); // all but COL_OPTIONS, which is edited with Option Editor anyways. diff --git a/include/grid_tricks.h b/include/grid_tricks.h index b4f1ae8d90..4a2b1855a1 100644 --- a/include/grid_tricks.h +++ b/include/grid_tricks.h @@ -70,6 +70,8 @@ protected: return e.GetKeyCode() == aChar && e.ControlDown() && !e.AltDown() && !e.ShiftDown() && !e.MetaDown(); } + void onGridCellLeftClick( wxGridEvent& event ); + void onGridCellRightClick( wxGridEvent& event ) { showPopupMenu(); @@ -87,6 +89,8 @@ protected: void onKeyDown( wxKeyEvent& ev ); + bool toggleCell( int aRow, int aCol ); + virtual void paste_clipboard(); virtual void paste_text( const wxString& cb_text ); diff --git a/include/lib_table_grid.h b/include/lib_table_grid.h index 3e5aded90e..8a98e526f4 100644 --- a/include/lib_table_grid.h +++ b/include/lib_table_grid.h @@ -24,19 +24,19 @@ #include -const wxColour COLOUR_ROW_ENABLED( 0, 0, 0 ); -const wxColour COLOUR_ROW_DISABLED( 100, 100, 100 ); - +const wxColour COLOUR_ROW_ENABLED( 0, 0, 0 ); +const wxColour COLOUR_ROW_DISABLED( 100, 100, 100 ); + /// The library table grid column order is established by this sequence. enum COL_ORDER { - COL_ENABLED, + COL_ENABLED, COL_NICKNAME, COL_URI, COL_TYPE, COL_OPTIONS, COL_DESCR, - + COL_COUNT // keep as last }; @@ -67,8 +67,8 @@ public: case COL_TYPE: return r->GetType(); case COL_OPTIONS: return r->GetOptions(); case COL_DESCR: return r->GetDescr(); - // Render a boolean value as its text equivalent - case COL_ENABLED: return r->GetIsEnabled() ? "1" : ""; + // Render a boolean value as its text equivalent + case COL_ENABLED: return r->GetIsEnabled() ? wxT( "1" ) : wxT( "0" ); default: ; // fall thru to wxEmptyString } @@ -77,6 +77,14 @@ public: return wxEmptyString; } + bool GetValueAsBool( int aRow, int aCol ) override + { + if( aRow < (int) size() && aCol == COL_ENABLED ) + return at( (size_t) aRow )->GetIsEnabled(); + else + return false; + } + void SetValue( int aRow, int aCol, const wxString &aValue ) override { if( aRow < (int) size() ) @@ -90,14 +98,19 @@ public: case COL_TYPE: r->SetType( aValue ); break; case COL_OPTIONS: r->SetOptions( aValue ); break; case COL_DESCR: r->SetDescr( aValue ); break; - case COL_ENABLED: - // Any non-empty string will set enabled to true - r->SetEnabled( !aValue.IsEmpty() ); - break; + case COL_ENABLED: + r->SetEnabled( aValue == wxT( "1" ) ); + break; } } } + void SetValueAsBool( int aRow, int aCol, bool aValue ) override + { + if( aRow < (int) size() && aCol == COL_ENABLED ) + at( (size_t) aRow )->SetEnabled( aValue ); + } + bool IsEmptyCell( int aRow, int aCol ) override { return !GetValue( aRow, aCol ); @@ -183,12 +196,12 @@ public: case COL_TYPE: return _( "Plugin Type" ); case COL_OPTIONS: return _( "Options" ); case COL_DESCR: return _( "Description" ); - case COL_ENABLED: return _( "Active" ); - + case COL_ENABLED: return _( "Active" ); + default: return wxEmptyString; } - } - + } + protected: virtual LIB_TABLE_ROW* at( size_t aIndex ) = 0; diff --git a/pcbnew/dialogs/dialog_footprint_wizard_list.cpp b/pcbnew/dialogs/dialog_footprint_wizard_list.cpp index a44690dee5..10bb84debc 100644 --- a/pcbnew/dialogs/dialog_footprint_wizard_list.cpp +++ b/pcbnew/dialogs/dialog_footprint_wizard_list.cpp @@ -66,7 +66,6 @@ DIALOG_FOOTPRINT_WIZARD_LIST::DIALOG_FOOTPRINT_WIZARD_LIST( wxWindow* aParent ) SetSize( size ); } - m_sdbSizerOK->SetDefault(); FinishDialogSettings(); diff --git a/pcbnew/dialogs/dialog_fp_lib_table.cpp b/pcbnew/dialogs/dialog_fp_lib_table.cpp index e0c5aaabad..7790b46df7 100644 --- a/pcbnew/dialogs/dialog_fp_lib_table.cpp +++ b/pcbnew/dialogs/dialog_fp_lib_table.cpp @@ -208,8 +208,8 @@ public: g->SetColAttr( COL_TYPE, attr ); attr = new wxGridCellAttr; - attr->SetEditor( new wxGridCellBoolEditor() ); attr->SetRenderer( new wxGridCellBoolRenderer() ); + attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS g->SetColAttr( COL_ENABLED, attr ); // all but COL_OPTIONS, which is edited with Option Editor anyways. diff --git a/pcbnew/footprint_wizard_frame.cpp b/pcbnew/footprint_wizard_frame.cpp index 8b8be2ad4c..e25d079d21 100644 --- a/pcbnew/footprint_wizard_frame.cpp +++ b/pcbnew/footprint_wizard_frame.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -85,8 +86,6 @@ BEGIN_EVENT_TABLE( FOOTPRINT_WIZARD_FRAME, EDA_DRAW_FRAME ) EVT_LISTBOX( ID_FOOTPRINT_WIZARD_PAGE_LIST, FOOTPRINT_WIZARD_FRAME::ClickOnPageList ) EVT_GRID_CMD_CELL_CHANGED( ID_FOOTPRINT_WIZARD_PARAMETER_LIST, FOOTPRINT_WIZARD_FRAME::ParametersUpdated ) - EVT_GRID_CMD_CELL_LEFT_CLICK( ID_FOOTPRINT_WIZARD_PARAMETER_LIST, - FOOTPRINT_WIZARD_FRAME::OnParameterCellClick ) EVT_MENU( ID_SET_RELATIVE_OFFSET, FOOTPRINT_WIZARD_FRAME::OnSetRelativeOffset ) END_EVENT_TABLE() @@ -164,6 +163,7 @@ FOOTPRINT_WIZARD_FRAME::FOOTPRINT_WIZARD_FRAME( KIWAY* aKiway, // Creates the list of parameters for the current parameter page m_parameterGridPage = -1; initParameterGrid(); + m_parameterGrid->PushEventHandler( new GRID_TRICKS( m_parameterGrid ) ); ReCreatePageList(); @@ -229,6 +229,9 @@ FOOTPRINT_WIZARD_FRAME::FOOTPRINT_WIZARD_FRAME( KIWAY* aKiway, FOOTPRINT_WIZARD_FRAME::~FOOTPRINT_WIZARD_FRAME() { + // Delete the GRID_TRICKS. + m_parameterGrid->PopEventHandler( true ); + EDA_3D_VIEWER* draw3DFrame = Get3DViewerFrame(); if( draw3DFrame ) @@ -311,9 +314,6 @@ void FOOTPRINT_WIZARD_FRAME::initParameterGrid() m_parameterGrid->Connect( wxEVT_SIZE, wxSizeEventHandler( FOOTPRINT_WIZARD_FRAME::OnGridSize ), NULL, this ); - m_parameterGrid->Connect( wxEVT_KEY_UP, - wxKeyEventHandler( FOOTPRINT_WIZARD_FRAME::OnParameterGridKeyPress ), - NULL, this ); } @@ -391,14 +391,10 @@ void FOOTPRINT_WIZARD_FRAME::ReCreateParameterList() m_parameterGrid->SetReadOnly( i, WIZ_COL_NAME ); m_parameterGrid->SetCellAlignment( i, WIZ_COL_NAME, wxALIGN_LEFT, wxALIGN_CENTRE ); - // Set the editor type of the - // Boolean parameters are displayed using a checkbox if( units == WIZARD_PARAM_UNITS_BOOL ) { - // NOTE: Not using wxGridCellBoolEditor because it doesn't work well - // Setting read-only to disable the grid editor; value will be - // updated by the OnParameterCellClick event handler. + // Set to ReadOnly as we delegate interactivity to GRID_TRICKS m_parameterGrid->SetReadOnly( i, WIZ_COL_VALUE ); m_parameterGrid->SetCellRenderer( i, WIZ_COL_VALUE, new wxGridCellBoolRenderer ); } diff --git a/pcbnew/footprint_wizard_frame.h b/pcbnew/footprint_wizard_frame.h index bef58de292..441344051d 100644 --- a/pcbnew/footprint_wizard_frame.h +++ b/pcbnew/footprint_wizard_frame.h @@ -195,10 +195,6 @@ private: */ void ParametersUpdated( wxGridEvent& event ); - void OnParameterCellClick( wxGridEvent& event ); - - void OnParameterGridKeyPress( wxKeyEvent& event ); - bool OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu ) override; /** diff --git a/pcbnew/footprint_wizard_frame_functions.cpp b/pcbnew/footprint_wizard_frame_functions.cpp index bfa1e357a1..4b4cae2eea 100644 --- a/pcbnew/footprint_wizard_frame_functions.cpp +++ b/pcbnew/footprint_wizard_frame_functions.cpp @@ -290,93 +290,6 @@ void FOOTPRINT_WIZARD_FRAME::ParametersUpdated( wxGridEvent& event ) } -void FOOTPRINT_WIZARD_FRAME::OnParameterCellClick( wxGridEvent& event ) -{ - auto footprintWizard = GetMyWizard(); - - if( !footprintWizard ) - return; - - if( m_parameterGridPage < 0 ) - return; - - if( event.GetCol() != WIZ_COL_VALUE ) - return; - - auto types = footprintWizard->GetParameterTypes( m_parameterGridPage ); - auto values = footprintWizard->GetParameterValues( m_parameterGridPage ); - - int row = event.GetRow(); - bool has_changed = false; - - // Handle toggling of boolean parameters - if( types[row] == WIZARD_PARAM_UNITS_BOOL ) - { - has_changed = true; - values[row] = ( values[row] == "1" ) ? "0" : "1"; - m_parameterGrid->SetCellValue( row, WIZ_COL_VALUE, values[row] ); - } - else - { - event.Skip(); - } - - if( has_changed ) - { - wxString res = footprintWizard->SetParameterValues( m_parameterGridPage, values ); - - if( !res.IsEmpty() ) - wxMessageBox( res ); - - ReloadFootprint(); - DisplayWizardInfos(); - } -} - - -void FOOTPRINT_WIZARD_FRAME::OnParameterGridKeyPress( wxKeyEvent& event ) -{ - auto footprintWizard = GetMyWizard(); - int row = m_parameterGrid->GetGridCursorRow(); - int col = m_parameterGrid->GetGridCursorCol(); - bool has_changed = false; - - - if( !footprintWizard || m_parameterGridPage < 0 || - col != WIZ_COL_VALUE || event.GetKeyCode() != ' ' ) - { - event.Skip(); - return; - } - - auto types = footprintWizard->GetParameterTypes( m_parameterGridPage ); - auto values = footprintWizard->GetParameterValues( m_parameterGridPage ); - - // Handle toggling of boolean parameters when user presses space - if( types[row] == WIZARD_PARAM_UNITS_BOOL ) - { - has_changed = true; - values[row] = ( values[row] == "1" ) ? "0" : "1"; - m_parameterGrid->SetCellValue( row, WIZ_COL_VALUE, values[row] ); - } - else - { - m_parameterGrid->EnableCellEditControl(); - } - - if( has_changed ) - { - wxString res = footprintWizard->SetParameterValues( m_parameterGridPage, values ); - - if( !res.IsEmpty() ) - wxMessageBox( res ); - - ReloadFootprint(); - DisplayWizardInfos(); - } -} - - /** * Function RedrawActiveWindow * Display the current selected component.