28#include <nlohmann/json.hpp>
32#include <wx/settings.h>
36 wxGridCellStringRenderer()
42 int aRow,
int aCol,
bool isSelected )
44 wxString value = aGrid.GetCellValue( aRow, aCol );
47 value =
model->GetResolvedValue( aRow, aCol );
52 wxGridCellRenderer::Draw( aGrid, aAttr, aDC, aRect, aRow, aCol, isSelected );
53 SetTextColoursAndFont( aGrid, aAttr, aDC, isSelected );
54 aGrid.DrawTextRectangle( aDC, value, rect, wxALIGN_LEFT, wxALIGN_CENTRE );
61 wxString value = aGrid.GetCellValue( aRow, aCol );
64 value =
model->GetResolvedValue( aRow, aCol );
66 return wxGridCellStringRenderer::DoGetBestSize( aAttr, aDC, value );
104 wxCHECK( aRow >= 0 && aRow < GetNumberRows(),
false );
114 wxCHECK_RET( aAttr, wxS(
"Cannot apply a renderer to a null cell attribute" ) );
124 wxColour bg = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW );
125 bool isDark = ( bg.Red() + bg.Green() + bg.Blue() ) < 384;
140 if( datasheetCol < 0 )
145 if( attrIt ==
m_colAttrs.end() || !attrIt->second )
148 return aCol == datasheetCol ||
IsURL(
GetValue( aRow, aCol ) );
155 wxCHECK( datasheetCol >= 0,
nullptr );
158 wxCHECK( attrIt !=
m_colAttrs.end() && attrIt->second,
nullptr );
160 return attrIt->second->Clone();
169 wxGridCellAttr* stripedAttr = aAttr ? aAttr->Clone() :
new wxGridCellAttr;
170 wxSafeDecRef( aAttr );
181 if( !stripedAttr->HasBackgroundColour() )
182 stripedAttr->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
190 constexpr double ROW_HINT_OPACITY = 0.1;
191 constexpr double COLUMN_HINT_OPACITY = 0.05;
197 if( !
grid || !
grid->IsCursorRowColumnHighlightEnabled()
198 || ( aRow !=
grid->GetGridCursorRow() && aCol !=
grid->GetGridCursorCol() ) )
203 wxColour background = aAttr && aAttr->HasBackgroundColour() ? aAttr->GetBackgroundColour()
204 :
grid->GetDefaultCellBackgroundColour();
205 wxColour highlight = wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT );
206 double hintOpacity = aRow ==
grid->GetGridCursorRow() ? ROW_HINT_OPACITY : COLUMN_HINT_OPACITY;
208 wxColour hintedBackground( wxColour::AlphaBlend( highlight.Red(), background.Red(), hintOpacity ),
209 wxColour::AlphaBlend( highlight.Green(), background.Green(), hintOpacity ),
210 wxColour::AlphaBlend( highlight.Blue(), background.Blue(), hintOpacity ) );
212 wxGridCellAttr* hintedAttr = aAttr ? aAttr->Clone() :
new wxGridCellAttr;
213 wxSafeDecRef( aAttr );
214 hintedAttr->SetBackgroundColour( hintedBackground );
222 if( wxGrid*
grid = GetView() )
223 static_cast<WX_GRID*
>(
grid )->CommitPendingChanges(
true );
229 wxCHECK_RET( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ),
"Invalid Column Number" );
230 wxCHECK_RET( aNewPos >= 0 && aNewPos <
static_cast<int>(
m_cols.size() ),
"Invalid New Column Position" );
232 if( aCol == aNewPos )
246 std::rotate( std::begin(
m_cols ) + aCol, std::begin(
m_cols ) + aCol + 1, std::begin(
m_cols ) + aNewPos + 1 );
255 std::rotate( std::begin(
m_cols ) + aNewPos, std::begin(
m_cols ) + aCol, std::begin(
m_cols ) + aCol + 1 );
262 wxCHECK_RET( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ),
"Invalid Column Number" );
268 fieldsStore.erase(
m_cols[aCol].m_fieldName );
280 wxSafeDecRef( attrIt->second );
284 std::map<int, wxGridCellAttr*> shiftedColAttrs;
287 shiftedColAttrs[col > aCol ? col - 1 : col] = attr;
291 if( wxGrid*
grid = GetView() )
293 wxGridTableMessage msg(
this, wxGRIDTABLE_NOTIFY_COLS_DELETED, aCol, 1 );
294 grid->ProcessTableMessage( msg );
303 wxCHECK_RET( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ),
"Invalid Column Number" );
309 auto node = fieldsStore.extract(
m_cols[aCol].m_fieldName );
313 node.key() = newName;
314 fieldsStore.insert( std::move( node ) );
318 m_cols[aCol].m_fieldName = newName;
319 m_cols[aCol].m_label = newName;
326 wxCHECK_RET( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ),
"Invalid Column Number" );
327 m_cols[aCol].m_label = aLabel;
333 wxCHECK( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ), wxString() );
334 return m_cols[aCol].m_label;
340 wxCHECK( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ), wxString() );
341 return m_cols[aCol].m_fieldName;
349 for(
int row = 0; row < GetNumberRows(); ++row )
358 for(
size_t i = 0; i <
m_cols.size(); i++ )
361 return static_cast<int>( i );
370 std::vector<BOM_FIELD> fields;
373 fields.push_back( { col.m_fieldName, col.m_label, col.m_show, col.m_group } );
383 size_t foundCount = 0;
385 for(
const wxString& newField : aNewOrder )
387 if( foundCount >=
m_cols.size() )
392 if( col.m_fieldName == newField )
394 std::swap(
m_cols[foundCount], col );
405 wxCHECK( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ),
false );
412 wxCHECK( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ),
false );
419 wxCHECK( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ),
false );
426 wxCHECK( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ),
false );
433 wxCHECK( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ),
false );
440 wxCHECK( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ),
false );
448 wxCHECK( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ),
false );
456 wxCHECK( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ),
false );
465 for(
int col = 0; col < aCol; ++col )
477 wxCHECK( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ),
true );
485 wxCHECK( aRow >= 0 && aRow < GetNumberRows(),
true );
494 wxCHECK( aRow >= 0 && aRow < GetNumberRows(),
false );
495 wxCHECK( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ),
false );
518 wxCHECK( aRow >= 0 && aRow < GetNumberRows(),
false );
532 wxCHECK_RET( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ),
"Invalid Column Number" );
552 wxCHECK_RET( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ),
"Invalid Column Number" );
557 m_cols[aCol].m_group = aGroup;
563 wxCHECK_MSG( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ),
false,
"Invalid Column Number" );
564 return m_cols[aCol].m_group;
570 wxCHECK_RET( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ),
"Invalid Column Number" );
571 m_cols[aCol].m_show = aShow;
577 wxCHECK_MSG( aCol >= 0 && aCol <
static_cast<int>(
m_cols.size() ),
false,
"Invalid Column Number" );
578 return m_cols[aCol].m_show;
585 for(
size_t i = 0; i <
m_cols.size(); i++ )
591 std::set<wxString> seen;
592 std::vector<wxString> order;
595 for(
const BOM_FIELD& field : aPreset.fieldsOrdered )
598 if( !field.
name || seen.count( field.
name ) )
601 seen.insert( field.
name );
602 order.emplace_back( field.
name );
653 current.readOnly =
false;
680 for(
size_t col = 0; col <
m_cols.size(); col++ )
683 lastCol =
static_cast<int>( col );
691 out.Append( wxString::FromUTF8(
"\xEF\xBB\xBF" ) );
693 auto formatField = [&]( wxString aField,
bool aLast ) -> wxString
697 aField.Replace( wxS(
"\r" ), wxS(
"" ) );
698 aField.Replace( wxS(
"\n" ), wxS(
"" ) );
702 aField.Replace( wxS(
"\t" ), wxS(
"" ) );
714 for(
size_t col = 0; col <
m_cols.size(); col++ )
719 out.Append( formatField(
m_cols[col].m_label, col ==
static_cast<size_t>( lastCol ) ) );
723 for(
int row = 0; row < GetNumberRows(); row++ )
726 if(
GetRowState( row ) == ROW_STATE::EXPANDED_CHILD )
729 for(
size_t col = 0; col <
m_cols.size(); col++ )
734 out.Append( formatField(
736 col ==
static_cast<size_t>( lastCol ) ) );
746 return aFieldName == wxS(
"${DNP}" ) || aFieldName == wxS(
"${EXCLUDE_FROM_BOARD}" )
747 || aFieldName == wxS(
"${EXCLUDE_FROM_BOM}" ) || aFieldName == wxS(
"${EXCLUDE_FROM_POS_FILES}" )
748 || aFieldName == wxS(
"${EXCLUDE_FROM_SIM}" );
761 return wxEmptyString;
763 if( aFieldName == wxS(
"${DNP}" ) )
765 else if( aFieldName == wxS(
"${EXCLUDE_FROM_BOARD}" ) )
766 return wxS(
"Excluded from board" );
767 else if( aFieldName == wxS(
"${EXCLUDE_FROM_BOM}" ) )
768 return wxS(
"Excluded from BOM" );
769 else if( aFieldName == wxS(
"${EXCLUDE_FROM_POS_FILES}" ) )
770 return wxS(
"Excluded from position files" );
771 else if( aFieldName == wxS(
"${EXCLUDE_FROM_SIM}" ) )
772 return wxS(
"Excluded from simulation" );
774 return wxEmptyString;
782 nlohmann::json j = nlohmann::json::object();
786 nlohmann::json jfields = nlohmann::json::object();
788 for(
const auto& [
name, value] : fields )
789 jfields[std::string(
name.ToUTF8() )] = std::string( value.ToUTF8() );
791 j[std::string( key.AsString().ToUTF8() )] = jfields;
794 return wxString( j.dump() );
800 nlohmann::json j = nlohmann::json::parse( aState.ToStdString(),
nullptr,
false );
809 for(
auto it = j.begin(); it != j.end(); ++it )
811 KIID_PATH key( wxString::FromUTF8( it.key().c_str() ) );
812 std::map<wxString, wxString>& fields =
m_dataStore[key];
814 for(
auto fit = it.value().begin(); fit != it.value().end(); ++fit )
815 fields[wxString::FromUTF8( fit.key().c_str() )] =
816 wxString::FromUTF8( fit.value().get<std::string>().c_str() );
823 GetView()->ForceRefresh();
Contains everything completly generic to fields tables data models, as well as column functionality t...
bool cellUsesResolvedTextRenderer(int aRow, int aCol)
virtual bool fieldIsItemProperty(const wxString &aFieldName) const
bool cellUsesUrlEditor(int aRow, int aCol)
~FIELDS_TABLE_DATA_MODEL_BASE() override
FIELDS_TABLE_DATA_MODEL_BASE()
BOM_FILTER_SCOPE GetFilterScope() const
virtual bool IsCellEdited(int aRow, int aCol)=0
void SetExcludeDNP(bool aExclude)
bool ColIsComputed(int aCol) const
void SetSorting(int aCol, bool aAscending)
int GetNumberCols() override
void MoveColumn(int aCol, int aNewPos)
wxString GetColFieldName(int aCol)
bool ColIsValue(int aCol) const
bool ColIsItemProperty(int aCol) const
void SetShowColumn(int aCol, bool aShow)
void SetIncludeExcludedFromBOM(bool aInclude)
bool IsRowEdited(int aRow)
Return true if any cell in the row has been edited.
wxGridCellAttr * applyFieldPresenceRenderer(wxGridCellAttr *aAttr, int aRow, int aCol)
bool CanClearCell(int aRow, int aCol)
std::vector< BOM_FIELD > GetFieldsOrdered()
bool ColIsAttribute(int aCol) const
static const wxString QUANTITY_VARIABLE
void applyResolvedTextRenderer(wxGridCellAttr *aAttr, bool aApplyTint)
static const wxString ITEM_NUMBER_VARIABLE
void commitPendingGridChanges()
virtual bool ColIsReadOnly(int aCol) const
virtual void AddColumn(const wxString &aFieldName, const wxString &aLabel, bool aAddedByUser)=0
bool GetGroupColumn(int aCol)
wxString Export(const BOM_FMT_PRESET &aSettings)
wxGridCellRenderer * m_resolvedTextRenderer
bool ColIsReference(int aCol) const
virtual wxString GetExportValue(int aRow, int aCol, const wxString &aRefDelimiter, const wxString &aRefRangeDelimiter)=0
virtual bool ColIsItemIdentifier(int aCol) const
Reference for symbol/fields tables, lib_id for lib tables.
void SetColLabelValue(int aCol, const wxString &aLabel) override
wxGridCellAttr * cloneUrlEditorAttr()
void SetFilterScope(BOM_FILTER_SCOPE aScope)
bool ColIsQuantity(int aCol) const
virtual bool fieldIsAttribute(const wxString &aFieldName) const
BOM_PRESET GetBomSettings()
wxGridCellAttr * applyCellDecorations(wxGridCellAttr *aAttr, int aRow, int aCol)
virtual wxString getAttributeResolvedValue(const wxString &aFieldName, bool aValue) const
void SetFieldsOrder(const std::vector< wxString > &aNewOrder)
bool ColIsFootprint(int aCol) const
virtual bool IsCellReadOnly(int aRow, int aCol)
int GetFieldNameCol(const wxString &aFieldName) const
virtual wxString GetResolvedValue(int aRow, int aCol)=0
void RemoveColumn(int aCol)
bool GetIncludeExcludedFromBOM()
wxString SerializeUndoState() const override
void SetGroupingEnabled(bool aGroup)
bool IsExpanderColumn(int aCol) const override
int GetColDataWidth(int aCol)
bool ColIsItemNumber(int aCol) const
const wxString & GetFilter()
wxGridCellRenderer * m_stripedRenderer
std::vector< DATA_MODEL_COL > m_cols
bool GetGroupingEnabled()
void RestoreUndoState(const wxString &aState) override
void RenameColumn(int aCol, const wxString &newName)
void SetGroupColumn(int aCol, bool aGroup)
void SetFilter(const wxString &aFilter)
wxString GetColLabelValue(int aCol) override
bool GetShowColumn(int aCol)
void ApplyBomPreset(const BOM_PRESET &aPreset)
virtual void RebuildRows()=0
virtual bool IsCellClear(int aRow, int aCol)=0
BOM_FILTER_SCOPE m_filterScope
bool m_rebuildsEnabled
Items included by the user selection scope.
std::map< KIID_PATH, std::map< wxString, wxString > > m_dataStore
wxString GetValue(int aRow, int aCol) override
int GetNumberRows() override
Cell renderer that shows the expanded result of text variables (e.g.
GRID_CELL_RESOLVED_TEXT_RENDERER()
wxSize GetBestSize(wxGrid &aGrid, wxGridCellAttr &aAttr, wxDC &aDC, int aRow, int aCol) override
wxGridCellRenderer * Clone() const override
void Draw(wxGrid &aGrid, wxGridCellAttr &aAttr, wxDC &aDC, const wxRect &aRect, int aRow, int aCol, bool isSelected) override
virtual ROW_STATE GetRowState(int aRow) const
std::map< int, wxGridCellAttr * > m_colAttrs
bool IsGeneratedValue(const wxString &aValue)
Returns true if some of the string is generated, e.g contains a text var or expression.
bool IsGeneratedField(const wxString &aFieldName)
Returns true if the entire string is generated, e.g is a single text var reference.
STRIPED_CELL_RENDERER< wxGridCellStringRenderer > STRIPED_STRING_RENDERER
const wxColour TEXT_VARIABLE_DARK_AMBER(80, 70, 30)
const wxColour CLEARED_FIELD_STRIPE_ON_DARK_LIGHT_RED(220, 180, 180)
const wxColour TEXT_VARIABLE_LIGHT_YELLOW(255, 252, 200)
const wxColour CLEARED_FIELD_STRIPE_ON_LIGHT_DARK_RED(100, 10, 10)
KICOMMON_API wxSize GetTextSize(const wxString &aSingleLine, wxWindow *aWindow)
Return the size of aSingleLine of text when it is rendered in aWindow using whatever font is currentl...
bool IsURL(wxString aStr)
Performs a URL sniff-test on a string.
bool includeByteOrderMark
wxString refRangeDelimiter
The point of the data model classes is fundamentally to represent three things:
bool FieldNamesAreDuplicates(const wxString &aLhs, const wxString &aRhs, std::initializer_list< FIELD_T > aMandatoryFields)
Test whether two field names should be treated as duplicates for the purposes of field name uniquenes...
wxString GetDefaultFieldName(FIELD_T aFieldId, TRANSLATION aTranslation)
Return a default symbol field name for a mandatory field type.
FIELD_T
The set of all field indices assuming an array like sequence that a SCH_COMPONENT or LIB_PART can hol...
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ DATASHEET
name of datasheet
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
Functions to provide common constants and other functions to assist in making a consistent UI.