Implement dynamic assignment of component classes
This commit is contained in:
@@ -113,6 +113,7 @@ set( KICOMMON_SRCS
|
||||
settings/settings_manager.cpp
|
||||
|
||||
project/board_project_settings.cpp
|
||||
project/component_class_settings.cpp
|
||||
project/net_settings.cpp
|
||||
project/project_archiver.cpp
|
||||
project/project_file.cpp
|
||||
@@ -775,7 +776,10 @@ set( PCB_COMMON_SRCS
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/teardrop/teardrop_parameters.cpp #needed by board_design_settings.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/router/pns_meander.cpp #needed by board_design_settings.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/board.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/component_class_manager.cpp #needed by board.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/component_classes/component_class.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/component_classes/component_class_assignment_rule.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/component_classes/component_class_cache_proxy.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/component_classes/component_class_manager.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/board_item.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/pcb_dimension.cpp
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/pcb_shape.cpp
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
annular_width
|
||||
assertion
|
||||
assign_component_class
|
||||
board_edge
|
||||
buried_via
|
||||
clearance
|
||||
|
||||
@@ -0,0 +1,393 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <project/component_class_settings.h>
|
||||
#include <settings/parameters.h>
|
||||
|
||||
constexpr int componentClassSettingsSchemaVersion = 0;
|
||||
|
||||
|
||||
COMPONENT_CLASS_SETTINGS::COMPONENT_CLASS_SETTINGS( JSON_SETTINGS* aParent,
|
||||
const std::string& aPath ) :
|
||||
NESTED_SETTINGS( "component_class_settings", componentClassSettingsSchemaVersion, aParent,
|
||||
aPath, false ),
|
||||
m_enableSheetComponentClasses( false )
|
||||
{
|
||||
m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>(
|
||||
"sheet_component_classes",
|
||||
[&]() -> nlohmann::json
|
||||
{
|
||||
nlohmann::json ret = {};
|
||||
|
||||
ret["enabled"] = m_enableSheetComponentClasses;
|
||||
|
||||
return ret;
|
||||
},
|
||||
[&]( const nlohmann::json& aJson )
|
||||
{
|
||||
if( !aJson.is_object() )
|
||||
return;
|
||||
|
||||
if( !aJson.contains( "enabled" ) )
|
||||
return;
|
||||
|
||||
m_enableSheetComponentClasses = aJson["enabled"].get<bool>();
|
||||
},
|
||||
{} ) );
|
||||
|
||||
m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>(
|
||||
"assignments",
|
||||
[&]() -> nlohmann::json
|
||||
{
|
||||
nlohmann::json ret = nlohmann::json::array();
|
||||
|
||||
for( const COMPONENT_CLASS_ASSIGNMENT_DATA& assignment :
|
||||
m_componentClassAssignments )
|
||||
{
|
||||
ret.push_back( saveAssignment( assignment ) );
|
||||
}
|
||||
|
||||
return ret;
|
||||
},
|
||||
[&]( const nlohmann::json& aJson )
|
||||
{
|
||||
if( !aJson.is_array() )
|
||||
return;
|
||||
|
||||
ClearComponentClassAssignments();
|
||||
|
||||
for( const auto& assignmentJson : aJson )
|
||||
{
|
||||
COMPONENT_CLASS_ASSIGNMENT_DATA assignment = loadAssignment( assignmentJson );
|
||||
m_componentClassAssignments.push_back( assignment );
|
||||
}
|
||||
},
|
||||
{} ) );
|
||||
}
|
||||
|
||||
|
||||
COMPONENT_CLASS_SETTINGS::~COMPONENT_CLASS_SETTINGS()
|
||||
{
|
||||
// Release early before destroying members
|
||||
if( m_parent )
|
||||
{
|
||||
m_parent->ReleaseNestedSettings( this );
|
||||
m_parent = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nlohmann::json
|
||||
COMPONENT_CLASS_SETTINGS::saveAssignment( const COMPONENT_CLASS_ASSIGNMENT_DATA& aAssignment )
|
||||
{
|
||||
nlohmann::json ret;
|
||||
|
||||
const wxString matchOperator =
|
||||
aAssignment.GetConditionsOperator()
|
||||
== COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITIONS_OPERATOR::ALL
|
||||
? wxT( "ALL" )
|
||||
: wxT( "ANY" );
|
||||
|
||||
ret["component_class"] = aAssignment.GetComponentClass().ToUTF8();
|
||||
ret["conditions_operator"] = matchOperator.ToUTF8();
|
||||
|
||||
nlohmann::json conditionsJson;
|
||||
|
||||
for( const auto& [conditionType, conditionData] : aAssignment.GetConditions() )
|
||||
{
|
||||
nlohmann::json conditionJson;
|
||||
|
||||
if( !conditionData.first.empty() )
|
||||
conditionJson["primary"] = conditionData.first;
|
||||
|
||||
if( !conditionData.second.empty() )
|
||||
conditionJson["secondary"] = conditionData.second;
|
||||
|
||||
const wxString conditionName =
|
||||
COMPONENT_CLASS_ASSIGNMENT_DATA::GetConditionName( conditionType );
|
||||
conditionsJson[conditionName] = conditionJson;
|
||||
}
|
||||
|
||||
ret["conditions"] = conditionsJson;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
COMPONENT_CLASS_ASSIGNMENT_DATA
|
||||
COMPONENT_CLASS_SETTINGS::loadAssignment( const nlohmann::json& aJson )
|
||||
{
|
||||
COMPONENT_CLASS_ASSIGNMENT_DATA assignment;
|
||||
|
||||
assignment.SetComponentClass(
|
||||
wxString( aJson["component_class"].get<std::string>().c_str(), wxConvUTF8 ) );
|
||||
|
||||
const wxString matchOperator( aJson["conditions_operator"].get<std::string>().c_str(),
|
||||
wxConvUTF8 );
|
||||
|
||||
if( matchOperator == wxT( "ALL" ) )
|
||||
{
|
||||
assignment.SetConditionsOperation(
|
||||
COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITIONS_OPERATOR::ALL );
|
||||
}
|
||||
else
|
||||
{
|
||||
assignment.SetConditionsOperation(
|
||||
COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITIONS_OPERATOR::ANY );
|
||||
}
|
||||
|
||||
for( const auto& [conditionTypeStr, conditionData] : aJson["conditions"].items() )
|
||||
{
|
||||
wxString primary, secondary;
|
||||
COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE conditionType =
|
||||
COMPONENT_CLASS_ASSIGNMENT_DATA::GetConditionType( conditionTypeStr );
|
||||
|
||||
if( conditionData.contains( "primary" ) )
|
||||
primary = wxString( conditionData["primary"].get<std::string>().c_str(), wxConvUTF8 );
|
||||
|
||||
if( conditionData.contains( "secondary" ) )
|
||||
secondary =
|
||||
wxString( conditionData["secondary"].get<std::string>().c_str(), wxConvUTF8 );
|
||||
|
||||
assignment.SetCondition( conditionType, primary, secondary );
|
||||
}
|
||||
|
||||
return assignment;
|
||||
}
|
||||
|
||||
|
||||
bool COMPONENT_CLASS_SETTINGS::operator==( const COMPONENT_CLASS_SETTINGS& aOther ) const
|
||||
{
|
||||
// TODO: Implement this
|
||||
throw;
|
||||
//return true;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************************************
|
||||
*
|
||||
* COMPONENT_CLASS_ASSIGNMENT_DATA implementation
|
||||
*
|
||||
*************************************************************************************************/
|
||||
|
||||
wxString COMPONENT_CLASS_ASSIGNMENT_DATA::GetConditionName( const CONDITION_TYPE aCondition )
|
||||
{
|
||||
switch( aCondition )
|
||||
{
|
||||
case CONDITION_TYPE::REFERENCE: return wxT( "REFERENCE" );
|
||||
case CONDITION_TYPE::FOOTPRINT: return wxT( "FOOTPRINT" );
|
||||
case CONDITION_TYPE::SIDE: return wxT( "SIDE" );
|
||||
case CONDITION_TYPE::ROTATION: return wxT( "ROTATION" );
|
||||
case CONDITION_TYPE::FOOTPRINT_FIELD: return wxT( "FOOTPRINT_FIELD" );
|
||||
case CONDITION_TYPE::CUSTOM: return wxT( "CUSTOM" );
|
||||
case CONDITION_TYPE::SHEET_NAME: return wxT( "SHEET_NAME" );
|
||||
}
|
||||
|
||||
wxASSERT_MSG( false, "Invalid condition type" );
|
||||
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
|
||||
COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE
|
||||
COMPONENT_CLASS_ASSIGNMENT_DATA::GetConditionType( const wxString& aCondition )
|
||||
{
|
||||
if( aCondition == wxT( "REFERENCE" ) )
|
||||
return CONDITION_TYPE::REFERENCE;
|
||||
if( aCondition == wxT( "FOOTPRINT" ) )
|
||||
return CONDITION_TYPE::FOOTPRINT;
|
||||
if( aCondition == wxT( "SIDE" ) )
|
||||
return CONDITION_TYPE::SIDE;
|
||||
if( aCondition == wxT( "ROTATION" ) )
|
||||
return CONDITION_TYPE::ROTATION;
|
||||
if( aCondition == wxT( "FOOTPRINT_FIELD" ) )
|
||||
return CONDITION_TYPE::FOOTPRINT_FIELD;
|
||||
if( aCondition == wxT( "CUSTOM" ) )
|
||||
return CONDITION_TYPE::CUSTOM;
|
||||
if( aCondition == wxT( "SHEET_NAME" ) )
|
||||
return CONDITION_TYPE::SHEET_NAME;
|
||||
|
||||
wxASSERT_MSG( false, "Invalid condition type" );
|
||||
|
||||
return CONDITION_TYPE::REFERENCE;
|
||||
}
|
||||
|
||||
|
||||
wxString COMPONENT_CLASS_ASSIGNMENT_DATA::GetAssignmentInDRCLanguage() const
|
||||
{
|
||||
if( m_componentClass.empty() )
|
||||
return wxEmptyString;
|
||||
|
||||
if( m_conditions.empty() )
|
||||
{
|
||||
// A condition which always applies the netclass
|
||||
return wxString::Format( wxT( "(version 1) (assign_component_class \"%s\")" ),
|
||||
m_componentClass );
|
||||
}
|
||||
|
||||
// Lambda to format a comma-separated list of references in to a DRC expression
|
||||
auto getRefExpr = []( wxString aRefs ) -> wxString
|
||||
{
|
||||
aRefs.Trim( true ).Trim( false );
|
||||
|
||||
wxArrayString refs = wxSplit( aRefs, ',' );
|
||||
|
||||
if( refs.empty() )
|
||||
return wxEmptyString;
|
||||
|
||||
std::ranges::transform( refs, refs.begin(),
|
||||
[]( const wxString& aRef )
|
||||
{
|
||||
return wxString::Format( wxT( "A.Reference == '%s'" ), aRef );
|
||||
} );
|
||||
|
||||
wxString refsExpr = refs[0];
|
||||
|
||||
if( refs.size() > 1 )
|
||||
{
|
||||
for( auto itr = refs.begin() + 1; itr != refs.end(); ++itr )
|
||||
refsExpr = refsExpr + wxT( " || " ) + *itr;
|
||||
}
|
||||
|
||||
return wxString::Format( wxT( "( %s )" ), refsExpr );
|
||||
};
|
||||
|
||||
// Lambda to format a footprint match DRC expression
|
||||
auto getFootprintExpr = []( wxString aFootprint ) -> wxString
|
||||
{
|
||||
aFootprint.Trim( true ).Trim( false );
|
||||
|
||||
if( aFootprint.empty() )
|
||||
return wxEmptyString;
|
||||
|
||||
return wxString::Format( wxT( "( A.Library_Link == '%s' )" ), aFootprint );
|
||||
};
|
||||
|
||||
// Lambda to format a layer side DRC expression
|
||||
auto getSideExpr = []( const wxString& aSide ) -> wxString
|
||||
{
|
||||
if( aSide == wxT( "Any" ) )
|
||||
return wxEmptyString;
|
||||
|
||||
return wxString::Format( wxT( "( A.Layer == '%s' )" ),
|
||||
aSide == wxT( "Front" ) ? wxT( "F.Cu" ) : wxT( "B.Cu" ) );
|
||||
};
|
||||
|
||||
// Lambda to format a rotation DRC expression
|
||||
auto getRotationExpr = []( wxString aRotation ) -> wxString
|
||||
{
|
||||
aRotation.Trim( true ).Trim( false );
|
||||
|
||||
int dummy;
|
||||
|
||||
if( aRotation.empty() || aRotation == wxT( "Any" ) || !aRotation.ToInt( &dummy ) )
|
||||
return wxEmptyString;
|
||||
|
||||
return wxString::Format( wxT( "( A.Orientation == %s deg )" ), aRotation );
|
||||
};
|
||||
|
||||
|
||||
// Lambda to format a footprint field DRC expression
|
||||
auto getFootprintFieldExpr = []( wxString aFieldName, wxString aFieldMatch ) -> wxString
|
||||
{
|
||||
aFieldName.Trim( true ).Trim( false );
|
||||
aFieldMatch.Trim( true ).Trim( false );
|
||||
|
||||
if( aFieldName.empty() || aFieldMatch.empty() )
|
||||
return wxEmptyString;
|
||||
|
||||
return wxString::Format( wxT( "( A.getField('%s') == '%s' )" ), aFieldName, aFieldMatch );
|
||||
};
|
||||
|
||||
// Lambda to format a custom DRC expression
|
||||
auto getCustomFieldExpr = []( wxString aExpr ) -> wxString
|
||||
{
|
||||
aExpr.Trim( true ).Trim( false );
|
||||
|
||||
if( aExpr.empty() )
|
||||
return wxEmptyString;
|
||||
|
||||
return wxString::Format( wxT( "( %s )" ), aExpr );
|
||||
};
|
||||
|
||||
// Lambda to format a sheet name expression
|
||||
auto getSheetNameExpr = []( wxString aSheetName ) -> wxString
|
||||
{
|
||||
aSheetName.Trim( true ).Trim( false );
|
||||
|
||||
if( aSheetName.empty() )
|
||||
return wxEmptyString;
|
||||
|
||||
return wxString::Format( wxT( "( A.memberOfSheet('%s') )" ), aSheetName );
|
||||
};
|
||||
|
||||
std::vector<wxString> conditionsExprs;
|
||||
|
||||
for( auto& [conditionType, conditionData] : m_conditions )
|
||||
{
|
||||
wxString conditionExpr;
|
||||
|
||||
switch( conditionType )
|
||||
{
|
||||
case CONDITION_TYPE::REFERENCE: conditionExpr = getRefExpr( conditionData.first ); break;
|
||||
case CONDITION_TYPE::FOOTPRINT:
|
||||
conditionExpr = getFootprintExpr( conditionData.first );
|
||||
break;
|
||||
case CONDITION_TYPE::SIDE: conditionExpr = getSideExpr( conditionData.first ); break;
|
||||
case CONDITION_TYPE::ROTATION:
|
||||
conditionExpr = getRotationExpr( conditionData.first );
|
||||
break;
|
||||
case CONDITION_TYPE::FOOTPRINT_FIELD:
|
||||
conditionExpr = getFootprintFieldExpr( conditionData.first, conditionData.second );
|
||||
break;
|
||||
case CONDITION_TYPE::CUSTOM:
|
||||
conditionExpr = getCustomFieldExpr( conditionData.first );
|
||||
break;
|
||||
case CONDITION_TYPE::SHEET_NAME:
|
||||
conditionExpr = getSheetNameExpr( conditionData.first );
|
||||
break;
|
||||
}
|
||||
|
||||
if( !conditionExpr.empty() )
|
||||
conditionsExprs.push_back( conditionExpr );
|
||||
}
|
||||
|
||||
if( conditionsExprs.empty() )
|
||||
return wxString::Format( wxT( "(version 1) (assign_component_class \"%s\")" ),
|
||||
m_componentClass );
|
||||
|
||||
wxString allConditionsExpr = conditionsExprs[0];
|
||||
|
||||
if( conditionsExprs.size() > 1 )
|
||||
{
|
||||
wxString operatorExpr =
|
||||
m_conditionsOperator == CONDITIONS_OPERATOR::ALL ? wxT( " && " ) : wxT( " || " );
|
||||
|
||||
for( auto itr = conditionsExprs.begin() + 1; itr != conditionsExprs.end(); ++itr )
|
||||
{
|
||||
allConditionsExpr = allConditionsExpr + operatorExpr + *itr;
|
||||
}
|
||||
}
|
||||
|
||||
return wxString::Format(
|
||||
wxT( "(version 1) (assign_component_class \"%s\" (condition \"%s\" ) )" ),
|
||||
m_componentClass, allConditionsExpr );
|
||||
}
|
||||
@@ -20,10 +20,10 @@
|
||||
*/
|
||||
|
||||
#include <project.h>
|
||||
#include <project/component_class_settings.h>
|
||||
#include <project/net_settings.h>
|
||||
#include <settings/json_settings_internals.h>
|
||||
#include <project/project_file.h>
|
||||
#include <settings/common_settings.h>
|
||||
#include <settings/parameters.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
#include <wx/config.h>
|
||||
@@ -36,13 +36,8 @@ const int projectFileSchemaVersion = 3;
|
||||
|
||||
PROJECT_FILE::PROJECT_FILE( const wxString& aFullPath ) :
|
||||
JSON_SETTINGS( aFullPath, SETTINGS_LOC::PROJECT, projectFileSchemaVersion ),
|
||||
m_ErcSettings( nullptr ),
|
||||
m_SchematicSettings( nullptr ),
|
||||
m_BoardSettings(),
|
||||
m_sheets(),
|
||||
m_boards(),
|
||||
m_project( nullptr ),
|
||||
m_wasMigrated( false )
|
||||
m_ErcSettings( nullptr ), m_SchematicSettings( nullptr ), m_BoardSettings(),
|
||||
m_project( nullptr ), m_wasMigrated( false )
|
||||
{
|
||||
// Keep old files around
|
||||
m_deleteLegacyAfterMigration = false;
|
||||
@@ -119,6 +114,9 @@ PROJECT_FILE::PROJECT_FILE( const wxString& aFullPath ) :
|
||||
|
||||
m_NetSettings = std::make_shared<NET_SETTINGS>( this, "net_settings" );
|
||||
|
||||
m_ComponentClassSettings =
|
||||
std::make_shared<COMPONENT_CLASS_SETTINGS>( this, "component_class_settings" );
|
||||
|
||||
m_params.emplace_back( new PARAM_LAYER_PRESET( "board.layer_presets", &m_LayerPresets ) );
|
||||
|
||||
m_params.emplace_back( new PARAM_VIEWPORT( "board.viewports", &m_Viewports ) );
|
||||
|
||||
@@ -0,0 +1,434 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PANEL_ASSIGN_COMPONENT_CLASSES_H
|
||||
#define PANEL_ASSIGN_COMPONENT_CLASSES_H
|
||||
|
||||
|
||||
#include <panel_assign_component_classes_base.h>
|
||||
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <dialog_shim.h>
|
||||
#include <pcb_edit_frame.h>
|
||||
#include <project/component_class_settings.h>
|
||||
|
||||
|
||||
/**************************************************************************************************
|
||||
*
|
||||
* PANEL_ASSIGN_COMPONENT_CLASSES
|
||||
*
|
||||
*************************************************************************************************/
|
||||
|
||||
/**
|
||||
* Top-level panel for dynamic component class assignment configuration. Nests a
|
||||
* PANEL_COMPONENT_CLASS_ASSIGNMENT panel for each set of component class assignment conditions
|
||||
*/
|
||||
class PANEL_COMPONENT_CLASS_ASSIGNMENT;
|
||||
|
||||
class PANEL_ASSIGN_COMPONENT_CLASSES : public PANEL_ASSIGN_COMPONENT_CLASSES_BASE
|
||||
{
|
||||
public:
|
||||
PANEL_ASSIGN_COMPONENT_CLASSES( wxWindow* aParentWindow, PCB_EDIT_FRAME* aFrame,
|
||||
std::shared_ptr<COMPONENT_CLASS_SETTINGS> aSettings,
|
||||
DIALOG_SHIM* aDlg );
|
||||
|
||||
~PANEL_ASSIGN_COMPONENT_CLASSES() override;
|
||||
|
||||
/// Loads current component class assignments from the board settings
|
||||
bool TransferDataToWindow() override;
|
||||
|
||||
/// Saves the component class assignments to the board settings
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
/// Loads component class assignments from the given settings object
|
||||
void ImportSettingsFrom( const std::shared_ptr<COMPONENT_CLASS_SETTINGS>& aOtherSettings );
|
||||
|
||||
/// Adds a new component class assignment rule
|
||||
void OnAddAssignmentClick( wxCommandEvent& event ) override;
|
||||
|
||||
/// Removes a given component class assignment rule
|
||||
void RemoveAssignment( PANEL_COMPONENT_CLASS_ASSIGNMENT* aPanel );
|
||||
|
||||
/// Returns references for all currently selected footprints
|
||||
const std::vector<wxString>& GetSelectionRefs() const { return m_selectionRefs; }
|
||||
|
||||
/// Returns names of all fields present in footprints
|
||||
const std::vector<wxString>& GetFieldNames() const { return m_fieldNames; }
|
||||
|
||||
/// Returns names of all sheets present in footprints
|
||||
const std::vector<wxString>& GetSheetNames() const { return m_sheetNames; }
|
||||
|
||||
/// Gets the active edit frame
|
||||
PCB_EDIT_FRAME* GetFrame() const { return m_frame; }
|
||||
|
||||
/// Validates that all assignment rules can compile successfully
|
||||
bool Validate() override;
|
||||
|
||||
private:
|
||||
/// Adds a new component class assignment rule
|
||||
PANEL_COMPONENT_CLASS_ASSIGNMENT* addAssignment();
|
||||
|
||||
/// Scrolls the panel to specified assignment rule
|
||||
void scrollToAssignment( const PANEL_COMPONENT_CLASS_ASSIGNMENT* aAssignment ) const;
|
||||
|
||||
/// The parent dialog
|
||||
DIALOG_SHIM* m_dlg;
|
||||
|
||||
/// The active edit frame
|
||||
PCB_EDIT_FRAME* m_frame;
|
||||
|
||||
/// Vector of all currently displayed assignment rules
|
||||
std::vector<PANEL_COMPONENT_CLASS_ASSIGNMENT*> m_assignments;
|
||||
|
||||
/// The active settings object
|
||||
std::shared_ptr<COMPONENT_CLASS_SETTINGS> m_componentClassSettings;
|
||||
|
||||
/// All currently selected footprint references
|
||||
std::vector<wxString> m_selectionRefs;
|
||||
|
||||
/// All footprint fields names present on the board
|
||||
std::vector<wxString> m_fieldNames;
|
||||
|
||||
/// All sheet names present on the board
|
||||
std::vector<wxString> m_sheetNames;
|
||||
|
||||
/// The list of all currently present component class assignments
|
||||
wxBoxSizer* m_assignmentsList;
|
||||
};
|
||||
|
||||
|
||||
/**************************************************************************************************
|
||||
*
|
||||
* CONDITION_DATA
|
||||
*
|
||||
*************************************************************************************************/
|
||||
|
||||
/**
|
||||
* Class used to provide a unified interface from condition panels
|
||||
* Handles determining the type of condition in use, and getting and settings the field data
|
||||
*/
|
||||
class CONDITION_DATA
|
||||
{
|
||||
public:
|
||||
CONDITION_DATA( const COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE aCondition,
|
||||
wxTextEntry* aPrimary, wxTextEntry* aSecondary = nullptr ) :
|
||||
m_conditionType( aCondition ), m_primaryCtrl( aPrimary ), m_secondaryCtrl( aSecondary )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~CONDITION_DATA() {};
|
||||
|
||||
/// Gets the type of condition (e.g. Reference, Side) this data represents
|
||||
virtual COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE GetConditionType() const
|
||||
{
|
||||
return m_conditionType;
|
||||
}
|
||||
|
||||
/// Gets the primary data member for the condition (e.g. Reference, Side)
|
||||
virtual wxString GetPrimaryField() const;
|
||||
|
||||
/// Sets the primary data member for the condition (e.g. Reference, Side)
|
||||
virtual void SetPrimaryField( const wxString& aVal );
|
||||
|
||||
/// Gets the primary data member for the condition (e.g. FOOTPRITNT field value)
|
||||
virtual wxString GetSecondaryField() const;
|
||||
|
||||
/// Sets the primary data member for the condition (e.g. FOOTPRITNT field
|
||||
/// value)
|
||||
virtual void SetSecondaryField( const wxString& aVal );
|
||||
|
||||
private:
|
||||
/// The type of condition being referenced
|
||||
COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE m_conditionType;
|
||||
|
||||
/// The primary data field in the condition panel
|
||||
wxTextEntry* m_primaryCtrl;
|
||||
|
||||
/// The Secondary data field in the condition panel
|
||||
wxTextEntry* m_secondaryCtrl;
|
||||
};
|
||||
|
||||
|
||||
/**************************************************************************************************
|
||||
*
|
||||
* PANEL_COMPONENT_CLASS_ASSIGNMENT
|
||||
*
|
||||
*************************************************************************************************/
|
||||
|
||||
/**
|
||||
* Panel which configures a set of conditions for a component class assignment rule
|
||||
*/
|
||||
class PANEL_COMPONENT_CLASS_ASSIGNMENT : public PANEL_COMPONENT_CLASS_ASSIGNMENT_BASE
|
||||
{
|
||||
public:
|
||||
/// IDs for match type popup menu
|
||||
enum ADD_MATCH_POPUP
|
||||
{
|
||||
ID_REFERENCE = wxID_HIGHEST + 1,
|
||||
ID_FOOTPRINT,
|
||||
ID_SIDE,
|
||||
ID_ROTATION,
|
||||
ID_FOOTPRINT_FIELD,
|
||||
ID_SHEET_NAME,
|
||||
ID_CUSTOM
|
||||
};
|
||||
|
||||
PANEL_COMPONENT_CLASS_ASSIGNMENT( wxWindow* aParent,
|
||||
PANEL_ASSIGN_COMPONENT_CLASSES* aPanelParent,
|
||||
DIALOG_SHIM* aDlg );
|
||||
~PANEL_COMPONENT_CLASS_ASSIGNMENT();
|
||||
|
||||
/// Deletes this component class assignment rule
|
||||
void OnDeleteAssignmentClick( wxCommandEvent& event ) override;
|
||||
|
||||
/// Adds a match condition to this component class assignment rule
|
||||
void OnAddConditionClick( wxCommandEvent& event ) override;
|
||||
|
||||
/// Highlights footprints matching this set of conditions
|
||||
void OnHighlightItemsClick( wxCommandEvent& event ) override;
|
||||
|
||||
/// Adds a condition to this component class assignment rule
|
||||
CONDITION_DATA* AddCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE aCondition );
|
||||
|
||||
/// Removes a given condition from this component class assignment rule (note: called from the child
|
||||
/// condition panel)
|
||||
void RemoveCondition( wxPanel* aMatch );
|
||||
|
||||
const std::vector<CONDITION_DATA*>& GetConditions() const { return m_matches; }
|
||||
|
||||
/// Sets the resulting component class for this assignment
|
||||
void SetComponentClass( const wxString& aComponentClass ) const;
|
||||
|
||||
/// Gets the resulting component class for this assignment
|
||||
const wxString GetComponentClass() const;
|
||||
|
||||
/// Sets the boolean operator applied to all assignment conditions
|
||||
void
|
||||
SetConditionsOperator( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITIONS_OPERATOR aCondition ) const;
|
||||
|
||||
/// Gets the boolean operator applied to all assignment conditions
|
||||
COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITIONS_OPERATOR GetConditionsOperator() const;
|
||||
|
||||
/// Converts the UI representation in to the internal assignment data representation
|
||||
COMPONENT_CLASS_ASSIGNMENT_DATA GenerateAssignmentData() const;
|
||||
|
||||
protected:
|
||||
/// Handles add match condition popup menu selections
|
||||
void onMenu( wxCommandEvent& aEvent );
|
||||
|
||||
/// The top-level configuration panel which owns this assignment rule
|
||||
PANEL_ASSIGN_COMPONENT_CLASSES* m_parentPanel;
|
||||
|
||||
/// The sizer containing match condition panels
|
||||
wxStaticBoxSizer* m_matchesList;
|
||||
|
||||
/// Set containing all currently configured match condition types
|
||||
std::unordered_set<COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE> m_conditionTypes;
|
||||
|
||||
/// The parent configuration dialog
|
||||
DIALOG_SHIM* m_dlg;
|
||||
|
||||
/// All match conditions for this component class assignment rule
|
||||
std::vector<CONDITION_DATA*> m_matches;
|
||||
};
|
||||
|
||||
|
||||
/**************************************************************************************************
|
||||
*
|
||||
* PANEL_COMPONENT_CLASS_CONDITION_REFERENCE
|
||||
*
|
||||
*************************************************************************************************/
|
||||
|
||||
/**
|
||||
* Configures matching based on footprint reference
|
||||
*/
|
||||
class PANEL_COMPONENT_CLASS_CONDITION_REFERENCE
|
||||
: public PANEL_COMPONENT_CLASS_CONDITION_REFERENCE_BASE,
|
||||
public CONDITION_DATA
|
||||
{
|
||||
public:
|
||||
/// IDs for match type popup menu
|
||||
enum IMPORT_POPUP_IDS
|
||||
{
|
||||
ID_IMPORT_REFS = wxID_HIGHEST + 1
|
||||
};
|
||||
|
||||
explicit PANEL_COMPONENT_CLASS_CONDITION_REFERENCE( wxWindow* aParent );
|
||||
|
||||
void OnDeleteConditionClick( wxCommandEvent& event ) override;
|
||||
|
||||
void OnImportRefsClick( wxCommandEvent& event ) override;
|
||||
void SetSelectionRefs( const std::vector<wxString>& aRefs ) { m_selectionRefs = aRefs; }
|
||||
|
||||
protected:
|
||||
/// Handles import references popup menu selections
|
||||
void onMenu( wxCommandEvent& aEvent );
|
||||
|
||||
PANEL_COMPONENT_CLASS_ASSIGNMENT* m_panelParent;
|
||||
std::vector<wxString> m_selectionRefs;
|
||||
};
|
||||
|
||||
|
||||
/**************************************************************************************************
|
||||
*
|
||||
* PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT
|
||||
*
|
||||
*************************************************************************************************/
|
||||
|
||||
/**
|
||||
* Configures matching based on footprint library identifier
|
||||
*/
|
||||
class PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT
|
||||
: public PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT_BASE,
|
||||
public CONDITION_DATA
|
||||
{
|
||||
public:
|
||||
explicit PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT( wxWindow* aParent, DIALOG_SHIM* aDlg );
|
||||
|
||||
void OnDeleteConditionClick( wxCommandEvent& event ) override;
|
||||
void OnShowLibraryClick( wxCommandEvent& event ) override;
|
||||
|
||||
protected:
|
||||
PANEL_COMPONENT_CLASS_ASSIGNMENT* m_panelParent;
|
||||
DIALOG_SHIM* m_dlg;
|
||||
};
|
||||
|
||||
|
||||
/**************************************************************************************************
|
||||
*
|
||||
* PANEL_COMPONENT_CLASS_CONDITION_SIDE
|
||||
*
|
||||
*************************************************************************************************/
|
||||
|
||||
/**
|
||||
* Configures matching based on which side of the board a footprint is on
|
||||
*/
|
||||
class PANEL_COMPONENT_CLASS_CONDITION_SIDE : public PANEL_COMPONENT_CLASS_CONDITION_SIDE_BASE,
|
||||
public CONDITION_DATA
|
||||
{
|
||||
public:
|
||||
explicit PANEL_COMPONENT_CLASS_CONDITION_SIDE( wxWindow* aParent );
|
||||
|
||||
void OnDeleteConditionClick( wxCommandEvent& event ) override;
|
||||
|
||||
protected:
|
||||
PANEL_COMPONENT_CLASS_ASSIGNMENT* m_panelParent;
|
||||
};
|
||||
|
||||
|
||||
/**************************************************************************************************
|
||||
*
|
||||
* PANEL_COMPONENT_CLASS_CONDITION_ROTATION
|
||||
*
|
||||
*************************************************************************************************/
|
||||
|
||||
/**
|
||||
* Configures matching based on footprint rotation
|
||||
*/
|
||||
class PANEL_COMPONENT_CLASS_CONDITION_ROTATION
|
||||
: public PANEL_COMPONENT_CLASS_CONDITION_ROTATION_BASE,
|
||||
public CONDITION_DATA
|
||||
{
|
||||
public:
|
||||
explicit PANEL_COMPONENT_CLASS_CONDITION_ROTATION( wxWindow* aParent );
|
||||
|
||||
void OnDeleteConditionClick( wxCommandEvent& event ) override;
|
||||
|
||||
protected:
|
||||
PANEL_COMPONENT_CLASS_ASSIGNMENT* m_panelParent;
|
||||
};
|
||||
|
||||
|
||||
/**************************************************************************************************
|
||||
*
|
||||
* PANEL_COMPONENT_CLASS_CONDITION_FIELD
|
||||
*
|
||||
*************************************************************************************************/
|
||||
|
||||
/**
|
||||
* Configures matching based on footprint field contents
|
||||
*/
|
||||
class PANEL_COMPONENT_CLASS_CONDITION_FIELD : public PANEL_COMPONENT_CLASS_CONDITION_FIELD_BASE,
|
||||
public CONDITION_DATA
|
||||
{
|
||||
public:
|
||||
explicit PANEL_COMPONENT_CLASS_CONDITION_FIELD( wxWindow* aParent );
|
||||
|
||||
void OnDeleteConditionClick( wxCommandEvent& event ) override;
|
||||
|
||||
void SetFieldsList( const std::vector<wxString>& aFields );
|
||||
|
||||
protected:
|
||||
PANEL_COMPONENT_CLASS_ASSIGNMENT* m_panelParent;
|
||||
};
|
||||
|
||||
|
||||
/**************************************************************************************************
|
||||
*
|
||||
* PANEL_COMPONENT_CLASS_CONDITION_CUSTOM
|
||||
*
|
||||
*************************************************************************************************/
|
||||
|
||||
/**
|
||||
* Configures matching based on a custom DRC expression
|
||||
*/
|
||||
class PANEL_COMPONENT_CLASS_CONDITION_CUSTOM : public PANEL_COMPONENT_CLASS_CONDITION_CUSTOM_BASE,
|
||||
public CONDITION_DATA
|
||||
{
|
||||
public:
|
||||
explicit PANEL_COMPONENT_CLASS_CONDITION_CUSTOM( wxWindow* aParent );
|
||||
|
||||
void OnDeleteConditionClick( wxCommandEvent& event ) override;
|
||||
|
||||
protected:
|
||||
PANEL_COMPONENT_CLASS_ASSIGNMENT* m_panelParent;
|
||||
};
|
||||
|
||||
|
||||
/**************************************************************************************************
|
||||
*
|
||||
* PANEL_COMPONENT_CLASS_SHEET
|
||||
*
|
||||
*************************************************************************************************/
|
||||
|
||||
/**
|
||||
* Configures matching based on a custom DRC expression
|
||||
*/
|
||||
class PANEL_COMPONENT_CLASS_CONDITION_SHEET : public PANEL_COMPONENT_CLASS_CONDITION_SHEET_BASE,
|
||||
public CONDITION_DATA
|
||||
{
|
||||
public:
|
||||
explicit PANEL_COMPONENT_CLASS_CONDITION_SHEET( wxWindow* aParent );
|
||||
|
||||
void OnDeleteConditionClick( wxCommandEvent& event ) override;
|
||||
|
||||
void SetSheetsList( const std::vector<wxString>& aSheets );
|
||||
|
||||
protected:
|
||||
PANEL_COMPONENT_CLASS_ASSIGNMENT* m_panelParent;
|
||||
};
|
||||
|
||||
#endif //PANEL_ASSIGN_COMPONENT_CLASSES_H
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PANEL_GENERATE_COMPONENT_CLASSES_H
|
||||
#define PANEL_GENERATE_COMPONENT_CLASSES_H
|
||||
|
||||
#include <panel_generate_component_classes_base.h>
|
||||
|
||||
#include <eda_draw_frame.h>
|
||||
#include <project/component_class_settings.h>
|
||||
#include <vector>
|
||||
|
||||
|
||||
class PANEL_GENERATE_COMPONENT_CLASSES : public PANEL_GENERATE_COMPONENT_CLASSES_BASE
|
||||
{
|
||||
public:
|
||||
PANEL_GENERATE_COMPONENT_CLASSES( wxWindow* aParentWindow, EDA_DRAW_FRAME* aFrame,
|
||||
std::shared_ptr<COMPONENT_CLASS_SETTINGS> aSettings,
|
||||
std::vector<wxString>& aSelectionRefs );
|
||||
|
||||
bool TransferDataToWindow() override;
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
bool Validate() override;
|
||||
|
||||
//void ImportSettingsFrom( const std::shared_ptr<NET_SETTINGS>& aNetSettings );
|
||||
|
||||
protected:
|
||||
EDA_DRAW_FRAME* m_frame;
|
||||
std::shared_ptr<COMPONENT_CLASS_SETTINGS> m_componentClassSettings;
|
||||
|
||||
std::vector<wxString> m_selectionRefs;
|
||||
};
|
||||
|
||||
#endif //PANEL_GENERATE_COMPONENT_CLASSES
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PROJECT_COMPONENT_CLASS_SETTINGS_H
|
||||
#define PROJECT_COMPONENT_CLASS_SETTINGS_H
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <settings/nested_settings.h>
|
||||
|
||||
|
||||
class KICOMMON_API COMPONENT_CLASS_ASSIGNMENT_DATA
|
||||
{
|
||||
public:
|
||||
/// A condition match type
|
||||
enum class CONDITION_TYPE
|
||||
{
|
||||
REFERENCE,
|
||||
FOOTPRINT,
|
||||
SIDE,
|
||||
ROTATION,
|
||||
FOOTPRINT_FIELD,
|
||||
CUSTOM,
|
||||
SHEET_NAME
|
||||
};
|
||||
|
||||
/// Whether conditions are applied with OR or AND logic
|
||||
enum class CONDITIONS_OPERATOR
|
||||
{
|
||||
ALL,
|
||||
ANY
|
||||
};
|
||||
|
||||
/// Sets the given condition type with the assocated match data
|
||||
void SetCondition( const CONDITION_TYPE aCondition, const wxString& aPrimaryData,
|
||||
const wxString& aSecondaryData )
|
||||
{
|
||||
m_conditions[aCondition] = { aPrimaryData, aSecondaryData };
|
||||
}
|
||||
|
||||
/// Gets all conditions
|
||||
const std::unordered_map<CONDITION_TYPE, std::pair<wxString, wxString>>& GetConditions() const
|
||||
{
|
||||
return m_conditions;
|
||||
}
|
||||
|
||||
/// Sets the resulting component class for matching footprints
|
||||
void SetComponentClass( const wxString& aComponentClass )
|
||||
{
|
||||
m_componentClass = aComponentClass;
|
||||
}
|
||||
|
||||
/// Gets the resulting component class for matching footprints
|
||||
const wxString& GetComponentClass() const { return m_componentClass; }
|
||||
|
||||
/// Sets the boolean operation in use for all conditions
|
||||
void SetConditionsOperation( const CONDITIONS_OPERATOR aOperator )
|
||||
{
|
||||
m_conditionsOperator = aOperator;
|
||||
}
|
||||
|
||||
/// Gets the boolean operation in use for all conditions
|
||||
CONDITIONS_OPERATOR GetConditionsOperator() const { return m_conditionsOperator; }
|
||||
|
||||
/// Maps a CONDITION_TYPE to a descriptive string
|
||||
static wxString GetConditionName( const CONDITION_TYPE aCondition );
|
||||
|
||||
/// Maps a descriptive string to a CONDITION_TYPE
|
||||
static CONDITION_TYPE GetConditionType( const wxString& aCondition );
|
||||
|
||||
/// Returns the DRC rules language for this component class assignment
|
||||
wxString GetAssignmentInDRCLanguage() const;
|
||||
|
||||
protected:
|
||||
/// The name of the component class for this assignment rule
|
||||
wxString m_componentClass;
|
||||
|
||||
/// Map of condition types to primary and secondary data fields for the condition
|
||||
std::unordered_map<CONDITION_TYPE, std::pair<wxString, wxString>> m_conditions;
|
||||
|
||||
/// Whether conditions are applied with AND or OR logic
|
||||
/// Defaults to ALL
|
||||
CONDITIONS_OPERATOR m_conditionsOperator{ CONDITIONS_OPERATOR::ALL };
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* COMPONENT_CLASS_SETTINGS stores data for component classes, including rules for automatic
|
||||
* generation of component classes.
|
||||
*/
|
||||
class KICOMMON_API COMPONENT_CLASS_SETTINGS : public NESTED_SETTINGS
|
||||
{
|
||||
public:
|
||||
COMPONENT_CLASS_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath );
|
||||
|
||||
virtual ~COMPONENT_CLASS_SETTINGS();
|
||||
|
||||
/// Sets whether component classes should be generated for components in hierarchical sheets
|
||||
void SetEnableSheetComponentClasses( bool aEnabled )
|
||||
{
|
||||
m_enableSheetComponentClasses = aEnabled;
|
||||
}
|
||||
|
||||
/// Gets whether component classes should be generated for components in hierarchical sheets
|
||||
bool GetEnableSheetComponentClasses() const { return m_enableSheetComponentClasses; }
|
||||
|
||||
/// Clear all dynamic component class assignments
|
||||
void ClearComponentClassAssignments() { m_componentClassAssignments.clear(); }
|
||||
|
||||
/// Gets all dynamic component class assignments
|
||||
const std::vector<COMPONENT_CLASS_ASSIGNMENT_DATA>& GetComponentClassAssignments() const
|
||||
{
|
||||
return m_componentClassAssignments;
|
||||
}
|
||||
|
||||
// Adds a dynamic component class assignment
|
||||
void AddComponentClassAssignment( const COMPONENT_CLASS_ASSIGNMENT_DATA& aAssignment )
|
||||
{
|
||||
m_componentClassAssignments.push_back( aAssignment );
|
||||
}
|
||||
|
||||
bool operator==( const COMPONENT_CLASS_SETTINGS& aOther ) const;
|
||||
|
||||
bool operator!=( const COMPONENT_CLASS_SETTINGS& aOther ) const
|
||||
{
|
||||
return !operator==( aOther );
|
||||
}
|
||||
|
||||
private:
|
||||
/// Toggle generation of component classes for hierarchical sheets
|
||||
bool m_enableSheetComponentClasses;
|
||||
|
||||
/// All dynamic component class assignment rules
|
||||
std::vector<COMPONENT_CLASS_ASSIGNMENT_DATA> m_componentClassAssignments;
|
||||
|
||||
/// Saves a dynamic component class assignment to JSON
|
||||
static nlohmann::json saveAssignment( const COMPONENT_CLASS_ASSIGNMENT_DATA& aAssignment );
|
||||
|
||||
/// Loads a dynamic component class assignment from JSON
|
||||
static COMPONENT_CLASS_ASSIGNMENT_DATA loadAssignment( const nlohmann::json& aJson );
|
||||
};
|
||||
|
||||
#endif // PROJECT_COMPONENT_CLASS_SETTINGS_H
|
||||
@@ -31,6 +31,7 @@
|
||||
class BOARD_DESIGN_SETTINGS;
|
||||
class ERC_SETTINGS;
|
||||
class NET_SETTINGS;
|
||||
class COMPONENT_CLASS_SETTINGS;
|
||||
class LAYER_PAIR_SETTINGS;
|
||||
class SCHEMATIC_SETTINGS;
|
||||
class TEMPLATES;
|
||||
@@ -105,6 +106,11 @@ public:
|
||||
return m_NetSettings;
|
||||
}
|
||||
|
||||
std::shared_ptr<COMPONENT_CLASS_SETTINGS>& ComponentClassSettings()
|
||||
{
|
||||
return m_ComponentClassSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if it should be safe to auto-save this file without user action
|
||||
*/
|
||||
@@ -182,6 +188,10 @@ public:
|
||||
*/
|
||||
std::shared_ptr<NET_SETTINGS> m_NetSettings;
|
||||
|
||||
/**
|
||||
* Component class settings for the project (owned here)
|
||||
*/
|
||||
std::shared_ptr<COMPONENT_CLASS_SETTINGS> m_ComponentClassSettings;
|
||||
|
||||
std::vector<LAYER_PRESET> m_LayerPresets; /// List of stored layer presets
|
||||
std::vector<VIEWPORT> m_Viewports; /// List of stored viewports (pos + zoom)
|
||||
|
||||
@@ -181,6 +181,8 @@ set( PCBNEW_DIALOGS
|
||||
dialogs/panel_pcbnew_display_origin_base.cpp
|
||||
dialogs/panel_rule_area_properties_keepout_base.cpp
|
||||
dialogs/panel_rule_area_properties_placement_base.cpp
|
||||
dialogs/panel_assign_component_classes.cpp
|
||||
dialogs/panel_assign_component_classes_base.cpp
|
||||
dialogs/panel_setup_constraints.cpp
|
||||
dialogs/panel_setup_constraints_base.cpp
|
||||
dialogs/panel_setup_dimensions.cpp
|
||||
@@ -329,7 +331,6 @@ set( PCBNEW_CLASS_SRCS
|
||||
array_pad_number_provider.cpp
|
||||
build_BOM_from_board.cpp
|
||||
cleanup_item.cpp
|
||||
component_class_manager.cpp
|
||||
convert_shape_list_to_polygon.cpp
|
||||
cross-probing.cpp
|
||||
edit.cpp
|
||||
@@ -428,6 +429,11 @@ set( PCBNEW_CLASS_SRCS
|
||||
widgets/net_inspector_panel.cpp
|
||||
widgets/pcb_net_inspector_panel.cpp
|
||||
|
||||
component_classes/component_class.cpp
|
||||
component_classes/component_class_cache_proxy.cpp
|
||||
component_classes/component_class_assignment_rule.cpp
|
||||
component_classes/component_class_manager.cpp
|
||||
|
||||
)
|
||||
|
||||
set( PCBNEW_GIT_SRCS
|
||||
|
||||
+18
-11
@@ -55,6 +55,7 @@
|
||||
#include <pcbnew_settings.h>
|
||||
#include <progress_reporter.h>
|
||||
#include <project.h>
|
||||
#include <project/component_class_settings.h>
|
||||
#include <project/net_settings.h>
|
||||
#include <project/project_file.h>
|
||||
#include <project/project_local_settings.h>
|
||||
@@ -73,18 +74,13 @@ VECTOR2I BOARD_ITEM::ZeroOffset( 0, 0 );
|
||||
|
||||
|
||||
BOARD::BOARD() :
|
||||
BOARD_ITEM_CONTAINER( (BOARD_ITEM*) nullptr, PCB_T ),
|
||||
m_LegacyDesignSettingsLoaded( false ),
|
||||
m_LegacyCopperEdgeClearanceLoaded( false ),
|
||||
m_LegacyNetclassesLoaded( false ),
|
||||
m_boardUse( BOARD_USE::NORMAL ),
|
||||
m_timeStamp( 1 ),
|
||||
m_paper( PAGE_INFO::A4 ),
|
||||
m_project( nullptr ),
|
||||
m_userUnits( EDA_UNITS::MM ),
|
||||
BOARD_ITEM_CONTAINER( (BOARD_ITEM*) nullptr, PCB_T ), m_LegacyDesignSettingsLoaded( false ),
|
||||
m_LegacyCopperEdgeClearanceLoaded( false ), m_LegacyNetclassesLoaded( false ),
|
||||
m_boardUse( BOARD_USE::NORMAL ), m_timeStamp( 1 ), m_paper( PAGE_INFO::A4 ),
|
||||
m_project( nullptr ), m_userUnits( EDA_UNITS::MM ),
|
||||
m_designSettings( new BOARD_DESIGN_SETTINGS( nullptr, "board.design_settings" ) ),
|
||||
m_NetInfo( this ),
|
||||
m_embedFonts( false )
|
||||
m_NetInfo( this ), m_embedFonts( false ),
|
||||
m_componentClassManager( std::make_unique<COMPONENT_CLASS_MANAGER>( this ) )
|
||||
{
|
||||
// A too small value do not allow connecting 2 shapes (i.e. segments) not exactly connected
|
||||
// A too large value do not allow safely connecting 2 shapes like very short segments.
|
||||
@@ -2162,6 +2158,17 @@ void BOARD::SynchronizeNetsAndNetClasses( bool aResetTrackAndViaSizes )
|
||||
}
|
||||
|
||||
|
||||
bool BOARD::SynchronizeComponentClasses( const std::unordered_set<wxString>& aNewSheetPaths ) const
|
||||
{
|
||||
std::shared_ptr<COMPONENT_CLASS_SETTINGS> settings =
|
||||
GetProject()->GetProjectFile().ComponentClassSettings();
|
||||
|
||||
return m_componentClassManager->SyncDynamicComponentClassAssignments(
|
||||
settings->GetComponentClassAssignments(), settings->GetEnableSheetComponentClasses(),
|
||||
aNewSheetPaths );
|
||||
}
|
||||
|
||||
|
||||
int BOARD::SetAreasNetCodesFromNetNames()
|
||||
{
|
||||
int error_count = 0;
|
||||
|
||||
+8
-3
@@ -27,7 +27,7 @@
|
||||
|
||||
#include <board_item_container.h>
|
||||
#include <board_stackup_manager/board_stackup.h>
|
||||
#include <component_class_manager.h>
|
||||
#include <component_classes/component_class_manager.h>
|
||||
#include <embedded_files.h>
|
||||
#include <common.h> // Needed for stl hash extensions
|
||||
#include <convert_shape_list_to_polygon.h> // for OUTLINE_ERROR_HANDLER
|
||||
@@ -1004,6 +1004,11 @@ public:
|
||||
*/
|
||||
void SynchronizeNetsAndNetClasses( bool aResetTrackAndViaSizes );
|
||||
|
||||
/**
|
||||
* Copy component class / component class generator information from the project settings
|
||||
*/
|
||||
bool SynchronizeComponentClasses( const std::unordered_set<wxString>& aNewSheetPaths ) const;
|
||||
|
||||
/**
|
||||
* Copy the current project's text variables into the boards property cache.
|
||||
*/
|
||||
@@ -1302,7 +1307,7 @@ public:
|
||||
/**
|
||||
* Gets the component class manager
|
||||
*/
|
||||
COMPONENT_CLASS_MANAGER& GetComponentClassManager() { return m_componentClassManager; }
|
||||
COMPONENT_CLASS_MANAGER& GetComponentClassManager() { return *m_componentClassManager; }
|
||||
|
||||
PROJECT::ELEM ProjectElementType() override { return PROJECT::ELEM::BOARD; }
|
||||
|
||||
@@ -1422,7 +1427,7 @@ private:
|
||||
|
||||
bool m_embedFonts;
|
||||
|
||||
COMPONENT_CLASS_MANAGER m_componentClassManager;
|
||||
std::unique_ptr<COMPONENT_CLASS_MANAGER> m_componentClassManager;
|
||||
};
|
||||
|
||||
|
||||
|
||||
+34
-2
@@ -42,6 +42,7 @@
|
||||
#include <teardrop/teardrop.h>
|
||||
|
||||
#include <functional>
|
||||
#include <project/project_file.h>
|
||||
using namespace std::placeholders;
|
||||
|
||||
|
||||
@@ -317,6 +318,15 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
||||
if( !staleTeardropPadsAndVias.empty() || !staleTeardropTracks.empty() )
|
||||
teardropMgr.RemoveTeardrops( *this, &staleTeardropPadsAndVias, &staleTeardropTracks );
|
||||
|
||||
auto updateComponentClasses = [this]( BOARD_ITEM* boardItem )
|
||||
{
|
||||
if( boardItem->Type() != PCB_FOOTPRINT_T )
|
||||
return;
|
||||
|
||||
FOOTPRINT* footprint = static_cast<FOOTPRINT*>( boardItem );
|
||||
GetBoard()->GetComponentClassManager().RebuildRequiredCaches( footprint );
|
||||
};
|
||||
|
||||
for( COMMIT_LINE& ent : m_changes )
|
||||
{
|
||||
if( !ent.m_item || !ent.m_item->IsBOARD_ITEM() )
|
||||
@@ -367,6 +377,8 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
||||
if( view && boardItem->Type() != PCB_NETINFO_T )
|
||||
view->Add( boardItem );
|
||||
|
||||
updateComponentClasses( boardItem );
|
||||
|
||||
break;
|
||||
|
||||
case CHT_REMOVE:
|
||||
@@ -510,6 +522,8 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
||||
propagateDamage( boardItem, staleZones, &staleHatchedShapes ); // after
|
||||
}
|
||||
|
||||
updateComponentClasses( boardItem );
|
||||
|
||||
if( view )
|
||||
view->Update( boardItem );
|
||||
|
||||
@@ -533,7 +547,10 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags )
|
||||
{
|
||||
item->ClearEditFlags();
|
||||
} );
|
||||
}
|
||||
} // ... and regenerate them.
|
||||
|
||||
// Invalidate component classes
|
||||
board->GetComponentClassManager().InvalidateComponentClasses();
|
||||
|
||||
if( m_isBoardEditor )
|
||||
{
|
||||
@@ -703,6 +720,15 @@ void BOARD_COMMIT::Revert()
|
||||
|
||||
board->IncrementTimeStamp(); // clear caches
|
||||
|
||||
auto updateComponentClasses = [this]( BOARD_ITEM* boardItem )
|
||||
{
|
||||
if( boardItem->Type() != PCB_FOOTPRINT_T )
|
||||
return;
|
||||
|
||||
FOOTPRINT* footprint = static_cast<FOOTPRINT*>( boardItem );
|
||||
GetBoard()->GetComponentClassManager().RebuildRequiredCaches( footprint );
|
||||
};
|
||||
|
||||
std::vector<BOARD_ITEM*> bulkAddedItems;
|
||||
std::vector<BOARD_ITEM*> bulkRemovedItems;
|
||||
std::vector<BOARD_ITEM*> itemsChanged;
|
||||
@@ -767,6 +793,8 @@ void BOARD_COMMIT::Revert()
|
||||
bulkAddedItems.push_back( boardItem );
|
||||
}
|
||||
|
||||
updateComponentClasses( boardItem );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -792,6 +820,8 @@ void BOARD_COMMIT::Revert()
|
||||
connectivity->Add( boardItem );
|
||||
itemsChanged.push_back( boardItem );
|
||||
|
||||
updateComponentClasses( boardItem );
|
||||
|
||||
delete entry.m_copy;
|
||||
break;
|
||||
}
|
||||
@@ -804,6 +834,9 @@ void BOARD_COMMIT::Revert()
|
||||
boardItem->ClearEditFlags();
|
||||
}
|
||||
|
||||
// Invalidate component classes
|
||||
board->GetComponentClassManager().InvalidateComponentClasses();
|
||||
|
||||
if( bulkAddedItems.size() > 0 || bulkRemovedItems.size() > 0 || itemsChanged.size() > 0 )
|
||||
board->OnItemsCompositeUpdate( bulkAddedItems, bulkRemovedItems, itemsChanged );
|
||||
|
||||
@@ -822,4 +855,3 @@ void BOARD_COMMIT::Revert()
|
||||
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,210 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <component_class_manager.h>
|
||||
|
||||
|
||||
void COMPONENT_CLASS::AddConstituentClass( COMPONENT_CLASS* componentClass )
|
||||
{
|
||||
m_constituentClasses.push_back( componentClass );
|
||||
}
|
||||
|
||||
|
||||
bool COMPONENT_CLASS::ContainsClassName( const wxString& className ) const
|
||||
{
|
||||
if( m_constituentClasses.size() == 0 )
|
||||
return false;
|
||||
|
||||
if( m_constituentClasses.size() == 1 )
|
||||
return m_name == className;
|
||||
|
||||
return std::any_of( m_constituentClasses.begin(), m_constituentClasses.end(),
|
||||
[&className]( const COMPONENT_CLASS* testClass )
|
||||
{
|
||||
return testClass->GetFullName() == className;
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
wxString COMPONENT_CLASS::GetName() const
|
||||
{
|
||||
if( m_constituentClasses.size() == 0 )
|
||||
return wxT( "<None>" );
|
||||
|
||||
if( m_constituentClasses.size() == 1 )
|
||||
return m_name;
|
||||
|
||||
wxASSERT( m_constituentClasses.size() >= 2 );
|
||||
|
||||
wxString name;
|
||||
|
||||
if( m_constituentClasses.size() == 2 )
|
||||
{
|
||||
name.Printf( _( "%s and %s" ), m_constituentClasses[0]->GetName(),
|
||||
m_constituentClasses[1]->GetName() );
|
||||
}
|
||||
else if( m_constituentClasses.size() == 3 )
|
||||
{
|
||||
name.Printf( _( "%s, %s and %s" ), m_constituentClasses[0]->GetName(),
|
||||
m_constituentClasses[1]->GetName(), m_constituentClasses[2]->GetName() );
|
||||
}
|
||||
else if( m_constituentClasses.size() > 3 )
|
||||
{
|
||||
name.Printf( _( "%s, %s and %d more" ), m_constituentClasses[0]->GetName(),
|
||||
m_constituentClasses[1]->GetName(),
|
||||
static_cast<int>( m_constituentClasses.size() - 2 ) );
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
bool COMPONENT_CLASS::IsEmpty() const
|
||||
{
|
||||
return m_constituentClasses.size() == 0;
|
||||
}
|
||||
|
||||
|
||||
COMPONENT_CLASS_MANAGER::COMPONENT_CLASS_MANAGER()
|
||||
{
|
||||
m_noneClass = std::make_unique<COMPONENT_CLASS>( wxEmptyString );
|
||||
}
|
||||
|
||||
|
||||
COMPONENT_CLASS* COMPONENT_CLASS_MANAGER::GetEffectiveComponentClass(
|
||||
const std::unordered_set<wxString>& classNames )
|
||||
{
|
||||
if( classNames.size() == 0 )
|
||||
return m_noneClass.get();
|
||||
|
||||
// Lambda to handle finding constituent component classes. This first checks the cache,
|
||||
// and if found moves the class to the primary classes map. If not found, it either returns
|
||||
// an existing class in the primary list or creates a new class.
|
||||
auto getOrCreateClass = [this]( const wxString& className )
|
||||
{
|
||||
if( m_classesCache.count( className ) )
|
||||
{
|
||||
auto existingClass = m_classesCache.extract( className );
|
||||
m_classes.insert( std::move( existingClass ) );
|
||||
}
|
||||
else if( !m_classes.count( className ) )
|
||||
{
|
||||
std::unique_ptr<COMPONENT_CLASS> newClass =
|
||||
std::make_unique<COMPONENT_CLASS>( className );
|
||||
newClass->AddConstituentClass( newClass.get() );
|
||||
m_classes[className] = std::move( newClass );
|
||||
}
|
||||
|
||||
return m_classes[className].get();
|
||||
};
|
||||
|
||||
// Handle single-assignment component classes
|
||||
if( classNames.size() == 1 )
|
||||
return getOrCreateClass( *classNames.begin() );
|
||||
|
||||
// Handle composite component classes
|
||||
std::vector<wxString> sortedClassNames( classNames.begin(), classNames.end() );
|
||||
|
||||
std::sort( sortedClassNames.begin(), sortedClassNames.end(),
|
||||
[]( const wxString& str1, const wxString& str2 )
|
||||
{
|
||||
return str1.Cmp( str2 ) < 0;
|
||||
} );
|
||||
|
||||
wxString fullName = GetFullClassNameForConstituents( sortedClassNames );
|
||||
|
||||
if( m_effectiveClassesCache.count( fullName ) )
|
||||
{
|
||||
// The effective class was previously constructed - copy it across to the new live map
|
||||
auto existingClass = m_effectiveClassesCache.extract( fullName );
|
||||
COMPONENT_CLASS* effClass = existingClass.mapped().get();
|
||||
m_effectiveClasses.insert( std::move( existingClass ) );
|
||||
|
||||
// Ensure that all constituent component classes are copied to the live map
|
||||
for( COMPONENT_CLASS* constClass : effClass->GetConstituentClasses() )
|
||||
{
|
||||
if( m_classesCache.count( constClass->GetFullName() ) )
|
||||
{
|
||||
auto constClassNode = m_classesCache.extract( constClass->GetFullName() );
|
||||
m_classes.insert( std::move( constClassNode ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( !m_effectiveClasses.count( fullName ) )
|
||||
{
|
||||
// The effective class was not previously constructed
|
||||
std::unique_ptr<COMPONENT_CLASS> effClass = std::make_unique<COMPONENT_CLASS>( fullName );
|
||||
|
||||
for( const wxString& className : sortedClassNames )
|
||||
effClass->AddConstituentClass( getOrCreateClass( className ) );
|
||||
|
||||
m_effectiveClasses[fullName] = std::move( effClass );
|
||||
}
|
||||
|
||||
return m_effectiveClasses[fullName].get();
|
||||
}
|
||||
|
||||
|
||||
void COMPONENT_CLASS_MANAGER::InitNetlistUpdate()
|
||||
{
|
||||
m_classesCache = std::move( m_classes );
|
||||
m_effectiveClassesCache = std::move( m_effectiveClasses );
|
||||
}
|
||||
|
||||
|
||||
void COMPONENT_CLASS_MANAGER::FinishNetlistUpdate()
|
||||
{
|
||||
m_classesCache.clear();
|
||||
m_effectiveClassesCache.clear();
|
||||
}
|
||||
|
||||
|
||||
wxString COMPONENT_CLASS_MANAGER::GetFullClassNameForConstituents(
|
||||
const std::unordered_set<wxString>& classNames )
|
||||
{
|
||||
std::vector<wxString> sortedClassNames( classNames.begin(), classNames.end() );
|
||||
|
||||
std::sort( sortedClassNames.begin(), sortedClassNames.end(),
|
||||
[]( const wxString& str1, const wxString& str2 )
|
||||
{
|
||||
return str1.Cmp( str2 ) < 0;
|
||||
} );
|
||||
|
||||
return GetFullClassNameForConstituents( sortedClassNames );
|
||||
}
|
||||
|
||||
|
||||
wxString
|
||||
COMPONENT_CLASS_MANAGER::GetFullClassNameForConstituents( const std::vector<wxString>& classNames )
|
||||
{
|
||||
if( classNames.size() == 0 )
|
||||
return wxEmptyString;
|
||||
|
||||
wxString fullName = classNames[0];
|
||||
|
||||
for( std::size_t i = 1; i < classNames.size(); ++i )
|
||||
{
|
||||
fullName += ",";
|
||||
fullName += classNames[i];
|
||||
}
|
||||
|
||||
return fullName;
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PCBNEW_COMPONENT_CLASS_MANAGER_H
|
||||
#define PCBNEW_COMPONENT_CLASS_MANAGER_H
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <wx/string.h>
|
||||
|
||||
#include <board_item.h>
|
||||
|
||||
/*
|
||||
* A lightweight representation of a component class. The membership within
|
||||
* m_consituentClasses allows determination of the type of class this is:
|
||||
*
|
||||
* m_constituentClasses.size() == 0: This is a null class (no assigment).
|
||||
* m_name is empty.
|
||||
* m_constituentClasses.size() == 1: This is an atomic class. The constituent class
|
||||
* pointer refers to itself. m_name contains the name of the atomic class
|
||||
* m_constituentClasses.size() > 1: This is a composite class. The constituent class
|
||||
* pointers refer to all atomic members. m_name contains a comma-delimited list of
|
||||
* all atomic member class names.
|
||||
*/
|
||||
class COMPONENT_CLASS
|
||||
{
|
||||
public:
|
||||
COMPONENT_CLASS( const wxString& name ) : m_name( name ) {}
|
||||
|
||||
/// Fetches the display name of this component class
|
||||
wxString GetName() const;
|
||||
|
||||
/// Fetches the full name of this component class
|
||||
const wxString& GetFullName() const { return m_name; }
|
||||
|
||||
/// Adds a constituent component class to an effective component class
|
||||
void AddConstituentClass( COMPONENT_CLASS* componentClass );
|
||||
|
||||
/// Determines if this (effective) component class contains a specific sub-class
|
||||
bool ContainsClassName( const wxString& className ) const;
|
||||
|
||||
/// Determines if this (effective) component class is empty (i.e. no classes defined)
|
||||
bool IsEmpty() const;
|
||||
|
||||
/// Fetches a vector of the constituent classes for this (effective) class
|
||||
const std::vector<COMPONENT_CLASS*>& GetConstituentClasses() const
|
||||
{
|
||||
return m_constituentClasses;
|
||||
}
|
||||
|
||||
private:
|
||||
/// The full name of the component class
|
||||
wxString m_name;
|
||||
|
||||
/// The COMPONENT_CLASS objects contributing to this complete component class
|
||||
std::vector<COMPONENT_CLASS*> m_constituentClasses;
|
||||
};
|
||||
|
||||
/*
|
||||
* A class to manage Component Classes in a board context
|
||||
*
|
||||
* This manager owns generated COMPONENT_CLASS objects, and guarantees that pointers to managed
|
||||
* objects are valid for the duration of the board lifetime. Note that, in order to maintain this
|
||||
* guarantee, there are two methods that must be called when updating the board from the netlist
|
||||
* (InitNetlistUpdate and FinishNetlistUpdate).
|
||||
*/
|
||||
class COMPONENT_CLASS_MANAGER
|
||||
{
|
||||
public:
|
||||
COMPONENT_CLASS_MANAGER();
|
||||
|
||||
/// @brief Gets the full effective class name for the given set of constituent classes
|
||||
static wxString
|
||||
GetFullClassNameForConstituents( const std::unordered_set<wxString>& classNames );
|
||||
|
||||
/// @brief Gets the full effective class name for the given set of constituent classes
|
||||
/// @param classNames a sorted vector of consituent class names
|
||||
static wxString GetFullClassNameForConstituents( const std::vector<wxString>& classNames );
|
||||
|
||||
/// @brief Gets an effective component class for the given constituent class names
|
||||
/// @param classes The names of the constituent component classes
|
||||
/// @return Effective COMPONENT_CLASS object
|
||||
COMPONENT_CLASS* GetEffectiveComponentClass( const std::unordered_set<wxString>& classNames );
|
||||
|
||||
/// Returns the unassigned component class
|
||||
const COMPONENT_CLASS* GetNoneComponentClass() const { return m_noneClass.get(); }
|
||||
|
||||
/// Prepare the manager for a board update
|
||||
/// Must be called prior to updating the PCB from the netlist
|
||||
void InitNetlistUpdate();
|
||||
|
||||
/// Cleans up the manager after a board update
|
||||
/// Must be called after updating the PCB from the netlist
|
||||
void FinishNetlistUpdate();
|
||||
|
||||
/// Resets the contents of the manager
|
||||
// All pointers to COMPONENT_CLASS objects will being invalid
|
||||
void Reset();
|
||||
|
||||
/// @brief Fetches a read-only map of the fundamental component classes
|
||||
const std::unordered_map<wxString, std::unique_ptr<COMPONENT_CLASS>>& GetClasses() const
|
||||
{
|
||||
return m_classes;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// All individual component classes
|
||||
std::unordered_map<wxString, std::unique_ptr<COMPONENT_CLASS>> m_classes;
|
||||
|
||||
/// Generated effective component classes
|
||||
std::unordered_map<wxString, std::unique_ptr<COMPONENT_CLASS>> m_effectiveClasses;
|
||||
|
||||
/// Cache of all individual component classes (for netlist updating)
|
||||
std::unordered_map<wxString, std::unique_ptr<COMPONENT_CLASS>> m_classesCache;
|
||||
|
||||
/// Cache of all generated effective component classes (for netlist updating)
|
||||
std::unordered_map<wxString, std::unique_ptr<COMPONENT_CLASS>> m_effectiveClassesCache;
|
||||
|
||||
/// The class to represent an unassigned component class
|
||||
std::unique_ptr<COMPONENT_CLASS> m_noneClass;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <component_classes/component_class.h>
|
||||
#include <wx/intl.h>
|
||||
|
||||
|
||||
void COMPONENT_CLASS::AddConstituentClass( COMPONENT_CLASS* componentClass )
|
||||
{
|
||||
m_constituentClasses.push_back( componentClass );
|
||||
}
|
||||
|
||||
|
||||
const COMPONENT_CLASS* COMPONENT_CLASS::GetConstituentClass( const wxString& className ) const
|
||||
{
|
||||
const auto itr = std::ranges::find_if( m_constituentClasses,
|
||||
[&className]( const COMPONENT_CLASS* testClass )
|
||||
{
|
||||
return testClass->GetName() == className;
|
||||
} );
|
||||
|
||||
if( itr != m_constituentClasses.end() )
|
||||
return *itr;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
bool COMPONENT_CLASS::ContainsClassName( const wxString& className ) const
|
||||
{
|
||||
return GetConstituentClass( className ) != nullptr;
|
||||
}
|
||||
|
||||
|
||||
wxString COMPONENT_CLASS::GetHumanReadableName() const
|
||||
{
|
||||
if( m_constituentClasses.size() == 0 )
|
||||
return wxT( "<None>" );
|
||||
|
||||
if( m_constituentClasses.size() == 1 )
|
||||
return m_name;
|
||||
|
||||
wxASSERT( m_constituentClasses.size() >= 2 );
|
||||
|
||||
wxString name;
|
||||
|
||||
if( m_constituentClasses.size() == 2 )
|
||||
{
|
||||
name.Printf( _( "%s and %s" ), m_constituentClasses[0]->GetName(),
|
||||
m_constituentClasses[1]->GetName() );
|
||||
}
|
||||
else if( m_constituentClasses.size() == 3 )
|
||||
{
|
||||
name.Printf( _( "%s, %s and %s" ), m_constituentClasses[0]->GetName(),
|
||||
m_constituentClasses[1]->GetName(), m_constituentClasses[2]->GetName() );
|
||||
}
|
||||
else if( m_constituentClasses.size() > 3 )
|
||||
{
|
||||
name.Printf( _( "%s, %s and %d more" ), m_constituentClasses[0]->GetName(),
|
||||
m_constituentClasses[1]->GetName(),
|
||||
static_cast<int>( m_constituentClasses.size() - 2 ) );
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
bool COMPONENT_CLASS::IsEmpty() const
|
||||
{
|
||||
return m_constituentClasses.empty();
|
||||
}
|
||||
|
||||
|
||||
bool COMPONENT_CLASS::operator==( const COMPONENT_CLASS& aComponent ) const
|
||||
{
|
||||
return GetName() == aComponent.GetName();
|
||||
}
|
||||
|
||||
|
||||
bool COMPONENT_CLASS::operator!=( const COMPONENT_CLASS& aComponent ) const
|
||||
{
|
||||
return !( *this == aComponent );
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PCBNEW_COMPONENT_CLASS_H
|
||||
#define PCBNEW_COMPONENT_CLASS_H
|
||||
|
||||
#include <wx/string.h>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* A lightweight representation of a component class. The membership within
|
||||
* m_consituentClasses allows determination of the type of class this is:
|
||||
*
|
||||
* m_constituentClasses.size() == 0: This is a null class (no assigment).
|
||||
* m_name is empty.
|
||||
* m_constituentClasses.size() == 1: This is an atomic class. The constituent class
|
||||
* pointer refers to itself. m_name contains the name of the atomic class
|
||||
* m_constituentClasses.size() > 1: This is a composite class. The constituent class
|
||||
* pointers refer to all atomic members. m_name contains a comma-delimited list of
|
||||
* all atomic member class names.
|
||||
*/
|
||||
class COMPONENT_CLASS
|
||||
{
|
||||
public:
|
||||
/// The assignment context in which this component class is used
|
||||
enum class USAGE
|
||||
{
|
||||
STATIC,
|
||||
DYNAMIC,
|
||||
STATIC_AND_DYNAMIC,
|
||||
EFFECTIVE
|
||||
};
|
||||
|
||||
/// Construct a new component class
|
||||
explicit COMPONENT_CLASS( const wxString& name, const USAGE aUsageContext ) :
|
||||
m_name( name ), m_usageContext( aUsageContext )
|
||||
{
|
||||
}
|
||||
|
||||
/// @brief Gets the consolidated name of this component class (which may be an aggregate). This is
|
||||
/// intended for display to users (e.g. in infobars or messages). WARNING: Do not use this
|
||||
/// to compare equivalence, or to export to other tools)
|
||||
wxString GetHumanReadableName() const;
|
||||
|
||||
/// Fetches the full name of this component class
|
||||
const wxString& GetName() const { return m_name; }
|
||||
|
||||
/// Adds a constituent component class to an effective component class
|
||||
void AddConstituentClass( COMPONENT_CLASS* componentClass );
|
||||
|
||||
/// Returns a named constituent class of this component class, or nullptr if not found
|
||||
const COMPONENT_CLASS* GetConstituentClass( const wxString& className ) const;
|
||||
|
||||
/// Determines if this (effective) component class contains a specific constituent class
|
||||
bool ContainsClassName( const wxString& className ) const;
|
||||
|
||||
/// Determines if this (effective) component class is empty (i.e. no classes defined)
|
||||
bool IsEmpty() const;
|
||||
|
||||
/// Fetches a vector of the constituent classes for this (effective) class
|
||||
const std::vector<COMPONENT_CLASS*>& GetConstituentClasses() const
|
||||
{
|
||||
return m_constituentClasses;
|
||||
}
|
||||
|
||||
/// Gets the assignment context in which this component class is being used
|
||||
USAGE GetUsageContext() const { return m_usageContext; }
|
||||
|
||||
/// Sets the assignment context in which this component class is being used
|
||||
void SetUsageContext( const USAGE aUsageContext ) { m_usageContext = aUsageContext; }
|
||||
|
||||
/// Tests two component classes for equality based on full class name
|
||||
bool operator==( const COMPONENT_CLASS& aComponent ) const;
|
||||
|
||||
/// Tests two component classes for inequality based on full class name
|
||||
bool operator!=( const COMPONENT_CLASS& aComponent ) const;
|
||||
|
||||
private:
|
||||
/// The full name of the component class
|
||||
wxString m_name;
|
||||
|
||||
/// The COMPONENT_CLASS objects contributing to this complete component class
|
||||
std::vector<COMPONENT_CLASS*> m_constituentClasses;
|
||||
|
||||
/// The assignment context in which this component class is being used
|
||||
USAGE m_usageContext;
|
||||
};
|
||||
|
||||
#endif //PCBNEW_COMPONENT_CLASS_H
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <component_classes/component_class_assignment_rule.h>
|
||||
#include <footprint.h>
|
||||
|
||||
|
||||
COMPONENT_CLASS_ASSIGNMENT_RULE::COMPONENT_CLASS_ASSIGNMENT_RULE(
|
||||
const wxString& aComponentClass, std::shared_ptr<DRC_RULE_CONDITION>&& aCondition ) :
|
||||
m_componentClass( aComponentClass ), m_condition( std::move( aCondition ) )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool COMPONENT_CLASS_ASSIGNMENT_RULE::Matches( const FOOTPRINT* aFootprint ) const
|
||||
{
|
||||
if( !m_condition )
|
||||
return true;
|
||||
|
||||
return m_condition->EvaluateFor( aFootprint, nullptr, 0, aFootprint->GetSide(), nullptr );
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef COMPONENT_CLASS_ASSIGNMENT_RULE_H
|
||||
#define COMPONENT_CLASS_ASSIGNMENT_RULE_H
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <wx/string.h>
|
||||
|
||||
#include <drc/drc_rule_condition.h>
|
||||
|
||||
class FOOTPRINT;
|
||||
|
||||
/**
|
||||
* Class which represents a component class assignment rule. These are used to dynamically assign component classes
|
||||
* based on FOOTPRINT parameters which are exposed through the DRC language.
|
||||
*/
|
||||
class COMPONENT_CLASS_ASSIGNMENT_RULE
|
||||
{
|
||||
public:
|
||||
/// Construct a component class assignment rule
|
||||
explicit COMPONENT_CLASS_ASSIGNMENT_RULE( const wxString& aComponentClass,
|
||||
std::shared_ptr<DRC_RULE_CONDITION>&& aCondition );
|
||||
|
||||
/// The component class to assign to matching footprints
|
||||
wxString GetComponentClass() const { return m_componentClass; }
|
||||
void SetComponentClass( const wxString& aComponentClass )
|
||||
{
|
||||
m_componentClass = aComponentClass;
|
||||
}
|
||||
|
||||
/// Tests whether this rules matches the given footprint
|
||||
bool Matches( const FOOTPRINT* aFootprint ) const;
|
||||
|
||||
protected:
|
||||
/// The component class to assign to matching footprints
|
||||
wxString m_componentClass;
|
||||
|
||||
/// The DRC condition which specifies footprint matches for this component class
|
||||
std::shared_ptr<DRC_RULE_CONDITION> m_condition;
|
||||
};
|
||||
|
||||
#endif // COMPONENT_CLASS_ASSIGNMENT_RULE_H
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <component_classes/component_class_cache_proxy.h>
|
||||
|
||||
#include <board.h>
|
||||
#include <footprint.h>
|
||||
|
||||
const COMPONENT_CLASS* COMPONENT_CLASS_CACHE_PROXY::GetComponentClass() const
|
||||
{
|
||||
COMPONENT_CLASS_MANAGER& mgr = m_footprint->GetBoard()->GetComponentClassManager();
|
||||
|
||||
if( mgr.GetTicker() > m_lastTickerValue )
|
||||
{
|
||||
RecomputeComponentClass( &mgr );
|
||||
}
|
||||
|
||||
return m_finalComponentClass;
|
||||
}
|
||||
|
||||
|
||||
void COMPONENT_CLASS_CACHE_PROXY::RecomputeComponentClass( COMPONENT_CLASS_MANAGER* manager ) const
|
||||
{
|
||||
if( !manager )
|
||||
manager = &m_footprint->GetBoard()->GetComponentClassManager();
|
||||
|
||||
m_dynamicComponentClass = manager->GetDynamicComponentClassesForFootprint( m_footprint );
|
||||
m_finalComponentClass =
|
||||
manager->GetCombinedComponentClass( m_staticComponentClass, m_dynamicComponentClass );
|
||||
m_lastTickerValue = manager->GetTicker();
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PCBNEW_COMPONENT_CLASS_CACHE_PROXY_H
|
||||
#define PCBNEW_COMPONENT_CLASS_CACHE_PROXY_H
|
||||
|
||||
#include <component_classes/component_class.h>
|
||||
#include <footprint.h>
|
||||
|
||||
/*
|
||||
* A class which acts as a cache-aware proxy for a FOOTPRINT's component class.
|
||||
* Creating dynamic component classes (from component class generators) is an
|
||||
* expensive operation, so we want to cache the results. This class is a cache
|
||||
* proxy which tracks the validity of the cached component class with respect
|
||||
* to loaded static and dynamic component class rules
|
||||
*/
|
||||
class COMPONENT_CLASS_CACHE_PROXY
|
||||
{
|
||||
public:
|
||||
explicit COMPONENT_CLASS_CACHE_PROXY( FOOTPRINT* footprint ) : m_footprint( footprint ) {}
|
||||
|
||||
/// Sets the static component class
|
||||
/// Static component classes are assigned in the schematic, and are transferred through the
|
||||
/// netlist
|
||||
void SetStaticComponentClass( const COMPONENT_CLASS* compClass )
|
||||
{
|
||||
m_staticComponentClass = compClass;
|
||||
}
|
||||
|
||||
/// Gets the static component class
|
||||
const COMPONENT_CLASS* GetStaticComponentClass() const { return m_staticComponentClass; }
|
||||
|
||||
/// Gets the full component class (static + dynamic resultant component class)
|
||||
const COMPONENT_CLASS* GetComponentClass() const;
|
||||
|
||||
/// Forces recomputation of the component class
|
||||
void RecomputeComponentClass( COMPONENT_CLASS_MANAGER* manager = nullptr ) const;
|
||||
|
||||
/// Invalidates the cache
|
||||
/// The component class will be recalculated on the next access
|
||||
void InvalidateCache() { m_lastTickerValue = -1; }
|
||||
|
||||
protected:
|
||||
FOOTPRINT* m_footprint;
|
||||
|
||||
const COMPONENT_CLASS* m_staticComponentClass{ nullptr };
|
||||
mutable const COMPONENT_CLASS* m_dynamicComponentClass{ nullptr };
|
||||
mutable const COMPONENT_CLASS* m_finalComponentClass{ nullptr };
|
||||
|
||||
mutable long long int m_lastTickerValue{ -1 };
|
||||
};
|
||||
|
||||
#endif //PCBNEW_COMPONENT_CLASS_CACHE_PROXY_H
|
||||
@@ -0,0 +1,507 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <component_classes/component_class_manager.h>
|
||||
|
||||
#include <board.h>
|
||||
#include <component_classes/component_class.h>
|
||||
#include <component_classes/component_class_assignment_rule.h>
|
||||
#include <drc/drc_cache_generator.h>
|
||||
#include <drc/drc_rule_parser.h>
|
||||
#include <footprint.h>
|
||||
#include <project/component_class_settings.h>
|
||||
#include <tools/drc_tool.h>
|
||||
|
||||
|
||||
COMPONENT_CLASS_MANAGER::COMPONENT_CLASS_MANAGER( BOARD* board ) :
|
||||
m_board( board ), m_hasCustomAssignmentConditions( false )
|
||||
{
|
||||
m_noneClass =
|
||||
std::make_shared<COMPONENT_CLASS>( wxEmptyString, COMPONENT_CLASS::USAGE::STATIC );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Computes and returns an effective component class for a (possibly empty) set of constituent
|
||||
* class names. This is called by the netlist updater to set static component classes on footprints.
|
||||
*
|
||||
* Where constituent or effective component classes already exist, they are re-used. This allows
|
||||
* efficient comparison of (effective) component classes by pointer in DRC checks.
|
||||
*
|
||||
* Preconditions: InitNetlistUpdate() must be called before invoking this method.
|
||||
* @param classNames The constitent component class names
|
||||
* @return A pointer to an effective COMPONENT_CLASS representing all constituent component classes
|
||||
*/
|
||||
COMPONENT_CLASS* COMPONENT_CLASS_MANAGER::GetEffectiveStaticComponentClass(
|
||||
const std::unordered_set<wxString>& classNames )
|
||||
{
|
||||
// Handle no component class condition
|
||||
if( classNames.size() == 0 )
|
||||
return m_noneClass.get();
|
||||
|
||||
// Handle single-assignment component classes
|
||||
if( classNames.size() == 1 )
|
||||
{
|
||||
const wxString& className = *classNames.begin();
|
||||
m_staticClassNamesCache.erase( className );
|
||||
return getOrCreateConstituentClass( className, COMPONENT_CLASS::USAGE::STATIC );
|
||||
}
|
||||
|
||||
// Handle composite component classes
|
||||
const std::vector<wxString> sortedClassNames = sortClassNames( classNames );
|
||||
wxString fullName = GetFullClassNameForConstituents( sortedClassNames );
|
||||
|
||||
COMPONENT_CLASS* effectiveClass =
|
||||
getOrCreateEffectiveClass( sortedClassNames, COMPONENT_CLASS::USAGE::STATIC );
|
||||
|
||||
for( const COMPONENT_CLASS* constituentClass : effectiveClass->GetConstituentClasses() )
|
||||
m_staticClassNamesCache.erase( constituentClass->GetName() );
|
||||
|
||||
return effectiveClass;
|
||||
}
|
||||
|
||||
|
||||
void COMPONENT_CLASS_MANAGER::InitNetlistUpdate()
|
||||
{
|
||||
for( const auto& [className, classPtr] : m_constituentClasses )
|
||||
{
|
||||
if( classPtr->GetUsageContext() == COMPONENT_CLASS::USAGE::STATIC
|
||||
|| classPtr->GetUsageContext() == COMPONENT_CLASS::USAGE::STATIC_AND_DYNAMIC )
|
||||
{
|
||||
m_staticClassNamesCache.insert( className );
|
||||
}
|
||||
}
|
||||
|
||||
++m_ticker;
|
||||
}
|
||||
|
||||
|
||||
void COMPONENT_CLASS_MANAGER::FinishNetlistUpdate()
|
||||
{
|
||||
// m_staticClassesCache now contains any static component classes that are unused from the
|
||||
// netlist update. Delete any effective component classes which refer to them in a static-only
|
||||
// context, or update their usage context.
|
||||
for( const wxString& className : m_staticClassNamesCache )
|
||||
{
|
||||
COMPONENT_CLASS* staticClass = m_constituentClasses[className].get();
|
||||
|
||||
if( staticClass->GetUsageContext() == COMPONENT_CLASS::USAGE::STATIC )
|
||||
{
|
||||
// Any static-only classes can be deleted, along with effective classes which refer to them
|
||||
std::unordered_set<wxString> classesToDelete;
|
||||
|
||||
for( const auto& [combinedFullName, combinedCompClass] : m_effectiveClasses )
|
||||
{
|
||||
if( combinedCompClass->ContainsClassName( className ) )
|
||||
classesToDelete.insert( combinedFullName );
|
||||
}
|
||||
|
||||
for( const wxString& classNameToDelete : classesToDelete )
|
||||
m_effectiveClasses.erase( classNameToDelete );
|
||||
|
||||
m_constituentClasses.erase( className );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set the component class to dynamic-only scope
|
||||
wxASSERT( staticClass->GetUsageContext()
|
||||
== COMPONENT_CLASS::USAGE::STATIC_AND_DYNAMIC );
|
||||
staticClass->SetUsageContext( COMPONENT_CLASS::USAGE::DYNAMIC );
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the caches
|
||||
m_staticClassNamesCache.clear();
|
||||
}
|
||||
|
||||
|
||||
wxString COMPONENT_CLASS_MANAGER::GetFullClassNameForConstituents(
|
||||
const std::unordered_set<wxString>& classNames )
|
||||
{
|
||||
const std::vector<wxString> sortedClassNames = sortClassNames( classNames );
|
||||
|
||||
return GetFullClassNameForConstituents( sortedClassNames );
|
||||
}
|
||||
|
||||
|
||||
wxString
|
||||
COMPONENT_CLASS_MANAGER::GetFullClassNameForConstituents( const std::vector<wxString>& classNames )
|
||||
{
|
||||
if( classNames.size() == 0 )
|
||||
return wxEmptyString;
|
||||
|
||||
wxString fullName = classNames[0];
|
||||
|
||||
for( std::size_t i = 1; i < classNames.size(); ++i )
|
||||
{
|
||||
fullName += ",";
|
||||
fullName += classNames[i];
|
||||
}
|
||||
|
||||
return fullName;
|
||||
}
|
||||
|
||||
|
||||
bool COMPONENT_CLASS_MANAGER::SyncDynamicComponentClassAssignments(
|
||||
const std::vector<COMPONENT_CLASS_ASSIGNMENT_DATA>& aAssignments,
|
||||
bool aGenerateSheetClasses, const std::unordered_set<wxString>& aNewSheetPaths )
|
||||
{
|
||||
m_hasCustomAssignmentConditions = false;
|
||||
bool success = true;
|
||||
|
||||
// Invalidate component class cache entries
|
||||
++m_ticker;
|
||||
|
||||
// Save previous dynamically assigned component class names
|
||||
std::unordered_set<wxString> prevClassNames;
|
||||
|
||||
for( const auto& rule : m_assignmentRules )
|
||||
prevClassNames.insert( rule->GetComponentClass() );
|
||||
|
||||
m_assignmentRules.clear();
|
||||
|
||||
// Parse all assignment rules
|
||||
std::vector<std::shared_ptr<COMPONENT_CLASS_ASSIGNMENT_RULE>> rules;
|
||||
|
||||
for( const COMPONENT_CLASS_ASSIGNMENT_DATA& assignment : aAssignments )
|
||||
{
|
||||
if( assignment.GetConditions().contains(
|
||||
COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::CUSTOM ) )
|
||||
{
|
||||
m_hasCustomAssignmentConditions = true;
|
||||
}
|
||||
|
||||
std::shared_ptr<COMPONENT_CLASS_ASSIGNMENT_RULE> rule = CompileAssignmentRule( assignment );
|
||||
|
||||
if( rule )
|
||||
rules.emplace_back( std::move( rule ) );
|
||||
else
|
||||
success = false;
|
||||
}
|
||||
|
||||
// Generate sheet classes if required
|
||||
if( aGenerateSheetClasses )
|
||||
{
|
||||
std::unordered_set<wxString> sheetNames = aNewSheetPaths;
|
||||
|
||||
for( const FOOTPRINT* footprint : m_board->Footprints() )
|
||||
sheetNames.insert( footprint->GetSheetname() );
|
||||
|
||||
for( wxString sheetName : sheetNames )
|
||||
{
|
||||
// Don't generate a class for empty sheets (e.g. manually placed footprints) or the root
|
||||
// sheet
|
||||
if( sheetName.empty() || sheetName == wxT( "/" ) )
|
||||
continue;
|
||||
|
||||
sheetName.Replace( wxT( "\"" ), wxT( "" ) );
|
||||
sheetName.Replace( wxT( "'" ), wxT( "" ) );
|
||||
|
||||
COMPONENT_CLASS_ASSIGNMENT_DATA assignment;
|
||||
assignment.SetComponentClass( sheetName );
|
||||
assignment.SetCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::SHEET_NAME,
|
||||
sheetName, wxEmptyString );
|
||||
|
||||
std::shared_ptr<COMPONENT_CLASS_ASSIGNMENT_RULE> rule =
|
||||
CompileAssignmentRule( assignment );
|
||||
|
||||
if( rule )
|
||||
rules.emplace_back( std::move( rule ) );
|
||||
else
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the assignment rules
|
||||
if( success )
|
||||
m_assignmentRules = std::move( rules );
|
||||
|
||||
// Re-use or create component classes which may be output by assignment rules
|
||||
for( const auto& rule : m_assignmentRules )
|
||||
{
|
||||
wxString className = rule->GetComponentClass();
|
||||
prevClassNames.erase( className );
|
||||
getOrCreateConstituentClass( className, COMPONENT_CLASS::USAGE::DYNAMIC );
|
||||
}
|
||||
|
||||
// prevClassNames now contains all dynamic component class names no longer in use. Remove any
|
||||
// effective component classes no longer in use.
|
||||
for( const wxString& className : prevClassNames )
|
||||
{
|
||||
COMPONENT_CLASS* dynamicClass = m_constituentClasses[className].get();
|
||||
|
||||
if( dynamicClass->GetUsageContext() == COMPONENT_CLASS::USAGE::DYNAMIC )
|
||||
{
|
||||
// Any dynamic-only classes can be deleted, along with effective classes which refer to them
|
||||
std::unordered_set<wxString> classesToDelete;
|
||||
|
||||
for( const auto& [combinedFullName, combinedCompClass] : m_effectiveClasses )
|
||||
{
|
||||
if( combinedCompClass->ContainsClassName( className ) )
|
||||
classesToDelete.insert( combinedFullName );
|
||||
}
|
||||
|
||||
for( const wxString& classNameToDelete : classesToDelete )
|
||||
m_effectiveClasses.erase( classNameToDelete );
|
||||
|
||||
m_constituentClasses.erase( className );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set the component class to dynamic-only scope
|
||||
wxASSERT( dynamicClass->GetUsageContext()
|
||||
== COMPONENT_CLASS::USAGE::STATIC_AND_DYNAMIC );
|
||||
dynamicClass->SetUsageContext( COMPONENT_CLASS::USAGE::STATIC );
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<COMPONENT_CLASS_ASSIGNMENT_RULE>
|
||||
COMPONENT_CLASS_MANAGER::CompileAssignmentRule( const COMPONENT_CLASS_ASSIGNMENT_DATA& aAssignment )
|
||||
{
|
||||
const wxString ruleSource = aAssignment.GetAssignmentInDRCLanguage();
|
||||
|
||||
// Ignore incomplete rules (e.g. no component class name specified)
|
||||
if( ruleSource.empty() )
|
||||
return nullptr;
|
||||
|
||||
DRC_RULES_PARSER parser( ruleSource, wxT( "Component class assignment rule" ) );
|
||||
|
||||
try
|
||||
{
|
||||
std::vector<std::shared_ptr<COMPONENT_CLASS_ASSIGNMENT_RULE>> parsed;
|
||||
|
||||
WX_STRING_REPORTER reporter;
|
||||
parser.ParseComponentClassAssignmentRules( parsed, &reporter );
|
||||
|
||||
if( reporter.HasMessageOfSeverity( RPT_SEVERITY_ERROR ) )
|
||||
return nullptr;
|
||||
|
||||
if( parsed.size() != 1 )
|
||||
return nullptr;
|
||||
|
||||
return parsed[0];
|
||||
}
|
||||
catch( PARSE_ERROR& )
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const COMPONENT_CLASS*
|
||||
COMPONENT_CLASS_MANAGER::GetCombinedComponentClass( const COMPONENT_CLASS* staticClass,
|
||||
const COMPONENT_CLASS* dynamicClass )
|
||||
{
|
||||
std::unordered_set<wxString> classNames;
|
||||
|
||||
if( staticClass )
|
||||
{
|
||||
for( const COMPONENT_CLASS* compClass : staticClass->GetConstituentClasses() )
|
||||
classNames.insert( compClass->GetName() );
|
||||
}
|
||||
|
||||
if( dynamicClass )
|
||||
{
|
||||
for( const COMPONENT_CLASS* compClass : dynamicClass->GetConstituentClasses() )
|
||||
classNames.insert( compClass->GetName() );
|
||||
}
|
||||
|
||||
if( classNames.empty() )
|
||||
return GetNoneComponentClass();
|
||||
|
||||
if( classNames.size() == 1 )
|
||||
{
|
||||
wxASSERT( m_constituentClasses.contains( *classNames.begin() ) );
|
||||
return m_constituentClasses[*classNames.begin()].get();
|
||||
}
|
||||
|
||||
const std::vector<wxString> sortedClassNames = sortClassNames( classNames );
|
||||
|
||||
wxString fullCombinedName = GetFullClassNameForConstituents( sortedClassNames );
|
||||
|
||||
if( !m_effectiveClasses.contains( fullCombinedName ) )
|
||||
{
|
||||
std::unique_ptr<COMPONENT_CLASS> combinedClass = std::make_unique<COMPONENT_CLASS>(
|
||||
fullCombinedName, COMPONENT_CLASS::USAGE::EFFECTIVE );
|
||||
|
||||
for( const wxString& className : sortedClassNames )
|
||||
{
|
||||
wxASSERT( m_constituentClasses.contains( className ) );
|
||||
combinedClass->AddConstituentClass( m_constituentClasses[className].get() );
|
||||
}
|
||||
|
||||
m_effectiveClasses[fullCombinedName] = std::move( combinedClass );
|
||||
}
|
||||
|
||||
return m_effectiveClasses[fullCombinedName].get();
|
||||
}
|
||||
|
||||
|
||||
void COMPONENT_CLASS_MANAGER::InvalidateComponentClasses()
|
||||
{
|
||||
++m_ticker;
|
||||
}
|
||||
|
||||
|
||||
void COMPONENT_CLASS_MANAGER::ForceComponentClassRecalculation() const
|
||||
{
|
||||
for( const auto& footprint : m_board->Footprints() )
|
||||
{
|
||||
footprint->RecomputeComponentClass();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const COMPONENT_CLASS*
|
||||
COMPONENT_CLASS_MANAGER::GetDynamicComponentClassesForFootprint( const FOOTPRINT* footprint )
|
||||
{
|
||||
std::unordered_set<wxString> classNames;
|
||||
|
||||
// Assemble matching component class names
|
||||
for( const auto& rule : m_assignmentRules )
|
||||
{
|
||||
if( rule->Matches( footprint ) )
|
||||
classNames.insert( rule->GetComponentClass() );
|
||||
}
|
||||
|
||||
// Handle composite component classes
|
||||
const std::vector<wxString> sortedClassNames = sortClassNames( classNames );
|
||||
const wxString fullName = GetFullClassNameForConstituents( sortedClassNames );
|
||||
|
||||
// No matching component classes
|
||||
if( classNames.empty() )
|
||||
return nullptr;
|
||||
|
||||
// One matching component class
|
||||
if( classNames.size() == 1 )
|
||||
return getOrCreateConstituentClass( *classNames.begin(), COMPONENT_CLASS::USAGE::DYNAMIC );
|
||||
|
||||
// Multiple matching component classes
|
||||
return getOrCreateEffectiveClass( sortedClassNames, COMPONENT_CLASS::USAGE::DYNAMIC );
|
||||
}
|
||||
|
||||
|
||||
std::vector<wxString>
|
||||
COMPONENT_CLASS_MANAGER::sortClassNames( const std::unordered_set<wxString>& classNames )
|
||||
{
|
||||
std::vector<wxString> sortedClassNames( classNames.begin(), classNames.end() );
|
||||
|
||||
std::ranges::sort( sortedClassNames,
|
||||
[]( const wxString& str1, const wxString& str2 )
|
||||
{
|
||||
return str1.Cmp( str2 ) < 0;
|
||||
} );
|
||||
|
||||
return sortedClassNames;
|
||||
}
|
||||
|
||||
|
||||
COMPONENT_CLASS*
|
||||
COMPONENT_CLASS_MANAGER::getOrCreateConstituentClass( const wxString& aClassName,
|
||||
COMPONENT_CLASS::USAGE aContext )
|
||||
{
|
||||
if( aContext == COMPONENT_CLASS::USAGE::STATIC_AND_DYNAMIC
|
||||
|| aContext == COMPONENT_CLASS::USAGE::EFFECTIVE )
|
||||
{
|
||||
wxFAIL_MSG( "Can't create a STATIC_AND_DYNAMIC or EFFECTIVE constituent component class" );
|
||||
return m_noneClass.get();
|
||||
}
|
||||
|
||||
if( m_constituentClasses.contains( aClassName ) )
|
||||
{
|
||||
COMPONENT_CLASS* compClass = m_constituentClasses[aClassName].get();
|
||||
|
||||
if( aContext != compClass->GetUsageContext() )
|
||||
compClass->SetUsageContext( COMPONENT_CLASS::USAGE::STATIC_AND_DYNAMIC );
|
||||
|
||||
return compClass;
|
||||
}
|
||||
|
||||
std::unique_ptr<COMPONENT_CLASS> newClass =
|
||||
std::make_unique<COMPONENT_CLASS>( aClassName, aContext );
|
||||
newClass->AddConstituentClass( newClass.get() );
|
||||
|
||||
m_constituentClasses[aClassName] = std::move( newClass );
|
||||
|
||||
return m_constituentClasses[aClassName].get();
|
||||
}
|
||||
|
||||
|
||||
COMPONENT_CLASS*
|
||||
COMPONENT_CLASS_MANAGER::getOrCreateEffectiveClass( const std::vector<wxString>& aClassNames,
|
||||
COMPONENT_CLASS::USAGE aContext )
|
||||
{
|
||||
wxString fullClassName = GetFullClassNameForConstituents( aClassNames );
|
||||
|
||||
if( m_effectiveClasses.contains( fullClassName ) )
|
||||
{
|
||||
COMPONENT_CLASS* compClass = m_effectiveClasses[fullClassName].get();
|
||||
|
||||
for( COMPONENT_CLASS* constituentClass : compClass->GetConstituentClasses() )
|
||||
{
|
||||
if( constituentClass->GetUsageContext() != aContext )
|
||||
constituentClass->SetUsageContext( COMPONENT_CLASS::USAGE::STATIC_AND_DYNAMIC );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::unique_ptr<COMPONENT_CLASS> effectiveClass = std::make_unique<COMPONENT_CLASS>(
|
||||
fullClassName, COMPONENT_CLASS::USAGE::EFFECTIVE );
|
||||
|
||||
for( const wxString& className : aClassNames )
|
||||
{
|
||||
COMPONENT_CLASS* constituentClass = getOrCreateConstituentClass( className, aContext );
|
||||
effectiveClass->AddConstituentClass( constituentClass );
|
||||
}
|
||||
|
||||
m_effectiveClasses[fullClassName] = std::move( effectiveClass );
|
||||
}
|
||||
|
||||
return m_effectiveClasses[fullClassName].get();
|
||||
}
|
||||
|
||||
|
||||
std::unordered_set<wxString> COMPONENT_CLASS_MANAGER::GetClassNames() const
|
||||
{
|
||||
std::unordered_set<wxString> classNames;
|
||||
|
||||
for( const auto& className : m_constituentClasses | std::views::keys )
|
||||
classNames.insert( className );
|
||||
|
||||
return classNames;
|
||||
}
|
||||
|
||||
|
||||
void COMPONENT_CLASS_MANAGER::RebuildRequiredCaches( FOOTPRINT* aFootprint ) const
|
||||
{
|
||||
if( aFootprint )
|
||||
{
|
||||
aFootprint->BuildCourtyardCaches();
|
||||
}
|
||||
else
|
||||
{
|
||||
for( FOOTPRINT* fp : m_board->Footprints() )
|
||||
fp->BuildCourtyardCaches();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PCBNEW_COMPONENT_CLASS_MANAGER_H
|
||||
#define PCBNEW_COMPONENT_CLASS_MANAGER_H
|
||||
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <wx/string.h>
|
||||
|
||||
#include <component_classes/component_class.h>
|
||||
#include <project/component_class_settings.h>
|
||||
|
||||
|
||||
class BOARD;
|
||||
class COMPONENT_CLASS_ASSIGNMENT_RULE;
|
||||
class DRC_TOOL;
|
||||
class FOOTPRINT;
|
||||
|
||||
/**
|
||||
* A class to manage Component Classes in a board context
|
||||
*
|
||||
* This manager owns generated COMPONENT_CLASS objects, and guarantees that pointers to managed
|
||||
* objects are valid for the duration of the board lifetime. Note that, in order to maintain this
|
||||
* guarantee, there are two methods that must be called when updating the board from the netlist
|
||||
* (InitNetlistUpdate and FinishNetlistUpdate).
|
||||
*/
|
||||
class COMPONENT_CLASS_MANAGER
|
||||
{
|
||||
public:
|
||||
explicit COMPONENT_CLASS_MANAGER( BOARD* board );
|
||||
|
||||
/// @brief Gets the full effective class name for the given set of constituent classes
|
||||
static wxString
|
||||
GetFullClassNameForConstituents( const std::unordered_set<wxString>& classNames );
|
||||
|
||||
/// @brief Gets the full effective class name for the given set of constituent classes
|
||||
/// @param classNames a sorted vector of consituent class names
|
||||
static wxString GetFullClassNameForConstituents( const std::vector<wxString>& classNames );
|
||||
|
||||
/// @brief Gets an effective component class for the given constituent class names
|
||||
/// @param classNames The names of the constituent component classes
|
||||
/// @return Effective COMPONENT_CLASS object
|
||||
COMPONENT_CLASS*
|
||||
GetEffectiveStaticComponentClass( const std::unordered_set<wxString>& classNames );
|
||||
|
||||
/// Returns the unassigned component class
|
||||
const COMPONENT_CLASS* GetNoneComponentClass() const { return m_noneClass.get(); }
|
||||
|
||||
/// Prepare the manager for a board update
|
||||
/// Must be called prior to updating the PCB from the netlist
|
||||
void InitNetlistUpdate();
|
||||
|
||||
/// Cleans up the manager after a board update
|
||||
/// Must be called after updating the PCB from the netlist
|
||||
void FinishNetlistUpdate();
|
||||
|
||||
/// Fetches a read-only map of the fundamental component classes
|
||||
std::unordered_set<wxString> GetClassNames() const;
|
||||
|
||||
/// Synchronises all dynamic component class assignment rules
|
||||
/// @returns false if rules fail to parse, true if successful
|
||||
bool SyncDynamicComponentClassAssignments(
|
||||
const std::vector<COMPONENT_CLASS_ASSIGNMENT_DATA>& aAssignments,
|
||||
bool aGenerateSheetClasses, const std::unordered_set<wxString>& aNewSheetPaths );
|
||||
|
||||
/// Gets the dynamic component classes which match the given footprint
|
||||
const COMPONENT_CLASS* GetDynamicComponentClassesForFootprint( const FOOTPRINT* footprint );
|
||||
|
||||
/// Gets the combined component class with the given static and dynamic constituent component classes
|
||||
const COMPONENT_CLASS* GetCombinedComponentClass( const COMPONENT_CLASS* staticClass,
|
||||
const COMPONENT_CLASS* dynamicClass );
|
||||
|
||||
/// Forces the component class for all footprints to be recalculated. This should be called before running DRC as
|
||||
/// checking for valid component class cache entries is threadsafe, but computing them is not. Blocking during this
|
||||
/// check would be a negative performance impact for DRC computation, so we force recalculation instead.
|
||||
void ForceComponentClassRecalculation() const;
|
||||
|
||||
/// Gets the component class validity ticker
|
||||
/// Used to check validity of cached component classes
|
||||
long long int GetTicker() const { return m_ticker; }
|
||||
|
||||
/// Invalidates any caches component classes and recomputes caches if required. This will force
|
||||
/// recomputation of component classes on next access
|
||||
void InvalidateComponentClasses();
|
||||
|
||||
/// Rebuilds any caches that may be required by custom assignment rules
|
||||
/// @param fp the footprint to rebuild. If null, rebuilds all footprint caches
|
||||
void RebuildRequiredCaches( FOOTPRINT* aFootprint = nullptr ) const;
|
||||
|
||||
/// Determines whether any custom dynamic rules have a custom assignment condition
|
||||
bool HasCustomAssignmentConditions() const { return m_hasCustomAssignmentConditions; }
|
||||
|
||||
static std::shared_ptr<COMPONENT_CLASS_ASSIGNMENT_RULE>
|
||||
CompileAssignmentRule( const COMPONENT_CLASS_ASSIGNMENT_DATA& aAssignment );
|
||||
|
||||
protected:
|
||||
/// Sorts the given class names in to canonical order
|
||||
static std::vector<wxString> sortClassNames( const std::unordered_set<wxString>& classNames );
|
||||
|
||||
/// Returns a constituent component class, re-using an existing instantiation where possible
|
||||
COMPONENT_CLASS* getOrCreateConstituentClass( const wxString& aClassName,
|
||||
COMPONENT_CLASS::USAGE aContext );
|
||||
|
||||
/// Returns an effective component class for the given set of constituent class names
|
||||
/// Precondition: aClassNames is sorted by sortClassNames
|
||||
COMPONENT_CLASS* getOrCreateEffectiveClass( const std::vector<wxString>& aClassNames,
|
||||
COMPONENT_CLASS::USAGE aContext );
|
||||
|
||||
/// The board these component classes are assigned to / from
|
||||
BOARD* m_board;
|
||||
|
||||
/// The class to represent an unassigned component class
|
||||
std::shared_ptr<COMPONENT_CLASS> m_noneClass;
|
||||
|
||||
/// All individual component classes from static assignments
|
||||
std::unordered_map<wxString, std::unique_ptr<COMPONENT_CLASS>> m_constituentClasses;
|
||||
|
||||
/// Generated effective (composite) static component classes
|
||||
std::unordered_map<wxString, std::unique_ptr<COMPONENT_CLASS>> m_effectiveClasses;
|
||||
|
||||
/// Cache of in-use static component class names
|
||||
/// Used for cleanup following netlist updates
|
||||
std::unordered_set<wxString> m_staticClassNamesCache;
|
||||
|
||||
|
||||
/// Active component class assignment rules
|
||||
std::vector<std::shared_ptr<COMPONENT_CLASS_ASSIGNMENT_RULE>> m_assignmentRules;
|
||||
|
||||
/// Quick lookup of presence of custom dynamic assignment conditions
|
||||
bool m_hasCustomAssignmentConditions;
|
||||
|
||||
/// Monotonically increasing ticker to test cached component class validity
|
||||
long long int m_ticker{ 0 };
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <dialogs/panel_setup_teardrops.h>
|
||||
#include <dialogs/panel_setup_tuning_patterns.h>
|
||||
#include <dialogs/panel_setup_netclasses.h>
|
||||
#include <dialogs/panel_assign_component_classes.h>
|
||||
#include <panel_text_variables.h>
|
||||
#include <project.h>
|
||||
#include <project/project_file.h>
|
||||
@@ -47,6 +48,8 @@
|
||||
|
||||
#include "dialog_board_setup.h"
|
||||
|
||||
#include <footprint.h>
|
||||
|
||||
|
||||
#define RESOLVE_PAGE( T, pageIndex ) static_cast<T*>( m_treebook->ResolvePage( pageIndex ) )
|
||||
|
||||
@@ -185,6 +188,17 @@ DIALOG_BOARD_SETUP::DIALOG_BOARD_SETUP( PCB_EDIT_FRAME* aFrame ) :
|
||||
false );
|
||||
}, _( "Net Classes" ) );
|
||||
|
||||
m_componentClassesPage = m_treebook->GetPageCount();
|
||||
m_treebook->AddLazySubPage(
|
||||
[this]( wxWindow* aParent ) -> wxWindow*
|
||||
{
|
||||
// Construct the panel
|
||||
return new PANEL_ASSIGN_COMPONENT_CLASSES(
|
||||
aParent, m_frame, m_frame->Prj().GetProjectFile().ComponentClassSettings(),
|
||||
this );
|
||||
},
|
||||
_( "Component Classes" ) );
|
||||
|
||||
m_customRulesPage = m_treebook->GetPageCount();
|
||||
m_treebook->AddLazySubPage(
|
||||
[this]( wxWindow* aParent ) -> wxWindow*
|
||||
@@ -377,6 +391,14 @@ void DIALOG_BOARD_SETUP::onAuxiliaryAction( wxCommandEvent& aEvent )
|
||||
m_netclassesPage )->ImportSettingsFrom( otherProjectFile.m_NetSettings );
|
||||
}
|
||||
|
||||
if( importDlg.m_ComponentClassesOpt->GetValue() )
|
||||
{
|
||||
PROJECT_FILE& otherProjectFile = otherPrj->GetProjectFile();
|
||||
|
||||
RESOLVE_PAGE( PANEL_ASSIGN_COMPONENT_CLASSES, m_componentClassesPage )
|
||||
->ImportSettingsFrom( otherProjectFile.m_ComponentClassSettings );
|
||||
}
|
||||
|
||||
if( importDlg.m_TracksAndViasOpt->GetValue() )
|
||||
{
|
||||
RESOLVE_PAGE( PANEL_SETUP_TRACKS_AND_VIAS,
|
||||
|
||||
@@ -67,6 +67,7 @@ private:
|
||||
size_t m_teardropsPage;
|
||||
size_t m_tuningPatternsPage;
|
||||
size_t m_netclassesPage;
|
||||
size_t m_componentClassesPage;
|
||||
size_t m_customRulesPage;
|
||||
size_t m_severitiesPage;
|
||||
size_t m_embeddedFilesPage;
|
||||
|
||||
@@ -83,7 +83,8 @@ bool DIALOG_IMPORT_SETTINGS::UpdateImportSettingsButton()
|
||||
|| m_ConstraintsOpt->IsChecked() || m_NetclassesOpt->IsChecked()
|
||||
|| m_SeveritiesOpt->IsChecked() || m_TextAndGraphicsOpt->IsChecked()
|
||||
|| m_FormattingOpt->IsChecked() || m_TracksAndViasOpt->IsChecked()
|
||||
|| m_TuningPatternsOpt->IsChecked() || m_CustomRulesOpt->IsChecked() );
|
||||
|| m_TuningPatternsOpt->IsChecked() || m_CustomRulesOpt->IsChecked()
|
||||
|| m_ComponentClassesOpt->IsChecked() );
|
||||
|
||||
m_sdbSizer1OK->Enable( buttonEnableState );
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -75,6 +75,9 @@ DIALOG_IMPORT_SETTINGS_BASE::DIALOG_IMPORT_SETTINGS_BASE( wxWindow* parent, wxWi
|
||||
m_NetclassesOpt = new wxCheckBox( this, wxID_ANY, _("Net classes"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bLeftCol->Add( m_NetclassesOpt, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_ComponentClassesOpt = new wxCheckBox( this, wxID_ANY, _("Component classes"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bLeftCol->Add( m_ComponentClassesOpt, 0, wxBOTTOM|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
m_CustomRulesOpt = new wxCheckBox( this, wxID_ANY, _("Custom rules"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bLeftCol->Add( m_CustomRulesOpt, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
@@ -120,6 +123,7 @@ DIALOG_IMPORT_SETTINGS_BASE::DIALOG_IMPORT_SETTINGS_BASE( wxWindow* parent, wxWi
|
||||
m_TracksAndViasOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
|
||||
m_TuningPatternsOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
|
||||
m_NetclassesOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
|
||||
m_ComponentClassesOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
|
||||
m_CustomRulesOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
|
||||
m_SeveritiesOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
|
||||
m_selectAllButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnSelectAll ), NULL, this );
|
||||
@@ -136,6 +140,7 @@ DIALOG_IMPORT_SETTINGS_BASE::~DIALOG_IMPORT_SETTINGS_BASE()
|
||||
m_TracksAndViasOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
|
||||
m_TuningPatternsOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
|
||||
m_NetclassesOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
|
||||
m_ComponentClassesOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
|
||||
m_CustomRulesOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
|
||||
m_SeveritiesOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnCheckboxClicked ), NULL, this );
|
||||
m_selectAllButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_SETTINGS_BASE::OnSelectAll ), NULL, this );
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -64,6 +64,7 @@ class DIALOG_IMPORT_SETTINGS_BASE : public DIALOG_SHIM
|
||||
wxCheckBox* m_TeardropsOpt;
|
||||
wxCheckBox* m_TuningPatternsOpt;
|
||||
wxCheckBox* m_NetclassesOpt;
|
||||
wxCheckBox* m_ComponentClassesOpt;
|
||||
wxCheckBox* m_CustomRulesOpt;
|
||||
wxCheckBox* m_SeveritiesOpt;
|
||||
|
||||
|
||||
@@ -250,8 +250,8 @@ bool DIALOG_RULE_AREA_PROPERTIES::TransferDataToWindow()
|
||||
// Fetch component classes
|
||||
std::set<wxString> classNames;
|
||||
|
||||
for( const auto& [k, v] : m_board->GetComponentClassManager().GetClasses() )
|
||||
classNames.insert( k );
|
||||
for( const wxString& className : m_board->GetComponentClassManager().GetClassNames() )
|
||||
classNames.insert( className );
|
||||
|
||||
for( const wxString& sourceName : classNames )
|
||||
m_placementProperties->m_componentClassCombo->Append( sourceName );
|
||||
|
||||
@@ -0,0 +1,788 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <dialogs/panel_assign_component_classes.h>
|
||||
|
||||
#include <bitmaps.h>
|
||||
#include <board.h>
|
||||
#include <component_classes/component_class_assignment_rule.h>
|
||||
#include <component_classes/component_class_manager.h>
|
||||
#include <footprint.h>
|
||||
#include <kiway.h>
|
||||
#include <pcb_edit_frame.h>
|
||||
#include <project/project_file.h>
|
||||
#include <tool/selection_tool.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tools/pcb_selection_tool.h>
|
||||
#include <widgets/paged_dialog.h>
|
||||
#include <widgets/std_bitmap_button.h>
|
||||
|
||||
|
||||
/**************************************************************************************************
|
||||
*
|
||||
* PANEL_ASSIGN_COMPONENT_CLASSES implementation
|
||||
* This is the top-level panel for component class configuration
|
||||
*
|
||||
*************************************************************************************************/
|
||||
|
||||
PANEL_ASSIGN_COMPONENT_CLASSES::PANEL_ASSIGN_COMPONENT_CLASSES(
|
||||
wxWindow* aParentWindow, PCB_EDIT_FRAME* aFrame,
|
||||
std::shared_ptr<COMPONENT_CLASS_SETTINGS> aSettings, DIALOG_SHIM* aDlg ) :
|
||||
PANEL_ASSIGN_COMPONENT_CLASSES_BASE( aParentWindow ), m_dlg( aDlg ), m_frame( aFrame ),
|
||||
m_componentClassSettings( std::move( aSettings ) ),
|
||||
m_assignmentsList( static_cast<wxBoxSizer*>( m_assignmentsScrollWindow->GetSizer() ) )
|
||||
{
|
||||
// Load footprint fields and sheet names
|
||||
const BOARD* board = dynamic_cast<BOARD*>( m_frame->GetModel() );
|
||||
std::set<wxString> fieldsSet;
|
||||
std::set<wxString> sheetsSet;
|
||||
|
||||
for( const FOOTPRINT* fp : board->Footprints() )
|
||||
{
|
||||
wxString sheetName = fp->GetSheetname();
|
||||
|
||||
if( !sheetName.empty() )
|
||||
{
|
||||
sheetName.Replace( wxT( "\"" ), wxT( "" ) );
|
||||
sheetName.Replace( wxT( "'" ), wxT( "" ) );
|
||||
sheetsSet.insert( fp->GetSheetname() );
|
||||
}
|
||||
|
||||
for( const PCB_FIELD* field : fp->GetFields() )
|
||||
fieldsSet.insert( field->GetName() );
|
||||
}
|
||||
|
||||
// Sort field names
|
||||
std::vector<wxString> fieldNames( fieldsSet.begin(), fieldsSet.end() );
|
||||
std::ranges::sort( fieldNames,
|
||||
[]( const wxString& a, const wxString& b )
|
||||
{
|
||||
return a.Cmp( b ) < 0;
|
||||
} );
|
||||
|
||||
m_fieldNames = std::move( fieldNames );
|
||||
|
||||
// Sort sheet names
|
||||
std::vector<wxString> sheetNames( sheetsSet.begin(), sheetsSet.end() );
|
||||
std::ranges::sort( sheetNames,
|
||||
[]( const wxString& a, const wxString& b )
|
||||
{
|
||||
return a.Cmp( b ) < 0;
|
||||
} );
|
||||
|
||||
m_sheetNames = std::move( sheetNames );
|
||||
|
||||
// Get references of currently selected items
|
||||
std::set<wxString> refsSet;
|
||||
|
||||
for( const EDA_ITEM* item : m_frame->GetCurrentSelection() )
|
||||
{
|
||||
if( item->Type() != PCB_FOOTPRINT_T )
|
||||
continue;
|
||||
|
||||
const FOOTPRINT* fp = static_cast<const FOOTPRINT*>( item );
|
||||
wxString ref = fp->GetReferenceAsString();
|
||||
refsSet.insert( ref );
|
||||
}
|
||||
|
||||
std::vector<wxString> refs( refsSet.begin(), refsSet.end() );
|
||||
std::ranges::sort( refs,
|
||||
[]( const wxString& a, const wxString& b )
|
||||
{
|
||||
return a.Cmp( b ) < 0;
|
||||
} );
|
||||
|
||||
m_selectionRefs = std::move( refs );
|
||||
}
|
||||
|
||||
|
||||
PANEL_ASSIGN_COMPONENT_CLASSES::~PANEL_ASSIGN_COMPONENT_CLASSES()
|
||||
{
|
||||
BOARD* board = dynamic_cast<BOARD*>( m_frame->GetModel() );
|
||||
PCB_SELECTION_TOOL* selTool = m_frame->GetToolManager()->GetTool<PCB_SELECTION_TOOL>();
|
||||
|
||||
for( FOOTPRINT* fp : board->Footprints() )
|
||||
selTool->UnbrightenItem( fp );
|
||||
|
||||
m_frame->GetCanvas()->Refresh();
|
||||
}
|
||||
|
||||
|
||||
bool PANEL_ASSIGN_COMPONENT_CLASSES::TransferDataToWindow()
|
||||
{
|
||||
// Load sheet-level settings
|
||||
m_assignSheetClasses->SetValue( m_componentClassSettings->GetEnableSheetComponentClasses() );
|
||||
|
||||
// Load dynamic component class assignments
|
||||
for( const COMPONENT_CLASS_ASSIGNMENT_DATA& assignmentData :
|
||||
m_componentClassSettings->GetComponentClassAssignments() )
|
||||
{
|
||||
PANEL_COMPONENT_CLASS_ASSIGNMENT* assignment = addAssignment();
|
||||
assignment->SetComponentClass( assignmentData.GetComponentClass() );
|
||||
assignment->SetConditionsOperator( assignmentData.GetConditionsOperator() );
|
||||
|
||||
for( const auto& [conditionType, conditionData] : assignmentData.GetConditions() )
|
||||
{
|
||||
CONDITION_DATA* match = assignment->AddCondition( conditionType );
|
||||
match->SetPrimaryField( conditionData.first );
|
||||
match->SetSecondaryField( conditionData.second );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PANEL_ASSIGN_COMPONENT_CLASSES::TransferDataFromWindow()
|
||||
{
|
||||
if( !Validate() )
|
||||
return false;
|
||||
|
||||
// Save sheet-level settings
|
||||
m_componentClassSettings->SetEnableSheetComponentClasses( m_assignSheetClasses->GetValue() );
|
||||
|
||||
// Save dynamic component class assignments
|
||||
m_componentClassSettings->ClearComponentClassAssignments();
|
||||
|
||||
for( const auto assignment : m_assignments )
|
||||
{
|
||||
COMPONENT_CLASS_ASSIGNMENT_DATA assignmentData = assignment->GenerateAssignmentData();
|
||||
m_componentClassSettings->AddComponentClassAssignment( assignmentData );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PANEL_ASSIGN_COMPONENT_CLASSES::Validate()
|
||||
{
|
||||
PCB_EDIT_FRAME* frame = GetFrame();
|
||||
BOARD* board = dynamic_cast<BOARD*>( frame->GetModel() );
|
||||
|
||||
frame->GetCanvas()->Refresh();
|
||||
|
||||
for( PANEL_COMPONENT_CLASS_ASSIGNMENT* assignment : m_assignments )
|
||||
{
|
||||
const COMPONENT_CLASS_ASSIGNMENT_DATA assignmentData = assignment->GenerateAssignmentData();
|
||||
const std::shared_ptr<COMPONENT_CLASS_ASSIGNMENT_RULE> rule =
|
||||
board->GetComponentClassManager().CompileAssignmentRule( assignmentData );
|
||||
|
||||
if( !rule )
|
||||
{
|
||||
const wxString msg = wxString::Format(
|
||||
_( "Error with conditions for component class assignment %s" ),
|
||||
assignment->GetComponentClass() );
|
||||
PAGED_DIALOG::GetDialog( this )->SetError( msg, this, assignment );
|
||||
scrollToAssignment( assignment );
|
||||
assignment->SetFocus();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_ASSIGN_COMPONENT_CLASSES::OnAddAssignmentClick( wxCommandEvent& event )
|
||||
{
|
||||
PANEL_COMPONENT_CLASS_ASSIGNMENT* assignment = addAssignment();
|
||||
scrollToAssignment( assignment );
|
||||
}
|
||||
|
||||
|
||||
PANEL_COMPONENT_CLASS_ASSIGNMENT* PANEL_ASSIGN_COMPONENT_CLASSES::addAssignment()
|
||||
{
|
||||
PANEL_COMPONENT_CLASS_ASSIGNMENT* assignmentPanel =
|
||||
new PANEL_COMPONENT_CLASS_ASSIGNMENT( m_assignmentsScrollWindow, this, m_dlg );
|
||||
|
||||
#if __OSX__
|
||||
m_assignmentsList->Add( assignmentPanel, 0, wxEXPAND, 5 );
|
||||
#else
|
||||
m_assignmentsList->Add( assignmentPanel, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5 );
|
||||
#endif
|
||||
|
||||
Layout();
|
||||
|
||||
m_assignments.push_back( assignmentPanel );
|
||||
|
||||
return assignmentPanel;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_ASSIGN_COMPONENT_CLASSES::scrollToAssignment(
|
||||
const PANEL_COMPONENT_CLASS_ASSIGNMENT* aAssignment ) const
|
||||
{
|
||||
const wxPoint viewStart = m_assignmentsScrollWindow->GetViewStart();
|
||||
const wxPoint panelPosition = aAssignment->GetPosition();
|
||||
const wxSize panelSize = aAssignment->GetClientSize();
|
||||
|
||||
m_assignmentsScrollWindow->Scroll( viewStart.x, panelPosition.y + panelSize.y );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_ASSIGN_COMPONENT_CLASSES::RemoveAssignment( PANEL_COMPONENT_CLASS_ASSIGNMENT* aPanel )
|
||||
{
|
||||
m_assignments.erase( std::ranges::find( m_assignments, aPanel ) );
|
||||
m_assignmentsList->Detach( aPanel );
|
||||
aPanel->Destroy();
|
||||
Layout();
|
||||
}
|
||||
|
||||
|
||||
void PANEL_ASSIGN_COMPONENT_CLASSES::ImportSettingsFrom(
|
||||
const std::shared_ptr<COMPONENT_CLASS_SETTINGS>& aOtherSettings )
|
||||
{
|
||||
std::shared_ptr<COMPONENT_CLASS_SETTINGS> savedSettings = m_componentClassSettings;
|
||||
|
||||
m_componentClassSettings = aOtherSettings;
|
||||
TransferDataToWindow();
|
||||
|
||||
m_componentClassSettings = std::move( savedSettings );
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************************************
|
||||
*
|
||||
* CONDITION_DATA implementation
|
||||
* Provides a common interface for all condition panel types
|
||||
*
|
||||
*************************************************************************************************/
|
||||
|
||||
wxString CONDITION_DATA::GetPrimaryField() const
|
||||
{
|
||||
wxString data = m_primaryCtrl->GetValue();
|
||||
data.Trim( true );
|
||||
data.Trim( false );
|
||||
|
||||
if( m_conditionType != COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::CUSTOM )
|
||||
{
|
||||
data.Replace( wxT( "\"" ), wxT( "" ) );
|
||||
data.Replace( wxT( "'" ), wxT( "" ) );
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
void CONDITION_DATA::SetPrimaryField( const wxString& aVal )
|
||||
{
|
||||
m_primaryCtrl->SetValue( aVal );
|
||||
}
|
||||
|
||||
|
||||
wxString CONDITION_DATA::GetSecondaryField() const
|
||||
{
|
||||
if( !m_secondaryCtrl )
|
||||
return wxEmptyString;
|
||||
|
||||
wxString data = m_secondaryCtrl->GetValue();
|
||||
data.Trim( true );
|
||||
data.Trim( false );
|
||||
|
||||
if( m_conditionType != COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::CUSTOM )
|
||||
{
|
||||
data.Replace( wxT( "\"" ), wxT( "" ) );
|
||||
data.Replace( wxT( "'" ), wxT( "" ) );
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
void CONDITION_DATA::SetSecondaryField( const wxString& aVal )
|
||||
{
|
||||
if( m_secondaryCtrl )
|
||||
m_secondaryCtrl->SetValue( aVal );
|
||||
};
|
||||
|
||||
/**************************************************************************************************
|
||||
*
|
||||
* PANEL_COMPONENT_CLASS_ASSIGNMENT implementation
|
||||
* This is the dynamically-added panel for each component class assignment rule set
|
||||
*
|
||||
*************************************************************************************************/
|
||||
|
||||
PANEL_COMPONENT_CLASS_ASSIGNMENT::PANEL_COMPONENT_CLASS_ASSIGNMENT(
|
||||
wxWindow* aParent, PANEL_ASSIGN_COMPONENT_CLASSES* aPanelParent, DIALOG_SHIM* aDlg ) :
|
||||
PANEL_COMPONENT_CLASS_ASSIGNMENT_BASE( aParent ), m_parentPanel( aPanelParent ),
|
||||
m_matchesList( static_cast<wxStaticBoxSizer*>( GetSizer() ) ), m_dlg( aDlg )
|
||||
{
|
||||
m_buttonAddCondition->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
|
||||
m_buttonDeleteAssignment->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
|
||||
m_buttonHighlightItems->SetBitmap( KiBitmapBundle( BITMAPS::net_highlight ) );
|
||||
|
||||
Connect( wxEVT_MENU, wxCommandEventHandler( PANEL_COMPONENT_CLASS_ASSIGNMENT::onMenu ), nullptr,
|
||||
this );
|
||||
}
|
||||
|
||||
|
||||
PANEL_COMPONENT_CLASS_ASSIGNMENT::~PANEL_COMPONENT_CLASS_ASSIGNMENT()
|
||||
{
|
||||
Disconnect( wxEVT_MENU, wxCommandEventHandler( PANEL_COMPONENT_CLASS_ASSIGNMENT::onMenu ),
|
||||
nullptr, this );
|
||||
}
|
||||
|
||||
|
||||
COMPONENT_CLASS_ASSIGNMENT_DATA PANEL_COMPONENT_CLASS_ASSIGNMENT::GenerateAssignmentData() const
|
||||
{
|
||||
COMPONENT_CLASS_ASSIGNMENT_DATA assignmentData;
|
||||
assignmentData.SetComponentClass( GetComponentClass() );
|
||||
assignmentData.SetConditionsOperation( GetConditionsOperator() );
|
||||
|
||||
for( const auto& condition : GetConditions() )
|
||||
{
|
||||
assignmentData.SetCondition( condition->GetConditionType(), condition->GetPrimaryField(),
|
||||
condition->GetSecondaryField() );
|
||||
}
|
||||
|
||||
return assignmentData;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_COMPONENT_CLASS_ASSIGNMENT::OnAddConditionClick( wxCommandEvent& event )
|
||||
{
|
||||
auto hasCondition = [this]( const COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE aCondition )
|
||||
{
|
||||
return m_conditionTypes.contains( aCondition );
|
||||
};
|
||||
|
||||
wxMenu menu;
|
||||
menu.Append( ID_REFERENCE, _( "Reference..." ) );
|
||||
menu.Append( ID_FOOTPRINT, _( "Footprint..." ) );
|
||||
menu.Append( ID_SIDE, _( "Side..." ) );
|
||||
menu.Append( ID_ROTATION, _( "Rotation..." ) );
|
||||
menu.Append( ID_FOOTPRINT_FIELD, _( "Footprint Field..." ) );
|
||||
menu.Append( ID_SHEET_NAME, _( "Sheet Name..." ) );
|
||||
menu.Append( ID_CUSTOM, _( "Custom..." ) );
|
||||
menu.Enable( ID_REFERENCE,
|
||||
!hasCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::REFERENCE ) );
|
||||
menu.Enable( ID_FOOTPRINT,
|
||||
!hasCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::FOOTPRINT ) );
|
||||
menu.Enable( ID_SIDE, !hasCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::SIDE ) );
|
||||
menu.Enable( ID_ROTATION,
|
||||
!hasCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::ROTATION ) );
|
||||
menu.Enable(
|
||||
ID_FOOTPRINT_FIELD,
|
||||
!hasCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::FOOTPRINT_FIELD ) );
|
||||
menu.Enable( ID_CUSTOM,
|
||||
!hasCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::CUSTOM ) );
|
||||
menu.Enable( ID_SHEET_NAME,
|
||||
!hasCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::SHEET_NAME ) );
|
||||
PopupMenu( &menu );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_COMPONENT_CLASS_ASSIGNMENT::OnDeleteAssignmentClick( wxCommandEvent& event )
|
||||
{
|
||||
m_parentPanel->RemoveAssignment( this );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_COMPONENT_CLASS_ASSIGNMENT::SetComponentClass( const wxString& aComponentClass ) const
|
||||
{
|
||||
m_componentClass->SetValue( aComponentClass );
|
||||
}
|
||||
|
||||
|
||||
const wxString PANEL_COMPONENT_CLASS_ASSIGNMENT::GetComponentClass() const
|
||||
{
|
||||
return m_componentClass->GetValue();
|
||||
}
|
||||
|
||||
|
||||
void PANEL_COMPONENT_CLASS_ASSIGNMENT::onMenu( wxCommandEvent& aEvent )
|
||||
{
|
||||
switch( aEvent.GetId() )
|
||||
{
|
||||
case ID_REFERENCE:
|
||||
AddCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::REFERENCE );
|
||||
break;
|
||||
case ID_FOOTPRINT:
|
||||
AddCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::FOOTPRINT );
|
||||
break;
|
||||
case ID_SIDE: AddCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::SIDE ); break;
|
||||
case ID_ROTATION:
|
||||
AddCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::ROTATION );
|
||||
break;
|
||||
case ID_FOOTPRINT_FIELD:
|
||||
AddCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::FOOTPRINT_FIELD );
|
||||
break;
|
||||
case ID_CUSTOM: AddCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::CUSTOM ); break;
|
||||
case ID_SHEET_NAME:
|
||||
AddCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::SHEET_NAME );
|
||||
break;
|
||||
|
||||
default: wxFAIL_MSG( wxT( "Unknown ID in context menu event" ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CONDITION_DATA* PANEL_COMPONENT_CLASS_ASSIGNMENT::AddCondition(
|
||||
const COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE aCondition )
|
||||
{
|
||||
wxASSERT_MSG( !m_conditionTypes.contains( aCondition ), "Condition type already exists" );
|
||||
|
||||
wxPanel* panelToAdd = nullptr;
|
||||
|
||||
switch( aCondition )
|
||||
{
|
||||
case COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::REFERENCE:
|
||||
{
|
||||
PANEL_COMPONENT_CLASS_CONDITION_REFERENCE* refsPanel =
|
||||
new PANEL_COMPONENT_CLASS_CONDITION_REFERENCE( this );
|
||||
refsPanel->SetSelectionRefs( m_parentPanel->GetSelectionRefs() );
|
||||
panelToAdd = refsPanel;
|
||||
m_conditionTypes.insert( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::REFERENCE );
|
||||
break;
|
||||
}
|
||||
case COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::FOOTPRINT:
|
||||
{
|
||||
panelToAdd = new PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT( this, m_dlg );
|
||||
m_conditionTypes.insert( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::FOOTPRINT );
|
||||
break;
|
||||
}
|
||||
case COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::SIDE:
|
||||
{
|
||||
panelToAdd = new PANEL_COMPONENT_CLASS_CONDITION_SIDE( this );
|
||||
m_conditionTypes.insert( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::SIDE );
|
||||
break;
|
||||
}
|
||||
case COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::ROTATION:
|
||||
{
|
||||
panelToAdd = new PANEL_COMPONENT_CLASS_CONDITION_ROTATION( this );
|
||||
m_conditionTypes.insert( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::ROTATION );
|
||||
break;
|
||||
}
|
||||
case COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::FOOTPRINT_FIELD:
|
||||
{
|
||||
PANEL_COMPONENT_CLASS_CONDITION_FIELD* fieldPanel =
|
||||
new PANEL_COMPONENT_CLASS_CONDITION_FIELD( this );
|
||||
fieldPanel->SetFieldsList( m_parentPanel->GetFieldNames() );
|
||||
panelToAdd = fieldPanel;
|
||||
m_conditionTypes.insert( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::FOOTPRINT_FIELD );
|
||||
break;
|
||||
}
|
||||
case COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::CUSTOM:
|
||||
{
|
||||
panelToAdd = new PANEL_COMPONENT_CLASS_CONDITION_CUSTOM( this );
|
||||
m_conditionTypes.insert( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::CUSTOM );
|
||||
break;
|
||||
}
|
||||
case COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::SHEET_NAME:
|
||||
{
|
||||
PANEL_COMPONENT_CLASS_CONDITION_SHEET* sheetPanel =
|
||||
new PANEL_COMPONENT_CLASS_CONDITION_SHEET( this );
|
||||
sheetPanel->SetSheetsList( m_parentPanel->GetSheetNames() );
|
||||
panelToAdd = sheetPanel;
|
||||
m_conditionTypes.insert( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::SHEET_NAME );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const size_t numItems = m_matchesList->GetItemCount();
|
||||
m_matchesList->Insert( numItems - 1, panelToAdd, 0, wxEXPAND | wxTOP, 5 );
|
||||
Layout();
|
||||
GetParent()->Layout();
|
||||
m_parentPanel->Layout();
|
||||
|
||||
CONDITION_DATA* conditionIface = dynamic_cast<CONDITION_DATA*>( panelToAdd );
|
||||
m_matches.push_back( conditionIface );
|
||||
|
||||
return conditionIface;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_COMPONENT_CLASS_ASSIGNMENT::RemoveCondition( wxPanel* aMatch )
|
||||
{
|
||||
if( CONDITION_DATA* matchData = dynamic_cast<CONDITION_DATA*>( aMatch ) )
|
||||
{
|
||||
m_conditionTypes.erase( matchData->GetConditionType() );
|
||||
m_matches.erase( std::ranges::find( m_matches, matchData ) );
|
||||
}
|
||||
|
||||
m_matchesList->Detach( aMatch );
|
||||
aMatch->Destroy();
|
||||
Layout();
|
||||
m_parentPanel->Layout();
|
||||
}
|
||||
|
||||
|
||||
void PANEL_COMPONENT_CLASS_ASSIGNMENT::SetConditionsOperator(
|
||||
const COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITIONS_OPERATOR aCondition ) const
|
||||
{
|
||||
if( aCondition == COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITIONS_OPERATOR::ALL )
|
||||
{
|
||||
m_radioAll->SetValue( true );
|
||||
m_radioAny->SetValue( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_radioAll->SetValue( false );
|
||||
m_radioAny->SetValue( true );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITIONS_OPERATOR
|
||||
PANEL_COMPONENT_CLASS_ASSIGNMENT::GetConditionsOperator() const
|
||||
{
|
||||
if( m_radioAll->GetValue() == true )
|
||||
return COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITIONS_OPERATOR::ALL;
|
||||
|
||||
return COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITIONS_OPERATOR::ANY;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_COMPONENT_CLASS_ASSIGNMENT::OnHighlightItemsClick( wxCommandEvent& event )
|
||||
{
|
||||
PCB_EDIT_FRAME* frame = m_parentPanel->GetFrame();
|
||||
BOARD* board = dynamic_cast<BOARD*>( frame->GetModel() );
|
||||
PCB_SELECTION_TOOL* selTool = frame->GetToolManager()->GetTool<PCB_SELECTION_TOOL>();
|
||||
|
||||
const COMPONENT_CLASS_ASSIGNMENT_DATA assignment = GenerateAssignmentData();
|
||||
const std::shared_ptr<COMPONENT_CLASS_ASSIGNMENT_RULE> rule =
|
||||
board->GetComponentClassManager().CompileAssignmentRule( assignment );
|
||||
|
||||
if( !rule )
|
||||
return;
|
||||
|
||||
for( FOOTPRINT* fp : board->Footprints() )
|
||||
{
|
||||
if( rule->Matches( fp ) )
|
||||
selTool->BrightenItem( fp );
|
||||
else
|
||||
selTool->UnbrightenItem( fp );
|
||||
}
|
||||
|
||||
frame->GetCanvas()->Refresh();
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************************************
|
||||
*
|
||||
* PANEL_COMPONENT_CLASS_CONDITION_* implementations
|
||||
* These are the dynamically-added panels for each condition / match type
|
||||
*
|
||||
*************************************************************************************************/
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_REFERENCE::PANEL_COMPONENT_CLASS_CONDITION_REFERENCE(
|
||||
wxWindow* aParent ) :
|
||||
PANEL_COMPONENT_CLASS_CONDITION_REFERENCE_BASE( aParent ),
|
||||
CONDITION_DATA( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::REFERENCE, m_refs ),
|
||||
m_panelParent( static_cast<PANEL_COMPONENT_CLASS_ASSIGNMENT*>( aParent ) )
|
||||
{
|
||||
m_title->SetMinSize( { GetTextExtent( _( "Footprint Field:" ) ).x, -1 } );
|
||||
|
||||
m_buttonImportRefs->SetBitmap( KiBitmapBundle( BITMAPS::config ) );
|
||||
m_buttonDeleteMatch->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
|
||||
|
||||
Connect( wxEVT_MENU, wxCommandEventHandler( PANEL_COMPONENT_CLASS_CONDITION_REFERENCE::onMenu ),
|
||||
nullptr, this );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_COMPONENT_CLASS_CONDITION_REFERENCE::OnDeleteConditionClick( wxCommandEvent& event )
|
||||
{
|
||||
m_panelParent->RemoveCondition( this );
|
||||
|
||||
Disconnect( wxEVT_MENU,
|
||||
wxCommandEventHandler( PANEL_COMPONENT_CLASS_CONDITION_REFERENCE::onMenu ), nullptr,
|
||||
this );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_COMPONENT_CLASS_CONDITION_REFERENCE::OnImportRefsClick( wxCommandEvent& event )
|
||||
{
|
||||
wxMenu menu;
|
||||
menu.Append( ID_IMPORT_REFS, _( "Import references from selection" ) );
|
||||
menu.Enable( ID_IMPORT_REFS, !m_selectionRefs.empty() );
|
||||
PopupMenu( &menu );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_COMPONENT_CLASS_CONDITION_REFERENCE::onMenu( wxCommandEvent& aEvent )
|
||||
{
|
||||
if( aEvent.GetId() != ID_IMPORT_REFS )
|
||||
wxFAIL_MSG( wxT( "Unknown ID in context menu event" ) );
|
||||
|
||||
if( m_selectionRefs.empty() )
|
||||
return;
|
||||
|
||||
wxString refs = m_selectionRefs[0];
|
||||
|
||||
for( size_t i = 1; i < m_selectionRefs.size(); i++ )
|
||||
{
|
||||
refs += wxT( "," );
|
||||
refs += m_selectionRefs[i];
|
||||
}
|
||||
|
||||
m_refs->SetValue( refs );
|
||||
}
|
||||
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT::PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT(
|
||||
wxWindow* aParent, DIALOG_SHIM* aDlg ) :
|
||||
PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT_BASE( aParent ),
|
||||
CONDITION_DATA( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::FOOTPRINT, m_footprint ),
|
||||
m_panelParent( static_cast<PANEL_COMPONENT_CLASS_ASSIGNMENT*>( aParent ) ), m_dlg( aDlg )
|
||||
{
|
||||
m_title->SetMinSize( { GetTextExtent( _( "Footprint Field:" ) ).x, -1 } );
|
||||
|
||||
m_buttonDeleteMatch->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
|
||||
m_buttonShowLibrary->SetBitmap( KiBitmapBundle( BITMAPS::small_library ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT::OnDeleteConditionClick( wxCommandEvent& event )
|
||||
{
|
||||
m_panelParent->RemoveCondition( this );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT::OnShowLibraryClick( wxCommandEvent& event )
|
||||
{
|
||||
wxString fpId = m_footprint->GetValue();
|
||||
|
||||
if( KIWAY_PLAYER* frame = m_dlg->Kiway().Player( FRAME_FOOTPRINT_CHOOSER, true, m_dlg ) )
|
||||
{
|
||||
if( frame->ShowModal( &fpId, this ) )
|
||||
{
|
||||
m_footprint->SetValue( fpId );
|
||||
}
|
||||
|
||||
frame->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_SIDE::PANEL_COMPONENT_CLASS_CONDITION_SIDE( wxWindow* aParent ) :
|
||||
PANEL_COMPONENT_CLASS_CONDITION_SIDE_BASE( aParent ),
|
||||
CONDITION_DATA( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::SIDE, m_side ),
|
||||
m_panelParent( static_cast<PANEL_COMPONENT_CLASS_ASSIGNMENT*>( aParent ) )
|
||||
{
|
||||
m_title->SetMinSize( { GetTextExtent( _( "Footprint Field:" ) ).x, -1 } );
|
||||
|
||||
m_buttonDeleteMatch->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
|
||||
m_side->Append( wxT( "Any" ) );
|
||||
m_side->Append( wxT( "Front" ) );
|
||||
m_side->Append( wxT( "Back" ) );
|
||||
m_side->SetValue( wxT( "Any" ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_COMPONENT_CLASS_CONDITION_SIDE::OnDeleteConditionClick( wxCommandEvent& event )
|
||||
{
|
||||
m_panelParent->RemoveCondition( this );
|
||||
}
|
||||
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_ROTATION::PANEL_COMPONENT_CLASS_CONDITION_ROTATION(
|
||||
wxWindow* aParent ) :
|
||||
PANEL_COMPONENT_CLASS_CONDITION_ROTATION_BASE( aParent ),
|
||||
CONDITION_DATA( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::ROTATION, m_rotation ),
|
||||
m_panelParent( static_cast<PANEL_COMPONENT_CLASS_ASSIGNMENT*>( aParent ) )
|
||||
{
|
||||
m_title->SetMinSize( { GetTextExtent( _( "Footprint Field:" ) ).x, -1 } );
|
||||
m_rotUnit->SetLabel( wxT( "°" ) );
|
||||
|
||||
m_buttonDeleteMatch->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
|
||||
m_rotation->Append( wxT( "Any" ) );
|
||||
m_rotation->Append( wxT( "0" ) );
|
||||
m_rotation->Append( wxT( "90" ) );
|
||||
m_rotation->Append( wxT( "180" ) );
|
||||
m_rotation->Append( wxT( "-90" ) );
|
||||
m_rotation->SetValue( wxT( "Any" ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_COMPONENT_CLASS_CONDITION_ROTATION::OnDeleteConditionClick( wxCommandEvent& event )
|
||||
{
|
||||
m_panelParent->RemoveCondition( this );
|
||||
}
|
||||
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_FIELD::PANEL_COMPONENT_CLASS_CONDITION_FIELD( wxWindow* aParent ) :
|
||||
PANEL_COMPONENT_CLASS_CONDITION_FIELD_BASE( aParent ),
|
||||
CONDITION_DATA( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::FOOTPRINT_FIELD,
|
||||
m_fieldName, m_fieldValue ),
|
||||
m_panelParent( static_cast<PANEL_COMPONENT_CLASS_ASSIGNMENT*>( aParent ) )
|
||||
{
|
||||
m_title->SetMinSize( { GetTextExtent( _( "Footprint Field:" ) ).x, -1 } );
|
||||
|
||||
m_buttonDeleteMatch->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_COMPONENT_CLASS_CONDITION_FIELD::OnDeleteConditionClick( wxCommandEvent& event )
|
||||
{
|
||||
m_panelParent->RemoveCondition( this );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_COMPONENT_CLASS_CONDITION_FIELD::SetFieldsList( const std::vector<wxString>& aFields )
|
||||
{
|
||||
m_fieldName->Append( aFields );
|
||||
}
|
||||
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_CUSTOM::PANEL_COMPONENT_CLASS_CONDITION_CUSTOM(
|
||||
wxWindow* aParent ) :
|
||||
PANEL_COMPONENT_CLASS_CONDITION_CUSTOM_BASE( aParent ),
|
||||
CONDITION_DATA( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::CUSTOM,
|
||||
m_customCondition ),
|
||||
m_panelParent( static_cast<PANEL_COMPONENT_CLASS_ASSIGNMENT*>( aParent ) )
|
||||
{
|
||||
m_title->SetMinSize( { GetTextExtent( _( "Footprint Field:" ) ).x, -1 } );
|
||||
|
||||
m_buttonDeleteMatch->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_COMPONENT_CLASS_CONDITION_CUSTOM::OnDeleteConditionClick( wxCommandEvent& event )
|
||||
{
|
||||
m_panelParent->RemoveCondition( this );
|
||||
}
|
||||
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_SHEET::PANEL_COMPONENT_CLASS_CONDITION_SHEET( wxWindow* aParent ) :
|
||||
PANEL_COMPONENT_CLASS_CONDITION_SHEET_BASE( aParent ),
|
||||
CONDITION_DATA( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::SHEET_NAME, m_sheetName ),
|
||||
m_panelParent( static_cast<PANEL_COMPONENT_CLASS_ASSIGNMENT*>( aParent ) )
|
||||
{
|
||||
m_title->SetMinSize( { GetTextExtent( _( "Footprint Field:" ) ).x, -1 } );
|
||||
|
||||
m_buttonDeleteMatch->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_COMPONENT_CLASS_CONDITION_SHEET::OnDeleteConditionClick( wxCommandEvent& event )
|
||||
{
|
||||
m_panelParent->RemoveCondition( this );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_COMPONENT_CLASS_CONDITION_SHEET::SetSheetsList( const std::vector<wxString>& aSheets )
|
||||
{
|
||||
m_sheetName->Append( aSheets );
|
||||
}
|
||||
@@ -0,0 +1,471 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "widgets/std_bitmap_button.h"
|
||||
|
||||
#include "panel_assign_component_classes_base.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PANEL_ASSIGN_COMPONENT_CLASSES_BASE::PANEL_ASSIGN_COMPONENT_CLASSES_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
|
||||
{
|
||||
wxBoxSizer* bSizerMain;
|
||||
bSizerMain = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_assignSheetClasses = new wxCheckBox( this, wxID_ANY, _("Assign component class per sheet"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizerMain->Add( m_assignSheetClasses, 0, wxALL, 5 );
|
||||
|
||||
m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
bSizerMain->Add( m_staticline1, 0, wxEXPAND | wxALL, 5 );
|
||||
|
||||
wxFlexGridSizer* fgSizer8;
|
||||
fgSizer8 = new wxFlexGridSizer( 0, 3, 0, 0 );
|
||||
fgSizer8->AddGrowableCol( 1 );
|
||||
fgSizer8->SetFlexibleDirection( wxHORIZONTAL );
|
||||
fgSizer8->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_staticText3 = new wxStaticText( this, wxID_ANY, _("Custom Assignments:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText3->Wrap( -1 );
|
||||
fgSizer8->Add( m_staticText3, 0, wxALL, 5 );
|
||||
|
||||
|
||||
fgSizer8->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_btnAddAssignment = new wxButton( this, wxID_ANY, _("Add Custom Assignment"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer8->Add( m_btnAddAssignment, 0, wxALL, 5 );
|
||||
|
||||
|
||||
bSizerMain->Add( fgSizer8, 0, wxEXPAND, 5 );
|
||||
|
||||
m_assignmentsScrollWindow = new wxScrolledWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL );
|
||||
m_assignmentsScrollWindow->SetScrollRate( 5, 5 );
|
||||
wxBoxSizer* m_assignmentsList;
|
||||
m_assignmentsList = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
m_assignmentsScrollWindow->SetSizer( m_assignmentsList );
|
||||
m_assignmentsScrollWindow->Layout();
|
||||
m_assignmentsList->Fit( m_assignmentsScrollWindow );
|
||||
bSizerMain->Add( m_assignmentsScrollWindow, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
this->SetSizer( bSizerMain );
|
||||
this->Layout();
|
||||
bSizerMain->Fit( this );
|
||||
|
||||
// Connect Events
|
||||
m_btnAddAssignment->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_ASSIGN_COMPONENT_CLASSES_BASE::OnAddAssignmentClick ), NULL, this );
|
||||
}
|
||||
|
||||
PANEL_ASSIGN_COMPONENT_CLASSES_BASE::~PANEL_ASSIGN_COMPONENT_CLASSES_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
m_btnAddAssignment->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_ASSIGN_COMPONENT_CLASSES_BASE::OnAddAssignmentClick ), NULL, this );
|
||||
|
||||
}
|
||||
|
||||
PANEL_COMPONENT_CLASS_ASSIGNMENT_BASE::PANEL_COMPONENT_CLASS_ASSIGNMENT_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
|
||||
{
|
||||
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT ) );
|
||||
|
||||
wxStaticBoxSizer* m_assignmentGroup;
|
||||
m_assignmentGroup = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL );
|
||||
|
||||
wxFlexGridSizer* m_header;
|
||||
m_header = new wxFlexGridSizer( 0, 5, 0, 0 );
|
||||
m_header->AddGrowableCol( 1 );
|
||||
m_header->SetFlexibleDirection( wxHORIZONTAL );
|
||||
m_header->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_NONE );
|
||||
|
||||
m_staticText101 = new wxStaticText( m_assignmentGroup->GetStaticBox(), wxID_ANY, _("Component Class:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText101->Wrap( -1 );
|
||||
m_header->Add( m_staticText101, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_componentClass = new wxTextCtrl( m_assignmentGroup->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_header->Add( m_componentClass, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_header->Add( 10, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_buttonHighlightItems = new STD_BITMAP_BUTTON( m_assignmentGroup->GetStaticBox(), wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_header->Add( m_buttonHighlightItems, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_buttonDeleteAssignment = new STD_BITMAP_BUTTON( m_assignmentGroup->GetStaticBox(), wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_header->Add( m_buttonDeleteAssignment, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_assignmentGroup->Add( m_header, 0, wxEXPAND, 0 );
|
||||
|
||||
wxBoxSizer* bSizer4;
|
||||
bSizer4 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
bSizer4->Add( 0, 5, 0, 0, 5 );
|
||||
|
||||
wxBoxSizer* bSizer3;
|
||||
bSizer3 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_buttonAddCondition = new STD_BITMAP_BUTTON( m_assignmentGroup->GetStaticBox(), wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
bSizer3->Add( m_buttonAddCondition, 0, wxALIGN_CENTER_VERTICAL, 0 );
|
||||
|
||||
|
||||
bSizer3->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_radioAll = new wxRadioButton( m_assignmentGroup->GetStaticBox(), wxID_ANY, _("Match All"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_radioAll->SetValue( true );
|
||||
bSizer3->Add( m_radioAll, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_radioAny = new wxRadioButton( m_assignmentGroup->GetStaticBox(), wxID_ANY, _("Match Any"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizer3->Add( m_radioAny, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
bSizer4->Add( bSizer3, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_assignmentGroup->Add( bSizer4, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
this->SetSizer( m_assignmentGroup );
|
||||
this->Layout();
|
||||
m_assignmentGroup->Fit( this );
|
||||
|
||||
// Connect Events
|
||||
m_buttonHighlightItems->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_ASSIGNMENT_BASE::OnHighlightItemsClick ), NULL, this );
|
||||
m_buttonDeleteAssignment->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_ASSIGNMENT_BASE::OnDeleteAssignmentClick ), NULL, this );
|
||||
m_buttonAddCondition->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_ASSIGNMENT_BASE::OnAddConditionClick ), NULL, this );
|
||||
}
|
||||
|
||||
PANEL_COMPONENT_CLASS_ASSIGNMENT_BASE::~PANEL_COMPONENT_CLASS_ASSIGNMENT_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
m_buttonHighlightItems->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_ASSIGNMENT_BASE::OnHighlightItemsClick ), NULL, this );
|
||||
m_buttonDeleteAssignment->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_ASSIGNMENT_BASE::OnDeleteAssignmentClick ), NULL, this );
|
||||
m_buttonAddCondition->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_ASSIGNMENT_BASE::OnAddConditionClick ), NULL, this );
|
||||
|
||||
}
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_REFERENCE_BASE::PANEL_COMPONENT_CLASS_CONDITION_REFERENCE_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
|
||||
{
|
||||
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT ) );
|
||||
|
||||
wxFlexGridSizer* m_conditionSizer;
|
||||
m_conditionSizer = new wxFlexGridSizer( 0, 65, 0, 0 );
|
||||
m_conditionSizer->AddGrowableCol( 1 );
|
||||
m_conditionSizer->SetFlexibleDirection( wxBOTH );
|
||||
m_conditionSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_title = new wxStaticText( this, wxID_ANY, _("Reference:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_title->Wrap( -1 );
|
||||
m_title->SetFont( wxFont( 12, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxT("Helvetica") ) );
|
||||
|
||||
m_conditionSizer->Add( m_title, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_refs = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_conditionSizer->Add( m_refs, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_conditionSizer->Add( 10, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_buttonImportRefs = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_conditionSizer->Add( m_buttonImportRefs, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_buttonDeleteMatch = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_conditionSizer->Add( m_buttonDeleteMatch, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
this->SetSizer( m_conditionSizer );
|
||||
this->Layout();
|
||||
m_conditionSizer->Fit( this );
|
||||
|
||||
// Connect Events
|
||||
m_refs->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( PANEL_COMPONENT_CLASS_CONDITION_REFERENCE_BASE::OnReferenceRightDown ), NULL, this );
|
||||
m_buttonImportRefs->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_CONDITION_REFERENCE_BASE::OnImportRefsClick ), NULL, this );
|
||||
m_buttonDeleteMatch->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_CONDITION_REFERENCE_BASE::OnDeleteConditionClick ), NULL, this );
|
||||
}
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_REFERENCE_BASE::~PANEL_COMPONENT_CLASS_CONDITION_REFERENCE_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
m_refs->Disconnect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( PANEL_COMPONENT_CLASS_CONDITION_REFERENCE_BASE::OnReferenceRightDown ), NULL, this );
|
||||
m_buttonImportRefs->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_CONDITION_REFERENCE_BASE::OnImportRefsClick ), NULL, this );
|
||||
m_buttonDeleteMatch->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_CONDITION_REFERENCE_BASE::OnDeleteConditionClick ), NULL, this );
|
||||
|
||||
}
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_SIDE_BASE::PANEL_COMPONENT_CLASS_CONDITION_SIDE_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
|
||||
{
|
||||
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT ) );
|
||||
|
||||
wxFlexGridSizer* m_conditionSizer;
|
||||
m_conditionSizer = new wxFlexGridSizer( 0, 4, 0, 0 );
|
||||
m_conditionSizer->AddGrowableCol( 1 );
|
||||
m_conditionSizer->SetFlexibleDirection( wxBOTH );
|
||||
m_conditionSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_title = new wxStaticText( this, wxID_ANY, _("Side:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_title->Wrap( -1 );
|
||||
m_title->SetFont( wxFont( 12, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxT("Helvetica") ) );
|
||||
|
||||
m_conditionSizer->Add( m_title, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_side = new wxComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY );
|
||||
m_conditionSizer->Add( m_side, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_conditionSizer->Add( 10, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_buttonDeleteMatch = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_conditionSizer->Add( m_buttonDeleteMatch, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
this->SetSizer( m_conditionSizer );
|
||||
this->Layout();
|
||||
m_conditionSizer->Fit( this );
|
||||
|
||||
// Connect Events
|
||||
m_buttonDeleteMatch->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_CONDITION_SIDE_BASE::OnDeleteConditionClick ), NULL, this );
|
||||
}
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_SIDE_BASE::~PANEL_COMPONENT_CLASS_CONDITION_SIDE_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
m_buttonDeleteMatch->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_CONDITION_SIDE_BASE::OnDeleteConditionClick ), NULL, this );
|
||||
|
||||
}
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_ROTATION_BASE::PANEL_COMPONENT_CLASS_CONDITION_ROTATION_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
|
||||
{
|
||||
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT ) );
|
||||
|
||||
wxFlexGridSizer* m_conditionSizer;
|
||||
m_conditionSizer = new wxFlexGridSizer( 0, 5, 0, 0 );
|
||||
m_conditionSizer->AddGrowableCol( 1 );
|
||||
m_conditionSizer->SetFlexibleDirection( wxBOTH );
|
||||
m_conditionSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_title = new wxStaticText( this, wxID_ANY, _("Rotation:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_title->Wrap( -1 );
|
||||
m_title->SetFont( wxFont( 12, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxT("Helvetica") ) );
|
||||
|
||||
m_conditionSizer->Add( m_title, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_rotation = new wxComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 );
|
||||
m_conditionSizer->Add( m_rotation, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_rotUnit = new wxStaticText( this, wxID_ANY, _("deg"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_rotUnit->Wrap( -1 );
|
||||
m_conditionSizer->Add( m_rotUnit, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_conditionSizer->Add( 10, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_buttonDeleteMatch = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_conditionSizer->Add( m_buttonDeleteMatch, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
this->SetSizer( m_conditionSizer );
|
||||
this->Layout();
|
||||
|
||||
// Connect Events
|
||||
m_buttonDeleteMatch->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_CONDITION_ROTATION_BASE::OnDeleteConditionClick ), NULL, this );
|
||||
}
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_ROTATION_BASE::~PANEL_COMPONENT_CLASS_CONDITION_ROTATION_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
m_buttonDeleteMatch->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_CONDITION_ROTATION_BASE::OnDeleteConditionClick ), NULL, this );
|
||||
|
||||
}
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT_BASE::PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
|
||||
{
|
||||
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT ) );
|
||||
|
||||
wxFlexGridSizer* m_conditionSizer;
|
||||
m_conditionSizer = new wxFlexGridSizer( 0, 6, 0, 0 );
|
||||
m_conditionSizer->AddGrowableCol( 1 );
|
||||
m_conditionSizer->SetFlexibleDirection( wxBOTH );
|
||||
m_conditionSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_title = new wxStaticText( this, wxID_ANY, _("Footprint:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_title->Wrap( -1 );
|
||||
m_title->SetFont( wxFont( 12, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxT("Helvetica") ) );
|
||||
|
||||
m_conditionSizer->Add( m_title, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_footprint = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_conditionSizer->Add( m_footprint, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_conditionSizer->Add( 10, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_buttonShowLibrary = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_conditionSizer->Add( m_buttonShowLibrary, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_conditionSizer->Add( 10, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_buttonDeleteMatch = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_conditionSizer->Add( m_buttonDeleteMatch, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
this->SetSizer( m_conditionSizer );
|
||||
this->Layout();
|
||||
m_conditionSizer->Fit( this );
|
||||
|
||||
// Connect Events
|
||||
m_buttonShowLibrary->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT_BASE::OnShowLibraryClick ), NULL, this );
|
||||
m_buttonDeleteMatch->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT_BASE::OnDeleteConditionClick ), NULL, this );
|
||||
}
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT_BASE::~PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
m_buttonShowLibrary->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT_BASE::OnShowLibraryClick ), NULL, this );
|
||||
m_buttonDeleteMatch->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT_BASE::OnDeleteConditionClick ), NULL, this );
|
||||
|
||||
}
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_FIELD_BASE::PANEL_COMPONENT_CLASS_CONDITION_FIELD_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
|
||||
{
|
||||
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT ) );
|
||||
|
||||
wxFlexGridSizer* m_conditionSizer;
|
||||
m_conditionSizer = new wxFlexGridSizer( 0, 7, 0, 0 );
|
||||
m_conditionSizer->AddGrowableCol( 1 );
|
||||
m_conditionSizer->AddGrowableCol( 4 );
|
||||
m_conditionSizer->SetFlexibleDirection( wxBOTH );
|
||||
m_conditionSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_title = new wxStaticText( this, wxID_ANY, _("Footprint Field:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_title->Wrap( -1 );
|
||||
m_title->SetFont( wxFont( 12, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxT("Helvetica") ) );
|
||||
|
||||
m_conditionSizer->Add( m_title, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_fieldName = new wxComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 );
|
||||
m_fieldName->SetFont( wxFont( 12, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxT("Helvetica") ) );
|
||||
|
||||
m_conditionSizer->Add( m_fieldName, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_conditionSizer->Add( 10, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_staticText44 = new wxStaticText( this, wxID_ANY, _("Field Value:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText44->Wrap( -1 );
|
||||
m_staticText44->SetFont( wxFont( 12, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxT("Helvetica") ) );
|
||||
|
||||
m_conditionSizer->Add( m_staticText44, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_fieldValue = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_fieldValue->SetFont( wxFont( 12, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxT("Helvetica") ) );
|
||||
|
||||
m_conditionSizer->Add( m_fieldValue, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_conditionSizer->Add( 10, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_buttonDeleteMatch = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_conditionSizer->Add( m_buttonDeleteMatch, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
this->SetSizer( m_conditionSizer );
|
||||
this->Layout();
|
||||
m_conditionSizer->Fit( this );
|
||||
|
||||
// Connect Events
|
||||
m_buttonDeleteMatch->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_CONDITION_FIELD_BASE::OnDeleteConditionClick ), NULL, this );
|
||||
}
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_FIELD_BASE::~PANEL_COMPONENT_CLASS_CONDITION_FIELD_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
m_buttonDeleteMatch->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_CONDITION_FIELD_BASE::OnDeleteConditionClick ), NULL, this );
|
||||
|
||||
}
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_CUSTOM_BASE::PANEL_COMPONENT_CLASS_CONDITION_CUSTOM_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
|
||||
{
|
||||
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT ) );
|
||||
|
||||
wxFlexGridSizer* m_conditionSizer;
|
||||
m_conditionSizer = new wxFlexGridSizer( 0, 4, 0, 0 );
|
||||
m_conditionSizer->AddGrowableCol( 1 );
|
||||
m_conditionSizer->SetFlexibleDirection( wxBOTH );
|
||||
m_conditionSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_title = new wxStaticText( this, wxID_ANY, _("Custom:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_title->Wrap( -1 );
|
||||
m_title->SetFont( wxFont( 12, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxT("Helvetica") ) );
|
||||
|
||||
m_conditionSizer->Add( m_title, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_customCondition = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_conditionSizer->Add( m_customCondition, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_conditionSizer->Add( 10, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_buttonDeleteMatch = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_conditionSizer->Add( m_buttonDeleteMatch, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
this->SetSizer( m_conditionSizer );
|
||||
this->Layout();
|
||||
m_conditionSizer->Fit( this );
|
||||
|
||||
// Connect Events
|
||||
m_buttonDeleteMatch->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_CONDITION_CUSTOM_BASE::OnDeleteConditionClick ), NULL, this );
|
||||
}
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_CUSTOM_BASE::~PANEL_COMPONENT_CLASS_CONDITION_CUSTOM_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
m_buttonDeleteMatch->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_CONDITION_CUSTOM_BASE::OnDeleteConditionClick ), NULL, this );
|
||||
|
||||
}
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_SHEET_BASE::PANEL_COMPONENT_CLASS_CONDITION_SHEET_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
|
||||
{
|
||||
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT ) );
|
||||
|
||||
wxFlexGridSizer* m_conditionSizer;
|
||||
m_conditionSizer = new wxFlexGridSizer( 0, 4, 0, 0 );
|
||||
m_conditionSizer->AddGrowableCol( 1 );
|
||||
m_conditionSizer->SetFlexibleDirection( wxBOTH );
|
||||
m_conditionSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_title = new wxStaticText( this, wxID_ANY, _("Sheet Name:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_title->Wrap( -1 );
|
||||
m_title->SetFont( wxFont( 12, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxT("Helvetica") ) );
|
||||
|
||||
m_conditionSizer->Add( m_title, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_sheetName = new wxComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY );
|
||||
m_conditionSizer->Add( m_sheetName, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_conditionSizer->Add( 10, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_buttonDeleteMatch = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_conditionSizer->Add( m_buttonDeleteMatch, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
this->SetSizer( m_conditionSizer );
|
||||
this->Layout();
|
||||
m_conditionSizer->Fit( this );
|
||||
|
||||
// Connect Events
|
||||
m_buttonDeleteMatch->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_CONDITION_SHEET_BASE::OnDeleteConditionClick ), NULL, this );
|
||||
}
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_SHEET_BASE::~PANEL_COMPONENT_CLASS_CONDITION_SHEET_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
m_buttonDeleteMatch->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_COMPONENT_CLASS_CONDITION_SHEET_BASE::OnDeleteConditionClick ), NULL, this );
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,269 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <wx/artprov.h>
|
||||
#include <wx/xrc/xmlres.h>
|
||||
#include <wx/intl.h>
|
||||
class STD_BITMAP_BUTTON;
|
||||
|
||||
#include <wx/string.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/statline.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/scrolwin.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/bmpbuttn.h>
|
||||
#include <wx/radiobut.h>
|
||||
#include <wx/statbox.h>
|
||||
#include <wx/combobox.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class PANEL_ASSIGN_COMPONENT_CLASSES_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class PANEL_ASSIGN_COMPONENT_CLASSES_BASE : public wxPanel
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxCheckBox* m_assignSheetClasses;
|
||||
wxStaticLine* m_staticline1;
|
||||
wxStaticText* m_staticText3;
|
||||
wxButton* m_btnAddAssignment;
|
||||
wxScrolledWindow* m_assignmentsScrollWindow;
|
||||
|
||||
// Virtual event handlers, override them in your derived class
|
||||
virtual void OnAddAssignmentClick( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
PANEL_ASSIGN_COMPONENT_CLASSES_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||
|
||||
~PANEL_ASSIGN_COMPONENT_CLASSES_BASE();
|
||||
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class PANEL_COMPONENT_CLASS_ASSIGNMENT_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class PANEL_COMPONENT_CLASS_ASSIGNMENT_BASE : public wxPanel
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxStaticText* m_staticText101;
|
||||
wxTextCtrl* m_componentClass;
|
||||
STD_BITMAP_BUTTON* m_buttonHighlightItems;
|
||||
STD_BITMAP_BUTTON* m_buttonDeleteAssignment;
|
||||
STD_BITMAP_BUTTON* m_buttonAddCondition;
|
||||
wxRadioButton* m_radioAll;
|
||||
wxRadioButton* m_radioAny;
|
||||
|
||||
// Virtual event handlers, override them in your derived class
|
||||
virtual void OnHighlightItemsClick( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnDeleteAssignmentClick( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnAddConditionClick( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
PANEL_COMPONENT_CLASS_ASSIGNMENT_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxBORDER_SUNKEN|wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||
|
||||
~PANEL_COMPONENT_CLASS_ASSIGNMENT_BASE();
|
||||
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class PANEL_COMPONENT_CLASS_CONDITION_REFERENCE_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class PANEL_COMPONENT_CLASS_CONDITION_REFERENCE_BASE : public wxPanel
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxStaticText* m_title;
|
||||
wxTextCtrl* m_refs;
|
||||
STD_BITMAP_BUTTON* m_buttonImportRefs;
|
||||
STD_BITMAP_BUTTON* m_buttonDeleteMatch;
|
||||
|
||||
// Virtual event handlers, override them in your derived class
|
||||
virtual void OnReferenceRightDown( wxMouseEvent& event ) { event.Skip(); }
|
||||
virtual void OnImportRefsClick( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnDeleteConditionClick( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_REFERENCE_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxBORDER_SUNKEN|wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||
|
||||
~PANEL_COMPONENT_CLASS_CONDITION_REFERENCE_BASE();
|
||||
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class PANEL_COMPONENT_CLASS_CONDITION_SIDE_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class PANEL_COMPONENT_CLASS_CONDITION_SIDE_BASE : public wxPanel
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxStaticText* m_title;
|
||||
wxComboBox* m_side;
|
||||
STD_BITMAP_BUTTON* m_buttonDeleteMatch;
|
||||
|
||||
// Virtual event handlers, override them in your derived class
|
||||
virtual void OnDeleteConditionClick( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_SIDE_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxBORDER_SUNKEN|wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||
|
||||
~PANEL_COMPONENT_CLASS_CONDITION_SIDE_BASE();
|
||||
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class PANEL_COMPONENT_CLASS_CONDITION_ROTATION_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class PANEL_COMPONENT_CLASS_CONDITION_ROTATION_BASE : public wxPanel
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxStaticText* m_title;
|
||||
wxComboBox* m_rotation;
|
||||
wxStaticText* m_rotUnit;
|
||||
STD_BITMAP_BUTTON* m_buttonDeleteMatch;
|
||||
|
||||
// Virtual event handlers, override them in your derived class
|
||||
virtual void OnDeleteConditionClick( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_ROTATION_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 303,65 ), long style = wxBORDER_SUNKEN|wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||
|
||||
~PANEL_COMPONENT_CLASS_CONDITION_ROTATION_BASE();
|
||||
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT_BASE : public wxPanel
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxStaticText* m_title;
|
||||
wxTextCtrl* m_footprint;
|
||||
STD_BITMAP_BUTTON* m_buttonShowLibrary;
|
||||
STD_BITMAP_BUTTON* m_buttonDeleteMatch;
|
||||
|
||||
// Virtual event handlers, override them in your derived class
|
||||
virtual void OnShowLibraryClick( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnDeleteConditionClick( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxBORDER_SUNKEN|wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||
|
||||
~PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT_BASE();
|
||||
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class PANEL_COMPONENT_CLASS_CONDITION_FIELD_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class PANEL_COMPONENT_CLASS_CONDITION_FIELD_BASE : public wxPanel
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxStaticText* m_title;
|
||||
wxComboBox* m_fieldName;
|
||||
wxStaticText* m_staticText44;
|
||||
wxTextCtrl* m_fieldValue;
|
||||
STD_BITMAP_BUTTON* m_buttonDeleteMatch;
|
||||
|
||||
// Virtual event handlers, override them in your derived class
|
||||
virtual void OnDeleteConditionClick( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_FIELD_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxBORDER_SUNKEN|wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||
|
||||
~PANEL_COMPONENT_CLASS_CONDITION_FIELD_BASE();
|
||||
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class PANEL_COMPONENT_CLASS_CONDITION_CUSTOM_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class PANEL_COMPONENT_CLASS_CONDITION_CUSTOM_BASE : public wxPanel
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxStaticText* m_title;
|
||||
wxTextCtrl* m_customCondition;
|
||||
STD_BITMAP_BUTTON* m_buttonDeleteMatch;
|
||||
|
||||
// Virtual event handlers, override them in your derived class
|
||||
virtual void OnDeleteConditionClick( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_CUSTOM_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxBORDER_SUNKEN|wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||
|
||||
~PANEL_COMPONENT_CLASS_CONDITION_CUSTOM_BASE();
|
||||
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class PANEL_COMPONENT_CLASS_CONDITION_SHEET_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class PANEL_COMPONENT_CLASS_CONDITION_SHEET_BASE : public wxPanel
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxStaticText* m_title;
|
||||
wxComboBox* m_sheetName;
|
||||
STD_BITMAP_BUTTON* m_buttonDeleteMatch;
|
||||
|
||||
// Virtual event handlers, override them in your derived class
|
||||
virtual void OnDeleteConditionClick( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
PANEL_COMPONENT_CLASS_CONDITION_SHEET_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxBORDER_SUNKEN|wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||
|
||||
~PANEL_COMPONENT_CLASS_CONDITION_SHEET_BASE();
|
||||
|
||||
};
|
||||
|
||||
@@ -632,6 +632,9 @@ void DRC_ENGINE::RunTests( EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aT
|
||||
if( !cacheGenerator.Run() ) // ... and regenerate them.
|
||||
return;
|
||||
|
||||
// Recompute component classes
|
||||
m_board->GetComponentClassManager().ForceComponentClassRecalculation();
|
||||
|
||||
int timestamp = m_board->GetTimeStamp();
|
||||
|
||||
for( DRC_TEST_PROVIDER* provider : m_testProviders )
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <drc_rules_lexer.h>
|
||||
#include <pcbexpr_evaluator.h>
|
||||
#include <reporter.h>
|
||||
#include <component_classes/component_class_assignment_rule.h>
|
||||
|
||||
using namespace DRCRULE_T;
|
||||
|
||||
@@ -182,6 +183,81 @@ void DRC_RULES_PARSER::Parse( std::vector<std::shared_ptr<DRC_RULE>>& aRules, RE
|
||||
}
|
||||
|
||||
|
||||
void DRC_RULES_PARSER::ParseComponentClassAssignmentRules(
|
||||
std::vector<std::shared_ptr<COMPONENT_CLASS_ASSIGNMENT_RULE>>& aRules, REPORTER* aReporter )
|
||||
{
|
||||
bool haveVersion = false;
|
||||
wxString msg;
|
||||
|
||||
m_reporter = aReporter;
|
||||
|
||||
for( T token = NextTok(); token != T_EOF; token = NextTok() )
|
||||
{
|
||||
if( token != T_LEFT )
|
||||
reportError( _( "Missing '('." ) );
|
||||
|
||||
token = NextTok();
|
||||
|
||||
if( !haveVersion && token != T_version )
|
||||
{
|
||||
reportError( _( "Missing version statement." ) );
|
||||
haveVersion = true; // don't keep on reporting it
|
||||
}
|
||||
|
||||
switch( token )
|
||||
{
|
||||
case T_version:
|
||||
haveVersion = true;
|
||||
token = NextTok();
|
||||
|
||||
if( (int) token == DSN_RIGHT )
|
||||
{
|
||||
reportError( _( "Missing version number." ) );
|
||||
break;
|
||||
}
|
||||
|
||||
if( (int) token == DSN_NUMBER )
|
||||
{
|
||||
m_requiredVersion = (int) strtol( CurText(), nullptr, 10 );
|
||||
m_tooRecent = ( m_requiredVersion > DRC_RULE_FILE_VERSION );
|
||||
token = NextTok();
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.Printf( _( "Unrecognized item '%s'.| Expected version number." ), FromUTF8() );
|
||||
reportError( msg );
|
||||
}
|
||||
|
||||
if( (int) token != DSN_RIGHT )
|
||||
{
|
||||
msg.Printf( _( "Unrecognized item '%s'." ), FromUTF8() );
|
||||
reportError( msg );
|
||||
parseUnknown();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case T_assign_component_class:
|
||||
aRules.emplace_back( parseComponentClassAssignment() );
|
||||
break;
|
||||
|
||||
case T_EOF: reportError( _( "Incomplete statement." ) ); break;
|
||||
|
||||
default:
|
||||
msg.Printf( _( "Unrecognized item '%s'.| Expected %s." ), FromUTF8(),
|
||||
wxT( "assign_component_class or version" ) );
|
||||
reportError( msg );
|
||||
parseUnknown();
|
||||
}
|
||||
}
|
||||
|
||||
if( m_reporter && !m_reporter->HasMessage() )
|
||||
m_reporter->Report( _( "No errors found." ), RPT_SEVERITY_INFO );
|
||||
|
||||
m_reporter = nullptr;
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<DRC_RULE> DRC_RULES_PARSER::parseDRC_RULE()
|
||||
{
|
||||
std::shared_ptr<DRC_RULE> rule = std::make_shared<DRC_RULE>();
|
||||
@@ -266,6 +342,80 @@ std::shared_ptr<DRC_RULE> DRC_RULES_PARSER::parseDRC_RULE()
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<COMPONENT_CLASS_ASSIGNMENT_RULE> DRC_RULES_PARSER::parseComponentClassAssignment()
|
||||
{
|
||||
std::shared_ptr<DRC_RULE_CONDITION> condition;
|
||||
|
||||
T token = NextTok();
|
||||
wxString msg;
|
||||
|
||||
if( !IsSymbol( token ) )
|
||||
reportError( _( "Missing component class name." ) );
|
||||
|
||||
wxString componentClass = FromUTF8();
|
||||
|
||||
for( token = NextTok(); token != T_RIGHT && token != T_EOF; token = NextTok() )
|
||||
{
|
||||
if( token != T_LEFT )
|
||||
reportError( _( "Missing '('." ) );
|
||||
|
||||
token = NextTok();
|
||||
|
||||
switch( token )
|
||||
{
|
||||
case T_condition:
|
||||
token = NextTok();
|
||||
|
||||
if( (int) token == DSN_RIGHT )
|
||||
{
|
||||
reportError( _( "Missing condition expression." ) );
|
||||
break;
|
||||
}
|
||||
|
||||
if( IsSymbol( token ) )
|
||||
{
|
||||
condition = std::make_shared<DRC_RULE_CONDITION>( FromUTF8() );
|
||||
|
||||
if( !condition->Compile( m_reporter, CurLineNumber(), CurOffset() ) )
|
||||
{
|
||||
reportError( wxString::Format( _( "Could not parse expression '%s'." ),
|
||||
FromUTF8() ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.Printf( _( "Unrecognized item '%s'.| Expected quoted expression." ),
|
||||
FromUTF8() );
|
||||
reportError( msg );
|
||||
}
|
||||
|
||||
if( (int) NextTok() != DSN_RIGHT )
|
||||
{
|
||||
reportError( wxString::Format( _( "Unrecognized item '%s'." ), FromUTF8() ) );
|
||||
parseUnknown();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case T_EOF: reportError( _( "Incomplete statement." ) ); return nullptr;
|
||||
|
||||
default:
|
||||
msg.Printf( _( "Unrecognized item '%s'.| Expected %s." ), FromUTF8(),
|
||||
wxT( "condition" ) );
|
||||
reportError( msg );
|
||||
parseUnknown();
|
||||
}
|
||||
}
|
||||
|
||||
if( (int) CurTok() != DSN_RIGHT )
|
||||
reportError( _( "Missing ')'." ) );
|
||||
|
||||
return std::make_shared<COMPONENT_CLASS_ASSIGNMENT_RULE>( componentClass,
|
||||
std::move( condition ) );
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
|
||||
{
|
||||
DRC_CONSTRAINT c;
|
||||
|
||||
@@ -45,9 +45,15 @@ public:
|
||||
|
||||
void Parse( std::vector<std::shared_ptr<DRC_RULE>>& aRules, REPORTER* aReporter );
|
||||
|
||||
void ParseComponentClassAssignmentRules(
|
||||
std::vector<std::shared_ptr<COMPONENT_CLASS_ASSIGNMENT_RULE>>& aRules,
|
||||
REPORTER* aReporter );
|
||||
|
||||
private:
|
||||
std::shared_ptr<DRC_RULE> parseDRC_RULE();
|
||||
|
||||
std::shared_ptr<COMPONENT_CLASS_ASSIGNMENT_RULE> parseComponentClassAssignment();
|
||||
|
||||
void parseConstraint( DRC_RULE* aRule );
|
||||
void parseValueWithUnits( const wxString& aExpr, int& aResult, bool aUnitless = false );
|
||||
LSET parseLayer();
|
||||
|
||||
@@ -807,6 +807,14 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
||||
loadedBoard->SetModified();
|
||||
}
|
||||
|
||||
if( !loadedBoard->SynchronizeComponentClasses( std::unordered_set<wxString>() ) )
|
||||
{
|
||||
m_infoBar->RemoveAllButtons();
|
||||
m_infoBar->AddCloseButton();
|
||||
m_infoBar->ShowMessage( _( "Could not load component class assignment rules" ),
|
||||
wxICON_WARNING, WX_INFOBAR::MESSAGE_TYPE::GENERIC );
|
||||
}
|
||||
|
||||
// we should not ask PCB_IOs to do these items:
|
||||
loadedBoard->BuildListOfNets();
|
||||
ResolveDRCExclusions( true );
|
||||
@@ -944,6 +952,9 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
||||
LoadProjectSettings();
|
||||
LoadDrawingSheet();
|
||||
|
||||
// Initialise caches used by component classes
|
||||
GetBoard()->GetComponentClassManager().RebuildRequiredCaches();
|
||||
|
||||
// Syncs the UI (appearance panel, etc) with the loaded board and project
|
||||
onBoardLoaded();
|
||||
|
||||
|
||||
+47
-20
@@ -33,6 +33,8 @@
|
||||
#include <confirm.h>
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
#include <convert_shape_list_to_polygon.h>
|
||||
#include <component_classes/component_class.h>
|
||||
#include <component_classes/component_class_cache_proxy.h>
|
||||
#include <drc/drc_item.h>
|
||||
#include <embedded_files.h>
|
||||
#include <font/font.h>
|
||||
@@ -67,12 +69,10 @@
|
||||
|
||||
|
||||
FOOTPRINT::FOOTPRINT( BOARD* parent ) :
|
||||
BOARD_ITEM_CONTAINER((BOARD_ITEM*) parent, PCB_FOOTPRINT_T ),
|
||||
m_boundingBoxCacheTimeStamp( 0 ),
|
||||
m_textExcludedBBoxCacheTimeStamp( 0 ),
|
||||
m_hullCacheTimeStamp( 0 ),
|
||||
m_initial_comments( nullptr ),
|
||||
m_componentClass( nullptr )
|
||||
BOARD_ITEM_CONTAINER( (BOARD_ITEM*) parent, PCB_FOOTPRINT_T ),
|
||||
m_boundingBoxCacheTimeStamp( 0 ), m_textExcludedBBoxCacheTimeStamp( 0 ),
|
||||
m_hullCacheTimeStamp( 0 ), m_initial_comments( nullptr ),
|
||||
m_componentClassCacheProxy( std::make_unique<COMPONENT_CLASS_CACHE_PROXY>( this ) )
|
||||
{
|
||||
m_attributes = 0;
|
||||
m_layer = F_Cu;
|
||||
@@ -104,8 +104,8 @@ FOOTPRINT::FOOTPRINT( BOARD* parent ) :
|
||||
|
||||
|
||||
FOOTPRINT::FOOTPRINT( const FOOTPRINT& aFootprint ) :
|
||||
BOARD_ITEM_CONTAINER( aFootprint ),
|
||||
EMBEDDED_FILES( aFootprint )
|
||||
BOARD_ITEM_CONTAINER( aFootprint ), EMBEDDED_FILES( aFootprint ),
|
||||
m_componentClassCacheProxy( std::make_unique<COMPONENT_CLASS_CACHE_PROXY>( this ) )
|
||||
{
|
||||
m_pos = aFootprint.m_pos;
|
||||
m_fpid = aFootprint.m_fpid;
|
||||
@@ -132,8 +132,6 @@ FOOTPRINT::FOOTPRINT( const FOOTPRINT& aFootprint ) :
|
||||
m_netTiePadGroups = aFootprint.m_netTiePadGroups;
|
||||
m_fileFormatVersionAtLoad = aFootprint.m_fileFormatVersionAtLoad;
|
||||
|
||||
m_componentClass = aFootprint.m_componentClass;
|
||||
|
||||
std::map<BOARD_ITEM*, BOARD_ITEM*> ptrMap;
|
||||
|
||||
// Copy fields
|
||||
@@ -754,8 +752,6 @@ FOOTPRINT& FOOTPRINT::operator=( FOOTPRINT&& aOther )
|
||||
m_zoneConnection = aOther.m_zoneConnection;
|
||||
m_netTiePadGroups = aOther.m_netTiePadGroups;
|
||||
|
||||
m_componentClass = aOther.m_componentClass;
|
||||
|
||||
// Move the fields
|
||||
for( PCB_FIELD* field : m_fields )
|
||||
delete field;
|
||||
@@ -867,8 +863,6 @@ FOOTPRINT& FOOTPRINT::operator=( const FOOTPRINT& aOther )
|
||||
m_zoneConnection = aOther.m_zoneConnection;
|
||||
m_netTiePadGroups = aOther.m_netTiePadGroups;
|
||||
|
||||
m_componentClass = aOther.m_componentClass;
|
||||
|
||||
std::map<BOARD_ITEM*, BOARD_ITEM*> ptrMap;
|
||||
|
||||
// Copy fields
|
||||
@@ -1717,9 +1711,11 @@ void FOOTPRINT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_I
|
||||
aList.emplace_back( _( "Rotation" ), wxString::Format( wxT( "%.4g" ),
|
||||
GetOrientation().AsDegrees() ) );
|
||||
|
||||
if( m_componentClass )
|
||||
if( !m_componentClassCacheProxy->GetComponentClass()->IsEmpty() )
|
||||
{
|
||||
aList.emplace_back( _( "Component Class" ), m_componentClass->GetName() );
|
||||
aList.emplace_back(
|
||||
_( "Component Class" ),
|
||||
m_componentClassCacheProxy->GetComponentClass()->GetHumanReadableName() );
|
||||
}
|
||||
|
||||
msg.Printf( _( "Footprint: %s" ), m_fpid.GetUniStringLibId() );
|
||||
@@ -4042,11 +4038,35 @@ void FOOTPRINT::EmbedFonts()
|
||||
}
|
||||
|
||||
|
||||
void FOOTPRINT::SetStaticComponentClass( const COMPONENT_CLASS* aClass ) const
|
||||
{
|
||||
m_componentClassCacheProxy->SetStaticComponentClass( aClass );
|
||||
}
|
||||
|
||||
|
||||
const COMPONENT_CLASS* FOOTPRINT::GetStaticComponentClass() const
|
||||
{
|
||||
return m_componentClassCacheProxy->GetStaticComponentClass();
|
||||
}
|
||||
|
||||
|
||||
void FOOTPRINT::RecomputeComponentClass() const
|
||||
{
|
||||
m_componentClassCacheProxy->RecomputeComponentClass();
|
||||
}
|
||||
|
||||
|
||||
const COMPONENT_CLASS* FOOTPRINT::GetComponentClass() const
|
||||
{
|
||||
return m_componentClassCacheProxy->GetComponentClass();
|
||||
}
|
||||
|
||||
|
||||
wxString FOOTPRINT::GetComponentClassAsString() const
|
||||
{
|
||||
if( m_componentClass )
|
||||
if( !m_componentClassCacheProxy->GetComponentClass()->IsEmpty() )
|
||||
{
|
||||
return m_componentClass->GetFullName();
|
||||
return m_componentClassCacheProxy->GetComponentClass()->GetName();
|
||||
}
|
||||
|
||||
return wxEmptyString;
|
||||
@@ -4057,8 +4077,15 @@ void FOOTPRINT::ResolveComponentClassNames(
|
||||
BOARD* aBoard, const std::unordered_set<wxString>& aComponentClassNames )
|
||||
{
|
||||
const COMPONENT_CLASS* componentClass =
|
||||
aBoard->GetComponentClassManager().GetEffectiveComponentClass( aComponentClassNames );
|
||||
SetComponentClass( componentClass );
|
||||
aBoard->GetComponentClassManager().GetEffectiveStaticComponentClass(
|
||||
aComponentClassNames );
|
||||
SetStaticComponentClass( componentClass );
|
||||
}
|
||||
|
||||
|
||||
void FOOTPRINT::InvalidateComponentClassCache() const
|
||||
{
|
||||
m_componentClassCacheProxy->InvalidateCache();
|
||||
}
|
||||
|
||||
|
||||
|
||||
+19
-10
@@ -32,7 +32,7 @@
|
||||
#include <board_item_container.h>
|
||||
#include <board_item.h>
|
||||
#include <collectors.h>
|
||||
#include <component_class_manager.h>
|
||||
#include <component_classes/component_class_manager.h>
|
||||
#include <embedded_files.h>
|
||||
#include <layer_ids.h> // ALL_LAYERS definition.
|
||||
#include <lset.h>
|
||||
@@ -54,6 +54,7 @@ class BOARD;
|
||||
class MSG_PANEL_ITEM;
|
||||
class SHAPE;
|
||||
class REPORTER;
|
||||
class COMPONENT_CLASS_CACHE_PROXY;
|
||||
|
||||
namespace KIGFX {
|
||||
class VIEW;
|
||||
@@ -984,7 +985,22 @@ public:
|
||||
double Similarity( const BOARD_ITEM& aOther ) const override;
|
||||
|
||||
/// Sets the component class object pointer for this footprint
|
||||
void SetComponentClass( const COMPONENT_CLASS* aClass ) { m_componentClass = aClass; }
|
||||
void SetStaticComponentClass( const COMPONENT_CLASS* aClass ) const;
|
||||
|
||||
/// Returns the component class for this footprint
|
||||
const COMPONENT_CLASS* GetStaticComponentClass() const;
|
||||
|
||||
/// Returns the component class for this footprint
|
||||
const COMPONENT_CLASS* GetComponentClass() const;
|
||||
|
||||
/// Used for display in the properties panel
|
||||
wxString GetComponentClassAsString() const;
|
||||
|
||||
/// Forces immediate recalculation of the component class for this footprint
|
||||
void RecomputeComponentClass() const;
|
||||
|
||||
/// Forces deferred (on next access) recalculation of the component class for this footprint
|
||||
void InvalidateComponentClassCache() const;
|
||||
|
||||
/**
|
||||
* @brief Sets the transient component class names
|
||||
@@ -1010,13 +1026,6 @@ public:
|
||||
void ResolveComponentClassNames( BOARD* aBoard,
|
||||
const std::unordered_set<wxString>& aComponentClassNames );
|
||||
|
||||
/// Returns the component class for this footprint
|
||||
const COMPONENT_CLASS* GetComponentClass() const { return m_componentClass; }
|
||||
|
||||
/// Used for display in the properties panel
|
||||
wxString GetComponentClassAsString() const;
|
||||
|
||||
|
||||
bool operator==( const BOARD_ITEM& aOther ) const override;
|
||||
bool operator==( const FOOTPRINT& aOther ) const;
|
||||
|
||||
@@ -1117,8 +1126,8 @@ private:
|
||||
mutable HASH_128 m_courtyard_cache_back_hash;
|
||||
mutable std::mutex m_courtyard_cache_mutex;
|
||||
|
||||
const COMPONENT_CLASS* m_componentClass;
|
||||
std::unordered_set<wxString> m_transientComponentClassNames;
|
||||
std::unique_ptr<COMPONENT_CLASS_CACHE_PROXY> m_componentClassCacheProxy;
|
||||
};
|
||||
|
||||
#endif // FOOTPRINT_H
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <base_units.h>
|
||||
#include <board.h>
|
||||
#include <board_design_settings.h>
|
||||
#include <component_classes/component_class.h>
|
||||
#include <netinfo.h>
|
||||
#include <footprint.h>
|
||||
#include <pad.h>
|
||||
@@ -157,7 +158,8 @@ FOOTPRINT* BOARD_NETLIST_UPDATER::addNewFootprint( COMPONENT* aComponent )
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
footprint->SetComponentClass( m_board->GetComponentClassManager().GetNoneComponentClass() );
|
||||
footprint->SetStaticComponentClass(
|
||||
m_board->GetComponentClassManager().GetNoneComponentClass() );
|
||||
|
||||
if( m_isDryRun )
|
||||
{
|
||||
@@ -207,8 +209,8 @@ void BOARD_NETLIST_UPDATER::updateComponentClass( FOOTPRINT* aFootprint, COMPONE
|
||||
wxString curClassName, newClassName;
|
||||
COMPONENT_CLASS* newClass = nullptr;
|
||||
|
||||
if( const COMPONENT_CLASS* curClass = aFootprint->GetComponentClass() )
|
||||
curClassName = curClass->GetFullName();
|
||||
if( const COMPONENT_CLASS* curClass = aFootprint->GetStaticComponentClass() )
|
||||
curClassName = curClass->GetName();
|
||||
|
||||
// Calculate the new component class
|
||||
if( m_isDryRun )
|
||||
@@ -218,9 +220,9 @@ void BOARD_NETLIST_UPDATER::updateComponentClass( FOOTPRINT* aFootprint, COMPONE
|
||||
}
|
||||
else
|
||||
{
|
||||
newClass = m_board->GetComponentClassManager().GetEffectiveComponentClass(
|
||||
newClass = m_board->GetComponentClassManager().GetEffectiveStaticComponentClass(
|
||||
aNewComponent->GetComponentClassNames() );
|
||||
newClassName = newClass->GetFullName();
|
||||
newClassName = newClass->GetName();
|
||||
}
|
||||
|
||||
if( curClassName == newClassName )
|
||||
@@ -254,7 +256,7 @@ void BOARD_NETLIST_UPDATER::updateComponentClass( FOOTPRINT* aFootprint, COMPONE
|
||||
{
|
||||
wxASSERT_MSG( newClass != nullptr, "Component class should not be nullptr" );
|
||||
|
||||
aFootprint->SetComponentClass( newClass );
|
||||
aFootprint->SetStaticComponentClass( newClass );
|
||||
|
||||
if( curClassName == wxEmptyString && newClassName != wxEmptyString )
|
||||
{
|
||||
@@ -1214,6 +1216,7 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
|
||||
FOOTPRINT* lastPreexistingFootprint = nullptr;
|
||||
COMPONENT* component = nullptr;
|
||||
wxString msg;
|
||||
std::unordered_set<wxString> sheetPaths;
|
||||
|
||||
m_errorCount = 0;
|
||||
m_warningCount = 0;
|
||||
@@ -1294,6 +1297,8 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
|
||||
updateFootprintParameters( tmp, component );
|
||||
updateComponentPadConnections( tmp, component );
|
||||
updateComponentClass( tmp, component );
|
||||
|
||||
sheetPaths.insert( footprint->GetSheetname() );
|
||||
}
|
||||
|
||||
matchCount++;
|
||||
@@ -1317,6 +1322,8 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
|
||||
updateFootprintParameters( footprint, component );
|
||||
updateComponentPadConnections( footprint, component );
|
||||
updateComponentClass( footprint, component );
|
||||
|
||||
sheetPaths.insert( footprint->GetSheetname() );
|
||||
}
|
||||
}
|
||||
else if( matchCount > 1 )
|
||||
@@ -1403,6 +1410,7 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
|
||||
{
|
||||
// Finalise the component class manager
|
||||
m_board->GetComponentClassManager().FinishNetlistUpdate();
|
||||
m_board->SynchronizeComponentClasses( sheetPaths );
|
||||
|
||||
m_board->BuildConnectivity();
|
||||
testConnectivity( aNetlist, footprintMap );
|
||||
|
||||
@@ -90,9 +90,14 @@ void PCB_EDIT_FRAME::OnNetlistChanged( BOARD_NETLIST_UPDATER& aUpdater, bool* aR
|
||||
|
||||
SetMsgPanel( board );
|
||||
|
||||
// Re-sync nets, netclasses, and DRC rules to account for new aggregate netclass rules
|
||||
// Re-sync nets and netclasses
|
||||
board->SynchronizeNetsAndNetClasses( false );
|
||||
|
||||
// Recompute component classes
|
||||
board->GetComponentClassManager().InvalidateComponentClasses();
|
||||
board->GetComponentClassManager().RebuildRequiredCaches();
|
||||
|
||||
// Resync DRC rules to account for new aggregate netclass / component class rules
|
||||
DRC_TOOL* drcTool = m_toolManager->GetTool<DRC_TOOL>();
|
||||
|
||||
try
|
||||
|
||||
@@ -1353,6 +1353,15 @@ void PCB_EDIT_FRAME::ShowBoardSetupDialog( const wxString& aInitialPage )
|
||||
if( dlg.ShowQuasiModal() == wxID_OK )
|
||||
{
|
||||
GetBoard()->SynchronizeNetsAndNetClasses( true );
|
||||
|
||||
if( !GetBoard()->SynchronizeComponentClasses( std::unordered_set<wxString>() ) )
|
||||
{
|
||||
m_infoBar->RemoveAllButtons();
|
||||
m_infoBar->AddCloseButton();
|
||||
m_infoBar->ShowMessage( _( "Could not load component class assignment rules" ),
|
||||
wxICON_WARNING, WX_INFOBAR::MESSAGE_TYPE::GENERIC );
|
||||
}
|
||||
|
||||
// We don't know if anything was modified, so err on the side of requiring a save
|
||||
OnModify();
|
||||
|
||||
@@ -2538,7 +2547,7 @@ void PCB_EDIT_FRAME::ExchangeFootprint( FOOTPRINT* aExisting, FOOTPRINT* aNew,
|
||||
aNew->SetSheetfile( aExisting->GetSheetfile() );
|
||||
aNew->SetSheetname( aExisting->GetSheetname() );
|
||||
aNew->SetFilters( aExisting->GetFilters() );
|
||||
aNew->SetComponentClass( aExisting->GetComponentClass() );
|
||||
aNew->SetStaticComponentClass( aExisting->GetComponentClass() );
|
||||
|
||||
aCommit.Remove( aExisting );
|
||||
aCommit.Add( aNew );
|
||||
|
||||
@@ -1201,14 +1201,14 @@ void PCB_IO_KICAD_SEXPR::format( const FOOTPRINT* aFootprint ) const
|
||||
m_out->Print( ")" );
|
||||
}
|
||||
|
||||
if( const COMPONENT_CLASS* compClass = aFootprint->GetComponentClass() )
|
||||
if( const COMPONENT_CLASS* compClass = aFootprint->GetStaticComponentClass() )
|
||||
{
|
||||
if( !compClass->IsEmpty() )
|
||||
{
|
||||
m_out->Print( "(component_classes" );
|
||||
|
||||
for( const COMPONENT_CLASS* constituent : compClass->GetConstituentClasses() )
|
||||
m_out->Print( "(class %s)", m_out->Quotew( constituent->GetFullName() ).c_str() );
|
||||
m_out->Print( "(class %s)", m_out->Quotew( constituent->GetName() ).c_str() );
|
||||
|
||||
m_out->Print( ")" );
|
||||
}
|
||||
|
||||
@@ -177,10 +177,10 @@ class PCB_IO_KICAD_SEXPR; // forward decl
|
||||
//#define SEXPR_BOARD_FILE_VERSION 20241229 // Expand User layers to arbitrary count
|
||||
//----------------- Start of 10.0 development -----------------
|
||||
//#define SEXPR_BOARD_FILE_VERSION 20250210 // Knockout for textboxes
|
||||
//#define SEXPR_BOARD_FILE_VERSION 20250222 // Hatching for PCB shapes
|
||||
//#define SEXPR_BOARD_FILE_VERSION 20250228 // ipc-4761 via protection features
|
||||
#define SEXPR_BOARD_FILE_VERSION 20250302 // Zone Hatching Offsets
|
||||
|
||||
//#define SEXPR_BOARD_FILE_VERSION 20250222 // Hatching for PCB shapes
|
||||
//#define SEXPR_BOARD_FILE_VERSION 20250228 // ipc-4761 via protection features
|
||||
//#define SEXPR_BOARD_FILE_VERSION 20250302 // Zone Hatching Offsets
|
||||
#define SEXPR_BOARD_FILE_VERSION 20250309 // Component class dynamic assignment rules
|
||||
|
||||
#define BOARD_FILE_HOST_VERSION 20200825 ///< Earlier files than this include the host tag
|
||||
#define LEGACY_ARC_FORMATTING 20210925 ///< These were the last to use old arc formatting
|
||||
|
||||
@@ -4507,7 +4507,8 @@ FOOTPRINT* PCB_IO_KICAD_SEXPR_PARSER::parseFOOTPRINT_unchecked( wxArrayString* a
|
||||
|
||||
if( m_board )
|
||||
{
|
||||
footprint->SetComponentClass( m_board->GetComponentClassManager().GetNoneComponentClass() );
|
||||
footprint->SetStaticComponentClass(
|
||||
m_board->GetComponentClassManager().GetNoneComponentClass() );
|
||||
}
|
||||
|
||||
token = NextTok();
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <board_connected_item.h>
|
||||
#include <pcbexpr_evaluator.h>
|
||||
#include <drc/drc_engine.h>
|
||||
#include <component_classes/component_class.h>
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Specialized Expression References
|
||||
@@ -216,7 +217,7 @@ public:
|
||||
return LIBEVAL::VALUE::AsString();
|
||||
|
||||
if( const COMPONENT_CLASS* compClass = m_item->GetComponentClass() )
|
||||
const_cast<PCBEXPR_COMPONENT_CLASS_VALUE*>( this )->Set( compClass->GetFullName() );
|
||||
const_cast<PCBEXPR_COMPONENT_CLASS_VALUE*>( this )->Set( compClass->GetName() );
|
||||
|
||||
return LIBEVAL::VALUE::AsString();
|
||||
}
|
||||
@@ -232,9 +233,7 @@ public:
|
||||
const COMPONENT_CLASS* aClass = m_item->GetComponentClass();
|
||||
const COMPONENT_CLASS* bClass = bValue->m_item->GetComponentClass();
|
||||
|
||||
// Note this depends on COMPONENT_CLASS_MANAGER maintaining ownership
|
||||
// of all unique component class objects
|
||||
return aClass == bClass;
|
||||
return *aClass == *bClass;
|
||||
}
|
||||
|
||||
if( b->GetType() == LIBEVAL::VT_STRING )
|
||||
@@ -242,7 +241,7 @@ public:
|
||||
if( m_item->GetComponentClass()->ContainsClassName( b->AsString() ) )
|
||||
return true;
|
||||
|
||||
return m_item->GetComponentClass()->GetFullName() == b->AsString();
|
||||
return m_item->GetComponentClass()->GetName() == b->AsString();
|
||||
}
|
||||
|
||||
return LIBEVAL::VALUE::EqualTo( aCtx, b );
|
||||
@@ -259,16 +258,14 @@ public:
|
||||
const COMPONENT_CLASS* aClass = m_item->GetComponentClass();
|
||||
const COMPONENT_CLASS* bClass = bValue->m_item->GetComponentClass();
|
||||
|
||||
// Note this depends on COMPONENT_CLASS_MANAGER maintaining ownership
|
||||
// of all unique component class objects
|
||||
return aClass != bClass;
|
||||
return *aClass != *bClass;
|
||||
}
|
||||
|
||||
if( b->GetType() == LIBEVAL::VT_STRING )
|
||||
{
|
||||
const bool isInConstituents =
|
||||
m_item->GetComponentClass()->ContainsClassName( b->AsString() );
|
||||
const bool isFullName = m_item->GetComponentClass()->GetFullName() == b->AsString();
|
||||
const bool isFullName = m_item->GetComponentClass()->GetName() == b->AsString();
|
||||
|
||||
return !isInConstituents && !isFullName;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <wx/log.h>
|
||||
#include <board.h>
|
||||
#include <board_design_settings.h>
|
||||
#include <component_classes/component_class.h>
|
||||
#include <drc/drc_rtree.h>
|
||||
#include <drc/drc_engine.h>
|
||||
#include <lset.h>
|
||||
|
||||
@@ -2059,6 +2059,9 @@ int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
|
||||
|
||||
board_item->Rotate( refPt, rotateAngle );
|
||||
board_item->Normalize();
|
||||
|
||||
if( board_item->Type() == PCB_FOOTPRINT_T )
|
||||
static_cast<FOOTPRINT*>( board_item )->InvalidateComponentClassCache();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2389,6 +2392,9 @@ int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent )
|
||||
|
||||
boardItem->Flip( refPt, flipDirection );
|
||||
boardItem->Normalize();
|
||||
|
||||
if( boardItem->Type() == PCB_FOOTPRINT_T )
|
||||
static_cast<FOOTPRINT*>( boardItem )->InvalidateComponentClassCache();
|
||||
}
|
||||
|
||||
if( !localCommit.Empty() )
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <geometry/convex_hull.h>
|
||||
#include <geometry/shape_utils.h>
|
||||
#include <pcb_group.h>
|
||||
#include <component_classes/component_class.h>
|
||||
#include <connectivity/connectivity_data.h>
|
||||
#include <connectivity/topo_match.h>
|
||||
#include <optional>
|
||||
|
||||
@@ -569,6 +569,13 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
|
||||
aList->GetPickedItemStatus( ii ) ) );
|
||||
break;
|
||||
}
|
||||
|
||||
if( eda_item->Type() == PCB_FOOTPRINT_T )
|
||||
{
|
||||
FOOTPRINT* fp = static_cast<FOOTPRINT*>( eda_item );
|
||||
fp->InvalidateComponentClassCache();
|
||||
GetBoard()->GetComponentClassManager().RebuildRequiredCaches( fp );
|
||||
}
|
||||
}
|
||||
|
||||
if( not_found )
|
||||
@@ -587,6 +594,8 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
|
||||
HideSolderMask();
|
||||
}
|
||||
|
||||
GetBoard()->GetComponentClassManager().InvalidateComponentClasses();
|
||||
|
||||
PCB_SELECTION_TOOL* selTool = m_toolManager->GetTool<PCB_SELECTION_TOOL>();
|
||||
selTool->RebuildSelection();
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,761 @@
|
||||
{
|
||||
"board": {
|
||||
"3dviewports": [],
|
||||
"design_settings": {
|
||||
"defaults": {
|
||||
"apply_defaults_to_fp_fields": false,
|
||||
"apply_defaults_to_fp_shapes": false,
|
||||
"apply_defaults_to_fp_text": false,
|
||||
"board_outline_line_width": 0.05,
|
||||
"copper_line_width": 0.2,
|
||||
"copper_text_italic": false,
|
||||
"copper_text_size_h": 1.5,
|
||||
"copper_text_size_v": 1.5,
|
||||
"copper_text_thickness": 0.3,
|
||||
"copper_text_upright": false,
|
||||
"courtyard_line_width": 0.05,
|
||||
"dimension_precision": 4,
|
||||
"dimension_units": 3,
|
||||
"dimensions": {
|
||||
"arrow_length": 1270000,
|
||||
"extension_offset": 500000,
|
||||
"keep_text_aligned": true,
|
||||
"suppress_zeroes": true,
|
||||
"text_position": 0,
|
||||
"units_format": 0
|
||||
},
|
||||
"fab_line_width": 0.1,
|
||||
"fab_text_italic": false,
|
||||
"fab_text_size_h": 1.0,
|
||||
"fab_text_size_v": 1.0,
|
||||
"fab_text_thickness": 0.15,
|
||||
"fab_text_upright": false,
|
||||
"other_line_width": 0.1,
|
||||
"other_text_italic": false,
|
||||
"other_text_size_h": 1.0,
|
||||
"other_text_size_v": 1.0,
|
||||
"other_text_thickness": 0.15,
|
||||
"other_text_upright": false,
|
||||
"pads": {
|
||||
"drill": 0.8,
|
||||
"height": 1.27,
|
||||
"width": 2.54
|
||||
},
|
||||
"silk_line_width": 0.1,
|
||||
"silk_text_italic": false,
|
||||
"silk_text_size_h": 1.0,
|
||||
"silk_text_size_v": 1.0,
|
||||
"silk_text_thickness": 0.1,
|
||||
"silk_text_upright": false,
|
||||
"zones": {
|
||||
"min_clearance": 0.5
|
||||
}
|
||||
},
|
||||
"diff_pair_dimensions": [],
|
||||
"drc_exclusions": [],
|
||||
"meta": {
|
||||
"version": 2
|
||||
},
|
||||
"rule_severities": {
|
||||
"annular_width": "error",
|
||||
"clearance": "error",
|
||||
"connection_width": "warning",
|
||||
"copper_edge_clearance": "error",
|
||||
"copper_sliver": "warning",
|
||||
"courtyards_overlap": "error",
|
||||
"creepage": "error",
|
||||
"diff_pair_gap_out_of_range": "error",
|
||||
"diff_pair_uncoupled_length_too_long": "error",
|
||||
"drill_out_of_range": "error",
|
||||
"duplicate_footprints": "warning",
|
||||
"extra_footprint": "warning",
|
||||
"footprint": "error",
|
||||
"footprint_filters_mismatch": "ignore",
|
||||
"footprint_symbol_mismatch": "warning",
|
||||
"footprint_type_mismatch": "ignore",
|
||||
"hole_clearance": "error",
|
||||
"hole_to_hole": "warning",
|
||||
"holes_co_located": "warning",
|
||||
"invalid_outline": "error",
|
||||
"isolated_copper": "warning",
|
||||
"item_on_disabled_layer": "error",
|
||||
"items_not_allowed": "error",
|
||||
"length_out_of_range": "error",
|
||||
"lib_footprint_issues": "warning",
|
||||
"lib_footprint_mismatch": "warning",
|
||||
"malformed_courtyard": "error",
|
||||
"microvia_drill_out_of_range": "error",
|
||||
"mirrored_text_on_front_layer": "warning",
|
||||
"missing_courtyard": "ignore",
|
||||
"missing_footprint": "warning",
|
||||
"net_conflict": "warning",
|
||||
"nonmirrored_text_on_back_layer": "warning",
|
||||
"npth_inside_courtyard": "ignore",
|
||||
"padstack": "warning",
|
||||
"pth_inside_courtyard": "ignore",
|
||||
"shorting_items": "error",
|
||||
"silk_edge_clearance": "warning",
|
||||
"silk_over_copper": "warning",
|
||||
"silk_overlap": "warning",
|
||||
"skew_out_of_range": "error",
|
||||
"solder_mask_bridge": "error",
|
||||
"starved_thermal": "error",
|
||||
"text_height": "warning",
|
||||
"text_on_edge_cuts": "error",
|
||||
"text_thickness": "warning",
|
||||
"through_hole_pad_without_hole": "error",
|
||||
"too_many_vias": "error",
|
||||
"track_angle": "error",
|
||||
"track_dangling": "warning",
|
||||
"track_segment_length": "error",
|
||||
"track_width": "error",
|
||||
"tracks_crossing": "error",
|
||||
"unconnected_items": "error",
|
||||
"unresolved_variable": "error",
|
||||
"via_dangling": "warning",
|
||||
"zones_intersect": "error"
|
||||
},
|
||||
"rules": {
|
||||
"max_error": 0.005,
|
||||
"min_clearance": 0.0,
|
||||
"min_connection": 0.0,
|
||||
"min_copper_edge_clearance": 0.5,
|
||||
"min_groove_width": 0.0,
|
||||
"min_hole_clearance": 0.25,
|
||||
"min_hole_to_hole": 0.25,
|
||||
"min_microvia_diameter": 0.2,
|
||||
"min_microvia_drill": 0.1,
|
||||
"min_resolved_spokes": 2,
|
||||
"min_silk_clearance": 0.0,
|
||||
"min_text_height": 0.8,
|
||||
"min_text_thickness": 0.08,
|
||||
"min_through_hole_diameter": 0.3,
|
||||
"min_track_width": 0.0,
|
||||
"min_via_annular_width": 0.1,
|
||||
"min_via_diameter": 0.5,
|
||||
"solder_mask_to_copper_clearance": 0.0,
|
||||
"use_height_for_length_calcs": true
|
||||
},
|
||||
"teardrop_options": [
|
||||
{
|
||||
"td_onpthpad": true,
|
||||
"td_onroundshapesonly": false,
|
||||
"td_onsmdpad": true,
|
||||
"td_ontrackend": false,
|
||||
"td_onvia": true
|
||||
}
|
||||
],
|
||||
"teardrop_parameters": [
|
||||
{
|
||||
"td_allow_use_two_tracks": true,
|
||||
"td_curve_segcount": 0,
|
||||
"td_height_ratio": 1.0,
|
||||
"td_length_ratio": 0.5,
|
||||
"td_maxheight": 2.0,
|
||||
"td_maxlen": 1.0,
|
||||
"td_on_pad_in_zone": false,
|
||||
"td_target_name": "td_round_shape",
|
||||
"td_width_to_size_filter_ratio": 0.9
|
||||
},
|
||||
{
|
||||
"td_allow_use_two_tracks": true,
|
||||
"td_curve_segcount": 0,
|
||||
"td_height_ratio": 1.0,
|
||||
"td_length_ratio": 0.5,
|
||||
"td_maxheight": 2.0,
|
||||
"td_maxlen": 1.0,
|
||||
"td_on_pad_in_zone": false,
|
||||
"td_target_name": "td_rect_shape",
|
||||
"td_width_to_size_filter_ratio": 0.9
|
||||
},
|
||||
{
|
||||
"td_allow_use_two_tracks": true,
|
||||
"td_curve_segcount": 0,
|
||||
"td_height_ratio": 1.0,
|
||||
"td_length_ratio": 0.5,
|
||||
"td_maxheight": 2.0,
|
||||
"td_maxlen": 1.0,
|
||||
"td_on_pad_in_zone": false,
|
||||
"td_target_name": "td_track_end",
|
||||
"td_width_to_size_filter_ratio": 0.9
|
||||
}
|
||||
],
|
||||
"track_widths": [],
|
||||
"tuning_pattern_settings": {
|
||||
"diff_pair_defaults": {
|
||||
"corner_radius_percentage": 80,
|
||||
"corner_style": 1,
|
||||
"max_amplitude": 1.0,
|
||||
"min_amplitude": 0.2,
|
||||
"single_sided": false,
|
||||
"spacing": 1.0
|
||||
},
|
||||
"diff_pair_skew_defaults": {
|
||||
"corner_radius_percentage": 80,
|
||||
"corner_style": 1,
|
||||
"max_amplitude": 1.0,
|
||||
"min_amplitude": 0.2,
|
||||
"single_sided": false,
|
||||
"spacing": 0.6
|
||||
},
|
||||
"single_track_defaults": {
|
||||
"corner_radius_percentage": 80,
|
||||
"corner_style": 1,
|
||||
"max_amplitude": 1.0,
|
||||
"min_amplitude": 0.2,
|
||||
"single_sided": false,
|
||||
"spacing": 0.6
|
||||
}
|
||||
},
|
||||
"via_dimensions": [],
|
||||
"zones_allow_external_fillets": false
|
||||
},
|
||||
"ipc2581": {
|
||||
"dist": "",
|
||||
"distpn": "",
|
||||
"internal_id": "",
|
||||
"mfg": "",
|
||||
"mpn": ""
|
||||
},
|
||||
"layer_pairs": [],
|
||||
"layer_presets": [],
|
||||
"viewports": []
|
||||
},
|
||||
"boards": [],
|
||||
"component_class_settings": {
|
||||
"assignments": [
|
||||
{
|
||||
"component_class": "CAP_1",
|
||||
"conditions": {
|
||||
"FOOTPRINT": {
|
||||
"primary": "Capacitor_SMD:C_0805_2012Metric"
|
||||
},
|
||||
"FOOTPRINT_FIELD": {
|
||||
"primary": "MY_FIELD",
|
||||
"secondary": "MY_VALUE"
|
||||
},
|
||||
"REFERENCE": {
|
||||
"primary": "C1"
|
||||
},
|
||||
"ROTATION": {
|
||||
"primary": "90"
|
||||
},
|
||||
"SIDE": {
|
||||
"primary": "Front"
|
||||
}
|
||||
},
|
||||
"conditions_operator": "ALL"
|
||||
},
|
||||
{
|
||||
"component_class": "CAP_2",
|
||||
"conditions": {
|
||||
"CUSTOM": {
|
||||
"primary": "A.intersectsArea('RULE_1')"
|
||||
},
|
||||
"REFERENCE": {
|
||||
"primary": "C?"
|
||||
}
|
||||
},
|
||||
"conditions_operator": "ALL"
|
||||
},
|
||||
{
|
||||
"component_class": "RES_1",
|
||||
"conditions": {
|
||||
"REFERENCE": {
|
||||
"primary": "R?"
|
||||
}
|
||||
},
|
||||
"conditions_operator": "ALL"
|
||||
},
|
||||
{
|
||||
"component_class": "RES_2",
|
||||
"conditions": {
|
||||
"REFERENCE": {
|
||||
"primary": "R*"
|
||||
}
|
||||
},
|
||||
"conditions_operator": "ALL"
|
||||
},
|
||||
{
|
||||
"component_class": "RES_3",
|
||||
"conditions": {
|
||||
"FOOTPRINT_FIELD": {
|
||||
"primary": "FIELD_2",
|
||||
"secondary": "ANOTHER*"
|
||||
}
|
||||
},
|
||||
"conditions_operator": "ALL"
|
||||
},
|
||||
{
|
||||
"component_class": "RES_4",
|
||||
"conditions": {
|
||||
"REFERENCE": {
|
||||
"primary": "R1"
|
||||
},
|
||||
"ROTATION": {
|
||||
"primary": "180"
|
||||
},
|
||||
"SIDE": {
|
||||
"primary": "Back"
|
||||
}
|
||||
},
|
||||
"conditions_operator": "ALL"
|
||||
},
|
||||
{
|
||||
"component_class": "ANY",
|
||||
"conditions": {
|
||||
"FOOTPRINT_FIELD": {
|
||||
"primary": "FIELD2",
|
||||
"secondary": "VALUE"
|
||||
},
|
||||
"REFERENCE": {
|
||||
"primary": "U1"
|
||||
}
|
||||
},
|
||||
"conditions_operator": "ANY"
|
||||
},
|
||||
{
|
||||
"component_class": "MULTI_REF",
|
||||
"conditions": {
|
||||
"REFERENCE": {
|
||||
"primary": "U3,U4"
|
||||
}
|
||||
},
|
||||
"conditions_operator": "ALL"
|
||||
},
|
||||
{
|
||||
"component_class": "REF_WILDCARD",
|
||||
"conditions": {
|
||||
"REFERENCE": {
|
||||
"primary": "U5?"
|
||||
}
|
||||
},
|
||||
"conditions_operator": "ALL"
|
||||
},
|
||||
{
|
||||
"component_class": "REF_WILDCARD2",
|
||||
"conditions": {
|
||||
"REFERENCE": {
|
||||
"primary": "U5*"
|
||||
}
|
||||
},
|
||||
"conditions_operator": "ALL"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"sheet_component_classes": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"cvpcb": {
|
||||
"equivalence_files": []
|
||||
},
|
||||
"erc": {
|
||||
"erc_exclusions": [],
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"pin_map": [
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
]
|
||||
],
|
||||
"rule_severities": {
|
||||
"bus_definition_conflict": "error",
|
||||
"bus_entry_needed": "error",
|
||||
"bus_to_bus_conflict": "error",
|
||||
"bus_to_net_conflict": "error",
|
||||
"different_unit_footprint": "error",
|
||||
"different_unit_net": "error",
|
||||
"duplicate_reference": "error",
|
||||
"duplicate_sheet_names": "error",
|
||||
"endpoint_off_grid": "warning",
|
||||
"extra_units": "error",
|
||||
"footprint_filter": "ignore",
|
||||
"footprint_link_issues": "warning",
|
||||
"four_way_junction": "ignore",
|
||||
"global_label_dangling": "warning",
|
||||
"hier_label_mismatch": "error",
|
||||
"label_dangling": "error",
|
||||
"label_multiple_wires": "warning",
|
||||
"lib_symbol_issues": "warning",
|
||||
"lib_symbol_mismatch": "warning",
|
||||
"missing_bidi_pin": "warning",
|
||||
"missing_input_pin": "warning",
|
||||
"missing_power_pin": "error",
|
||||
"missing_unit": "warning",
|
||||
"multiple_net_names": "warning",
|
||||
"net_not_bus_member": "warning",
|
||||
"no_connect_connected": "warning",
|
||||
"no_connect_dangling": "warning",
|
||||
"pin_not_connected": "error",
|
||||
"pin_not_driven": "error",
|
||||
"pin_to_pin": "warning",
|
||||
"power_pin_not_driven": "error",
|
||||
"same_local_global_label": "warning",
|
||||
"similar_label_and_power": "warning",
|
||||
"similar_labels": "warning",
|
||||
"similar_power": "warning",
|
||||
"simulation_model_issue": "ignore",
|
||||
"single_global_label": "ignore",
|
||||
"unannotated": "error",
|
||||
"unconnected_wire_endpoint": "warning",
|
||||
"unit_value_mismatch": "error",
|
||||
"unresolved_variable": "error",
|
||||
"wire_dangling": "error"
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"pinned_footprint_libs": [],
|
||||
"pinned_symbol_libs": []
|
||||
},
|
||||
"meta": {
|
||||
"filename": "component_classes.kicad_pro",
|
||||
"version": 3
|
||||
},
|
||||
"net_settings": {
|
||||
"classes": [
|
||||
{
|
||||
"bus_width": 12,
|
||||
"clearance": 0.2,
|
||||
"diff_pair_gap": 0.25,
|
||||
"diff_pair_via_gap": 0.25,
|
||||
"diff_pair_width": 0.2,
|
||||
"line_style": 0,
|
||||
"microvia_diameter": 0.3,
|
||||
"microvia_drill": 0.1,
|
||||
"name": "Default",
|
||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||
"priority": 2147483647,
|
||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||
"track_width": 0.2,
|
||||
"via_diameter": 0.6,
|
||||
"via_drill": 0.3,
|
||||
"wire_width": 6
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"version": 4
|
||||
},
|
||||
"net_colors": null,
|
||||
"netclass_assignments": null,
|
||||
"netclass_patterns": []
|
||||
},
|
||||
"pcbnew": {
|
||||
"last_paths": {
|
||||
"gencad": "",
|
||||
"idf": "",
|
||||
"netlist": "",
|
||||
"plot": "",
|
||||
"pos_files": "",
|
||||
"specctra_dsn": "",
|
||||
"step": "",
|
||||
"svg": "",
|
||||
"vrml": ""
|
||||
},
|
||||
"page_layout_descr_file": ""
|
||||
},
|
||||
"schematic": {
|
||||
"annotate_start_num": 0,
|
||||
"bom_export_filename": "${PROJECTNAME}.csv",
|
||||
"bom_fmt_presets": [],
|
||||
"bom_fmt_settings": {
|
||||
"field_delimiter": ",",
|
||||
"keep_line_breaks": false,
|
||||
"keep_tabs": false,
|
||||
"name": "CSV",
|
||||
"ref_delimiter": ",",
|
||||
"ref_range_delimiter": "",
|
||||
"string_delimiter": "\""
|
||||
},
|
||||
"bom_presets": [],
|
||||
"bom_settings": {
|
||||
"exclude_dnp": false,
|
||||
"fields_ordered": [
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Reference",
|
||||
"name": "Reference",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Qty",
|
||||
"name": "${QUANTITY}",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": true,
|
||||
"label": "Value",
|
||||
"name": "Value",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": true,
|
||||
"label": "DNP",
|
||||
"name": "${DNP}",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": true,
|
||||
"label": "Exclude from BOM",
|
||||
"name": "${EXCLUDE_FROM_BOM}",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": true,
|
||||
"label": "Exclude from Board",
|
||||
"name": "${EXCLUDE_FROM_BOARD}",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": true,
|
||||
"label": "Footprint",
|
||||
"name": "Footprint",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Datasheet",
|
||||
"name": "Datasheet",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Description",
|
||||
"name": "Description",
|
||||
"show": false
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "#",
|
||||
"name": "${ITEM_NUMBER}",
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"filter_string": "",
|
||||
"group_symbols": true,
|
||||
"include_excluded_from_bom": true,
|
||||
"name": "",
|
||||
"sort_asc": true,
|
||||
"sort_field": "Reference"
|
||||
},
|
||||
"connection_grid_size": 50.0,
|
||||
"drawing": {
|
||||
"dashed_lines_dash_length_ratio": 12.0,
|
||||
"dashed_lines_gap_length_ratio": 3.0,
|
||||
"default_line_thickness": 6.0,
|
||||
"default_text_size": 50.0,
|
||||
"field_names": [],
|
||||
"intersheets_ref_own_page": false,
|
||||
"intersheets_ref_prefix": "",
|
||||
"intersheets_ref_short": false,
|
||||
"intersheets_ref_show": false,
|
||||
"intersheets_ref_suffix": "",
|
||||
"junction_size_choice": 3,
|
||||
"label_size_ratio": 0.375,
|
||||
"operating_point_overlay_i_precision": 3,
|
||||
"operating_point_overlay_i_range": "~A",
|
||||
"operating_point_overlay_v_precision": 3,
|
||||
"operating_point_overlay_v_range": "~V",
|
||||
"overbar_offset_ratio": 1.23,
|
||||
"pin_symbol_size": 25.0,
|
||||
"text_offset_ratio": 0.15
|
||||
},
|
||||
"legacy_lib_dir": "",
|
||||
"legacy_lib_list": [],
|
||||
"meta": {
|
||||
"version": 1
|
||||
},
|
||||
"net_format_name": "",
|
||||
"page_layout_descr_file": "",
|
||||
"plot_directory": "",
|
||||
"space_save_all_events": true,
|
||||
"spice_current_sheet_as_root": false,
|
||||
"spice_external_command": "spice \"%I\"",
|
||||
"spice_model_current_sheet_as_root": true,
|
||||
"spice_save_all_currents": false,
|
||||
"spice_save_all_dissipations": false,
|
||||
"spice_save_all_voltages": false,
|
||||
"subpart_first_id": 65,
|
||||
"subpart_id_separator": 0
|
||||
},
|
||||
"sheets": [
|
||||
[
|
||||
"d9ed75ce-7084-4177-b32b-fceb2cf7aac3",
|
||||
"Root"
|
||||
],
|
||||
[
|
||||
"e826c7ec-b0cb-4f53-915d-da3597387304",
|
||||
"SHEET1"
|
||||
]
|
||||
],
|
||||
"text_variables": {}
|
||||
}
|
||||
@@ -0,0 +1,784 @@
|
||||
(kicad_sch
|
||||
(version 20250227)
|
||||
(generator "eeschema")
|
||||
(generator_version "9.99")
|
||||
(uuid "d9ed75ce-7084-4177-b32b-fceb2cf7aac3")
|
||||
(paper "A4")
|
||||
(lib_symbols
|
||||
(symbol "Device:C"
|
||||
(pin_numbers
|
||||
(hide yes)
|
||||
)
|
||||
(pin_names
|
||||
(offset 0.254)
|
||||
)
|
||||
(exclude_from_sim no)
|
||||
(in_bom yes)
|
||||
(on_board yes)
|
||||
(property "Reference" "C"
|
||||
(at 0.635 2.54 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left)
|
||||
)
|
||||
)
|
||||
(property "Value" "C"
|
||||
(at 0.635 -2.54 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left)
|
||||
)
|
||||
)
|
||||
(property "Footprint" ""
|
||||
(at 0.9652 -3.81 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Datasheet" "~"
|
||||
(at 0 0 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Description" "Unpolarized capacitor"
|
||||
(at 0 0 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "ki_keywords" "cap capacitor"
|
||||
(at 0 0 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "ki_fp_filters" "C_*"
|
||||
(at 0 0 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol "C_0_1"
|
||||
(polyline
|
||||
(pts
|
||||
(xy -2.032 0.762) (xy 2.032 0.762)
|
||||
)
|
||||
(stroke
|
||||
(width 0.508)
|
||||
(type default)
|
||||
)
|
||||
(fill
|
||||
(type none)
|
||||
)
|
||||
)
|
||||
(polyline
|
||||
(pts
|
||||
(xy -2.032 -0.762) (xy 2.032 -0.762)
|
||||
)
|
||||
(stroke
|
||||
(width 0.508)
|
||||
(type default)
|
||||
)
|
||||
(fill
|
||||
(type none)
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol "C_1_1"
|
||||
(pin passive line
|
||||
(at 0 3.81 270)
|
||||
(length 2.794)
|
||||
(name "~"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(number "1"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(pin passive line
|
||||
(at 0 -3.81 90)
|
||||
(length 2.794)
|
||||
(name "~"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(number "2"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(embedded_fonts no)
|
||||
)
|
||||
(symbol "Device:R"
|
||||
(pin_numbers
|
||||
(hide yes)
|
||||
)
|
||||
(pin_names
|
||||
(offset 0)
|
||||
)
|
||||
(exclude_from_sim no)
|
||||
(in_bom yes)
|
||||
(on_board yes)
|
||||
(property "Reference" "R"
|
||||
(at 2.032 0 90)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Value" "R"
|
||||
(at 0 0 90)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Footprint" ""
|
||||
(at -1.778 0 90)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Datasheet" "~"
|
||||
(at 0 0 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Description" "Resistor"
|
||||
(at 0 0 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "ki_keywords" "R res resistor"
|
||||
(at 0 0 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "ki_fp_filters" "R_*"
|
||||
(at 0 0 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol "R_0_1"
|
||||
(rectangle
|
||||
(start -1.016 -2.54)
|
||||
(end 1.016 2.54)
|
||||
(stroke
|
||||
(width 0.254)
|
||||
(type default)
|
||||
)
|
||||
(fill
|
||||
(type none)
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol "R_1_1"
|
||||
(pin passive line
|
||||
(at 0 3.81 270)
|
||||
(length 1.27)
|
||||
(name "~"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(number "1"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(pin passive line
|
||||
(at 0 -3.81 90)
|
||||
(length 1.27)
|
||||
(name "~"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(number "2"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(embedded_fonts no)
|
||||
)
|
||||
)
|
||||
(rule_area
|
||||
(polyline
|
||||
(pts
|
||||
(xy 59.69 54.61) (xy 71.12 54.61) (xy 71.12 68.58) (xy 59.69 68.58)
|
||||
)
|
||||
(stroke
|
||||
(width 0)
|
||||
(type dash)
|
||||
)
|
||||
(fill
|
||||
(type none)
|
||||
)
|
||||
(uuid 60676821-919a-4f11-bd58-e337d82fbd8b)
|
||||
)
|
||||
)
|
||||
(rule_area
|
||||
(polyline
|
||||
(pts
|
||||
(xy 83.82 49.53) (xy 111.76 49.53) (xy 111.76 71.12) (xy 83.82 71.12)
|
||||
)
|
||||
(stroke
|
||||
(width 0)
|
||||
(type dash)
|
||||
)
|
||||
(fill
|
||||
(type none)
|
||||
)
|
||||
(uuid a23b373f-8385-48e5-92cc-856340ee73bd)
|
||||
)
|
||||
)
|
||||
(rule_area
|
||||
(polyline
|
||||
(pts
|
||||
(xy 55.88 49.53) (xy 81.28 49.53) (xy 81.28 71.12) (xy 55.88 71.12)
|
||||
)
|
||||
(stroke
|
||||
(width 0)
|
||||
(type dash)
|
||||
)
|
||||
(fill
|
||||
(type none)
|
||||
)
|
||||
(uuid bf519547-0f5f-46b4-89ee-2b48c33cd0fa)
|
||||
)
|
||||
)
|
||||
(rule_area
|
||||
(polyline
|
||||
(pts
|
||||
(xy 87.63 54.61) (xy 99.06 54.61) (xy 99.06 68.58) (xy 87.63 68.58)
|
||||
)
|
||||
(stroke
|
||||
(width 0)
|
||||
(type dash)
|
||||
)
|
||||
(fill
|
||||
(type none)
|
||||
)
|
||||
(uuid cbff79ad-6039-46f6-903e-1814abb160d6)
|
||||
)
|
||||
)
|
||||
(netclass_flag ""
|
||||
(length 2.54)
|
||||
(shape round)
|
||||
(at 60.96 54.61 0)
|
||||
(fields_autoplaced yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left bottom)
|
||||
)
|
||||
(uuid "95ce2569-329d-4346-bbd4-b51dfac2d0ae")
|
||||
(property "Net Class" ""
|
||||
(at -93.98 -5.08 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Component Class" "CLASS_2"
|
||||
(at 61.6585 52.07 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
(italic yes)
|
||||
)
|
||||
(justify left)
|
||||
)
|
||||
)
|
||||
)
|
||||
(netclass_flag ""
|
||||
(length 2.54)
|
||||
(shape round)
|
||||
(at 88.9 54.61 0)
|
||||
(fields_autoplaced yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left bottom)
|
||||
)
|
||||
(uuid "aee35f39-27b9-471a-86b7-d88f529d2361")
|
||||
(property "Net Class" ""
|
||||
(at -66.04 -5.08 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Component Class" "CLASS_4"
|
||||
(at 89.5985 52.07 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
(italic yes)
|
||||
)
|
||||
(justify left)
|
||||
)
|
||||
)
|
||||
)
|
||||
(netclass_flag ""
|
||||
(length 2.54)
|
||||
(shape round)
|
||||
(at 57.15 49.53 0)
|
||||
(fields_autoplaced yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left bottom)
|
||||
)
|
||||
(uuid "dbcaa6d2-dcb9-4a23-9e8c-5540859c5c95")
|
||||
(property "Net Class" ""
|
||||
(at -97.79 -10.16 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Component Class" "CLASS_1"
|
||||
(at 57.8485 46.99 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
(italic yes)
|
||||
)
|
||||
(justify left)
|
||||
)
|
||||
)
|
||||
)
|
||||
(netclass_flag ""
|
||||
(length 2.54)
|
||||
(shape round)
|
||||
(at 85.09 49.53 0)
|
||||
(fields_autoplaced yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left bottom)
|
||||
)
|
||||
(uuid "ea51b758-1c26-4244-8696-148d5cd9f58c")
|
||||
(property "Net Class" ""
|
||||
(at -69.85 -10.16 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Component Class" "CLASS_3"
|
||||
(at 85.7885 46.99 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
(italic yes)
|
||||
)
|
||||
(justify left)
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol
|
||||
(lib_id "Device:R")
|
||||
(at 64.77 60.96 0)
|
||||
(unit 1)
|
||||
(exclude_from_sim no)
|
||||
(in_bom yes)
|
||||
(on_board yes)
|
||||
(dnp no)
|
||||
(fields_autoplaced yes)
|
||||
(uuid "46977abc-c53a-4b10-a881-2435f24468fa")
|
||||
(property "Reference" "R1"
|
||||
(at 67.31 59.6899 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left)
|
||||
)
|
||||
)
|
||||
(property "Value" "R"
|
||||
(at 67.31 62.2299 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left)
|
||||
)
|
||||
)
|
||||
(property "Footprint" "Resistor_SMD:R_0805_2012Metric"
|
||||
(at 62.992 60.96 90)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Datasheet" "~"
|
||||
(at 64.77 60.96 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Description" "Resistor"
|
||||
(at 64.77 60.96 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(pin "2"
|
||||
(uuid "53eae49a-03b2-47c9-b978-836e854c42a1")
|
||||
)
|
||||
(pin "1"
|
||||
(uuid "2dc56f9e-ed1a-423c-9716-246a54c077eb")
|
||||
)
|
||||
(instances
|
||||
(project ""
|
||||
(path "/d9ed75ce-7084-4177-b32b-fceb2cf7aac3"
|
||||
(reference "R1")
|
||||
(unit 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol
|
||||
(lib_id "Device:R")
|
||||
(at 74.93 60.96 0)
|
||||
(unit 1)
|
||||
(exclude_from_sim no)
|
||||
(in_bom yes)
|
||||
(on_board yes)
|
||||
(dnp no)
|
||||
(fields_autoplaced yes)
|
||||
(uuid "759e3836-df02-4bcc-823f-2488f4ccdc6a")
|
||||
(property "Reference" "R2"
|
||||
(at 77.47 59.6899 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left)
|
||||
)
|
||||
)
|
||||
(property "Value" "R"
|
||||
(at 77.47 62.2299 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left)
|
||||
)
|
||||
)
|
||||
(property "Footprint" "Resistor_SMD:R_1206_3216Metric"
|
||||
(at 73.152 60.96 90)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Datasheet" "~"
|
||||
(at 74.93 60.96 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Description" "Resistor"
|
||||
(at 74.93 60.96 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(pin "2"
|
||||
(uuid "213fa619-1218-4639-837f-def396924d49")
|
||||
)
|
||||
(pin "1"
|
||||
(uuid "3c26611e-5590-4cfc-9f38-c8d4c2888995")
|
||||
)
|
||||
(instances
|
||||
(project "dynamic_component_class"
|
||||
(path "/d9ed75ce-7084-4177-b32b-fceb2cf7aac3"
|
||||
(reference "R2")
|
||||
(unit 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol
|
||||
(lib_id "Device:C")
|
||||
(at 92.71 60.96 0)
|
||||
(unit 1)
|
||||
(exclude_from_sim no)
|
||||
(in_bom yes)
|
||||
(on_board yes)
|
||||
(dnp no)
|
||||
(fields_autoplaced yes)
|
||||
(uuid "ad3cf5f9-5e65-46c9-bb23-770c50780b5d")
|
||||
(property "Reference" "C1"
|
||||
(at 96.52 59.6899 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left)
|
||||
)
|
||||
)
|
||||
(property "Value" "C"
|
||||
(at 96.52 62.2299 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left)
|
||||
)
|
||||
)
|
||||
(property "Footprint" "Capacitor_SMD:C_0805_2012Metric"
|
||||
(at 93.6752 64.77 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Datasheet" "~"
|
||||
(at 92.71 60.96 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Description" "Unpolarized capacitor"
|
||||
(at 92.71 60.96 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(pin "1"
|
||||
(uuid "58054707-8b09-45ae-8013-e46b0d7e0c18")
|
||||
)
|
||||
(pin "2"
|
||||
(uuid "6718e73b-d736-47bd-ad02-995313219a5c")
|
||||
)
|
||||
(instances
|
||||
(project ""
|
||||
(path "/d9ed75ce-7084-4177-b32b-fceb2cf7aac3"
|
||||
(reference "C1")
|
||||
(unit 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol
|
||||
(lib_id "Device:C")
|
||||
(at 104.14 60.96 0)
|
||||
(unit 1)
|
||||
(exclude_from_sim no)
|
||||
(in_bom yes)
|
||||
(on_board yes)
|
||||
(dnp no)
|
||||
(fields_autoplaced yes)
|
||||
(uuid "efa7a2fa-3528-4332-b199-9931f7e1b80b")
|
||||
(property "Reference" "C2"
|
||||
(at 107.95 59.6899 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left)
|
||||
)
|
||||
)
|
||||
(property "Value" "C"
|
||||
(at 107.95 62.2299 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left)
|
||||
)
|
||||
)
|
||||
(property "Footprint" "Capacitor_SMD:C_0805_2012Metric"
|
||||
(at 105.1052 64.77 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Datasheet" "~"
|
||||
(at 104.14 60.96 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Description" "Unpolarized capacitor"
|
||||
(at 104.14 60.96 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(pin "1"
|
||||
(uuid "cb84c371-6a34-4196-b6f2-6452853b524b")
|
||||
)
|
||||
(pin "2"
|
||||
(uuid "24d51371-3fd2-4d66-9272-f054638174b7")
|
||||
)
|
||||
(instances
|
||||
(project "dynamic_component_class"
|
||||
(path "/d9ed75ce-7084-4177-b32b-fceb2cf7aac3"
|
||||
(reference "C2")
|
||||
(unit 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(sheet
|
||||
(at 148.59 40.64)
|
||||
(size 46.99 41.91)
|
||||
(exclude_from_sim no)
|
||||
(in_bom yes)
|
||||
(on_board yes)
|
||||
(dnp no)
|
||||
(fields_autoplaced yes)
|
||||
(stroke
|
||||
(width 0.1524)
|
||||
(type solid)
|
||||
)
|
||||
(fill
|
||||
(color 0 0 0 0.0000)
|
||||
)
|
||||
(uuid "e826c7ec-b0cb-4f53-915d-da3597387304")
|
||||
(property "Sheetname" "SHEET1"
|
||||
(at 148.59 39.9284 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left bottom)
|
||||
)
|
||||
)
|
||||
(property "Sheetfile" "component_classes_sheet1.kicad_sch"
|
||||
(at 148.59 83.1346 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left top)
|
||||
)
|
||||
)
|
||||
(instances
|
||||
(project "component_classes"
|
||||
(path "/d9ed75ce-7084-4177-b32b-fceb2cf7aac3"
|
||||
(page "2")
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(sheet_instances
|
||||
(path "/"
|
||||
(page "1")
|
||||
)
|
||||
)
|
||||
(embedded_fonts no)
|
||||
)
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <pcb_shape.h>
|
||||
#include <zone.h>
|
||||
#include <zone_filler.h>
|
||||
#include <drc/drc_cache_generator.h>
|
||||
#include <pcbnew_utils/board_file_utils.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <tool/tool_manager.h>
|
||||
@@ -113,6 +114,16 @@ void LoadBoard( SETTINGS_MANAGER& aSettingsManager, const wxString& aRelPath,
|
||||
aBoard->GetDesignSettings().m_DRCEngine = m_DRCEngine;
|
||||
aBoard->BuildListOfNets();
|
||||
aBoard->BuildConnectivity();
|
||||
|
||||
if( aBoard->GetProject() )
|
||||
{
|
||||
std::unordered_set<wxString> dummy;
|
||||
aBoard->SynchronizeComponentClasses( dummy );
|
||||
|
||||
DRC_CACHE_GENERATOR cacheGenerator;
|
||||
cacheGenerator.SetDRCEngine( m_DRCEngine.get() );
|
||||
cacheGenerator.Run();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ set( QA_PCBNEW_SRCS
|
||||
# test compilation units (start test_)
|
||||
test_array_pad_name_provider.cpp
|
||||
test_board_item.cpp
|
||||
test_component_classes.cpp
|
||||
test_generator_load_save.cpp
|
||||
test_graphics_load_save.cpp
|
||||
test_graphics_import_mgr.cpp
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <qa_utils/wx_utils/unit_test_utils.h>
|
||||
#include <pcbnew_utils/board_test_utils.h>
|
||||
#include <board.h>
|
||||
#include <board_design_settings.h>
|
||||
#include <component_classes/component_class.h>
|
||||
#include <pad.h>
|
||||
#include <pcb_track.h>
|
||||
#include <pcb_marker.h>
|
||||
#include <footprint.h>
|
||||
#include <drc/drc_item.h>
|
||||
#include <settings/settings_manager.h>
|
||||
|
||||
|
||||
struct PCB_COMPONENT_CLASS_FIXTURE
|
||||
{
|
||||
PCB_COMPONENT_CLASS_FIXTURE() :
|
||||
m_settingsManager( true /* headless */ )
|
||||
{ }
|
||||
|
||||
SETTINGS_MANAGER m_settingsManager;
|
||||
std::unique_ptr<BOARD> m_board;
|
||||
};
|
||||
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( ComponentClasses, PCB_COMPONENT_CLASS_FIXTURE )
|
||||
{
|
||||
KI_TEST::LoadBoard( m_settingsManager, "component_classes", m_board );
|
||||
|
||||
std::vector<DRC_ITEM> violations;
|
||||
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
|
||||
|
||||
std::vector<wxString> allClasses{ "ANY", "CAP_1", "CAP_2", "CLASS_1",
|
||||
"CLASS_2", "CLASS_3", "CLASS_4", "MULTI_REF",
|
||||
"REF_WILDCARD", "REF_WILDCARD2", "RES_1", "RES_2",
|
||||
"RES_3", "RES_4" };
|
||||
|
||||
auto testClasses = [&allClasses](const wxString& ref, const COMPONENT_CLASS* compClass, std::vector<wxString> assignedClasses)
|
||||
{
|
||||
std::vector<wxString> unassignedClasses;
|
||||
std::ranges::set_difference(allClasses, assignedClasses, std::back_inserter(unassignedClasses));
|
||||
|
||||
for( const wxString& className : assignedClasses )
|
||||
{
|
||||
if( !compClass->ContainsClassName( className ) )
|
||||
{
|
||||
BOOST_ERROR( wxString::Format(
|
||||
"%s component class failed (%s expected but not found - full class %s)",
|
||||
ref, className, compClass->GetName() ) );
|
||||
}
|
||||
}
|
||||
|
||||
for( const wxString& className : unassignedClasses )
|
||||
{
|
||||
if( compClass->ContainsClassName( className ) )
|
||||
{
|
||||
BOOST_ERROR( wxString::Format(
|
||||
"%s component class failed (%s found but not expected - full class %s)",
|
||||
ref, className, compClass->GetName() ) );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for( const auto fp : m_board->Footprints() )
|
||||
{
|
||||
if( fp->Reference().GetText() == wxT( "C1" ) )
|
||||
{
|
||||
testClasses( "C1", fp->GetComponentClass(), {"CAP_1", "CLASS_3", "CLASS_4"});
|
||||
}
|
||||
|
||||
if( fp->Reference().GetText() == wxT( "C2" ) )
|
||||
{
|
||||
testClasses( "C2", fp->GetComponentClass(), {"CAP_2", "CLASS_3"});
|
||||
}
|
||||
|
||||
if( fp->Reference().GetText() == wxT( "C3" ) )
|
||||
{
|
||||
testClasses( "C2", fp->GetComponentClass(), {});
|
||||
}
|
||||
|
||||
if( fp->Reference().GetText() == wxT( "R8" ) )
|
||||
{
|
||||
testClasses( "R8", fp->GetComponentClass(), {"RES_1", "RES_2"});
|
||||
}
|
||||
|
||||
if( fp->Reference().GetText() == wxT( "R88" ) )
|
||||
{
|
||||
testClasses( "R88", fp->GetComponentClass(), {"RES_2"});
|
||||
}
|
||||
|
||||
if( fp->Reference().GetText() == wxT( "R2" ) )
|
||||
{
|
||||
testClasses( "R2", fp->GetComponentClass(), {"CLASS_1", "RES_1", "RES_2", "RES_3"});
|
||||
}
|
||||
|
||||
if( fp->Reference().GetText() == wxT( "R1" ) )
|
||||
{
|
||||
testClasses( "R1", fp->GetComponentClass(), {"CLASS_1", "CLASS_2", "RES_1", "RES_2", "RES_4"});
|
||||
}
|
||||
|
||||
if( fp->Reference().GetText() == wxT( "U1" ) )
|
||||
{
|
||||
testClasses( "U1", fp->GetComponentClass(), { "ANY" } );
|
||||
}
|
||||
|
||||
if( fp->Reference().GetText() == wxT( "U2" ) )
|
||||
{
|
||||
testClasses( "U2", fp->GetComponentClass(), { "ANY" } );
|
||||
}
|
||||
|
||||
if( fp->Reference().GetText() == wxT( "U3" ) )
|
||||
{
|
||||
testClasses( "U3", fp->GetComponentClass(), { "MULTI_REF" } );
|
||||
}
|
||||
|
||||
if( fp->Reference().GetText() == wxT( "U4" ) )
|
||||
{
|
||||
testClasses( "U4", fp->GetComponentClass(), { "MULTI_REF" } );
|
||||
}
|
||||
|
||||
if( fp->Reference().GetText() == wxT( "U55" ) )
|
||||
{
|
||||
testClasses( "U55", fp->GetComponentClass(), { "REF_WILDCARD", "REF_WILDCARD2" } );
|
||||
}
|
||||
|
||||
if( fp->Reference().GetText() == wxT( "U555" ) )
|
||||
{
|
||||
testClasses( "U555", fp->GetComponentClass(), { "REF_WILDCARD2" } );
|
||||
}
|
||||
|
||||
if( fp->Reference().GetText() == wxT( "R3" ) )
|
||||
{
|
||||
testClasses( "R3", fp->GetComponentClass(), { "/SHEET1/", "RES_1", "RES_2" } );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user