25#include <wx/tokenzr.h>
27#include <wx/settings.h>
29#include <wx/textentry.h>
46 wxGridCellAttr::wxAttrKind aKind )
48 wxGridCellAttr* attr = aInputAttr;
50 if( wxGridCellAttrProvider* provider = GetAttrProvider() )
52 wxGridCellAttr* providerAttr = provider->GetAttr( aRow, aCol, aKind );
56 attr =
new wxGridCellAttr;
57 attr->SetKind( wxGridCellAttr::Merged );
61 attr->MergeWith( aInputAttr );
65 attr->MergeWith( providerAttr );
66 providerAttr->DecRef();
74#define MIN_GRIDCELL_MARGIN FromDIP( 2 )
81 aEntry->SetMargins( 0, 0 );
87#if defined( __WXMSW__ ) || defined( __WXGTK__ )
95 KIGFX::COLOR4D bg = wxSystemSettings::GetColour( wxSYS_COLOUR_FRAMEBK );
96 KIGFX::COLOR4D fg = wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER );
107 wxDCBrushChanger SetBrush( dc, *wxTRANSPARENT_BRUSH );
110 rect.SetTop( rect.GetTop() + 1 );
111 rect.SetLeft( rect.GetLeft() + 1 );
112 rect.SetBottom( rect.GetBottom() - 1 );
113 rect.SetRight( rect.GetRight() - 1 );
114 dc.DrawRectangle( rect );
124 wxDCBrushChanger SetBrush( dc, *wxTRANSPARENT_BRUSH );
127 rect.SetTop( rect.GetTop() + 1 );
128 rect.SetLeft( rect.GetLeft() );
129 rect.SetBottom( rect.GetBottom() - 1 );
130 rect.SetRight( rect.GetRight() - 1 );
131 dc.DrawRectangle( rect );
141 wxDCBrushChanger SetBrush( dc, *wxTRANSPARENT_BRUSH );
144 rect.SetTop( rect.GetTop() + 1 );
145 rect.SetLeft( rect.GetLeft() + 1 );
146 rect.SetBottom( rect.GetBottom() - 1 );
147 rect.SetRight( rect.GetRight() );
148 dc.DrawRectangle( rect );
161 wxGridCellAttrProvider(),
175 wxGridCellAttr*
GetAttr(
int row,
int col, wxGridCellAttr::wxAttrKind kind )
const override
177 wxGridCellAttrPtr cellAttr( wxGridCellAttrProvider::GetAttr( row, col, kind ) );
182 return cellAttr.release();
190 if( !cellAttr->HasBackgroundColour() )
192 cellAttr = cellAttr->Clone();
193 cellAttr->SetBackgroundColour(
m_attrEven->GetBackgroundColour() );
197 return cellAttr.release();
206 long style,
const wxString&
name ) :
207 wxGrid( parent, id, pos, size, style,
name ),
208 m_weOwnTable( false )
212 SetDefaultRowSize( GetDefaultRowSize() + FromDIP( 4 ) );
214 SetDefaultCellOverflow(
false );
241 wxGrid::SetColLabelSize( wxGRID_AUTOSIZE );
254 if( aHeight == 0 || aHeight == wxGRID_AUTOSIZE )
256 wxGrid::SetColLabelSize( aHeight );
263 wxGrid::SetColLabelSize( std::max( aHeight, minHeight ) );
277 int numberCols = GetNumberCols();
278 int* formBuilderColWidths =
new int[numberCols];
280 for(
int i = 0; i < numberCols; ++i )
281 formBuilderColWidths[ i ] = GetColSize( i );
283 wxGrid::SetTable( aTable );
287 numberCols = std::min( numberCols, GetNumberCols() );
289 for(
int i = 0; i < numberCols; ++i )
294 SetColSize( i, std::max( formBuilderColWidths[ i ], headingWidth ) );
297 delete[] formBuilderColWidths;
310 wxGridTableBase*
table = wxGrid::GetTable();
312 wxCHECK_MSG(
table, ,
"Tried to enable alternate row colors without a table assigned to the grid" );
316 wxColor
color = wxGrid::GetDefaultCellBackgroundColour();
321 table->SetAttrProvider(
nullptr );
331 int row = aEvent.GetRow();
332 int col = aEvent.GetCol();
334 if( row >= 0 && row < GetNumberRows() && col >= 0 && col < GetNumberCols() )
336 if( GetSelectionMode() == wxGrid::wxGridSelectCells )
338 SelectBlock( row, col, row, col,
false );
340 else if( GetSelectionMode() == wxGrid::wxGridSelectRows
341 || GetSelectionMode() == wxGrid::wxGridSelectRowsOrColumns )
343 SelectBlock( row, 0, row, GetNumberCols() - 1,
false );
345 else if( GetSelectionMode() == wxGrid::wxGridSelectColumns )
347 SelectBlock( 0, col, GetNumberRows() - 1, col,
false );
357 int row = aEvent.GetRow();
358 int col = aEvent.GetCol();
360 const std::pair<wxString, wxString>& beforeAfter =
m_evalBeforeAfter[ { row, col } ];
362 if( GetCellValue( row, col ) == beforeAfter.second )
363 SetCellValue( row, col, beforeAfter.first );
370 const int col = aEvent.GetCol();
377 EDA_UNITS cellUnits = cellUnitsData.first;
380 m_eval->SetDefaultUnits( cellUnits );
382 const int row = aEvent.GetRow();
385 bool isNullable =
false;
386 wxGridCellEditor* cellEditor = GetCellEditor( row, col );
391 isNullable = nullable->IsNullable();
393 cellEditor->DecRef();
397 [
this, row, col, isNullable, unitsProvider, cellDataType]()
401 if( row >= GetNumberRows() || col >= GetNumberCols() )
404 wxString stringValue = GetCellValue( row, col );
405 bool processedOk =
true;
408 processedOk =
m_eval->Process( stringValue );
416 std::optional<int> val;
437 if( stringValue != evalValue )
439 SetCellValue( row, col, evalValue );
459 wxGrid::SetTable(
nullptr );
466 wxString shownColumns;
468 for(
int i = 0; i < GetNumberCols(); ++i )
470 if( IsColShown( i ) )
472 if( shownColumns.Length() )
473 shownColumns << wxT(
" " );
485 std::bitset<64> shownColumns;
487 for(
int ii = 0; ii < GetNumberCols(); ++ii )
488 shownColumns[ii] = IsColShown( ii );
496 for(
int i = 0; i < GetNumberCols(); ++i )
499 wxStringTokenizer shownTokens( shownColumns );
501 while( shownTokens.HasMoreTokens() )
504 shownTokens.GetNextToken().ToLong( &colNumber );
506 if( colNumber >= 0 && colNumber < GetNumberCols() )
507 ShowCol( (
int) colNumber );
514 if( m_nativeColumnLabels )
515 wxGrid::DrawCornerLabel( dc );
517 wxRect rect( wxSize( m_rowLabelWidth, m_colLabelHeight ) );
524 wxDCBrushChanger setBrush( dc, m_colLabelWin->GetBackgroundColour() );
525 wxDCPenChanger setPen( dc, m_colLabelWin->GetBackgroundColour() );
526 dc.DrawRectangle( rect.Inflate( 1 ) );
535 if( m_nativeColumnLabels )
536 wxGrid::DrawColLabel( dc, col );
538 if( GetColWidth( col ) <= 0 || m_colLabelHeight <= 0 )
541 wxRect rect( GetColLeft( col ), 0, GetColWidth( col ), m_colLabelHeight );
548 wxDCBrushChanger setBrush( dc, m_colLabelWin->GetBackgroundColour() );
549 wxDCPenChanger setPen( dc, m_colLabelWin->GetBackgroundColour() );
550 dc.DrawRectangle( rect.Inflate( 1 ) );
556 dc.SetFont( GetLabelFont() );
559 GetColLabelAlignment( &hAlign, &vAlign );
560 const int orient = GetColLabelTextOrientation();
563 hAlign = wxALIGN_LEFT;
565 if( hAlign == wxALIGN_LEFT )
568 rend.DrawLabel( *
this, dc, GetColLabelValue( col ), rect, hAlign, vAlign, orient );
574 if( GetRowHeight( row ) <= 0 || m_rowLabelWidth <= 0 )
577 wxRect rect( 0, GetRowTop( row ), m_rowLabelWidth, GetRowHeight( row ) );
584 wxDCBrushChanger setBrush( dc, m_colLabelWin->GetBackgroundColour() );
585 wxDCPenChanger setPen( dc, m_colLabelWin->GetBackgroundColour() );
586 dc.DrawRectangle( rect.Inflate( 1 ) );
592 dc.SetFont( GetLabelFont() );
595 GetRowLabelAlignment(&hAlign, &vAlign);
597 if( hAlign == wxALIGN_LEFT )
600 rend.DrawLabel( *
this, dc, GetRowLabelValue( row ), rect, hAlign, vAlign, wxHORIZONTAL );
606 if( !IsCellEditControlEnabled() )
609 HideCellEditControl();
612 m_cellEditCtrlEnabled =
false;
614 int row = m_currentCellCoords.GetRow();
615 int col = m_currentCellCoords.GetCol();
617 wxString oldval = GetCellValue( row, col );
620 wxGridCellAttr* attr = GetCellAttr( row, col );
621 wxGridCellEditor*
editor = attr->GetEditor(
this, row, col );
623 editor->EndEdit( row, col,
this, oldval, &newval );
634 if( !IsCellEditControlEnabled() )
637 if( !aQuietMode && SendEvent( wxEVT_GRID_EDITOR_HIDDEN ) == -1 )
640 HideCellEditControl();
643 m_cellEditCtrlEnabled =
false;
645 int row = m_currentCellCoords.GetRow();
646 int col = m_currentCellCoords.GetCol();
648 wxString oldval = GetCellValue( row, col );
651 wxGridCellAttr* attr = GetCellAttr( row, col );
652 wxGridCellEditor*
editor = attr->GetEditor(
this, row, col );
654 bool changed =
editor->EndEdit( row, col,
this, oldval, &newval );
661 if( !aQuietMode && SendEvent( wxEVT_GRID_CELL_CHANGING, newval ) == -1 )
664 editor->ApplyEdit( row, col,
this );
669 if( !aQuietMode && SendEvent( wxEVT_GRID_CELL_CHANGED, oldval ) == -1 )
672 SetCellValue( row, col, oldval );
689 auto [row, editCol] = aAdder();
693 MakeCellVisible( row, std::max( editCol, 0 ) );
694 SetGridCursor( row, std::max( editCol, 0 ) );
698 EnableCellEditControl(
true );
699 ShowCellEditControl();
716 const std::function<
void(
int row )>& aDeleter )
718 wxArrayInt selectedRows = GetSelectedRows();
720 if( selectedRows.empty() && GetGridCursorRow() >= 0 )
721 selectedRows.push_back( GetGridCursorRow() );
723 if( selectedRows.empty() )
726 for(
int row : selectedRows )
728 if( !aFilter( row ) )
737 [](
int* first,
int* second )
739 return *second - *first;
742 int nextSelRow = selectedRows.back() - 1;
744 if( nextSelRow >= 0 )
746 GoToCell( nextSelRow, GetGridCursorCol() );
747 SetGridCursor( nextSelRow, GetGridCursorCol() );
750 for(
int row : selectedRows )
757 for(
int col = 0; col < GetNumberCols(); ++col )
759 wxString temp = GetCellValue( aRowA, col );
760 SetCellValue( aRowA, col, GetCellValue( aRowB, col ) );
761 SetCellValue( aRowB, col, temp );
778 const std::function<
void(
int row )>& aMover )
783 int i = GetGridCursorRow();
785 if( i > 0 && aFilter( i ) )
789 SetGridCursor( i - 1, GetGridCursorCol() );
790 MakeCellVisible( GetGridCursorRow(), GetGridCursorCol() );
811 const std::function<
void(
int row )>& aMover )
816 int i = GetGridCursorRow();
818 if( i + 1 < GetNumberRows() && aFilter( i ) )
822 SetGridCursor( i + 1, GetGridCursorCol() );
823 MakeCellVisible( GetGridCursorRow(), GetGridCursorCol() );
856 wxString stringValue = GetCellValue( aRow, aCol );
862 m_eval->SetDefaultUnits( cellUnits );
864 if(
m_eval->Process( stringValue ) )
865 stringValue =
m_eval->Result();
874 wxString stringValue = GetCellValue( aRow, aCol );
880 m_eval->SetDefaultUnits( cellUnits );
883 stringValue =
m_eval->Result();
897 cellDataType = EDA_DATA_TYPE::DISTANCE;
899 SetCellValue( aRow, aCol,
getUnitsProvider( aCol )->StringFromValue( aValue,
true, cellDataType ) );
905 SetCellValue( aRow, aCol,
getUnitsProvider( aCol )->StringFromOptionalValue( aValue,
true ) );
923 size = GetRowLabelSize();
925 for(
int row = 0; aContents && row < GetNumberRows(); row++ )
926 size = std::max( size,
int( GetTextExtent( GetRowLabelValue( row ) + wxS(
"M" ) ).x ) );
931 size = GetColSize( aCol );
939 size = std::max( size,
int( GetTextExtent( GetColLabelValue( aCol ) + wxS(
"M" ) ).x ) );
942 for(
int row = 0; aContents && row < GetNumberRows(); row++ )
945 if( GetTable()->CanGetValueAs( row, aCol, wxGRID_VALUE_STRING ) )
946 size = std::max( size, GetTextExtent( GetCellValue( row, aCol ) + wxS(
"M" ) ).x );
948 size = std::max( size, GetTextExtent(
"MM" ).x );
958 int line_height = int( GetTextExtent(
"Mj" ).y ) + 3;
959 int row_height = GetColLabelSize();
960 int initial_row_height = row_height;
965 for(
int col = 0; col < GetNumberCols(); col++ )
967 int nl_count = GetColLabelValue( col ).Freq(
'\n' );
972 if( row_height < line_height * ( nl_count+1 ) )
973 row_height += line_height * nl_count;
979 if( initial_row_height != row_height )
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
A color representation with 4 components: red, green, blue, alpha.
wxColour ToColour() const
COLOR4D Mix(const COLOR4D &aColor, double aFactor) const
Return a color that is mixed with the input by a factor.
static const wxString NullUiString
The string that is used in the UI to represent a null value.
std::optional< int > OptionalValueFromString(const wxString &aTextValue, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
Converts aTextValue in aUnits to internal units used by the frame.
wxString StringFromOptionalValue(std::optional< int > aValue, bool aAddUnitLabel=false, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
Converts an optional aValue in internal units into a united string.
EDA_UNITS GetUserUnits() const
static EDA_DATA_TYPE GetTypeFromUnits(const EDA_UNITS aUnits)
Gets the inferred type from the given units.
wxString StringFromValue(double aValue, bool aAddUnitLabel=false, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
Converts aValue in internal units into a united string.
int ValueFromString(const wxString &aTextValue, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
Converts aTextValue in aUnits to internal units used by the frame.
Attribute provider that provides attributes (or modifies the existing attribute) to alternate a row c...
WX_GRID_ALT_ROW_COLOR_PROVIDER(const wxColor &aBaseColor)
wxGridCellAttr * GetAttr(int row, int col, wxGridCellAttr::wxAttrKind kind) const override
wxGridCellAttrPtr m_attrEven
void UpdateColors(const wxColor &aBaseColor)
void DrawBorder(const wxGrid &grid, wxDC &dc, wxRect &rect) const override
wxGridCellAttr * enhanceAttr(wxGridCellAttr *aInputAttr, int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind)
int GetVisibleWidth(int aCol, bool aHeader=true, bool aContents=true, bool aKeep=false)
Calculate the specified column based on the actual size of the text on screen.
void onGridCellSelect(wxGridEvent &aEvent)
void SetLabelFont(const wxFont &aFont)
Hide wxGrid's SetLabelFont() because for some reason on MSW it's a one-shot and subsequent calls to i...
void onDPIChanged(wxDPIChangedEvent &event)
void ShowHideColumns(const wxString &shownColumns)
Show/hide the grid columns based on a tokenized string of shown column indexes.
void OnMoveRowUp(const std::function< void(int row)> &aMover)
std::map< int, UNITS_PROVIDER * > m_unitsProviders
void SetTable(wxGridTableBase *table, bool aTakeOwnership=false)
Hide wxGrid's SetTable() method with one which doesn't mess up the grid column widths when setting th...
void DestroyTable(wxGridTableBase *aTable)
Work-around for a bug in wxGrid which crashes when deleting the table if the cell edit control was no...
std::unordered_map< int, std::pair< EDA_UNITS, EDA_DATA_TYPE > > m_autoEvalColsUnits
void SetAutoEvalColUnits(int col, EDA_UNITS aUnit, EDA_DATA_TYPE aUnitType)
Set the unit and unit data type to use for a given column.
bool CancelPendingChanges()
void SetColLabelSize(int aHeight)
Hide wxGrid's SetColLabelSize() method with one which makes sure the size is tall enough for the syst...
void SwapRows(int aRowA, int aRowB)
These aren't that tricky, but might as well share code.
std::pair< EDA_UNITS, EDA_DATA_TYPE > getColumnUnits(int aCol) const
Returns the units and data type associated with a given column.
void SetUnitValue(int aRow, int aCol, int aValue)
Set a unitized cell's value.
WX_GRID(wxWindow *parent, wxWindowID id, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxWANTS_CHARS, const wxString &name=wxGridNameStr)
int GetUnitValue(int aRow, int aCol)
Apply standard KiCad unit and eval services to a numeric cell.
std::vector< int > m_autoEvalCols
UNITS_PROVIDER * getUnitsProvider(int aCol) const
std::map< std::pair< int, int >, std::pair< wxString, wxString > > m_evalBeforeAfter
void DrawCornerLabel(wxDC &dc) override
A re-implementation of wxGrid::DrawCornerLabel which draws flat borders.
void onCellEditorHidden(wxGridEvent &aEvent)
void OnMoveRowDown(const std::function< void(int row)> &aMover)
void onGridColMove(wxGridEvent &aEvent)
void SetOptionalUnitValue(int aRow, int aCol, std::optional< int > aValue)
Set a unitized cell's optional value.
void onCellEditorShown(wxGridEvent &aEvent)
void EnsureColLabelsVisible()
Ensure the height of the row displaying the column labels is enough, even if labels are multiline tex...
void OnDeleteRows(const std::function< void(int row)> &aDeleter)
Handles a row deletion event.
wxString GetShownColumnsAsString()
Get a tokenized string containing the shown column indexes.
void OnAddRow(const std::function< std::pair< int, int >()> &aAdder)
void DrawRowLabel(wxDC &dc, int row) override
A re-implementation of wxGrid::DrawRowLabel which draws flat borders.
std::bitset< 64 > GetShownColumns()
static void CellEditorSetMargins(wxTextEntryBase *aEntry)
A helper function to set OS-specific margins for text-based cell editors.
std::optional< int > GetOptionalUnitValue(int aRow, int aCol)
Apply standard KiCad unit and eval services to a numeric cell.
void EnableAlternateRowColors(bool aEnable=true)
Enable alternate row highlighting, where every odd row has a different background color than the even...
void SetUnitsProvider(UNITS_PROVIDER *aProvider, int aCol=0)
Set a EUNITS_PROVIDER to enable use of unit- and eval-based Getters.
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
std::unique_ptr< NUMERIC_EVALUATOR > m_eval
void DrawColLabel(wxDC &dc, int col) override
A re-implementation of wxGrid::DrawColLabel which left-aligns the first column and draws flat borders...
static void CellEditorTransformSizeRect(wxRect &aRect)
A helper function to tweak sizes of text-based cell editors depending on OS.
EDA_DATA_TYPE
The type of unit.
KICOMMON_API wxFont GetControlFont(wxWindow *aWindow)
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
PGM_BASE & Pgm()
The global program "get" accessor.
Functions to provide common constants and other functions to assist in making a consistent UI.
wxColour getBorderColour()
#define MIN_GRIDCELL_MARGIN