Compare commits
241 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 61a17e4c8b | |||
| 67dda92437 | |||
| 4dfe564243 | |||
| 5b3c0028ea | |||
| 53d219e9d5 | |||
| a4da356ac7 | |||
| 2915a9d1a2 | |||
| 6778eb8352 | |||
| bdf8c04daf | |||
| a32ca5d0c4 | |||
| 992bee7ec9 | |||
| 7216527224 | |||
| 09bbabeef3 | |||
| 3ee74e2966 | |||
| 312356c284 | |||
| 6b9dba3d45 | |||
| 02c03ba2b6 | |||
| c35ba8f4cd | |||
| c344e170b9 | |||
| 5b5253b6e2 | |||
| 2954378f58 | |||
| eea71b9209 | |||
| 8eb98a2094 | |||
| 85d9feefff | |||
| c059cbce12 | |||
| a84aa449b2 | |||
| a4a2ec07c4 | |||
| d5557caa33 | |||
| 47717ca779 | |||
| d7f742f911 | |||
| 86ebc85404 | |||
| 5d4ed4b21a | |||
| 1ca0737c34 | |||
| 3a29fa44e3 | |||
| 3517d25aec | |||
| 8d62a5fd3f | |||
| 9e5876df5c | |||
| fdc3806ed1 | |||
| 798b827a12 | |||
| 4ade0ac73d | |||
| 65fd8d22ed | |||
| 481c1592ae | |||
| 9af12e60d2 | |||
| 048448296d | |||
| e03308e5ca | |||
| 16691c8d03 | |||
| dac0296e3a | |||
| 52ce4c0313 | |||
| 1956204635 | |||
| b4bd14ba10 | |||
| 8f7f6739c3 | |||
| 4eebd8ad6c | |||
| 4b3d67ffda | |||
| f3e3236a43 | |||
| 82ee4a81ed | |||
| 55fbdddbb7 | |||
| 7cce1901b2 | |||
| 0f4f1c0d3b | |||
| 78849ba5c0 | |||
| a066c57fcc | |||
| 8684c0f9be | |||
| db94f8c8ef | |||
| db0f7ec457 | |||
| 2bf4cca58a | |||
| 4470f4e6d8 | |||
| e516ab5114 | |||
| 0282b142b8 | |||
| 676108952e | |||
| 8470091a4b | |||
| 3302ef537f | |||
| 366f7aea6b | |||
| eed2221651 | |||
| 90093c0fdd | |||
| 2adccce3b8 | |||
| 6bf9653bef | |||
| 04c083ac48 | |||
| 9a236e5972 | |||
| 521e773f2c | |||
| e28aa6d16c | |||
| 001c90c69f | |||
| cba73e6cea | |||
| 5af4f3f9df | |||
| e1b922ae19 | |||
| f1d988788a | |||
| 8e6cb7b350 | |||
| 6685eefc8e | |||
| 8d231b8c96 | |||
| 313e09cfd3 | |||
| 5a05a1337e | |||
| a40929fa71 | |||
| 37eb5f4a8d | |||
| b7d1fb944c | |||
| 9797d2d133 | |||
| e34bb98ba1 | |||
| 60440094ba | |||
| c198e5ee15 | |||
| ceedfd9b7e | |||
| a4fbbaaa0b | |||
| 6cbdac5bf1 | |||
| 26629928c3 | |||
| 55c864ec45 | |||
| 07b5fd342a | |||
| 4481fcc75e | |||
| a155dd32e8 | |||
| c4c804edf7 | |||
| b26ca0e21a | |||
| 97b15a1708 | |||
| e808ab7409 | |||
| 7dc8527022 | |||
| f7765ea5b9 | |||
| f1d687cfdb | |||
| 57468c29f9 | |||
| 30df673ffa | |||
| 55b7852a65 | |||
| 026685ee48 | |||
| 8b5c292397 | |||
| 941420abed | |||
| a042d1aab4 | |||
| 53c2543474 | |||
| bac0820864 | |||
| e0381f25f7 | |||
| ce2ea3f3ae | |||
| c0d38de280 | |||
| 9a728c37df | |||
| 6be6210b67 | |||
| b21165722b | |||
| fd5d68ca9b | |||
| 9f26cbb89a | |||
| 0dc894356b | |||
| 6b5acdea1f | |||
| 892c5726f5 | |||
| 6c7261a223 | |||
| ae11213622 | |||
| 4bf35cbed8 | |||
| 7916e56963 | |||
| b9b4ff6f5e | |||
| 734222bd88 | |||
| 01590385c7 | |||
| 9be4bf0d14 | |||
| b1677d5f47 | |||
| 1e13a7640e | |||
| 804283877c | |||
| 65ace8d03d | |||
| 890376d04f | |||
| 18990587b9 | |||
| 75ef003747 | |||
| b9a6f47929 | |||
| 857219d70d | |||
| 92275c41cc | |||
| 09985988e7 | |||
| 524d431438 | |||
| ccd052cc99 | |||
| 1f461c7508 | |||
| 4bea619855 | |||
| f3621496fb | |||
| 1238c081c6 | |||
| 663e857df6 | |||
| 92ffd898f5 | |||
| 76e0f94532 | |||
| ff2d0cfb10 | |||
| 1cc10be443 | |||
| d2db96886d | |||
| 3d4a7c7c3f | |||
| d46139d5e3 | |||
| 40f938dc75 | |||
| 30dbafaf7c | |||
| 05dedbd892 | |||
| c0dba1e00d | |||
| cc3e57b52f | |||
| 70a6697c16 | |||
| 869f30e291 | |||
| 4c78652690 | |||
| afcda88ee3 | |||
| 605fe4ce99 | |||
| a3ee317277 | |||
| f7bce264bb | |||
| dfe6cb7afa | |||
| 8bdc62c111 | |||
| 350687f355 | |||
| 3a5a911012 | |||
| b40d19eb79 | |||
| 3e4ca3a1c7 | |||
| 663918107e | |||
| 1ac1f0445f | |||
| bce982877c | |||
| 9704543b7a | |||
| f90c3ef075 | |||
| 11177bf658 | |||
| 81f55dfc9c | |||
| c935ef890a | |||
| 71af5b106a | |||
| d24012bef5 | |||
| e904731e28 | |||
| dcd304c5d8 | |||
| 8275176792 | |||
| 8589bd3773 | |||
| c07604bb03 | |||
| b4131f2575 | |||
| b718c228fe | |||
| 3d04d78f76 | |||
| 6ebccdecc6 | |||
| 4e8d6de1de | |||
| 8b281b4d1c | |||
| 8ce12fb1af | |||
| 9e4efe5d72 | |||
| ab6c64b49a | |||
| dd71173263 | |||
| 89ed09744b | |||
| ddec1d5317 | |||
| 50dd6185bb | |||
| 6df17bba99 | |||
| ed89827908 | |||
| b61f6c35c7 | |||
| f9253485da | |||
| 7dc554ec34 | |||
| c7608c4bad | |||
| 10ca34e2a7 | |||
| e4fc918b11 | |||
| c1a21c9ab1 | |||
| 4ac848f18a | |||
| 46faa0f678 | |||
| 4072bc05af | |||
| e196f71d58 | |||
| b9d3b571bc | |||
| 816e3efbd5 | |||
| 8afbe544a3 | |||
| c7b7830495 | |||
| af3654d389 | |||
| 838cefaf48 | |||
| 4dca966c5d | |||
| 2609882346 | |||
| 36fc9191b9 | |||
| 4583522ea2 | |||
| f0e2adc3df | |||
| 091b34c05f | |||
| 09bc9cd77a | |||
| e893ed4590 | |||
| c0ad519e53 | |||
| 03af8dcc88 | |||
| 45e17307a1 | |||
| 357226eb71 |
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2015-2023 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 2023 CERN
|
||||
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2024 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
|
||||
@@ -142,8 +142,8 @@ BOARD_ADAPTER::BOARD_ADAPTER() :
|
||||
m_offboardPadsFront = nullptr;
|
||||
m_offboardPadsBack = nullptr;
|
||||
|
||||
m_frontPlatedPadPolys = nullptr;
|
||||
m_backPlatedPadPolys = nullptr;
|
||||
m_frontPlatedPadAndGraphicPolys = nullptr;
|
||||
m_backPlatedPadAndGraphicPolys = nullptr;
|
||||
m_frontPlatedCopperPolys = nullptr;
|
||||
m_backPlatedCopperPolys = nullptr;
|
||||
|
||||
@@ -397,13 +397,18 @@ void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningR
|
||||
break;
|
||||
|
||||
case BS_ITEM_TYPE_COPPER:
|
||||
if( item->GetBrdLayerId() == F_Cu )
|
||||
m_frontCopperThickness3DU = item->GetThickness() * m_biuTo3Dunits;
|
||||
else if( item->GetBrdLayerId() == B_Cu )
|
||||
m_backCopperThickness3DU = item->GetThickness() * m_biuTo3Dunits;
|
||||
else if( item->IsEnabled() )
|
||||
thickness += item->GetThickness();
|
||||
{
|
||||
// The copper thickness must be > 0 to avoid draw issues (divide by 0 for instance)
|
||||
// We use a minimal arbitrary value = 1 micrometer here:
|
||||
int copper_thickness = std::max( item->GetThickness(), pcbIUScale.mmToIU( 0.001 ) );
|
||||
|
||||
if( item->GetBrdLayerId() == F_Cu )
|
||||
m_frontCopperThickness3DU = copper_thickness * m_biuTo3Dunits;
|
||||
else if( item->GetBrdLayerId() == B_Cu )
|
||||
m_backCopperThickness3DU = copper_thickness * m_biuTo3Dunits;
|
||||
else if( item->IsEnabled() )
|
||||
thickness += copper_thickness;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -449,7 +454,7 @@ void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningR
|
||||
for( ; layer < MAX_CU_LAYERS; layer++ )
|
||||
{
|
||||
m_layerZcoordBottom[layer] = -( m_boardBodyThickness3DU / 2.0f );
|
||||
m_layerZcoordTop[layer] = -( m_boardBodyThickness3DU / 2.0f ) - m_backCopperThickness3DU;
|
||||
m_layerZcoordTop[layer] = m_layerZcoordBottom[layer] - m_backCopperThickness3DU;
|
||||
}
|
||||
|
||||
// This is the top of the copper layer thickness.
|
||||
|
||||
@@ -331,8 +331,8 @@ public:
|
||||
*/
|
||||
const MAP_POLY& GetPolyMap() const noexcept { return m_layers_poly; }
|
||||
|
||||
const SHAPE_POLY_SET* GetFrontPlatedPadPolys() { return m_frontPlatedPadPolys; }
|
||||
const SHAPE_POLY_SET* GetBackPlatedPadPolys() { return m_backPlatedPadPolys; }
|
||||
const SHAPE_POLY_SET* GetFrontPlatedPadAndGraphicPolys() { return m_frontPlatedPadAndGraphicPolys; }
|
||||
const SHAPE_POLY_SET* GetBackPlatedPadAndGraphicPolys() { return m_backPlatedPadAndGraphicPolys; }
|
||||
const MAP_POLY& GetHoleIdPolysMap() const noexcept { return m_layerHoleIdPolys; }
|
||||
const MAP_POLY& GetHoleOdPolysMap() const noexcept { return m_layerHoleOdPolys; }
|
||||
|
||||
@@ -438,8 +438,8 @@ private:
|
||||
MAP_POLY m_layers_poly; ///< Amalgamated polygon contours for various types
|
||||
///< of items
|
||||
|
||||
SHAPE_POLY_SET* m_frontPlatedPadPolys;
|
||||
SHAPE_POLY_SET* m_backPlatedPadPolys;
|
||||
SHAPE_POLY_SET* m_frontPlatedPadAndGraphicPolys;
|
||||
SHAPE_POLY_SET* m_backPlatedPadAndGraphicPolys;
|
||||
SHAPE_POLY_SET* m_frontPlatedCopperPolys;
|
||||
SHAPE_POLY_SET* m_backPlatedCopperPolys;
|
||||
|
||||
|
||||
@@ -117,8 +117,8 @@ void BOARD_ADAPTER::destroyLayers()
|
||||
|
||||
DELETE_AND_FREE_MAP( m_layers_poly );
|
||||
|
||||
DELETE_AND_FREE( m_frontPlatedPadPolys )
|
||||
DELETE_AND_FREE( m_backPlatedPadPolys )
|
||||
DELETE_AND_FREE( m_frontPlatedPadAndGraphicPolys )
|
||||
DELETE_AND_FREE( m_backPlatedPadAndGraphicPolys )
|
||||
DELETE_AND_FREE( m_frontPlatedCopperPolys )
|
||||
DELETE_AND_FREE( m_backPlatedCopperPolys )
|
||||
|
||||
@@ -241,8 +241,8 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||
|
||||
if( cfg.differentiate_plated_copper )
|
||||
{
|
||||
m_frontPlatedPadPolys = new SHAPE_POLY_SET;
|
||||
m_backPlatedPadPolys = new SHAPE_POLY_SET;
|
||||
m_frontPlatedPadAndGraphicPolys = new SHAPE_POLY_SET;
|
||||
m_backPlatedPadAndGraphicPolys = new SHAPE_POLY_SET;
|
||||
m_frontPlatedCopperPolys = new SHAPE_POLY_SET;
|
||||
m_backPlatedCopperPolys = new SHAPE_POLY_SET;
|
||||
|
||||
@@ -586,10 +586,10 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||
// ADD PLATED PADS contours
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
{
|
||||
footprint->TransformPadsToPolySet( *m_frontPlatedPadPolys, F_Cu, 0, maxError,
|
||||
footprint->TransformPadsToPolySet( *m_frontPlatedPadAndGraphicPolys, F_Cu, 0, maxError,
|
||||
ERROR_INSIDE, true, false, true );
|
||||
|
||||
footprint->TransformPadsToPolySet( *m_backPlatedPadPolys, B_Cu, 0, maxError,
|
||||
footprint->TransformPadsToPolySet( *m_backPlatedPadAndGraphicPolys, B_Cu, 0, maxError,
|
||||
ERROR_INSIDE, true, false, true );
|
||||
}
|
||||
}
|
||||
@@ -1050,21 +1050,33 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
}
|
||||
|
||||
// SUBTRACT PLATED COPPER FROM (UNPLATED) COPPER
|
||||
// Subtract plated copper from unplated copper
|
||||
bool hasF_Cu = false;
|
||||
bool hasB_Cu = false;
|
||||
|
||||
if( m_layers_poly.find( F_Cu ) != m_layers_poly.end() )
|
||||
{
|
||||
m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedPadPolys, SHAPE_POLY_SET::PM_FAST );
|
||||
m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedPadAndGraphicPolys, SHAPE_POLY_SET::PM_FAST );
|
||||
m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedCopperPolys, SHAPE_POLY_SET::PM_FAST );
|
||||
hasF_Cu = true;
|
||||
}
|
||||
|
||||
if( m_layers_poly.find( B_Cu ) != m_layers_poly.end() )
|
||||
{
|
||||
m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedPadPolys, SHAPE_POLY_SET::PM_FAST );
|
||||
m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedPadAndGraphicPolys, SHAPE_POLY_SET::PM_FAST );
|
||||
m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedCopperPolys, SHAPE_POLY_SET::PM_FAST );
|
||||
hasB_Cu = true;
|
||||
}
|
||||
|
||||
m_frontPlatedPadPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
m_backPlatedPadPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
// Add plated graphic items to build vertical walls
|
||||
if( hasF_Cu && m_frontPlatedCopperPolys->OutlineCount() )
|
||||
m_frontPlatedPadAndGraphicPolys->Append( *m_frontPlatedCopperPolys );
|
||||
|
||||
if( hasB_Cu && m_backPlatedCopperPolys->OutlineCount() )
|
||||
m_backPlatedPadAndGraphicPolys->Append( *m_backPlatedCopperPolys );
|
||||
|
||||
m_frontPlatedPadAndGraphicPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
m_backPlatedPadAndGraphicPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
m_frontPlatedCopperPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
m_backPlatedCopperPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
@@ -1134,6 +1146,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||
if( layerPoly != m_layers_poly.end() )
|
||||
{
|
||||
// This will make a union of all added contours
|
||||
layerPoly->second->ClearArcs();
|
||||
layerPoly->second->Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -613,12 +613,12 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
|
||||
|
||||
if( m_boardAdapter.m_Cfg->m_Render.differentiate_plated_copper )
|
||||
{
|
||||
const SHAPE_POLY_SET* frontPlatedPadPolys = m_boardAdapter.GetFrontPlatedPadPolys();
|
||||
const SHAPE_POLY_SET* backPlatedPadPolys = m_boardAdapter.GetBackPlatedPadPolys();
|
||||
const SHAPE_POLY_SET* frontPlatedPadAndGraphicPolys = m_boardAdapter.GetFrontPlatedPadAndGraphicPolys();
|
||||
const SHAPE_POLY_SET* backPlatedPadAndGraphicPolys = m_boardAdapter.GetBackPlatedPadAndGraphicPolys();
|
||||
|
||||
if( frontPlatedPadPolys )
|
||||
if( frontPlatedPadAndGraphicPolys )
|
||||
{
|
||||
SHAPE_POLY_SET poly = frontPlatedPadPolys->CloneDropTriangulation();
|
||||
SHAPE_POLY_SET poly = frontPlatedPadAndGraphicPolys->CloneDropTriangulation();
|
||||
poly.BooleanIntersection( m_boardAdapter.GetBoardPoly(), SHAPE_POLY_SET::PM_FAST );
|
||||
poly.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
|
||||
poly.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
|
||||
@@ -630,9 +630,9 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
|
||||
m_layers[F_Cu] = generateEmptyLayerList( F_Cu );
|
||||
}
|
||||
|
||||
if( backPlatedPadPolys )
|
||||
if( backPlatedPadAndGraphicPolys )
|
||||
{
|
||||
SHAPE_POLY_SET poly = backPlatedPadPolys->CloneDropTriangulation();
|
||||
SHAPE_POLY_SET poly = backPlatedPadAndGraphicPolys->CloneDropTriangulation();
|
||||
poly.BooleanIntersection( m_boardAdapter.GetBoardPoly(), SHAPE_POLY_SET::PM_FAST );
|
||||
poly.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
|
||||
poly.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
|
||||
@@ -917,6 +917,10 @@ void RENDER_3D_OPENGL::load3dModels( REPORTER* aStatusReporter )
|
||||
if( !m_boardAdapter.GetBoard() )
|
||||
return;
|
||||
|
||||
// Building the 3D models late crashes on recent versions of macOS
|
||||
// Unclear the exact mechanism, but as a workaround, just build them
|
||||
// all the time. See https://gitlab.com/kicad/code/kicad/-/issues/17198
|
||||
#ifndef __WXMAC__
|
||||
if( !m_boardAdapter.m_IsPreviewer
|
||||
&& !m_boardAdapter.m_Cfg->m_Render.show_footprints_normal
|
||||
&& !m_boardAdapter.m_Cfg->m_Render.show_footprints_insert
|
||||
@@ -924,6 +928,7 @@ void RENDER_3D_OPENGL::load3dModels( REPORTER* aStatusReporter )
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Go for all footprints
|
||||
for( const FOOTPRINT* footprint : m_boardAdapter.GetBoard()->Footprints() )
|
||||
|
||||
@@ -83,6 +83,13 @@ const APPEARANCE_CONTROLS_3D::APPEARANCE_SETTING_3D APPEARANCE_CONTROLS_3D::s_la
|
||||
RR( _HKI( "Background End" ), LAYER_3D_BACKGROUND_BOTTOM, _HKI( "Background gradient end color" ) ),
|
||||
};
|
||||
|
||||
// The list of IDs that can have colors coming from the board stackup, and cannot be
|
||||
// modified if use colors from stackup is activated
|
||||
static std::vector<int> inStackupColors{ LAYER_3D_BOARD, LAYER_3D_COPPER_TOP,
|
||||
LAYER_3D_COPPER_BOTTOM, LAYER_3D_SOLDERPASTE,
|
||||
LAYER_3D_SILKSCREEN_TOP, LAYER_3D_SILKSCREEN_BOTTOM,
|
||||
LAYER_3D_SOLDERMASK_TOP, LAYER_3D_SOLDERMASK_BOTTOM
|
||||
};
|
||||
|
||||
APPEARANCE_CONTROLS_3D::APPEARANCE_CONTROLS_3D( EDA_3D_VIEWER_FRAME* aParent,
|
||||
wxWindow* aFocusOwner ) :
|
||||
@@ -568,8 +575,14 @@ void APPEARANCE_CONTROLS_3D::UpdateLayerCtls()
|
||||
{
|
||||
setting->m_Ctl_color->SetSwatchColor( colors[ setting->m_Id ], false );
|
||||
|
||||
if( cfg )
|
||||
setting->m_Ctl_color->SetReadOnly( cfg->m_UseStackupColors );
|
||||
// if cfg->m_UseStackupColors is set, board colors cannot be modified locally, but
|
||||
// other colors can be
|
||||
if( std::find( inStackupColors.begin(), inStackupColors.end(), setting->m_Id )
|
||||
!= inStackupColors.end() )
|
||||
{
|
||||
if( cfg )
|
||||
setting->m_Ctl_color->SetReadOnly( cfg->m_UseStackupColors );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -514,6 +514,8 @@ if( MSVC )
|
||||
string( APPEND CMAKE_CXX_FLAGS " /wd4800" )
|
||||
# /Zi: create PDB
|
||||
string( APPEND CMAKE_CXX_FLAGS " /Zi" )
|
||||
# /Zc:__cplusplus: define this macro according to C++ standard version
|
||||
string( APPEND CMAKE_CXX_FLAGS " /Zc:__cplusplus" )
|
||||
# /GF: enable string pooling
|
||||
string( APPEND CMAKE_CXX_FLAGS_RELEASE " /GF" )
|
||||
string( APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " /GF" )
|
||||
|
||||
+39
-19
@@ -27,7 +27,7 @@
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
# Set the needed libraries
|
||||
set( OCC_LIBS
|
||||
set( OCC_LIBS_COMMON
|
||||
TKBinL
|
||||
TKBin
|
||||
TKBinTObj
|
||||
@@ -45,7 +45,6 @@ set( OCC_LIBS
|
||||
TKGeomAlgo
|
||||
TKGeomBase
|
||||
TKHLR
|
||||
TKIGES
|
||||
TKLCAF
|
||||
TKMath
|
||||
TKMesh
|
||||
@@ -56,18 +55,10 @@ set( OCC_LIBS
|
||||
TKRWMesh
|
||||
TKService
|
||||
TKShHealing
|
||||
TKSTEP209
|
||||
TKSTEPAttr
|
||||
TKSTEPBase
|
||||
TKSTEP
|
||||
TKSTL
|
||||
TKTObj
|
||||
TKTopAlgo
|
||||
TKV3d
|
||||
TKVRML
|
||||
TKXCAF
|
||||
TKXDEIGES
|
||||
TKXDESTEP
|
||||
TKXMesh
|
||||
TKXmlL
|
||||
TKXml
|
||||
@@ -76,6 +67,27 @@ set( OCC_LIBS
|
||||
TKXSBase
|
||||
)
|
||||
|
||||
# Libraries valid pre-7.8.0
|
||||
set( OCC_LIBS_PRE_78
|
||||
TKIGES
|
||||
TKSTEP209
|
||||
TKSTEPAttr
|
||||
TKSTEPBase
|
||||
TKSTEP
|
||||
TKSTL
|
||||
TKVRML
|
||||
TKXDEIGES
|
||||
TKXDESTEP
|
||||
)
|
||||
|
||||
# Libraries for versions >= 7.8.0
|
||||
set( OCC_LIBS_POST_78
|
||||
TKDEIGES
|
||||
TKDEGLTF
|
||||
TKDESTEP
|
||||
TKDESTL
|
||||
)
|
||||
|
||||
set(OCC_TYPE "OpenCASCADE Standard Edition")
|
||||
if(WIN32)
|
||||
if(CYGWIN OR MINGW)
|
||||
@@ -178,9 +190,8 @@ endif(OCC_INCLUDE_DIR AND NOT ${OCC_INCLUDE_DIR} STREQUAL "OCC_INCLUDE_DIR-NOTFO
|
||||
include(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OCC REQUIRED_VARS OCC_INCLUDE_DIR VERSION_VAR OCC_VERSION_STRING)
|
||||
|
||||
if(OCC_FOUND)
|
||||
foreach(lib IN LISTS OCC_LIBS)
|
||||
|
||||
macro(occ_lib_search SEARCH_LIST)
|
||||
foreach(lib IN LISTS ${SEARCH_LIST})
|
||||
#Use the specified library location if given
|
||||
find_library(OCC_TEMP_LIB ${lib} HINTS ${OCC_LIBRARY_DIR} NO_DEFAULT_PATH)
|
||||
if(${OCC_TEMP_LIB} STREQUAL "OCC_TEMP_LIB-NOTFOUND")
|
||||
@@ -197,11 +208,20 @@ if(OCC_FOUND)
|
||||
|
||||
unset(OCC_TEMP_LIB CACHE)
|
||||
endforeach(lib)
|
||||
endmacro()
|
||||
|
||||
#Convert path names to absolute for cleaner display
|
||||
get_filename_component(OCC_INCLUDE_DIR "${OCC_INCLUDE_DIR}" ABSOLUTE)
|
||||
get_filename_component(OCC_LIBRARY_DIR "${OCC_LIBRARY_DIR}" ABSOLUTE)
|
||||
message(STATUS "Found ${OCC_TYPE} version: ${OCC_VERSION_STRING}")
|
||||
message(STATUS " ++ ${OCC_TYPE} include directory: ${OCC_INCLUDE_DIR}")
|
||||
message(STATUS " ++ ${OCC_TYPE} shared libraries directory: ${OCC_LIBRARY_DIR}")
|
||||
if(OCC_FOUND)
|
||||
occ_lib_search( OCC_LIBS_COMMON )
|
||||
if(OCC_VERSION_STRING VERSION_LESS "7.8.0")
|
||||
occ_lib_search( OCC_LIBS_PRE_78 )
|
||||
else()
|
||||
occ_lib_search( OCC_LIBS_POST_78 )
|
||||
endif()
|
||||
|
||||
#Convert path names to absolute for cleaner display
|
||||
get_filename_component(OCC_INCLUDE_DIR "${OCC_INCLUDE_DIR}" ABSOLUTE)
|
||||
get_filename_component(OCC_LIBRARY_DIR "${OCC_LIBRARY_DIR}" ABSOLUTE)
|
||||
message(STATUS "Found ${OCC_TYPE} version: ${OCC_VERSION_STRING}")
|
||||
message(STATUS " ++ ${OCC_TYPE} include directory: ${OCC_INCLUDE_DIR}")
|
||||
message(STATUS " ++ ${OCC_TYPE} shared libraries directory: ${OCC_LIBRARY_DIR}")
|
||||
endif(OCC_FOUND)
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
# KiCad.
|
||||
#
|
||||
# Note: This version string should follow the semantic versioning system
|
||||
set( KICAD_SEMANTIC_VERSION "8.0.1" )
|
||||
set( KICAD_SEMANTIC_VERSION "8.0.2" )
|
||||
|
||||
# Default the version to the semantic version.
|
||||
# This is overridden by the git repository tag though (if using git)
|
||||
|
||||
@@ -388,8 +388,10 @@ set( COMMON_IO_SRCS
|
||||
io/io_utils.cpp
|
||||
|
||||
# Altium
|
||||
io/altium/altium_parser.cpp
|
||||
io/altium/altium_binary_parser.cpp
|
||||
io/altium/altium_ascii_parser.cpp
|
||||
io/altium/altium_parser_utils.cpp
|
||||
io/altium/altium_props_utils.cpp
|
||||
|
||||
# Cadstar
|
||||
io/cadstar/cadstar_archive_parser.cpp
|
||||
|
||||
@@ -104,6 +104,11 @@ static const wxChar EnableEeschemaPrintCairo[] = wxT( "EnableEeschemaPrintCairo"
|
||||
static const wxChar DisambiguationTime[] = wxT( "DisambiguationTime" );
|
||||
static const wxChar PcbSelectionVisibilityRatio[] = wxT( "PcbSelectionVisibilityRatio" );
|
||||
static const wxChar MinimumSegmentLength[] = wxT( "MinimumSegmentLength" );
|
||||
static const wxChar OcePluginLinearDeflection[] = wxT( "OcePluginLinearDeflection" );
|
||||
static const wxChar OcePluginAngularDeflection[] = wxT( "OcePluginAngularDeflection" );
|
||||
static const wxChar TriangulateSimplificationLevel[] = wxT( "TriangulateSimplificationLevel" );
|
||||
static const wxChar TriangulateMinimumArea[] = wxT( "TriangulateMinimumArea" );
|
||||
static const wxChar EnableCacheFriendlyFracture[] = wxT( "EnableCacheFriendlyFracture" );
|
||||
} // namespace KEYS
|
||||
|
||||
|
||||
@@ -248,6 +253,14 @@ ADVANCED_CFG::ADVANCED_CFG()
|
||||
|
||||
m_MinimumSegmentLength = 50;
|
||||
|
||||
m_OcePluginLinearDeflection = 0.14;
|
||||
m_OcePluginAngularDeflection = 30;
|
||||
|
||||
m_TriangulateSimplificationLevel = 50;
|
||||
m_TriangulateMinimumArea = 1000;
|
||||
|
||||
m_EnableCacheFriendlyFracture = true;
|
||||
|
||||
loadFromConfigFile();
|
||||
}
|
||||
|
||||
@@ -444,6 +457,26 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg )
|
||||
&m_MinimumSegmentLength,
|
||||
m_MinimumSegmentLength, 10, 1000 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::OcePluginLinearDeflection,
|
||||
&m_OcePluginLinearDeflection,
|
||||
m_OcePluginLinearDeflection, 0.01, 1.0 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::OcePluginAngularDeflection,
|
||||
&m_OcePluginAngularDeflection,
|
||||
m_OcePluginAngularDeflection, 0.01, 360.0 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::TriangulateSimplificationLevel,
|
||||
&m_TriangulateSimplificationLevel,
|
||||
m_TriangulateSimplificationLevel, 0, 1000 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::TriangulateMinimumArea,
|
||||
&m_TriangulateMinimumArea,
|
||||
m_TriangulateMinimumArea, 0, 100000 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::EnableCacheFriendlyFracture,
|
||||
&m_EnableCacheFriendlyFracture,
|
||||
m_EnableCacheFriendlyFracture ) );
|
||||
|
||||
// Special case for trace mask setting...we just grab them and set them immediately
|
||||
// Because we even use wxLogTrace inside of advanced config
|
||||
wxString traceMasks;
|
||||
|
||||
@@ -70,7 +70,11 @@ DIALOG_CONFIGURE_PATHS::DIALOG_CONFIGURE_PATHS( wxWindow* aParent ) :
|
||||
m_EnvVars->ClearRows();
|
||||
m_EnvVars->AppendCols( 1 ); // for the isExternal flags
|
||||
m_EnvVars->HideCol( TV_FLAG_COL );
|
||||
#ifndef __WXMAC__
|
||||
// macos crashes on languages at least using non-ascii characters for the column header here of all places
|
||||
// if we use native column headers, so guard it for windows to still look nice
|
||||
m_EnvVars->UseNativeColHeader( true );
|
||||
#endif
|
||||
|
||||
wxGridCellAttr* attr = new wxGridCellAttr;
|
||||
attr->SetEditor( new GRID_CELL_PATH_EDITOR( this, m_EnvVars, &m_curdir, wxEmptyString ) );
|
||||
|
||||
@@ -71,6 +71,18 @@ PANEL_GRID_SETTINGS::PANEL_GRID_SETTINGS( wxWindow* aParent, UNITS_PROVIDER* aUn
|
||||
m_checkGridOverrideWires->Show( false );
|
||||
m_gridOverrideWiresChoice->Show( false );
|
||||
}
|
||||
|
||||
if( m_frameType == FRAME_GERBER )
|
||||
{
|
||||
m_overridesLabel->Show( false );
|
||||
m_staticline3->Show( false );
|
||||
|
||||
m_checkGridOverrideText->Show( false );
|
||||
m_gridOverrideTextChoice->Show( false );
|
||||
|
||||
m_checkGridOverrideGraphics->Show( false );
|
||||
m_gridOverrideGraphicsChoice->Show( false );
|
||||
}
|
||||
}
|
||||
|
||||
int hk1 = ACTIONS::gridFast1.GetHotKey();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3)
|
||||
// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -111,7 +111,7 @@ PANEL_GRID_SETTINGS_BASE::PANEL_GRID_SETTINGS_BASE( wxWindow* parent, wxWindowID
|
||||
bSizerRightCol->Add( m_staticline3, 0, wxEXPAND|wxTOP|wxBOTTOM, 2 );
|
||||
|
||||
wxFlexGridSizer* fgGridOverrides;
|
||||
fgGridOverrides = new wxFlexGridSizer( 0, 2, 4, 0 );
|
||||
fgGridOverrides = new wxFlexGridSizer( 0, 2, 5, 0 );
|
||||
fgGridOverrides->AddGrowableCol( 1 );
|
||||
fgGridOverrides->SetFlexibleDirection( wxBOTH );
|
||||
fgGridOverrides->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
@@ -122,7 +122,7 @@ PANEL_GRID_SETTINGS_BASE::PANEL_GRID_SETTINGS_BASE( wxWindow* parent, wxWindowID
|
||||
wxArrayString m_gridOverrideConnectedChoiceChoices;
|
||||
m_gridOverrideConnectedChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_gridOverrideConnectedChoiceChoices, 0 );
|
||||
m_gridOverrideConnectedChoice->SetSelection( 0 );
|
||||
fgGridOverrides->Add( m_gridOverrideConnectedChoice, 0, wxALL, 5 );
|
||||
fgGridOverrides->Add( m_gridOverrideConnectedChoice, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_checkGridOverrideWires = new wxCheckBox( this, wxID_ANY, _("Wires:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgGridOverrides->Add( m_checkGridOverrideWires, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT|wxLEFT, 8 );
|
||||
@@ -130,7 +130,7 @@ PANEL_GRID_SETTINGS_BASE::PANEL_GRID_SETTINGS_BASE( wxWindow* parent, wxWindowID
|
||||
wxArrayString m_gridOverrideWiresChoiceChoices;
|
||||
m_gridOverrideWiresChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_gridOverrideWiresChoiceChoices, 0 );
|
||||
m_gridOverrideWiresChoice->SetSelection( 0 );
|
||||
fgGridOverrides->Add( m_gridOverrideWiresChoice, 0, wxALL, 5 );
|
||||
fgGridOverrides->Add( m_gridOverrideWiresChoice, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_checkGridOverrideVias = new wxCheckBox( this, wxID_ANY, _("Vias:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgGridOverrides->Add( m_checkGridOverrideVias, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT|wxLEFT, 8 );
|
||||
@@ -138,7 +138,7 @@ PANEL_GRID_SETTINGS_BASE::PANEL_GRID_SETTINGS_BASE( wxWindow* parent, wxWindowID
|
||||
wxArrayString m_gridOverrideViasChoiceChoices;
|
||||
m_gridOverrideViasChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_gridOverrideViasChoiceChoices, 0 );
|
||||
m_gridOverrideViasChoice->SetSelection( 0 );
|
||||
fgGridOverrides->Add( m_gridOverrideViasChoice, 0, wxALL, 5 );
|
||||
fgGridOverrides->Add( m_gridOverrideViasChoice, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_checkGridOverrideText = new wxCheckBox( this, wxID_ANY, _("Text:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgGridOverrides->Add( m_checkGridOverrideText, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT|wxLEFT, 8 );
|
||||
@@ -146,7 +146,7 @@ PANEL_GRID_SETTINGS_BASE::PANEL_GRID_SETTINGS_BASE( wxWindow* parent, wxWindowID
|
||||
wxArrayString m_gridOverrideTextChoiceChoices;
|
||||
m_gridOverrideTextChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_gridOverrideTextChoiceChoices, 0 );
|
||||
m_gridOverrideTextChoice->SetSelection( 0 );
|
||||
fgGridOverrides->Add( m_gridOverrideTextChoice, 0, wxALL, 5 );
|
||||
fgGridOverrides->Add( m_gridOverrideTextChoice, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_checkGridOverrideGraphics = new wxCheckBox( this, wxID_ANY, _("Graphics:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgGridOverrides->Add( m_checkGridOverrideGraphics, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT|wxLEFT, 8 );
|
||||
@@ -154,7 +154,7 @@ PANEL_GRID_SETTINGS_BASE::PANEL_GRID_SETTINGS_BASE( wxWindow* parent, wxWindowID
|
||||
wxArrayString m_gridOverrideGraphicsChoiceChoices;
|
||||
m_gridOverrideGraphicsChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_gridOverrideGraphicsChoiceChoices, 0 );
|
||||
m_gridOverrideGraphicsChoice->SetSelection( 0 );
|
||||
fgGridOverrides->Add( m_gridOverrideGraphicsChoice, 0, wxALL, 5 );
|
||||
fgGridOverrides->Add( m_gridOverrideGraphicsChoice, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
|
||||
bSizerRightCol->Add( fgGridOverrides, 0, wxEXPAND|wxTOP|wxBOTTOM|wxRIGHT, 10 );
|
||||
|
||||
+1850
-1823
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3)
|
||||
// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
|
||||
@@ -1202,6 +1202,7 @@ void EDA_BASE_FRAME::ShowPreferences( wxString aStartPage, wxString aStartParent
|
||||
book->AddPage( new wxPanel( book ), _( "Gerber Viewer" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_DISPLAY_OPTIONS ), _( "Display Options" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_COLORS ), _( "Colors" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_GRIDS ), _( "Grids" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_GBR_EXCELLON_OPTIONS ), _( "Excellon Options" ) );
|
||||
}
|
||||
catch( ... )
|
||||
|
||||
+29
-15
@@ -1973,53 +1973,65 @@ static struct EDA_SHAPE_DESC
|
||||
return false;
|
||||
};
|
||||
|
||||
const wxString shapeProps = _HKI( "Shape Properties" );
|
||||
|
||||
auto shape = new PROPERTY_ENUM<EDA_SHAPE, SHAPE_T>( _HKI( "Shape" ),
|
||||
NO_SETTER( EDA_SHAPE, SHAPE_T ), &EDA_SHAPE::GetShape );
|
||||
propMgr.AddProperty( shape );
|
||||
propMgr.AddProperty( shape, shapeProps );
|
||||
|
||||
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "Start X" ),
|
||||
&EDA_SHAPE::SetStartX, &EDA_SHAPE::GetStartX, PROPERTY_DISPLAY::PT_COORD,
|
||||
ORIGIN_TRANSFORMS::ABS_X_COORD ) )
|
||||
ORIGIN_TRANSFORMS::ABS_X_COORD ),
|
||||
shapeProps )
|
||||
.SetAvailableFunc( isNotPolygonOrCircle );
|
||||
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "Start Y" ),
|
||||
&EDA_SHAPE::SetStartY, &EDA_SHAPE::GetStartY, PROPERTY_DISPLAY::PT_COORD,
|
||||
ORIGIN_TRANSFORMS::ABS_Y_COORD ) )
|
||||
ORIGIN_TRANSFORMS::ABS_Y_COORD ),
|
||||
shapeProps )
|
||||
.SetAvailableFunc( isNotPolygonOrCircle );
|
||||
|
||||
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "Center X" ),
|
||||
&EDA_SHAPE::SetStartX, &EDA_SHAPE::GetStartX, PROPERTY_DISPLAY::PT_COORD,
|
||||
ORIGIN_TRANSFORMS::ABS_X_COORD ) )
|
||||
ORIGIN_TRANSFORMS::ABS_X_COORD ),
|
||||
shapeProps )
|
||||
.SetAvailableFunc( isCircle );
|
||||
|
||||
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "Center Y" ),
|
||||
&EDA_SHAPE::SetStartY, &EDA_SHAPE::GetStartY, PROPERTY_DISPLAY::PT_COORD,
|
||||
ORIGIN_TRANSFORMS::ABS_Y_COORD ) )
|
||||
ORIGIN_TRANSFORMS::ABS_Y_COORD ),
|
||||
shapeProps )
|
||||
.SetAvailableFunc( isCircle );
|
||||
|
||||
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "Radius" ),
|
||||
&EDA_SHAPE::SetRadius, &EDA_SHAPE::GetRadius, PROPERTY_DISPLAY::PT_SIZE,
|
||||
ORIGIN_TRANSFORMS::NOT_A_COORD ) )
|
||||
ORIGIN_TRANSFORMS::NOT_A_COORD ),
|
||||
shapeProps )
|
||||
.SetAvailableFunc( isCircle );
|
||||
|
||||
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "End X" ),
|
||||
&EDA_SHAPE::SetEndX, &EDA_SHAPE::GetEndX, PROPERTY_DISPLAY::PT_COORD,
|
||||
ORIGIN_TRANSFORMS::ABS_X_COORD ) )
|
||||
ORIGIN_TRANSFORMS::ABS_X_COORD ),
|
||||
shapeProps )
|
||||
.SetAvailableFunc( isNotPolygonOrCircle );
|
||||
|
||||
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "End Y" ),
|
||||
&EDA_SHAPE::SetEndY, &EDA_SHAPE::GetEndY, PROPERTY_DISPLAY::PT_COORD,
|
||||
ORIGIN_TRANSFORMS::ABS_Y_COORD ) )
|
||||
ORIGIN_TRANSFORMS::ABS_Y_COORD ),
|
||||
shapeProps )
|
||||
.SetAvailableFunc( isNotPolygonOrCircle );
|
||||
|
||||
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "Line Width" ),
|
||||
&EDA_SHAPE::SetWidth, &EDA_SHAPE::GetWidth, PROPERTY_DISPLAY::PT_SIZE ) );
|
||||
&EDA_SHAPE::SetWidth, &EDA_SHAPE::GetWidth, PROPERTY_DISPLAY::PT_SIZE ),
|
||||
shapeProps );
|
||||
|
||||
void ( EDA_SHAPE::*lineStyleSetter )( LINE_STYLE ) = &EDA_SHAPE::SetLineStyle;
|
||||
propMgr.AddProperty( new PROPERTY_ENUM<EDA_SHAPE, LINE_STYLE>(
|
||||
_HKI( "Line Style" ), lineStyleSetter, &EDA_SHAPE::GetLineStyle ) );
|
||||
propMgr.AddProperty( new PROPERTY_ENUM<EDA_SHAPE, LINE_STYLE>( _HKI( "Line Style" ),
|
||||
lineStyleSetter, &EDA_SHAPE::GetLineStyle ),
|
||||
shapeProps );
|
||||
|
||||
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, COLOR4D>( _HKI( "Line Color" ),
|
||||
&EDA_SHAPE::SetLineColor, &EDA_SHAPE::GetLineColor ) )
|
||||
&EDA_SHAPE::SetLineColor, &EDA_SHAPE::GetLineColor ),
|
||||
shapeProps )
|
||||
.SetIsHiddenFromRulesEditor();
|
||||
|
||||
auto angle = new PROPERTY<EDA_SHAPE, EDA_ANGLE>( _HKI( "Angle" ),
|
||||
@@ -2033,7 +2045,7 @@ static struct EDA_SHAPE_DESC
|
||||
|
||||
return false;
|
||||
} );
|
||||
propMgr.AddProperty( angle );
|
||||
propMgr.AddProperty( angle, shapeProps );
|
||||
|
||||
auto fillAvailable =
|
||||
[=]( INSPECTABLE* aItem ) -> bool
|
||||
@@ -2056,11 +2068,13 @@ static struct EDA_SHAPE_DESC
|
||||
};
|
||||
|
||||
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, bool>( _HKI( "Filled" ),
|
||||
&EDA_SHAPE::SetFilled, &EDA_SHAPE::IsFilled ) )
|
||||
&EDA_SHAPE::SetFilled, &EDA_SHAPE::IsFilled ),
|
||||
shapeProps )
|
||||
.SetAvailableFunc( fillAvailable );
|
||||
|
||||
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, COLOR4D>( _HKI( "Fill Color" ),
|
||||
&EDA_SHAPE::SetFillColor, &EDA_SHAPE::GetFillColor ) )
|
||||
&EDA_SHAPE::SetFillColor, &EDA_SHAPE::GetFillColor ),
|
||||
shapeProps )
|
||||
.SetAvailableFunc( fillAvailable )
|
||||
.SetIsHiddenFromRulesEditor();
|
||||
}
|
||||
|
||||
+6
-6
@@ -364,8 +364,8 @@ void EDA_TEXT::SetTextSize( VECTOR2I aNewSize, bool aEnforceMinTextSize )
|
||||
|
||||
if( aEnforceMinTextSize )
|
||||
{
|
||||
int min = m_IuScale.get().MilsToIU( TEXT_MIN_SIZE_MILS );
|
||||
int max = m_IuScale.get().MilsToIU( TEXT_MAX_SIZE_MILS );
|
||||
int min = m_IuScale.get().mmToIU( TEXT_MIN_SIZE_MM );
|
||||
int max = m_IuScale.get().mmToIU( TEXT_MAX_SIZE_MM );
|
||||
|
||||
aNewSize = VECTOR2I( alg::clamp( min, aNewSize.x, max ),
|
||||
alg::clamp( min, aNewSize.y, max ) );
|
||||
@@ -380,8 +380,8 @@ void EDA_TEXT::SetTextSize( VECTOR2I aNewSize, bool aEnforceMinTextSize )
|
||||
|
||||
void EDA_TEXT::SetTextWidth( int aWidth )
|
||||
{
|
||||
int min = m_IuScale.get().MilsToIU( TEXT_MIN_SIZE_MILS );
|
||||
int max = m_IuScale.get().MilsToIU( TEXT_MAX_SIZE_MILS );
|
||||
int min = m_IuScale.get().mmToIU( TEXT_MIN_SIZE_MM );
|
||||
int max = m_IuScale.get().mmToIU( TEXT_MAX_SIZE_MM );
|
||||
|
||||
m_attributes.m_Size.x = alg::clamp( min, aWidth, max );
|
||||
ClearRenderCache();
|
||||
@@ -391,8 +391,8 @@ void EDA_TEXT::SetTextWidth( int aWidth )
|
||||
|
||||
void EDA_TEXT::SetTextHeight( int aHeight )
|
||||
{
|
||||
int min = m_IuScale.get().MilsToIU( TEXT_MIN_SIZE_MILS );
|
||||
int max = m_IuScale.get().MilsToIU( TEXT_MAX_SIZE_MILS );
|
||||
int min = m_IuScale.get().mmToIU( TEXT_MIN_SIZE_MM );
|
||||
int max = m_IuScale.get().mmToIU( TEXT_MAX_SIZE_MM );
|
||||
|
||||
m_attributes.m_Size.y = alg::clamp( min, aHeight, max );
|
||||
ClearRenderCache();
|
||||
|
||||
+48
-15
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2024 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
|
||||
@@ -28,6 +28,22 @@
|
||||
#include <charconv>
|
||||
#include <wx/translation.h>
|
||||
|
||||
|
||||
static void removeTrailingZeros( wxString& aText )
|
||||
{
|
||||
int len = aText.length();
|
||||
int removeLast = 0;
|
||||
|
||||
while( --len > 0 && aText[len] == '0' )
|
||||
removeLast++;
|
||||
|
||||
if( len >= 0 && ( aText[len] == '.' || aText[len] == ',' ) )
|
||||
removeLast++;
|
||||
|
||||
aText = aText.RemoveLast( removeLast );
|
||||
}
|
||||
|
||||
|
||||
bool EDA_UNIT_UTILS::IsImperialUnit( EDA_UNITS aUnit )
|
||||
{
|
||||
switch( aUnit )
|
||||
@@ -305,29 +321,46 @@ wxString EDA_UNIT_UTILS::UI::StringFromValue( const EDA_IU_SCALE& aIuScale, EDA_
|
||||
break;
|
||||
}
|
||||
|
||||
char buf[50];
|
||||
const wxChar* format = nullptr;
|
||||
|
||||
if( value_to_print != 0.0 && fabs( value_to_print ) <= 0.0001 )
|
||||
switch( aUnits )
|
||||
{
|
||||
int len = snprintf( buf, sizeof( buf ) - 1, "%.10f", value_to_print );
|
||||
|
||||
while( --len > 0 && buf[len] == '0' )
|
||||
buf[len] = '\0';
|
||||
case EDA_UNITS::MILS:
|
||||
#if defined( EESCHEMA )
|
||||
format = wxT( "%.3f" );
|
||||
#else
|
||||
format = wxT( "%.5f" );
|
||||
#endif
|
||||
break;
|
||||
|
||||
if( len >= 0 && ( buf[len] == '.' || buf[len] == ',' ) )
|
||||
buf[len] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf( buf, sizeof( buf ) - 1, "%.10g", value_to_print );
|
||||
case EDA_UNITS::INCHES:
|
||||
#if defined( EESCHEMA )
|
||||
format = wxT( "%.6f" );
|
||||
#else
|
||||
format = wxT( "%.8f" );
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
format = wxT( "%.10f" );
|
||||
break;
|
||||
}
|
||||
|
||||
wxString stringValue( buf, wxConvUTF8 );
|
||||
wxString text;
|
||||
text.Printf( format, value_to_print );
|
||||
removeTrailingZeros( text );
|
||||
|
||||
if( value_to_print != 0.0 && ( text == wxS( "0" ) || text == wxS( "-0" ) ) )
|
||||
{
|
||||
text.Printf( wxS( "%.10f" ), value_to_print );
|
||||
removeTrailingZeros( text );
|
||||
}
|
||||
|
||||
if( aAddUnitsText )
|
||||
stringValue += EDA_UNIT_UTILS::GetText( aUnits, aType );
|
||||
text << EDA_UNIT_UTILS::GetText( aUnits, aType );
|
||||
|
||||
return stringValue;
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -59,7 +59,9 @@ void IO_ERROR::init( const wxString& aProblem, const char* aThrowersFile,
|
||||
// a short filename will be printed (it is better for user, the full filename has no meaning).
|
||||
wxString srcname = aThrowersFile;
|
||||
|
||||
where.Printf( _( "from %s : %s() line %d" ),
|
||||
// No need for translations of source code file/line messages (and wxWidget's translation
|
||||
// stuff has bitten us before. May be related to KICAD-YP.
|
||||
where.Printf( wxS( "from %s : %s() line %d" ),
|
||||
srcname.AfterLast( '/' ),
|
||||
wxString( aThrowersFunction ),
|
||||
aThrowersLineNumber );
|
||||
@@ -87,7 +89,9 @@ void PARSE_ERROR::init( const wxString& aProblem, const char* aThrowersFile,
|
||||
// a short filename will be printed (it is better for user, the full filename has no meaning).
|
||||
wxString srcname = aThrowersFile;
|
||||
|
||||
where.Printf( _( "from %s : %s() line:%d" ),
|
||||
// No need for translations of source code file/line messages (and wxWidget's translation
|
||||
// stuff has bitten us before. May be related to KICAD-YP.
|
||||
where.Printf( wxS( "from %s : %s() line %d" ),
|
||||
srcname.AfterLast( '/' ),
|
||||
wxString( aThrowersFunction ),
|
||||
aThrowersLineNumber );
|
||||
|
||||
+15
-3
@@ -82,19 +82,19 @@ std::unique_ptr<GLYPH> STROKE_GLYPH::Transform( const VECTOR2D& aGlyphSize, cons
|
||||
end.x *= aGlyphSize.x;
|
||||
end.y *= aGlyphSize.y;
|
||||
|
||||
if( aTilt )
|
||||
if( aTilt != 0.0 )
|
||||
end.x -= end.y * aTilt;
|
||||
|
||||
glyph->m_boundingBox.SetEnd( end );
|
||||
glyph->m_boundingBox.Offset( aOffset );
|
||||
|
||||
for( std::vector<VECTOR2D>& pointList : *glyph.get() )
|
||||
for( std::vector<VECTOR2D>& pointList : *glyph )
|
||||
{
|
||||
for( VECTOR2D& point : pointList )
|
||||
{
|
||||
point *= aGlyphSize;
|
||||
|
||||
if( aTilt )
|
||||
if( aTilt != 0.0 )
|
||||
point.x -= point.y * aTilt;
|
||||
|
||||
point += aOffset;
|
||||
@@ -111,6 +111,18 @@ std::unique_ptr<GLYPH> STROKE_GLYPH::Transform( const VECTOR2D& aGlyphSize, cons
|
||||
}
|
||||
|
||||
|
||||
void STROKE_GLYPH::Move( const VECTOR2I& aOffset )
|
||||
{
|
||||
m_boundingBox.Offset( aOffset );
|
||||
|
||||
for( std::vector<VECTOR2D>& pointList : *this )
|
||||
{
|
||||
for( VECTOR2D& point : pointList )
|
||||
point += aOffset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BOX2D OUTLINE_GLYPH::BoundingBox()
|
||||
{
|
||||
BOX2I bbox = BBox();
|
||||
|
||||
@@ -327,8 +327,9 @@ const FP_LIB_TABLE_ROW* FP_LIB_TABLE::FindRow( const wxString& aNickname, bool a
|
||||
|
||||
if( !row )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "fp-lib-table files contain no library named '%s'." ),
|
||||
aNickname );
|
||||
// We don't generally show this string to the user (who is unlikely to know what
|
||||
// "fp-lib-table" means), and translating it may produce Sentry KICAD-YP.
|
||||
wxString msg = wxString::Format( wxS( "'%s' not found in fp-lib-table." ), aNickname );
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
|
||||
|
||||
@@ -185,7 +185,11 @@ void ANTIALIASING_SUPERSAMPLING::Present()
|
||||
glBindTexture( GL_TEXTURE_2D, compositor->GetBufferTexture( ssaaMainBuffer ) );
|
||||
compositor->SetBuffer( OPENGL_COMPOSITOR::DIRECT_RENDERING );
|
||||
|
||||
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE );
|
||||
|
||||
draw_fullscreen_primitive();
|
||||
|
||||
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
|
||||
}
|
||||
|
||||
|
||||
@@ -547,7 +551,11 @@ void ANTIALIASING_SMAA::Present()
|
||||
glActiveTexture( GL_TEXTURE1 );
|
||||
glBindTexture( GL_TEXTURE_2D, blendTex );
|
||||
|
||||
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE );
|
||||
|
||||
pass_3_shader->Use();
|
||||
draw_fullscreen_triangle();
|
||||
pass_3_shader->Deactivate();
|
||||
|
||||
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
|
||||
}
|
||||
|
||||
@@ -297,7 +297,7 @@ void OPENGL_COMPOSITOR::ClearBuffer( const COLOR4D& aColor )
|
||||
{
|
||||
wxASSERT( m_initialized );
|
||||
|
||||
glClearColor( aColor.r, aColor.g, aColor.b, 0.0f );
|
||||
glClearColor( aColor.r, aColor.g, aColor.b, m_curFbo == DIRECT_RENDERING ? 1.0f : 0.0f );
|
||||
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
|
||||
}
|
||||
|
||||
|
||||
@@ -1005,11 +1005,20 @@ void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius,
|
||||
|
||||
VECTOR2D p( cos( startAngle ) * aRadius, sin( startAngle ) * aRadius );
|
||||
double alpha;
|
||||
unsigned int lineCount = 0;
|
||||
|
||||
for( alpha = startAngle + alphaIncrement; alpha <= endAngle; alpha += alphaIncrement )
|
||||
lineCount++;
|
||||
|
||||
if( alpha != endAngle )
|
||||
lineCount++;
|
||||
|
||||
reserveLineQuads( lineCount );
|
||||
|
||||
for( alpha = startAngle + alphaIncrement; alpha <= endAngle; alpha += alphaIncrement )
|
||||
{
|
||||
VECTOR2D p_next( cos( alpha ) * aRadius, sin( alpha ) * aRadius );
|
||||
DrawLine( p, p_next );
|
||||
drawLineQuad( p, p_next, false );
|
||||
|
||||
p = p_next;
|
||||
}
|
||||
@@ -1018,7 +1027,7 @@ void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius,
|
||||
if( alpha != endAngle )
|
||||
{
|
||||
VECTOR2D p_last( cos( endAngle ) * aRadius, sin( endAngle ) * aRadius );
|
||||
DrawLine( p, p_last );
|
||||
drawLineQuad( p, p_last, false );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1058,9 +1067,21 @@ void OPENGL_GAL::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius,
|
||||
if( seg_count % 2 != 0 )
|
||||
seg_count += 1;
|
||||
|
||||
// Our shaders have trouble rendering null line quads, so delegate this task to DrawSegment.
|
||||
if( seg_count == 0 )
|
||||
{
|
||||
VECTOR2D p_start( aCenterPoint.x + cos( startAngle ) * aRadius,
|
||||
aCenterPoint.y + sin( startAngle ) * aRadius );
|
||||
|
||||
VECTOR2D p_end( aCenterPoint.x + cos( endAngle ) * aRadius,
|
||||
aCenterPoint.y + sin( endAngle ) * aRadius );
|
||||
|
||||
DrawSegment( p_start, p_end, aWidth );
|
||||
return;
|
||||
}
|
||||
|
||||
// Recalculate alphaIncrement with a even integer number of segment
|
||||
if( seg_count )
|
||||
alphaIncrement = ( endAngle - startAngle ) / seg_count;
|
||||
alphaIncrement = ( endAngle - startAngle ) / seg_count;
|
||||
|
||||
Save();
|
||||
m_currentManager->Translate( aCenterPoint.x, aCenterPoint.y, 0.0 );
|
||||
|
||||
@@ -444,7 +444,7 @@ void GRID_TRICKS::doPopupSelection( wxCommandEvent& event )
|
||||
break;
|
||||
|
||||
default:
|
||||
if( menu_id >= GRIDTRICKS_FIRST_SHOWHIDE )
|
||||
if( menu_id >= GRIDTRICKS_FIRST_SHOWHIDE && m_grid->CommitPendingChanges( false ) )
|
||||
{
|
||||
int col = menu_id - GRIDTRICKS_FIRST_SHOWHIDE;
|
||||
|
||||
|
||||
@@ -32,14 +32,18 @@
|
||||
class PSEUDO_ACTION : public TOOL_ACTION
|
||||
{
|
||||
public:
|
||||
PSEUDO_ACTION( const wxString& aLabel, int aHotKey )
|
||||
PSEUDO_ACTION( const wxString& aLabel, int aHotKey, int aHotKeyAlt = 0 )
|
||||
{
|
||||
m_friendlyName = aLabel;
|
||||
m_hotKey = aHotKey;
|
||||
m_hotKeyAlt = aHotKeyAlt;
|
||||
}
|
||||
};
|
||||
|
||||
static PSEUDO_ACTION* g_gesturePseudoActions[] = {
|
||||
new PSEUDO_ACTION( _( "Accept Autocomplete" ), WXK_RETURN, WXK_NUMPAD_ENTER ),
|
||||
new PSEUDO_ACTION( _( "Cancel Autocomplete" ), WXK_ESCAPE ),
|
||||
new PSEUDO_ACTION( _( "Toggle Checkbox" ), WXK_SPACE ),
|
||||
new PSEUDO_ACTION( _( "Pan Left/Right" ), MD_CTRL + PSEUDO_WXK_WHEEL ),
|
||||
new PSEUDO_ACTION( _( "Pan Up/Down" ), MD_SHIFT + PSEUDO_WXK_WHEEL ),
|
||||
new PSEUDO_ACTION( _( "Finish Drawing" ), PSEUDO_WXK_DBLCLICK ),
|
||||
|
||||
+64
-63
@@ -63,79 +63,80 @@ struct hotkey_name_descr
|
||||
#define KEY_NON_FOUND -1
|
||||
static struct hotkey_name_descr hotkeyNameList[] =
|
||||
{
|
||||
{ wxT( "F1" ), WXK_F1 },
|
||||
{ wxT( "F2" ), WXK_F2 },
|
||||
{ wxT( "F3" ), WXK_F3 },
|
||||
{ wxT( "F4" ), WXK_F4 },
|
||||
{ wxT( "F5" ), WXK_F5 },
|
||||
{ wxT( "F6" ), WXK_F6 },
|
||||
{ wxT( "F7" ), WXK_F7 },
|
||||
{ wxT( "F8" ), WXK_F8 },
|
||||
{ wxT( "F9" ), WXK_F9 },
|
||||
{ wxT( "F10" ), WXK_F10 },
|
||||
{ wxT( "F11" ), WXK_F11 },
|
||||
{ wxT( "F12" ), WXK_F12 },
|
||||
{ wxT( "F13" ), WXK_F13 },
|
||||
{ wxT( "F14" ), WXK_F14 },
|
||||
{ wxT( "F15" ), WXK_F15 },
|
||||
{ wxT( "F16" ), WXK_F16 },
|
||||
{ wxT( "F17" ), WXK_F17 },
|
||||
{ wxT( "F18" ), WXK_F18 },
|
||||
{ wxT( "F19" ), WXK_F19 },
|
||||
{ wxT( "F20" ), WXK_F20 },
|
||||
{ wxT( "F21" ), WXK_F21 },
|
||||
{ wxT( "F22" ), WXK_F22 },
|
||||
{ wxT( "F23" ), WXK_F23 },
|
||||
{ wxT( "F24" ), WXK_F24 },
|
||||
{ wxT( "F1" ), WXK_F1 },
|
||||
{ wxT( "F2" ), WXK_F2 },
|
||||
{ wxT( "F3" ), WXK_F3 },
|
||||
{ wxT( "F4" ), WXK_F4 },
|
||||
{ wxT( "F5" ), WXK_F5 },
|
||||
{ wxT( "F6" ), WXK_F6 },
|
||||
{ wxT( "F7" ), WXK_F7 },
|
||||
{ wxT( "F8" ), WXK_F8 },
|
||||
{ wxT( "F9" ), WXK_F9 },
|
||||
{ wxT( "F10" ), WXK_F10 },
|
||||
{ wxT( "F11" ), WXK_F11 },
|
||||
{ wxT( "F12" ), WXK_F12 },
|
||||
{ wxT( "F13" ), WXK_F13 },
|
||||
{ wxT( "F14" ), WXK_F14 },
|
||||
{ wxT( "F15" ), WXK_F15 },
|
||||
{ wxT( "F16" ), WXK_F16 },
|
||||
{ wxT( "F17" ), WXK_F17 },
|
||||
{ wxT( "F18" ), WXK_F18 },
|
||||
{ wxT( "F19" ), WXK_F19 },
|
||||
{ wxT( "F20" ), WXK_F20 },
|
||||
{ wxT( "F21" ), WXK_F21 },
|
||||
{ wxT( "F22" ), WXK_F22 },
|
||||
{ wxT( "F23" ), WXK_F23 },
|
||||
{ wxT( "F24" ), WXK_F24 },
|
||||
|
||||
{ wxT( "Esc" ), WXK_ESCAPE },
|
||||
{ wxT( "Del" ), WXK_DELETE },
|
||||
{ wxT( "Tab" ), WXK_TAB },
|
||||
{ wxT( "Back" ), WXK_BACK },
|
||||
{ wxT( "Ins" ), WXK_INSERT },
|
||||
{ wxT( "Esc" ), WXK_ESCAPE },
|
||||
{ wxT( "Del" ), WXK_DELETE },
|
||||
{ wxT( "Tab" ), WXK_TAB },
|
||||
{ wxT( "Back" ), WXK_BACK },
|
||||
{ wxT( "Ins" ), WXK_INSERT },
|
||||
|
||||
{ wxT( "Home" ), WXK_HOME },
|
||||
{ wxT( "End" ), WXK_END },
|
||||
{ wxT( "PgUp" ), WXK_PAGEUP },
|
||||
{ wxT( "PgDn" ), WXK_PAGEDOWN },
|
||||
{ wxT( "Home" ), WXK_HOME },
|
||||
{ wxT( "End" ), WXK_END },
|
||||
{ wxT( "PgUp" ), WXK_PAGEUP },
|
||||
{ wxT( "PgDn" ), WXK_PAGEDOWN },
|
||||
|
||||
{ wxT( "Up" ), WXK_UP },
|
||||
{ wxT( "Down" ), WXK_DOWN },
|
||||
{ wxT( "Left" ), WXK_LEFT },
|
||||
{ wxT( "Right" ), WXK_RIGHT },
|
||||
{ wxT( "Up" ), WXK_UP },
|
||||
{ wxT( "Down" ), WXK_DOWN },
|
||||
{ wxT( "Left" ), WXK_LEFT },
|
||||
{ wxT( "Right" ), WXK_RIGHT },
|
||||
|
||||
{ wxT( "Return" ), WXK_RETURN },
|
||||
{ wxT( "Return" ), WXK_RETURN },
|
||||
|
||||
{ wxT( "Space" ), WXK_SPACE },
|
||||
{ wxT( "Space" ), WXK_SPACE },
|
||||
|
||||
{ wxT( "Num Pad 0" ), WXK_NUMPAD0 },
|
||||
{ wxT( "Num Pad 1" ), WXK_NUMPAD1 },
|
||||
{ wxT( "Num Pad 2" ), WXK_NUMPAD2 },
|
||||
{ wxT( "Num Pad 3" ), WXK_NUMPAD3 },
|
||||
{ wxT( "Num Pad 4" ), WXK_NUMPAD4 },
|
||||
{ wxT( "Num Pad 5" ), WXK_NUMPAD5 },
|
||||
{ wxT( "Num Pad 6" ), WXK_NUMPAD6 },
|
||||
{ wxT( "Num Pad 7" ), WXK_NUMPAD7 },
|
||||
{ wxT( "Num Pad 8" ), WXK_NUMPAD8 },
|
||||
{ wxT( "Num Pad 9" ), WXK_NUMPAD9 },
|
||||
{ wxT( "Num Pad +" ), WXK_NUMPAD_ADD },
|
||||
{ wxT( "Num Pad -" ), WXK_NUMPAD_SUBTRACT },
|
||||
{ wxT( "Num Pad *" ), WXK_NUMPAD_MULTIPLY },
|
||||
{ wxT( "Num Pad /" ), WXK_NUMPAD_DIVIDE },
|
||||
{ wxT( "Num Pad ." ), WXK_NUMPAD_SEPARATOR },
|
||||
{ wxT( "Num Pad F1"), WXK_NUMPAD_F1 },
|
||||
{ wxT( "Num Pad F2"), WXK_NUMPAD_F2 },
|
||||
{ wxT( "Num Pad F3"), WXK_NUMPAD_F3 },
|
||||
{ wxT( "Num Pad F4"), WXK_NUMPAD_F4 },
|
||||
{ wxT( "Num Pad 0" ), WXK_NUMPAD0 },
|
||||
{ wxT( "Num Pad 1" ), WXK_NUMPAD1 },
|
||||
{ wxT( "Num Pad 2" ), WXK_NUMPAD2 },
|
||||
{ wxT( "Num Pad 3" ), WXK_NUMPAD3 },
|
||||
{ wxT( "Num Pad 4" ), WXK_NUMPAD4 },
|
||||
{ wxT( "Num Pad 5" ), WXK_NUMPAD5 },
|
||||
{ wxT( "Num Pad 6" ), WXK_NUMPAD6 },
|
||||
{ wxT( "Num Pad 7" ), WXK_NUMPAD7 },
|
||||
{ wxT( "Num Pad 8" ), WXK_NUMPAD8 },
|
||||
{ wxT( "Num Pad 9" ), WXK_NUMPAD9 },
|
||||
{ wxT( "Num Pad +" ), WXK_NUMPAD_ADD },
|
||||
{ wxT( "Num Pad -" ), WXK_NUMPAD_SUBTRACT },
|
||||
{ wxT( "Num Pad *" ), WXK_NUMPAD_MULTIPLY },
|
||||
{ wxT( "Num Pad /" ), WXK_NUMPAD_DIVIDE },
|
||||
{ wxT( "Num Pad ." ), WXK_NUMPAD_SEPARATOR },
|
||||
{ wxT( "Num Pad Enter" ), WXK_NUMPAD_ENTER },
|
||||
{ wxT( "Num Pad F1"), WXK_NUMPAD_F1 },
|
||||
{ wxT( "Num Pad F2"), WXK_NUMPAD_F2 },
|
||||
{ wxT( "Num Pad F3"), WXK_NUMPAD_F3 },
|
||||
{ wxT( "Num Pad F4"), WXK_NUMPAD_F4 },
|
||||
|
||||
{ wxT( "" ), 0 },
|
||||
{ wxT( "" ), 0 },
|
||||
|
||||
{ wxT( "Click" ), PSEUDO_WXK_CLICK },
|
||||
{ wxT( "DblClick" ), PSEUDO_WXK_DBLCLICK },
|
||||
{ wxT( "Wheel" ), PSEUDO_WXK_WHEEL },
|
||||
{ wxT( "Click" ), PSEUDO_WXK_CLICK },
|
||||
{ wxT( "DblClick" ), PSEUDO_WXK_DBLCLICK },
|
||||
{ wxT( "Wheel" ), PSEUDO_WXK_WHEEL },
|
||||
|
||||
// Do not change this line: end of list
|
||||
{ wxT( "" ), KEY_NON_FOUND }
|
||||
{ wxT( "" ), KEY_NON_FOUND }
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2019-2020 Thomas Pointhuber <thomas.pointhuber@gmx.at>
|
||||
* Copyright (C) 2020-2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "altium_ascii_parser.h"
|
||||
#include "altium_parser_utils.h"
|
||||
|
||||
|
||||
ALTIUM_ASCII_PARSER::ALTIUM_ASCII_PARSER( const wxString& aInputFile ) :
|
||||
m_fileInput( aInputFile.fn_str() )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
std::map<wxString, wxString> ALTIUM_ASCII_PARSER::ReadProperties()
|
||||
{
|
||||
std::map<wxString, wxString> kv;
|
||||
std::string str;
|
||||
std::string line;
|
||||
|
||||
// Lines ending with |> continue on the next line
|
||||
do
|
||||
{
|
||||
if( !std::getline( m_fileInput, line ) )
|
||||
{
|
||||
m_error = true;
|
||||
return kv;
|
||||
}
|
||||
|
||||
if( ( line.size() > 2 && line[line.size() - 2] == '|' && line[line.size() - 1] == '>' ) )
|
||||
{
|
||||
str.append( line, 0, line.size() - 2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
str.append( line );
|
||||
break;
|
||||
}
|
||||
} while( true );
|
||||
|
||||
std::size_t token_end = 0;
|
||||
|
||||
while( token_end < str.size() && token_end != std::string::npos )
|
||||
{
|
||||
std::size_t token_start = str.find( '|', token_end );
|
||||
std::size_t token_equal = str.find( '=', token_end );
|
||||
std::size_t key_start;
|
||||
|
||||
if( token_start <= token_equal )
|
||||
{
|
||||
key_start = token_start + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Leading "|" before "RECORD=28" may be missing in older schematic versions.
|
||||
key_start = token_end;
|
||||
}
|
||||
|
||||
token_end = str.find( '|', key_start );
|
||||
|
||||
if( token_equal >= token_end )
|
||||
{
|
||||
continue; // this looks like an error: skip the entry. Also matches on std::string::npos
|
||||
}
|
||||
|
||||
if( token_end == std::string::npos )
|
||||
{
|
||||
token_end = str.size() + 1; // this is the correct offset
|
||||
}
|
||||
|
||||
std::string keyS = str.substr( key_start, token_equal - key_start );
|
||||
std::string valueS = str.substr( token_equal + 1, token_end - token_equal - 1 );
|
||||
|
||||
// convert the strings to wxStrings, since we use them everywhere
|
||||
// value can have non-ASCII characters, so we convert them from LATIN1/ISO8859-1
|
||||
wxString key( keyS.c_str(), wxConvISO8859_1 );
|
||||
// Altium stores keys either in Upper, or in CamelCase. Lets unify it.
|
||||
wxString canonicalKey = key.Trim( false ).Trim( true ).MakeUpper();
|
||||
// If the key starts with '%UTF8%' we have to parse the value using UTF8
|
||||
wxString value;
|
||||
|
||||
if( canonicalKey.StartsWith( "%UTF8%" ) )
|
||||
value = wxString( valueS.c_str(), wxConvUTF8 );
|
||||
else
|
||||
value = wxString( valueS.c_str(), wxConvISO8859_1 );
|
||||
|
||||
if( canonicalKey != wxS( "PATTERN" ) && canonicalKey != wxS( "SOURCEFOOTPRINTLIBRARY" ) )
|
||||
{
|
||||
// Breathless hack because I haven't a clue what the story is here (but this character
|
||||
// appears in a lot of radial dimensions and is rendered by Altium as a space).
|
||||
value.Replace( wxT( "ÿ" ), wxT( " " ) );
|
||||
}
|
||||
|
||||
// Storage binary data do not need conversion.
|
||||
if( str.rfind( "|BINARY", 0 ) != 0 )
|
||||
{
|
||||
if( canonicalKey == wxT( "DESIGNATOR" ) || canonicalKey == wxT( "NAME" )
|
||||
|| canonicalKey == wxT( "TEXT" ) )
|
||||
{
|
||||
value = AltiumPropertyToKiCadString( value );
|
||||
}
|
||||
}
|
||||
|
||||
kv.insert( { canonicalKey, value.Trim() } );
|
||||
}
|
||||
|
||||
return kv;
|
||||
}
|
||||
|
||||
|
||||
bool ALTIUM_ASCII_PARSER::CanRead()
|
||||
{
|
||||
return m_fileInput && m_fileInput.peek() != std::ifstream::traits_type::eof();
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2019-2020 Thomas Pointhuber <thomas.pointhuber@gmx.at>
|
||||
* Copyright (C) 2020-2024 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 _ALTIUM_PARSER_H
|
||||
#define _ALTIUM_PARSER_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
#include <wx/string.h>
|
||||
|
||||
|
||||
class ALTIUM_ASCII_PARSER
|
||||
{
|
||||
public:
|
||||
ALTIUM_ASCII_PARSER( const wxString& aInputFile );
|
||||
|
||||
std::map<wxString, wxString> ReadProperties();
|
||||
|
||||
bool CanRead();
|
||||
|
||||
bool HasParsingError()
|
||||
{
|
||||
return m_error;
|
||||
}
|
||||
|
||||
private:
|
||||
std::ifstream m_fileInput;
|
||||
bool m_error = false;
|
||||
};
|
||||
|
||||
#endif //_ALTIUM_PARSER_H
|
||||
@@ -22,7 +22,7 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "altium_parser.h"
|
||||
#include "altium_binary_parser.h"
|
||||
#include "altium_parser_utils.h"
|
||||
|
||||
#include <compoundfilereader.h>
|
||||
@@ -350,13 +350,13 @@ void ALTIUM_COMPOUND_FILE::cacheLibFootprintNames()
|
||||
|
||||
if( m_reader->IsStream( entry ) && fileName == L"Parameters" )
|
||||
{
|
||||
ALTIUM_PARSER parametersReader( *this, entry );
|
||||
ALTIUM_BINARY_PARSER parametersReader( *this, entry );
|
||||
std::map<wxString, wxString> parameterProperties =
|
||||
parametersReader.ReadProperties();
|
||||
|
||||
wxString key = ALTIUM_PARSER::ReadString(
|
||||
wxString key = ALTIUM_PROPS_UTILS::ReadString(
|
||||
parameterProperties, wxT( "PATTERN" ), wxT( "" ) );
|
||||
wxString fpName = ALTIUM_PARSER::ReadUnicodeString(
|
||||
wxString fpName = ALTIUM_PROPS_UTILS::ReadUnicodeString(
|
||||
parameterProperties, wxT( "PATTERN" ), wxT( "" ) );
|
||||
|
||||
m_libFootprintDirNameCache[key] = fpName;
|
||||
@@ -370,7 +370,7 @@ void ALTIUM_COMPOUND_FILE::cacheLibFootprintNames()
|
||||
}
|
||||
|
||||
|
||||
ALTIUM_PARSER::ALTIUM_PARSER( const ALTIUM_COMPOUND_FILE& aFile,
|
||||
ALTIUM_BINARY_PARSER::ALTIUM_BINARY_PARSER( const ALTIUM_COMPOUND_FILE& aFile,
|
||||
const CFB::COMPOUND_FILE_ENTRY* aEntry )
|
||||
{
|
||||
m_subrecord_end = nullptr;
|
||||
@@ -384,7 +384,7 @@ ALTIUM_PARSER::ALTIUM_PARSER( const ALTIUM_COMPOUND_FILE& aFile,
|
||||
}
|
||||
|
||||
|
||||
ALTIUM_PARSER::ALTIUM_PARSER( std::unique_ptr<char[]>& aContent, size_t aSize )
|
||||
ALTIUM_BINARY_PARSER::ALTIUM_BINARY_PARSER( std::unique_ptr<char[]>& aContent, size_t aSize )
|
||||
{
|
||||
m_subrecord_end = nullptr;
|
||||
m_size = aSize;
|
||||
@@ -394,7 +394,7 @@ ALTIUM_PARSER::ALTIUM_PARSER( std::unique_ptr<char[]>& aContent, size_t aSize )
|
||||
}
|
||||
|
||||
|
||||
std::map<wxString, wxString> ALTIUM_PARSER::ReadProperties(
|
||||
std::map<wxString, wxString> ALTIUM_BINARY_PARSER::ReadProperties(
|
||||
std::function<std::map<wxString, wxString>( const std::string& )> handleBinaryData )
|
||||
{
|
||||
|
||||
@@ -502,123 +502,3 @@ std::map<wxString, wxString> ALTIUM_PARSER::ReadProperties(
|
||||
return kv;
|
||||
}
|
||||
|
||||
|
||||
int32_t ALTIUM_PARSER::ConvertToKicadUnit( const double aValue )
|
||||
{
|
||||
constexpr double int_limit = ( std::numeric_limits<int>::max() - 10 ) / 2.54;
|
||||
|
||||
int32_t iu = KiROUND( Clamp<double>( -int_limit, aValue, int_limit ) * 2.54 );
|
||||
|
||||
// Altium's internal precision is 0.1uinch. KiCad's is 1nm. Round to nearest 10nm to clean
|
||||
// up most rounding errors. This allows lossless conversion of increments of 0.05mils and
|
||||
// 0.01um.
|
||||
return KiROUND( (double) iu / 10.0 ) * 10;
|
||||
}
|
||||
|
||||
|
||||
int ALTIUM_PARSER::ReadInt( const std::map<wxString, wxString>& aProps, const wxString& aKey,
|
||||
int aDefault )
|
||||
{
|
||||
const std::map<wxString, wxString>::const_iterator& value = aProps.find( aKey );
|
||||
return value == aProps.end() ? aDefault : wxAtoi( value->second );
|
||||
}
|
||||
|
||||
|
||||
double ALTIUM_PARSER::ReadDouble( const std::map<wxString, wxString>& aProps, const wxString& aKey,
|
||||
double aDefault )
|
||||
{
|
||||
const std::map<wxString, wxString>::const_iterator& value = aProps.find( aKey );
|
||||
|
||||
if( value == aProps.end() )
|
||||
return aDefault;
|
||||
|
||||
// Locale independent str -> double conversation
|
||||
std::istringstream istr( (const char*) value->second.mb_str() );
|
||||
istr.imbue( std::locale::classic() );
|
||||
|
||||
double doubleValue;
|
||||
istr >> doubleValue;
|
||||
return doubleValue;
|
||||
}
|
||||
|
||||
|
||||
bool ALTIUM_PARSER::ReadBool( const std::map<wxString, wxString>& aProps, const wxString& aKey,
|
||||
bool aDefault )
|
||||
{
|
||||
const std::map<wxString, wxString>::const_iterator& value = aProps.find( aKey );
|
||||
|
||||
if( value == aProps.end() )
|
||||
return aDefault;
|
||||
else
|
||||
return value->second == "T" || value->second == "TRUE";
|
||||
}
|
||||
|
||||
|
||||
int32_t ALTIUM_PARSER::ReadKicadUnit( const std::map<wxString, wxString>& aProps,
|
||||
const wxString& aKey, const wxString& aDefault )
|
||||
{
|
||||
const wxString& value = ReadString( aProps, aKey, aDefault );
|
||||
|
||||
wxString prefix;
|
||||
|
||||
if( !value.EndsWith( "mil", &prefix ) )
|
||||
{
|
||||
wxLogError( _( "Unit '%s' does not end with 'mil'." ), value );
|
||||
return 0;
|
||||
}
|
||||
|
||||
prefix.StartsWith( "+", &prefix );
|
||||
|
||||
double mils;
|
||||
|
||||
if( !prefix.ToCDouble( &mils ) )
|
||||
{
|
||||
wxLogError( _( "Cannot convert '%s' to double." ), prefix );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ConvertToKicadUnit( mils * 10000 );
|
||||
}
|
||||
|
||||
|
||||
wxString ALTIUM_PARSER::ReadString( const std::map<wxString, wxString>& aProps,
|
||||
const wxString& aKey, const wxString& aDefault )
|
||||
{
|
||||
const auto& utf8Value = aProps.find( wxString( "%UTF8%" ) + aKey );
|
||||
|
||||
if( utf8Value != aProps.end() )
|
||||
return utf8Value->second;
|
||||
|
||||
const auto& value = aProps.find( aKey );
|
||||
|
||||
if( value != aProps.end() )
|
||||
return value->second;
|
||||
|
||||
return aDefault;
|
||||
}
|
||||
|
||||
|
||||
wxString ALTIUM_PARSER::ReadUnicodeString( const std::map<wxString, wxString>& aProps,
|
||||
const wxString& aKey, const wxString& aDefault )
|
||||
{
|
||||
const auto& unicodeFlag = aProps.find( wxS( "UNICODE" ) );
|
||||
|
||||
if( unicodeFlag != aProps.end() && unicodeFlag->second.Contains( wxS( "EXISTS" ) ) )
|
||||
{
|
||||
const auto& unicodeValue = aProps.find( wxString( "UNICODE__" ) + aKey );
|
||||
|
||||
if( unicodeValue != aProps.end() )
|
||||
{
|
||||
wxArrayString arr = wxSplit( unicodeValue->second, ',', '\0' );
|
||||
wxString out;
|
||||
|
||||
for( wxString part : arr )
|
||||
out += wxString( wchar_t( wxAtoi( part ) ) );
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
return ReadString( aProps, aKey, aDefault );
|
||||
}
|
||||
|
||||
@@ -22,8 +22,10 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef ALTIUM_PARSER_H
|
||||
#define ALTIUM_PARSER_H
|
||||
#ifndef _ALTIUM_BINARY_PARSER_H
|
||||
#define _ALTIUM_BINARY_PARSER_H
|
||||
|
||||
#include "altium_props_utils.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
@@ -106,12 +108,12 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class ALTIUM_PARSER
|
||||
class ALTIUM_BINARY_PARSER
|
||||
{
|
||||
public:
|
||||
ALTIUM_PARSER( const ALTIUM_COMPOUND_FILE& aFile, const CFB::COMPOUND_FILE_ENTRY* aEntry );
|
||||
ALTIUM_PARSER( std::unique_ptr<char[]>& aContent, size_t aSize );
|
||||
~ALTIUM_PARSER() = default;
|
||||
ALTIUM_BINARY_PARSER( const ALTIUM_COMPOUND_FILE& aFile, const CFB::COMPOUND_FILE_ENTRY* aEntry );
|
||||
ALTIUM_BINARY_PARSER( std::unique_ptr<char[]>& aContent, size_t aSize );
|
||||
~ALTIUM_BINARY_PARSER() = default;
|
||||
|
||||
template <typename Type>
|
||||
Type Read()
|
||||
@@ -229,7 +231,7 @@ public:
|
||||
|
||||
int32_t ReadKicadUnit()
|
||||
{
|
||||
return ConvertToKicadUnit( Read<int32_t>() );
|
||||
return ALTIUM_PROPS_UTILS::ConvertToKicadUnit( Read<int32_t>() );
|
||||
}
|
||||
|
||||
int32_t ReadKicadUnitX()
|
||||
@@ -270,26 +272,6 @@ public:
|
||||
return std::map<wxString, wxString>();
|
||||
} );
|
||||
|
||||
static int32_t ConvertToKicadUnit( const double aValue );
|
||||
|
||||
static int ReadInt( const std::map<wxString, wxString>& aProps,
|
||||
const wxString& aKey, int aDefault );
|
||||
|
||||
static double ReadDouble( const std::map<wxString, wxString>& aProps,
|
||||
const wxString& aKey, double aDefault );
|
||||
|
||||
static bool ReadBool( const std::map<wxString, wxString>& aProps,
|
||||
const wxString& aKey, bool aDefault );
|
||||
|
||||
static int32_t ReadKicadUnit( const std::map<wxString, wxString>& aProps,
|
||||
const wxString& aKey, const wxString& aDefault );
|
||||
|
||||
static wxString ReadString( const std::map<wxString, wxString>& aProps,
|
||||
const wxString& aKey, const wxString& aDefault );
|
||||
|
||||
static wxString ReadUnicodeString( const std::map<wxString, wxString>& aProps,
|
||||
const wxString& aKey, const wxString& aDefault );
|
||||
|
||||
void Skip( size_t aLength )
|
||||
{
|
||||
if( GetRemainingBytes() >= aLength )
|
||||
@@ -447,4 +429,4 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
#endif //ALTIUM_PARSER_H
|
||||
#endif //_ALTIUM_BINARY_PARSER_H
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2019-2020 Thomas Pointhuber <thomas.pointhuber@gmx.at>
|
||||
* Copyright (C) 2020-2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "altium_props_utils.h"
|
||||
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <math/util.h>
|
||||
|
||||
#include <wx/crt.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/translation.h>
|
||||
|
||||
|
||||
int32_t ALTIUM_PROPS_UTILS::ConvertToKicadUnit( const double aValue )
|
||||
{
|
||||
constexpr double int_limit = ( std::numeric_limits<int>::max() - 10 ) / 2.54;
|
||||
|
||||
int32_t iu = KiROUND( Clamp<double>( -int_limit, aValue, int_limit ) * 2.54 );
|
||||
|
||||
// Altium's internal precision is 0.1uinch. KiCad's is 1nm. Round to nearest 10nm to clean
|
||||
// up most rounding errors. This allows lossless conversion of increments of 0.05mils and
|
||||
// 0.01um.
|
||||
return KiROUND( (double) iu / 10.0 ) * 10;
|
||||
}
|
||||
|
||||
|
||||
int ALTIUM_PROPS_UTILS::ReadInt( const std::map<wxString, wxString>& aProps, const wxString& aKey,
|
||||
int aDefault )
|
||||
{
|
||||
const std::map<wxString, wxString>::const_iterator& value = aProps.find( aKey );
|
||||
return value == aProps.end() ? aDefault : wxAtoi( value->second );
|
||||
}
|
||||
|
||||
|
||||
double ALTIUM_PROPS_UTILS::ReadDouble( const std::map<wxString, wxString>& aProps, const wxString& aKey,
|
||||
double aDefault )
|
||||
{
|
||||
const std::map<wxString, wxString>::const_iterator& value = aProps.find( aKey );
|
||||
|
||||
if( value == aProps.end() )
|
||||
return aDefault;
|
||||
|
||||
// Locale independent str -> double conversation
|
||||
std::istringstream istr( (const char*) value->second.mb_str() );
|
||||
istr.imbue( std::locale::classic() );
|
||||
|
||||
double doubleValue;
|
||||
istr >> doubleValue;
|
||||
return doubleValue;
|
||||
}
|
||||
|
||||
|
||||
bool ALTIUM_PROPS_UTILS::ReadBool( const std::map<wxString, wxString>& aProps, const wxString& aKey,
|
||||
bool aDefault )
|
||||
{
|
||||
const std::map<wxString, wxString>::const_iterator& value = aProps.find( aKey );
|
||||
|
||||
if( value == aProps.end() )
|
||||
return aDefault;
|
||||
else
|
||||
return value->second == "T" || value->second == "TRUE";
|
||||
}
|
||||
|
||||
|
||||
int32_t ALTIUM_PROPS_UTILS::ReadKicadUnit( const std::map<wxString, wxString>& aProps,
|
||||
const wxString& aKey, const wxString& aDefault )
|
||||
{
|
||||
const wxString& value = ReadString( aProps, aKey, aDefault );
|
||||
|
||||
wxString prefix;
|
||||
|
||||
if( !value.EndsWith( "mil", &prefix ) )
|
||||
{
|
||||
wxLogError( _( "Unit '%s' does not end with 'mil'." ), value );
|
||||
return 0;
|
||||
}
|
||||
|
||||
prefix.StartsWith( "+", &prefix );
|
||||
|
||||
double mils;
|
||||
|
||||
if( !prefix.ToCDouble( &mils ) )
|
||||
{
|
||||
wxLogError( _( "Cannot convert '%s' to double." ), prefix );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ConvertToKicadUnit( mils * 10000 );
|
||||
}
|
||||
|
||||
|
||||
wxString ALTIUM_PROPS_UTILS::ReadString( const std::map<wxString, wxString>& aProps,
|
||||
const wxString& aKey, const wxString& aDefault )
|
||||
{
|
||||
const auto& utf8Value = aProps.find( wxString( "%UTF8%" ) + aKey );
|
||||
|
||||
if( utf8Value != aProps.end() )
|
||||
return utf8Value->second;
|
||||
|
||||
const auto& value = aProps.find( aKey );
|
||||
|
||||
if( value != aProps.end() )
|
||||
return value->second;
|
||||
|
||||
return aDefault;
|
||||
}
|
||||
|
||||
|
||||
wxString ALTIUM_PROPS_UTILS::ReadUnicodeString( const std::map<wxString, wxString>& aProps,
|
||||
const wxString& aKey, const wxString& aDefault )
|
||||
{
|
||||
const auto& unicodeFlag = aProps.find( wxS( "UNICODE" ) );
|
||||
|
||||
if( unicodeFlag != aProps.end() && unicodeFlag->second.Contains( wxS( "EXISTS" ) ) )
|
||||
{
|
||||
const auto& unicodeValue = aProps.find( wxString( "UNICODE__" ) + aKey );
|
||||
|
||||
if( unicodeValue != aProps.end() )
|
||||
{
|
||||
wxArrayString arr = wxSplit( unicodeValue->second, ',', '\0' );
|
||||
wxString out;
|
||||
|
||||
for( wxString part : arr )
|
||||
out += wxString( wchar_t( wxAtoi( part ) ) );
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
return ReadString( aProps, aKey, aDefault );
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2019-2020 Thomas Pointhuber <thomas.pointhuber@gmx.at>
|
||||
* Copyright (C) 2020-2024 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 _ALTIUM_PROPS_UTILS_H
|
||||
#define _ALTIUM_PROPS_UTILS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <map>
|
||||
|
||||
#include <wx/string.h>
|
||||
|
||||
|
||||
class ALTIUM_PROPS_UTILS
|
||||
{
|
||||
public:
|
||||
static int32_t ConvertToKicadUnit( const double aValue );
|
||||
|
||||
static int ReadInt( const std::map<wxString, wxString>& aProps, const wxString& aKey,
|
||||
int aDefault );
|
||||
|
||||
static double ReadDouble( const std::map<wxString, wxString>& aProps, const wxString& aKey,
|
||||
double aDefault );
|
||||
|
||||
static bool ReadBool( const std::map<wxString, wxString>& aProps, const wxString& aKey,
|
||||
bool aDefault );
|
||||
|
||||
static int32_t ReadKicadUnit( const std::map<wxString, wxString>& aProps, const wxString& aKey,
|
||||
const wxString& aDefault );
|
||||
|
||||
static wxString ReadString( const std::map<wxString, wxString>& aProps, const wxString& aKey,
|
||||
const wxString& aDefault );
|
||||
|
||||
static wxString ReadUnicodeString( const std::map<wxString, wxString>& aProps,
|
||||
const wxString& aKey, const wxString& aDefault );
|
||||
};
|
||||
|
||||
#endif //_ALTIUM_PROPS_UTILS_H
|
||||
@@ -979,13 +979,20 @@ EELEMENT::EELEMENT( wxXmlNode* aElement )
|
||||
<!ATTLIST element
|
||||
name %String; #REQUIRED
|
||||
library %String; #REQUIRED
|
||||
library_urn %Urn; ""
|
||||
package %String; #REQUIRED
|
||||
package3d_urn %Urn; ""
|
||||
override_package3d_urn %Urn; ""
|
||||
override_package_urn %Urn; ""
|
||||
override_locally_modified %Bool; "no"
|
||||
value %String; #REQUIRED
|
||||
x %Coord; #REQUIRED
|
||||
y %Coord; #REQUIRED
|
||||
locked %Bool; "no"
|
||||
populate %Bool; "yes"
|
||||
smashed %Bool; "no"
|
||||
rot %Rotation; "R0"
|
||||
grouprefs IDREFS #IMPLIED
|
||||
>
|
||||
*/
|
||||
|
||||
@@ -1001,6 +1008,7 @@ EELEMENT::EELEMENT( wxXmlNode* aElement )
|
||||
y = parseRequiredAttribute<ECOORD>( aElement, "y" );
|
||||
|
||||
// optional
|
||||
library_urn = parseOptionalAttribute<wxString>( aElement, "library_urn" );
|
||||
locked = parseOptionalAttribute<bool>( aElement, "locked" );
|
||||
smashed = parseOptionalAttribute<bool>( aElement, "smashed" );
|
||||
rot = parseOptionalAttribute<EROT>( aElement, "rot" );
|
||||
|
||||
@@ -817,6 +817,7 @@ struct EELEMENT
|
||||
{
|
||||
wxString name;
|
||||
wxString library;
|
||||
opt_wxString library_urn;
|
||||
wxString package;
|
||||
wxString value;
|
||||
ECOORD x;
|
||||
|
||||
@@ -87,6 +87,7 @@ void EASYEDA::from_json( const nlohmann::json& j, EASYEDA::DOCUMENT& d )
|
||||
PARSE_VALUE( head );
|
||||
|
||||
PARSE_VALUE( canvas );
|
||||
PARSE_VALUE( title );
|
||||
PARSE_VALUE( shape );
|
||||
PARSE_VALUE( dataStr );
|
||||
}
|
||||
|
||||
@@ -73,9 +73,10 @@ struct DOCUMENT
|
||||
|
||||
// BBox
|
||||
// colors
|
||||
wxString canvas;
|
||||
wxArrayString shape;
|
||||
std::optional<nlohmann::json> dataStr;
|
||||
wxString canvas;
|
||||
wxString title;
|
||||
wxArrayString shape;
|
||||
std::optional<nlohmann::json> dataStr;
|
||||
};
|
||||
|
||||
struct C_PARA
|
||||
|
||||
@@ -229,6 +229,9 @@ void Prettify( std::string& aSource, char aQuoteChar )
|
||||
++cursor;
|
||||
}
|
||||
|
||||
// newline required at end of line / file for POSIX compliance. Keeps git diffs clean.
|
||||
formatted += '\n';
|
||||
|
||||
aSource = std::move( formatted );
|
||||
}
|
||||
|
||||
|
||||
@@ -247,7 +247,12 @@ void LIB_TREE_NODE_ITEM::UpdateScore( EDA_COMBINED_MATCHER* aMatcher, const wxSt
|
||||
{
|
||||
int currentScore = aMatcher->ScoreTerms( m_SearchTerms );
|
||||
|
||||
if( m_Score >= 0 && currentScore > 0 )
|
||||
// This is a hack: the second phase of search in the adapter will look for a tokenized
|
||||
// LIB_ID and send the lib part down here. While we generally want to prune ourselves
|
||||
// out here (by setting score to -1) the first time we fail to match a search term,
|
||||
// we want to give the same search term a second chance if it has been split from a library
|
||||
// name.
|
||||
if( ( m_Score >= 0 || !aLib.IsEmpty() ) && currentScore > 0 )
|
||||
m_Score += currentScore;
|
||||
else
|
||||
m_Score = -1; // Item has failed to match this term, rule it out
|
||||
@@ -290,28 +295,42 @@ LIB_TREE_NODE_ITEM& LIB_TREE_NODE_LIBRARY::AddItem( LIB_TREE_ITEM* aItem )
|
||||
void LIB_TREE_NODE_LIBRARY::UpdateScore( EDA_COMBINED_MATCHER* aMatcher, const wxString& aLib,
|
||||
std::function<bool( LIB_TREE_NODE& aNode )>* aFilter )
|
||||
{
|
||||
int newScore = 0;
|
||||
int maxChildScore = 0;
|
||||
|
||||
for( std::unique_ptr<LIB_TREE_NODE>& child: m_Children )
|
||||
{
|
||||
child->UpdateScore( aMatcher, aLib, aFilter );
|
||||
newScore = std::max( newScore, child->m_Score );
|
||||
maxChildScore = std::max( maxChildScore, child->m_Score );
|
||||
}
|
||||
|
||||
// Each time UpdateScore is called for a library, child (item) scores may go up or down.
|
||||
// If the all go down to zero, we need to make sure to drop the library from the list.
|
||||
if( newScore > 0 )
|
||||
m_Score = std::max( m_Score, newScore );
|
||||
if( maxChildScore > 0 )
|
||||
m_Score = std::max( m_Score, maxChildScore );
|
||||
else
|
||||
m_Score = 0;
|
||||
|
||||
// aLib test is additive, but only when we've already accumulated some score from children
|
||||
if( !aLib.IsEmpty() && m_Name.Lower().Matches( aLib ) && m_Score > 0 )
|
||||
if( !aLib.IsEmpty()
|
||||
&& m_Name.Lower().Matches( aLib )
|
||||
&& ( m_Score > 0 || m_Children.empty() ) )
|
||||
{
|
||||
m_Score += 1;
|
||||
}
|
||||
|
||||
// aMatcher test is additive, but only when we've already accumulated some score from children
|
||||
if( aMatcher && m_Score > 0 )
|
||||
m_Score += aMatcher->ScoreTerms( m_SearchTerms );
|
||||
// aMatcher test is additive
|
||||
if( aMatcher )
|
||||
{
|
||||
int ownScore = aMatcher->ScoreTerms( m_SearchTerms );
|
||||
m_Score += ownScore;
|
||||
|
||||
// If we have a hit on a library, show all children in that library
|
||||
if( maxChildScore <= 0 && ownScore > 0 )
|
||||
{
|
||||
for( std::unique_ptr<LIB_TREE_NODE>& child: m_Children )
|
||||
child->ForceScore( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
// show all nodes if no search/filter/etc. criteria are given
|
||||
if( m_Children.empty() && !aMatcher && aLib.IsEmpty() && ( !aFilter || (*aFilter)(*this) ) )
|
||||
|
||||
@@ -302,11 +302,6 @@ void LIB_TREE_MODEL_ADAPTER::UpdateSearchString( const wxString& aSearch, bool a
|
||||
|
||||
m_tree.UpdateScore( &itemNameMatcher, lib, nullptr );
|
||||
}
|
||||
else
|
||||
{
|
||||
// In case the full token happens to match a library name
|
||||
m_tree.UpdateScore( nullptr, '*' + term + '*', nullptr );
|
||||
}
|
||||
}
|
||||
|
||||
if( firstTerm )
|
||||
|
||||
+19
-15
@@ -169,6 +169,10 @@ wxString PATHS::GetStockDataPath( bool aRespectRunFromBuildDir )
|
||||
path = GetExecutablePath() + wxT( ".." );
|
||||
#endif
|
||||
}
|
||||
else if( wxGetEnv( wxT( "KICAD_STOCK_DATA_HOME" ), &path ) && !path.IsEmpty() )
|
||||
{
|
||||
return path;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined( __WXMAC__ )
|
||||
@@ -291,12 +295,16 @@ wxString PATHS::GetStockPlugins3DPath()
|
||||
{
|
||||
wxFileName fn;
|
||||
|
||||
#ifdef __WXGTK__
|
||||
// KICAD_PLUGINDIR = CMAKE_INSTALL_FULL_LIBDIR path is the absolute path
|
||||
// corresponding to the install path used for constructing KICAD_USER_PLUGIN
|
||||
wxString tfname = wxString::FromUTF8Unchecked( KICAD_PLUGINDIR );
|
||||
fn.Assign( tfname, "" );
|
||||
fn.AppendDir( wxT( "kicad" ) );
|
||||
#if defined( __WXMSW__ )
|
||||
if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
|
||||
{
|
||||
fn.AssignDir( getWindowsKiCadRoot() );
|
||||
}
|
||||
else
|
||||
{
|
||||
fn.AssignDir( GetExecutablePath() );
|
||||
}
|
||||
|
||||
fn.AppendDir( wxT( "plugins" ) );
|
||||
#elif defined( __WXMAC__ )
|
||||
fn.Assign( wxStandardPaths::Get().GetPluginsDir(), wxEmptyString );
|
||||
@@ -319,15 +327,11 @@ wxString PATHS::GetStockPlugins3DPath()
|
||||
fn.AppendDir( wxT( "PlugIns" ) );
|
||||
}
|
||||
#else
|
||||
if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
|
||||
{
|
||||
fn.AssignDir( getWindowsKiCadRoot() );
|
||||
}
|
||||
else
|
||||
{
|
||||
fn.AssignDir( GetExecutablePath() );
|
||||
}
|
||||
|
||||
// KICAD_PLUGINDIR = CMAKE_INSTALL_FULL_LIBDIR path is the absolute path
|
||||
// corresponding to the install path used for constructing KICAD_USER_PLUGIN
|
||||
wxString tfname = wxString::FromUTF8Unchecked( KICAD_PLUGINDIR );
|
||||
fn.Assign( tfname, "" );
|
||||
fn.AppendDir( wxT( "kicad" ) );
|
||||
fn.AppendDir( wxT( "plugins" ) );
|
||||
#endif
|
||||
|
||||
|
||||
@@ -833,10 +833,21 @@ void GERBER_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
{
|
||||
SetCurrentLineWidth( aWidth );
|
||||
|
||||
EDA_ANGLE endAngle = aStartAngle + aAngle;
|
||||
double arcLength = std::abs( aRadius * aAngle.AsRadians() );
|
||||
|
||||
// aFill is not used here.
|
||||
plotArc( aCenter, aStartAngle, endAngle, aRadius, false );
|
||||
if( arcLength < 100 || std::abs( aAngle.AsDegrees() ) < 0.1 )
|
||||
{
|
||||
// Prevent plotting very short arcs as full circles, especially with 4.5 mm precision.
|
||||
// Also reduce the risk of integer overflow issues.
|
||||
polyArc( aCenter, aStartAngle, aAngle, aRadius, aFill, aWidth );
|
||||
}
|
||||
else
|
||||
{
|
||||
EDA_ANGLE endAngle = aStartAngle + aAngle;
|
||||
|
||||
// aFill is not used here.
|
||||
plotArc( aCenter, aStartAngle, endAngle, aRadius, false );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -879,19 +890,19 @@ void GERBER_PLOTTER::plotArc( const SHAPE_ARC& aArc, bool aPlotInRegion )
|
||||
|
||||
|
||||
void GERBER_PLOTTER::plotArc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aEndAngle, int aRadius, bool aPlotInRegion )
|
||||
const EDA_ANGLE& aEndAngle, double aRadius, bool aPlotInRegion )
|
||||
{
|
||||
VECTOR2I start, end;
|
||||
start.x = aCenter.x + KiROUND( aRadius * aStartAngle.Cos() );
|
||||
start.y = aCenter.y + KiROUND( aRadius * aStartAngle.Sin() );
|
||||
start.x = KiROUND( aCenter.x + aRadius * aStartAngle.Cos() );
|
||||
start.y = KiROUND( aCenter.y + aRadius * aStartAngle.Sin() );
|
||||
|
||||
if( !aPlotInRegion )
|
||||
MoveTo( start );
|
||||
else
|
||||
LineTo( start );
|
||||
|
||||
end.x = aCenter.x + KiROUND( aRadius * aEndAngle.Cos() );
|
||||
end.y = aCenter.y + KiROUND( aRadius * aEndAngle.Sin() );
|
||||
end.x = KiROUND( aCenter.x + aRadius * aEndAngle.Cos() );
|
||||
end.y = KiROUND( aCenter.y + aRadius * aEndAngle.Sin() );
|
||||
VECTOR2D devEnd = userToDeviceCoordinates( end );
|
||||
// devRelCenter is the position on arc center relative to the arc start, in Gerber coord.
|
||||
VECTOR2D devRelCenter = userToDeviceCoordinates( aCenter ) - userToDeviceCoordinates( start );
|
||||
|
||||
@@ -565,6 +565,13 @@ void HPGL_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
if( aRadius <= 0 )
|
||||
return;
|
||||
|
||||
// Avoid integer overflow when calculating the center point
|
||||
if( std::abs( aAngle.AsDegrees() ) < 5 )
|
||||
{
|
||||
polyArc( aCenter, aStartAngle, aAngle, aRadius, aFill, aWidth );
|
||||
return;
|
||||
}
|
||||
|
||||
double const radius_device = userToDeviceSize( aRadius );
|
||||
double const circumf_device = 2.0 * M_PI * radius_device;
|
||||
double const target_chord_length = m_arcTargetChordLength;
|
||||
@@ -581,11 +588,11 @@ void HPGL_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
EDA_ANGLE startAngle = -aStartAngle;
|
||||
|
||||
// Calculate arc start point:
|
||||
VECTOR2I cmap( aCenter.x + KiROUND( aRadius * startAngle.Cos() ),
|
||||
aCenter.y - KiROUND( aRadius * startAngle.Sin() ) );
|
||||
VECTOR2I cmap( KiROUND( aCenter.x + aRadius * startAngle.Cos() ),
|
||||
KiROUND( aCenter.y - aRadius * startAngle.Sin() ) );
|
||||
VECTOR2D cmap_dev = userToDeviceCoordinates( cmap );
|
||||
|
||||
startOrAppendItem( cmap_dev, wxString::Format( "AA %.0f,%.0f,%.0f,%g",
|
||||
startOrAppendItem( cmap_dev, wxString::Format( "AA %.0f,%.0f,%g,%g",
|
||||
centre_device.x,
|
||||
centre_device.y,
|
||||
angle.AsDegrees(),
|
||||
|
||||
@@ -354,21 +354,21 @@ void PDF_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
SetCurrentLineWidth( aWidth );
|
||||
|
||||
// Usual trig arc plotting routine...
|
||||
start.x = aCenter.x + KiROUND( aRadius * (-startAngle).Cos() );
|
||||
start.y = aCenter.y + KiROUND( aRadius * (-startAngle).Sin() );
|
||||
start.x = KiROUND( aCenter.x + aRadius * ( -startAngle ).Cos() );
|
||||
start.y = KiROUND( aCenter.y + aRadius * ( -startAngle ).Sin() );
|
||||
VECTOR2D pos_dev = userToDeviceCoordinates( start );
|
||||
fprintf( m_workFile, "%g %g m ", pos_dev.x, pos_dev.y );
|
||||
|
||||
for( EDA_ANGLE ii = startAngle + delta; ii < endAngle; ii += delta )
|
||||
{
|
||||
end.x = aCenter.x + KiROUND( aRadius * (-ii).Cos() );
|
||||
end.y = aCenter.y + KiROUND( aRadius * (-ii).Sin() );
|
||||
end.x = KiROUND( aCenter.x + aRadius * ( -ii ).Cos() );
|
||||
end.y = KiROUND( aCenter.y + aRadius * ( -ii ).Sin() );
|
||||
pos_dev = userToDeviceCoordinates( end );
|
||||
fprintf( m_workFile, "%g %g l ", pos_dev.x, pos_dev.y );
|
||||
}
|
||||
|
||||
end.x = aCenter.x + KiROUND( aRadius * (-endAngle).Cos() );
|
||||
end.y = aCenter.y + KiROUND( aRadius * (-endAngle).Sin() );
|
||||
end.x = KiROUND( aCenter.x + aRadius * ( -endAngle ).Cos() );
|
||||
end.y = KiROUND( aCenter.y + aRadius * ( -endAngle ).Sin() );
|
||||
pos_dev = userToDeviceCoordinates( end );
|
||||
fprintf( m_workFile, "%g %g l ", pos_dev.x, pos_dev.y );
|
||||
|
||||
|
||||
@@ -191,8 +191,8 @@ void PLOTTER::polyArc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
|
||||
SetCurrentLineWidth( aWidth );
|
||||
|
||||
start.x = aCenter.x + KiROUND( aRadius * startAngle.Cos() );
|
||||
start.y = aCenter.y + sign * KiROUND( aRadius * startAngle.Sin() );
|
||||
start.x = KiROUND( aCenter.x + aRadius * startAngle.Cos() );
|
||||
start.y = KiROUND( aCenter.y + sign * aRadius * startAngle.Sin() );
|
||||
|
||||
if( aFill != FILL_T::NO_FILL )
|
||||
{
|
||||
@@ -206,13 +206,13 @@ void PLOTTER::polyArc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
||||
|
||||
for( EDA_ANGLE ii = startAngle + delta; ii < endAngle; ii += delta )
|
||||
{
|
||||
end.x = aCenter.x + KiROUND( aRadius * ii.Cos() );
|
||||
end.y = aCenter.y + sign * KiROUND( aRadius * ii.Sin() );
|
||||
end.x = KiROUND( aCenter.x + aRadius * ii.Cos() );
|
||||
end.y = KiROUND( aCenter.y + sign * aRadius * ii.Sin() );
|
||||
LineTo( end );
|
||||
}
|
||||
|
||||
end.x = aCenter.x + KiROUND( aRadius * endAngle.Cos() );
|
||||
end.y = aCenter.y + sign * KiROUND( aRadius * endAngle.Sin() );
|
||||
end.x = KiROUND( aCenter.x + aRadius * endAngle.Cos() );
|
||||
end.y = KiROUND( aCenter.y + sign * aRadius * endAngle.Sin() );
|
||||
|
||||
if( aFill != FILL_T::NO_FILL )
|
||||
{
|
||||
@@ -706,7 +706,6 @@ void PLOTTER::Text( const VECTOR2I& aPos,
|
||||
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
|
||||
|
||||
SetColor( aColor );
|
||||
SetCurrentLineWidth( aPenWidth, aData );
|
||||
|
||||
if( aPenWidth == 0 && aBold ) // Use default values if aPenWidth == 0
|
||||
aPenWidth = GetPenSizeForBold( std::min( aSize.x, aSize.y ) );
|
||||
@@ -718,6 +717,7 @@ void PLOTTER::Text( const VECTOR2I& aPos,
|
||||
// Stroke callback
|
||||
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
|
||||
{
|
||||
SetCurrentLineWidth( aPenWidth );
|
||||
MoveTo( aPt1 );
|
||||
LineTo( aPt2 );
|
||||
PenFinish();
|
||||
|
||||
@@ -731,19 +731,47 @@ bool SETTINGS_MANAGER::GetPreviousVersionPaths( std::vector<wxString>* aPaths )
|
||||
}
|
||||
}
|
||||
|
||||
alg::delete_if( *aPaths, []( const wxString& aPath ) -> bool
|
||||
{
|
||||
wxFileName fulldir = wxFileName::DirName( aPath );
|
||||
const wxArrayString& dirs = fulldir.GetDirs();
|
||||
|
||||
if( dirs.empty() || !fulldir.IsDirReadable() )
|
||||
return true;
|
||||
|
||||
std::string ver = dirs.back().ToStdString();
|
||||
|
||||
if( !extractVersion( ver ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
} );
|
||||
|
||||
std::sort( aPaths->begin(), aPaths->end(),
|
||||
[&]( const wxString& a, const wxString& b ) -> bool
|
||||
{
|
||||
wxString verA = wxFileName::DirName( a ).GetDirs().back();
|
||||
wxString verB = wxFileName::DirName( b ).GetDirs().back();
|
||||
wxFileName aPath = wxFileName::DirName( a );
|
||||
wxFileName bPath = wxFileName::DirName( b );
|
||||
|
||||
if( !extractVersion( verA.ToStdString() )
|
||||
|| !extractVersion( verB.ToStdString() ) )
|
||||
{
|
||||
const wxArrayString& aDirs = aPath.GetDirs();
|
||||
const wxArrayString& bDirs = bPath.GetDirs();
|
||||
|
||||
if( aDirs.empty() )
|
||||
return false;
|
||||
}
|
||||
|
||||
return compareVersions( verA.ToStdString(), verB.ToStdString() ) >= 0;
|
||||
if( bDirs.empty() )
|
||||
return true;
|
||||
|
||||
std::string verA = aDirs.back().ToStdString();
|
||||
std::string verB = bDirs.back().ToStdString();
|
||||
|
||||
if( !extractVersion( verA ) )
|
||||
return false;
|
||||
|
||||
if( !extractVersion( verB ) )
|
||||
return true;
|
||||
|
||||
return compareVersions( verA, verB ) >= 0;
|
||||
} );
|
||||
|
||||
return aPaths->size() > 0;
|
||||
|
||||
+16
-9
@@ -98,6 +98,18 @@ bool TITLE_BLOCK::TextVarResolver( wxString* aToken, const PROJECT* aProject ) c
|
||||
bool tokenUpdated = false;
|
||||
wxString originalToken = *aToken;
|
||||
|
||||
auto getCurrentDate =
|
||||
[]() -> wxString
|
||||
{
|
||||
// We can choose different formats. Should probably be kept in sync with ISSUE_DATE
|
||||
// formatting in DIALOG_PAGES_SETTINGS.
|
||||
//
|
||||
// return wxDateTime::Now().Format( wxLocale::GetInfo( wxLOCALE_SHORT_DATE_FMT ) );
|
||||
// return wxDateTime::Now().Format( wxLocale::GetInfo( wxLOCALE_LONG_DATE_FMT ) );
|
||||
// return wxDateTime::Now().Format( wxT("%Y-%b-%d") );
|
||||
return wxDateTime::Now().FormatISODate();
|
||||
};
|
||||
|
||||
if( aToken->IsSameAs( wxT( "ISSUE_DATE" ) ) )
|
||||
{
|
||||
*aToken = GetDate();
|
||||
@@ -105,14 +117,7 @@ bool TITLE_BLOCK::TextVarResolver( wxString* aToken, const PROJECT* aProject ) c
|
||||
}
|
||||
else if( aToken->IsSameAs( wxT( "CURRENT_DATE" ) ) )
|
||||
{
|
||||
// We can choose different formats. Should probably be kept in sync with ISSUE_DATE
|
||||
// formatting in DIALOG_PAGES_SETTINGS.
|
||||
//
|
||||
// *aToken = wxDateTime::Now().Format( wxLocale::GetInfo( wxLOCALE_SHORT_DATE_FMT ) );
|
||||
// *aToken = wxDateTime::Now().Format( wxLocale::GetInfo( wxLOCALE_LONG_DATE_FMT ) );
|
||||
// *aToken = wxDateTime::Now().Format( wxT("%Y-%b-%d") );
|
||||
*aToken = wxDateTime::Now().FormatISODate();
|
||||
|
||||
*aToken = getCurrentDate();
|
||||
tokenUpdated = true;
|
||||
}
|
||||
else if( aToken->IsSameAs( wxT( "REVISION" ) ) )
|
||||
@@ -152,7 +157,9 @@ bool TITLE_BLOCK::TextVarResolver( wxString* aToken, const PROJECT* aProject ) c
|
||||
|
||||
if( tokenUpdated )
|
||||
{
|
||||
if( aProject )
|
||||
if( aToken->IsSameAs( wxT( "CURRENT_DATE" ) ) )
|
||||
*aToken = getCurrentDate();
|
||||
else if( aProject )
|
||||
*aToken = ExpandTextVars( *aToken, aProject );
|
||||
|
||||
// This is the default fallback, so don't claim we resolved it
|
||||
|
||||
@@ -547,7 +547,7 @@ int COMMON_TOOLS::ToggleGridOverrides( const TOOL_EVENT& aEvent )
|
||||
int COMMON_TOOLS::GridProperties( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
auto showGridPrefs =
|
||||
[this]( wxString aParentName )
|
||||
[this]( const wxString& aParentName )
|
||||
{
|
||||
m_frame->CallAfter(
|
||||
[this, aParentName]()
|
||||
@@ -563,6 +563,7 @@ int COMMON_TOOLS::GridProperties( const TOOL_EVENT& aEvent )
|
||||
case FRAME_PCB_EDITOR: showGridPrefs( _( "PCB Editor" ) ); break;
|
||||
case FRAME_FOOTPRINT_EDITOR: showGridPrefs( _( "Footprint Editor" ) ); break;
|
||||
case FRAME_PL_EDITOR: showGridPrefs( _( "Drawing Sheet Editor" ) ); break;
|
||||
case FRAME_GERBER: showGridPrefs( _( "Gerber Viewer" ) ); break;
|
||||
default: wxFAIL_MSG( "Unknown frame: " + GetName() ); break;
|
||||
}
|
||||
|
||||
|
||||
@@ -622,6 +622,9 @@ void VIEW::SetCenter( const VECTOR2D& aCenter, const std::vector<BOX2D>& obscuri
|
||||
BOX2I bbox = unobscuredPoly.BBox();
|
||||
int step = std::min( bbox.GetWidth(), bbox.GetHeight() ) / 10;
|
||||
|
||||
if( step < 20 )
|
||||
step = 20;
|
||||
|
||||
while( !unobscuredPoly.IsEmpty() )
|
||||
{
|
||||
unobscuredCenter = unobscuredPoly.BBox().Centre();
|
||||
|
||||
@@ -81,7 +81,8 @@ WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, EDA_DRAW_PANEL_GAL* aParentPane
|
||||
m_lastTimestamp( 0 ),
|
||||
#endif
|
||||
m_cursorPos( 0, 0 ),
|
||||
m_updateCursor( true )
|
||||
m_updateCursor( true ),
|
||||
m_infinitePanWorks( false )
|
||||
{
|
||||
LoadSettings();
|
||||
|
||||
@@ -276,7 +277,8 @@ void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
|
||||
{
|
||||
if( !justWarped )
|
||||
{
|
||||
if( KIPLATFORM::UI::WarpPointer( m_parentPanel, x + warpX, y + warpY ) )
|
||||
if( m_infinitePanWorks
|
||||
&& KIPLATFORM::UI::WarpPointer( m_parentPanel, x + warpX, y + warpY ) )
|
||||
{
|
||||
m_dragStartPoint += VECTOR2D( warpX, warpY );
|
||||
justWarped = true;
|
||||
@@ -452,7 +454,7 @@ void WX_VIEW_CONTROLS::onButton( wxMouseEvent& aEvent )
|
||||
{
|
||||
m_dragStartPoint = VECTOR2D( aEvent.GetX(), aEvent.GetY() );
|
||||
setState( DRAG_PANNING );
|
||||
KIPLATFORM::UI::InfiniteDragPrepareWindow( m_parentPanel );
|
||||
m_infinitePanWorks = KIPLATFORM::UI::InfiniteDragPrepareWindow( m_parentPanel );
|
||||
|
||||
#if defined USE_MOUSE_CAPTURE
|
||||
if( !m_parentPanel->HasCapture() )
|
||||
|
||||
@@ -92,6 +92,12 @@ void FOOTPRINT_PREVIEW_WIDGET::SetUserUnits( EDA_UNITS aUnits )
|
||||
}
|
||||
|
||||
|
||||
void FOOTPRINT_PREVIEW_WIDGET::SetPinFunctions( const std::map<wxString, wxString>& aPinFunctions )
|
||||
{
|
||||
m_prev_panel->SetPinFunctions( aPinFunctions );
|
||||
}
|
||||
|
||||
|
||||
void FOOTPRINT_PREVIEW_WIDGET::DisplayFootprint( const LIB_ID& aFPID )
|
||||
{
|
||||
if( !m_prev_panel || m_libid == aFPID )
|
||||
|
||||
@@ -287,8 +287,8 @@ protected:
|
||||
|
||||
/*
|
||||
* Symbol netlist format:
|
||||
* pinCount
|
||||
* fpFilters
|
||||
* pinNumber pinName <tab> pinNumber pinName...
|
||||
* fpFilter fpFilter...
|
||||
*/
|
||||
std::string m_symbolNetlist;
|
||||
};
|
||||
|
||||
@@ -174,6 +174,14 @@ void PROPERTIES_PANEL::rebuildProperties( const SELECTION& aSelection )
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
else if( aSelection.Size() == 1 )
|
||||
{
|
||||
m_caption->SetLabel( aSelection.Front()->GetFriendlyName() );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_caption->SetLabel( wxString::Format( _( "%d objects selected" ), aSelection.Size() ) );
|
||||
}
|
||||
|
||||
// Get all the selected types
|
||||
std::set<TYPE_ID> types;
|
||||
@@ -292,15 +300,6 @@ void PROPERTIES_PANEL::rebuildProperties( const SELECTION& aSelection )
|
||||
}
|
||||
}
|
||||
|
||||
if( aSelection.Size() > 1 )
|
||||
{
|
||||
m_caption->SetLabel( wxString::Format( _( "%d objects selected" ), aSelection.Size() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_caption->SetLabel( aSelection.Front()->GetFriendlyName() );
|
||||
}
|
||||
|
||||
const wxString unspecifiedGroupCaption = _( "Basic Properties" );
|
||||
|
||||
for( const wxString& groupName : groupDisplayOrder )
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Chris Pavlina <pavlina.chris@gmail.com>
|
||||
* Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2016-2024 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
|
||||
@@ -202,12 +202,14 @@ protected:
|
||||
// Let EVT_CHAR handle this one
|
||||
aEvent.DoAllowNextEvent();
|
||||
|
||||
// On Windows, wxEvent::Skip must NOT be called.
|
||||
// On Linux and OSX, wxEvent::Skip MUST be called.
|
||||
// No, I don't know why.
|
||||
#ifndef __WXMSW__
|
||||
aEvent.Skip();
|
||||
#ifdef __WXMSW__
|
||||
// On Windows, looks like a OnChar event is not generated when
|
||||
// using the Alt key modifier. So ensure m_event is up to date
|
||||
// to handle the right key code when releasing the key and therefore
|
||||
// closing the dialog
|
||||
m_event = aEvent;
|
||||
#endif
|
||||
aEvent.Skip();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -465,21 +465,14 @@ void DISPLAY_FOOTPRINTS_FRAME::ReloadFootprint( FOOTPRINT* aFootprint )
|
||||
return;
|
||||
|
||||
GetBoard()->DeleteAllFootprints();
|
||||
GetBoard()->RemoveUnusedNets( nullptr );
|
||||
GetCanvas()->GetView()->Clear();
|
||||
|
||||
|
||||
for( PAD* pad : aFootprint->Pads() )
|
||||
{
|
||||
const COMPONENT_NET& net = m_currentComp->GetNet( pad->GetNumber() );
|
||||
|
||||
if( !net.GetPinFunction().IsEmpty() )
|
||||
{
|
||||
NETINFO_ITEM* netinfo = new NETINFO_ITEM( GetBoard() );
|
||||
netinfo->SetNetname( net.GetPinFunction() );
|
||||
GetBoard()->Add( netinfo );
|
||||
pad->SetNet( netinfo );
|
||||
}
|
||||
pad->SetPinFunction( net.GetPinFunction() );
|
||||
}
|
||||
|
||||
GetBoard()->Add( aFootprint );
|
||||
@@ -504,7 +497,6 @@ void DISPLAY_FOOTPRINTS_FRAME::InitDisplay()
|
||||
return;
|
||||
|
||||
GetBoard()->DeleteAllFootprints();
|
||||
GetBoard()->RemoveUnusedNets( nullptr );
|
||||
GetCanvas()->GetView()->Clear();
|
||||
|
||||
INFOBAR_REPORTER infoReporter( m_infoBar );
|
||||
@@ -528,12 +520,7 @@ void DISPLAY_FOOTPRINTS_FRAME::InitDisplay()
|
||||
const COMPONENT_NET& net = comp->GetNet( pad->GetNumber() );
|
||||
|
||||
if( !net.GetPinFunction().IsEmpty() )
|
||||
{
|
||||
NETINFO_ITEM* netinfo = new NETINFO_ITEM( GetBoard() );
|
||||
netinfo->SetNetname( net.GetPinFunction() );
|
||||
GetBoard()->Add( netinfo );
|
||||
pad->SetNet( netinfo );
|
||||
}
|
||||
pad->SetPinFunction( net.GetPinFunction() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(kicad_pcb
|
||||
(version 20231231)
|
||||
(version 20240108)
|
||||
(generator "pcbnew")
|
||||
(generator_version "7.99")
|
||||
(generator_version "8.0")
|
||||
(general
|
||||
(thickness 1.6002)
|
||||
(legacy_teardrops no)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+251
-55
@@ -85,8 +85,51 @@ void CONNECTION_SUBGRAPH::RemoveItem( SCH_ITEM* aItem )
|
||||
}
|
||||
|
||||
|
||||
void CONNECTION_SUBGRAPH::ExchangeItem( SCH_ITEM* aOldItem, SCH_ITEM* aNewItem )
|
||||
{
|
||||
m_items.erase( aOldItem );
|
||||
m_items.insert( aNewItem );
|
||||
|
||||
m_drivers.erase( aOldItem );
|
||||
m_drivers.insert( aNewItem );
|
||||
|
||||
if( aOldItem == m_driver )
|
||||
{
|
||||
m_driver = aNewItem;
|
||||
m_driver_connection = aNewItem->GetOrInitConnection( m_sheet, m_graph );
|
||||
}
|
||||
|
||||
SCH_CONNECTION* old_conn = aOldItem->Connection( &m_sheet );
|
||||
SCH_CONNECTION* new_conn = aNewItem->GetOrInitConnection( m_sheet, m_graph );
|
||||
|
||||
if( old_conn && new_conn )
|
||||
{
|
||||
new_conn->Clone( *old_conn );
|
||||
|
||||
if( old_conn->IsDriver() )
|
||||
new_conn->SetDriver( aNewItem );
|
||||
|
||||
new_conn->ClearDirty();
|
||||
}
|
||||
|
||||
if( aOldItem->Type() == SCH_SHEET_PIN_T )
|
||||
{
|
||||
m_hier_pins.erase( static_cast<SCH_SHEET_PIN*>( aOldItem ) );
|
||||
m_hier_pins.insert( static_cast<SCH_SHEET_PIN*>( aNewItem ) );
|
||||
}
|
||||
|
||||
if( aOldItem->Type() == SCH_HIER_LABEL_T )
|
||||
{
|
||||
m_hier_ports.erase( static_cast<SCH_HIERLABEL*>( aOldItem ) );
|
||||
m_hier_ports.insert( static_cast<SCH_HIERLABEL*>( aNewItem ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CONNECTION_SUBGRAPH::ResolveDrivers( bool aCheckMultipleDrivers )
|
||||
{
|
||||
std::lock_guard lock( m_driver_mutex );
|
||||
|
||||
auto candidate_cmp = [&]( SCH_ITEM* a, SCH_ITEM* b ) -> bool
|
||||
{
|
||||
// meet irreflexive requirements of std::sort
|
||||
@@ -574,6 +617,53 @@ void CONNECTION_GRAPH::Merge( CONNECTION_GRAPH& aGraph )
|
||||
}
|
||||
|
||||
|
||||
void CONNECTION_GRAPH::ExchangeItem( SCH_ITEM* aOldItem, SCH_ITEM* aNewItem )
|
||||
{
|
||||
wxCHECK2( aOldItem->Type() == aNewItem->Type(), return );
|
||||
|
||||
auto exchange = [&]( SCH_ITEM* aOld, SCH_ITEM* aNew )
|
||||
{
|
||||
auto it = m_item_to_subgraph_map.find( aOld );
|
||||
|
||||
if( it == m_item_to_subgraph_map.end() )
|
||||
return;
|
||||
|
||||
CONNECTION_SUBGRAPH* sg = it->second;
|
||||
|
||||
sg->ExchangeItem( aOld, aNew );
|
||||
|
||||
m_item_to_subgraph_map.erase( it );
|
||||
m_item_to_subgraph_map.emplace( aNew, sg );
|
||||
|
||||
for( auto it2 = m_items.begin(); it2 != m_items.end(); ++it2 )
|
||||
{
|
||||
if( *it2 == aOld )
|
||||
{
|
||||
*it2 = aNew;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exchange( aOldItem, aNewItem );
|
||||
|
||||
if( aOldItem->Type() == SCH_SYMBOL_T )
|
||||
{
|
||||
SCH_SYMBOL* oldSymbol = static_cast<SCH_SYMBOL*>( aOldItem );
|
||||
SCH_SYMBOL* newSymbol = static_cast<SCH_SYMBOL*>( aNewItem );
|
||||
std::vector<SCH_PIN*> oldPins = oldSymbol->GetPins( &m_schematic->CurrentSheet() );
|
||||
std::vector<SCH_PIN*> newPins = newSymbol->GetPins( &m_schematic->CurrentSheet() );
|
||||
|
||||
wxCHECK2( oldPins.size() == newPins.size(), return );
|
||||
|
||||
for( size_t ii = 0; ii < oldPins.size(); ii++ )
|
||||
{
|
||||
exchange( oldPins[ii], newPins[ii] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CONNECTION_GRAPH::Reset()
|
||||
{
|
||||
for( auto& subgraph : m_subgraphs )
|
||||
@@ -631,6 +721,21 @@ void CONNECTION_GRAPH::Recalculate( const SCH_SHEET_LIST& aSheetList, bool aUnco
|
||||
items.push_back( item );
|
||||
dirty_items.insert( item );
|
||||
}
|
||||
// If the symbol isn't dirty, look at the pins
|
||||
// TODO: remove symbols from connectivity graph and only use pins
|
||||
else if( item->Type() == SCH_SYMBOL_T )
|
||||
{
|
||||
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
|
||||
|
||||
for( SCH_PIN* pin : symbol->GetPins( &sheet ) )
|
||||
{
|
||||
if( pin->IsConnectivityDirty() )
|
||||
{
|
||||
items.push_back( pin );
|
||||
dirty_items.insert( pin );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the hierarchy info stored in the SCH_SCREEN (such as symbol units) reflects
|
||||
// the current SCH_SHEET_PATH
|
||||
@@ -672,7 +777,7 @@ void CONNECTION_GRAPH::Recalculate( const SCH_SHEET_LIST& aSheetList, bool aUnco
|
||||
|
||||
PROF_TIMER build_graph( "buildConnectionGraph" );
|
||||
|
||||
buildConnectionGraph( aChangedItemHandler );
|
||||
buildConnectionGraph( aChangedItemHandler, aUnconditional );
|
||||
|
||||
if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
|
||||
build_graph.Show();
|
||||
@@ -710,37 +815,76 @@ std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> CONNECTION_GRAPH::ExtractAffected
|
||||
aSubgraph->getAllConnectedItems( retvals, subgraphs );
|
||||
};
|
||||
|
||||
auto extract_element = [&]( SCH_ITEM* aItem )
|
||||
{
|
||||
CONNECTION_SUBGRAPH* item_sg = GetSubgraphForItem( aItem );
|
||||
|
||||
if( !item_sg )
|
||||
{
|
||||
wxLogTrace( ConnTrace, wxT( "Item %s not found in connection graph" ), aItem->GetTypeDesc() );
|
||||
return;
|
||||
}
|
||||
if( !item_sg->ResolveDrivers( true ) )
|
||||
{
|
||||
wxLogTrace( ConnTrace, wxT( "Item %s in subgraph %ld (%p) has no driver" ),
|
||||
aItem->GetTypeDesc(), item_sg->m_code, item_sg );
|
||||
}
|
||||
|
||||
std::vector<CONNECTION_SUBGRAPH*> sg_to_scan = GetAllSubgraphs( item_sg->GetNetName() );
|
||||
|
||||
if( sg_to_scan.empty() )
|
||||
{
|
||||
wxLogTrace( ConnTrace, wxT( "Item %s in subgraph %ld with net %s has no neighbors" ),
|
||||
aItem->GetTypeDesc(), item_sg->m_code, item_sg->GetNetName() );
|
||||
sg_to_scan.push_back( item_sg );
|
||||
}
|
||||
|
||||
wxLogTrace( ConnTrace,
|
||||
wxT( "Removing all item %s connections from subgraph %ld with net %s: Found "
|
||||
"%zu subgraphs" ),
|
||||
aItem->GetTypeDesc(), item_sg->m_code, item_sg->GetNetName(),
|
||||
sg_to_scan.size() );
|
||||
|
||||
for( CONNECTION_SUBGRAPH* sg : sg_to_scan )
|
||||
|
||||
{
|
||||
traverse_subgraph( sg );
|
||||
|
||||
for( auto& bus_it : sg->m_bus_neighbors )
|
||||
{
|
||||
for( CONNECTION_SUBGRAPH* bus_sg : bus_it.second )
|
||||
traverse_subgraph( bus_sg );
|
||||
}
|
||||
|
||||
for( auto& bus_it : sg->m_bus_parents )
|
||||
{
|
||||
for( CONNECTION_SUBGRAPH* bus_sg : bus_it.second )
|
||||
traverse_subgraph( bus_sg );
|
||||
}
|
||||
}
|
||||
|
||||
alg::delete_matching( m_items, aItem );
|
||||
};
|
||||
|
||||
for( SCH_ITEM* item : aItems )
|
||||
{
|
||||
auto it = m_item_to_subgraph_map.find( item );
|
||||
|
||||
if( it == m_item_to_subgraph_map.end() )
|
||||
continue;
|
||||
|
||||
CONNECTION_SUBGRAPH* sg = it->second;
|
||||
|
||||
traverse_subgraph( sg );
|
||||
|
||||
for( auto& bus_it : sg->m_bus_neighbors )
|
||||
if( item->Type() == SCH_SHEET_T )
|
||||
{
|
||||
for( CONNECTION_SUBGRAPH* bus_sg : bus_it.second )
|
||||
traverse_subgraph( bus_sg );
|
||||
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
|
||||
|
||||
for( SCH_SHEET_PIN* pin : sheet->GetPins() )
|
||||
extract_element( pin );
|
||||
}
|
||||
|
||||
for( auto& bus_it : sg->m_bus_parents )
|
||||
{
|
||||
for( CONNECTION_SUBGRAPH* bus_sg : bus_it.second )
|
||||
traverse_subgraph( bus_sg );
|
||||
}
|
||||
|
||||
alg::delete_matching( m_items, item );
|
||||
|
||||
if( item->Type() == SCH_SYMBOL_T )
|
||||
else if ( item->Type() == SCH_SYMBOL_T )
|
||||
{
|
||||
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
|
||||
|
||||
for( SCH_PIN* pin : symbol->GetPins( &sg->m_sheet ) )
|
||||
alg::delete_matching( m_items, pin );
|
||||
for( SCH_PIN* pin : symbol->GetPins( &m_schematic->CurrentSheet() ) )
|
||||
extract_element( pin );
|
||||
}
|
||||
else
|
||||
{
|
||||
extract_element( item );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -770,6 +914,7 @@ void CONNECTION_GRAPH::RemoveItem( SCH_ITEM* aItem )
|
||||
|
||||
void CONNECTION_GRAPH::removeSubgraphs( std::set<CONNECTION_SUBGRAPH*>& aSubgraphs )
|
||||
{
|
||||
wxLogTrace( ConnTrace, wxT( "Removing %zu subgraphs" ), aSubgraphs.size() );
|
||||
std::sort( m_driver_subgraphs.begin(), m_driver_subgraphs.end() );
|
||||
std::sort( m_subgraphs.begin(), m_subgraphs.end() );
|
||||
std::set<int> codes_to_remove;
|
||||
@@ -928,12 +1073,30 @@ void CONNECTION_GRAPH::removeSubgraphs( std::set<CONNECTION_SUBGRAPH*>& aSubgrap
|
||||
void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
|
||||
const std::vector<SCH_ITEM*>& aItemList )
|
||||
{
|
||||
wxLogTrace( wxT( "Updating connectivity for sheet %s with %zu items" ),
|
||||
aSheet.Last()->GetFileName(), aItemList.size() );
|
||||
std::map<VECTOR2I, std::vector<SCH_ITEM*>> connection_map;
|
||||
|
||||
auto updatePin = [&]( SCH_PIN* aPin, SCH_CONNECTION* aConn )
|
||||
{
|
||||
aConn->SetType( CONNECTION_TYPE::NET );
|
||||
|
||||
// because calling the first time is not thread-safe
|
||||
wxString name = aPin->GetDefaultNetName( aSheet );
|
||||
aPin->ClearConnectedItems( aSheet );
|
||||
|
||||
// power symbol pins need to be post-processed later
|
||||
if( aPin->IsGlobalPower() )
|
||||
{
|
||||
aConn->SetName( name );
|
||||
m_global_power_pins.emplace_back( std::make_pair( aSheet, aPin ) );
|
||||
}
|
||||
};
|
||||
|
||||
for( SCH_ITEM* item : aItemList )
|
||||
{
|
||||
std::vector<VECTOR2I> points = item->GetConnectionPoints();
|
||||
item->ConnectedItems( aSheet ).clear();
|
||||
item->ClearConnectedItems( aSheet );
|
||||
|
||||
if( item->Type() == SCH_SHEET_T )
|
||||
{
|
||||
@@ -941,7 +1104,7 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
|
||||
{
|
||||
pin->InitializeConnection( aSheet, this );
|
||||
|
||||
pin->ConnectedItems( aSheet ).clear();
|
||||
pin->ClearConnectedItems( aSheet );
|
||||
|
||||
connection_map[ pin->GetTextPos() ].push_back( pin );
|
||||
m_items.emplace_back( pin );
|
||||
@@ -953,23 +1116,10 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
|
||||
|
||||
for( SCH_PIN* pin : symbol->GetPins( &aSheet ) )
|
||||
{
|
||||
SCH_CONNECTION* conn = pin->InitializeConnection( aSheet, this );
|
||||
|
||||
VECTOR2I pos = pin->GetPosition();
|
||||
|
||||
// because calling the first time is not thread-safe
|
||||
wxString name = pin->GetDefaultNetName( aSheet );
|
||||
pin->ConnectedItems( aSheet ).clear();
|
||||
|
||||
// power symbol pins need to be post-processed later
|
||||
if( pin->IsGlobalPower() )
|
||||
{
|
||||
conn->SetName( name );
|
||||
m_global_power_pins.emplace_back( std::make_pair( aSheet, pin ) );
|
||||
}
|
||||
|
||||
connection_map[ pos ].push_back( pin );
|
||||
m_items.emplace_back( pin );
|
||||
SCH_CONNECTION* conn = pin->InitializeConnection( aSheet, this );
|
||||
updatePin( pin, conn );
|
||||
connection_map[ pin->GetPosition() ].push_back( pin );
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -994,7 +1144,10 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
|
||||
break;
|
||||
|
||||
case SCH_PIN_T:
|
||||
conn->SetType( CONNECTION_TYPE::NET );
|
||||
if( points.empty() )
|
||||
points = { static_cast<SCH_PIN*>( item )->GetPosition() };
|
||||
|
||||
updatePin( static_cast<SCH_PIN*>( item ), conn );
|
||||
break;
|
||||
|
||||
case SCH_BUS_WIRE_ENTRY_T:
|
||||
@@ -1075,9 +1228,6 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
|
||||
connected_item->SetLayer( busLine ? LAYER_BUS_JUNCTION : LAYER_JUNCTION );
|
||||
}
|
||||
|
||||
SCH_ITEM_SET& connected_set = connected_item->ConnectedItems( aSheet );
|
||||
connected_set.reserve( connection_vec.size() );
|
||||
|
||||
for( SCH_ITEM* test_item : connection_vec )
|
||||
{
|
||||
bool bus_connection_ok = true;
|
||||
@@ -1111,7 +1261,7 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
|
||||
test_item->ConnectionPropagatesTo( connected_item ) &&
|
||||
bus_connection_ok )
|
||||
{
|
||||
connected_set.push_back( test_item );
|
||||
connected_item->AddConnectionTo( aSheet, test_item );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1213,7 +1363,7 @@ void CONNECTION_GRAPH::buildItemSubGraphs()
|
||||
connected_conn->SetSubgraphCode( subgraph->m_code );
|
||||
m_item_to_subgraph_map[connected_item] = subgraph;
|
||||
subgraph->AddItem( connected_item );
|
||||
SCH_ITEM_SET& citemset = connected_item->ConnectedItems( sheet );
|
||||
const SCH_ITEM_VEC& citemset = connected_item->ConnectedItems( sheet );
|
||||
|
||||
for( SCH_ITEM* citem : citemset )
|
||||
{
|
||||
@@ -1248,6 +1398,8 @@ void CONNECTION_GRAPH::resolveAllDrivers()
|
||||
return candidate->m_dirty;
|
||||
} );
|
||||
|
||||
wxLogTrace( ConnTrace, wxT( "Resolving drivers for %zu subgraphs" ), dirty_graphs.size() );
|
||||
|
||||
std::vector<std::future<size_t>> returns( dirty_graphs.size() );
|
||||
|
||||
auto update_lambda = []( CONNECTION_SUBGRAPH* subgraph ) -> size_t
|
||||
@@ -1378,7 +1530,7 @@ void CONNECTION_GRAPH::generateBusAliasMembers()
|
||||
|
||||
for( CONNECTION_SUBGRAPH* subgraph : m_driver_subgraphs )
|
||||
{
|
||||
SCH_ITEM_SET vec = subgraph->GetAllBusLabels();
|
||||
SCH_ITEM_VEC vec = subgraph->GetAllBusLabels();
|
||||
|
||||
for( SCH_ITEM* item : vec )
|
||||
{
|
||||
@@ -1556,14 +1708,20 @@ void CONNECTION_GRAPH::processSubGraphs()
|
||||
|
||||
if( !subgraph->m_strong_driver )
|
||||
{
|
||||
std::vector<CONNECTION_SUBGRAPH*>* vec = &m_net_name_to_subgraphs_map.at( name );
|
||||
std::vector<CONNECTION_SUBGRAPH*> vec_empty;
|
||||
std::vector<CONNECTION_SUBGRAPH*>* vec = &vec_empty;
|
||||
|
||||
if( m_net_name_to_subgraphs_map.count( name ) )
|
||||
vec = &m_net_name_to_subgraphs_map.at( name );
|
||||
|
||||
// If we are a unique bus vector, check if we aren't actually unique because of another
|
||||
// subgraph with a similar bus vector
|
||||
if( vec->size() <= 1 && subgraph->m_driver_connection->Type() == CONNECTION_TYPE::BUS )
|
||||
{
|
||||
wxString prefixOnly = name.BeforeFirst( '[' ) + wxT( "[]" );
|
||||
vec = &m_net_name_to_subgraphs_map.at( prefixOnly );
|
||||
|
||||
if( m_net_name_to_subgraphs_map.count( prefixOnly ) )
|
||||
vec = &m_net_name_to_subgraphs_map.at( prefixOnly );
|
||||
}
|
||||
|
||||
if( vec->size() > 1 )
|
||||
@@ -1858,7 +2016,7 @@ void CONNECTION_GRAPH::processSubGraphs()
|
||||
// on some portion of the items.
|
||||
|
||||
|
||||
void CONNECTION_GRAPH::buildConnectionGraph( std::function<void( SCH_ITEM* )>* aChangedItemHandler )
|
||||
void CONNECTION_GRAPH::buildConnectionGraph( std::function<void( SCH_ITEM* )>* aChangedItemHandler, bool aUnconditional )
|
||||
{
|
||||
// Recache all bus aliases for later use
|
||||
wxCHECK_RET( m_schematic, wxT( "Connection graph cannot be built without schematic pointer" ) );
|
||||
@@ -2216,6 +2374,17 @@ void CONNECTION_GRAPH::buildConnectionGraph( std::function<void( SCH_ITEM* )>* a
|
||||
|
||||
for( const auto& [ netname, subgraphs ] : m_net_name_to_subgraphs_map )
|
||||
checkNetclassDrivers( subgraphs );
|
||||
|
||||
if( !aUnconditional )
|
||||
{
|
||||
for( auto& [ netname, netclass ] : oldAssignments )
|
||||
{
|
||||
if( netSettings->m_NetClassLabelAssignments.count( netname ) )
|
||||
continue;
|
||||
|
||||
netSettings->m_NetClassLabelAssignments[ netname ] = netclass;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2831,8 +3000,8 @@ CONNECTION_SUBGRAPH* CONNECTION_GRAPH::GetSubgraphForItem( SCH_ITEM* aItem )
|
||||
}
|
||||
|
||||
|
||||
const std::vector<CONNECTION_SUBGRAPH*> CONNECTION_GRAPH::GetAllSubgraphs(
|
||||
const wxString& aNetName ) const
|
||||
const std::vector<CONNECTION_SUBGRAPH*>
|
||||
CONNECTION_GRAPH::GetAllSubgraphs( const wxString& aNetName ) const
|
||||
{
|
||||
std::vector<CONNECTION_SUBGRAPH*> subgraphs;
|
||||
|
||||
@@ -3647,6 +3816,33 @@ bool CONNECTION_GRAPH::ercCheckLabels( const CONNECTION_SUBGRAPH* aSubgraph )
|
||||
if( label_map.empty() )
|
||||
return true;
|
||||
|
||||
// No-connects on net neighbors will be noticed before, but to notice them on bus parents we
|
||||
// need to walk the graph
|
||||
for( auto pair : aSubgraph->m_bus_parents )
|
||||
{
|
||||
for( CONNECTION_SUBGRAPH* busParent : pair.second )
|
||||
{
|
||||
if( busParent->m_no_connect )
|
||||
{
|
||||
has_nc = true;
|
||||
break;
|
||||
}
|
||||
|
||||
CONNECTION_SUBGRAPH* hp = busParent->m_hier_parent;
|
||||
|
||||
while( hp )
|
||||
{
|
||||
if( hp->m_no_connect )
|
||||
{
|
||||
has_nc = true;
|
||||
break;
|
||||
}
|
||||
|
||||
hp = hp->m_hier_parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wxString netName = GetResolvedSubgraphName( aSubgraph );
|
||||
|
||||
wxCHECK_MSG( m_schematic, true, wxS( "Null m_schematic in CONNECTION_GRAPH::ercCheckLabels" ) );
|
||||
|
||||
@@ -199,6 +199,11 @@ public:
|
||||
|
||||
void RemoveItem( SCH_ITEM* aItem );
|
||||
|
||||
/**
|
||||
* Replaces all references to #aOldItem with #aNewItem in the subgraph.
|
||||
*/
|
||||
void ExchangeItem( SCH_ITEM* aOldItem, SCH_ITEM* aNewItem );
|
||||
|
||||
// Use this to keep a connection pointer that is not owned by any item
|
||||
// This will be destroyed with the subgraph
|
||||
void StoreImplicitConnection( SCH_CONNECTION* aConnection )
|
||||
@@ -301,6 +306,8 @@ private:
|
||||
/// A cache of connections that are part of this subgraph but that don't have
|
||||
/// an owning element (i.e. bus members)
|
||||
std::set<SCH_CONNECTION*> m_bus_element_connections;
|
||||
|
||||
std::mutex m_driver_mutex;
|
||||
};
|
||||
|
||||
struct NET_NAME_CODE_CACHE_KEY
|
||||
@@ -454,6 +461,11 @@ public:
|
||||
|
||||
void RemoveItem( SCH_ITEM* aItem );
|
||||
|
||||
/**
|
||||
* Replace all references to #aOldItem with #aNewItem in the graph.
|
||||
*/
|
||||
void ExchangeItem( SCH_ITEM* aOldItem, SCH_ITEM* aNewItem );
|
||||
|
||||
private:
|
||||
/**
|
||||
* Update the graphical connectivity between items (i.e. where they touch)
|
||||
@@ -497,8 +509,12 @@ private:
|
||||
* the driver is first selected by CONNECTION_SUBGRAPH::ResolveDrivers(),
|
||||
* and then the connection for the chosen driver is propagated to all the
|
||||
* other items in the subgraph.
|
||||
*
|
||||
* If the unconitional flag is set, all existing net classes will be removed
|
||||
* and re-created. Otherwise, we will preserve existing net classes that do not
|
||||
* conflict with the new net classes.
|
||||
*/
|
||||
void buildConnectionGraph( std::function<void( SCH_ITEM* )>* aChangedItemHandler );
|
||||
void buildConnectionGraph( std::function<void( SCH_ITEM* )>* aChangedItemHandler, bool aUnconditional );
|
||||
|
||||
/**
|
||||
* Generate individual item subgraphs on a per-sheet basis.
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include <bitmaps.h>
|
||||
#include <connection_graph.h>
|
||||
#include <string_utils.h> // WildCompareString
|
||||
#include <kiway.h>
|
||||
#include <refdes_utils.h>
|
||||
@@ -47,6 +48,7 @@ bool g_resetFieldVisibilities[2] = { true, false };
|
||||
bool g_resetFieldEffects[2] = { true, false };
|
||||
bool g_resetFieldPositions[2] = { true, false };
|
||||
bool g_resetAttributes[2] = { true, false };
|
||||
bool g_resetCustomPower[2] = { false, false };
|
||||
|
||||
|
||||
DIALOG_CHANGE_SYMBOLS::DIALOG_CHANGE_SYMBOLS( SCH_EDIT_FRAME* aParent, SCH_SYMBOL* aSymbol,
|
||||
@@ -146,6 +148,7 @@ DIALOG_CHANGE_SYMBOLS::DIALOG_CHANGE_SYMBOLS( SCH_EDIT_FRAME* aParent, SCH_SYMBO
|
||||
m_resetFieldEffects->SetValue( g_resetFieldEffects[ (int) m_mode ] );
|
||||
m_resetFieldPositions->SetValue( g_resetFieldPositions[ (int) m_mode ] );
|
||||
m_resetAttributes->SetValue( g_resetAttributes[ (int) m_mode ] );
|
||||
m_resetCustomPower->SetValue( g_resetCustomPower[ (int) m_mode ] );
|
||||
|
||||
// DIALOG_SHIM needs a unique hash_key because classname is not sufficient
|
||||
// because the update and change versions of this dialog have different controls.
|
||||
@@ -227,6 +230,7 @@ DIALOG_CHANGE_SYMBOLS::~DIALOG_CHANGE_SYMBOLS()
|
||||
g_resetFieldEffects[ (int) m_mode ] = m_resetFieldEffects->GetValue();
|
||||
g_resetFieldPositions[ (int) m_mode ] = m_resetFieldPositions->GetValue();
|
||||
g_resetAttributes[ (int) m_mode ] = m_resetAttributes->GetValue();
|
||||
g_resetCustomPower[ (int) m_mode ] = m_resetCustomPower->GetValue();
|
||||
}
|
||||
|
||||
|
||||
@@ -599,7 +603,17 @@ int DIALOG_CHANGE_SYMBOLS::processSymbols( SCH_COMMIT* aCommit,
|
||||
wxCHECK( screen, 0 );
|
||||
|
||||
screen->Remove( symbol );
|
||||
aCommit->Modify( symbol, screen );
|
||||
SCH_SYMBOL* symbol_copy = static_cast<SCH_SYMBOL*>( symbol->Clone() );
|
||||
aCommit->Modified( symbol, symbol_copy, screen );
|
||||
|
||||
CONNECTION_GRAPH* connectionGraph = screen->Schematic()->ConnectionGraph();
|
||||
|
||||
// When we replace the lib symbol below, we free the associated pins if the new symbol has
|
||||
// fewer than the original. This will cause the connection graph to be out of date unless
|
||||
// we replace references in the graph to the old symbol/pins with references to the ones stored
|
||||
// in the undo stack.
|
||||
if( connectionGraph )
|
||||
connectionGraph->ExchangeItem( symbol, symbol_copy );
|
||||
}
|
||||
|
||||
for( const auto& [ symbol, symbol_change_info ] : symbols )
|
||||
@@ -671,7 +685,9 @@ int DIALOG_CHANGE_SYMBOLS::processSymbols( SCH_COMMIT* aCommit,
|
||||
}
|
||||
else if( i == VALUE_FIELD )
|
||||
{
|
||||
symbol->SetValueFieldText( UnescapeString( libField->GetText() ) );
|
||||
if( ( symbol->IsPower() && m_resetCustomPower->IsChecked() )
|
||||
|| !symbol->IsPower() )
|
||||
symbol->SetValueFieldText( UnescapeString( libField->GetText() ) );
|
||||
}
|
||||
else if( i == FOOTPRINT_FIELD )
|
||||
{
|
||||
|
||||
@@ -146,6 +146,11 @@ DIALOG_CHANGE_SYMBOLS_BASE::DIALOG_CHANGE_SYMBOLS_BASE( wxWindow* parent, wxWind
|
||||
m_resetAttributes = new wxCheckBox( m_updateOptionsSizer->GetStaticBox(), wxID_ANY, _("Update/reset symbol attributes"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_updateOptionsSizer->Add( m_resetAttributes, 0, wxBOTTOM|wxRIGHT, 5 );
|
||||
|
||||
m_updateOptionsSizer->Add( 0, 10, 1, wxEXPAND, 5 );
|
||||
|
||||
m_resetCustomPower = new wxCheckBox( m_updateOptionsSizer->GetStaticBox(), wxID_ANY, _("Reset custom power symbols"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_updateOptionsSizer->Add( m_resetCustomPower, 0, wxBOTTOM|wxRIGHT, 5 );
|
||||
|
||||
|
||||
bSizerUpdate->Add( m_updateOptionsSizer, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 8 );
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ class DIALOG_CHANGE_SYMBOLS_BASE : public DIALOG_SHIM
|
||||
wxCheckBox* m_resetFieldEffects;
|
||||
wxCheckBox* m_resetFieldPositions;
|
||||
wxCheckBox* m_resetAttributes;
|
||||
wxCheckBox* m_resetCustomPower;
|
||||
WX_HTML_REPORT_PANEL* m_messagePanel;
|
||||
wxStdDialogButtonSizer* m_sdbSizer;
|
||||
wxButton* m_sdbSizerOK;
|
||||
|
||||
@@ -429,17 +429,28 @@ DIALOG_LIB_FIELD_PROPERTIES::DIALOG_LIB_FIELD_PROPERTIES( SCH_BASE_FRAME* aParen
|
||||
|
||||
if( m_fieldId == FOOTPRINT_FIELD )
|
||||
{
|
||||
LIB_SYMBOL* symbol = aField->GetParent();
|
||||
wxString netlist;
|
||||
|
||||
/*
|
||||
* Symbol netlist format:
|
||||
* pinCount
|
||||
* fpFilters
|
||||
* pinNumber pinName <tab> pinNumber pinName...
|
||||
* fpFilter fpFilter...
|
||||
*/
|
||||
netlist << wxString::Format( wxS( "%d\r" ), symbol->GetPinCount() );
|
||||
wxString netlist;
|
||||
|
||||
wxArrayString fpFilters = symbol->GetFPFilters();
|
||||
std::vector<LIB_PIN*> pinList;
|
||||
|
||||
aField->GetParent()->GetPins( pinList, 0, 1 ); // All units, but a single convert
|
||||
|
||||
wxArrayString pins;
|
||||
|
||||
for( LIB_PIN* pin : pinList )
|
||||
pins.push_back( pin->GetNumber() + ' ' + pin->GetShownName() );
|
||||
|
||||
if( !pins.IsEmpty() )
|
||||
netlist << EscapeString( wxJoin( pins, '\t' ), CTX_LINE );
|
||||
|
||||
netlist << wxS( "\r" );
|
||||
|
||||
wxArrayString fpFilters = aField->GetParent()->GetFPFilters();
|
||||
|
||||
if( !fpFilters.IsEmpty() )
|
||||
netlist << EscapeString( wxJoin( fpFilters, ' ' ), CTX_LINE );
|
||||
@@ -473,7 +484,7 @@ void DIALOG_LIB_FIELD_PROPERTIES::UpdateField( LIB_FIELD* aField )
|
||||
}
|
||||
|
||||
|
||||
DIALOG_SCH_FIELD_PROPERTIES::DIALOG_SCH_FIELD_PROPERTIES( SCH_BASE_FRAME* aParent,
|
||||
DIALOG_SCH_FIELD_PROPERTIES::DIALOG_SCH_FIELD_PROPERTIES( SCH_EDIT_FRAME* aParent,
|
||||
const wxString& aTitle,
|
||||
const SCH_FIELD* aField ) :
|
||||
DIALOG_FIELD_PROPERTIES( aParent, aTitle, aField ),
|
||||
@@ -483,17 +494,27 @@ DIALOG_SCH_FIELD_PROPERTIES::DIALOG_SCH_FIELD_PROPERTIES( SCH_BASE_FRAME* aParen
|
||||
|
||||
if( aField->GetParent() && aField->GetParent()->Type() == SCH_SYMBOL_T )
|
||||
{
|
||||
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( aField->GetParent() );
|
||||
wxString netlist;
|
||||
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( aField->GetParent() );
|
||||
SCH_SHEET_PATH sheetPath = aParent->GetCurrentSheet();
|
||||
|
||||
m_fieldId = aField->GetId();
|
||||
|
||||
/*
|
||||
* Symbol netlist format:
|
||||
* pinCount
|
||||
* fpFilters
|
||||
* pinNumber pinName <tab> pinNumber pinName...
|
||||
* fpFilter fpFilter...
|
||||
*/
|
||||
netlist << wxString::Format( wxS( "%zu\r" ), symbol->GetFullPinCount() );
|
||||
wxString netlist;
|
||||
|
||||
wxArrayString pins;
|
||||
|
||||
for( SCH_PIN* pin : symbol->GetPins( &sheetPath ) )
|
||||
pins.push_back( pin->GetNumber() + ' ' + pin->GetShownName() );
|
||||
|
||||
if( !pins.IsEmpty() )
|
||||
netlist << EscapeString( wxJoin( pins, '\t' ), CTX_LINE );
|
||||
|
||||
netlist << wxS( "\r" );
|
||||
|
||||
wxArrayString fpFilters = symbol->GetLibSymbolRef()->GetFPFilters();
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ public:
|
||||
class DIALOG_SCH_FIELD_PROPERTIES : public DIALOG_FIELD_PROPERTIES
|
||||
{
|
||||
public:
|
||||
DIALOG_SCH_FIELD_PROPERTIES( SCH_BASE_FRAME* aParent, const wxString& aTitle,
|
||||
DIALOG_SCH_FIELD_PROPERTIES( SCH_EDIT_FRAME* aParent, const wxString& aTitle,
|
||||
const SCH_FIELD* aField );
|
||||
|
||||
~DIALOG_SCH_FIELD_PROPERTIES() {}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2019-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2019-2024 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
|
||||
@@ -594,7 +594,7 @@ bool DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::TransferDataFromWindow()
|
||||
|
||||
if( !commit.Empty() )
|
||||
{
|
||||
commit.Push( _( "Edit Text and Graphics" ), SKIP_CONNECTIVITY );
|
||||
commit.Push( _( "Edit Text and Graphics" ) );
|
||||
m_parent->HardRedraw();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2018-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2018-2024 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
|
||||
@@ -72,7 +72,7 @@ bool DIALOG_IMAGE_PROPERTIES::TransferDataFromWindow()
|
||||
m_bitmap->SetPosition( VECTOR2I( m_posX.GetValue(), m_posY.GetValue() ) );
|
||||
|
||||
if( !commit.Empty() )
|
||||
commit.Push( _( "Image Properties" ), SKIP_CONNECTIVITY );
|
||||
commit.Push( _( "Image Properties" ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2020 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2020-2024 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
|
||||
@@ -110,8 +110,7 @@ bool DIALOG_JUNCTION_PROPS::TransferDataFromWindow()
|
||||
m_frame->GetCanvas()->GetView()->Update( junction );
|
||||
}
|
||||
|
||||
commit.Push( m_junctions.size() == 1 ? _( "Edit Junction" ) : _( "Edit Junctions" ),
|
||||
SKIP_CONNECTIVITY );
|
||||
commit.Push( m_junctions.size() == 1 ? _( "Edit Junction" ) : _( "Edit Junctions" ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2013 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2024 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
|
||||
@@ -599,7 +599,7 @@ bool DIALOG_LABEL_PROPERTIES::TransferDataFromWindow()
|
||||
m_currentLabel->AutoAutoplaceFields( m_Parent->GetScreen() );
|
||||
|
||||
if( !commit.Empty() )
|
||||
commit.Push( _( "Edit Label" ), SKIP_CONNECTIVITY );
|
||||
commit.Push( _( "Edit Label Properties" ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 Seth Hillbrand <hillbrand@ucdavis.edu>
|
||||
* Copyright (C) 2014-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2014-2024 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
|
||||
@@ -149,6 +149,6 @@ bool DIALOG_LINE_PROPERTIES::TransferDataFromWindow()
|
||||
line->SetLineColor( m_colorSwatch->GetSwatchColor() );
|
||||
}
|
||||
|
||||
commit.Push( m_lines.size() == 1 ? _( "Edit Line" ) : _( "Edit Lines" ), SKIP_CONNECTIVITY );
|
||||
commit.Push( m_lines.size() == 1 ? _( "Edit Line" ) : _( "Edit Lines" ) );
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2021-2024 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
|
||||
@@ -166,8 +166,7 @@ bool DIALOG_SHAPE_PROPERTIES::TransferDataFromWindow()
|
||||
|
||||
if( !commit.Empty() )
|
||||
{
|
||||
commit.Push( wxString::Format( _( "Edit %s" ), m_shape->EDA_SHAPE::GetFriendlyName() ),
|
||||
SKIP_CONNECTIVITY );
|
||||
commit.Push( wxString::Format( _( "Edit %s" ), m_shape->EDA_SHAPE::GetFriendlyName() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <wildcards_and_files_ext.h>
|
||||
#include <widgets/std_bitmap_button.h>
|
||||
#include <kiplatform/ui.h>
|
||||
#include <sch_commit.h>
|
||||
#include <sch_edit_frame.h>
|
||||
#include <sch_sheet.h>
|
||||
#include <schematic.h>
|
||||
@@ -45,10 +46,12 @@
|
||||
#include "wx/dcclient.h"
|
||||
|
||||
DIALOG_SHEET_PROPERTIES::DIALOG_SHEET_PROPERTIES( SCH_EDIT_FRAME* aParent, SCH_SHEET* aSheet,
|
||||
bool* aClearAnnotationNewItems ) :
|
||||
bool* aClearAnnotationNewItems,
|
||||
bool* aUpdateHierarchyNavigator ) :
|
||||
DIALOG_SHEET_PROPERTIES_BASE( aParent ),
|
||||
m_frame( aParent ),
|
||||
m_clearAnnotationNewItems( aClearAnnotationNewItems ),
|
||||
m_updateHierarchyNavigator( aUpdateHierarchyNavigator ),
|
||||
m_borderWidth( aParent, m_borderWidthLabel, m_borderWidthCtrl, m_borderWidthUnits ),
|
||||
m_dummySheet( *aSheet ),
|
||||
m_dummySheetNameField( VECTOR2I( -1, -1 ), SHEETNAME, &m_dummySheet )
|
||||
@@ -257,9 +260,17 @@ static bool positioningChanged( FIELDS_GRID_TABLE<SCH_FIELD>* a, std::vector<SCH
|
||||
|
||||
bool DIALOG_SHEET_PROPERTIES::TransferDataFromWindow()
|
||||
{
|
||||
wxCHECK( m_sheet && m_frame, false );
|
||||
|
||||
if( !wxDialog::TransferDataFromWindow() ) // Calls our Validate() method.
|
||||
return false;
|
||||
|
||||
SCH_COMMIT commit( m_frame );
|
||||
|
||||
commit.Modify( m_sheet, m_frame->GetScreen() );
|
||||
|
||||
bool isUndoable = true;
|
||||
|
||||
// Sheet file names can be relative or absolute.
|
||||
wxString sheetFileName = m_fields->at( SHEETFILENAME ).GetText();
|
||||
|
||||
@@ -328,13 +339,17 @@ bool DIALOG_SHEET_PROPERTIES::TransferDataFromWindow()
|
||||
}
|
||||
}
|
||||
|
||||
if( !onSheetFilenameChanged( newRelativeFilename ) )
|
||||
if( !onSheetFilenameChanged( newRelativeFilename, &isUndoable ) )
|
||||
{
|
||||
if( clearFileName )
|
||||
currentScreen->SetFileName( wxEmptyString );
|
||||
|
||||
return false;
|
||||
}
|
||||
else if( m_updateHierarchyNavigator )
|
||||
{
|
||||
*m_updateHierarchyNavigator = true;
|
||||
}
|
||||
|
||||
if( clearFileName )
|
||||
currentScreen->SetFileName( wxEmptyString );
|
||||
@@ -345,6 +360,9 @@ bool DIALOG_SHEET_PROPERTIES::TransferDataFromWindow()
|
||||
|
||||
wxString newSheetname = m_fields->at( SHEETNAME ).GetText();
|
||||
|
||||
if( ( newSheetname != m_sheet->GetName() ) && m_updateHierarchyNavigator )
|
||||
*m_updateHierarchyNavigator = true;
|
||||
|
||||
if( newSheetname.IsEmpty() )
|
||||
newSheetname = _( "Untitled Sheet" );
|
||||
|
||||
@@ -407,14 +425,26 @@ bool DIALOG_SHEET_PROPERTIES::TransferDataFromWindow()
|
||||
for( SCH_ITEM* item : m_frame->GetScreen()->Items().OfType( SCH_SHEET_T ) )
|
||||
m_frame->UpdateItem( item );
|
||||
|
||||
m_frame->OnModify();
|
||||
if( isUndoable )
|
||||
{
|
||||
commit.Push( _( "Edit Sheet Properties" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we are renaming files, the undo/redo list becomes invalid and must be cleared.
|
||||
m_frame->ClearUndoRedoList();
|
||||
m_frame->OnModify();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DIALOG_SHEET_PROPERTIES::onSheetFilenameChanged( const wxString& aNewFilename )
|
||||
bool DIALOG_SHEET_PROPERTIES::onSheetFilenameChanged( const wxString& aNewFilename,
|
||||
bool* aIsUndoable )
|
||||
{
|
||||
wxCHECK( aIsUndoable, false );
|
||||
|
||||
wxString msg;
|
||||
wxFileName sheetFileName(
|
||||
EnsureFileExtension( aNewFilename, FILEEXT::KiCadSchematicFileExtension ) );
|
||||
@@ -494,7 +524,6 @@ bool DIALOG_SHEET_PROPERTIES::onSheetFilenameChanged( const wxString& aNewFilena
|
||||
}
|
||||
else // Existing sheet.
|
||||
{
|
||||
bool isUndoable = true;
|
||||
isExistingSheet = true;
|
||||
|
||||
if( !m_frame->AllowCaseSensitiveFileNameClashes( newAbsoluteFilename ) )
|
||||
@@ -515,7 +544,7 @@ bool DIALOG_SHEET_PROPERTIES::onSheetFilenameChanged( const wxString& aNewFilena
|
||||
if( newAbsoluteFilename.Cmp( oldAbsoluteFilename ) != 0 )
|
||||
{
|
||||
// Sheet file name changes cannot be undone.
|
||||
isUndoable = false;
|
||||
*aIsUndoable = false;
|
||||
|
||||
if( useScreen || loadFromFile ) // Load from existing file.
|
||||
{
|
||||
@@ -553,12 +582,6 @@ bool DIALOG_SHEET_PROPERTIES::onSheetFilenameChanged( const wxString& aNewFilena
|
||||
}
|
||||
}
|
||||
|
||||
// If we are renaming files, the undo/redo list becomes invalid and must be cleared
|
||||
if( isUndoable )
|
||||
m_frame->SaveCopyInUndoList( m_frame->GetScreen(), m_sheet, UNDO_REDO::CHANGED, false );
|
||||
else
|
||||
m_frame->ClearUndoRedoList();
|
||||
|
||||
if( renameFile )
|
||||
{
|
||||
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
|
||||
@@ -614,6 +637,12 @@ bool DIALOG_SHEET_PROPERTIES::onSheetFilenameChanged( const wxString& aNewFilena
|
||||
|
||||
// It's safe to set the sheet screen now.
|
||||
m_sheet->SetScreen( useScreen );
|
||||
|
||||
SCH_SHEET_LIST sheetHierarchy( m_sheet ); // The hierarchy of the loaded file.
|
||||
|
||||
sheetHierarchy.AddNewSymbolInstances( currentSheet );
|
||||
sheetHierarchy.AddNewSheetInstances( currentSheet,
|
||||
fullHierarchy.GetLastVirtualPageNumber() );
|
||||
}
|
||||
else if( loadFromFile )
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2009 Wayne Stambaugh <stambaughw@verizon.net>
|
||||
* Copyright (C) 2014-2020 KiCad Developers, see AUTHORS.TXT for contributors.
|
||||
* Copyright (C) 2014-2024 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
|
||||
@@ -38,12 +38,13 @@ class DIALOG_SHEET_PROPERTIES : public DIALOG_SHEET_PROPERTIES_BASE
|
||||
{
|
||||
public:
|
||||
DIALOG_SHEET_PROPERTIES( SCH_EDIT_FRAME* aParent, SCH_SHEET* aSheet,
|
||||
bool* aClearAnnotationNewItems );
|
||||
bool* aClearAnnotationNewItems,
|
||||
bool* aUpdateHierarchyNavigator );
|
||||
|
||||
~DIALOG_SHEET_PROPERTIES() override;
|
||||
|
||||
private:
|
||||
bool onSheetFilenameChanged( const wxString& aNewFilename );
|
||||
bool onSheetFilenameChanged( const wxString& aNewFilename, bool* aIsUndoable );
|
||||
|
||||
bool TransferDataToWindow() override;
|
||||
bool TransferDataFromWindow() override;
|
||||
@@ -66,6 +67,7 @@ private:
|
||||
SCH_EDIT_FRAME* m_frame;
|
||||
SCH_SHEET* m_sheet;
|
||||
bool* m_clearAnnotationNewItems;
|
||||
bool* m_updateHierarchyNavigator;
|
||||
|
||||
wxSize m_size;
|
||||
int m_delayedFocusRow;
|
||||
|
||||
@@ -146,13 +146,17 @@ protected:
|
||||
{
|
||||
if( m_fieldsCtrl->GetTextValue( row, FIELD_NAME_COLUMN ) == fieldName )
|
||||
{
|
||||
m_fieldsCtrl->SetToggleValue( show, row, SHOW_FIELD_COLUMN );
|
||||
if( m_grid->CommitPendingChanges( false ) )
|
||||
m_fieldsCtrl->SetToggleValue( show, row, SHOW_FIELD_COLUMN );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GRID_TRICKS::doPopupSelection( event );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1039,6 +1043,10 @@ void DIALOG_SYMBOL_FIELDS_TABLE::OnTableCellClick( wxGridEvent& event )
|
||||
|
||||
void DIALOG_SYMBOL_FIELDS_TABLE::OnTableRangeSelected( wxGridRangeSelectEvent& aEvent )
|
||||
{
|
||||
// Cross-probing should only work in Edit page
|
||||
if( m_nbPages->GetSelection() != 0 )
|
||||
return;
|
||||
|
||||
// Multi-select can grab the rows that are expanded child refs, and also the row
|
||||
// containing the list of all child refs. Make sure we add refs/symbols uniquely
|
||||
std::set<SCH_REFERENCE> refs;
|
||||
@@ -1063,10 +1071,10 @@ void DIALOG_SYMBOL_FIELDS_TABLE::OnTableRangeSelected( wxGridRangeSelectEvent& a
|
||||
|
||||
if( refs.size() > 0 )
|
||||
{
|
||||
// Use of full path based on UUID allows select of not yet annotated or duplicaded symbols
|
||||
// Use of full path based on UUID allows select of not yet annotated or duplicated symbols
|
||||
wxString symbol_path = refs.begin()->GetFullPath();
|
||||
|
||||
// Focus only handles on item at this time
|
||||
// Focus only handles one item at this time
|
||||
editor->FindSymbolAndItem( &symbol_path, nullptr, true, HIGHLIGHT_SYMBOL,
|
||||
wxEmptyString );
|
||||
}
|
||||
@@ -1288,6 +1296,7 @@ void DIALOG_SYMBOL_FIELDS_TABLE::OnExport( wxCommandEvent& aEvent )
|
||||
return;
|
||||
}
|
||||
|
||||
out.Close(); // close the file before we tell the user it's done with the info modal :workflow meme:
|
||||
msg.Printf( _( "Wrote BOM output to '%s'" ), outputFile.GetFullPath() );
|
||||
DisplayInfoMessage( this, msg );
|
||||
}
|
||||
|
||||
@@ -536,7 +536,7 @@ bool DIALOG_TEXT_PROPERTIES::TransferDataFromWindow()
|
||||
}
|
||||
|
||||
if( !commit.Empty() )
|
||||
commit.Push( _( "Edit Text" ), SKIP_CONNECTIVITY );
|
||||
commit.Push( _( "Edit Text Properties" ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -126,6 +126,19 @@ SCHEMATIC* EESCHEMA_HELPERS::LoadSchematic( wxString& aFileName, SCH_IO_MGR::SCH
|
||||
|
||||
SCHEMATIC* schematic = new SCHEMATIC( project );
|
||||
|
||||
SCH_SHEET* rootSheet = new SCH_SHEET( schematic );
|
||||
schematic->SetRoot( rootSheet );
|
||||
|
||||
SCH_SCREEN* rootScreen = new SCH_SCREEN( schematic );
|
||||
const_cast<KIID&>( rootSheet->m_Uuid ) = rootScreen->GetUuid();
|
||||
schematic->Root().SetScreen( rootScreen );
|
||||
|
||||
|
||||
schematic->RootScreen()->SetFileName( wxEmptyString );
|
||||
|
||||
// Don't leave root page number empty
|
||||
schematic->RootScreen()->SetPageNumber( wxT( "1" ) );
|
||||
|
||||
wxFileName schFile = aFileName;
|
||||
schFile.MakeAbsolute();
|
||||
|
||||
|
||||
+5
-1
@@ -559,6 +559,7 @@ int ERC_TESTER::TestMissingNetclasses()
|
||||
{
|
||||
int err_count = 0;
|
||||
std::shared_ptr<NET_SETTINGS>& settings = m_schematic->Prj().GetProjectFile().NetSettings();
|
||||
wxString defaultNetclass = settings->m_DefaultNetClass->GetName();
|
||||
|
||||
auto logError =
|
||||
[&]( const SCH_SHEET_PATH& sheet, SCH_ITEM* item, const wxString& netclass )
|
||||
@@ -590,8 +591,11 @@ int ERC_TESTER::TestMissingNetclasses()
|
||||
{
|
||||
wxString netclass = field->GetText();
|
||||
|
||||
if( settings->m_NetClasses.count( netclass ) == 0 )
|
||||
if( !netclass.IsSameAs( defaultNetclass )
|
||||
&& settings->m_NetClasses.count( netclass ) == 0 )
|
||||
{
|
||||
logError( sheet, item, netclass );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,16 +62,24 @@ enum
|
||||
|
||||
static wxString netList( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH& aSheetPath )
|
||||
{
|
||||
wxCHECK( aSymbol && aSymbol->GetLibSymbolRef(), wxEmptyString );
|
||||
|
||||
/*
|
||||
* Symbol netlist format:
|
||||
* pinCount
|
||||
* fpFilters
|
||||
* pinNumber pinName <tab> pinNumber pinName...
|
||||
* fpFilter fpFilter...
|
||||
*/
|
||||
wxString netlist;
|
||||
|
||||
netlist << wxString::Format( wxS( "%zu\r" ), aSymbol->GetFullPinCount() );
|
||||
wxArrayString pins;
|
||||
|
||||
wxCHECK( aSymbol && aSymbol->GetLibSymbolRef(), wxEmptyString );
|
||||
for( SCH_PIN* pin : aSymbol->GetPins( &aSheetPath ) )
|
||||
pins.push_back( pin->GetNumber() + ' ' + pin->GetShownName() );
|
||||
|
||||
if( !pins.IsEmpty() )
|
||||
netlist << EscapeString( wxJoin( pins, '\t' ), CTX_LINE );
|
||||
|
||||
netlist << wxS( "\r" );
|
||||
|
||||
wxArrayString fpFilters = aSymbol->GetLibSymbolRef()->GetFPFilters();
|
||||
|
||||
@@ -88,12 +96,24 @@ static wxString netList( LIB_SYMBOL* aSymbol )
|
||||
{
|
||||
/*
|
||||
* Symbol netlist format:
|
||||
* pinCount
|
||||
* fpFilters
|
||||
* pinNumber pinName <tab> pinNumber pinName...
|
||||
* fpFilter fpFilter...
|
||||
*/
|
||||
wxString netlist;
|
||||
|
||||
netlist << wxString::Format( wxS( "%d\r" ), aSymbol->GetPinCount() );
|
||||
std::vector<LIB_PIN*> pinList;
|
||||
|
||||
aSymbol->GetPins( pinList, 0, 1 ); // All units, but a single convert
|
||||
|
||||
wxArrayString pins;
|
||||
|
||||
for( LIB_PIN* pin : pinList )
|
||||
pins.push_back( pin->GetNumber() + ' ' + pin->GetShownName() );
|
||||
|
||||
if( !pins.IsEmpty() )
|
||||
netlist << EscapeString( wxJoin( pins, '\t' ), CTX_LINE );
|
||||
|
||||
netlist << wxS( "\r" );
|
||||
|
||||
wxArrayString fpFilters = aSymbol->GetFPFilters();
|
||||
|
||||
|
||||
@@ -267,6 +267,7 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
||||
// Make ${SHEETNAME} work on the root sheet until we properly support
|
||||
// naming the root sheet
|
||||
Schematic().Root().SetName( _( "Root" ) );
|
||||
wxLogDebug( "Loaded schematic with root sheet UUID %s", Schematic().Root().m_Uuid.AsString() );
|
||||
}
|
||||
|
||||
if( !pi->GetError().IsEmpty() )
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <i18n_utility.h>
|
||||
#include <pgm_base.h>
|
||||
#include <font/font.h>
|
||||
#include <settings/settings_manager.h>
|
||||
@@ -183,3 +184,49 @@ void LIB_ITEM::ViewGetLayers( int aLayers[], int& aCount ) const
|
||||
aLayers[1] = LAYER_DEVICE_BACKGROUND;
|
||||
aLayers[2] = LAYER_SELECTION_SHADOWS;
|
||||
}
|
||||
|
||||
|
||||
static struct LIB_ITEM_DESC
|
||||
{
|
||||
LIB_ITEM_DESC()
|
||||
{
|
||||
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
|
||||
REGISTER_TYPE( LIB_ITEM );
|
||||
propMgr.AddTypeCast( new TYPE_CAST<LIB_ITEM, EDA_ITEM> );
|
||||
propMgr.InheritsAfter( TYPE_HASH( LIB_ITEM ), TYPE_HASH( EDA_ITEM ) );
|
||||
|
||||
auto multiUnit =
|
||||
[=]( INSPECTABLE* aItem ) -> bool
|
||||
{
|
||||
if( LIB_ITEM* libItem = dynamic_cast<LIB_ITEM*>( aItem ) )
|
||||
{
|
||||
if( LIB_SYMBOL* symbol = libItem->GetParent() )
|
||||
return symbol->IsMulti();
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
auto multiBodyStyle =
|
||||
[=]( INSPECTABLE* aItem ) -> bool
|
||||
{
|
||||
if( LIB_ITEM* libItem = dynamic_cast<LIB_ITEM*>( aItem ) )
|
||||
{
|
||||
if( LIB_SYMBOL* symbol = libItem->GetParent() )
|
||||
return symbol->HasAlternateBodyStyle();
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
propMgr.AddProperty( new PROPERTY<LIB_ITEM, int>( _HKI( "Unit" ),
|
||||
&LIB_ITEM::SetUnit, &LIB_ITEM::GetUnit ) )
|
||||
.SetAvailableFunc( multiUnit );
|
||||
propMgr.AddProperty( new PROPERTY<LIB_ITEM, int>( _HKI( "Body Style" ),
|
||||
&LIB_ITEM::SetBodyStyle, &LIB_ITEM::GetBodyStyle ) )
|
||||
.SetAvailableFunc( multiBodyStyle );
|
||||
|
||||
propMgr.AddProperty( new PROPERTY<LIB_ITEM, bool>( _HKI( "Private" ),
|
||||
&LIB_ITEM::SetPrivate, &LIB_ITEM::IsPrivate ) );
|
||||
}
|
||||
} _LIB_ITEM_DESC;
|
||||
|
||||
@@ -1661,7 +1661,8 @@ static struct LIB_PIN_DESC
|
||||
|
||||
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
|
||||
REGISTER_TYPE( LIB_PIN );
|
||||
propMgr.InheritsAfter( TYPE_HASH( LIB_PIN ), TYPE_HASH( SCH_ITEM ) );
|
||||
propMgr.AddTypeCast( new TYPE_CAST<LIB_PIN, LIB_ITEM> );
|
||||
propMgr.InheritsAfter( TYPE_HASH( LIB_PIN ), TYPE_HASH( LIB_ITEM ) );
|
||||
|
||||
propMgr.AddProperty( new PROPERTY<LIB_PIN, wxString>( _HKI( "Pin Name" ),
|
||||
&LIB_PIN::SetName, &LIB_PIN::GetName ) );
|
||||
|
||||
@@ -600,7 +600,8 @@ static struct LIB_SHAPE_DESC
|
||||
FILL_T ( LIB_SHAPE::*fillModeGetter )() const = &LIB_SHAPE::GetFillMode;
|
||||
|
||||
propMgr.AddProperty( new PROPERTY_ENUM< LIB_SHAPE, FILL_T>( _HKI( "Fill" ),
|
||||
fillModeSetter, fillModeGetter ) );
|
||||
fillModeSetter, fillModeGetter ),
|
||||
_HKI( "Shape Properties" ) );
|
||||
}
|
||||
} _LIB_SHAPE_DESC;
|
||||
|
||||
|
||||
@@ -703,7 +703,9 @@ const wxString LIB_SYMBOL::GetLibraryName() const
|
||||
|
||||
bool LIB_SYMBOL::IsPower() const
|
||||
{
|
||||
if( LIB_SYMBOL_SPTR parent = m_parent.lock() )
|
||||
std::shared_ptr<LIB_SYMBOL> parent;
|
||||
|
||||
if( !m_parent.expired() && ( parent = m_parent.lock() ) )
|
||||
{
|
||||
if( parent->IsRoot() )
|
||||
return parent->m_options == ENTRY_POWER;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2004 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2004-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2004-2024 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
|
||||
@@ -424,6 +424,25 @@ std::vector<VECTOR2I> SCH_BUS_ENTRY_BASE::GetConnectionPoints() const
|
||||
}
|
||||
|
||||
|
||||
bool SCH_BUS_ENTRY_BASE::HasConnectivityChanges( const SCH_ITEM* aItem,
|
||||
const SCH_SHEET_PATH* aInstance ) const
|
||||
{
|
||||
// Do not compare to ourself.
|
||||
if( aItem == this )
|
||||
return false;
|
||||
|
||||
const SCH_BUS_ENTRY_BASE* busEntry = dynamic_cast<const SCH_BUS_ENTRY_BASE*>( aItem );
|
||||
|
||||
// Don't compare against a different SCH_ITEM.
|
||||
wxCHECK( busEntry, false );
|
||||
|
||||
if( GetPosition() != busEntry->GetPosition() )
|
||||
return true;
|
||||
|
||||
return GetEnd() != busEntry->GetEnd();
|
||||
}
|
||||
|
||||
|
||||
wxString SCH_BUS_WIRE_ENTRY::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
|
||||
{
|
||||
return wxString( _( "Bus to Wire Entry" ) );
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
|
||||
* Copyright (C) 2004-2021 KiCad Developers, see change_log.txt for contributors.
|
||||
* Copyright (C) 2004-2024 KiCad Developers, see change_log.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
|
||||
@@ -108,6 +108,9 @@ public:
|
||||
|
||||
bool IsConnectable() const override { return true; }
|
||||
|
||||
bool HasConnectivityChanges( const SCH_ITEM* aItem,
|
||||
const SCH_SHEET_PATH* aInstance = nullptr ) const override;
|
||||
|
||||
std::vector<VECTOR2I> GetConnectionPoints() const override;
|
||||
|
||||
VECTOR2I GetPosition() const override { return m_pos; }
|
||||
|
||||
+34
-9
@@ -211,23 +211,28 @@ void SCH_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
|
||||
if( schItem->IsSelected() )
|
||||
selectedModified = true;
|
||||
|
||||
if( !( aCommitFlags & SKIP_CONNECTIVITY ) && schItem->IsConnectable() )
|
||||
auto updateConnectivityFlag = [&, this]()
|
||||
{
|
||||
dirtyConnectivity = true;
|
||||
if( schItem->IsConnectable() )
|
||||
{
|
||||
dirtyConnectivity = true;
|
||||
|
||||
// Do a local clean up if there are any connectable objects in the commit.
|
||||
if( connectivityCleanUp == NO_CLEANUP )
|
||||
connectivityCleanUp = LOCAL_CLEANUP;
|
||||
// Do a local clean up if there are any connectable objects in the commit.
|
||||
if( connectivityCleanUp == NO_CLEANUP )
|
||||
connectivityCleanUp = LOCAL_CLEANUP;
|
||||
|
||||
// Do a full rebauild of the connectivity if there is a sheet in the commit.
|
||||
if( schItem->Type() == SCH_SHEET_T )
|
||||
connectivityCleanUp = GLOBAL_CLEANUP;
|
||||
}
|
||||
// Do a full rebauild of the connectivity if there is a sheet in the commit.
|
||||
if( schItem->Type() == SCH_SHEET_T )
|
||||
connectivityCleanUp = GLOBAL_CLEANUP;
|
||||
}
|
||||
};
|
||||
|
||||
switch( changeType )
|
||||
{
|
||||
case CHT_ADD:
|
||||
{
|
||||
updateConnectivityFlag();
|
||||
|
||||
if( !( aCommitFlags & SKIP_UNDO ) )
|
||||
undoList.PushItem( ITEM_PICKER( screen, schItem, UNDO_REDO::NEWITEM ) );
|
||||
|
||||
@@ -250,6 +255,8 @@ void SCH_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
|
||||
|
||||
case CHT_REMOVE:
|
||||
{
|
||||
updateConnectivityFlag();
|
||||
|
||||
if( !( aCommitFlags & SKIP_UNDO ) )
|
||||
undoList.PushItem( ITEM_PICKER( screen, schItem, UNDO_REDO::DELETED ) );
|
||||
|
||||
@@ -290,6 +297,19 @@ void SCH_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
|
||||
ITEM_PICKER itemWrapper( screen, schItem, UNDO_REDO::CHANGED );
|
||||
wxASSERT( ent.m_copy );
|
||||
itemWrapper.SetLink( ent.m_copy );
|
||||
|
||||
const SCH_ITEM* itemCopy = static_cast<const SCH_ITEM*>( ent.m_copy );
|
||||
|
||||
wxCHECK2( itemCopy, continue );
|
||||
|
||||
SCH_SHEET_PATH currentSheet;
|
||||
|
||||
if( frame )
|
||||
currentSheet = frame->GetCurrentSheet();
|
||||
|
||||
if( itemCopy->HasConnectivityChanges( schItem, ¤tSheet ) )
|
||||
updateConnectivityFlag();
|
||||
|
||||
undoList.PushItem( itemWrapper );
|
||||
ent.m_copy = nullptr; // We've transferred ownership to the undo list
|
||||
}
|
||||
@@ -339,7 +359,12 @@ void SCH_COMMIT::pushSchEdit( const wxString& aMessage, int aCommitFlags )
|
||||
frame->SaveCopyInUndoList( undoList, UNDO_REDO::UNSPECIFIED, false, dirtyConnectivity );
|
||||
|
||||
if( dirtyConnectivity )
|
||||
{
|
||||
wxLogTrace( wxS( "CONN_PROFILE" ),
|
||||
wxS( "SCH_COMMIT::pushSchEdit() %s clean up connectivity rebuild." ),
|
||||
( connectivityCleanUp == LOCAL_CLEANUP ) ? wxS( "local" ) : wxS( "global" ) );
|
||||
frame->RecalculateConnections( this, connectivityCleanUp );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 CERN
|
||||
* Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2016-2024 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
|
||||
@@ -40,7 +40,6 @@ class EE_TOOL_BASE;
|
||||
#define SKIP_UNDO 0x0001
|
||||
#define APPEND_UNDO 0x0002
|
||||
#define SKIP_SET_DIRTY 0x0004
|
||||
#define SKIP_CONNECTIVITY 0x0008
|
||||
|
||||
class SCH_COMMIT : public COMMIT
|
||||
{
|
||||
|
||||
+29
-20
@@ -1718,7 +1718,7 @@ void SCH_EDIT_FRAME::RecalculateConnections( SCH_COMMIT* aCommit, SCH_CLEANUP_FL
|
||||
{
|
||||
PICKED_ITEMS_LIST* changed_list = m_undoList.m_CommandsList.back();
|
||||
std::set<SCH_ITEM*> changed_items;
|
||||
std::vector<VECTOR2I> pts;
|
||||
std::set<VECTOR2I> pts;
|
||||
std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> item_paths;
|
||||
|
||||
for( unsigned ii = 0; ii < changed_list->GetCount(); ++ii )
|
||||
@@ -1733,23 +1733,47 @@ void SCH_EDIT_FRAME::RecalculateConnections( SCH_COMMIT* aCommit, SCH_CLEANUP_FL
|
||||
SCH_SHEET_PATHS& paths = screen->GetClientSheetPaths();
|
||||
|
||||
std::vector<VECTOR2I> tmp_pts = item->GetConnectionPoints();
|
||||
pts.insert( pts.end(), tmp_pts.begin(), tmp_pts.end() );
|
||||
pts.insert( tmp_pts.begin(), tmp_pts.end() );
|
||||
changed_items.insert( item );
|
||||
|
||||
for( SCH_SHEET_PATH& path : paths )
|
||||
item_paths.insert( std::make_pair( path, item ) );
|
||||
|
||||
item = dynamic_cast<SCH_ITEM*>( changed_list->GetPickedItemLink( ii ) );
|
||||
|
||||
if( !item || !item->IsConnectable() )
|
||||
continue;
|
||||
|
||||
tmp_pts = item->GetConnectionPoints();
|
||||
pts.insert( tmp_pts.begin(), tmp_pts.end() );
|
||||
changed_items.insert( item );
|
||||
|
||||
// We have to directly add the pins here because the link may not exist on the schematic
|
||||
// anymore and so won't be picked up by GetScreen()->Items().Overlapping() below.
|
||||
if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item ) )
|
||||
{
|
||||
std::vector<SCH_PIN*> pins = symbol->GetPins();
|
||||
changed_items.insert( pins.begin(), pins.end() );
|
||||
}
|
||||
|
||||
for( SCH_SHEET_PATH& path : paths )
|
||||
item_paths.insert( std::make_pair( path, item ) );
|
||||
}
|
||||
|
||||
for( VECTOR2I& pt: pts )
|
||||
for( const VECTOR2I& pt: pts )
|
||||
{
|
||||
for( SCH_ITEM* item : GetScreen()->Items().Overlapping( pt ) )
|
||||
{
|
||||
// Leave this check in place. Overlapping items are not necessarily connectable.
|
||||
if( !item->IsConnectable() )
|
||||
continue;
|
||||
|
||||
if( item->Type() == SCH_LINE_T )
|
||||
{
|
||||
if( item->HitTest( pt ) )
|
||||
changed_items.insert( item );
|
||||
}
|
||||
else if( item->Type() == SCH_SYMBOL_T )
|
||||
else if( item->Type() == SCH_SYMBOL_T && item->IsConnected( pt ) )
|
||||
{
|
||||
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
|
||||
std::vector<SCH_PIN*> pins = symbol->GetPins();
|
||||
@@ -1767,7 +1791,6 @@ void SCH_EDIT_FRAME::RecalculateConnections( SCH_COMMIT* aCommit, SCH_CLEANUP_FL
|
||||
}
|
||||
else
|
||||
{
|
||||
// Non-connectable objects have already been pruned.
|
||||
if( item->IsConnected( pt ) )
|
||||
changed_items.insert( item );
|
||||
}
|
||||
@@ -1786,21 +1809,7 @@ void SCH_EDIT_FRAME::RecalculateConnections( SCH_COMMIT* aCommit, SCH_CLEANUP_FL
|
||||
for( auto&[ path, item ] : all_items )
|
||||
{
|
||||
wxCHECK2( item, continue );
|
||||
|
||||
switch( item->Type() )
|
||||
{
|
||||
case SCH_FIELD_T:
|
||||
case SCH_PIN_T:
|
||||
{
|
||||
SCH_ITEM* parent = static_cast<SCH_ITEM*>( item->GetParent() );
|
||||
wxCHECK2( parent, continue );
|
||||
parent->SetConnectivityDirty();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
item->SetConnectivityDirty();
|
||||
}
|
||||
item->SetConnectivityDirty();
|
||||
}
|
||||
|
||||
new_graph.Recalculate( list, false, &changeHandler );
|
||||
|
||||
@@ -574,9 +574,12 @@ public:
|
||||
* this sheet need to have their annotation cleared i.e. when an existing item list is used.
|
||||
* it can happens when the edited sheet used an existing file, or becomes a new instance
|
||||
* of a already existing sheet.
|
||||
* @param aUpdateHierarchyNavigator is an optional flag to indicate the sheet changes require
|
||||
* the hierarchy navigator panel to be updated.
|
||||
*/
|
||||
bool EditSheetProperties( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy,
|
||||
bool* aClearAnnotationNewItems );
|
||||
bool* aClearAnnotationNewItems,
|
||||
bool* aUpdateHierarchyNavigator = nullptr );
|
||||
|
||||
void InitSheet( SCH_SHEET* aSheet, const wxString& aNewFilename );
|
||||
|
||||
|
||||
@@ -332,7 +332,12 @@ SCH_FIELD::GetRenderCache( const wxString& forResolvedText, const VECTOR2I& forP
|
||||
VECTOR2I delta = forPosition - m_renderCachePos;
|
||||
|
||||
for( std::unique_ptr<KIFONT::GLYPH>& glyph : m_renderCache )
|
||||
static_cast<KIFONT::OUTLINE_GLYPH*>( glyph.get() )->Move( delta );
|
||||
{
|
||||
if( glyph->IsOutline() )
|
||||
static_cast<KIFONT::OUTLINE_GLYPH*>( glyph.get() )->Move( delta );
|
||||
else
|
||||
static_cast<KIFONT::STROKE_GLYPH*>( glyph.get() )->Move( delta );
|
||||
}
|
||||
|
||||
m_renderCachePos = forPosition;
|
||||
}
|
||||
|
||||
@@ -24,19 +24,21 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
#include <charconv>
|
||||
|
||||
#include <base_units.h>
|
||||
#include <ki_exception.h>
|
||||
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "io/altium/altium_parser.h"
|
||||
#include "sch_io/altium/altium_parser_sch.h"
|
||||
#include "io/altium/altium_binary_parser.h"
|
||||
#include "io/altium/altium_props_utils.h"
|
||||
|
||||
|
||||
ALTIUM_SCH_RECORD ReadRecord( const std::map<wxString, wxString>& aProps )
|
||||
{
|
||||
int recordId = ALTIUM_PARSER::ReadInt( aProps, "RECORD", -1 );
|
||||
int recordId = ALTIUM_PROPS_UTILS::ReadInt( aProps, "RECORD", -1 );
|
||||
return static_cast<ALTIUM_SCH_RECORD>( recordId );
|
||||
}
|
||||
|
||||
@@ -55,8 +57,8 @@ constexpr int Altium2KiCadUnit( const int val, const int frac )
|
||||
int ReadKiCadUnitFrac( const std::map<wxString, wxString>& aProps, const wxString& aKey )
|
||||
{
|
||||
// a unit is stored using two fields, denoting the size in mils and a fraction size
|
||||
int key = ALTIUM_PARSER::ReadInt( aProps, aKey, 0 );
|
||||
int keyFrac = ALTIUM_PARSER::ReadInt( aProps, aKey + "_FRAC", 0 );
|
||||
int key = ALTIUM_PROPS_UTILS::ReadInt( aProps, aKey, 0 );
|
||||
int keyFrac = ALTIUM_PROPS_UTILS::ReadInt( aProps, aKey + "_FRAC", 0 );
|
||||
return Altium2KiCadUnit( key, keyFrac );
|
||||
}
|
||||
|
||||
@@ -65,21 +67,21 @@ int ReadKiCadUnitFrac1( const std::map<wxString, wxString>& aProps, const wxStri
|
||||
{
|
||||
// a unit is stored using two fields, denoting the size in mils and a fraction size
|
||||
// Dunno why Altium invents different units for the same purpose
|
||||
int key = ALTIUM_PARSER::ReadInt( aProps, aKey, 0 );
|
||||
int keyFrac = ALTIUM_PARSER::ReadInt( aProps, aKey + "_FRAC1", 0 );
|
||||
int key = ALTIUM_PROPS_UTILS::ReadInt( aProps, aKey, 0 );
|
||||
int keyFrac = ALTIUM_PROPS_UTILS::ReadInt( aProps, aKey + "_FRAC1", 0 );
|
||||
return Altium2KiCadUnit( key * 10, keyFrac );
|
||||
}
|
||||
|
||||
|
||||
int ReadOwnerIndex( const std::map<wxString, wxString>& aProperties )
|
||||
{
|
||||
return ALTIUM_PARSER::ReadInt( aProperties, "OWNERINDEX", ALTIUM_COMPONENT_NONE );
|
||||
return ALTIUM_PROPS_UTILS::ReadInt( aProperties, "OWNERINDEX", ALTIUM_COMPONENT_NONE );
|
||||
}
|
||||
|
||||
|
||||
int ReadOwnerPartId( const std::map<wxString, wxString>& aProperties )
|
||||
{
|
||||
return ALTIUM_PARSER::ReadInt( aProperties, "OWNERPARTID", ALTIUM_COMPONENT_NONE );
|
||||
return ALTIUM_PROPS_UTILS::ReadInt( aProperties, "OWNERPARTID", ALTIUM_COMPONENT_NONE );
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +89,7 @@ template <typename T>
|
||||
T ReadEnum( const std::map<wxString, wxString>& aProps, const wxString& aKey, int aLower,
|
||||
int aUpper, T aDefault )
|
||||
{
|
||||
int value = ALTIUM_PARSER::ReadInt( aProps, aKey, static_cast<int>( aDefault ) );
|
||||
int value = ALTIUM_PROPS_UTILS::ReadInt( aProps, aKey, static_cast<int>( aDefault ) );
|
||||
|
||||
if( value < aLower || value > aUpper )
|
||||
return aDefault;
|
||||
@@ -96,7 +98,41 @@ T ReadEnum( const std::map<wxString, wxString>& aProps, const wxString& aKey, in
|
||||
}
|
||||
|
||||
|
||||
ASCH_STORAGE_FILE::ASCH_STORAGE_FILE( ALTIUM_PARSER& aReader )
|
||||
ASCH_STORAGE_FILE::ASCH_STORAGE_FILE( const std::map<wxString, wxString>& aProps )
|
||||
{
|
||||
filename = ALTIUM_PROPS_UTILS::ReadString( aProps, "NAME", "" );
|
||||
size_t dataSize = ALTIUM_PROPS_UTILS::ReadInt( aProps, "DATA_LEN", 0 );
|
||||
|
||||
wxString hexData = ALTIUM_PROPS_UTILS::ReadString( aProps, "DATA", "" );
|
||||
const size_t charCount = hexData.size();
|
||||
|
||||
if( charCount != dataSize * 2 )
|
||||
{
|
||||
THROW_IO_ERROR( wxString::Format( "Invalid binary file hex data size. Chars expected: %d, "
|
||||
"hex string length: %d",
|
||||
int( dataSize * 2 ), int( hexData.size() ) ) );
|
||||
}
|
||||
|
||||
data.resize( dataSize );
|
||||
|
||||
char str[3] = { 0 };
|
||||
uint8_t b = 0;
|
||||
size_t outputId = 0;
|
||||
|
||||
for( size_t inputId = 1; inputId < charCount; inputId += 2 )
|
||||
{
|
||||
str[0] = (char) hexData[inputId - 1];
|
||||
str[1] = (char) hexData[inputId];
|
||||
|
||||
std::from_chars( str, str + 2, b, 16 );
|
||||
data[outputId] = b;
|
||||
|
||||
outputId++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ASCH_STORAGE_FILE::ASCH_STORAGE_FILE( ALTIUM_BINARY_PARSER& aReader )
|
||||
{
|
||||
aReader.Skip( 5 );
|
||||
filename = aReader.ReadWxString();
|
||||
@@ -108,7 +144,7 @@ ASCH_STORAGE_FILE::ASCH_STORAGE_FILE( ALTIUM_PARSER& aReader )
|
||||
}
|
||||
|
||||
|
||||
ASCH_ADDITIONAL_FILE::ASCH_ADDITIONAL_FILE( ALTIUM_PARSER& aReader )
|
||||
ASCH_ADDITIONAL_FILE::ASCH_ADDITIONAL_FILE( ALTIUM_BINARY_PARSER& aReader )
|
||||
{
|
||||
aReader.Skip( 5 );
|
||||
FileName = aReader.ReadWxString();
|
||||
@@ -124,23 +160,23 @@ ASCH_SYMBOL::ASCH_SYMBOL( const std::map<wxString, wxString>& aProps )
|
||||
{
|
||||
wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::COMPONENT );
|
||||
|
||||
currentpartid = ALTIUM_PARSER::ReadInt( aProps, "CURRENTPARTID", ALTIUM_COMPONENT_NONE );
|
||||
libreference = ALTIUM_PARSER::ReadString( aProps, "LIBREFERENCE", "" );
|
||||
sourcelibraryname = ALTIUM_PARSER::ReadString( aProps, "SOURCELIBRARYNAME", "" );
|
||||
componentdescription = ALTIUM_PARSER::ReadString( aProps, "COMPONENTDESCRIPTION", "" );
|
||||
currentpartid = ALTIUM_PROPS_UTILS::ReadInt( aProps, "CURRENTPARTID", ALTIUM_COMPONENT_NONE );
|
||||
libreference = ALTIUM_PROPS_UTILS::ReadString( aProps, "LIBREFERENCE", "" );
|
||||
sourcelibraryname = ALTIUM_PROPS_UTILS::ReadString( aProps, "SOURCELIBRARYNAME", "" );
|
||||
componentdescription = ALTIUM_PROPS_UTILS::ReadString( aProps, "COMPONENTDESCRIPTION", "" );
|
||||
|
||||
orientation = ALTIUM_PARSER::ReadInt( aProps, "ORIENTATION", 0 );
|
||||
isMirrored = ALTIUM_PARSER::ReadBool( aProps, "ISMIRRORED", false );
|
||||
orientation = ALTIUM_PROPS_UTILS::ReadInt( aProps, "ORIENTATION", 0 );
|
||||
isMirrored = ALTIUM_PROPS_UTILS::ReadBool( aProps, "ISMIRRORED", false );
|
||||
location = VECTOR2I( ReadKiCadUnitFrac( aProps, "LOCATION.X" ),
|
||||
-ReadKiCadUnitFrac( aProps, "LOCATION.Y" ) );
|
||||
|
||||
partcount = ALTIUM_PARSER::ReadInt( aProps, "PARTCOUNT", 0 );
|
||||
displaymodecount = ALTIUM_PARSER::ReadInt( aProps, "DISPLAYMODECOUNT", 0 );
|
||||
m_indexInSheet = ALTIUM_PARSER::ReadInt( aProps, "INDEXINSHEET", -1 );
|
||||
partcount = ALTIUM_PROPS_UTILS::ReadInt( aProps, "PARTCOUNT", 0 );
|
||||
displaymodecount = ALTIUM_PROPS_UTILS::ReadInt( aProps, "DISPLAYMODECOUNT", 0 );
|
||||
m_indexInSheet = ALTIUM_PROPS_UTILS::ReadInt( aProps, "INDEXINSHEET", -1 );
|
||||
|
||||
// DISPLAYMODE may be a string. Leave displaymode at 0 in this case.
|
||||
displaymode = 0;
|
||||
wxString displayModeStr = ALTIUM_PARSER::ReadString( aProps, "DISPLAYMODE", "" );
|
||||
wxString displayModeStr = ALTIUM_PROPS_UTILS::ReadString( aProps, "DISPLAYMODE", "" );
|
||||
|
||||
long v = 0;
|
||||
|
||||
@@ -154,7 +190,7 @@ ASCH_TEMPLATE::ASCH_TEMPLATE( const std::map<wxString, wxString>& aProps ) :
|
||||
{
|
||||
wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::TEMPLATE );
|
||||
|
||||
filename = ALTIUM_PARSER::ReadString( aProps, "FILENAME", "" );
|
||||
filename = ALTIUM_PROPS_UTILS::ReadString( aProps, "FILENAME", "" );
|
||||
}
|
||||
|
||||
|
||||
@@ -163,29 +199,29 @@ ASCH_PIN::ASCH_PIN( const std::map<wxString, wxString>& aProps ) :
|
||||
{
|
||||
wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::PIN );
|
||||
|
||||
isKiCadLibPin = ALTIUM_PARSER::ReadBool( aProps, "ISKICADLIBPIN", false );
|
||||
ownerpartdisplaymode = ALTIUM_PARSER::ReadInt( aProps, "OWNERPARTDISPLAYMODE", 0 );
|
||||
isKiCadLibPin = ALTIUM_PROPS_UTILS::ReadBool( aProps, "ISKICADLIBPIN", false );
|
||||
ownerpartdisplaymode = ALTIUM_PROPS_UTILS::ReadInt( aProps, "OWNERPARTDISPLAYMODE", 0 );
|
||||
|
||||
name = ALTIUM_PARSER::ReadString( aProps, "NAME", "" );
|
||||
text = ALTIUM_PARSER::ReadString( aProps, "TEXT", "" );
|
||||
designator = ALTIUM_PARSER::ReadString( aProps, "DESIGNATOR", "" );
|
||||
name = ALTIUM_PROPS_UTILS::ReadString( aProps, "NAME", "" );
|
||||
text = ALTIUM_PROPS_UTILS::ReadString( aProps, "TEXT", "" );
|
||||
designator = ALTIUM_PROPS_UTILS::ReadString( aProps, "DESIGNATOR", "" );
|
||||
|
||||
int symbolOuterInt = ALTIUM_PARSER::ReadInt( aProps, "SYMBOL_OUTER", 0 );
|
||||
int symbolOuterInt = ALTIUM_PROPS_UTILS::ReadInt( aProps, "SYMBOL_OUTER", 0 );
|
||||
symbolOuter = ASCH_PIN_SYMBOL::FromInt( symbolOuterInt );
|
||||
|
||||
int symbolInnerInt = ALTIUM_PARSER::ReadInt( aProps, "SYMBOL_INNER", 0 );
|
||||
int symbolInnerInt = ALTIUM_PROPS_UTILS::ReadInt( aProps, "SYMBOL_INNER", 0 );
|
||||
symbolInner = ASCH_PIN_SYMBOL::FromInt( symbolInnerInt );
|
||||
|
||||
int symbolOuterEdgeInt = ALTIUM_PARSER::ReadInt( aProps, "SYMBOL_OUTEREDGE", 0 );
|
||||
int symbolOuterEdgeInt = ALTIUM_PROPS_UTILS::ReadInt( aProps, "SYMBOL_OUTEREDGE", 0 );
|
||||
symbolOuterEdge = ASCH_PIN_SYMBOL::FromInt( symbolOuterEdgeInt );
|
||||
|
||||
int symbolInnerEdgeInt = ALTIUM_PARSER::ReadInt( aProps, "SYMBOL_INNEREDGE", 0 );
|
||||
int symbolInnerEdgeInt = ALTIUM_PROPS_UTILS::ReadInt( aProps, "SYMBOL_INNEREDGE", 0 );
|
||||
symbolInnerEdge = ASCH_PIN_SYMBOL::FromInt( symbolInnerEdgeInt );
|
||||
|
||||
electrical = ReadEnum<ASCH_PIN_ELECTRICAL>( aProps, "ELECTRICAL", 0, 7,
|
||||
ASCH_PIN_ELECTRICAL::INPUT );
|
||||
|
||||
int pinconglomerate = ALTIUM_PARSER::ReadInt( aProps, "PINCONGLOMERATE", 0 );
|
||||
int pinconglomerate = ALTIUM_PROPS_UTILS::ReadInt( aProps, "PINCONGLOMERATE", 0 );
|
||||
|
||||
orientation = static_cast<ASCH_RECORD_ORIENTATION>( pinconglomerate & 0x03 );
|
||||
hidden = ( pinconglomerate & 0x04 ) != 0;
|
||||
@@ -195,14 +231,14 @@ ASCH_PIN::ASCH_PIN( const std::map<wxString, wxString>& aProps ) :
|
||||
locked = ( pinconglomerate & 0x40 ) != 0;
|
||||
|
||||
|
||||
int x = ALTIUM_PARSER::ReadInt( aProps, "LOCATION.X", 0 );
|
||||
int xfrac = ALTIUM_PARSER::ReadInt( aProps, "LOCATION.X_FRAC", 0 );
|
||||
int y = ALTIUM_PARSER::ReadInt( aProps, "LOCATION.Y", 0 );
|
||||
int yfrac = ALTIUM_PARSER::ReadInt( aProps, "LOCATION.Y_FRAC", 0 );
|
||||
int x = ALTIUM_PROPS_UTILS::ReadInt( aProps, "LOCATION.X", 0 );
|
||||
int xfrac = ALTIUM_PROPS_UTILS::ReadInt( aProps, "LOCATION.X_FRAC", 0 );
|
||||
int y = ALTIUM_PROPS_UTILS::ReadInt( aProps, "LOCATION.Y", 0 );
|
||||
int yfrac = ALTIUM_PROPS_UTILS::ReadInt( aProps, "LOCATION.Y_FRAC", 0 );
|
||||
location = VECTOR2I( Altium2KiCadUnit( x, xfrac ), -Altium2KiCadUnit( y, yfrac ) );
|
||||
|
||||
int p = ALTIUM_PARSER::ReadInt( aProps, "PINLENGTH", 0 );
|
||||
int pfrac = ALTIUM_PARSER::ReadInt( aProps, "PINLENGTH_FRAC", 0 );
|
||||
int p = ALTIUM_PROPS_UTILS::ReadInt( aProps, "PINLENGTH", 0 );
|
||||
int pfrac = ALTIUM_PROPS_UTILS::ReadInt( aProps, "PINLENGTH_FRAC", 0 );
|
||||
pinlength = Altium2KiCadUnit( p, pfrac );
|
||||
|
||||
// this code calculates the location as required by KiCad without rounding error attached
|
||||
@@ -256,17 +292,17 @@ ASCH_OWNER_INTERFACE::ASCH_OWNER_INTERFACE( const std::map<wxString, wxString>&
|
||||
{
|
||||
ownerindex = ReadOwnerIndex( aProps );
|
||||
ownerpartid = ReadOwnerPartId( aProps );
|
||||
ownerpartdisplaymode = ALTIUM_PARSER::ReadInt( aProps, "OWNERPARTDISPLAYMODE", 0 );
|
||||
indexinsheet = ALTIUM_PARSER::ReadInt( aProps, "INDEXINSHEET", 0 );
|
||||
IsNotAccesible = ALTIUM_PARSER::ReadBool( aProps, "ISNOTACCESIBLE", false );
|
||||
ownerpartdisplaymode = ALTIUM_PROPS_UTILS::ReadInt( aProps, "OWNERPARTDISPLAYMODE", 0 );
|
||||
indexinsheet = ALTIUM_PROPS_UTILS::ReadInt( aProps, "INDEXINSHEET", 0 );
|
||||
IsNotAccesible = ALTIUM_PROPS_UTILS::ReadBool( aProps, "ISNOTACCESIBLE", false );
|
||||
}
|
||||
|
||||
|
||||
ASCH_FILL_INTERFACE::ASCH_FILL_INTERFACE( const std::map<wxString, wxString>& aProps )
|
||||
{
|
||||
AreaColor = ALTIUM_PARSER::ReadInt( aProps, "AREACOLOR", 0 );
|
||||
IsSolid = ALTIUM_PARSER::ReadBool( aProps, "ISSOLID", false );
|
||||
IsTransparent = ALTIUM_PARSER::ReadBool( aProps, "TRANSPARENT", false );
|
||||
AreaColor = ALTIUM_PROPS_UTILS::ReadInt( aProps, "AREACOLOR", 0 );
|
||||
IsSolid = ALTIUM_PROPS_UTILS::ReadBool( aProps, "ISSOLID", false );
|
||||
IsTransparent = ALTIUM_PROPS_UTILS::ReadBool( aProps, "TRANSPARENT", false );
|
||||
}
|
||||
|
||||
|
||||
@@ -279,7 +315,7 @@ ASCH_BORDER_INTERFACE::ASCH_BORDER_INTERFACE( const std::map<wxString, wxString>
|
||||
if( LineWidth == 0 )
|
||||
LineWidth = schIUScale.MilsToIU( 1 );
|
||||
|
||||
Color = ALTIUM_PARSER::ReadInt( aProps, "COLOR", 0 );
|
||||
Color = ALTIUM_PROPS_UTILS::ReadInt( aProps, "COLOR", 0 );
|
||||
}
|
||||
|
||||
|
||||
@@ -291,11 +327,11 @@ ASCH_LABEL::ASCH_LABEL( const std::map<wxString, wxString>& aProps ) :
|
||||
location = VECTOR2I( ReadKiCadUnitFrac( aProps, "LOCATION.X" ),
|
||||
-ReadKiCadUnitFrac( aProps, "LOCATION.Y" ) );
|
||||
|
||||
text = ALTIUM_PARSER::ReadString( aProps, "TEXT", "" );
|
||||
text = ALTIUM_PROPS_UTILS::ReadString( aProps, "TEXT", "" );
|
||||
|
||||
textColor = 0;
|
||||
fontId = ALTIUM_PARSER::ReadInt( aProps, "FONTID", 0 );
|
||||
isMirrored = ALTIUM_PARSER::ReadBool( aProps, "ISMIRRORED", false );
|
||||
fontId = ALTIUM_PROPS_UTILS::ReadInt( aProps, "FONTID", 0 );
|
||||
isMirrored = ALTIUM_PROPS_UTILS::ReadBool( aProps, "ISMIRRORED", false );
|
||||
|
||||
justification = ReadEnum<ASCH_LABEL_JUSTIFICATION>( aProps, "JUSTIFICATION", 0, 8,
|
||||
ASCH_LABEL_JUSTIFICATION::BOTTOM_LEFT );
|
||||
@@ -321,20 +357,20 @@ ASCH_TEXT_FRAME::ASCH_TEXT_FRAME( const std::map<wxString, wxString>& aProps ) :
|
||||
Size = VECTOR2I( ReadKiCadUnitFrac( aProps, "CORNER.X" ) - Location.x,
|
||||
-ReadKiCadUnitFrac( aProps, "CORNER.Y" ) - Location.y );
|
||||
|
||||
Text = ALTIUM_PARSER::ReadString( aProps, "TEXT", "" );
|
||||
Text = ALTIUM_PROPS_UTILS::ReadString( aProps, "TEXT", "" );
|
||||
Text.Replace( "~1", "\n", true );
|
||||
|
||||
FontID = ALTIUM_PARSER::ReadInt( aProps, "FONTID", 0 );
|
||||
IsWordWrapped = ALTIUM_PARSER::ReadBool( aProps, "WORDWRAP", false );
|
||||
ShowBorder = ALTIUM_PARSER::ReadBool( aProps, "SHOWBORDER", false );
|
||||
FontID = ALTIUM_PROPS_UTILS::ReadInt( aProps, "FONTID", 0 );
|
||||
IsWordWrapped = ALTIUM_PROPS_UTILS::ReadBool( aProps, "WORDWRAP", false );
|
||||
ShowBorder = ALTIUM_PROPS_UTILS::ReadBool( aProps, "SHOWBORDER", false );
|
||||
TextMargin = ReadKiCadUnitFrac( aProps, "TEXTMARGIN" );
|
||||
|
||||
AreaColor = ALTIUM_PARSER::ReadInt( aProps, "AREACOLOR", 0 );
|
||||
BorderColor = ALTIUM_PARSER::ReadInt( aProps, "COLOR", 0 );
|
||||
TextColor = ALTIUM_PARSER::ReadInt( aProps, "TEXTCOLOR", 0 );
|
||||
AreaColor = ALTIUM_PROPS_UTILS::ReadInt( aProps, "AREACOLOR", 0 );
|
||||
BorderColor = ALTIUM_PROPS_UTILS::ReadInt( aProps, "COLOR", 0 );
|
||||
TextColor = ALTIUM_PROPS_UTILS::ReadInt( aProps, "TEXTCOLOR", 0 );
|
||||
|
||||
BorderWidth = ReadKiCadUnitFrac( aProps, "LINEWIDTH" );
|
||||
isSolid = ALTIUM_PARSER::ReadBool( aProps, "ISSOLID", false );
|
||||
isSolid = ALTIUM_PROPS_UTILS::ReadBool( aProps, "ISSOLID", false );
|
||||
|
||||
Alignment = ReadEnum<ASCH_TEXT_FRAME_ALIGNMENT>( aProps, "ALIGNMENT", 1, 3,
|
||||
ASCH_TEXT_FRAME_ALIGNMENT::LEFT );
|
||||
@@ -346,7 +382,7 @@ ASCH_NOTE::ASCH_NOTE( const std::map<wxString, wxString>& aProperties ) :
|
||||
{
|
||||
wxASSERT( ReadRecord( aProperties ) == ALTIUM_SCH_RECORD::NOTE );
|
||||
|
||||
author = ALTIUM_PARSER::ReadString( aProperties, "AUTHOR", "" );
|
||||
author = ALTIUM_PROPS_UTILS::ReadString( aProperties, "AUTHOR", "" );
|
||||
}
|
||||
|
||||
|
||||
@@ -356,7 +392,7 @@ ASCH_BEZIER::ASCH_BEZIER( const std::map<wxString, wxString>& aProps ) :
|
||||
{
|
||||
wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::BEZIER );
|
||||
|
||||
int locationCount = ALTIUM_PARSER::ReadInt( aProps, "LOCATIONCOUNT", 0 );
|
||||
int locationCount = ALTIUM_PROPS_UTILS::ReadInt( aProps, "LOCATIONCOUNT", 0 );
|
||||
|
||||
for( int i = 1; i <= locationCount; i++ )
|
||||
{
|
||||
@@ -373,7 +409,7 @@ ASCH_POLYLINE::ASCH_POLYLINE( const std::map<wxString, wxString>& aProps ) :
|
||||
{
|
||||
wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::POLYLINE );
|
||||
|
||||
int locationCount = ALTIUM_PARSER::ReadInt( aProps, "LOCATIONCOUNT", 0 );
|
||||
int locationCount = ALTIUM_PROPS_UTILS::ReadInt( aProps, "LOCATIONCOUNT", 0 );
|
||||
|
||||
for( int i = 1; i <= locationCount; i++ )
|
||||
{
|
||||
@@ -394,7 +430,7 @@ ASCH_POLYGON::ASCH_POLYGON( const std::map<wxString, wxString>& aProps ) :
|
||||
{
|
||||
wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::POLYGON );
|
||||
|
||||
int locationCount = ALTIUM_PARSER::ReadInt( aProps, "LOCATIONCOUNT", 0 );
|
||||
int locationCount = ALTIUM_PROPS_UTILS::ReadInt( aProps, "LOCATIONCOUNT", 0 );
|
||||
|
||||
for( int i = 1; i <= locationCount; i++ )
|
||||
{
|
||||
@@ -437,8 +473,8 @@ ASCH_ARC::ASCH_ARC( const std::map<wxString, wxString>& aProps ) :
|
||||
if( m_IsElliptical )
|
||||
m_SecondaryRadius = ReadKiCadUnitFrac( aProps, "SECONDARYRADIUS" );
|
||||
|
||||
m_StartAngle = ALTIUM_PARSER::ReadDouble( aProps, "STARTANGLE", 0 );
|
||||
m_EndAngle = ALTIUM_PARSER::ReadDouble( aProps, "ENDANGLE", 0 );
|
||||
m_StartAngle = ALTIUM_PROPS_UTILS::ReadDouble( aProps, "STARTANGLE", 0 );
|
||||
m_EndAngle = ALTIUM_PROPS_UTILS::ReadDouble( aProps, "ENDANGLE", 0 );
|
||||
}
|
||||
|
||||
|
||||
@@ -479,7 +515,7 @@ ASCH_SIGNAL_HARNESS::ASCH_SIGNAL_HARNESS( const std::map<wxString, wxString>& aP
|
||||
wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::SIGNAL_HARNESS );
|
||||
|
||||
|
||||
int locationCount = ALTIUM_PARSER::ReadInt( aProps, "LOCATIONCOUNT", 0 );
|
||||
int locationCount = ALTIUM_PROPS_UTILS::ReadInt( aProps, "LOCATIONCOUNT", 0 );
|
||||
|
||||
for( int i = 1; i <= locationCount; i++ )
|
||||
{
|
||||
@@ -488,7 +524,7 @@ ASCH_SIGNAL_HARNESS::ASCH_SIGNAL_HARNESS( const std::map<wxString, wxString>& aP
|
||||
-ReadKiCadUnitFrac( aProps, "Y" + si ) );
|
||||
}
|
||||
|
||||
Color = ALTIUM_PARSER::ReadInt( aProps, "COLOR", 0 );
|
||||
Color = ALTIUM_PROPS_UTILS::ReadInt( aProps, "COLOR", 0 );
|
||||
LineWidth = ReadKiCadUnitFrac( aProps, "LINEWIDTH" );
|
||||
}
|
||||
|
||||
@@ -503,8 +539,8 @@ ASCH_HARNESS_CONNECTOR::ASCH_HARNESS_CONNECTOR( const std::map<wxString, wxStrin
|
||||
-ReadKiCadUnitFrac( aProps, "LOCATION.Y" ) );
|
||||
Size = VECTOR2I( ReadKiCadUnitFrac( aProps, "XSIZE" ), ReadKiCadUnitFrac( aProps, "YSIZE" ) );
|
||||
|
||||
Color = ALTIUM_PARSER::ReadInt( aProps, "COLOR", 0 );
|
||||
AreaColor = ALTIUM_PARSER::ReadInt( aProps, "AREACOLOR", 0 );
|
||||
Color = ALTIUM_PROPS_UTILS::ReadInt( aProps, "COLOR", 0 );
|
||||
AreaColor = ALTIUM_PROPS_UTILS::ReadInt( aProps, "AREACOLOR", 0 );
|
||||
|
||||
indexinsheet = 0;
|
||||
LineWidth = 0;;
|
||||
@@ -526,14 +562,14 @@ ASCH_HARNESS_ENTRY::ASCH_HARNESS_ENTRY( const std::map<wxString, wxString>& aPro
|
||||
|
||||
Side = ReadEnum<ASCH_SHEET_ENTRY_SIDE>( aProps, "SIDE", 0, 3, ASCH_SHEET_ENTRY_SIDE::LEFT );
|
||||
|
||||
Name = ALTIUM_PARSER::ReadString( aProps, "NAME", "" );
|
||||
Name = ALTIUM_PROPS_UTILS::ReadString( aProps, "NAME", "" );
|
||||
|
||||
OwnerIndexAdditionalList = ALTIUM_PARSER::ReadBool( aProps, "OWNERINDEXADDITIONALLIST", true );
|
||||
OwnerIndexAdditionalList = ALTIUM_PROPS_UTILS::ReadBool( aProps, "OWNERINDEXADDITIONALLIST", true );
|
||||
|
||||
Color = ALTIUM_PARSER::ReadInt( aProps, "COLOR", 0 );
|
||||
AreaColor = ALTIUM_PARSER::ReadInt( aProps, "AREACOLOR", 0 );
|
||||
TextColor = ALTIUM_PARSER::ReadInt( aProps, "TEXTCOLOR", 0 );
|
||||
TextFontID = ALTIUM_PARSER::ReadInt( aProps, "TEXTFONTID", 0 );
|
||||
Color = ALTIUM_PROPS_UTILS::ReadInt( aProps, "COLOR", 0 );
|
||||
AreaColor = ALTIUM_PROPS_UTILS::ReadInt( aProps, "AREACOLOR", 0 );
|
||||
TextColor = ALTIUM_PROPS_UTILS::ReadInt( aProps, "TEXTCOLOR", 0 );
|
||||
TextFontID = ALTIUM_PROPS_UTILS::ReadInt( aProps, "TEXTFONTID", 0 );
|
||||
TextStyle = 0;
|
||||
}
|
||||
|
||||
@@ -545,16 +581,16 @@ ASCH_HARNESS_TYPE::ASCH_HARNESS_TYPE( const std::map<wxString, wxString>& aProps
|
||||
|
||||
//ownerindex = ReadOwnerIndex( aProps ); // use SCH_IO_ALTIUM::m_harnessEntryParent instead!
|
||||
|
||||
Text = ALTIUM_PARSER::ReadString( aProps, "TEXT", "" );
|
||||
Text = ALTIUM_PROPS_UTILS::ReadString( aProps, "TEXT", "" );
|
||||
|
||||
Location = VECTOR2I( ReadKiCadUnitFrac( aProps, "LOCATION.X" ),
|
||||
-ReadKiCadUnitFrac( aProps, "LOCATION.Y" ) );
|
||||
|
||||
IsHidden = ALTIUM_PARSER::ReadBool( aProps, "ISHIDDEN", false );
|
||||
OwnerIndexAdditionalList = ALTIUM_PARSER::ReadBool( aProps, "OWNERINDEXADDITIONALLIST", true );
|
||||
IsHidden = ALTIUM_PROPS_UTILS::ReadBool( aProps, "ISHIDDEN", false );
|
||||
OwnerIndexAdditionalList = ALTIUM_PROPS_UTILS::ReadBool( aProps, "OWNERINDEXADDITIONALLIST", true );
|
||||
|
||||
Color = ALTIUM_PARSER::ReadInt( aProps, "COLOR", 0 );
|
||||
FontID = ALTIUM_PARSER::ReadInt( aProps, "TEXTFONTID", 0 );
|
||||
Color = ALTIUM_PROPS_UTILS::ReadInt( aProps, "COLOR", 0 );
|
||||
FontID = ALTIUM_PROPS_UTILS::ReadInt( aProps, "TEXTFONTID", 0 );
|
||||
}
|
||||
|
||||
|
||||
@@ -583,10 +619,10 @@ ASCH_SHEET_SYMBOL::ASCH_SHEET_SYMBOL( const std::map<wxString, wxString>& aProps
|
||||
size = VECTOR2I( ReadKiCadUnitFrac( aProps, "XSIZE" ),
|
||||
ReadKiCadUnitFrac( aProps, "YSIZE" ) );
|
||||
|
||||
isSolid = ALTIUM_PARSER::ReadBool( aProps, "ISSOLID", false );
|
||||
isSolid = ALTIUM_PROPS_UTILS::ReadBool( aProps, "ISSOLID", false );
|
||||
|
||||
color = ALTIUM_PARSER::ReadInt( aProps, "COLOR", 0 );
|
||||
areacolor = ALTIUM_PARSER::ReadInt( aProps, "AREACOLOR", 0 );
|
||||
color = ALTIUM_PROPS_UTILS::ReadInt( aProps, "COLOR", 0 );
|
||||
areacolor = ALTIUM_PROPS_UTILS::ReadInt( aProps, "AREACOLOR", 0 );
|
||||
}
|
||||
|
||||
|
||||
@@ -600,7 +636,7 @@ ASCH_SHEET_ENTRY::ASCH_SHEET_ENTRY( const std::map<wxString, wxString>& aProps )
|
||||
|
||||
side = ReadEnum<ASCH_SHEET_ENTRY_SIDE>( aProps, "SIDE", 0, 3, ASCH_SHEET_ENTRY_SIDE::LEFT );
|
||||
|
||||
name = ALTIUM_PARSER::ReadString( aProps, "NAME", "" );
|
||||
name = ALTIUM_PROPS_UTILS::ReadString( aProps, "NAME", "" );
|
||||
|
||||
iotype = ReadEnum<ASCH_PORT_IOTYPE>( aProps, "IOTYPE", 0, 3, ASCH_PORT_IOTYPE::UNSPECIFIED );
|
||||
style = ReadEnum<ASCH_PORT_STYLE>( aProps, "STYLE", 0, 7, ASCH_PORT_STYLE::NONE_HORIZONTAL );
|
||||
@@ -619,8 +655,8 @@ ASCH_POWER_PORT::ASCH_POWER_PORT( const std::map<wxString, wxString>& aProps ) :
|
||||
orientation = ReadEnum<ASCH_RECORD_ORIENTATION>( aProps, "ORIENTATION", 0, 3,
|
||||
ASCH_RECORD_ORIENTATION::RIGHTWARDS );
|
||||
|
||||
text = ALTIUM_PARSER::ReadString( aProps, "TEXT", "" );
|
||||
showNetName = ALTIUM_PARSER::ReadBool( aProps, "SHOWNETNAME", true );
|
||||
text = ALTIUM_PROPS_UTILS::ReadString( aProps, "TEXT", "" );
|
||||
showNetName = ALTIUM_PROPS_UTILS::ReadBool( aProps, "SHOWNETNAME", true );
|
||||
|
||||
style = ReadEnum<ASCH_POWER_PORT_STYLE>( aProps, "STYLE", 0, 10,
|
||||
ASCH_POWER_PORT_STYLE::CIRCLE );
|
||||
@@ -636,8 +672,8 @@ ASCH_PORT::ASCH_PORT( const std::map<wxString, wxString>& aProps ) :
|
||||
Location = VECTOR2I( ReadKiCadUnitFrac( aProps, "LOCATION.X" ),
|
||||
-ReadKiCadUnitFrac( aProps, "LOCATION.Y" ) );
|
||||
|
||||
Name = ALTIUM_PARSER::ReadString( aProps, "NAME", "" );
|
||||
HarnessType = ALTIUM_PARSER::ReadString( aProps, "HARNESSTYPE", "" );
|
||||
Name = ALTIUM_PROPS_UTILS::ReadString( aProps, "NAME", "" );
|
||||
HarnessType = ALTIUM_PROPS_UTILS::ReadString( aProps, "HARNESSTYPE", "" );
|
||||
|
||||
Width = ReadKiCadUnitFrac( aProps, "WIDTH" );
|
||||
Height = ReadKiCadUnitFrac( aProps, "HEIGHT" );
|
||||
@@ -645,10 +681,10 @@ ASCH_PORT::ASCH_PORT( const std::map<wxString, wxString>& aProps ) :
|
||||
IOtype = ReadEnum<ASCH_PORT_IOTYPE>( aProps, "IOTYPE", 0, 3, ASCH_PORT_IOTYPE::UNSPECIFIED );
|
||||
Style = ReadEnum<ASCH_PORT_STYLE>( aProps, "STYLE", 0, 7, ASCH_PORT_STYLE::NONE_HORIZONTAL );
|
||||
|
||||
AreaColor = ALTIUM_PARSER::ReadInt( aProps, "AREACOLOR", 0 );
|
||||
Color = ALTIUM_PARSER::ReadInt( aProps, "COLOR", 0 );
|
||||
FontID = ALTIUM_PARSER::ReadInt( aProps, "TEXTFONTID", 0 );
|
||||
TextColor = ALTIUM_PARSER::ReadInt( aProps, "TEXTCOLOR", 0 );
|
||||
AreaColor = ALTIUM_PROPS_UTILS::ReadInt( aProps, "AREACOLOR", 0 );
|
||||
Color = ALTIUM_PROPS_UTILS::ReadInt( aProps, "COLOR", 0 );
|
||||
FontID = ALTIUM_PROPS_UTILS::ReadInt( aProps, "TEXTFONTID", 0 );
|
||||
TextColor = ALTIUM_PROPS_UTILS::ReadInt( aProps, "TEXTCOLOR", 0 );
|
||||
|
||||
Alignment = ReadEnum<ASCH_TEXT_FRAME_ALIGNMENT>( aProps, "ALIGNMENT", 1, 3,
|
||||
ASCH_TEXT_FRAME_ALIGNMENT::LEFT );
|
||||
@@ -662,8 +698,8 @@ ASCH_NO_ERC::ASCH_NO_ERC( const std::map<wxString, wxString>& aProps )
|
||||
location = VECTOR2I( ReadKiCadUnitFrac( aProps, "LOCATION.X" ),
|
||||
-ReadKiCadUnitFrac( aProps, "LOCATION.Y" ) );
|
||||
|
||||
isActive = ALTIUM_PARSER::ReadBool( aProps, "ISACTIVE", true );
|
||||
suppressAll = ALTIUM_PARSER::ReadInt( aProps, "SUPPRESSALL", true );
|
||||
isActive = ALTIUM_PROPS_UTILS::ReadBool( aProps, "ISACTIVE", true );
|
||||
suppressAll = ALTIUM_PROPS_UTILS::ReadInt( aProps, "SUPPRESSALL", true );
|
||||
}
|
||||
|
||||
|
||||
@@ -672,7 +708,7 @@ ASCH_NET_LABEL::ASCH_NET_LABEL( const std::map<wxString, wxString>& aProps ) :
|
||||
{
|
||||
wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::NET_LABEL );
|
||||
|
||||
text = ALTIUM_PARSER::ReadString( aProps, "TEXT", "" );
|
||||
text = ALTIUM_PROPS_UTILS::ReadString( aProps, "TEXT", "" );
|
||||
|
||||
location = VECTOR2I( ReadKiCadUnitFrac( aProps, "LOCATION.X" ),
|
||||
-ReadKiCadUnitFrac( aProps, "LOCATION.Y" ) );
|
||||
@@ -690,7 +726,7 @@ ASCH_BUS::ASCH_BUS( const std::map<wxString, wxString>& aProps ) :
|
||||
{
|
||||
wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::BUS );
|
||||
|
||||
int locationcount = ALTIUM_PARSER::ReadInt( aProps, "LOCATIONCOUNT", 0 );
|
||||
int locationcount = ALTIUM_PROPS_UTILS::ReadInt( aProps, "LOCATIONCOUNT", 0 );
|
||||
|
||||
for( int i = 1; i <= locationcount; i++ )
|
||||
{
|
||||
@@ -708,7 +744,7 @@ ASCH_WIRE::ASCH_WIRE( const std::map<wxString, wxString>& aProps ) :
|
||||
{
|
||||
wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::WIRE );
|
||||
|
||||
int locationcount = ALTIUM_PARSER::ReadInt( aProps, "LOCATIONCOUNT", 0 );
|
||||
int locationcount = ALTIUM_PROPS_UTILS::ReadInt( aProps, "LOCATIONCOUNT", 0 );
|
||||
|
||||
for( int i = 1; i <= locationcount; i++ )
|
||||
{
|
||||
@@ -738,15 +774,15 @@ ASCH_IMAGE::ASCH_IMAGE( const std::map<wxString, wxString>& aProps ) :
|
||||
{
|
||||
wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::IMAGE );
|
||||
|
||||
filename = ALTIUM_PARSER::ReadString( aProps, "FILENAME", "" );
|
||||
filename = ALTIUM_PROPS_UTILS::ReadString( aProps, "FILENAME", "" );
|
||||
|
||||
location = VECTOR2I( ReadKiCadUnitFrac( aProps, "LOCATION.X" ),
|
||||
-ReadKiCadUnitFrac( aProps, "LOCATION.Y" ) );
|
||||
corner = VECTOR2I( ReadKiCadUnitFrac( aProps, "CORNER.X" ),
|
||||
-ReadKiCadUnitFrac( aProps, "CORNER.Y" ) );
|
||||
|
||||
embedimage = ALTIUM_PARSER::ReadBool( aProps, "EMBEDIMAGE", false );
|
||||
keepaspect = ALTIUM_PARSER::ReadBool( aProps, "KEEPASPECT", false );
|
||||
embedimage = ALTIUM_PROPS_UTILS::ReadBool( aProps, "EMBEDIMAGE", false );
|
||||
keepaspect = ALTIUM_PROPS_UTILS::ReadBool( aProps, "KEEPASPECT", false );
|
||||
}
|
||||
|
||||
|
||||
@@ -757,16 +793,16 @@ ASCH_SHEET_FONT::ASCH_SHEET_FONT( const std::map<wxString, wxString>& aProps, in
|
||||
|
||||
const wxString sid = std::to_string( aId );
|
||||
|
||||
FontName = ALTIUM_PARSER::ReadString( aProps, "FONTNAME" + sid, "" );
|
||||
FontName = ALTIUM_PROPS_UTILS::ReadString( aProps, "FONTNAME" + sid, "" );
|
||||
|
||||
Size = ReadKiCadUnitFrac( aProps, "SIZE" + sid );
|
||||
Rotation = ALTIUM_PARSER::ReadInt( aProps, "ROTATION" + sid, 0 );
|
||||
Rotation = ALTIUM_PROPS_UTILS::ReadInt( aProps, "ROTATION" + sid, 0 );
|
||||
|
||||
Italic = ALTIUM_PARSER::ReadBool( aProps, "ITALIC" + sid, false );
|
||||
Bold = ALTIUM_PARSER::ReadBool( aProps, "BOLD" + sid, false );
|
||||
Underline = ALTIUM_PARSER::ReadBool( aProps, "UNDERLINE" + sid, false );
|
||||
Italic = ALTIUM_PROPS_UTILS::ReadBool( aProps, "ITALIC" + sid, false );
|
||||
Bold = ALTIUM_PROPS_UTILS::ReadBool( aProps, "BOLD" + sid, false );
|
||||
Underline = ALTIUM_PROPS_UTILS::ReadBool( aProps, "UNDERLINE" + sid, false );
|
||||
|
||||
AreaColor = ALTIUM_PARSER::ReadInt( aProps, "AREACOLOR" + sid, 0 );
|
||||
AreaColor = ALTIUM_PROPS_UTILS::ReadInt( aProps, "AREACOLOR" + sid, 0 );
|
||||
}
|
||||
|
||||
|
||||
@@ -803,12 +839,12 @@ ASCH_SHEET::ASCH_SHEET( const std::map<wxString, wxString>& aProps ) :
|
||||
{
|
||||
wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::SHEET );
|
||||
|
||||
int fontidcount = ALTIUM_PARSER::ReadInt( aProps, "FONTIDCOUNT", 0 );
|
||||
int fontidcount = ALTIUM_PROPS_UTILS::ReadInt( aProps, "FONTIDCOUNT", 0 );
|
||||
|
||||
for( int i = 1; i <= fontidcount; i++ )
|
||||
fonts.emplace_back( aProps, i );
|
||||
|
||||
useCustomSheet = ALTIUM_PARSER::ReadBool( aProps, "USECUSTOMSHEET", false );
|
||||
useCustomSheet = ALTIUM_PROPS_UTILS::ReadBool( aProps, "USECUSTOMSHEET", false );
|
||||
|
||||
customSize = VECTOR2I( ReadKiCadUnitFrac( aProps, "CUSTOMX" ),
|
||||
ReadKiCadUnitFrac( aProps, "CUSTOMY" ) );
|
||||
@@ -824,7 +860,7 @@ ASCH_SHEET_NAME::ASCH_SHEET_NAME( const std::map<wxString, wxString>& aProps ) :
|
||||
{
|
||||
wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::SHEET_NAME );
|
||||
|
||||
text = ALTIUM_PARSER::ReadString( aProps, "TEXT", "" );
|
||||
text = ALTIUM_PROPS_UTILS::ReadString( aProps, "TEXT", "" );
|
||||
|
||||
orientation = ReadEnum<ASCH_RECORD_ORIENTATION>( aProps, "ORIENTATION", 0, 3,
|
||||
ASCH_RECORD_ORIENTATION::RIGHTWARDS );
|
||||
@@ -832,7 +868,7 @@ ASCH_SHEET_NAME::ASCH_SHEET_NAME( const std::map<wxString, wxString>& aProps ) :
|
||||
location = VECTOR2I( ReadKiCadUnitFrac( aProps, "LOCATION.X" ),
|
||||
-ReadKiCadUnitFrac( aProps, "LOCATION.Y" ) );
|
||||
|
||||
isHidden = ALTIUM_PARSER::ReadBool( aProps, "ISHIDDEN", false );
|
||||
isHidden = ALTIUM_PROPS_UTILS::ReadBool( aProps, "ISHIDDEN", false );
|
||||
}
|
||||
|
||||
|
||||
@@ -841,7 +877,7 @@ ASCH_FILE_NAME::ASCH_FILE_NAME( const std::map<wxString, wxString>& aProps ) :
|
||||
{
|
||||
wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::FILE_NAME );
|
||||
|
||||
text = ALTIUM_PARSER::ReadString( aProps, "TEXT", "" );
|
||||
text = ALTIUM_PROPS_UTILS::ReadString( aProps, "TEXT", "" );
|
||||
|
||||
orientation = ReadEnum<ASCH_RECORD_ORIENTATION>( aProps, "ORIENTATION", 0, 3,
|
||||
ASCH_RECORD_ORIENTATION::RIGHTWARDS );
|
||||
@@ -849,7 +885,7 @@ ASCH_FILE_NAME::ASCH_FILE_NAME( const std::map<wxString, wxString>& aProps ) :
|
||||
location = VECTOR2I( ReadKiCadUnitFrac( aProps, "LOCATION.X" ),
|
||||
-ReadKiCadUnitFrac( aProps, "LOCATION.Y" ) );
|
||||
|
||||
isHidden = ALTIUM_PARSER::ReadBool( aProps, "ISHIDDEN", false );
|
||||
isHidden = ALTIUM_PROPS_UTILS::ReadBool( aProps, "ISHIDDEN", false );
|
||||
}
|
||||
|
||||
|
||||
@@ -858,9 +894,9 @@ ASCH_DESIGNATOR::ASCH_DESIGNATOR( const std::map<wxString, wxString>& aProps ) :
|
||||
{
|
||||
wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::DESIGNATOR );
|
||||
|
||||
name = ALTIUM_PARSER::ReadString( aProps, "NAME", "" );
|
||||
text = ALTIUM_PARSER::ReadString( aProps, "TEXT", "" );
|
||||
fontId = ALTIUM_PARSER::ReadInt( aProps, "FONTID", 0 );
|
||||
name = ALTIUM_PROPS_UTILS::ReadString( aProps, "NAME", "" );
|
||||
text = ALTIUM_PROPS_UTILS::ReadString( aProps, "TEXT", "" );
|
||||
fontId = ALTIUM_PROPS_UTILS::ReadInt( aProps, "FONTID", 0 );
|
||||
|
||||
justification = ReadEnum<ASCH_LABEL_JUSTIFICATION>( aProps, "JUSTIFICATION", 0, 8,
|
||||
ASCH_LABEL_JUSTIFICATION::BOTTOM_LEFT );
|
||||
@@ -878,12 +914,12 @@ ASCH_IMPLEMENTATION::ASCH_IMPLEMENTATION( const std::map<wxString, wxString>& aP
|
||||
{
|
||||
wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::IMPLEMENTATION );
|
||||
|
||||
ownerindex = ALTIUM_PARSER::ReadInt( aProps, "OWNERINDEX", ALTIUM_COMPONENT_NONE );
|
||||
name = ALTIUM_PARSER::ReadString( aProps, "MODELNAME", "" );
|
||||
type = ALTIUM_PARSER::ReadString( aProps, "MODELTYPE", "" );
|
||||
libname = ALTIUM_PARSER::ReadString( aProps, "MODELDATAFILE0", "" );
|
||||
description = ALTIUM_PARSER::ReadString( aProps, "DESCRIPTION", "" );
|
||||
isCurrent = ALTIUM_PARSER::ReadBool( aProps, "ISCURRENT", false );
|
||||
ownerindex = ALTIUM_PROPS_UTILS::ReadInt( aProps, "OWNERINDEX", ALTIUM_COMPONENT_NONE );
|
||||
name = ALTIUM_PROPS_UTILS::ReadString( aProps, "MODELNAME", "" );
|
||||
type = ALTIUM_PROPS_UTILS::ReadString( aProps, "MODELTYPE", "" );
|
||||
libname = ALTIUM_PROPS_UTILS::ReadString( aProps, "MODELDATAFILE0", "" );
|
||||
description = ALTIUM_PROPS_UTILS::ReadString( aProps, "DESCRIPTION", "" );
|
||||
isCurrent = ALTIUM_PROPS_UTILS::ReadBool( aProps, "ISCURRENT", false );
|
||||
}
|
||||
|
||||
|
||||
@@ -920,14 +956,14 @@ ASCH_PARAMETER::ASCH_PARAMETER( const std::map<wxString, wxString>& aProps ) :
|
||||
orientation = ReadEnum<ASCH_RECORD_ORIENTATION>( aProps, "ORIENTATION", 0, 3,
|
||||
ASCH_RECORD_ORIENTATION::RIGHTWARDS );
|
||||
|
||||
name = ALTIUM_PARSER::ReadString( aProps, "NAME", "" );
|
||||
text = ALTIUM_PARSER::ReadString( aProps, "TEXT", "" );
|
||||
name = ALTIUM_PROPS_UTILS::ReadString( aProps, "NAME", "" );
|
||||
text = ALTIUM_PROPS_UTILS::ReadString( aProps, "TEXT", "" );
|
||||
|
||||
isHidden = ALTIUM_PARSER::ReadBool( aProps, "ISHIDDEN", false );
|
||||
isMirrored = ALTIUM_PARSER::ReadBool( aProps, "ISMIRRORED", false );
|
||||
isShowName = ALTIUM_PARSER::ReadBool( aProps, "SHOWNAME", false );
|
||||
isHidden = ALTIUM_PROPS_UTILS::ReadBool( aProps, "ISHIDDEN", false );
|
||||
isMirrored = ALTIUM_PROPS_UTILS::ReadBool( aProps, "ISMIRRORED", false );
|
||||
isShowName = ALTIUM_PROPS_UTILS::ReadBool( aProps, "SHOWNAME", false );
|
||||
|
||||
fontId = ALTIUM_PARSER::ReadInt( aProps, "FONTID", 0 );
|
||||
fontId = ALTIUM_PROPS_UTILS::ReadInt( aProps, "FONTID", 0 );
|
||||
}
|
||||
|
||||
|
||||
@@ -936,5 +972,5 @@ ASCH_HYPERLINK::ASCH_HYPERLINK( const std::map<wxString, wxString>& aProps ) :
|
||||
{
|
||||
wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::HYPERLINK );
|
||||
|
||||
url = ALTIUM_PARSER::ReadString( aProps, "URL", "" );
|
||||
url = ALTIUM_PROPS_UTILS::ReadString( aProps, "URL", "" );
|
||||
}
|
||||
@@ -36,14 +36,15 @@
|
||||
// this constant specifies a item which is not inside an component
|
||||
const int ALTIUM_COMPONENT_NONE = -1;
|
||||
|
||||
class ALTIUM_PARSER;
|
||||
class ALTIUM_BINARY_PARSER;
|
||||
|
||||
struct ASCH_STORAGE_FILE
|
||||
{
|
||||
wxString filename;
|
||||
std::vector<char> data;
|
||||
|
||||
explicit ASCH_STORAGE_FILE( ALTIUM_PARSER& aReader );
|
||||
explicit ASCH_STORAGE_FILE( const std::map<wxString, wxString>& aProps );
|
||||
explicit ASCH_STORAGE_FILE( ALTIUM_BINARY_PARSER& aReader );
|
||||
};
|
||||
|
||||
struct ASCH_ADDITIONAL_FILE
|
||||
@@ -51,7 +52,7 @@ struct ASCH_ADDITIONAL_FILE
|
||||
wxString FileName;
|
||||
std::vector<char> Data;
|
||||
|
||||
explicit ASCH_ADDITIONAL_FILE( ALTIUM_PARSER& aReader );
|
||||
explicit ASCH_ADDITIONAL_FILE( ALTIUM_BINARY_PARSER& aReader );
|
||||
};
|
||||
|
||||
enum class ALTIUM_SCH_RECORD
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
#include "altium_parser_sch.h"
|
||||
#include "sch_shape.h"
|
||||
#include <io/io_utils.h>
|
||||
#include <io/altium/altium_parser.h>
|
||||
#include <io/altium/altium_binary_parser.h>
|
||||
#include <io/altium/altium_ascii_parser.h>
|
||||
#include <io/altium/altium_parser_utils.h>
|
||||
#include <sch_io/altium/sch_io_altium.h>
|
||||
|
||||
@@ -65,6 +66,7 @@
|
||||
#include <wx/zstream.h>
|
||||
#include <wx/wfstream.h>
|
||||
#include <magic_enum.hpp>
|
||||
#include "sch_io_altium.h"
|
||||
|
||||
// Harness port object itself does not contain color information about itself
|
||||
// It seems altium is drawing harness ports using these colors
|
||||
@@ -242,13 +244,26 @@ int SCH_IO_ALTIUM::GetModifyHash() const
|
||||
}
|
||||
|
||||
|
||||
bool SCH_IO_ALTIUM::checkFileHeader( const wxString& aFileName )
|
||||
bool SCH_IO_ALTIUM::isBinaryFile( const wxString& aFileName )
|
||||
{
|
||||
// Compound File Binary Format header
|
||||
return IO_UTILS::fileStartsWithBinaryHeader( aFileName, IO_UTILS::COMPOUND_FILE_HEADER );
|
||||
}
|
||||
|
||||
|
||||
bool SCH_IO_ALTIUM::isASCIIFile( const wxString& aFileName )
|
||||
{
|
||||
// ASCII file format
|
||||
return IO_UTILS::fileStartsWithPrefix( aFileName, wxS( "|HEADER=" ), false );
|
||||
}
|
||||
|
||||
|
||||
bool SCH_IO_ALTIUM::checkFileHeader( const wxString& aFileName )
|
||||
{
|
||||
return isBinaryFile( aFileName ) || isASCIIFile( aFileName );
|
||||
}
|
||||
|
||||
|
||||
bool SCH_IO_ALTIUM::CanReadSchematicFile( const wxString& aFileName ) const
|
||||
{
|
||||
if( !SCH_IO::CanReadSchematicFile( aFileName ) )
|
||||
@@ -441,27 +456,34 @@ SCH_SHEET* SCH_IO_ALTIUM::getCurrentSheet()
|
||||
|
||||
void SCH_IO_ALTIUM::ParseAltiumSch( const wxString& aFileName )
|
||||
{
|
||||
ALTIUM_COMPOUND_FILE altiumSchFile( aFileName );
|
||||
|
||||
// Load path may be different from the project path.
|
||||
wxFileName parentFileName = aFileName;
|
||||
|
||||
try
|
||||
if( isBinaryFile( aFileName ) )
|
||||
{
|
||||
ParseStorage( altiumSchFile ); // we need this before parsing the FileHeader
|
||||
ParseFileHeader( altiumSchFile );
|
||||
ALTIUM_COMPOUND_FILE altiumSchFile( aFileName );
|
||||
|
||||
// Parse "Additional" because sheet is set up during "FileHeader" parsing.
|
||||
ParseAdditional( altiumSchFile );
|
||||
try
|
||||
{
|
||||
ParseStorage( altiumSchFile ); // we need this before parsing the FileHeader
|
||||
ParseFileHeader( altiumSchFile );
|
||||
|
||||
// Parse "Additional" because sheet is set up during "FileHeader" parsing.
|
||||
ParseAdditional( altiumSchFile );
|
||||
}
|
||||
catch( const CFB::CFBException& exception )
|
||||
{
|
||||
THROW_IO_ERROR( exception.what() );
|
||||
}
|
||||
catch( const std::exception& exc )
|
||||
{
|
||||
wxLogDebug( wxT( "Unhandled exception in Altium schematic parsers: %s." ), exc.what() );
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch( const CFB::CFBException& exception )
|
||||
else // ASCII
|
||||
{
|
||||
THROW_IO_ERROR( exception.what() );
|
||||
}
|
||||
catch( const std::exception& exc )
|
||||
{
|
||||
wxLogDebug( wxT( "Unhandled exception in Altium schematic parsers: %s." ), exc.what() );
|
||||
throw;
|
||||
ParseASCIISchematic( aFileName );
|
||||
}
|
||||
|
||||
SCH_SCREEN* currentScreen = getCurrentScreen();
|
||||
@@ -550,11 +572,11 @@ void SCH_IO_ALTIUM::ParseStorage( const ALTIUM_COMPOUND_FILE& aAltiumSchFile )
|
||||
if( file == nullptr )
|
||||
return;
|
||||
|
||||
ALTIUM_PARSER reader( aAltiumSchFile, file );
|
||||
ALTIUM_BINARY_PARSER reader( aAltiumSchFile, file );
|
||||
|
||||
std::map<wxString, wxString> properties = reader.ReadProperties();
|
||||
wxString header = ALTIUM_PARSER::ReadString( properties, "HEADER", "" );
|
||||
int weight = ALTIUM_PARSER::ReadInt( properties, "WEIGHT", 0 );
|
||||
wxString header = ALTIUM_PROPS_UTILS::ReadString( properties, "HEADER", "" );
|
||||
int weight = ALTIUM_PROPS_UTILS::ReadInt( properties, "WEIGHT", 0 );
|
||||
|
||||
if( weight < 0 )
|
||||
THROW_IO_ERROR( "Storage weight is negative!" );
|
||||
@@ -579,13 +601,15 @@ void SCH_IO_ALTIUM::ParseStorage( const ALTIUM_COMPOUND_FILE& aAltiumSchFile )
|
||||
|
||||
void SCH_IO_ALTIUM::ParseAdditional( const ALTIUM_COMPOUND_FILE& aAltiumSchFile )
|
||||
{
|
||||
const CFB::COMPOUND_FILE_ENTRY* file = aAltiumSchFile.FindStream( { "Additional" } );
|
||||
wxString streamName = wxS( "Additional" );
|
||||
|
||||
const CFB::COMPOUND_FILE_ENTRY* file =
|
||||
aAltiumSchFile.FindStream( { streamName.ToStdString() } );
|
||||
|
||||
if( file == nullptr )
|
||||
return;
|
||||
|
||||
ALTIUM_PARSER reader( aAltiumSchFile, file );
|
||||
|
||||
ALTIUM_BINARY_PARSER reader( aAltiumSchFile, file );
|
||||
|
||||
if( reader.GetRemainingBytes() <= 0 )
|
||||
{
|
||||
@@ -595,7 +619,7 @@ void SCH_IO_ALTIUM::ParseAdditional( const ALTIUM_COMPOUND_FILE& aAltiumSchFile
|
||||
{
|
||||
std::map<wxString, wxString> properties = reader.ReadProperties();
|
||||
|
||||
int recordId = ALTIUM_PARSER::ReadInt( properties, "RECORD", 0 );
|
||||
int recordId = ALTIUM_PROPS_UTILS::ReadInt( properties, "RECORD", 0 );
|
||||
ALTIUM_SCH_RECORD record = static_cast<ALTIUM_SCH_RECORD>( recordId );
|
||||
|
||||
if( record != ALTIUM_SCH_RECORD::HEADER )
|
||||
@@ -606,39 +630,7 @@ void SCH_IO_ALTIUM::ParseAdditional( const ALTIUM_COMPOUND_FILE& aAltiumSchFile
|
||||
{
|
||||
std::map<wxString, wxString> properties = reader.ReadProperties();
|
||||
|
||||
int recordId = ALTIUM_PARSER::ReadInt( properties, "RECORD", 0 );
|
||||
ALTIUM_SCH_RECORD record = static_cast<ALTIUM_SCH_RECORD>( recordId );
|
||||
|
||||
// see: https://github.com/vadmium/python-altium/blob/master/format.md
|
||||
switch( record )
|
||||
{
|
||||
case ALTIUM_SCH_RECORD::HARNESS_CONNECTOR:
|
||||
ParseHarnessConnector( index, properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::HARNESS_ENTRY:
|
||||
ParseHarnessEntry( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::HARNESS_TYPE:
|
||||
ParseHarnessType( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::SIGNAL_HARNESS:
|
||||
ParseSignalHarness( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::BLANKET:
|
||||
m_reporter->Report( _( "Blanket not currently supported." ), RPT_SEVERITY_ERROR );
|
||||
break;
|
||||
|
||||
default:
|
||||
m_reporter->Report( wxString::Format( _( "Unknown or unexpected record ID %d found "
|
||||
"inside \"Additional\" section." ),
|
||||
recordId ),
|
||||
RPT_SEVERITY_ERROR );
|
||||
break;
|
||||
}
|
||||
ParseRecord( index, properties, streamName );
|
||||
}
|
||||
|
||||
// Handle harness Ports
|
||||
@@ -657,12 +649,15 @@ void SCH_IO_ALTIUM::ParseAdditional( const ALTIUM_COMPOUND_FILE& aAltiumSchFile
|
||||
|
||||
void SCH_IO_ALTIUM::ParseFileHeader( const ALTIUM_COMPOUND_FILE& aAltiumSchFile )
|
||||
{
|
||||
const CFB::COMPOUND_FILE_ENTRY* file = aAltiumSchFile.FindStream( { "FileHeader" } );
|
||||
wxString streamName = wxS( "FileHeader" );
|
||||
|
||||
const CFB::COMPOUND_FILE_ENTRY* file =
|
||||
aAltiumSchFile.FindStream( { streamName.ToStdString() } );
|
||||
|
||||
if( file == nullptr )
|
||||
THROW_IO_ERROR( "FileHeader not found" );
|
||||
|
||||
ALTIUM_PARSER reader( aAltiumSchFile, file );
|
||||
ALTIUM_BINARY_PARSER reader( aAltiumSchFile, file );
|
||||
|
||||
if( reader.GetRemainingBytes() <= 0 )
|
||||
{
|
||||
@@ -672,7 +667,7 @@ void SCH_IO_ALTIUM::ParseFileHeader( const ALTIUM_COMPOUND_FILE& aAltiumSchFile
|
||||
{
|
||||
std::map<wxString, wxString> properties = reader.ReadProperties();
|
||||
|
||||
wxString libtype = ALTIUM_PARSER::ReadString( properties, "HEADER", "" );
|
||||
wxString libtype = ALTIUM_PROPS_UTILS::ReadString( properties, "HEADER", "" );
|
||||
|
||||
if( libtype.CmpNoCase( "Protel for Windows - Schematic Capture Binary File Version 5.0" ) )
|
||||
THROW_IO_ERROR( _( "Expected Altium Schematic file version 5.0" ) );
|
||||
@@ -689,183 +684,7 @@ void SCH_IO_ALTIUM::ParseFileHeader( const ALTIUM_COMPOUND_FILE& aAltiumSchFile
|
||||
{
|
||||
std::map<wxString, wxString> properties = reader.ReadProperties();
|
||||
|
||||
int recordId = ALTIUM_PARSER::ReadInt( properties, "RECORD", -1 );
|
||||
ALTIUM_SCH_RECORD record = static_cast<ALTIUM_SCH_RECORD>( recordId );
|
||||
|
||||
// see: https://github.com/vadmium/python-altium/blob/master/format.md
|
||||
switch( record )
|
||||
{
|
||||
case ALTIUM_SCH_RECORD::HEADER:
|
||||
THROW_IO_ERROR( "Header already parsed" );
|
||||
|
||||
case ALTIUM_SCH_RECORD::COMPONENT:
|
||||
ParseComponent( index, properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::PIN:
|
||||
ParsePin( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::IEEE_SYMBOL:
|
||||
m_reporter->Report( _( "Record 'IEEE_SYMBOL' not handled." ), RPT_SEVERITY_INFO );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::LABEL:
|
||||
ParseLabel( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::BEZIER:
|
||||
ParseBezier( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::POLYLINE:
|
||||
ParsePolyline( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::POLYGON:
|
||||
ParsePolygon( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::ELLIPSE:
|
||||
ParseEllipse( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::PIECHART:
|
||||
m_reporter->Report( _( "Record 'PIECHART' not handled." ), RPT_SEVERITY_INFO );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::ROUND_RECTANGLE:
|
||||
ParseRoundRectangle( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::ELLIPTICAL_ARC:
|
||||
case ALTIUM_SCH_RECORD::ARC:
|
||||
ParseArc( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::LINE:
|
||||
ParseLine( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::RECTANGLE:
|
||||
ParseRectangle( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::SHEET_SYMBOL:
|
||||
ParseSheetSymbol( index, properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::SHEET_ENTRY:
|
||||
ParseSheetEntry( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::POWER_PORT:
|
||||
ParsePowerPort( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::PORT:
|
||||
// Ports are parsed after the sheet was parsed
|
||||
// This is required because we need all electrical connection points before placing.
|
||||
m_altiumPortsCurrentSheet.emplace_back( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::NO_ERC:
|
||||
ParseNoERC( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::NET_LABEL:
|
||||
ParseNetLabel( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::BUS:
|
||||
ParseBus( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::WIRE:
|
||||
ParseWire( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::TEXT_FRAME:
|
||||
ParseTextFrame( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::JUNCTION:
|
||||
ParseJunction( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::IMAGE:
|
||||
ParseImage( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::SHEET:
|
||||
ParseSheet( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::SHEET_NAME:
|
||||
ParseSheetName( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::FILE_NAME:
|
||||
ParseFileName( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::DESIGNATOR:
|
||||
ParseDesignator( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::BUS_ENTRY:
|
||||
ParseBusEntry( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::TEMPLATE:
|
||||
ParseTemplate( index, properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::PARAMETER:
|
||||
ParseParameter( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::PARAMETER_SET:
|
||||
m_reporter->Report( _( "Parameter Set not currently supported." ), RPT_SEVERITY_ERROR );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::IMPLEMENTATION_LIST:
|
||||
ParseImplementationList( index, properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::IMPLEMENTATION:
|
||||
ParseImplementation( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::MAP_DEFINER_LIST:
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::MAP_DEFINER:
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::IMPL_PARAMS:
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::NOTE:
|
||||
ParseNote( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::COMPILE_MASK:
|
||||
m_reporter->Report( _( "Compile mask not currently supported." ), RPT_SEVERITY_ERROR );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::HYPERLINK:
|
||||
break;
|
||||
|
||||
default:
|
||||
m_reporter->Report( wxString::Format( _( "Unknown or unexpected record id %d found "
|
||||
"inside \"FileHeader\" section." ),
|
||||
recordId ),
|
||||
RPT_SEVERITY_ERROR );
|
||||
break;
|
||||
}
|
||||
|
||||
SCH_IO_ALTIUM::m_harnessOwnerIndexOffset = index;
|
||||
ParseRecord( index, properties, streamName );
|
||||
}
|
||||
|
||||
if( reader.HasParsingError() )
|
||||
@@ -902,6 +721,8 @@ void SCH_IO_ALTIUM::ParseFileHeader( const ALTIUM_COMPOUND_FILE& aAltiumSchFile
|
||||
m_altiumPortsCurrentSheet.clear();
|
||||
m_altiumComponents.clear();
|
||||
m_altiumTemplates.clear();
|
||||
m_altiumImplementationList.clear();
|
||||
|
||||
m_symbols.clear();
|
||||
m_libSymbols.clear();
|
||||
|
||||
@@ -914,6 +735,324 @@ void SCH_IO_ALTIUM::ParseFileHeader( const ALTIUM_COMPOUND_FILE& aAltiumSchFile
|
||||
}
|
||||
|
||||
|
||||
void SCH_IO_ALTIUM::ParseASCIISchematic( const wxString& aFileName )
|
||||
{
|
||||
// Read storage content first
|
||||
{
|
||||
ALTIUM_ASCII_PARSER storageReader( aFileName );
|
||||
|
||||
while( storageReader.CanRead() )
|
||||
{
|
||||
std::map<wxString, wxString> properties = storageReader.ReadProperties();
|
||||
|
||||
// Binary data
|
||||
if( properties.find( wxS( "BINARY" ) ) != properties.end() )
|
||||
m_altiumStorage.emplace_back( properties );
|
||||
}
|
||||
}
|
||||
|
||||
// Read other data
|
||||
ALTIUM_ASCII_PARSER reader( aFileName );
|
||||
|
||||
if( !reader.CanRead() )
|
||||
{
|
||||
THROW_IO_ERROR( "FileHeader does not contain any data" );
|
||||
}
|
||||
else
|
||||
{
|
||||
std::map<wxString, wxString> properties = reader.ReadProperties();
|
||||
|
||||
wxString libtype = ALTIUM_PROPS_UTILS::ReadString( properties, "HEADER", "" );
|
||||
|
||||
if( libtype.CmpNoCase( "Protel for Windows - Schematic Capture Ascii File Version 5.0" ) )
|
||||
THROW_IO_ERROR( _( "Expected Altium Schematic file version 5.0" ) );
|
||||
}
|
||||
|
||||
// Prepare some local variables
|
||||
wxCHECK( m_altiumPortsCurrentSheet.empty(), /* void */ );
|
||||
wxCHECK( !m_currentTitleBlock, /* void */ );
|
||||
|
||||
m_currentTitleBlock = std::make_unique<TITLE_BLOCK>();
|
||||
|
||||
// index is required to resolve OWNERINDEX
|
||||
int index = 0;
|
||||
|
||||
while( reader.CanRead() )
|
||||
{
|
||||
std::map<wxString, wxString> properties = reader.ReadProperties();
|
||||
|
||||
// Reset index at headers
|
||||
if( properties.find( wxS( "HEADER" ) ) != properties.end() )
|
||||
{
|
||||
index = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( properties.find( wxS( "RECORD" ) ) != properties.end() )
|
||||
ParseRecord( index, properties, aFileName );
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
if( reader.HasParsingError() )
|
||||
THROW_IO_ERROR( "stream was not parsed correctly!" );
|
||||
|
||||
if( reader.CanRead() )
|
||||
THROW_IO_ERROR( "stream is not fully parsed" );
|
||||
|
||||
// assign LIB_SYMBOL -> COMPONENT
|
||||
for( std::pair<const int, SCH_SYMBOL*>& symbol : m_symbols )
|
||||
{
|
||||
auto libSymbolIt = m_libSymbols.find( symbol.first );
|
||||
|
||||
if( libSymbolIt == m_libSymbols.end() )
|
||||
THROW_IO_ERROR( "every symbol should have a symbol attached" );
|
||||
|
||||
m_pi->SaveSymbol( getLibFileName().GetFullPath(),
|
||||
new LIB_SYMBOL( *( libSymbolIt->second ) ), m_properties.get() );
|
||||
|
||||
symbol.second->SetLibSymbol( libSymbolIt->second );
|
||||
}
|
||||
|
||||
SCH_SCREEN* screen = getCurrentScreen();
|
||||
wxCHECK( screen, /* void */ );
|
||||
|
||||
// Handle title blocks
|
||||
screen->SetTitleBlock( *m_currentTitleBlock );
|
||||
m_currentTitleBlock.reset();
|
||||
|
||||
// Handle harness Ports
|
||||
for( const ASCH_PORT& port : m_altiumHarnessPortsCurrentSheet )
|
||||
ParseHarnessPort( port );
|
||||
|
||||
// Handle Ports
|
||||
for( const ASCH_PORT& port : m_altiumPortsCurrentSheet )
|
||||
ParsePort( port );
|
||||
|
||||
m_altiumPortsCurrentSheet.clear();
|
||||
m_altiumComponents.clear();
|
||||
m_altiumTemplates.clear();
|
||||
m_altiumImplementationList.clear();
|
||||
|
||||
m_symbols.clear();
|
||||
m_libSymbols.clear();
|
||||
|
||||
// Otherwise we cannot save the imported sheet?
|
||||
SCH_SHEET* sheet = getCurrentSheet();
|
||||
|
||||
wxCHECK( sheet, /* void */ );
|
||||
|
||||
sheet->SetModified();
|
||||
}
|
||||
|
||||
|
||||
void SCH_IO_ALTIUM::ParseRecord( int index, std::map<wxString, wxString>& properties,
|
||||
const wxString& aSectionName )
|
||||
{
|
||||
int recordId = ALTIUM_PROPS_UTILS::ReadInt( properties, "RECORD", -1 );
|
||||
ALTIUM_SCH_RECORD record = static_cast<ALTIUM_SCH_RECORD>( recordId );
|
||||
|
||||
// see: https://github.com/vadmium/python-altium/blob/master/format.md
|
||||
switch( record )
|
||||
{
|
||||
// FileHeader section
|
||||
|
||||
case ALTIUM_SCH_RECORD::HEADER:
|
||||
THROW_IO_ERROR( "Header already parsed" );
|
||||
|
||||
case ALTIUM_SCH_RECORD::COMPONENT:
|
||||
ParseComponent( index, properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::PIN:
|
||||
ParsePin( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::IEEE_SYMBOL:
|
||||
m_reporter->Report( _( "Record 'IEEE_SYMBOL' not handled." ), RPT_SEVERITY_INFO );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::LABEL:
|
||||
ParseLabel( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::BEZIER:
|
||||
ParseBezier( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::POLYLINE:
|
||||
ParsePolyline( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::POLYGON:
|
||||
ParsePolygon( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::ELLIPSE:
|
||||
ParseEllipse( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::PIECHART:
|
||||
m_reporter->Report( _( "Record 'PIECHART' not handled." ), RPT_SEVERITY_INFO );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::ROUND_RECTANGLE:
|
||||
ParseRoundRectangle( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::ELLIPTICAL_ARC:
|
||||
case ALTIUM_SCH_RECORD::ARC:
|
||||
ParseArc( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::LINE:
|
||||
ParseLine( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::RECTANGLE:
|
||||
ParseRectangle( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::SHEET_SYMBOL:
|
||||
ParseSheetSymbol( index, properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::SHEET_ENTRY:
|
||||
ParseSheetEntry( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::POWER_PORT:
|
||||
ParsePowerPort( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::PORT:
|
||||
// Ports are parsed after the sheet was parsed
|
||||
// This is required because we need all electrical connection points before placing.
|
||||
m_altiumPortsCurrentSheet.emplace_back( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::NO_ERC:
|
||||
ParseNoERC( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::NET_LABEL:
|
||||
ParseNetLabel( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::BUS:
|
||||
ParseBus( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::WIRE:
|
||||
ParseWire( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::TEXT_FRAME:
|
||||
ParseTextFrame( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::JUNCTION:
|
||||
ParseJunction( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::IMAGE:
|
||||
ParseImage( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::SHEET:
|
||||
ParseSheet( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::SHEET_NAME:
|
||||
ParseSheetName( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::FILE_NAME:
|
||||
ParseFileName( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::DESIGNATOR:
|
||||
ParseDesignator( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::BUS_ENTRY:
|
||||
ParseBusEntry( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::TEMPLATE:
|
||||
ParseTemplate( index, properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::PARAMETER:
|
||||
ParseParameter( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::PARAMETER_SET:
|
||||
m_reporter->Report( _( "Parameter Set not currently supported." ), RPT_SEVERITY_ERROR );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::IMPLEMENTATION_LIST:
|
||||
ParseImplementationList( index, properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::IMPLEMENTATION:
|
||||
ParseImplementation( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::MAP_DEFINER_LIST:
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::MAP_DEFINER:
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::IMPL_PARAMS:
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::NOTE:
|
||||
ParseNote( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::COMPILE_MASK:
|
||||
m_reporter->Report( _( "Compile mask not currently supported." ), RPT_SEVERITY_ERROR );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::HYPERLINK:
|
||||
break;
|
||||
|
||||
// Additional section
|
||||
|
||||
case ALTIUM_SCH_RECORD::HARNESS_CONNECTOR:
|
||||
ParseHarnessConnector( index, properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::HARNESS_ENTRY:
|
||||
ParseHarnessEntry( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::HARNESS_TYPE:
|
||||
ParseHarnessType( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::SIGNAL_HARNESS:
|
||||
ParseSignalHarness( properties );
|
||||
break;
|
||||
|
||||
case ALTIUM_SCH_RECORD::BLANKET:
|
||||
m_reporter->Report( _( "Blanket not currently supported." ), RPT_SEVERITY_ERROR );
|
||||
break;
|
||||
|
||||
default:
|
||||
m_reporter->Report(
|
||||
wxString::Format( _( "Unknown or unexpected record id %d found in %s." ), recordId,
|
||||
aSectionName ),
|
||||
RPT_SEVERITY_ERROR );
|
||||
break;
|
||||
}
|
||||
|
||||
SCH_IO_ALTIUM::m_harnessOwnerIndexOffset = index;
|
||||
}
|
||||
|
||||
|
||||
bool SCH_IO_ALTIUM::IsComponentPartVisible( const ASCH_OWNER_INTERFACE& aElem ) const
|
||||
{
|
||||
const auto& component = m_altiumComponents.find( aElem.ownerindex );
|
||||
@@ -1001,6 +1140,7 @@ void SCH_IO_ALTIUM::ParseComponent( int aIndex, const std::map<wxString, wxStrin
|
||||
// component->SetOrientation( elem.orientation );
|
||||
symbol->SetLibId( libId );
|
||||
symbol->SetUnit( std::max( 0, elem.currentpartid ) );
|
||||
symbol->GetField( DESCRIPTION_FIELD )->SetText( elem.componentdescription );
|
||||
|
||||
SCH_SCREEN* screen = getCurrentScreen();
|
||||
wxCHECK( screen, /* void */ );
|
||||
@@ -3404,7 +3544,7 @@ void SCH_IO_ALTIUM::ParseWire( const std::map<wxString, wxString>& aProperties )
|
||||
SCH_LINE* wire = new SCH_LINE( elem.points.at( i ) + m_sheetOffset,
|
||||
SCH_LAYER_ID::LAYER_WIRE );
|
||||
wire->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
|
||||
wire->SetLineWidth( elem.lineWidth );
|
||||
// wire->SetLineWidth( elem.lineWidth );
|
||||
|
||||
wire->SetFlags( IS_NEW );
|
||||
screen->Append( wire );
|
||||
@@ -3978,7 +4118,7 @@ std::map<wxString,LIB_SYMBOL*> SCH_IO_ALTIUM::ParseLibFile( const ALTIUM_COMPOUN
|
||||
|
||||
for( auto& [name, entry] : syms )
|
||||
{
|
||||
ALTIUM_PARSER reader( aAltiumLibFile, entry );
|
||||
ALTIUM_BINARY_PARSER reader( aAltiumLibFile, entry );
|
||||
std::vector<LIB_SYMBOL*> symbols;
|
||||
|
||||
if( reader.GetRemainingBytes() <= 0 )
|
||||
@@ -3988,7 +4128,7 @@ std::map<wxString,LIB_SYMBOL*> SCH_IO_ALTIUM::ParseLibFile( const ALTIUM_COMPOUN
|
||||
|
||||
{
|
||||
std::map<wxString, wxString> properties = reader.ReadProperties();
|
||||
int recordId = ALTIUM_PARSER::ReadInt( properties, "RECORD", 0 );
|
||||
int recordId = ALTIUM_PROPS_UTILS::ReadInt( properties, "RECORD", 0 );
|
||||
ALTIUM_SCH_RECORD record = static_cast<ALTIUM_SCH_RECORD>( recordId );
|
||||
|
||||
if( record != ALTIUM_SCH_RECORD::COMPONENT )
|
||||
@@ -4053,7 +4193,7 @@ std::map<wxString,LIB_SYMBOL*> SCH_IO_ALTIUM::ParseLibFile( const ALTIUM_COMPOUN
|
||||
if( properties.empty() )
|
||||
continue;
|
||||
|
||||
int recordId = ALTIUM_PARSER::ReadInt( properties, "RECORD", 0 );
|
||||
int recordId = ALTIUM_PROPS_UTILS::ReadInt( properties, "RECORD", 0 );
|
||||
ALTIUM_SCH_RECORD record = static_cast<ALTIUM_SCH_RECORD>( recordId );
|
||||
|
||||
switch( record )
|
||||
@@ -4218,7 +4358,7 @@ void SCH_IO_ALTIUM::ParseLibHeader( const ALTIUM_COMPOUND_FILE& aAltiumSchFile,
|
||||
if( file == nullptr )
|
||||
THROW_IO_ERROR( "FileHeader not found" );
|
||||
|
||||
ALTIUM_PARSER reader( aAltiumSchFile, file );
|
||||
ALTIUM_BINARY_PARSER reader( aAltiumSchFile, file );
|
||||
|
||||
if( reader.GetRemainingBytes() <= 0 )
|
||||
{
|
||||
@@ -4227,7 +4367,7 @@ void SCH_IO_ALTIUM::ParseLibHeader( const ALTIUM_COMPOUND_FILE& aAltiumSchFile,
|
||||
|
||||
std::map<wxString, wxString> properties = reader.ReadProperties();
|
||||
|
||||
wxString libtype = ALTIUM_PARSER::ReadString( properties, "HEADER", "" );
|
||||
wxString libtype = ALTIUM_PROPS_UTILS::ReadString( properties, "HEADER", "" );
|
||||
|
||||
if( libtype.CmpNoCase( "Protel for Windows - Schematic Library Editor Binary File Version 5.0" ) )
|
||||
THROW_IO_ERROR( _( "Expected Altium Schematic Library file version 5.0" ) );
|
||||
|
||||
@@ -116,6 +116,11 @@ public:
|
||||
void ParseAdditional( const ALTIUM_COMPOUND_FILE& aAltiumSchFile );
|
||||
void ParseFileHeader( const ALTIUM_COMPOUND_FILE& aAltiumSchFile );
|
||||
|
||||
void ParseASCIISchematic( const wxString& aFileName );
|
||||
|
||||
void ParseRecord( int index, std::map<wxString, wxString>& properties,
|
||||
const wxString& aSectionName );
|
||||
|
||||
private:
|
||||
SCH_SCREEN* getCurrentScreen();
|
||||
SCH_SHEET* getCurrentSheet();
|
||||
@@ -212,6 +217,8 @@ private:
|
||||
void ensureLoadedLibrary( const wxString& aLibraryPath, const STRING_UTF8_MAP* aProperties );
|
||||
long long getLibraryTimestamp( const wxString& aLibraryPath ) const;
|
||||
|
||||
static bool isBinaryFile( const wxString& aFileName );
|
||||
static bool isASCIIFile( const wxString& aFileName );
|
||||
static bool checkFileHeader( const wxString& aFileName );
|
||||
|
||||
std::map<wxString, long long> m_timestamps;
|
||||
|
||||
@@ -79,7 +79,7 @@ void SCH_IO_DATABASE::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
|
||||
|
||||
for( auto const& pair : m_nameToSymbolcache )
|
||||
{
|
||||
LIB_SYMBOL* symbol = pair.second;
|
||||
LIB_SYMBOL* symbol = pair.second.get();
|
||||
|
||||
if( !powerSymbolsOnly || symbol->IsPower() )
|
||||
aSymbolList.emplace_back( symbol );
|
||||
@@ -151,7 +151,7 @@ LIB_SYMBOL* SCH_IO_DATABASE::LoadSymbol( const wxString& aLibraryPath,
|
||||
|
||||
wxCHECK( foundTable, nullptr );
|
||||
|
||||
return loadSymbolFromRow( aAliasName, *foundTable, result );
|
||||
return loadSymbolFromRow( aAliasName, *foundTable, result ).release();
|
||||
}
|
||||
|
||||
|
||||
@@ -236,10 +236,10 @@ void SCH_IO_DATABASE::cacheLib()
|
||||
wxString name( fmt::format( "{}{}", prefix,
|
||||
std::any_cast<std::string>( result[table.key_col] ) ) );
|
||||
|
||||
LIB_SYMBOL* symbol = loadSymbolFromRow( name, table, result );
|
||||
std::unique_ptr<LIB_SYMBOL> symbol = loadSymbolFromRow( name, table, result );
|
||||
|
||||
if( symbol )
|
||||
m_nameToSymbolcache.insert( { symbol->GetName(), symbol } );
|
||||
m_nameToSymbolcache[symbol->GetName()] = std::move( symbol );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,11 +414,11 @@ std::optional<bool> SCH_IO_DATABASE::boolFromAny( const std::any& aVal )
|
||||
}
|
||||
|
||||
|
||||
LIB_SYMBOL* SCH_IO_DATABASE::loadSymbolFromRow( const wxString& aSymbolName,
|
||||
std::unique_ptr<LIB_SYMBOL> SCH_IO_DATABASE::loadSymbolFromRow( const wxString& aSymbolName,
|
||||
const DATABASE_LIB_TABLE& aTable,
|
||||
const DATABASE_CONNECTION::ROW& aRow )
|
||||
{
|
||||
LIB_SYMBOL* symbol = nullptr;
|
||||
std::unique_ptr<LIB_SYMBOL> symbol = nullptr;
|
||||
|
||||
if( aRow.count( aTable.symbols_col ) )
|
||||
{
|
||||
@@ -436,7 +436,7 @@ LIB_SYMBOL* SCH_IO_DATABASE::loadSymbolFromRow( const wxString& aSymbolName,
|
||||
{
|
||||
wxLogTrace( traceDatabase, wxT( "loadSymbolFromRow: found original symbol '%s'" ),
|
||||
symbolIdStr );
|
||||
symbol = originalSymbol->Duplicate();
|
||||
symbol.reset( originalSymbol->Duplicate() );
|
||||
symbol->SetSourceLibId( symbolId );
|
||||
}
|
||||
else if( !symbolId.IsValid() )
|
||||
@@ -455,7 +455,7 @@ LIB_SYMBOL* SCH_IO_DATABASE::loadSymbolFromRow( const wxString& aSymbolName,
|
||||
{
|
||||
// Actual symbol not found: return metadata only; error will be indicated in the
|
||||
// symbol chooser
|
||||
symbol = new LIB_SYMBOL( aSymbolName );
|
||||
symbol.reset( new LIB_SYMBOL( aSymbolName ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -93,9 +93,9 @@ private:
|
||||
|
||||
void connect();
|
||||
|
||||
LIB_SYMBOL* loadSymbolFromRow( const wxString& aSymbolName,
|
||||
const DATABASE_LIB_TABLE& aTable,
|
||||
const DATABASE_CONNECTION::ROW& aRow );
|
||||
std::unique_ptr<LIB_SYMBOL> loadSymbolFromRow( const wxString& aSymbolName,
|
||||
const DATABASE_LIB_TABLE& aTable,
|
||||
const DATABASE_CONNECTION::ROW& aRow );
|
||||
|
||||
static std::optional<bool> boolFromAny( const std::any& aVal );
|
||||
|
||||
@@ -110,7 +110,7 @@ private:
|
||||
|
||||
std::set<wxString> m_defaultShownFields;
|
||||
|
||||
std::map<wxString, LIB_SYMBOL*> m_nameToSymbolcache;
|
||||
std::map<wxString, std::unique_ptr<LIB_SYMBOL>> m_nameToSymbolcache;
|
||||
|
||||
long long m_cacheTimestamp;
|
||||
|
||||
|
||||
@@ -445,11 +445,11 @@ void SCH_EASYEDA_PARSER::ParseSymbolShapes( LIB_SYMBOL* aSymbol
|
||||
wxString fillColor = arr[5].Lower();
|
||||
//bool locked = arr[7] != wxS( "0" );
|
||||
|
||||
std::vector<SHAPE_LINE_CHAIN> lineChains =
|
||||
std::vector<SHAPE_LINE_CHAIN> lineChains =
|
||||
ParseLineChains( pointsData, schIUScale.MilsToIU( 10 ), false );
|
||||
|
||||
for( SHAPE_LINE_CHAIN outline : lineChains )
|
||||
{
|
||||
{
|
||||
std::unique_ptr<LIB_SHAPE> shape =
|
||||
std::make_unique<LIB_SHAPE>( aSymbol, SHAPE_T::POLY );
|
||||
|
||||
@@ -806,6 +806,55 @@ void SCH_EASYEDA_PARSER::ParseSymbolShapes( LIB_SYMBOL* aSymbol
|
||||
int pinUnit = 0;
|
||||
int kPinLen = ScaleSize( std::abs( pinLen ) );
|
||||
|
||||
if( segments.size() > 5 )
|
||||
{
|
||||
wxArrayString dotParts = wxSplit( segments[5], '~', '\0' );
|
||||
wxArrayString clockParts = wxSplit( segments[6], '~', '\0' );
|
||||
|
||||
if( dotParts.size() == 3 && clockParts.size() == 2 )
|
||||
{
|
||||
if( dotParts[0] == wxS( "1" ) )
|
||||
{
|
||||
VECTOR2D dotPos( Convert( dotParts[1] ), Convert( dotParts[2] ) );
|
||||
|
||||
std::unique_ptr<LIB_SHAPE> circle =
|
||||
std::make_unique<LIB_SHAPE>( aSymbol, SHAPE_T::CIRCLE );
|
||||
|
||||
circle->SetCenter( RelPosSym( dotPos ) );
|
||||
circle->SetEnd( RelPosSym(
|
||||
pinPos + ( dotPos - pinPos ).Resize( std::abs( pinLen ) ) ) );
|
||||
|
||||
circle->SetUnit( 0 );
|
||||
|
||||
aSymbol->AddDrawItem( circle.release() );
|
||||
}
|
||||
|
||||
if( clockParts[0] == wxS( "1" ) )
|
||||
{
|
||||
std::vector<SHAPE_LINE_CHAIN> lineChains =
|
||||
ParseLineChains( clockParts[1], schIUScale.MilsToIU( 10 ), false );
|
||||
|
||||
for( SHAPE_LINE_CHAIN outline : lineChains )
|
||||
{
|
||||
std::unique_ptr<LIB_SHAPE> shape =
|
||||
std::make_unique<LIB_SHAPE>( aSymbol, SHAPE_T::POLY );
|
||||
|
||||
outline.Mirror( false, true );
|
||||
|
||||
if( outline.IsClosed() )
|
||||
outline.Append( outline.CPoint( 0 ), true );
|
||||
|
||||
for( const VECTOR2I& pt : outline.CPoints() )
|
||||
shape->AddPoint( pt );
|
||||
|
||||
shape->SetUnit( 0 );
|
||||
|
||||
aSymbol->AddDrawItem( shape.release() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<LIB_PIN> pin = std::make_unique<LIB_PIN>( aSymbol );
|
||||
|
||||
pin->SetName( pinName );
|
||||
@@ -837,6 +886,7 @@ void SCH_EASYEDA_PARSER::ParseSymbolShapes( LIB_SYMBOL* aSymbol
|
||||
wxString fontSize = arr[7];
|
||||
wxString baselineAlign = arr[10];
|
||||
wxString textStr = arr[12];
|
||||
bool visible = arr[13] != wxS( "0" );
|
||||
|
||||
textStr.Replace( wxS( "\\n" ), wxS( "\n" ) );
|
||||
textStr = UnescapeHTML( textStr );
|
||||
@@ -874,6 +924,7 @@ void SCH_EASYEDA_PARSER::ParseSymbolShapes( LIB_SYMBOL* aSymbol
|
||||
textItem->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
|
||||
|
||||
textItem->SetFont( KIFONT::FONT::GetFont( fontname ) );
|
||||
textItem->SetVisible( visible );
|
||||
|
||||
double ptSize = 7;
|
||||
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include <sch_screen.h>
|
||||
#include <kiplatform/environment.h>
|
||||
#include <project_sch.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
#include <string_utils.h>
|
||||
|
||||
#include <wx/log.h>
|
||||
#include <wx/stdstream.h>
|
||||
@@ -496,17 +498,11 @@ static void LoadSchematic( SCHEMATIC* aSchematic, SCH_SHEET* aRootSheet, const w
|
||||
if( topDocType == EASYEDA::DOC_TYPE::SCHEMATIC_SHEET
|
||||
|| topDocType == EASYEDA::DOC_TYPE::SCHEMATIC_LIST )
|
||||
{
|
||||
int pageNum = 1;
|
||||
EASYEDA::DOCUMENT_SCHEMATICS schDoc = js.get<EASYEDA::DOCUMENT_SCHEMATICS>();
|
||||
|
||||
bool first = true;
|
||||
|
||||
for( const EASYEDA::DOCUMENT& subDoc : *schDoc.schematics )
|
||||
{
|
||||
if( first )
|
||||
first = false; // TODO
|
||||
else
|
||||
break;
|
||||
|
||||
if( subDoc.docType )
|
||||
{
|
||||
if( *subDoc.docType != EASYEDA::DOC_TYPE::SCHEMATIC_SHEET )
|
||||
@@ -520,7 +516,56 @@ static void LoadSchematic( SCHEMATIC* aSchematic, SCH_SHEET* aRootSheet, const w
|
||||
|
||||
EASYEDA::DOCUMENT dataStrDoc = subDoc.dataStr->get<EASYEDA::DOCUMENT>();
|
||||
|
||||
parser.ParseSchematic( aSchematic, aRootSheet, aFileName, dataStrDoc.shape );
|
||||
if( schDoc.schematics->size() > 1 )
|
||||
{
|
||||
wxString sheetTitle =
|
||||
!subDoc.title.empty() ? subDoc.title : ( wxString() << pageNum );
|
||||
|
||||
wxString sheetBaseName = EscapeString( sheetTitle, CTX_FILENAME );
|
||||
|
||||
wxFileName sheetFname( aFileName );
|
||||
sheetFname.SetFullName(
|
||||
sheetBaseName + wxS( "." )
|
||||
+ wxString::FromUTF8( FILEEXT::KiCadSchematicFileExtension ) );
|
||||
|
||||
wxFileName relSheetPath( sheetFname );
|
||||
relSheetPath.MakeRelativeTo(
|
||||
wxFileName( aRootSheet->GetFileName() ).GetPath() );
|
||||
|
||||
std::unique_ptr<SCH_SHEET> subSheet = std::make_unique<SCH_SHEET>( aSchematic );
|
||||
subSheet->SetFileName( relSheetPath.GetFullPath() );
|
||||
subSheet->SetName( sheetTitle );
|
||||
|
||||
SCH_SCREEN* screen = new SCH_SCREEN( aSchematic );
|
||||
screen->SetFileName( sheetFname.GetFullPath() );
|
||||
screen->SetPageNumber( wxString() << pageNum );
|
||||
subSheet->SetScreen( screen );
|
||||
|
||||
VECTOR2I pos;
|
||||
pos.x = schIUScale.MilsToIU( 200 );
|
||||
pos.y = schIUScale.MilsToIU( 200 )
|
||||
+ ( subSheet->GetSize().y + schIUScale.MilsToIU( 200 ) )
|
||||
* ( pageNum - 1 );
|
||||
|
||||
subSheet->SetPosition( pos );
|
||||
|
||||
SCH_SHEET_PATH sheetPath;
|
||||
sheetPath.push_back( aRootSheet );
|
||||
sheetPath.push_back( subSheet.get() );
|
||||
sheetPath.SetPageNumber( wxString() << pageNum );
|
||||
aSchematic->SetCurrentSheet( sheetPath );
|
||||
|
||||
parser.ParseSchematic( aSchematic, subSheet.get(), aFileName,
|
||||
dataStrDoc.shape );
|
||||
|
||||
aRootSheet->GetScreen()->Append( subSheet.release() );
|
||||
}
|
||||
else
|
||||
{
|
||||
parser.ParseSchematic( aSchematic, aRootSheet, aFileName, dataStrDoc.shape );
|
||||
}
|
||||
|
||||
pageNum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -532,14 +532,14 @@ EASYEDAPRO::SYM_INFO SCH_EASYEDAPRO_PARSER::ParseSymbol( const std::vector<nlohm
|
||||
{
|
||||
VECTOR2D start, size;
|
||||
wxString mimeType, data;
|
||||
double angle = 0;
|
||||
//double angle = 0;
|
||||
int upsideDown = 0;
|
||||
|
||||
if( line.at( 3 ).is_number() )
|
||||
{
|
||||
start = VECTOR2D( line.at( 3 ), line.at( 4 ) );
|
||||
size = VECTOR2D( line.at( 5 ), line.at( 6 ) );
|
||||
angle = line.at( 7 );
|
||||
//angle = line.at( 7 );
|
||||
upsideDown = line.at( 8 );
|
||||
|
||||
wxString imageUrl = line.at( 9 );
|
||||
@@ -563,7 +563,7 @@ EASYEDAPRO::SYM_INFO SCH_EASYEDAPRO_PARSER::ParseSymbol( const std::vector<nlohm
|
||||
|
||||
start = VECTOR2D( line.at( 4 ), line.at( 5 ) );
|
||||
size = VECTOR2D( line.at( 6 ), line.at( 7 ) );
|
||||
angle = line.at( 8 );
|
||||
//angle = line.at( 8 );
|
||||
data = line.at( 9 ).get<wxString>();
|
||||
}
|
||||
|
||||
|
||||
@@ -469,7 +469,9 @@ SCH_SHEET* SCH_IO_EASYEDAPRO::LoadSchematicFile( const wxString& aFileName,
|
||||
if( !m_projectData )
|
||||
return nullptr;
|
||||
|
||||
auto cbs = [&]( const wxString& name, const wxString& symUuid, wxInputStream& zip ) -> bool
|
||||
const int schSheetsCount = prjSchematicSheets.size();
|
||||
|
||||
auto cbs = [&]( const wxString& name, const wxString& baseName, wxInputStream& zip ) -> bool
|
||||
{
|
||||
if( !name.EndsWith( wxS( ".esch" ) ) )
|
||||
EASY_IT_CONTINUE;
|
||||
@@ -500,41 +502,52 @@ SCH_SHEET* SCH_IO_EASYEDAPRO::LoadSchematicFile( const wxString& aFileName,
|
||||
if( prjSheetIt == prjSchematicSheets.end() )
|
||||
EASY_IT_CONTINUE;
|
||||
|
||||
wxString sheetBaseName =
|
||||
sheetId + wxS( "_" ) + EscapeString( prjSheetIt->name, CTX_FILENAME );
|
||||
|
||||
wxFileName sheetFname( aFileName );
|
||||
sheetFname.SetFullName( sheetBaseName + wxS( "." )
|
||||
+ wxString::FromUTF8( FILEEXT::KiCadSchematicFileExtension ) );
|
||||
|
||||
std::unique_ptr<SCH_SHEET> subSheet = std::make_unique<SCH_SHEET>( aSchematic );
|
||||
subSheet->SetFileName( sheetFname.GetFullPath() );
|
||||
subSheet->SetName( prjSheetIt->name );
|
||||
|
||||
SCH_SCREEN* screen = new SCH_SCREEN( aSchematic );
|
||||
screen->SetFileName( sheetFname.GetFullPath() );
|
||||
screen->SetPageNumber( sheetId );
|
||||
subSheet->SetScreen( screen );
|
||||
|
||||
VECTOR2I pos;
|
||||
pos.x = schIUScale.MilsToIU( 200 );
|
||||
pos.y = schIUScale.MilsToIU( 200 )
|
||||
+ ( subSheet->GetSize().y + schIUScale.MilsToIU( 200 ) ) * ( sheetId_i - 1 );
|
||||
|
||||
subSheet->SetPosition( pos );
|
||||
|
||||
std::vector<nlohmann::json> lines = EASYEDAPRO::ParseJsonLines( zip, name );
|
||||
|
||||
SCH_SHEET_PATH sheetPath;
|
||||
sheetPath.push_back( rootSheet );
|
||||
sheetPath.push_back( subSheet.get() );
|
||||
sheetPath.SetPageNumber( sheetId );
|
||||
aSchematic->SetCurrentSheet( sheetPath );
|
||||
if( schSheetsCount > 1 )
|
||||
{
|
||||
wxString sheetBaseName =
|
||||
sheetId + wxS( "_" ) + EscapeString( prjSheetIt->name, CTX_FILENAME );
|
||||
|
||||
parser.ParseSchematic( aSchematic, subSheet.get(), project, m_projectData->m_Symbols,
|
||||
m_projectData->m_Blobs, lines, libName );
|
||||
wxFileName sheetFname( aFileName );
|
||||
sheetFname.SetFullName( sheetBaseName + wxS( "." )
|
||||
+ wxString::FromUTF8( FILEEXT::KiCadSchematicFileExtension ) );
|
||||
|
||||
rootSheet->GetScreen()->Append( subSheet.release() );
|
||||
wxFileName relSheetPath( sheetFname );
|
||||
relSheetPath.MakeRelativeTo( rootFname.GetPath() );
|
||||
|
||||
std::unique_ptr<SCH_SHEET> subSheet = std::make_unique<SCH_SHEET>( aSchematic );
|
||||
subSheet->SetFileName( relSheetPath.GetFullPath() );
|
||||
subSheet->SetName( prjSheetIt->name );
|
||||
|
||||
SCH_SCREEN* screen = new SCH_SCREEN( aSchematic );
|
||||
screen->SetFileName( sheetFname.GetFullPath() );
|
||||
screen->SetPageNumber( sheetId );
|
||||
subSheet->SetScreen( screen );
|
||||
|
||||
VECTOR2I pos;
|
||||
pos.x = schIUScale.MilsToIU( 200 );
|
||||
pos.y = schIUScale.MilsToIU( 200 )
|
||||
+ ( subSheet->GetSize().y + schIUScale.MilsToIU( 200 ) ) * ( sheetId_i - 1 );
|
||||
|
||||
subSheet->SetPosition( pos );
|
||||
|
||||
SCH_SHEET_PATH sheetPath;
|
||||
sheetPath.push_back( rootSheet );
|
||||
sheetPath.push_back( subSheet.get() );
|
||||
sheetPath.SetPageNumber( sheetId );
|
||||
aSchematic->SetCurrentSheet( sheetPath );
|
||||
|
||||
parser.ParseSchematic( aSchematic, subSheet.get(), project, m_projectData->m_Symbols,
|
||||
m_projectData->m_Blobs, lines, libName );
|
||||
|
||||
rootSheet->GetScreen()->Append( subSheet.release() );
|
||||
}
|
||||
else
|
||||
{
|
||||
parser.ParseSchematic( aSchematic, rootSheet, project, m_projectData->m_Symbols,
|
||||
m_projectData->m_Blobs, lines, libName );
|
||||
}
|
||||
|
||||
EASY_IT_CONTINUE;
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user