mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-04-11 16:10:10 +00:00
Add SCH_RULE_AREA shapes to eeschema
Includes: - Fix GAL to draw closed polygons in eeschema - Add functionality to eeschema to draw arbitary polygons - Update polygon item previews to have customisable edge colour - Add new SCH_RULE_AREA class, derived from a poly SCH_SHAPE - Add SCH_RULE_AREA to paint and plot methods - Add new rule area color preference to themes
This commit is contained in:
parent
da1926d723
commit
be8744176c
common
eeschema
CMakeLists.txtconnection_graph.cppconnection_graph.hee_collectors.cpperc.cpperc.herc_item.cpperc_item.herc_settings.hmenubar.cppsch_commit.cppsch_edit_frame.cppsch_file_versions.h
sch_io/kicad_sexpr
sch_item.hsch_label.cppsch_label.hsch_painter.cppsch_plotter.hsch_rule_area.cppsch_rule_area.hsch_view.hschematic.keywordsschematic_undo_redo.cpptoolbars_sch_editor.cpptools
include
qa
data/eeschema
RuleAreaNetclassConflictOnWire_1.kicad_schRuleAreaNetclassConflictOnWire_2.kicad_schRuleAreaNoOverlap.kicad_schRuleAreaOneNetclassDirective.kicad_schRuleAreaOneOverlap.kicad_schRuleAreaOneOverlapTwice.kicad_schRuleAreaThreeNetclassDirectives.kicad_schRuleAreaTwoNetclassDirectives.kicad_schRuleAreaTwoOverlaps.kicad_sch
tests/eeschema
@ -374,6 +374,7 @@ static struct EDA_ITEM_DESC
|
||||
.Map( SCH_LINE_T, _HKI( "Line" ) )
|
||||
.Map( SCH_BITMAP_T, _HKI( "Bitmap" ) )
|
||||
.Map( SCH_SHAPE_T, _HKI( "Graphic" ) )
|
||||
.Map( SCH_RULE_AREA_T, _HKI( "Rule Area" ) )
|
||||
.Map( SCH_TEXT_T, _HKI( "Text" ) )
|
||||
.Map( SCH_TEXTBOX_T, _HKI( "Text Box" ) )
|
||||
.Map( SCH_TABLE_T, _HKI( "Table" ) )
|
||||
|
@ -122,6 +122,7 @@ wxString LayerName( int aLayer )
|
||||
case LAYER_FIELDS: return _( "Symbol fields" );
|
||||
case LAYER_INTERSHEET_REFS: return _( "Sheet references" );
|
||||
case LAYER_NETCLASS_REFS: return _( "Net class references" );
|
||||
case LAYER_RULE_AREAS: return _( "Rule areas" );
|
||||
case LAYER_DEVICE: return _( "Symbol body outlines" );
|
||||
case LAYER_DEVICE_BACKGROUND: return _( "Symbol body fills" );
|
||||
case LAYER_NOTES: return _( "Schematic text && graphics" );
|
||||
|
@ -33,6 +33,20 @@ const double POLYGON_ITEM::POLY_LINE_WIDTH = 1;
|
||||
POLYGON_ITEM::POLYGON_ITEM() :
|
||||
SIMPLE_OVERLAY_ITEM()
|
||||
{
|
||||
m_lineColor = KIGFX::COLOR4D::UNSPECIFIED;
|
||||
m_leaderColor = KIGFX::COLOR4D::UNSPECIFIED;
|
||||
}
|
||||
|
||||
|
||||
void POLYGON_ITEM::SetLineColor( KIGFX::COLOR4D lineColor )
|
||||
{
|
||||
m_lineColor = lineColor;
|
||||
}
|
||||
|
||||
|
||||
void POLYGON_ITEM::SetLeaderColor( KIGFX::COLOR4D leaderColor )
|
||||
{
|
||||
m_leaderColor = leaderColor;
|
||||
}
|
||||
|
||||
|
||||
@ -62,8 +76,13 @@ void POLYGON_ITEM::drawPreviewShape( KIGFX::VIEW* aView ) const
|
||||
KIGFX::GAL& gal = *aView->GetGAL();
|
||||
RENDER_SETTINGS* renderSettings = aView->GetPainter()->GetSettings();
|
||||
|
||||
gal.SetIsStroke( true );
|
||||
|
||||
if( m_lockedChain.PointCount() >= 2 )
|
||||
{
|
||||
if( m_lineColor != KIGFX::COLOR4D::UNSPECIFIED )
|
||||
gal.SetStrokeColor( m_lineColor );
|
||||
|
||||
gal.SetLineWidth( (float) aView->ToWorld( POLY_LINE_WIDTH ) );
|
||||
gal.DrawPolyline( m_lockedChain );
|
||||
}
|
||||
@ -71,7 +90,11 @@ void POLYGON_ITEM::drawPreviewShape( KIGFX::VIEW* aView ) const
|
||||
// draw the leader line in a different color
|
||||
if( m_leaderChain.PointCount() >= 2 )
|
||||
{
|
||||
gal.SetStrokeColor( renderSettings->GetLayerColor( LAYER_AUX_ITEMS ) );
|
||||
if( m_leaderColor != KIGFX::COLOR4D::UNSPECIFIED )
|
||||
gal.SetStrokeColor( m_leaderColor );
|
||||
else
|
||||
gal.SetStrokeColor( renderSettings->GetLayerColor( LAYER_AUX_ITEMS ) );
|
||||
|
||||
gal.DrawPolyline( m_leaderChain );
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,7 @@ static const std::map<int, COLOR4D> s_defaultTheme =
|
||||
{ LAYER_HIERLABEL, CSS_COLOR( 114, 86, 0, 1 ) },
|
||||
{ LAYER_LOCLABEL, CSS_COLOR( 15, 15, 15, 1 ) },
|
||||
{ LAYER_NETCLASS_REFS, CSS_COLOR( 72, 72, 72, 1 ) },
|
||||
{ LAYER_RULE_AREAS, CSS_COLOR( 255, 0, 0, 1 ) },
|
||||
{ LAYER_NOCONNECT, CSS_COLOR( 0, 0, 132, 1 ) },
|
||||
{ LAYER_NOTES, CSS_COLOR( 0, 0, 194, 1 ) },
|
||||
{ LAYER_PRIVATE_NOTES, CSS_COLOR( 72, 72, 255, 1 ) },
|
||||
@ -268,6 +269,7 @@ static const std::map<int, COLOR4D> s_classicTheme =
|
||||
{ LAYER_HIERLABEL, COLOR4D( BROWN ) },
|
||||
{ LAYER_LOCLABEL, COLOR4D( BLACK ) },
|
||||
{ LAYER_NETCLASS_REFS, COLOR4D( BLACK ) },
|
||||
{ LAYER_RULE_AREAS, COLOR4D( RED ) },
|
||||
{ LAYER_NOCONNECT, COLOR4D( BLUE ) },
|
||||
{ LAYER_NOTES, COLOR4D( LIGHTBLUE ) },
|
||||
{ LAYER_PRIVATE_NOTES, COLOR4D( LIGHTBLUE ) },
|
||||
|
@ -75,6 +75,7 @@ COLOR_SETTINGS::COLOR_SETTINGS( const wxString& aFilename, bool aAbsolutePath )
|
||||
CLR( "schematic.label_hier", LAYER_HIERLABEL );
|
||||
CLR( "schematic.label_local", LAYER_LOCLABEL );
|
||||
CLR( "schematic.netclass_flag", LAYER_NETCLASS_REFS );
|
||||
CLR( "schematic.rule_area", LAYER_RULE_AREAS );
|
||||
CLR( "schematic.no_connect", LAYER_NOCONNECT );
|
||||
CLR( "schematic.note", LAYER_NOTES );
|
||||
CLR( "schematic.private_note", LAYER_PRIVATE_NOTES );
|
||||
|
@ -383,6 +383,7 @@ set( EESCHEMA_SRCS
|
||||
sch_render_settings.cpp
|
||||
sch_screen.cpp
|
||||
sch_shape.cpp
|
||||
sch_rule_area.cpp
|
||||
sch_sheet.cpp
|
||||
sch_sheet_path.cpp
|
||||
sch_sheet_pin.cpp
|
||||
@ -431,6 +432,7 @@ set( EESCHEMA_SRCS
|
||||
tools/ee_point_editor.cpp
|
||||
tools/ee_selection.cpp
|
||||
tools/ee_selection_tool.cpp
|
||||
tools/rule_area_create_helper.cpp
|
||||
tools/sch_drawing_tools.cpp
|
||||
tools/sch_edit_table_tool.cpp
|
||||
tools/sch_edit_tool.cpp
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <sch_line.h>
|
||||
#include <sch_marker.h>
|
||||
#include <sch_pin.h>
|
||||
#include <sch_rule_area.h>
|
||||
#include <sch_sheet.h>
|
||||
#include <sch_sheet_path.h>
|
||||
#include <sch_sheet_pin.h>
|
||||
@ -430,10 +431,35 @@ const wxString& CONNECTION_SUBGRAPH::GetNameForDriver( SCH_ITEM* aItem ) const
|
||||
}
|
||||
|
||||
|
||||
const wxString CONNECTION_SUBGRAPH::GetNetclassForDriver( SCH_ITEM* aItem ) const
|
||||
const std::vector<std::pair<wxString, SCH_ITEM*>>
|
||||
CONNECTION_SUBGRAPH::GetNetclassesForDriver( SCH_ITEM* aItem, bool returnAll ) const
|
||||
{
|
||||
wxString netclass;
|
||||
std::vector<std::pair<wxString, SCH_ITEM*>> foundNetclasses;
|
||||
|
||||
const std::unordered_set<SCH_RULE_AREA*>& ruleAreaCache = aItem->GetRuleAreaCache();
|
||||
|
||||
// Get netclasses on attached rule areas
|
||||
for( SCH_RULE_AREA* ruleArea : ruleAreaCache )
|
||||
{
|
||||
const std::vector<std::pair<wxString, SCH_ITEM*>> ruleNetclasses =
|
||||
ruleArea->GetResolvedNetclasses();
|
||||
|
||||
if( ruleNetclasses.size() > 0 )
|
||||
{
|
||||
if( returnAll )
|
||||
{
|
||||
foundNetclasses.insert( foundNetclasses.end(), ruleNetclasses.begin(),
|
||||
ruleNetclasses.end() );
|
||||
}
|
||||
else
|
||||
{
|
||||
foundNetclasses.push_back( ruleNetclasses[0] );
|
||||
return foundNetclasses;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get netclasses on child fields
|
||||
aItem->RunOnChildren(
|
||||
[&]( SCH_ITEM* aChild )
|
||||
{
|
||||
@ -443,15 +469,19 @@ const wxString CONNECTION_SUBGRAPH::GetNetclassForDriver( SCH_ITEM* aItem ) cons
|
||||
|
||||
if( field->GetCanonicalName() == wxT( "Netclass" ) )
|
||||
{
|
||||
netclass = field->GetText();
|
||||
return false;
|
||||
wxString netclass = field->GetText();
|
||||
|
||||
if( netclass != wxEmptyString )
|
||||
foundNetclasses.push_back( { field->GetText(), aItem } );
|
||||
|
||||
return returnAll;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} );
|
||||
|
||||
return netclass;
|
||||
return foundNetclasses;
|
||||
}
|
||||
|
||||
|
||||
@ -742,7 +772,9 @@ void CONNECTION_GRAPH::Recalculate( const SCH_SHEET_LIST& aSheetList, bool aUnco
|
||||
}
|
||||
else if( item->Type() == SCH_SHEET_T )
|
||||
{
|
||||
for( SCH_SHEET_PIN* pin : static_cast<SCH_SHEET*>( item )->GetPins() )
|
||||
SCH_SHEET* sheetItem = static_cast<SCH_SHEET*>( item );
|
||||
|
||||
for( SCH_SHEET_PIN* pin : sheetItem->GetPins() )
|
||||
{
|
||||
if( pin->IsConnectivityDirty() )
|
||||
{
|
||||
@ -2347,10 +2379,14 @@ void CONNECTION_GRAPH::buildConnectionGraph( std::function<void( SCH_ITEM* )>* a
|
||||
{
|
||||
for( SCH_ITEM* item : subgraph->m_items )
|
||||
{
|
||||
netclass = subgraph->GetNetclassForDriver( item );
|
||||
const std::vector<std::pair<wxString, SCH_ITEM*>> netclassesWithProviders =
|
||||
subgraph->GetNetclassesForDriver( item, false );
|
||||
|
||||
if( !netclass.IsEmpty() )
|
||||
if( netclassesWithProviders.size() > 0 )
|
||||
{
|
||||
netclass = netclassesWithProviders[0].first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( !netclass.IsEmpty() )
|
||||
@ -3188,40 +3224,52 @@ bool CONNECTION_GRAPH::ercCheckNetclassConflicts( const std::vector<CONNECTION_S
|
||||
wxString firstNetclass;
|
||||
SCH_ITEM* firstNetclassDriver = nullptr;
|
||||
const SCH_SHEET_PATH* firstNetclassDriverSheet = nullptr;
|
||||
bool conflictFound = false;
|
||||
|
||||
for( const CONNECTION_SUBGRAPH* subgraph : subgraphs )
|
||||
{
|
||||
for( SCH_ITEM* item : subgraph->m_items )
|
||||
{
|
||||
const wxString netclass = subgraph->GetNetclassForDriver( item );
|
||||
const std::vector<std::pair<wxString, SCH_ITEM*>> netclassesWithProvider =
|
||||
subgraph->GetNetclassesForDriver( item, true );
|
||||
|
||||
if( netclass.IsEmpty() )
|
||||
if( netclassesWithProvider.size() == 0 )
|
||||
continue;
|
||||
|
||||
if( netclass != firstNetclass )
|
||||
auto checkNetclass = [&]( const std::pair<wxString, SCH_ITEM*>& netclass )
|
||||
{
|
||||
if( !firstNetclassDriver )
|
||||
if( netclass.first != firstNetclass )
|
||||
{
|
||||
firstNetclass = netclass;
|
||||
firstNetclassDriver = item;
|
||||
firstNetclassDriverSheet = &subgraph->GetSheet();
|
||||
continue;
|
||||
if( !firstNetclassDriver )
|
||||
{
|
||||
firstNetclass = netclass.first;
|
||||
firstNetclassDriver = netclass.second;
|
||||
firstNetclassDriverSheet = &subgraph->GetSheet();
|
||||
}
|
||||
else
|
||||
{
|
||||
conflictFound = true;
|
||||
|
||||
std::shared_ptr<ERC_ITEM> ercItem =
|
||||
ERC_ITEM::Create( ERCE_NETCLASS_CONFLICT );
|
||||
ercItem->SetItems( firstNetclassDriver, netclass.second );
|
||||
ercItem->SetSheetSpecificPath( subgraph->GetSheet() );
|
||||
ercItem->SetItemsSheetPaths( *firstNetclassDriverSheet,
|
||||
subgraph->GetSheet() );
|
||||
|
||||
SCH_MARKER* marker =
|
||||
new SCH_MARKER( ercItem, netclass.second->GetPosition() );
|
||||
subgraph->m_sheet.LastScreen()->Append( marker );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_NETCLASS_CONFLICT );
|
||||
ercItem->SetItems( firstNetclassDriver, item );
|
||||
ercItem->SetSheetSpecificPath( subgraph->GetSheet() );
|
||||
ercItem->SetItemsSheetPaths( *firstNetclassDriverSheet, subgraph->GetSheet() );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, item->GetPosition() );
|
||||
subgraph->m_sheet.LastScreen()->Append( marker );
|
||||
|
||||
return false;
|
||||
}
|
||||
for( const std::pair<wxString, SCH_ITEM*>& netclass : netclassesWithProvider )
|
||||
checkNetclass( netclass );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return conflictFound;
|
||||
}
|
||||
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#define _CONNECTION_GRAPH_H
|
||||
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <erc_settings.h>
|
||||
@ -122,7 +123,12 @@ public:
|
||||
/// Return the candidate net name for a driver.
|
||||
const wxString& GetNameForDriver( SCH_ITEM* aItem ) const;
|
||||
|
||||
const wxString GetNetclassForDriver( SCH_ITEM* aItem ) const;
|
||||
/// Return the resolved netclasses for the item, and the source item providing the netclass
|
||||
/// @param aItem the item to query for netclass assignments
|
||||
/// @param returnAll If true, return all assigned netclasses (for ERC). If false, stop on first
|
||||
/// netclass (for connectivity).
|
||||
const std::vector<std::pair<wxString, SCH_ITEM*>>
|
||||
GetNetclassesForDriver( SCH_ITEM* aItem, bool returnAll ) const;
|
||||
|
||||
/// Combine another subgraph on the same sheet into this one.
|
||||
void Absorb( CONNECTION_SUBGRAPH* aOther );
|
||||
|
@ -51,7 +51,8 @@ const std::vector<KICAD_T> EE_COLLECTOR::EditableItems = {
|
||||
SCH_BITMAP_T,
|
||||
SCH_LINE_T,
|
||||
SCH_BUS_WIRE_ENTRY_T,
|
||||
SCH_JUNCTION_T
|
||||
SCH_JUNCTION_T,
|
||||
SCH_RULE_AREA_T
|
||||
};
|
||||
|
||||
|
||||
@ -76,7 +77,8 @@ const std::vector<KICAD_T> EE_COLLECTOR::MovableItems =
|
||||
SCH_FIELD_T,
|
||||
SCH_SYMBOL_T,
|
||||
SCH_SHEET_PIN_T,
|
||||
SCH_SHEET_T
|
||||
SCH_SHEET_T,
|
||||
SCH_RULE_AREA_T
|
||||
};
|
||||
|
||||
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <sch_edit_frame.h>
|
||||
#include <sch_marker.h>
|
||||
#include <sch_reference_list.h>
|
||||
#include <sch_rule_area.h>
|
||||
#include <sch_sheet.h>
|
||||
#include <sch_sheet_pin.h>
|
||||
#include <sch_textbox.h>
|
||||
@ -1229,6 +1230,73 @@ int ERC_TESTER::TestSimModelIssues()
|
||||
}
|
||||
|
||||
|
||||
int ERC_TESTER::RunRuleAreaERC()
|
||||
{
|
||||
int numErrors = 0;
|
||||
ERC_SETTINGS& settings = m_schematic->ErcSettings();
|
||||
|
||||
if( !settings.IsTestEnabled( ERCE_OVERLAPPING_RULE_AREAS ) )
|
||||
return 0;
|
||||
|
||||
std::map<SCH_SCREEN*, std::vector<SCH_RULE_AREA*>> allScreenRuleAreas;
|
||||
|
||||
SCH_SCREENS screens( m_schematic->Root() );
|
||||
|
||||
for( SCH_SCREEN* screen = screens.GetFirst(); screen != nullptr; screen = screens.GetNext() )
|
||||
{
|
||||
for( SCH_ITEM* item : screen->Items().OfType( SCH_RULE_AREA_T ) )
|
||||
{
|
||||
allScreenRuleAreas[screen].push_back( static_cast<SCH_RULE_AREA*>( item ) );
|
||||
}
|
||||
}
|
||||
|
||||
if( settings.IsTestEnabled( ERCE_OVERLAPPING_RULE_AREAS ) )
|
||||
numErrors += TestRuleAreaOverlappingRuleAreasERC( allScreenRuleAreas );
|
||||
|
||||
return numErrors;
|
||||
}
|
||||
|
||||
|
||||
int ERC_TESTER::TestRuleAreaOverlappingRuleAreasERC(
|
||||
std::map<SCH_SCREEN*, std::vector<SCH_RULE_AREA*>>& allScreenRuleAreas )
|
||||
{
|
||||
int numErrors = 0;
|
||||
|
||||
for( auto screenRuleAreas : allScreenRuleAreas )
|
||||
{
|
||||
std::vector<SCH_RULE_AREA*>& ruleAreas = screenRuleAreas.second;
|
||||
|
||||
for( std::size_t i = 0; i < ruleAreas.size(); ++i )
|
||||
{
|
||||
SHAPE_POLY_SET& polyFirst = ruleAreas[i]->GetPolyShape();
|
||||
|
||||
for( std::size_t j = i + 1; j < ruleAreas.size(); ++j )
|
||||
{
|
||||
SHAPE_POLY_SET polySecond = ruleAreas[j]->GetPolyShape();
|
||||
if( polyFirst.Collide( &polySecond ) )
|
||||
{
|
||||
numErrors++;
|
||||
|
||||
SCH_SCREEN* screen = screenRuleAreas.first;
|
||||
SCH_SHEET_PATH firstSheet = screen->GetClientSheetPaths()[0];
|
||||
|
||||
std::shared_ptr<ERC_ITEM> ercItem =
|
||||
ERC_ITEM::Create( ERCE_OVERLAPPING_RULE_AREAS );
|
||||
ercItem->SetItems( ruleAreas[i], ruleAreas[j] );
|
||||
ercItem->SetSheetSpecificPath( firstSheet );
|
||||
ercItem->SetItemsSheetPaths( firstSheet, firstSheet );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, ruleAreas[i]->GetPosition() );
|
||||
screen->Append( marker );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return numErrors;
|
||||
}
|
||||
|
||||
|
||||
void ERC_TESTER::RunTests( DS_PROXY_VIEW_ITEM* aDrawingSheet, SCH_EDIT_FRAME* aEditFrame,
|
||||
KIFACE* aCvPcb, PROJECT* aProject, PROGRESS_REPORTER* aProgressReporter )
|
||||
{
|
||||
@ -1267,6 +1335,14 @@ void ERC_TESTER::RunTests( DS_PROXY_VIEW_ITEM* aDrawingSheet, SCH_EDIT_FRAME* aE
|
||||
|
||||
m_schematic->ConnectionGraph()->RunERC();
|
||||
|
||||
if( aProgressReporter )
|
||||
aProgressReporter->AdvancePhase( _( "Checking rule areas..." ) );
|
||||
|
||||
if( settings.IsTestEnabled( ERCE_OVERLAPPING_RULE_AREAS ) )
|
||||
{
|
||||
RunRuleAreaERC();
|
||||
}
|
||||
|
||||
if( aProgressReporter )
|
||||
aProgressReporter->AdvancePhase( _( "Checking units..." ) );
|
||||
|
||||
|
@ -27,6 +27,8 @@
|
||||
#define ERC_H
|
||||
|
||||
#include <erc_settings.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
|
||||
class SCH_SHEET_LIST;
|
||||
@ -36,6 +38,8 @@ class SCH_EDIT_FRAME;
|
||||
class PROGRESS_REPORTER;
|
||||
struct KIFACE;
|
||||
class PROJECT;
|
||||
class SCREEN;
|
||||
class SCH_RULE_AREA;
|
||||
|
||||
|
||||
extern const wxString CommentERC_H[];
|
||||
@ -141,6 +145,17 @@ public:
|
||||
*/
|
||||
int TestMissingNetclasses();
|
||||
|
||||
/**
|
||||
* Tests for rule area ERC issues
|
||||
*/
|
||||
int RunRuleAreaERC();
|
||||
|
||||
/**
|
||||
* Runs ERC to check for overlapping rule areas
|
||||
*/
|
||||
int TestRuleAreaOverlappingRuleAreasERC(
|
||||
std::map<SCH_SCREEN*, std::vector<SCH_RULE_AREA*>>& allScreenRuleAreas );
|
||||
|
||||
void RunTests( DS_PROXY_VIEW_ITEM* aDrawingSheet, SCH_EDIT_FRAME* aEditFrame,
|
||||
KIFACE* aCvPcb, PROJECT* aProject, PROGRESS_REPORTER* aProgressReporter );
|
||||
|
||||
|
@ -119,6 +119,10 @@ ERC_ITEM ERC_ITEM::netclassConflict( ERCE_NETCLASS_CONFLICT,
|
||||
_( "Conflicting netclass assignments" ),
|
||||
wxT( "conflicting_netclasses" ) );
|
||||
|
||||
ERC_ITEM ERC_ITEM::overlappingRuleAreas( ERCE_OVERLAPPING_RULE_AREAS,
|
||||
_( "Overlapping rule areas" ),
|
||||
wxT( "overlapping_rule_areas" ) );
|
||||
|
||||
ERC_ITEM ERC_ITEM::netNotBusMember( ERCE_BUS_ENTRY_CONFLICT,
|
||||
_( "Net is graphically connected to a bus but not a bus member" ),
|
||||
wxT( "net_not_bus_member" ) );
|
||||
@ -239,7 +243,8 @@ std::vector<std::reference_wrapper<RC_ITEM>> ERC_ITEM::allItemTypes( {
|
||||
ERC_ITEM::missingUnits,
|
||||
ERC_ITEM::missingInputPin,
|
||||
ERC_ITEM::missingBidiPin,
|
||||
ERC_ITEM::missingPowerInputPin
|
||||
ERC_ITEM::missingPowerInputPin,
|
||||
ERC_ITEM::overlappingRuleAreas
|
||||
} );
|
||||
|
||||
|
||||
@ -269,6 +274,7 @@ std::shared_ptr<ERC_ITEM> ERC_ITEM::Create( int aErrorCode )
|
||||
case ERCE_BUS_TO_BUS_CONFLICT: return std::make_shared<ERC_ITEM>( busToBusConflict );
|
||||
case ERCE_BUS_TO_NET_CONFLICT: return std::make_shared<ERC_ITEM>( busToNetConflict );
|
||||
case ERCE_NETCLASS_CONFLICT: return std::make_shared<ERC_ITEM>( netclassConflict );
|
||||
case ERCE_OVERLAPPING_RULE_AREAS: return std::make_shared<ERC_ITEM>( overlappingRuleAreas );
|
||||
case ERCE_GLOBLABEL: return std::make_shared<ERC_ITEM>( globalLabelDangling );
|
||||
case ERCE_UNRESOLVED_VARIABLE: return std::make_shared<ERC_ITEM>( unresolvedVariable );
|
||||
case ERCE_UNDEFINED_NETCLASS: return std::make_shared<ERC_ITEM>( undefinedNetclass );
|
||||
|
@ -202,6 +202,7 @@ private:
|
||||
static ERC_ITEM busDefinitionConflict;
|
||||
static ERC_ITEM multipleNetNames;
|
||||
static ERC_ITEM netclassConflict;
|
||||
static ERC_ITEM overlappingRuleAreas;
|
||||
static ERC_ITEM netNotBusMember;
|
||||
static ERC_ITEM busToBusConflict;
|
||||
static ERC_ITEM busToNetConflict;
|
||||
|
@ -67,6 +67,7 @@ enum ERCE_T
|
||||
ERCE_BUS_TO_NET_CONFLICT, ///< A bus wire is graphically connected to a net port/pin
|
||||
///< (or vice versa).
|
||||
ERCE_NETCLASS_CONFLICT, ///< Multiple labels assign different netclasses to same net.
|
||||
ERCE_OVERLAPPING_RULE_AREAS, ///< Rule areas are overlapping
|
||||
ERCE_GLOBLABEL, ///< A global label is unique.
|
||||
ERCE_UNRESOLVED_VARIABLE, ///< A text variable could not be resolved.
|
||||
ERCE_UNDEFINED_NETCLASS, ///< A netclass was referenced but not defined.
|
||||
|
@ -248,8 +248,9 @@ void SCH_EDIT_FRAME::doReCreateMenuBar()
|
||||
placeMenu->Add( EE_ACTIONS::placeNoConnect );
|
||||
placeMenu->Add( EE_ACTIONS::placeJunction );
|
||||
placeMenu->Add( EE_ACTIONS::placeLabel );
|
||||
placeMenu->Add( EE_ACTIONS::placeClassLabel );
|
||||
placeMenu->Add( EE_ACTIONS::placeGlobalLabel );
|
||||
placeMenu->Add( EE_ACTIONS::placeClassLabel );
|
||||
placeMenu->Add( EE_ACTIONS::drawRuleArea );
|
||||
|
||||
placeMenu->AppendSeparator();
|
||||
placeMenu->Add( EE_ACTIONS::placeHierLabel );
|
||||
|
@ -221,22 +221,21 @@ void SCH_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
|
||||
} );
|
||||
}
|
||||
|
||||
auto updateConnectivityFlag =
|
||||
[&]()
|
||||
{
|
||||
if( schItem->IsConnectable() )
|
||||
{
|
||||
dirtyConnectivity = true;
|
||||
auto updateConnectivityFlag = [&]()
|
||||
{
|
||||
if( schItem->IsConnectable() || ( schItem->Type() == SCH_RULE_AREA_T ) )
|
||||
{
|
||||
dirtyConnectivity = true;
|
||||
|
||||
// Do a local clean up if there are any connectable objects in the commit.
|
||||
if( connectivityCleanUp == NO_CLEANUP )
|
||||
connectivityCleanUp = LOCAL_CLEANUP;
|
||||
// Do a local clean up if there are any connectable objects in the commit.
|
||||
if( connectivityCleanUp == NO_CLEANUP )
|
||||
connectivityCleanUp = LOCAL_CLEANUP;
|
||||
|
||||
// Do a full rebauild of the connectivity if there is a sheet in the commit.
|
||||
if( schItem->Type() == SCH_SHEET_T )
|
||||
connectivityCleanUp = GLOBAL_CLEANUP;
|
||||
}
|
||||
};
|
||||
// Do a full rebauild of the connectivity if there is a sheet in the commit.
|
||||
if( schItem->Type() == SCH_SHEET_T )
|
||||
connectivityCleanUp = GLOBAL_CLEANUP;
|
||||
}
|
||||
};
|
||||
|
||||
switch( changeType )
|
||||
{
|
||||
@ -318,8 +317,11 @@ void SCH_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
|
||||
if( frame )
|
||||
currentSheet = frame->GetCurrentSheet();
|
||||
|
||||
if( itemCopy->HasConnectivityChanges( schItem, ¤tSheet ) )
|
||||
if( itemCopy->HasConnectivityChanges( schItem, ¤tSheet )
|
||||
|| ( itemCopy->Type() == SCH_RULE_AREA_T ) )
|
||||
{
|
||||
updateConnectivityFlag();
|
||||
}
|
||||
|
||||
undoList.PushItem( itemWrapper );
|
||||
ent.m_copy = nullptr; // We've transferred ownership to the undo list
|
||||
|
@ -22,6 +22,7 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <api/api_handler_sch.h>
|
||||
#include <api/api_server.h>
|
||||
#include <base_units.h>
|
||||
@ -36,6 +37,7 @@
|
||||
#include <eeschema_id.h>
|
||||
#include <executable_names.h>
|
||||
#include <gal/graphics_abstraction_layer.h>
|
||||
#include <geometry/shape_segment.h>
|
||||
#include <gestfich.h>
|
||||
#include <dialogs/html_message_box.h>
|
||||
#include <core/ignore.h>
|
||||
@ -59,6 +61,7 @@
|
||||
#include <sch_sheet_pin.h>
|
||||
#include <schematic.h>
|
||||
#include <sch_commit.h>
|
||||
#include <sch_rule_area.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <advanced_config.h>
|
||||
#include <sim/simulator_frame.h>
|
||||
@ -85,6 +88,7 @@
|
||||
#include <tools/sch_move_tool.h>
|
||||
#include <tools/sch_navigate_tool.h>
|
||||
#include <tools/sch_find_replace_tool.h>
|
||||
#include <unordered_set>
|
||||
#include <view/view_controls.h>
|
||||
#include <widgets/wx_infobar.h>
|
||||
#include <widgets/hierarchy_pane.h>
|
||||
@ -756,6 +760,7 @@ void SCH_EDIT_FRAME::setupUIConditions()
|
||||
CURRENT_TOOL( EE_ACTIONS::placeClassLabel );
|
||||
CURRENT_TOOL( EE_ACTIONS::placeGlobalLabel );
|
||||
CURRENT_TOOL( EE_ACTIONS::placeHierLabel );
|
||||
CURRENT_TOOL( EE_ACTIONS::drawRuleArea );
|
||||
CURRENT_TOOL( EE_ACTIONS::drawSheet );
|
||||
CURRENT_TOOL( EE_ACTIONS::placeSheetPin );
|
||||
CURRENT_TOOL( EE_ACTIONS::syncSheetPins );
|
||||
@ -1763,52 +1768,150 @@ void SCH_EDIT_FRAME::RecalculateConnections( SCH_COMMIT* aCommit, SCH_CLEANUP_FL
|
||||
if( !ADVANCED_CFG::GetCfg().m_IncrementalConnectivity || aCleanupFlags == GLOBAL_CLEANUP
|
||||
|| m_undoList.m_CommandsList.empty() )
|
||||
{
|
||||
// Update all rule areas so we can cascade implied connectivity changes
|
||||
std::unordered_set<SCH_SCREEN*> all_screens;
|
||||
|
||||
for( const SCH_SHEET_PATH& path : list )
|
||||
all_screens.insert( path.LastScreen() );
|
||||
|
||||
SCH_RULE_AREA::UpdateRuleAreasInScreens( all_screens, GetCanvas()->GetView() );
|
||||
|
||||
// Recalculate all connectivity
|
||||
Schematic().ConnectionGraph()->Recalculate( list, true, &changeHandler );
|
||||
}
|
||||
else
|
||||
{
|
||||
struct CHANGED_ITEM
|
||||
{
|
||||
SCH_ITEM* item;
|
||||
SCH_ITEM* linked_item;
|
||||
SCH_SCREEN* screen;
|
||||
};
|
||||
|
||||
PICKED_ITEMS_LIST* changed_list = m_undoList.m_CommandsList.back();
|
||||
std::set<SCH_ITEM*> changed_items;
|
||||
std::set<VECTOR2I> pts;
|
||||
|
||||
// Final change sets
|
||||
std::set<SCH_ITEM*> changed_items;
|
||||
std::set<VECTOR2I> pts;
|
||||
std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> item_paths;
|
||||
|
||||
for( unsigned ii = 0; ii < changed_list->GetCount(); ++ii )
|
||||
// Working change sets
|
||||
std::unordered_set<SCH_SCREEN*> changed_screens;
|
||||
std::set<std::pair<SCH_RULE_AREA*, SCH_SCREEN*>> changed_rule_areas;
|
||||
std::vector<CHANGED_ITEM> changed_connectable_items;
|
||||
|
||||
// Lambda to add an item to the connectivity update sets
|
||||
auto addItemToChangeSet =
|
||||
[&changed_items, &pts, &item_paths, &changed_screens]( CHANGED_ITEM itemData )
|
||||
{
|
||||
SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( changed_list->GetPickedItem( ii ) );
|
||||
SCH_SHEET_PATHS& paths = itemData.screen->GetClientSheetPaths();
|
||||
|
||||
// Ignore objects that are not connectable.
|
||||
if( !item || !item->IsConnectable() )
|
||||
continue;
|
||||
|
||||
SCH_SCREEN* screen = static_cast<SCH_SCREEN*>( changed_list->GetScreenForItem( ii ) );
|
||||
SCH_SHEET_PATHS& paths = screen->GetClientSheetPaths();
|
||||
|
||||
std::vector<VECTOR2I> tmp_pts = item->GetConnectionPoints();
|
||||
std::vector<VECTOR2I> tmp_pts = itemData.item->GetConnectionPoints();
|
||||
pts.insert( tmp_pts.begin(), tmp_pts.end() );
|
||||
changed_items.insert( item );
|
||||
changed_items.insert( itemData.item );
|
||||
|
||||
for( SCH_SHEET_PATH& path : paths )
|
||||
item_paths.insert( std::make_pair( path, item ) );
|
||||
item_paths.insert( std::make_pair( path, itemData.item ) );
|
||||
|
||||
item = dynamic_cast<SCH_ITEM*>( changed_list->GetPickedItemLink( ii ) );
|
||||
if( !itemData.linked_item || !itemData.linked_item->IsConnectable() )
|
||||
return;
|
||||
|
||||
if( !item || !item->IsConnectable() )
|
||||
continue;
|
||||
|
||||
tmp_pts = item->GetConnectionPoints();
|
||||
tmp_pts = itemData.linked_item->GetConnectionPoints();
|
||||
pts.insert( tmp_pts.begin(), tmp_pts.end() );
|
||||
changed_items.insert( item );
|
||||
changed_items.insert( itemData.linked_item );
|
||||
|
||||
// We have to directly add the pins here because the link may not exist on the schematic
|
||||
// anymore and so won't be picked up by GetScreen()->Items().Overlapping() below.
|
||||
if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item ) )
|
||||
if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( itemData.linked_item ) )
|
||||
{
|
||||
std::vector<SCH_PIN*> pins = symbol->GetPins();
|
||||
changed_items.insert( pins.begin(), pins.end() );
|
||||
}
|
||||
|
||||
for( SCH_SHEET_PATH& path : paths )
|
||||
item_paths.insert( std::make_pair( path, item ) );
|
||||
item_paths.insert( std::make_pair( path, itemData.linked_item ) );
|
||||
};
|
||||
|
||||
// Get all changed connectable items and determine all changed screens
|
||||
for( unsigned ii = 0; ii < changed_list->GetCount(); ++ii )
|
||||
{
|
||||
SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( changed_list->GetPickedItem( ii ) );
|
||||
|
||||
if( item )
|
||||
{
|
||||
SCH_SCREEN* screen =
|
||||
static_cast<SCH_SCREEN*>( changed_list->GetScreenForItem( ii ) );
|
||||
changed_screens.insert( screen );
|
||||
|
||||
if( item->Type() == SCH_RULE_AREA_T )
|
||||
{
|
||||
SCH_RULE_AREA* ruleArea = static_cast<SCH_RULE_AREA*>( item );
|
||||
|
||||
// Clear item and directive associations for this rule area
|
||||
ruleArea->ResetDirectivesAndItems( GetCanvas()->GetView() );
|
||||
|
||||
changed_rule_areas.insert( { ruleArea, screen } );
|
||||
}
|
||||
else if( item->IsConnectable() )
|
||||
{
|
||||
SCH_ITEM* linked_item =
|
||||
dynamic_cast<SCH_ITEM*>( changed_list->GetPickedItemLink( ii ) );
|
||||
changed_connectable_items.push_back( { item, linked_item, screen } );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update rule areas in changed screens to propagate any directive connectivity changes
|
||||
std::vector<std::pair<SCH_RULE_AREA*, SCH_SCREEN*>> forceUpdateRuleAreas =
|
||||
SCH_RULE_AREA::UpdateRuleAreasInScreens( changed_screens, GetCanvas()->GetView() );
|
||||
|
||||
std::for_each( forceUpdateRuleAreas.begin(), forceUpdateRuleAreas.end(),
|
||||
[&]( std::pair<SCH_RULE_AREA*, SCH_SCREEN*>& updatedRuleArea )
|
||||
{
|
||||
changed_rule_areas.insert( updatedRuleArea );
|
||||
} );
|
||||
|
||||
// If a SCH_RULE_AREA was changed, we need to add all past and present contained items to
|
||||
// update their connectivity
|
||||
for( const std::pair<SCH_RULE_AREA*, SCH_SCREEN*>& changedRuleArea : changed_rule_areas )
|
||||
{
|
||||
for( SCH_ITEM* containedItem :
|
||||
changedRuleArea.first->GetPastAndPresentContainedItems() )
|
||||
{
|
||||
addItemToChangeSet( { containedItem, nullptr, changedRuleArea.second } );
|
||||
}
|
||||
}
|
||||
|
||||
// Add all changed items, and associated items, to the change set
|
||||
for( CHANGED_ITEM& changed_item_data : changed_connectable_items )
|
||||
{
|
||||
addItemToChangeSet( changed_item_data );
|
||||
|
||||
// If a SCH_DIRECTIVE_LABEL was changed which is attached to a SCH_RULE_AREA, we need
|
||||
// to add the contained items to the change set to force update of their connectivity
|
||||
if( changed_item_data.item->Type() == SCH_DIRECTIVE_LABEL_T )
|
||||
{
|
||||
const std::vector<VECTOR2I> labelConnectionPoints =
|
||||
changed_item_data.item->GetConnectionPoints();
|
||||
|
||||
EE_RTREE::EE_TYPE candidateRuleAreas =
|
||||
changed_item_data.screen->Items().Overlapping(
|
||||
SCH_RULE_AREA_T, changed_item_data.item->GetBoundingBox() );
|
||||
|
||||
for( SCH_ITEM* candidateRuleArea : candidateRuleAreas )
|
||||
{
|
||||
SCH_RULE_AREA* ruleArea = static_cast<SCH_RULE_AREA*>( candidateRuleArea );
|
||||
std::vector<SHAPE*> borderShapes = ruleArea->MakeEffectiveShapes( true );
|
||||
|
||||
if( ruleArea->GetPolyShape().CollideEdge( labelConnectionPoints[0], nullptr,
|
||||
5 ) )
|
||||
{
|
||||
for( SCH_ITEM* containedItem : ruleArea->GetPastAndPresentContainedItems() )
|
||||
addItemToChangeSet(
|
||||
{ containedItem, nullptr, changed_item_data.screen } );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( const VECTOR2I& pt: pts )
|
||||
|
@ -103,4 +103,5 @@
|
||||
//#define SEXPR_SCHEMATIC_FILE_VERSION 20230808 // Move Sim.Enable field to exclude_from_sim attr
|
||||
//#define SEXPR_SCHEMATIC_FILE_VERSION 20230819 // Allow multiple library symbol inheritance depth.
|
||||
//#define SEXPR_SCHEMATIC_FILE_VERSION 20231120 // generator_version; V8 cleanups
|
||||
#define SEXPR_SCHEMATIC_FILE_VERSION 20240101 // Tables.
|
||||
//#define SEXPR_SCHEMATIC_FILE_VERSION 20240101 // Tables.
|
||||
#define SEXPR_SCHEMATIC_FILE_VERSION 20240417 // Rule areas
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <sch_pin.h>
|
||||
#include <sch_shape.h>
|
||||
#include <sch_no_connect.h>
|
||||
#include <sch_rule_area.h>
|
||||
#include <sch_text.h>
|
||||
#include <sch_textbox.h>
|
||||
#include <sch_table.h>
|
||||
@ -470,6 +471,10 @@ void SCH_IO_KICAD_SEXPR::Format( SCH_SHEET* aSheet )
|
||||
case SCH_SHAPE_T:
|
||||
saveShape( static_cast<SCH_SHAPE*>( item ), 1 );
|
||||
break;
|
||||
|
||||
case SCH_RULE_AREA_T:
|
||||
saveRuleArea( static_cast<SCH_RULE_AREA*>( item ), 1 );
|
||||
break;
|
||||
|
||||
case SCH_TEXT_T:
|
||||
case SCH_LABEL_T:
|
||||
@ -599,6 +604,10 @@ void SCH_IO_KICAD_SEXPR::Format( EE_SELECTION* aSelection, SCH_SHEET_PATH* aSele
|
||||
saveShape( static_cast<SCH_SHAPE*>( item ), 0 );
|
||||
break;
|
||||
|
||||
case SCH_RULE_AREA_T:
|
||||
saveRuleArea( static_cast<SCH_RULE_AREA*>( item ), 0 );
|
||||
break;
|
||||
|
||||
case SCH_TEXT_T:
|
||||
case SCH_LABEL_T:
|
||||
case SCH_GLOBAL_LABEL_T:
|
||||
@ -1234,6 +1243,16 @@ void SCH_IO_KICAD_SEXPR::saveShape( SCH_SHAPE* aShape, int aNestLevel )
|
||||
}
|
||||
|
||||
|
||||
void SCH_IO_KICAD_SEXPR::saveRuleArea( SCH_RULE_AREA* aRuleArea, int aNestLevel )
|
||||
{
|
||||
wxCHECK_RET( aRuleArea != nullptr && m_out != nullptr, "" );
|
||||
|
||||
m_out->Print( aNestLevel, "(rule_area " );
|
||||
saveShape( aRuleArea, aNestLevel + 1 );
|
||||
m_out->Print( aNestLevel, ")\n" );
|
||||
}
|
||||
|
||||
|
||||
void SCH_IO_KICAD_SEXPR::saveLine( SCH_LINE* aLine, int aNestLevel )
|
||||
{
|
||||
wxCHECK_RET( aLine != nullptr && m_out != nullptr, "" );
|
||||
|
@ -43,6 +43,7 @@ class SCH_JUNCTION;
|
||||
class SCH_NO_CONNECT;
|
||||
class SCH_LINE;
|
||||
class SCH_SHAPE;
|
||||
class SCH_RULE_AREA;
|
||||
class SCH_BUS_ENTRY_BASE;
|
||||
class SCH_TEXT;
|
||||
class SCH_TEXTBOX;
|
||||
@ -151,6 +152,7 @@ private:
|
||||
void saveBusEntry( SCH_BUS_ENTRY_BASE* aBusEntry, int aNestLevel );
|
||||
void saveLine( SCH_LINE* aLine, int aNestLevel );
|
||||
void saveShape( SCH_SHAPE* aShape, int aNestLevel );
|
||||
void saveRuleArea( SCH_RULE_AREA* aRuleArea, int aNestLevel );
|
||||
void saveText( SCH_TEXT* aText, int aNestLevel );
|
||||
void saveTextBox( SCH_TEXTBOX* aText, int aNestLevel );
|
||||
void saveTable( SCH_TABLE* aTable, int aNestLevel );
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include <sch_edit_frame.h> // SYM_ORIENT_XXX
|
||||
#include <sch_field.h>
|
||||
#include <sch_line.h>
|
||||
#include <sch_rule_area.h>
|
||||
#include <sch_textbox.h>
|
||||
#include <sch_table.h>
|
||||
#include <sch_tablecell.h>
|
||||
@ -2745,6 +2746,10 @@ void SCH_IO_KICAD_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet, bool aIsCopya
|
||||
screen->Append( parseSchBezier() );
|
||||
break;
|
||||
|
||||
case T_rule_area:
|
||||
screen->Append( parseSchRuleArea() );
|
||||
break;
|
||||
|
||||
case T_netclass_flag: // present only during early development of 7.0
|
||||
KI_FALLTHROUGH;
|
||||
|
||||
@ -2782,7 +2787,7 @@ void SCH_IO_KICAD_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet, bool aIsCopya
|
||||
default:
|
||||
Expecting( "symbol, paper, page, title_block, bitmap, sheet, junction, no_connect, "
|
||||
"bus_entry, line, bus, text, label, class_label, global_label, "
|
||||
"hierarchical_label, symbol_instances, or bus_alias" );
|
||||
"hierarchical_label, symbol_instances, rule_area, or bus_alias" );
|
||||
}
|
||||
}
|
||||
|
||||
@ -3927,6 +3932,43 @@ SCH_SHAPE* SCH_IO_KICAD_SEXPR_PARSER::parseSchRectangle()
|
||||
}
|
||||
|
||||
|
||||
SCH_RULE_AREA* SCH_IO_KICAD_SEXPR_PARSER::parseSchRuleArea()
|
||||
{
|
||||
wxCHECK_MSG( CurTok() == T_rule_area, nullptr,
|
||||
wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a rule area." ) );
|
||||
|
||||
T token;
|
||||
STROKE_PARAMS stroke( schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS ), LINE_STYLE::DEFAULT );
|
||||
FILL_PARAMS fill;
|
||||
std::unique_ptr<SCH_RULE_AREA> ruleArea = std::make_unique<SCH_RULE_AREA>();
|
||||
|
||||
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
|
||||
{
|
||||
if( token != T_LEFT )
|
||||
Expecting( T_LEFT );
|
||||
|
||||
token = NextTok();
|
||||
|
||||
switch( token )
|
||||
{
|
||||
case T_polyline:
|
||||
{
|
||||
std::unique_ptr<SCH_SHAPE> poly( parseSchPolyLine() );
|
||||
ruleArea->SetPolyShape( poly->GetPolyShape() );
|
||||
ruleArea->SetStroke( poly->GetStroke() );
|
||||
ruleArea->SetFillMode( poly->GetFillMode() );
|
||||
ruleArea->SetFillColor( poly->GetFillColor() );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Expecting( "polyline" );
|
||||
}
|
||||
}
|
||||
|
||||
return ruleArea.release();
|
||||
}
|
||||
|
||||
|
||||
SCH_SHAPE* SCH_IO_KICAD_SEXPR_PARSER::parseSchBezier()
|
||||
{
|
||||
wxCHECK_MSG( CurTok() == T_bezier, nullptr,
|
||||
|
@ -45,6 +45,7 @@ class SCH_SYMBOL;
|
||||
class SCH_FIELD;
|
||||
class SCH_ITEM;
|
||||
class SCH_SHAPE;
|
||||
class SCH_RULE_AREA;
|
||||
class SCH_JUNCTION;
|
||||
class SCH_LINE;
|
||||
class SCH_NO_CONNECT;
|
||||
@ -221,6 +222,7 @@ private:
|
||||
SCH_SHAPE* parseSchCircle();
|
||||
SCH_SHAPE* parseSchRectangle();
|
||||
SCH_SHAPE* parseSchBezier();
|
||||
SCH_RULE_AREA* parseSchRuleArea();
|
||||
SCH_TEXT* parseSchText();
|
||||
SCH_TEXTBOX* parseSchTextBox();
|
||||
void parseSchTextBoxContent( SCH_TEXTBOX* aTextBox );
|
||||
|
@ -26,6 +26,7 @@
|
||||
#define SCH_ITEM_H
|
||||
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
@ -44,6 +45,7 @@ class SCHEMATIC;
|
||||
class SYMBOL;
|
||||
class LINE_READER;
|
||||
class SCH_EDIT_FRAME;
|
||||
class SCH_RULE_AREA;
|
||||
struct SCH_PLOT_OPTS;
|
||||
|
||||
namespace KIFONT
|
||||
@ -628,6 +630,24 @@ public:
|
||||
wxCHECK_MSG( false, /*void*/, wxT( "Plot not implemented in " ) + GetClass() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the cache of rule areas (called prior to schematic connectivity recomputation)
|
||||
*/
|
||||
void ClearRuleAreasCache() { m_rule_areas_cache.clear(); }
|
||||
|
||||
/**
|
||||
* Adds a rule area to the item's cache
|
||||
*/
|
||||
void AddRuleAreaToCache( SCH_RULE_AREA* aRuleArea ) { m_rule_areas_cache.insert( aRuleArea ); }
|
||||
|
||||
/**
|
||||
* Gets the cache of rule areas enclosing this item
|
||||
*/
|
||||
const std::unordered_set<SCH_RULE_AREA*>& GetRuleAreaCache() const
|
||||
{
|
||||
return m_rule_areas_cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* The list of flags used by the #compare function.
|
||||
*
|
||||
@ -721,6 +741,9 @@ protected:
|
||||
|
||||
bool m_connectivity_dirty;
|
||||
|
||||
/// Store pointers to rule areas which this item is contained within
|
||||
std::unordered_set<SCH_RULE_AREA*> m_rule_areas_cache;
|
||||
|
||||
private:
|
||||
friend class LIB_SYMBOL;
|
||||
};
|
||||
|
@ -1808,6 +1808,30 @@ wxString SCH_DIRECTIVE_LABEL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider
|
||||
}
|
||||
|
||||
|
||||
void SCH_DIRECTIVE_LABEL::AddConnectedRuleArea( SCH_RULE_AREA* aRuleArea )
|
||||
{
|
||||
m_connected_rule_areas.insert( aRuleArea );
|
||||
}
|
||||
|
||||
|
||||
void SCH_DIRECTIVE_LABEL::ClearConnectedRuleAreas()
|
||||
{
|
||||
m_connected_rule_areas.clear();
|
||||
}
|
||||
|
||||
|
||||
void SCH_DIRECTIVE_LABEL::RemoveConnectedRuleArea( SCH_RULE_AREA* aRuleArea )
|
||||
{
|
||||
m_connected_rule_areas.erase( aRuleArea );
|
||||
}
|
||||
|
||||
|
||||
bool SCH_DIRECTIVE_LABEL::IsDangling() const
|
||||
{
|
||||
return m_isDangling && m_connected_rule_areas.empty();
|
||||
}
|
||||
|
||||
|
||||
SCH_GLOBALLABEL::SCH_GLOBALLABEL( const VECTOR2I& pos, const wxString& text ) :
|
||||
SCH_LABEL_BASE( pos, text, SCH_GLOBAL_LABEL_T )
|
||||
{
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include <sch_field.h>
|
||||
#include <sch_connection.h> // for CONNECTION_TYPE
|
||||
|
||||
class SCH_RULE_AREA;
|
||||
|
||||
|
||||
/*
|
||||
* Spin style for labels of all kinds on schematics
|
||||
@ -474,9 +476,24 @@ public:
|
||||
void MirrorHorizontally( int aCenter ) override;
|
||||
void MirrorVertically( int aCenter ) override;
|
||||
|
||||
/// @brief Adds an entry to the connected rule area cache
|
||||
void AddConnectedRuleArea( SCH_RULE_AREA* aRuleArea );
|
||||
|
||||
/// @brief Removes all rule areas from the cache
|
||||
void ClearConnectedRuleAreas();
|
||||
|
||||
/// @brief Removes a specific rule area from the cache
|
||||
void RemoveConnectedRuleArea( SCH_RULE_AREA* aRuleArea );
|
||||
|
||||
/// @brief Determines dangling state from connectivity and cached connected rule areas
|
||||
virtual bool IsDangling() const override;
|
||||
|
||||
private:
|
||||
int m_pinLength;
|
||||
int m_symbolSize;
|
||||
|
||||
/// Cache of any rule areas with borders which this label connects to
|
||||
std::unordered_set<SCH_RULE_AREA*> m_connected_rule_areas;
|
||||
};
|
||||
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user