Compare commits
316 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 59f308850e | |||
| e775a7581a | |||
| ec99e10b31 | |||
| 240d7921ba | |||
| 9ac006b114 | |||
| c3fef1cae2 | |||
| ca1c99a0d1 | |||
| 06ae7a20df | |||
| f536ecdc00 | |||
| a4bdd38367 | |||
| 6fb6d3e444 | |||
| a3952c37bf | |||
| c24ee72fe3 | |||
| f988b807c4 | |||
| cb1a596b10 | |||
| c41cd75b62 | |||
| 0df48f3002 | |||
| 2d58184080 | |||
| 1ef6e69d83 | |||
| dbd4af16c6 | |||
| 2263535d3a | |||
| 3ce4a5bf7f | |||
| f62c3431ff | |||
| a652084922 | |||
| ed30599db8 | |||
| d8752970e9 | |||
| 57a4c93cf5 | |||
| a116f5783d | |||
| 2730098c42 | |||
| 836d17359f | |||
| a4406bb137 | |||
| bbb67b415a | |||
| 0842360dbb | |||
| e58b23a54b | |||
| 72342bd8a5 | |||
| fa77fc3310 | |||
| 53fe2a7203 | |||
| 480dfafb4f | |||
| f5e13c5ceb | |||
| eadc902f84 | |||
| b461a3b64d | |||
| 75c758e5f4 | |||
| 05912b0381 | |||
| fb387a2c09 | |||
| 1380feef72 | |||
| 6c91a3022e | |||
| e55989120e | |||
| 14f12ccf51 | |||
| 82a1b02b4a | |||
| e99a2fbc56 | |||
| d3d23d18fb | |||
| cbf1b2af47 | |||
| 4f5fca4e67 | |||
| e0158a8ed7 | |||
| 40e7ba67d1 | |||
| e664605c90 | |||
| 5a51a6b179 | |||
| eb7929ccb6 | |||
| e85eec2e6b | |||
| 121394c0c0 | |||
| 5ad74d58f8 | |||
| afe2516d57 | |||
| ccf6e78cd5 | |||
| fef91fc8b9 | |||
| 4156587abe | |||
| 629eccaf09 | |||
| f89803eb64 | |||
| da12746a3a | |||
| b023019b0d | |||
| 1fdaa1083e | |||
| 2f8e846b9e | |||
| e42db52d14 | |||
| d4ec455ce0 | |||
| 0547c7ba91 | |||
| 8f4b809599 | |||
| 8432fb4fea | |||
| 84df2c86ae | |||
| 49ced23ba8 | |||
| 00bf2ca36f | |||
| b92861c7e3 | |||
| a189102628 | |||
| 58a6eb653b | |||
| 9159f5a004 | |||
| f1c570d793 | |||
| 832af39f34 | |||
| 9260f58803 | |||
| 1a5c515e45 | |||
| 87c8688f70 | |||
| d13179f9e4 | |||
| 75de21314c | |||
| 239f8e0905 | |||
| f4ac624bb3 | |||
| 2be0b98135 | |||
| 36c5719535 | |||
| 1f870bf76c | |||
| d5cc334e20 | |||
| fd98188ee4 | |||
| c3446f9c2d | |||
| e6e29b6c4c | |||
| 6096b5c4d8 | |||
| 838eadd47f | |||
| afb43531e8 | |||
| 3533e8b119 | |||
| 0e6ad13db8 | |||
| 0d725fcc2c | |||
| 7e747085d3 | |||
| f1376396c2 | |||
| 4eb9281f4d | |||
| c895816cb0 | |||
| 9f814c0f6a | |||
| e14aef9bd5 | |||
| 2b106a2b34 | |||
| f6494d2980 | |||
| 78a6c1a909 | |||
| c858643100 | |||
| 17b0bdc9fe | |||
| 2e0cdebb0c | |||
| a5f8955d78 | |||
| 0eca698a39 | |||
| 16f259da81 | |||
| c3ee477a1b | |||
| 33da35db04 | |||
| 533be1ec70 | |||
| b64573f5d4 | |||
| 1d6caa9a35 | |||
| c74b0943f3 | |||
| bb579294a0 | |||
| ad9f5f4dd7 | |||
| bf2e34f32e | |||
| bd57957df7 | |||
| 093db600ff | |||
| 131013f291 | |||
| 909d199379 | |||
| 5f16f4ab99 | |||
| fff95fa4e6 | |||
| a38327a39c | |||
| 686048dcce | |||
| 330c0f86de | |||
| 83317f1b80 | |||
| a416eb2cf6 | |||
| 2959c94bd3 | |||
| 063d9c8305 | |||
| 5e97608fa5 | |||
| 50dca2d02b | |||
| cd3785744c | |||
| 357810a5d5 | |||
| 1b71bc115d | |||
| de40286e81 | |||
| 8d0ff95760 | |||
| ffddf9fec3 | |||
| 3a35d96130 | |||
| 8add678d87 | |||
| a8bcf8c9e4 | |||
| 090374a1dc | |||
| e7aa95d53d | |||
| f6ccf18cf5 | |||
| 4542ce8c70 | |||
| f80287bc27 | |||
| e10ab74917 | |||
| 23ddb99026 | |||
| efbac9e128 | |||
| 62044c2731 | |||
| 7d1a38d46f | |||
| d885bc14e1 | |||
| 886937a3ea | |||
| 99eff43ab4 | |||
| 880269780d | |||
| 7f1b891679 | |||
| ceced2a9a4 | |||
| d3a8cb84a6 | |||
| 6b43bb8fe3 | |||
| a74cffac39 | |||
| 83d2891cef | |||
| 0faad370f9 | |||
| 23fab89131 | |||
| 48189172ea | |||
| 0c9eda44d4 | |||
| f0a9ce3ab4 | |||
| ea5878a0c9 | |||
| f67382612d | |||
| 3fe7ae07ed | |||
| 8bcfa81bea | |||
| c17918d9c1 | |||
| f752df0595 | |||
| 0836b5b661 | |||
| 2cefccf7bf | |||
| 3dc86c5a4f | |||
| 05ae712e77 | |||
| 04db374326 | |||
| e3558b7dcf | |||
| 99e10c6112 | |||
| 537934339e | |||
| ee343e1263 | |||
| 6eeca9aa90 | |||
| 86beb339b7 | |||
| 67b5af23aa | |||
| 88f65f4e47 | |||
| af5b6b0eba | |||
| 57ef739404 | |||
| 584eb9f531 | |||
| 36a4d5a511 | |||
| 72737b20cd | |||
| d05093e6f7 | |||
| a7e6928f4e | |||
| 951fd2d693 | |||
| be991cfcd6 | |||
| aab36d9b85 | |||
| 3cd6935acb | |||
| 6daef080e3 | |||
| 6ee909b958 | |||
| c11ae8bd02 | |||
| c7a4ea97c3 | |||
| 81ebb1030a | |||
| 86ec36d183 | |||
| 207f2e568b | |||
| 19753719cb | |||
| 5f025dcd73 | |||
| c796eeaf8b | |||
| bdbd7f0c9c | |||
| b0e09327db | |||
| 96a3621b8e | |||
| 8f259211e7 | |||
| 0d9d8c28f1 | |||
| 058a0bbf93 | |||
| 4d46e0ceb7 | |||
| 123ff326d4 | |||
| 14d4c38979 | |||
| 9c87a52b6e | |||
| 30c2028852 | |||
| 95e6be0e81 | |||
| 955313e97d | |||
| 32c2135047 | |||
| 702e08b083 | |||
| 8f58e1a9e0 | |||
| 0cc25f10c6 | |||
| 61ef88a0ac | |||
| 02a95b958d | |||
| 5cd88dbd20 | |||
| ec53ed6a37 | |||
| 242413a334 | |||
| f88dce1627 | |||
| 5c456370d9 | |||
| 93fdd35b31 | |||
| 70d5fccb54 | |||
| 6ca7c3a3a1 | |||
| 88448ce746 | |||
| 1fee2c626b | |||
| 480a9ac77d | |||
| 889689e31a | |||
| c8e49599ce | |||
| 351cb7e104 | |||
| 5c5e41500a | |||
| 2e739e743d | |||
| 1eee3d350b | |||
| d2d7e630bd | |||
| d11cd173dc | |||
| 12e0427038 | |||
| 9bcb6f0adf | |||
| 09490e1f46 | |||
| f33120c540 | |||
| 82ed223b02 | |||
| bfdbf969c2 | |||
| 7d409b9404 | |||
| 7673f220a9 | |||
| 75daa1afec | |||
| 27657e00fe | |||
| 26b8812f15 | |||
| 07e13c51d1 | |||
| f9b59b4fdf | |||
| 76a3b3db97 | |||
| 4b0416e92a | |||
| 5d6bb4b04f | |||
| 2764f292cb | |||
| 7ca59e24c6 | |||
| e1a2d60672 | |||
| 9672390104 | |||
| 33c2005c18 | |||
| 3e1309110e | |||
| aae7d94ffd | |||
| 5b0d752e0c | |||
| 0f93752f14 | |||
| 049ecc43e3 | |||
| 2209f5e93b | |||
| a17cd9d054 | |||
| 4497aaa3fa | |||
| 00226ae40a | |||
| 45963a3443 | |||
| 4aa1a881f3 | |||
| f3dd5b73f8 | |||
| fd049ef510 | |||
| 7d389f8024 | |||
| df63f47deb | |||
| c521efa35d | |||
| af1561b848 | |||
| 691931f74d | |||
| da5e1de1c8 | |||
| 043892bdc6 | |||
| 34d2aeaac3 | |||
| 4481e89046 | |||
| 8120e47bfd | |||
| db526e581c | |||
| 246be732a1 | |||
| 27a0bd2535 | |||
| 8f57fd82a0 | |||
| 1ef90c898e | |||
| cf133975c1 | |||
| c468b68c5a | |||
| acbddc904b | |||
| 83624acfd2 | |||
| d915ddc647 | |||
| 61b741c34e | |||
| aa1910a834 | |||
| dba36c07fe | |||
| 8451e6dcf1 | |||
| 88dfe6eb9c | |||
| 800b697d06 |
@@ -201,7 +201,8 @@ void BOARD_ADAPTER::addFootprintShapes( const FOOTPRINT* aFootprint, CONTAINER_2
|
||||
|
||||
if( textbox->GetLayer() == aLayerId )
|
||||
{
|
||||
addShape( textbox, aContainer, aFootprint );
|
||||
if( textbox->IsBorderEnabled() )
|
||||
addShape( textbox, aContainer, aFootprint );
|
||||
addText( textbox, aContainer, aFootprint );
|
||||
}
|
||||
|
||||
@@ -260,6 +261,19 @@ void BOARD_ADAPTER::createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDs
|
||||
{
|
||||
const PCB_ARC* arc = static_cast<const PCB_ARC*>( aTrack );
|
||||
|
||||
if( arc->IsDegenerated() )
|
||||
{
|
||||
// Draw this very small arc like a track segment (a PCB_TRACE_T)
|
||||
PCB_TRACK track( arc->GetParent() );
|
||||
track.SetStart( arc->GetStart() );
|
||||
track.SetEnd( arc->GetEnd() );
|
||||
track.SetWidth( arc->GetWidth() );
|
||||
track.SetLayer( arc->GetLayer() );
|
||||
|
||||
createTrack( &track, aDstContainer );
|
||||
return;
|
||||
}
|
||||
|
||||
VECTOR2D center( arc->GetCenter() );
|
||||
EDA_ANGLE arc_angle = arc->GetAngle();
|
||||
double radius = arc->GetRadius();
|
||||
@@ -625,16 +639,12 @@ void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aConta
|
||||
if( inner_radius3DU < 0 )
|
||||
inner_radius3DU = 0.0;
|
||||
|
||||
if( outer_radius3DU == 0.0 )
|
||||
{
|
||||
// Don't attempt to render degenerate shapes
|
||||
}
|
||||
else if( aShape->IsFilled() )
|
||||
if( aShape->IsFilled() )
|
||||
{
|
||||
aContainer->Add( new FILLED_CIRCLE_2D( center3DU, outer_radius3DU,
|
||||
*aOwner ) );
|
||||
}
|
||||
else
|
||||
else if( outer_radius3DU > inner_radius3DU )
|
||||
{
|
||||
aContainer->Add( new RING_2D( center3DU, inner_radius3DU, outer_radius3DU,
|
||||
*aOwner ) );
|
||||
@@ -782,7 +792,7 @@ void BOARD_ADAPTER::buildPadOutlineAsSegments( const PAD* aPad, CONTAINER_2D_BAS
|
||||
}
|
||||
|
||||
// For other shapes, add outlines as thick segments in polygon buffer
|
||||
const std::shared_ptr<SHAPE_POLY_SET>& corners = aPad->GetEffectivePolygon();
|
||||
const std::shared_ptr<SHAPE_POLY_SET>& corners = aPad->GetEffectivePolygon( ERROR_INSIDE );
|
||||
const SHAPE_LINE_CHAIN& path = corners->COutline( 0 );
|
||||
|
||||
for( int j = 0; j < path.PointCount(); j++ )
|
||||
|
||||
@@ -605,7 +605,8 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||
|
||||
case PCB_TEXTBOX_T:
|
||||
addText( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
|
||||
addShape( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
|
||||
if( static_cast<PCB_TEXTBOX*>( item )->IsBorderEnabled() )
|
||||
addShape( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
|
||||
break;
|
||||
|
||||
case PCB_DIM_ALIGNED_T:
|
||||
|
||||
@@ -51,7 +51,7 @@ void BOARD_ADAPTER::buildPadOutlineAsPolygon( const PAD* aPad, SHAPE_POLY_SET& a
|
||||
}
|
||||
|
||||
// For other shapes, add outlines as thick segments in polygon buffer
|
||||
const std::shared_ptr<SHAPE_POLY_SET>& corners = aPad->GetEffectivePolygon();
|
||||
const std::shared_ptr<SHAPE_POLY_SET>& corners = aPad->GetEffectivePolygon( ERROR_INSIDE );
|
||||
const SHAPE_LINE_CHAIN& path = corners->COutline( 0 );
|
||||
|
||||
for( int ii = 0; ii < path.PointCount(); ++ii )
|
||||
|
||||
@@ -483,23 +483,21 @@ void MODEL_3D::Draw( bool aTransparent, float aOpacity, bool aUseSelectedMateria
|
||||
|
||||
// Sort from back to front
|
||||
std::sort( materialsSorted.begin(), materialsSorted.end(),
|
||||
[&]( std::pair<const MODEL_3D::MATERIAL*, float>& a,
|
||||
std::pair<const MODEL_3D::MATERIAL*, float>& b ) {
|
||||
// If A is inside B, then A is rendered first
|
||||
if( b.first->m_bbox.Inside( a.first->m_bbox ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( a.first->m_bbox.Inside( b.first->m_bbox ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
[&]( std::pair<const MODEL_3D::MATERIAL*, float>& a,
|
||||
std::pair<const MODEL_3D::MATERIAL*, float>& b )
|
||||
{
|
||||
bool aInsideB = a.first->m_bbox.Inside( b.first->m_bbox );
|
||||
bool bInsideA = b.first->m_bbox.Inside( a.first->m_bbox );
|
||||
|
||||
return a.second > b.second;
|
||||
} );
|
||||
// If A is inside B, then A is rendered first
|
||||
if( aInsideB != bInsideA )
|
||||
return bInsideA;
|
||||
|
||||
if( a.second != b.second )
|
||||
return a.second > b.second;
|
||||
|
||||
return a.first > b.first; // compare pointers as a last resort
|
||||
} );
|
||||
|
||||
for( const std::pair<const MODEL_3D::MATERIAL*, float>& mat : materialsSorted )
|
||||
{
|
||||
|
||||
@@ -1388,10 +1388,14 @@ void RENDER_3D_OPENGL::renderTransparentModels( const glm::mat4 &aCameraViewMatr
|
||||
|
||||
// Sort from back to front
|
||||
std::sort( transparentModelList.begin(), transparentModelList.end(),
|
||||
[&]( std::pair<const MODELTORENDER *, float>& a,
|
||||
std::pair<const MODELTORENDER *, float>& b ) {
|
||||
return a.second > b.second;
|
||||
} );
|
||||
[&]( std::pair<const MODELTORENDER *, float>& a,
|
||||
std::pair<const MODELTORENDER *, float>& b )
|
||||
{
|
||||
if( a.second != b.second )
|
||||
return a.second > b.second;
|
||||
|
||||
return a.first > b.first; // use pointers as a last resort
|
||||
} );
|
||||
|
||||
// Start rendering calls
|
||||
glPushMatrix();
|
||||
|
||||
@@ -1911,9 +1911,19 @@ void RENDER_3D_RAYTRACE::initializeBlockPositions()
|
||||
|
||||
const SFVEC2UI center( m_realBufferSize.x / 2, m_realBufferSize.y / 2 );
|
||||
std::sort( m_blockPositions.begin(), m_blockPositions.end(),
|
||||
[&]( const SFVEC2UI& a, const SFVEC2UI& b ) {
|
||||
[&]( const SFVEC2UI& a, const SFVEC2UI& b )
|
||||
{
|
||||
// Sort order: inside out.
|
||||
return distance( a, center ) < distance( b, center );
|
||||
float distanceA = distance( a, center );
|
||||
float distanceB = distance( b, center );
|
||||
|
||||
if( distanceA != distanceB )
|
||||
return distanceA < distanceB;
|
||||
|
||||
if( a[0] != b[0] )
|
||||
return a[0] < b[0];
|
||||
|
||||
return a[1] < b[1];
|
||||
} );
|
||||
|
||||
// Create m_shader buffer
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
# KiCad.
|
||||
#
|
||||
# Note: This version string should follow the semantic versioning system
|
||||
set( KICAD_SEMANTIC_VERSION "7.0.7" )
|
||||
set( KICAD_SEMANTIC_VERSION "7.0.9" )
|
||||
|
||||
# Default the version to the semantic version.
|
||||
# This is overridden by the git repository tag though (if using git)
|
||||
|
||||
@@ -176,6 +176,7 @@ set( COMMON_WIDGET_SRCS
|
||||
widgets/footprint_preview_widget.cpp
|
||||
widgets/footprint_select_widget.cpp
|
||||
widgets/gal_options_panel.cpp
|
||||
widgets/gal_options_panel_base.cpp
|
||||
widgets/grid_bitmap_toggle.cpp
|
||||
widgets/grid_color_swatch_helpers.cpp
|
||||
widgets/grid_combobox.cpp
|
||||
|
||||
+1
-1
@@ -155,7 +155,7 @@ long KIDIALOG::getStyle( KD_TYPE aType )
|
||||
}
|
||||
|
||||
|
||||
bool OverrideLock( wxWindow* aParent, const wxString& aMessage )
|
||||
bool AskOverrideLock( wxWindow* aParent, const wxString& aMessage )
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
// wxMessageDialog gets the button spacing wrong on Mac so we have to use wxRichMessageDialog.
|
||||
|
||||
@@ -217,7 +217,13 @@ bool DATABASE_CONNECTION::CacheTableInfo( const std::string& aTable,
|
||||
nanodbc::catalog catalog( *m_conn );
|
||||
nanodbc::catalog::tables tables = catalog.find_tables( fromUTF8( aTable ) );
|
||||
|
||||
tables.next();
|
||||
if( !tables.next() )
|
||||
{
|
||||
wxLogTrace( traceDatabase, wxT( "CacheTableInfo: table '%s' not found in catalog" ),
|
||||
aTable );
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string key = toUTF8( tables.table_name() );
|
||||
m_tables[key] = toUTF8( tables.table_type() );
|
||||
|
||||
@@ -238,7 +244,7 @@ bool DATABASE_CONNECTION::CacheTableInfo( const std::string& aTable,
|
||||
catch( nanodbc::database_error& e )
|
||||
{
|
||||
m_lastError = e.what();
|
||||
wxLogTrace( traceDatabase, wxT( "Exception while syncing columns for table %s: %s" ),
|
||||
wxLogTrace( traceDatabase, wxT( "Exception while syncing columns for table '%s': %s" ),
|
||||
key, m_lastError );
|
||||
return false;
|
||||
}
|
||||
@@ -429,7 +435,22 @@ bool DATABASE_CONNECTION::SelectOne( const std::string& aTable,
|
||||
for( short i = 0; i < results.columns(); ++i )
|
||||
{
|
||||
std::string column = toUTF8( results.column_name( i ) );
|
||||
aResult[ column ] = toUTF8( results.get<nanodbc::string>( i, NANODBC_TEXT( "" ) ) );
|
||||
|
||||
switch( results.column_datatype( i ) )
|
||||
{
|
||||
case SQL_DOUBLE:
|
||||
case SQL_FLOAT:
|
||||
case SQL_REAL:
|
||||
case SQL_DECIMAL:
|
||||
case SQL_NUMERIC:
|
||||
{
|
||||
aResult[column] = fmt::format( "{:G}", results.get<double>( i ) );
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
aResult[column] = toUTF8( results.get<nanodbc::string>( i, NANODBC_TEXT( "" ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( nanodbc::database_error& e )
|
||||
@@ -528,7 +549,23 @@ bool DATABASE_CONNECTION::SelectAll( const std::string& aTable, const std::strin
|
||||
for( short j = 0; j < results.columns(); ++j )
|
||||
{
|
||||
std::string column = toUTF8( results.column_name( j ) );
|
||||
result[column] = toUTF8( results.get<nanodbc::string>( j, NANODBC_TEXT( "" ) ) );
|
||||
|
||||
switch( results.column_datatype( j ) )
|
||||
{
|
||||
case SQL_DOUBLE:
|
||||
case SQL_FLOAT:
|
||||
case SQL_REAL:
|
||||
case SQL_DECIMAL:
|
||||
case SQL_NUMERIC:
|
||||
{
|
||||
result[column] = fmt::format( "{:G}", results.get<double>( j ) );
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
result[column] = toUTF8( results.get<nanodbc::string>( j,
|
||||
NANODBC_TEXT( "" ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
aResults.emplace_back( std::move( result ) );
|
||||
|
||||
+36
-1
@@ -133,12 +133,41 @@ DIALOG_SHIM::DIALOG_SHIM( wxWindow* aParent, wxWindowID id, const wxString& titl
|
||||
Pgm().App().SetTopWindow( (EDA_BASE_FRAME*) kiwayHolder );
|
||||
#endif
|
||||
|
||||
Connect( wxEVT_PAINT, wxPaintEventHandler( DIALOG_SHIM::OnPaint ) );
|
||||
Bind( wxEVT_PAINT, &DIALOG_SHIM::OnPaint, this );
|
||||
}
|
||||
|
||||
|
||||
DIALOG_SHIM::~DIALOG_SHIM()
|
||||
{
|
||||
Unbind( wxEVT_CLOSE_WINDOW, &DIALOG_SHIM::OnCloseWindow, this );
|
||||
Unbind( wxEVT_BUTTON, &DIALOG_SHIM::OnButton, this );
|
||||
Unbind( wxEVT_PAINT, &DIALOG_SHIM::OnPaint, this );
|
||||
|
||||
std::function<void( wxWindowList& )> disconnectFocusHandlers = [&]( wxWindowList& children )
|
||||
{
|
||||
for( wxWindow* child : children )
|
||||
{
|
||||
if( wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( child ) )
|
||||
{
|
||||
textCtrl->Disconnect( wxEVT_SET_FOCUS,
|
||||
wxFocusEventHandler( DIALOG_SHIM::onChildSetFocus ), nullptr,
|
||||
this );
|
||||
}
|
||||
else if( wxStyledTextCtrl* scintilla = dynamic_cast<wxStyledTextCtrl*>( child ) )
|
||||
{
|
||||
scintilla->Disconnect( wxEVT_SET_FOCUS,
|
||||
wxFocusEventHandler( DIALOG_SHIM::onChildSetFocus ), nullptr,
|
||||
this );
|
||||
}
|
||||
else
|
||||
{
|
||||
disconnectFocusHandlers( child->GetChildren() );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
disconnectFocusHandlers( GetChildren() );
|
||||
|
||||
// if the dialog is quasi-modal, this will end its event loop
|
||||
if( IsQuasiModal() )
|
||||
EndQuasiModal( wxID_CANCEL );
|
||||
@@ -282,6 +311,9 @@ bool DIALOG_SHIM::Show( bool show )
|
||||
ret = wxDialog::Show( show );
|
||||
}
|
||||
|
||||
if( m_parent )
|
||||
m_parent->SetFocus();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -483,6 +515,9 @@ int DIALOG_SHIM::ShowQuasiModal()
|
||||
|
||||
m_qmodal_showing = false;
|
||||
|
||||
if( parent )
|
||||
parent->SetFocus();
|
||||
|
||||
return GetReturnCode();
|
||||
}
|
||||
|
||||
|
||||
@@ -159,6 +159,7 @@ void PANEL_COLOR_SETTINGS::OnThemeChanged( wxCommandEvent& event )
|
||||
m_cbTheme->SetSelection( idx );
|
||||
|
||||
m_optOverrideColors->SetValue( newSettings->GetOverrideSchItemColors() );
|
||||
m_optOverrideColors->Enable( !newSettings->IsReadOnly() );
|
||||
|
||||
*m_currentSettings = *newSettings;
|
||||
updateSwatches();
|
||||
@@ -174,6 +175,7 @@ void PANEL_COLOR_SETTINGS::OnThemeChanged( wxCommandEvent& event )
|
||||
return;
|
||||
|
||||
m_optOverrideColors->SetValue( selected->GetOverrideSchItemColors() );
|
||||
m_optOverrideColors->Enable( !selected->IsReadOnly() );
|
||||
|
||||
*m_currentSettings = *selected;
|
||||
onNewThemeSelected();
|
||||
|
||||
@@ -161,16 +161,18 @@ void PANEL_SETUP_SEVERITIES::ImportSettingsFrom( std::map<int, SEVERITY>& aSetti
|
||||
{
|
||||
int errorCode = item.GetErrorCode();
|
||||
|
||||
if(! m_buttonMap[ errorCode ][0] ) // this entry does not actually exist
|
||||
continue;
|
||||
wxRadioButton* button = nullptr;
|
||||
|
||||
switch( aSettings[ errorCode ] )
|
||||
{
|
||||
case RPT_SEVERITY_ERROR: m_buttonMap[ errorCode ][0]->SetValue( true ); break;
|
||||
case RPT_SEVERITY_WARNING: m_buttonMap[ errorCode ][1]->SetValue( true ); break;
|
||||
case RPT_SEVERITY_IGNORE: m_buttonMap[ errorCode ][2]->SetValue( true ); break;
|
||||
default: break;
|
||||
case RPT_SEVERITY_ERROR: button = m_buttonMap[ errorCode ][0]; break;
|
||||
case RPT_SEVERITY_WARNING: button = m_buttonMap[ errorCode ][1]; break;
|
||||
case RPT_SEVERITY_IGNORE: button = m_buttonMap[ errorCode ][2]; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if( button ) // this entry must actually exist
|
||||
button->SetValue( true );
|
||||
}
|
||||
|
||||
if( m_pinMapSpecialCase )
|
||||
|
||||
@@ -106,14 +106,22 @@ void DS_PROXY_VIEW_ITEM::ViewDraw( int aLayer, VIEW* aView ) const
|
||||
|
||||
buildDrawList( aView, m_properties, &drawList );
|
||||
|
||||
BOX2I viewport( aView->GetViewport().GetOrigin(), aView->GetViewport().GetSize() );
|
||||
|
||||
// Draw the title block normally even if the view is flipped
|
||||
bool flipped = gal->IsFlippedX();
|
||||
|
||||
if( flipped )
|
||||
{
|
||||
int pageWidth = m_pageInfo->GetWidthMils() * m_mils2IUscalefactor;
|
||||
|
||||
gal->Save();
|
||||
gal->Translate( VECTOR2D( m_pageInfo->GetWidthMils() * m_mils2IUscalefactor, 0 ) );
|
||||
gal->Translate( VECTOR2D( pageWidth, 0 ) );
|
||||
gal->Scale( VECTOR2D( -1.0, 1.0 ) );
|
||||
|
||||
int right = pageWidth - viewport.GetLeft();
|
||||
int left = right - viewport.GetWidth();
|
||||
viewport.SetOrigin( left, viewport.GetTop() );
|
||||
}
|
||||
|
||||
DS_PAINTER ws_painter( gal );
|
||||
@@ -126,8 +134,6 @@ void DS_PROXY_VIEW_ITEM::ViewDraw( int aLayer, VIEW* aView ) const
|
||||
ws_settings->SetDefaultFont( settings->GetDefaultFont() );
|
||||
|
||||
// Draw all the components that make the drawing sheet
|
||||
BOX2I viewport( aView->GetViewport().GetOrigin(), aView->GetViewport().GetSize() );
|
||||
|
||||
for( DS_DRAW_ITEM_BASE* item = drawList.GetFirst(); item; item = drawList.GetNext() )
|
||||
{
|
||||
if( viewport.Intersects( item->GetApproxBBox() ) )
|
||||
|
||||
@@ -230,6 +230,15 @@ bool EDA_DRAW_FRAME::LockFile( const wxString& aFileName )
|
||||
|
||||
m_file_checker = std::make_unique<LOCKFILE>( aFileName );
|
||||
|
||||
if( !m_file_checker->Valid() && m_file_checker->IsLockedByMe() )
|
||||
{
|
||||
// If we cannot acquire the lock but we appear to be the one who
|
||||
// locked it, check to see if there is another KiCad instance running.
|
||||
// If there is not, then we can override the lock. This could happen if
|
||||
// KiCad crashed or was interrupted
|
||||
if( !Pgm().SingleInstance()->IsAnotherRunning() )
|
||||
m_file_checker->OverrideLock();
|
||||
}
|
||||
// If the file is valid, return true. This could mean that the file is
|
||||
// locked or it could mean that the file is read-only
|
||||
return m_file_checker->Valid();
|
||||
|
||||
+16
-4
@@ -114,6 +114,12 @@ wxString EDA_ITEM::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
|
||||
}
|
||||
|
||||
|
||||
bool isWordChar( const wxUniChar& c )
|
||||
{
|
||||
return wxIsalnum( c ) || c == '_';
|
||||
}
|
||||
|
||||
|
||||
bool EDA_ITEM::Matches( const wxString& aText, const EDA_SEARCH_DATA& aSearchData ) const
|
||||
{
|
||||
wxString text = aText;
|
||||
@@ -129,6 +135,12 @@ bool EDA_ITEM::Matches( const wxString& aText, const EDA_SEARCH_DATA& aSearchDat
|
||||
searchText.MakeUpper();
|
||||
}
|
||||
|
||||
auto isWordChar =
|
||||
[]( const wxUniChar& c )
|
||||
{
|
||||
return wxIsalnum( c ) || c == '_';
|
||||
};
|
||||
|
||||
if( aSearchData.matchMode == EDA_SEARCH_MATCH_MODE::WHOLEWORD )
|
||||
{
|
||||
int ii = 0;
|
||||
@@ -143,8 +155,8 @@ bool EDA_ITEM::Matches( const wxString& aText, const EDA_SEARCH_DATA& aSearchDat
|
||||
ii = next;
|
||||
next += searchText.length();
|
||||
|
||||
bool startOK = ( ii == 0 || !wxIsalnum( text.GetChar( ii - 1 ) ) );
|
||||
bool endOK = ( next == (int) text.length() || !wxIsalnum( text.GetChar( next ) ) );
|
||||
bool startOK = ( ii == 0 || !isWordChar( text.GetChar( ii - 1 ) ) );
|
||||
bool endOK = ( next == (int) text.length() || !isWordChar( text.GetChar( next ) ) );
|
||||
|
||||
if( startOK && endOK )
|
||||
return true;
|
||||
@@ -201,8 +213,8 @@ bool EDA_ITEM::Replace( const EDA_SEARCH_DATA& aSearchData, wxString& aText )
|
||||
|
||||
if( aSearchData.matchMode == EDA_SEARCH_MATCH_MODE::WHOLEWORD )
|
||||
{
|
||||
startOK = ( ii == 0 || !wxIsalnum( text.GetChar( ii - 1 ) ) );
|
||||
endOK = ( next == (int) text.length() || !wxIsalnum( text.GetChar( next ) ) );
|
||||
startOK = ( ii == 0 || !isWordChar( text.GetChar( ii - 1 ) ) );
|
||||
endOK = ( next == (int) text.length() || !isWordChar( text.GetChar( next ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -417,11 +417,11 @@ void EDA_SHAPE::RebuildBezierToSegmentsPointsList( int aMinSegLen )
|
||||
// Ensure last point respects aMinSegLen parameter
|
||||
if( m_bezierPoints.size() > 2 )
|
||||
{
|
||||
int idx = m_bezierPoints.size()-1;
|
||||
int idx = m_bezierPoints.size() - 1;
|
||||
|
||||
if( VECTOR2I( m_bezierPoints[idx] - m_bezierPoints[idx]-1 ).EuclideanNorm() < aMinSegLen )
|
||||
if( VECTOR2I( m_bezierPoints[idx] - m_bezierPoints[idx] - 1 ).EuclideanNorm() < aMinSegLen )
|
||||
{
|
||||
m_bezierPoints[idx]-1 = m_bezierPoints[idx];
|
||||
m_bezierPoints[idx - 1] = m_bezierPoints[idx];
|
||||
m_bezierPoints.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
+11
-7
@@ -881,7 +881,8 @@ void EDA_TEXT::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControl
|
||||
|
||||
|
||||
std::shared_ptr<SHAPE_COMPOUND> EDA_TEXT::GetEffectiveTextShape( bool aTriangulate,
|
||||
bool aUseTextRotation ) const
|
||||
const BOX2I& aBBox,
|
||||
const EDA_ANGLE& aAngle ) const
|
||||
{
|
||||
std::shared_ptr<SHAPE_COMPOUND> shape = std::make_shared<SHAPE_COMPOUND>();
|
||||
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
|
||||
@@ -893,16 +894,19 @@ std::shared_ptr<SHAPE_COMPOUND> EDA_TEXT::GetEffectiveTextShape( bool aTriangula
|
||||
|
||||
std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = nullptr;
|
||||
|
||||
if( aUseTextRotation )
|
||||
if( aBBox.GetWidth() )
|
||||
{
|
||||
drawPos = aBBox.GetCenter();
|
||||
attrs.m_Halign = GR_TEXT_H_ALIGN_CENTER;
|
||||
attrs.m_Valign = GR_TEXT_V_ALIGN_CENTER;
|
||||
attrs.m_Angle = aAngle;
|
||||
}
|
||||
else
|
||||
{
|
||||
attrs.m_Angle = GetDrawRotation();
|
||||
|
||||
if( font->IsOutline() )
|
||||
cache = GetRenderCache( font, shownText, drawPos );
|
||||
}
|
||||
else
|
||||
{
|
||||
attrs.m_Angle = ANGLE_0;
|
||||
cache = GetRenderCache( font, shownText, VECTOR2I() );
|
||||
}
|
||||
|
||||
if( aTriangulate )
|
||||
|
||||
@@ -253,11 +253,6 @@ wxString FILENAME_RESOLVER::ResolvePath( const wxString& aFileName, const wxStri
|
||||
// first attempt to use the name as specified:
|
||||
wxString tname = aFileName;
|
||||
|
||||
#ifdef _WIN32
|
||||
// translate from KiCad's internal UNIX-like path to MSWin paths
|
||||
tname.Replace( wxT( "/" ), wxT( "\\" ) );
|
||||
#endif
|
||||
|
||||
// Note: variable expansion must preferably be performed via a threadsafe wrapper for the
|
||||
// getenv() system call. If we allow the wxFileName::Normalize() routine to perform expansion
|
||||
// then we will have a race condition since wxWidgets does not assure a threadsafe wrapper
|
||||
|
||||
@@ -47,7 +47,6 @@ wxString FONTCONFIG::Version()
|
||||
|
||||
FONTCONFIG::FONTCONFIG()
|
||||
{
|
||||
(void) FcInitLoadConfigAndFonts();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -94,9 +94,10 @@ public:
|
||||
private:
|
||||
struct CACHED_BITMAP
|
||||
{
|
||||
GLuint id;
|
||||
int w, h;
|
||||
size_t size;
|
||||
GLuint id;
|
||||
int w, h;
|
||||
size_t size;
|
||||
long long int accessTime;
|
||||
};
|
||||
|
||||
GLuint cacheBitmap( const BITMAP_BASE* aBitmap );
|
||||
@@ -105,9 +106,9 @@ private:
|
||||
const size_t m_cacheMaxSize = 256 * 1024 * 1024;
|
||||
|
||||
std::map<const KIID, CACHED_BITMAP> m_bitmaps;
|
||||
std::list<KIID> m_cacheLru;
|
||||
size_t m_cacheSize;
|
||||
std::list<GLuint> m_freedTextureIds;
|
||||
std::list<KIID> m_cacheLru;
|
||||
size_t m_cacheSize;
|
||||
std::list<GLuint> m_freedTextureIds;
|
||||
};
|
||||
|
||||
}; // namespace KIGFX
|
||||
@@ -130,6 +131,7 @@ GLuint GL_BITMAP_CACHE::RequestBitmap( const BITMAP_BASE* aBitmap )
|
||||
// A bitmap is found in cache bitmap. Ensure the associated texture is still valid.
|
||||
if( glIsTexture( it->second.id ) )
|
||||
{
|
||||
it->second.accessTime = wxGetUTCTimeMillis().GetValue();
|
||||
return it->second.id;
|
||||
}
|
||||
else
|
||||
@@ -182,56 +184,115 @@ GLuint GL_BITMAP_CACHE::cacheBitmap( const BITMAP_BASE* aBitmap )
|
||||
m_freedTextureIds.pop_front();
|
||||
}
|
||||
|
||||
bmp.size = bmp.w * bmp.h * 4;
|
||||
auto buf = std::make_unique<uint8_t[]>( bmp.size );
|
||||
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
|
||||
|
||||
for( int y = 0; y < bmp.h; y++ )
|
||||
if( imgData.HasAlpha() || imgData.HasMask() )
|
||||
{
|
||||
for( int x = 0; x < bmp.w; x++ )
|
||||
bmp.size = bmp.w * bmp.h * 4;
|
||||
auto buf = std::make_unique<uint8_t[]>( bmp.size );
|
||||
|
||||
uint8_t* dstP = buf.get();
|
||||
uint8_t* srcP = imgData.GetData();
|
||||
|
||||
long long pxCount = static_cast<long long>( bmp.w ) * bmp.h;
|
||||
|
||||
if( imgData.HasAlpha() )
|
||||
{
|
||||
uint8_t* p = buf.get() + ( bmp.w * y + x ) * 4;
|
||||
uint8_t* srcAlpha = imgData.GetAlpha();
|
||||
|
||||
p[0] = imgData.GetRed( x, y );
|
||||
p[1] = imgData.GetGreen( x, y );
|
||||
p[2] = imgData.GetBlue( x, y );
|
||||
for( long long px = 0; px < pxCount; px++ )
|
||||
{
|
||||
memcpy( dstP, srcP, 3 );
|
||||
dstP[3] = *srcAlpha;
|
||||
|
||||
if( imgData.HasAlpha() )
|
||||
p[3] = imgData.GetAlpha( x, y );
|
||||
else if( imgData.HasMask() && p[0] == imgData.GetMaskRed()
|
||||
&& p[1] == imgData.GetMaskGreen() && p[2] == imgData.GetMaskBlue() )
|
||||
p[3] = wxALPHA_TRANSPARENT;
|
||||
else
|
||||
p[3] = wxALPHA_OPAQUE;
|
||||
srcAlpha += 1;
|
||||
srcP += 3;
|
||||
dstP += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( imgData.HasMask() )
|
||||
{
|
||||
uint8_t maskRed = imgData.GetMaskRed();
|
||||
uint8_t maskGreen = imgData.GetMaskGreen();
|
||||
uint8_t maskBlue = imgData.GetMaskBlue();
|
||||
|
||||
glBindTexture( GL_TEXTURE_2D, textureID );
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, bmp.w, bmp.h, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
buf.get() );
|
||||
for( long long px = 0; px < pxCount; px++ )
|
||||
{
|
||||
memcpy( dstP, srcP, 3 );
|
||||
|
||||
if( srcP[0] == maskRed && srcP[1] == maskGreen && srcP[2] == maskBlue )
|
||||
dstP[3] = wxALPHA_TRANSPARENT;
|
||||
else
|
||||
dstP[3] = wxALPHA_OPAQUE;
|
||||
|
||||
srcP += 3;
|
||||
dstP += 4;
|
||||
}
|
||||
}
|
||||
|
||||
glBindTexture( GL_TEXTURE_2D, textureID );
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, bmp.w, bmp.h, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
buf.get() );
|
||||
}
|
||||
else
|
||||
{
|
||||
bmp.size = bmp.w * bmp.h * 3;
|
||||
|
||||
uint8_t* srcP = imgData.GetData();
|
||||
|
||||
glBindTexture( GL_TEXTURE_2D, textureID );
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, bmp.w, bmp.h, 0, GL_RGB, GL_UNSIGNED_BYTE, srcP );
|
||||
}
|
||||
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
|
||||
|
||||
long long currentTime = wxGetUTCTimeMillis().GetValue();
|
||||
|
||||
bmp.id = textureID;
|
||||
bmp.accessTime = currentTime;
|
||||
|
||||
#ifndef DISABLE_BITMAP_CACHE
|
||||
m_cacheLru.emplace_back( aBitmap->GetImageID() );
|
||||
m_cacheSize += bmp.size;
|
||||
m_bitmaps.emplace( aBitmap->GetImageID(), std::move( bmp ) );
|
||||
|
||||
if( m_cacheLru.size() > m_cacheMaxElements
|
||||
|| m_cacheSize > m_cacheMaxSize )
|
||||
if( m_cacheLru.size() + 1 > m_cacheMaxElements || m_cacheSize + bmp.size > m_cacheMaxSize )
|
||||
{
|
||||
KIID last = m_cacheLru.front();
|
||||
CACHED_BITMAP& cachedBitmap = m_bitmaps[last];
|
||||
KIID toRemove( 0 );
|
||||
auto toRemoveLru = m_cacheLru.end();
|
||||
|
||||
// Remove entries accessed > 1s ago first
|
||||
for( const auto& [kiid, cachedBmp] : m_bitmaps )
|
||||
{
|
||||
const int cacheTimeoutMillis = 1000L;
|
||||
|
||||
if( currentTime - cachedBmp.accessTime > cacheTimeoutMillis )
|
||||
{
|
||||
toRemove = kiid;
|
||||
toRemoveLru = std::find( m_cacheLru.begin(), m_cacheLru.end(), toRemove );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, remove the latest entry (it's less likely to be needed soon)
|
||||
if( toRemove == niluuid )
|
||||
{
|
||||
toRemoveLru = m_cacheLru.end();
|
||||
toRemoveLru--;
|
||||
|
||||
toRemove = *toRemoveLru;
|
||||
}
|
||||
|
||||
CACHED_BITMAP& cachedBitmap = m_bitmaps[toRemove];
|
||||
|
||||
m_cacheSize -= cachedBitmap.size;
|
||||
glDeleteTextures( 1, &cachedBitmap.id );
|
||||
m_freedTextureIds.emplace_back( cachedBitmap.id );
|
||||
|
||||
m_bitmaps.erase( last );
|
||||
m_cacheLru.pop_front();
|
||||
m_bitmaps.erase( toRemove );
|
||||
m_cacheLru.erase( toRemoveLru );
|
||||
}
|
||||
|
||||
m_cacheLru.emplace_back( aBitmap->GetImageID() );
|
||||
m_cacheSize += bmp.size;
|
||||
m_bitmaps.emplace( aBitmap->GetImageID(), std::move( bmp ) );
|
||||
#endif
|
||||
|
||||
return textureID;
|
||||
@@ -1111,13 +1172,21 @@ void OPENGL_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEn
|
||||
m_currentManager->Color( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b,
|
||||
m_strokeColor.a );
|
||||
|
||||
std::deque<VECTOR2D> pointList;
|
||||
pointList.push_back( aStartPoint );
|
||||
pointList.push_back( diagonalPointA );
|
||||
pointList.push_back( aEndPoint );
|
||||
pointList.push_back( diagonalPointB );
|
||||
pointList.push_back( aStartPoint );
|
||||
DrawPolyline( pointList );
|
||||
// DrawLine (and DrawPolyline )
|
||||
// has problem with 0 length lines so enforce minimum
|
||||
if( aStartPoint == aEndPoint )
|
||||
DrawLine( aStartPoint + VECTOR2D( 1.0, 0.0 ), aEndPoint );
|
||||
else
|
||||
{
|
||||
std::deque<VECTOR2D> pointList;
|
||||
|
||||
pointList.push_back( aStartPoint );
|
||||
pointList.push_back( diagonalPointA );
|
||||
pointList.push_back( aEndPoint );
|
||||
pointList.push_back( diagonalPointB );
|
||||
pointList.push_back( aStartPoint );
|
||||
DrawPolyline( pointList );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+72
-12
@@ -38,6 +38,7 @@
|
||||
#include <gestfich.h>
|
||||
#include <string_utils.h>
|
||||
#include <launch_ext.h>
|
||||
#include "wx/tokenzr.h"
|
||||
|
||||
void QuoteString( wxString& string )
|
||||
{
|
||||
@@ -114,22 +115,78 @@ wxString FindKicadFile( const wxString& shortname )
|
||||
|
||||
int ExecuteFile( const wxString& aEditorName, const wxString& aFileName, wxProcess *aCallback )
|
||||
{
|
||||
wxString fullEditorName;
|
||||
wxString param;
|
||||
wxString fullEditorName;
|
||||
std::vector<wxString> params;
|
||||
|
||||
#ifdef __UNIX__
|
||||
int space = aEditorName.Find( ' ' );
|
||||
wxString param;
|
||||
bool inSingleQuotes = false;
|
||||
bool inDoubleQuotes = false;
|
||||
|
||||
if( space > 0 && !aEditorName.Contains( "\"" ) && !aEditorName.Contains( "\'" ) )
|
||||
auto pushParam =
|
||||
[&]()
|
||||
{
|
||||
if( !param.IsEmpty() )
|
||||
{
|
||||
params.push_back( param );
|
||||
param.clear();
|
||||
}
|
||||
};
|
||||
|
||||
for( wxUniChar ch : aEditorName )
|
||||
{
|
||||
fullEditorName = FindKicadFile( aEditorName.Mid( 0, space ) );
|
||||
param = aEditorName.Mid( space + 1 );
|
||||
if( inSingleQuotes )
|
||||
{
|
||||
if( ch == '\'' )
|
||||
{
|
||||
pushParam();
|
||||
inSingleQuotes = false;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
param += ch;
|
||||
}
|
||||
}
|
||||
else if( inDoubleQuotes )
|
||||
{
|
||||
if( ch == '"' )
|
||||
{
|
||||
pushParam();
|
||||
inDoubleQuotes = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
param += ch;
|
||||
}
|
||||
}
|
||||
else if( ch == '\'' )
|
||||
{
|
||||
pushParam();
|
||||
inSingleQuotes = true;
|
||||
}
|
||||
else if( ch == '"' )
|
||||
{
|
||||
pushParam();
|
||||
inDoubleQuotes = true;
|
||||
}
|
||||
else if( ch == ' ' )
|
||||
{
|
||||
pushParam();
|
||||
}
|
||||
else
|
||||
{
|
||||
param += ch;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
pushParam();
|
||||
|
||||
fullEditorName = FindKicadFile( params[0] );
|
||||
params.erase( params.begin() );
|
||||
#else
|
||||
fullEditorName = FindKicadFile( aEditorName );
|
||||
#endif
|
||||
{
|
||||
fullEditorName = FindKicadFile( aEditorName );
|
||||
}
|
||||
|
||||
if( wxFileExists( fullEditorName ) )
|
||||
{
|
||||
@@ -138,8 +195,11 @@ int ExecuteFile( const wxString& aEditorName, const wxString& aFileName, wxProce
|
||||
|
||||
args[i++] = fullEditorName.wc_str();
|
||||
|
||||
if( !param.IsEmpty() )
|
||||
args[i++] = param.wc_str();
|
||||
if( !params.empty() )
|
||||
{
|
||||
for( const wxString& p : params )
|
||||
args[i++] = p.wc_str();
|
||||
}
|
||||
|
||||
if( !aFileName.IsEmpty() )
|
||||
args[i++] = aFileName.wc_str();
|
||||
|
||||
@@ -55,6 +55,11 @@ public:
|
||||
bool m_plotBorderTitleBlocks;
|
||||
|
||||
LSET m_printMaskLayer;
|
||||
|
||||
// How holes in pads/vias are plotted:
|
||||
// 0 = no hole, 1 = small shape, 2 = actual shape
|
||||
// Not used in some plotters (Gerber)
|
||||
int m_drillShapeOption;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
m_outputFile(),
|
||||
m_xOrigin( 0.0 ),
|
||||
m_yOrigin( 0.0 ),
|
||||
m_minDistance( 0.01 ) // 0.01 mm is a good value to connect 2 items of the board outlines
|
||||
m_boardOutlinesChainingEpsilon( 0.01 ) // 0.01 mm is a good value to connect 2 items of the board outlines
|
||||
{
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
wxString m_outputFile;
|
||||
double m_xOrigin;
|
||||
double m_yOrigin;
|
||||
double m_minDistance;
|
||||
double m_boardOutlinesChainingEpsilon;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
|
||||
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2023 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
|
||||
@@ -47,6 +47,11 @@ public:
|
||||
int m_pageSizeMode;
|
||||
|
||||
LSET m_printMaskLayer;
|
||||
|
||||
// How holes in pads/vias are plotted:
|
||||
// 0 = no hole, 1 = small shape, 2 = actual shape
|
||||
// Not used in some plotters (Gerber)
|
||||
int m_drillShapeOption;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -32,6 +32,9 @@ wxString LayerName( int aLayer )
|
||||
switch( aLayer )
|
||||
{
|
||||
// PCB_LAYER_ID
|
||||
case UNDEFINED_LAYER: return _( "undefined" );
|
||||
|
||||
// Copper
|
||||
case F_Cu: return wxT( "F.Cu" );
|
||||
case In1_Cu: return wxT( "In1.Cu" );
|
||||
case In2_Cu: return wxT( "In2.Cu" );
|
||||
|
||||
+123
-31
@@ -127,6 +127,13 @@ LIB_TABLE::~LIB_TABLE()
|
||||
}
|
||||
|
||||
|
||||
void LIB_TABLE::Clear()
|
||||
{
|
||||
m_rows.clear();
|
||||
m_rowsMap.clear();
|
||||
}
|
||||
|
||||
|
||||
bool LIB_TABLE::IsEmpty( bool aIncludeFallback )
|
||||
{
|
||||
if( !aIncludeFallback || !m_fallBack )
|
||||
@@ -191,31 +198,26 @@ LIB_TABLE_ROW* LIB_TABLE::findRow( const wxString& aNickName, bool aCheckIfEnabl
|
||||
|
||||
do
|
||||
{
|
||||
cur->ensureIndex();
|
||||
std::shared_lock<std::shared_mutex> lock( cur->m_mutex, std::try_to_lock );
|
||||
|
||||
std::shared_lock<std::shared_mutex> lock( cur->m_nickIndexMutex );
|
||||
if( !cur->m_rowsMap.count( aNickName ) )
|
||||
continue;
|
||||
|
||||
for( const std::pair<const wxString, int>& entry : cur->m_nickIndex )
|
||||
{
|
||||
if( entry.first == aNickName )
|
||||
{
|
||||
row = &cur->m_rows[entry.second];
|
||||
row = &*cur->m_rowsMap.at( aNickName );
|
||||
|
||||
if( !aCheckIfEnabled || row->GetIsEnabled() )
|
||||
return row;
|
||||
}
|
||||
}
|
||||
if( !aCheckIfEnabled || row->GetIsEnabled() )
|
||||
return row;
|
||||
|
||||
// Repeat, this time looking for names that were "fixed" by legacy versions because
|
||||
// the old eeschema file format didn't support spaces in tokens.
|
||||
for( const std::pair<const wxString, int>& entry : cur->m_nickIndex )
|
||||
for( const std::pair<const wxString, LIB_TABLE_ROWS_ITER>& entry : cur->m_rowsMap )
|
||||
{
|
||||
wxString legacyLibName = entry.first;
|
||||
legacyLibName.Replace( " ", "_" );
|
||||
|
||||
if( legacyLibName == aNickName )
|
||||
{
|
||||
row = &cur->m_rows[entry.second];
|
||||
row = &*entry.second;
|
||||
|
||||
if( !aCheckIfEnabled || row->GetIsEnabled() )
|
||||
return row;
|
||||
@@ -235,9 +237,7 @@ const LIB_TABLE_ROW* LIB_TABLE::FindRowByURI( const wxString& aURI )
|
||||
|
||||
do
|
||||
{
|
||||
cur->ensureIndex();
|
||||
|
||||
for( unsigned i = 0; i < cur->m_rows.size(); i++ )
|
||||
for( unsigned i = 0; i < cur->m_rows.size(); i++ )
|
||||
{
|
||||
wxString tmp = cur->m_rows[i].GetFullURI( true );
|
||||
|
||||
@@ -276,10 +276,10 @@ std::vector<wxString> LIB_TABLE::GetLogicalLibs()
|
||||
|
||||
do
|
||||
{
|
||||
for( LIB_TABLE_ROWS_CITER it = cur->m_rows.begin(); it!=cur->m_rows.end(); ++it )
|
||||
for( const LIB_TABLE_ROW& row : cur->m_rows )
|
||||
{
|
||||
if( it->GetIsEnabled() )
|
||||
unique.insert( it->GetNickName() );
|
||||
if( row.GetIsEnabled() )
|
||||
unique.insert( row.GetNickName() );
|
||||
}
|
||||
|
||||
} while( ( cur = cur->m_fallBack ) != nullptr );
|
||||
@@ -303,28 +303,120 @@ std::vector<wxString> LIB_TABLE::GetLogicalLibs()
|
||||
|
||||
bool LIB_TABLE::InsertRow( LIB_TABLE_ROW* aRow, bool doReplace )
|
||||
{
|
||||
ensureIndex();
|
||||
std::lock_guard<std::shared_mutex> lock( m_mutex );
|
||||
|
||||
std::lock_guard<std::shared_mutex> lock( m_nickIndexMutex );
|
||||
auto it = m_rowsMap.find( aRow->GetNickName() );
|
||||
|
||||
INDEX_CITER it = m_nickIndex.find( aRow->GetNickName() );
|
||||
if( it != m_rowsMap.end() )
|
||||
{
|
||||
if( !doReplace )
|
||||
return false;
|
||||
|
||||
aRow->SetParent( this );
|
||||
|
||||
if( it == m_nickIndex.end() )
|
||||
m_rows.replace( it->second, aRow );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rows.push_back( aRow );
|
||||
m_nickIndex.insert( INDEX_VALUE( aRow->GetNickName(), m_rows.size() - 1 ) );
|
||||
return true;
|
||||
}
|
||||
|
||||
if( doReplace )
|
||||
aRow->SetParent( this );
|
||||
reindex();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool LIB_TABLE::RemoveRow( const LIB_TABLE_ROW* aRow )
|
||||
{
|
||||
std::lock_guard<std::shared_mutex> lock( m_mutex );
|
||||
|
||||
bool found = false;
|
||||
auto it = m_rowsMap.find( aRow->GetNickName() );
|
||||
|
||||
if( it != m_rowsMap.end() )
|
||||
{
|
||||
m_rows.replace( it->second, aRow );
|
||||
return true;
|
||||
if( &*it->second == aRow )
|
||||
{
|
||||
found = true;
|
||||
m_rows.erase( it->second );
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
if( !found )
|
||||
{
|
||||
// Bookkeeping got messed up...
|
||||
for( size_t i = m_rows.size() - 1; i >= 0; --i )
|
||||
{
|
||||
if( &m_rows[i] == aRow )
|
||||
{
|
||||
m_rows.erase( m_rows.begin() + i );
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( found )
|
||||
reindex();
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
bool LIB_TABLE::ReplaceRow( size_t aIndex, LIB_TABLE_ROW* aRow )
|
||||
{
|
||||
std::lock_guard<std::shared_mutex> lock( m_mutex );
|
||||
|
||||
if( aIndex >= m_rows.size() )
|
||||
return false;
|
||||
|
||||
m_rowsMap.erase( m_rows[aIndex].GetNickName() );
|
||||
|
||||
m_rows.replace( aIndex, aRow );
|
||||
reindex();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool LIB_TABLE::ChangeRowOrder( size_t aIndex, int aOffset )
|
||||
{
|
||||
std::lock_guard<std::shared_mutex> lock( m_mutex );
|
||||
|
||||
if( aIndex >= m_rows.size() )
|
||||
return false;
|
||||
|
||||
int newPos = static_cast<int>( aIndex ) + aOffset;
|
||||
|
||||
if( newPos < 0 || newPos > static_cast<int>( m_rows.size() ) - 1 )
|
||||
return false;
|
||||
|
||||
auto element = m_rows.release( m_rows.begin() + aIndex );
|
||||
|
||||
m_rows.insert( m_rows.begin() + newPos, element.release() );
|
||||
reindex();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void LIB_TABLE::TransferRows( LIB_TABLE_ROWS& aRowsList )
|
||||
{
|
||||
std::lock_guard<std::shared_mutex> lock( m_mutex );
|
||||
|
||||
m_rows.transfer( m_rows.end(), aRowsList.begin(), aRowsList.end(), aRowsList );
|
||||
|
||||
reindex();
|
||||
}
|
||||
|
||||
|
||||
void LIB_TABLE::reindex()
|
||||
{
|
||||
m_rowsMap.clear();
|
||||
|
||||
for( LIB_TABLE_ROWS_ITER it = m_rows.begin(); it != m_rows.end(); ++it )
|
||||
{
|
||||
it->SetParent( this );
|
||||
m_rowsMap[it->GetNickName()] = it;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+21
-12
@@ -90,7 +90,7 @@ void LIB_TREE_NODE::SortNodes()
|
||||
std::sort( m_Children.begin(), m_Children.end(),
|
||||
[]( std::unique_ptr<LIB_TREE_NODE>& a, std::unique_ptr<LIB_TREE_NODE>& b )
|
||||
{
|
||||
return Compare( *a, *b ) > 0;
|
||||
return Compare( *a, *b );
|
||||
} );
|
||||
|
||||
for( std::unique_ptr<LIB_TREE_NODE>& node: m_Children )
|
||||
@@ -98,27 +98,38 @@ void LIB_TREE_NODE::SortNodes()
|
||||
}
|
||||
|
||||
|
||||
int LIB_TREE_NODE::Compare( LIB_TREE_NODE const& aNode1, LIB_TREE_NODE const& aNode2 )
|
||||
bool LIB_TREE_NODE::Compare( LIB_TREE_NODE const& aNode1, LIB_TREE_NODE const& aNode2 )
|
||||
{
|
||||
if( aNode1.m_Type != aNode2.m_Type )
|
||||
return 0;
|
||||
return aNode1.m_Type < aNode2.m_Type;
|
||||
|
||||
// Recently used sorts at top
|
||||
if( aNode1.m_Name.StartsWith( wxT( "-- " ) ) )
|
||||
return 1;
|
||||
{
|
||||
if( aNode2.m_Name.StartsWith( wxT( "-- " ) ) )
|
||||
{
|
||||
return aNode1.m_IntrinsicRank > aNode2.m_IntrinsicRank;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if( aNode2.m_Name.StartsWith( wxT( "-- " ) ) )
|
||||
return 0;
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pinned nodes go next
|
||||
if( aNode1.m_Pinned && !aNode2.m_Pinned )
|
||||
return 1;
|
||||
return true;
|
||||
else if( aNode2.m_Pinned && !aNode1.m_Pinned )
|
||||
return -1;
|
||||
return false;
|
||||
|
||||
if( aNode1.m_Parent != aNode2.m_Parent )
|
||||
return 0;
|
||||
if( aNode1.m_IntrinsicRank != aNode2.m_IntrinsicRank )
|
||||
return aNode1.m_IntrinsicRank > aNode2.m_IntrinsicRank;
|
||||
|
||||
return aNode1.m_IntrinsicRank - aNode2.m_IntrinsicRank;
|
||||
return reinterpret_cast<const void*>( &aNode1 ) < reinterpret_cast<const void*>( &aNode2 );
|
||||
}
|
||||
|
||||
|
||||
@@ -311,8 +322,6 @@ LIB_TREE_NODE_LIB_ID& LIB_TREE_NODE_LIB::AddItem( LIB_TREE_ITEM* aItem )
|
||||
|
||||
void LIB_TREE_NODE_LIB::UpdateScore( EDA_COMBINED_MATCHER& aMatcher, const wxString& aLib )
|
||||
{
|
||||
m_Score = 0;
|
||||
|
||||
// We need to score leaf nodes, which are usually (but not always) children.
|
||||
|
||||
if( m_Children.size() )
|
||||
|
||||
@@ -288,6 +288,24 @@ wxString PATHS::GetStockPlugins3DPath()
|
||||
fn.AppendDir( wxT( "plugins" ) );
|
||||
#elif defined( __WXMAC__ )
|
||||
fn.Assign( wxStandardPaths::Get().GetPluginsDir(), wxEmptyString );
|
||||
|
||||
// This must be mapped to main bundle for everything but kicad.app
|
||||
const wxArrayString dirs = fn.GetDirs();
|
||||
|
||||
// Check if we are the main kicad binary. in this case, the path will be
|
||||
// /path/to/bundlename.app/Contents/PlugIns
|
||||
// If we are an aux binary, the path will be something like
|
||||
// /path/to/bundlename.app/Contents/Applications/<standalone>.app/Contents/PlugIns
|
||||
if( dirs.GetCount() >= 6 &&
|
||||
dirs[dirs.GetCount() - 4] == wxT( "Applications" ) &&
|
||||
dirs[dirs.GetCount() - 6].Lower().EndsWith( wxT( "app" ) ) )
|
||||
{
|
||||
fn.RemoveLastDir();
|
||||
fn.RemoveLastDir();
|
||||
fn.RemoveLastDir();
|
||||
fn.RemoveLastDir();
|
||||
fn.AppendDir( wxT( "PlugIns" ) );
|
||||
}
|
||||
#else
|
||||
if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
|
||||
{
|
||||
@@ -434,6 +452,17 @@ wxString PATHS::GetOSXKicadDataDir()
|
||||
|
||||
|
||||
#ifdef __WXWINDOWS__
|
||||
wxString PATHS::GetWindowsFontConfigDir()
|
||||
{
|
||||
wxFileName fn;
|
||||
fn.AssignDir( getWindowsKiCadRoot() );
|
||||
fn.AppendDir( wxS( "etc" ) );
|
||||
fn.AppendDir( wxS( "fonts" ) );
|
||||
|
||||
return fn.GetPathWithSep();
|
||||
}
|
||||
|
||||
|
||||
wxString PATHS::getWindowsKiCadRoot()
|
||||
{
|
||||
wxFileName root( Pgm().GetExecutablePath() + wxT( "/../" ) );
|
||||
|
||||
@@ -161,6 +161,8 @@ void PGM_BASE::Destroy()
|
||||
// unlike a normal destructor, this is designed to be called more than once safely:
|
||||
delete m_locale;
|
||||
m_locale = nullptr;
|
||||
|
||||
m_pgm_checker.reset();
|
||||
}
|
||||
|
||||
|
||||
@@ -443,6 +445,8 @@ bool PGM_BASE::InitPgm( bool aHeadless, bool aSkipPyInit, bool aIsUnitTest )
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
m_pgm_checker = std::make_unique<wxSingleInstanceChecker>();
|
||||
m_pgm_checker->Create( pgm_name, wxStandardPaths::Get().GetTempDir() );
|
||||
|
||||
// Init KiCad environment
|
||||
// the environment variable KICAD (if exists) gives the kicad path:
|
||||
@@ -479,6 +483,13 @@ bool PGM_BASE::InitPgm( bool aHeadless, bool aSkipPyInit, bool aIsUnitTest )
|
||||
SetLanguagePath();
|
||||
SetDefaultLanguage( tmp );
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// We need to set this because the internal fontconfig logic
|
||||
// seems to search relative to the dll rather the other logic it
|
||||
// has to look for the /etc folder above the dll
|
||||
wxSetEnv( "FONTCONFIG_PATH", PATHS::GetWindowsFontConfigDir() );
|
||||
#endif
|
||||
|
||||
m_settings_manager = std::make_unique<SETTINGS_MANAGER>( aHeadless );
|
||||
|
||||
// Our unit test mocks break if we continue
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <string_utils.h>
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
#include <trigo.h>
|
||||
#include <fmt/core.h>
|
||||
|
||||
/**
|
||||
* Oblique angle for DXF native text
|
||||
@@ -146,6 +147,26 @@ void DXF_PLOTTER::SetUnits( DXF_UNITS aUnit )
|
||||
}
|
||||
|
||||
|
||||
// convert aValue to a string, and remove trailing zeros
|
||||
// In DXF files coordinates need a high precision: at least 9 digits when given
|
||||
// in inches and 7 digits when in mm.
|
||||
// So we use 16 digits and remove trailing 0 (if any)
|
||||
static std::string formatCoord( double aValue )
|
||||
{
|
||||
std::string buf;
|
||||
|
||||
buf = fmt::format( "{:.16f}", aValue );
|
||||
|
||||
// remove trailing zeros
|
||||
while( !buf.empty() && buf[buf.size() - 1] == '0' )
|
||||
{
|
||||
buf.pop_back();
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
void DXF_PLOTTER::SetViewport( const VECTOR2I& aOffset, double aIusPerDecimil,
|
||||
double aScale, bool aMirror )
|
||||
{
|
||||
@@ -417,11 +438,24 @@ void DXF_PLOTTER::SetColor( const COLOR4D& color )
|
||||
void DXF_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill, int width )
|
||||
{
|
||||
wxASSERT( m_outputFile );
|
||||
MoveTo( p1 );
|
||||
LineTo( VECTOR2I( p1.x, p2.y ) );
|
||||
LineTo( VECTOR2I( p2.x, p2.y ) );
|
||||
LineTo( VECTOR2I( p2.x, p1.y ) );
|
||||
FinishTo( VECTOR2I( p1.x, p1.y ) );
|
||||
|
||||
if( p1 != p2 )
|
||||
{
|
||||
MoveTo( p1 );
|
||||
LineTo( VECTOR2I( p1.x, p2.y ) );
|
||||
LineTo( VECTOR2I( p2.x, p2.y ) );
|
||||
LineTo( VECTOR2I( p2.x, p1.y ) );
|
||||
FinishTo( VECTOR2I( p1.x, p1.y ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw as a point
|
||||
wxString cname = getDXFColorName( m_currentColor );
|
||||
VECTOR2D point_dev = userToDeviceCoordinates( p1 );
|
||||
|
||||
fprintf( m_outputFile, "0\nPOINT\n8\n%s\n10\n%g\n20\n%g\n", TO_UTF8( cname ), point_dev.x,
|
||||
point_dev.y );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -431,31 +465,43 @@ void DXF_PLOTTER::Circle( const VECTOR2I& centre, int diameter, FILL_T fill, int
|
||||
double radius = userToDeviceSize( diameter / 2 );
|
||||
VECTOR2D centre_dev = userToDeviceCoordinates( centre );
|
||||
|
||||
wxString cname = getDXFColorName( m_currentColor );
|
||||
|
||||
if( radius > 0 )
|
||||
{
|
||||
wxString cname = getDXFColorName( m_currentColor );
|
||||
|
||||
if( fill == FILL_T::NO_FILL )
|
||||
{
|
||||
fprintf( m_outputFile, "0\nCIRCLE\n8\n%s\n10\n%g\n20\n%g\n40\n%g\n",
|
||||
fprintf( m_outputFile, "0\nCIRCLE\n8\n%s\n10\n%s\n20\n%s\n40\n%s\n",
|
||||
TO_UTF8( cname ),
|
||||
centre_dev.x, centre_dev.y, radius );
|
||||
formatCoord( centre_dev.x ).c_str(),
|
||||
formatCoord( centre_dev.y ).c_str(),
|
||||
formatCoord( radius ).c_str() );
|
||||
}
|
||||
else if( fill == FILL_T::FILLED_SHAPE )
|
||||
{
|
||||
double r = radius*0.5;
|
||||
double r = radius * 0.5;
|
||||
fprintf( m_outputFile, "0\nPOLYLINE\n" );
|
||||
fprintf( m_outputFile, "8\n%s\n66\n1\n70\n1\n", TO_UTF8( cname ) );
|
||||
fprintf( m_outputFile, "40\n%g\n41\n%g\n", radius, radius);
|
||||
fprintf( m_outputFile, "40\n%s\n41\n%s\n",
|
||||
formatCoord( radius ).c_str(),
|
||||
formatCoord( radius ).c_str() );
|
||||
fprintf( m_outputFile, "0\nVERTEX\n8\n%s\n", TO_UTF8( cname ) );
|
||||
fprintf( m_outputFile, "10\n%g\n 20\n%g\n42\n1.0\n",
|
||||
centre_dev.x-r, centre_dev.y );
|
||||
fprintf( m_outputFile, "10\n%s\n 20\n%s\n42\n1.0\n",
|
||||
formatCoord( centre_dev.x-r ).c_str(),
|
||||
formatCoord( centre_dev.y ).c_str() );
|
||||
fprintf( m_outputFile, "0\nVERTEX\n8\n%s\n", TO_UTF8( cname ) );
|
||||
fprintf( m_outputFile, "10\n%g\n 20\n%g\n42\n1.0\n",
|
||||
centre_dev.x+r, centre_dev.y );
|
||||
fprintf( m_outputFile, "10\n%s\n 20\n%s\n42\n1.0\n",
|
||||
formatCoord( centre_dev.x+r ).c_str(),
|
||||
formatCoord( centre_dev.y ).c_str() );
|
||||
fprintf( m_outputFile, "0\nSEQEND\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw as a point
|
||||
fprintf( m_outputFile, "0\nPOINT\n8\n%s\n10\n%g\n20\n%g\n", TO_UTF8( cname ), centre_dev.x,
|
||||
centre_dev.y );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -578,9 +624,12 @@ void DXF_PLOTTER::PenTo( const VECTOR2I& pos, char plume )
|
||||
// DXF LINE
|
||||
wxString cname = getDXFColorName( m_currentColor );
|
||||
const char* lname = getDXFLineType( static_cast<PLOT_DASH_TYPE>( m_currentLineType ) );
|
||||
fprintf( m_outputFile, "0\nLINE\n8\n%s\n6\n%s\n10\n%g\n20\n%g\n11\n%g\n21\n%g\n",
|
||||
fprintf( m_outputFile, "0\nLINE\n8\n%s\n6\n%s\n10\n%s\n20\n%s\n11\n%s\n21\n%s\n",
|
||||
TO_UTF8( cname ), lname,
|
||||
pen_lastpos_dev.x, pen_lastpos_dev.y, pos_dev.x, pos_dev.y );
|
||||
formatCoord( pen_lastpos_dev.x ).c_str(),
|
||||
formatCoord( pen_lastpos_dev.y ).c_str(),
|
||||
formatCoord( pos_dev.x ).c_str(),
|
||||
formatCoord( pos_dev.y ).c_str() );
|
||||
}
|
||||
|
||||
m_penLastpos = pos;
|
||||
@@ -626,8 +675,8 @@ void DXF_PLOTTER::ThickSegment( const VECTOR2I& aStart, const VECTOR2I& aEnd, in
|
||||
}
|
||||
|
||||
|
||||
void DXF_PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill, int aWidth )
|
||||
void DXF_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill, int aWidth )
|
||||
{
|
||||
wxASSERT( m_outputFile );
|
||||
|
||||
@@ -648,9 +697,11 @@ void DXF_PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
// Emit a DXF ARC entity
|
||||
wxString cname = getDXFColorName( m_currentColor );
|
||||
fprintf( m_outputFile,
|
||||
"0\nARC\n8\n%s\n10\n%g\n20\n%g\n40\n%g\n50\n%g\n51\n%g\n",
|
||||
"0\nARC\n8\n%s\n10\n%s\n20\n%s\n40\n%s\n50\n%.8f\n51\n%.8f\n",
|
||||
TO_UTF8( cname ),
|
||||
centre_device.x, centre_device.y, radius_device,
|
||||
formatCoord( centre_device.x ).c_str(),
|
||||
formatCoord( centre_device.y ).c_str(),
|
||||
formatCoord( radius_device ).c_str(),
|
||||
startAngle.AsDegrees(), endAngle.AsDegrees() );
|
||||
}
|
||||
|
||||
@@ -936,21 +987,21 @@ void DXF_PLOTTER::plotOneLineOfText( const VECTOR2I& aPos, const COLOR4D& aColor
|
||||
" 8\n"
|
||||
"%s\n" // Layer name
|
||||
" 10\n"
|
||||
"%g\n" // First point X
|
||||
"%s\n" // First point X
|
||||
" 11\n"
|
||||
"%g\n" // Second point X
|
||||
"%s\n" // Second point X
|
||||
" 20\n"
|
||||
"%g\n" // First point Y
|
||||
"%s\n" // First point Y
|
||||
" 21\n"
|
||||
"%g\n" // Second point Y
|
||||
"%s\n" // Second point Y
|
||||
" 40\n"
|
||||
"%g\n" // Text height
|
||||
"%s\n" // Text height
|
||||
" 41\n"
|
||||
"%g\n" // Width factor
|
||||
"%s\n" // Width factor
|
||||
" 50\n"
|
||||
"%g\n" // Rotation
|
||||
"%.8f\n" // Rotation
|
||||
" 51\n"
|
||||
"%g\n" // Oblique angle
|
||||
"%.8f\n" // Oblique angle
|
||||
" 71\n"
|
||||
"%d\n" // Mirror flags
|
||||
" 72\n"
|
||||
@@ -960,9 +1011,9 @@ void DXF_PLOTTER::plotOneLineOfText( const VECTOR2I& aPos, const COLOR4D& aColor
|
||||
aAttributes.m_Bold ?
|
||||
(aAttributes.m_Italic ? "KICADBI" : "KICADB")
|
||||
: (aAttributes.m_Italic ? "KICADI" : "KICAD"), TO_UTF8( cname ),
|
||||
origin_dev.x, origin_dev.x,
|
||||
origin_dev.y, origin_dev.y,
|
||||
size_dev.y, fabs( size_dev.x / size_dev.y ),
|
||||
formatCoord( origin_dev.x ).c_str(), formatCoord( origin_dev.x ).c_str(),
|
||||
formatCoord( origin_dev.y ).c_str(), formatCoord( origin_dev.y ).c_str(),
|
||||
formatCoord( size_dev.y ).c_str(), formatCoord( fabs( size_dev.x / size_dev.y ) ).c_str(),
|
||||
aAttributes.m_Angle.AsDegrees(),
|
||||
aAttributes.m_Italic ? DXF_OBLIQUE_ANGLE : 0,
|
||||
aAttributes.m_Mirrored ? 2 : 0, // X mirror flag
|
||||
|
||||
@@ -826,8 +826,8 @@ void GERBER_PLOTTER::Circle( const VECTOR2I& aCenter, int aDiameter, FILL_T aFil
|
||||
|
||||
|
||||
|
||||
void GERBER_PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill, int aWidth )
|
||||
void GERBER_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill, int aWidth )
|
||||
{
|
||||
SetCurrentLineWidth( aWidth );
|
||||
|
||||
@@ -1149,8 +1149,8 @@ void GERBER_PLOTTER::ThickSegment( const VECTOR2I& start, const VECTOR2I& end, i
|
||||
}
|
||||
}
|
||||
|
||||
void GERBER_PLOTTER::ThickArc( const VECTOR2I& aCentre, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, int aRadius, int aWidth,
|
||||
void GERBER_PLOTTER::ThickArc( const VECTOR2D& aCentre, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, double aRadius, int aWidth,
|
||||
OUTLINE_MODE aTraceMode, void* aData )
|
||||
{
|
||||
GBR_METADATA *gbr_metadata = static_cast<GBR_METADATA*>( aData );
|
||||
|
||||
@@ -394,22 +394,16 @@ void HPGL_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T aFill, i
|
||||
VECTOR2D p1_device = userToDeviceCoordinates( p1 );
|
||||
VECTOR2D p2_device = userToDeviceCoordinates( p2 );
|
||||
|
||||
MoveTo( p1 );
|
||||
// EA command seems to always fill the rectangle, so plot as a polygon instead
|
||||
std::vector<VECTOR2I> cornerList;
|
||||
|
||||
if( aFill == FILL_T::FILLED_SHAPE )
|
||||
{
|
||||
startOrAppendItem( p1_device, wxString::Format( "RA %.0f,%.0f;",
|
||||
p2_device.x,
|
||||
p2_device.y ) );
|
||||
}
|
||||
cornerList.emplace_back( p1.x, p1.y );
|
||||
cornerList.emplace_back( p2.x, p1.y );
|
||||
cornerList.emplace_back( p2.x, p2.y );
|
||||
cornerList.emplace_back( p1.x, p2.y );
|
||||
cornerList.emplace_back( p1.x, p1.y );
|
||||
|
||||
startOrAppendItem( p1_device, wxString::Format( "EA %.0f,%.0f;",
|
||||
p2_device.x,
|
||||
p2_device.y ) );
|
||||
|
||||
m_current_item->loc_end = m_current_item->loc_start;
|
||||
m_current_item->bbox.Merge( p2_device );
|
||||
PenFinish();
|
||||
PlotPoly( cornerList, aFill, aWidth, nullptr );
|
||||
}
|
||||
|
||||
|
||||
@@ -435,7 +429,6 @@ void HPGL_PLOTTER::Circle( const VECTOR2I& aCenter, int aDiameter, FILL_T aFill,
|
||||
chord_angle.AsDegrees(),
|
||||
hpgl_end_polygon_cmd ) );
|
||||
m_current_item->lift_before = true;
|
||||
m_current_item->pen_returns = true;
|
||||
m_current_item->bbox.Merge( BOX2D( center_dev - radius,
|
||||
VECTOR2D( 2 * radius, 2 * radius ) ) );
|
||||
PenFinish();
|
||||
@@ -448,7 +441,6 @@ void HPGL_PLOTTER::Circle( const VECTOR2I& aCenter, int aDiameter, FILL_T aFill,
|
||||
radius,
|
||||
chord_angle.AsDegrees() ) );
|
||||
m_current_item->lift_before = true;
|
||||
m_current_item->pen_returns = true;
|
||||
m_current_item->bbox.Merge( BOX2D( center_dev - radius,
|
||||
VECTOR2D( 2 * radius, 2 * radius ) ) );
|
||||
PenFinish();
|
||||
@@ -567,8 +559,8 @@ void HPGL_PLOTTER::ThickSegment( const VECTOR2I& start, const VECTOR2I& end,
|
||||
}
|
||||
|
||||
|
||||
void HPGL_PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill, int aWidth )
|
||||
void HPGL_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill, int aWidth )
|
||||
{
|
||||
if( aRadius <= 0 )
|
||||
return;
|
||||
|
||||
@@ -217,12 +217,43 @@ void PDF_PLOTTER::SetDash( int aLineWidth, PLOT_DASH_TYPE aLineStyle )
|
||||
void PDF_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill, int width )
|
||||
{
|
||||
wxASSERT( m_workFile );
|
||||
|
||||
SetCurrentLineWidth( width );
|
||||
|
||||
VECTOR2I size = p2 - p1;
|
||||
|
||||
if( size.x == 0 && size.y == 0 )
|
||||
{
|
||||
// Can't draw zero-sized rectangles
|
||||
SetCurrentLineWidth( width );
|
||||
|
||||
MoveTo( VECTOR2I( p1.x, p1.y ) );
|
||||
FinishTo( VECTOR2I( p1.x, p1.y ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( std::min( std::abs( size.x ), std::abs( size.y ) ) < width )
|
||||
{
|
||||
// Too thick stroked rectangles are buggy, draw as polygon
|
||||
std::vector<VECTOR2I> cornerList;
|
||||
|
||||
cornerList.emplace_back( p1.x, p1.y );
|
||||
cornerList.emplace_back( p2.x, p1.y );
|
||||
cornerList.emplace_back( p2.x, p2.y );
|
||||
cornerList.emplace_back( p1.x, p2.y );
|
||||
cornerList.emplace_back( p1.x, p1.y );
|
||||
|
||||
PlotPoly( cornerList, fill, width, nullptr );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
VECTOR2D p1_dev = userToDeviceCoordinates( p1 );
|
||||
VECTOR2D p2_dev = userToDeviceCoordinates( p2 );
|
||||
|
||||
SetCurrentLineWidth( width );
|
||||
fprintf( m_workFile, "%g %g %g %g re %c\n", p1_dev.x, p1_dev.y,
|
||||
p2_dev.x - p1_dev.x, p2_dev.y - p1_dev.y, fill == FILL_T::NO_FILL ? 'S' : 'B' );
|
||||
fprintf( m_workFile, "%g %g %g %g re %c\n", p1_dev.x, p1_dev.y, p2_dev.x - p1_dev.x,
|
||||
p2_dev.y - p1_dev.y, fill == FILL_T::NO_FILL ? 'S' : 'B' );
|
||||
}
|
||||
|
||||
|
||||
@@ -336,8 +367,8 @@ void PDF_PLOTTER::Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, const VE
|
||||
}
|
||||
|
||||
|
||||
void PDF_PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill, int aWidth )
|
||||
void PDF_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill, int aWidth )
|
||||
{
|
||||
wxASSERT( m_workFile );
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ void PSLIKE_PLOTTER::FlashPadOval( const VECTOR2I& aPadPos, const VECTOR2I& aSiz
|
||||
if( aTraceMode == FILLED )
|
||||
ThickSegment( a + aPadPos, b + aPadPos, size.x, aTraceMode, nullptr );
|
||||
else
|
||||
sketchOval( aPadPos, size, orient, -1 );
|
||||
sketchOval( aPadPos, size, orient, USE_DEFAULT_LINE_WIDTH );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -443,8 +443,8 @@ void SVG_PLOTTER::Circle( const VECTOR2I& pos, int diametre, FILL_T fill, int wi
|
||||
}
|
||||
|
||||
|
||||
void SVG_PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill, int aWidth )
|
||||
void SVG_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill, int aWidth )
|
||||
{
|
||||
/* Draws an arc of a circle, centered on (xc,yc), with starting point (x1, y1) and ending
|
||||
* at (x2, y2). The current pen is used for the outline and the current brush for filling
|
||||
|
||||
@@ -145,13 +145,31 @@ double PLOTTER::GetDashGapLenIU( int aLineWidth ) const
|
||||
return userToDeviceSize( m_renderSettings->GetGapLength( aLineWidth ) );
|
||||
}
|
||||
|
||||
|
||||
#include <wx/log.h>
|
||||
void PLOTTER::Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, const VECTOR2I& aEnd,
|
||||
FILL_T aFill, int aWidth, int aMaxError )
|
||||
{
|
||||
EDA_ANGLE startAngle( aStart - aCenter );
|
||||
EDA_ANGLE endAngle( aEnd - aCenter );
|
||||
int radius = ( aStart - aCenter ).EuclideanNorm();
|
||||
// Recalculate aCenter using double to be sure we will use a exact value, from aStart and aEnd
|
||||
// it must be on the line passing by the middle of segment {aStart, aEnd}
|
||||
// To simplify calculations, use aStart as origin in intermediate calculations
|
||||
VECTOR2D center = aCenter - aStart;
|
||||
VECTOR2D end = aEnd - aStart;
|
||||
EDA_ANGLE segAngle( end );
|
||||
|
||||
// Rotate end and center, to make segment {aStart, aEnd} horizontal
|
||||
RotatePoint( end, segAngle );
|
||||
RotatePoint( center, segAngle );
|
||||
|
||||
// center.x must be at end.x/2 coordinate
|
||||
center.x = end.x / 2;
|
||||
|
||||
// Now calculate the right center position
|
||||
RotatePoint( center, -segAngle );
|
||||
center += aStart;
|
||||
|
||||
EDA_ANGLE startAngle( VECTOR2D( aStart ) - center );
|
||||
EDA_ANGLE endAngle( VECTOR2D( aEnd ) - center );
|
||||
double radius = ( VECTOR2D( aStart ) - center ).EuclideanNorm();
|
||||
|
||||
if( startAngle > endAngle )
|
||||
{
|
||||
@@ -168,12 +186,12 @@ void PLOTTER::Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, const VECTOR
|
||||
startAngle = -startAngle;
|
||||
endAngle = -endAngle;
|
||||
|
||||
Arc( aCenter, startAngle, endAngle, radius, aFill, aWidth );
|
||||
Arc( center, startAngle, endAngle, radius, aFill, aWidth );
|
||||
}
|
||||
|
||||
|
||||
void PLOTTER::Arc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, int aRadius, FILL_T aFill, int aWidth )
|
||||
void PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill, int aWidth )
|
||||
{
|
||||
EDA_ANGLE startAngle( aStartAngle );
|
||||
EDA_ANGLE endAngle( aEndAngle );
|
||||
@@ -570,8 +588,8 @@ void PLOTTER::ThickSegment( const VECTOR2I& start, const VECTOR2I& end, int widt
|
||||
}
|
||||
|
||||
|
||||
void PLOTTER::ThickArc( const VECTOR2I& centre, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, int aRadius, int aWidth,
|
||||
void PLOTTER::ThickArc( const VECTOR2D& centre, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, double aRadius, int aWidth,
|
||||
OUTLINE_MODE aTraceMode, void* aData )
|
||||
{
|
||||
if( aTraceMode == FILLED )
|
||||
|
||||
@@ -569,9 +569,42 @@ bool PROJECT_FILE::SaveToFile( const wxString& aDirectory, bool aForce )
|
||||
|
||||
bool PROJECT_FILE::SaveAs( const wxString& aDirectory, const wxString& aFile )
|
||||
{
|
||||
wxFileName oldFilename( GetFilename() );
|
||||
wxString oldProjectName = oldFilename.GetName();
|
||||
wxString oldProjectPath = oldFilename.GetPath();
|
||||
|
||||
Set( "meta.filename", aFile + "." + ProjectFileExtension );
|
||||
SetFilename( aFile );
|
||||
|
||||
auto updatePath =
|
||||
[&]( wxString& aPath )
|
||||
{
|
||||
if( aPath.StartsWith( oldProjectName + wxS( "." ) ) )
|
||||
aPath.Replace( oldProjectName, aFile, false );
|
||||
else if( aPath.StartsWith( oldProjectPath + wxS( "/" ) ) )
|
||||
aPath.Replace( oldProjectPath, aDirectory, false );
|
||||
};
|
||||
|
||||
updatePath( m_BoardDrawingSheetFile );
|
||||
|
||||
for( int ii = LAST_PATH_FIRST; ii < (int) LAST_PATH_SIZE; ++ii )
|
||||
updatePath( m_PcbLastPath[ ii ] );
|
||||
|
||||
auto updatePathByPtr =
|
||||
[&]( const std::string& aPtr )
|
||||
{
|
||||
if( std::optional<wxString> path = Get<wxString>( aPtr ) )
|
||||
{
|
||||
updatePath( path.value() );
|
||||
Set( aPtr, path.value() );
|
||||
}
|
||||
};
|
||||
|
||||
updatePathByPtr( "schematic.page_layout_descr_file" );
|
||||
updatePathByPtr( "schematic.plot_directory" );
|
||||
updatePathByPtr( "schematic.ngspice.workbook_filename" );
|
||||
updatePathByPtr( "pcbnew.page_layout_descr_file" );
|
||||
|
||||
// While performing Save As, we have already checked that we can write to the directory
|
||||
// so don't carry the previous flag
|
||||
SetReadOnly( false );
|
||||
|
||||
+2
-1
@@ -63,7 +63,8 @@ void RC_ITEM::SetItems( const EDA_ITEM* aItem, const EDA_ITEM* bItem,
|
||||
{
|
||||
m_ids.clear();
|
||||
|
||||
m_ids.push_back( aItem->m_Uuid );
|
||||
if( aItem )
|
||||
m_ids.push_back( aItem->m_Uuid );
|
||||
|
||||
if( bItem )
|
||||
m_ids.push_back( bItem->m_Uuid );
|
||||
|
||||
+10
-28
@@ -48,35 +48,17 @@
|
||||
|
||||
static int vprint( std::string* result, const char* format, va_list ap )
|
||||
{
|
||||
char msg[512];
|
||||
// This function can call vsnprintf twice.
|
||||
// But internally, vsnprintf retrieves arguments from the va_list identified by arg as if
|
||||
// va_arg was used on it, and thus the state of the va_list is likely to be altered by the call.
|
||||
// see: www.cplusplus.com/reference/cstdio/vsnprintf
|
||||
// we make a copy of va_list ap for the second call, if happens
|
||||
va_list tmp;
|
||||
va_copy( tmp, ap );
|
||||
size_t len = vsnprintf( nullptr, 0, format, tmp );
|
||||
va_end( tmp );
|
||||
|
||||
size_t len = vsnprintf( msg, sizeof(msg), format, ap );
|
||||
// Resize the output to hold the required data
|
||||
size_t size = result->size();
|
||||
result->resize( size + len );
|
||||
|
||||
if( len < sizeof(msg) ) // the output fit into msg
|
||||
{
|
||||
result->append( msg, msg + len );
|
||||
}
|
||||
else
|
||||
{
|
||||
// output was too big, so now incur the expense of allocating
|
||||
// a buf for holding suffient characters.
|
||||
|
||||
std::vector<char> buf;
|
||||
buf.reserve( len+1 ); // reserve(), not resize() which writes. +1 for trailing nul.
|
||||
|
||||
len = vsnprintf( &buf[0], len+1, format, tmp );
|
||||
|
||||
result->append( &buf[0], &buf[0] + len );
|
||||
}
|
||||
|
||||
va_end( tmp ); // Release the temporary va_list, initialised from ap
|
||||
// Now do the actual printing
|
||||
len = vsnprintf( result->data() + size, len + 1, format, ap );
|
||||
|
||||
return len;
|
||||
}
|
||||
@@ -443,18 +425,18 @@ int OUTPUTFORMATTER::vprint( const char* fmt, va_list ap )
|
||||
// we make a copy of va_list ap for the second call, if happens
|
||||
va_list tmp;
|
||||
va_copy( tmp, ap );
|
||||
int ret = vsnprintf( &m_buffer[0], m_buffer.size(), fmt, ap );
|
||||
int ret = vsnprintf( m_buffer.data(), m_buffer.size(), fmt, ap );
|
||||
|
||||
if( ret >= (int) m_buffer.size() )
|
||||
{
|
||||
m_buffer.resize( ret + 1000 );
|
||||
ret = vsnprintf( &m_buffer[0], m_buffer.size(), fmt, tmp );
|
||||
ret = vsnprintf( m_buffer.data(), m_buffer.size(), fmt, tmp );
|
||||
}
|
||||
|
||||
va_end( tmp ); // Release the temporary va_list, initialised from ap
|
||||
|
||||
if( ret > 0 )
|
||||
write( &m_buffer[0], ret );
|
||||
write( m_buffer.data(), ret );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,15 @@
|
||||
using namespace STROKEPARAMS_T;
|
||||
|
||||
|
||||
const std::map<PLOT_DASH_TYPE, struct lineTypeStruct> lineTypeNames = {
|
||||
{ PLOT_DASH_TYPE::SOLID, { _( "Solid" ), BITMAPS::stroke_solid } },
|
||||
{ PLOT_DASH_TYPE::DASH, { _( "Dashed" ), BITMAPS::stroke_dash } },
|
||||
{ PLOT_DASH_TYPE::DOT, { _( "Dotted" ), BITMAPS::stroke_dot } },
|
||||
{ PLOT_DASH_TYPE::DASHDOT, { _( "Dash-Dot" ), BITMAPS::stroke_dashdot } },
|
||||
{ PLOT_DASH_TYPE::DASHDOTDOT, { _( "Dash-Dot-Dot" ), BITMAPS::stroke_dashdotdot } }
|
||||
};
|
||||
|
||||
|
||||
void STROKE_PARAMS::Stroke( const SHAPE* aShape, PLOT_DASH_TYPE aLineStyle, int aWidth,
|
||||
const KIGFX::RENDER_SETTINGS* aRenderSettings,
|
||||
std::function<void( const VECTOR2I& a, const VECTOR2I& b )> aStroker )
|
||||
|
||||
@@ -80,6 +80,20 @@ principle should be easily implemented by adapting the current STL containers.
|
||||
%ignore to_json;
|
||||
%ignore from_json;
|
||||
|
||||
%rename(GetEffectiveTextShapeNative) EDA_TEXT::GetEffectiveTextShape;
|
||||
|
||||
%extend EDA_TEXT
|
||||
{
|
||||
%pythoncode
|
||||
%{
|
||||
|
||||
# KiCad 7.0 API Compatibility
|
||||
def GetEffectiveTextShape(self, aTriangulate=True, aUseTextRotation=True):
|
||||
return self.GetEffectiveTextShapeNative(aTriangulate)
|
||||
|
||||
%}
|
||||
}
|
||||
|
||||
// headers/imports that must be included in the _wrapper.cpp at top
|
||||
|
||||
%{
|
||||
|
||||
@@ -59,6 +59,10 @@ ACTION_MENU::ACTION_MENU( bool isContextMenu, TOOL_INTERACTIVE* aTool ) :
|
||||
|
||||
ACTION_MENU::~ACTION_MENU()
|
||||
{
|
||||
Disconnect( wxEVT_COMMAND_MENU_SELECTED, wxMenuEventHandler( ACTION_MENU::OnMenuEvent ),
|
||||
nullptr, this );
|
||||
Disconnect( wxEVT_IDLE, wxIdleEventHandler( ACTION_MENU::OnIdle ), nullptr, this );
|
||||
|
||||
// Set parent to NULL to prevent submenus from unregistering from a nonexistent object
|
||||
for( ACTION_MENU* menu : m_submenus )
|
||||
menu->SetParent( nullptr );
|
||||
|
||||
@@ -697,3 +697,8 @@ const TOOL_EVENT EVENTS::InhibitSelectionEditing( TC_MESSAGE, TA_ACTION, "common
|
||||
const TOOL_EVENT EVENTS::UninhibitSelectionEditing( TC_MESSAGE, TA_ACTION, "common.Interactive.uninhibit" );
|
||||
|
||||
const TOOL_EVENT EVENTS::DisambiguatePoint( TC_MESSAGE, TA_ACTION, "common.Interactive.disambiguate" );
|
||||
|
||||
// System-wide undo/redo Events
|
||||
|
||||
const TOOL_EVENT EVENTS::UndoRedoPreEvent( TC_MESSAGE, TA_UNDO_REDO_POST, AS_GLOBAL );
|
||||
const TOOL_EVENT EVENTS::UndoRedoPostEvent( TC_MESSAGE, TA_UNDO_REDO_POST, AS_GLOBAL );
|
||||
|
||||
@@ -305,9 +305,15 @@ int COMMON_TOOLS::doZoomFit( ZOOM_FIT_TYPE_T aFitType )
|
||||
// Currently "Zoom to Objects" is only supported in Eeschema & Pcbnew. Support for other
|
||||
// programs in the suite can be added as needed.
|
||||
|
||||
if( aFitType == ZOOM_FIT_ALL )
|
||||
{
|
||||
if( frame->IsType( FRAME_PCB_EDITOR ) )
|
||||
bBox = m_frame->GetDocumentExtents( false );
|
||||
}
|
||||
|
||||
if( aFitType == ZOOM_FIT_OBJECTS )
|
||||
{
|
||||
if( frame->IsType( FRAME_SCH ) || frame->IsType( FRAME_PCB_EDITOR ) )
|
||||
if( frame->IsType( FRAME_SCH ) )
|
||||
bBox = m_frame->GetDocumentExtents( false );
|
||||
else
|
||||
aFitType = ZOOM_FIT_ALL; // Just do a "Zoom to Fit" for unsupported editors
|
||||
@@ -327,6 +333,7 @@ int COMMON_TOOLS::doZoomFit( ZOOM_FIT_TYPE_T aFitType )
|
||||
if( !std::isfinite( scale ) )
|
||||
{
|
||||
view->SetCenter( VECTOR2D( 0, 0 ) );
|
||||
canvas->Refresh();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -355,6 +362,7 @@ int COMMON_TOOLS::doZoomFit( ZOOM_FIT_TYPE_T aFitType )
|
||||
|
||||
view->SetScale( scale / margin_scale_factor );
|
||||
view->SetCenter( bBox.Centre() );
|
||||
canvas->Refresh();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -374,6 +382,7 @@ int COMMON_TOOLS::CenterContents( const TOOL_EVENT& aEvent )
|
||||
VECTOR2D scrollbarSize = VECTOR2D( canvas->GetSize() - canvas->GetClientSize() );
|
||||
VECTOR2D worldScrollbarSize = getView()->ToWorld( scrollbarSize, false );
|
||||
getView()->SetCenter( getView()->GetCenter() + worldScrollbarSize / 2.0 );
|
||||
canvas->Refresh();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -415,6 +424,8 @@ int COMMON_TOOLS::doZoomToPreset( int idx, bool aCenterOnCursor )
|
||||
getView()->SetScale( scale );
|
||||
}
|
||||
|
||||
m_frame->GetCanvas()->Refresh();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -521,7 +521,7 @@ void VIEW::SetViewport( const BOX2D& aViewport )
|
||||
{
|
||||
VECTOR2D ssize = ToWorld( m_gal->GetScreenPixelSize(), false );
|
||||
|
||||
wxCHECK( ssize.x > 0 && ssize.y > 0, /*void*/ );
|
||||
wxCHECK( fabs(ssize.x) > 0 && fabs(ssize.y) > 0, /*void*/ );
|
||||
|
||||
VECTOR2D centre = aViewport.Centre();
|
||||
VECTOR2D vsize = aViewport.GetSize();
|
||||
|
||||
@@ -21,17 +21,6 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/choice.h>
|
||||
#include <wx/radiobox.h>
|
||||
#include <wx/spinctrl.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/statbox.h>
|
||||
#include <wx/statline.h>
|
||||
|
||||
#include <ignore.h>
|
||||
#include <widgets/gal_options_panel.h>
|
||||
#include <settings/app_settings.h>
|
||||
#include <eda_draw_frame.h>
|
||||
@@ -45,9 +34,9 @@ static const double gridThicknessMin = 1.0;
|
||||
static const double gridThicknessMax = 10.0;
|
||||
static const double gridThicknessStep = 0.5;
|
||||
|
||||
static const double gridMinSpacingMin = 5;
|
||||
static const double gridMinSpacingMax = 200;
|
||||
static const double gridMinSpacingStep = 5;
|
||||
static const int gridMinSpacingMin = 5;
|
||||
static const int gridMinSpacingMax = 200;
|
||||
static const int gridMinSpacingStep = 5;
|
||||
|
||||
|
||||
///TODO: These are duplicated in gal_display_options - Unify!
|
||||
@@ -68,153 +57,35 @@ static const UTIL::CFG_MAP<KIGFX::GRID_SNAPPING> gridSnapConfigVals =
|
||||
|
||||
|
||||
GAL_OPTIONS_PANEL::GAL_OPTIONS_PANEL( wxWindow* aParent, APP_SETTINGS_BASE* aAppSettings ) :
|
||||
wxPanel( aParent, wxID_ANY ),
|
||||
GAL_OPTIONS_PANEL_BASE( aParent ),
|
||||
m_cfg( aAppSettings )
|
||||
{
|
||||
// the main sizer that holds "columns" of settings
|
||||
m_mainSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
SetSizer( m_mainSizer );
|
||||
|
||||
// second-level sizers that are one "column" of settings each
|
||||
wxBoxSizer* sLeftSizer = new wxBoxSizer( wxVERTICAL );
|
||||
m_mainSizer->Add( sLeftSizer, 1, wxRIGHT | wxBOTTOM | wxEXPAND, 5 );
|
||||
|
||||
/*
|
||||
* Rendering engine
|
||||
*/
|
||||
#ifndef __WXMAC__
|
||||
{
|
||||
wxString engineChoices[] = { _( "Accelerated graphics" ), _( "Fallback graphics" ) };
|
||||
m_renderingEngine = new wxRadioBox( this, wxID_ANY, _( "Rendering Engine" ),
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
sizeof( engineChoices ) / sizeof( wxString ),
|
||||
engineChoices, 1, wxRA_SPECIFY_COLS );
|
||||
m_renderingEngine->SetItemToolTip( 0, _( "Hardware-accelerated graphics (recommended)" ) );
|
||||
m_renderingEngine->SetItemToolTip( 1, _( "Software graphics (for computers which do not "
|
||||
"support KiCad's hardware acceleration "
|
||||
"requirements)" ) );
|
||||
|
||||
sLeftSizer->Add( m_renderingEngine, 0, wxTOP | wxBOTTOM | wxRIGHT | wxEXPAND, 5 );
|
||||
}
|
||||
// Rendering engine
|
||||
#ifdef __WXMAC__
|
||||
// On MAC, Cairo render does not work.
|
||||
m_renderingEngine->Hide();
|
||||
#endif
|
||||
m_renderingEngine->SetItemToolTip( 0, _( "Hardware-accelerated graphics (recommended)" ) );
|
||||
m_renderingEngine->SetItemToolTip( 1, _( "Software graphics (for computers which do not "
|
||||
"support KiCad's hardware acceleration "
|
||||
"requirements)" ) );
|
||||
|
||||
/*
|
||||
* Grid settings subpanel
|
||||
*/
|
||||
// Grid settings subpanel
|
||||
int selection = 0; // default selection
|
||||
|
||||
for( double size = gridThicknessMin; size <= gridThicknessMax; size += gridThicknessStep )
|
||||
{
|
||||
wxStaticText* gridLabel = new wxStaticText( this, wxID_ANY, _( "Grid Options" ) );
|
||||
sLeftSizer->Add( gridLabel, 0, wxTOP|wxRIGHT|wxLEFT|wxEXPAND, 13 );
|
||||
m_gridThicknessList.push_back( size );
|
||||
m_gridLineWidth->Append( wxString::Format( wxT( "%.1f" ), size ) );
|
||||
|
||||
wxStaticLine* staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition,
|
||||
wxDefaultSize, wxLI_HORIZONTAL );
|
||||
sLeftSizer->Add( staticline1, 0, wxEXPAND|wxBOTTOM, 5 );
|
||||
|
||||
wxBoxSizer* sGridSettings = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxString m_gridStyleChoices[] = {
|
||||
_( "Dots" ),
|
||||
_( "Lines" ),
|
||||
_( "Small crosses" )
|
||||
};
|
||||
|
||||
int m_gridStyleNChoices = sizeof( m_gridStyleChoices ) / sizeof( wxString );
|
||||
m_gridStyle = new wxRadioBox( this, wxID_ANY, _( "Grid Style" ), wxDefaultPosition,
|
||||
wxDefaultSize, m_gridStyleNChoices, m_gridStyleChoices, 1,
|
||||
wxRA_SPECIFY_COLS );
|
||||
sGridSettings->Add( m_gridStyle, 0, wxALL | wxEXPAND, 5 );
|
||||
|
||||
wxFlexGridSizer* sGridSettingsGrid;
|
||||
sGridSettingsGrid = new wxFlexGridSizer( 0, 3, 0, 0 );
|
||||
sGridSettingsGrid->AddGrowableCol( 1 );
|
||||
sGridSettingsGrid->SetFlexibleDirection( wxBOTH );
|
||||
sGridSettingsGrid->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
l_gridLineWidth = new wxStaticText( this, wxID_ANY, _( "Grid thickness:" ) );
|
||||
l_gridLineWidth->Wrap( -1 );
|
||||
sGridSettingsGrid->Add( l_gridLineWidth, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT | wxTOP, 5 );
|
||||
|
||||
m_gridLineWidth = new wxSpinCtrlDouble( this, wxID_ANY );
|
||||
m_gridLineWidth->SetRange( gridThicknessMin, gridThicknessMax );
|
||||
m_gridLineWidth->SetIncrement( gridThicknessStep );
|
||||
m_gridLineWidth->SetDigits( 1 );
|
||||
sGridSettingsGrid->Add( m_gridLineWidth, 0, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxTOP, 5 );
|
||||
|
||||
l_gridLineWidthUnits = new wxStaticText( this, wxID_ANY, _( "px" ) );
|
||||
l_gridLineWidthUnits->Wrap( -1 );
|
||||
sGridSettingsGrid->Add( l_gridLineWidthUnits, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT | wxLEFT | wxTOP, 5 );
|
||||
|
||||
l_gridMinSpacing = new wxStaticText( this, wxID_ANY, _( "Min grid spacing:" ) );
|
||||
l_gridMinSpacing->Wrap( -1 );
|
||||
sGridSettingsGrid->Add( l_gridMinSpacing, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT | wxTOP, 5 );
|
||||
|
||||
m_gridMinSpacing = new wxSpinCtrlDouble( this, wxID_ANY);
|
||||
m_gridMinSpacing->SetRange( gridMinSpacingMin, gridMinSpacingMax );
|
||||
m_gridMinSpacing->SetIncrement( gridMinSpacingStep );
|
||||
m_gridMinSpacing->SetDigits( 0 );
|
||||
sGridSettingsGrid->Add( m_gridMinSpacing, 0, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxTOP, 5 );
|
||||
|
||||
l_gridMinSpacingUnits = new wxStaticText( this, wxID_ANY, _( "px" ) );
|
||||
l_gridMinSpacingUnits->Wrap( -1 );
|
||||
sGridSettingsGrid->Add( l_gridMinSpacingUnits, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT | wxLEFT | wxTOP, 5 );
|
||||
|
||||
l_gridSnapOptions = new wxStaticText( this, wxID_ANY, _( "Snap to Grid:" ) );
|
||||
l_gridSnapOptions->Wrap( -1 );
|
||||
sGridSettingsGrid->Add( l_gridSnapOptions, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT | wxTOP, 5 );
|
||||
|
||||
wxString gridSnapChoices[] = { _( "Always" ), _( "When grid shown" ), _( "Never" ) };
|
||||
int gridSnapNChoices = sizeof( gridSnapChoices ) / sizeof( wxString );
|
||||
m_gridSnapOptions = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
||||
gridSnapNChoices, gridSnapChoices );
|
||||
m_gridSnapOptions->Select( 0 );
|
||||
sGridSettingsGrid->Add( m_gridSnapOptions, 0,
|
||||
wxALIGN_CENTER_VERTICAL | wxEXPAND | wxTOP | wxBOTTOM, 5 );
|
||||
|
||||
l_gridSnapSpace = new wxStaticText( this, wxID_ANY, _( "px" ) );
|
||||
l_gridSnapSpace->Wrap( -1 );
|
||||
l_gridSnapSpace->Hide();
|
||||
sGridSettingsGrid->Add( l_gridSnapSpace, 0,
|
||||
wxALIGN_CENTER_VERTICAL | wxALL | wxRESERVE_SPACE_EVEN_IF_HIDDEN,
|
||||
5 );
|
||||
|
||||
|
||||
sGridSettings->Add( sGridSettingsGrid, 1, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 5 );
|
||||
|
||||
sLeftSizer->Add( sGridSettings, 0, wxEXPAND|wxLEFT, 5 );
|
||||
if( m_cfg->m_Window.grid.line_width == size )
|
||||
selection = m_gridLineWidth->GetCount() - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cursor settings subpanel
|
||||
*/
|
||||
{
|
||||
sLeftSizer->Add( 0, 15, 0, wxEXPAND, 5 );
|
||||
m_gridLineWidth->SetSelection( selection );
|
||||
|
||||
wxStaticText* gridLabel = new wxStaticText( this, wxID_ANY, _( "Cursor Options" ) );
|
||||
sLeftSizer->Add( gridLabel, 0, wxTOP|wxRIGHT|wxLEFT|wxEXPAND, 13 );
|
||||
|
||||
wxStaticLine* staticline2 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition,
|
||||
wxDefaultSize, wxLI_HORIZONTAL );
|
||||
sLeftSizer->Add( staticline2, 0, wxEXPAND|wxBOTTOM, 5 );
|
||||
|
||||
wxBoxSizer* sCursorSettings = new wxBoxSizer( wxVERTICAL );
|
||||
sLeftSizer->Add( sCursorSettings, 0, wxEXPAND|wxLEFT, 5 );
|
||||
|
||||
wxString m_CursorShapeChoices[] = {
|
||||
_( "Small crosshair" ),
|
||||
_( "Full window crosshair" )
|
||||
};
|
||||
|
||||
int m_CursorShapeNChoices = sizeof( m_CursorShapeChoices ) / sizeof( wxString );
|
||||
m_cursorShape = new wxRadioBox( this, wxID_ANY, _( "Cursor Shape" ), wxDefaultPosition,
|
||||
wxDefaultSize, m_CursorShapeNChoices, m_CursorShapeChoices,
|
||||
1, wxRA_SPECIFY_COLS );
|
||||
|
||||
m_cursorShape->SetSelection( 0 );
|
||||
m_cursorShape->SetToolTip( _( "Cursor shape for drawing, placement and movement tools" ) );
|
||||
sCursorSettings->Add( m_cursorShape, 0, wxALL | wxEXPAND, 5 );
|
||||
|
||||
m_forceCursorDisplay = new wxCheckBox( this, wxID_ANY, _( "Always show crosshairs" ) );
|
||||
sCursorSettings->Add( m_forceCursorDisplay, 0, wxALL | wxEXPAND, 5 );
|
||||
}
|
||||
m_gridMinSpacing->SetRange( gridMinSpacingMin, gridMinSpacingMax );
|
||||
m_gridMinSpacing->SetIncrement( gridMinSpacingStep );
|
||||
}
|
||||
|
||||
|
||||
@@ -231,7 +102,7 @@ bool GAL_OPTIONS_PANEL::TransferDataToWindow()
|
||||
|
||||
m_gridSnapOptions->SetSelection( m_cfg->m_Window.grid.snap );
|
||||
m_gridStyle->SetSelection( m_cfg->m_Window.grid.style );
|
||||
m_gridLineWidth->SetValue( m_cfg->m_Window.grid.line_width );
|
||||
|
||||
m_gridMinSpacing->SetValue( m_cfg->m_Window.grid.min_spacing );
|
||||
|
||||
m_cursorShape->SetSelection( m_cfg->m_Window.cursor.fullscreen_cursor );
|
||||
@@ -245,7 +116,10 @@ bool GAL_OPTIONS_PANEL::TransferDataFromWindow()
|
||||
{
|
||||
m_cfg->m_Window.grid.snap = m_gridSnapOptions->GetSelection();
|
||||
m_cfg->m_Window.grid.style = m_gridStyle->GetSelection();
|
||||
m_cfg->m_Window.grid.line_width = m_gridLineWidth->GetValue();
|
||||
|
||||
if( m_gridLineWidth->GetSelection() >= 0 )
|
||||
m_cfg->m_Window.grid.line_width = m_gridThicknessList[ m_gridLineWidth->GetSelection() ];
|
||||
|
||||
m_cfg->m_Window.grid.min_spacing = m_gridMinSpacing->GetValue();
|
||||
|
||||
m_cfg->m_Window.cursor.fullscreen_cursor = m_cursorShape->GetSelection();
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.0-39-g3487c3cb)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "gal_options_panel_base.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GAL_OPTIONS_PANEL_BASE::GAL_OPTIONS_PANEL_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
|
||||
{
|
||||
wxBoxSizer* mainSizer;
|
||||
mainSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxBoxSizer* sLeftSizer;
|
||||
sLeftSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxString m_renderingEngineChoices[] = { _("Accelerated graphics"), _("Fallback graphics") };
|
||||
int m_renderingEngineNChoices = sizeof( m_renderingEngineChoices ) / sizeof( wxString );
|
||||
m_renderingEngine = new wxRadioBox( this, wxID_ANY, _("Rendering Engine"), wxDefaultPosition, wxDefaultSize, m_renderingEngineNChoices, m_renderingEngineChoices, 1, wxRA_SPECIFY_COLS );
|
||||
m_renderingEngine->SetSelection( 0 );
|
||||
sLeftSizer->Add( m_renderingEngine, 0, wxALL, 5 );
|
||||
|
||||
|
||||
mainSizer->Add( sLeftSizer, 0, wxEXPAND, 5 );
|
||||
|
||||
m_staticText1 = new wxStaticText( this, wxID_ANY, _("Grid Options"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText1->Wrap( -1 );
|
||||
mainSizer->Add( m_staticText1, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
mainSizer->Add( m_staticline1, 0, wxEXPAND | wxALL, 5 );
|
||||
|
||||
wxString m_gridStyleChoices[] = { _("Dots"), _("Lines"), _("Small crosses") };
|
||||
int m_gridStyleNChoices = sizeof( m_gridStyleChoices ) / sizeof( wxString );
|
||||
m_gridStyle = new wxRadioBox( this, wxID_ANY, _("Grid Style"), wxDefaultPosition, wxDefaultSize, m_gridStyleNChoices, m_gridStyleChoices, 1, wxRA_SPECIFY_COLS );
|
||||
m_gridStyle->SetSelection( 0 );
|
||||
mainSizer->Add( m_gridStyle, 0, wxALL, 5 );
|
||||
|
||||
wxFlexGridSizer* fgGridSettingsGrid;
|
||||
fgGridSettingsGrid = new wxFlexGridSizer( 0, 3, 0, 0 );
|
||||
fgGridSettingsGrid->AddGrowableCol( 1 );
|
||||
fgGridSettingsGrid->SetFlexibleDirection( wxBOTH );
|
||||
fgGridSettingsGrid->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
l_gridLineWidth = new wxStaticText( this, wxID_ANY, _("Grid thickness:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
l_gridLineWidth->Wrap( -1 );
|
||||
fgGridSettingsGrid->Add( l_gridLineWidth, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
wxArrayString m_gridLineWidthChoices;
|
||||
m_gridLineWidth = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_gridLineWidthChoices, 0 );
|
||||
m_gridLineWidth->SetSelection( 0 );
|
||||
fgGridSettingsGrid->Add( m_gridLineWidth, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
l_gridLineWidthUnits = new wxStaticText( this, wxID_ANY, _("px"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
l_gridLineWidthUnits->Wrap( -1 );
|
||||
fgGridSettingsGrid->Add( l_gridLineWidthUnits, 0, wxALL, 5 );
|
||||
|
||||
l_gridMinSpacing = new wxStaticText( this, wxID_ANY, _("Min grid spacing:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
l_gridMinSpacing->Wrap( -1 );
|
||||
fgGridSettingsGrid->Add( l_gridMinSpacing, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_gridMinSpacing = new wxSpinCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 5, 200, 10 );
|
||||
fgGridSettingsGrid->Add( m_gridMinSpacing, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
l_gridMinSpacingUnits = new wxStaticText( this, wxID_ANY, _("px"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
l_gridMinSpacingUnits->Wrap( -1 );
|
||||
fgGridSettingsGrid->Add( l_gridMinSpacingUnits, 0, wxALL, 5 );
|
||||
|
||||
l_gridSnapOptions = new wxStaticText( this, wxID_ANY, _("Snap to grid:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
l_gridSnapOptions->Wrap( -1 );
|
||||
fgGridSettingsGrid->Add( l_gridSnapOptions, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
wxString m_gridSnapOptionsChoices[] = { _("Always"), _("When grid shown"), _("Never") };
|
||||
int m_gridSnapOptionsNChoices = sizeof( m_gridSnapOptionsChoices ) / sizeof( wxString );
|
||||
m_gridSnapOptions = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_gridSnapOptionsNChoices, m_gridSnapOptionsChoices, 0 );
|
||||
m_gridSnapOptions->SetSelection( 0 );
|
||||
fgGridSettingsGrid->Add( m_gridSnapOptions, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
fgGridSettingsGrid->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
mainSizer->Add( fgGridSettingsGrid, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
mainSizer->Add( 0, 15, 0, 0, 5 );
|
||||
|
||||
m_stGridLabel = new wxStaticText( this, wxID_ANY, _("Cursor Options"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_stGridLabel->Wrap( -1 );
|
||||
mainSizer->Add( m_stGridLabel, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_staticline2 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
mainSizer->Add( m_staticline2, 0, wxEXPAND | wxALL, 5 );
|
||||
|
||||
wxBoxSizer* sCursorSettings;
|
||||
sCursorSettings = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxString m_cursorShapeChoices[] = { _("Small crosshair"), _("Full window crosshair") };
|
||||
int m_cursorShapeNChoices = sizeof( m_cursorShapeChoices ) / sizeof( wxString );
|
||||
m_cursorShape = new wxRadioBox( this, wxID_ANY, _("Cursor Shape"), wxDefaultPosition, wxDefaultSize, m_cursorShapeNChoices, m_cursorShapeChoices, 1, wxRA_SPECIFY_COLS );
|
||||
m_cursorShape->SetSelection( 0 );
|
||||
m_cursorShape->SetToolTip( _("Cursor shape for drawing, placement and movement tools") );
|
||||
|
||||
sCursorSettings->Add( m_cursorShape, 0, wxALL, 5 );
|
||||
|
||||
m_forceCursorDisplay = new wxCheckBox( this, wxID_ANY, _("Always show crosshairs"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
sCursorSettings->Add( m_forceCursorDisplay, 0, wxALL, 5 );
|
||||
|
||||
|
||||
mainSizer->Add( sCursorSettings, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
this->SetSizer( mainSizer );
|
||||
this->Layout();
|
||||
}
|
||||
|
||||
GAL_OPTIONS_PANEL_BASE::~GAL_OPTIONS_PANEL_BASE()
|
||||
{
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,62 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.0-39-g3487c3cb)
|
||||
// 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>
|
||||
#include <wx/string.h>
|
||||
#include <wx/radiobox.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/statline.h>
|
||||
#include <wx/choice.h>
|
||||
#include <wx/spinctrl.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/panel.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class GAL_OPTIONS_PANEL_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class GAL_OPTIONS_PANEL_BASE : public wxPanel
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxRadioBox* m_renderingEngine;
|
||||
wxStaticText* m_staticText1;
|
||||
wxStaticLine* m_staticline1;
|
||||
wxRadioBox* m_gridStyle;
|
||||
wxStaticText* l_gridLineWidth;
|
||||
wxChoice* m_gridLineWidth;
|
||||
wxStaticText* l_gridLineWidthUnits;
|
||||
wxStaticText* l_gridMinSpacing;
|
||||
wxSpinCtrl* m_gridMinSpacing;
|
||||
wxStaticText* l_gridMinSpacingUnits;
|
||||
wxStaticText* l_gridSnapOptions;
|
||||
wxChoice* m_gridSnapOptions;
|
||||
wxStaticText* m_stGridLabel;
|
||||
wxStaticLine* m_staticline2;
|
||||
wxRadioBox* m_cursorShape;
|
||||
wxCheckBox* m_forceCursorDisplay;
|
||||
|
||||
public:
|
||||
|
||||
GAL_OPTIONS_PANEL_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 387,523 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||
|
||||
~GAL_OPTIONS_PANEL_BASE();
|
||||
|
||||
};
|
||||
|
||||
@@ -66,8 +66,11 @@ UNIT_BINDER::UNIT_BINDER( UNITS_PROVIDER* aUnitsProvider, wxWindow* aEventSource
|
||||
if( textEntry )
|
||||
{
|
||||
wxClientDC dc( m_valueCtrl );
|
||||
|
||||
// Gives enough room to display a value in inches i )n textEntry
|
||||
// 4 digits + '.' + 10 digits + 2 chars (units) look enough.
|
||||
wxSize minSize = m_valueCtrl->GetMinSize();
|
||||
int minWidth = dc.GetTextExtent( wxT( "XXX.XXXXXXX" ) ).GetWidth();
|
||||
int minWidth = dc.GetTextExtent( wxT( "XXXX.XXXXXXXXXXUU" ) ).GetWidth();
|
||||
|
||||
if( minSize.GetWidth() < minWidth )
|
||||
m_valueCtrl->SetMinSize( wxSize( minWidth, minSize.GetHeight() ) );
|
||||
|
||||
+219
-170
@@ -55,7 +55,7 @@
|
||||
* Flag to enable connectivity profiling
|
||||
* @ingroup trace_env_vars
|
||||
*/
|
||||
static const wxChar ConnProfileMask[] = wxT( "CONN_PROFILE" );
|
||||
static const wxChar DanglingProfileMask[] = wxT( "CONN_PROFILE" );
|
||||
|
||||
/*
|
||||
* Flag to enable connectivity tracing
|
||||
@@ -64,11 +64,72 @@ static const wxChar ConnProfileMask[] = wxT( "CONN_PROFILE" );
|
||||
static const wxChar ConnTrace[] = wxT( "CONN" );
|
||||
|
||||
|
||||
void CONNECTION_SUBGRAPH::RemoveItem( SCH_ITEM* aItem )
|
||||
{
|
||||
m_items.erase( aItem );
|
||||
m_drivers.erase( aItem );
|
||||
|
||||
if( aItem == m_driver )
|
||||
{
|
||||
m_driver = nullptr;
|
||||
m_driver_connection = nullptr;
|
||||
}
|
||||
|
||||
if( aItem->Type() == SCH_SHEET_PIN_T )
|
||||
m_hier_pins.erase( static_cast<SCH_SHEET_PIN*>( aItem ) );
|
||||
|
||||
if( aItem->Type() == SCH_HIER_LABEL_T )
|
||||
m_hier_ports.erase( static_cast<SCH_HIERLABEL*>( aItem ) );
|
||||
}
|
||||
|
||||
|
||||
bool CONNECTION_SUBGRAPH::ResolveDrivers( bool aCheckMultipleDrivers )
|
||||
{
|
||||
PRIORITY highest_priority = PRIORITY::INVALID;
|
||||
std::vector<SCH_ITEM*> candidates;
|
||||
std::vector<SCH_ITEM*> strong_drivers;
|
||||
auto candidate_cmp = [&]( SCH_ITEM* a, SCH_ITEM* b ) -> bool
|
||||
{
|
||||
// meet irreflexive requirements of std::sort
|
||||
if( a == b )
|
||||
return false;
|
||||
|
||||
SCH_CONNECTION* ac = a->Connection( &m_sheet );
|
||||
SCH_CONNECTION* bc = b->Connection( &m_sheet );
|
||||
|
||||
// Ensure we don't pick the subset over the superset
|
||||
if( ac->IsBus() && bc->IsBus() )
|
||||
return bc->IsSubsetOf( ac );
|
||||
|
||||
// Ensure we don't pick a hidden power pin on a regular symbol over
|
||||
// one on a power symbol
|
||||
if( a->Type() == SCH_PIN_T && b->Type() == SCH_PIN_T )
|
||||
{
|
||||
SCH_PIN* pa = static_cast<SCH_PIN*>( a );
|
||||
SCH_PIN* pb = static_cast<SCH_PIN*>( b );
|
||||
|
||||
bool aPower = pa->GetLibPin()->GetParent()->IsPower();
|
||||
bool bPower = pb->GetLibPin()->GetParent()->IsPower();
|
||||
|
||||
if( aPower && !bPower )
|
||||
return true;
|
||||
else if( bPower && !aPower )
|
||||
return false;
|
||||
}
|
||||
|
||||
const wxString& a_name = GetNameForDriver( a );
|
||||
const wxString& b_name = GetNameForDriver( b );
|
||||
bool a_lowQualityName = a_name.Contains( "-Pad" );
|
||||
bool b_lowQualityName = b_name.Contains( "-Pad" );
|
||||
|
||||
if( a_lowQualityName && !b_lowQualityName )
|
||||
return false;
|
||||
else if( b_lowQualityName && !a_lowQualityName )
|
||||
return true;
|
||||
else
|
||||
return a_name < b_name;
|
||||
};
|
||||
|
||||
PRIORITY highest_priority = PRIORITY::INVALID;
|
||||
std::set<SCH_ITEM*, decltype( candidate_cmp )> candidates( candidate_cmp );
|
||||
std::set<SCH_ITEM*> strong_drivers;
|
||||
|
||||
m_driver = nullptr;
|
||||
|
||||
@@ -88,17 +149,17 @@ bool CONNECTION_SUBGRAPH::ResolveDrivers( bool aCheckMultipleDrivers )
|
||||
continue;
|
||||
|
||||
if( item_priority >= PRIORITY::HIER_LABEL )
|
||||
strong_drivers.push_back( item );
|
||||
strong_drivers.insert( item );
|
||||
|
||||
if( item_priority > highest_priority )
|
||||
{
|
||||
candidates.clear();
|
||||
candidates.push_back( item );
|
||||
candidates.insert( item );
|
||||
highest_priority = item_priority;
|
||||
}
|
||||
else if( !candidates.empty() && ( item_priority == highest_priority ) )
|
||||
{
|
||||
candidates.push_back( item );
|
||||
candidates.insert( item );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,56 +189,10 @@ bool CONNECTION_SUBGRAPH::ResolveDrivers( bool aCheckMultipleDrivers )
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// For all other driver types, sort by quality of name
|
||||
std::sort( candidates.begin(), candidates.end(),
|
||||
[&]( SCH_ITEM* a, SCH_ITEM* b ) -> bool
|
||||
{
|
||||
// meet irreflexive requirements of std::sort
|
||||
if( a == b )
|
||||
return false;
|
||||
|
||||
SCH_CONNECTION* ac = a->Connection( &m_sheet );
|
||||
SCH_CONNECTION* bc = b->Connection( &m_sheet );
|
||||
|
||||
// Ensure we don't pick the subset over the superset
|
||||
if( ac->IsBus() && bc->IsBus() )
|
||||
return bc->IsSubsetOf( ac );
|
||||
|
||||
// Ensure we don't pick a hidden power pin on a regular symbol over
|
||||
// one on a power symbol
|
||||
if( a->Type() == SCH_PIN_T && b->Type() == SCH_PIN_T )
|
||||
{
|
||||
SCH_PIN* pa = static_cast<SCH_PIN*>( a );
|
||||
SCH_PIN* pb = static_cast<SCH_PIN*>( b );
|
||||
|
||||
bool aPower = pa->GetLibPin()->GetParent()->IsPower();
|
||||
bool bPower = pb->GetLibPin()->GetParent()->IsPower();
|
||||
|
||||
if( aPower && !bPower )
|
||||
return true;
|
||||
else if( bPower && !aPower )
|
||||
return false;
|
||||
}
|
||||
|
||||
const wxString& a_name = GetNameForDriver( a );
|
||||
const wxString& b_name = GetNameForDriver( b );
|
||||
bool a_lowQualityName = a_name.Contains( "-Pad" );
|
||||
bool b_lowQualityName = b_name.Contains( "-Pad" );
|
||||
|
||||
if( a_lowQualityName && !b_lowQualityName )
|
||||
return false;
|
||||
else if( b_lowQualityName && !a_lowQualityName )
|
||||
return true;
|
||||
else
|
||||
return a_name < b_name;
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
if( !m_driver )
|
||||
m_driver = candidates[0];
|
||||
m_driver = *candidates.begin();
|
||||
}
|
||||
|
||||
if( strong_drivers.size() > 1 )
|
||||
@@ -185,7 +200,10 @@ bool CONNECTION_SUBGRAPH::ResolveDrivers( bool aCheckMultipleDrivers )
|
||||
|
||||
// Drop weak drivers
|
||||
if( m_strong_driver )
|
||||
m_drivers = strong_drivers;
|
||||
{
|
||||
m_drivers.clear();
|
||||
m_drivers.insert( strong_drivers.begin(), strong_drivers.end() );
|
||||
}
|
||||
|
||||
// Cache driver connection
|
||||
if( m_driver )
|
||||
@@ -200,30 +218,6 @@ bool CONNECTION_SUBGRAPH::ResolveDrivers( bool aCheckMultipleDrivers )
|
||||
m_driver_connection = nullptr;
|
||||
}
|
||||
|
||||
if( aCheckMultipleDrivers && m_multiple_drivers )
|
||||
{
|
||||
// First check if all the candidates are actually the same
|
||||
bool same = true;
|
||||
const wxString& first = GetNameForDriver( candidates[0] );
|
||||
SCH_ITEM* second_item = nullptr;
|
||||
|
||||
for( unsigned i = 1; i < candidates.size(); i++ )
|
||||
{
|
||||
if( GetNameForDriver( candidates[i] ) != first )
|
||||
{
|
||||
second_item = candidates[i];
|
||||
same = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( !same )
|
||||
{
|
||||
m_first_driver = m_driver;
|
||||
m_second_driver = second_item;
|
||||
}
|
||||
}
|
||||
|
||||
return ( m_driver != nullptr );
|
||||
}
|
||||
|
||||
@@ -233,9 +227,16 @@ void CONNECTION_SUBGRAPH::getAllConnectedItems( std::set<std::pair<SCH_SHEET_PAT
|
||||
CONNECTION_SUBGRAPH* sg = this;
|
||||
|
||||
while( sg->m_absorbed_by )
|
||||
{
|
||||
wxASSERT( sg->m_graph == sg->m_absorbed_by->m_graph );
|
||||
sg = sg->m_absorbed_by;
|
||||
}
|
||||
|
||||
// If we are unable to insert the subgraph into the set, then we have already
|
||||
// visited it and don't need to add it again.
|
||||
if( aSubgraphs.insert( sg ).second == false )
|
||||
return;
|
||||
|
||||
aSubgraphs.insert( sg );
|
||||
aSubgraphs.insert( sg->m_absorbed_subgraphs.begin(), sg->m_absorbed_subgraphs.end() );
|
||||
|
||||
for( SCH_ITEM* item : sg->m_items )
|
||||
@@ -356,9 +357,12 @@ wxString CONNECTION_SUBGRAPH::driverName( SCH_ITEM* aItem ) const
|
||||
|
||||
const wxString& CONNECTION_SUBGRAPH::GetNameForDriver( SCH_ITEM* aItem ) const
|
||||
{
|
||||
auto [it, success] = m_driver_name_cache.try_emplace( aItem, driverName( aItem ) );
|
||||
auto it = m_driver_name_cache.find( aItem );
|
||||
|
||||
return it->second;
|
||||
if( it != m_driver_name_cache.end() )
|
||||
return it->second;
|
||||
|
||||
return m_driver_name_cache.emplace( aItem, driverName( aItem ) ).first->second;
|
||||
}
|
||||
|
||||
|
||||
@@ -426,15 +430,15 @@ void CONNECTION_SUBGRAPH::Absorb( CONNECTION_SUBGRAPH* aOther )
|
||||
|
||||
void CONNECTION_SUBGRAPH::AddItem( SCH_ITEM* aItem )
|
||||
{
|
||||
m_items.push_back( aItem );
|
||||
m_items.insert( aItem );
|
||||
|
||||
if( aItem->Connection( &m_sheet )->IsDriver() )
|
||||
m_drivers.push_back( aItem );
|
||||
m_drivers.insert( aItem );
|
||||
|
||||
if( aItem->Type() == SCH_SHEET_PIN_T )
|
||||
m_hier_pins.push_back( static_cast<SCH_SHEET_PIN*>( aItem ) );
|
||||
m_hier_pins.insert( static_cast<SCH_SHEET_PIN*>( aItem ) );
|
||||
else if( aItem->Type() == SCH_HIER_LABEL_T )
|
||||
m_hier_ports.push_back( static_cast<SCH_HIERLABEL*>( aItem ) );
|
||||
m_hier_ports.insert( static_cast<SCH_HIERLABEL*>( aItem ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -506,7 +510,12 @@ void CONNECTION_GRAPH::Merge( CONNECTION_GRAPH& aGraph )
|
||||
std::back_inserter( m_subgraphs ) );
|
||||
|
||||
for( CONNECTION_SUBGRAPH* sg : aGraph.m_subgraphs )
|
||||
{
|
||||
if( sg->m_driver_connection )
|
||||
sg->m_driver_connection->SetGraph( this );
|
||||
|
||||
sg->m_graph = this;
|
||||
}
|
||||
|
||||
std::copy( aGraph.m_driver_subgraphs.begin(),
|
||||
aGraph.m_driver_subgraphs.end(),
|
||||
@@ -543,6 +552,7 @@ void CONNECTION_GRAPH::Merge( CONNECTION_GRAPH& aGraph )
|
||||
m_last_bus_code = std::max( m_last_bus_code, aGraph.m_last_bus_code );
|
||||
m_last_net_code = std::max( m_last_net_code, aGraph.m_last_net_code );
|
||||
m_last_subgraph_code = std::max( m_last_subgraph_code, aGraph.m_last_subgraph_code );
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -585,6 +595,7 @@ void CONNECTION_GRAPH::Recalculate( const SCH_SHEET_LIST& aSheetList, bool aUnco
|
||||
PROF_TIMER update_items( "updateItemConnectivity" );
|
||||
|
||||
m_sheetList = aSheetList;
|
||||
std::set<SCH_ITEM*> dirty_items;
|
||||
|
||||
for( const SCH_SHEET_PATH& sheet : aSheetList )
|
||||
{
|
||||
@@ -596,8 +607,12 @@ void CONNECTION_GRAPH::Recalculate( const SCH_SHEET_LIST& aSheetList, bool aUnco
|
||||
for( SCH_ITEM* item : sheet.LastScreen()->Items() )
|
||||
{
|
||||
if( item->IsConnectable() && ( aUnconditional || item->IsConnectivityDirty() ) )
|
||||
{
|
||||
wxLogTrace( ConnTrace, wxT( "Adding item %s to connectivity graph update" ),
|
||||
item->GetTypeDesc() );
|
||||
items.push_back( item );
|
||||
|
||||
dirty_items.insert( item );
|
||||
}
|
||||
// Ensure the hierarchy info stored in SCREENS is built and up to date
|
||||
// (multi-unit symbols)
|
||||
if( item->Type() == SCH_SYMBOL_T )
|
||||
@@ -629,19 +644,22 @@ void CONNECTION_GRAPH::Recalculate( const SCH_SHEET_LIST& aSheetList, bool aUnco
|
||||
}
|
||||
}
|
||||
|
||||
if( wxLog::IsAllowedTraceMask( ConnProfileMask ) )
|
||||
for( SCH_ITEM* item : dirty_items )
|
||||
item->SetConnectivityDirty( false );
|
||||
|
||||
if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
|
||||
update_items.Show();
|
||||
|
||||
PROF_TIMER build_graph( "buildConnectionGraph" );
|
||||
|
||||
buildConnectionGraph( aChangedItemHandler );
|
||||
|
||||
if( wxLog::IsAllowedTraceMask( ConnProfileMask ) )
|
||||
if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
|
||||
build_graph.Show();
|
||||
|
||||
recalc_time.Stop();
|
||||
|
||||
if( wxLog::IsAllowedTraceMask( ConnProfileMask ) )
|
||||
if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
|
||||
recalc_time.Show();
|
||||
}
|
||||
|
||||
@@ -655,11 +673,17 @@ std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> CONNECTION_GRAPH::ExtractAffected
|
||||
{
|
||||
// Find the primary subgraph on this sheet
|
||||
while( aSubgraph->m_absorbed_by )
|
||||
{
|
||||
wxASSERT( aSubgraph->m_graph == aSubgraph->m_absorbed_by->m_graph );
|
||||
aSubgraph = aSubgraph->m_absorbed_by;
|
||||
}
|
||||
|
||||
// Find the top most connected subgraph on all sheets
|
||||
while( aSubgraph->m_hier_parent )
|
||||
{
|
||||
wxASSERT( aSubgraph->m_graph == aSubgraph->m_hier_parent->m_graph );
|
||||
aSubgraph = aSubgraph->m_hier_parent;
|
||||
}
|
||||
|
||||
// Recurse through all subsheets to collect connected items
|
||||
aSubgraph->getAllConnectedItems( retvals, subgraphs );
|
||||
@@ -751,23 +775,23 @@ void CONNECTION_GRAPH::removeSubgraphs( std::set<CONNECTION_SUBGRAPH*>& aSubgrap
|
||||
{
|
||||
auto it = std::lower_bound( m_driver_subgraphs.begin(), m_driver_subgraphs.end(), sg );
|
||||
|
||||
if( it != m_driver_subgraphs.end() )
|
||||
m_driver_subgraphs.erase( it );
|
||||
while( it != m_driver_subgraphs.end() && *it == sg )
|
||||
it = m_driver_subgraphs.erase( it );
|
||||
}
|
||||
|
||||
{
|
||||
auto it = std::lower_bound( m_subgraphs.begin(), m_subgraphs.end(), sg );
|
||||
|
||||
if( it != m_subgraphs.end() )
|
||||
m_subgraphs.erase( it );
|
||||
while( it != m_subgraphs.end() && *it == sg )
|
||||
it = m_subgraphs.erase( it );
|
||||
}
|
||||
|
||||
for( auto el : m_sheet_to_subgraphs_map )
|
||||
{
|
||||
auto it = std::lower_bound( el.second.begin(), el.second.end(), sg );
|
||||
|
||||
if( it != el.second.end() )
|
||||
el.second.erase( it );
|
||||
while( it != el.second.end() && *it == sg )
|
||||
it = el.second.erase( it );
|
||||
}
|
||||
|
||||
auto remove_sg = [sg]( auto it ) -> bool
|
||||
@@ -844,6 +868,7 @@ void CONNECTION_GRAPH::removeSubgraphs( std::set<CONNECTION_SUBGRAPH*>& aSubgrap
|
||||
for( CONNECTION_SUBGRAPH* sg : aSubgraphs )
|
||||
{
|
||||
sg->m_code = -1;
|
||||
sg->m_graph = nullptr;
|
||||
delete sg;
|
||||
}
|
||||
}
|
||||
@@ -931,8 +956,6 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
|
||||
for( const VECTOR2I& point : points )
|
||||
connection_map[ point ].push_back( item );
|
||||
}
|
||||
|
||||
item->SetConnectivityDirty( false );
|
||||
}
|
||||
|
||||
for( const auto& it : connection_map )
|
||||
@@ -1319,11 +1342,15 @@ void CONNECTION_GRAPH::generateBusAliasMembers()
|
||||
wxString name = conn->FullLocalName();
|
||||
|
||||
CONNECTION_SUBGRAPH* new_sg = new CONNECTION_SUBGRAPH( this );
|
||||
|
||||
// This connection cannot form a part of the item because the item is not, itself
|
||||
// connected to this subgraph. It exists as part of a virtual item that may be connected
|
||||
// to other items but is not in the schematic.
|
||||
SCH_CONNECTION* new_conn = new SCH_CONNECTION( item, subgraph->m_sheet );
|
||||
new_conn->SetGraph( this );
|
||||
|
||||
new_conn->SetName( name );
|
||||
new_conn->SetType( CONNECTION_TYPE::NET );
|
||||
subgraph->StoreImplicitConnection( new_conn );
|
||||
int code = assignNewNetCode( *new_conn );
|
||||
|
||||
wxLogTrace( ConnTrace, wxS( "SG(%ld), Adding full local name (%s) with sg (%d) on subsheet %s" ), subgraph->m_code,
|
||||
@@ -1637,10 +1664,16 @@ void CONNECTION_GRAPH::processSubGraphs()
|
||||
// by the chosen driver of the subgraph, so we need to create a dummy connection
|
||||
add_connections_to_check( subgraph );
|
||||
|
||||
std::set<SCH_CONNECTION*> checked_connections;
|
||||
|
||||
for( unsigned i = 0; i < connections_to_check.size(); i++ )
|
||||
{
|
||||
auto member = connections_to_check[i];
|
||||
|
||||
// Don't check the same connection twice
|
||||
if( !checked_connections.insert( member.get() ).second )
|
||||
continue;
|
||||
|
||||
if( member->IsBus() )
|
||||
{
|
||||
connections_to_check.insert( connections_to_check.end(),
|
||||
@@ -1776,7 +1809,7 @@ void CONNECTION_GRAPH::buildConnectionGraph( std::function<void( SCH_ITEM* )>* a
|
||||
PROF_TIMER sub_graph( "buildItemSubGraphs" );
|
||||
buildItemSubGraphs();
|
||||
|
||||
if( wxLog::IsAllowedTraceMask( ConnProfileMask ) )
|
||||
if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
|
||||
sub_graph.Show();
|
||||
|
||||
|
||||
@@ -1796,7 +1829,7 @@ void CONNECTION_GRAPH::buildConnectionGraph( std::function<void( SCH_ITEM* )>* a
|
||||
PROF_TIMER proc_sub_graph( "ProcessSubGraphs" );
|
||||
processSubGraphs();
|
||||
|
||||
if( wxLog::IsAllowedTraceMask( ConnProfileMask ) )
|
||||
if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
|
||||
proc_sub_graph.Show();
|
||||
|
||||
// Absorbed subgraphs should no longer be considered
|
||||
@@ -2180,47 +2213,96 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph, boo
|
||||
std::unordered_set<CONNECTION_SUBGRAPH*> visited;
|
||||
std::unordered_set<SCH_CONNECTION*> stale_bus_members;
|
||||
|
||||
auto visit =
|
||||
[&]( CONNECTION_SUBGRAPH* aParent )
|
||||
auto visit =[&]( CONNECTION_SUBGRAPH* aParent )
|
||||
{
|
||||
for( SCH_SHEET_PIN* pin : aParent->m_hier_pins )
|
||||
{
|
||||
SCH_SHEET_PATH path = aParent->m_sheet;
|
||||
path.push_back( pin->GetParent() );
|
||||
|
||||
auto it = m_sheet_to_subgraphs_map.find( path );
|
||||
|
||||
if( it == m_sheet_to_subgraphs_map.end() )
|
||||
continue;
|
||||
|
||||
for( CONNECTION_SUBGRAPH* candidate : it->second )
|
||||
{
|
||||
for( SCH_SHEET_PIN* pin : aParent->m_hier_pins )
|
||||
if( !candidate->m_strong_driver
|
||||
|| candidate->m_hier_ports.empty()
|
||||
|| visited.count( candidate ) )
|
||||
{
|
||||
SCH_SHEET_PATH path = aParent->m_sheet;
|
||||
path.push_back( pin->GetParent() );
|
||||
continue;
|
||||
}
|
||||
|
||||
auto it = m_sheet_to_subgraphs_map.find( path );
|
||||
|
||||
if( it == m_sheet_to_subgraphs_map.end() )
|
||||
continue;
|
||||
|
||||
for( CONNECTION_SUBGRAPH* candidate : it->second )
|
||||
for( SCH_HIERLABEL* label : candidate->m_hier_ports )
|
||||
{
|
||||
if( candidate->GetNameForDriver( label ) == aParent->GetNameForDriver( pin ) )
|
||||
{
|
||||
if( !candidate->m_strong_driver
|
||||
|| candidate->m_hier_ports.empty()
|
||||
|| visited.count( candidate ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
wxLogTrace( ConnTrace, wxS( "%lu: found child %lu (%s)" ), aParent->m_code,
|
||||
candidate->m_code, candidate->m_driver_connection->Name() );
|
||||
|
||||
for( SCH_HIERLABEL* label : candidate->m_hier_ports )
|
||||
{
|
||||
if( candidate->GetNameForDriver( label ) == aParent->GetNameForDriver( pin ) )
|
||||
{
|
||||
wxLogTrace( ConnTrace, wxS( "%lu: found child %lu (%s)" ), aParent->m_code,
|
||||
candidate->m_code, candidate->m_driver_connection->Name() );
|
||||
candidate->m_hier_parent = aParent;
|
||||
aParent->m_hier_children.insert( candidate );
|
||||
|
||||
candidate->m_hier_parent = aParent;
|
||||
aParent->m_hier_children.insert( candidate );
|
||||
wxASSERT( candidate->m_graph == aParent->m_graph );
|
||||
|
||||
search_list.push_back( candidate );
|
||||
break;
|
||||
}
|
||||
}
|
||||
search_list.push_back( candidate );
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
auto propagate_bus_neighbors = [&]( CONNECTION_SUBGRAPH* aParentGraph ) {
|
||||
for( SCH_HIERLABEL* label : aParent->m_hier_ports )
|
||||
{
|
||||
SCH_SHEET_PATH path = aParent->m_sheet;
|
||||
path.pop_back();
|
||||
|
||||
auto it = m_sheet_to_subgraphs_map.find( path );
|
||||
|
||||
if( it == m_sheet_to_subgraphs_map.end() )
|
||||
continue;
|
||||
|
||||
for( CONNECTION_SUBGRAPH* candidate : it->second )
|
||||
{
|
||||
if( candidate->m_hier_pins.empty()
|
||||
|| visited.count( candidate )
|
||||
|| candidate->m_driver_connection->Type() != aParent->m_driver_connection->Type() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const KIID& last_parent_uuid = aParent->m_sheet.Last()->m_Uuid;
|
||||
|
||||
for( SCH_SHEET_PIN* pin : candidate->m_hier_pins )
|
||||
{
|
||||
// If the last sheet UUIDs won't match, no need to check the full path
|
||||
if( pin->GetParent()->m_Uuid != last_parent_uuid )
|
||||
continue;
|
||||
|
||||
SCH_SHEET_PATH pin_path = path;
|
||||
pin_path.push_back( pin->GetParent() );
|
||||
|
||||
if( pin_path != aParent->m_sheet )
|
||||
continue;
|
||||
|
||||
if( aParent->GetNameForDriver( label ) == candidate->GetNameForDriver( pin ) )
|
||||
{
|
||||
wxLogTrace( ConnTrace, wxS( "%lu: found additional parent %lu (%s)" ),
|
||||
aParent->m_code, candidate->m_code,
|
||||
candidate->m_driver_connection->Name() );
|
||||
|
||||
aParent->m_hier_children.insert( candidate );
|
||||
search_list.push_back( candidate );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto propagate_bus_neighbors = [&]( CONNECTION_SUBGRAPH* aParentGraph )
|
||||
{
|
||||
for( const auto& kv : aParentGraph->m_bus_neighbors )
|
||||
{
|
||||
for( CONNECTION_SUBGRAPH* neighbor : kv.second )
|
||||
@@ -2338,9 +2420,8 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph, boo
|
||||
{
|
||||
auto child = search_list[i];
|
||||
|
||||
visited.insert( child );
|
||||
|
||||
visit( child );
|
||||
if( visited.insert( child ).second )
|
||||
visit( child );
|
||||
|
||||
child->m_dirty = false;
|
||||
}
|
||||
@@ -2793,38 +2874,7 @@ int CONNECTION_GRAPH::RunERC()
|
||||
bool CONNECTION_GRAPH::ercCheckMultipleDrivers( const CONNECTION_SUBGRAPH* aSubgraph )
|
||||
{
|
||||
wxCHECK( aSubgraph, false );
|
||||
/*
|
||||
* This was changed late in 6.0 to fix https://gitlab.com/kicad/code/kicad/-/issues/9367
|
||||
* so I'm going to leave the original code in for just a little while. If anyone comes
|
||||
* across this in 7.0 development (or later), feel free to delete.
|
||||
*/
|
||||
#if 0
|
||||
if( aSubgraph->m_second_driver )
|
||||
{
|
||||
SCH_ITEM* primary = aSubgraph->m_first_driver;
|
||||
SCH_ITEM* secondary = aSubgraph->m_second_driver;
|
||||
|
||||
wxPoint pos = primary->Type() == SCH_PIN_T ?
|
||||
static_cast<SCH_PIN*>( primary )->GetTransformedPosition() :
|
||||
primary->GetPosition();
|
||||
|
||||
const wxString& primaryName = aSubgraph->GetNameForDriver( primary );
|
||||
const wxString& secondaryName = aSubgraph->GetNameForDriver( secondary );
|
||||
|
||||
wxString msg = wxString::Format( _( "Both %s and %s are attached to the same "
|
||||
"items; %s will be used in the netlist" ),
|
||||
primaryName, secondaryName, primaryName );
|
||||
|
||||
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_DRIVER_CONFLICT );
|
||||
ercItem->SetItems( primary, secondary );
|
||||
ercItem->SetErrorMessage( msg );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, pos );
|
||||
aSubgraph->m_sheet.LastScreen()->Append( marker );
|
||||
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if( aSubgraph->m_multiple_drivers )
|
||||
{
|
||||
for( SCH_ITEM* driver : aSubgraph->m_drivers )
|
||||
@@ -2859,7 +2909,6 @@ bool CONNECTION_GRAPH::ercCheckMultipleDrivers( const CONNECTION_SUBGRAPH* aSubg
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -3077,7 +3126,7 @@ bool CONNECTION_GRAPH::ercCheckBusToBusEntryConflicts( const CONNECTION_SUBGRAPH
|
||||
bus_name = bus_wire->Connection( &sheet )->Name();
|
||||
|
||||
std::set<wxString> test_names;
|
||||
test_names.insert( bus_entry->Connection( &sheet )->Name() );
|
||||
test_names.insert( bus_entry->Connection( &sheet )->FullLocalName() );
|
||||
|
||||
wxString baseName = sheet.PathHumanReadable();
|
||||
|
||||
@@ -3090,11 +3139,11 @@ bool CONNECTION_GRAPH::ercCheckBusToBusEntryConflicts( const CONNECTION_SUBGRAPH
|
||||
{
|
||||
for( const auto& sub_member : member->Members() )
|
||||
{
|
||||
if( test_names.count( sub_member->Name() ) )
|
||||
if( test_names.count( sub_member->FullLocalName() ) )
|
||||
conflict = false;
|
||||
}
|
||||
}
|
||||
else if( test_names.count( member->Name() ) )
|
||||
else if( test_names.count( member->FullLocalName() ) )
|
||||
{
|
||||
conflict = false;
|
||||
}
|
||||
|
||||
+23
-16
@@ -86,12 +86,14 @@ public:
|
||||
m_bus_entry( nullptr ),
|
||||
m_driver( nullptr ),
|
||||
m_driver_connection( nullptr ),
|
||||
m_hier_parent( nullptr ),
|
||||
m_first_driver( nullptr ),
|
||||
m_second_driver( nullptr )
|
||||
m_hier_parent( nullptr )
|
||||
{}
|
||||
|
||||
~CONNECTION_SUBGRAPH() = default;
|
||||
~CONNECTION_SUBGRAPH()
|
||||
{
|
||||
for( SCH_CONNECTION* connection : m_bus_element_connections )
|
||||
delete connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines which potential driver should drive the subgraph.
|
||||
@@ -130,7 +132,7 @@ public:
|
||||
void UpdateItemConnections();
|
||||
|
||||
/// Provides a read-only reference to the items in the subgraph
|
||||
const std::vector<SCH_ITEM*>& GetItems() const
|
||||
const std::set<SCH_ITEM*>& GetItems() const
|
||||
{
|
||||
return m_items;
|
||||
}
|
||||
@@ -162,6 +164,15 @@ public:
|
||||
return PRIORITY::NONE;
|
||||
}
|
||||
|
||||
void RemoveItem( SCH_ITEM* aItem );
|
||||
|
||||
// Use this to keep a connection pointer that is not owned by any item
|
||||
// This will be destroyed with the subgraph
|
||||
void StoreImplicitConnection( SCH_CONNECTION* aConnection )
|
||||
{
|
||||
m_bus_element_connections.insert( aConnection );
|
||||
}
|
||||
|
||||
private:
|
||||
wxString driverName( SCH_ITEM* aItem ) const;
|
||||
|
||||
@@ -206,9 +217,9 @@ public:
|
||||
/// Bus entry in graph, if any
|
||||
SCH_ITEM* m_bus_entry;
|
||||
|
||||
std::vector<SCH_ITEM*> m_items;
|
||||
std::set<SCH_ITEM*> m_items;
|
||||
|
||||
std::vector<SCH_ITEM*> m_drivers;
|
||||
std::set<SCH_ITEM*> m_drivers;
|
||||
|
||||
SCH_ITEM* m_driver;
|
||||
|
||||
@@ -237,10 +248,10 @@ public:
|
||||
std::unordered_set<CONNECTION_SUBGRAPH*> > m_bus_parents;
|
||||
|
||||
// Cache for lookup of any hierarchical (sheet) pins on this subgraph (for referring down)
|
||||
std::vector<SCH_SHEET_PIN*> m_hier_pins;
|
||||
std::set<SCH_SHEET_PIN*> m_hier_pins;
|
||||
|
||||
// Cache for lookup of any hierarchical ports on this subgraph (for referring up)
|
||||
std::vector<SCH_HIERLABEL*> m_hier_ports;
|
||||
std::set<SCH_HIERLABEL*> m_hier_ports;
|
||||
|
||||
// If not null, this indicates the subgraph on a higher level sheet that is linked to this one
|
||||
CONNECTION_SUBGRAPH* m_hier_parent;
|
||||
@@ -251,14 +262,10 @@ public:
|
||||
/// A cache of escaped netnames from schematic items
|
||||
mutable std::unordered_map<SCH_ITEM*, wxString> m_driver_name_cache;
|
||||
|
||||
/**
|
||||
* Stores the primary driver for the multiple drivers ERC check. This is the chosen driver
|
||||
* before subgraphs are absorbed (so m_driver may be different)
|
||||
*/
|
||||
SCH_ITEM* m_first_driver;
|
||||
/// A cache of connections that are part of this subgraph but that don't have
|
||||
/// an owning element (i.e. bus members)
|
||||
std::set<SCH_CONNECTION*> m_bus_element_connections;
|
||||
|
||||
/// Used for multiple drivers ERC message; stores the second possible driver (or nullptr)
|
||||
SCH_ITEM* m_second_driver;
|
||||
};
|
||||
|
||||
struct NET_NAME_CODE_CACHE_KEY
|
||||
|
||||
@@ -226,8 +226,6 @@ void DIALOG_ANNOTATE::OnApplyClick( wxCommandEvent& event )
|
||||
|
||||
m_Parent->GetCanvas()->Refresh();
|
||||
|
||||
m_btnClear->Enable();
|
||||
|
||||
m_sdbSizer1Cancel->SetDefault();
|
||||
|
||||
// Don't close dialog if there are things the user needs to address
|
||||
@@ -248,7 +246,6 @@ void DIALOG_ANNOTATE::OnClearAnnotationClick( wxCommandEvent& event )
|
||||
bool appendUndo = false;
|
||||
|
||||
m_Parent->DeleteAnnotation( GetScope(), GetRecursive(), &appendUndo );
|
||||
m_btnClear->Enable( false );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <schematic.h>
|
||||
#include <template_fieldnames.h>
|
||||
#include <widgets/wx_html_report_panel.h>
|
||||
#include <widgets/std_bitmap_button.h>
|
||||
|
||||
bool g_selectRefDes = false;
|
||||
bool g_selectValue = false;
|
||||
@@ -702,6 +703,10 @@ int DIALOG_CHANGE_SYMBOLS::processSymbols( const std::map<SCH_SYMBOL*,
|
||||
|
||||
symbol->SetSchSymbolLibraryName( wxEmptyString );
|
||||
screen->Append( symbol );
|
||||
|
||||
if( resetPositions )
|
||||
symbol->AutoAutoplaceFields( screen );
|
||||
|
||||
frame->GetCanvas()->GetView()->Update( symbol );
|
||||
|
||||
msg = getSymbolReferences( *symbol, symbol_change_info.m_LibId );
|
||||
@@ -720,8 +725,18 @@ wxString DIALOG_CHANGE_SYMBOLS::getSymbolReferences( SCH_SYMBOL& aSymbol, const
|
||||
wxString references;
|
||||
LIB_ID oldId = aSymbol.GetLibId();
|
||||
|
||||
SCH_EDIT_FRAME* parent = dynamic_cast< SCH_EDIT_FRAME* >( GetParent() );
|
||||
|
||||
wxCHECK( parent, msg );
|
||||
|
||||
SCH_SHEET_LIST sheets = parent->Schematic().GetSheets();
|
||||
|
||||
for( const SCH_SYMBOL_INSTANCE& instance : aSymbol.GetInstanceReferences() )
|
||||
{
|
||||
// Only include the symbol instances for the current project.
|
||||
if( !sheets.HasPath( instance.m_Path ) )
|
||||
continue;
|
||||
|
||||
if( references.IsEmpty() )
|
||||
references = instance.m_Reference;
|
||||
else
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "widgets/std_bitmap_button.h"
|
||||
#include "widgets/wx_html_report_panel.h"
|
||||
|
||||
#include "dialog_change_symbols_base.h"
|
||||
@@ -20,7 +21,7 @@ DIALOG_CHANGE_SYMBOLS_BASE::DIALOG_CHANGE_SYMBOLS_BASE( wxWindow* parent, wxWind
|
||||
wxBoxSizer* matchSizerMargins;
|
||||
matchSizerMargins = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_matchSizer = new wxGridBagSizer( 3, 5 );
|
||||
m_matchSizer = new wxGridBagSizer( 3, 0 );
|
||||
m_matchSizer->SetFlexibleDirection( wxBOTH );
|
||||
m_matchSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
@@ -48,7 +49,7 @@ DIALOG_CHANGE_SYMBOLS_BASE::DIALOG_CHANGE_SYMBOLS_BASE( wxWindow* parent, wxWind
|
||||
m_specifiedId = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER );
|
||||
m_matchSizer->Add( m_specifiedId, wxGBPosition( 5, 0 ), wxGBSpan( 1, 2 ), wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
|
||||
|
||||
m_matchIdBrowserButton = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_matchIdBrowserButton = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_matchSizer->Add( m_matchIdBrowserButton, wxGBPosition( 5, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT, 3 );
|
||||
|
||||
|
||||
@@ -77,9 +78,9 @@ DIALOG_CHANGE_SYMBOLS_BASE::DIALOG_CHANGE_SYMBOLS_BASE( wxWindow* parent, wxWind
|
||||
bSizer1 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_newId = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER );
|
||||
bSizer1->Add( m_newId, 1, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
bSizer1->Add( m_newId, 1, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
m_newIdBrowserButton = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_newIdBrowserButton = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
bSizer1->Add( m_newIdBrowserButton, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 );
|
||||
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
<property name="flexible_direction">wxBOTH</property>
|
||||
<property name="growablecols">1</property>
|
||||
<property name="growablerows">1</property>
|
||||
<property name="hgap">5</property>
|
||||
<property name="hgap">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">m_matchSizer</property>
|
||||
<property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
|
||||
@@ -694,7 +694,7 @@
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
@@ -860,7 +860,7 @@
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxTextCtrl" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
@@ -984,7 +984,7 @@
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <wx/artprov.h>
|
||||
#include <wx/xrc/xmlres.h>
|
||||
#include <wx/intl.h>
|
||||
class STD_BITMAP_BUTTON;
|
||||
class WX_HTML_REPORT_PANEL;
|
||||
|
||||
#include "dialog_shim.h"
|
||||
@@ -56,11 +57,11 @@ class DIALOG_CHANGE_SYMBOLS_BASE : public DIALOG_SHIM
|
||||
wxTextCtrl* m_specifiedValue;
|
||||
wxRadioButton* m_matchById;
|
||||
wxTextCtrl* m_specifiedId;
|
||||
wxBitmapButton* m_matchIdBrowserButton;
|
||||
STD_BITMAP_BUTTON* m_matchIdBrowserButton;
|
||||
wxStaticLine* m_staticline1;
|
||||
wxBoxSizer* m_newIdSizer;
|
||||
wxTextCtrl* m_newId;
|
||||
wxBitmapButton* m_newIdBrowserButton;
|
||||
STD_BITMAP_BUTTON* m_newIdBrowserButton;
|
||||
wxStaticBoxSizer* m_updateFieldsSizer;
|
||||
wxCheckListBox* m_fieldsBox;
|
||||
wxButton* m_selAllBtn;
|
||||
|
||||
@@ -482,7 +482,11 @@ void DIALOG_CHOOSE_SYMBOL::PopulateFootprintSelector( LIB_ID const& aLibId )
|
||||
LIB_FIELD* fp_field = symbol->GetFieldById( FOOTPRINT_FIELD );
|
||||
wxString fp_name = fp_field ? fp_field->GetFullText() : wxString( "" );
|
||||
|
||||
symbol->GetPins( temp_pins );
|
||||
// All units, but only a single De Morgan variant.
|
||||
if( symbol->HasConversion() )
|
||||
symbol->GetPins( temp_pins, 0, 1 );
|
||||
else
|
||||
symbol->GetPins( temp_pins );
|
||||
|
||||
m_fp_sel_ctrl->FilterByPinCount( temp_pins.size() );
|
||||
m_fp_sel_ctrl->FilterByFootprintFilters( symbol->GetFPFilters(), true );
|
||||
|
||||
@@ -667,7 +667,7 @@ void DIALOG_SCH_FIELD_PROPERTIES::UpdateField( SCH_FIELD* aField, SCH_SHEET_PATH
|
||||
}
|
||||
else if( parent && parent->Type() == SCH_GLOBAL_LABEL_T )
|
||||
{
|
||||
if( fieldType == 0 )
|
||||
if( aField->GetCanonicalName() == wxT( "Intersheetrefs" ) )
|
||||
{
|
||||
if( m_visible->GetValue() != parent->Schematic()->Settings().m_IntersheetRefsShow )
|
||||
{
|
||||
|
||||
@@ -592,6 +592,7 @@ void DIALOG_LIB_SYMBOL_PROPERTIES::OnDeleteField( wxCommandEvent& event )
|
||||
}
|
||||
|
||||
m_grid->CommitPendingChanges( true /* quiet mode */ );
|
||||
m_grid->ClearSelection();
|
||||
|
||||
// Reverse sort so deleting a row doesn't change the indexes of the other rows.
|
||||
selectedRows.Sort( []( int* first, int* second ) { return *second - *first; } );
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2015-2022 KiCad Developers, see AUTHORS.TXT for contributors.
|
||||
* Copyright (C) 2015-2023 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
|
||||
@@ -324,7 +324,69 @@ bool DIALOG_PRINT_USING_PRINTER::TransferDataFromWindow()
|
||||
|
||||
int sheet_count = m_parent->Schematic().Root().CountSheets();
|
||||
|
||||
wxPrintDialogData printDialogData( m_parent->GetPageSetupData().GetPrintData() );
|
||||
wxPrintData data = m_parent->GetPageSetupData().GetPrintData();
|
||||
|
||||
#if defined( __WXGTK__ ) && !wxCHECK_VERSION( 3, 2, 3 )
|
||||
// In GTK, the default bottom margin is bigger by 0.31 inches for
|
||||
// Letter, Legal, A4 paper sizes (see gtk_paper_size_get_default_bottom_margin).
|
||||
//
|
||||
// wxWidgets doesn't handle this properly when paper is in
|
||||
// landscape orientation.
|
||||
//
|
||||
// Using custom page size avoids the problematic
|
||||
// gtk_page_setup_set_paper_size_and_default_margins call in wxWidgets.
|
||||
|
||||
wxPaperSize paperId = data.GetPaperId();
|
||||
const wxChar* paperType = nullptr;
|
||||
|
||||
// clang-format off
|
||||
std::set<wxPaperSize> letterSizes = {
|
||||
// na_letter
|
||||
wxPAPER_LETTER,
|
||||
wxPAPER_LETTERSMALL,
|
||||
wxPAPER_NOTE,
|
||||
wxPAPER_LETTER_TRANSVERSE,
|
||||
wxPAPER_LETTER_ROTATED
|
||||
};
|
||||
|
||||
std::set<wxPaperSize> legalSizes = {
|
||||
// na_legal
|
||||
wxPAPER_LEGAL
|
||||
};
|
||||
|
||||
std::set<wxPaperSize> a4Sizes = {
|
||||
// iso_a4
|
||||
wxPAPER_A4,
|
||||
wxPAPER_A4SMALL,
|
||||
wxPAPER_A4_TRANSVERSE,
|
||||
wxPAPER_A4_ROTATED
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
if( letterSizes.count( paperId ) )
|
||||
paperType = PAGE_INFO::USLetter;
|
||||
else if( legalSizes.count( paperId ) )
|
||||
paperType = PAGE_INFO::USLegal;
|
||||
else if( a4Sizes.count( paperId ) )
|
||||
paperType = PAGE_INFO::A4;
|
||||
|
||||
if( paperType )
|
||||
{
|
||||
PAGE_INFO pageInfo( paperType, data.GetOrientation() == wxPORTRAIT );
|
||||
|
||||
if( pageInfo.IsPortrait() )
|
||||
data.SetPaperSize( wxSize( EDA_UNIT_UTILS::Mils2mm( pageInfo.GetWidthMils() ),
|
||||
EDA_UNIT_UTILS::Mils2mm( pageInfo.GetHeightMils() ) ) );
|
||||
else
|
||||
data.SetPaperSize( wxSize( EDA_UNIT_UTILS::Mils2mm( pageInfo.GetHeightMils() ),
|
||||
EDA_UNIT_UTILS::Mils2mm( pageInfo.GetWidthMils() ) ) );
|
||||
|
||||
data.SetOrientation( pageInfo.GetWxOrientation() );
|
||||
data.SetPaperId( wxPAPER_NONE );
|
||||
}
|
||||
#endif
|
||||
|
||||
wxPrintDialogData printDialogData( data );
|
||||
printDialogData.SetMaxPage( sheet_count );
|
||||
|
||||
if( sheet_count > 1 )
|
||||
|
||||
@@ -67,6 +67,8 @@ DIALOG_SCHEMATIC_SETUP::DIALOG_SCHEMATIC_SETUP( SCH_EDIT_FRAME* aFrame ) :
|
||||
}, _( "Field Name Templates" ) );
|
||||
|
||||
m_treebook->AddPage( new wxPanel( GetTreebook() ), _( "Electrical Rules" ) );
|
||||
|
||||
m_severitiesPage = m_treebook->GetPageCount();
|
||||
m_treebook->AddLazySubPage(
|
||||
[this]( wxWindow* aParent ) -> wxWindow*
|
||||
{
|
||||
|
||||
@@ -208,9 +208,8 @@ bool DIALOG_SHEET_PROPERTIES::Validate()
|
||||
for( size_t i = SHEET_MANDATORY_FIELDS; i < m_fields->size(); ++i )
|
||||
{
|
||||
SCH_FIELD& field = m_fields->at( i );
|
||||
wxString fieldName = field.GetName( false );
|
||||
|
||||
if( fieldName.IsEmpty() )
|
||||
if( field.GetName( false ).empty() && !field.GetText().empty() )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "Fields must have a name." ) );
|
||||
|
||||
@@ -367,7 +366,7 @@ bool DIALOG_SHEET_PROPERTIES::TransferDataFromWindow()
|
||||
SCH_FIELD& field = m_fields->at( ii );
|
||||
const wxString& fieldName = field.GetCanonicalName();
|
||||
|
||||
if( fieldName.IsEmpty() && field.GetText().IsEmpty() )
|
||||
if( field.IsEmpty() )
|
||||
m_fields->erase( m_fields->begin() + ii );
|
||||
else if( fieldName.IsEmpty() )
|
||||
field.SetName( _( "untitled" ) );
|
||||
|
||||
@@ -49,19 +49,20 @@ using CATEGORY = SIM_MODEL::PARAM::CATEGORY;
|
||||
|
||||
template <typename T_symbol, typename T_field>
|
||||
DIALOG_SIM_MODEL<T_symbol, T_field>::DIALOG_SIM_MODEL( wxWindow* aParent, T_symbol& aSymbol,
|
||||
std::vector<T_field>& aFields )
|
||||
: DIALOG_SIM_MODEL_BASE( aParent ),
|
||||
m_symbol( aSymbol ),
|
||||
m_fields( aFields ),
|
||||
m_libraryModelsMgr( &Prj() ),
|
||||
m_builtinModelsMgr( &Prj() ),
|
||||
m_prevModel( nullptr ),
|
||||
m_curModelType( SIM_MODEL::TYPE::NONE ),
|
||||
m_scintillaTricks( nullptr ),
|
||||
m_firstCategory( nullptr ),
|
||||
m_prevParamGridSelection( nullptr ),
|
||||
m_lastParamGridWidth( 0 ),
|
||||
m_inKillFocus( false )
|
||||
std::vector<T_field>& aFields ) :\
|
||||
DIALOG_SIM_MODEL_BASE( aParent ),
|
||||
m_symbol( aSymbol ),
|
||||
m_fields( aFields ),
|
||||
m_libraryModelsMgr( &Prj() ),
|
||||
m_builtinModelsMgr( &Prj() ),
|
||||
m_prevModel( nullptr ),
|
||||
m_curModelType( SIM_MODEL::TYPE::NONE ),
|
||||
m_scintillaTricksCode( nullptr ),
|
||||
m_scintillaTricksSubckt( nullptr ),
|
||||
m_firstCategory( nullptr ),
|
||||
m_prevParamGridSelection( nullptr ),
|
||||
m_lastParamGridWidth( 0 ),
|
||||
m_inKillFocus( false )
|
||||
{
|
||||
m_browseButton->SetBitmap( KiBitmap( BITMAPS::small_folder ) );
|
||||
|
||||
@@ -81,7 +82,8 @@ DIALOG_SIM_MODEL<T_symbol, T_field>::DIALOG_SIM_MODEL( wxWindow* aParent, T_symb
|
||||
|
||||
m_typeChoice->Clear();
|
||||
|
||||
m_scintillaTricks = new SCINTILLA_TRICKS( m_codePreview, wxT( "{}" ), false );
|
||||
m_scintillaTricksCode = new SCINTILLA_TRICKS( m_codePreview, wxT( "{}" ), false );
|
||||
m_scintillaTricksSubckt = new SCINTILLA_TRICKS( m_subckt, wxT( "()" ), false );
|
||||
|
||||
m_paramGridMgr->Bind( wxEVT_PG_SELECTED, &DIALOG_SIM_MODEL::onParamGridSelectionChange, this );
|
||||
|
||||
@@ -131,7 +133,8 @@ DIALOG_SIM_MODEL<T_symbol, T_field>::~DIALOG_SIM_MODEL()
|
||||
// Delete the GRID_TRICKS.
|
||||
m_pinAssignmentsGrid->PopEventHandler( true );
|
||||
|
||||
delete m_scintillaTricks;
|
||||
delete m_scintillaTricksCode;
|
||||
delete m_scintillaTricksSubckt;
|
||||
}
|
||||
|
||||
|
||||
@@ -185,6 +188,9 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataToWindow()
|
||||
{
|
||||
m_libraryPathText->ChangeValue( libraryFilename );
|
||||
m_curModelType = SIM_MODEL::ReadTypeFromFields( m_fields, &reporter );
|
||||
|
||||
// load library will mangle the set reporter
|
||||
m_libraryModelsMgr.SetReporter( &reporter );
|
||||
m_libraryModelsMgr.CreateModel( nullptr, m_sortedPartPins, m_fields );
|
||||
|
||||
m_modelNameChoice->Append( _( "<unknown>" ) );
|
||||
@@ -660,6 +666,7 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::updatePinAssignments( SIM_MODEL* aMode
|
||||
{
|
||||
SIM_MODEL_SUBCKT* subckt = static_cast<SIM_MODEL_SUBCKT*>( aModel );
|
||||
m_subckt->SetText( subckt->GetSpiceCode() );
|
||||
m_subckt->SetEditable( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -130,7 +130,8 @@ private:
|
||||
std::map<SIM_MODEL::DEVICE_T, SIM_MODEL::TYPE> m_curModelTypeOfDeviceType;
|
||||
SIM_MODEL::TYPE m_curModelType;
|
||||
|
||||
SCINTILLA_TRICKS* m_scintillaTricks;
|
||||
SCINTILLA_TRICKS* m_scintillaTricksCode;
|
||||
SCINTILLA_TRICKS* m_scintillaTricksSubckt;
|
||||
|
||||
wxPGProperty* m_firstCategory; // Used to add principal parameters to root.
|
||||
wxPGProperty* m_prevParamGridSelection;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 2017-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2017-2023 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
|
||||
@@ -54,10 +54,16 @@ DIALOG_SYMBOL_REMAP::DIALOG_SYMBOL_REMAP( SCH_EDIT_FRAME* aParent ) :
|
||||
{
|
||||
m_remapped = false;
|
||||
|
||||
if( !wxFileName::IsDirWritable( Prj().GetProjectPath() ) )
|
||||
wxString projectPath = Prj().GetProjectPath();
|
||||
|
||||
if( !wxFileName::IsDirWritable( projectPath ) )
|
||||
{
|
||||
DisplayInfoMessage( this, _( "Remapping is not possible because you have insufficient "
|
||||
"privileges to the project folder '%s'." ) );
|
||||
wxString msg =
|
||||
wxString::Format( _( "Remapping is not possible because you have insufficient "
|
||||
"privileges to the project folder '%s'." ),
|
||||
projectPath );
|
||||
|
||||
DisplayInfoMessage( this, msg );
|
||||
|
||||
// Disable the remap button.
|
||||
m_remapped = true;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -296,10 +296,10 @@ DIALOG_TEXT_PROPERTIES_BASE::DIALOG_TEXT_PROPERTIES_BASE( wxWindow* parent, wxWi
|
||||
bSizer11 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_hyperlinkCombo = new WX_COMBOBOX( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 );
|
||||
bSizer11->Add( m_hyperlinkCombo, 1, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
bSizer11->Add( m_hyperlinkCombo, 1, wxALIGN_CENTER_VERTICAL|wxFIXED_MINSIZE, 5 );
|
||||
|
||||
|
||||
m_textEntrySizer->Add( bSizer11, wxGBPosition( 9, 1 ), wxGBSpan( 1, 6 ), wxEXPAND|wxBOTTOM|wxALIGN_CENTER_VERTICAL, 5 );
|
||||
m_textEntrySizer->Add( bSizer11, wxGBPosition( 9, 1 ), wxGBSpan( 1, 5 ), wxEXPAND|wxBOTTOM|wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
|
||||
m_textEntrySizer->AddGrowableCol( 3 );
|
||||
|
||||
@@ -2925,7 +2925,7 @@
|
||||
</object>
|
||||
<object class="gbsizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="colspan">6</property>
|
||||
<property name="colspan">5</property>
|
||||
<property name="column">1</property>
|
||||
<property name="flag">wxEXPAND|wxBOTTOM|wxALIGN_CENTER_VERTICAL</property>
|
||||
<property name="row">9</property>
|
||||
@@ -2937,7 +2937,7 @@
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxFIXED_MINSIZE</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxBitmapComboBox" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
|
||||
@@ -53,9 +53,6 @@ PANEL_SETUP_BUSES::PANEL_SETUP_BUSES( wxWindow* aWindow, SCH_EDIT_FRAME* aFrame
|
||||
m_membersGrid->PushEventHandler( new GRID_TRICKS( m_membersGrid,
|
||||
[this]( wxCommandEvent& aEvent )
|
||||
{
|
||||
wxIdleEvent dummy;
|
||||
reloadMembersGridOnIdle( dummy );
|
||||
|
||||
OnAddMember( aEvent );
|
||||
} ) );
|
||||
|
||||
@@ -306,6 +303,12 @@ void PANEL_SETUP_BUSES::OnMemberGridCellChanging( wxGridEvent& event )
|
||||
// Parse a space-separated list and add each one
|
||||
wxStringTokenizer tok( name, " " );
|
||||
|
||||
if( tok.CountTokens() > 1 )
|
||||
{
|
||||
m_membersGridDirty = true;
|
||||
Bind( wxEVT_IDLE, &PANEL_SETUP_BUSES::reloadMembersGridOnIdle, this );
|
||||
}
|
||||
|
||||
while( tok.HasMoreTokens() )
|
||||
alias->Members().push_back( tok.GetNextToken() );
|
||||
}
|
||||
@@ -314,9 +317,6 @@ void PANEL_SETUP_BUSES::OnMemberGridCellChanging( wxGridEvent& event )
|
||||
alias->Members().push_back( m_membersGrid->GetCellValue( ii, 0 ) );
|
||||
}
|
||||
}
|
||||
|
||||
m_membersGridDirty = true;
|
||||
Bind( wxEVT_IDLE, &PANEL_SETUP_BUSES::reloadMembersGridOnIdle, this );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -180,7 +180,7 @@ protected:
|
||||
tbl->AppendRows( tmp_tbl.GetCount() - tbl->GetNumberRows() );
|
||||
|
||||
for( unsigned i = 0; i < tmp_tbl.GetCount(); ++i )
|
||||
tbl->m_rows.replace( i, tmp_tbl.At( i ).clone() );
|
||||
tbl->ReplaceRow( i, tmp_tbl.At( i ).clone() );
|
||||
}
|
||||
|
||||
m_grid->AutoSizeColumns( false );
|
||||
@@ -447,9 +447,6 @@ bool PANEL_SYM_LIB_TABLE::verifyTables()
|
||||
{
|
||||
SYMBOL_LIB_TABLE_ROW& row = dynamic_cast<SYMBOL_LIB_TABLE_ROW&>( table->At( r ) );
|
||||
|
||||
if( !row.GetParent() )
|
||||
row.SetParent( table );
|
||||
|
||||
if( !row.GetIsEnabled() )
|
||||
continue;
|
||||
|
||||
@@ -667,11 +664,7 @@ void PANEL_SYM_LIB_TABLE::moveUpHandler( wxCommandEvent& event )
|
||||
// @todo: add multiple selection moves.
|
||||
if( curRow >= 1 )
|
||||
{
|
||||
boost::ptr_vector< LIB_TABLE_ROW >::auto_type move_me =
|
||||
tbl->m_rows.release( tbl->m_rows.begin() + curRow );
|
||||
|
||||
--curRow;
|
||||
tbl->m_rows.insert( tbl->m_rows.begin() + curRow, move_me.release() );
|
||||
tbl->ChangeRowOrder( curRow--, -1 );
|
||||
|
||||
if( tbl->GetView() )
|
||||
{
|
||||
@@ -697,11 +690,7 @@ void PANEL_SYM_LIB_TABLE::moveDownHandler( wxCommandEvent& event )
|
||||
// @todo: add multiple selection moves.
|
||||
if( unsigned( curRow + 1 ) < tbl->m_rows.size() )
|
||||
{
|
||||
boost::ptr_vector< LIB_TABLE_ROW >::auto_type move_me =
|
||||
tbl->m_rows.release( tbl->m_rows.begin() + curRow );
|
||||
|
||||
++curRow;
|
||||
tbl->m_rows.insert( tbl->m_rows.begin() + curRow, move_me.release() );
|
||||
tbl->ChangeRowOrder( curRow++, 1 );
|
||||
|
||||
if( tbl->GetView() )
|
||||
{
|
||||
@@ -889,9 +878,7 @@ bool PANEL_SYM_LIB_TABLE::TransferDataFromWindow()
|
||||
m_parent->m_GlobalTableChanged = true;
|
||||
|
||||
m_globalTable->Clear();
|
||||
m_globalTable->m_rows.transfer( m_globalTable->m_rows.end(), global_model()->m_rows.begin(),
|
||||
global_model()->m_rows.end(), global_model()->m_rows );
|
||||
m_globalTable->reindex();
|
||||
m_globalTable->TransferRows( global_model()->m_rows );
|
||||
}
|
||||
|
||||
if( project_model() && *project_model() != *m_projectTable )
|
||||
@@ -899,9 +886,7 @@ bool PANEL_SYM_LIB_TABLE::TransferDataFromWindow()
|
||||
m_parent->m_ProjectTableChanged = true;
|
||||
|
||||
m_projectTable->Clear();
|
||||
m_projectTable->m_rows.transfer( m_projectTable->m_rows.end(), project_model()->m_rows.begin(),
|
||||
project_model()->m_rows.end(), project_model()->m_rows );
|
||||
m_projectTable->reindex();
|
||||
m_projectTable->TransferRows( project_model()->m_rows );
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -332,12 +332,15 @@ bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits )
|
||||
// This is process-level-initialization, not project-level-initialization of the DSO.
|
||||
// Do nothing in here pertinent to a project!
|
||||
InitSettings( new EESCHEMA_SETTINGS );
|
||||
aProgram->GetSettingsManager().RegisterSettings( KifaceSettings(), false );
|
||||
|
||||
// Register the symbol editor settings as well because they share a KiFACE and need to be
|
||||
// loaded prior to use to avoid threading deadlocks
|
||||
aProgram->GetSettingsManager().RegisterSettings( new SYMBOL_EDITOR_SETTINGS, false );
|
||||
aProgram->GetSettingsManager().Load();
|
||||
aProgram->GetSettingsManager().RegisterSettings( new SYMBOL_EDITOR_SETTINGS );
|
||||
|
||||
// We intentionally register KifaceSettings after SYMBOL_EDITOR_SETTINGS
|
||||
// In legacy configs, many settings were in a single editor config nd the migration routine
|
||||
// for the main editor file will try and call into the now separate settings stores
|
||||
// to move the settings into them
|
||||
aProgram->GetSettingsManager().RegisterSettings( KifaceSettings() );
|
||||
|
||||
start_common( aCtlBits );
|
||||
|
||||
|
||||
@@ -164,7 +164,7 @@ void SCH_EDIT_FRAME::saveProjectSettings()
|
||||
|
||||
void SCH_EDIT_FRAME::SaveProjectLocalSettings()
|
||||
{
|
||||
// No schematic local settings yet
|
||||
RecordERCExclusions();
|
||||
}
|
||||
|
||||
|
||||
|
||||
+4
-18
@@ -619,8 +619,6 @@ int ERC_TESTER::TestPinToPin()
|
||||
}
|
||||
}
|
||||
|
||||
std::set<std::pair<ERC_SCH_PIN_CONTEXT, ERC_SCH_PIN_CONTEXT>> tested;
|
||||
|
||||
ERC_SCH_PIN_CONTEXT needsDriver;
|
||||
bool hasDriver = false;
|
||||
|
||||
@@ -638,8 +636,9 @@ int ERC_TESTER::TestPinToPin()
|
||||
}
|
||||
}
|
||||
|
||||
for( ERC_SCH_PIN_CONTEXT& refPin : pins )
|
||||
for( auto refIt = pins.begin(); refIt != pins.end(); ++refIt )
|
||||
{
|
||||
ERC_SCH_PIN_CONTEXT& refPin = *refIt;
|
||||
ELECTRICAL_PINTYPE refType = refPin.Pin()->GetType();
|
||||
|
||||
if( DrivenPinTypes.count( refType ) )
|
||||
@@ -663,22 +662,9 @@ int ERC_TESTER::TestPinToPin()
|
||||
else
|
||||
hasDriver |= ( DrivingPinTypes.count( refType ) != 0 );
|
||||
|
||||
for( ERC_SCH_PIN_CONTEXT& testPin : pins )
|
||||
for( auto testIt = refIt + 1; testIt != pins.end(); ++testIt )
|
||||
{
|
||||
if( testPin == refPin )
|
||||
continue;
|
||||
|
||||
ERC_SCH_PIN_CONTEXT first_pin = refPin;
|
||||
ERC_SCH_PIN_CONTEXT second_pin = testPin;
|
||||
|
||||
if( second_pin < first_pin )
|
||||
std::swap( first_pin, second_pin );
|
||||
|
||||
std::pair<ERC_SCH_PIN_CONTEXT, ERC_SCH_PIN_CONTEXT> pair =
|
||||
std::make_pair( first_pin, second_pin );
|
||||
|
||||
if( auto [ins_pin, inserted ] = tested.insert( pair ); !inserted )
|
||||
continue;
|
||||
ERC_SCH_PIN_CONTEXT& testPin = *testIt;
|
||||
|
||||
// Multiple pins in the same symbol that share a type,
|
||||
// name and position are considered
|
||||
|
||||
@@ -580,7 +580,7 @@ wxString FIELDS_GRID_TABLE<T>::GetValue( int aRow, int aCol )
|
||||
return StringFromBool( field.IsNameShown() );
|
||||
|
||||
case FDC_H_ALIGN:
|
||||
switch ( field.GetHorizJustify() )
|
||||
switch ( field.GetEffectiveHorizJustify() )
|
||||
{
|
||||
case GR_TEXT_H_ALIGN_LEFT: return _( "Left" );
|
||||
case GR_TEXT_H_ALIGN_CENTER: return _( "Center" );
|
||||
@@ -590,7 +590,7 @@ wxString FIELDS_GRID_TABLE<T>::GetValue( int aRow, int aCol )
|
||||
break;
|
||||
|
||||
case FDC_V_ALIGN:
|
||||
switch ( field.GetVertJustify() )
|
||||
switch ( field.GetEffectiveVertJustify() )
|
||||
{
|
||||
case GR_TEXT_V_ALIGN_TOP: return _( "Top" );
|
||||
case GR_TEXT_V_ALIGN_CENTER: return _( "Center" );
|
||||
@@ -727,28 +727,52 @@ void FIELDS_GRID_TABLE<T>::SetValue( int aRow, int aCol, const wxString &aValue
|
||||
break;
|
||||
|
||||
case FDC_H_ALIGN:
|
||||
{
|
||||
GR_TEXT_H_ALIGN_T horizontalJustification;
|
||||
|
||||
if( value == _( "Left" ) )
|
||||
field.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
|
||||
horizontalJustification = GR_TEXT_H_ALIGN_LEFT;
|
||||
else if( value == _( "Center" ) )
|
||||
field.SetHorizJustify( GR_TEXT_H_ALIGN_CENTER );
|
||||
horizontalJustification = GR_TEXT_H_ALIGN_CENTER;
|
||||
else if( value == _( "Right" ) )
|
||||
field.SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
|
||||
horizontalJustification = GR_TEXT_H_ALIGN_RIGHT;
|
||||
else
|
||||
wxFAIL_MSG( wxT( "unknown horizontal alignment: " ) + value );
|
||||
|
||||
// Note that we must set justifications before we can ask if they're flipped. If the old
|
||||
// justification is center then it won't know (whereas if the new justification is center
|
||||
// the we don't care).
|
||||
field.SetHorizJustify( horizontalJustification );
|
||||
|
||||
if( field.IsHorizJustifyFlipped() )
|
||||
field.SetHorizJustify( EDA_TEXT::MapHorizJustify( - horizontalJustification ) );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case FDC_V_ALIGN:
|
||||
{
|
||||
GR_TEXT_V_ALIGN_T verticalJustification;
|
||||
|
||||
if( value == _( "Top" ) )
|
||||
field.SetVertJustify( GR_TEXT_V_ALIGN_TOP );
|
||||
verticalJustification = GR_TEXT_V_ALIGN_TOP;
|
||||
else if( value == _( "Center" ) )
|
||||
field.SetVertJustify( GR_TEXT_V_ALIGN_CENTER );
|
||||
verticalJustification = GR_TEXT_V_ALIGN_CENTER;
|
||||
else if( value == _( "Bottom" ) )
|
||||
field.SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
|
||||
verticalJustification = GR_TEXT_V_ALIGN_BOTTOM;
|
||||
else
|
||||
wxFAIL_MSG( wxT( "unknown vertical alignment: " ) + value);
|
||||
|
||||
// Note that we must set justifications before we can ask if they're flipped. If the old
|
||||
// justification is center then it won't know (whereas if the new justification is center
|
||||
// the we don't care).
|
||||
field.SetVertJustify( verticalJustification );
|
||||
|
||||
if( field.IsVertJustifyFlipped() )
|
||||
field.SetVertJustify( EDA_TEXT::MapVertJustify( -verticalJustification ) );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case FDC_ITALIC:
|
||||
field.SetItalic( BoolFromString( value ) );
|
||||
|
||||
+25
-2
@@ -103,7 +103,7 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
||||
{
|
||||
msg.Printf( _( "Schematic '%s' is already open." ), wx_filename.GetFullName() );
|
||||
|
||||
if( !OverrideLock( this, msg ) )
|
||||
if( !AskOverrideLock( this, msg ) )
|
||||
return false;
|
||||
|
||||
m_file_checker->OverrideLock( false );
|
||||
@@ -590,6 +590,15 @@ void SCH_EDIT_FRAME::OnImportProject( wxCommandEvent& aEvent )
|
||||
if( !AskToSaveChanges() )
|
||||
return;
|
||||
|
||||
if( Schematic().RootScreen() && !Schematic().RootScreen()->Items().empty() )
|
||||
{
|
||||
wxString msg = _( "This operation replaces the contents of the current project.\n\n"
|
||||
"Do you want to proceed?" );
|
||||
|
||||
if( !IsOK( this, msg ) )
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the project location if none is set or if we are running in standalone mode
|
||||
bool setProject = Prj().GetProjectFullName().IsEmpty() || Kiface().IsSingle();
|
||||
wxString path = wxPathOnly( Prj().GetProjectFullName() );
|
||||
@@ -638,6 +647,9 @@ void SCH_EDIT_FRAME::OnImportProject( wxCommandEvent& aEvent )
|
||||
Schematic().SetProject( nullptr );
|
||||
GetSettingsManager()->UnloadProject( &Prj(), false );
|
||||
|
||||
// Clear view before destroying schematic as repaints depend on schematic being valid
|
||||
SetScreen( nullptr );
|
||||
|
||||
Schematic().Reset();
|
||||
|
||||
wxFileName projectFn( dlg.GetPath() );
|
||||
@@ -696,6 +708,17 @@ bool SCH_EDIT_FRAME::saveSchematicFile( SCH_SHEET* aSheet, const wxString& aSave
|
||||
if( !IsWritable( schematicFileName ) )
|
||||
return false;
|
||||
|
||||
wxFileName projectFile( schematicFileName );
|
||||
|
||||
projectFile.SetExt( ProjectFileExtension );
|
||||
|
||||
if( projectFile.FileExists() )
|
||||
{
|
||||
// Save various ERC settings, such as violation severities (which may have been edited
|
||||
// via the ERC dialog as well as the Schematic Setup dialog), ERC exclusions, etc.
|
||||
saveProjectSettings();
|
||||
}
|
||||
|
||||
wxString tempFile = wxFileName::CreateTempFileName( wxS( "eeschema" ) );
|
||||
|
||||
// Save
|
||||
@@ -1220,7 +1243,7 @@ bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType )
|
||||
msg.Printf( _( "Schematic '%s' is already open by '%s' at '%s'." ), aFileName,
|
||||
m_file_checker->GetUsername(), m_file_checker->GetHostname() );
|
||||
|
||||
if( !OverrideLock( this, msg ) )
|
||||
if( !AskOverrideLock( this, msg ) )
|
||||
return false;
|
||||
|
||||
m_file_checker->OverrideLock();
|
||||
|
||||
@@ -415,7 +415,7 @@ wxString LIB_FIELD::GetShownText( bool aAllowExtraText, int aDepth ) const
|
||||
{
|
||||
wxString text = EDA_TEXT::GetShownText( aAllowExtraText, aDepth );
|
||||
|
||||
if( IsNameShown() )
|
||||
if( IsNameShown() && aAllowExtraText )
|
||||
text = GetName() << wxT( ": " ) << text;
|
||||
|
||||
return text;
|
||||
|
||||
@@ -118,6 +118,12 @@ public:
|
||||
|
||||
KIFONT::FONT* getDrawFont() const override;
|
||||
|
||||
bool IsHorizJustifyFlipped() const { return false; }
|
||||
bool IsVertJustifyFlipped() const { return false; }
|
||||
|
||||
GR_TEXT_H_ALIGN_T GetEffectiveHorizJustify() const { return GetHorizJustify(); }
|
||||
GR_TEXT_V_ALIGN_T GetEffectiveVertJustify() const { return GetVertJustify(); }
|
||||
|
||||
/**
|
||||
* Copy parameters of this field to another field. Pointers are not copied.
|
||||
*
|
||||
|
||||
@@ -847,7 +847,7 @@ void LIB_SYMBOL::GetPins( LIB_PINS& aList, int aUnit, int aConvert ) const
|
||||
* when m_convert == 0, the body item is common to shapes
|
||||
*/
|
||||
|
||||
LIB_SYMBOL_SPTR parent = m_parent.lock();
|
||||
LIB_SYMBOL_SPTR parent = m_parent.lock();
|
||||
const LIB_ITEMS_CONTAINER& drawItems = parent ? parent->m_drawings : m_drawings;
|
||||
|
||||
for( const LIB_ITEM& item : drawItems[LIB_PIN_T] )
|
||||
@@ -856,7 +856,7 @@ void LIB_SYMBOL::GetPins( LIB_PINS& aList, int aUnit, int aConvert ) const
|
||||
if( aUnit && item.m_unit && ( item.m_unit != aUnit ) )
|
||||
continue;
|
||||
|
||||
// Shape filtering:
|
||||
// De Morgan variant filtering:
|
||||
if( aConvert && item.m_convert && ( item.m_convert != aConvert ) )
|
||||
continue;
|
||||
|
||||
@@ -1276,6 +1276,7 @@ bool LIB_SYMBOL::HasConversion() const
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int LIB_SYMBOL::GetMaxPinNumber() const
|
||||
{
|
||||
int maxPinNumber = 0;
|
||||
|
||||
@@ -106,10 +106,14 @@ void SCH_EDIT_FRAME::doReCreateMenuBar()
|
||||
ACTION_MENU* submenuImport = new ACTION_MENU( false, selTool );
|
||||
submenuImport->SetTitle( _( "Import" ) );
|
||||
submenuImport->SetIcon( BITMAPS::import );
|
||||
submenuImport->Add( _( "Non-KiCad Schematic..." ),
|
||||
|
||||
if( Kiface().IsSingle() )
|
||||
{
|
||||
submenuImport->Add( _( "Non-KiCad Schematic..." ),
|
||||
_( "Replace current schematic sheet with one imported from another application" ),
|
||||
ID_IMPORT_NON_KICAD_SCH,
|
||||
BITMAPS::import_document );
|
||||
}
|
||||
|
||||
submenuImport->Add( EE_ACTIONS::importFPAssignments, ACTION_MENU::NORMAL, _( "Footprint Assignments..." ) );
|
||||
fileMenu->Add( submenuImport );
|
||||
|
||||
@@ -43,6 +43,8 @@ public:
|
||||
bool IsDanglingStart() const { return m_isDanglingStart; }
|
||||
bool IsDanglingEnd() const { return m_isDanglingEnd; }
|
||||
|
||||
void SetEndDangling( bool aDanglingState ) { m_isDanglingEnd = aDanglingState; }
|
||||
|
||||
// Do not create a copy constructor. The one generated by the compiler is adequate.
|
||||
|
||||
~SCH_BUS_ENTRY_BASE() { }
|
||||
|
||||
@@ -1496,9 +1496,10 @@ void SCH_EDIT_FRAME::RecalculateConnections( SCH_CLEANUP_FLAGS aCleanupFlags )
|
||||
}
|
||||
else
|
||||
{
|
||||
auto& changed_list = m_undoList.m_CommandsList.back();
|
||||
PICKED_ITEMS_LIST* changed_list = m_undoList.m_CommandsList.back();
|
||||
std::set<SCH_ITEM*> changed_items;
|
||||
std::vector<VECTOR2I> pts;
|
||||
std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> item_paths;
|
||||
|
||||
for( unsigned ii = 0; ii < changed_list->GetCount(); ++ii )
|
||||
{
|
||||
@@ -1507,11 +1508,16 @@ void SCH_EDIT_FRAME::RecalculateConnections( SCH_CLEANUP_FLAGS aCleanupFlags )
|
||||
if( !item || !IsEeschemaType( item->Type() ) )
|
||||
continue;
|
||||
|
||||
SCH_SCREEN* screen = static_cast<SCH_SCREEN*>( changed_list->GetScreenForItem( ii ) );
|
||||
SCH_ITEM* sch_item = static_cast<SCH_ITEM*>( item );
|
||||
SCH_SHEET_PATHS& paths = screen->GetClientSheetPaths();
|
||||
|
||||
std::vector<VECTOR2I> tmp_pts = sch_item->GetConnectionPoints();
|
||||
pts.insert( pts.end(), tmp_pts.begin(), tmp_pts.end() );
|
||||
changed_items.insert( sch_item );
|
||||
|
||||
for( SCH_SHEET_PATH& path : paths )
|
||||
item_paths.insert( std::make_pair( path, sch_item ) );
|
||||
}
|
||||
|
||||
for( VECTOR2I& pt: pts )
|
||||
@@ -1546,6 +1552,8 @@ void SCH_EDIT_FRAME::RecalculateConnections( SCH_CLEANUP_FLAGS aCleanupFlags )
|
||||
Schematic().ConnectionGraph()->ExtractAffectedItems(
|
||||
changed_items );
|
||||
|
||||
all_items.insert( item_paths.begin(), item_paths.end() );
|
||||
|
||||
CONNECTION_GRAPH new_graph( &Schematic() );
|
||||
|
||||
new_graph.SetLastCodes( Schematic().ConnectionGraph() );
|
||||
@@ -1556,7 +1564,6 @@ void SCH_EDIT_FRAME::RecalculateConnections( SCH_CLEANUP_FLAGS aCleanupFlags )
|
||||
{
|
||||
case SCH_FIELD_T:
|
||||
case SCH_PIN_T:
|
||||
case SCH_SHEET_PIN_T:
|
||||
static_cast<SCH_ITEM*>( item->GetParent() )->SetConnectivityDirty();
|
||||
break;
|
||||
|
||||
|
||||
@@ -92,8 +92,10 @@ SCH_FIELD::SCH_FIELD( const SCH_FIELD& aField ) :
|
||||
|
||||
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : aField.m_renderCache )
|
||||
{
|
||||
KIFONT::OUTLINE_GLYPH* outline_glyph = static_cast<KIFONT::OUTLINE_GLYPH*>( glyph.get() );
|
||||
m_renderCache.emplace_back( std::make_unique<KIFONT::OUTLINE_GLYPH>( *outline_glyph ) );
|
||||
if( KIFONT::OUTLINE_GLYPH* outline = dynamic_cast<KIFONT::OUTLINE_GLYPH*>( glyph.get() ) )
|
||||
m_renderCache.emplace_back( std::make_unique<KIFONT::OUTLINE_GLYPH>( *outline ) );
|
||||
else if( KIFONT::STROKE_GLYPH* stroke = dynamic_cast<KIFONT::STROKE_GLYPH*>( glyph.get() ) )
|
||||
m_renderCache.emplace_back( std::make_unique<KIFONT::STROKE_GLYPH>( *stroke ) );
|
||||
}
|
||||
|
||||
m_renderCacheValid = aField.m_renderCacheValid;
|
||||
@@ -116,8 +118,10 @@ SCH_FIELD& SCH_FIELD::operator=( const SCH_FIELD& aField )
|
||||
|
||||
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : aField.m_renderCache )
|
||||
{
|
||||
KIFONT::OUTLINE_GLYPH* outline_glyph = static_cast<KIFONT::OUTLINE_GLYPH*>( glyph.get() );
|
||||
m_renderCache.emplace_back( std::make_unique<KIFONT::OUTLINE_GLYPH>( *outline_glyph ) );
|
||||
if( KIFONT::OUTLINE_GLYPH* outline = dynamic_cast<KIFONT::OUTLINE_GLYPH*>( glyph.get() ) )
|
||||
m_renderCache.emplace_back( std::make_unique<KIFONT::OUTLINE_GLYPH>( *outline ) );
|
||||
else if( KIFONT::STROKE_GLYPH* stroke = dynamic_cast<KIFONT::STROKE_GLYPH*>( glyph.get() ) )
|
||||
m_renderCache.emplace_back( std::make_unique<KIFONT::STROKE_GLYPH>( *stroke ) );
|
||||
}
|
||||
|
||||
m_renderCacheValid = aField.m_renderCacheValid;
|
||||
|
||||
+13
-1
@@ -94,7 +94,7 @@ public:
|
||||
|
||||
bool IsHypertext() const override
|
||||
{
|
||||
return m_id == 0 && m_parent && m_parent->Type() == SCH_GLOBAL_LABEL_T;
|
||||
return GetCanonicalName() == wxT( "Intersheetrefs" );
|
||||
}
|
||||
|
||||
void DoHypertextAction( EDA_DRAW_FRAME* aFrame ) const override;
|
||||
@@ -134,6 +134,18 @@ public:
|
||||
return GetShownText( nullptr, aAllowExtraText, aDepth );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if both the name and value of the field are empty. Whitespace
|
||||
* does not count as non-empty
|
||||
*/
|
||||
bool IsEmpty()
|
||||
{
|
||||
wxString name( m_name );
|
||||
wxString value( GetText() );
|
||||
|
||||
return name.Trim().empty() && value.Trim().empty();
|
||||
}
|
||||
|
||||
COLOR4D GetFieldColor() const;
|
||||
|
||||
void SetLastResolvedState( const SCH_ITEM* aItem ) override
|
||||
|
||||
@@ -149,9 +149,6 @@ SCH_CONNECTION* SCH_ITEM::Connection( const SCH_SHEET_PATH* aSheet ) const
|
||||
if( !IsConnectable() )
|
||||
return nullptr;
|
||||
|
||||
wxCHECK_MSG( !IsConnectivityDirty(), nullptr,
|
||||
wxT( "Shouldn't be asking for connection if connectivity is dirty!" ) );
|
||||
|
||||
if( !aSheet )
|
||||
aSheet = &Schematic()->CurrentSheet();
|
||||
|
||||
@@ -167,7 +164,12 @@ SCH_CONNECTION* SCH_ITEM::Connection( const SCH_SHEET_PATH* aSheet ) const
|
||||
void SCH_ITEM::SetConnectionGraph( CONNECTION_GRAPH* aGraph )
|
||||
{
|
||||
for( auto& [path, conn] : m_connection_map )
|
||||
{
|
||||
conn->SetGraph( aGraph );
|
||||
|
||||
for( auto& member : conn->AllMembers() )
|
||||
member->SetGraph( aGraph );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -213,10 +215,11 @@ void SCH_ITEM::AddConnectionTo( const SCH_SHEET_PATH& aSheet, SCH_ITEM* aItem )
|
||||
SCH_CONNECTION* SCH_ITEM::InitializeConnection( const SCH_SHEET_PATH& aSheet,
|
||||
CONNECTION_GRAPH* aGraph )
|
||||
{
|
||||
SetConnectivityDirty( false );
|
||||
|
||||
SCH_CONNECTION* connection = Connection( &aSheet );
|
||||
|
||||
// N.B. Do not clear the dirty connectivity flag here because we may need
|
||||
// to create a connection for a different sheet, and we don't want to
|
||||
// skip the connection creation because the flag is cleared.
|
||||
if( connection )
|
||||
{
|
||||
connection->Reset();
|
||||
@@ -239,8 +242,6 @@ SCH_CONNECTION* SCH_ITEM::GetOrInitConnection( const SCH_SHEET_PATH& aSheet,
|
||||
if( !IsConnectable() )
|
||||
return nullptr;
|
||||
|
||||
SetConnectivityDirty( false );
|
||||
|
||||
SCH_CONNECTION* connection = Connection( &aSheet );
|
||||
|
||||
if( connection )
|
||||
|
||||
+40
-4
@@ -1037,8 +1037,27 @@ void SCH_LABEL_BASE::Plot( PLOTTER* aPlotter, bool aBackground ) const
|
||||
{
|
||||
aPlotter->PlotText( textpos, color, GetShownText( true ), attrs, font );
|
||||
|
||||
if( s_poly.size() )
|
||||
aPlotter->PlotPoly( s_poly, FILL_T::NO_FILL, penWidth );
|
||||
if( GetShape() == LABEL_FLAG_SHAPE::F_DOT )
|
||||
{
|
||||
aPlotter->MoveTo( s_poly[0] );
|
||||
aPlotter->LineTo( s_poly[1] );
|
||||
|
||||
int diameter = ( s_poly[2] - s_poly[1] ).EuclideanNorm() * 2;
|
||||
aPlotter->FilledCircle( s_poly[2], diameter , FILLED, nullptr );
|
||||
}
|
||||
else if( GetShape() == LABEL_FLAG_SHAPE::F_ROUND )
|
||||
{
|
||||
aPlotter->MoveTo( s_poly[0] );
|
||||
aPlotter->LineTo( s_poly[1] );
|
||||
|
||||
int diameter = ( s_poly[2] - s_poly[1] ).EuclideanNorm() * 2;
|
||||
aPlotter->ThickCircle( s_poly[2], diameter, penWidth, FILLED, nullptr );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !s_poly.empty() )
|
||||
aPlotter->PlotPoly( s_poly, FILL_T::NO_FILL, penWidth );
|
||||
}
|
||||
|
||||
// Plot attributes to a hypertext menu
|
||||
std::vector<wxString> properties;
|
||||
@@ -1092,8 +1111,25 @@ void SCH_LABEL_BASE::Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aO
|
||||
|
||||
CreateGraphicShape( aSettings, s_poly, GetTextPos() + aOffset );
|
||||
|
||||
if( !s_poly.empty() )
|
||||
GRPoly( DC, s_poly.size(), &s_poly[0], false, penWidth, color, color );
|
||||
if( GetShape() == LABEL_FLAG_SHAPE::F_DOT )
|
||||
{
|
||||
GRLine( DC, s_poly[0], s_poly[1], penWidth, color );
|
||||
|
||||
int radius = ( s_poly[2] - s_poly[1] ).EuclideanNorm();
|
||||
GRFilledCircle( DC, s_poly[2], radius, penWidth, color, color );
|
||||
}
|
||||
else if( GetShape() == LABEL_FLAG_SHAPE::F_ROUND )
|
||||
{
|
||||
GRLine( DC, s_poly[0], s_poly[1], penWidth, color );
|
||||
|
||||
int radius = ( s_poly[2] - s_poly[1] ).EuclideanNorm();
|
||||
GRCircle( DC, s_poly[2], radius, penWidth, color );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !s_poly.empty() )
|
||||
GRPoly( DC, s_poly.size(), &s_poly[0], false, penWidth, color, color );
|
||||
}
|
||||
|
||||
for( SCH_FIELD& field : m_fields )
|
||||
field.Print( aSettings, aOffset );
|
||||
|
||||
+96
-97
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2014 CERN
|
||||
* Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2019-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
*
|
||||
@@ -86,7 +86,10 @@ std::vector<KICAD_T> SCH_PAINTER::g_ScaledSelectionTypes = {
|
||||
SCH_LINE_T,
|
||||
LIB_SHAPE_T, SCH_SHAPE_T,
|
||||
SCH_BITMAP_T,
|
||||
SCH_GLOBAL_LABEL_T,
|
||||
SCH_DIRECTIVE_LABEL_T,
|
||||
SCH_HIER_LABEL_T,
|
||||
SCH_SHEET_PIN_T,
|
||||
LIB_SYMBOL_T, SCH_SYMBOL_T,
|
||||
SCH_SHEET_T,
|
||||
LIB_PIN_T, SCH_PIN_T
|
||||
@@ -186,7 +189,7 @@ SCH_PAINTER::SCH_PAINTER( GAL* aGal ) :
|
||||
m_schematic( nullptr )
|
||||
{ }
|
||||
|
||||
bool SCH_PAINTER::Draw( const VIEW_ITEM *aItem, int aLayer )
|
||||
bool SCH_PAINTER::Draw( const VIEW_ITEM* aItem, int aLayer )
|
||||
{
|
||||
const EDA_ITEM* item = dynamic_cast<const EDA_ITEM*>( aItem );
|
||||
|
||||
@@ -198,7 +201,7 @@ bool SCH_PAINTER::Draw( const VIEW_ITEM *aItem, int aLayer )
|
||||
return false;
|
||||
}
|
||||
|
||||
void SCH_PAINTER::draw( const EDA_ITEM *aItem, int aLayer, bool aDimmed )
|
||||
void SCH_PAINTER::draw( const EDA_ITEM* aItem, int aLayer, bool aDimmed )
|
||||
{
|
||||
|
||||
#ifdef CONNECTIVITY_DEBUG
|
||||
@@ -369,7 +372,7 @@ float SCH_PAINTER::getShadowWidth( bool aForHighlight ) const
|
||||
}
|
||||
|
||||
|
||||
COLOR4D SCH_PAINTER::getRenderColor( const EDA_ITEM *aItem, int aLayer, bool aDrawingShadows,
|
||||
COLOR4D SCH_PAINTER::getRenderColor( const EDA_ITEM* aItem, int aLayer, bool aDrawingShadows,
|
||||
bool aDimmed ) const
|
||||
{
|
||||
COLOR4D color = m_schSettings.GetLayerColor( aLayer );
|
||||
@@ -666,7 +669,7 @@ void SCH_PAINTER::triLine( const VECTOR2D &a, const VECTOR2D &b, const VECTOR2D
|
||||
}
|
||||
|
||||
|
||||
void SCH_PAINTER::draw( const LIB_SYMBOL *aSymbol, int aLayer, bool aDrawFields, int aUnit,
|
||||
void SCH_PAINTER::draw( const LIB_SYMBOL* aSymbol, int aLayer, bool aDrawFields, int aUnit,
|
||||
int aConvert, bool aDimmed )
|
||||
{
|
||||
if( !aUnit )
|
||||
@@ -751,7 +754,11 @@ bool SCH_PAINTER::setDeviceColors( const LIB_ITEM* aItem, int aLayer, bool aDimm
|
||||
{
|
||||
COLOR4D fillColour = shape->GetFillColor();
|
||||
|
||||
if( aDimmed )
|
||||
if( m_schSettings.m_OverrideItemColors )
|
||||
{
|
||||
fillColour = getRenderColor( aItem, LAYER_DEVICE_BACKGROUND, false, aDimmed );
|
||||
}
|
||||
else if( aDimmed )
|
||||
{
|
||||
fillColour = fillColour.Mix(
|
||||
m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ), 0.5f );
|
||||
@@ -928,7 +935,7 @@ void SCH_PAINTER::draw( const LIB_SHAPE *aShape, int aLayer, bool aDimmed )
|
||||
}
|
||||
|
||||
|
||||
void SCH_PAINTER::draw( const LIB_FIELD *aField, int aLayer, bool aDimmed )
|
||||
void SCH_PAINTER::draw( const LIB_FIELD* aField, int aLayer, bool aDimmed )
|
||||
{
|
||||
bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
|
||||
|
||||
@@ -1704,7 +1711,7 @@ void SCH_PAINTER::drawDanglingSymbol( const VECTOR2I& aPos, const COLOR4D& aColo
|
||||
}
|
||||
|
||||
|
||||
void SCH_PAINTER::draw( const SCH_JUNCTION *aJct, int aLayer )
|
||||
void SCH_PAINTER::draw( const SCH_JUNCTION* aJct, int aLayer )
|
||||
{
|
||||
bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
|
||||
|
||||
@@ -1936,7 +1943,6 @@ void SCH_PAINTER::draw( const SCH_SHAPE* aShape, int aLayer )
|
||||
void SCH_PAINTER::draw( const SCH_TEXT* aText, int aLayer )
|
||||
{
|
||||
bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
|
||||
bool drawingDangling = aLayer == LAYER_DANGLING;
|
||||
|
||||
if( drawingShadows && !( aText->IsBrightened() || aText->IsSelected() ) )
|
||||
return;
|
||||
@@ -1972,18 +1978,6 @@ void SCH_PAINTER::draw( const SCH_TEXT* aText, int aLayer )
|
||||
return;
|
||||
}
|
||||
|
||||
if( drawingDangling )
|
||||
{
|
||||
if( aText->IsDangling() )
|
||||
{
|
||||
drawDanglingSymbol( aText->GetTextPos(), color,
|
||||
schIUScale.MilsToIU( DANGLING_SYMBOL_SIZE / 2 ), true,
|
||||
drawingShadows, aText->IsBrightened() );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_gal->SetStrokeColor( color );
|
||||
m_gal->SetFillColor( color );
|
||||
|
||||
@@ -2507,9 +2501,10 @@ void SCH_PAINTER::draw( const SCH_FIELD* aField, int aLayer, bool aDimmed )
|
||||
}
|
||||
|
||||
|
||||
void SCH_PAINTER::draw( const SCH_GLOBALLABEL *aLabel, int aLayer )
|
||||
void SCH_PAINTER::draw( const SCH_GLOBALLABEL* aLabel, int aLayer )
|
||||
{
|
||||
bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
|
||||
bool drawingDangling = aLayer == LAYER_DANGLING;
|
||||
|
||||
if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children )
|
||||
{
|
||||
@@ -2525,6 +2520,18 @@ void SCH_PAINTER::draw( const SCH_GLOBALLABEL *aLabel, int aLayer )
|
||||
|
||||
COLOR4D color = getRenderColor( aLabel, LAYER_GLOBLABEL, drawingShadows );
|
||||
|
||||
if( drawingDangling )
|
||||
{
|
||||
if( aLabel->IsDangling() )
|
||||
{
|
||||
drawDanglingSymbol( aLabel->GetTextPos(), color,
|
||||
schIUScale.MilsToIU( DANGLING_SYMBOL_SIZE / 2 ), true,
|
||||
drawingShadows, aLabel->IsBrightened() );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<VECTOR2I> pts;
|
||||
std::deque<VECTOR2D> pts2;
|
||||
|
||||
@@ -2533,46 +2540,30 @@ void SCH_PAINTER::draw( const SCH_GLOBALLABEL *aLabel, int aLayer )
|
||||
for( const VECTOR2I& p : pts )
|
||||
pts2.emplace_back( VECTOR2D( p.x, p.y ) );
|
||||
|
||||
// The text is drawn inside the graphic shape.
|
||||
// On Cairo the graphic shape is filled by the background before drawing the text.
|
||||
// However if the text is selected, it is draw twice: first on LAYER_SELECTION_SHADOWS
|
||||
// and second on the text layer. The second must not erase the first drawing.
|
||||
bool fillBg = ( ( aLayer == LAYER_SELECTION_SHADOWS ) || !aLabel->IsSelected() )
|
||||
&& aLayer != LAYER_DANGLING;
|
||||
m_gal->SetIsFill( fillBg );
|
||||
m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) );
|
||||
m_gal->SetIsStroke( true );
|
||||
m_gal->SetLineWidth( getTextThickness( aLabel ) );
|
||||
m_gal->SetLineWidth( getLineWidth( aLabel, drawingShadows ) );
|
||||
m_gal->SetStrokeColor( color );
|
||||
m_gal->DrawPolyline( pts2 );
|
||||
|
||||
draw( static_cast<const SCH_TEXT*>( aLabel ), aLayer );
|
||||
}
|
||||
|
||||
|
||||
void SCH_PAINTER::draw( const SCH_LABEL *aLabel, int aLayer )
|
||||
{
|
||||
bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
|
||||
|
||||
if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children )
|
||||
if( drawingShadows )
|
||||
{
|
||||
for( const SCH_FIELD& field : aLabel->GetFields() )
|
||||
draw( &field, aLayer, false );
|
||||
m_gal->SetIsFill( eeconfig()->m_Selection.fill_shapes );
|
||||
m_gal->SetFillColor( color );
|
||||
m_gal->DrawPolygon( pts2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_gal->SetIsFill( false );
|
||||
m_gal->DrawPolyline( pts2 );
|
||||
}
|
||||
|
||||
if( isFieldsLayer( aLayer ) )
|
||||
return;
|
||||
|
||||
if( drawingShadows && !( aLabel->IsBrightened() || aLabel->IsSelected() ) )
|
||||
return;
|
||||
|
||||
draw( static_cast<const SCH_TEXT*>( aLabel ), aLayer );
|
||||
}
|
||||
|
||||
|
||||
void SCH_PAINTER::draw( const SCH_HIERLABEL *aLabel, int aLayer )
|
||||
void SCH_PAINTER::draw( const SCH_LABEL* aLabel, int aLayer )
|
||||
{
|
||||
bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
|
||||
bool drawingDangling = aLayer == LAYER_DANGLING;
|
||||
|
||||
if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children )
|
||||
{
|
||||
@@ -2588,6 +2579,53 @@ void SCH_PAINTER::draw( const SCH_HIERLABEL *aLabel, int aLayer )
|
||||
|
||||
COLOR4D color = getRenderColor( aLabel, LAYER_HIERLABEL, drawingShadows );
|
||||
|
||||
if( drawingDangling )
|
||||
{
|
||||
if( aLabel->IsDangling() )
|
||||
{
|
||||
drawDanglingSymbol( aLabel->GetTextPos(), color,
|
||||
schIUScale.MilsToIU( DANGLING_SYMBOL_SIZE / 2 ), true,
|
||||
drawingShadows, aLabel->IsBrightened() );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
draw( static_cast<const SCH_TEXT*>( aLabel ), aLayer );
|
||||
}
|
||||
|
||||
|
||||
void SCH_PAINTER::draw( const SCH_HIERLABEL* aLabel, int aLayer )
|
||||
{
|
||||
bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
|
||||
bool drawingDangling = aLayer == LAYER_DANGLING;
|
||||
|
||||
if( !( drawingShadows || drawingDangling ) || eeconfig()->m_Selection.draw_selected_children )
|
||||
{
|
||||
for( const SCH_FIELD& field : aLabel->GetFields() )
|
||||
draw( &field, aLayer, false );
|
||||
}
|
||||
|
||||
if( isFieldsLayer( aLayer ) )
|
||||
return;
|
||||
|
||||
if( drawingShadows && !( aLabel->IsBrightened() || aLabel->IsSelected() ) )
|
||||
return;
|
||||
|
||||
COLOR4D color = getRenderColor( aLabel, LAYER_HIERLABEL, drawingShadows );
|
||||
|
||||
if( drawingDangling )
|
||||
{
|
||||
if( aLabel->IsDangling() )
|
||||
{
|
||||
drawDanglingSymbol( aLabel->GetTextPos(), color,
|
||||
schIUScale.MilsToIU( DANGLING_SYMBOL_SIZE / 2 ), true,
|
||||
drawingShadows, aLabel->IsBrightened() );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_schematic )
|
||||
{
|
||||
SCH_CONNECTION* conn = nullptr;
|
||||
@@ -2610,7 +2648,7 @@ void SCH_PAINTER::draw( const SCH_HIERLABEL *aLabel, int aLayer )
|
||||
m_gal->SetIsFill( true );
|
||||
m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) );
|
||||
m_gal->SetIsStroke( true );
|
||||
m_gal->SetLineWidth( getTextThickness( aLabel ) );
|
||||
m_gal->SetLineWidth( getLineWidth( aLabel, drawingShadows ) );
|
||||
m_gal->SetStrokeColor( color );
|
||||
m_gal->DrawPolyline( pts2 );
|
||||
|
||||
@@ -2618,7 +2656,7 @@ void SCH_PAINTER::draw( const SCH_HIERLABEL *aLabel, int aLayer )
|
||||
}
|
||||
|
||||
|
||||
void SCH_PAINTER::draw( const SCH_DIRECTIVE_LABEL *aLabel, int aLayer )
|
||||
void SCH_PAINTER::draw( const SCH_DIRECTIVE_LABEL* aLabel, int aLayer )
|
||||
{
|
||||
bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
|
||||
|
||||
@@ -2688,53 +2726,14 @@ void SCH_PAINTER::draw( const SCH_SHEET *aSheet, int aLayer )
|
||||
{
|
||||
for( const SCH_FIELD& field : aSheet->GetFields() )
|
||||
draw( &field, aLayer, false );
|
||||
|
||||
for( SCH_SHEET_PIN* sheetPin : aSheet->GetPins() )
|
||||
draw( static_cast<SCH_HIERLABEL*>( sheetPin ), aLayer );
|
||||
}
|
||||
|
||||
if( isFieldsLayer( aLayer ) )
|
||||
return;
|
||||
|
||||
if( aLayer == LAYER_HIERLABEL || aLayer == LAYER_SELECTION_SHADOWS )
|
||||
{
|
||||
for( SCH_SHEET_PIN* sheetPin : aSheet->GetPins() )
|
||||
{
|
||||
if( drawingShadows )
|
||||
{
|
||||
if( ( aSheet->IsBrightened() || aSheet->IsSelected() )
|
||||
&& eeconfig()->m_Selection.draw_selected_children )
|
||||
{
|
||||
// fall through to draw
|
||||
}
|
||||
else if( sheetPin->IsBrightened() || sheetPin->IsSelected() )
|
||||
{
|
||||
// fall through to draw
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
int width = std::max( aSheet->GetPenWidth(), m_schSettings.GetDefaultPenWidth() );
|
||||
VECTOR2I initial_pos = sheetPin->GetTextPos();
|
||||
VECTOR2I offset_pos = initial_pos;
|
||||
|
||||
// For aesthetic reasons, the SHEET_PIN is drawn with a small offset of width / 2
|
||||
switch( sheetPin->GetSide() )
|
||||
{
|
||||
case SHEET_SIDE::TOP: offset_pos.y += KiROUND( width / 2.0 ); break;
|
||||
case SHEET_SIDE::BOTTOM: offset_pos.y -= KiROUND( width / 2.0 ); break;
|
||||
case SHEET_SIDE::RIGHT: offset_pos.x -= KiROUND( width / 2.0 ); break;
|
||||
case SHEET_SIDE::LEFT: offset_pos.x += KiROUND( width / 2.0 ); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
sheetPin->SetTextPos( offset_pos );
|
||||
draw( static_cast<SCH_HIERLABEL*>( sheetPin ), aLayer );
|
||||
m_gal->DrawLine( offset_pos, initial_pos );
|
||||
sheetPin->SetTextPos( initial_pos );
|
||||
}
|
||||
}
|
||||
|
||||
VECTOR2D pos = aSheet->GetPosition();
|
||||
VECTOR2D size = aSheet->GetSize();
|
||||
|
||||
@@ -2759,7 +2758,7 @@ void SCH_PAINTER::draw( const SCH_SHEET *aSheet, int aLayer )
|
||||
}
|
||||
|
||||
|
||||
void SCH_PAINTER::draw( const SCH_NO_CONNECT *aNC, int aLayer )
|
||||
void SCH_PAINTER::draw( const SCH_NO_CONNECT* aNC, int aLayer )
|
||||
{
|
||||
bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
|
||||
|
||||
@@ -2838,7 +2837,7 @@ void SCH_PAINTER::draw( const SCH_BUS_ENTRY_BASE *aEntry, int aLayer )
|
||||
}
|
||||
|
||||
|
||||
void SCH_PAINTER::draw( const SCH_BITMAP *aBitmap, int aLayer )
|
||||
void SCH_PAINTER::draw( const SCH_BITMAP* aBitmap, int aLayer )
|
||||
{
|
||||
m_gal->Save();
|
||||
m_gal->Translate( aBitmap->GetPosition() );
|
||||
@@ -2883,7 +2882,7 @@ void SCH_PAINTER::draw( const SCH_BITMAP *aBitmap, int aLayer )
|
||||
}
|
||||
|
||||
|
||||
void SCH_PAINTER::draw( const SCH_MARKER *aMarker, int aLayer )
|
||||
void SCH_PAINTER::draw( const SCH_MARKER* aMarker, int aLayer )
|
||||
{
|
||||
bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
|
||||
|
||||
|
||||
@@ -110,6 +110,8 @@ public:
|
||||
|
||||
void SetIsDangling( bool isDangling ) { m_isDangling = isDangling; }
|
||||
|
||||
void SetLibPin( LIB_PIN* aLibPin ) { m_libPin = aLibPin; }
|
||||
|
||||
/**
|
||||
* @param aPin Comparison Pin
|
||||
* @return True if aPin is stacked with this pin
|
||||
|
||||
@@ -274,7 +274,7 @@ ASCH_TEXT_FRAME::ASCH_TEXT_FRAME( const std::map<wxString, wxString>& aProps )
|
||||
AreaColor = ALTIUM_PARSER::ReadInt( aProps, "AREACOLOR", 0 );
|
||||
BorderColor = ALTIUM_PARSER::ReadInt( aProps, "COLOR", 0 );
|
||||
|
||||
IsSolid = ALTIUM_PARSER::ReadBool( aProps, "WORDWRAP", true );
|
||||
IsSolid = ALTIUM_PARSER::ReadBool( aProps, "ISSOLID", false );
|
||||
|
||||
Alignment = ReadEnum<ASCH_TEXT_FRAME_ALIGNMENT>( aProps, "ALIGNMENT", 1, 3,
|
||||
ASCH_TEXT_FRAME_ALIGNMENT::LEFT );
|
||||
@@ -331,13 +331,8 @@ ASCH_POLYLINE::ASCH_POLYLINE( const std::map<wxString, wxString>& aProps )
|
||||
LineWidth = ReadKiCadUnitFrac( aProps, "LINEWIDTH" );
|
||||
Color = ALTIUM_PARSER::ReadInt( aProps, "COLOR", 0 );
|
||||
|
||||
int linestyleVar = ALTIUM_PARSER::ReadInt( aProps, "LINESTYLEEXT", 0 );
|
||||
|
||||
// overwrite if present.
|
||||
linestyleVar = ALTIUM_PARSER::ReadInt( aProps, "LINESTYLE", linestyleVar );
|
||||
LineStyle = linestyleVar >= 0 && linestyleVar <= 3 ?
|
||||
static_cast<ASCH_POLYLINE_LINESTYLE>( linestyleVar ) :
|
||||
ASCH_POLYLINE_LINESTYLE::SOLID;
|
||||
auto lineStyleExt = ReadEnum( aProps, "LINESTYLEEXT", 0, 3, ASCH_POLYLINE_LINESTYLE::SOLID );
|
||||
LineStyle = ReadEnum( aProps, "LINESTYLE", 0, 3, lineStyleExt ); // overwrite if present.
|
||||
}
|
||||
|
||||
|
||||
@@ -447,7 +442,11 @@ ASCH_LINE::ASCH_LINE( const std::map<wxString, wxString>& aProps )
|
||||
point2 = VECTOR2I( ReadKiCadUnitFrac( aProps, "CORNER.X" ),
|
||||
-ReadKiCadUnitFrac( aProps, "CORNER.Y" ) );
|
||||
|
||||
lineWidth = ReadKiCadUnitFrac( aProps, "LINEWIDTH" );
|
||||
LineWidth = ReadKiCadUnitFrac( aProps, "LINEWIDTH" );
|
||||
Color = ALTIUM_PARSER::ReadInt( aProps, "COLOR", 0 );
|
||||
|
||||
auto lineStyleExt = ReadEnum( aProps, "LINESTYLEEXT", 0, 3, ASCH_POLYLINE_LINESTYLE::SOLID );
|
||||
LineStyle = ReadEnum( aProps, "LINESTYLE", 0, 3, lineStyleExt ); // overwrite if present.
|
||||
}
|
||||
|
||||
|
||||
@@ -679,8 +678,6 @@ ASCH_BUS::ASCH_BUS( const std::map<wxString, wxString>& aProps )
|
||||
{
|
||||
wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::BUS );
|
||||
|
||||
indexinsheet = ALTIUM_PARSER::ReadInt( aProps, "INDEXINSHEET", 0 );
|
||||
|
||||
int locationcount = ALTIUM_PARSER::ReadInt( aProps, "LOCATIONCOUNT", 0 );
|
||||
|
||||
for( int i = 1; i <= locationcount; i++ )
|
||||
@@ -698,8 +695,6 @@ ASCH_WIRE::ASCH_WIRE( const std::map<wxString, wxString>& aProps )
|
||||
{
|
||||
wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::WIRE );
|
||||
|
||||
indexinsheet = ALTIUM_PARSER::ReadInt( aProps, "INDEXINSHEET", 0 );
|
||||
|
||||
int locationcount = ALTIUM_PARSER::ReadInt( aProps, "LOCATIONCOUNT", 0 );
|
||||
|
||||
for( int i = 1; i <= locationcount; i++ )
|
||||
@@ -800,6 +795,11 @@ ASCH_SHEET::ASCH_SHEET( const std::map<wxString, wxString>& aProps )
|
||||
for( int i = 1; i <= fontidcount; i++ )
|
||||
fonts.emplace_back( aProps, i );
|
||||
|
||||
useCustomSheet = ALTIUM_PARSER::ReadBool( aProps, "USECUSTOMSHEET", false );
|
||||
|
||||
customSize = VECTOR2I( ReadKiCadUnitFrac( aProps, "CUSTOMX" ),
|
||||
ReadKiCadUnitFrac( aProps, "CUSTOMY" ) );
|
||||
|
||||
sheetSize = ReadEnum<ASCH_SHEET_SIZE>( aProps, "SHEETSTYLE", 0, 17, ASCH_SHEET_SIZE::A4 );
|
||||
sheetOrientation = ReadEnum<ASCH_SHEET_WORKSPACEORIENTATION>(
|
||||
aProps, "WORKSPACEORIENTATION", 0, 1, ASCH_SHEET_WORKSPACEORIENTATION::LANDSCAPE );
|
||||
|
||||
@@ -437,7 +437,10 @@ struct ASCH_LINE
|
||||
VECTOR2I point1;
|
||||
VECTOR2I point2;
|
||||
|
||||
int lineWidth;
|
||||
int LineWidth;
|
||||
int Color;
|
||||
|
||||
ASCH_POLYLINE_LINESTYLE LineStyle;
|
||||
|
||||
explicit ASCH_LINE( const std::map<wxString, wxString>& aProps );
|
||||
};
|
||||
@@ -773,6 +776,9 @@ struct ASCH_SHEET
|
||||
{
|
||||
std::vector<ASCH_SHEET_FONT> fonts;
|
||||
|
||||
bool useCustomSheet;
|
||||
VECTOR2I customSize;
|
||||
|
||||
ASCH_SHEET_SIZE sheetSize;
|
||||
ASCH_SHEET_WORKSPACEORIENTATION sheetOrientation;
|
||||
|
||||
|
||||
@@ -1743,7 +1743,10 @@ void SCH_ALTIUM_PLUGIN::ParseLine( const std::map<wxString, wxString>& aProperti
|
||||
// close polygon
|
||||
SCH_LINE* line = new SCH_LINE( elem.point1 + m_sheetOffset, SCH_LAYER_ID::LAYER_NOTES );
|
||||
line->SetEndPoint( elem.point2 + m_sheetOffset );
|
||||
line->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); // TODO?
|
||||
|
||||
COLOR4D color = GetColorFromInt( elem.Color );
|
||||
line->SetStroke( STROKE_PARAMS( elem.LineWidth, GetPlotDashType( elem.LineStyle ),
|
||||
color == PUREBLUE ? COLOR4D::UNSPECIFIED : color ) );
|
||||
|
||||
line->SetFlags( IS_NEW );
|
||||
screen->Append( line );
|
||||
@@ -1773,7 +1776,9 @@ void SCH_ALTIUM_PLUGIN::ParseLine( const std::map<wxString, wxString>& aProperti
|
||||
line->AddPoint( GetRelativePosition( elem.point1 + m_sheetOffset, symbol ) );
|
||||
line->AddPoint( GetRelativePosition( elem.point2 + m_sheetOffset, symbol ) );
|
||||
|
||||
line->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) );
|
||||
COLOR4D color = GetColorFromInt( elem.Color );
|
||||
line->SetStroke( STROKE_PARAMS( elem.LineWidth, GetPlotDashType( elem.LineStyle ),
|
||||
color == PUREBLUE ? COLOR4D::UNSPECIFIED : color ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2788,27 +2793,36 @@ void SCH_ALTIUM_PLUGIN::ParseSheet( const std::map<wxString, wxString>& aPropert
|
||||
|
||||
bool isPortrait = m_altiumSheet->sheetOrientation == ASCH_SHEET_WORKSPACEORIENTATION::PORTRAIT;
|
||||
|
||||
switch( m_altiumSheet->sheetSize )
|
||||
if( m_altiumSheet->useCustomSheet )
|
||||
{
|
||||
default:
|
||||
case ASCH_SHEET_SIZE::A4: pageInfo.SetType( "A4", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::A3: pageInfo.SetType( "A3", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::A2: pageInfo.SetType( "A2", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::A1: pageInfo.SetType( "A1", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::A0: pageInfo.SetType( "A0", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::A: pageInfo.SetType( "A", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::B: pageInfo.SetType( "B", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::C: pageInfo.SetType( "C", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::D: pageInfo.SetType( "D", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::E: pageInfo.SetType( "E", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::LETTER: pageInfo.SetType( "USLetter", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::LEGAL: pageInfo.SetType( "USLegal", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::TABLOID: pageInfo.SetType( "A3", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::ORCAD_A: pageInfo.SetType( "A", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::ORCAD_B: pageInfo.SetType( "B", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::ORCAD_C: pageInfo.SetType( "C", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::ORCAD_D: pageInfo.SetType( "D", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::ORCAD_E: pageInfo.SetType( "E", isPortrait ); break;
|
||||
PAGE_INFO::SetCustomWidthMils( schIUScale.IUToMils( m_altiumSheet->customSize.x ) );
|
||||
PAGE_INFO::SetCustomHeightMils( schIUScale.IUToMils( m_altiumSheet->customSize.y ) );
|
||||
pageInfo.SetType( PAGE_INFO::Custom, isPortrait );
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( m_altiumSheet->sheetSize )
|
||||
{
|
||||
default:
|
||||
case ASCH_SHEET_SIZE::A4: pageInfo.SetType( "A4", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::A3: pageInfo.SetType( "A3", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::A2: pageInfo.SetType( "A2", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::A1: pageInfo.SetType( "A1", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::A0: pageInfo.SetType( "A0", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::A: pageInfo.SetType( "A", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::B: pageInfo.SetType( "B", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::C: pageInfo.SetType( "C", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::D: pageInfo.SetType( "D", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::E: pageInfo.SetType( "E", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::LETTER: pageInfo.SetType( "USLetter", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::LEGAL: pageInfo.SetType( "USLegal", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::TABLOID: pageInfo.SetType( "A3", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::ORCAD_A: pageInfo.SetType( "A", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::ORCAD_B: pageInfo.SetType( "B", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::ORCAD_C: pageInfo.SetType( "C", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::ORCAD_D: pageInfo.SetType( "D", isPortrait ); break;
|
||||
case ASCH_SHEET_SIZE::ORCAD_E: pageInfo.SetType( "E", isPortrait ); break;
|
||||
}
|
||||
}
|
||||
|
||||
screen->SetPageSettings( pageInfo );
|
||||
|
||||
@@ -192,6 +192,11 @@ LIB_SYMBOL* SCH_SEXPR_PARSER::ParseSymbol( LIB_SYMBOL_MAP& aSymbolLibMap, int aF
|
||||
|
||||
name = FromUTF8();
|
||||
|
||||
// Some symbol LIB_IDs have the '/' character escaped which can break derived symbol links.
|
||||
// The '/' character is no longer an illegal LIB_ID character so it doesn't need to be
|
||||
// escaped.
|
||||
name.Replace( wxS( "{slash}" ), wxT( "/" ) );
|
||||
|
||||
LIB_ID id;
|
||||
int bad_pos = id.Parse( name );
|
||||
|
||||
@@ -268,6 +273,12 @@ LIB_SYMBOL* SCH_SEXPR_PARSER::ParseSymbol( LIB_SYMBOL_MAP& aSymbolLibMap, int aF
|
||||
}
|
||||
|
||||
name = FromUTF8();
|
||||
|
||||
// Some symbol LIB_IDs have the '/' character escaped which can break derived
|
||||
// symbol links. The '/' character is no longer an illegal LIB_ID character so
|
||||
// it doesn't need to be escaped.
|
||||
name.Replace( wxS( "{slash}" ), wxT( "/" ) );
|
||||
|
||||
auto it = aSymbolLibMap.find( name );
|
||||
|
||||
if( it == aSymbolLibMap.end() )
|
||||
@@ -293,6 +304,11 @@ LIB_SYMBOL* SCH_SEXPR_PARSER::ParseSymbol( LIB_SYMBOL_MAP& aSymbolLibMap, int aF
|
||||
|
||||
name = FromUTF8();
|
||||
|
||||
// Some symbol LIB_IDs have the '/' character escaped which can break derived
|
||||
// symbol links. The '/' character is no longer an illegal LIB_ID character so
|
||||
// it doesn't need to be escaped.
|
||||
name.Replace( wxS( "{slash}" ), wxT( "/" ) );
|
||||
|
||||
if( !name.StartsWith( m_symbolName ) )
|
||||
{
|
||||
error.Printf( _( "Invalid symbol unit name prefix %s" ), name.c_str() );
|
||||
@@ -2593,6 +2609,11 @@ SCH_SYMBOL* SCH_SEXPR_PARSER::parseSchematicSymbol()
|
||||
}
|
||||
|
||||
libName = FromUTF8();
|
||||
// Some symbol LIB_IDs or lib_name have the '/' character escaped which can break
|
||||
// symbol links. The '/' character is no longer an illegal LIB_ID character so
|
||||
// it doesn't need to be escaped.
|
||||
libName.Replace( "{slash}", "/" );
|
||||
|
||||
NeedRIGHT();
|
||||
break;
|
||||
}
|
||||
@@ -2606,6 +2627,11 @@ SCH_SYMBOL* SCH_SEXPR_PARSER::parseSchematicSymbol()
|
||||
|
||||
LIB_ID libId;
|
||||
wxString name = FromUTF8();
|
||||
// Some symbol LIB_IDs have the '/' character escaped which can break
|
||||
// symbol links. The '/' character is no longer an illegal LIB_ID character so
|
||||
// it doesn't need to be escaped.
|
||||
name.Replace( "{slash}", "/" );
|
||||
|
||||
int bad_pos = libId.Parse( name );
|
||||
|
||||
if( bad_pos >= 0 )
|
||||
|
||||
@@ -1495,6 +1495,13 @@ LIB_SYMBOL* SCH_SEXPR_PLUGIN::LoadSymbol( const wxString& aLibraryPath, const wx
|
||||
if( it == m_cache->m_symbols.end() && aSymbolName.Contains( '/' ) )
|
||||
it = m_cache->m_symbols.find( EscapeString( aSymbolName, CTX_LEGACY_LIBID ) );
|
||||
|
||||
if( it == m_cache->m_symbols.end() && aSymbolName.Contains( wxT( "{slash}" ) ) )
|
||||
{
|
||||
wxString unescaped = aSymbolName;
|
||||
unescaped.Replace( wxT( "{slash}" ), wxT( "/" ) );
|
||||
it = m_cache->m_symbols.find( unescaped );
|
||||
}
|
||||
|
||||
if( it == m_cache->m_symbols.end() )
|
||||
return nullptr;
|
||||
|
||||
|
||||
@@ -353,6 +353,8 @@ void SCH_LEGACY_PLUGIN::LoadContent( LINE_READER& aReader, SCH_SCREEN* aScreen,
|
||||
aScreen->Append( loadText( aReader ) );
|
||||
else if( strCompare( "BusAlias", line ) )
|
||||
aScreen->AddBusAlias( loadBusAlias( aReader, aScreen ) );
|
||||
else if( strCompare( "Kmarq", line ) )
|
||||
continue; // Ignore legacy (until 2009) ERC marker entry
|
||||
else if( strCompare( "$EndSCHEMATC", line ) )
|
||||
return;
|
||||
else
|
||||
|
||||
@@ -652,8 +652,7 @@ void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId, int
|
||||
}
|
||||
|
||||
// Remove aAdditionalRefs references
|
||||
for( size_t i = originalSize; i < ( aAdditionalRefs.GetCount() + originalSize ); i++ )
|
||||
RemoveItem( originalSize );
|
||||
m_flatList.erase( m_flatList.begin() + originalSize, m_flatList.end() );
|
||||
|
||||
wxASSERT( originalSize == GetCount() ); // Make sure we didn't make a mistake
|
||||
}
|
||||
|
||||
+42
-15
@@ -63,6 +63,12 @@
|
||||
#include "sch_bus_entry.h"
|
||||
#include "sim/sim_model_ideal.h"
|
||||
|
||||
/*
|
||||
* Flag to enable profiling of the TestDanglingEnds() function.
|
||||
* @ingroup trace_env_vars
|
||||
*/
|
||||
static const wxChar DanglingProfileMask[] = wxT( "DANGLING_PROFILE" );
|
||||
|
||||
SCH_SCREEN::SCH_SCREEN( EDA_ITEM* aParent ) :
|
||||
BASE_SCREEN( aParent, SCH_SCREEN_T ),
|
||||
m_fileFormatVersionAtLoad( 0 ),
|
||||
@@ -835,7 +841,7 @@ bool SCH_SCREEN::IsTerminalPoint( const VECTOR2I& aPosition, int aLayer ) const
|
||||
|
||||
label = GetLabel( aPosition );
|
||||
|
||||
if( label && label->IsConnected( aPosition ) )
|
||||
if( label && !label->IsNew() && label->IsConnected( aPosition ) )
|
||||
return true;
|
||||
|
||||
break;
|
||||
@@ -847,7 +853,7 @@ bool SCH_SCREEN::IsTerminalPoint( const VECTOR2I& aPosition, int aLayer ) const
|
||||
break;
|
||||
|
||||
case LAYER_WIRE:
|
||||
if( GetItem( aPosition, 1, SCH_BUS_WIRE_ENTRY_T) )
|
||||
if( GetItem( aPosition, 1, SCH_BUS_WIRE_ENTRY_T ) )
|
||||
return true;
|
||||
|
||||
if( GetItem( aPosition, 1, SCH_JUNCTION_T ) )
|
||||
@@ -861,7 +867,7 @@ bool SCH_SCREEN::IsTerminalPoint( const VECTOR2I& aPosition, int aLayer ) const
|
||||
|
||||
label = GetLabel( aPosition, 1 );
|
||||
|
||||
if( label && label->IsConnected( aPosition ) )
|
||||
if( label && !label->IsNew() && label->IsConnected( aPosition ) )
|
||||
return true;
|
||||
|
||||
sheetPin = GetSheetPin( aPosition );
|
||||
@@ -1168,12 +1174,14 @@ void SCH_SCREEN::Plot( PLOTTER* aPlotter ) const
|
||||
item->Plot( aPlotter, background );
|
||||
}
|
||||
|
||||
// Plot the background items
|
||||
for( const SCH_ITEM* item : other )
|
||||
{
|
||||
aPlotter->SetCurrentLineWidth( std::max( item->GetPenWidth(), defaultPenWidth ) );
|
||||
item->Plot( aPlotter, background );
|
||||
}
|
||||
|
||||
// Plot the foreground items
|
||||
for( const SCH_ITEM* item : other )
|
||||
{
|
||||
aPlotter->SetCurrentLineWidth( std::max( item->GetPenWidth(), defaultPenWidth ) );
|
||||
@@ -1187,7 +1195,10 @@ void SCH_SCREEN::Plot( PLOTTER* aPlotter ) const
|
||||
aPlotter->SetCurrentLineWidth( std::max( sym->GetPenWidth(), defaultPenWidth ) );
|
||||
|
||||
for( SCH_FIELD field : sym->GetFields() )
|
||||
{
|
||||
field.ClearRenderCache();
|
||||
field.Plot( aPlotter, false );
|
||||
}
|
||||
|
||||
sym->PlotPins( aPlotter );
|
||||
|
||||
@@ -1355,24 +1366,40 @@ void SCH_SCREEN::GetSheets( std::vector<SCH_ITEM*>* aItems ) const
|
||||
void SCH_SCREEN::TestDanglingEnds( const SCH_SHEET_PATH* aPath,
|
||||
std::function<void( SCH_ITEM* )>* aChangedHandler ) const
|
||||
{
|
||||
PROF_TIMER timer( __FUNCTION__ );
|
||||
|
||||
std::vector<DANGLING_END_ITEM> endPoints;
|
||||
|
||||
auto getends =
|
||||
[&]( SCH_ITEM* item )
|
||||
{
|
||||
if( item->IsConnectable() )
|
||||
item->GetEndPoints( endPoints );
|
||||
};
|
||||
auto update_state =
|
||||
[&]( SCH_ITEM* item )
|
||||
{
|
||||
if( item->UpdateDanglingState( endPoints, aPath ) )
|
||||
{
|
||||
if( aChangedHandler )
|
||||
(*aChangedHandler)( item );
|
||||
}
|
||||
};
|
||||
|
||||
for( SCH_ITEM* item : Items() )
|
||||
{
|
||||
if( item->IsConnectable() )
|
||||
{
|
||||
endPoints.clear();
|
||||
|
||||
for( SCH_ITEM* overlapping : Items().Overlapping( item->GetBoundingBox() ) )
|
||||
overlapping->GetEndPoints( endPoints );
|
||||
|
||||
if( item->UpdateDanglingState( endPoints, aPath ) )
|
||||
{
|
||||
if( aChangedHandler )
|
||||
(*aChangedHandler)( item );
|
||||
}
|
||||
}
|
||||
getends( item );
|
||||
item->RunOnChildren( getends );
|
||||
}
|
||||
|
||||
for( SCH_ITEM* item : Items() )
|
||||
{
|
||||
update_state( item );
|
||||
item->RunOnChildren( update_state );
|
||||
}
|
||||
if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
|
||||
timer.Show();
|
||||
}
|
||||
|
||||
|
||||
|
||||
+19
-19
@@ -347,19 +347,17 @@ void SCH_SHEET::SwapData( SCH_ITEM* aItem )
|
||||
void SCH_SHEET::SetFields( const std::vector<SCH_FIELD>& aFields )
|
||||
{
|
||||
m_fields = aFields;
|
||||
int next_id = SHEET_MANDATORY_FIELDS;
|
||||
|
||||
for( int ii = 0; ii < int( m_fields.size() ); )
|
||||
{
|
||||
if( m_fields[ii].GetId() < 0 || m_fields[ii].GetId() >= ssize_t( m_fields.size() ) )
|
||||
m_fields[ii].SetId( next_id++ );
|
||||
// Ensure that mandatory fields are at the beginning
|
||||
std::sort( m_fields.begin(), m_fields.end(),
|
||||
[]( const SCH_FIELD& a, const SCH_FIELD& b )
|
||||
{
|
||||
return a.GetId() < b.GetId();
|
||||
} );
|
||||
|
||||
if( m_fields[ii].GetId() != ii )
|
||||
std::swap( m_fields[ii], m_fields[m_fields[ii].GetId()]);
|
||||
|
||||
if( m_fields[ii].GetId() == ii )
|
||||
++ii;
|
||||
}
|
||||
// After mandatory fields, the rest should be sequential user fields
|
||||
for( int ii = SHEET_MANDATORY_FIELDS; ii < static_cast<int>( m_fields.size() ); ++ii )
|
||||
m_fields[ii].SetId( ii );
|
||||
|
||||
// Make sure that we get the UNIX variant of the file path
|
||||
SetFileName( m_fields[SHEETFILENAME].GetText() );
|
||||
@@ -648,14 +646,16 @@ void SCH_SHEET::AutoplaceFields( SCH_SCREEN* aScreen, bool /* aManual */ )
|
||||
|
||||
void SCH_SHEET::ViewGetLayers( int aLayers[], int& aCount ) const
|
||||
{
|
||||
aCount = 7;
|
||||
aLayers[0] = LAYER_HIERLABEL;
|
||||
aLayers[1] = LAYER_SHEETNAME;
|
||||
aLayers[2] = LAYER_SHEETFILENAME;
|
||||
aLayers[3] = LAYER_SHEETFIELDS;
|
||||
aLayers[4] = LAYER_SHEET;
|
||||
aLayers[5] = LAYER_SHEET_BACKGROUND;
|
||||
aLayers[6] = LAYER_SELECTION_SHADOWS;
|
||||
aCount = 8;
|
||||
aLayers[0] = LAYER_DANGLING; // Sheet pins are drawn by their parent sheet, so the
|
||||
// parent needs to draw to LAYER_DANGLING
|
||||
aLayers[1] = LAYER_HIERLABEL;
|
||||
aLayers[2] = LAYER_SHEETNAME;
|
||||
aLayers[3] = LAYER_SHEETFILENAME;
|
||||
aLayers[4] = LAYER_SHEETFIELDS;
|
||||
aLayers[5] = LAYER_SHEET;
|
||||
aLayers[6] = LAYER_SHEET_BACKGROUND;
|
||||
aLayers[7] = LAYER_SELECTION_SHADOWS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1045,15 +1045,15 @@ SCH_SHEET_PATH* SCH_SHEET_LIST::FindSheetForPath( const SCH_SHEET_PATH* aPath )
|
||||
}
|
||||
|
||||
|
||||
SCH_SHEET_PATH* SCH_SHEET_LIST::FindSheetForScreen( const SCH_SCREEN* aScreen )
|
||||
SCH_SHEET_PATH SCH_SHEET_LIST::FindSheetForScreen( const SCH_SCREEN* aScreen )
|
||||
{
|
||||
for( SCH_SHEET_PATH& sheetpath : *this )
|
||||
{
|
||||
if( sheetpath.LastScreen() == aScreen )
|
||||
return &sheetpath;
|
||||
return sheetpath;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return SCH_SHEET_PATH();
|
||||
}
|
||||
|
||||
|
||||
@@ -1302,3 +1302,14 @@ int SCH_SHEET_LIST::GetLastVirtualPageNumber() const
|
||||
return lastVirtualPageNumber;
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SHEET_LIST::HasPath( const KIID_PATH& aPath ) const
|
||||
{
|
||||
for( const SCH_SHEET_PATH& path : *this )
|
||||
{
|
||||
if( path.Path() == aPath )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -573,10 +573,10 @@ public:
|
||||
SCH_SHEET_PATH* FindSheetForPath( const SCH_SHEET_PATH* aPath );
|
||||
|
||||
/**
|
||||
* Return a pointer to the first #SCH_SHEET_PATH object (not necessarily the only one) using
|
||||
* a particular screen.
|
||||
* Return the first #SCH_SHEET_PATH object (not necessarily the only one) using a particular
|
||||
* screen.
|
||||
*/
|
||||
SCH_SHEET_PATH* FindSheetForScreen( const SCH_SCREEN* aScreen );
|
||||
SCH_SHEET_PATH FindSheetForScreen( const SCH_SCREEN* aScreen );
|
||||
|
||||
/**
|
||||
* Return a #SCH_SHEET_LIST with a copy of all the #SCH_SHEET_PATH using a particular screen.
|
||||
@@ -672,6 +672,8 @@ public:
|
||||
|
||||
void RemoveSymbolInstances( const SCH_SHEET_PATH& aPrefixSheetPath );
|
||||
|
||||
bool HasPath( const KIID_PATH& aPath ) const;
|
||||
|
||||
private:
|
||||
SCH_SHEET_PATH m_currentSheetPath;
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user