Compare commits
175 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 ) );
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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.8" )
|
||||
|
||||
# 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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 )
|
||||
|
||||
+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();
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -898,7 +898,7 @@ std::shared_ptr<SHAPE_COMPOUND> EDA_TEXT::GetEffectiveTextShape( bool aTriangula
|
||||
attrs.m_Angle = GetDrawRotation();
|
||||
|
||||
if( font->IsOutline() )
|
||||
cache = GetRenderCache( font, shownText, drawPos );
|
||||
cache = GetRenderCache( font, shownText, VECTOR2I() );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -47,7 +47,6 @@ wxString FONTCONFIG::Version()
|
||||
|
||||
FONTCONFIG::FONTCONFIG()
|
||||
{
|
||||
(void) FcInitLoadConfigAndFonts();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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
-10
@@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -434,6 +434,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( "/../" ) );
|
||||
|
||||
@@ -479,6 +479,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
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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() ) );
|
||||
|
||||
+213
-165
@@ -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,79 @@ 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;
|
||||
};
|
||||
|
||||
auto strong_cmp = [this]( SCH_ITEM* a, SCH_ITEM* b ) -> bool
|
||||
{
|
||||
const wxString& a_name = GetNameForDriver( a );
|
||||
const wxString& b_name = GetNameForDriver( b );
|
||||
return a_name < b_name;
|
||||
};
|
||||
|
||||
PRIORITY highest_priority = PRIORITY::INVALID;
|
||||
std::set<SCH_ITEM*, decltype( candidate_cmp )> candidates( candidate_cmp );
|
||||
std::set<SCH_ITEM*, decltype( strong_cmp )> strong_drivers( strong_cmp );
|
||||
|
||||
m_driver = nullptr;
|
||||
|
||||
@@ -88,17 +156,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 +196,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 +207,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 +225,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,7 +234,10 @@ 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;
|
||||
}
|
||||
|
||||
aSubgraphs.insert( sg );
|
||||
aSubgraphs.insert( sg->m_absorbed_subgraphs.begin(), sg->m_absorbed_subgraphs.end() );
|
||||
@@ -356,9 +360,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 +433,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 +513,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 +555,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 +598,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 +610,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 +647,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 +676,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 +778,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 +871,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 +959,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 )
|
||||
@@ -1637,10 +1663,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 +1808,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 +1828,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 +2212,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 +2419,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 +2873,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 +2908,6 @@ bool CONNECTION_GRAPH::ercCheckMultipleDrivers( const CONNECTION_SUBGRAPH* aSubg
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -86,9 +86,7 @@ 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;
|
||||
@@ -130,7 +128,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 +160,8 @@ public:
|
||||
return PRIORITY::NONE;
|
||||
}
|
||||
|
||||
void RemoveItem( SCH_ITEM* aItem );
|
||||
|
||||
private:
|
||||
wxString driverName( SCH_ITEM* aItem ) const;
|
||||
|
||||
@@ -206,9 +206,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 +237,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 +251,6 @@ 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;
|
||||
|
||||
/// 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" ) );
|
||||
|
||||
@@ -185,6 +185,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>" ) );
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -638,6 +638,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 +699,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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 )
|
||||
|
||||
+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;
|
||||
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
+37
-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 );
|
||||
@@ -1355,24 +1361,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;
|
||||
};
|
||||
|
||||
+47
-2
@@ -1154,6 +1154,10 @@ void SCH_SYMBOL::GetContextualTextVars( wxArrayString* aVars ) const
|
||||
aVars->push_back( wxT( "EXCLUDE_FROM_BOM" ) );
|
||||
aVars->push_back( wxT( "EXCLUDE_FROM_BOARD" ) );
|
||||
aVars->push_back( wxT( "DNP" ) );
|
||||
aVars->push_back( wxT( "SHORT_NET_NAME(<pin_number>)" ) );
|
||||
aVars->push_back( wxT( "NET_NAME(<pin_number>)" ) );
|
||||
aVars->push_back( wxT( "NET_CLASS(<pin_number>)" ) );
|
||||
aVars->push_back( wxT( "PIN_NAME(<pin_number>)" ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -1217,7 +1221,11 @@ bool SCH_SYMBOL::ResolveTextVar( wxString* token, int aDepth, const SCH_SHEET_PA
|
||||
|
||||
wxArrayString parts = wxSplit( footprint, ':' );
|
||||
|
||||
*token = parts[ 0 ];
|
||||
if( parts.Count() > 0 )
|
||||
*token = parts[ 0 ];
|
||||
else
|
||||
*token = wxEmptyString;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if( token->IsSameAs( wxT( "FOOTPRINT_NAME" ) ) )
|
||||
@@ -1228,7 +1236,11 @@ bool SCH_SYMBOL::ResolveTextVar( wxString* token, int aDepth, const SCH_SHEET_PA
|
||||
|
||||
wxArrayString parts = wxSplit( footprint, ':' );
|
||||
|
||||
*token = parts[ std::min( 1, (int) parts.size() - 1 ) ];
|
||||
if( parts.Count() > 1 )
|
||||
*token = parts[ std::min( 1, (int) parts.size() - 1 ) ];
|
||||
else
|
||||
*token = wxEmptyString;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if( token->IsSameAs( wxT( "UNIT" ) ) )
|
||||
@@ -1275,6 +1287,39 @@ bool SCH_SYMBOL::ResolveTextVar( wxString* token, int aDepth, const SCH_SHEET_PA
|
||||
*token = this->GetDNP() ? _( "DNP" ) : wxT( "" );
|
||||
return true;
|
||||
}
|
||||
else if( token->StartsWith( wxT( "SHORT_NET_NAME(" ) )
|
||||
|| token->StartsWith( wxT( "NET_NAME(" ) )
|
||||
|| token->StartsWith( wxT( "NET_CLASS(" ) )
|
||||
|| token->StartsWith( wxT( "PIN_NAME(" ) ) )
|
||||
{
|
||||
wxString pinNumber = token->AfterFirst( '(' );
|
||||
pinNumber = pinNumber.BeforeLast( ')' );
|
||||
|
||||
for( SCH_PIN* pin : GetPins( aPath ) )
|
||||
{
|
||||
if( pin->GetNumber() == pinNumber )
|
||||
{
|
||||
if( token->StartsWith( wxT( "PIN_NAME" ) ) )
|
||||
{
|
||||
*token = pin->GetAlt().IsEmpty() ? pin->GetName() : pin->GetAlt();
|
||||
return true;
|
||||
}
|
||||
|
||||
SCH_CONNECTION* conn = pin->Connection( aPath );
|
||||
|
||||
if( !conn )
|
||||
*token = wxEmptyString;
|
||||
else if( token->StartsWith( wxT( "SHORT_NET_NAME" ) ) )
|
||||
*token = conn->LocalName();
|
||||
else if( token->StartsWith( wxT( "NET_NAME" ) ) )
|
||||
*token = conn->Name();
|
||||
else if( token->StartsWith( wxT( "NET_CLASS" ) ) )
|
||||
*token = pin->GetEffectiveNetClass( aPath )->GetName();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See if parent can resolve it (this will recurse to ancestors)
|
||||
|
||||
|
||||
@@ -301,7 +301,7 @@ void SCH_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
|
||||
}
|
||||
else if( status == UNDO_REDO::PAGESETTINGS )
|
||||
{
|
||||
SCH_SHEET_PATH& undoSheet = *m_schematic->GetSheets().FindSheetForScreen( screen );
|
||||
SCH_SHEET_PATH undoSheet = m_schematic->GetSheets().FindSheetForScreen( screen );
|
||||
|
||||
if( GetCurrentSheet() != undoSheet )
|
||||
{
|
||||
@@ -339,8 +339,8 @@ void SCH_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
|
||||
|
||||
if( field->GetId() == REFERENCE_FIELD )
|
||||
{
|
||||
symbol->SetRef( m_schematic->GetSheets().FindSheetForScreen( screen ),
|
||||
field->GetText() );
|
||||
SCH_SHEET_PATH sheet = m_schematic->GetSheets().FindSheetForScreen( screen );
|
||||
symbol->SetRef( &sheet, field->GetText() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -281,10 +281,8 @@ void SYMBOL_LIB_TABLE::Format( OUTPUTFORMATTER* aOutput, int aIndentLevel ) cons
|
||||
aOutput->Print( aIndentLevel, "(sym_lib_table\n" );
|
||||
aOutput->Print( aIndentLevel + 1, "(version %d)\n", m_version );
|
||||
|
||||
for( LIB_TABLE_ROWS_CITER it = m_rows.begin(); it != m_rows.end(); ++it )
|
||||
{
|
||||
it->Format( aOutput, aIndentLevel+1 );
|
||||
}
|
||||
for( const LIB_TABLE_ROW& row : m_rows )
|
||||
row.Format( aOutput, aIndentLevel + 1 );
|
||||
|
||||
aOutput->Print( aIndentLevel, ")\n" );
|
||||
}
|
||||
@@ -359,7 +357,9 @@ void SYMBOL_LIB_TABLE::LoadSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
|
||||
const wxString& aNickname, bool aPowerSymbolsOnly )
|
||||
{
|
||||
SYMBOL_LIB_TABLE_ROW* row = FindRow( aNickname, true );
|
||||
wxCHECK( row && row->plugin, /* void */ );
|
||||
|
||||
if( !row || !row->plugin )
|
||||
return;
|
||||
|
||||
std::lock_guard<std::mutex> lock( row->GetMutex() );
|
||||
|
||||
|
||||
@@ -1150,7 +1150,7 @@ void EE_SELECTION_TOOL::GuessSelectionCandidates( EE_COLLECTOR& collector, const
|
||||
}
|
||||
}
|
||||
|
||||
text->GetEffectiveTextShape( false )->Collide( poss, closestDist, &dist );
|
||||
text->GetEffectiveTextShape( false )->Collide( poss, INT_MAX / 2, &dist );
|
||||
}
|
||||
else if( symbol )
|
||||
{
|
||||
|
||||
@@ -149,8 +149,6 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
|
||||
auto addSymbol =
|
||||
[&]( SCH_SYMBOL* aSymbol )
|
||||
{
|
||||
m_frame->SaveCopyForRepeatItem( aSymbol );
|
||||
|
||||
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
|
||||
m_selectionTool->AddItemToSel( aSymbol );
|
||||
|
||||
@@ -343,6 +341,8 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
|
||||
if( m_frame->eeconfig()->m_AutoplaceFields.enable )
|
||||
symbol->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
|
||||
|
||||
m_frame->SaveCopyForRepeatItem( symbol );
|
||||
|
||||
symbol->ClearEditFlags();
|
||||
m_view->Update( symbol );
|
||||
m_frame->GetScreen()->Update( symbol );
|
||||
|
||||
@@ -1574,6 +1574,9 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
|
||||
std::map<KIID, EDA_ITEM*> itemMap;
|
||||
hierarchy.FillItemMap( itemMap );
|
||||
|
||||
// Keep track of updated library symbols
|
||||
std::map<LIB_SYMBOL*, LIB_SYMBOL*> libItemMap;
|
||||
|
||||
// Keep track of pasted sheets and symbols for the different paths to the hierarchy.
|
||||
std::map<SCH_SHEET_PATH, SCH_REFERENCE_LIST> pastedSymbols;
|
||||
std::map<SCH_SHEET_PATH, SCH_SHEET_LIST> pastedSheets;
|
||||
@@ -1768,8 +1771,18 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
|
||||
item->SetFlags( STARTPOINT | ENDPOINT );
|
||||
|
||||
item->SetFlags( IS_NEW | IS_PASTED | IS_MOVING );
|
||||
LIB_SYMBOL* libItem = nullptr;
|
||||
SCH_SYMBOL* sym = dyn_cast<SCH_SYMBOL*>( item );
|
||||
|
||||
if( sym )
|
||||
libItem = sym->GetLibSymbolRef().get();
|
||||
|
||||
m_frame->AddItemToScreenAndUndoList( m_frame->GetScreen(), (SCH_ITEM*) item, i > 0 );
|
||||
|
||||
// Keep track of updated library symbols
|
||||
if( libItem && sym )
|
||||
libItemMap[libItem] = sym->GetLibSymbolRef().get();
|
||||
|
||||
// Reset flags for subsequent move operation
|
||||
item->SetFlags( IS_NEW | IS_PASTED | IS_MOVING );
|
||||
|
||||
@@ -1819,6 +1832,14 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
|
||||
|| pasteMode == PASTE_MODE::RESPECT_OPTIONS
|
||||
|| pastedSymbols[sheetPath][i].AlwaysAnnotate() )
|
||||
{
|
||||
LIB_SYMBOL* libItem = pastedSymbols[sheetPath][i].GetLibPart();
|
||||
auto it = libItemMap.find( libItem );
|
||||
|
||||
if( it != libItemMap.end() )
|
||||
pastedSymbols[sheetPath][i] = SCH_REFERENCE( pastedSymbols[sheetPath][i].GetSymbol(),
|
||||
it->second,
|
||||
pastedSymbols[sheetPath][i].GetSheetPath() );
|
||||
|
||||
annotatedSymbols[sheetPath].AddItem( pastedSymbols[sheetPath][i] );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,6 +381,7 @@ int SCH_LINE_WIRE_BUS_TOOL::UnfoldBus( const TOOL_EVENT& aEvent )
|
||||
SCH_LINE* SCH_LINE_WIRE_BUS_TOOL::doUnfoldBus( const wxString& aNet, const VECTOR2I& aPos )
|
||||
{
|
||||
SCHEMATIC_SETTINGS& cfg = getModel<SCHEMATIC>()->Settings();
|
||||
SCH_SCREEN* screen = m_frame->GetScreen();
|
||||
|
||||
VECTOR2I pos = aPos;
|
||||
|
||||
@@ -390,7 +391,7 @@ SCH_LINE* SCH_LINE_WIRE_BUS_TOOL::doUnfoldBus( const wxString& aNet, const VECTO
|
||||
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
|
||||
|
||||
m_busUnfold.entry = new SCH_BUS_WIRE_ENTRY( pos );
|
||||
m_busUnfold.entry->SetParent( m_frame->GetScreen() );
|
||||
m_busUnfold.entry->SetParent( screen );
|
||||
m_frame->AddToScreen( m_busUnfold.entry, m_frame->GetScreen() );
|
||||
|
||||
m_busUnfold.label = new SCH_LABEL( m_busUnfold.entry->GetEnd(), aNet );
|
||||
@@ -405,6 +406,15 @@ SCH_LINE* SCH_LINE_WIRE_BUS_TOOL::doUnfoldBus( const wxString& aNet, const VECTO
|
||||
|
||||
getViewControls()->SetCrossHairCursorPosition( m_busUnfold.entry->GetEnd(), false );
|
||||
|
||||
std::vector<DANGLING_END_ITEM> endPoints;
|
||||
|
||||
for( SCH_ITEM* item : screen->Items().Overlapping( m_busUnfold.entry->GetBoundingBox() ) )
|
||||
item->GetEndPoints( endPoints );
|
||||
|
||||
m_busUnfold.entry->UpdateDanglingState( endPoints );
|
||||
m_busUnfold.entry->SetEndDangling( false );
|
||||
m_busUnfold.label->SetIsDangling( false );
|
||||
|
||||
return startSegments( LAYER_WIRE, m_busUnfold.entry->GetEnd() );
|
||||
}
|
||||
|
||||
|
||||
@@ -924,6 +924,9 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
for( EDA_ITEM* item : selection )
|
||||
updateItem( item, true );
|
||||
|
||||
if( selection.GetSize() == 1 && selection.Front()->IsNew() )
|
||||
m_frame->SaveCopyForRepeatItem( static_cast<SCH_ITEM*>( selection.Front() ) );
|
||||
|
||||
m_selectionTool->RemoveItemsFromSel( &m_dragAdditions, QUIET_MODE );
|
||||
|
||||
// If we move items away from a junction, we _may_ want to add a junction there
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2007-2014 Jean-Pierre Charras jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2007-2023 Jean-Pierre Charras jp.charras at wanadoo.fr
|
||||
* 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
|
||||
@@ -182,7 +182,13 @@ void GBR_TO_PCB_EXPORTER::export_non_copper_item( const GERBER_DRAW_ITEM* aGbrIt
|
||||
case GBR_SPOT_POLY:
|
||||
case GBR_SPOT_MACRO:
|
||||
d_codeDescr->ConvertShapeToPolygon( aGbrItem );
|
||||
writePcbPolygon( d_codeDescr->m_Polygon, aLayer, aGbrItem->GetABPosition( seg_start ) );
|
||||
{
|
||||
SHAPE_POLY_SET polyshape = d_codeDescr->m_Polygon;
|
||||
|
||||
// Compensate the Y axis orientation ( writePcbPolygon invert the Y coordinate )
|
||||
polyshape.Outline( 0 ).Mirror( false, true );
|
||||
writePcbPolygon( polyshape, aLayer, aGbrItem->GetABPosition( seg_start ) );
|
||||
}
|
||||
break;
|
||||
|
||||
case GBR_ARC:
|
||||
|
||||
@@ -30,8 +30,6 @@
|
||||
|
||||
class DIALOG_GRID_SETTINGS : public DIALOG_GRID_SETTINGS_BASE
|
||||
{
|
||||
EDA_DRAW_FRAME* m_parent;
|
||||
|
||||
public:
|
||||
/// This has no dependencies on calling wxFrame derivative, such as PCB_BASE_FRAME.
|
||||
DIALOG_GRID_SETTINGS( EDA_DRAW_FRAME* aParent );
|
||||
@@ -44,10 +42,13 @@ private:
|
||||
|
||||
void RebuildGridSizes();
|
||||
|
||||
UNIT_BINDER m_gridOriginX;
|
||||
UNIT_BINDER m_gridOriginY;
|
||||
UNIT_BINDER m_userGridX;
|
||||
UNIT_BINDER m_userGridY;
|
||||
private:
|
||||
EDA_DRAW_FRAME* m_parent;
|
||||
|
||||
UNIT_BINDER m_gridOriginX;
|
||||
UNIT_BINDER m_gridOriginY;
|
||||
UNIT_BINDER m_userGridX;
|
||||
UNIT_BINDER m_userGridY;
|
||||
};
|
||||
|
||||
#endif // DIALOG_GRID_SETTINGS_H
|
||||
|
||||
+33
-80
@@ -328,13 +328,7 @@ public:
|
||||
virtual ~LIB_TABLE();
|
||||
|
||||
/// Delete all rows.
|
||||
void Clear()
|
||||
{
|
||||
std::lock_guard<std::shared_mutex> lock( m_nickIndexMutex );
|
||||
|
||||
m_rows.clear();
|
||||
m_nickIndex.clear();
|
||||
}
|
||||
void Clear();
|
||||
|
||||
/**
|
||||
* Compares this table against another.
|
||||
@@ -444,23 +438,30 @@ public:
|
||||
bool InsertRow( LIB_TABLE_ROW* aRow, bool doReplace = false );
|
||||
|
||||
/**
|
||||
* Removes a row from the table.
|
||||
* Removes a row from the table and frees the pointer
|
||||
* @param aRow is the row to remove
|
||||
* @return true if the row was found (and removed)
|
||||
*/
|
||||
bool RemoveRow( const LIB_TABLE_ROW* aRow )
|
||||
{
|
||||
for( auto iter = m_rows.begin(); iter != m_rows.end(); ++iter )
|
||||
{
|
||||
if( *iter == *aRow )
|
||||
{
|
||||
m_rows.erase( iter, iter + 1 );
|
||||
reindex();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool RemoveRow( const LIB_TABLE_ROW* aRow );
|
||||
|
||||
/**
|
||||
* Replaces the Nth row with the given new row
|
||||
* @return true if successful
|
||||
*/
|
||||
bool ReplaceRow( size_t aIndex, LIB_TABLE_ROW* aRow );
|
||||
|
||||
/**
|
||||
* Moves a row within the table
|
||||
* @param aIndex is the current index of the row to move
|
||||
* @param aOffset is the number of positions to move it by in the table
|
||||
* @return true if the move resulted in a change
|
||||
*/
|
||||
bool ChangeRowOrder( size_t aIndex, int aOffset );
|
||||
|
||||
/**
|
||||
* Takes ownership of another list of rows; the original list will be freed
|
||||
*/
|
||||
void TransferRows( LIB_TABLE_ROWS& aRowsList );
|
||||
|
||||
/**
|
||||
* @return a #LIB_TABLE_ROW pointer if \a aURI is found in this table or in any chained
|
||||
@@ -521,18 +522,6 @@ public:
|
||||
return m_version;
|
||||
}
|
||||
|
||||
/**
|
||||
* While this is an encapsulation leak, calling it before threaded loads *may* prevent
|
||||
* some Sentry crashes we're seeing (KICAD-4S).
|
||||
*/
|
||||
void EnsureIndex()
|
||||
{
|
||||
ensureIndex();
|
||||
|
||||
if( m_fallBack )
|
||||
m_fallBack->EnsureIndex();
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Return a #LIB_TABLE_ROW if \a aNickname is found in this table or in any chained
|
||||
@@ -552,60 +541,24 @@ protected:
|
||||
*/
|
||||
bool migrate();
|
||||
|
||||
/**
|
||||
* Rebuilds the m_nickIndex
|
||||
*
|
||||
* @param aForce is to avoid rebuilding the index multiple times because multiple threads hit ensureIndex
|
||||
* at the same time
|
||||
*/
|
||||
void reindex()
|
||||
{
|
||||
std::lock_guard<std::shared_mutex> lock( m_nickIndexMutex );
|
||||
|
||||
m_nickIndex.clear();
|
||||
|
||||
for( LIB_TABLE_ROWS_ITER it = m_rows.begin(); it != m_rows.end(); ++it )
|
||||
m_nickIndex.insert( INDEX_VALUE( it->GetNickName(), it - m_rows.begin() ) );
|
||||
}
|
||||
|
||||
void ensureIndex()
|
||||
{
|
||||
// The dialog lib table editor may not maintain the nickIndex.
|
||||
// Lazy indexing may be required. To handle lazy indexing, we must enforce
|
||||
// that "nickIndex" is either empty or accurate, but never inaccurate.
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> lock( m_nickIndexMutex );
|
||||
|
||||
if( m_nickIndex.size() )
|
||||
return;
|
||||
}
|
||||
|
||||
reindex();
|
||||
}
|
||||
|
||||
private:
|
||||
friend class PANEL_FP_LIB_TABLE;
|
||||
friend class LIB_TABLE_GRID;
|
||||
void reindex();
|
||||
|
||||
protected:
|
||||
LIB_TABLE_ROWS m_rows;
|
||||
|
||||
/// this is a non-owning index into the LIB_TABLE_ROWS table
|
||||
typedef std::map<wxString,int> INDEX; // "int" is std::vector array index
|
||||
typedef INDEX::iterator INDEX_ITER;
|
||||
typedef INDEX::const_iterator INDEX_CITER;
|
||||
typedef INDEX::value_type INDEX_VALUE;
|
||||
|
||||
/// this particular key is the nickName within each row.
|
||||
INDEX m_nickIndex;
|
||||
|
||||
LIB_TABLE* m_fallBack;
|
||||
|
||||
/// Versioning to handle importing old tables
|
||||
mutable int m_version;
|
||||
|
||||
/// Mutex to protect access to the nickIndex variable
|
||||
mutable std::shared_mutex m_nickIndexMutex;
|
||||
/// Owning set of rows.
|
||||
// TODO: This should really be private; but the lib table grids re-use it
|
||||
// (without using m_rowsMap).
|
||||
LIB_TABLE_ROWS m_rows;
|
||||
|
||||
/// this is a non-owning index into the LIB_TABLE_ROWS table
|
||||
std::map<wxString, LIB_TABLE_ROWS_ITER> m_rowsMap;
|
||||
|
||||
/// Mutex to protect access to the rows vector
|
||||
mutable std::shared_mutex m_mutex;
|
||||
};
|
||||
|
||||
#endif // _LIB_TABLE_BASE_H_
|
||||
|
||||
@@ -101,10 +101,9 @@ public:
|
||||
void SortNodes();
|
||||
|
||||
/**
|
||||
* Compare two nodes. Returns negative if aNode1 < aNode2, zero if aNode1 ==
|
||||
* aNode2, or positive if aNode1 > aNode2.
|
||||
* Compare two nodes. Returns true if aNode1 < aNode2.
|
||||
*/
|
||||
static int Compare( LIB_TREE_NODE const& aNode1, LIB_TREE_NODE const& aNode2 );
|
||||
static bool Compare( LIB_TREE_NODE const& aNode1, LIB_TREE_NODE const& aNode2 );
|
||||
|
||||
LIB_TREE_NODE();
|
||||
virtual ~LIB_TREE_NODE() {}
|
||||
|
||||
@@ -170,6 +170,13 @@ public:
|
||||
static wxString GetOSXKicadDataDir();
|
||||
#endif
|
||||
|
||||
#ifdef __WXWINDOWS__
|
||||
/**
|
||||
* @return The macOS specific bundle data directory for KiCad
|
||||
*/
|
||||
static wxString GetWindowsFontConfigDir();
|
||||
#endif
|
||||
|
||||
private:
|
||||
// we are a static helper
|
||||
PATHS() {}
|
||||
|
||||
@@ -67,14 +67,7 @@ struct lineTypeStruct
|
||||
/*
|
||||
* Conversion map between PLOT_DASH_TYPE values and style names displayed
|
||||
*/
|
||||
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 } }
|
||||
};
|
||||
extern const std::map<PLOT_DASH_TYPE, struct lineTypeStruct> lineTypeNames;
|
||||
|
||||
|
||||
#define DEFAULT_STYLE _( "Default" )
|
||||
|
||||
@@ -221,6 +221,10 @@ public:
|
||||
|
||||
///< Used to inform tool that it should display the disambiguation menu
|
||||
const static TOOL_EVENT DisambiguatePoint;
|
||||
|
||||
const static TOOL_EVENT UndoRedoPreEvent;
|
||||
const static TOOL_EVENT UndoRedoPostEvent;
|
||||
|
||||
};
|
||||
|
||||
#endif // __ACTIONS_H
|
||||
|
||||
@@ -24,8 +24,7 @@
|
||||
#ifndef WIDGETS_GAL_OPTIONS_PANEL__H_
|
||||
#define WIDGETS_GAL_OPTIONS_PANEL__H_
|
||||
|
||||
#include <wx/panel.h>
|
||||
|
||||
#include <../../common/widgets/gal_options_panel_base.h>
|
||||
#include <gal/gal_display_options.h>
|
||||
|
||||
class wxBoxSizer;
|
||||
@@ -37,7 +36,8 @@ class wxStaticText;
|
||||
class EDA_DRAW_FRAME;
|
||||
class APP_SETTINGS_BASE;
|
||||
|
||||
class GAL_OPTIONS_PANEL: public wxPanel
|
||||
|
||||
class GAL_OPTIONS_PANEL: public GAL_OPTIONS_PANEL_BASE
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -56,28 +56,7 @@ public:
|
||||
bool ResetPanel( APP_SETTINGS_BASE* aAppSettings );
|
||||
|
||||
private:
|
||||
wxBoxSizer* m_mainSizer;
|
||||
|
||||
#ifndef __WXMAC__
|
||||
wxRadioBox* m_renderingEngine;
|
||||
#endif
|
||||
|
||||
wxRadioBox* m_gridStyle;
|
||||
wxStaticText* l_gridLineWidth;
|
||||
wxSpinCtrlDouble* m_gridLineWidth;
|
||||
wxStaticText* l_gridLineWidthUnits;
|
||||
|
||||
wxStaticText* l_gridMinSpacing;
|
||||
wxSpinCtrlDouble* m_gridMinSpacing;
|
||||
wxStaticText* l_gridMinSpacingUnits;
|
||||
|
||||
wxStaticText* l_gridSnapOptions;
|
||||
wxChoice* m_gridSnapOptions;
|
||||
wxStaticText* l_gridSnapSpace;
|
||||
|
||||
wxRadioBox* m_cursorShape;
|
||||
wxCheckBox* m_forceCursorDisplay;
|
||||
|
||||
std::vector<double> m_gridThicknessList; // List of available grid thickness
|
||||
APP_SETTINGS_BASE* m_cfg;
|
||||
};
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#define ARG_EXCELLON_MINIMALHEAD "--excellon-min-header"
|
||||
#define ARG_EXCELLON_SEPARATE_TH "--excellon-separate-th"
|
||||
#define ARG_EXCELLON_ZEROS_FORMAT "--excellon-zeros-format"
|
||||
#define ARG_EXCELLON_OVAL_FORMAT "--excellon-oval-format"
|
||||
#define ARG_GERBER_PRECISION "--gerber-precision"
|
||||
#define ARG_EXCELLON_UNITS "--excellon-units"
|
||||
#define ARG_GENERATE_MAP "--generate-map"
|
||||
@@ -54,6 +55,10 @@ CLI::EXPORT_PCB_DRILL_COMMAND::EXPORT_PCB_DRILL_COMMAND() : EXPORT_PCB_BASE_COMM
|
||||
.help( UTF8STDSTR(
|
||||
_( "Valid options are: decimal,suppressleading,suppresstrailing,keep." ) ) );
|
||||
|
||||
m_argParser.add_argument( ARG_EXCELLON_OVAL_FORMAT )
|
||||
.default_value( std::string( "alternate" ) )
|
||||
.help( UTF8STDSTR( _( "Valid options are: route,alternate." ) ) );
|
||||
|
||||
m_argParser.add_argument( "-u", ARG_EXCELLON_UNITS )
|
||||
.default_value( std::string( "mm" ) )
|
||||
.help( UTF8STDSTR( _( "Output units, valid options:in,mm" ) ) );
|
||||
@@ -160,6 +165,22 @@ int CLI::EXPORT_PCB_DRILL_COMMAND::doPerform( KIWAY& aKiway )
|
||||
return EXIT_CODES::ERR_ARGS;
|
||||
}
|
||||
|
||||
wxString drillFormat =
|
||||
FROM_UTF8( m_argParser.get<std::string>( ARG_EXCELLON_OVAL_FORMAT ).c_str() );
|
||||
if( drillFormat == wxS( "route" ) )
|
||||
{
|
||||
drillJob->m_excellonOvalDrillRoute = true;
|
||||
}
|
||||
else if( drillFormat == wxS( "alternate" ) )
|
||||
{
|
||||
drillJob->m_excellonOvalDrillRoute = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
wxFprintf( stderr, _( "Invalid oval drill format specified\n" ) );
|
||||
return EXIT_CODES::ERR_ARGS;
|
||||
}
|
||||
|
||||
wxString mapFormat = FROM_UTF8( m_argParser.get<std::string>( ARG_MAP_FORMAT ).c_str() );
|
||||
|
||||
if( mapFormat == wxS( "pdf" ) )
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
#include <locale_io.h>
|
||||
|
||||
#define ARG_DRILL_SHAPE_OPTION "--drill-shape-opt"
|
||||
|
||||
|
||||
CLI::EXPORT_PCB_PDF_COMMAND::EXPORT_PCB_PDF_COMMAND() : EXPORT_PCB_BASE_COMMAND( "pdf" )
|
||||
{
|
||||
@@ -67,7 +69,13 @@ CLI::EXPORT_PCB_PDF_COMMAND::EXPORT_PCB_PDF_COMMAND() : EXPORT_PCB_BASE_COMMAND(
|
||||
|
||||
m_argParser.add_argument( "-t", ARG_THEME )
|
||||
.default_value( std::string() )
|
||||
.help( UTF8STDSTR( _( "Color theme to use (will default to pcbnew settings)" ) ) );
|
||||
.help( UTF8STDSTR( _( "Color theme to use (will default to PCB Editor settings)" ) ) );
|
||||
|
||||
m_argParser.add_argument( ARG_DRILL_SHAPE_OPTION )
|
||||
.help( UTF8STDSTR( _( "Set pad/via drill shape option (0 = no shape, 1 = "
|
||||
"small shape, 2 = actual shape)" ) ) )
|
||||
.scan<'i', int>()
|
||||
.default_value( 2 );
|
||||
}
|
||||
|
||||
|
||||
@@ -99,10 +107,12 @@ int CLI::EXPORT_PCB_PDF_COMMAND::doPerform( KIWAY& aKiway )
|
||||
pdfJob->m_colorTheme = FROM_UTF8( m_argParser.get<std::string>( ARG_THEME ).c_str() );
|
||||
pdfJob->m_negative = m_argParser.get<bool>( ARG_NEGATIVE );
|
||||
|
||||
pdfJob->m_drillShapeOption = m_argParser.get<int>( ARG_DRILL_SHAPE_OPTION );
|
||||
|
||||
pdfJob->m_printMaskLayer = m_selectedLayers;
|
||||
|
||||
LOCALE_IO dummy; // Switch to "C" locale
|
||||
int exitCode = aKiway.ProcessJob( KIWAY::FACE_PCB, pdfJob.get() );
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ int CLI::EXPORT_PCB_STEP_COMMAND::doPerform( KIWAY& aKiway )
|
||||
std::smatch sm;
|
||||
std::string str( minDistance.ToUTF8() );
|
||||
std::regex_search( str, sm, re_pattern );
|
||||
step->m_minDistance = atof( sm.str( 1 ).c_str() );
|
||||
step->m_boardOutlinesChainingEpsilon = atof( sm.str( 1 ).c_str() );
|
||||
|
||||
std::string tunit( sm[2] );
|
||||
|
||||
@@ -162,7 +162,7 @@ int CLI::EXPORT_PCB_STEP_COMMAND::doPerform( KIWAY& aKiway )
|
||||
{
|
||||
if( !tunit.compare( "in" ) || !tunit.compare( "inch" ) )
|
||||
{
|
||||
step->m_minDistance *= 25.4;
|
||||
step->m_boardOutlinesChainingEpsilon *= 25.4;
|
||||
}
|
||||
else if( tunit.compare( "mm" ) )
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@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
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#define ARG_EXCLUDE_DRAWING_SHEET "--exclude-drawing-sheet"
|
||||
#define ARG_PAGE_SIZE "--page-size-mode"
|
||||
#define ARG_DRILL_SHAPE_OPTION "--drill-shape-opt"
|
||||
|
||||
|
||||
CLI::EXPORT_PCB_SVG_COMMAND::EXPORT_PCB_SVG_COMMAND() : EXPORT_PCB_BASE_COMMAND( "svg" )
|
||||
@@ -68,6 +69,12 @@ CLI::EXPORT_PCB_SVG_COMMAND::EXPORT_PCB_SVG_COMMAND() : EXPORT_PCB_BASE_COMMAND(
|
||||
.help( UTF8STDSTR( _( "No drawing sheet" ) ) )
|
||||
.implicit_value( true )
|
||||
.default_value( false );
|
||||
|
||||
m_argParser.add_argument( ARG_DRILL_SHAPE_OPTION )
|
||||
.help( UTF8STDSTR( _( "Set pad/via drill shape option (0 = no shape, 1 = "
|
||||
"small shape, 2 = actual shape)" ) ) )
|
||||
.scan<'i', int>()
|
||||
.default_value( 2 );
|
||||
}
|
||||
|
||||
|
||||
@@ -83,6 +90,7 @@ int CLI::EXPORT_PCB_SVG_COMMAND::doPerform( KIWAY& aKiway )
|
||||
svgJob->m_blackAndWhite = m_argParser.get<bool>( ARG_BLACKANDWHITE );
|
||||
svgJob->m_pageSizeMode = m_argParser.get<int>( ARG_PAGE_SIZE );
|
||||
svgJob->m_negative = m_argParser.get<bool>( ARG_NEGATIVE );
|
||||
svgJob->m_drillShapeOption = m_argParser.get<int>( ARG_DRILL_SHAPE_OPTION );
|
||||
|
||||
svgJob->m_filename = FROM_UTF8( m_argParser.get<std::string>( ARG_INPUT ).c_str() );
|
||||
svgJob->m_outputFile = FROM_UTF8( m_argParser.get<std::string>( ARG_OUTPUT ).c_str() );
|
||||
|
||||
@@ -10,6 +10,7 @@ set( KIMATH_SRCS
|
||||
src/geometry/convex_hull.cpp
|
||||
src/geometry/direction_45.cpp
|
||||
src/geometry/geometry_utils.cpp
|
||||
src/geometry/oval.cpp
|
||||
src/geometry/seg.cpp
|
||||
src/geometry/shape.cpp
|
||||
src/geometry/shape_arc.cpp
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 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 Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef GEOMETRY_OVAL_H_
|
||||
#define GEOMETRY_OVAL_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <math/vector2d.h>
|
||||
#include <geometry/eda_angle.h>
|
||||
|
||||
enum OVAL_KEY_POINTS
|
||||
{
|
||||
OVAL_CENTER = 1 << 0,
|
||||
OVAL_CAP_TIPS = 1 << 1,
|
||||
OVAL_CAP_CENTERS = 1 << 2,
|
||||
OVAL_SIDE_MIDPOINTS = 1 << 3,
|
||||
OVAL_SIDE_ENDS = 1 << 4,
|
||||
OVAL_CARDINAL_EXTREMES = 1 << 5,
|
||||
OVAL_ALL_KEY_POINTS = 0xFF
|
||||
};
|
||||
|
||||
using OVAL_KEY_POINT_FLAGS = unsigned int;
|
||||
|
||||
/**
|
||||
* @brief Get a list of interesting points on an oval (rectangle
|
||||
* with semicircular end caps)
|
||||
*
|
||||
* This may includes:
|
||||
* - The middles of the sides
|
||||
* - The tips of the end caps
|
||||
* - The extreme cardinal points of the whole oval (if rotated non-cardinally)
|
||||
*
|
||||
* @param aOvalSize - The size of the oval (overall length and width)
|
||||
* @param aRotation - The rotation of the oval
|
||||
* @param aFlags - The flags indicating which points to return
|
||||
*
|
||||
* @return std::vector<VECTOR2I> - The list of points
|
||||
*/
|
||||
std::vector<VECTOR2I> GetOvalKeyPoints( const VECTOR2I& aOvalSize, const EDA_ANGLE& aRotation,
|
||||
OVAL_KEY_POINT_FLAGS aFlags );
|
||||
|
||||
#endif /* GEOMETRY_OVAL_H_ */
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2014 CERN
|
||||
* Copyright (C) 2018-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "geometry/oval.h"
|
||||
|
||||
#include <trigo.h> // for RotatePoint
|
||||
|
||||
|
||||
std::vector<VECTOR2I> GetOvalKeyPoints( const VECTOR2I& aOvalSize, const EDA_ANGLE& aRotation,
|
||||
OVAL_KEY_POINT_FLAGS aFlags )
|
||||
{
|
||||
const VECTOR2I half_size = aOvalSize / 2;
|
||||
const int half_width = std::min( half_size.x, half_size.y );
|
||||
const int half_len = std::max( half_size.x, half_size.y );
|
||||
|
||||
// Points on a non-rotated pad at the origin, long-axis is y
|
||||
// (so for now, width is left/right, len is up/down)
|
||||
std::vector<VECTOR2I> pts;
|
||||
|
||||
if ( aFlags & OVAL_CENTER )
|
||||
{
|
||||
// Centre is easy
|
||||
pts.emplace_back( 0, 0 );
|
||||
};
|
||||
|
||||
if ( aFlags & OVAL_SIDE_MIDPOINTS )
|
||||
{
|
||||
// Side midpoints
|
||||
pts.emplace_back( half_width, 0 );
|
||||
pts.emplace_back( -half_width, 0 );
|
||||
}
|
||||
|
||||
if ( aFlags & OVAL_CAP_TIPS )
|
||||
{
|
||||
// Cap ends
|
||||
pts.emplace_back( 0, half_len );
|
||||
pts.emplace_back( 0, -half_len );
|
||||
}
|
||||
|
||||
// Distance from centre to cap centres
|
||||
const int d_centre_to_cap_centre = half_len - half_width;
|
||||
|
||||
if ( aFlags & OVAL_CAP_CENTERS )
|
||||
{
|
||||
// Cap centres
|
||||
pts.emplace_back( 0, d_centre_to_cap_centre );
|
||||
pts.emplace_back( 0, -d_centre_to_cap_centre );
|
||||
}
|
||||
|
||||
if ( aFlags & OVAL_SIDE_ENDS )
|
||||
{
|
||||
// End points of flat sides (always vertical)
|
||||
pts.emplace_back( half_width, d_centre_to_cap_centre );
|
||||
pts.emplace_back( half_width, -d_centre_to_cap_centre );
|
||||
pts.emplace_back( -half_width, d_centre_to_cap_centre );
|
||||
pts.emplace_back( -half_width, -d_centre_to_cap_centre );
|
||||
}
|
||||
|
||||
// If the pad is horizontal (i.e. x > y), we'll rotate the whole thing
|
||||
// 90 degrees and work with it as if it was vertical
|
||||
const bool swap_xy = half_size.x > half_size.y;
|
||||
const EDA_ANGLE rotation = aRotation + ( swap_xy ? -ANGLE_90 : ANGLE_0 );
|
||||
|
||||
// Add the quadrant points to the caps only if rotated
|
||||
// (otherwise they're just the tips)
|
||||
if( ( aFlags & OVAL_CARDINAL_EXTREMES ) && !rotation.IsCardinal() )
|
||||
{
|
||||
// We need to find two perpendicular lines from the centres
|
||||
// of each cap to the cap edge, which will hit the points
|
||||
// where the cap is tangent to H/V lines when rotated into place.
|
||||
//
|
||||
// Because we know the oval is always vertical, this means the
|
||||
// two lines are formed between _|, through \/ to |_
|
||||
// where the apex is the cap centre.
|
||||
|
||||
// The vector from a cap centre to the tip (i.e. vertical)
|
||||
const VECTOR2I cap_radial = { 0, half_width };
|
||||
|
||||
// Rotate in the opposite direction to the oval's rotation
|
||||
// (that will be unwound later)
|
||||
EDA_ANGLE radial_line_rotation = -rotation;
|
||||
|
||||
radial_line_rotation.Normalize90();
|
||||
|
||||
VECTOR2I cap_radial_to_x_axis = cap_radial;
|
||||
RotatePoint( cap_radial_to_x_axis, radial_line_rotation );
|
||||
|
||||
// Find the other line - it's 90 degrees away, but re-normalise
|
||||
// as it could be to the left or right
|
||||
radial_line_rotation -= ANGLE_90;
|
||||
radial_line_rotation.Normalize90();
|
||||
|
||||
VECTOR2I cap_radial_to_y_axis = cap_radial;
|
||||
RotatePoint( cap_radial_to_y_axis, radial_line_rotation );
|
||||
|
||||
// The quadrant points are then the relevant offsets from each cap centre
|
||||
pts.emplace_back( VECTOR2I{ 0, d_centre_to_cap_centre } + cap_radial_to_y_axis );
|
||||
pts.emplace_back( VECTOR2I{ 0, d_centre_to_cap_centre } + cap_radial_to_x_axis );
|
||||
// The opposite cap offsets go from the other cap centre, the other way
|
||||
pts.emplace_back( VECTOR2I{ 0, -d_centre_to_cap_centre } - cap_radial_to_y_axis );
|
||||
pts.emplace_back( VECTOR2I{ 0, -d_centre_to_cap_centre } - cap_radial_to_x_axis );
|
||||
}
|
||||
|
||||
for( VECTOR2I& pt : pts )
|
||||
{
|
||||
// Transform to the actual orientation
|
||||
// Already includes the extra 90 to swap x/y if needed
|
||||
RotatePoint( pt, rotation );
|
||||
}
|
||||
|
||||
return pts;
|
||||
}
|
||||
@@ -48,6 +48,13 @@ bool KIPLATFORM::APP::Init()
|
||||
}
|
||||
|
||||
|
||||
bool KIPLATFORM::APP::AttachConsole( bool aTryAlloc )
|
||||
{
|
||||
// Not implemented on this platform
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool KIPLATFORM::APP::IsOperatingSystemUnsupported()
|
||||
{
|
||||
// Not implemented on this platform
|
||||
|
||||
@@ -36,6 +36,14 @@ namespace KIPLATFORM
|
||||
*/
|
||||
bool Init();
|
||||
|
||||
/**
|
||||
* Tries to attach a console window with stdout, stderr and stdin.
|
||||
*
|
||||
* @param aTryAlloc try to allocate the console if cannot attach to it.
|
||||
* @return true if attach successful, false if unsuccessful
|
||||
*/
|
||||
bool AttachConsole( bool aTryAlloc );
|
||||
|
||||
/**
|
||||
* Checks if the Operating System is explicitly unsupported and we want to prevent
|
||||
* users from sending bug reports and show them a disclaimer on startup.
|
||||
|
||||
+67
-37
@@ -35,6 +35,30 @@
|
||||
#include <werapi.h> // issues on msys2
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
extern "C"
|
||||
{
|
||||
// So there exists this malware called Nahimic by A-Volute, which is marketed as an audio enhancement
|
||||
// software. In reality it's an aggressive form of malware that injects itself wildly into every process
|
||||
// on the system for god knows what reason. It even includes a tracking/analytics package, <insert tinfoil hat>
|
||||
// Our problem is this garbage basically bugs out OpenGL (why an audio driver does that, who knows, its made by morons)
|
||||
// And then we get issues reported both in our issue tracker and sentry reports as a result
|
||||
// At least these malware authors were nice to include a dumb "disable" trick where it checks if the exe is exporting
|
||||
// a symbol called NoHotPatch, so here we are.
|
||||
// Hopefully this works and stops the bug reports. Apparently the worst part is this malware aggressively gets reinstalled
|
||||
// by awful low-tier motherboard vendors like MSI, Alienware and others who bundled it into their driver packages
|
||||
// and distributed it over Windows Update
|
||||
// Did I mention they clearly had issues with other apps so instead of fixing their malware, they blacklisted a hundred common
|
||||
// apps and even some games in their own config? Obviously kicad isn't on that blacklist :(
|
||||
// This malware seems to no longer be distributed as Nahimic and replaced with "Sonar" by SteelSeries.
|
||||
// Time will tell if it's the same garbage, I'm not volunteering to install it.
|
||||
__declspec(dllexport) void NoHotPatch()
|
||||
{
|
||||
// this is a intentionally empty function
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool KIPLATFORM::APP::Init()
|
||||
{
|
||||
@@ -60,43 +84,7 @@ bool KIPLATFORM::APP::Init()
|
||||
|
||||
// In order to support GUI and CLI
|
||||
// Let's attach to console when it's possible, or allocate if requested.
|
||||
bool tryAlloc = wxGetEnv( wxS( "KICAD_ALLOC_CONSOLE" ), nullptr );
|
||||
|
||||
HANDLE handle;
|
||||
if( AttachConsole( ATTACH_PARENT_PROCESS ) || ( tryAlloc && AllocConsole() ) )
|
||||
{
|
||||
#if !defined( __MINGW32__ ) // These redirections create problems on mingw:
|
||||
// Nothing is printed to the console
|
||||
|
||||
|
||||
if( GetStdHandle( STD_INPUT_HANDLE ) != INVALID_HANDLE_VALUE )
|
||||
{
|
||||
freopen( "CONIN$", "r", stdin );
|
||||
setvbuf( stdin, NULL, _IONBF, 0 );
|
||||
}
|
||||
|
||||
if( GetStdHandle( STD_OUTPUT_HANDLE ) != INVALID_HANDLE_VALUE )
|
||||
{
|
||||
freopen( "CONOUT$", "w", stdout );
|
||||
setvbuf( stdout, NULL, _IONBF, 0 );
|
||||
}
|
||||
|
||||
if( GetStdHandle( STD_ERROR_HANDLE ) != INVALID_HANDLE_VALUE )
|
||||
{
|
||||
freopen( "CONOUT$", "w", stderr );
|
||||
setvbuf( stderr, NULL, _IONBF, 0 );
|
||||
}
|
||||
#endif
|
||||
|
||||
std::ios::sync_with_stdio( true );
|
||||
|
||||
std::wcout.clear();
|
||||
std::cout.clear();
|
||||
std::wcerr.clear();
|
||||
std::cerr.clear();
|
||||
std::wcin.clear();
|
||||
std::cin.clear();
|
||||
}
|
||||
AttachConsole( wxGetEnv( wxS( "KICAD_ALLOC_CONSOLE" ), nullptr ) );
|
||||
|
||||
// It may be useful to log up to traces in a console, but in Release builds the log level changes to Info
|
||||
// Also we have to force the active target to stderr or else it goes to the void
|
||||
@@ -114,6 +102,48 @@ bool KIPLATFORM::APP::Init()
|
||||
}
|
||||
|
||||
|
||||
bool KIPLATFORM::APP::AttachConsole( bool aTryAlloc )
|
||||
{
|
||||
if( ::AttachConsole( ATTACH_PARENT_PROCESS ) || ( aTryAlloc && ::AllocConsole() ) )
|
||||
{
|
||||
#if !defined( __MINGW32__ ) // These redirections create problems on mingw:
|
||||
// Nothing is printed to the console
|
||||
|
||||
if( ::GetStdHandle( STD_INPUT_HANDLE ) != INVALID_HANDLE_VALUE )
|
||||
{
|
||||
freopen( "CONIN$", "r", stdin );
|
||||
setvbuf( stdin, NULL, _IONBF, 0 );
|
||||
}
|
||||
|
||||
if( ::GetStdHandle( STD_OUTPUT_HANDLE ) != INVALID_HANDLE_VALUE )
|
||||
{
|
||||
freopen( "CONOUT$", "w", stdout );
|
||||
setvbuf( stdout, NULL, _IONBF, 0 );
|
||||
}
|
||||
|
||||
if( ::GetStdHandle( STD_ERROR_HANDLE ) != INVALID_HANDLE_VALUE )
|
||||
{
|
||||
freopen( "CONOUT$", "w", stderr );
|
||||
setvbuf( stderr, NULL, _IONBF, 0 );
|
||||
}
|
||||
#endif
|
||||
|
||||
std::ios::sync_with_stdio( true );
|
||||
|
||||
std::wcout.clear();
|
||||
std::cout.clear();
|
||||
std::wcerr.clear();
|
||||
std::cerr.clear();
|
||||
std::wcin.clear();
|
||||
std::cin.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool KIPLATFORM::APP::IsOperatingSystemUnsupported()
|
||||
{
|
||||
#if defined( PYTHON_VERSION_MAJOR ) && ( ( PYTHON_VERSION_MAJOR == 3 && PYTHON_VERSION_MINOR >= 8 ) \
|
||||
|
||||
@@ -32,6 +32,13 @@ bool KIPLATFORM::APP::Init()
|
||||
}
|
||||
|
||||
|
||||
bool KIPLATFORM::APP::AttachConsole( bool aTryAlloc )
|
||||
{
|
||||
// Not implemented on this platform
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool KIPLATFORM::APP::IsOperatingSystemUnsupported()
|
||||
{
|
||||
// Not implemented on this platform
|
||||
|
||||
+13
-1
@@ -2374,7 +2374,6 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer,
|
||||
{
|
||||
footprint->TransformPadsToPolySet( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
|
||||
|
||||
// Microwave footprints may have items on copper layers
|
||||
footprint->TransformFPShapesToPolySet( aOutlines, aLayer, 0, maxError, ERROR_INSIDE,
|
||||
true, /* include text */
|
||||
true, /* include shapes */
|
||||
@@ -2428,6 +2427,19 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer,
|
||||
break;
|
||||
}
|
||||
|
||||
case PCB_DIM_ALIGNED_T:
|
||||
case PCB_DIM_CENTER_T:
|
||||
case PCB_DIM_RADIAL_T:
|
||||
case PCB_DIM_ORTHOGONAL_T:
|
||||
case PCB_DIM_LEADER_T:
|
||||
{
|
||||
const PCB_DIMENSION_BASE* dim = static_cast<const PCB_DIMENSION_BASE*>( item );
|
||||
|
||||
dim->TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
|
||||
dim->TransformTextToPolySet( aOutlines, 0, maxError, ERROR_INSIDE );
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -616,6 +616,7 @@ void BOARD_STACKUP::BuildDefaultStackupList( const BOARD_DESIGN_SETTINGS* aSetti
|
||||
{
|
||||
const BOARD_STACKUP& source_stackup = aSettings->GetStackupDescriptor();
|
||||
m_EdgeConnectorConstraints = source_stackup.m_EdgeConnectorConstraints;
|
||||
m_HasDielectricConstrains = source_stackup.m_HasDielectricConstrains;
|
||||
m_CastellatedPads = source_stackup.m_CastellatedPads;
|
||||
m_EdgePlating = source_stackup.m_EdgePlating;
|
||||
m_FinishType = source_stackup.m_FinishType;
|
||||
|
||||
@@ -1271,6 +1271,12 @@ bool PANEL_SETUP_BOARD_STACKUP::TransferDataFromWindow()
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if( brd_stackup.m_HasDielectricConstrains != m_impedanceControlled->GetValue() )
|
||||
{
|
||||
brd_stackup.m_HasDielectricConstrains = m_impedanceControlled->GetValue();
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if( !m_brdSettings->m_HasStackup )
|
||||
{
|
||||
m_brdSettings->m_HasStackup = true;
|
||||
|
||||
@@ -524,10 +524,10 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aShapeList, SHAPE_POLY_SE
|
||||
{
|
||||
(*aErrorHandler)( _( "(multiple board outlines not supported)" ), a, b,
|
||||
contours[ contourIndex ].GetPoint( 0 ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aPolygons.AddOutline( contours[ contourIndex ] );
|
||||
@@ -574,9 +574,7 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aShapeList, SHAPE_POLY_SE
|
||||
{
|
||||
BOARD_ITEM* a = fetchOwner( *seg1 );
|
||||
BOARD_ITEM* b = fetchOwner( *seg2 );
|
||||
|
||||
if( a && b )
|
||||
(*aErrorHandler)( _( "(self-intersecting)" ), a, b, ( *seg1 ).A );
|
||||
(*aErrorHandler)( _( "(self-intersecting)" ), a, b, ( *seg1 ).A );
|
||||
}
|
||||
|
||||
selfIntersecting = true;
|
||||
@@ -588,9 +586,7 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aShapeList, SHAPE_POLY_SE
|
||||
{
|
||||
BOARD_ITEM* a = fetchOwner( *seg1 );
|
||||
BOARD_ITEM* b = fetchOwner( *seg2 );
|
||||
|
||||
if( a && b )
|
||||
(*aErrorHandler)( _( "(self-intersecting)" ), a, b, *pt );
|
||||
(*aErrorHandler)( _( "(self-intersecting)" ), a, b, *pt );
|
||||
}
|
||||
|
||||
selfIntersecting = true;
|
||||
|
||||
@@ -195,9 +195,8 @@ void PCB_EDIT_FRAME::OnExportIDF3( wxCommandEvent& event )
|
||||
if( dlg.GetAutoAdjustOffset() )
|
||||
{
|
||||
BOX2I bbox = GetBoard()->GetBoardEdgesBoundingBox();
|
||||
|
||||
aXRef = bbox.Centre().x * pcbIUScale.MM_PER_IU;
|
||||
aYRef = bbox.Centre().y * pcbIUScale.MM_PER_IU;
|
||||
aXRef = pcbIUScale.IUTomm( bbox.GetCenter().x );
|
||||
aYRef = pcbIUScale.IUTomm( bbox.GetCenter().y );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2022 Kicad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2023 Kicad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2020 New Pagodi(https://stackoverflow.com/users/6846682/new-pagodi)
|
||||
* from https://stackoverflow.com/a/63289812/1522001
|
||||
*
|
||||
@@ -205,6 +205,12 @@ DIALOG_EXPORT_STEP_LOG::DIALOG_EXPORT_STEP_LOG( wxWindow* aParent, wxString aSte
|
||||
Bind( wxEVT_THREAD_STDERR, &DIALOG_EXPORT_STEP_LOG::onThreadInput, this );
|
||||
Bind( wxEVT_CLOSE_WINDOW, &DIALOG_EXPORT_STEP_LOG::onClose, this );
|
||||
|
||||
// Print the command line used to run kicad-cli.
|
||||
// it can be useful if kicad-cli as a problem.
|
||||
m_textCtrlLog->AppendText( _( "Command line:\n" ) );
|
||||
m_textCtrlLog->AppendText( aStepCmd );
|
||||
m_textCtrlLog->AppendText( wxT( "\n\n" ) );
|
||||
|
||||
m_stdioThread = new STDSTREAM_THREAD( this, m_process, m_msgQueue );
|
||||
m_stdioThread->Run();
|
||||
|
||||
|
||||
@@ -230,10 +230,9 @@ void PCB_EDIT_FRAME::OnExportVRML( wxCommandEvent& event )
|
||||
if( dlg.GetOriginChoice() == 1 )
|
||||
{
|
||||
// Origin = board center:
|
||||
BOARD* pcb = GetBoard();
|
||||
VECTOR2I center = pcb->GetBoundingBox().GetCenter();
|
||||
aXRef = pcbIUScale.IUTomm( center.x );
|
||||
aYRef = pcbIUScale.IUTomm( center.y );
|
||||
BOX2I bbox = GetBoard()->GetBoardEdgesBoundingBox();
|
||||
aXRef = pcbIUScale.IUTomm( bbox.GetCenter().x );
|
||||
aYRef = pcbIUScale.IUTomm( bbox.GetCenter().y );
|
||||
}
|
||||
|
||||
double scale = scaleList[dlg.GetUnits()]; // final scale export
|
||||
|
||||
@@ -136,6 +136,9 @@ void DIALOG_FOOTPRINT_CHECKER::runChecks()
|
||||
OUTLINE_ERROR_HANDLER outlineErrorHandler =
|
||||
[&]( const wxString& aMsg, BOARD_ITEM* aItemA, BOARD_ITEM* aItemB, const VECTOR2I& aPt )
|
||||
{
|
||||
if( !aItemA ) // If we only have a single item, make sure it's A
|
||||
std::swap( aItemA, aItemB );
|
||||
|
||||
errorHandler( aItemA, aItemB, nullptr, DRCE_MALFORMED_COURTYARD, aMsg, aPt );
|
||||
};
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2013 Dick Hollenbeck, dick@softplc.com
|
||||
* Copyright (C) 2008-2013 Wayne Stambaugh <stambaughw@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
|
||||
@@ -552,6 +552,10 @@ void DIALOG_PAD_PROPERTIES::initValues()
|
||||
m_trapAxisCtrl->SetSelection( 1 );
|
||||
}
|
||||
|
||||
// Store the initial thermal spoke angle to restore it, because some initializations
|
||||
// can change this value (mainly after m_PadShapeSelector initializations)
|
||||
EDA_ANGLE spokeInitialAngle = m_dummyPad->GetThermalSpokeAngle();
|
||||
|
||||
m_padToDieOpt->SetValue( m_dummyPad->GetPadToDieLength() != 0 );
|
||||
m_padToDie.ChangeValue( m_dummyPad->GetPadToDieLength() );
|
||||
|
||||
@@ -664,6 +668,11 @@ void DIALOG_PAD_PROPERTIES::initValues()
|
||||
OnPadShapeSelection( cmd_event );
|
||||
OnOffsetCheckbox( cmd_event );
|
||||
|
||||
// Restore thermal spoke angle to its initial value, because it can be modified
|
||||
// by the call to OnPadShapeSelection()
|
||||
m_dummyPad->SetThermalSpokeAngle( spokeInitialAngle );
|
||||
m_spokeAngle.SetAngleValue( m_dummyPad->GetThermalSpokeAngle() );
|
||||
|
||||
// Update basic shapes list
|
||||
displayPrimitivesList();
|
||||
}
|
||||
@@ -881,9 +890,7 @@ void DIALOG_PAD_PROPERTIES::OnPadShapeSelection( wxCommandEvent& event )
|
||||
m_sizeY.Enable( m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CIRCLE
|
||||
&& m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR );
|
||||
|
||||
m_offsetShapeOpt->Enable( m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CIRCLE
|
||||
&& m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR
|
||||
&& m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CUSTOM_RECT_ANCHOR );
|
||||
m_offsetShapeOpt->Enable( m_PadShapeSelector->GetSelection() != CHOICE_SHAPE_CIRCLE );
|
||||
|
||||
if( !m_offsetShapeOpt->IsEnabled() )
|
||||
m_offsetShapeOpt->SetValue( false );
|
||||
@@ -1243,7 +1250,7 @@ bool DIALOG_PAD_PROPERTIES::padValuesOK()
|
||||
|
||||
if( m_dummyPad->GetShape() == PAD_SHAPE::CUSTOM )
|
||||
{
|
||||
// allow 0-sized anchor pads
|
||||
pad_size = m_dummyPad->GetBoundingBox().GetSize();
|
||||
}
|
||||
else if( m_dummyPad->GetShape() == PAD_SHAPE::CIRCLE )
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user