CADSTAR Schematic Archive Importer: Load all fields in symbols

- Load Fields in the library items as well as schematic instances
- Remove invalid characters (e.g. '\n', '\t', '\r') in fields
- Load footprint field (assume that the footprint library name
  is the same as the filename of the schematic)
This commit is contained in:
Roberto Fernandez Bautista 2021-01-27 00:09:58 +00:00 committed by Wayne Stambaugh
parent 67ccee338e
commit b0051c07cb
6 changed files with 388 additions and 39 deletions

View File

@ -2166,6 +2166,83 @@ void CADSTAR_ARCHIVE_PARSER::DOCUMENTATION_SYMBOL::Parse( XNODE* aNode, PARSER_C
}
void CADSTAR_ARCHIVE_PARSER::DFLTSETTINGS::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "DFLTSETTINGS" ) );
Color = GetXmlAttributeIDString( aNode, 0 );
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( cNodeName == wxT( "INVISIBLE" ) )
{
IsVisible = false;
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
}
}
}
void CADSTAR_ARCHIVE_PARSER::ATTRCOL::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "ATTRCOL" ) );
AttributeID = GetXmlAttributeIDString( aNode, 0 );
Color = GetXmlAttributeIDString( aNode, 1 );
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( cNodeName == wxT( "INVISIBLE" ) )
{
IsVisible = false;
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
}
}
}
void CADSTAR_ARCHIVE_PARSER::ATTRCOLORS::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
{
wxASSERT( aNode->GetName() == wxT( "ATTRCOLORS" ) );
XNODE* cNode = aNode->GetChildren();
for( ; cNode; cNode = cNode->GetNext() )
{
wxString cNodeName = cNode->GetName();
if( cNodeName == wxT( "DFLTSETTINGS" ) )
{
DefaultSettings.Parse( cNode, aContext );
}
else if( cNodeName == wxT( "ATTRCOL" ) )
{
ATTRCOL attrcol;
attrcol.Parse( cNode, aContext );
AttributeColors.insert( { attrcol.AttributeID, attrcol } );
}
else
{
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
}
}
}
void CADSTAR_ARCHIVE_PARSER::InsertAttributeAtEnd( XNODE* aNode, wxString aValue )
{
wxString result;

View File

@ -104,6 +104,7 @@ public:
typedef wxString NET_ID;
typedef wxString NETELEMENT_ID;
typedef wxString DOCUMENTATION_SYMBOL_ID;
typedef wxString COLOR_ID;
static const long UNDEFINED_VALUE = -1;
@ -1217,6 +1218,34 @@ public:
};
struct DFLTSETTINGS : PARSER
{
COLOR_ID Color;
bool IsVisible = true;
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
};
struct ATTRCOL : PARSER
{
ATTRIBUTE_ID AttributeID;
COLOR_ID Color;
bool IsVisible = true;
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
};
struct ATTRCOLORS : PARSER
{
DFLTSETTINGS DefaultSettings;
std::map<ATTRIBUTE_ID, ATTRCOL> AttributeColors;
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
};
///////////////////////
// HELPER FUNCTIONS: //
///////////////////////
@ -1336,6 +1365,13 @@ public:
*/
static void FixTextPositionNoAlignment( EDA_TEXT* aKiCadTextItem );
static wxString generateLibName( const wxString& aRefName, const wxString& aAlternateName )
{
return aRefName
+ ( ( aAlternateName.size() > 0 ) ? ( wxT( " (" ) + aAlternateName + wxT( ")" ) )
: wxT( "" ) );
}
}; // class CADSTAR_ARCHIVE_PARSER
#endif // CADSTAR_ARCHIVE_PARSER_H_

View File

@ -341,15 +341,74 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadSchematicSymbolInstances()
}
LIB_PART* kiPart = mPartMap.at( sym.PartRef.RefID );
double compOrientationTenthDegree = 0.0;
double symOrientDeciDeg = 0.0;
SCH_COMPONENT* component =
loadSchematicSymbol( sym, kiPart, compOrientationTenthDegree );
SCH_COMPONENT* component = loadSchematicSymbol( sym, kiPart, symOrientDeciDeg );
SCH_FIELD* refField = component->GetField( REFERENCE_FIELD );
sym.ComponentRef.Designator.Replace( wxT( "\n" ), wxT( "\\n" ) );
sym.ComponentRef.Designator.Replace( wxT( "\r" ), wxT( "\\r" ) );
sym.ComponentRef.Designator.Replace( wxT( "\t" ), wxT( "\\t" ) );
sym.ComponentRef.Designator.Replace( wxT( " " ), wxT( "_" ) );
refField->SetText( sym.ComponentRef.Designator );
loadSymbolFieldAttribute(
sym.ComponentRef.AttrLoc, compOrientationTenthDegree, refField );
loadSymbolFieldAttribute( sym.ComponentRef.AttrLoc, symOrientDeciDeg,
sym.Mirror, refField );
if( sym.HasPartRef )
{
SCH_FIELD* partField = component->GetField( FIELD1 );
if( !partField )
{
component->AddField(
SCH_FIELD( wxPoint(), FIELD1, component, wxT( "Part Name" ) ) );
partField = component->GetField( FIELD1 );
}
wxString partname = getPart( sym.PartRef.RefID ).Name;
partname.Replace( wxT( "\n" ), wxT( "\\n" ) );
partname.Replace( wxT( "\r" ), wxT( "\\r" ) );
partname.Replace( wxT( "\t" ), wxT( "\\t" ) );
partField->SetText( partname );
loadSymbolFieldAttribute( sym.PartRef.AttrLoc, symOrientDeciDeg,
sym.Mirror, partField );
}
int fieldIdx = FIELD1;
for( auto attr : sym.AttributeValues )
{
ATTRIBUTE_VALUE attrVal = attr.second;
if( attrVal.HasLocation )
{
//SCH_FIELD* attrField = getFieldByName( component );
wxString attrName = getAttributeName( attrVal.AttributeID );
SCH_FIELD* attrField = component->FindField( attrName );
if( !attrField )
{
component->AddField(
SCH_FIELD( wxPoint(), ++fieldIdx, component, attrName ) );
attrField = component->GetField( fieldIdx );
}
attrVal.Value.Replace( wxT( "\n" ), wxT( "\\n" ) );
attrVal.Value.Replace( wxT( "\r" ), wxT( "\\r" ) );
attrVal.Value.Replace( wxT( "\t" ), wxT( "\\t" ) );
attrField->SetText( attrVal.Value );
loadSymbolFieldAttribute( attrVal.AttributeLocation, symOrientDeciDeg,
sym.Mirror, attrField );
attrField->SetVisible( isAttributeVisible( attrVal.AttributeID ) );
}
}
}
else if( sym.IsSymbolVariant )
{
@ -997,10 +1056,7 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadSymDefIntoLibrary( const SYMDEF_ID& aSymdef
wxCHECK( Library.SymbolDefinitions.find( aSymdefID ) != Library.SymbolDefinitions.end(), );
SYMDEF_SCM symbol = Library.SymbolDefinitions.at( aSymdefID );
//TODO add symbolName to KiCad part "unit"
wxString symbolName = generateSymDefName( aSymdefID );
int gateNumber = getKiCadUnitNumberFromGate( aGateID );
int gateNumber = getKiCadUnitNumberFromGate( aGateID );
for( std::pair<FIGURE_ID, FIGURE> figPair : symbol.Figures )
{
@ -1081,8 +1137,8 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadSymDefIntoLibrary( const SYMDEF_ID& aSymdef
if( symbol.TextLocations.find( SYMBOL_NAME_ATTRID ) != symbol.TextLocations.end() )
{
TEXT_LOCATION textLoc = symbol.TextLocations.at( SYMBOL_NAME_ATTRID );
LIB_FIELD* field = aPart->GetField( REFERENCE_FIELD );
loadLibraryFieldAttribute( textLoc, symbol.Origin, field );
LIB_FIELD* field = &aPart->GetReferenceField();
applyToLibraryFieldAttribute( textLoc, symbol.Origin, field );
field->SetUnit( gateNumber );
}
@ -1098,14 +1154,148 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadSymDefIntoLibrary( const SYMDEF_ID& aSymdef
}
field->SetName( "Part Name" );
loadLibraryFieldAttribute( textLoc, symbol.Origin, field );
applyToLibraryFieldAttribute( textLoc, symbol.Origin, field );
if( aCadstarPart )
field->SetText( aCadstarPart->Definition.Name );
{
wxString partName = aCadstarPart->Name;
partName.Replace( wxT( "\n" ), wxT( "\\n" ) );
partName.Replace( wxT( "\r" ), wxT( "\\r" ) );
partName.Replace( wxT( "\t" ), wxT( "\\t" ) );
field->SetText( partName );
}
field->SetUnit( gateNumber );
}
if( aCadstarPart )
{
int fieldIdx = FIELD1;
wxString footprintRefName = wxEmptyString;
wxString footprintAlternateName = wxEmptyString;
auto loadLibraryField =
[&]( ATTRIBUTE_VALUE& aAttributeVal )
{
wxString attrName = getAttributeName( aAttributeVal.AttributeID );
LIB_FIELD* attrField = nullptr;
//Remove invalid field characters
aAttributeVal.Value.Replace( wxT( "\n" ), wxT( "\\n" ) );
aAttributeVal.Value.Replace( wxT( "\r" ), wxT( "\\r" ) );
aAttributeVal.Value.Replace( wxT( "\t" ), wxT( "\\t" ) );
//TODO: Handle "links": In cadstar a field can be a "link" if its name starts with the
//characters "Link ". Need to figure out how to convert them to equivalent in KiCad
if( attrName == wxT( "(PartDefinitionNameStem)" ) )
{
//Space not allowed in Reference field
aAttributeVal.Value.Replace( wxT( " " ), "_" );
aPart->GetReferenceField().SetText( aAttributeVal.Value );
return;
}
else if( attrName == wxT( "(PartDescription)" ) )
{
aPart->SetDescription( aAttributeVal.Value );
return;
}
else if( attrName == wxT( "(PartDefinitionReferenceName)" ) )
{
footprintRefName = aAttributeVal.Value;
return;
}
else if( attrName == wxT( "(PartDefinitionAlternateName)" ) )
{
footprintAlternateName = aAttributeVal.Value;
return;
}
else
{
attrField = aPart->FindField( attrName );
}
if( !attrField )
{
aPart->AddField( new LIB_FIELD( aPart, ++fieldIdx ) );
attrField = aPart->GetField( fieldIdx );
attrField->SetName( attrName );
}
attrField->SetText( aAttributeVal.Value );
attrField->SetUnit( gateNumber );
if( aAttributeVal.HasLocation )
{
// #1 Check if the part itself defined a location for the field
applyToLibraryFieldAttribute( aAttributeVal.AttributeLocation, symbol.Origin,
attrField );
attrField->SetVisible( isAttributeVisible( aAttributeVal.AttributeID ) );
}
else if( symbol.TextLocations.find( aAttributeVal.AttributeID )
!= symbol.TextLocations.end() )
{
// #2 Look in the symbol definition: Text locations
TEXT_LOCATION symTxtLoc = symbol.TextLocations.at( aAttributeVal.AttributeID );
applyToLibraryFieldAttribute( symTxtLoc, symbol.Origin, attrField );
attrField->SetVisible( isAttributeVisible( symTxtLoc.AttributeID ) );
}
else if( symbol.AttributeValues.find( aAttributeVal.AttributeID )
!= symbol.AttributeValues.end() )
{
// #3 Look in the symbol definition: Attribute values
ATTRIBUTE_VALUE symAttrVal =
symbol.AttributeValues.at( aAttributeVal.AttributeID );
if( symAttrVal.HasLocation )
{
applyToLibraryFieldAttribute( symAttrVal.AttributeLocation, symbol.Origin,
attrField );
attrField->SetVisible( isAttributeVisible( symAttrVal.AttributeID ) );
}
else
{
attrField->SetVisible( false );
applyTextSettings( wxT( "TC1" ), ALIGNMENT::NO_ALIGNMENT,
JUSTIFICATION::LEFT, attrField );
}
}
else
{
attrField->SetVisible( false );
applyTextSettings( wxT( "TC1" ), ALIGNMENT::NO_ALIGNMENT,
JUSTIFICATION::LEFT, attrField );
}
};
// Load all attributes in the Part Definition
for( std::pair<ATTRIBUTE_ID, ATTRIBUTE_VALUE> attr : aCadstarPart->Definition.AttributeValues )
{
ATTRIBUTE_VALUE attrVal = attr.second;
loadLibraryField( attrVal );
}
// Load all attributes in the Part itself.
for( std::pair<ATTRIBUTE_ID, ATTRIBUTE_VALUE> attr : aCadstarPart->AttributeValues )
{
ATTRIBUTE_VALUE attrVal = attr.second;
loadLibraryField( attrVal );
}
wxString fpNameInLibrary = generateLibName( footprintRefName, footprintAlternateName );
wxArrayString fpFilters;
fpFilters.Add( fpNameInLibrary );
aPart->SetFPFilters( fpFilters );
// Assume that the PCB footprint library name will be the same as the schematic filename
wxFileName schFilename( Filename );
wxString libName = schFilename.GetName();
aPart->GetFootprintField().SetText( libName + wxT( ":" ) + fpNameInLibrary );
}
if( aCadstarPart && aCadstarPart->Definition.HidePinNames )
{
aPart->SetShowPinNames( false );
@ -1187,7 +1377,7 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadLibrarySymbolShapeVertices(
}
void CADSTAR_SCH_ARCHIVE_LOADER::loadLibraryFieldAttribute(
void CADSTAR_SCH_ARCHIVE_LOADER::applyToLibraryFieldAttribute(
const ATTRIBUTE_LOCATION& aCadstarAttrLoc, wxPoint aSymbolOrigin, LIB_FIELD* aKiCadField )
{
aKiCadField->SetTextPos( getKiCadLibraryPoint( aCadstarAttrLoc.Position, aSymbolOrigin ) );
@ -1267,16 +1457,49 @@ SCH_COMPONENT* CADSTAR_SCH_ARCHIVE_LOADER::loadSchematicSymbol(
void CADSTAR_SCH_ARCHIVE_LOADER::loadSymbolFieldAttribute(
const ATTRIBUTE_LOCATION& aCadstarAttrLoc, const double& aComponentOrientationDeciDeg,
SCH_FIELD* aKiCadField )
bool aIsMirrored, SCH_FIELD* aKiCadField )
{
aKiCadField->SetPosition( getKiCadPoint( aCadstarAttrLoc.Position ) );
aKiCadField->SetTextAngle(
getAngleTenthDegree( aCadstarAttrLoc.OrientAngle ) - aComponentOrientationDeciDeg );
aKiCadField->SetTextAngle( getAngleTenthDegree( aCadstarAttrLoc.OrientAngle )
- aComponentOrientationDeciDeg );
aKiCadField->SetBold( false );
aKiCadField->SetVisible( true );
applyTextSettings( aCadstarAttrLoc.TextCodeID, aCadstarAttrLoc.Alignment,
aCadstarAttrLoc.Justification, aKiCadField );
ALIGNMENT fieldAlignment = aCadstarAttrLoc.Alignment;
JUSTIFICATION fieldJustification = aCadstarAttrLoc.Justification;
// KiCad mirrors the justification and alignment when the component is mirrored but CADSTAR
// specifies it post-mirroring
if( aIsMirrored )
{
switch( fieldAlignment )
{
// Change left to right:
case ALIGNMENT::NO_ALIGNMENT:
case ALIGNMENT::BOTTOMLEFT: fieldAlignment = ALIGNMENT::BOTTOMRIGHT; break;
case ALIGNMENT::CENTERLEFT: fieldAlignment = ALIGNMENT::CENTERRIGHT; break;
case ALIGNMENT::TOPLEFT: fieldAlignment = ALIGNMENT::TOPRIGHT; break;
//Change right to left:
case ALIGNMENT::BOTTOMRIGHT: fieldAlignment = ALIGNMENT::BOTTOMLEFT; break;
case ALIGNMENT::CENTERRIGHT: fieldAlignment = ALIGNMENT::CENTERLEFT; break;
case ALIGNMENT::TOPRIGHT: fieldAlignment = ALIGNMENT::TOPLEFT; break;
// Center alignment does not mirror:
case ALIGNMENT::BOTTOMCENTER:
case ALIGNMENT::CENTERCENTER:
case ALIGNMENT::TOPCENTER: break;
}
switch( fieldJustification )
{
case JUSTIFICATION::LEFT: fieldJustification = JUSTIFICATION::RIGHT; break;
case JUSTIFICATION::RIGHT: fieldJustification = JUSTIFICATION::LEFT; break;
case JUSTIFICATION::CENTER: break;
}
}
applyTextSettings( aCadstarAttrLoc.TextCodeID, fieldAlignment, fieldJustification,
aKiCadField );
}
@ -1751,20 +1974,15 @@ CADSTAR_SCH_ARCHIVE_LOADER::SYMDEF_ID CADSTAR_SCH_ARCHIVE_LOADER::getSymDefFromN
return SYMDEF_ID();
}
wxString CADSTAR_SCH_ARCHIVE_LOADER::generateSymDefName( const SYMDEF_ID& aSymdefID )
bool CADSTAR_SCH_ARCHIVE_LOADER::isAttributeVisible( const ATTRIBUTE_ID& aCadstarAttributeID )
{
wxCHECK( Library.SymbolDefinitions.find( aSymdefID ) != Library.SymbolDefinitions.end(),
wxEmptyString );
// Use CADSTAR visibility settings to determine if an attribute is visible
if( AttrColors.AttributeColors.find( aCadstarAttributeID ) != AttrColors.AttributeColors.end() )
{
return AttrColors.AttributeColors.at( aCadstarAttributeID ).IsVisible;
}
SYMDEF_SCM symbol = Library.SymbolDefinitions.at( aSymdefID );
wxString symbolName =
symbol.ReferenceName
+ ( ( symbol.Alternate.size() > 0 ) ? ( wxT( " (" ) + symbol.Alternate + wxT( ")" ) ) :
wxT( "" ) );
return symbolName;
return false; // If there is no visibility setting, assume not displayed
}

View File

@ -129,7 +129,7 @@ private:
void loadLibrarySymbolShapeVertices( const std::vector<VERTEX>& aCadstarVertices,
wxPoint aSymbolOrigin, LIB_PART* aPart, int aGateNumber );
void loadLibraryFieldAttribute( const ATTRIBUTE_LOCATION& aCadstarAttrLoc,
void applyToLibraryFieldAttribute( const ATTRIBUTE_LOCATION& aCadstarAttrLoc,
wxPoint aSymbolOrigin, LIB_FIELD* aKiCadField );
//Helper Functions for loading symbols in schematic
@ -137,7 +137,8 @@ private:
double& aComponentOrientationDeciDeg );
void loadSymbolFieldAttribute( const ATTRIBUTE_LOCATION& aCadstarAttrLoc,
const double& aComponentOrientationDeciDeg, SCH_FIELD* aKiCadField );
const double& aComponentOrientationDeciDeg, bool aIsMirrored,
SCH_FIELD* aKiCadField );
int getComponentOrientation( double aOrientAngleDeciDeg, double& aReturnedOrientationDeciDeg );
@ -173,8 +174,8 @@ private:
//Helper Functions for obtaining CADSTAR elements from the parsed structures
SYMDEF_ID getSymDefFromName( const wxString& aSymdefName, const wxString& aSymDefAlternate );
bool isAttributeVisible( const ATTRIBUTE_ID& aCadstarAttributeID );
wxString generateSymDefName( const SYMDEF_ID& aSymdefID );
int getLineThickness( const LINECODE_ID& aCadstarLineCodeID );
PLOT_DASH_TYPE getLineStyle( const LINECODE_ID& aCadstarLineCodeID );
PART getPart( const PART_ID& aCadstarPartID );
@ -191,7 +192,7 @@ private:
int getKiCadUnitNumberFromGate( const GATE_ID& aCadstarGateID );
LABEL_SPIN_STYLE getSpinStyle( const long long& aCadstarOrientation, bool aMirror );
LABEL_SPIN_STYLE getSpinStyleDeciDeg( const double& aOrientationDeciDeg );
SCH_FIELD* getFieldByName( SCH_COMPONENT* aComponent );
//General Graphical manipulation functions
std::pair<wxPoint, wxSize> getFigureExtentsKiCad( const FIGURE& aCadstarFigure );

View File

@ -82,9 +82,25 @@ void CADSTAR_SCH_ARCHIVE_PARSER::Parse()
}
else if( cNode->GetName() == wxT( "DISPLAY" ) )
{
// No design information here (no need to parse)
// Contains CADSTAR Display settings such as layer/element colours and visibility.
// In the future these settings could be converted to KiCad
// For now only interested in Attribute visibilities, in order to set field visibilities
// in the importer desing
XNODE* subNode = cNode->GetChildren();
for( ; subNode; subNode = subNode->GetNext() )
{
if( subNode->GetName() == wxT( "ATTRCOLORS" ) )
{
AttrColors.Parse( subNode, &mContext );
}
else
{
// No design information here
// Contains CADSTAR Display settings such as layer/element colours and visibility.
// In the future these settings could be converted to KiCad
}
}
}
else
{
@ -1171,7 +1187,7 @@ void CADSTAR_SCH_ARCHIVE_PARSER::NET_SCH::JUNCTION_SCH::Parse( XNODE* aNode, PAR
THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
}
}
}

View File

@ -445,6 +445,7 @@ public:
PARTS Parts;
SHEETS Sheets;
SCHEMATIC Schematic;
ATTRCOLORS AttrColors;
double KiCadUnitMultiplier; ///<Use this value to convert units in this CSA file to KiCad units