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 )
80 aEntry->SetMargins( 0, 0 );
86#if defined( __WXMSW__ ) || defined( __WXGTK__ )
94 KIGFX::COLOR4D bg = wxSystemSettings::GetColour( wxSYS_COLOUR_FRAMEBK );
95 KIGFX::COLOR4D fg = wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER );
106 wxDCBrushChanger SetBrush( dc, *wxTRANSPARENT_BRUSH );
109 rect.SetTop( rect.GetTop() + 1 );
110 rect.SetLeft( rect.GetLeft() + 1 );
111 rect.SetBottom( rect.GetBottom() - 1 );
112 rect.SetRight( rect.GetRight() - 1 );
113 dc.DrawRectangle( rect );
123 wxDCBrushChanger SetBrush( dc, *wxTRANSPARENT_BRUSH );
126 rect.SetTop( rect.GetTop() + 1 );
127 rect.SetLeft( rect.GetLeft() );
128 rect.SetBottom( rect.GetBottom() - 1 );
129 rect.SetRight( rect.GetRight() - 1 );
130 dc.DrawRectangle( rect );
140 wxDCBrushChanger SetBrush( dc, *wxTRANSPARENT_BRUSH );
143 rect.SetTop( rect.GetTop() + 1 );
144 rect.SetLeft( rect.GetLeft() + 1 );
145 rect.SetBottom( rect.GetBottom() - 1 );
146 rect.SetRight( rect.GetRight() );
147 dc.DrawRectangle( rect );
160 wxGridCellAttrProvider(),
174 wxGridCellAttr*
GetAttr(
int row,
int col, wxGridCellAttr::wxAttrKind kind )
const override
176 wxGridCellAttrPtr cellAttr( wxGridCellAttrProvider::GetAttr( row, col, kind ) );
181 return cellAttr.release();
189 if( !cellAttr->HasBackgroundColour() )
191 cellAttr = cellAttr->Clone();
192 cellAttr->SetBackgroundColour(
m_attrEven->GetBackgroundColour() );
196 return cellAttr.release();
204WX_GRID::WX_GRID( wxWindow *parent, wxWindowID
id,
const wxPoint& pos,
const wxSize& size,
long style,
205 const wxString&
name ) :
206 wxGrid( parent, id, pos, size, style,
name ),
210 SetDefaultRowSize( GetDefaultRowSize() + FromDIP( 4 ) );
212 SetDefaultCellOverflow(
false );
239 wxGrid::SetColLabelSize( wxGRID_AUTOSIZE );
248 if( aHeight == 0 || aHeight == wxGRID_AUTOSIZE )
250 wxGrid::SetColLabelSize( aHeight );
257 wxGrid::SetColLabelSize( std::max( aHeight, minHeight ) );
271 int numberCols = GetNumberCols();
272 int* formBuilderColWidths =
new int[numberCols];
274 for(
int i = 0; i < numberCols; ++i )
275 formBuilderColWidths[ i ] = GetColSize( i );
277 wxGrid::SetTable( aTable );
281 numberCols = std::min( numberCols, GetNumberCols() );
283 for(
int i = 0; i < numberCols; ++i )
288 SetColSize( i, std::max( formBuilderColWidths[ i ], headingWidth ) );
291 delete[] formBuilderColWidths;
304 wxGridTableBase*
table = wxGrid::GetTable();
306 wxCHECK_MSG(
table, ,
"Tried to enable alternate row colors without a table assigned to the grid" );
310 wxColor
color = wxGrid::GetDefaultCellBackgroundColour();
315 table->SetAttrProvider(
nullptr );
325 int row = aEvent.GetRow();
326 int col = aEvent.GetCol();
328 if( row >= 0 && row < GetNumberRows() && col >= 0 && col < GetNumberCols() )
330 if( GetSelectionMode() == wxGrid::wxGridSelectCells )
332 SelectBlock( row, col, row, col,
false );
334 else if( GetSelectionMode() == wxGrid::wxGridSelectRows
335 || GetSelectionMode() == wxGrid::wxGridSelectRowsOrColumns )
337 SelectBlock( row, 0, row, GetNumberCols() - 1,
false );
339 else if( GetSelectionMode() == wxGrid::wxGridSelectColumns )
341 SelectBlock( 0, col, GetNumberRows() - 1, col,
false );
351 int row = aEvent.GetRow();
352 int col = aEvent.GetCol();
354 const std::pair<wxString, wxString>& beforeAfter =
m_evalBeforeAfter[ { row, col } ];
356 if( GetCellValue( row, col ) == beforeAfter.second )
357 SetCellValue( row, col, beforeAfter.first );
364 const int col = aEvent.GetCol();
371 EDA_UNITS cellUnits = cellUnitsData.first;
374 m_eval->SetDefaultUnits( cellUnits );
376 const int row = aEvent.GetRow();
379 bool isNullable =
false;
380 wxGridCellEditor* cellEditor = GetCellEditor( row, col );
385 isNullable = nullable->IsNullable();
387 cellEditor->DecRef();
391 [
this, row, col, isNullable, unitsProvider, cellDataType]()
395 if( row >= GetNumberRows() || col >= GetNumberCols() )
398 wxString stringValue = GetCellValue( row, col );
399 bool processedOk =
true;
402 processedOk =
m_eval->Process( stringValue );
410 std::optional<int> val;
430 if( stringValue != evalValue )
432 SetCellValue( row, col, evalValue );
452 wxGrid::SetTable(
nullptr );
459 wxString shownColumns;
461 for(
int i = 0; i < GetNumberCols(); ++i )
463 if( IsColShown( i ) )
465 if( shownColumns.Length() )
466 shownColumns << wxT(
" " );
478 std::bitset<64> shownColumns;
480 for(
int ii = 0; ii < GetNumberCols(); ++ii )
481 shownColumns[ii] = IsColShown( ii );
489 for(
int i = 0; i < GetNumberCols(); ++i )
492 wxStringTokenizer shownTokens( shownColumns,
" \t\r\n", wxTOKEN_STRTOK );
494 while( shownTokens.HasMoreTokens() )
497 shownTokens.GetNextToken().ToLong( &colNumber );
499 if( colNumber >= 0 && colNumber < GetNumberCols() )
500 ShowCol( (
int) colNumber );
507 if( m_nativeColumnLabels )
508 wxGrid::DrawCornerLabel( dc );
510 wxRect rect( wxSize( m_rowLabelWidth, m_colLabelHeight ) );
516 wxDCBrushChanger setBrush( dc, m_colLabelWin->GetBackgroundColour() );
517 wxDCPenChanger setPen( dc, m_colLabelWin->GetBackgroundColour() );
518 dc.DrawRectangle( rect.Inflate( 1 ) );
527 if( m_nativeColumnLabels )
528 wxGrid::DrawColLabel( dc, col );
530 if( GetColWidth( col ) <= 0 || m_colLabelHeight <= 0 )
533 wxRect rect( GetColLeft( col ), 0, GetColWidth( col ), m_colLabelHeight );
539 wxDCBrushChanger setBrush( dc, m_colLabelWin->GetBackgroundColour() );
540 wxDCPenChanger setPen( dc, m_colLabelWin->GetBackgroundColour() );
541 dc.DrawRectangle( rect.Inflate( 1 ) );
547 dc.SetFont( GetLabelFont() );
550 GetColLabelAlignment( &hAlign, &vAlign );
551 const int orient = GetColLabelTextOrientation();
554 hAlign = wxALIGN_LEFT;
556 if( hAlign == wxALIGN_LEFT )
559 rend.DrawLabel( *
this, dc, GetColLabelValue( col ), rect, hAlign, vAlign, orient );
565 if( GetRowHeight( row ) <= 0 || m_rowLabelWidth <= 0 )
568 wxRect rect( 0, GetRowTop( row ), m_rowLabelWidth, GetRowHeight( row ) );
574 wxDCBrushChanger setBrush( dc, m_colLabelWin->GetBackgroundColour() );
575 wxDCPenChanger setPen( dc, m_colLabelWin->GetBackgroundColour() );
576 dc.DrawRectangle( rect.Inflate( 1 ) );
582 dc.SetFont( GetLabelFont() );
585 GetRowLabelAlignment(&hAlign, &vAlign);
587 if( hAlign == wxALIGN_LEFT )
590 rend.DrawLabel( *
this, dc, GetRowLabelValue( row ), rect, hAlign, vAlign, wxHORIZONTAL );
596 if( !IsCellEditControlEnabled() )
599 HideCellEditControl();
602 m_cellEditCtrlEnabled =
false;
604 int row = m_currentCellCoords.GetRow();
605 int col = m_currentCellCoords.GetCol();
607 wxString oldval = GetCellValue( row, col );
610 wxGridCellAttr* attr = GetCellAttr( row, col );
611 wxGridCellEditor*
editor = attr->GetEditor(
this, row, col );
613 editor->EndEdit( row, col,
this, oldval, &newval );
624 if( !IsCellEditControlEnabled() )
627 if( !aQuietMode && SendEvent( wxEVT_GRID_EDITOR_HIDDEN ) == -1 )
630 HideCellEditControl();
633 m_cellEditCtrlEnabled =
false;
635 int row = m_currentCellCoords.GetRow();
636 int col = m_currentCellCoords.GetCol();
638 wxString oldval = GetCellValue( row, col );
641 wxGridCellAttr* attr = GetCellAttr( row, col );
642 wxGridCellEditor*
editor = attr->GetEditor(
this, row, col );
644 bool changed =
editor->EndEdit( row, col,
this, oldval, &newval );
651 if( !aQuietMode && SendEvent( wxEVT_GRID_CELL_CHANGING, newval ) == -1 )
654 editor->ApplyEdit( row, col,
this );
659 if( !aQuietMode && SendEvent( wxEVT_GRID_CELL_CHANGED, oldval ) == -1 )
662 SetCellValue( row, col, oldval );
679 auto [row, editCol] = aAdder();
683 MakeCellVisible( row, std::max( editCol, 0 ) );
684 SetGridCursor( row, std::max( editCol, 0 ) );
688 EnableCellEditControl(
true );
689 ShowCellEditControl();
706 const std::function<
void(
int row )>& aDeleter )
708 wxArrayInt selectedRows = GetSelectedRows();
710 if( selectedRows.empty() && GetGridCursorRow() >= 0 )
711 selectedRows.push_back( GetGridCursorRow() );
713 if( selectedRows.empty() )
716 for(
int row : selectedRows )
718 if( !aFilter( row ) )
727 [](
int* first,
int* second )
729 return *second - *first;
732 int nextSelRow = selectedRows.back() - 1;
734 if( nextSelRow >= 0 )
736 GoToCell( nextSelRow, GetGridCursorCol() );
737 SetGridCursor( nextSelRow, GetGridCursorCol() );
740 for(
int row : selectedRows )
747 for(
int col = 0; col < GetNumberCols(); ++col )
749 wxString temp = GetCellValue( aRowA, col );
750 SetCellValue( aRowA, col, GetCellValue( aRowB, col ) );
751 SetCellValue( aRowB, col, temp );
768 const std::function<
void(
int row )>& aMover )
773 int i = GetGridCursorRow();
775 if( i > 0 && aFilter( i ) )
779 SetGridCursor( i - 1, GetGridCursorCol() );
780 MakeCellVisible( GetGridCursorRow(), GetGridCursorCol() );
801 const std::function<
void(
int row )>& aMover )
806 int i = GetGridCursorRow();
808 if( i + 1 < GetNumberRows() && aFilter( i ) )
812 SetGridCursor( i + 1, GetGridCursorCol() );
813 MakeCellVisible( GetGridCursorRow(), GetGridCursorCol() );
846 wxString stringValue = GetCellValue( aRow, aCol );
852 m_eval->SetDefaultUnits( cellUnits );
854 if(
m_eval->Process( stringValue ) )
855 stringValue =
m_eval->Result();
864 wxString stringValue = GetCellValue( aRow, aCol );
870 m_eval->SetDefaultUnits( cellUnits );
873 stringValue =
m_eval->Result();
889 SetCellValue( aRow, aCol,
getUnitsProvider( aCol )->StringFromValue( aValue,
true, cellDataType ) );
895 SetCellValue( aRow, aCol,
getUnitsProvider( aCol )->StringFromOptionalValue( aValue,
true ) );
913 size = GetRowLabelSize();
915 for(
int row = 0; aContents && row < GetNumberRows(); row++ )
916 size = std::max( size,
int( GetTextExtent( GetRowLabelValue( row ) + wxS(
"M" ) ).x ) );
921 size = GetColSize( aCol );
929 size = std::max( size,
int( GetTextExtent( GetColLabelValue( aCol ) + wxS(
"M" ) ).x ) );
932 for(
int row = 0; aContents && row < GetNumberRows(); row++ )
935 if( GetTable()->CanGetValueAs( row, aCol, wxGRID_VALUE_STRING ) )
936 size = std::max( size, GetTextExtent( GetCellValue( row, aCol ) + wxS(
"M" ) ).x );
938 size = std::max( size, GetTextExtent(
"MM" ).x );
948 int line_height = int( GetTextExtent(
"Mj" ).y ) + 3;
949 int row_height = GetColLabelSize();
950 int initial_row_height = row_height;
955 for(
int col = 0; col < GetNumberCols(); col++ )
957 int nl_count = GetColLabelValue( col ).Freq(
'\n' );
962 if( row_height < line_height * ( nl_count+1 ) )
963 row_height += line_height * nl_count;
969 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