Compare commits
426 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3d87537dd2 | |||
| 862d975c2c | |||
| 45d58fbefc | |||
| 7b7e4e1ae5 | |||
| 3f04b80ff4 | |||
| 5830cdd1c0 | |||
| 2416b28cda | |||
| 729cf7a39d | |||
| 4d56690a7e | |||
| e30128f6f5 | |||
| c4a42f28c8 | |||
| bdbbba54f9 | |||
| 80c2fb39b1 | |||
| 63506cf777 | |||
| 6c1d615f66 | |||
| c0ca2f1830 | |||
| cf5f36aac5 | |||
| cc51807241 | |||
| e1865c1178 | |||
| b81ba520f8 | |||
| edbb9c5194 | |||
| cda6aed408 | |||
| 74172612fa | |||
| 7209239a62 | |||
| 16edde8611 | |||
| 33f8bcb7c7 | |||
| fb6505d8cb | |||
| 39935311fc | |||
| 851f893e8e | |||
| bfa1661edf | |||
| 110663d214 | |||
| 847fa7f2c4 | |||
| ef798f446f | |||
| 2de1bd7a4a | |||
| 250942264b | |||
| 6818eff90e | |||
| b2eb1f829e | |||
| a60e7e27b6 | |||
| 601995c759 | |||
| 63ce2307c8 | |||
| 03bc9551c7 | |||
| c8cd214cb0 | |||
| fe11bc8330 | |||
| d0796399a2 | |||
| c2d72180f8 | |||
| 57729414e3 | |||
| b664fb7a7d | |||
| fe1a8bea8c | |||
| 3606ad725c | |||
| e8e24b372f | |||
| 3bfa5807c8 | |||
| b797735c24 | |||
| d0af5fb5fc | |||
| 5ca91c404a | |||
| 6ba7967adc | |||
| 9dfc492cb9 | |||
| 0876fed91b | |||
| 651f50a26d | |||
| 99456d4351 | |||
| 529048dac1 | |||
| be2e0cc272 | |||
| 48a776f7c5 | |||
| 43929781a2 | |||
| e02229a234 | |||
| 821fe6ea42 | |||
| e740db61f5 | |||
| a700531aba | |||
| 7d9cf00fd9 | |||
| 6127ae92a5 | |||
| f8c92e355b | |||
| f7f6ea54fe | |||
| fdfe5a813e | |||
| 636d009860 | |||
| 7d96d5940d | |||
| d3a60f7d83 | |||
| 604871518f | |||
| 5a68077f60 | |||
| 8054f1a948 | |||
| 80bf1048d0 | |||
| d85e52e9fd | |||
| e21f0ec9fb | |||
| 1adfca8f2d | |||
| f89256e51e | |||
| e98e9f72df | |||
| f8ff9705ff | |||
| e3e52d055a | |||
| 6de8b99cf2 | |||
| c9829cf9a8 | |||
| 0fc4ccf8d9 | |||
| 330b1fd733 | |||
| 455ec428f2 | |||
| 39959844e5 | |||
| d5de4bb5c7 | |||
| 6706a5c462 | |||
| 15fe2f2fd0 | |||
| c23679d9bd | |||
| f226772938 | |||
| 6a53e318e5 | |||
| 776a28a10e | |||
| 3a98eacdb9 | |||
| a8004cb161 | |||
| f00222b3a6 | |||
| 96dded48d4 | |||
| 950cccdc1c | |||
| 5b7a1a8177 | |||
| 96aa472ff9 | |||
| 0ec50e9096 | |||
| 6bc48e9ca8 | |||
| 5505add08e | |||
| 4d8297a1f6 | |||
| e1cd74dd78 | |||
| 2567f45c1d | |||
| 0ea7dabc12 | |||
| bf8c7d7697 | |||
| 891c919c23 | |||
| 375a7303c5 | |||
| e14e9cf8a9 | |||
| 4e98ce87c7 | |||
| 207820e112 | |||
| dbbecefcb9 | |||
| df8f166847 | |||
| 79ef8e14aa | |||
| 5081165611 | |||
| 3bfcaf2455 | |||
| 9e2416d2c9 | |||
| 49eecf66fe | |||
| bc3a4e4ede | |||
| 3645c3c0cc | |||
| 7902c1cc58 | |||
| 2a2781e1bc | |||
| 9510b07807 | |||
| 072c0f06cd | |||
| b75e782aef | |||
| d9fe48171b | |||
| eeee5afdfd | |||
| 790b810621 | |||
| e33bf78d96 | |||
| bd86999615 | |||
| 1b108afd0b | |||
| a8384beb6f | |||
| c44d31fcfb | |||
| d801a8689c | |||
| 4a1abd239a | |||
| 423732910d | |||
| e4ce5e5262 | |||
| 2998d31f2c | |||
| da98413f82 | |||
| f562466189 | |||
| 0deae6bdd2 | |||
| 31f8e73cf8 | |||
| e58f50602d | |||
| c870505141 | |||
| c20e81fbdd | |||
| 58d0c4112d | |||
| 1cb80e1ad0 | |||
| 2584c46c28 | |||
| 2ce96415a6 | |||
| 8eded13d96 | |||
| 069143dc05 | |||
| 9d09ce0538 | |||
| d9dd691108 | |||
| f69ebe55ad | |||
| ff604cc6a3 | |||
| 8ccc5bd8f2 | |||
| 02b1f552fd | |||
| f058dc9ed8 | |||
| 2c061ed67a | |||
| 9bfbe3acd8 | |||
| 40bdd26e39 | |||
| b0f8055377 | |||
| 33f4fc9873 | |||
| c90842dd08 | |||
| 310b4cdf75 | |||
| 2208e0db16 | |||
| cf4c403094 | |||
| dd55ffb75c | |||
| d34faf30cc | |||
| 3720a52ecb | |||
| 47de9f8f04 | |||
| 14378812be | |||
| 0070a4686e | |||
| 5c63df28e4 | |||
| e5ea37507c | |||
| 53bd87d792 | |||
| 02252be29d | |||
| 9e9598af5f | |||
| 9dc35b575c | |||
| 3cd24f656b | |||
| 73eac90922 | |||
| 70e5c9f7c6 | |||
| d820a7fe42 | |||
| b9d7a0565f | |||
| ad2486b09f | |||
| 4742043a7e | |||
| 9e56c7e5c9 | |||
| 674fbfa889 | |||
| ae1cc29dc6 | |||
| f1c772ba55 | |||
| 6f6505f6a1 | |||
| af4a4cbc08 | |||
| 40462012ee | |||
| 70514be11f | |||
| 7558dad915 | |||
| 5e9b982ddf | |||
| 17539a564e | |||
| 43aa0bfdc3 | |||
| 7ab4bf3823 | |||
| ae01dc8ef1 | |||
| 187aa1c171 | |||
| 17b1b68ac7 | |||
| 35f15f016d | |||
| 70277e5514 | |||
| 2874688281 | |||
| 826096790d | |||
| a2e66f6667 | |||
| c241032a3b | |||
| 9ca35cbcee | |||
| 9c386026a8 | |||
| 012a9bb7cb | |||
| 563aa3ed74 | |||
| e8ef863861 | |||
| a24cdcb3f0 | |||
| 5314ba6440 | |||
| c465a6ebc7 | |||
| 4e5038eb3e | |||
| 2372359aaa | |||
| 5e0251c2ba | |||
| fd5eeceb4f | |||
| da480aba47 | |||
| 63f4f42e6a | |||
| 8d246dbee0 | |||
| 79517e44ce | |||
| a940607524 | |||
| 0cf1a67e29 | |||
| f4cdb97141 | |||
| 0cfa88ca9a | |||
| 2535237c31 | |||
| 4c86a5ce64 | |||
| c75c7d084a | |||
| dd154c155f | |||
| 0838543745 | |||
| bd1f01f7ee | |||
| 8ab1d91f3c | |||
| 35a7490342 | |||
| d0314aab88 | |||
| 812aba6065 | |||
| 6abcfeeb0f | |||
| 703b18519f | |||
| 1199af0d52 | |||
| 2f1ebebba3 | |||
| 19f4852280 | |||
| 0be07689a7 | |||
| f227ccfd5d | |||
| fd9804a3dc | |||
| 502f2dab11 | |||
| 8e46ae5ce8 | |||
| 8a863cdf54 | |||
| 493e733f0c | |||
| 38ac1b2f2d | |||
| 1394509734 | |||
| 1ffe0da204 | |||
| 46d423a164 | |||
| 7aebc4b11f | |||
| c1dcfdffb1 | |||
| 191558e2d7 | |||
| 912c2eac09 | |||
| 802d20c409 | |||
| 8f75841c85 | |||
| c3f8d8b5a1 | |||
| 79b6991d7b | |||
| 17dc324e85 | |||
| 23479821e3 | |||
| 9396735733 | |||
| 901c330478 | |||
| 354c320329 | |||
| 0ea559e3b8 | |||
| 6fd898d1b3 | |||
| d20c2fe5c5 | |||
| 3585c184cc | |||
| 429544c188 | |||
| 8385ce3021 | |||
| 0b98acfe12 | |||
| acb5ce7108 | |||
| 63b06af6b1 | |||
| e5a85b107f | |||
| e2982a0e47 | |||
| 5396bb970f | |||
| d4937f1b3e | |||
| 1c6f3f8f0d | |||
| 6341548939 | |||
| a91dd68444 | |||
| a8175f49a6 | |||
| 05110b7bdc | |||
| aadcc43dbb | |||
| ff6f398607 | |||
| a30ad0b54a | |||
| ab835937a7 | |||
| b17eb3a584 | |||
| 9c2bc98fd3 | |||
| 96bd27ef0f | |||
| 23351b2046 | |||
| 69bd4218f7 | |||
| f27f001fcb | |||
| be772ecd18 | |||
| 48ba236851 | |||
| 5120566c77 | |||
| 7789857e30 | |||
| 89d85800ab | |||
| 43dcf09747 | |||
| a372594dea | |||
| 414e6dc43e | |||
| f34d146c38 | |||
| d9f5d1d865 | |||
| b15d6bd10a | |||
| 54f621c570 | |||
| d29d981784 | |||
| 3801a8adc0 | |||
| 7d4cb91f39 | |||
| 0f497d1b7a | |||
| 5f1976f341 | |||
| 6036331b25 | |||
| 5129143bcb | |||
| d7d31e4b76 | |||
| b00f855c26 | |||
| 4b0177c8fe | |||
| b11ec85706 | |||
| de48f41184 | |||
| 55bdef9bd2 | |||
| 5cc2bef954 | |||
| 8ce9f08268 | |||
| 6ccaf5e27d | |||
| a24912d01d | |||
| 8ad0f24031 | |||
| 2498655cc5 | |||
| b2ac4b2c65 | |||
| 899c2d9080 | |||
| b4ac59d9d3 | |||
| a5305aa235 | |||
| 680163f8a8 | |||
| 0fdd1df208 | |||
| 9367b7f309 | |||
| f8d15a641a | |||
| d56e488f2d | |||
| cf9fafaba5 | |||
| d5ca09dffc | |||
| b24f51908b | |||
| 15fd0aa989 | |||
| 246b6fcdd6 | |||
| 2b7c79541b | |||
| 7f40cac4b0 | |||
| 7978c8c291 | |||
| fc6ec23ac1 | |||
| 02ec87b036 | |||
| da82ba00e4 | |||
| b041a77cfa | |||
| 9fcd4113b0 | |||
| 762258203c | |||
| 75a4036e45 | |||
| f0d7a09af9 | |||
| 7be3a6b3c5 | |||
| 08bc14ccf2 | |||
| 5781cb0ce5 | |||
| ed2148d634 | |||
| 8e9d44942f | |||
| 8b1f1c0296 | |||
| 4eb9440a42 | |||
| 7cf7270738 | |||
| 9c48707c88 | |||
| ff21a16f7d | |||
| 3b072ca8b4 | |||
| e56355fc17 | |||
| cfae33e7a8 | |||
| c6c4f9ae4b | |||
| 46f7223dd9 | |||
| 75bba51b0b | |||
| 34ed850a23 | |||
| 266ee381d5 | |||
| 15a44d75fb | |||
| f93304b144 | |||
| 5fe583e195 | |||
| 9153fcd04a | |||
| 0f5219ad92 | |||
| 5b90195dfa | |||
| 28c6ac53b7 | |||
| 79e8c8df67 | |||
| f02722b7a7 | |||
| 34e116c18b | |||
| 1a5e00254d | |||
| f36a0eeb95 | |||
| f8b3f5b02f | |||
| dca9df1908 | |||
| f2e1b8cc7a | |||
| 9c4eab9677 | |||
| 470d7d228d | |||
| 71eefc8322 | |||
| ef96ee4a99 | |||
| 35968dfe18 | |||
| b3965c014c | |||
| c3cc615f37 | |||
| bc232a7b6b | |||
| 880098d659 | |||
| 1640c27cd2 | |||
| 96fc0feb4d | |||
| fdae390c52 | |||
| 2cb5643556 | |||
| d689d1a866 | |||
| 76c690c819 | |||
| 3c601180c2 | |||
| 3c83040c4b | |||
| 6147e997ff | |||
| e88bef0023 | |||
| 54a3ca06c0 | |||
| 0cb82a0985 | |||
| b7f8f95725 | |||
| 30276fb5f7 | |||
| f37531ed39 | |||
| fd4ac7c5df | |||
| b8b9f646c6 | |||
| f561f85ebb | |||
| 7cba8e847d | |||
| f8ac6df0cd | |||
| 310e339c39 | |||
| 6b6d97e726 | |||
| 7c910c2d0b | |||
| 1b8f25235c | |||
| f7133168c1 |
+1
-1
@@ -40,6 +40,6 @@ include:
|
||||
- local: '/.gitlab/templates.yml'
|
||||
- local: '/.gitlab/Fedora-Linux-CI.yml'
|
||||
- local: '/.gitlab/Ubuntu-20.04-CI.yml'
|
||||
- local: '/.gitlab/Windows-CI.yml'
|
||||
# - local: '/.gitlab/Windows-CI.yml'
|
||||
- local: '/.gitlab/coverity.yml'
|
||||
- local: '/.gitlab/linux-metadata-validate.yml'
|
||||
|
||||
@@ -493,15 +493,10 @@ void BOARD_ADAPTER::addPadsWithClearance( const FOOTPRINT* aFootprint,
|
||||
{
|
||||
for( PAD* pad : aFootprint->Pads() )
|
||||
{
|
||||
if( !pad->IsOnLayer( aLayerId ) )
|
||||
if( !pad->FlashLayer( aLayerId ) )
|
||||
continue;
|
||||
|
||||
// Skip pad annulus when not connected on this layer (if removing is enabled)
|
||||
if( !pad->FlashLayer( aLayerId ) && IsCopperLayer( aLayerId ) )
|
||||
continue;
|
||||
|
||||
// NPTH pads are not drawn on layers if the
|
||||
// shape size and pos is the same as their hole:
|
||||
// NPTH pads are not drawn on layers if the shape size and pos is the same as their hole:
|
||||
if( aSkipNPTHPadsWihNoCopper && ( pad->GetAttribute() == PAD_ATTRIB::NPTH ) )
|
||||
{
|
||||
if( pad->GetDrillSize() == pad->GetSize() && pad->GetOffset() == wxPoint( 0, 0 ) )
|
||||
@@ -526,19 +521,28 @@ void BOARD_ADAPTER::addPadsWithClearance( const FOOTPRINT* aFootprint,
|
||||
}
|
||||
}
|
||||
|
||||
const bool isPlated = ( ( aLayerId == F_Cu ) && pad->FlashLayer( F_Mask ) ) ||
|
||||
( ( aLayerId == B_Cu ) && pad->FlashLayer( B_Mask ) );
|
||||
|
||||
if( aSkipPlatedPads && isPlated )
|
||||
continue;
|
||||
|
||||
if( aSkipNonPlatedPads && !isPlated )
|
||||
continue;
|
||||
|
||||
wxSize margin( aInflateValue, aInflateValue );
|
||||
|
||||
switch( aLayerId )
|
||||
{
|
||||
case F_Cu:
|
||||
if( aSkipPlatedPads && pad->FlashLayer( F_Mask ) )
|
||||
continue;
|
||||
|
||||
if( aSkipNonPlatedPads && !pad->FlashLayer( F_Mask ) )
|
||||
continue;
|
||||
|
||||
break;
|
||||
|
||||
case B_Cu:
|
||||
if( aSkipPlatedPads && pad->FlashLayer( B_Mask ) )
|
||||
continue;
|
||||
|
||||
if( aSkipNonPlatedPads && !pad->FlashLayer( B_Mask ) )
|
||||
continue;
|
||||
|
||||
break;
|
||||
|
||||
case F_Mask:
|
||||
case B_Mask:
|
||||
margin.x += pad->GetSolderMaskMargin();
|
||||
|
||||
@@ -549,7 +549,6 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
{
|
||||
addPadsWithClearance( footprint, m_platedPadsFront, F_Cu, 0, true, false, true );
|
||||
|
||||
addPadsWithClearance( footprint, m_platedPadsBack, B_Cu, 0, true, false, true );
|
||||
}
|
||||
|
||||
@@ -569,8 +568,8 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||
// Add pads to polygon list
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
{
|
||||
// Note: NPTH pads are not drawn on copper layers when the pad
|
||||
// has same shape as its hole
|
||||
// Note: NPTH pads are not drawn on copper layers when the pad has same shape as
|
||||
// its hole
|
||||
footprint->TransformPadsWithClearanceToPolygon( *layerPoly, curr_layer_id,
|
||||
0, ARC_HIGH_DEF, ERROR_INSIDE,
|
||||
true, renderPlatedPadsAsPlated,
|
||||
|
||||
@@ -374,6 +374,22 @@ OPENGL_RENDER_LIST* RENDER_3D_OPENGL::generateLayerList( const BVH_CONTAINER_2D*
|
||||
}
|
||||
|
||||
|
||||
OPENGL_RENDER_LIST* RENDER_3D_OPENGL::generateEmptyLayerList( PCB_LAYER_ID aLayerId )
|
||||
{
|
||||
float layer_z_bot = 0.0f;
|
||||
float layer_z_top = 0.0f;
|
||||
|
||||
getLayerZPos( aLayerId, layer_z_top, layer_z_bot );
|
||||
|
||||
TRIANGLE_DISPLAY_LIST* layerTriangles = new TRIANGLE_DISPLAY_LIST( 1 );
|
||||
|
||||
// store in a list so it will be latter deleted
|
||||
m_triangles.push_back( layerTriangles );
|
||||
|
||||
return new OPENGL_RENDER_LIST( *layerTriangles, m_circleTexture, layer_z_bot, layer_z_top );
|
||||
}
|
||||
|
||||
|
||||
OPENGL_RENDER_LIST* RENDER_3D_OPENGL::createBoard( const SHAPE_POLY_SET& aBoardPoly,
|
||||
const BVH_CONTAINER_2D* aThroughHoles )
|
||||
{
|
||||
@@ -388,9 +404,8 @@ OPENGL_RENDER_LIST* RENDER_3D_OPENGL::createBoard( const SHAPE_POLY_SET& aBoardP
|
||||
|
||||
if( listBoardObject2d.size() > 0 )
|
||||
{
|
||||
// We will set a unitary Z so it will in future used with transformations
|
||||
// since the board poly will be used not only to draw itself but also the
|
||||
// solder mask layers.
|
||||
// We will set a unitary Z so it will in future used with transformations since the
|
||||
// board poly will be used not only to draw itself but also the solder mask layers.
|
||||
const float layer_z_top = 1.0f;
|
||||
const float layer_z_bot = 0.0f;
|
||||
|
||||
@@ -563,7 +578,7 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
|
||||
const BVH_CONTAINER_2D* container2d = ii.second;
|
||||
|
||||
SHAPE_POLY_SET polyListSubtracted;
|
||||
SHAPE_POLY_SET* aPolyList = nullptr;
|
||||
SHAPE_POLY_SET* polyList = nullptr;
|
||||
|
||||
// Load the vertical (Z axis) component of shapes
|
||||
|
||||
@@ -580,9 +595,8 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
|
||||
{
|
||||
polyListSubtracted.BooleanSubtract( m_boardAdapter.GetThroughHoleOdPolys(),
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
polyListSubtracted.BooleanSubtract(
|
||||
m_boardAdapter.GetOuterNonPlatedThroughHolePoly(),
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
polyListSubtracted.BooleanSubtract( m_boardAdapter.GetOuterNonPlatedThroughHolePoly(),
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
}
|
||||
|
||||
if( m_boardAdapter.GetFlag( FL_SUBTRACT_MASK_FROM_SILK ) )
|
||||
@@ -600,10 +614,10 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
|
||||
}
|
||||
}
|
||||
|
||||
aPolyList = &polyListSubtracted;
|
||||
polyList = &polyListSubtracted;
|
||||
}
|
||||
|
||||
OPENGL_RENDER_LIST* oglList = generateLayerList( container2d, aPolyList, layer_id,
|
||||
OPENGL_RENDER_LIST* oglList = generateLayerList( container2d, polyList, layer_id,
|
||||
&m_boardAdapter.GetThroughHoleIds() );
|
||||
|
||||
if( oglList != nullptr )
|
||||
@@ -626,6 +640,10 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
|
||||
|
||||
m_platedPadsFront = generateLayerList( m_boardAdapter.GetPlatedPadsFront(),
|
||||
&polySubtracted, F_Cu );
|
||||
|
||||
// An entry for F_Cu must exist in m_layers or we'll never look at m_platedPadsFront
|
||||
if( m_layers.count( F_Cu ) == 0 )
|
||||
m_layers[F_Cu] = generateEmptyLayerList( F_Cu );
|
||||
}
|
||||
|
||||
if( m_boardAdapter.GetBackPlatedPadPolys() )
|
||||
@@ -640,6 +658,10 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
|
||||
|
||||
m_platedPadsBack = generateLayerList( m_boardAdapter.GetPlatedPadsBack(),
|
||||
&polySubtracted, B_Cu );
|
||||
|
||||
// An entry for B_Cu must exist in m_layers or we'll never look at m_platedPadsBack
|
||||
if( m_layers.count( B_Cu ) == 0 )
|
||||
m_layers[B_Cu] = generateEmptyLayerList( B_Cu );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -650,6 +650,7 @@ GLuint OPENGL_RENDER_LIST::generate_top_or_bot_seg_ends(
|
||||
|
||||
glDrawArrays( GL_TRIANGLES, 0, aTriangleContainer->GetVertexSize() );
|
||||
|
||||
glBindTexture( GL_TEXTURE_2D, 0 );
|
||||
glDisable( GL_TEXTURE_2D );
|
||||
glDisable( GL_ALPHA_TEST );
|
||||
glDisable( GL_BLEND );
|
||||
|
||||
@@ -504,7 +504,7 @@ void RENDER_3D_OPENGL::setCopperMaterial()
|
||||
void RENDER_3D_OPENGL::setPlatedCopperAndDepthOffset( PCB_LAYER_ID aLayer_id )
|
||||
{
|
||||
glEnable( GL_POLYGON_OFFSET_FILL );
|
||||
glPolygonOffset(-0.1f, -2.0f );
|
||||
glPolygonOffset( -0.1f, -2.0f );
|
||||
setLayerMaterial( aLayer_id );
|
||||
}
|
||||
|
||||
@@ -704,18 +704,16 @@ bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter,
|
||||
{
|
||||
pLayerDispList->DrawAllCameraCulled( m_camera.GetPos().z, drawMiddleSegments );
|
||||
|
||||
// Draw copper plated pads
|
||||
if( ( ( layer_id == F_Cu ) || ( layer_id == B_Cu ) ) &&
|
||||
( m_platedPadsFront || m_platedPadsBack ) )
|
||||
setPlatedCopperAndDepthOffset( layer_id );
|
||||
|
||||
// Draw plated pads
|
||||
if( layer_id == F_Cu && m_platedPadsFront )
|
||||
{
|
||||
setPlatedCopperAndDepthOffset( layer_id );
|
||||
m_platedPadsFront->DrawAllCameraCulled( m_camera.GetPos().z,
|
||||
drawMiddleSegments );
|
||||
}
|
||||
else if( layer_id == B_Cu && m_platedPadsBack )
|
||||
{
|
||||
setPlatedCopperAndDepthOffset( layer_id );
|
||||
m_platedPadsBack->DrawAllCameraCulled( m_camera.GetPos().z,
|
||||
drawMiddleSegments );
|
||||
}
|
||||
@@ -751,16 +749,10 @@ bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter,
|
||||
viasHolesLayer,
|
||||
m_antiBoard );
|
||||
|
||||
// Draw copper plated pads
|
||||
|
||||
if( ( ( layer_id == F_Cu ) || ( layer_id == B_Cu ) ) &&
|
||||
( m_platedPadsFront || m_platedPadsBack ) )
|
||||
{
|
||||
setPlatedCopperAndDepthOffset( layer_id );
|
||||
}
|
||||
|
||||
// Draw plated pads
|
||||
if( layer_id == F_Cu && m_platedPadsFront )
|
||||
{
|
||||
setPlatedCopperAndDepthOffset( layer_id );
|
||||
m_platedPadsFront->DrawAllCameraCulledSubtractLayer(
|
||||
drawMiddleSegments,
|
||||
m_outerThroughHoles,
|
||||
@@ -769,6 +761,7 @@ bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter,
|
||||
}
|
||||
else if( layer_id == B_Cu && m_platedPadsBack )
|
||||
{
|
||||
setPlatedCopperAndDepthOffset( layer_id );
|
||||
m_platedPadsBack->DrawAllCameraCulledSubtractLayer(
|
||||
drawMiddleSegments,
|
||||
m_outerThroughHoles,
|
||||
@@ -785,21 +778,16 @@ bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter,
|
||||
m_outerThroughHoles,
|
||||
m_antiBoard );
|
||||
|
||||
// Draw copper plated pads
|
||||
if( ( ( layer_id == F_Cu ) || ( layer_id == B_Cu ) ) &&
|
||||
( m_platedPadsFront || m_platedPadsBack ) )
|
||||
{
|
||||
setPlatedCopperAndDepthOffset( layer_id );
|
||||
}
|
||||
|
||||
if( layer_id == F_Cu && m_platedPadsFront )
|
||||
{
|
||||
setPlatedCopperAndDepthOffset( layer_id );
|
||||
m_platedPadsFront->DrawAllCameraCulledSubtractLayer( drawMiddleSegments,
|
||||
m_outerThroughHoles,
|
||||
m_antiBoard );
|
||||
}
|
||||
else if( layer_id == B_Cu && m_platedPadsBack )
|
||||
{
|
||||
setPlatedCopperAndDepthOffset( layer_id );
|
||||
m_platedPadsBack->DrawAllCameraCulledSubtractLayer( drawMiddleSegments,
|
||||
m_outerThroughHoles,
|
||||
m_antiBoard );
|
||||
|
||||
@@ -84,6 +84,8 @@ private:
|
||||
PCB_LAYER_ID aLayerId,
|
||||
const BVH_CONTAINER_2D* aThroughHoles = nullptr );
|
||||
|
||||
OPENGL_RENDER_LIST* generateEmptyLayerList( PCB_LAYER_ID aLayerId );
|
||||
|
||||
void addTopAndBottomTriangles( TRIANGLE_DISPLAY_LIST* aDst, const SFVEC2F& v0,
|
||||
const SFVEC2F& v1, const SFVEC2F& v2, float top, float bot );
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <kiface_base.h>
|
||||
#include <tools/eda_3d_controller.h>
|
||||
#include "eda_3d_actions.h"
|
||||
#include "dialogs/panel_preview_3d_model.h"
|
||||
#include <3d_rendering/opengl/render_3d_opengl.h>
|
||||
|
||||
|
||||
@@ -113,10 +114,36 @@ int EDA_3D_CONTROLLER::Main( const TOOL_EVENT& aEvent )
|
||||
// Main loop: keep receiving events
|
||||
while( TOOL_EVENT* evt = Wait() )
|
||||
{
|
||||
if( evt->IsClick( BUT_RIGHT ) )
|
||||
if( evt->IsCancelInteractive() )
|
||||
{
|
||||
wxWindow* canvas = m_toolMgr->GetToolHolder()->GetToolCanvas();
|
||||
wxWindow* topLevelParent = canvas->GetParent();
|
||||
|
||||
while( topLevelParent && !topLevelParent->IsTopLevel() )
|
||||
topLevelParent = topLevelParent->GetParent();
|
||||
|
||||
if( topLevelParent && dynamic_cast<DIALOG_SHIM*>( topLevelParent ) )
|
||||
{
|
||||
DIALOG_SHIM* dialog = static_cast<DIALOG_SHIM*>( topLevelParent );
|
||||
|
||||
if( dialog->IsQuasiModal() )
|
||||
dialog->EndQuasiModal( wxID_CANCEL );
|
||||
else
|
||||
dialog->EndModal( wxID_CANCEL );
|
||||
}
|
||||
else
|
||||
{
|
||||
evt->SetPassEvent();
|
||||
}
|
||||
}
|
||||
else if( evt->IsClick( BUT_RIGHT ) )
|
||||
{
|
||||
m_menu.ShowContextMenu();
|
||||
}
|
||||
else
|
||||
{
|
||||
evt->SetPassEvent();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2015-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2015-2022 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
|
||||
@@ -124,8 +124,10 @@ PANEL_PREVIEW_3D_MODEL::PANEL_PREVIEW_3D_MODEL( wxWindow* aParent, PCB_BASE_FRAM
|
||||
m_SizerPanelView->Add( m_previewPane, 1, wxEXPAND, 5 );
|
||||
|
||||
for( wxEventType eventType : { wxEVT_MENU_OPEN, wxEVT_MENU_CLOSE, wxEVT_MENU_HIGHLIGHT } )
|
||||
{
|
||||
Connect( eventType, wxMenuEventHandler( PANEL_PREVIEW_3D_MODEL::OnMenuEvent ), nullptr,
|
||||
this );
|
||||
}
|
||||
|
||||
#ifdef __WXOSX__
|
||||
// Call layout once to get the proper button sizes after the bitmaps have been set
|
||||
|
||||
+22
-7
@@ -156,6 +156,11 @@ option( KICAD_STEP_EXPORT_LIB
|
||||
"Build and use kicad2step as a library, meant for debugging"
|
||||
OFF )
|
||||
|
||||
cmake_dependent_option( KICAD_WIN32_VERIFY_CODESIGN
|
||||
"When enabled, verifies the code signing signature of certain DLLs loaded during runtime."
|
||||
OFF "WIN32"
|
||||
OFF )
|
||||
|
||||
# Global setting: exports are explicit
|
||||
set( CMAKE_CXX_VISIBILITY_PRESET "hidden" )
|
||||
set( CMAKE_VISIBILITY_INLINES_HIDDEN ON )
|
||||
@@ -177,6 +182,10 @@ if( KICAD_GAL_PROFILE )
|
||||
add_definitions( -DKICAD_GAL_PROFILE )
|
||||
endif()
|
||||
|
||||
if( KICAD_WIN32_VERIFY_CODESIGN )
|
||||
add_definitions( -DKICAD_WIN32_VERIFY_CODESIGN )
|
||||
endif()
|
||||
|
||||
# Ensure DEBUG is defined for all platforms in Debug builds
|
||||
# change to add_compile_definitions() after minimum required CMake version is 3.12
|
||||
set_property( DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$<CONFIG:Debug>:DEBUG> )
|
||||
@@ -490,9 +499,10 @@ endif()
|
||||
# KIFACE_SUFFIX is the file extension used for top level program modules which
|
||||
# implement the KIFACE interface. A valid suffix starts with a period '.'.
|
||||
|
||||
if( false )
|
||||
# This is the eventual situation near milestone C) of modular-kicad blueprint.
|
||||
# Until then we use .kiface extension so we don't collide with python DSO.
|
||||
if( WIN32 )
|
||||
# We use .kiface extension so we don't collide with python DSO. (Linux/mac issue?)
|
||||
# Windows works fine with the native dll extension
|
||||
# which also resolves metadata issues because windows wants to see the dll extension
|
||||
set( KIFACE_SUFFIX ${CMAKE_SHARED_MODULE_SUFFIX} )
|
||||
else()
|
||||
# Temporary situation until we can dovetail the python DSO into the kiface DSO.
|
||||
@@ -838,9 +848,11 @@ if( UNIX AND NOT APPLE AND KICAD_SCRIPTING_WXPYTHON )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
message( STATUS "Found ${WXPYTHON_FLAVOR} "
|
||||
"${WXPYTHON_VERSION}/${WXPYTHON_TOOLKIT} "
|
||||
"(wxWidgets ${WXPYTHON_WXVERSION})" )
|
||||
if( WXPYTHON_FLAVOR )
|
||||
message( STATUS "Found wxPython ${WXPYTHON_FLAVOR} "
|
||||
"${WXPYTHON_VERSION}/${WXPYTHON_TOOLKIT} "
|
||||
"(wxWidgets ${WXPYTHON_WXVERSION})" )
|
||||
endif()
|
||||
|
||||
#
|
||||
# Find wxWidgets library, required
|
||||
@@ -1000,7 +1012,10 @@ add_subdirectory( cvpcb ) # must be after pcbnew
|
||||
add_subdirectory( kicad ) # should follow pcbnew, eeschema
|
||||
add_subdirectory( tools )
|
||||
add_subdirectory( utils )
|
||||
add_subdirectory( qa )
|
||||
|
||||
if( KICAD_BUILD_QA_TESTS )
|
||||
add_subdirectory( qa )
|
||||
endif()
|
||||
|
||||
# Demos
|
||||
if( KICAD_INSTALL_DEMOS )
|
||||
|
||||
@@ -46,7 +46,7 @@ if( CMAKE_MATCH_COUNT EQUAL 3 )
|
||||
|
||||
set( KICAD_WIN32_RC_FILEVER_STR "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}.${KICAD_GIT_REV}\\0" )
|
||||
set( KICAD_WIN32_RC_FILEVER "${CMAKE_MATCH_1}, ${CMAKE_MATCH_2}, ${CMAKE_MATCH_3}, ${KICAD_GIT_REV}" )
|
||||
set( KICAD_WIN32_RC_PRODVER_STR "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}\\0" )
|
||||
set( KICAD_WIN32_RC_PRODVER_STR "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}\\0" )
|
||||
set( KICAD_WIN32_RC_PRODVER "${CMAKE_MATCH_1}, ${CMAKE_MATCH_2}, ${CMAKE_MATCH_3}, ${KICAD_GIT_REV}" )
|
||||
else()
|
||||
message( FATAL_ERROR "Unable to extract major, minor and patch version string" )
|
||||
|
||||
@@ -231,11 +231,7 @@ endif()
|
||||
#=====================================================================
|
||||
if(wxWidgets_FIND_STYLE STREQUAL "win32")
|
||||
# Useful common wx libs needed by almost all components.
|
||||
if(VCPKG_TOOLCHAIN)
|
||||
set(wxWidgets_COMMON_LIBRARIES libpng16 tiff jpeg zlib libexpat)
|
||||
else()
|
||||
set(wxWidgets_COMMON_LIBRARIES png tiff jpeg zlib regex expat)
|
||||
endif()
|
||||
set(wxWidgets_COMMON_LIBRARIES png tiff jpeg zlib regex expat)
|
||||
|
||||
# DEPRECATED: Use find_package(wxWidgets COMPONENTS mono) instead.
|
||||
if(NOT wxWidgets_FIND_COMPONENTS)
|
||||
@@ -258,22 +254,24 @@ if(wxWidgets_FIND_STYLE STREQUAL "win32")
|
||||
#-------------------------------------------------------------------
|
||||
#
|
||||
# Get filename components for a configuration. For example,
|
||||
# if _CONFIGURATION = mswunivud, then _UNV=univ, _UCD=u _DBG=d
|
||||
# if _CONFIGURATION = mswu, then _UNV="", _UCD=u _DBG=""
|
||||
# if _CONFIGURATION = mswunivud, then _PF="msw", _UNV=univ, _UCD=u _DBG=d
|
||||
# if _CONFIGURATION = mswu, then _PF="msw", _UNV="", _UCD=u _DBG=""
|
||||
#
|
||||
macro(WX_GET_NAME_COMPONENTS _CONFIGURATION _UNV _UCD _DBG)
|
||||
macro(WX_GET_NAME_COMPONENTS _CONFIGURATION _PF _UNV _UCD _DBG)
|
||||
DBG_MSG_V(${_CONFIGURATION})
|
||||
string(REGEX MATCH "univ" ${_UNV} "${_CONFIGURATION}")
|
||||
string(REGEX REPLACE "msw.*(u)[d]*$" "u" ${_UCD} "${_CONFIGURATION}")
|
||||
string(REGEX REPLACE "[msw|qt].*(u)[d]*$" "u" ${_UCD} "${_CONFIGURATION}")
|
||||
if(${_UCD} STREQUAL ${_CONFIGURATION})
|
||||
set(${_UCD} "")
|
||||
endif()
|
||||
string(REGEX MATCH "d$" ${_DBG} "${_CONFIGURATION}")
|
||||
string(REGEX MATCH "^[msw|qt]*" ${_PF} "${_CONFIGURATION}")
|
||||
endmacro()
|
||||
|
||||
#
|
||||
# Find libraries associated to a configuration.
|
||||
#
|
||||
macro(WX_FIND_LIBS _UNV _UCD _DBG)
|
||||
macro(WX_FIND_LIBS _PF _UNV _UCD _DBG)
|
||||
DBG_MSG_V("m_unv = ${_UNV}")
|
||||
DBG_MSG_V("m_ucd = ${_UCD}")
|
||||
DBG_MSG_V("m_dbg = ${_DBG}")
|
||||
@@ -286,7 +284,6 @@ if(wxWidgets_FIND_STYLE STREQUAL "win32")
|
||||
NAMES
|
||||
wx${LIB}${_UCD}${_DBG} # for regex
|
||||
wx${LIB}${_DBG}
|
||||
${LIB}${_DBG} # vcpkg libraries aren't specific to wx
|
||||
PATHS ${WX_LIB_DIR}
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
@@ -326,13 +323,13 @@ if(wxWidgets_FIND_STYLE STREQUAL "win32")
|
||||
# Find wxWidgets monolithic library.
|
||||
find_library(WX_mono${_DBG}
|
||||
NAMES
|
||||
wxmsw${_UNV}31${_UCD}${_DBG}
|
||||
wxmsw${_UNV}30${_UCD}${_DBG}
|
||||
wxmsw${_UNV}29${_UCD}${_DBG}
|
||||
wxmsw${_UNV}28${_UCD}${_DBG}
|
||||
wxmsw${_UNV}27${_UCD}${_DBG}
|
||||
wxmsw${_UNV}26${_UCD}${_DBG}
|
||||
wxmsw${_UNV}25${_UCD}${_DBG}
|
||||
wx${_PF}${_UNV}31${_UCD}${_DBG}
|
||||
wx${_PF}${_UNV}30${_UCD}${_DBG}
|
||||
wx${_PF}${_UNV}29${_UCD}${_DBG}
|
||||
wx${_PF}${_UNV}28${_UCD}${_DBG}
|
||||
wx${_PF}${_UNV}27${_UCD}${_DBG}
|
||||
wx${_PF}${_UNV}26${_UCD}${_DBG}
|
||||
wx${_PF}${_UNV}25${_UCD}${_DBG}
|
||||
PATHS ${WX_LIB_DIR}
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
@@ -340,16 +337,16 @@ if(wxWidgets_FIND_STYLE STREQUAL "win32")
|
||||
|
||||
# Find wxWidgets multilib libraries.
|
||||
foreach(LIB core adv aui html media xrc dbgrid gl qa richtext
|
||||
webview stc ribbon propgrid)
|
||||
stc ribbon propgrid webview)
|
||||
find_library(WX_${LIB}${_DBG}
|
||||
NAMES
|
||||
wxmsw${_UNV}31${_UCD}${_DBG}_${LIB}
|
||||
wxmsw${_UNV}30${_UCD}${_DBG}_${LIB}
|
||||
wxmsw${_UNV}29${_UCD}${_DBG}_${LIB}
|
||||
wxmsw${_UNV}28${_UCD}${_DBG}_${LIB}
|
||||
wxmsw${_UNV}27${_UCD}${_DBG}_${LIB}
|
||||
wxmsw${_UNV}26${_UCD}${_DBG}_${LIB}
|
||||
wxmsw${_UNV}25${_UCD}${_DBG}_${LIB}
|
||||
wx${_PF}${_UNV}31${_UCD}${_DBG}_${LIB}
|
||||
wx${_PF}${_UNV}30${_UCD}${_DBG}_${LIB}
|
||||
wx${_PF}${_UNV}29${_UCD}${_DBG}_${LIB}
|
||||
wx${_PF}${_UNV}28${_UCD}${_DBG}_${LIB}
|
||||
wx${_PF}${_UNV}27${_UCD}${_DBG}_${LIB}
|
||||
wx${_PF}${_UNV}26${_UCD}${_DBG}_${LIB}
|
||||
wx${_PF}${_UNV}25${_UCD}${_DBG}_${LIB}
|
||||
PATHS ${WX_LIB_DIR}
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
@@ -515,74 +512,6 @@ if(wxWidgets_FIND_STYLE STREQUAL "win32")
|
||||
set(WX_LIB_DIR_PREFIX vc)
|
||||
endif()
|
||||
|
||||
if(VCPKG_TOOLCHAIN)
|
||||
set(wxWidgets_FOUND TRUE)
|
||||
find_path(wxWidgets_ROOT_DIR
|
||||
NAMES include/wx/wx.h
|
||||
PATHS
|
||||
ENV wxWidgets_ROOT_DIR
|
||||
DOC "wxWidgets base/installation directory"
|
||||
)
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(wxWidgets_LIB_DIR ${wxWidgets_ROOT_DIR}/debug/lib)
|
||||
set(wxWidgets_CONFIGURATION mswud)
|
||||
else()
|
||||
set(wxWidgets_LIB_DIR ${wxWidgets_ROOT_DIR}/lib)
|
||||
set(wxWidgets_CONFIGURATION mswu)
|
||||
endif()
|
||||
|
||||
set(wxWidgets_BIN_DIR ${wxWidgets_ROOT_DIR}/bin)
|
||||
set(wxWidgets_INCLUDE_DIR ${wxWidgets_ROOT_DIR}/include)
|
||||
file(GLOB DLL ${wxWidgets_BIN_DIR}/wxmsw*.dll)
|
||||
if (DLL)
|
||||
set(wxWidgets_DEFINITIONS WXUSINGDLL)
|
||||
DBG_MSG_V("detected SHARED/DLL tree wxWidgets_LIB_DIR=${wxWidgets_LIB_DIR}")
|
||||
endif ()
|
||||
set(WX_ROOT_DIR ${wxWidgets_ROOT_DIR})
|
||||
set(WX_LIB_DIR ${wxWidgets_LIB_DIR}) # needed by macro
|
||||
set(WX_CONFIGURATION_LIST ${wxWidgets_CONFIGURATION})
|
||||
|
||||
# Set wxWidgets lib setup include directory.
|
||||
if (EXISTS ${wxWidgets_INCLUDE_DIR}/wx/setup.h)
|
||||
set(wxWidgets_INCLUDE_DIRS ${wxWidgets_INCLUDE_DIR})
|
||||
else ()
|
||||
DBG_MSG("wxWidgets_FOUND FALSE because ${wxWidgets_INCLUDE_DIR}/wx/setup.h does not exists.")
|
||||
set(wxWidgets_FOUND FALSE)
|
||||
endif ()
|
||||
|
||||
# Set wxWidgets main include directory.
|
||||
if (EXISTS ${wxWidgets_ROOT_DIR}/include/wx/wx.h)
|
||||
list(APPEND wxWidgets_INCLUDE_DIRS ${wxWidgets_ROOT_DIR}/include)
|
||||
else ()
|
||||
DBG_MSG("wxWidgets_FOUND FALSE because wxWidgets_ROOT_DIR=${wxWidgets_ROOT_DIR} has no ${wxWidgets_ROOT_DIR}/include/wx/wx.h")
|
||||
set(wxWidgets_FOUND FALSE)
|
||||
endif ()
|
||||
|
||||
DBG_MSG_V("WX_CONFIGURATION_LIST=${WX_CONFIGURATION_LIST}")
|
||||
|
||||
|
||||
# Get configuration parameters from the name.
|
||||
WX_GET_NAME_COMPONENTS(${wxWidgets_CONFIGURATION} UNV UCD DBG)
|
||||
|
||||
|
||||
# Find wxWidgets libraries.
|
||||
WX_FIND_LIBS("${UNV}" "${UCD}" "${DBG}")
|
||||
if (WX_USE_REL_AND_DBG)
|
||||
WX_FIND_LIBS("${UNV}" "${UCD}" "d")
|
||||
endif ()
|
||||
|
||||
# Settings for requested libs (i.e., include dir, libraries, etc.).
|
||||
WX_SET_LIBRARIES(wxWidgets_FIND_COMPONENTS "${DBG}")
|
||||
|
||||
# Add necessary definitions for unicode builds
|
||||
if ("${UCD}" STREQUAL "u")
|
||||
list(APPEND wxWidgets_DEFINITIONS UNICODE _UNICODE)
|
||||
endif ()
|
||||
|
||||
# Add necessary definitions for debug builds
|
||||
set(wxWidgets_DEFINITIONS_DEBUG _DEBUG __WXDEBUG__)
|
||||
|
||||
else()
|
||||
if(BUILD_SHARED_LIBS)
|
||||
find_path(wxWidgets_LIB_DIR
|
||||
NAMES
|
||||
@@ -617,7 +546,6 @@ if(wxWidgets_FIND_STYLE STREQUAL "win32")
|
||||
DOC "Path to wxWidgets libraries"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# If wxWidgets_LIB_DIR changed, clear all libraries.
|
||||
@@ -675,7 +603,7 @@ if(wxWidgets_FIND_STYLE STREQUAL "win32")
|
||||
endif()
|
||||
|
||||
# Get configuration parameters from the name.
|
||||
WX_GET_NAME_COMPONENTS(${wxWidgets_CONFIGURATION} UNV UCD DBG)
|
||||
WX_GET_NAME_COMPONENTS(${wxWidgets_CONFIGURATION} PF UNV UCD DBG)
|
||||
|
||||
# Set wxWidgets lib setup include directory.
|
||||
if(EXISTS ${WX_LIB_DIR}/${wxWidgets_CONFIGURATION}/wx/setup.h)
|
||||
@@ -695,9 +623,9 @@ if(wxWidgets_FIND_STYLE STREQUAL "win32")
|
||||
endif()
|
||||
|
||||
# Find wxWidgets libraries.
|
||||
WX_FIND_LIBS("${UNV}" "${UCD}" "${DBG}")
|
||||
WX_FIND_LIBS("${PF}" "${UNV}" "${UCD}" "${DBG}")
|
||||
if(WX_USE_REL_AND_DBG)
|
||||
WX_FIND_LIBS("${UNV}" "${UCD}" "d")
|
||||
WX_FIND_LIBS("${PF}" "${UNV}" "${UCD}" "d")
|
||||
endif()
|
||||
|
||||
# Settings for requested libs (i.e., include dir, libraries, etc.).
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
# KiCad.
|
||||
#
|
||||
# Note: This version string should follow the semantic versioning system
|
||||
set( KICAD_SEMANTIC_VERSION "6.0.2" )
|
||||
set( KICAD_SEMANTIC_VERSION "6.0.5" )
|
||||
|
||||
# Default the version to the semantic version.
|
||||
# This is overridden by the git repository tag though (if using git)
|
||||
|
||||
@@ -16,9 +16,6 @@ KiCad uses a host of CI resources.
|
||||
|
||||
GitLab CI pipeline status can be viewed for Linux and Windows builds of the latest commits.
|
||||
|
||||
Additional status is available for builds:
|
||||
[<img alt="Jenkins" src="https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fjenkins.simonrichter.eu%2Fjob%2Fwindows-kicad-ps-pipeline%2F&label=Windows%2C%20MSVC%Nightly&style=plastic">](https://jenkins.simonrichter.eu/job/windows-kicad-ps-pipeline/)
|
||||
|
||||
## Release status
|
||||
[](https://repology.org/project/kicad/versions)
|
||||
[](https://repology.org/metapackage/kicad/versions)
|
||||
|
||||
+28
-28
@@ -266,12 +266,12 @@ ADVANCED_CFG::ADVANCED_CFG()
|
||||
m_DrawArcAccuracy = 10.0;
|
||||
m_DrawArcCenterMaxAngle = 50.0;
|
||||
m_MaxTangentAngleDeviation = 1.0;
|
||||
m_MaxTrackLengthToKeep = 0.0001;
|
||||
m_MaxTrackLengthToKeep = 0.0005;
|
||||
m_ExtraZoneDisplayModes = false;
|
||||
m_DrawTriangulationOutlines = false;
|
||||
|
||||
m_ExtraClearance = 0.0001;
|
||||
m_DRCEpsilon = 0.0001; // 0.1um is small enough not to materially violate
|
||||
m_ExtraClearance = 0.0005;
|
||||
m_DRCEpsilon = 0.0005; // 0.5um is small enough not to materially violate
|
||||
// any constraints.
|
||||
|
||||
m_HoleWallThickness = 0.020; // IPC-6012 says 15-18um; Cadence says at least
|
||||
@@ -334,83 +334,83 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg )
|
||||
std::vector<PARAM_CFG*> configParams;
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::RealtimeConnectivity,
|
||||
&m_RealTimeConnectivity, true ) );
|
||||
&m_RealTimeConnectivity, m_RealTimeConnectivity ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::ExtraFillMargin,
|
||||
&m_ExtraClearance, 0.0005, 0.0, 1.0 ) );
|
||||
&m_ExtraClearance, m_ExtraClearance, 0.0, 1.0 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::DRCEpsilon,
|
||||
&m_DRCEpsilon, 0.0005, 0.0, 1.0 ) );
|
||||
&m_DRCEpsilon, m_DRCEpsilon, 0.0, 1.0 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::HoleWallThickness,
|
||||
&m_HoleWallThickness, 0.020, 0.0, 1.0 ) );
|
||||
&m_HoleWallThickness, m_HoleWallThickness, 0.0, 1.0 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::CoroutineStackSize,
|
||||
&m_CoroutineStackSize, AC_STACK::default_stack,
|
||||
AC_STACK::min_stack, AC_STACK::max_stack ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ShowRouterDebugGraphics,
|
||||
&m_ShowRouterDebugGraphics, false ) );
|
||||
&m_ShowRouterDebugGraphics, m_ShowRouterDebugGraphics ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::CompactFileSave,
|
||||
&m_CompactSave, false ) );
|
||||
&m_CompactSave, m_CompactSave ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::DrawArcAccuracy,
|
||||
&m_DrawArcAccuracy, 10.0, 0.0, 100000.0 ) );
|
||||
&m_DrawArcAccuracy, m_DrawArcAccuracy, 0.0, 100000.0 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::DrawArcCenterStartEndMaxAngle,
|
||||
&m_DrawArcCenterMaxAngle, 50.0, 0.0, 100000.0 ) );
|
||||
&m_DrawArcCenterMaxAngle, m_DrawArcCenterMaxAngle, 0.0, 100000.0 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::MaxTangentTrackAngleDeviation,
|
||||
&m_MaxTangentAngleDeviation, 1.0, 0.0, 90.0 ) );
|
||||
&m_MaxTangentAngleDeviation, m_MaxTangentAngleDeviation, 0.0, 90.0 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::MaxTrackLengthToKeep,
|
||||
&m_MaxTrackLengthToKeep, 0.0005, 0.0, 1.0 ) );
|
||||
&m_MaxTrackLengthToKeep, m_MaxTrackLengthToKeep, 0.0, 1.0 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ExtraZoneDisplayModes,
|
||||
&m_ExtraZoneDisplayModes, false ) );
|
||||
&m_ExtraZoneDisplayModes, m_ExtraZoneDisplayModes ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::StrokeTriangulation,
|
||||
&m_DrawTriangulationOutlines, false ) );
|
||||
&m_DrawTriangulationOutlines, m_DrawTriangulationOutlines ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::MinPlotPenWidth,
|
||||
&m_MinPlotPenWidth, 0.0212, 0.0, 1.0 ) );
|
||||
&m_MinPlotPenWidth, m_MinPlotPenWidth, 0.0, 1.0 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::DebugZoneFiller,
|
||||
&m_DebugZoneFiller, false ) );
|
||||
&m_DebugZoneFiller, m_DebugZoneFiller ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::DebugPDFWriter,
|
||||
&m_DebugPDFWriter, false ) );
|
||||
&m_DebugPDFWriter, m_DebugPDFWriter ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::SmallDrillMarkSize,
|
||||
&m_SmallDrillMarkSize, 0.35, 0.0, 3.0 ) );
|
||||
&m_SmallDrillMarkSize, m_SmallDrillMarkSize, 0.0, 3.0 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::HotkeysDumper,
|
||||
&m_HotkeysDumper, false ) );
|
||||
&m_HotkeysDumper, m_HotkeysDumper ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::DrawBoundingBoxes,
|
||||
&m_DrawBoundingBoxes, false ) );
|
||||
&m_DrawBoundingBoxes, m_DrawBoundingBoxes ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ShowPcbnewExportNetlist,
|
||||
&m_ShowPcbnewExportNetlist, false ) );
|
||||
&m_ShowPcbnewExportNetlist, m_ShowPcbnewExportNetlist ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::Skip3DModelFileCache,
|
||||
&m_Skip3DModelFileCache, false ) );
|
||||
&m_Skip3DModelFileCache, m_Skip3DModelFileCache ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::Skip3DModelMemoryCache,
|
||||
&m_Skip3DModelMemoryCache, false ) );
|
||||
&m_Skip3DModelMemoryCache, m_Skip3DModelMemoryCache ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::HideVersionFromTitle,
|
||||
&m_HideVersionFromTitle, false ) );
|
||||
&m_HideVersionFromTitle, m_HideVersionFromTitle ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ShowRepairSchematic,
|
||||
&m_ShowRepairSchematic, false ) );
|
||||
&m_ShowRepairSchematic, m_ShowRepairSchematic ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ShowEventCounters,
|
||||
&m_ShowEventCounters, false ) );
|
||||
&m_ShowEventCounters, m_ShowEventCounters ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::AllowManualCanvasScale,
|
||||
&m_AllowManualCanvasScale, false ) );
|
||||
&m_AllowManualCanvasScale, m_AllowManualCanvasScale ) );
|
||||
|
||||
// Special case for trace mask setting...we just grab them and set them immediately
|
||||
// Because we even use wxLogTrace inside of advanced config
|
||||
|
||||
@@ -158,7 +158,6 @@ wxImage BITMAP_STORE::getImage( BITMAPS aBitmapId, int aHeight )
|
||||
|
||||
wxMemoryInputStream is( data, count );
|
||||
wxImage image( is, wxBITMAP_TYPE_PNG );
|
||||
wxBitmap bitmap( image );
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2009 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2009 Jean-Pierre Charras, jean-pierre.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2018 CERN
|
||||
* Author: Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
@@ -70,6 +70,7 @@ BOARD_PRINTOUT::BOARD_PRINTOUT( const BOARD_PRINTOUT_SETTINGS& aParams,
|
||||
m_settings( aParams )
|
||||
{
|
||||
m_view = aView;
|
||||
m_gerbviewPrint = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,12 +86,12 @@ void BOARD_PRINTOUT::GetPageInfo( int* minPage, int* maxPage, int* selPageFrom,
|
||||
|
||||
void BOARD_PRINTOUT::DrawPage( const wxString& aLayerName, int aPageNum, int aPageCount )
|
||||
{
|
||||
auto dc = GetDC();
|
||||
wxDC* dc = GetDC();
|
||||
KIGFX::GAL_DISPLAY_OPTIONS options;
|
||||
auto galPrint = KIGFX::GAL_PRINT::Create( options, dc );
|
||||
auto gal = galPrint->GetGAL();
|
||||
auto printCtx = galPrint->GetPrintCtx();
|
||||
auto painter = getPainter( gal );
|
||||
std::unique_ptr<KIGFX::GAL_PRINT> galPrint = KIGFX::GAL_PRINT::Create( options, dc );
|
||||
KIGFX::GAL* gal = galPrint->GetGAL();
|
||||
KIGFX::PRINT_CONTEXT* printCtx = galPrint->GetPrintCtx();
|
||||
std::unique_ptr<KIGFX::PAINTER> painter = getPainter( gal );
|
||||
std::unique_ptr<KIGFX::VIEW> view( m_view->DataReference() );
|
||||
|
||||
// Target paper size
|
||||
@@ -175,6 +176,11 @@ void BOARD_PRINTOUT::DrawPage( const wxString& aLayerName, int aPageNum, int aPa
|
||||
gal->SetClearColor( dstSettings->GetBackgroundColor() );
|
||||
gal->ClearScreen();
|
||||
|
||||
if( m_gerbviewPrint )
|
||||
// Mandatory in Gerbview to use the same order for printing as for screen redraw
|
||||
// due to negative objects that need a specific order
|
||||
view->UseDrawPriority( true );
|
||||
|
||||
{
|
||||
KIGFX::GAL_DRAWING_CONTEXT ctx( gal );
|
||||
view->Redraw();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2010 Rafael Sokolowski <Rafael.Sokolowski@web.de>
|
||||
* Copyright (C) 2010-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2010-2022 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
|
||||
@@ -64,7 +64,7 @@ static void buildKicadAboutBanner( EDA_BASE_FRAME* aParent, ABOUT_APP_INFO& aInf
|
||||
aInfo.SetAppName( Pgm().App().GetAppName() );
|
||||
|
||||
/* Copyright information */
|
||||
aInfo.SetCopyright( "(C) 1992-2021 KiCad Developers Team" );
|
||||
aInfo.SetCopyright( "(C) 1992-2022 KiCad Developers Team" );
|
||||
|
||||
/* KiCad build version */
|
||||
wxString version;
|
||||
|
||||
@@ -419,7 +419,7 @@ void DIALOG_ABOUT::createNotebookHtmlPage( wxNotebook* aParent, const wxString&
|
||||
wxStaticText* DIALOG_ABOUT::wxStaticTextRef( wxScrolledWindow* aParent, const wxString& aReference )
|
||||
{
|
||||
wxStaticText* text = new wxStaticText( aParent, wxID_ANY,
|
||||
wxT( "(wxT( " ) + aReference + wxT( " ))" ) );
|
||||
wxT( "(" ) + aReference + wxT( ")" ) );
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
@@ -213,6 +213,7 @@ void EDA_DRAW_PANEL_GAL::DoRePaint()
|
||||
try
|
||||
{
|
||||
cntUpd.Start();
|
||||
|
||||
try
|
||||
{
|
||||
m_view->UpdateItems();
|
||||
@@ -229,9 +230,7 @@ void EDA_DRAW_PANEL_GAL::DoRePaint()
|
||||
cntUpd.Stop();
|
||||
|
||||
cntCtx.Start();
|
||||
int cookie = rand();
|
||||
m_gal->LockContext( cookie );
|
||||
m_gal->BeginDrawing();
|
||||
KIGFX::GAL_DRAWING_CONTEXT ctx( m_gal );
|
||||
cntCtx.Stop();
|
||||
|
||||
if( m_view->IsTargetDirty( KIGFX::TARGET_OVERLAY )
|
||||
@@ -273,9 +272,6 @@ void EDA_DRAW_PANEL_GAL::DoRePaint()
|
||||
m_gal->DrawCursor( m_viewControls->GetCursorPosition() );
|
||||
|
||||
cntCtxDestroy.Start();
|
||||
m_gal->EndDrawing();
|
||||
m_gal->UnlockContext( cookie );
|
||||
cntCtxDestroy.Stop();
|
||||
}
|
||||
catch( std::exception& err )
|
||||
{
|
||||
@@ -294,6 +290,9 @@ void EDA_DRAW_PANEL_GAL::DoRePaint()
|
||||
}
|
||||
}
|
||||
|
||||
// ctx goes out of scope here so destructor would be called
|
||||
cntCtxDestroy.Stop();
|
||||
|
||||
|
||||
if( isDirty )
|
||||
{
|
||||
|
||||
@@ -152,9 +152,8 @@ wxString DS_DRAW_ITEM_LIST::BuildFullText( const wxString& aTextbase )
|
||||
}
|
||||
else if( m_titleBlock )
|
||||
{
|
||||
m_titleBlock->TextVarResolver( token, m_project );
|
||||
// no need for tokenUpdated; TextVarResolver() did a full resolve
|
||||
return true;
|
||||
return m_titleBlock->TextVarResolver( token, m_project );
|
||||
}
|
||||
|
||||
if( tokenUpdated )
|
||||
|
||||
@@ -694,7 +694,7 @@ void EDA_DRAW_FRAME::SetMsgPanel( EDA_ITEM* aItem )
|
||||
|
||||
void EDA_DRAW_FRAME::UpdateMsgPanel()
|
||||
{
|
||||
GetToolManager()->PostEvent( EVENTS::SelectedItemsModified );
|
||||
GetToolManager()->ProcessEvent( EVENTS::SelectedItemsModified );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -320,6 +320,7 @@ static struct EDA_ITEM_DESC
|
||||
.Map( PCB_FP_SHAPE_T, _HKI( "Graphic" ) )
|
||||
.Map( PCB_FP_ZONE_T, _HKI( "Zone" ) )
|
||||
.Map( PCB_TRACE_T, _HKI( "Track" ) )
|
||||
.Map( PCB_ARC_T, _HKI( "Track" ) )
|
||||
.Map( PCB_VIA_T, _HKI( "Via" ) )
|
||||
.Map( PCB_MARKER_T, _HKI( "Marker" ) )
|
||||
.Map( PCB_DIM_ALIGNED_T, _HKI( "Dimension" ) )
|
||||
|
||||
+27
-5
@@ -436,6 +436,12 @@ void EDA_SHAPE::SetCenter( const wxPoint& aCenter )
|
||||
|
||||
wxPoint EDA_SHAPE::GetArcMid() const
|
||||
{
|
||||
// If none of the input data have changed since we loaded the arc,
|
||||
// keep the original mid point data to minimize churn
|
||||
if( m_arcMidData.start == m_start && m_arcMidData.end == m_end
|
||||
&& m_arcMidData.center == m_arcCenter )
|
||||
return m_arcMidData.mid;
|
||||
|
||||
wxPoint mid = m_start;
|
||||
RotatePoint( &mid, m_arcCenter, -GetArcAngle() / 2.0 );
|
||||
return mid;
|
||||
@@ -486,19 +492,35 @@ int EDA_SHAPE::GetRadius() const
|
||||
}
|
||||
|
||||
|
||||
void EDA_SHAPE::SetCachedArcData( const wxPoint& aStart, const wxPoint& aMid, const wxPoint& aEnd, const wxPoint& aCenter )
|
||||
{
|
||||
m_arcMidData.start = aStart;
|
||||
m_arcMidData.end = aEnd;
|
||||
m_arcMidData.center = aCenter;
|
||||
m_arcMidData.mid = aMid;
|
||||
}
|
||||
|
||||
|
||||
void EDA_SHAPE::SetArcGeometry( const wxPoint& aStart, const wxPoint& aMid, const wxPoint& aEnd )
|
||||
{
|
||||
m_arcMidData = {};
|
||||
m_start = aStart;
|
||||
m_end = aEnd;
|
||||
m_arcCenter = CalcArcCenter( aStart, aMid, aEnd );
|
||||
wxPoint new_mid = GetArcMid();
|
||||
|
||||
m_endsSwapped = false;
|
||||
|
||||
/**
|
||||
* If the input winding doesn't match our internal winding, the calculated midpoint will end up
|
||||
* on the other side of the arc. In this case, we need to flip the start/end points and flag this
|
||||
* change for the system
|
||||
// Watch the ordering here. GetArcMid above needs to be called prior to initializing the
|
||||
// m_arcMidData structure in order to ensure we get the calculated variant, not the cached
|
||||
SetCachedArcData( aStart, aMid, aEnd, m_arcCenter );
|
||||
|
||||
/*
|
||||
* If the input winding doesn't match our internal winding, the calculated midpoint will end
|
||||
* up on the other side of the arc. In this case, we need to flip the start/end points and
|
||||
* flag this change for the system.
|
||||
*/
|
||||
wxPoint new_mid = GetArcMid();
|
||||
|
||||
VECTOR2D dist( new_mid - aMid );
|
||||
VECTOR2D dist2( new_mid - m_arcCenter );
|
||||
|
||||
|
||||
+4
-2
@@ -188,7 +188,7 @@ bool EDA_TEXT::Replace( const wxFindReplaceData& aSearchData )
|
||||
|
||||
void EDA_TEXT::cacheShownText()
|
||||
{
|
||||
if( m_text.IsEmpty() || m_text == wxT( "~" ) ) // ~ is legacy empty-string token
|
||||
if( m_text.IsEmpty() )
|
||||
{
|
||||
m_shown_text = wxEmptyString;
|
||||
m_shown_text_has_text_var_refs = false;
|
||||
@@ -316,7 +316,9 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, bool aInvertY ) const
|
||||
|
||||
// interline spacing is only *between* lines, so total height is the height of the first
|
||||
// line plus the interline distance (with interline spacing) for all subsequent lines
|
||||
textsize.y += KiROUND( ( strings.GetCount() - 1 ) * interline );
|
||||
// Don't add interline spacing to empty textboxes
|
||||
if( strings.GetCount() )
|
||||
textsize.y += KiROUND( ( strings.GetCount() - 1 ) * interline );
|
||||
}
|
||||
|
||||
rect.SetSize( textsize );
|
||||
|
||||
+13
-1
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2019 Ian McInerney <Ian.S.McInerney@ieee.org>
|
||||
* Copyright (C) 2019 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2022 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
|
||||
@@ -165,6 +165,18 @@ void FILE_HISTORY::doAddClearItem( wxMenu* aMenu )
|
||||
}
|
||||
|
||||
|
||||
void FILE_HISTORY::UpdateClearText( wxMenu* aMenu, wxString aClearText )
|
||||
{
|
||||
size_t itemPos;
|
||||
wxMenuItem* clearItem = aMenu->FindChildItem( m_clearId, &itemPos );
|
||||
|
||||
if( clearItem && itemPos > 1 ) // clearItem is the last menu, after a separator
|
||||
{
|
||||
clearItem->SetItemLabel( aClearText );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FILE_HISTORY::ClearFileHistory()
|
||||
{
|
||||
while( GetCount() > 0 )
|
||||
|
||||
@@ -465,10 +465,10 @@ bool FILENAME_RESOLVER::addPath( const SEARCH_PATH& aPath )
|
||||
wxString msg = _( "Alias: " );
|
||||
msg.append( tpath.m_Alias );
|
||||
msg.append( wxT( "\n" ) );
|
||||
msg.append( _( "This path:wxT( " ) + wxS( " ) " ) );
|
||||
msg.append( _( "This path:" ) + wxS( " " ) );
|
||||
msg.append( tpath.m_Pathvar );
|
||||
msg.append( wxT( "\n" ) );
|
||||
msg.append( _( "Existing path:wxT( " ) + wxS( " ) " ) );
|
||||
msg.append( _( "Existing path:" ) + wxS( " " ) );
|
||||
msg.append( sPL->m_Pathvar );
|
||||
wxMessageBox( msg, _( "Bad alias (duplicate name)" ) );
|
||||
|
||||
|
||||
@@ -642,9 +642,8 @@ void GRID_TRICKS::paste_text( const wxString& cb_text )
|
||||
|
||||
for( int row = start_row; row < end_row; ++row )
|
||||
{
|
||||
// If number of selected rows bigger than count of rows in
|
||||
// the clipboard, paste from the clipboard again and again
|
||||
// while end of the selection is reached.
|
||||
// If number of selected rows is larger than the count of rows on the clipboard, paste
|
||||
// again and again until the end of the selection is reached.
|
||||
if( !rows.HasMoreTokens() )
|
||||
rows.SetString( cb_text, ROW_SEP, wxTOKEN_RET_EMPTY );
|
||||
|
||||
@@ -662,9 +661,12 @@ void GRID_TRICKS::paste_text( const wxString& cb_text )
|
||||
|
||||
for( int col = start_col; col < end_col; ++col )
|
||||
{
|
||||
// If number of selected columns bigger than count of columns in
|
||||
// the clipboard, paste from the clipboard again and again while
|
||||
// end of the selection is reached.
|
||||
// Skip hidden columns
|
||||
if( !m_grid->IsColShown( col ) )
|
||||
continue;
|
||||
|
||||
// If number of selected cols is larger than the count of cols on the clipboard,
|
||||
// paste again and again until the end of the selection is reached.
|
||||
if( !cols.HasMoreTokens() )
|
||||
cols.SetString( rowTxt, COL_SEP, wxTOKEN_RET_EMPTY );
|
||||
|
||||
|
||||
+8
-2
@@ -40,8 +40,14 @@
|
||||
// boost:mt19937 is not thread-safe
|
||||
static std::mutex rng_mutex;
|
||||
|
||||
// Create only once, as seeding is *very* expensive
|
||||
static boost::mt19937 rng;
|
||||
// Static rng and generators are used because the overhead of constant seeding is expensive
|
||||
// We break out the rng separately from the generator because we want to control seeding in cases like unit tests
|
||||
#if BOOST_VERSION >= 106700
|
||||
static boost::uuids::detail::random_provider seeder; // required to ensure the rng has a random initial seed
|
||||
#else
|
||||
static boost::uuids::detail::seed_rng seeder; // required to ensure the rng has a random initial seed
|
||||
#endif
|
||||
static boost::mt19937 rng( seeder );
|
||||
static boost::uuids::basic_random_generator<boost::mt19937> randomGenerator( rng );
|
||||
|
||||
// These don't have the same performance penalty, but we might as well be consistent
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <core/arraydim.h>
|
||||
#include <id.h>
|
||||
#include <kiplatform/app.h>
|
||||
#include <kiplatform/environment.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <logging.h>
|
||||
|
||||
@@ -230,6 +231,15 @@ KIFACE* KIWAY::KiFACE( FACE_T aFaceId, bool doLoad )
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef KICAD_WIN32_VERIFY_CODESIGN
|
||||
bool codeSignOk = KIPLATFORM::ENV::VerifyFileSignature( dname );
|
||||
if( !codeSignOk )
|
||||
{
|
||||
msg.Printf( _( "Failed to verify kiface library '%s' signature." ), dname );
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
#endif
|
||||
|
||||
wxDynamicLibrary dso;
|
||||
|
||||
void* addr = nullptr;
|
||||
|
||||
@@ -239,6 +239,26 @@ wxString PATHS::GetStockScriptingPath()
|
||||
}
|
||||
|
||||
|
||||
wxString PATHS::GetStockTemplatesPath()
|
||||
{
|
||||
wxString path;
|
||||
|
||||
path = GetStockDataPath() + wxT( "/template" );
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
wxString PATHS::GetLocaleDataPath()
|
||||
{
|
||||
wxString path;
|
||||
|
||||
path = GetStockDataPath() + wxT( "/internat" );
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
wxString PATHS::GetStockPluginsPath()
|
||||
{
|
||||
wxFileName fn;
|
||||
|
||||
+2
-42
@@ -56,6 +56,7 @@
|
||||
#include <settings/settings_manager.h>
|
||||
#include <systemdirsappend.h>
|
||||
#include <trace_helpers.h>
|
||||
#include <paths.h>
|
||||
|
||||
|
||||
/**
|
||||
@@ -540,48 +541,7 @@ void PGM_BASE::SetLanguageIdentifier( int menu_id )
|
||||
|
||||
void PGM_BASE::SetLanguagePath()
|
||||
{
|
||||
SEARCH_STACK guesses;
|
||||
|
||||
SystemDirsAppend( &guesses );
|
||||
|
||||
// Add our internat dir to the wxLocale catalog of paths
|
||||
for( unsigned i = 0; i < guesses.GetCount(); i++ )
|
||||
{
|
||||
wxFileName fn( guesses[i], wxEmptyString );
|
||||
|
||||
// Append path for Windows and unix KiCad package install
|
||||
fn.AppendDir( wxT( "share" ) );
|
||||
fn.AppendDir( wxT( "internat" ) );
|
||||
|
||||
if( fn.IsDirReadable() )
|
||||
{
|
||||
wxLogTrace( traceLocale, wxT( "Adding locale lookup path: " ) + fn.GetPath() );
|
||||
wxLocale::AddCatalogLookupPathPrefix( fn.GetPath() );
|
||||
}
|
||||
|
||||
// Append path for unix standard install
|
||||
fn.RemoveLastDir();
|
||||
fn.AppendDir( wxT( "kicad" ) );
|
||||
fn.AppendDir( wxT( "internat" ) );
|
||||
|
||||
if( fn.IsDirReadable() )
|
||||
{
|
||||
wxLogTrace( traceLocale, wxT( "Adding locale lookup path: " ) + fn.GetPath() );
|
||||
wxLocale::AddCatalogLookupPathPrefix( fn.GetPath() );
|
||||
}
|
||||
|
||||
// Append path for macOS install
|
||||
fn.RemoveLastDir();
|
||||
fn.RemoveLastDir();
|
||||
fn.RemoveLastDir();
|
||||
fn.AppendDir( wxT( "internat" ) );
|
||||
|
||||
if( fn.IsDirReadable() )
|
||||
{
|
||||
wxLogTrace( traceLocale, wxT( "Adding locale lookup path: " ) + fn.GetPath() );
|
||||
wxLocale::AddCatalogLookupPathPrefix( fn.GetPath() );
|
||||
}
|
||||
}
|
||||
wxLocale::AddCatalogLookupPathPrefix( PATHS::GetLocaleDataPath() );
|
||||
|
||||
if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2022 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
|
||||
@@ -842,8 +842,6 @@ void GERBER_PLOTTER::plotArc( const SHAPE_ARC& aArc, bool aPlotInRegion )
|
||||
wxPoint start( aArc.GetP0() );
|
||||
wxPoint end( aArc.GetP1() );
|
||||
wxPoint center( aArc.GetCenter() );
|
||||
double start_angle = aArc.GetStartAngle();
|
||||
double end_angle = aArc.GetEndAngle();
|
||||
|
||||
if( !aPlotInRegion )
|
||||
MoveTo( start);
|
||||
@@ -851,14 +849,20 @@ void GERBER_PLOTTER::plotArc( const SHAPE_ARC& aArc, bool aPlotInRegion )
|
||||
LineTo( start );
|
||||
|
||||
DPOINT devEnd = userToDeviceCoordinates( end );
|
||||
DPOINT devCenter = userToDeviceCoordinates( center ) - userToDeviceCoordinates( start );
|
||||
DPOINT devCenter = userToDeviceCoordinates( center - start );
|
||||
VECTOR2I arcMidPoint = aArc.GetArcMid();
|
||||
|
||||
// We need to know if the arc is CW or CCW in device coordinates, so build this arc.
|
||||
SHAPE_ARC deviceArc( userToDeviceCoordinates( start ),
|
||||
userToDeviceCoordinates( wxPoint( arcMidPoint.x, arcMidPoint.y ) ),
|
||||
devEnd, 0 );
|
||||
|
||||
fprintf( m_outputFile, "G75*\n" ); // Multiquadrant (360 degrees) mode
|
||||
|
||||
if( start_angle < end_angle )
|
||||
fprintf( m_outputFile, "G03*\n" ); // Active circular interpolation, CCW
|
||||
else
|
||||
if( deviceArc.IsClockwise() )
|
||||
fprintf( m_outputFile, "G02*\n" ); // Active circular interpolation, CW
|
||||
else
|
||||
fprintf( m_outputFile, "G03*\n" ); // Active circular interpolation, CCW
|
||||
|
||||
fprintf( m_outputFile, "X%dY%dI%dJ%dD01*\n",
|
||||
KiROUND( devEnd.x ), KiROUND( devEnd.y ),
|
||||
@@ -1010,6 +1014,10 @@ void GERBER_PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aPoly, FILL_T aFill, int
|
||||
const SHAPE_ARC& arc = aPoly.Arc( arcindex );
|
||||
|
||||
plotArc( arc, ii > 0 );
|
||||
|
||||
// skip points on arcs, since we plot the arc itself
|
||||
while( ii+1 < aPoly.PointCount() && arcindex == aPoly.ArcIndex( ii+1 ) )
|
||||
ii++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1040,12 +1048,17 @@ void GERBER_PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aPoly, FILL_T aFill, int
|
||||
const SHAPE_ARC& arc = aPoly.Arc( arcindex );
|
||||
|
||||
plotArc( arc, ii > 0 );
|
||||
|
||||
// skip points on arcs, since we plot the arc itself
|
||||
while( ii+1 < aPoly.PointCount() && arcindex == aPoly.ArcIndex( ii+1 ) )
|
||||
ii++;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the thick outline is closed for filled polygons
|
||||
// (if not filled, could be only a polyline)
|
||||
if( aFill != FILL_T::NO_FILL && ( aPoly.CPoint( 0 ) != aPoly.CPoint( -1 ) ) )
|
||||
if( ( aPoly.CPoint( 0 ) != aPoly.CPoint( -1 ) )
|
||||
&& ( aPoly.IsClosed() || aFill != FILL_T::NO_FILL ) )
|
||||
LineTo( wxPoint( aPoly.CPoint( 0 ) ) );
|
||||
|
||||
PenFinish();
|
||||
|
||||
@@ -93,12 +93,6 @@ DPOINT PLOTTER::userToDeviceCoordinates( const wxPoint& aCoordinate )
|
||||
{
|
||||
wxPoint pos = aCoordinate - m_plotOffset;
|
||||
|
||||
// Don't allow overflows; they can cause rendering failures in some file viewers
|
||||
// (such as Acrobat)
|
||||
int clampSize = MAX_PAGE_SIZE_MILS * m_IUsPerDecimil * 10 / 2;
|
||||
pos.x = std::max( -clampSize, std::min( pos.x, clampSize ) );
|
||||
pos.y = std::max( -clampSize, std::min( pos.y, clampSize ) );
|
||||
|
||||
double x = pos.x * m_plotScale;
|
||||
double y = ( m_paperSize.y - pos.y * m_plotScale );
|
||||
|
||||
|
||||
@@ -538,18 +538,20 @@ EDIMENSION::EDIMENSION( wxXmlNode* aDimension )
|
||||
y2 %Coord; #REQUIRED
|
||||
x3 %Coord; #REQUIRED
|
||||
y3 %Coord; #REQUIRED
|
||||
textsize %Coord;
|
||||
layer %Layer; #REQUIRED
|
||||
dtype %DimensionType; "parallel"
|
||||
>
|
||||
*/
|
||||
|
||||
x1 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "x1" ) );
|
||||
y1 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "y1" ) );
|
||||
x2 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "x2" ) );
|
||||
y2 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "y2" ) );
|
||||
x3 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "x3" ) );
|
||||
y3 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "y3" ) );
|
||||
layer = parseRequiredAttribute<int>( aDimension, wxT( "layer" ) );
|
||||
x1 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "x1" ) );
|
||||
y1 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "y1" ) );
|
||||
x2 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "x2" ) );
|
||||
y2 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "y2" ) );
|
||||
x3 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "x3" ) );
|
||||
y3 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "y3" ) );
|
||||
textsize = parseOptionalAttribute<ECOORD>( aDimension, wxT( "textsize" ) );
|
||||
layer = parseRequiredAttribute<int>( aDimension, wxT( "layer" ) );
|
||||
dimensionType = parseOptionalAttribute<wxString>( aDimension, wxT( "dtype" ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -531,13 +531,13 @@ struct EJUNCTION
|
||||
/// Eagle label
|
||||
struct ELABEL
|
||||
{
|
||||
ECOORD x;
|
||||
ECOORD y;
|
||||
ECOORD size;
|
||||
LAYER_NUM layer;
|
||||
opt_erot rot;
|
||||
ECOORD x;
|
||||
ECOORD y;
|
||||
ECOORD size;
|
||||
LAYER_NUM layer;
|
||||
opt_erot rot;
|
||||
opt_wxString xref;
|
||||
wxString netname;
|
||||
wxString netname;
|
||||
|
||||
ELABEL( wxXmlNode* aLabel, const wxString& aNetName );
|
||||
};
|
||||
@@ -619,14 +619,14 @@ struct EATTR
|
||||
/// Eagle dimension element
|
||||
struct EDIMENSION
|
||||
{
|
||||
ECOORD x1;
|
||||
ECOORD y1;
|
||||
ECOORD x2;
|
||||
ECOORD y2;
|
||||
ECOORD x3;
|
||||
ECOORD y3;
|
||||
int layer;
|
||||
|
||||
ECOORD x1;
|
||||
ECOORD y1;
|
||||
ECOORD x2;
|
||||
ECOORD y2;
|
||||
ECOORD x3;
|
||||
ECOORD y3;
|
||||
opt_ecoord textsize;
|
||||
int layer;
|
||||
opt_wxString dimensionType;
|
||||
|
||||
EDIMENSION( wxXmlNode* aDimension );
|
||||
|
||||
@@ -83,7 +83,7 @@ void POLYGON_GEOM_MANAGER::SetLeaderMode( LEADER_MODE aMode )
|
||||
|
||||
bool POLYGON_GEOM_MANAGER::IsSelfIntersecting( bool aIncludeLeaderPts ) const
|
||||
{
|
||||
auto pts( m_lockedPoints );
|
||||
SHAPE_LINE_CHAIN pts( m_lockedPoints );
|
||||
|
||||
if( aIncludeLeaderPts )
|
||||
{
|
||||
|
||||
@@ -37,6 +37,8 @@ SCINTILLA_TRICKS::SCINTILLA_TRICKS( wxStyledTextCtrl* aScintilla, const wxString
|
||||
m_te( aScintilla ),
|
||||
m_braces( aBraces ),
|
||||
m_lastCaretPos( -1 ),
|
||||
m_lastSelStart( -1 ),
|
||||
m_lastSelEnd( -1 ),
|
||||
m_suppressAutocomplete( false ),
|
||||
m_singleLine( aSingleLine ),
|
||||
m_returnCallback( aReturnCallback )
|
||||
@@ -337,10 +339,14 @@ void SCINTILLA_TRICKS::onScintillaUpdateUI( wxStyledTextEvent& aEvent )
|
||||
|
||||
// Has the caret changed position?
|
||||
int caretPos = m_te->GetCurrentPos();
|
||||
int selStart = m_te->GetSelectionStart();
|
||||
int selEnd = m_te->GetSelectionEnd();
|
||||
|
||||
if( m_lastCaretPos != caretPos )
|
||||
if( m_lastCaretPos != caretPos || m_lastSelStart != selStart || m_lastSelEnd != selEnd )
|
||||
{
|
||||
m_lastCaretPos = caretPos;
|
||||
m_lastSelStart = selStart;
|
||||
m_lastSelEnd = selEnd;
|
||||
int bracePos1 = -1;
|
||||
int bracePos2 = -1;
|
||||
|
||||
|
||||
@@ -509,44 +509,7 @@ void COMMON_SETTINGS::InitializeEnvironment()
|
||||
path.AppendDir( wxT( "3dmodels" ) );
|
||||
addVar( wxT( "KICAD6_3DMODEL_DIR" ), path.GetFullPath() );
|
||||
|
||||
// We don't have just one default template path, so use this logic that originally was in
|
||||
// PGM_BASE::InitPgm to determine the best default template path
|
||||
{
|
||||
// Attempt to find the best default template path.
|
||||
SEARCH_STACK bases;
|
||||
SEARCH_STACK templatePaths;
|
||||
|
||||
SystemDirsAppend( &bases );
|
||||
|
||||
for( unsigned i = 0; i < bases.GetCount(); ++i )
|
||||
{
|
||||
wxFileName fn( bases[i], wxEmptyString );
|
||||
|
||||
// Add KiCad template file path to search path list.
|
||||
fn.AppendDir( "template" );
|
||||
|
||||
// Only add path if exists and can be read by the user.
|
||||
if( fn.DirExists() && fn.IsDirReadable() )
|
||||
{
|
||||
wxLogTrace( tracePathsAndFiles, "Checking template path '%s' exists",
|
||||
fn.GetPath() );
|
||||
templatePaths.AddPaths( fn.GetPath() );
|
||||
}
|
||||
}
|
||||
|
||||
if( templatePaths.IsEmpty() )
|
||||
{
|
||||
path = basePath;
|
||||
path.AppendDir( "template" );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Take the first one. There may be more but this will likely be the best option.
|
||||
path.AssignDir( templatePaths[0] );
|
||||
}
|
||||
|
||||
addVar( wxT( "KICAD6_TEMPLATE_DIR" ), path.GetFullPath() );
|
||||
}
|
||||
addVar( wxT( "KICAD6_TEMPLATE_DIR" ), PATHS::GetStockTemplatesPath() );
|
||||
|
||||
addVar( wxT( "KICAD_USER_TEMPLATE_DIR" ), PATHS::GetUserTemplatesPath() );
|
||||
|
||||
|
||||
@@ -387,6 +387,7 @@ wxString SETTINGS_MANAGER::GetPathForSettingsFile( JSON_SETTINGS* aSettings )
|
||||
return GetUserSettingsPath();
|
||||
|
||||
case SETTINGS_LOC::PROJECT:
|
||||
// TODO: MDI support
|
||||
return Prj().GetProjectPath();
|
||||
|
||||
case SETTINGS_LOC::COLORS:
|
||||
@@ -954,42 +955,48 @@ std::vector<wxString> SETTINGS_MANAGER::GetOpenProjects() const
|
||||
}
|
||||
|
||||
|
||||
bool SETTINGS_MANAGER::SaveProject( const wxString& aFullPath )
|
||||
bool SETTINGS_MANAGER::SaveProject( const wxString& aFullPath, PROJECT* aProject )
|
||||
{
|
||||
if( !aProject )
|
||||
aProject = &Prj();
|
||||
|
||||
wxString path = aFullPath;
|
||||
|
||||
if( path.empty() )
|
||||
path = Prj().GetProjectFullName();
|
||||
path = aProject->GetProjectFullName();
|
||||
|
||||
// TODO: refactor for MDI
|
||||
if( Prj().IsReadOnly() )
|
||||
if( aProject->IsReadOnly() )
|
||||
return false;
|
||||
|
||||
if( !m_project_files.count( path ) )
|
||||
return false;
|
||||
|
||||
PROJECT_FILE* project = m_project_files.at( path );
|
||||
wxString projectPath = GetPathForSettingsFile( project );
|
||||
wxString projectPath = aProject->GetProjectPath();
|
||||
|
||||
project->SaveToFile( projectPath );
|
||||
Prj().GetLocalSettings().SaveToFile( projectPath );
|
||||
aProject->GetLocalSettings().SaveToFile( projectPath );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SETTINGS_MANAGER::SaveProjectAs( const wxString& aFullPath )
|
||||
void SETTINGS_MANAGER::SaveProjectAs( const wxString& aFullPath, PROJECT* aProject )
|
||||
{
|
||||
wxString oldName = Prj().GetProjectFullName();
|
||||
if( !aProject )
|
||||
aProject = &Prj();
|
||||
|
||||
wxString oldName = aProject->GetProjectFullName();
|
||||
|
||||
if( aFullPath.IsSameAs( oldName ) )
|
||||
{
|
||||
SaveProject( aFullPath );
|
||||
SaveProject( aFullPath, aProject );
|
||||
return;
|
||||
}
|
||||
|
||||
// Changing this will cause UnloadProject to not save over the "old" project when loading below
|
||||
Prj().setProjectFullName( aFullPath );
|
||||
aProject->setProjectFullName( aFullPath );
|
||||
|
||||
wxFileName fn( aFullPath );
|
||||
|
||||
@@ -997,14 +1004,14 @@ void SETTINGS_MANAGER::SaveProjectAs( const wxString& aFullPath )
|
||||
|
||||
// Ensure read-only flags are copied; this allows doing a "Save As" on a standalong board/sch
|
||||
// without creating project files if the checkbox is turned off
|
||||
project->SetReadOnly( Prj().IsReadOnly() );
|
||||
Prj().GetLocalSettings().SetReadOnly( Prj().IsReadOnly() );
|
||||
project->SetReadOnly( aProject->IsReadOnly() );
|
||||
aProject->GetLocalSettings().SetReadOnly( aProject->IsReadOnly() );
|
||||
|
||||
project->SetFilename( fn.GetName() );
|
||||
project->SaveToFile( fn.GetPath() );
|
||||
|
||||
Prj().GetLocalSettings().SetFilename( fn.GetName() );
|
||||
Prj().GetLocalSettings().SaveToFile( fn.GetPath() );
|
||||
aProject->GetLocalSettings().SetFilename( fn.GetName() );
|
||||
aProject->GetLocalSettings().SaveToFile( fn.GetPath() );
|
||||
|
||||
m_project_files[fn.GetFullPath()] = project;
|
||||
m_project_files.erase( oldName );
|
||||
@@ -1014,9 +1021,12 @@ void SETTINGS_MANAGER::SaveProjectAs( const wxString& aFullPath )
|
||||
}
|
||||
|
||||
|
||||
void SETTINGS_MANAGER::SaveProjectCopy( const wxString& aFullPath )
|
||||
void SETTINGS_MANAGER::SaveProjectCopy( const wxString& aFullPath, PROJECT* aProject )
|
||||
{
|
||||
PROJECT_FILE* project = m_project_files.at( Prj().GetProjectFullName() );
|
||||
if( !aProject )
|
||||
aProject = &Prj();
|
||||
|
||||
PROJECT_FILE* project = m_project_files.at( aProject->GetProjectFullName() );
|
||||
wxString oldName = project->GetFilename();
|
||||
wxFileName fn( aFullPath );
|
||||
|
||||
@@ -1027,9 +1037,11 @@ void SETTINGS_MANAGER::SaveProjectCopy( const wxString& aFullPath )
|
||||
project->SaveToFile( fn.GetPath() );
|
||||
project->SetFilename( oldName );
|
||||
|
||||
Prj().GetLocalSettings().SetFilename( fn.GetName() );
|
||||
Prj().GetLocalSettings().SaveToFile( fn.GetPath() );
|
||||
Prj().GetLocalSettings().SetFilename( oldName );
|
||||
PROJECT_LOCAL_SETTINGS& localSettings = aProject->GetLocalSettings();
|
||||
|
||||
localSettings.SetFilename( fn.GetName() );
|
||||
localSettings.SaveToFile( fn.GetPath() );
|
||||
localSettings.SetFilename( oldName );
|
||||
|
||||
project->SetReadOnly( readOnly );
|
||||
}
|
||||
|
||||
+31
-3
@@ -50,6 +50,8 @@ wxString ConvertToNewOverbarNotation( const wxString& aOldStr )
|
||||
if( aOldStr == wxT( "~" ) )
|
||||
return aOldStr;
|
||||
|
||||
newStr.reserve( aOldStr.length() );
|
||||
|
||||
for( wxString::const_iterator chIt = aOldStr.begin(); chIt != aOldStr.end(); ++chIt )
|
||||
{
|
||||
if( *chIt == '~' )
|
||||
@@ -140,7 +142,17 @@ bool ConvertSmartQuotesAndDashes( wxString* aString )
|
||||
|
||||
wxString EscapeString( const wxString& aSource, ESCAPE_CONTEXT aContext )
|
||||
{
|
||||
wxString converted;
|
||||
wxString converted;
|
||||
std::vector<bool> braceStack; // true == formatting construct
|
||||
|
||||
auto hasFormattingPrefix =
|
||||
[&]()
|
||||
{
|
||||
static wxString prefixes = wxT( "~_^" );
|
||||
return !converted.IsEmpty() && prefixes.Find( converted.Last() ) >= 0;
|
||||
};
|
||||
|
||||
converted.reserve( aSource.length() );
|
||||
|
||||
for( wxUniChar c: aSource )
|
||||
{
|
||||
@@ -155,7 +167,7 @@ wxString EscapeString( const wxString& aSource, ESCAPE_CONTEXT aContext )
|
||||
}
|
||||
else if( aContext == CTX_LIBID )
|
||||
{
|
||||
if( c == '{' )
|
||||
if( c == '{' && !hasFormattingPrefix() )
|
||||
converted += wxT( "{brace}" );
|
||||
else if( c == '/' )
|
||||
converted += wxT( "{slash}" );
|
||||
@@ -223,7 +235,9 @@ wxString EscapeString( const wxString& aSource, ESCAPE_CONTEXT aContext )
|
||||
converted += c;
|
||||
}
|
||||
else
|
||||
{
|
||||
converted += c;
|
||||
}
|
||||
}
|
||||
|
||||
return converted;
|
||||
@@ -232,8 +246,16 @@ wxString EscapeString( const wxString& aSource, ESCAPE_CONTEXT aContext )
|
||||
|
||||
wxString UnescapeString( const wxString& aSource )
|
||||
{
|
||||
size_t sourceLen = aSource.length();
|
||||
|
||||
// smallest escape string is three characters, shortcut everything else
|
||||
if( sourceLen <= 2 )
|
||||
{
|
||||
return aSource;
|
||||
}
|
||||
|
||||
wxString newbuf;
|
||||
size_t sourceLen = aSource.length();
|
||||
newbuf.reserve( sourceLen );
|
||||
|
||||
for( size_t i = 0; i < sourceLen; ++i )
|
||||
{
|
||||
@@ -305,6 +327,8 @@ wxString TitleCaps( const wxString& aString )
|
||||
|
||||
wxStringSplit( aString, words, ' ' );
|
||||
|
||||
result.reserve( aString.length() );
|
||||
|
||||
for( const wxString& word : words )
|
||||
{
|
||||
if( !result.IsEmpty() )
|
||||
@@ -423,6 +447,8 @@ std::string EscapedUTF8( const wxString& aString )
|
||||
|
||||
std::string ret;
|
||||
|
||||
ret.reserve( utf8.length() + 2 );
|
||||
|
||||
ret += '"';
|
||||
|
||||
for( std::string::const_iterator it = utf8.begin(); it!=utf8.end(); ++it )
|
||||
@@ -454,6 +480,8 @@ wxString EscapeHTML( const wxString& aString )
|
||||
{
|
||||
wxString converted;
|
||||
|
||||
converted.reserve( aString.length() );
|
||||
|
||||
for( wxUniChar c : aString )
|
||||
{
|
||||
if( c == '\"' )
|
||||
|
||||
@@ -183,21 +183,20 @@ wxMenuItem* ACTION_MENU::Add( const TOOL_ACTION& aAction, bool aIsCheckmarkEntry
|
||||
|
||||
wxMenuItem* ACTION_MENU::Add( ACTION_MENU* aMenu )
|
||||
{
|
||||
ACTION_MENU* menuCopy = aMenu->Clone();
|
||||
m_submenus.push_back( menuCopy );
|
||||
m_submenus.push_back( aMenu );
|
||||
|
||||
wxASSERT_MSG( !menuCopy->m_title.IsEmpty(), wxT( "Set a title for ACTION_MENU using SetTitle()" ) );
|
||||
wxASSERT_MSG( !aMenu->m_title.IsEmpty(), wxT( "Set a title for ACTION_MENU using SetTitle()" ) );
|
||||
|
||||
if( !!aMenu->m_icon )
|
||||
{
|
||||
wxMenuItem* newItem = new wxMenuItem( this, -1, menuCopy->m_title );
|
||||
wxMenuItem* newItem = new wxMenuItem( this, -1, aMenu->m_title );
|
||||
AddBitmapToMenuItem( newItem, KiBitmap( aMenu->m_icon ) );
|
||||
newItem->SetSubMenu( menuCopy );
|
||||
newItem->SetSubMenu( aMenu );
|
||||
return Append( newItem );
|
||||
}
|
||||
else
|
||||
{
|
||||
return AppendSubMenu( menuCopy, menuCopy->m_title );
|
||||
return AppendSubMenu( aMenu, aMenu->m_title );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -144,20 +144,21 @@ void CONDITIONAL_MENU::Evaluate( SELECTION& aSelection )
|
||||
switch( entry.Type() )
|
||||
{
|
||||
case ENTRY::ACTION:
|
||||
menuItem = Add( *entry.Action(), entry.IsCheckmarkEntry() );
|
||||
Add( *entry.Action(), entry.IsCheckmarkEntry() );
|
||||
menu_count++;
|
||||
break;
|
||||
|
||||
case ENTRY::MENU:
|
||||
menuItem = Add( entry.Menu() );
|
||||
entry.Menu()->UpdateTitle();
|
||||
Add( entry.Menu()->Clone() );
|
||||
menu_count++;
|
||||
break;
|
||||
|
||||
case ENTRY::WXITEM:
|
||||
menuItem = new wxMenuItem( this,
|
||||
entry.wxItem()->GetId(),
|
||||
entry.wxItem()->GetItemLabel(),
|
||||
entry.wxItem()->GetHelp(),
|
||||
wxGetTranslation( entry.wxItem()->GetItemLabel() ),
|
||||
wxGetTranslation( entry.wxItem()->GetHelp() ),
|
||||
entry.wxItem()->GetKind() );
|
||||
|
||||
if( !!entry.GetIcon() )
|
||||
@@ -171,7 +172,7 @@ void CONDITIONAL_MENU::Evaluate( SELECTION& aSelection )
|
||||
|
||||
case ENTRY::SEPARATOR:
|
||||
if( menu_count )
|
||||
menuItem = AppendSeparator();
|
||||
AppendSeparator();
|
||||
|
||||
menu_count = 0;
|
||||
break;
|
||||
|
||||
@@ -37,7 +37,7 @@ GRID_MENU::GRID_MENU( EDA_DRAW_FRAME* aParent ) :
|
||||
ACTION_MENU( true ),
|
||||
m_parent( aParent )
|
||||
{
|
||||
SetTitle( _( "Grid" ) );
|
||||
UpdateTitle();
|
||||
SetIcon( BITMAPS::grid_select );
|
||||
|
||||
APP_SETTINGS_BASE* settings = m_parent->config();
|
||||
@@ -59,6 +59,12 @@ OPT_TOOL_EVENT GRID_MENU::eventHandler( const wxMenuEvent& aEvent )
|
||||
}
|
||||
|
||||
|
||||
void GRID_MENU::UpdateTitle()
|
||||
{
|
||||
SetTitle( _( "Grid" ) );
|
||||
}
|
||||
|
||||
|
||||
void GRID_MENU::update()
|
||||
{
|
||||
APP_SETTINGS_BASE* settings = m_parent->config();
|
||||
|
||||
@@ -40,13 +40,8 @@ ZOOM_MENU::ZOOM_MENU( EDA_DRAW_FRAME* aParent ) :
|
||||
ACTION_MENU( true ),
|
||||
m_parent( aParent )
|
||||
{
|
||||
SetTitle( _( "Zoom" ) );
|
||||
UpdateTitle();
|
||||
SetIcon( BITMAPS::zoom_selection );
|
||||
|
||||
int i = ID_POPUP_ZOOM_LEVEL_START + 1; // 0 reserved for menus which support auto-zoom
|
||||
|
||||
for( double factor : m_parent->config()->m_Window.zoom_factors )
|
||||
Append( i++, wxString::Format( _( "Zoom: %.2f" ), factor ), wxEmptyString, wxITEM_CHECK );
|
||||
}
|
||||
|
||||
|
||||
@@ -58,17 +53,30 @@ OPT_TOOL_EVENT ZOOM_MENU::eventHandler( const wxMenuEvent& aEvent )
|
||||
}
|
||||
|
||||
|
||||
void ZOOM_MENU::UpdateTitle()
|
||||
{
|
||||
SetTitle( _( "Zoom" ) );
|
||||
}
|
||||
|
||||
|
||||
void ZOOM_MENU::update()
|
||||
{
|
||||
Clear();
|
||||
|
||||
int ii = ID_POPUP_ZOOM_LEVEL_START + 1; // 0 reserved for menus which support auto-zoom
|
||||
|
||||
for( double factor : m_parent->config()->m_Window.zoom_factors )
|
||||
Append( ii++, wxString::Format( _( "Zoom: %.2f" ), factor ), wxEmptyString, wxITEM_CHECK );
|
||||
|
||||
double zoom = m_parent->GetCanvas()->GetGAL()->GetZoomFactor();
|
||||
|
||||
const std::vector<double>& zoomList = m_parent->config()->m_Window.zoom_factors;
|
||||
|
||||
for( size_t i = 0; i < zoomList.size(); ++i )
|
||||
for( size_t jj = 0; jj < zoomList.size(); ++jj )
|
||||
{
|
||||
// Search for a value near the current zoom setting:
|
||||
double rel_error = std::fabs( zoomList[i] - zoom ) / zoom;
|
||||
double rel_error = std::fabs( zoomList[jj] - zoom ) / zoom;
|
||||
// IDs start with 1 (leaving 0 for auto-zoom)
|
||||
Check( ID_POPUP_ZOOM_LEVEL_START + i + 1, rel_error < 0.1 );
|
||||
Check( ID_POPUP_ZOOM_LEVEL_START + jj + 1, rel_error < 0.1 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <trace_helpers.h>
|
||||
#include <settings/common_settings.h>
|
||||
#include <math/util.h> // for KiROUND
|
||||
#include <geometry/geometry_utils.h>
|
||||
#include <widgets/ui_common.h>
|
||||
#include <class_draw_panel_gal.h>
|
||||
#include <kiplatform/ui.h>
|
||||
@@ -300,7 +301,7 @@ void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
|
||||
}
|
||||
|
||||
if( m_updateCursor ) // do not update the cursor position if it was explicitly set
|
||||
m_cursorPos = m_view->ToWorld( mousePos );
|
||||
m_cursorPos = GetClampedCoords( m_view->ToWorld( mousePos ) );
|
||||
else
|
||||
m_updateCursor = true;
|
||||
|
||||
@@ -648,7 +649,7 @@ VECTOR2D WX_VIEW_CONTROLS::GetMousePosition( bool aWorldCoordinates ) const
|
||||
wxPoint msp = getMouseScreenPosition();
|
||||
VECTOR2D screenPos( msp.x, msp.y );
|
||||
|
||||
return aWorldCoordinates ? m_view->ToWorld( screenPos ) : screenPos;
|
||||
return aWorldCoordinates ? GetClampedCoords( m_view->ToWorld( screenPos ) ) : screenPos;
|
||||
}
|
||||
|
||||
|
||||
@@ -675,7 +676,7 @@ VECTOR2D WX_VIEW_CONTROLS::GetCursorPosition( bool aEnableSnapping ) const
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetRawCursorPosition( aEnableSnapping );
|
||||
return GetClampedCoords( GetRawCursorPosition( aEnableSnapping ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -685,10 +686,12 @@ void WX_VIEW_CONTROLS::SetCursorPosition( const VECTOR2D& aPosition, bool aWarpV
|
||||
{
|
||||
m_updateCursor = false;
|
||||
|
||||
VECTOR2D clampedPosition = GetClampedCoords( aPosition );
|
||||
|
||||
if( aTriggeredByArrows )
|
||||
{
|
||||
m_settings.m_lastKeyboardCursorPositionValid = true;
|
||||
m_settings.m_lastKeyboardCursorPosition = aPosition;
|
||||
m_settings.m_lastKeyboardCursorPosition = clampedPosition;
|
||||
m_settings.m_lastKeyboardCursorCommand = aArrowCommand;
|
||||
m_cursorWarped = false;
|
||||
}
|
||||
@@ -700,8 +703,8 @@ void WX_VIEW_CONTROLS::SetCursorPosition( const VECTOR2D& aPosition, bool aWarpV
|
||||
m_cursorWarped = true;
|
||||
}
|
||||
|
||||
WarpCursor( aPosition, true, aWarpView );
|
||||
m_cursorPos = aPosition;
|
||||
WarpCursor( clampedPosition, true, aWarpView );
|
||||
m_cursorPos = clampedPosition;
|
||||
}
|
||||
|
||||
|
||||
@@ -710,14 +713,16 @@ void WX_VIEW_CONTROLS::SetCrossHairCursorPosition( const VECTOR2D& aPosition,
|
||||
{
|
||||
m_updateCursor = false;
|
||||
|
||||
VECTOR2D clampedPosition = GetClampedCoords( aPosition );
|
||||
|
||||
const VECTOR2I& screenSize = m_view->GetGAL()->GetScreenPixelSize();
|
||||
BOX2I screen( VECTOR2I( 0, 0 ), screenSize );
|
||||
VECTOR2D screenPos = m_view->ToScreen( aPosition );
|
||||
BOX2I screen( VECTOR2I( 0, 0 ), screenSize );
|
||||
VECTOR2D screenPos = m_view->ToScreen( clampedPosition );
|
||||
|
||||
if( aWarpView && !screen.Contains( screenPos ) )
|
||||
m_view->SetCenter( aPosition );
|
||||
m_view->SetCenter( clampedPosition );
|
||||
|
||||
m_cursorPos = aPosition;
|
||||
m_cursorPos = clampedPosition;
|
||||
}
|
||||
|
||||
|
||||
@@ -727,14 +732,15 @@ void WX_VIEW_CONTROLS::WarpCursor( const VECTOR2D& aPosition, bool aWorldCoordin
|
||||
if( aWorldCoordinates )
|
||||
{
|
||||
const VECTOR2I& screenSize = m_view->GetGAL()->GetScreenPixelSize();
|
||||
BOX2I screen( VECTOR2I( 0, 0 ), screenSize );
|
||||
VECTOR2D screenPos = m_view->ToScreen( aPosition );
|
||||
BOX2I screen( VECTOR2I( 0, 0 ), screenSize );
|
||||
VECTOR2D clampedPosition = GetClampedCoords( aPosition );
|
||||
VECTOR2D screenPos = m_view->ToScreen( clampedPosition );
|
||||
|
||||
if( !screen.Contains( screenPos ) )
|
||||
{
|
||||
if( aWarpView )
|
||||
{
|
||||
m_view->SetCenter( aPosition );
|
||||
m_view->SetCenter( clampedPosition );
|
||||
m_parentPanel->WarpPointer( screenSize.x / 2, screenSize.y / 2 );
|
||||
}
|
||||
}
|
||||
@@ -889,7 +895,7 @@ void WX_VIEW_CONTROLS::refreshMouse()
|
||||
moveEvent.SetShiftDown( wxGetKeyState( WXK_SHIFT ) );
|
||||
moveEvent.SetAltDown( wxGetKeyState( WXK_ALT ) );
|
||||
|
||||
m_cursorPos = m_view->ToWorld( VECTOR2D( msp.x, msp.y ) );
|
||||
m_cursorPos = GetClampedCoords( m_view->ToWorld( VECTOR2D( msp.x, msp.y ) ) );
|
||||
wxPostEvent( m_parentPanel, moveEvent );
|
||||
}
|
||||
|
||||
@@ -943,6 +949,8 @@ void WX_VIEW_CONTROLS::UpdateScrollbars()
|
||||
|
||||
void WX_VIEW_CONTROLS::ForceCursorPosition( bool aEnabled, const VECTOR2D& aPosition )
|
||||
{
|
||||
VECTOR2D clampedPosition = GetClampedCoords( aPosition );
|
||||
|
||||
m_settings.m_forceCursorPosition = aEnabled;
|
||||
m_settings.m_forcedPosition = aPosition;
|
||||
m_settings.m_forcedPosition = clampedPosition;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* @author Jon Evans <jon@craftyjon.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/statbmp.h>
|
||||
#include <wx/timer.h>
|
||||
|
||||
wxDEFINE_EVENT( TOGGLE_CHANGED, wxCommandEvent );
|
||||
|
||||
@@ -35,7 +36,8 @@ BITMAP_TOGGLE::BITMAP_TOGGLE( wxWindow *aParent, wxWindowID aId, const wxBitmap&
|
||||
wxPanel( aParent, aId ),
|
||||
m_checked( aChecked ),
|
||||
m_unchecked_bitmap( aUncheckedBitmap ),
|
||||
m_checked_bitmap( aCheckedBitmap )
|
||||
m_checked_bitmap( aCheckedBitmap ),
|
||||
m_debounce( 0 )
|
||||
{
|
||||
wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
SetSizer( sizer );
|
||||
@@ -47,13 +49,21 @@ BITMAP_TOGGLE::BITMAP_TOGGLE( wxWindow *aParent, wxWindowID aId, const wxBitmap&
|
||||
sizer->Add( m_bitmap, 0, 0 );
|
||||
|
||||
m_bitmap->Bind( wxEVT_LEFT_UP,
|
||||
[&]( wxMouseEvent& )
|
||||
[&]( wxMouseEvent& event )
|
||||
{
|
||||
wxLongLong now = wxGetLocalTimeMillis();
|
||||
|
||||
if( now - m_debounce < 50 )
|
||||
return;
|
||||
else
|
||||
m_debounce = now;
|
||||
|
||||
SetValue( !GetValue() );
|
||||
wxCommandEvent event( TOGGLE_CHANGED );
|
||||
event.SetInt( m_checked );
|
||||
event.SetEventObject( this );
|
||||
wxPostEvent( this, event );
|
||||
|
||||
wxCommandEvent command( TOGGLE_CHANGED );
|
||||
command.SetInt( m_checked );
|
||||
command.SetEventObject( this );
|
||||
wxPostEvent( this, command );
|
||||
} );
|
||||
|
||||
auto passOnEvent =
|
||||
|
||||
@@ -59,10 +59,17 @@ wxString GRID_CELL_TEXT_BUTTON::GetValue() const
|
||||
void GRID_CELL_TEXT_BUTTON::SetSize( const wxRect& aRect )
|
||||
{
|
||||
wxRect rect( aRect );
|
||||
rect.Inflate( -1 );
|
||||
|
||||
#if defined( __WXMAC__ )
|
||||
rect.Inflate( 3 ); // no FOCUS_RING, even on Mac
|
||||
rect.Inflate( 2 ); // ignore FOCUS_RING
|
||||
#elif defined( __WXGTK__ )
|
||||
rect.Inflate( -3 ); // The -3 is a very sad hack here. Some GTK themes overrun the
|
||||
// default -1, preventing display. Unfortunately, we don't appear to
|
||||
// have a good method of finding the current margin needed.
|
||||
// Some GTK resize events seem to update the cell size but not all and
|
||||
// not consistently.
|
||||
#else
|
||||
rect.Inflate( -1 );
|
||||
#endif
|
||||
|
||||
Combo()->SetSize( rect, wxSIZE_ALLOW_MINUS_ONE );
|
||||
|
||||
@@ -63,7 +63,7 @@ EDA_MSG_PANEL::~EDA_MSG_PANEL()
|
||||
int EDA_MSG_PANEL::GetRequiredHeight( wxWindow* aWindow )
|
||||
{
|
||||
wxSize fontSizeInPixels;
|
||||
wxScreenDC dc;
|
||||
wxWindowDC dc( aWindow );
|
||||
|
||||
dc.SetFont( KIUI::GetControlFont( aWindow ) );
|
||||
dc.GetTextExtent( wxT( "W" ), &fontSizeInPixels.x, &fontSizeInPixels.y );
|
||||
|
||||
@@ -335,7 +335,12 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
std::sort( netNames.begin(), netNames.end() );
|
||||
std::sort( netNames.begin(), netNames.end(),
|
||||
[]( const wxString& lhs, const wxString& rhs )
|
||||
{
|
||||
return StrNumCmp( lhs, rhs, true /* ignore case */ ) < 0;
|
||||
} );
|
||||
|
||||
|
||||
// Special handling for <no net>
|
||||
if( filter.IsEmpty() || wxString( NO_NET ).MakeLower().Matches( filter ) )
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 CERN
|
||||
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
*
|
||||
@@ -121,7 +121,7 @@ bool PROGRESS_REPORTER_BASE::KeepRefreshing( bool aWait )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxMilliSleep( 20 );
|
||||
wxMilliSleep( 33 /* 30 FPS refresh rate */ );
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -40,6 +40,11 @@ WX_GRID::WX_GRID( wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxS
|
||||
|
||||
// Make sure the GUI font scales properly on GTK
|
||||
SetDefaultCellFont( KIUI::GetControlFont( this ) );
|
||||
|
||||
#if wxCHECK_VERSION( 3, 1, 0 )
|
||||
Connect( wxEVT_DPI_CHANGED, wxDPIChangedEventHandler( WX_GRID::onDPIChanged ), nullptr, this );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -47,9 +52,25 @@ WX_GRID::~WX_GRID()
|
||||
{
|
||||
if( m_weOwnTable )
|
||||
DestroyTable( GetTable() );
|
||||
|
||||
#if wxCHECK_VERSION( 3, 1, 0 )
|
||||
Disconnect( wxEVT_DPI_CHANGED, wxDPIChangedEventHandler( WX_GRID::onDPIChanged ), nullptr, this );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
#if wxCHECK_VERSION( 3, 1, 0 )
|
||||
void WX_GRID::onDPIChanged(wxDPIChangedEvent& aEvt)
|
||||
{
|
||||
/// This terrible hack is a way to avoid the incredibly disruptive resizing of grids that happens on Macs
|
||||
/// when moving a window between monitors of different DPIs.
|
||||
#ifndef __WXMAC__
|
||||
aEvt.Skip();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void WX_GRID::SetColLabelSize( int aHeight )
|
||||
{
|
||||
if( aHeight == 0 )
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2022 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
|
||||
@@ -94,7 +94,10 @@ int CVPCB_MAINFRAME::buildEquivalenceList( FOOTPRINT_EQUIVALENCE_LIST& aList,
|
||||
{
|
||||
fn = wxExpandEnvVars( equfile );
|
||||
|
||||
tmp = search.FindValidPath( fn.GetFullPath() );
|
||||
if( fn.IsAbsolute() || fn.FileExists() )
|
||||
tmp = fn.GetFullPath();
|
||||
else
|
||||
tmp = search.FindValidPath( fn.GetFullPath() );
|
||||
|
||||
if( !tmp )
|
||||
{
|
||||
@@ -102,8 +105,7 @@ int CVPCB_MAINFRAME::buildEquivalenceList( FOOTPRINT_EQUIVALENCE_LIST& aList,
|
||||
|
||||
if( aErrorMessages )
|
||||
{
|
||||
error_msg.Printf( _( "Equivalence file '%s' could not be found in the "
|
||||
"default search paths." ),
|
||||
error_msg.Printf( _( "Equivalence file '%s' could not be found." ),
|
||||
fn.GetFullName() );
|
||||
|
||||
if( ! aErrorMessages->IsEmpty() )
|
||||
|
||||
@@ -175,7 +175,7 @@ set( EESCHEMA_SRCS
|
||||
fields_grid_table.cpp
|
||||
files-io.cpp
|
||||
generate_alias_info.cpp
|
||||
getpart.cpp
|
||||
picksymbol.cpp
|
||||
hierarch.cpp
|
||||
lib_shape.cpp
|
||||
lib_item.cpp
|
||||
|
||||
@@ -144,14 +144,14 @@ public:
|
||||
*/
|
||||
void DoAutoplace( bool aManual )
|
||||
{
|
||||
bool force_wire_spacing = false;
|
||||
bool forceWireSpacing = false;
|
||||
SIDE_AND_NPINS sideandpins = chooseSideForFields( aManual );
|
||||
SIDE field_side = sideandpins.side;
|
||||
wxPoint fbox_pos = fieldBoxPlacement( sideandpins );
|
||||
EDA_RECT field_box( fbox_pos, m_fbox_size );
|
||||
|
||||
if( aManual )
|
||||
force_wire_spacing = fitFieldsBetweenWires( &field_box, field_side );
|
||||
forceWireSpacing = fitFieldsBetweenWires( &field_box, field_side );
|
||||
|
||||
// Move the fields
|
||||
int last_y_coord = field_box.GetTop();
|
||||
@@ -160,6 +160,9 @@ public:
|
||||
{
|
||||
SCH_FIELD* field = m_fields[field_idx];
|
||||
|
||||
if( !field->IsVisible() )
|
||||
continue;
|
||||
|
||||
if( m_allow_rejustify )
|
||||
{
|
||||
if( sideandpins.pins > 0 )
|
||||
@@ -175,8 +178,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
wxPoint pos( fieldHorizPlacement( field, field_box ),
|
||||
fieldVertPlacement( field, field_box, &last_y_coord, !force_wire_spacing ) );
|
||||
wxPoint pos( fieldHPlacement( field, field_box ),
|
||||
fieldVPlacement( field, field_box, &last_y_coord, !forceWireSpacing ) );
|
||||
|
||||
if( m_align_to_grid )
|
||||
{
|
||||
@@ -201,7 +204,15 @@ protected:
|
||||
int max_field_width = 0;
|
||||
int total_height = 0;
|
||||
|
||||
std::vector<SCH_FIELD*> visibleFields;
|
||||
|
||||
for( SCH_FIELD* field : m_fields )
|
||||
{
|
||||
if( field->IsVisible() )
|
||||
visibleFields.push_back( field );
|
||||
}
|
||||
|
||||
for( SCH_FIELD* field : visibleFields )
|
||||
{
|
||||
if( m_symbol->GetTransform().y1 )
|
||||
field->SetTextAngle( TEXT_ANGLE_VERT );
|
||||
@@ -215,7 +226,7 @@ protected:
|
||||
max_field_width = std::max( max_field_width, field_width );
|
||||
|
||||
// Remove interline spacing from field_height for last line.
|
||||
if( field == m_fields[ m_fields.size() - 1 ] )
|
||||
if( field == visibleFields.back() )
|
||||
field_height *= 0.62;
|
||||
|
||||
if( !aDynamic )
|
||||
@@ -322,6 +333,7 @@ protected:
|
||||
if( item_box.Intersects( aRect ) )
|
||||
filtered.push_back( item );
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
@@ -642,7 +654,7 @@ protected:
|
||||
*
|
||||
* @return Correct field horizontal position
|
||||
*/
|
||||
int fieldHorizPlacement( SCH_FIELD *aField, const EDA_RECT &aFieldBox )
|
||||
int fieldHPlacement( SCH_FIELD *aField, const EDA_RECT &aFieldBox )
|
||||
{
|
||||
int field_hjust;
|
||||
int field_xcoord;
|
||||
@@ -677,13 +689,13 @@ protected:
|
||||
*
|
||||
* @param aField - the field to place.
|
||||
* @param aFieldBox - box in which fields will be placed.
|
||||
* @param aPosAccum - pointer to a position accumulator
|
||||
* @param aAccumulatedPosition - pointer to a position accumulator
|
||||
* @param aDynamic - use dynamic spacing
|
||||
*
|
||||
* @return Correct field vertical position
|
||||
*/
|
||||
int fieldVertPlacement( SCH_FIELD *aField, const EDA_RECT &aFieldBox, int *aPosAccum,
|
||||
bool aDynamic )
|
||||
int fieldVPlacement( SCH_FIELD *aField, const EDA_RECT &aFieldBox, int *aAccumulatedPosition,
|
||||
bool aDynamic )
|
||||
{
|
||||
int field_height;
|
||||
int padding;
|
||||
@@ -704,9 +716,9 @@ protected:
|
||||
padding = FIELD_PADDING;
|
||||
}
|
||||
|
||||
int placement = *aPosAccum + padding / 2 + field_height / 2;
|
||||
int placement = *aAccumulatedPosition + padding / 2 + field_height / 2;
|
||||
|
||||
*aPosAccum += padding + field_height;
|
||||
*aAccumulatedPosition += padding + field_height;
|
||||
|
||||
return placement;
|
||||
}
|
||||
|
||||
+242
-150
@@ -366,6 +366,9 @@ void CONNECTION_SUBGRAPH::UpdateItemConnections()
|
||||
{
|
||||
SCH_CONNECTION* item_conn = item->GetOrInitConnection( m_sheet, m_graph );
|
||||
|
||||
if( !item_conn )
|
||||
continue;
|
||||
|
||||
if( ( m_driver_connection->IsBus() && item_conn->IsNet() ) ||
|
||||
( m_driver_connection->IsNet() && item_conn->IsBus() ) )
|
||||
{
|
||||
@@ -585,142 +588,147 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
|
||||
// Pre-scan to see if we have a bus at this location
|
||||
SCH_LINE* busLine = aSheet.LastScreen()->GetBus( it.first );
|
||||
|
||||
for( auto primary_it = connection_vec.begin(); primary_it != connection_vec.end(); primary_it++ )
|
||||
// We don't want to spin up a new thread for fewer than 4 items (overhead costs)
|
||||
size_t parallelThreadCount = std::min<size_t>( std::thread::hardware_concurrency(),
|
||||
( connection_vec.size() + 3 ) / 4 );
|
||||
|
||||
std::atomic<size_t> nextItem( 0 );
|
||||
std::mutex update_mutex;
|
||||
std::vector<std::future<size_t>> returns( parallelThreadCount );
|
||||
|
||||
auto update_lambda = [&]() -> size_t
|
||||
{
|
||||
SCH_ITEM* connected_item = *primary_it;
|
||||
|
||||
// Bus entries are special: they can have connection points in the
|
||||
// middle of a wire segment, because the junction algo doesn't split
|
||||
// the segment in two where you place a bus entry. This means that
|
||||
// bus entries that don't land on the end of a line segment need to
|
||||
// have "virtual" connection points to the segments they graphically
|
||||
// touch.
|
||||
if( connected_item->Type() == SCH_BUS_WIRE_ENTRY_T )
|
||||
for( size_t ii = nextItem++; ii < connection_vec.size(); ii = nextItem++ )
|
||||
{
|
||||
// If this location only has the connection point of the bus
|
||||
// entry itself, this means that either the bus entry is not
|
||||
// connected to anything graphically, or that it is connected to
|
||||
// a segment at some point other than at one of the endpoints.
|
||||
if( connection_vec.size() == 1 )
|
||||
{
|
||||
if( busLine )
|
||||
{
|
||||
auto bus_entry = static_cast<SCH_BUS_WIRE_ENTRY*>( connected_item );
|
||||
bus_entry->m_connected_bus_item = busLine;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bus-to-bus entries are treated just like bus wires
|
||||
else if( connected_item->Type() == SCH_BUS_BUS_ENTRY_T )
|
||||
{
|
||||
if( connection_vec.size() < 2 )
|
||||
{
|
||||
if( busLine )
|
||||
{
|
||||
auto bus_entry = static_cast<SCH_BUS_BUS_ENTRY*>( connected_item );
|
||||
|
||||
if( it.first == bus_entry->GetPosition() )
|
||||
bus_entry->m_connected_bus_items[0] = busLine;
|
||||
else
|
||||
bus_entry->m_connected_bus_items[1] = busLine;
|
||||
|
||||
bus_entry->ConnectedItems( aSheet ).insert( busLine );
|
||||
busLine->ConnectedItems( aSheet ).insert( bus_entry );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Change junctions to be on bus junction layer if they are touching a bus
|
||||
else if( connected_item->Type() == SCH_JUNCTION_T )
|
||||
{
|
||||
connected_item->SetLayer( busLine ? LAYER_BUS_JUNCTION : LAYER_JUNCTION );
|
||||
}
|
||||
|
||||
for( auto test_it = primary_it + 1; test_it != connection_vec.end(); test_it++ )
|
||||
{
|
||||
bool bus_connection_ok = true;
|
||||
SCH_ITEM* test_item = *test_it;
|
||||
|
||||
wxASSERT( test_item != connected_item );
|
||||
|
||||
// Set up the link between the bus entry net and the bus
|
||||
SCH_ITEM* connected_item = connection_vec[ii];
|
||||
// Bus entries are special: they can have connection points in the
|
||||
// middle of a wire segment, because the junction algo doesn't split
|
||||
// the segment in two where you place a bus entry. This means that
|
||||
// bus entries that don't land on the end of a line segment need to
|
||||
// have "virtual" connection points to the segments they graphically
|
||||
// touch.
|
||||
if( connected_item->Type() == SCH_BUS_WIRE_ENTRY_T )
|
||||
{
|
||||
if( test_item->GetLayer() == LAYER_BUS )
|
||||
// If this location only has the connection point of the bus
|
||||
// entry itself, this means that either the bus entry is not
|
||||
// connected to anything graphically, or that it is connected to
|
||||
// a segment at some point other than at one of the endpoints.
|
||||
if( connection_vec.size() == 1 )
|
||||
{
|
||||
auto bus_entry = static_cast<SCH_BUS_WIRE_ENTRY*>( connected_item );
|
||||
bus_entry->m_connected_bus_item = test_item;
|
||||
if( busLine )
|
||||
{
|
||||
auto bus_entry = static_cast<SCH_BUS_WIRE_ENTRY*>( connected_item );
|
||||
bus_entry->m_connected_bus_item = busLine;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bus entries only connect to bus lines on the end that is touching a bus line.
|
||||
// If the user has overlapped another net line with the endpoint of the bus entry
|
||||
// where the entry connects to a bus, we don't want to short-circuit it.
|
||||
// Bus-to-bus entries are treated just like bus wires
|
||||
else if( connected_item->Type() == SCH_BUS_BUS_ENTRY_T )
|
||||
{
|
||||
if( connection_vec.size() < 2 )
|
||||
{
|
||||
if( busLine )
|
||||
{
|
||||
auto bus_entry = static_cast<SCH_BUS_BUS_ENTRY*>( connected_item );
|
||||
|
||||
if( it.first == bus_entry->GetPosition() )
|
||||
bus_entry->m_connected_bus_items[0] = busLine;
|
||||
else
|
||||
bus_entry->m_connected_bus_items[1] = busLine;
|
||||
|
||||
std::lock_guard<std::mutex> lock( update_mutex );
|
||||
bus_entry->AddConnectionTo( aSheet, busLine );
|
||||
busLine->AddConnectionTo( aSheet, bus_entry );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Change junctions to be on bus junction layer if they are touching a bus
|
||||
else if( connected_item->Type() == SCH_JUNCTION_T )
|
||||
{
|
||||
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;
|
||||
|
||||
if( test_item == connected_item )
|
||||
continue;
|
||||
|
||||
// Set up the link between the bus entry net and the bus
|
||||
if( connected_item->Type() == SCH_BUS_WIRE_ENTRY_T )
|
||||
{
|
||||
if( test_item->GetLayer() == LAYER_BUS )
|
||||
{
|
||||
auto bus_entry = static_cast<SCH_BUS_WIRE_ENTRY*>( connected_item );
|
||||
bus_entry->m_connected_bus_item = test_item;
|
||||
}
|
||||
}
|
||||
|
||||
// Bus entries only connect to bus lines on the end that is touching a bus line.
|
||||
// If the user has overlapped another net line with the endpoint of the bus entry
|
||||
// where the entry connects to a bus, we don't want to short-circuit it.
|
||||
if( connected_item->Type() == SCH_BUS_WIRE_ENTRY_T )
|
||||
{
|
||||
bus_connection_ok = !busLine || test_item->GetLayer() == LAYER_BUS;
|
||||
}
|
||||
else if( test_item->Type() == SCH_BUS_WIRE_ENTRY_T )
|
||||
{
|
||||
bus_connection_ok = !busLine || connected_item->GetLayer() == LAYER_BUS;
|
||||
}
|
||||
|
||||
if( connected_item->ConnectionPropagatesTo( test_item ) &&
|
||||
test_item->ConnectionPropagatesTo( connected_item ) &&
|
||||
bus_connection_ok )
|
||||
{
|
||||
connected_set.push_back( test_item );
|
||||
}
|
||||
}
|
||||
|
||||
// If we got this far and did not find a connected bus item for a bus entry,
|
||||
// we should do a manual scan in case there is a bus item on this connection
|
||||
// point but we didn't pick it up earlier because there is *also* a net item here.
|
||||
if( connected_item->Type() == SCH_BUS_WIRE_ENTRY_T )
|
||||
{
|
||||
bus_connection_ok = !busLine || test_item->GetLayer() == LAYER_BUS;
|
||||
}
|
||||
else if( test_item->Type() == SCH_BUS_WIRE_ENTRY_T )
|
||||
{
|
||||
bus_connection_ok = !busLine || connected_item->GetLayer() == LAYER_BUS;
|
||||
}
|
||||
auto bus_entry = static_cast<SCH_BUS_WIRE_ENTRY*>( connected_item );
|
||||
|
||||
if( connected_item->ConnectionPropagatesTo( test_item ) &&
|
||||
test_item->ConnectionPropagatesTo( connected_item ) &&
|
||||
bus_connection_ok )
|
||||
{
|
||||
connected_item->ConnectedItems( aSheet ).insert( test_item );
|
||||
test_item->ConnectedItems( aSheet ).insert( connected_item );
|
||||
if( !bus_entry->m_connected_bus_item )
|
||||
{
|
||||
SCH_SCREEN* screen = aSheet.LastScreen();
|
||||
SCH_LINE* bus = screen->GetBus( it.first );
|
||||
|
||||
if( bus )
|
||||
bus_entry->m_connected_bus_item = bus;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we got this far and did not find a connected bus item for a bus entry,
|
||||
// we should do a manual scan in case there is a bus item on this connection
|
||||
// point but we didn't pick it up earlier because there is *also* a net item here.
|
||||
if( connected_item->Type() == SCH_BUS_WIRE_ENTRY_T )
|
||||
{
|
||||
auto bus_entry = static_cast<SCH_BUS_WIRE_ENTRY*>( connected_item );
|
||||
return 1;
|
||||
};
|
||||
|
||||
if( !bus_entry->m_connected_bus_item )
|
||||
{
|
||||
SCH_SCREEN* screen = aSheet.LastScreen();
|
||||
SCH_LINE* bus = screen->GetBus( it.first );
|
||||
|
||||
if( bus )
|
||||
bus_entry->m_connected_bus_item = bus;
|
||||
}
|
||||
}
|
||||
if( parallelThreadCount == 1 )
|
||||
update_lambda();
|
||||
else
|
||||
{
|
||||
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
|
||||
returns[ii] = std::async( std::launch::async, update_lambda );
|
||||
|
||||
// Finalize the threads
|
||||
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
|
||||
returns[ii].wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO(JE) This won't give the same subgraph IDs (and eventually net/graph codes)
|
||||
// to the same subgraph necessarily if it runs over and over again on the same
|
||||
// sheet. We need:
|
||||
//
|
||||
// a) a cache of net/bus codes, like used before
|
||||
// b) to persist the CONNECTION_GRAPH globally so the cache is persistent,
|
||||
// c) some way of trying to avoid changing net names. so we should keep track
|
||||
// of the previous driver of a net, and if it comes down to choosing between
|
||||
// equally-prioritized drivers, choose the one that already exists as a driver
|
||||
// on some portion of the items.
|
||||
|
||||
|
||||
void CONNECTION_GRAPH::buildConnectionGraph()
|
||||
void CONNECTION_GRAPH::buildItemSubGraphs()
|
||||
{
|
||||
// Recache all bus aliases for later use
|
||||
wxCHECK_RET( m_schematic, wxT( "Connection graph cannot be built without schematic pointer" ) );
|
||||
|
||||
SCH_SHEET_LIST all_sheets = m_schematic->GetSheets();
|
||||
|
||||
for( unsigned i = 0; i < all_sheets.size(); i++ )
|
||||
{
|
||||
for( const auto& alias : all_sheets[i].LastScreen()->GetBusAliases() )
|
||||
m_bus_alias_cache[ alias->GetName() ] = alias;
|
||||
}
|
||||
|
||||
// Build subgraphs from items (on a per-sheet basis)
|
||||
|
||||
for( SCH_ITEM* item : m_items )
|
||||
@@ -742,21 +750,25 @@ void CONNECTION_GRAPH::buildConnectionGraph()
|
||||
connection->SetSubgraphCode( subgraph->m_code );
|
||||
m_item_to_subgraph_map[item] = subgraph;
|
||||
|
||||
std::list<SCH_ITEM*> members;
|
||||
std::list<SCH_ITEM*> memberlist;
|
||||
|
||||
auto get_items =
|
||||
[&]( SCH_ITEM* aItem ) -> bool
|
||||
{
|
||||
SCH_CONNECTION* conn = aItem->GetOrInitConnection( sheet, this );
|
||||
bool unique = !( aItem->GetFlags() & CANDIDATE );
|
||||
|
||||
return ( conn->SubgraphCode() == 0 );
|
||||
if( conn && !conn->SubgraphCode() )
|
||||
aItem->SetFlags( CANDIDATE );
|
||||
|
||||
return ( unique && conn && ( conn->SubgraphCode() == 0 ) );
|
||||
};
|
||||
|
||||
std::copy_if( item->ConnectedItems( sheet ).begin(),
|
||||
item->ConnectedItems( sheet ).end(),
|
||||
std::back_inserter( members ), get_items );
|
||||
std::back_inserter( memberlist ), get_items );
|
||||
|
||||
for( SCH_ITEM* connected_item : members )
|
||||
for( SCH_ITEM* connected_item : memberlist )
|
||||
{
|
||||
if( connected_item->Type() == SCH_NO_CONNECT_T )
|
||||
subgraph->m_no_connect = connected_item;
|
||||
@@ -770,24 +782,32 @@ void CONNECTION_GRAPH::buildConnectionGraph()
|
||||
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 );
|
||||
|
||||
std::copy_if( connected_item->ConnectedItems( sheet ).begin(),
|
||||
connected_item->ConnectedItems( sheet ).end(),
|
||||
std::back_inserter( members ), get_items );
|
||||
for( SCH_ITEM* citem : citemset )
|
||||
{
|
||||
if( citem->HasFlag( CANDIDATE ) )
|
||||
continue;
|
||||
|
||||
if( get_items( citem ) )
|
||||
memberlist.push_back( citem );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( SCH_ITEM* connected_item : memberlist )
|
||||
connected_item->ClearFlags( CANDIDATE );
|
||||
|
||||
subgraph->m_dirty = true;
|
||||
m_subgraphs.push_back( subgraph );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO(JE): Net codes are non-deterministic. Fortunately, they are also not really used for
|
||||
* anything. We should consider removing them entirely and just using net names everywhere.
|
||||
*/
|
||||
}
|
||||
|
||||
void CONNECTION_GRAPH::resolveAllDrivers()
|
||||
{
|
||||
// Resolve drivers for subgraphs and propagate connectivity info
|
||||
|
||||
// We don't want to spin up a new thread for fewer than 8 nets (overhead costs)
|
||||
@@ -867,7 +887,11 @@ void CONNECTION_GRAPH::buildConnectionGraph()
|
||||
{
|
||||
return candidate->m_driver;
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
void CONNECTION_GRAPH::collectAllDriverValues()
|
||||
{
|
||||
// Check for subgraphs with the same net name but only weak drivers.
|
||||
// For example, two wires that are both connected to hierarchical
|
||||
// sheet pins that happen to have the same name, but are not the same.
|
||||
@@ -922,7 +946,11 @@ void CONNECTION_GRAPH::buildConnectionGraph()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CONNECTION_GRAPH::generateInvisiblePinSubGraphs()
|
||||
{
|
||||
// Generate subgraphs for invisible power pins. These will be merged with other subgraphs
|
||||
// on the same sheet in the next loop.
|
||||
|
||||
@@ -942,7 +970,7 @@ void CONNECTION_GRAPH::buildConnectionGraph()
|
||||
SCH_CONNECTION* connection = pin->GetOrInitConnection( sheet, this );
|
||||
|
||||
// If this pin already has a subgraph, don't need to process
|
||||
if( connection->SubgraphCode() > 0 )
|
||||
if( !connection || connection->SubgraphCode() > 0 )
|
||||
continue;
|
||||
|
||||
connection->SetName( pin->GetShownName() );
|
||||
@@ -979,7 +1007,11 @@ void CONNECTION_GRAPH::buildConnectionGraph()
|
||||
|
||||
connection->SetSubgraphCode( subgraph->m_code );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CONNECTION_GRAPH::processSubGraphs()
|
||||
{
|
||||
// Here we do all the local (sheet) processing of each subgraph, including assigning net
|
||||
// codes, merging subgraphs together that use label connections, etc.
|
||||
|
||||
@@ -1306,6 +1338,58 @@ void CONNECTION_GRAPH::buildConnectionGraph()
|
||||
subgraph->m_driver_connection->Name() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// TODO(JE) This won't give the same subgraph IDs (and eventually net/graph codes)
|
||||
// to the same subgraph necessarily if it runs over and over again on the same
|
||||
// sheet. We need:
|
||||
//
|
||||
// a) a cache of net/bus codes, like used before
|
||||
// b) to persist the CONNECTION_GRAPH globally so the cache is persistent,
|
||||
// c) some way of trying to avoid changing net names. so we should keep track
|
||||
// of the previous driver of a net, and if it comes down to choosing between
|
||||
// equally-prioritized drivers, choose the one that already exists as a driver
|
||||
// on some portion of the items.
|
||||
|
||||
|
||||
void CONNECTION_GRAPH::buildConnectionGraph()
|
||||
{
|
||||
// Recache all bus aliases for later use
|
||||
wxCHECK_RET( m_schematic, wxT( "Connection graph cannot be built without schematic pointer" ) );
|
||||
|
||||
SCH_SHEET_LIST all_sheets = m_schematic->GetSheets();
|
||||
|
||||
for( unsigned i = 0; i < all_sheets.size(); i++ )
|
||||
{
|
||||
for( const auto& alias : all_sheets[i].LastScreen()->GetBusAliases() )
|
||||
m_bus_alias_cache[ alias->GetName() ] = alias;
|
||||
}
|
||||
|
||||
PROF_TIMER sub_graph( "buildItemSubGraphs" );
|
||||
buildItemSubGraphs();
|
||||
|
||||
if( wxLog::IsAllowedTraceMask( ConnProfileMask ) )
|
||||
sub_graph.Show();
|
||||
|
||||
|
||||
/**
|
||||
* TODO(JE): Net codes are non-deterministic. Fortunately, they are also not really used for
|
||||
* anything. We should consider removing them entirely and just using net names everywhere.
|
||||
*/
|
||||
|
||||
resolveAllDrivers();
|
||||
|
||||
collectAllDriverValues();
|
||||
|
||||
generateInvisiblePinSubGraphs();
|
||||
|
||||
PROF_TIMER proc_sub_graph( "ProcessSubGraphs" );
|
||||
processSubGraphs();
|
||||
|
||||
if( wxLog::IsAllowedTraceMask( ConnProfileMask ) )
|
||||
proc_sub_graph.Show();
|
||||
|
||||
// Absorbed subgraphs should no longer be considered
|
||||
alg::delete_if( m_driver_subgraphs, [&]( const CONNECTION_SUBGRAPH* candidate ) -> bool
|
||||
{
|
||||
@@ -1328,7 +1412,13 @@ void CONNECTION_GRAPH::buildConnectionGraph()
|
||||
m_sheet_to_subgraphs_map[ subgraph->m_sheet ].emplace_back( subgraph );
|
||||
|
||||
// Update item connections at this point so that neighbor propagation works
|
||||
nextSubgraph.store( 0 );
|
||||
std::atomic<size_t> nextSubgraph( 0 );
|
||||
|
||||
// We don't want to spin up a new thread for fewer than 8 nets (overhead costs)
|
||||
size_t parallelThreadCount = std::min<size_t>( std::thread::hardware_concurrency(),
|
||||
( m_subgraphs.size() + 3 ) / 4 );
|
||||
|
||||
std::vector<std::future<size_t>> returns( parallelThreadCount );
|
||||
|
||||
auto preliminaryUpdateTask =
|
||||
[&]() -> size_t
|
||||
@@ -1901,7 +1991,7 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
|
||||
// member to have the correct connection info
|
||||
if( conn->IsBus() && !stale_bus_members.empty() )
|
||||
{
|
||||
for( auto stale_member : stale_bus_members )
|
||||
for( SCH_CONNECTION* stale_member : stale_bus_members )
|
||||
{
|
||||
for( CONNECTION_SUBGRAPH* subgraph : visited )
|
||||
{
|
||||
@@ -1933,13 +2023,13 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
|
||||
std::shared_ptr<SCH_CONNECTION> CONNECTION_GRAPH::getDefaultConnection( SCH_ITEM* aItem,
|
||||
CONNECTION_SUBGRAPH* aSubgraph )
|
||||
{
|
||||
auto c = std::shared_ptr<SCH_CONNECTION>( nullptr );
|
||||
std::shared_ptr<SCH_CONNECTION> c = std::shared_ptr<SCH_CONNECTION>( nullptr );
|
||||
|
||||
switch( aItem->Type() )
|
||||
{
|
||||
case SCH_PIN_T:
|
||||
{
|
||||
auto pin = static_cast<SCH_PIN*>( aItem );
|
||||
SCH_PIN* pin = static_cast<SCH_PIN*>( aItem );
|
||||
|
||||
if( pin->IsPowerConnection() )
|
||||
c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->m_sheet );
|
||||
@@ -1981,7 +2071,7 @@ SCH_CONNECTION* CONNECTION_GRAPH::matchBusMember( SCH_CONNECTION* aBusConnection
|
||||
// Vector bus: compare against index, because we allow the name
|
||||
// to be different
|
||||
|
||||
for( const auto& bus_member : aBusConnection->Members() )
|
||||
for( const std::shared_ptr<SCH_CONNECTION>& bus_member : aBusConnection->Members() )
|
||||
{
|
||||
if( bus_member->VectorIndex() == aSearch->VectorIndex() )
|
||||
{
|
||||
@@ -1993,14 +2083,14 @@ SCH_CONNECTION* CONNECTION_GRAPH::matchBusMember( SCH_CONNECTION* aBusConnection
|
||||
else
|
||||
{
|
||||
// Group bus
|
||||
for( const auto& c : aBusConnection->Members() )
|
||||
for( const std::shared_ptr<SCH_CONNECTION>& c : aBusConnection->Members() )
|
||||
{
|
||||
// Vector inside group: compare names, because for bus groups
|
||||
// we expect the naming to be consistent across all usages
|
||||
// TODO(JE) explain this in the docs
|
||||
if( c->Type() == CONNECTION_TYPE::BUS )
|
||||
{
|
||||
for( const auto& bus_member : c->Members() )
|
||||
for( const std::shared_ptr<SCH_CONNECTION>& bus_member : c->Members() )
|
||||
{
|
||||
if( bus_member->LocalName() == aSearch->LocalName() )
|
||||
{
|
||||
@@ -2051,7 +2141,7 @@ std::vector<const CONNECTION_SUBGRAPH*> CONNECTION_GRAPH::GetBusesNeedingMigrati
|
||||
{
|
||||
std::vector<const CONNECTION_SUBGRAPH*> ret;
|
||||
|
||||
for( auto&& subgraph : m_subgraphs )
|
||||
for( CONNECTION_SUBGRAPH* subgraph : m_subgraphs )
|
||||
{
|
||||
// Graph is supposed to be up-to-date before calling this
|
||||
wxASSERT( !subgraph->m_dirty );
|
||||
@@ -2313,8 +2403,8 @@ bool CONNECTION_GRAPH::ercCheckMultipleDrivers( const CONNECTION_SUBGRAPH* aSubg
|
||||
|
||||
bool CONNECTION_GRAPH::ercCheckBusToNetConflicts( const CONNECTION_SUBGRAPH* aSubgraph )
|
||||
{
|
||||
auto sheet = aSubgraph->m_sheet;
|
||||
auto screen = sheet.LastScreen();
|
||||
const SCH_SHEET_PATH& sheet = aSubgraph->m_sheet;
|
||||
SCH_SCREEN* screen = sheet.LastScreen();
|
||||
|
||||
SCH_ITEM* net_item = nullptr;
|
||||
SCH_ITEM* bus_item = nullptr;
|
||||
@@ -2371,8 +2461,8 @@ bool CONNECTION_GRAPH::ercCheckBusToNetConflicts( const CONNECTION_SUBGRAPH* aSu
|
||||
bool CONNECTION_GRAPH::ercCheckBusToBusConflicts( const CONNECTION_SUBGRAPH* aSubgraph )
|
||||
{
|
||||
wxString msg;
|
||||
auto sheet = aSubgraph->m_sheet;
|
||||
auto screen = sheet.LastScreen();
|
||||
const SCH_SHEET_PATH& sheet = aSubgraph->m_sheet;
|
||||
SCH_SCREEN* screen = sheet.LastScreen();
|
||||
|
||||
SCH_ITEM* label = nullptr;
|
||||
SCH_ITEM* port = nullptr;
|
||||
@@ -2440,8 +2530,8 @@ bool CONNECTION_GRAPH::ercCheckBusToBusConflicts( const CONNECTION_SUBGRAPH* aSu
|
||||
bool CONNECTION_GRAPH::ercCheckBusToBusEntryConflicts( const CONNECTION_SUBGRAPH* aSubgraph )
|
||||
{
|
||||
bool conflict = false;
|
||||
auto sheet = aSubgraph->m_sheet;
|
||||
auto screen = sheet.LastScreen();
|
||||
const SCH_SHEET_PATH& sheet = aSubgraph->m_sheet;
|
||||
SCH_SCREEN* screen = sheet.LastScreen();
|
||||
|
||||
SCH_BUS_WIRE_ENTRY* bus_entry = nullptr;
|
||||
SCH_ITEM* bus_wire = nullptr;
|
||||
@@ -2453,7 +2543,7 @@ bool CONNECTION_GRAPH::ercCheckBusToBusEntryConflicts( const CONNECTION_SUBGRAPH
|
||||
return true;
|
||||
}
|
||||
|
||||
for( auto item : aSubgraph->m_items )
|
||||
for( SCH_ITEM* item : aSubgraph->m_items )
|
||||
{
|
||||
switch( item->Type() )
|
||||
{
|
||||
@@ -2509,7 +2599,9 @@ bool CONNECTION_GRAPH::ercCheckBusToBusEntryConflicts( const CONNECTION_SUBGRAPH
|
||||
// or global label
|
||||
if( conflict && CONNECTION_SUBGRAPH::GetDriverPriority( aSubgraph->m_driver )
|
||||
>= CONNECTION_SUBGRAPH::PRIORITY::POWER_PIN )
|
||||
{
|
||||
conflict = false;
|
||||
}
|
||||
|
||||
if( conflict )
|
||||
{
|
||||
@@ -2653,8 +2745,8 @@ bool CONNECTION_GRAPH::ercCheckNoConnects( const CONNECTION_SUBGRAPH* aSubgraph
|
||||
wxString name = pin->Connection( &sheet )->Name();
|
||||
wxString local_name = pin->Connection( &sheet )->Name( true );
|
||||
|
||||
if( m_global_label_cache.count( name ) ||
|
||||
( m_local_label_cache.count( std::make_pair( sheet, local_name ) ) ) )
|
||||
if( m_global_label_cache.count( name )
|
||||
|| m_local_label_cache.count( std::make_pair( sheet, local_name ) ) )
|
||||
{
|
||||
has_other_connections = true;
|
||||
}
|
||||
@@ -2787,7 +2879,7 @@ bool CONNECTION_GRAPH::ercCheckLabels( const CONNECTION_SUBGRAPH* aSubgraph )
|
||||
return false;
|
||||
};
|
||||
|
||||
for( auto item : aSubgraph->m_items )
|
||||
for( SCH_ITEM* item : aSubgraph->m_items )
|
||||
{
|
||||
switch( item->Type() )
|
||||
{
|
||||
@@ -2837,9 +2929,9 @@ bool CONNECTION_GRAPH::ercCheckLabels( const CONNECTION_SUBGRAPH* aSubgraph )
|
||||
|
||||
if( isGlobal )
|
||||
{
|
||||
// This will be set to true if the global is connected to a pin above, but we
|
||||
// want to reset this to false so that globals get flagged if they only have a
|
||||
// single instance connected to a single pin
|
||||
// This will be set to true if the global is connected to a pin above, but we want to
|
||||
// reset this to false so that globals get flagged if they only have a single instance
|
||||
// connected to a single pin
|
||||
hasOtherConnections = ( pinCount > 1 );
|
||||
|
||||
auto it = m_net_name_to_subgraphs_map.find( name );
|
||||
@@ -2853,9 +2945,9 @@ bool CONNECTION_GRAPH::ercCheckLabels( const CONNECTION_SUBGRAPH* aSubgraph )
|
||||
else if( text->Type() == SCH_HIER_LABEL_T )
|
||||
{
|
||||
// For a hier label, check if the parent pin is connected
|
||||
if( aSubgraph->m_hier_parent &&
|
||||
( aSubgraph->m_hier_parent->m_strong_driver ||
|
||||
aSubgraph->m_hier_parent->m_drivers.size() > 1) )
|
||||
if( aSubgraph->m_hier_parent
|
||||
&& ( aSubgraph->m_hier_parent->m_strong_driver
|
||||
|| aSubgraph->m_hier_parent->m_drivers.size() > 1) )
|
||||
{
|
||||
// For now, a simple check: if there is more than one driver, the parent is probably
|
||||
// connected elsewhere (because at least one driver will be the hier pin itself)
|
||||
|
||||
@@ -370,6 +370,33 @@ private:
|
||||
*/
|
||||
void buildConnectionGraph();
|
||||
|
||||
/**
|
||||
* Generates individual item subgraphs on a per-sheet basis
|
||||
*/
|
||||
void buildItemSubGraphs();
|
||||
|
||||
/**
|
||||
* Finds all subgraphs in the connection graph and calls ResolveDrivers() in
|
||||
* parallel
|
||||
*/
|
||||
void resolveAllDrivers();
|
||||
|
||||
/**
|
||||
* Maps the driver values for each subgraph
|
||||
*/
|
||||
void collectAllDriverValues();
|
||||
|
||||
/**
|
||||
* Iterate through the invisible power pins to collect the global labels
|
||||
* as drivers
|
||||
*/
|
||||
void generateInvisiblePinSubGraphs();
|
||||
|
||||
/**
|
||||
* Process all subgraphs to assign netcodes and merge subgraphs based on labels
|
||||
*/
|
||||
void processSubGraphs();
|
||||
|
||||
/**
|
||||
* Helper to assign a new net code to a connection
|
||||
*
|
||||
|
||||
@@ -396,7 +396,7 @@ void DIALOG_ERC::testErc()
|
||||
|| settings.IsTestEnabled( ERCE_POWERPIN_NOT_DRIVEN )
|
||||
|| settings.IsTestEnabled( ERCE_PIN_NOT_DRIVEN ) )
|
||||
{
|
||||
tester.TestPinToPin();
|
||||
tester.TestPinToPin();
|
||||
}
|
||||
|
||||
// Test similar labels (i;e. labels which are identical when
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <sch_line.h>
|
||||
#include <sch_junction.h>
|
||||
#include <sch_sheet.h>
|
||||
#include <sch_sheet_pin.h>
|
||||
#include <schematic.h>
|
||||
#include <advanced_config.h>
|
||||
#include <tool/tool_manager.h>
|
||||
@@ -412,6 +413,12 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::visitItem( const SCH_SHEET_PATH& aShe
|
||||
if( m_setBgColor->GetValue() )
|
||||
sheet->SetBackgroundColor( m_bgColorSwatch->GetSwatchColor() );
|
||||
}
|
||||
|
||||
if( m_sheetPins->GetValue() )
|
||||
{
|
||||
for( SCH_SHEET_PIN* pin : sheet->GetPins() )
|
||||
processItem( aSheetPath, pin );
|
||||
}
|
||||
}
|
||||
else if( aItem->Type() == SCH_JUNCTION_T )
|
||||
{
|
||||
@@ -439,8 +446,6 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::visitItem( const SCH_SHEET_PATH& aShe
|
||||
processItem( aSheetPath, aItem );
|
||||
else if( m_hierLabels->GetValue() && aItem->Type() == SCH_HIER_LABEL_T )
|
||||
processItem( aSheetPath, aItem );
|
||||
else if( m_sheetPins->GetValue() && aItem->Type() == SCH_SHEET_PIN_T )
|
||||
processItem( aSheetPath, aItem );
|
||||
else if( m_schTextAndGraphics->GetValue() && aItem->IsType( schTextAndGraphics ) )
|
||||
processItem( aSheetPath, aItem );
|
||||
}
|
||||
|
||||
@@ -621,6 +621,7 @@ void DIALOG_LIB_EDIT_PIN_TABLE::OnAddRow( wxCommandEvent& event )
|
||||
newPin->SetOrientation( last->GetOrientation() );
|
||||
newPin->SetType( last->GetType() );
|
||||
newPin->SetShape( last->GetShape() );
|
||||
newPin->SetParent( last->GetParent() );
|
||||
|
||||
wxPoint pos = last->GetPosition();
|
||||
|
||||
|
||||
@@ -75,10 +75,10 @@ bool DIALOG_LIB_SHAPE_PROPERTIES::TransferDataToWindow()
|
||||
|
||||
bool enblConvOptStyle = symbol && symbol->HasConversion();
|
||||
|
||||
// if a symbol contains no graphic items, symbol->HasConversion() returns false.
|
||||
// but when creating a new symbol, with DeMorgan option set, the ApplyToAllConversions
|
||||
// must be enabled even if symbol->HasConversion() returns false in order to be able
|
||||
// to create graphic items shared by all body styles
|
||||
// If a symbol contains no conversion-specific pins or graphic items, symbol->HasConversion()
|
||||
// will return false.
|
||||
// But when creating a new symbol, with DeMorgan option set, the ApplyToAllConversions
|
||||
// must be enabled in order to be able to create graphic items shared by all body styles.
|
||||
if( m_frame->GetShowDeMorgan() )
|
||||
enblConvOptStyle = true;
|
||||
|
||||
|
||||
@@ -174,7 +174,13 @@ bool DIALOG_LIB_SYMBOL_PROPERTIES::TransferDataToWindow()
|
||||
m_SelNumberOfUnits->SetValue( m_libEntry->GetUnitCount() );
|
||||
m_OptionPartsInterchangeable->SetValue( !m_libEntry->UnitsLocked() ||
|
||||
m_libEntry->GetUnitCount() == 1 );
|
||||
m_AsConvertButt->SetValue( m_libEntry->HasConversion() );
|
||||
|
||||
// If a symbol contains no conversion-specific pins or graphic items, symbol->HasConversion()
|
||||
// will return false. But when editing a symbol with DeMorgan option set, we don't want to
|
||||
// keep turning it off just because there aren't any conversion-specific items yet, so we force
|
||||
// it to on if the parent frame has it enabled.
|
||||
m_AsConvertButt->SetValue( m_Parent->GetShowDeMorgan() );
|
||||
|
||||
m_OptionPower->SetValue( m_libEntry->IsPower() );
|
||||
m_excludeFromBomCheckBox->SetValue( !m_libEntry->GetIncludeInBom() );
|
||||
m_excludeFromBoardCheckBox->SetValue( !m_libEntry->GetIncludeOnBoard() );
|
||||
@@ -367,6 +373,7 @@ bool DIALOG_LIB_SYMBOL_PROPERTIES::TransferDataFromWindow()
|
||||
m_libEntry->LockUnits( m_libEntry->GetUnitCount() > 1 &&
|
||||
!m_OptionPartsInterchangeable->GetValue() );
|
||||
m_libEntry->SetConversion( m_AsConvertButt->GetValue() );
|
||||
m_Parent->SetShowDeMorgan( m_AsConvertButt->GetValue() );
|
||||
|
||||
if( m_OptionPower->GetValue() )
|
||||
m_libEntry->SetPower();
|
||||
@@ -448,17 +455,23 @@ void DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanging( wxGridEvent& event )
|
||||
|
||||
void DIALOG_LIB_SYMBOL_PROPERTIES::OnSymbolNameText( wxCommandEvent& event )
|
||||
{
|
||||
if( !m_Parent->IsSymbolFromSchematic() )
|
||||
if( !m_Parent->IsSymbolFromSchematic() || m_OptionPower->IsChecked() )
|
||||
m_grid->SetCellValue( VALUE_FIELD, FDC_VALUE, m_SymbolNameCtrl->GetValue() );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_LIB_SYMBOL_PROPERTIES::OnSymbolNameKillFocus( wxFocusEvent& event )
|
||||
{
|
||||
if( !m_delayedFocusCtrl && !m_SymbolNameCtrl->GetValidator()->Validate( m_SymbolNameCtrl ) )
|
||||
if( !m_delayedFocusCtrl )
|
||||
{
|
||||
// If the validation fails and we throw up a dialog then GTK will give us another
|
||||
// KillFocus event and we end up in infinite recursion. So we use m_delayedFocusCtrl
|
||||
// as a re-entrancy block and then clear it again if validation passes.
|
||||
m_delayedFocusCtrl = m_SymbolNameCtrl;
|
||||
m_delayedFocusPage = 0;
|
||||
|
||||
if( m_SymbolNameCtrl->GetValidator()->Validate( m_SymbolNameCtrl ) )
|
||||
m_delayedFocusCtrl = nullptr;
|
||||
}
|
||||
|
||||
event.Skip();
|
||||
@@ -593,7 +606,7 @@ void DIALOG_LIB_SYMBOL_PROPERTIES::OnEditSpiceModel( wxCommandEvent& event )
|
||||
{
|
||||
#ifdef KICAD_SPICE
|
||||
int diff = m_fields->size();
|
||||
auto symbol = SCH_SYMBOL( *m_libEntry, m_libEntry->GetLibId(), nullptr );
|
||||
auto symbol = SCH_SYMBOL( *m_libEntry, m_libEntry->GetLibId(), nullptr, 0 );
|
||||
|
||||
DIALOG_SPICE_MODEL dialog( this, symbol, m_fields );
|
||||
|
||||
|
||||
@@ -168,7 +168,6 @@ private:
|
||||
|
||||
public:
|
||||
SCH_EDIT_FRAME* m_Parent;
|
||||
wxString m_DefaultNetFmtName;
|
||||
NETLIST_PAGE_DIALOG* m_PanelNetType[4 + CUSTOMPANEL_COUNTMAX];
|
||||
};
|
||||
|
||||
@@ -217,11 +216,7 @@ NETLIST_PAGE_DIALOG::NETLIST_PAGE_DIALOG( wxNotebook* parent, const wxString& ti
|
||||
m_TitleStringCtrl = nullptr;
|
||||
m_AdjustPassiveValues = nullptr;
|
||||
|
||||
wxString netfmtName = static_cast<NETLIST_DIALOG*>( parent->GetParent() )->m_DefaultNetFmtName;
|
||||
|
||||
bool selected = m_pageNetFmtName == netfmtName;
|
||||
|
||||
parent->AddPage( this, title, selected );
|
||||
parent->AddPage( this, title, false );
|
||||
|
||||
wxBoxSizer* MainBoxSizer = new wxBoxSizer( wxVERTICAL );
|
||||
SetSizer( MainBoxSizer );
|
||||
@@ -246,8 +241,6 @@ NETLIST_DIALOG::NETLIST_DIALOG( SCH_EDIT_FRAME* parent ) :
|
||||
|
||||
SCHEMATIC_SETTINGS& settings = m_Parent->Schematic().Settings();
|
||||
|
||||
m_DefaultNetFmtName = settings.m_NetFormatName;
|
||||
|
||||
for( NETLIST_PAGE_DIALOG*& page : m_PanelNetType)
|
||||
page = nullptr;
|
||||
|
||||
@@ -271,6 +264,15 @@ NETLIST_DIALOG::NETLIST_DIALOG( SCH_EDIT_FRAME* parent ) :
|
||||
|
||||
m_sdbSizer2OK->SetDefault();
|
||||
|
||||
for( int ii = 0; m_PanelNetType[ii] && ii < 4 + CUSTOMPANEL_COUNTMAX; ++ii )
|
||||
{
|
||||
if( m_PanelNetType[ii]->GetPageNetFmtName() == settings.m_NetFormatName )
|
||||
{
|
||||
m_NoteBook->ChangeSelection( ii );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Now all widgets have the size fixed, call FinishDialogSettings
|
||||
finishDialogSettings();
|
||||
}
|
||||
@@ -416,8 +418,6 @@ void NETLIST_DIALOG::OnNetlistTypeSelection( wxNotebookEvent& event )
|
||||
if( currPage == nullptr )
|
||||
return;
|
||||
|
||||
m_DefaultNetFmtName = currPage->GetPageNetFmtName();
|
||||
|
||||
m_buttonDelGenerator->Enable( currPage->m_IdNetType >= NET_TYPE_CUSTOM1 );
|
||||
}
|
||||
|
||||
@@ -431,8 +431,7 @@ void NETLIST_DIALOG::NetlistUpdateOpt()
|
||||
|
||||
settings.m_SpiceAdjustPassiveValues = adjust;
|
||||
settings.m_SpiceCommandString = spice_cmd_string;
|
||||
settings.m_NetFormatName = wxEmptyString;
|
||||
settings.m_NetFormatName = m_DefaultNetFmtName;
|
||||
settings.m_NetFormatName = m_PanelNetType[m_NoteBook->GetSelection()]->GetPageNetFmtName();
|
||||
}
|
||||
|
||||
|
||||
@@ -591,7 +590,6 @@ void NETLIST_DIALOG::OnDelGenerator( wxCommandEvent& event )
|
||||
|
||||
currPage->m_CommandStringCtrl->SetValue( wxEmptyString );
|
||||
currPage->m_TitleStringCtrl->SetValue( wxEmptyString );
|
||||
m_DefaultNetFmtName = m_PanelNetType[PANELPCBNEW]->GetPageNetFmtName();
|
||||
|
||||
WriteCurrentNetlistSetup();
|
||||
|
||||
@@ -718,17 +716,8 @@ int InvokeDialogNetList( SCH_EDIT_FRAME* aCaller )
|
||||
{
|
||||
NETLIST_DIALOG dlg( aCaller );
|
||||
|
||||
SCHEMATIC_SETTINGS& settings = aCaller->Schematic().Settings();
|
||||
|
||||
wxString curr_default_netformat = settings.m_NetFormatName;
|
||||
|
||||
int ret = dlg.ShowModal();
|
||||
|
||||
// Update the default netlist and store it in prj config if it was explicitly changed.
|
||||
settings.m_NetFormatName = dlg.m_DefaultNetFmtName; // can have temporary changed
|
||||
|
||||
if( curr_default_netformat != dlg.m_DefaultNetFmtName )
|
||||
aCaller->SaveProjectSettings();
|
||||
aCaller->SaveProjectSettings();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1250,7 +1250,15 @@ wxString DIALOG_PLOT_SCHEMATIC::getOutputPath()
|
||||
wxStandardPaths::Get().GetDocumentsDir() );
|
||||
|
||||
// Build the absolute path of current output directory to preselect it in the file browser.
|
||||
wxString path = ExpandEnvVarSubstitutions( m_outputDirectoryName->GetValue(), &Prj() );
|
||||
std::function<bool( wxString* )> textResolver =
|
||||
[&]( wxString* token ) -> bool
|
||||
{
|
||||
return m_parent->Schematic().ResolveTextVar( token, 0 );
|
||||
};
|
||||
|
||||
wxString path = m_outputDirectoryName->GetValue();
|
||||
path = ExpandTextVars( path, &textResolver, nullptr, &Prj() );
|
||||
path = ExpandEnvVarSubstitutions( path, &Prj() );
|
||||
|
||||
fn.SetPath( path );
|
||||
|
||||
|
||||
@@ -208,8 +208,17 @@ public:
|
||||
for( unsigned i = 0; i < m_symbolsList.GetCount(); ++i )
|
||||
{
|
||||
SCH_SYMBOL* symbol = m_symbolsList[ i ].GetSymbol();
|
||||
m_dataStore[ symbol->m_Uuid ][ aFieldName ] = symbol->GetFieldText( aFieldName,
|
||||
m_frame );
|
||||
|
||||
wxCHECK( symbol && ( symbol->GetInstanceReferences().size() != 0 ), /* void */ );
|
||||
|
||||
wxString val = symbol->GetFieldText( aFieldName, m_frame );
|
||||
|
||||
if( aFieldName == wxT( "Value" ) )
|
||||
val = symbol->GetInstanceReferences()[0].m_Value;
|
||||
else if( aFieldName == wxT( "Footprint" ) )
|
||||
val = symbol->GetInstanceReferences()[0].m_Footprint;
|
||||
|
||||
m_dataStore[ symbol->m_Uuid ][ aFieldName ] = val;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -700,8 +700,19 @@ bool DIALOG_SYMBOL_PROPERTIES::TransferDataFromWindow()
|
||||
m_symbol->SetIncludeInBom( !m_cbExcludeFromBom->IsChecked() );
|
||||
m_symbol->SetIncludeOnBoard( !m_cbExcludeFromBoard->IsChecked() );
|
||||
|
||||
// The value, footprint and datasheet fields and exclude from bill of materials setting
|
||||
// should be kept in sync in multi-unit parts.
|
||||
// Update any assignments
|
||||
if( m_dataModel )
|
||||
{
|
||||
for( const SCH_PIN& model_pin : *m_dataModel )
|
||||
{
|
||||
// map from the edited copy back to the "real" pin in the symbol.
|
||||
SCH_PIN* src_pin = m_symbol->GetPin( model_pin.GetLibPin() );
|
||||
src_pin->SetAlt( model_pin.GetAlt() );
|
||||
}
|
||||
}
|
||||
|
||||
// Keep fields other than the reference, include/exclude flags, and alternate pin assignements
|
||||
// in sync in multi-unit parts.
|
||||
if( m_symbol->GetUnitCount() > 1 && m_symbol->IsAnnotated( &GetParent()->GetCurrentSheet() ) )
|
||||
{
|
||||
wxString ref = m_symbol->GetRef( &GetParent()->GetCurrentSheet() );
|
||||
@@ -722,25 +733,49 @@ bool DIALOG_SYMBOL_PROPERTIES::TransferDataFromWindow()
|
||||
appendUndo );
|
||||
otherUnit->SetValue( m_fields->at( VALUE_FIELD ).GetText() );
|
||||
otherUnit->SetFootprint( m_fields->at( FOOTPRINT_FIELD ).GetText() );
|
||||
otherUnit->GetField( DATASHEET_FIELD )->SetText( m_fields->at( DATASHEET_FIELD ).GetText() );
|
||||
|
||||
for( size_t ii = DATASHEET_FIELD; ii < m_fields->size(); ++ii )
|
||||
{
|
||||
SCH_FIELD* otherField = otherUnit->FindField( m_fields->at( ii ).GetName() );
|
||||
|
||||
if( otherField )
|
||||
{
|
||||
otherField->SetText( m_fields->at( ii ).GetText() );
|
||||
}
|
||||
else
|
||||
{
|
||||
SCH_FIELD* newField = otherUnit->AddField( m_fields->at( ii ) );
|
||||
const_cast<KIID&>( newField->m_Uuid ) = KIID();
|
||||
}
|
||||
}
|
||||
|
||||
for( size_t ii = otherUnit->GetFields().size() - 1; ii > DATASHEET_FIELD; ii-- )
|
||||
{
|
||||
SCH_FIELD& otherField = otherUnit->GetFields().at( ii );
|
||||
|
||||
if( !m_symbol->FindField( otherField.GetName() ) )
|
||||
otherUnit->GetFields().erase( otherUnit->GetFields().begin() + ii );
|
||||
}
|
||||
|
||||
otherUnit->SetIncludeInBom( !m_cbExcludeFromBom->IsChecked() );
|
||||
otherUnit->SetIncludeOnBoard( !m_cbExcludeFromBoard->IsChecked() );
|
||||
|
||||
if( m_dataModel )
|
||||
{
|
||||
for( const SCH_PIN& model_pin : *m_dataModel )
|
||||
{
|
||||
SCH_PIN* src_pin = otherUnit->GetPin( model_pin.GetNumber() );
|
||||
|
||||
if( src_pin )
|
||||
src_pin->SetAlt( model_pin.GetAlt() );
|
||||
}
|
||||
}
|
||||
|
||||
GetParent()->UpdateItem( otherUnit, false, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update any assignments
|
||||
if( m_dataModel )
|
||||
{
|
||||
for( const SCH_PIN& model_pin : *m_dataModel )
|
||||
{
|
||||
// map from the edited copy back to the "real" pin in the symbol.
|
||||
SCH_PIN* src_pin = m_symbol->GetPin( model_pin.GetLibPin() );
|
||||
src_pin->SetAlt( model_pin.GetAlt() );
|
||||
}
|
||||
}
|
||||
|
||||
currentScreen->Append( m_symbol );
|
||||
GetParent()->TestDanglingEnds();
|
||||
GetParent()->UpdateItem( m_symbol, false, true );
|
||||
|
||||
@@ -146,48 +146,8 @@ void EE_COLLECTOR::Collect( SCH_SCREEN* aScreen, const KICAD_T aFilterList[], co
|
||||
|
||||
if( aScreen )
|
||||
{
|
||||
// Symbols and sheets own their own children so have to be visited even if
|
||||
// they're not in the filter list
|
||||
bool symbolsVisited = false;
|
||||
bool sheetsVisited = false;
|
||||
bool globalLabelsVisited = false;
|
||||
|
||||
EE_RTREE& items = aScreen->Items();
|
||||
|
||||
for( const KICAD_T *filter = aFilterList; *filter != EOT; ++filter )
|
||||
{
|
||||
for( SCH_ITEM *item : items.Overlapping( *filter, aPos, m_Threshold ) )
|
||||
{
|
||||
if( *filter == SCH_SYMBOL_T || *filter == SCH_LOCATE_ANY_T )
|
||||
symbolsVisited = true;
|
||||
|
||||
if( *filter == SCH_SHEET_T || *filter == SCH_LOCATE_ANY_T )
|
||||
sheetsVisited = true;
|
||||
|
||||
if( *filter == SCH_GLOBAL_LABEL_T || *filter == SCH_LOCATE_ANY_T )
|
||||
globalLabelsVisited = true;
|
||||
|
||||
item->Visit( m_inspector, nullptr, m_scanTypes );
|
||||
}
|
||||
}
|
||||
|
||||
if( !symbolsVisited )
|
||||
{
|
||||
for( SCH_ITEM *item : items.Overlapping( SCH_SYMBOL_T, aPos, m_Threshold ) )
|
||||
item->Visit( m_inspector, nullptr, m_scanTypes );
|
||||
}
|
||||
|
||||
if( !sheetsVisited )
|
||||
{
|
||||
for( SCH_ITEM *item : items.Overlapping( SCH_SHEET_T, aPos, m_Threshold ) )
|
||||
item->Visit( m_inspector, nullptr, m_scanTypes );
|
||||
}
|
||||
|
||||
if( !globalLabelsVisited )
|
||||
{
|
||||
for( SCH_ITEM *item : items.Overlapping( SCH_GLOBAL_LABEL_T, aPos, m_Threshold ) )
|
||||
item->Visit( m_inspector, nullptr, m_scanTypes );
|
||||
}
|
||||
for( SCH_ITEM *item : aScreen->Items().Overlapping( SCH_LOCATE_ANY_T, aPos, m_Threshold ) )
|
||||
item->Visit( m_inspector, nullptr, m_scanTypes );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -192,7 +192,7 @@ void SCH_EDIT_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
|
||||
|
||||
void SCH_BASE_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
|
||||
{
|
||||
wxCHECK_RET( aCfg, wxT( "Call to SCH_BASE_FRAME::SaveSettings with null settings" ) );
|
||||
wxCHECK_RET( aCfg, wxT( "Call to SCH_BASE_FRAME::LoadSettings with null settings" ) );
|
||||
|
||||
EDA_DRAW_FRAME::LoadSettings( aCfg );
|
||||
|
||||
|
||||
+7
-6
@@ -439,9 +439,13 @@ int ERC_TESTER::TestPinToPin()
|
||||
{
|
||||
std::vector<SCH_PIN*> pins;
|
||||
std::unordered_map<EDA_ITEM*, SCH_SCREEN*> pinToScreenMap;
|
||||
bool has_noconnect = false;
|
||||
|
||||
for( CONNECTION_SUBGRAPH* subgraph: net.second )
|
||||
{
|
||||
if( subgraph->m_no_connect )
|
||||
has_noconnect = true;
|
||||
|
||||
for( EDA_ITEM* item : subgraph->m_items )
|
||||
{
|
||||
if( item->Type() == SCH_PIN_T )
|
||||
@@ -452,10 +456,6 @@ int ERC_TESTER::TestPinToPin()
|
||||
}
|
||||
}
|
||||
|
||||
// Single-pin nets are handled elsewhere
|
||||
if( pins.size() < 2 )
|
||||
continue;
|
||||
|
||||
std::set<std::pair<SCH_PIN*, SCH_PIN*>> tested;
|
||||
|
||||
SCH_PIN* needsDriver = nullptr;
|
||||
@@ -542,7 +542,7 @@ int ERC_TESTER::TestPinToPin()
|
||||
}
|
||||
}
|
||||
|
||||
if( needsDriver && !hasDriver )
|
||||
if( needsDriver && !hasDriver && !has_noconnect )
|
||||
{
|
||||
int err_code = ispowerNet ? ERCE_POWERPIN_NOT_DRIVEN : ERCE_PIN_NOT_DRIVEN;
|
||||
|
||||
@@ -744,8 +744,9 @@ int ERC_TESTER::TestLibSymbolIssues()
|
||||
}
|
||||
|
||||
std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
|
||||
constexpr int flags = LIB_ITEM::COMPARE_FLAGS::EQUALITY | LIB_ITEM::COMPARE_FLAGS::ERC;
|
||||
|
||||
if( *flattenedSymbol != *libSymbolInSchematic )
|
||||
if( flattenedSymbol->Compare( *libSymbolInSchematic, flags ) != 0 )
|
||||
{
|
||||
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_LIB_SYMBOL_ISSUES );
|
||||
ercItem->SetItems( symbol );
|
||||
|
||||
@@ -502,7 +502,7 @@ void FIELDS_GRID_TABLE<T>::SetValue( int aRow, int aCol, const wxString &aValue
|
||||
value = fn.GetFullPath();
|
||||
}
|
||||
}
|
||||
else if( m_frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) && aRow == VALUE_FIELD )
|
||||
else if( m_parentType == SCH_SYMBOL_T && aRow == VALUE_FIELD )
|
||||
{
|
||||
value = EscapeString( value, CTX_LIBID );
|
||||
}
|
||||
|
||||
+15
-11
@@ -62,6 +62,7 @@
|
||||
#include <wx/ffile.h>
|
||||
#include <wx/filedlg.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/stdpaths.h>
|
||||
#include <tools/ee_inspection_tool.h>
|
||||
#include <paths.h>
|
||||
#include <wx_filename.h> // For ::ResolvePossibleSymlinks
|
||||
@@ -631,6 +632,10 @@ void SCH_EDIT_FRAME::OnImportProject( wxCommandEvent& aEvent )
|
||||
if( dlg.ShowModal() == wxID_CANCEL )
|
||||
return;
|
||||
|
||||
// Don't leave dangling pointers to previously-opened document.
|
||||
m_toolManager->GetTool<EE_SELECTION_TOOL>()->ClearSelection();
|
||||
ClearUndoRedoList();
|
||||
|
||||
if( setProject )
|
||||
{
|
||||
Schematic().SetProject( nullptr );
|
||||
@@ -664,8 +669,6 @@ void SCH_EDIT_FRAME::OnImportProject( wxCommandEvent& aEvent )
|
||||
return;
|
||||
}
|
||||
|
||||
m_toolManager->GetTool<EE_SELECTION_TOOL>()->ClearSelection();
|
||||
|
||||
importFile( dlg.GetPath(), pluginType );
|
||||
|
||||
RefreshCanvas();
|
||||
@@ -693,9 +696,9 @@ bool SCH_EDIT_FRAME::saveSchematicFile( SCH_SHEET* aSheet, const wxString& aSave
|
||||
if( !IsWritable( schematicFileName ) )
|
||||
return false;
|
||||
|
||||
wxFileName tempFile( schematicFileName );
|
||||
tempFile.SetName( wxT( "." ) + tempFile.GetName() );
|
||||
tempFile.SetExt( tempFile.GetExt() + wxT( "$" ) );
|
||||
wxStandardPaths& paths = wxStandardPaths::Get();
|
||||
wxString tempFile = wxFileName::CreateTempFileName(
|
||||
paths.GetTempDir() + wxFileName::GetPathSeparator() + wxT( "eeschema" ) );
|
||||
|
||||
// Save
|
||||
wxLogTrace( traceAutoSave, "Saving file " + schematicFileName.GetFullPath() );
|
||||
@@ -706,7 +709,7 @@ bool SCH_EDIT_FRAME::saveSchematicFile( SCH_SHEET* aSheet, const wxString& aSave
|
||||
|
||||
try
|
||||
{
|
||||
pi->Save( tempFile.GetFullPath(), aSheet, &Schematic() );
|
||||
pi->Save( tempFile, aSheet, &Schematic() );
|
||||
success = true;
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
@@ -717,11 +720,11 @@ bool SCH_EDIT_FRAME::saveSchematicFile( SCH_SHEET* aSheet, const wxString& aSave
|
||||
DisplayError( this, msg );
|
||||
|
||||
msg.Printf( _( "Failed to create temporary file '%s'." ),
|
||||
tempFile.GetFullPath() );
|
||||
tempFile );
|
||||
SetMsgPanel( wxEmptyString, msg );
|
||||
|
||||
// In case we started a file but didn't fully write it, clean up
|
||||
wxRemoveFile( tempFile.GetFullPath() );
|
||||
wxRemoveFile( tempFile );
|
||||
|
||||
success = false;
|
||||
}
|
||||
@@ -729,18 +732,18 @@ bool SCH_EDIT_FRAME::saveSchematicFile( SCH_SHEET* aSheet, const wxString& aSave
|
||||
if( success )
|
||||
{
|
||||
// Replace the original with the temporary file we just wrote
|
||||
success = wxRenameFile( tempFile.GetFullPath(), schematicFileName.GetFullPath() );
|
||||
success = wxRenameFile( tempFile, schematicFileName.GetFullPath() );
|
||||
|
||||
if( !success )
|
||||
{
|
||||
msg.Printf( _( "Error saving schematic file '%s'.\n"
|
||||
"Failed to rename temporary file '%s'." ),
|
||||
schematicFileName.GetFullPath(),
|
||||
tempFile.GetFullPath() );
|
||||
tempFile );
|
||||
DisplayError( this, msg );
|
||||
|
||||
msg.Printf( _( "Failed to rename temporary file '%s'." ),
|
||||
tempFile.GetFullPath() );
|
||||
tempFile );
|
||||
SetMsgPanel( wxEmptyString, msg );
|
||||
}
|
||||
}
|
||||
@@ -1080,6 +1083,7 @@ bool SCH_EDIT_FRAME::SaveProject( bool aSaveAs )
|
||||
}
|
||||
else
|
||||
{
|
||||
RecordERCExclusions(); // ensure ERC Exclusions list is up to date
|
||||
GetSettingsManager()->SaveProject();
|
||||
}
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ void LIB_FIELD::Copy( LIB_FIELD* aTarget ) const
|
||||
}
|
||||
|
||||
|
||||
int LIB_FIELD::compare( const LIB_ITEM& aOther, LIB_ITEM::COMPARE_FLAGS aCompareFlags ) const
|
||||
int LIB_FIELD::compare( const LIB_ITEM& aOther, int aCompareFlags ) const
|
||||
{
|
||||
wxASSERT( aOther.Type() == LIB_FIELD_T );
|
||||
|
||||
|
||||
@@ -185,8 +185,7 @@ private:
|
||||
* - Field width.
|
||||
* - Field height.
|
||||
*/
|
||||
int compare( const LIB_ITEM& aOther,
|
||||
LIB_ITEM::COMPARE_FLAGS aCompareFlags = LIB_ITEM::COMPARE_FLAGS::NORMAL ) const override;
|
||||
int compare( const LIB_ITEM& aOther, int aCompareFlags = 0 ) const override;
|
||||
|
||||
/**
|
||||
* Print the field.
|
||||
|
||||
@@ -64,7 +64,7 @@ void LIB_ITEM::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_IT
|
||||
}
|
||||
|
||||
|
||||
int LIB_ITEM::compare( const LIB_ITEM& aOther, LIB_ITEM::COMPARE_FLAGS aCompareFlags ) const
|
||||
int LIB_ITEM::compare( const LIB_ITEM& aOther, int aCompareFlags ) const
|
||||
{
|
||||
if( Type() != aOther.Type() )
|
||||
return Type() - aOther.Type();
|
||||
|
||||
+13
-6
@@ -73,11 +73,19 @@ public:
|
||||
/**
|
||||
* The list of flags used by the #compare function.
|
||||
*
|
||||
* - NORMAL This compares everything between two #LIB_ITEM objects.
|
||||
* - UNIT This compare flag ignores unit and convert and pin number information when
|
||||
* comparing #LIB_ITEM objects for unit comparison.
|
||||
* - UNIT This flag relaxes unit, conversion and pin number constraints. It is used for
|
||||
* #LIB_ITEM object unit comparisons.
|
||||
* - EQUALITY This flag relaxes ordering contstraints so that fields, etc. don't have to
|
||||
* appear in the same order to be considered equal.
|
||||
* - ERC This flag relaxes constraints on data that is settable in the schematic editor. It
|
||||
* compares only symbol-editor-only data.
|
||||
*/
|
||||
enum COMPARE_FLAGS : int { NORMAL = 0x00, UNIT = 0x01, EQUALITY = 0x02 };
|
||||
enum COMPARE_FLAGS : int
|
||||
{
|
||||
UNIT = 0x01,
|
||||
EQUALITY = 0x02,
|
||||
ERC = 0x04
|
||||
};
|
||||
|
||||
/**
|
||||
* Provide a user-consumable name of the object type. Perform localization when
|
||||
@@ -285,8 +293,7 @@ protected:
|
||||
* zero if the object is equal to \a aOther object, or greater than 0 if the
|
||||
* object is greater than \a aOther object.
|
||||
*/
|
||||
virtual int compare( const LIB_ITEM& aOther,
|
||||
LIB_ITEM::COMPARE_FLAGS aCompareFlags = LIB_ITEM::COMPARE_FLAGS::NORMAL ) const;
|
||||
virtual int compare( const LIB_ITEM& aOther, int aCompareFlags = 0 ) const;
|
||||
|
||||
/**
|
||||
* Print the item to \a aDC.
|
||||
|
||||
+12
-1
@@ -870,7 +870,7 @@ EDA_ITEM* LIB_PIN::Clone() const
|
||||
}
|
||||
|
||||
|
||||
int LIB_PIN::compare( const LIB_ITEM& aOther, LIB_ITEM::COMPARE_FLAGS aCompareFlags ) const
|
||||
int LIB_PIN::compare( const LIB_ITEM& aOther, int aCompareFlags ) const
|
||||
{
|
||||
wxASSERT( aOther.Type() == LIB_PIN_T );
|
||||
|
||||
@@ -1061,6 +1061,17 @@ void LIB_PIN::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITE
|
||||
}
|
||||
|
||||
|
||||
void LIB_PIN::ViewGetLayers( int aLayers[], int& aCount ) const
|
||||
{
|
||||
aCount = 3;
|
||||
aLayers[0] = LAYER_DANGLING; // We don't really show dangling vs non-dangling (since there
|
||||
// are no connections in the symbol editor), but it's still
|
||||
// a good visual indication of which end of the pin is which.
|
||||
aLayers[1] = LAYER_DEVICE;
|
||||
aLayers[2] = LAYER_SELECTION_SHADOWS;
|
||||
}
|
||||
|
||||
|
||||
const EDA_RECT LIB_PIN::GetBoundingBox( bool aIncludeInvisibles, bool aPinOnly ) const
|
||||
{
|
||||
EDA_RECT bbox;
|
||||
|
||||
+3
-2
@@ -170,6 +170,8 @@ public:
|
||||
|
||||
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
|
||||
|
||||
void ViewGetLayers( int aLayers[], int& aCount ) const override;
|
||||
|
||||
/* Cannot use a default parameter here as it will not be compatible with the virtual. */
|
||||
const EDA_RECT GetBoundingBox() const override { return GetBoundingBox( false ); }
|
||||
|
||||
@@ -271,8 +273,7 @@ private:
|
||||
* - Pin horizontal (X) position.
|
||||
* - Pin vertical (Y) position.
|
||||
*/
|
||||
int compare( const LIB_ITEM& aOther,
|
||||
LIB_ITEM::COMPARE_FLAGS aCompareFlags = LIB_ITEM::COMPARE_FLAGS::NORMAL ) const override;
|
||||
int compare( const LIB_ITEM& aOther, int aCompareFlags = 0 ) const override;
|
||||
|
||||
protected:
|
||||
wxPoint m_position; // Position of the pin.
|
||||
|
||||
@@ -66,7 +66,7 @@ EDA_ITEM* LIB_SHAPE::Clone() const
|
||||
}
|
||||
|
||||
|
||||
int LIB_SHAPE::compare( const LIB_ITEM& aOther, LIB_ITEM::COMPARE_FLAGS aCompareFlags ) const
|
||||
int LIB_SHAPE::compare( const LIB_ITEM& aOther, int aCompareFlags ) const
|
||||
{
|
||||
int retv = LIB_ITEM::compare( aOther, aCompareFlags );
|
||||
|
||||
@@ -256,7 +256,12 @@ void LIB_SHAPE::print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset,
|
||||
|
||||
CalcArcAngles( t1, t2 );
|
||||
|
||||
if( aTransform.MapAngles( &t1, &t2 ) == ( NormalizeAngle180( t1 - t2 ) > 0 ) )
|
||||
// N.B. The order of evaluation is critical here as MapAngles will modify t1, t2
|
||||
// and the Normalize routine depends on these modifications for the correct output
|
||||
bool transformed = aTransform.MapAngles( &t1, &t2 );
|
||||
bool transformed2 = ( NormalizeAngle180( t1 - t2 ) > 0 );
|
||||
|
||||
if( transformed == transformed2 )
|
||||
std::swap( pt1, pt2 );
|
||||
}
|
||||
|
||||
|
||||
@@ -113,8 +113,7 @@ private:
|
||||
* - Circle vertical (Y) position.
|
||||
* - Circle radius.
|
||||
*/
|
||||
int compare( const LIB_ITEM& aOther,
|
||||
LIB_ITEM::COMPARE_FLAGS aCompareFlags = LIB_ITEM::COMPARE_FLAGS::NORMAL ) const override;
|
||||
int compare( const LIB_ITEM& aOther, int aCompareFlags = 0 ) const override;
|
||||
|
||||
void print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset, void* aData,
|
||||
const TRANSFORM& aTransform ) override;
|
||||
|
||||
+33
-18
@@ -209,20 +209,25 @@ const LIB_SYMBOL& LIB_SYMBOL::operator=( const LIB_SYMBOL& aSymbol )
|
||||
}
|
||||
|
||||
|
||||
int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, LIB_ITEM::COMPARE_FLAGS aCompareFlags ) const
|
||||
int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags ) const
|
||||
{
|
||||
if( m_me == aRhs.m_me )
|
||||
return 0;
|
||||
|
||||
int retv = m_name.Cmp( aRhs.m_name );
|
||||
int retv = 0;
|
||||
|
||||
if( retv )
|
||||
return retv;
|
||||
if( ( aCompareFlags & LIB_ITEM::COMPARE_FLAGS::ERC ) == 0 )
|
||||
{
|
||||
retv = m_name.Cmp( aRhs.m_name );
|
||||
|
||||
retv = m_libId.compare( aRhs.m_libId );
|
||||
if( retv )
|
||||
return retv;
|
||||
|
||||
if( retv )
|
||||
return retv;
|
||||
retv = m_libId.compare( aRhs.m_libId );
|
||||
|
||||
if( retv )
|
||||
return retv;
|
||||
}
|
||||
|
||||
if( m_parent.lock() < aRhs.m_parent.lock() )
|
||||
return -1;
|
||||
@@ -258,8 +263,15 @@ int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, LIB_ITEM::COMPARE_FLAGS aCompar
|
||||
{
|
||||
const LIB_FIELD* lhsField = static_cast<const LIB_FIELD*>( lhsItem );
|
||||
|
||||
if( lhsField->IsMandatory() )
|
||||
if( lhsField->GetId() == VALUE_FIELD )
|
||||
{
|
||||
if( ( aCompareFlags & LIB_ITEM::COMPARE_FLAGS::ERC ) == 0 || IsPower() )
|
||||
retv = lhsItem->compare( *rhsItem, aCompareFlags );
|
||||
}
|
||||
else if( lhsField->IsMandatory() )
|
||||
{
|
||||
retv = lhsItem->compare( *rhsItem, aCompareFlags );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -322,17 +334,20 @@ int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, LIB_ITEM::COMPARE_FLAGS aCompar
|
||||
if( m_unitsLocked != aRhs.m_unitsLocked )
|
||||
return ( m_unitsLocked ) ? 1 : -1;
|
||||
|
||||
if( m_showPinNames != aRhs.m_showPinNames )
|
||||
return ( m_showPinNames ) ? 1 : -1;
|
||||
if( ( aCompareFlags & LIB_ITEM::COMPARE_FLAGS::ERC ) == 0 )
|
||||
{
|
||||
if( m_showPinNames != aRhs.m_showPinNames )
|
||||
return ( m_showPinNames ) ? 1 : -1;
|
||||
|
||||
if( m_showPinNumbers != aRhs.m_showPinNumbers )
|
||||
return ( m_showPinNumbers ) ? 1 : -1;
|
||||
if( m_showPinNumbers != aRhs.m_showPinNumbers )
|
||||
return ( m_showPinNumbers ) ? 1 : -1;
|
||||
|
||||
if( m_includeInBom != aRhs.m_includeInBom )
|
||||
return ( m_includeInBom ) ? 1 : -1;
|
||||
if( m_includeInBom != aRhs.m_includeInBom )
|
||||
return ( m_includeInBom ) ? 1 : -1;
|
||||
|
||||
if( m_includeOnBoard != aRhs.m_includeOnBoard )
|
||||
return ( m_includeOnBoard ) ? 1 : -1;
|
||||
if( m_includeOnBoard != aRhs.m_includeOnBoard )
|
||||
return ( m_includeOnBoard ) ? 1 : -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -917,10 +932,10 @@ const EDA_RECT LIB_SYMBOL::GetBodyBoundingBox( int aUnit, int aConvert, bool aIn
|
||||
{
|
||||
const LIB_PIN& pin = static_cast<const LIB_PIN&>( item );
|
||||
|
||||
// Note: the roots of the pins are always inlcuded for symbols that don't have a
|
||||
// Note: the roots of the pins are always included for symbols that don't have a
|
||||
// well-defined body.
|
||||
|
||||
if( aIncludePins )
|
||||
if( aIncludePins && pin.IsVisible() )
|
||||
bbox.Merge( pin.GetBoundingBox( false, true ) );
|
||||
else
|
||||
bbox.Merge( pin.GetPinRoot() );
|
||||
|
||||
@@ -612,8 +612,7 @@ public:
|
||||
* 1 if this symbol is greater than \a aRhs
|
||||
* 0 if this symbol is the same as \a aRhs
|
||||
*/
|
||||
int Compare( const LIB_SYMBOL& aRhs,
|
||||
LIB_ITEM::COMPARE_FLAGS aCompareFlags = LIB_ITEM::COMPARE_FLAGS::NORMAL ) const;
|
||||
int Compare( const LIB_SYMBOL& aRhs, int aCompareFlags = 0 ) const;
|
||||
|
||||
bool operator==( const LIB_SYMBOL* aSymbol ) const { return this == aSymbol; }
|
||||
bool operator==( const LIB_SYMBOL& aSymbol ) const
|
||||
|
||||
@@ -84,7 +84,7 @@ EDA_ITEM* LIB_TEXT::Clone() const
|
||||
}
|
||||
|
||||
|
||||
int LIB_TEXT::compare( const LIB_ITEM& aOther, LIB_ITEM::COMPARE_FLAGS aCompareFlags ) const
|
||||
int LIB_TEXT::compare( const LIB_ITEM& aOther, int aCompareFlags ) const
|
||||
{
|
||||
wxASSERT( aOther.Type() == LIB_TEXT_T );
|
||||
|
||||
|
||||
+1
-2
@@ -117,8 +117,7 @@ private:
|
||||
* - Text width.
|
||||
* - Text height.
|
||||
*/
|
||||
int compare( const LIB_ITEM& aOther,
|
||||
LIB_ITEM::COMPARE_FLAGS aCompareFlags = LIB_ITEM::COMPARE_FLAGS::NORMAL ) const override;
|
||||
int compare( const LIB_ITEM& aOther, int aCompareFlags = 0 ) const override;
|
||||
|
||||
void print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset, void* aData,
|
||||
const TRANSFORM& aTransform ) override;
|
||||
|
||||
@@ -62,17 +62,20 @@ void SCH_EDIT_FRAME::ReCreateMenuBar()
|
||||
if( !openRecentMenu )
|
||||
{
|
||||
openRecentMenu = new ACTION_MENU( false, selTool );
|
||||
openRecentMenu->SetTitle( _( "Open Recent" ) );
|
||||
openRecentMenu->SetIcon( BITMAPS::recent );
|
||||
|
||||
fileHistory.UseMenu( openRecentMenu );
|
||||
fileHistory.AddFilesToMenu( openRecentMenu );
|
||||
}
|
||||
|
||||
// Ensure the title is up to date after changing language
|
||||
openRecentMenu->SetTitle( _( "Open Recent" ) );
|
||||
fileHistory.UpdateClearText( openRecentMenu, _( "Clear Recent Files" ) );
|
||||
|
||||
fileMenu->Add( ACTIONS::doNew );
|
||||
fileMenu->Add( ACTIONS::open );
|
||||
|
||||
wxMenuItem* item = fileMenu->Add( openRecentMenu );
|
||||
wxMenuItem* item = fileMenu->Add( openRecentMenu->Clone() );
|
||||
|
||||
// Add the file menu condition here since it needs the item ID for the submenu
|
||||
ACTION_CONDITIONS cond;
|
||||
|
||||
@@ -209,12 +209,12 @@ wxString NETLIST_EXPORTER_PSPICE::GetSpiceFieldDefVal( SPICE_FIELD aField, SCH_S
|
||||
wxString value = aSymbol->GetField( VALUE_FIELD )->GetShownText();
|
||||
|
||||
// Is it a passive component?
|
||||
if( aCtl & NET_ADJUST_PASSIVE_VALS && ( prim == 'C' || prim == 'L' || prim == 'R' ) )
|
||||
if( ( aCtl & NET_ADJUST_PASSIVE_VALS ) && ( prim == 'C' || prim == 'L' || prim == 'R' ) )
|
||||
{
|
||||
// Regular expression to match common formats used for passive parts description
|
||||
// (e.g. 100k, 2k3, 1 uF)
|
||||
wxRegEx passiveVal(
|
||||
"^([0-9\\. ]+)([fFpPnNuUmMkKgGtT]|M(e|E)(g|G))?([fFhH]|ohm)?([-1-9 ]*)$" );
|
||||
wxT( "^([0-9\\. ]+)([fFpPnNuUmMkKgGtTμµ𝛍𝜇𝝁 ]|M(e|E)(g|G))?([fFhHΩΩ𝛀𝛺𝝮]|ohm)?([-1-9 ]*)$" ) );
|
||||
|
||||
if( passiveVal.Matches( value ) )
|
||||
{
|
||||
|
||||
@@ -105,7 +105,10 @@ PICKED_SYMBOL SCH_BASE_FRAME::PickSymbolFromLibTree( const SCHLIB_FILTER* aFilte
|
||||
Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>();
|
||||
Pgm().GetSettingsManager().GetAppSettings<SYMBOL_EDITOR_SETTINGS>();
|
||||
|
||||
wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER> adapter = SYMBOL_TREE_MODEL_ADAPTER::Create( this, libs );
|
||||
wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER> dataPtr
|
||||
= SYMBOL_TREE_MODEL_ADAPTER::Create( this, libs );
|
||||
SYMBOL_TREE_MODEL_ADAPTER* modelAdapter
|
||||
= static_cast<SYMBOL_TREE_MODEL_ADAPTER*>( dataPtr.get() );
|
||||
bool loaded = false;
|
||||
|
||||
if( aFilter )
|
||||
@@ -117,14 +120,14 @@ PICKED_SYMBOL SCH_BASE_FRAME::PickSymbolFromLibTree( const SCHLIB_FILTER* aFilte
|
||||
if( libs->HasLibrary( liblist[ii], true ) )
|
||||
{
|
||||
loaded = true;
|
||||
static_cast<SYMBOL_TREE_MODEL_ADAPTER*>( adapter.get() )->AddLibrary( liblist[ii] );
|
||||
modelAdapter->AddLibrary( liblist[ii] );
|
||||
}
|
||||
}
|
||||
|
||||
adapter->AssignIntrinsicRanks();
|
||||
modelAdapter->AssignIntrinsicRanks();
|
||||
|
||||
if( aFilter->GetFilterPowerSymbols() )
|
||||
adapter->SetFilter( SYMBOL_TREE_MODEL_ADAPTER::SYM_FILTER_POWER );
|
||||
modelAdapter->SetFilter( SYMBOL_TREE_MODEL_ADAPTER::SYM_FILTER_POWER );
|
||||
}
|
||||
|
||||
std::vector< LIB_TREE_ITEM* > history_list;
|
||||
@@ -138,29 +141,34 @@ PICKED_SYMBOL SCH_BASE_FRAME::PickSymbolFromLibTree( const SCHLIB_FILTER* aFilte
|
||||
history_list.push_back( symbol );
|
||||
}
|
||||
|
||||
adapter->DoAddLibrary( wxT( "-- " ) + _( "Recently Used" ) + " --", wxEmptyString, history_list,
|
||||
true );
|
||||
modelAdapter->DoAddLibrary( wxT( "-- " ) + _( "Recently Used" ) + wxT( " --" ), wxEmptyString,
|
||||
history_list, true );
|
||||
|
||||
if( !aHistoryList.empty() )
|
||||
adapter->SetPreselectNode( aHistoryList[0].LibId, aHistoryList[0].Unit );
|
||||
modelAdapter->SetPreselectNode( aHistoryList[0].LibId, aHistoryList[0].Unit );
|
||||
|
||||
const std::vector< wxString > libNicknames = libs->GetLogicalLibs();
|
||||
|
||||
if( !loaded )
|
||||
static_cast<SYMBOL_TREE_MODEL_ADAPTER*>( adapter.get() )->AddLibraries( libNicknames,
|
||||
this );
|
||||
{
|
||||
if( !modelAdapter->AddLibraries( libNicknames, this ) )
|
||||
{
|
||||
// loading cancelled by user
|
||||
return PICKED_SYMBOL();
|
||||
}
|
||||
}
|
||||
|
||||
if( aHighlight && aHighlight->IsValid() )
|
||||
adapter->SetPreselectNode( *aHighlight, /* aUnit */ 0 );
|
||||
modelAdapter->SetPreselectNode( *aHighlight, /* aUnit */ 0 );
|
||||
|
||||
wxString dialogTitle;
|
||||
|
||||
if( adapter->GetFilter() == SYMBOL_TREE_MODEL_ADAPTER::SYM_FILTER_POWER )
|
||||
dialogTitle.Printf( _( "Choose Power Symbol (%d items loaded)" ), adapter->GetItemCount() );
|
||||
if( modelAdapter->GetFilter() == SYMBOL_TREE_MODEL_ADAPTER::SYM_FILTER_POWER )
|
||||
dialogTitle.Printf( _( "Choose Power Symbol (%d items loaded)" ), dataPtr->GetItemCount() );
|
||||
else
|
||||
dialogTitle.Printf( _( "Choose Symbol (%d items loaded)" ), adapter->GetItemCount() );
|
||||
dialogTitle.Printf( _( "Choose Symbol (%d items loaded)" ), dataPtr->GetItemCount() );
|
||||
|
||||
DIALOG_CHOOSE_SYMBOL dlg( this, dialogTitle, adapter, aConvert, aAllowFields, aShowFootprints,
|
||||
DIALOG_CHOOSE_SYMBOL dlg( this, dialogTitle, dataPtr, aConvert, aAllowFields, aShowFootprints,
|
||||
aUseLibBrowser );
|
||||
|
||||
if( dlg.ShowModal() == wxID_CANCEL )
|
||||
+11
-13
@@ -25,9 +25,8 @@
|
||||
#include "pin_numbers.h"
|
||||
#include <wx/crt.h>
|
||||
|
||||
namespace {
|
||||
|
||||
wxString GetNextSymbol( const wxString& str, wxString::size_type& cursor )
|
||||
wxString PIN_NUMBERS::getNextSymbol( const wxString& str, wxString::size_type& cursor )
|
||||
{
|
||||
if( str.size() <= cursor )
|
||||
return wxEmptyString;
|
||||
@@ -36,14 +35,15 @@ wxString GetNextSymbol( const wxString& str, wxString::size_type& cursor )
|
||||
|
||||
wxChar c = str[cursor];
|
||||
|
||||
if( wxIsdigit( c ) || c == '+' || c == '-' )
|
||||
// Need to check that there is a digit in the string before we parse it as a numeric
|
||||
if( ( wxIsdigit( c ) || ( ( c == '+' || c == '-' ) && ( cursor < str.size() - 1 ) && wxIsdigit( str[cursor + 1] ) ) ) )
|
||||
{
|
||||
// number, possibly with sign
|
||||
while( ++cursor < str.size() )
|
||||
{
|
||||
c = str[cursor];
|
||||
|
||||
if( wxIsdigit( c ) || c == 'v' || c == 'V' )
|
||||
if( wxIsdigit( c ) || c == 'v' || c == 'V' || c == '.' )
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
@@ -65,8 +65,6 @@ wxString GetNextSymbol( const wxString& str, wxString::size_type& cursor )
|
||||
return str.substr( begin, cursor - begin );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
wxString PIN_NUMBERS::GetSummary() const
|
||||
{
|
||||
@@ -117,8 +115,8 @@ int PIN_NUMBERS::Compare( const wxString& lhs, const wxString& rhs )
|
||||
|
||||
for( ; ; )
|
||||
{
|
||||
symbol1 = GetNextSymbol( lhs, cursor1 );
|
||||
symbol2 = GetNextSymbol( rhs, cursor2 );
|
||||
symbol1 = getNextSymbol( lhs, cursor1 );
|
||||
symbol2 = getNextSymbol( rhs, cursor2 );
|
||||
|
||||
if( symbol1.empty() && symbol2.empty() )
|
||||
return 0;
|
||||
@@ -129,12 +127,12 @@ int PIN_NUMBERS::Compare( const wxString& lhs, const wxString& rhs )
|
||||
if( symbol2.empty() )
|
||||
return 2;
|
||||
|
||||
wxChar c1 = symbol1[0];
|
||||
wxChar c2 = symbol2[0];
|
||||
bool sym1_isnumeric = symbol1.find_first_of( "0123456789" ) != wxString::npos;
|
||||
bool sym2_isnumeric = symbol2.find_first_of( "0123456789" ) != wxString::npos;
|
||||
|
||||
if( wxIsdigit( c1 ) || c1 == '-' || c1 == '+' )
|
||||
if( sym1_isnumeric )
|
||||
{
|
||||
if( wxIsdigit( c2 ) || c2 == '-' || c2 == '+' )
|
||||
if( sym2_isnumeric )
|
||||
{
|
||||
// numeric comparison
|
||||
wxString::size_type v1 = symbol1.find_first_of( wxT( "vV" ) );
|
||||
@@ -173,7 +171,7 @@ int PIN_NUMBERS::Compare( const wxString& lhs, const wxString& rhs )
|
||||
}
|
||||
else
|
||||
{
|
||||
if( wxIsdigit( c2 ) || c2 == '-' || c2 == '+' )
|
||||
if( sym2_isnumeric )
|
||||
return 2;
|
||||
|
||||
int res = symbol1.Cmp( symbol2 );
|
||||
|
||||
@@ -47,6 +47,8 @@ private:
|
||||
|
||||
typedef std::set<wxString, less> container_type;
|
||||
|
||||
static wxString getNextSymbol( const wxString& str, wxString::size_type& cursor );
|
||||
|
||||
public:
|
||||
typedef container_type::value_type value_type;
|
||||
typedef container_type::iterator iterator;
|
||||
|
||||
+29
-8
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2004-2021 KiCad Developers, see change_log.txt for contributors.
|
||||
* Copyright (C) 2004-2022 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
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <core/arraydim.h>
|
||||
#include <lib_pin.h>
|
||||
#include <pin_type.h>
|
||||
#include "pgm_base.h"
|
||||
|
||||
|
||||
// These are true singletons so it's OK for them to be globals.
|
||||
@@ -46,8 +47,8 @@ struct pinTypeStruct
|
||||
BITMAPS bitmap;
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
const std::map<ELECTRICAL_PINTYPE, struct pinTypeStruct> pinTypes = {
|
||||
|
||||
std::map<ELECTRICAL_PINTYPE, struct pinTypeStruct> g_pinTypes = {
|
||||
{ ELECTRICAL_PINTYPE::PT_INPUT, { _( "Input" ), BITMAPS::pintype_input } },
|
||||
{ ELECTRICAL_PINTYPE::PT_OUTPUT, { _( "Output" ), BITMAPS::pintype_output } },
|
||||
{ ELECTRICAL_PINTYPE::PT_BIDI, { _( "Bidirectional" ), BITMAPS::pintype_bidi } },
|
||||
@@ -61,7 +62,9 @@ const std::map<ELECTRICAL_PINTYPE, struct pinTypeStruct> pinTypes = {
|
||||
{ ELECTRICAL_PINTYPE::PT_OPENEMITTER, { _( "Open emitter" ), BITMAPS::pintype_openemit } },
|
||||
{ ELECTRICAL_PINTYPE::PT_NC, { _( "Unconnected" ), BITMAPS::pintype_noconnect } },
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
int g_pinTypesLanguage = wxLANGUAGE_UNKNOWN;
|
||||
|
||||
|
||||
struct pinShapeStruct
|
||||
@@ -236,9 +239,27 @@ const std::vector<BITMAPS>& PinOrientationIcons()
|
||||
|
||||
wxString ElectricalPinTypeGetText( ELECTRICAL_PINTYPE aType )
|
||||
{
|
||||
auto findIt = pinTypes.find( aType );
|
||||
if( g_pinTypesLanguage != Pgm().GetSelectedLanguageIdentifier() )
|
||||
{
|
||||
g_pinTypes[ELECTRICAL_PINTYPE::PT_INPUT].name = _( "Input" );
|
||||
g_pinTypes[ELECTRICAL_PINTYPE::PT_OUTPUT].name = _( "Output" );
|
||||
g_pinTypes[ELECTRICAL_PINTYPE::PT_BIDI].name = _( "Bidirectional" );
|
||||
g_pinTypes[ELECTRICAL_PINTYPE::PT_TRISTATE].name = _( "Tri-state" );
|
||||
g_pinTypes[ELECTRICAL_PINTYPE::PT_PASSIVE].name = _( "Passive" );
|
||||
g_pinTypes[ELECTRICAL_PINTYPE::PT_NIC].name = _( "Free" );
|
||||
g_pinTypes[ELECTRICAL_PINTYPE::PT_UNSPECIFIED].name = _( "Unspecified" );
|
||||
g_pinTypes[ELECTRICAL_PINTYPE::PT_POWER_IN].name = _( "Power input" );
|
||||
g_pinTypes[ELECTRICAL_PINTYPE::PT_POWER_OUT].name = _( "Power output" );
|
||||
g_pinTypes[ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR].name = _( "Open collector" );
|
||||
g_pinTypes[ELECTRICAL_PINTYPE::PT_OPENEMITTER].name = _( "Open emitter" );
|
||||
g_pinTypes[ELECTRICAL_PINTYPE::PT_NC].name = _( "Unconnected" );
|
||||
|
||||
wxCHECK_MSG( findIt != pinTypes.end(), wxT( "???" ), "Could not find pin type in lookup map" );
|
||||
g_pinTypesLanguage = Pgm().GetSelectedLanguageIdentifier();
|
||||
}
|
||||
|
||||
auto findIt = g_pinTypes.find( aType );
|
||||
|
||||
wxCHECK_MSG( findIt != g_pinTypes.end(), wxT( "???" ), wxT( "Pin type not found!" ) );
|
||||
|
||||
return findIt->second.name;
|
||||
}
|
||||
@@ -246,9 +267,9 @@ wxString ElectricalPinTypeGetText( ELECTRICAL_PINTYPE aType )
|
||||
|
||||
BITMAPS ElectricalPinTypeGetBitmap( ELECTRICAL_PINTYPE aType )
|
||||
{
|
||||
auto findIt = pinTypes.find( aType );
|
||||
auto findIt = g_pinTypes.find( aType );
|
||||
|
||||
wxCHECK_MSG( findIt != pinTypes.end(), BITMAPS::INVALID_BITMAP,
|
||||
wxCHECK_MSG( findIt != g_pinTypes.end(), BITMAPS::INVALID_BITMAP,
|
||||
wxT( "Could not find pin type in lookup map" ) );
|
||||
|
||||
return findIt->second.bitmap;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Chris Pavlina <pavlina.chris@gmail.com>
|
||||
* Copyright (C) 2015-2021 KiCad Developers, see change_log.txt for contributors.
|
||||
* Copyright (C) 2015-2022 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
|
||||
@@ -89,7 +89,6 @@ static void getSymbols( SCHEMATIC* aSchematic, std::vector<SCH_SYMBOL*>& aSymbol
|
||||
static LIB_SYMBOL* findSymbol( const wxString& aName, SYMBOL_LIBS* aLibs, bool aCached )
|
||||
{
|
||||
LIB_SYMBOL *symbol = nullptr;
|
||||
// wxString new_name = LIB_ID::FixIllegalChars( aName, false );
|
||||
|
||||
for( SYMBOL_LIB& each_lib : *aLibs )
|
||||
{
|
||||
@@ -101,6 +100,17 @@ static LIB_SYMBOL* findSymbol( const wxString& aName, SYMBOL_LIBS* aLibs, bool a
|
||||
|
||||
symbol = each_lib.FindSymbol( aName );
|
||||
|
||||
// At some point during V5 development, the LIB_ID delimiter character ':' was
|
||||
// replaced by '_' when writing the symbol cache library so we have to test for
|
||||
// the LIB_NICKNAME_LIB_SYMBOL_NAME case.
|
||||
if( symbol == nullptr && each_lib.IsCache() )
|
||||
{
|
||||
wxString name = aName;
|
||||
|
||||
if( name.Replace( wxT( ":" ), wxT( "_" ) ) )
|
||||
symbol = each_lib.FindSymbol( name );
|
||||
}
|
||||
|
||||
if( symbol )
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -412,7 +412,7 @@ void SCH_CONNECTION::AppendInfoToMsgPanel( std::vector<MSG_PANEL_ITEM>& aList )
|
||||
// CONNECTION_GRAPH entirely in the future, as they are mostly only useful for netlist exports.
|
||||
#if 0
|
||||
if( !IsBus() )
|
||||
aList.emplace_back( _( "Net CodewxT( " ), wxString::Format( " )%d", m_net_code ) );
|
||||
aList.emplace_back( _( "Net Code" ), wxString::Format( "%d", m_net_code ) );
|
||||
#endif
|
||||
|
||||
if( auto alias = m_graph->GetBusAlias( m_name ) )
|
||||
@@ -474,7 +474,7 @@ bool SCH_CONNECTION::MightBeBusLabel( const wxString& aLabel )
|
||||
// Weak heuristic for performance reasons. Stronger test will be used for connectivity
|
||||
wxString label = UnescapeString( aLabel );
|
||||
|
||||
return label.Contains( wxT( "[wxT( " ) ) || label.Contains( wxT( " ){" ) );
|
||||
return label.Contains( wxT( "[" ) ) || label.Contains( wxT( "{" ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1502,6 +1502,8 @@ void SCH_EDIT_FRAME::ShowChangedLanguage()
|
||||
// status bar
|
||||
UpdateMsgPanel();
|
||||
|
||||
UpdateTitle();
|
||||
|
||||
// This ugly hack is to fix an option(left) toolbar update bug that seems to only affect
|
||||
// windows. See https://bugs.launchpad.net/kicad/+bug/1816492. For some reason, calling
|
||||
// wxWindow::Refresh() does not resolve the issue. Only a resize event seems to force the
|
||||
|
||||
+11
-2
@@ -140,7 +140,7 @@ SCH_CONNECTION* SCH_ITEM::Connection( const SCH_SHEET_PATH* aSheet ) const
|
||||
if( !IsConnectable() )
|
||||
return nullptr;
|
||||
|
||||
wxASSERT_MSG( !IsConnectivityDirty(),
|
||||
wxCHECK_MSG( !IsConnectivityDirty(), nullptr,
|
||||
wxT( "Shouldn't be asking for connection if connectivity is dirty!" ) );
|
||||
|
||||
if( !aSheet )
|
||||
@@ -182,7 +182,13 @@ SCH_ITEM_SET& SCH_ITEM::ConnectedItems( const SCH_SHEET_PATH& aSheet )
|
||||
|
||||
void SCH_ITEM::AddConnectionTo( const SCH_SHEET_PATH& aSheet, SCH_ITEM* aItem )
|
||||
{
|
||||
m_connected_items[ aSheet ].insert( aItem );
|
||||
SCH_ITEM_SET& set = m_connected_items[ aSheet ];
|
||||
|
||||
// The vector elements are small, so reserve 1k at a time to prevent re-allocations
|
||||
if( set.size() == set.capacity() )
|
||||
set.reserve( set.size() + 4096 );
|
||||
|
||||
set.emplace_back( aItem );
|
||||
}
|
||||
|
||||
|
||||
@@ -212,6 +218,9 @@ SCH_CONNECTION* SCH_ITEM::InitializeConnection( const SCH_SHEET_PATH& aSheet,
|
||||
SCH_CONNECTION* SCH_ITEM::GetOrInitConnection( const SCH_SHEET_PATH& aSheet,
|
||||
CONNECTION_GRAPH* aGraph )
|
||||
{
|
||||
if( !IsConnectable() )
|
||||
return nullptr;
|
||||
|
||||
SetConnectivityDirty( false );
|
||||
|
||||
SCH_CONNECTION* connection = Connection( &aSheet );
|
||||
|
||||
+2
-2
@@ -26,7 +26,7 @@
|
||||
#define SCH_ITEM_H
|
||||
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <set>
|
||||
|
||||
#include <eda_item.h>
|
||||
#include <plotters/plotter.h> // for PLOT_DASH_TYPE definition
|
||||
@@ -131,7 +131,7 @@ private:
|
||||
};
|
||||
|
||||
|
||||
typedef std::unordered_set<SCH_ITEM*> SCH_ITEM_SET;
|
||||
typedef std::vector<SCH_ITEM*> SCH_ITEM_SET;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -447,10 +447,12 @@ void SCH_LINE::MirrorHorizontally( int aCenter )
|
||||
|
||||
void SCH_LINE::Rotate( const wxPoint& aCenter )
|
||||
{
|
||||
// When we allow off grid items, the
|
||||
// else if should become a plain if to allow
|
||||
// rotation around the center of the line
|
||||
if( m_flags & STARTPOINT )
|
||||
RotatePoint( &m_start, aCenter, 900 );
|
||||
|
||||
if( m_flags & ENDPOINT )
|
||||
else if( m_flags & ENDPOINT )
|
||||
RotatePoint( &m_end, aCenter, 900 );
|
||||
}
|
||||
|
||||
|
||||
@@ -1013,10 +1013,10 @@ void SCH_PAINTER::draw( LIB_PIN *aPin, int aLayer )
|
||||
c = getRenderColor( aPin, LAYER_HIDDEN, drawingShadows );
|
||||
}
|
||||
|
||||
float insideOffset = textOffset - thickness[INSIDE] / 2.0;
|
||||
float outsideOffset = 2 * Mils2iu( PIN_TEXT_MARGIN ) - thickness[OUTSIDE] / 2.0;
|
||||
float aboveOffset = Mils2iu( PIN_TEXT_MARGIN ) + ( thickness[ABOVE] + penWidth ) / 2.0;
|
||||
float belowOffset = Mils2iu( PIN_TEXT_MARGIN ) + ( thickness[BELOW] + penWidth ) / 2.0;
|
||||
float insideOffset = textOffset - thickness[INSIDE] / 2.0;
|
||||
float outsideOffset = Mils2iu( PIN_TEXT_MARGIN ) + TARGET_PIN_RADIUS - thickness[OUTSIDE] / 2.0;
|
||||
float aboveOffset = Mils2iu( PIN_TEXT_MARGIN ) + penWidth / 2.0 + thickness[ABOVE] / 2.0;
|
||||
float belowOffset = Mils2iu( PIN_TEXT_MARGIN ) + penWidth / 2.0 + thickness[BELOW] / 2.0;
|
||||
|
||||
if( isDangling )
|
||||
outsideOffset += TARGET_PIN_RADIUS / 2.0;
|
||||
|
||||
@@ -1308,6 +1308,13 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadSymDefIntoLibrary( const SYMDEF_ID& aSymdef
|
||||
SYMDEF_SCM symbol = Library.SymbolDefinitions.at( aSymdefID );
|
||||
int gateNumber = getKiCadUnitNumberFromGate( aGateID );
|
||||
|
||||
// Ensure there are no items on this unit (e.g. if we already previously loaded the symbol from
|
||||
// the part definition)
|
||||
std::vector<LIB_ITEM*> drawItems = aSymbol->GetUnitDrawItems( gateNumber, 0 );
|
||||
|
||||
for( LIB_ITEM* item : drawItems )
|
||||
aSymbol->RemoveDrawItem( item );
|
||||
|
||||
for( std::pair<FIGURE_ID, FIGURE> figPair : symbol.Figures )
|
||||
{
|
||||
FIGURE fig = figPair.second;
|
||||
|
||||
@@ -1352,11 +1352,20 @@ void SCH_EAGLE_PLUGIN::loadInstance( wxXmlNode* aInstanceNode )
|
||||
// with a hash character to mute netlist updater complaints
|
||||
wxString reference = package.IsEmpty() ? '#' + einstance.part : einstance.part;
|
||||
|
||||
// reference must end with a number but EAGLE does not enforce this
|
||||
if( reference.find_last_not_of( "0123456789" ) == (reference.Length()-1) )
|
||||
reference.Append( "0" );
|
||||
|
||||
// EAGLE allows references to be single digits. This breaks KiCad netlisting, which requires
|
||||
// parts to have non-digit + digit annotation. If the reference begins with a number,
|
||||
// we prepend 'UNK' (unknown) for the symbol designator
|
||||
if( reference.find_first_not_of( wxT( "0123456789" ) ) == wxString::npos )
|
||||
reference.Prepend( wxT( "UNK" ) );
|
||||
if( reference.find_first_not_of( "0123456789" ) != 0 )
|
||||
reference.Prepend( "UNK" );
|
||||
|
||||
// EAGLE allows designator to start with # but that is used in KiCad
|
||||
// for symbols which do not have a footprint
|
||||
if( einstance.part.find_first_not_of( "#" ) != 0 )
|
||||
reference.Prepend( "UNK" );
|
||||
|
||||
SCH_SHEET_PATH sheetpath;
|
||||
m_rootSheet->LocatePathOfScreen( screen, &sheetpath );
|
||||
|
||||
@@ -1013,15 +1013,15 @@ LIB_SHAPE* SCH_SEXPR_PARSER::parseArc()
|
||||
}
|
||||
}
|
||||
|
||||
arc->SetStart( startPoint );
|
||||
arc->SetEnd( endPoint );
|
||||
|
||||
if( hasMidPoint )
|
||||
{
|
||||
arc->SetCenter( (wxPoint) CalcArcCenter( arc->GetStart(), midPoint, arc->GetEnd() ) );
|
||||
arc->SetArcGeometry( startPoint, midPoint, endPoint);
|
||||
}
|
||||
else if( hasAngles )
|
||||
{
|
||||
arc->SetStart( startPoint );
|
||||
arc->SetEnd( endPoint );
|
||||
|
||||
/**
|
||||
* This accounts for an oddity in the old library format, where the symbol is overdefined.
|
||||
* The previous draw (based on wxwidgets) used start point and end point and always drew
|
||||
@@ -1035,6 +1035,7 @@ LIB_SHAPE* SCH_SEXPR_PARSER::parseArc()
|
||||
arc->SetStart( arc->GetEnd() );
|
||||
arc->SetEnd( temp );
|
||||
}
|
||||
|
||||
arc->SetCenter( center );
|
||||
}
|
||||
else
|
||||
@@ -1568,15 +1569,15 @@ void SCH_SEXPR_PARSER::parsePAGE_INFO( PAGE_INFO& aPageInfo )
|
||||
// Perform some controls to avoid crashes if the size is edited by hands
|
||||
if( width < MIN_PAGE_SIZE_MILS )
|
||||
width = MIN_PAGE_SIZE_MILS;
|
||||
else if( width > MAX_PAGE_SIZE_MILS )
|
||||
width = MAX_PAGE_SIZE_MILS;
|
||||
else if( width > MAX_PAGE_SIZE_EESCHEMA_MILS )
|
||||
width = MAX_PAGE_SIZE_EESCHEMA_MILS;
|
||||
|
||||
int height = Mm2mils( parseDouble( "height" ) ); // height stored in mm so we convert to mils
|
||||
|
||||
if( height < MIN_PAGE_SIZE_MILS )
|
||||
height = MIN_PAGE_SIZE_MILS;
|
||||
else if( height > MAX_PAGE_SIZE_MILS )
|
||||
height = MAX_PAGE_SIZE_MILS;
|
||||
else if( height > MAX_PAGE_SIZE_EESCHEMA_MILS )
|
||||
height = MAX_PAGE_SIZE_EESCHEMA_MILS;
|
||||
|
||||
aPageInfo.SetWidthMils( width );
|
||||
aPageInfo.SetHeightMils( height );
|
||||
|
||||
@@ -1090,14 +1090,11 @@ void SCH_SEXPR_PLUGIN::saveSymbol( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aSheetPa
|
||||
m_out->Print( 0, ")" );
|
||||
}
|
||||
|
||||
int unit = -1;
|
||||
int unit = ( aSymbol->GetInstanceReferences().size() == 0 ) ?
|
||||
aSymbol->GetUnit() :
|
||||
aSymbol->GetInstanceReferences()[0].m_Unit;
|
||||
|
||||
if( !( aSymbol->GetInstanceReferences().size() > 1 ) )
|
||||
unit = aSymbol->GetUnit();
|
||||
else if( aSheetPath != nullptr )
|
||||
unit = aSymbol->GetUnitSelection( aSheetPath );
|
||||
if ( unit >= 0 )
|
||||
m_out->Print( 0, " (unit %d)", unit );
|
||||
m_out->Print( 0, " (unit %d)", unit );
|
||||
|
||||
if( aSymbol->GetConvert() == LIB_ITEM::LIB_CONVERT::DEMORGAN )
|
||||
m_out->Print( 0, " (convert %d)", aSymbol->GetConvert() );
|
||||
@@ -1118,10 +1115,49 @@ void SCH_SEXPR_PLUGIN::saveSymbol( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aSheetPa
|
||||
|
||||
for( SCH_FIELD& field : aSymbol->GetFields() )
|
||||
{
|
||||
saveField( &field, aNestLevel + 1 );
|
||||
int id = field.GetId();
|
||||
wxString value = field.GetText();
|
||||
|
||||
// The instance fields are always set to the first sheet instance of the project to
|
||||
// schematic file changes when switching sheet instances with the current project
|
||||
// schematic. It does not solve the problem for schematics shared between projects.
|
||||
if( id == REFERENCE_FIELD )
|
||||
{
|
||||
field.SetText( ( aSymbol->GetInstanceReferences().size() == 0 ) ?
|
||||
value :
|
||||
aSymbol->GetInstanceReferences()[0].m_Reference );
|
||||
}
|
||||
else if( id == VALUE_FIELD )
|
||||
{
|
||||
field.SetText( ( aSymbol->GetInstanceReferences().size() == 0 ) ?
|
||||
value :
|
||||
aSymbol->GetInstanceReferences()[0].m_Value );
|
||||
}
|
||||
else if( id == FOOTPRINT_FIELD )
|
||||
{
|
||||
field.SetText( ( aSymbol->GetInstanceReferences().size() == 0 ) ?
|
||||
value :
|
||||
aSymbol->GetInstanceReferences()[0].m_Footprint );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
saveField( &field, aNestLevel + 1 );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
// Restore the changed field text on write error.
|
||||
if( id == REFERENCE_FIELD || id == VALUE_FIELD || id == FOOTPRINT_FIELD )
|
||||
field.SetText( value );
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
if( id == REFERENCE_FIELD || id == VALUE_FIELD || id == FOOTPRINT_FIELD )
|
||||
field.SetText( value );
|
||||
}
|
||||
|
||||
for( const SCH_PIN* pin : aSymbol->GetPins() )
|
||||
for( const std::unique_ptr<SCH_PIN>& pin : aSymbol->GetRawPins() )
|
||||
{
|
||||
if( pin->GetAlt().IsEmpty() )
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user