Compare commits
290 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d7388e2a70 | |||
| c4009544a9 | |||
| 4da5cf1413 | |||
| dc403c58e0 | |||
| 9c4f534cf1 | |||
| 94a7976082 | |||
| 77b80299e3 | |||
| cd59090581 | |||
| 3e29875c97 | |||
| 49afac5288 | |||
| da0cb7a9c8 | |||
| a58d408edd | |||
| 5be2066abb | |||
| d36064cd81 | |||
| 0531096961 | |||
| 9c88e88742 | |||
| 0c64c23b74 | |||
| 87c8aa9f24 | |||
| 47b2d3f1b1 | |||
| fd76dbc379 | |||
| 5f3fc426d9 | |||
| c17215bc22 | |||
| 7584892de9 | |||
| dbc3c99a73 | |||
| cbeed7bd1f | |||
| 34aa03a5ba | |||
| 7c9fcc5697 | |||
| bff819edb0 | |||
| 88c5b39b79 | |||
| 2b6be64168 | |||
| 6b31bbe9f3 | |||
| 340be56082 | |||
| 07d129bbf0 | |||
| 7de3289851 | |||
| 48e405c769 | |||
| 1ce834f529 | |||
| 656d5307fe | |||
| 3ed66aa3e0 | |||
| bef6630bc5 | |||
| a17639b16e | |||
| c942f94357 | |||
| e6fd6ee369 | |||
| 18a8cb285f | |||
| c616fc850e | |||
| 3b34c031d7 | |||
| 4e3a86d808 | |||
| 020376937e | |||
| af1e8ed763 | |||
| a20bd59e3f | |||
| 7d689e0c61 | |||
| 458df1ebab | |||
| d91d07d187 | |||
| 77963d9ff8 | |||
| 4ed1954b4b | |||
| c73cc2cd79 | |||
| 6793e9c519 | |||
| c5c26f8852 | |||
| e107873497 | |||
| c616d58f5b | |||
| a3b63ef9f0 | |||
| 9d8dc30e23 | |||
| 759274d1d3 | |||
| 2fa20a9fbc | |||
| 34ce2b4ea0 | |||
| 8d35d823b5 | |||
| ea6a258ace | |||
| 3742cec2c1 | |||
| 64a88e3f16 | |||
| 7537ee6789 | |||
| c69cd13081 | |||
| 5f101e600d | |||
| e51a7da116 | |||
| c6b942e8a9 | |||
| 3bed425849 | |||
| 5069061bab | |||
| e098a10221 | |||
| ccdbe4c5b2 | |||
| 3351ec1cdb | |||
| a6afb12fec | |||
| a49abfe5e4 | |||
| 12c48f2ab3 | |||
| 10a0afa270 | |||
| 09b86de38f | |||
| 8714a7968f | |||
| 9ac733b34a | |||
| b7fe4e8fce | |||
| 01f20537f0 | |||
| bc48b23e15 | |||
| e35bdea63d | |||
| ec16ccbb2d | |||
| 8fea9d938e | |||
| c977a078c1 | |||
| 50e178535b | |||
| fdd933f6a5 | |||
| beb053393f | |||
| ad61c264a4 | |||
| 7d8c6361ff | |||
| 4e066e015d | |||
| fd7a08a331 | |||
| 587ae98c6d | |||
| 17340772f6 | |||
| dcf61f1550 | |||
| 9af2b78a64 | |||
| b01425be64 | |||
| 69576ac50a | |||
| a3b0277a5e | |||
| 53ccabbe45 | |||
| 78be3ce5a1 | |||
| cdedffec99 | |||
| c6b02b1cab | |||
| 70756c53f5 | |||
| 4658c41dc5 | |||
| 87f8ec5d7b | |||
| 29ee58365c | |||
| 9a73015ac1 | |||
| ee7f80c2eb | |||
| 2f98aa55dc | |||
| cade74ef59 | |||
| d9e874757b | |||
| 07ef43189a | |||
| 34358a72d0 | |||
| 60fcbde2f2 | |||
| fe35e4f803 | |||
| 1081ef0b8e | |||
| 73daa9cb42 | |||
| 739180acfe | |||
| ded56fe5d5 | |||
| 106f201af8 | |||
| 217053cd7d | |||
| f0f45a6a22 | |||
| 17dcfdbf7a | |||
| a8d09657a8 | |||
| 0375634464 | |||
| cd19b4bce4 | |||
| 4562476557 | |||
| 8b811aa383 | |||
| 99c0fa8d66 | |||
| 3e90637a00 | |||
| 9977764d54 | |||
| 16f809ad00 | |||
| 958cc30eda | |||
| c29f7a6aad | |||
| c49f65280d | |||
| bb31f4800b | |||
| c734aecda7 | |||
| 13f32147b3 | |||
| 88676dadb9 | |||
| 8452c3db0a | |||
| 07159b6a35 | |||
| 9b50755f6a | |||
| f7329ea56d | |||
| 441ddc9a70 | |||
| 78d6055881 | |||
| 0d2cc0ff72 | |||
| 238c0ad506 | |||
| 8aea02cba9 | |||
| 0a48c891d5 | |||
| 48a9caf030 | |||
| d6031bef58 | |||
| a51e368a1d | |||
| c590c75199 | |||
| ba01994ab8 | |||
| 3a2bd67ba6 | |||
| f19ab7adbb | |||
| f609ee4c88 | |||
| 84da12c5c4 | |||
| 1650d195db | |||
| 2967f1d64f | |||
| 89ee2ea22d | |||
| 1daaa0a056 | |||
| 016206812e | |||
| 3de56dee38 | |||
| 41b756a637 | |||
| 839a0f4afd | |||
| 225e18738a | |||
| 8e4ff8e843 | |||
| 9011c873f9 | |||
| 26025feb5b | |||
| af7bf2fe46 | |||
| 012ab10c16 | |||
| 18ab9c78a8 | |||
| 9ece7797d6 | |||
| 4dc0291ae8 | |||
| 5d6d5ff3fc | |||
| 1c97c71a74 | |||
| d913a6d2d2 | |||
| cbdff703f0 | |||
| 8241358a44 | |||
| f0511f6f26 | |||
| 35639fa910 | |||
| b7d1a08566 | |||
| 3bba622e2d | |||
| 1a3f226bca | |||
| 143a89556f | |||
| fbad7ae602 | |||
| a1646bbd6c | |||
| d4f42a7fef | |||
| f56e45aa49 | |||
| 08a8081eb9 | |||
| 7c21dc3014 | |||
| 0c643fc992 | |||
| b39ccfcb77 | |||
| cdb5dbfae1 | |||
| 19890b7f99 | |||
| 424f02bdca | |||
| c435d2ee99 | |||
| 0b0d30e9a0 | |||
| fd2a9293e0 | |||
| 1f74103e0b | |||
| f078598bfe | |||
| e4ff452ffb | |||
| 4f66c68ff8 | |||
| e7d946bec6 | |||
| 3e01b80871 | |||
| dd93d53ec9 | |||
| 995815c20e | |||
| 8aec186cfa | |||
| b84560e959 | |||
| c4a4dbd561 | |||
| ab9b2d2869 | |||
| a26c8b01c9 | |||
| 81432e4da7 | |||
| eb10e6d4a1 | |||
| 71ee4d4c83 | |||
| f91a75b61b | |||
| 8b24496b79 | |||
| 5eed4e41a4 | |||
| 519abec88b | |||
| 26ef463ffa | |||
| ad4667bb96 | |||
| 499105c1c3 | |||
| 614b327d23 | |||
| e0c57b7f20 | |||
| 03968c7bcc | |||
| e32a58b0a9 | |||
| cf3f3e2221 | |||
| fc65a157f5 | |||
| 559b1827ca | |||
| 7858ed43a5 | |||
| 1a267cde75 | |||
| 6b1efe8492 | |||
| 12d96d1a90 | |||
| 935d3a3c52 | |||
| ae2aab85d9 | |||
| 47c3127db3 | |||
| 19d3e041be | |||
| 9228a6cd09 | |||
| 582377e86f | |||
| f359ca38d0 | |||
| 0108e8f56c | |||
| f823a43c1c | |||
| a31302da9f | |||
| f51657632b | |||
| 78fb820a26 | |||
| 47fc6dede2 | |||
| 9c9a1b7895 | |||
| 3cc86898b1 | |||
| 16b7b9af89 | |||
| aedcae8092 | |||
| b32fd3521f | |||
| b9b5c14867 | |||
| 82084218d9 | |||
| a4a7160b45 | |||
| a30b99b794 | |||
| 1f0c58a524 | |||
| 6e8de14766 | |||
| cce2bf9086 | |||
| 1371a58259 | |||
| ab12223247 | |||
| 6a2c35dc42 | |||
| ad6a4e5621 | |||
| 99fc22adb5 | |||
| dfaae5e3ca | |||
| dfa8f2e0ec | |||
| 2704c30404 | |||
| 8a1072ce75 | |||
| e5cb28c7fe | |||
| ed7f0d3234 | |||
| 7be1c84be2 | |||
| c37358fd33 | |||
| c71db323fb | |||
| b8d09c9b42 | |||
| 29fe6c1446 | |||
| 9b3ee263c3 | |||
| c54f57b8e5 | |||
| 603a500bc0 | |||
| 7e68c57747 | |||
| 644c4f8c0a | |||
| 5ae377f41a | |||
| 1d534303d4 |
@@ -4,16 +4,16 @@
|
||||
win64_build:
|
||||
stage: build
|
||||
tags:
|
||||
- kicad-windows-1809
|
||||
- kicad-windows-ltsc2022
|
||||
interruptible: false
|
||||
image: registry.gitlab.com/kicad/kicad-ci/windows-build-image/win1809-msvc:latest
|
||||
image: registry.gitlab.com/kicad/kicad-ci/windows-build-image/ltsc2022-msvc:latest
|
||||
variables:
|
||||
VCPKG_BINARY_SOURCES: 'nuget,kicad,readwrite'
|
||||
# Switch the compressor to fastzip and reduce the compression level
|
||||
FF_USE_FASTZIP: "true"
|
||||
CACHE_COMPRESSION_LEVEL: "fast"
|
||||
cache:
|
||||
key: win64-vcpkg-"$CI_COMMIT_REF_SLUG"
|
||||
key: win64-vcpkg-$CI_COMMIT_REF_SLUG
|
||||
paths:
|
||||
- build\windows\vcpkg_installed
|
||||
- .vcpkgCache
|
||||
|
||||
@@ -15,7 +15,7 @@ macos_build:
|
||||
- cd build/macos
|
||||
- cmake
|
||||
-G Ninja
|
||||
-DCMAKE_TOOLCHAIN_FILE=/Users/ci/kicad-mac-builder/toolchain/kicad-mac-builder.cmake
|
||||
-DCMAKE_TOOLCHAIN_FILE=/Users/$USER/kicad-mac-builder/toolchain/kicad-mac-builder.cmake
|
||||
../../
|
||||
- cmake --build . 2>&1 | tee compilation_log.txt
|
||||
- cd ../../
|
||||
|
||||
@@ -643,12 +643,33 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||
// add also this shape to the plated copper polygon list if required
|
||||
if( cfg.differentiate_plated_copper )
|
||||
{
|
||||
if( layer == F_Cu )
|
||||
item->TransformShapeToPolygon( *m_frontPlatedCopperPolys, F_Cu,
|
||||
0, maxError, ERROR_INSIDE );
|
||||
else if( layer == B_Cu )
|
||||
item->TransformShapeToPolygon( *m_backPlatedCopperPolys, B_Cu,
|
||||
0, maxError, ERROR_INSIDE );
|
||||
// Note: for TEXT and TEXTBOX, TransformShapeToPolygon returns the bounding
|
||||
// box shape, not the exact text shape. So it is not used for these items
|
||||
if( layer == F_Cu || layer == B_Cu )
|
||||
{
|
||||
SHAPE_POLY_SET* platedCopperPolys = layer == F_Cu
|
||||
? m_frontPlatedCopperPolys
|
||||
: m_backPlatedCopperPolys;
|
||||
|
||||
if( item->Type() == PCB_TEXTBOX_T )
|
||||
{
|
||||
PCB_TEXTBOX* text_box = static_cast<PCB_TEXTBOX*>( item );
|
||||
text_box->TransformTextToPolySet( *platedCopperPolys,
|
||||
0, maxError, ERROR_INSIDE );
|
||||
// Add box outlines
|
||||
text_box->PCB_SHAPE::TransformShapeToPolygon( *platedCopperPolys, layer,
|
||||
0, maxError, ERROR_INSIDE );
|
||||
}
|
||||
else if( item->Type() == PCB_TEXT_T )
|
||||
{
|
||||
static_cast<PCB_TEXT*>( item )->TransformTextToPolySet(
|
||||
*platedCopperPolys,
|
||||
0, maxError, ERROR_INSIDE );
|
||||
}
|
||||
else
|
||||
item->TransformShapeToPolygon( *platedCopperPolys, layer,
|
||||
0, maxError, ERROR_INSIDE );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,12 @@ COLOR_RGB::COLOR_RGB( const SFVEC3F& aColor )
|
||||
}
|
||||
|
||||
|
||||
COLOR_RGB::operator SFVEC3F() const
|
||||
{
|
||||
return SFVEC3F( r / 255.0f, g / 255.0f, b / 255.0f );
|
||||
}
|
||||
|
||||
|
||||
COLOR_RGB BlendColor( const COLOR_RGB& aC1, const COLOR_RGB& aC2 )
|
||||
{
|
||||
const unsigned int r = aC1.r + aC2.r;
|
||||
|
||||
@@ -50,6 +50,8 @@ union COLOR_RGB
|
||||
g = aG;
|
||||
b = aB;
|
||||
}
|
||||
|
||||
operator SFVEC3F() const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -429,7 +429,7 @@ void RENDER_3D_RAYTRACE::Reload( REPORTER* aStatusReporter, REPORTER* aWarningRe
|
||||
|
||||
boardPolyCopy.Fracture( SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
for( int ii = 0; ii < outlineCount; ii++ )
|
||||
for( int ii = 0; ii < boardPolyCopy.OutlineCount(); ii++ )
|
||||
{
|
||||
ConvertPolygonToBlocks( boardPolyCopy, *m_outlineBoard2dObjects,
|
||||
m_boardAdapter.BiuTo3dUnits(), divFactor,
|
||||
|
||||
@@ -42,10 +42,15 @@ void FRUSTUM::GenerateFrustum( const RAY& topLeft, const RAY& topRight, const RA
|
||||
m_point[2] = bottomLeft.m_Origin;
|
||||
m_point[3] = topLeft.m_Origin;
|
||||
|
||||
m_normals[0] = glm::cross( topRight.m_Dir, topLeft.m_Dir ); // TOP
|
||||
m_normals[1] = glm::cross( bottomRight.m_Dir, topRight.m_Dir ); // RIGHT
|
||||
m_normals[2] = glm::cross( bottomLeft.m_Dir, bottomRight.m_Dir ); // BOTTOM
|
||||
m_normals[3] = glm::cross( topLeft.m_Dir, bottomLeft.m_Dir ); // LEFT
|
||||
SFVEC3F tl_tr = topRight.m_Origin - topLeft.m_Origin;
|
||||
SFVEC3F tr_br = bottomRight.m_Origin - topRight.m_Origin;
|
||||
SFVEC3F br_bl = bottomLeft.m_Origin - bottomRight.m_Origin;
|
||||
SFVEC3F bl_tl = topLeft.m_Origin - bottomLeft.m_Origin;
|
||||
|
||||
m_normals[0] = glm::cross( tl_tr, topLeft.m_Dir ); // TOP
|
||||
m_normals[1] = glm::cross( tr_br, topRight.m_Dir ); // RIGHT
|
||||
m_normals[2] = glm::cross( br_bl, bottomRight.m_Dir ); // BOTTOM
|
||||
m_normals[3] = glm::cross( bl_tl, bottomLeft.m_Dir ); // LEFT
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -39,6 +39,41 @@
|
||||
#include <wx/log.h>
|
||||
|
||||
|
||||
#ifdef USE_SRGB_SPACE
|
||||
|
||||
/// @todo This should be removed in future when KiCad supports a greater version of glm lib.
|
||||
#define SRGB_GAMA 2.4f
|
||||
|
||||
|
||||
// This function implements the conversion from linear RGB to sRGB
|
||||
// https://github.com/g-truc/glm/blob/master/glm/gtc/color_space.inl#L12
|
||||
static SFVEC3F convertLinearToSRGB( const SFVEC3F& aRGBcolor )
|
||||
{
|
||||
const float gammaCorrection = 1.0f / SRGB_GAMA;
|
||||
const SFVEC3F clampedColor = glm::clamp( aRGBcolor, SFVEC3F( 0.0f ), SFVEC3F( 1.0f ) );
|
||||
|
||||
return glm::mix( glm::pow( clampedColor, SFVEC3F(gammaCorrection) ) * 1.055f - 0.055f,
|
||||
clampedColor * 12.92f,
|
||||
glm::lessThan( clampedColor, SFVEC3F(0.0031308f) ) );
|
||||
}
|
||||
|
||||
|
||||
// This function implements the conversion from sRGB to linear RGB
|
||||
// https://github.com/g-truc/glm/blob/master/glm/gtc/color_space.inl#L35
|
||||
SFVEC3F ConvertSRGBToLinear( const SFVEC3F& aSRGBcolor )
|
||||
{
|
||||
const float gammaCorrection = SRGB_GAMA;
|
||||
|
||||
return glm::mix( glm::pow( ( aSRGBcolor + SFVEC3F( 0.055f ) )
|
||||
* SFVEC3F( 0.94786729857819905213270142180095f ),
|
||||
SFVEC3F( gammaCorrection ) ),
|
||||
aSRGBcolor * SFVEC3F( 0.07739938080495356037151702786378f ),
|
||||
glm::lessThanEqual( aSRGBcolor, SFVEC3F( 0.04045f ) ) );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
RENDER_3D_RAYTRACE::RENDER_3D_RAYTRACE( EDA_3D_CANVAS* aCanvas, BOARD_ADAPTER& aAdapter, CAMERA& aCamera ) :
|
||||
RENDER_3D_BASE( aCanvas, aAdapter, aCamera ),
|
||||
m_postShaderSsao( aCamera )
|
||||
@@ -145,6 +180,19 @@ static inline void SetPixel( GLubyte* p, const COLOR_RGB& v )
|
||||
}
|
||||
|
||||
|
||||
static void SetPixelSRGB( uint8_t* p, const COLOR_RGB& v )
|
||||
{
|
||||
SFVEC3F color = v;
|
||||
|
||||
#ifdef USE_SRGB_SPACE
|
||||
color = convertLinearToSRGB( color );
|
||||
#endif
|
||||
|
||||
COLOR_RGB rgb( color );
|
||||
SetPixel( p, rgb );
|
||||
}
|
||||
|
||||
|
||||
bool RENDER_3D_RAYTRACE::Redraw( bool aIsMoving, REPORTER* aStatusReporter,
|
||||
REPORTER* aWarningReporter )
|
||||
{
|
||||
@@ -406,41 +454,6 @@ void RENDER_3D_RAYTRACE::renderTracing( GLubyte* ptrPBO, REPORTER* aStatusReport
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_SRGB_SPACE
|
||||
|
||||
/// @todo This should be removed in future when KiCad supports a greater version of glm lib.
|
||||
#define SRGB_GAMA 2.4f
|
||||
|
||||
|
||||
// This function implements the conversion from linear RGB to sRGB
|
||||
// https://github.com/g-truc/glm/blob/master/glm/gtc/color_space.inl#L12
|
||||
static SFVEC3F convertLinearToSRGB( const SFVEC3F& aRGBcolor )
|
||||
{
|
||||
const float gammaCorrection = 1.0f / SRGB_GAMA;
|
||||
const SFVEC3F clampedColor = glm::clamp( aRGBcolor, SFVEC3F( 0.0f ), SFVEC3F( 1.0f ) );
|
||||
|
||||
return glm::mix( glm::pow( clampedColor, SFVEC3F(gammaCorrection) ) * 1.055f - 0.055f,
|
||||
clampedColor * 12.92f,
|
||||
glm::lessThan( clampedColor, SFVEC3F(0.0031308f) ) );
|
||||
}
|
||||
|
||||
|
||||
// This function implements the conversion from sRGB to linear RGB
|
||||
// https://github.com/g-truc/glm/blob/master/glm/gtc/color_space.inl#L35
|
||||
SFVEC3F ConvertSRGBToLinear( const SFVEC3F& aSRGBcolor )
|
||||
{
|
||||
const float gammaCorrection = SRGB_GAMA;
|
||||
|
||||
return glm::mix( glm::pow( ( aSRGBcolor + SFVEC3F( 0.055f ) )
|
||||
* SFVEC3F( 0.94786729857819905213270142180095f ),
|
||||
SFVEC3F( gammaCorrection ) ),
|
||||
aSRGBcolor * SFVEC3F( 0.07739938080495356037151702786378f ),
|
||||
glm::lessThanEqual( aSRGBcolor, SFVEC3F( 0.04045f ) ) );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void RENDER_3D_RAYTRACE::renderFinalColor( GLubyte* ptrPBO, const SFVEC3F& rgbColor,
|
||||
bool applyColorSpaceConversion )
|
||||
{
|
||||
@@ -946,6 +959,9 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO )
|
||||
{
|
||||
m_isPreview = true;
|
||||
|
||||
m_backgroundColorTop = ConvertSRGBToLinear( m_boardAdapter.m_BgColorTop );
|
||||
m_backgroundColorBottom = ConvertSRGBToLinear( m_boardAdapter.m_BgColorBot );
|
||||
|
||||
std::atomic<size_t> nextBlock( 0 );
|
||||
std::atomic<size_t> threadsFinished( 0 );
|
||||
|
||||
@@ -982,13 +998,16 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO )
|
||||
// Calculate background gradient color
|
||||
SFVEC3F bgColor[RAYPACKET_DIM];
|
||||
|
||||
SFVEC3F bgTopColor = m_backgroundColorTop;
|
||||
SFVEC3F bgBotColor = m_backgroundColorBottom;
|
||||
|
||||
for( unsigned int y = 0; y < RAYPACKET_DIM; ++y )
|
||||
{
|
||||
const float posYfactor =
|
||||
(float) ( windowsPos.y + y * 4.0f ) / (float) m_windowSize.y;
|
||||
|
||||
bgColor[y] = (SFVEC3F) m_boardAdapter.m_BgColorTop * SFVEC3F( posYfactor )
|
||||
+ (SFVEC3F) m_boardAdapter.m_BgColorBot
|
||||
bgColor[y] = (SFVEC3F) bgTopColor * SFVEC3F( posYfactor )
|
||||
+ (SFVEC3F) bgBotColor
|
||||
* ( SFVEC3F( 1.0f ) - SFVEC3F( posYfactor ) );
|
||||
}
|
||||
|
||||
@@ -1499,28 +1518,29 @@ void RENDER_3D_RAYTRACE::renderPreview( GLubyte* ptrPBO )
|
||||
&ptrPBO[( 4 * x + m_blockPositionsFast[iBlock].x
|
||||
+ m_realBufferSize.x
|
||||
* ( m_blockPositionsFast[iBlock].y + 4 * y ) ) * 4];
|
||||
SetPixel( ptr + 0, cLT );
|
||||
SetPixel( ptr + 4, BlendColor( cLT, cLRT, cLTC ) );
|
||||
SetPixel( ptr + 8, cLRT );
|
||||
SetPixel( ptr + 12, BlendColor( cLRT, cRT, cRTC ) );
|
||||
|
||||
SetPixelSRGB( ptr + 0, cLT );
|
||||
SetPixelSRGB( ptr + 4, BlendColor( cLT, cLRT, cLTC ) );
|
||||
SetPixelSRGB( ptr + 8, cLRT );
|
||||
SetPixelSRGB( ptr + 12, BlendColor( cLRT, cRT, cRTC ) );
|
||||
|
||||
ptr += m_realBufferSize.x * 4;
|
||||
SetPixel( ptr + 0, BlendColor( cLT , cLTB, cLTC ) );
|
||||
SetPixel( ptr + 4, BlendColor( cLTC, BlendColor( cLT , cC ) ) );
|
||||
SetPixel( ptr + 8, BlendColor( cC, BlendColor( cLRT, cLTC, cRTC ) ) );
|
||||
SetPixel( ptr + 12, BlendColor( cRTC, BlendColor( cRT , cC ) ) );
|
||||
SetPixelSRGB( ptr + 0, BlendColor( cLT , cLTB, cLTC ) );
|
||||
SetPixelSRGB( ptr + 4, BlendColor( cLTC, BlendColor( cLT , cC ) ) );
|
||||
SetPixelSRGB( ptr + 8, BlendColor( cC, BlendColor( cLRT, cLTC, cRTC ) ) );
|
||||
SetPixelSRGB( ptr + 12, BlendColor( cRTC, BlendColor( cRT , cC ) ) );
|
||||
|
||||
ptr += m_realBufferSize.x * 4;
|
||||
SetPixel( ptr + 0, cLTB );
|
||||
SetPixel( ptr + 4, BlendColor( cC, BlendColor( cLTB, cLTC, cLBC ) ) );
|
||||
SetPixel( ptr + 8, cC );
|
||||
SetPixel( ptr + 12, BlendColor( cC, BlendColor( cRTB, cRTC, cRBC ) ) );
|
||||
SetPixelSRGB( ptr + 0, cLTB );
|
||||
SetPixelSRGB( ptr + 4, BlendColor( cC, BlendColor( cLTB, cLTC, cLBC ) ) );
|
||||
SetPixelSRGB( ptr + 8, cC );
|
||||
SetPixelSRGB( ptr + 12, BlendColor( cC, BlendColor( cRTB, cRTC, cRBC ) ) );
|
||||
|
||||
ptr += m_realBufferSize.x * 4;
|
||||
SetPixel( ptr + 0, BlendColor( cLB , cLTB, cLBC ) );
|
||||
SetPixel( ptr + 4, BlendColor( cLBC, BlendColor( cLB , cC ) ) );
|
||||
SetPixel( ptr + 8, BlendColor( cC, BlendColor( cLRB, cLBC, cRBC ) ) );
|
||||
SetPixel( ptr + 12, BlendColor( cRBC, BlendColor( cRB , cC ) ) );
|
||||
SetPixelSRGB( ptr + 0, BlendColor( cLB , cLTB, cLBC ) );
|
||||
SetPixelSRGB( ptr + 4, BlendColor( cLBC, BlendColor( cLB , cC ) ) );
|
||||
SetPixelSRGB( ptr + 8, BlendColor( cC, BlendColor( cLRB, cLBC, cRBC ) ) );
|
||||
SetPixelSRGB( ptr + 12, BlendColor( cRBC, BlendColor( cRB , cC ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1572,9 +1592,6 @@ SFVEC3F RENDER_3D_RAYTRACE::shadeHit( const SFVEC3F& aBgColor, const RAY& aRay,
|
||||
|
||||
light->GetLightParameters( hitPoint, vectorToLight, colorOfLight, distToLight );
|
||||
|
||||
if( m_isPreview )
|
||||
colorOfLight = SFVEC3F( 1.0f );
|
||||
|
||||
const float NdotL = glm::dot( aHitInfo.m_HitNormal, vectorToLight );
|
||||
|
||||
// Only calc shade if the normal is facing the direction of light,
|
||||
@@ -1641,10 +1658,6 @@ SFVEC3F RENDER_3D_RAYTRACE::shadeHit( const SFVEC3F& aBgColor, const RAY& aRay,
|
||||
outColor += objMaterial->Shade( aRay, aHitInfo, NdotL, diffuseColorObj, vectorToLight,
|
||||
colorOfLight, shadow_att_factor_light );
|
||||
}
|
||||
|
||||
// Only use the headlight for preview
|
||||
if( m_isPreview )
|
||||
break;
|
||||
}
|
||||
|
||||
// Improvement: this is not taking in account the lightcolor
|
||||
|
||||
@@ -573,6 +573,9 @@ if( MSVC )
|
||||
if( KICAD_WIN32_BUILD_PARALLEL_CL_MP )
|
||||
string( APPEND CMAKE_CXX_FLAGS " /MP" )
|
||||
endif()
|
||||
|
||||
set( CMAKE_INSTALL_UCRT_LIBRARIES TRUE )
|
||||
include( InstallRequiredSystemLibraries )
|
||||
endif()
|
||||
|
||||
# KIFACE_SUFFIX is the file extension used for top level program modules which
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
# KiCad.
|
||||
#
|
||||
# Note: This version string should follow the semantic versioning system
|
||||
set( KICAD_SEMANTIC_VERSION "8.0.8-rc1" )
|
||||
set( KICAD_SEMANTIC_VERSION "8.0.9-unknown" )
|
||||
|
||||
# Default the version to the semantic version.
|
||||
# This is overridden by the git repository tag though (if using git)
|
||||
|
||||
@@ -110,9 +110,9 @@ static const wxChar TriangulateSimplificationLevel[] = wxT( "TriangulateSimplifi
|
||||
static const wxChar TriangulateMinimumArea[] = wxT( "TriangulateMinimumArea" );
|
||||
static const wxChar EnableCacheFriendlyFracture[] = wxT( "EnableCacheFriendlyFracture" );
|
||||
static const wxChar MinParallelAngle[] = wxT( "MinParallelAngle" );
|
||||
static const wxChar ResolveTextRecursionDepth[] = wxT( "ResolveTextRecursionDepth" );
|
||||
} // namespace KEYS
|
||||
|
||||
|
||||
/**
|
||||
* List of known groups for advanced configuration options.
|
||||
*
|
||||
@@ -264,6 +264,8 @@ ADVANCED_CFG::ADVANCED_CFG()
|
||||
|
||||
m_MinParallelAngle = 0.001;
|
||||
|
||||
m_ResolveTextRecursionDepth = 3;
|
||||
|
||||
loadFromConfigFile();
|
||||
}
|
||||
|
||||
@@ -484,6 +486,10 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg )
|
||||
&m_MinParallelAngle, m_MinParallelAngle,
|
||||
0.0, 45.0 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::ResolveTextRecursionDepth,
|
||||
&m_ResolveTextRecursionDepth,
|
||||
m_ResolveTextRecursionDepth, 0, 10 ) );
|
||||
|
||||
// Special case for trace mask setting...we just grab them and set them immediately
|
||||
// Because we even use wxLogTrace inside of advanced config
|
||||
wxString traceMasks;
|
||||
|
||||
@@ -182,7 +182,7 @@ BACKGROUND_JOB_REPORTER::BACKGROUND_JOB_REPORTER( BACKGROUND_JOBS_MONITOR* aMoni
|
||||
|
||||
bool BACKGROUND_JOB_REPORTER::updateUI()
|
||||
{
|
||||
return true;
|
||||
return !m_cancelled;
|
||||
}
|
||||
|
||||
|
||||
@@ -265,7 +265,11 @@ void BACKGROUND_JOBS_MONITOR::Remove( std::shared_ptr<BACKGROUND_JOB> aJob )
|
||||
return job == aJob;
|
||||
} ) );
|
||||
|
||||
if( m_jobs.size() == 0 )
|
||||
if( m_jobs.size() > 0 )
|
||||
{
|
||||
jobUpdated( m_jobs.front() );
|
||||
}
|
||||
else
|
||||
{
|
||||
for( KISTATUSBAR* statusBar : m_statusBars )
|
||||
{
|
||||
|
||||
@@ -57,6 +57,10 @@ WX_PT_ENTRY_DIALOG::WX_PT_ENTRY_DIALOG( EDA_DRAW_FRAME* aParent, const wxString&
|
||||
{
|
||||
m_labelX->SetLabel( aLabelX );
|
||||
m_labelY->SetLabel( aLabelY );
|
||||
|
||||
m_unit_binder_x.SetCoordType( ORIGIN_TRANSFORMS::ABS_X_COORD );
|
||||
m_unit_binder_y.SetCoordType( ORIGIN_TRANSFORMS::ABS_Y_COORD );
|
||||
|
||||
m_unit_binder_x.SetValue( aDefaultValue.x );
|
||||
m_unit_binder_y.SetValue( aDefaultValue.y );
|
||||
|
||||
|
||||
@@ -191,20 +191,16 @@ void PANEL_COLOR_SETTINGS::OnThemeChanged( wxCommandEvent& event )
|
||||
void PANEL_COLOR_SETTINGS::updateSwatches()
|
||||
{
|
||||
if( m_swatches.empty() )
|
||||
{
|
||||
createSwatches();
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isReadOnly = m_currentSettings->IsReadOnly();
|
||||
COLOR4D background = m_currentSettings->GetColor( m_backgroundLayer );
|
||||
|
||||
for( std::pair<int, COLOR_SWATCH*> pair : m_swatches )
|
||||
{
|
||||
pair.second->SetSwatchBackground( background );
|
||||
pair.second->SetSwatchColor( m_currentSettings->GetColor( pair.first ), false );
|
||||
pair.second->SetReadOnly( isReadOnly );
|
||||
}
|
||||
bool isReadOnly = m_currentSettings->IsReadOnly();
|
||||
COLOR4D background = m_currentSettings->GetColor( m_backgroundLayer );
|
||||
|
||||
for( std::pair<int, COLOR_SWATCH*> pair : m_swatches )
|
||||
{
|
||||
pair.second->SetSwatchBackground( background );
|
||||
pair.second->SetSwatchColor( m_currentSettings->GetColor( pair.first ), false );
|
||||
pair.second->SetReadOnly( isReadOnly );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,6 @@ EDA_DRAW_FRAME::EDA_DRAW_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrame
|
||||
m_drawBgColor = COLOR4D( BLACK ); // the background color of the draw canvas:
|
||||
// BLACK for Pcbnew, BLACK or WHITE for Eeschema
|
||||
m_colorSettings = nullptr;
|
||||
m_msgFrameHeight = EDA_MSG_PANEL::GetRequiredHeight( this );
|
||||
m_polarCoords = false;
|
||||
m_findReplaceData = std::make_unique<EDA_SEARCH_DATA>();
|
||||
m_hotkeyPopup = nullptr;
|
||||
@@ -170,15 +169,16 @@ EDA_DRAW_FRAME::EDA_DRAW_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrame
|
||||
stsbar->SetFont( KIUI::GetStatusFont( this ) );
|
||||
}
|
||||
|
||||
m_messagePanel = new EDA_MSG_PANEL( this, -1, wxPoint( 0, m_frameSize.y ), wxDefaultSize );
|
||||
m_messagePanel->SetBackgroundColour( COLOR4D( LIGHTGRAY ).ToColour() );
|
||||
m_msgFrameHeight = m_messagePanel->GetBestSize().y;
|
||||
|
||||
// Create child subwindows.
|
||||
GetClientSize( &m_frameSize.x, &m_frameSize.y );
|
||||
m_framePos.x = m_framePos.y = 0;
|
||||
m_frameSize.y -= m_msgFrameHeight;
|
||||
|
||||
m_messagePanel = new EDA_MSG_PANEL( this, -1, wxPoint( 0, m_frameSize.y ),
|
||||
wxSize( m_frameSize.x, m_msgFrameHeight ) );
|
||||
|
||||
m_messagePanel->SetBackgroundColour( COLOR4D( LIGHTGRAY ).ToColour() );
|
||||
m_messagePanel->SetSize( m_frameSize.x, m_msgFrameHeight );
|
||||
|
||||
Bind( wxEVT_DPI_CHANGED,
|
||||
[&]( wxDPIChangedEvent& )
|
||||
@@ -190,11 +190,13 @@ EDA_DRAW_FRAME::EDA_DRAW_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrame
|
||||
// especially important even for first launches as the constructor of the window
|
||||
// here usually doesn't have the correct dpi awareness yet
|
||||
m_frameSize.y += m_msgFrameHeight;
|
||||
m_msgFrameHeight = EDA_MSG_PANEL::GetRequiredHeight( this );
|
||||
m_msgFrameHeight = m_messagePanel->GetBestSize().y;
|
||||
m_frameSize.y -= m_msgFrameHeight;
|
||||
|
||||
m_messagePanel->SetPosition( wxPoint( 0, m_frameSize.y ) );
|
||||
m_messagePanel->SetSize( m_frameSize.x, m_msgFrameHeight );
|
||||
|
||||
// Don't skip, otherwise the frame gets too big
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
@@ -476,6 +476,12 @@ int EDA_COMBINED_MATCHER::ScoreTerms( std::vector<SEARCH_TERM>& aWeightedTerms )
|
||||
if( !term.Normalized )
|
||||
{
|
||||
term.Text = term.Text.MakeLower().Trim( false ).Trim( true );
|
||||
|
||||
// Don't cause KiCad to hang if someone accidentally pastes the PCB or schematic
|
||||
// into the search box.
|
||||
if( term.Text.Length() > 1000 )
|
||||
term.Text = term.Text.Left( 1000 );
|
||||
|
||||
term.Normalized = true;
|
||||
}
|
||||
|
||||
|
||||
+11
-1
@@ -269,12 +269,18 @@ void EDA_SHAPE::move( const VECTOR2I& aMoveVector )
|
||||
switch ( m_shape )
|
||||
{
|
||||
case SHAPE_T::ARC:
|
||||
m_arcCenter += aMoveVector;
|
||||
m_arcMidData.center += aMoveVector;
|
||||
m_arcMidData.start += aMoveVector;
|
||||
m_arcMidData.end += aMoveVector;
|
||||
m_arcMidData.mid += aMoveVector;
|
||||
KI_FALLTHROUGH;
|
||||
|
||||
case SHAPE_T::SEGMENT:
|
||||
case SHAPE_T::RECTANGLE:
|
||||
case SHAPE_T::CIRCLE:
|
||||
m_start += aMoveVector;
|
||||
m_end += aMoveVector;
|
||||
m_arcCenter += aMoveVector;
|
||||
break;
|
||||
|
||||
case SHAPE_T::POLY:
|
||||
@@ -368,6 +374,10 @@ void EDA_SHAPE::rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
|
||||
RotatePoint( m_start, aRotCentre, aAngle );
|
||||
RotatePoint( m_end, aRotCentre, aAngle );
|
||||
RotatePoint( m_arcCenter, aRotCentre, aAngle );
|
||||
RotatePoint( m_arcMidData.start, aRotCentre, aAngle );
|
||||
RotatePoint( m_arcMidData.end, aRotCentre, aAngle );
|
||||
RotatePoint( m_arcMidData.mid, aRotCentre, aAngle );
|
||||
RotatePoint( m_arcMidData.center, aRotCentre, aAngle );
|
||||
break;
|
||||
|
||||
case SHAPE_T::RECTANGLE:
|
||||
|
||||
@@ -267,6 +267,7 @@ struct GLYPH_CACHE_KEY {
|
||||
bool fakeItalic;
|
||||
bool fakeBold;
|
||||
bool mirror;
|
||||
bool supersub;
|
||||
EDA_ANGLE angle;
|
||||
|
||||
bool operator==(const GLYPH_CACHE_KEY& rhs ) const
|
||||
@@ -278,6 +279,7 @@ struct GLYPH_CACHE_KEY {
|
||||
&& fakeItalic == rhs.fakeItalic
|
||||
&& fakeBold == rhs.fakeBold
|
||||
&& mirror == rhs.mirror
|
||||
&& supersub == rhs.supersub
|
||||
&& angle == rhs.angle;
|
||||
}
|
||||
};
|
||||
@@ -296,6 +298,7 @@ namespace std
|
||||
^ hash<int>()( k.fakeItalic )
|
||||
^ hash<int>()( k.fakeBold )
|
||||
^ hash<int>()( k.mirror )
|
||||
^ hash<int>()( k.supersub )
|
||||
^ hash<int>()( k.angle.AsTenthsOfADegree() );
|
||||
}
|
||||
};
|
||||
@@ -312,11 +315,10 @@ VECTOR2I OUTLINE_FONT::getTextAsGlyphsUnlocked( BOX2I* aBBox,
|
||||
VECTOR2D glyphSize = aSize;
|
||||
FT_Face face = m_face;
|
||||
double scaler = faceSize();
|
||||
bool supersub = IsSuperscript( aTextStyle ) || IsSubscript( aTextStyle );
|
||||
|
||||
if( IsSubscript( aTextStyle ) || IsSuperscript( aTextStyle ) )
|
||||
{
|
||||
if( supersub )
|
||||
scaler = subscriptSize();
|
||||
}
|
||||
|
||||
// set glyph resolution so that FT_Load_Glyph() results are good enough for decomposing
|
||||
FT_Set_Char_Size( face, 0, scaler, GLYPH_RESOLUTION, 0 );
|
||||
@@ -355,7 +357,7 @@ VECTOR2I OUTLINE_FONT::getTextAsGlyphsUnlocked( BOX2I* aBBox,
|
||||
if( aGlyphs )
|
||||
{
|
||||
GLYPH_CACHE_KEY key = { face, glyphInfo[i].codepoint, scaler, m_forDrawingSheet,
|
||||
m_fakeItal, m_fakeBold, aMirror, aAngle };
|
||||
m_fakeItal, m_fakeBold, aMirror, supersub, aAngle };
|
||||
GLYPH_DATA& glyphData = s_glyphCache[ key ];
|
||||
|
||||
if( glyphData.m_Contours.empty() )
|
||||
|
||||
@@ -143,8 +143,15 @@ bool HTTP_LIB_CONNECTION::syncCategories()
|
||||
{
|
||||
HTTP_LIB_CATEGORY category;
|
||||
|
||||
category.id = item.value()["id"].get<std::string>();
|
||||
category.name = item.value()["name"].get<std::string>();
|
||||
auto& value = item.value();
|
||||
category.id = value["id"].get<std::string>();
|
||||
category.name = value["name"].get<std::string>();
|
||||
|
||||
if( value.contains( "description" ) )
|
||||
{
|
||||
category.description = value["description"].get<std::string>();
|
||||
m_categoryDescriptions[category.name] = category.description;
|
||||
}
|
||||
|
||||
m_categories.push_back( category );
|
||||
}
|
||||
@@ -179,12 +186,12 @@ bool HTTP_LIB_CONNECTION::SelectOne( const std::string& aPartID, HTTP_LIB_PART&
|
||||
if( m_cachedParts.find( aPartID ) != m_cachedParts.end() )
|
||||
{
|
||||
// check if it's outdated, if so re-fetch
|
||||
if( std::difftime( std::time( nullptr ), m_cachedParts[aPartID].lastCached ) < m_source.timeout_parts )
|
||||
if( std::difftime( std::time( nullptr ), m_cachedParts[aPartID].lastCached )
|
||||
< m_source.timeout_parts )
|
||||
{
|
||||
aFetchedPart = m_cachedParts[aPartID];
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::string res = "";
|
||||
@@ -203,7 +210,7 @@ bool HTTP_LIB_CONNECTION::SelectOne( const std::string& aPartID, HTTP_LIB_PART&
|
||||
return false;
|
||||
}
|
||||
|
||||
nlohmann::json response = nlohmann::json::parse( res );
|
||||
nlohmann::ordered_json response = nlohmann::ordered_json::parse( res );
|
||||
std::string key = "";
|
||||
std::string value = "";
|
||||
|
||||
@@ -252,6 +259,9 @@ bool HTTP_LIB_CONNECTION::SelectOne( const std::string& aPartID, HTTP_LIB_PART&
|
||||
aFetchedPart.exclude_from_sim = boolFromString( exclude, false );
|
||||
}
|
||||
|
||||
// remove previously loaded fields
|
||||
aFetchedPart.fields.clear();
|
||||
|
||||
// Extract available fields
|
||||
for( const auto& field : response.at( "fields" ).items() )
|
||||
{
|
||||
@@ -273,10 +283,8 @@ bool HTTP_LIB_CONNECTION::SelectOne( const std::string& aPartID, HTTP_LIB_PART&
|
||||
}
|
||||
|
||||
// Add field to fields list
|
||||
if( key.length() )
|
||||
{
|
||||
aFetchedPart.fields[key] = std::make_tuple( value, visible );
|
||||
}
|
||||
aFetchedPart.fields.push_back(
|
||||
std::make_pair( key, std::make_tuple( value, visible ) ) );
|
||||
}
|
||||
}
|
||||
catch( const std::exception& e )
|
||||
@@ -297,7 +305,7 @@ bool HTTP_LIB_CONNECTION::SelectOne( const std::string& aPartID, HTTP_LIB_PART&
|
||||
}
|
||||
|
||||
|
||||
bool HTTP_LIB_CONNECTION::SelectAll( const HTTP_LIB_CATEGORY& aCategory,
|
||||
bool HTTP_LIB_CONNECTION::SelectAll( const HTTP_LIB_CATEGORY& aCategory,
|
||||
std::vector<HTTP_LIB_PART>& aParts )
|
||||
{
|
||||
if( !IsValidEndpoint() )
|
||||
@@ -319,8 +327,6 @@ bool HTTP_LIB_CONNECTION::SelectAll( const HTTP_LIB_CATEGORY& aCategory,
|
||||
res = curl->GetBuffer();
|
||||
|
||||
nlohmann::json response = nlohmann::json::parse( res );
|
||||
std::string key = "";
|
||||
std::string value = "";
|
||||
|
||||
for( nlohmann::json& item : response )
|
||||
{
|
||||
@@ -332,7 +338,8 @@ bool HTTP_LIB_CONNECTION::SelectAll( const HTTP_LIB_CATEGORY& aCategory,
|
||||
if( item.contains( "description" ) )
|
||||
{
|
||||
// At this point we don't display anything so just set it to false
|
||||
part.fields["description"] = std::make_tuple( item.at( "description" ), false );
|
||||
part.fields.push_back( std::make_pair(
|
||||
"description", std::make_tuple( item.at( "description" ), false ) ) );
|
||||
}
|
||||
|
||||
// API might not want to return an optional name.
|
||||
|
||||
@@ -128,16 +128,19 @@ void GRAPHICS_IMPORTER_BUFFER::ImportTo( GRAPHICS_IMPORTER& aImporter )
|
||||
// in the KiCad drawing area
|
||||
else if( aImporter.GetImportOffsetMM() == VECTOR2D( 0, 0 ) )
|
||||
{
|
||||
VECTOR2D offset = boundingBox.GetOrigin();
|
||||
aImporter.SetImportOffsetMM( -offset );
|
||||
if( boundingBox.GetRight() > std::numeric_limits<int>::max()
|
||||
|| boundingBox.GetBottom() > std::numeric_limits<int>::max()
|
||||
|| boundingBox.GetLeft() < std::numeric_limits<int>::min()
|
||||
|| boundingBox.GetTop() < std::numeric_limits<int>::min() )
|
||||
{
|
||||
VECTOR2D offset = boundingBox.GetOrigin();
|
||||
aImporter.SetImportOffsetMM( -offset );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
VECTOR2D bbox_origin = boundingBox.GetOrigin();
|
||||
aImporter.SetImportOffsetMM( -bbox_origin + aImporter.GetImportOffsetMM() );
|
||||
|
||||
double total_scale_x = aImporter.GetScale().x * aImporter.GetMillimeterToIuFactor();
|
||||
double total_scale_y = aImporter.GetScale().y * aImporter.GetMillimeterToIuFactor();
|
||||
double total_scale_x = aImporter.GetScale().x * aImporter.GetMillimeterToIuFactor();
|
||||
double total_scale_y = aImporter.GetScale().y * aImporter.GetMillimeterToIuFactor();
|
||||
|
||||
double max_offset_x =
|
||||
( aImporter.GetImportOffsetMM().x + boundingBox.GetRight() ) * total_scale_x;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
#include <functional>
|
||||
#include <cstdio>
|
||||
#include <array>
|
||||
|
||||
constexpr auto DEFAULT_ALIGNMENT = ETEXT::BOTTOM_LEFT;
|
||||
|
||||
@@ -190,10 +191,10 @@ ECOORD::ECOORD( const wxString& aValue, enum ECOORD::EAGLE_UNIT aUnit )
|
||||
{
|
||||
// This array is used to adjust the fraction part value basing on the number of digits
|
||||
// in the fraction.
|
||||
constexpr int DIVIDERS[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
|
||||
constexpr unsigned int DIVIDERS_MAX_IDX = sizeof( DIVIDERS ) / sizeof( DIVIDERS[0] ) - 1;
|
||||
static std::array<int, 9> DIVIDERS = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
|
||||
|
||||
int integer, fraction, pre_fraction, post_fraction;
|
||||
int integer, pre_fraction, post_fraction;
|
||||
long long unsigned fraction;
|
||||
|
||||
// The following check is needed to handle correctly negative fractions where the integer
|
||||
// part == 0.
|
||||
@@ -201,7 +202,7 @@ ECOORD::ECOORD( const wxString& aValue, enum ECOORD::EAGLE_UNIT aUnit )
|
||||
|
||||
// %n is used to find out how many digits contains the fraction part, e.g. 0.001 contains 3
|
||||
// digits.
|
||||
int ret = sscanf( aValue.c_str(), "%d.%n%d%n", &integer, &pre_fraction, &fraction,
|
||||
int ret = sscanf( aValue.c_str(), "%d.%n%llu%n", &integer, &pre_fraction, &fraction,
|
||||
&post_fraction );
|
||||
|
||||
if( ret == 0 )
|
||||
@@ -217,11 +218,11 @@ ECOORD::ECOORD( const wxString& aValue, enum ECOORD::EAGLE_UNIT aUnit )
|
||||
|
||||
// adjust the number of digits if necessary as we cannot handle anything smaller than
|
||||
// nanometers (rounding).
|
||||
if( (unsigned) digits > DIVIDERS_MAX_IDX )
|
||||
if( digits >= static_cast<int>( DIVIDERS.size() ) )
|
||||
{
|
||||
int diff = digits - DIVIDERS_MAX_IDX;
|
||||
digits = DIVIDERS_MAX_IDX;
|
||||
fraction /= DIVIDERS[diff];
|
||||
long long unsigned denom = pow( 10, digits - DIVIDERS.size() + 1 );
|
||||
digits = DIVIDERS.size() - 1;
|
||||
fraction /= denom;
|
||||
}
|
||||
|
||||
int frac_value = ConvertToNm( fraction, aUnit ) / DIVIDERS[digits];
|
||||
|
||||
@@ -118,7 +118,8 @@ static int progressinfo( void* aProgress, double aDLtotal, double aDLnow, double
|
||||
|
||||
|
||||
KICAD_CURL_EASY::KICAD_CURL_EASY() :
|
||||
m_headers( nullptr )
|
||||
m_headers( nullptr ),
|
||||
m_curlSharedLock( KICAD_CURL::Mutex() )
|
||||
{
|
||||
m_CURL = curl_easy_init();
|
||||
|
||||
@@ -194,12 +195,6 @@ KICAD_CURL_EASY::~KICAD_CURL_EASY()
|
||||
|
||||
int KICAD_CURL_EASY::Perform()
|
||||
{
|
||||
std::shared_lock lock( KICAD_CURL::Mutex(), std::try_to_lock );
|
||||
|
||||
// If can't lock, we should be in the process of tearing down.
|
||||
if( !lock )
|
||||
return CURLE_ABORTED_BY_CALLBACK;
|
||||
|
||||
if( m_headers )
|
||||
curl_easy_setopt( m_CURL, CURLOPT_HTTPHEADER, m_headers );
|
||||
|
||||
|
||||
@@ -281,17 +281,21 @@ void LIB_TREE_MODEL_ADAPTER::UpdateSearchString( const wxString& aSearch, bool a
|
||||
|
||||
m_tree.ResetScore();
|
||||
|
||||
wxStringTokenizer tokenizer( aSearch );
|
||||
bool firstTerm = true;
|
||||
// Don't cause KiCad to hang if someone accidentally pastes the PCB or schematic into
|
||||
// the search box.
|
||||
constexpr int MAX_TERMS = 100;
|
||||
|
||||
while( tokenizer.HasMoreTokens() )
|
||||
wxStringTokenizer tokenizer( aSearch );
|
||||
int termCount = 0;
|
||||
|
||||
while( tokenizer.HasMoreTokens() && termCount < MAX_TERMS )
|
||||
{
|
||||
// First search for the full token, in case it appears in a search string
|
||||
wxString term = tokenizer.GetNextToken().Lower();
|
||||
EDA_COMBINED_MATCHER termMatcher( term, CTX_LIBITEM );
|
||||
|
||||
m_tree.UpdateScore( &termMatcher, wxEmptyString, firstTerm ? m_filter : nullptr );
|
||||
firstTerm = false;
|
||||
m_tree.UpdateScore( &termMatcher, wxEmptyString, m_filter );
|
||||
termCount++;
|
||||
|
||||
if( term.Contains( ":" ) )
|
||||
{
|
||||
@@ -304,7 +308,7 @@ void LIB_TREE_MODEL_ADAPTER::UpdateSearchString( const wxString& aSearch, bool a
|
||||
}
|
||||
}
|
||||
|
||||
if( firstTerm )
|
||||
if( termCount == 0 )
|
||||
{
|
||||
// No terms processed; just run the filter
|
||||
m_tree.UpdateScore( nullptr, wxEmptyString, m_filter );
|
||||
|
||||
@@ -1092,3 +1092,35 @@ GAL_SET GAL_SET::DefaultVisible()
|
||||
static const GAL_SET saved( visible, arrayDim( visible ) );
|
||||
return saved;
|
||||
}
|
||||
|
||||
|
||||
/// The layers the user has control over the visibility of, stored in project local settings
|
||||
GAL_SET GAL_SET::UserVisbilityLayers()
|
||||
{
|
||||
static const GAL_LAYER_ID layers[] = {
|
||||
LAYER_TRACKS,
|
||||
LAYER_VIAS,
|
||||
LAYER_PADS,
|
||||
LAYER_ZONES,
|
||||
LAYER_DRAW_BITMAPS,
|
||||
LAYER_FOOTPRINTS_FR,
|
||||
LAYER_FOOTPRINTS_BK,
|
||||
LAYER_PADS_TH,
|
||||
LAYER_FP_VALUES,
|
||||
LAYER_FP_REFERENCES,
|
||||
LAYER_FP_TEXT,
|
||||
LAYER_HIDDEN_TEXT,
|
||||
LAYER_ANCHOR,
|
||||
LAYER_RATSNEST,
|
||||
LAYER_DRC_WARNING,
|
||||
LAYER_DRC_ERROR,
|
||||
LAYER_DRC_EXCLUSION,
|
||||
LAYER_LOCKED_ITEM_SHADOW,
|
||||
LAYER_CONFLICTS_SHADOW,
|
||||
LAYER_DRAWINGSHEET,
|
||||
LAYER_GRID,
|
||||
};
|
||||
|
||||
static const GAL_SET saved( layers, arrayDim( layers ) );
|
||||
return saved;
|
||||
}
|
||||
|
||||
@@ -777,6 +777,14 @@ void PDF_PLOTTER::ClosePage()
|
||||
VECTOR2D retval = VECTOR2D( aCoord ) * PTsPERMIL / ( m_IUsPerDecimil * 10 );
|
||||
// PDF y=0 is at bottom of page, invert coordinate
|
||||
retval.y = psPaperSize.y - retval.y;
|
||||
|
||||
// The pdf plot can be mirrored (from left to right). So mirror the
|
||||
// x coordinate if m_plotMirror is set
|
||||
if( m_plotMirror )
|
||||
{
|
||||
retval.x = ( psPaperSize.x - retval.x );
|
||||
}
|
||||
|
||||
return retval;
|
||||
};
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include <wildcards_and_files_ext.h>
|
||||
#include <wxstream_helper.h>
|
||||
#include <wx/log.h>
|
||||
#include <kiplatform/io.h>
|
||||
|
||||
|
||||
#define ZipFileExtension wxT( "zip" )
|
||||
@@ -156,10 +155,7 @@ bool PROJECT_ARCHIVER::Archive( const wxString& aSrcDir, const wxString& aDestFi
|
||||
wxString msg;
|
||||
wxString oldCwd = wxGetCwd();
|
||||
|
||||
wxFileName sourceDir( aSrcDir );
|
||||
KIPLATFORM::IO::LongPathAdjustment( sourceDir );
|
||||
|
||||
wxSetWorkingDirectory( sourceDir.GetFullPath() );
|
||||
wxSetWorkingDirectory( aSrcDir );
|
||||
|
||||
wxFFileOutputStream ostream( aDestFile );
|
||||
|
||||
@@ -178,12 +174,12 @@ bool PROJECT_ARCHIVER::Archive( const wxString& aSrcDir, const wxString& aDestFi
|
||||
wxArrayString files;
|
||||
|
||||
for( unsigned ii = 0; ii < arrayDim( extensionList ); ii++ )
|
||||
wxDir::GetAllFiles( sourceDir.GetFullPath(), &files, extensionList[ii], wxDIR_FILES | wxDIR_DIRS );
|
||||
wxDir::GetAllFiles( aSrcDir, &files, extensionList[ii], wxDIR_FILES | wxDIR_DIRS );
|
||||
|
||||
if( aIncludeExtraFiles )
|
||||
{
|
||||
for( unsigned ii = 0; ii < arrayDim( extraExtensionList ); ii++ )
|
||||
wxDir::GetAllFiles( sourceDir.GetFullPath(), &files, extraExtensionList[ii], wxDIR_FILES | wxDIR_DIRS );
|
||||
wxDir::GetAllFiles( aSrcDir, &files, extraExtensionList[ii], wxDIR_FILES | wxDIR_DIRS );
|
||||
}
|
||||
|
||||
for( unsigned ii = 0; ii < files.GetCount(); ++ii )
|
||||
@@ -193,7 +189,6 @@ bool PROJECT_ARCHIVER::Archive( const wxString& aSrcDir, const wxString& aDestFi
|
||||
wxFileName package( files[ ii ] );
|
||||
package.MakeRelativeTo( aSrcDir );
|
||||
package.SetExt( wxS( "pkg" ) );
|
||||
KIPLATFORM::IO::LongPathAdjustment( package );
|
||||
|
||||
if( package.Exists() )
|
||||
files.push_back( package.GetFullName() );
|
||||
@@ -219,13 +214,11 @@ bool PROJECT_ARCHIVER::Archive( const wxString& aSrcDir, const wxString& aDestFi
|
||||
wxFileSystem fsfile;
|
||||
|
||||
wxFileName curr_fn( files[ii] );
|
||||
KIPLATFORM::IO::LongPathAdjustment( curr_fn );
|
||||
curr_fn.MakeRelativeTo( sourceDir.GetFullPath() );
|
||||
|
||||
curr_fn.MakeRelativeTo( aSrcDir );
|
||||
currFilename = curr_fn.GetFullPath();
|
||||
|
||||
// Read input file and add it to the zip file:
|
||||
wxFSFile* infile = fsfile.OpenFile( currFilename );
|
||||
wxFSFile* infile = fsfile.OpenFile( wxFileSystem::FileNameToURL( curr_fn ) );
|
||||
|
||||
if( infile )
|
||||
{
|
||||
|
||||
@@ -41,7 +41,8 @@ PROJECT_FILE::PROJECT_FILE( const wxString& aFullPath ) :
|
||||
m_BoardSettings(),
|
||||
m_sheets(),
|
||||
m_boards(),
|
||||
m_project( nullptr )
|
||||
m_project( nullptr ),
|
||||
m_wasMigrated( false )
|
||||
{
|
||||
// Keep old files around
|
||||
m_deleteLegacyAfterMigration = false;
|
||||
@@ -588,7 +589,14 @@ bool PROJECT_FILE::SaveToFile( const wxString& aDirectory, bool aForce )
|
||||
|
||||
Set( "meta.filename", m_project->GetProjectName() + "." + FILEEXT::ProjectFileExtension );
|
||||
|
||||
return JSON_SETTINGS::SaveToFile( aDirectory, aForce );
|
||||
// Even if parameters were not modified, we should resave after migration
|
||||
bool force = aForce || m_wasMigrated;
|
||||
|
||||
// If we're actually going ahead and doing the save, the flag that keeps code from doing the save
|
||||
// should be cleared at this point
|
||||
m_wasMigrated = false;
|
||||
|
||||
return JSON_SETTINGS::SaveToFile( aDirectory, force );
|
||||
}
|
||||
|
||||
|
||||
@@ -630,6 +638,10 @@ bool PROJECT_FILE::SaveAs( const wxString& aDirectory, const wxString& aFile )
|
||||
updatePathByPtr( "schematic.ngspice.workbook_filename" );
|
||||
updatePathByPtr( "pcbnew.page_layout_descr_file" );
|
||||
|
||||
// If we're actually going ahead and doing the save, the flag that keeps code from doing the save
|
||||
// should be cleared at this point
|
||||
m_wasMigrated = false;
|
||||
|
||||
// While performing Save As, we have already checked that we can write to the directory
|
||||
// so don't carry the previous flag
|
||||
SetReadOnly( false );
|
||||
|
||||
@@ -42,7 +42,8 @@ PROJECT_LOCAL_SETTINGS::PROJECT_LOCAL_SETTINGS( PROJECT* aProject, const wxStrin
|
||||
m_ZoneOpacity( 0.6 ),
|
||||
m_ImageOpacity( 0.6 ),
|
||||
m_SelectionFilter(),
|
||||
m_project( aProject )
|
||||
m_project( aProject ),
|
||||
m_wasMigrated( false )
|
||||
{
|
||||
// Keep old files around
|
||||
m_deleteLegacyAfterMigration = false;
|
||||
@@ -77,20 +78,23 @@ PROJECT_LOCAL_SETTINGS::PROJECT_LOCAL_SETTINGS( PROJECT* aProject, const wxStrin
|
||||
return;
|
||||
}
|
||||
|
||||
m_VisibleItems.reset();
|
||||
m_VisibleItems &= ~GAL_SET::UserVisbilityLayers();
|
||||
GAL_SET visible;
|
||||
|
||||
for( const nlohmann::json& entry : aVal )
|
||||
{
|
||||
try
|
||||
{
|
||||
int i = entry.get<int>();
|
||||
m_VisibleItems.set( i );
|
||||
visible.set( i );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
// Non-integer or out of range entry in the array; ignore
|
||||
}
|
||||
}
|
||||
|
||||
m_VisibleItems |= GAL_SET::UserVisbilityLayers() & visible;
|
||||
},
|
||||
{} ) );
|
||||
|
||||
@@ -272,6 +276,8 @@ PROJECT_LOCAL_SETTINGS::PROJECT_LOCAL_SETTINGS( PROJECT* aProject, const wxStrin
|
||||
{
|
||||
At( "board" ).erase( "visible_items" );
|
||||
}
|
||||
|
||||
m_wasMigrated = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -330,6 +336,7 @@ PROJECT_LOCAL_SETTINGS::PROJECT_LOCAL_SETTINGS( PROJECT* aProject, const wxStrin
|
||||
}
|
||||
|
||||
At( "board" )["visible_items"] = visible;
|
||||
m_wasMigrated = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -354,7 +361,14 @@ bool PROJECT_LOCAL_SETTINGS::SaveToFile( const wxString& aDirectory, bool aForce
|
||||
|
||||
Set( "meta.filename", m_project->GetProjectName() + "." + FILEEXT::ProjectLocalSettingsFileExtension );
|
||||
|
||||
return JSON_SETTINGS::SaveToFile( aDirectory, aForce );
|
||||
// Even if parameters were not modified, we should resave after migration
|
||||
bool force = aForce || m_wasMigrated;
|
||||
|
||||
// If we're actually going ahead and doing the save, the flag that keeps code from doing the save
|
||||
// should be cleared at this point
|
||||
m_wasMigrated = false;
|
||||
|
||||
return JSON_SETTINGS::SaveToFile( aDirectory, force );
|
||||
}
|
||||
|
||||
|
||||
@@ -363,6 +377,10 @@ bool PROJECT_LOCAL_SETTINGS::SaveAs( const wxString& aDirectory, const wxString&
|
||||
Set( "meta.filename", aFile + "." + FILEEXT::ProjectLocalSettingsFileExtension );
|
||||
SetFilename( aFile );
|
||||
|
||||
// If we're actually going ahead and doing the save, the flag that keeps code from doing the save
|
||||
// should be cleared at this point
|
||||
m_wasMigrated = false;
|
||||
|
||||
return JSON_SETTINGS::SaveToFile( aDirectory, true );
|
||||
}
|
||||
|
||||
|
||||
@@ -540,8 +540,12 @@ wxValidator* PGPROPERTY_ANGLE::DoGetValidator() const
|
||||
|
||||
wxSize PGPROPERTY_COLORENUM::OnMeasureImage( int aItem ) const
|
||||
{
|
||||
// TODO(JE) calculate size from window metrics?
|
||||
return wxSize( 16, 12 );
|
||||
wxSize size( 16, -1 );
|
||||
|
||||
if( wxPropertyGrid* pg = GetGrid() )
|
||||
size = pg->FromDIP( size );
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -79,6 +79,7 @@ JSON_SETTINGS::JSON_SETTINGS( const wxString& aFilename, SETTINGS_LOC aLocation,
|
||||
m_deleteLegacyAfterMigration( true ),
|
||||
m_resetParamsIfMissing( true ),
|
||||
m_schemaVersion( aSchemaVersion ),
|
||||
m_isFutureFormat( false ),
|
||||
m_manager( nullptr )
|
||||
{
|
||||
m_internals = std::make_unique<JSON_SETTINGS_INTERNALS>();
|
||||
@@ -325,6 +326,7 @@ bool JSON_SETTINGS::LoadFromFile( const wxString& aDirectory )
|
||||
wxLogTrace( traceSettings,
|
||||
wxT( "%s: warning: file version %d is newer than latest (%d)" ),
|
||||
GetFullFilename(), filever, m_schemaVersion );
|
||||
m_isFutureFormat = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include <dialogs/dialog_migrate_settings.h>
|
||||
#include <gestfich.h>
|
||||
#include <kiplatform/environment.h>
|
||||
#include <kiplatform/io.h>
|
||||
#include <kiway.h>
|
||||
#include <lockfile.h>
|
||||
#include <macros.h>
|
||||
@@ -156,6 +155,13 @@ void SETTINGS_MANAGER::Save()
|
||||
if( dynamic_cast<COLOR_SETTINGS*>( settings.get() ) )
|
||||
continue;
|
||||
|
||||
// Never automatically save project settings, caller should use SaveProject or UnloadProject
|
||||
if( dynamic_cast<PROJECT_FILE*>( settings.get() )
|
||||
|| dynamic_cast<PROJECT_LOCAL_SETTINGS*>( settings.get() ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
settings->SaveToFile( GetPathForSettingsFile( settings.get() ) );
|
||||
}
|
||||
}
|
||||
@@ -1179,6 +1185,9 @@ bool SETTINGS_MANAGER::unloadProjectFile( PROJECT* aProject, bool aSave )
|
||||
|
||||
PROJECT_FILE* file = m_project_files[name];
|
||||
|
||||
if( !file->ShouldAutoSave() )
|
||||
aSave = false;
|
||||
|
||||
auto it = std::find_if( m_settings.begin(), m_settings.end(),
|
||||
[&file]( const std::unique_ptr<JSON_SETTINGS>& aPtr )
|
||||
{
|
||||
@@ -1189,7 +1198,9 @@ bool SETTINGS_MANAGER::unloadProjectFile( PROJECT* aProject, bool aSave )
|
||||
{
|
||||
wxString projectPath = GetPathForSettingsFile( it->get() );
|
||||
|
||||
FlushAndRelease( &aProject->GetLocalSettings(), aSave );
|
||||
bool saveLocalSettings = aSave && aProject->GetLocalSettings().ShouldAutoSave();
|
||||
|
||||
FlushAndRelease( &aProject->GetLocalSettings(), saveLocalSettings );
|
||||
|
||||
if( aSave )
|
||||
( *it )->SaveToFile( projectPath );
|
||||
@@ -1223,7 +1234,6 @@ bool SETTINGS_MANAGER::BackupProject( REPORTER& aReporter ) const
|
||||
target.SetPath( GetProjectBackupsPath() );
|
||||
target.SetName( fileName );
|
||||
target.SetExt( FILEEXT::ArchiveFileExtension );
|
||||
KIPLATFORM::IO::LongPathAdjustment( target );
|
||||
|
||||
if( !target.DirExists() && !wxMkdir( target.GetPath() ) )
|
||||
{
|
||||
|
||||
@@ -171,7 +171,7 @@ class TEXT_BUTTON_SYMBOL_CHOOSER : public wxComboCtrl
|
||||
public:
|
||||
TEXT_BUTTON_SYMBOL_CHOOSER( wxWindow* aParent, DIALOG_SHIM* aParentDlg,
|
||||
const wxString& aPreselect ) :
|
||||
wxComboCtrl( aParent ),
|
||||
wxComboCtrl( aParent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 0, 0 ) ),
|
||||
m_dlg( aParentDlg ),
|
||||
m_preselect( aPreselect )
|
||||
{
|
||||
@@ -233,7 +233,7 @@ class TEXT_BUTTON_FP_CHOOSER : public wxComboCtrl
|
||||
public:
|
||||
TEXT_BUTTON_FP_CHOOSER( wxWindow* aParent, DIALOG_SHIM* aParentDlg,
|
||||
const wxString& aSymbolNetlist, const wxString& aPreselect ) :
|
||||
wxComboCtrl( aParent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
|
||||
wxComboCtrl( aParent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 0, 0 ),
|
||||
wxTE_PROCESS_ENTER | wxBORDER_NONE ),
|
||||
m_dlg( aParentDlg ),
|
||||
m_preselect( aPreselect ),
|
||||
@@ -324,7 +324,7 @@ class TEXT_BUTTON_URL : public wxComboCtrl
|
||||
{
|
||||
public:
|
||||
TEXT_BUTTON_URL( wxWindow* aParent, DIALOG_SHIM* aParentDlg, SEARCH_STACK* aSearchStack ) :
|
||||
wxComboCtrl( aParent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
|
||||
wxComboCtrl( aParent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(0, 0),
|
||||
wxTE_PROCESS_ENTER | wxBORDER_NONE ),
|
||||
m_dlg( aParentDlg ),
|
||||
m_searchStack( aSearchStack )
|
||||
@@ -379,7 +379,7 @@ public:
|
||||
wxString* aCurrentDir, const wxString& aFileFilter = wxEmptyString,
|
||||
bool aNormalize = false,
|
||||
const wxString& aNormalizeBasePath = wxEmptyString ) :
|
||||
wxComboCtrl( aParent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
|
||||
wxComboCtrl( aParent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 0, 0 ),
|
||||
wxTE_PROCESS_ENTER | wxBORDER_NONE ),
|
||||
m_dlg( aParentDlg ),
|
||||
m_grid( aGrid ),
|
||||
@@ -399,7 +399,7 @@ public:
|
||||
std::function<wxString( WX_GRID* grid, int row )> aFileFilterFn,
|
||||
bool aNormalize = false,
|
||||
const wxString& aNormalizeBasePath = wxEmptyString ) :
|
||||
wxComboCtrl( aParent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
|
||||
wxComboCtrl( aParent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 0, 0 ),
|
||||
wxTE_PROCESS_ENTER | wxBORDER_NONE ),
|
||||
m_dlg( aParentDlg ),
|
||||
m_grid( aGrid ),
|
||||
|
||||
@@ -133,7 +133,7 @@ void GRID_CELL_STC_EDITOR::SetSize( const wxRect& aRect )
|
||||
|
||||
void GRID_CELL_STC_EDITOR::Create( wxWindow* aParent, wxWindowID aId, wxEvtHandler* aEventHandler )
|
||||
{
|
||||
m_control = new wxStyledTextCtrl( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
||||
m_control = new wxStyledTextCtrl( aParent, wxID_ANY, wxDefaultPosition, wxSize( 0, 0 ),
|
||||
wxBORDER_NONE );
|
||||
|
||||
stc_ctrl()->SetTabIndents( false );
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
|
||||
BEGIN_EVENT_TABLE( EDA_MSG_PANEL, wxPanel )
|
||||
EVT_DPI_CHANGED( EDA_MSG_PANEL::OnDPIChanged )
|
||||
EVT_PAINT( EDA_MSG_PANEL::OnPaint )
|
||||
END_EVENT_TABLE()
|
||||
|
||||
@@ -50,7 +51,9 @@ EDA_MSG_PANEL::EDA_MSG_PANEL( wxWindow* aParent, int aId, const wxPoint& aPositi
|
||||
|
||||
m_last_x = 0;
|
||||
|
||||
m_fontSize = GetTextExtent( wxT( "W" ) );
|
||||
updateFontSize();
|
||||
|
||||
InvalidateBestSize();
|
||||
}
|
||||
|
||||
|
||||
@@ -59,16 +62,31 @@ EDA_MSG_PANEL::~EDA_MSG_PANEL()
|
||||
}
|
||||
|
||||
|
||||
int EDA_MSG_PANEL::GetRequiredHeight( wxWindow* aWindow )
|
||||
void EDA_MSG_PANEL::updateFontSize()
|
||||
{
|
||||
wxSize fontSizeInPixels;
|
||||
wxWindowDC dc( aWindow );
|
||||
wxFont font = KIUI::GetControlFont( this );
|
||||
GetTextExtent( wxT( "W" ), &m_fontSize.x, &m_fontSize.y, 0, 0, &font );
|
||||
}
|
||||
|
||||
dc.SetFont( KIUI::GetControlFont( aWindow ) );
|
||||
dc.GetTextExtent( wxT( "W" ), &fontSizeInPixels.x, &fontSizeInPixels.y );
|
||||
|
||||
// make space for two rows of text plus a number of pixels between them.
|
||||
return 2 * fontSizeInPixels.y + 0;
|
||||
wxSize EDA_MSG_PANEL::DoGetBestSize() const
|
||||
{
|
||||
return wxSize( wxDefaultCoord, 2 * m_fontSize.y + 0 );
|
||||
}
|
||||
|
||||
|
||||
wxSize EDA_MSG_PANEL::DoGetBestClientSize() const
|
||||
{
|
||||
return wxPanel::DoGetBestClientSize();
|
||||
}
|
||||
|
||||
|
||||
void EDA_MSG_PANEL::OnDPIChanged( wxDPIChangedEvent& aEvent )
|
||||
{
|
||||
updateFontSize();
|
||||
InvalidateBestSize();
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -58,12 +58,11 @@ WX_INFOBAR::WX_INFOBAR( wxWindow* aParent, wxAuiManager* aMgr, wxWindowID aWinid
|
||||
{
|
||||
m_showTimer = new wxTimer( this, ID_CLOSE_INFOBAR );
|
||||
|
||||
wxColour fg, bg;
|
||||
KIPLATFORM::UI::GetInfoBarColours( fg, bg );
|
||||
SetBackgroundColour( bg );
|
||||
SetForegroundColour( fg );
|
||||
#ifdef __WXMAC__
|
||||
// wxWidgets hard-codes wxSYS_COLOUR_INFOBK to { 0xFF, 0xFF, 0xD3 } on Mac.
|
||||
if( KIPLATFORM::UI::IsDarkTheme() )
|
||||
SetBackgroundColour( wxColour( 28, 27, 20 ) );
|
||||
else
|
||||
SetBackgroundColour( wxColour( 255, 249, 189 ) );
|
||||
|
||||
// Infobar is broken on Mac without the effects
|
||||
SetShowHideEffects( wxSHOW_EFFECT_ROLL_TO_BOTTOM, wxSHOW_EFFECT_ROLL_TO_TOP );
|
||||
|
||||
@@ -885,12 +885,16 @@ void DIALOG_ERC::OnSeverity( wxCommandEvent& aEvent )
|
||||
void DIALOG_ERC::deleteAllMarkers( bool aIncludeExclusions )
|
||||
{
|
||||
// Clear current selection list to avoid selection of deleted items
|
||||
// Freeze to avoid repainting the dialog, which can cause a RePaint()
|
||||
// of the screen as well
|
||||
Freeze();
|
||||
m_parent->GetToolManager()->RunAction( EE_ACTIONS::clearSelection );
|
||||
|
||||
m_markerTreeModel->DeleteItems( false, aIncludeExclusions, false );
|
||||
|
||||
SCH_SCREENS screens( m_parent->Schematic().Root() );
|
||||
screens.DeleteAllMarkers( MARKER_BASE::MARKER_ERC, aIncludeExclusions );
|
||||
Thaw();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -352,6 +352,8 @@ bool DIALOG_SHEET_PROPERTIES::TransferDataFromWindow()
|
||||
{
|
||||
if( clearFileName )
|
||||
currentScreen->SetFileName( wxEmptyString );
|
||||
else
|
||||
m_fields->at( SHEETFILENAME ).SetText( oldFilename );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -561,6 +563,7 @@ bool DIALOG_SHEET_PROPERTIES::onSheetFilenameChanged( const wxString& aNewFilena
|
||||
if( useScreen || loadFromFile ) // Load from existing file.
|
||||
{
|
||||
clearAnnotation = true;
|
||||
oldScreen = m_sheet->GetScreen();
|
||||
|
||||
if( !IsOK( this, wxString::Format( _( "Change '%s' link from '%s' to '%s'?" ),
|
||||
newAbsoluteFilename,
|
||||
|
||||
@@ -836,12 +836,26 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::loadLibrary( const wxString& aLibraryP
|
||||
|
||||
wxArrayString modelNames;
|
||||
|
||||
bool modelNameExists = false;
|
||||
|
||||
for( const auto& [name, model] : library()->GetModels() )
|
||||
{
|
||||
modelNames.Add( name );
|
||||
|
||||
if( name == modelName )
|
||||
modelNameExists = true;
|
||||
}
|
||||
|
||||
m_modelNameChoice->Clear();
|
||||
m_modelNameChoice->Append( modelNames );
|
||||
|
||||
if( !modelNameExists )
|
||||
{
|
||||
m_infoBar->ShowMessage(
|
||||
wxString::Format( _( "No model named '%s' in '%s'." ), modelName, aLibraryPath ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( isIbisLoaded() )
|
||||
{
|
||||
wxArrayString emptyArray;
|
||||
|
||||
@@ -471,6 +471,27 @@ bool DIALOG_SYMBOL_REMAP::backupProject( REPORTER& aReporter )
|
||||
errorMsg += tmp;
|
||||
}
|
||||
|
||||
// Back up the old (2007) cache library.
|
||||
srcFileName.SetPath( Prj().GetProjectPath() );
|
||||
srcFileName.SetName( Prj().GetProjectName() + wxS( ".cache" ) );
|
||||
srcFileName.SetExt( FILEEXT::LegacySymbolLibFileExtension );
|
||||
|
||||
destFileName = srcFileName;
|
||||
destFileName.SetName( destFileName.GetName() + timeStamp );
|
||||
destFileName.AppendDir( backupFolder );
|
||||
|
||||
aReporter.Report( wxString::Format( _( "Backing up file '%s' to '%s'." ),
|
||||
srcFileName.GetFullPath(),
|
||||
destFileName.GetFullPath() ),
|
||||
RPT_SEVERITY_INFO );
|
||||
|
||||
if( srcFileName.Exists()
|
||||
&& !wxCopyFile( srcFileName.GetFullPath(), destFileName.GetFullPath() ) )
|
||||
{
|
||||
errorMsg += wxString::Format( _( "Failed to back up file '%s'.\n" ),
|
||||
srcFileName.GetFullPath() );
|
||||
}
|
||||
|
||||
// Back up the rescue symbol library if it exists.
|
||||
srcFileName.SetName( Prj().GetProjectName() + wxS( "-rescue" ) );
|
||||
destFileName.SetName( srcFileName.GetName() + timeStamp );
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
#include <wx/socket.h>
|
||||
#include <widgets/wx_aui_utils.h>
|
||||
#include <drawing_sheet/ds_proxy_view_item.h>
|
||||
#include <project/project_local_settings.h>
|
||||
|
||||
|
||||
#define DIFF_SYMBOLS_DIALOG_NAME wxT( "DiffSymbolsDialog" )
|
||||
|
||||
+19
-13
@@ -32,6 +32,8 @@
|
||||
|
||||
#include <wx/log.h>
|
||||
#include <wx/menu.h>
|
||||
|
||||
#include <advanced_config.h>
|
||||
#include <base_units.h>
|
||||
#include <common.h> // for ExpandTextVars
|
||||
#include <eda_item.h>
|
||||
@@ -238,21 +240,25 @@ wxString SCH_FIELD::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraT
|
||||
text = wxS( "" );
|
||||
}
|
||||
|
||||
for( int ii = 0; ii < 10 && text.Contains( wxT( "${" ) ); ++ii )
|
||||
// The iteration here it to allow for nested variables in the
|
||||
// text strings (e.g. ${${VAR}}). Although the symbols and sheets
|
||||
// and labels recurse, text that is none of those types such as text
|
||||
// boxes and labels do not. This only loops if there is still a
|
||||
// variable to resolve.
|
||||
for( int ii = aDepth;
|
||||
ii < ADVANCED_CFG::GetCfg().m_ResolveTextRecursionDepth && text.Contains( wxT( "${" ) );
|
||||
++ii )
|
||||
{
|
||||
if( aDepth < 10 )
|
||||
if( m_parent && m_parent->Type() == SCH_SYMBOL_T )
|
||||
text = ExpandTextVars( text, &symbolResolver );
|
||||
else if( m_parent && m_parent->Type() == SCH_SHEET_T )
|
||||
text = ExpandTextVars( text, &sheetResolver );
|
||||
else if( m_parent && m_parent->IsType( { SCH_LABEL_LOCATE_ANY_T } ) )
|
||||
text = ExpandTextVars( text, &labelResolver );
|
||||
else if( Schematic() )
|
||||
{
|
||||
if( m_parent && m_parent->Type() == SCH_SYMBOL_T )
|
||||
text = ExpandTextVars( text, &symbolResolver );
|
||||
else if( m_parent && m_parent->Type() == SCH_SHEET_T )
|
||||
text = ExpandTextVars( text, &sheetResolver );
|
||||
else if( m_parent && m_parent->IsType( { SCH_LABEL_LOCATE_ANY_T } ) )
|
||||
text = ExpandTextVars( text, &labelResolver );
|
||||
else if( Schematic() )
|
||||
{
|
||||
text = ExpandTextVars( text, &Schematic()->Prj() );
|
||||
text = ExpandTextVars( text, &schematicResolver );
|
||||
}
|
||||
text = ExpandTextVars( text, &Schematic()->Prj() );
|
||||
text = ExpandTextVars( text, &schematicResolver );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -92,6 +92,9 @@ SCH_SHEET* SCH_IO_CADSTAR_ARCHIVE::LoadSchematicFile( const wxString& aFi
|
||||
SCH_SCREEN* screen = new SCH_SCREEN( aSchematic );
|
||||
screen->SetFileName( aFileName );
|
||||
rootSheet->SetScreen( screen );
|
||||
|
||||
// Virtual root sheet UUID must be the same as the schematic file UUID.
|
||||
const_cast<KIID&>( rootSheet->m_Uuid ) = screen->GetUuid();
|
||||
}
|
||||
|
||||
CADSTAR_SCH_ARCHIVE_LOADER csaLoader( aFileName, m_reporter, m_progressReporter );
|
||||
|
||||
@@ -220,12 +220,22 @@ void SCH_IO_EAGLE::loadLayerDefs( wxXmlNode* aLayers )
|
||||
* </layers>
|
||||
*/
|
||||
|
||||
if( elayer.name == wxT( "Nets" ) )
|
||||
switch ( elayer.number)
|
||||
{
|
||||
case 91:
|
||||
m_layerMap[elayer.number] = LAYER_WIRE;
|
||||
else if( elayer.name == wxT( "Info" ) || elayer.name == wxT( "Guide" ) )
|
||||
m_layerMap[elayer.number] = LAYER_NOTES;
|
||||
else if( elayer.name == wxT( "Busses" ) )
|
||||
break;
|
||||
case 92:
|
||||
m_layerMap[elayer.number] = LAYER_BUS;
|
||||
break;
|
||||
case 97:
|
||||
case 98:
|
||||
m_layerMap[elayer.number] = LAYER_NOTES;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2903,7 +2913,7 @@ bool SCH_IO_EAGLE::checkHeader( const wxString& aFileName ) const
|
||||
|
||||
wxTextInputStream text( input );
|
||||
|
||||
for( int i = 0; i < 4; i++ )
|
||||
for( int i = 0; i < 8; i++ )
|
||||
{
|
||||
if( input.Eof() )
|
||||
return false;
|
||||
|
||||
@@ -640,6 +640,9 @@ SCH_SHEET* SCH_IO_EASYEDA::LoadSchematicFile( const wxString& aFileName, SCHEMAT
|
||||
|
||||
screen->SetFileName( aFileName );
|
||||
rootSheet->SetScreen( screen );
|
||||
|
||||
// Virtual root sheet UUID must be the same as the schematic file UUID.
|
||||
const_cast<KIID&>( rootSheet->m_Uuid ) = screen->GetUuid();
|
||||
}
|
||||
|
||||
SYMBOL_LIB_TABLE* libTable = PROJECT_SCH::SchSymbolLibTable( &aSchematic->Prj() );
|
||||
|
||||
@@ -552,7 +552,7 @@ SCH_EASYEDAPRO_PARSER::ParseSymbol( const std::vector<nlohmann::json>& aLines,
|
||||
else if( type == wxS( "TEXT" ) )
|
||||
{
|
||||
VECTOR2D pos( line.at( 2 ), line.at( 3 ) );
|
||||
double angle = line.at( 4 );
|
||||
double angle = line.at( 4 ).is_number() ? line.at( 4 ).get<double>() : 0.0;
|
||||
wxString textStr = line.at( 5 );
|
||||
wxString fontStyleStr = line.at( 6 );
|
||||
|
||||
@@ -960,7 +960,7 @@ void SCH_EASYEDAPRO_PARSER::ParseSchematic( SCHEMATIC* aSchematic, SCH_SHEET* aR
|
||||
else if( type == wxS( "TEXT" ) )
|
||||
{
|
||||
VECTOR2D pos( line.at( 2 ), line.at( 3 ) );
|
||||
double angle = line.at( 4 );
|
||||
double angle = line.at( 4 ).is_number() ? line.at( 4 ).get<double>() : 0.0;
|
||||
wxString textStr = line.at( 5 );
|
||||
wxString fontStyleStr = line.at( 6 );
|
||||
|
||||
|
||||
@@ -455,6 +455,9 @@ SCH_SHEET* SCH_IO_EASYEDAPRO::LoadSchematicFile( const wxString& aFileName,
|
||||
|
||||
screen->SetFileName( aFileName );
|
||||
rootSheet->SetScreen( screen );
|
||||
|
||||
// Virtual root sheet UUID must be the same as the schematic file UUID.
|
||||
const_cast<KIID&>( rootSheet->m_Uuid ) = screen->GetUuid();
|
||||
}
|
||||
|
||||
SYMBOL_LIB_TABLE* libTable = PROJECT_SCH::SchSymbolLibTable( &aSchematic->Prj() );
|
||||
|
||||
@@ -29,8 +29,7 @@
|
||||
#include "sch_io_http_lib.h"
|
||||
|
||||
|
||||
SCH_IO_HTTP_LIB::SCH_IO_HTTP_LIB() : SCH_IO( wxS( "HTTP library" ) ),
|
||||
m_libTable( nullptr )
|
||||
SCH_IO_HTTP_LIB::SCH_IO_HTTP_LIB() : SCH_IO( wxS( "HTTP library" ) ), m_libTable( nullptr )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -56,11 +55,11 @@ void SCH_IO_HTTP_LIB::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
|
||||
const wxString& aLibraryPath,
|
||||
const STRING_UTF8_MAP* aProperties )
|
||||
{
|
||||
wxCHECK_RET( m_libTable, _("httplib plugin missing library table handle!") );
|
||||
wxCHECK_RET( m_libTable, _( "httplib plugin missing library table handle!" ) );
|
||||
ensureSettings( aLibraryPath );
|
||||
ensureConnection();
|
||||
|
||||
if( !m_conn)
|
||||
if( !m_conn )
|
||||
{
|
||||
THROW_IO_ERROR( m_lastError );
|
||||
return;
|
||||
@@ -70,13 +69,11 @@ void SCH_IO_HTTP_LIB::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
|
||||
( aProperties
|
||||
&& aProperties->find( SYMBOL_LIB_TABLE::PropPowerSymsOnly ) != aProperties->end() );
|
||||
|
||||
for(const HTTP_LIB_CATEGORY& category : m_conn->getCategories() )
|
||||
for( const HTTP_LIB_CATEGORY& category : m_conn->getCategories() )
|
||||
{
|
||||
bool refresh_cache = true;
|
||||
|
||||
std::vector<HTTP_LIB_PART> found_parts;
|
||||
|
||||
// Check if there is already a part in our cache, if not fetch it
|
||||
// Check if there is already a part in our cache, if not fetch it
|
||||
if( m_cachedCategories.find( category.id ) != m_cachedCategories.end() )
|
||||
{
|
||||
// check if it's outdated, if so re-fetch
|
||||
@@ -89,26 +86,7 @@ void SCH_IO_HTTP_LIB::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
|
||||
|
||||
if( refresh_cache )
|
||||
{
|
||||
if( !m_conn->SelectAll( category, found_parts ) )
|
||||
{
|
||||
if( !m_conn->GetLastError().empty() )
|
||||
{
|
||||
wxString msg =
|
||||
wxString::Format( _( "Error retriving data from HTTP library %s: %s" ),
|
||||
category.name, m_conn->GetLastError() );
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// remove cached parts
|
||||
m_cachedCategories[category.id].cachedParts.clear();
|
||||
|
||||
// Copy newly cached data across
|
||||
m_cachedCategories[category.id].cachedParts = found_parts;
|
||||
m_cachedCategories[category.id].lastCached = std::time( nullptr );
|
||||
|
||||
syncCache( category );
|
||||
}
|
||||
|
||||
for( const HTTP_LIB_PART& part : m_cachedCategories[category.id].cachedParts )
|
||||
@@ -119,14 +97,12 @@ void SCH_IO_HTTP_LIB::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
|
||||
|
||||
if( symbol && ( !powerSymbolsOnly || symbol->IsPower() ) )
|
||||
aSymbolList.emplace_back( symbol );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LIB_SYMBOL* SCH_IO_HTTP_LIB::LoadSymbol( const wxString& aLibraryPath,
|
||||
const wxString& aAliasName,
|
||||
LIB_SYMBOL* SCH_IO_HTTP_LIB::LoadSymbol( const wxString& aLibraryPath, const wxString& aAliasName,
|
||||
const STRING_UTF8_MAP* aProperties )
|
||||
{
|
||||
wxCHECK( m_libTable, nullptr );
|
||||
@@ -145,13 +121,17 @@ LIB_SYMBOL* SCH_IO_HTTP_LIB::LoadSymbol( const wxString& aLibraryPath,
|
||||
|
||||
std::vector<HTTP_LIB_CATEGORY> categories = m_conn->getCategories();
|
||||
|
||||
std::tuple relations = m_conn->getCachedParts()[partName];
|
||||
if( m_conn->getCachedParts().empty() )
|
||||
{
|
||||
syncCache();
|
||||
}
|
||||
|
||||
std::tuple relations = m_conn->getCachedParts()[partName];
|
||||
std::string associatedCatID = std::get<1>( relations );
|
||||
|
||||
// get the matching category
|
||||
for( const HTTP_LIB_CATEGORY& categoryIter : categories )
|
||||
{
|
||||
std::string associatedCatID = std::get<1>( relations );
|
||||
|
||||
if( categoryIter.id == associatedCatID )
|
||||
{
|
||||
foundCategory = &categoryIter;
|
||||
@@ -197,26 +177,30 @@ LIB_SYMBOL* SCH_IO_HTTP_LIB::LoadSymbol( const wxString& aLibraryPath,
|
||||
|
||||
void SCH_IO_HTTP_LIB::GetSubLibraryNames( std::vector<wxString>& aNames )
|
||||
{
|
||||
ensureSettings( wxEmptyString );
|
||||
ensureSettings( wxEmptyString );
|
||||
|
||||
aNames.clear();
|
||||
aNames.clear();
|
||||
|
||||
std::set<wxString> categoryNames;
|
||||
std::set<wxString> categoryNames;
|
||||
|
||||
for( const HTTP_LIB_CATEGORY& categoryIter : m_conn->getCategories() )
|
||||
{
|
||||
for( const HTTP_LIB_CATEGORY& categoryIter : m_conn->getCategories() )
|
||||
{
|
||||
if( categoryNames.count( categoryIter.name ) )
|
||||
continue;
|
||||
|
||||
aNames.emplace_back( categoryIter.name );
|
||||
categoryNames.insert( categoryIter.name );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wxString SCH_IO_HTTP_LIB::GetSubLibraryDescription( const wxString& aName )
|
||||
{
|
||||
return m_conn->getCategoryDescription( std::string( aName.mb_str() ) );
|
||||
}
|
||||
|
||||
void SCH_IO_HTTP_LIB::GetAvailableSymbolFields( std::vector<wxString>& aNames )
|
||||
{
|
||||
// TODO: Implement this sometime; This is currently broken...
|
||||
// TODO: Implement this sometime; This is currently broken...
|
||||
std::copy( m_customFields.begin(), m_customFields.end(), std::back_inserter( aNames ) );
|
||||
}
|
||||
|
||||
@@ -230,13 +214,12 @@ void SCH_IO_HTTP_LIB::GetDefaultSymbolFields( std::vector<wxString>& aNames )
|
||||
|
||||
void SCH_IO_HTTP_LIB::ensureSettings( const wxString& aSettingsPath )
|
||||
{
|
||||
|
||||
auto tryLoad = [&]()
|
||||
{
|
||||
if( !m_settings->LoadFromFile() )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "HTTP library settings file %s missing or invalid" ),
|
||||
aSettingsPath );
|
||||
wxString msg = wxString::Format(
|
||||
_( "HTTP library settings file %s missing or invalid" ), aSettingsPath );
|
||||
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
@@ -252,11 +235,10 @@ void SCH_IO_HTTP_LIB::ensureSettings( const wxString& aSettingsPath )
|
||||
|
||||
if( m_settings->getSupportedAPIVersion() != m_settings->m_Source.api_version )
|
||||
{
|
||||
wxString msg = wxString::Format(
|
||||
_( "HTTP library settings file %s uses API version %s, but KiCad requires version %s" ),
|
||||
aSettingsPath,
|
||||
m_settings->m_Source.api_version,
|
||||
m_settings->getSupportedAPIVersion() );
|
||||
wxString msg = wxString::Format( _( "HTTP library settings file %s uses API version "
|
||||
"%s, but KiCad requires version %s" ),
|
||||
aSettingsPath, m_settings->m_Source.api_version,
|
||||
m_settings->getSupportedAPIVersion() );
|
||||
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
@@ -264,8 +246,7 @@ void SCH_IO_HTTP_LIB::ensureSettings( const wxString& aSettingsPath )
|
||||
if( m_settings->m_Source.root_url.empty() )
|
||||
{
|
||||
wxString msg = wxString::Format(
|
||||
_( "HTTP library settings file %s is missing the root URL!" ),
|
||||
aSettingsPath );
|
||||
_( "HTTP library settings file %s is missing the root URL!" ), aSettingsPath );
|
||||
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
@@ -290,7 +271,6 @@ void SCH_IO_HTTP_LIB::ensureSettings( const wxString& aSettingsPath )
|
||||
|
||||
// Append api version to root URL
|
||||
m_settings->m_Source.root_url += m_settings->m_Source.api_version + "/";
|
||||
|
||||
};
|
||||
|
||||
if( !m_settings && !aSettingsPath.IsEmpty() )
|
||||
@@ -322,9 +302,8 @@ void SCH_IO_HTTP_LIB::ensureConnection()
|
||||
|
||||
if( !m_conn || !m_conn->IsValidEndpoint() )
|
||||
{
|
||||
wxString msg = wxString::Format(
|
||||
_( "Could not connect to %s. Errors: %s" ),
|
||||
m_settings->m_Source.root_url, m_lastError );
|
||||
wxString msg = wxString::Format( _( "Could not connect to %s. Errors: %s" ),
|
||||
m_settings->m_Source.root_url, m_lastError );
|
||||
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
@@ -351,6 +330,38 @@ void SCH_IO_HTTP_LIB::connect()
|
||||
}
|
||||
}
|
||||
|
||||
void SCH_IO_HTTP_LIB::syncCache()
|
||||
{
|
||||
for( const HTTP_LIB_CATEGORY& category : m_conn->getCategories() )
|
||||
{
|
||||
syncCache( category );
|
||||
}
|
||||
}
|
||||
|
||||
void SCH_IO_HTTP_LIB::syncCache( const HTTP_LIB_CATEGORY& category )
|
||||
{
|
||||
std::vector<HTTP_LIB_PART> found_parts;
|
||||
|
||||
if( !m_conn->SelectAll( category, found_parts ) )
|
||||
{
|
||||
if( !m_conn->GetLastError().empty() )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Error retriving data from HTTP library %s: %s" ),
|
||||
category.name, m_conn->GetLastError() );
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// remove cached parts
|
||||
m_cachedCategories[category.id].cachedParts.clear();
|
||||
|
||||
// Copy newly cached data across
|
||||
m_cachedCategories[category.id].cachedParts = found_parts;
|
||||
m_cachedCategories[category.id].lastCached = std::time( nullptr );
|
||||
}
|
||||
|
||||
|
||||
LIB_SYMBOL* SCH_IO_HTTP_LIB::loadSymbolFromPart( const wxString& aSymbolName,
|
||||
const HTTP_LIB_CATEGORY& aCategory,
|
||||
@@ -478,7 +489,6 @@ LIB_SYMBOL* SCH_IO_HTTP_LIB::loadSymbolFromPart( const wxString& aSymbo
|
||||
|
||||
m_customFields.insert( fieldName );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,8 @@ public:
|
||||
|
||||
void GetSubLibraryNames( std::vector<wxString>& aNames ) override;
|
||||
|
||||
wxString GetSubLibraryDescription( const wxString& aName ) override;
|
||||
|
||||
void GetAvailableSymbolFields( std::vector<wxString>& aNames ) override;
|
||||
|
||||
void GetDefaultSymbolFields( std::vector<wxString>& aNames ) override;
|
||||
@@ -78,20 +80,22 @@ public:
|
||||
const wxString& GetError() const override { return m_lastError; }
|
||||
|
||||
private:
|
||||
|
||||
void ensureSettings( const wxString& aSettingsPath );
|
||||
|
||||
void ensureConnection();
|
||||
|
||||
void connect();
|
||||
|
||||
LIB_SYMBOL* loadSymbolFromPart( const wxString& aSymbolName,
|
||||
const HTTP_LIB_CATEGORY& aCategory,
|
||||
void syncCache();
|
||||
|
||||
void syncCache( const HTTP_LIB_CATEGORY& category );
|
||||
|
||||
LIB_SYMBOL* loadSymbolFromPart( const wxString& aSymbolName, const HTTP_LIB_CATEGORY& aCategory,
|
||||
const HTTP_LIB_PART& aPart );
|
||||
|
||||
SYMBOL_LIB_TABLE* m_libTable;
|
||||
|
||||
/// Generally will be null if no valid connection is established
|
||||
/// Generally will be null if no valid connection is established
|
||||
std::unique_ptr<HTTP_LIB_CONNECTION> m_conn;
|
||||
|
||||
std::unique_ptr<HTTP_LIB_SETTINGS> m_settings;
|
||||
@@ -110,9 +114,8 @@ private:
|
||||
wxString datasheet_field = "datasheet";
|
||||
wxString reference_field = "reference";
|
||||
|
||||
// category.id category
|
||||
// category.id category
|
||||
std::map<std::string, HTTP_LIB_CATEGORY> m_cachedCategories;
|
||||
|
||||
};
|
||||
|
||||
#endif // SCH_IO_HTTP_LIB_H_
|
||||
|
||||
@@ -65,6 +65,9 @@ SCH_SHEET* SCH_IO_LTSPICE::LoadSchematicFile( const wxString& aFileName, SCHEMAT
|
||||
|
||||
screen->SetFileName( aFileName );
|
||||
rootSheet->SetScreen( screen );
|
||||
|
||||
// Virtual root sheet UUID must be the same as the schematic file UUID.
|
||||
const_cast<KIID&>( rootSheet->m_Uuid ) = screen->GetUuid();
|
||||
}
|
||||
|
||||
SYMBOL_LIB_TABLE* libTable = PROJECT_SCH::SchSymbolLibTable( &aSchematic->Prj() );
|
||||
|
||||
@@ -301,6 +301,17 @@ public:
|
||||
*/
|
||||
virtual void GetSubLibraryNames( std::vector<wxString>& aNames ) {}
|
||||
|
||||
/**
|
||||
* Gets a description of a sublibrary.
|
||||
*
|
||||
* Has no effect if SupportsSubLibraries() returns false.
|
||||
*
|
||||
* @param aName contains the name of the sublibrary for which the description is retrieved
|
||||
*
|
||||
* @return the description of the sublibrary
|
||||
*/
|
||||
virtual wxString GetSubLibraryDescription( const wxString& aName ) { return wxEmptyString; }
|
||||
|
||||
/**
|
||||
* Retrieves a list of (custom) field names that are present on symbols in this library.
|
||||
* The plugin is responsible for guaranteeing that this list contains the set of unique
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <advanced_config.h>
|
||||
#include <base_units.h>
|
||||
#include <pgm_base.h>
|
||||
#include <sch_edit_frame.h>
|
||||
@@ -903,7 +904,7 @@ wxString SCH_LABEL_BASE::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowE
|
||||
}
|
||||
else if( HasTextVars() )
|
||||
{
|
||||
if( aDepth < 10 )
|
||||
if( aDepth < ADVANCED_CFG::GetCfg().m_ResolveTextRecursionDepth )
|
||||
text = ExpandTextVars( text, &textResolver );
|
||||
}
|
||||
|
||||
|
||||
@@ -227,8 +227,12 @@ void SCH_PLOTTER::plotOneSheetPDF( PLOTTER* aPlotter, SCH_SCREEN* aScreen,
|
||||
if( aPlotSettings.m_useBackgroundColor && aPlotter->GetColorMode() )
|
||||
{
|
||||
aPlotter->SetColor( aPlotter->RenderSettings()->GetBackgroundColor() );
|
||||
VECTOR2I end( aPlotter->PageSettings().GetWidthIU( schIUScale.IU_PER_MILS ),
|
||||
aPlotter->PageSettings().GetHeightIU( schIUScale.IU_PER_MILS ) );
|
||||
|
||||
// Use page size selected in schematic to know the schematic bg area
|
||||
const PAGE_INFO& actualPage = aScreen->GetPageSettings(); // page size selected in schematic
|
||||
VECTOR2I end( actualPage.GetWidthIU( schIUScale.IU_PER_MILS ),
|
||||
actualPage.GetHeightIU( schIUScale.IU_PER_MILS ) );
|
||||
|
||||
aPlotter->Rect( VECTOR2I( 0, 0 ), end, FILL_T::FILLED_SHAPE, 1.0 );
|
||||
}
|
||||
|
||||
@@ -437,8 +441,11 @@ bool SCH_PLOTTER::plotOneSheetPS( const wxString& aFileName, SCH_SCREEN* aScreen
|
||||
{
|
||||
plotter->SetColor( plotter->RenderSettings()->GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) );
|
||||
|
||||
VECTOR2I end( plotter->PageSettings().GetWidthIU( schIUScale.IU_PER_MILS ),
|
||||
plotter->PageSettings().GetHeightIU( schIUScale.IU_PER_MILS ) );
|
||||
// Use page size selected in schematic to know the schematic bg area
|
||||
const PAGE_INFO& actualPage = aScreen->GetPageSettings(); // page size selected in schematic
|
||||
VECTOR2I end( actualPage.GetWidthIU( schIUScale.IU_PER_MILS ),
|
||||
actualPage.GetHeightIU( schIUScale.IU_PER_MILS ) );
|
||||
|
||||
plotter->Rect( VECTOR2I( 0, 0 ), end, FILL_T::FILLED_SHAPE, 1.0 );
|
||||
}
|
||||
|
||||
@@ -612,8 +619,11 @@ bool SCH_PLOTTER::plotOneSheetSVG( const wxString& aFileName, SCH_SCREEN* aScree
|
||||
if( aPlotSettings.m_useBackgroundColor && plotter->GetColorMode() )
|
||||
{
|
||||
plotter->SetColor( plotter->RenderSettings()->GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) );
|
||||
VECTOR2I end( plotter->PageSettings().GetWidthIU( schIUScale.IU_PER_MILS ),
|
||||
plotter->PageSettings().GetHeightIU( schIUScale.IU_PER_MILS ) );
|
||||
|
||||
// Use page size selected in schematic to know the schematic bg area
|
||||
VECTOR2I end( actualPage.GetWidthIU( schIUScale.IU_PER_MILS ),
|
||||
actualPage.GetHeightIU( schIUScale.IU_PER_MILS ) );
|
||||
|
||||
plotter->Rect( VECTOR2I( 0, 0 ), end, FILL_T::FILLED_SHAPE, 1.0 );
|
||||
}
|
||||
|
||||
|
||||
@@ -631,6 +631,7 @@ void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId, int
|
||||
std::vector<int> units = { ref_unit.GetUnit() };
|
||||
LastReferenceNumber = FindFirstUnusedReference( ref_unit, minRefId, units );
|
||||
ref_unit.m_numRef = LastReferenceNumber;
|
||||
ref_unit.m_numRefStr = wxString::Format( "%d", LastReferenceNumber );
|
||||
ref_unit.m_isNew = false;
|
||||
ref_unit.m_flag = 1;
|
||||
}
|
||||
@@ -664,7 +665,7 @@ int SCH_REFERENCE_LIST::CheckAnnotation( ANNOTATION_ERROR_HANDLER aHandler )
|
||||
if( m_flatList[ii].m_isNew ) // Not yet annotated
|
||||
{
|
||||
if( m_flatList[ii].m_numRef >= 0 )
|
||||
tmp << m_flatList[ii].m_numRef;
|
||||
tmp << m_flatList[ii].m_numRefStr;
|
||||
else
|
||||
tmp = wxT( "?" );
|
||||
|
||||
@@ -692,7 +693,7 @@ int SCH_REFERENCE_LIST::CheckAnnotation( ANNOTATION_ERROR_HANDLER aHandler )
|
||||
if( std::max( m_flatList[ii].GetLibPart()->GetUnitCount(), 1 ) < m_flatList[ii].m_unit )
|
||||
{
|
||||
if( m_flatList[ii].m_numRef >= 0 )
|
||||
tmp << m_flatList[ii].m_numRef;
|
||||
tmp << m_flatList[ii].m_numRefStr;
|
||||
else
|
||||
tmp = wxT( "?" );
|
||||
|
||||
@@ -731,7 +732,7 @@ int SCH_REFERENCE_LIST::CheckAnnotation( ANNOTATION_ERROR_HANDLER aHandler )
|
||||
if( first.m_unit == second.m_unit )
|
||||
{
|
||||
if( first.m_numRef >= 0 )
|
||||
tmp << first.m_numRef;
|
||||
tmp << first.m_numRefStr;
|
||||
else
|
||||
tmp = wxT( "?" );
|
||||
|
||||
@@ -751,12 +752,12 @@ int SCH_REFERENCE_LIST::CheckAnnotation( ANNOTATION_ERROR_HANDLER aHandler )
|
||||
if( first.GetLibPart()->GetUnitCount() != second.GetLibPart()->GetUnitCount() )
|
||||
{
|
||||
if( first.m_numRef >= 0 )
|
||||
tmp << first.m_numRef;
|
||||
tmp << first.m_numRefStr;
|
||||
else
|
||||
tmp = wxT( "?" );
|
||||
|
||||
if( second.m_numRef >= 0 )
|
||||
tmp2 << second.m_numRef;
|
||||
tmp2 << second.m_numRefStr;
|
||||
else
|
||||
tmp2 = wxT( "?" );
|
||||
|
||||
|
||||
@@ -181,17 +181,10 @@ public:
|
||||
|
||||
wxString GetRefNumber() const
|
||||
{
|
||||
wxString ref;
|
||||
|
||||
if( m_numRef < 0 )
|
||||
return wxT( "?" );
|
||||
|
||||
// To avoid a risk of duplicate, for power symbols the ref number is 0nnn instead of nnn.
|
||||
// Just because sometimes only power symbols are annotated
|
||||
if( GetLibPart() && GetLibPart()->IsPower() )
|
||||
ref = wxT( "0" );
|
||||
|
||||
return ref << m_numRef;
|
||||
return m_numRefStr;
|
||||
}
|
||||
|
||||
int CompareValue( const SCH_REFERENCE& item ) const
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <advanced_config.h>
|
||||
#include <base_units.h>
|
||||
#include <pgm_base.h>
|
||||
#include <sch_edit_frame.h>
|
||||
@@ -278,7 +279,7 @@ wxString SCH_TEXT::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraTe
|
||||
}
|
||||
else if( HasTextVars() )
|
||||
{
|
||||
if( aDepth < 10 )
|
||||
if( aDepth < ADVANCED_CFG::GetCfg().m_ResolveTextRecursionDepth )
|
||||
text = ExpandTextVars( text, &textResolver );
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <advanced_config.h>
|
||||
#include <base_units.h>
|
||||
#include <pgm_base.h>
|
||||
#include <sch_edit_frame.h>
|
||||
@@ -309,7 +310,7 @@ wxString SCH_TEXTBOX::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtr
|
||||
|
||||
if( HasTextVars() )
|
||||
{
|
||||
if( aDepth < 10 )
|
||||
if( aDepth < ADVANCED_CFG::GetCfg().m_ResolveTextRecursionDepth )
|
||||
text = ExpandTextVars( text, &textResolver );
|
||||
}
|
||||
|
||||
|
||||
@@ -104,6 +104,15 @@ void SYMBOL_LIB_TABLE_ROW::GetSubLibraryNames( std::vector<wxString>& aNames ) c
|
||||
}
|
||||
|
||||
|
||||
wxString SYMBOL_LIB_TABLE_ROW::GetSubLibraryDescription( const wxString& aName ) const
|
||||
{
|
||||
if( !plugin )
|
||||
return wxEmptyString;
|
||||
|
||||
return plugin->GetSubLibraryDescription( aName );
|
||||
}
|
||||
|
||||
|
||||
void SYMBOL_LIB_TABLE_ROW::ShowSettingsDialog( wxWindow* aParent ) const
|
||||
{
|
||||
wxCHECK( plugin, /* void */ );
|
||||
|
||||
@@ -95,6 +95,8 @@ public:
|
||||
|
||||
void GetSubLibraryNames( std::vector<wxString>& aNames ) const;
|
||||
|
||||
wxString GetSubLibraryDescription( const wxString& aName ) const;
|
||||
|
||||
/**
|
||||
* @see SCH_IO::GetAvailableSymbolFields
|
||||
*/
|
||||
|
||||
@@ -485,13 +485,20 @@ void SYMBOL_LIBS::SetLibNamesAndPaths( PROJECT* aProject, const wxString& aPaths
|
||||
|
||||
const wxString SYMBOL_LIBS::CacheName( const wxString& aFullProjectFilename )
|
||||
{
|
||||
wxFileName name = aFullProjectFilename;
|
||||
wxFileName filename( aFullProjectFilename );
|
||||
wxString name = filename.GetName();
|
||||
|
||||
name.SetName( name.GetName() + "-cache" );
|
||||
name.SetExt( FILEEXT::LegacySymbolLibFileExtension );
|
||||
filename.SetName( name + "-cache" );
|
||||
filename.SetExt( FILEEXT::LegacySymbolLibFileExtension );
|
||||
|
||||
if( name.FileExists() )
|
||||
return name.GetFullPath();
|
||||
if( filename.FileExists() )
|
||||
return filename.GetFullPath();
|
||||
|
||||
// Try the old (2007) cache name
|
||||
filename.SetName( name + ".cache" );
|
||||
|
||||
if( filename.FileExists() )
|
||||
return filename.GetFullPath();
|
||||
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
@@ -158,10 +158,11 @@ bool SYMBOL_TREE_MODEL_ADAPTER::AddLibraries( const std::vector<wxString>& aNick
|
||||
wxString suffix = lib.IsEmpty() ? wxString( wxT( "" ) )
|
||||
: wxString::Format( wxT( " - %s" ), lib );
|
||||
wxString name = wxString::Format( wxT( "%s%s" ), libNickname, suffix );
|
||||
wxString desc;
|
||||
wxString desc = row->GetSubLibraryDescription( lib );
|
||||
|
||||
if( !parentDesc.IsEmpty() )
|
||||
desc = wxString::Format( wxT( "%s (%s)" ), parentDesc, lib );
|
||||
desc = wxString::Format( wxT( "%s (%s)" ), parentDesc,
|
||||
( desc.IsEmpty() ) ? lib : desc );
|
||||
|
||||
UTF8 utf8Lib( lib );
|
||||
|
||||
|
||||
@@ -376,10 +376,13 @@ void BACK_ANNOTATE::applyChangelist()
|
||||
bool oldExBOM = ref.GetSymbol()->GetExcludedFromBOM();
|
||||
bool skip = ( ref.GetSymbol()->GetFlags() & SKIP_STRUCT ) > 0;
|
||||
|
||||
auto boolString = []( bool b ) -> wxString
|
||||
{
|
||||
return b ? _( "true" ) : _( "false" );
|
||||
};
|
||||
auto boolString =
|
||||
[]( bool b ) -> wxString
|
||||
{
|
||||
return b ? _( "true" ) : _( "false" );
|
||||
};
|
||||
if( !m_dryRun )
|
||||
commit.Modify( symbol, screen );
|
||||
|
||||
if( m_processReferences && ref.GetRef() != fpData.m_ref && !skip )
|
||||
{
|
||||
@@ -389,10 +392,7 @@ void BACK_ANNOTATE::applyChangelist()
|
||||
fpData.m_ref );
|
||||
|
||||
if( !m_dryRun )
|
||||
{
|
||||
commit.Modify( symbol, screen );
|
||||
symbol->SetRef( &ref.GetSheetPath(), fpData.m_ref );
|
||||
}
|
||||
|
||||
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
|
||||
}
|
||||
@@ -406,10 +406,7 @@ void BACK_ANNOTATE::applyChangelist()
|
||||
fpData.m_footprint );
|
||||
|
||||
if( !m_dryRun )
|
||||
{
|
||||
commit.Modify( symbol, screen );
|
||||
symbol->SetFootprintFieldText( fpData.m_footprint );
|
||||
}
|
||||
|
||||
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
|
||||
}
|
||||
@@ -423,10 +420,7 @@ void BACK_ANNOTATE::applyChangelist()
|
||||
fpData.m_value );
|
||||
|
||||
if( !m_dryRun )
|
||||
{
|
||||
commit.Modify( symbol, screen );
|
||||
symbol->SetValueFieldText( fpData.m_value );
|
||||
}
|
||||
|
||||
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
|
||||
}
|
||||
@@ -438,10 +432,7 @@ void BACK_ANNOTATE::applyChangelist()
|
||||
boolString( oldDNP ), boolString( fpData.m_DNP ) );
|
||||
|
||||
if( !m_dryRun )
|
||||
{
|
||||
commit.Modify( symbol, screen );
|
||||
symbol->SetDNP( fpData.m_DNP );
|
||||
}
|
||||
|
||||
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
|
||||
}
|
||||
@@ -454,10 +445,7 @@ void BACK_ANNOTATE::applyChangelist()
|
||||
boolString( fpData.m_excludeFromBOM ) );
|
||||
|
||||
if( !m_dryRun )
|
||||
{
|
||||
commit.Modify( symbol, screen );
|
||||
symbol->SetExcludedFromBOM( fpData.m_excludeFromBOM );
|
||||
}
|
||||
|
||||
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
|
||||
}
|
||||
@@ -519,10 +507,7 @@ void BACK_ANNOTATE::applyChangelist()
|
||||
symField->GetCanonicalName(), fpFieldValue );
|
||||
|
||||
if( !m_dryRun )
|
||||
{
|
||||
commit.Modify( symbol, screen );
|
||||
symField->SetText( fpFieldValue );
|
||||
}
|
||||
|
||||
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
|
||||
}
|
||||
@@ -535,11 +520,10 @@ void BACK_ANNOTATE::applyChangelist()
|
||||
|
||||
if( !m_dryRun )
|
||||
{
|
||||
commit.Modify( symbol, screen );
|
||||
|
||||
SCH_FIELD newField( VECTOR2I( 0, 0 ), symbol->GetFieldCount(), symbol,
|
||||
SCH_FIELD newField( symbol->GetPosition(), symbol->GetFieldCount(), symbol,
|
||||
fpFieldName );
|
||||
newField.SetText( fpFieldValue );
|
||||
newField.SetVisible( false ); // Don't clutter up the schematic
|
||||
symbol->AddField( newField );
|
||||
}
|
||||
|
||||
@@ -549,24 +533,26 @@ void BACK_ANNOTATE::applyChangelist()
|
||||
|
||||
// 3. Existing field has been deleted from footprint and needs to be deleted from symbol
|
||||
// Check all symbol fields for existence in the footprint field map
|
||||
for( SCH_FIELD& field : symbol->GetFields() )
|
||||
for( int ii = symbol->GetFieldCount() - 1; ii >= 0; --ii )
|
||||
{
|
||||
// Never delete mandatory fields
|
||||
if( field.GetId() < MANDATORY_FIELDS )
|
||||
SCH_FIELD* field = symbol->GetFieldById( ii );
|
||||
|
||||
if( !field )
|
||||
continue;
|
||||
|
||||
if( fpData.m_fieldsMap.find( field.GetCanonicalName() )
|
||||
// Never delete mandatory fields
|
||||
if( field->IsMandatory() )
|
||||
continue;
|
||||
|
||||
if( fpData.m_fieldsMap.find( field->GetCanonicalName() )
|
||||
== fpData.m_fieldsMap.end() )
|
||||
{
|
||||
// Field not found in footprint field map, delete it
|
||||
m_changesCount++;
|
||||
msg.Printf( _( "Delete field '%s.'" ), field.GetCanonicalName() );
|
||||
msg.Printf( _( "Delete field '%s.'" ), field->GetCanonicalName() );
|
||||
|
||||
if( !m_dryRun )
|
||||
{
|
||||
commit.Modify( symbol, screen );
|
||||
symbol->RemoveField( &field );
|
||||
}
|
||||
symbol->RemoveField( field );
|
||||
|
||||
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
|
||||
}
|
||||
|
||||
@@ -393,118 +393,37 @@ int SYMBOL_EDITOR_MOVE_TOOL::AlignElements( const TOOL_EVENT& aEvent )
|
||||
|
||||
for( EDA_ITEM* item : selection )
|
||||
{
|
||||
if( LIB_SHAPE* shape = dynamic_cast<LIB_SHAPE*>( item ) )
|
||||
{
|
||||
VECTOR2I newStart = grid.AlignGrid( shape->GetStart(), grid.GetItemGrid( shape ) );
|
||||
VECTOR2I newEnd = grid.AlignGrid( shape->GetEnd(), grid.GetItemGrid( shape ) );
|
||||
VECTOR2I newPos = grid.AlignGrid( item->GetPosition(), grid.GetItemGrid( item ) );
|
||||
VECTOR2I delta = newPos - item->GetPosition();
|
||||
|
||||
switch( shape->GetShape() )
|
||||
{
|
||||
case SHAPE_T::SEGMENT:
|
||||
case SHAPE_T::RECTANGLE:
|
||||
case SHAPE_T::CIRCLE:
|
||||
case SHAPE_T::ARC:
|
||||
if( newStart == newEnd ||
|
||||
shape->GetShape() == SHAPE_T::CIRCLE || shape->GetShape() == SHAPE_T::ARC )
|
||||
{
|
||||
// For arc and circle, never modify the shape. just snap its position
|
||||
// For others, don't collapse shape; just snap its position
|
||||
if( newStart != shape->GetStart() )
|
||||
doMoveItem( shape, newStart - shape->GetStart() );
|
||||
}
|
||||
else if( newStart != shape->GetStart() || newEnd != shape->GetEnd() )
|
||||
{
|
||||
// Snap both ends
|
||||
commit.Modify( shape, m_frame->GetScreen() );
|
||||
|
||||
shape->SetStart( newStart );
|
||||
shape->SetEnd( newEnd );
|
||||
|
||||
updateItem( item, true );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
break;
|
||||
|
||||
case SHAPE_T::POLY:
|
||||
if( shape->GetPointCount() > 0 )
|
||||
{
|
||||
std::vector<VECTOR2I> newPts;
|
||||
|
||||
for( const VECTOR2I& pt : shape->GetPolyShape().Outline( 0 ).CPoints() )
|
||||
newPts.push_back( grid.AlignGrid( pt, grid.GetItemGrid( shape ) ) );
|
||||
|
||||
bool collapsed = false;
|
||||
|
||||
for( int ii = 0; ii < (int) newPts.size() - 1; ++ii )
|
||||
{
|
||||
if( newPts[ii] == newPts[ii + 1] )
|
||||
collapsed = true;
|
||||
}
|
||||
|
||||
if( collapsed )
|
||||
{
|
||||
// Don't collapse shape; just snap its position
|
||||
if( newStart != shape->GetStart() )
|
||||
doMoveItem( shape, newStart - shape->GetStart() );
|
||||
}
|
||||
else
|
||||
{
|
||||
commit.Modify( shape, m_frame->GetScreen() );
|
||||
|
||||
for( int ii = 0; ii < (int) newPts.size(); ++ii )
|
||||
shape->GetPolyShape().Outline( 0 ).SetPoint( ii, newPts[ii] );
|
||||
|
||||
updateItem( item, true );
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SHAPE_T::BEZIER:
|
||||
// Snapping bezier control points is unlikely to be useful. Just snap its
|
||||
// position.
|
||||
if( newStart != shape->GetStart() )
|
||||
doMoveItem( shape, newStart - shape->GetStart() );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
VECTOR2I newPos = grid.AlignGrid( item->GetPosition(), grid.GetItemGrid( item ) );
|
||||
VECTOR2I delta = newPos - item->GetPosition();
|
||||
|
||||
if( delta != VECTOR2I( 0, 0 ) )
|
||||
doMoveItem( item, delta );
|
||||
if( delta != VECTOR2I( 0, 0 ) )
|
||||
doMoveItem( item, delta );
|
||||
|
||||
if( LIB_PIN* pin = dynamic_cast<LIB_PIN*>( item ) )
|
||||
{
|
||||
int length = pin->GetLength();
|
||||
int pinGrid;
|
||||
|
||||
if( pin->GetOrientation() == PIN_ORIENTATION::PIN_LEFT
|
||||
|| pin->GetOrientation() == PIN_ORIENTATION::PIN_RIGHT )
|
||||
{
|
||||
pinGrid = KiROUND( grid.GetGridSize( grid.GetItemGrid( item ) ).x );
|
||||
}
|
||||
else
|
||||
{
|
||||
pinGrid = KiROUND( grid.GetGridSize( grid.GetItemGrid( item ) ).y );
|
||||
}
|
||||
|
||||
int newLength = KiROUND( (double) length / pinGrid ) * pinGrid;
|
||||
|
||||
if( newLength > 0 )
|
||||
pin->SetLength( newLength );
|
||||
if( pin->GetOrientation() == PIN_ORIENTATION::PIN_LEFT
|
||||
|| pin->GetOrientation() == PIN_ORIENTATION::PIN_RIGHT )
|
||||
{
|
||||
pinGrid = KiROUND( grid.GetGridSize( grid.GetItemGrid( item ) ).x );
|
||||
}
|
||||
else
|
||||
{
|
||||
pinGrid = KiROUND( grid.GetGridSize( grid.GetItemGrid( item ) ).y );
|
||||
}
|
||||
|
||||
int newLength = KiROUND( (double) length / pinGrid ) * pinGrid;
|
||||
|
||||
if( newLength > 0 )
|
||||
pin->SetLength( newLength );
|
||||
}
|
||||
}
|
||||
|
||||
m_toolMgr->PostEvent( EVENTS::SelectedItemsMoved );
|
||||
|
||||
commit.Push( _( "Align" ) );
|
||||
commit.Push( _( "Align Items to Grid" ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -162,10 +162,14 @@ bool SYMBOL_EDITOR_PIN_TOOL::EditPinProperties( LIB_PIN* aPin )
|
||||
if( !aPin->GetUnit() || other->GetUnit() == aPin->GetUnit() )
|
||||
aPin->GetParent()->RemoveDrawItem( other );
|
||||
}
|
||||
else if( other->GetBodyStyle() == aPin->GetBodyStyle() )
|
||||
|
||||
if( other->GetBodyStyle() == aPin->GetBodyStyle() )
|
||||
{
|
||||
other->SetPosition( aPin->GetPosition() );
|
||||
other->ChangeLength( aPin->GetLength() );
|
||||
|
||||
// Must be done after ChangeLenght(), which can alter the position
|
||||
other->SetPosition( aPin->GetPosition() );
|
||||
|
||||
other->SetShape( aPin->GetShape() );
|
||||
}
|
||||
|
||||
|
||||
@@ -577,6 +577,15 @@ public:
|
||||
*/
|
||||
double m_MinParallelAngle;
|
||||
|
||||
/**
|
||||
* The number of recursions to resolve text variables.
|
||||
*
|
||||
* Setting name: "ResolveTextRecursionDepth"
|
||||
* Valid values: 0 to 10
|
||||
* Default value: 2
|
||||
*/
|
||||
int m_ResolveTextRecursionDepth;
|
||||
|
||||
///@}
|
||||
|
||||
private:
|
||||
|
||||
@@ -60,15 +60,18 @@ public:
|
||||
|
||||
std::vector<HTTP_LIB_CATEGORY> getCategories() const { return m_categories; }
|
||||
|
||||
std::string getCategoryDescription( const std::string& aCategoryName ) const
|
||||
{
|
||||
return m_categoryDescriptions.at( aCategoryName );
|
||||
}
|
||||
|
||||
auto getCachedParts() { return m_cache; }
|
||||
|
||||
private:
|
||||
|
||||
// This is clunky but at the moment the only way to free the pointer after use without KiCad crashing.
|
||||
// at this point we can't use smart pointers as there is a problem with the order of how things are deleted/freed
|
||||
std::unique_ptr<KICAD_CURL_EASY> createCurlEasyObject()
|
||||
{
|
||||
|
||||
std::unique_ptr<KICAD_CURL_EASY> aCurl( new KICAD_CURL_EASY() );
|
||||
|
||||
// prepare curl
|
||||
@@ -88,7 +91,7 @@ private:
|
||||
|
||||
wxString httpErrorCodeDescription( uint16_t aHttpCode );
|
||||
|
||||
HTTP_LIB_SOURCE m_source;
|
||||
HTTP_LIB_SOURCE m_source;
|
||||
|
||||
// part.id part
|
||||
std::map<std::string, HTTP_LIB_PART> m_cachedParts;
|
||||
@@ -100,7 +103,8 @@ private:
|
||||
|
||||
std::string m_lastError;
|
||||
|
||||
std::vector<HTTP_LIB_CATEGORY> m_categories;
|
||||
std::vector<HTTP_LIB_CATEGORY> m_categories;
|
||||
std::map<std::string, std::string> m_categoryDescriptions;
|
||||
|
||||
std::map<std::string, std::string> m_parts;
|
||||
|
||||
@@ -108,7 +112,6 @@ private:
|
||||
const std::string http_endpoint_parts = "parts";
|
||||
const std::string http_endpoint_settings = "settings";
|
||||
const std::string http_endpoint_auth = "authentication";
|
||||
|
||||
};
|
||||
|
||||
#endif //KICAD_HTTP_LIB_CONNECTION_H
|
||||
|
||||
@@ -54,14 +54,16 @@ struct HTTP_LIB_PART
|
||||
|
||||
std::time_t lastCached = 0;
|
||||
|
||||
std::map<std::string, std::tuple<std::string, bool>> fields; ///< additional generic fields
|
||||
std::vector<std::pair<std::string, std::tuple<std::string, bool>>>
|
||||
fields; ///< additional generic fields
|
||||
};
|
||||
|
||||
|
||||
struct HTTP_LIB_CATEGORY
|
||||
{
|
||||
std::string id; ///< id of category
|
||||
std::string name; ///< name of category
|
||||
std::string id; ///< id of category
|
||||
std::string name; ///< name of category
|
||||
std::string description; ///< description of category
|
||||
|
||||
std::time_t lastCached = 0;
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <shared_mutex>
|
||||
|
||||
typedef void CURL;
|
||||
struct curl_slist;
|
||||
@@ -162,10 +163,11 @@ private:
|
||||
template <typename T>
|
||||
int setOption( int aOption, T aArg );
|
||||
|
||||
CURL* m_CURL;
|
||||
curl_slist* m_headers;
|
||||
std::string m_buffer;
|
||||
std::unique_ptr<CURL_PROGRESS> progress;
|
||||
CURL* m_CURL;
|
||||
curl_slist* m_headers;
|
||||
std::string m_buffer;
|
||||
std::unique_ptr<CURL_PROGRESS> progress;
|
||||
std::shared_lock<std::shared_mutex> m_curlSharedLock;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -345,6 +345,8 @@ public:
|
||||
std::vector<GAL_LAYER_ID> Seq() const;
|
||||
|
||||
static GAL_SET DefaultVisible();
|
||||
|
||||
static GAL_SET UserVisbilityLayers();
|
||||
};
|
||||
|
||||
/// Eeschema drawing layers
|
||||
|
||||
@@ -103,6 +103,11 @@ public:
|
||||
return m_NetSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if it should be safe to auto-save this file without user action
|
||||
*/
|
||||
bool ShouldAutoSave() const { return !m_wasMigrated && !m_isFutureFormat; }
|
||||
|
||||
protected:
|
||||
wxString getFileExt() const override;
|
||||
|
||||
@@ -188,6 +193,8 @@ private:
|
||||
|
||||
/// A link to the owning PROJECT
|
||||
PROJECT* m_project;
|
||||
|
||||
bool m_wasMigrated;
|
||||
};
|
||||
|
||||
// Specializations to allow directly reading/writing FILE_INFO_PAIRs from JSON
|
||||
|
||||
@@ -71,6 +71,11 @@ public:
|
||||
|
||||
void ClearFileState();
|
||||
|
||||
/**
|
||||
* @return true if it should be safe to auto-save this file without user action
|
||||
*/
|
||||
bool ShouldAutoSave() const { return !m_wasMigrated && !m_isFutureFormat; }
|
||||
|
||||
protected:
|
||||
wxString getFileExt() const override
|
||||
{
|
||||
@@ -144,6 +149,8 @@ public:
|
||||
private:
|
||||
/// A link to the owning project
|
||||
PROJECT* m_project;
|
||||
|
||||
bool m_wasMigrated;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -332,6 +332,9 @@ protected:
|
||||
/// Version of this settings schema.
|
||||
int m_schemaVersion;
|
||||
|
||||
/// Set to true if this settings is loaded from a file with a newer schema version than is known
|
||||
bool m_isFutureFormat;
|
||||
|
||||
/// A pointer to the settings manager managing this file (may be null)
|
||||
SETTINGS_MANAGER* m_manager;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
|
||||
* Copyright (C) 2011-2012 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -105,16 +105,13 @@ public:
|
||||
long style=wxTAB_TRAVERSAL, const wxString& name=wxPanelNameStr);
|
||||
~EDA_MSG_PANEL();
|
||||
|
||||
/**
|
||||
* Return the required height (in pixels) of a EDA_MSG_PANEL.
|
||||
*
|
||||
* This takes into consideration the system gui font, wxSYS_DEFAULT_GUI_FONT.
|
||||
*/
|
||||
static int GetRequiredHeight( wxWindow* aWindow );
|
||||
|
||||
void OnPaint( wxPaintEvent& aEvent );
|
||||
void OnDPIChanged( wxDPIChangedEvent& aEvent );
|
||||
void EraseMsgBox();
|
||||
|
||||
wxSize DoGetBestSize() const override;
|
||||
wxSize DoGetBestClientSize() const override;
|
||||
|
||||
/**
|
||||
* Set a message at \a aXPosition to \a aUpperText and \a aLowerText in the message panel.
|
||||
*
|
||||
@@ -154,15 +151,12 @@ public:
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
protected:
|
||||
void updateFontSize();
|
||||
|
||||
void showItem( wxDC& dc, const MSG_PANEL_ITEM& aItem );
|
||||
|
||||
void erase( wxDC* DC );
|
||||
|
||||
/**
|
||||
* Calculate the width and height of a text string using the system UI font.
|
||||
*/
|
||||
wxSize computeTextSize( const wxString& text ) const;
|
||||
|
||||
protected:
|
||||
std::vector<MSG_PANEL_ITEM> m_Items;
|
||||
int m_last_x; ///< the last used x coordinate
|
||||
|
||||
@@ -33,6 +33,8 @@ DIALOG_UPDATE_CHECK_PROMPT::DIALOG_UPDATE_CHECK_PROMPT( wxWindow* aWindow ) :
|
||||
#ifndef KICAD_UPDATE_CHECK
|
||||
m_cbKiCadUpdates->Hide();
|
||||
#endif
|
||||
|
||||
m_sdbSizerOK->SetFocus();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -80,6 +80,8 @@
|
||||
#include "kicad_manager_frame.h"
|
||||
#include "settings/kicad_settings.h"
|
||||
|
||||
#include <project/project_file.h>
|
||||
|
||||
|
||||
#define SEP() wxFileName::GetPathSeparator()
|
||||
|
||||
@@ -220,7 +222,7 @@ KICAD_MANAGER_FRAME::KICAD_MANAGER_FRAME( wxWindow* parent, const wxString& titl
|
||||
|
||||
m_auimgr.AddPane( m_launcher, EDA_PANE().Canvas().Name( "Launcher" ).Center()
|
||||
.Caption( _( "Editors" ) ).PaneBorder( false )
|
||||
.MinSize( m_launcher->GetBestSize() ) );
|
||||
.MinSize( m_launcher->GetBestSize() + FromDIP( wxSize( 80, 20 ) ) ) );
|
||||
|
||||
m_auimgr.Update();
|
||||
|
||||
@@ -231,7 +233,11 @@ KICAD_MANAGER_FRAME::KICAD_MANAGER_FRAME( wxWindow* parent, const wxString& titl
|
||||
|
||||
// Only fit the initial window size the first time KiCad is run.
|
||||
if( mainSizer && config()->m_Window.state.size_x == 0 && config()->m_Window.state.size_y == 0 )
|
||||
{
|
||||
Layout();
|
||||
mainSizer->Fit( this );
|
||||
Center();
|
||||
}
|
||||
|
||||
if( ADVANCED_CFG::GetCfg().m_HideVersionFromTitle )
|
||||
SetTitle( wxT( "KiCad" ) );
|
||||
@@ -596,15 +602,21 @@ bool KICAD_MANAGER_FRAME::CloseProject( bool aSave )
|
||||
if( !Kiway().PlayersClose( false ) )
|
||||
return false;
|
||||
|
||||
bool shouldSaveProject = Prj().GetLocalSettings().ShouldAutoSave()
|
||||
&& Prj().GetProjectFile().ShouldAutoSave();
|
||||
|
||||
// Save the project file for the currently loaded project.
|
||||
if( m_active_project )
|
||||
{
|
||||
SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
|
||||
|
||||
mgr.TriggerBackupIfNeeded( NULL_REPORTER::GetInstance() );
|
||||
if( shouldSaveProject )
|
||||
{
|
||||
mgr.TriggerBackupIfNeeded( NULL_REPORTER::GetInstance() );
|
||||
|
||||
if( aSave )
|
||||
mgr.SaveProject();
|
||||
if( aSave )
|
||||
mgr.SaveProject();
|
||||
}
|
||||
|
||||
m_active_project = false;
|
||||
mgr.UnloadProject( &Prj() );
|
||||
|
||||
+19
-9
@@ -263,12 +263,7 @@ bool PLUGIN_CONTENT_MANAGER::FetchRepository( const wxString& aUrl, PCM_REPOSITO
|
||||
aReporter->SetTitle( _( "Fetching repository" ) );
|
||||
|
||||
if( !DownloadToStream( aUrl, &repository_stream, aReporter, 20480 ) )
|
||||
{
|
||||
if( m_dialog )
|
||||
wxLogError( _( "Unable to load repository url" ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
nlohmann::json repository_json;
|
||||
|
||||
@@ -284,7 +279,7 @@ bool PLUGIN_CONTENT_MANAGER::FetchRepository( const wxString& aUrl, PCM_REPOSITO
|
||||
{
|
||||
if( m_dialog )
|
||||
{
|
||||
wxLogError( wxString::Format( _( "Unable to parse repository: %s" ), e.what() ) );
|
||||
wxLogError( _( "Unable to parse repository: %s" ), e.what() );
|
||||
wxLogError( _( "The given repository URL does not look like a valid KiCad package "
|
||||
"repository. Please double check the URL." ) );
|
||||
}
|
||||
@@ -1094,6 +1089,22 @@ std::unordered_map<wxString, wxBitmap> PLUGIN_CONTENT_MANAGER::GetInstalledPacka
|
||||
}
|
||||
|
||||
|
||||
struct UPDATE_CANCELLER
|
||||
{
|
||||
UPDATE_CANCELLER( std::shared_ptr<BACKGROUND_JOB>& aJob ) : m_jobToCancel( aJob ) {};
|
||||
~UPDATE_CANCELLER()
|
||||
{
|
||||
if( m_jobToCancel )
|
||||
{
|
||||
Pgm().GetBackgroundJobMonitor().Remove( m_jobToCancel );
|
||||
m_jobToCancel.reset();
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<BACKGROUND_JOB>& m_jobToCancel;
|
||||
};
|
||||
|
||||
|
||||
void PLUGIN_CONTENT_MANAGER::RunBackgroundUpdate()
|
||||
{
|
||||
// If the thread is already running don't create it again
|
||||
@@ -1106,6 +1117,8 @@ void PLUGIN_CONTENT_MANAGER::RunBackgroundUpdate()
|
||||
m_updateThread = std::thread(
|
||||
[this]()
|
||||
{
|
||||
UPDATE_CANCELLER canceller( m_updateBackgroundJob );
|
||||
|
||||
if( m_installed.size() == 0 )
|
||||
return;
|
||||
|
||||
@@ -1162,9 +1175,6 @@ void PLUGIN_CONTENT_MANAGER::RunBackgroundUpdate()
|
||||
return;
|
||||
}
|
||||
|
||||
Pgm().GetBackgroundJobMonitor().Remove( m_updateBackgroundJob );
|
||||
m_updateBackgroundJob = nullptr;
|
||||
|
||||
// Update the badge on PCM button
|
||||
m_availableUpdateCallback( availableUpdateCount );
|
||||
} );
|
||||
|
||||
@@ -808,7 +808,8 @@ int KICAD_MANAGER_CONTROL::ShowPlayer( const TOOL_EVENT& aEvent )
|
||||
|
||||
// Save window state to disk now. Don't wait around for a crash.
|
||||
if( Pgm().GetCommonSettings()->m_Session.remember_open_files
|
||||
&& !player->GetCurrentFileName().IsEmpty() )
|
||||
&& !player->GetCurrentFileName().IsEmpty()
|
||||
&& Prj().GetLocalSettings().ShouldAutoSave() )
|
||||
{
|
||||
wxFileName rfn( player->GetCurrentFileName() );
|
||||
rfn.MakeRelativeTo( Prj().GetProjectPath() );
|
||||
|
||||
@@ -86,6 +86,19 @@ UPDATE_MANAGER::UPDATE_MANAGER() : m_working( false )
|
||||
}
|
||||
|
||||
|
||||
UPDATE_MANAGER::~UPDATE_MANAGER()
|
||||
{
|
||||
if( m_updateBackgroundJob )
|
||||
{
|
||||
if( m_updateBackgroundJob->m_reporter )
|
||||
m_updateBackgroundJob->m_reporter->Cancel();
|
||||
|
||||
if( m_updateTask.valid() )
|
||||
m_updateTask.wait();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int UPDATE_MANAGER::PostRequest( const wxString& aUrl, std::string aRequestBody,
|
||||
std::ostream* aOutput, PROGRESS_REPORTER* aReporter,
|
||||
const size_t aSizeLimit )
|
||||
@@ -165,12 +178,14 @@ void UPDATE_MANAGER::CheckForUpdate( wxWindow* aNoticeParent )
|
||||
|
||||
auto update_check = [aNoticeParent, this]() -> void
|
||||
{
|
||||
std::shared_ptr<BACKGROUND_JOB_REPORTER> reporter = m_updateBackgroundJob->m_reporter;
|
||||
|
||||
std::stringstream update_json_stream;
|
||||
std::stringstream request_json_stream;
|
||||
|
||||
wxString aUrl = UPDATE_QUERY_ENDPOINT;
|
||||
m_updateBackgroundJob->m_reporter->SetNumPhases( 1 );
|
||||
m_updateBackgroundJob->m_reporter->Report( _( "Requesting update info" ) );
|
||||
reporter->SetNumPhases( 1 );
|
||||
reporter->Report( _( "Requesting update info" ) );
|
||||
|
||||
UPDATE_REQUEST requestContent;
|
||||
|
||||
@@ -208,8 +223,8 @@ void UPDATE_MANAGER::CheckForUpdate( wxWindow* aNoticeParent )
|
||||
nlohmann::json requestJson = nlohmann::json( requestContent );
|
||||
request_json_stream << requestJson;
|
||||
|
||||
int responseCode =
|
||||
PostRequest( aUrl, request_json_stream.str(), &update_json_stream, NULL, 20480 );
|
||||
int responseCode = PostRequest( aUrl, request_json_stream.str(), &update_json_stream,
|
||||
reporter.get(), 20480 );
|
||||
|
||||
// Check that the response is 200 (content provided)
|
||||
// We can also return 204 for no update
|
||||
@@ -261,5 +276,5 @@ void UPDATE_MANAGER::CheckForUpdate( wxWindow* aNoticeParent )
|
||||
};
|
||||
|
||||
thread_pool& tp = GetKiCadThreadPool();
|
||||
tp.push_task( update_check );
|
||||
m_updateTask = tp.submit( update_check );
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <wx/string.h>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <future>
|
||||
|
||||
class PROGRESS_REPORTER;
|
||||
struct BACKGROUND_JOB;
|
||||
@@ -35,6 +36,7 @@ class UPDATE_MANAGER
|
||||
{
|
||||
public:
|
||||
UPDATE_MANAGER();
|
||||
~UPDATE_MANAGER();
|
||||
|
||||
void CheckForUpdate( wxWindow* aNoticeParent );
|
||||
int PostRequest( const wxString& aUrl, std::string aRequestBody, std::ostream* aOutput,
|
||||
@@ -43,4 +45,5 @@ public:
|
||||
private:
|
||||
std::atomic<bool> m_working;
|
||||
std::shared_ptr<BACKGROUND_JOB> m_updateBackgroundJob;
|
||||
std::future<void> m_updateTask;
|
||||
};
|
||||
@@ -180,6 +180,16 @@ public:
|
||||
*/
|
||||
const VECTOR2I NearestPoint( const SEG &aSeg ) const;
|
||||
|
||||
/**
|
||||
* Compute closest points between this segment and \a aSeg.
|
||||
*
|
||||
* @param aPtA point on this segment (output)
|
||||
* @param aPtB point on the other segment (output)
|
||||
* @param aDistSq squared distance between points (output)
|
||||
* @return true if the operation was successful
|
||||
*/
|
||||
bool NearestPoints( const SEG& aSeg, VECTOR2I& aPtA, VECTOR2I& aPtB, int64_t& aDistSq ) const;
|
||||
|
||||
/**
|
||||
* Reflect a point using this segment as axis.
|
||||
*
|
||||
|
||||
@@ -118,6 +118,17 @@ public:
|
||||
|
||||
VECTOR2I NearestPoint( const VECTOR2I& aP ) const;
|
||||
|
||||
|
||||
/**
|
||||
* Compute closest points between this arc and \a aArc.
|
||||
*
|
||||
* @param aPtA point on this arc (output)
|
||||
* @param aPtB point on the other arc (output)
|
||||
* @param aDistSq squared distance between points (output)
|
||||
* @return true if the operation was successful
|
||||
*/
|
||||
bool NearestPoints( const SHAPE_ARC& aArc, VECTOR2I& aPtA, VECTOR2I& aPtB, int64_t& aDistSq ) const;
|
||||
|
||||
bool Collide( const SEG& aSeg, int aClearance = 0, int* aActual = nullptr,
|
||||
VECTOR2I* aLocation = nullptr ) const override;
|
||||
bool Collide( const VECTOR2I& aP, int aClearance = 0, int* aActual = nullptr,
|
||||
|
||||
@@ -81,11 +81,10 @@ struct CLIPPER_Z_VALUE
|
||||
*/
|
||||
class SHAPE_LINE_CHAIN : public SHAPE_LINE_CHAIN_BASE
|
||||
{
|
||||
private:
|
||||
public:
|
||||
typedef std::vector<VECTOR2I>::iterator point_iter;
|
||||
typedef std::vector<VECTOR2I>::const_iterator point_citer;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Represent an intersection between two line segments
|
||||
*/
|
||||
@@ -218,6 +217,40 @@ public:
|
||||
virtual bool Collide( const SEG& aSeg, int aClearance = 0, int* aActual = nullptr,
|
||||
VECTOR2I* aLocation = nullptr ) const override;
|
||||
|
||||
/**
|
||||
* Finds closest points between this and the other line chain. Doesn't test segments or arcs.
|
||||
*
|
||||
* @param aOther the line chain to test against.
|
||||
* @param aPt0 closest point on this line chain (output).
|
||||
* @param aPt1 closest point on the other line chain (output).
|
||||
* @param aDistance distance between points (output).
|
||||
* @return true, if the operation was successful.
|
||||
*/
|
||||
bool ClosestPoints( const SHAPE_LINE_CHAIN& aOther, VECTOR2I& aPt0, VECTOR2I& aPt1 ) const;
|
||||
|
||||
static bool ClosestPoints( const point_citer& aMyStart, const point_citer& aMyEnd,
|
||||
const point_citer& aOtherStart, const point_citer& aOtherEnd,
|
||||
VECTOR2I& aPt0, VECTOR2I& aPt1, int64_t& aDistSq );
|
||||
|
||||
static bool ClosestSegments( const VECTOR2I& aMyPrevPt, const point_citer& aMyStart,
|
||||
const point_citer& aMyEnd, const VECTOR2I& aOtherPrevPt,
|
||||
const point_citer& aOtherStart, const point_citer& aOtherEnd,
|
||||
VECTOR2I& aPt0, VECTOR2I& aPt1, int64_t& aDistSq );
|
||||
|
||||
/**
|
||||
* Finds closest points between segments of this and the other line chain. Doesn't guarantee
|
||||
* that the points are the absolute closest (use ClosestSegments for that) as there might
|
||||
* be edge cases, but it is much faster.
|
||||
*
|
||||
* @param aOther the line chain to test against.
|
||||
* @param aPt0 closest point on this line chain (output).
|
||||
* @param aPt1 closest point on the other line chain (output).
|
||||
* @param aDistance distance between points (output).
|
||||
* @return true, if the operation was successful.
|
||||
*/
|
||||
bool ClosestSegmentsFast( const SHAPE_LINE_CHAIN& aOther, VECTOR2I& aPt0,
|
||||
VECTOR2I& aPt1 ) const;
|
||||
|
||||
SHAPE_LINE_CHAIN& operator=( const SHAPE_LINE_CHAIN& ) = default;
|
||||
|
||||
SHAPE* Clone() const override;
|
||||
|
||||
@@ -42,6 +42,10 @@ struct BOX2I_MINMAX
|
||||
{
|
||||
}
|
||||
|
||||
BOX2I_MINMAX( const VECTOR2I& aPt ) : BOX2I_MINMAX( aPt.x, aPt.y ) {}
|
||||
|
||||
BOX2I_MINMAX( int aX, int aY ) : m_Left( aX ), m_Top( aY ), m_Right( aX ), m_Bottom( aY ) {}
|
||||
|
||||
BOX2I_MINMAX( const BOX2I& aBox ) :
|
||||
m_Left( aBox.GetLeft() ), m_Top( aBox.GetTop() ), m_Right( aBox.GetRight() ),
|
||||
m_Bottom( aBox.GetBottom() )
|
||||
@@ -81,6 +85,31 @@ struct BOX2I_MINMAX
|
||||
return left <= right && top <= bottom;
|
||||
}
|
||||
|
||||
void Merge( const VECTOR2I& aPt )
|
||||
{
|
||||
m_Left = std::min( m_Left, aPt.x );
|
||||
m_Right = std::max( m_Right, aPt.x );
|
||||
m_Top = std::min( m_Top, aPt.y );
|
||||
m_Bottom = std::max( m_Bottom, aPt.y );
|
||||
}
|
||||
|
||||
VECTOR2I GetCenter() const
|
||||
{
|
||||
int cx = ( (int64_t) m_Left + m_Right ) / 2;
|
||||
int cy = ( (int64_t) m_Top + m_Bottom ) / 2;
|
||||
|
||||
return VECTOR2I( cx, cy );
|
||||
}
|
||||
|
||||
double GetDiameter() const
|
||||
{
|
||||
VECTOR2L start( m_Left, m_Top );
|
||||
VECTOR2L end( m_Right, m_Bottom );
|
||||
VECTOR2L d = end - start;
|
||||
|
||||
return std::hypot( d.x, d.y );
|
||||
}
|
||||
|
||||
int m_Left;
|
||||
int m_Top;
|
||||
int m_Right;
|
||||
|
||||
@@ -180,6 +180,17 @@ public:
|
||||
*/
|
||||
extended_type Dot( const VECTOR2<T>& aVector ) const;
|
||||
|
||||
/**
|
||||
* Compute the distance between two vectors. This is a double precision
|
||||
* value because the distance is frequently non-integer.
|
||||
*/
|
||||
double Distance( const VECTOR2<extended_type>& aVector ) const;
|
||||
|
||||
/**
|
||||
* Compute the squared distance between two vectors.
|
||||
*/
|
||||
constexpr extended_type SquaredDistance( const VECTOR2<T>& aVector ) const;
|
||||
|
||||
|
||||
// Operators
|
||||
|
||||
@@ -468,6 +479,22 @@ typename VECTOR2<T>::extended_type VECTOR2<T>::Dot( const VECTOR2<T>& aVector )
|
||||
(extended_type) y * (extended_type) aVector.y;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
double VECTOR2<T>::Distance( const VECTOR2<extended_type>& aVector ) const
|
||||
{
|
||||
VECTOR2<double> diff( static_cast<double>( aVector.x - x ), static_cast<double>( aVector.y - y ) );
|
||||
return diff.EuclideanNorm();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr typename VECTOR2<T>::extended_type
|
||||
VECTOR2<T>::SquaredDistance( const VECTOR2<T>& aVector ) const
|
||||
{
|
||||
const extended_type dx = (extended_type) x - aVector.x;
|
||||
const extended_type dy = (extended_type) y - aVector.y;
|
||||
return dx * dx + dy * dy;
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
bool VECTOR2<T>::operator<( const VECTOR2<T>& aVector ) const
|
||||
|
||||
@@ -147,6 +147,64 @@ const VECTOR2I SEG::NearestPoint( const SEG& aSeg ) const
|
||||
}
|
||||
|
||||
|
||||
bool SEG::NearestPoints( const SEG& aSeg, VECTOR2I& aPtA, VECTOR2I& aPtB, int64_t& aDistSq ) const
|
||||
{
|
||||
if( OPT_VECTOR2I p = Intersect( aSeg ) )
|
||||
{
|
||||
aPtA = aPtB = *p;
|
||||
aDistSq = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const VECTOR2I pts_origin[4] =
|
||||
{
|
||||
aSeg.NearestPoint( A ),
|
||||
aSeg.NearestPoint( B ),
|
||||
NearestPoint( aSeg.A ),
|
||||
NearestPoint( aSeg.B )
|
||||
};
|
||||
|
||||
const VECTOR2I* pts_a_out[4] =
|
||||
{
|
||||
&A,
|
||||
&B,
|
||||
&pts_origin[2],
|
||||
&pts_origin[3]
|
||||
};
|
||||
|
||||
const VECTOR2I* pts_b_out[4] =
|
||||
{
|
||||
&pts_origin[0],
|
||||
&pts_origin[1],
|
||||
&aSeg.A,
|
||||
&aSeg.B
|
||||
};
|
||||
|
||||
const ecoord pts_dist[4] =
|
||||
{
|
||||
( pts_origin[0] - A ).SquaredEuclideanNorm(),
|
||||
( pts_origin[1] - B ).SquaredEuclideanNorm(),
|
||||
( pts_origin[2] - aSeg.A ).SquaredEuclideanNorm(),
|
||||
( pts_origin[3] - aSeg.B ).SquaredEuclideanNorm()
|
||||
};
|
||||
|
||||
int min_i = 0;
|
||||
|
||||
for( int i = 0; i < 4; i++ )
|
||||
{
|
||||
if( pts_dist[i] < pts_dist[min_i] )
|
||||
min_i = i;
|
||||
}
|
||||
|
||||
aPtA = *pts_a_out[min_i];
|
||||
aPtB = *pts_b_out[min_i];
|
||||
aDistSq = pts_dist[min_i];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SEG::intersects( const SEG& aSeg, bool aIgnoreEndpoints, bool aLines, VECTOR2I* aPt ) const
|
||||
{
|
||||
const VECTOR2<ecoord> e = VECTOR2<ecoord>( B ) - A;
|
||||
|
||||
@@ -395,6 +395,77 @@ VECTOR2I SHAPE_ARC::NearestPoint( const VECTOR2I& aP ) const
|
||||
}
|
||||
|
||||
|
||||
bool SHAPE_ARC::NearestPoints( const SHAPE_ARC& aArc, VECTOR2I& aPtA, VECTOR2I& aPtB,
|
||||
int64_t& aDistSq ) const
|
||||
{
|
||||
aDistSq = std::numeric_limits<int64_t>::max();
|
||||
|
||||
VECTOR2I center1 = GetCenter();
|
||||
VECTOR2I center2 = aArc.GetCenter();
|
||||
|
||||
int64_t dist = center1.SquaredDistance( center2 );
|
||||
|
||||
// Start by checking endpoints
|
||||
std::vector<VECTOR2I> pts1 = { m_start, m_end };
|
||||
std::vector<VECTOR2I> pts2 = { aArc.GetP0(), aArc.GetP1() };
|
||||
|
||||
for( const VECTOR2I& pt1 : pts1 )
|
||||
{
|
||||
for( const VECTOR2I& pt2 : pts2 )
|
||||
{
|
||||
int64_t distSq = pt1.SquaredDistance( pt2 );
|
||||
|
||||
if( distSq < aDistSq )
|
||||
{
|
||||
aDistSq = distSq;
|
||||
aPtA = pt1;
|
||||
aPtB = pt2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the centers are the same, the end points are always the closest
|
||||
// or at least equidistant
|
||||
if( dist > 0 )
|
||||
{
|
||||
CIRCLE circle1( center1, GetRadius() );
|
||||
CIRCLE circle2( center2, aArc.GetRadius() );
|
||||
|
||||
// First check for intersections on the circles
|
||||
std::vector<VECTOR2I> pts = circle1.Intersect( circle2 );
|
||||
|
||||
for( const VECTOR2I& pt : pts )
|
||||
{
|
||||
if( sliceContainsPoint( pt ) && aArc.sliceContainsPoint( pt ) )
|
||||
{
|
||||
aPtA = pt;
|
||||
aPtB = pt;
|
||||
aDistSq = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for the closest points on the circles
|
||||
VECTOR2I pt1 = circle1.NearestPoint( center2 );
|
||||
VECTOR2I pt2 = circle2.NearestPoint( center1 );
|
||||
|
||||
if( sliceContainsPoint( pt1 ) && aArc.sliceContainsPoint( pt2 ) )
|
||||
{
|
||||
int64_t distSq = pt1.SquaredDistance( pt2 );
|
||||
|
||||
if( distSq < aDistSq )
|
||||
{
|
||||
aDistSq = distSq;
|
||||
aPtA = pt1;
|
||||
aPtB = pt2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SHAPE_ARC::Collide( const VECTOR2I& aP, int aClearance, int* aActual,
|
||||
VECTOR2I* aLocation ) const
|
||||
{
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <geometry/shape_line_chain.h>
|
||||
#include <geometry/shape_poly_set.h>
|
||||
#include <math/box2.h> // for BOX2I
|
||||
#include <math/box2_minmax.h>
|
||||
#include <math/util.h> // for rescale
|
||||
#include <math/vector2d.h> // for VECTOR2, VECTOR2I
|
||||
#include <trigo.h> // for RotatePoint
|
||||
@@ -547,6 +548,262 @@ void SHAPE_LINE_CHAIN::Rotate( const EDA_ANGLE& aAngle, const VECTOR2I& aCenter
|
||||
}
|
||||
|
||||
|
||||
bool SHAPE_LINE_CHAIN::ClosestSegmentsFast( const SHAPE_LINE_CHAIN& aOther, VECTOR2I& aPt0,
|
||||
VECTOR2I& aPt1 ) const
|
||||
{
|
||||
const std::vector<VECTOR2I>& myPts = m_points;
|
||||
const std::vector<VECTOR2I>& otherPts = aOther.m_points;
|
||||
|
||||
const int c_maxBoxes = 100;
|
||||
const int c_minPtsPerBox = 20;
|
||||
|
||||
int myPointsPerBox = std::max( c_minPtsPerBox, int( myPts.size() / c_maxBoxes ) + 1 );
|
||||
int otherPointsPerBox = std::max( c_minPtsPerBox, int( otherPts.size() / c_maxBoxes ) + 1 );
|
||||
|
||||
int myNumBoxes = ( myPts.size() + myPointsPerBox - 1 ) / myPointsPerBox;
|
||||
int otherNumBoxes = ( otherPts.size() + otherPointsPerBox - 1 ) / otherPointsPerBox;
|
||||
|
||||
struct BOX
|
||||
{
|
||||
BOX2I_MINMAX bbox;
|
||||
VECTOR2I center;
|
||||
int radius;
|
||||
bool valid = false;
|
||||
};
|
||||
|
||||
std::vector<BOX> myBoxes( myNumBoxes );
|
||||
std::vector<BOX> otherBoxes( otherNumBoxes );
|
||||
|
||||
// Calculate bounding boxes
|
||||
for( size_t i = 0; i < myPts.size(); i++ )
|
||||
{
|
||||
const VECTOR2I pt = myPts[i];
|
||||
BOX& box = myBoxes[i / myPointsPerBox];
|
||||
|
||||
if( box.valid )
|
||||
{
|
||||
box.bbox.Merge( pt );
|
||||
}
|
||||
else
|
||||
{
|
||||
box.bbox = BOX2I_MINMAX( pt );
|
||||
box.valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
for( size_t i = 0; i < otherPts.size(); i++ )
|
||||
{
|
||||
const VECTOR2I pt = otherPts[i];
|
||||
BOX& box = otherBoxes[i / otherPointsPerBox];
|
||||
|
||||
if( box.valid )
|
||||
{
|
||||
box.bbox.Merge( pt );
|
||||
}
|
||||
else
|
||||
{
|
||||
box.bbox = BOX2I_MINMAX( pt );
|
||||
box.valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Store centers and radiuses
|
||||
for( BOX& box : myBoxes )
|
||||
{
|
||||
box.center = box.bbox.GetCenter();
|
||||
box.radius = int( box.bbox.GetDiameter() / 2 );
|
||||
}
|
||||
|
||||
for( BOX& box : otherBoxes )
|
||||
{
|
||||
box.center = box.bbox.GetCenter();
|
||||
box.radius = int( box.bbox.GetDiameter() / 2 );
|
||||
}
|
||||
|
||||
// Find closest pairs
|
||||
struct DIST_PAIR
|
||||
{
|
||||
DIST_PAIR( int64_t aDistSq, size_t aIdA, size_t aIdB ) :
|
||||
dist( aDistSq ), idA( aIdA ), idB( aIdB )
|
||||
{
|
||||
}
|
||||
|
||||
int64_t dist;
|
||||
size_t idA;
|
||||
size_t idB;
|
||||
};
|
||||
|
||||
std::vector<DIST_PAIR> pairsToTest;
|
||||
|
||||
for( size_t ia = 0; ia < myBoxes.size(); ia++ )
|
||||
{
|
||||
for( size_t ib = 0; ib < otherBoxes.size(); ib++ )
|
||||
{
|
||||
const BOX& ca = myBoxes[ia];
|
||||
const BOX& cb = otherBoxes[ib];
|
||||
|
||||
if( !ca.valid || !cb.valid )
|
||||
continue;
|
||||
|
||||
VECTOR2L pA( ca.center );
|
||||
VECTOR2L pB( cb.center );
|
||||
|
||||
int64_t dist = ( pB - pA ).EuclideanNorm();
|
||||
|
||||
dist -= ca.radius;
|
||||
dist -= cb.radius;
|
||||
|
||||
pairsToTest.emplace_back( dist, ia, ib );
|
||||
}
|
||||
}
|
||||
|
||||
std::sort( pairsToTest.begin(), pairsToTest.end(),
|
||||
[]( const DIST_PAIR& a, const DIST_PAIR& b )
|
||||
{
|
||||
return a.dist < b.dist;
|
||||
} );
|
||||
|
||||
const int c_polyPairsLimit = 5;
|
||||
|
||||
// Find closest segments in tested pairs
|
||||
int64_t total_closest_dist_sq = VECTOR2I::ECOORD_MAX;
|
||||
|
||||
for( size_t pairId = 0; pairId < pairsToTest.size() && pairId < c_polyPairsLimit; pairId++ )
|
||||
{
|
||||
const DIST_PAIR& pair = pairsToTest[pairId];
|
||||
|
||||
VECTOR2I ptA;
|
||||
VECTOR2I ptB;
|
||||
int64_t dist_sq;
|
||||
|
||||
size_t myStartId = pair.idA * myPointsPerBox;
|
||||
size_t myEndId = myStartId + myPointsPerBox;
|
||||
|
||||
if( myEndId > myPts.size() )
|
||||
myEndId = myPts.size();
|
||||
|
||||
VECTOR2I myPrevPt = myPts[myStartId == 0 ? myPts.size() - 1 : myStartId - 1];
|
||||
|
||||
size_t otherStartId = pair.idB * otherPointsPerBox;
|
||||
size_t otherEndId = otherStartId + otherPointsPerBox;
|
||||
|
||||
if( otherEndId > otherPts.size() )
|
||||
otherEndId = otherPts.size();
|
||||
|
||||
VECTOR2I otherPrevPt = otherPts[otherStartId == 0 ? otherPts.size() - 1 : otherStartId - 1];
|
||||
|
||||
if( ClosestSegments( myPrevPt, myPts.begin() + myStartId, myPts.begin() + myEndId,
|
||||
otherPrevPt, otherPts.begin() + otherStartId,
|
||||
otherPts.begin() + otherEndId, ptA, ptB, dist_sq ) )
|
||||
{
|
||||
if( dist_sq < total_closest_dist_sq )
|
||||
{
|
||||
total_closest_dist_sq = dist_sq;
|
||||
aPt0 = ptA;
|
||||
aPt1 = ptB;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return total_closest_dist_sq != VECTOR2I::ECOORD_MAX;
|
||||
}
|
||||
|
||||
|
||||
bool SHAPE_LINE_CHAIN::ClosestSegments( const VECTOR2I& aMyPrevPt, const point_citer& aMyStart,
|
||||
const point_citer& aMyEnd, const VECTOR2I& aOtherPrevPt,
|
||||
const point_citer& aOtherStart,
|
||||
const point_citer& aOtherEnd, VECTOR2I& aPt0,
|
||||
VECTOR2I& aPt1, int64_t& aDistSq )
|
||||
{
|
||||
if( aMyStart == aMyEnd )
|
||||
return false;
|
||||
|
||||
if( aOtherStart == aOtherEnd )
|
||||
return false;
|
||||
|
||||
int64_t closest_dist_sq = VECTOR2I::ECOORD_MAX;
|
||||
VECTOR2I lastPtA = aMyPrevPt;
|
||||
|
||||
for( point_citer itA = aMyStart; itA != aMyEnd; itA++ )
|
||||
{
|
||||
const VECTOR2I& ptA = *itA;
|
||||
VECTOR2I lastPtB = aOtherPrevPt;
|
||||
|
||||
for( point_citer itB = aOtherStart; itB != aOtherEnd; itB++ )
|
||||
{
|
||||
const VECTOR2I& ptB = *itB;
|
||||
|
||||
SEG segA( lastPtA, ptA );
|
||||
SEG segB( lastPtB, ptB );
|
||||
|
||||
VECTOR2I nearestA, nearestB;
|
||||
|
||||
int64_t dist_sq;
|
||||
|
||||
if( segA.NearestPoints( segB, nearestA, nearestB, dist_sq ) )
|
||||
{
|
||||
if( dist_sq < closest_dist_sq )
|
||||
{
|
||||
closest_dist_sq = dist_sq;
|
||||
aPt0 = nearestA;
|
||||
aPt1 = nearestB;
|
||||
}
|
||||
}
|
||||
|
||||
lastPtB = ptB;
|
||||
}
|
||||
|
||||
lastPtA = ptA;
|
||||
}
|
||||
|
||||
aDistSq = closest_dist_sq;
|
||||
return closest_dist_sq != VECTOR2I::ECOORD_MAX;
|
||||
}
|
||||
|
||||
|
||||
bool SHAPE_LINE_CHAIN::ClosestPoints( const point_citer& aMyStart, const point_citer& aMyEnd,
|
||||
const point_citer& aOtherStart, const point_citer& aOtherEnd,
|
||||
VECTOR2I& aPt0, VECTOR2I& aPt1, int64_t& aDistSq )
|
||||
{
|
||||
int64_t closest_dist_sq = VECTOR2I::ECOORD_MAX;
|
||||
|
||||
for( point_citer itA = aMyStart; itA != aMyEnd; itA++ )
|
||||
{
|
||||
const VECTOR2I& ptA = *itA;
|
||||
|
||||
for( point_citer itB = aOtherStart; itB != aOtherEnd; itB++ )
|
||||
{
|
||||
const VECTOR2I& ptB = *itB;
|
||||
|
||||
ecoord dx = (ecoord) ptB.x - ptA.x;
|
||||
ecoord dy = (ecoord) ptB.y - ptA.y;
|
||||
|
||||
SEG::ecoord dist_sq = dx * dx + dy * dy;
|
||||
|
||||
if( dist_sq < closest_dist_sq )
|
||||
{
|
||||
closest_dist_sq = dist_sq;
|
||||
aPt0 = ptA;
|
||||
aPt1 = ptB;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aDistSq = closest_dist_sq;
|
||||
return closest_dist_sq != VECTOR2I::ECOORD_MAX;
|
||||
}
|
||||
|
||||
|
||||
bool SHAPE_LINE_CHAIN::ClosestPoints( const SHAPE_LINE_CHAIN& aOther, VECTOR2I& aPt0,
|
||||
VECTOR2I& aPt1 ) const
|
||||
{
|
||||
ecoord dist_sq;
|
||||
|
||||
return ClosestPoints( m_points.cbegin(), m_points.cend(), aOther.m_points.cbegin(),
|
||||
aOther.m_points.cend(), aPt0, aPt1, dist_sq );
|
||||
}
|
||||
|
||||
|
||||
bool SHAPE_LINE_CHAIN_BASE::Collide( const SEG& aSeg, int aClearance, int* aActual,
|
||||
VECTOR2I* aLocation ) const
|
||||
{
|
||||
|
||||
@@ -64,6 +64,45 @@ wxColour KIPLATFORM::UI::GetDialogBGColour()
|
||||
}
|
||||
|
||||
|
||||
void KIPLATFORM::UI::GetInfoBarColours( wxColour& aFgColour, wxColour& aBgColour )
|
||||
{
|
||||
// The GTK3.24 way of getting the colours is to use the style context
|
||||
// Earlier GTKs should be able to use the system settings
|
||||
#if( GTK_CHECK_VERSION( 3, 24, 0 ) )
|
||||
GdkRGBA* rgba;
|
||||
GtkWidgetPath* path = gtk_widget_path_new();
|
||||
GtkStyleContext* sc = gtk_style_context_new();
|
||||
gtk_widget_path_append_type( path, GTK_TYPE_WINDOW );
|
||||
gtk_widget_path_iter_set_object_name( path, -1, "infobar" );
|
||||
gtk_widget_path_iter_add_class( path, -1, "background" );
|
||||
gtk_widget_path_iter_add_class( path, -1, "info" );
|
||||
gtk_widget_path_append_type( path, G_TYPE_NONE );
|
||||
gtk_widget_path_iter_set_object_name( path, -1, "revealer" );
|
||||
gtk_widget_path_append_type( path, G_TYPE_NONE );
|
||||
gtk_widget_path_iter_set_object_name( path, -1, "box" );
|
||||
|
||||
gtk_style_context_set_path( sc, path );
|
||||
gtk_style_context_set_state( sc, GTK_STATE_FLAG_NORMAL );
|
||||
|
||||
gtk_style_context_get( sc, GTK_STATE_FLAG_NORMAL, "background-color", &rgba, NULL );
|
||||
aBgColour = wxColour(*rgba);
|
||||
gdk_rgba_free(rgba);
|
||||
|
||||
gtk_style_context_get( sc, GTK_STATE_FLAG_NORMAL, "color", &rgba, NULL );
|
||||
aFgColour = wxColour(*rgba);
|
||||
gdk_rgba_free(rgba);
|
||||
|
||||
gtk_widget_path_free( path );
|
||||
g_object_unref( sc );
|
||||
|
||||
#else
|
||||
aBgColour = wxSystemSettings::GetColour( wxSYS_COLOUR_INFOBK );
|
||||
aFgColour = wxSystemSettings::GetColour( wxSYS_COLOUR_INFOTEXT );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
void KIPLATFORM::UI::ForceFocus( wxWindow* aWindow )
|
||||
{
|
||||
aWindow->SetFocus();
|
||||
|
||||
@@ -119,6 +119,11 @@ namespace KIPLATFORM
|
||||
*/
|
||||
double GetContentScaleFactor( const wxWindow* aWindow );
|
||||
|
||||
/**
|
||||
* Return the background and foreground colors for info bars in the current scheme
|
||||
*/
|
||||
void GetInfoBarColours( wxColour& aFGColour, wxColour& aBGColour );
|
||||
|
||||
/**
|
||||
* Tries to determine the size of the viewport of a scrollable widget (wxDataViewCtrl, wxGrid)
|
||||
* that won't be obscured by scrollbars.
|
||||
|
||||
@@ -73,6 +73,13 @@ wxColour KIPLATFORM::UI::GetDialogBGColour()
|
||||
}
|
||||
|
||||
|
||||
void KIPLATFORM::UI::GetInfoBarColours( wxColour& aFGColour, wxColour& aBGColour )
|
||||
{
|
||||
aBGColour = wxSystemSettings::GetColour( wxSYS_COLOUR_INFOBK );
|
||||
aFGColour = wxSystemSettings::GetColour( wxSYS_COLOUR_INFOTEXT );
|
||||
}
|
||||
|
||||
|
||||
void KIPLATFORM::UI::ForceFocus( wxWindow* aWindow )
|
||||
{
|
||||
aWindow->SetFocus();
|
||||
|
||||
@@ -62,6 +62,18 @@ wxColour KIPLATFORM::UI::GetDialogBGColour()
|
||||
}
|
||||
|
||||
|
||||
void KIPLATFORM::UI::GetInfoBarColours( wxColour& aFGColour, wxColour& aBGColour )
|
||||
{
|
||||
aFGColour = wxSystemSettings::GetColour( wxSYS_COLOUR_INFOTEXT );
|
||||
|
||||
// wxWidgets hard-codes wxSYS_COLOUR_INFOBK to { 0xFF, 0xFF, 0xD3 } on Mac.
|
||||
if( KIPLATFORM::UI::IsDarkTheme() )
|
||||
aBGColour = wxColour( 28, 27, 20 );
|
||||
else
|
||||
aBGColour = wxColour( 255, 249, 189 );
|
||||
}
|
||||
|
||||
|
||||
void KIPLATFORM::UI::ForceFocus( wxWindow* aWindow )
|
||||
{
|
||||
// On OSX we need to forcefully give the focus to the window
|
||||
|
||||
@@ -316,7 +316,7 @@ void AR_AUTOPLACER::buildFpAreas( FOOTPRINT* aFootprint, int aFpClearance )
|
||||
if( aFootprint->GetLayer() == B_Cu )
|
||||
layerMask.set( B_Cu );
|
||||
|
||||
BOX2I fpBBox = aFootprint->GetBoundingBox();
|
||||
BOX2I fpBBox = aFootprint->GetBoundingBox( false, false );
|
||||
|
||||
fpBBox.Inflate( ( m_matrix.m_GridRouting / 2 ) + aFpClearance );
|
||||
|
||||
@@ -332,11 +332,11 @@ void AR_AUTOPLACER::buildFpAreas( FOOTPRINT* aFootprint, int aFpClearance )
|
||||
}
|
||||
|
||||
|
||||
void AR_AUTOPLACER::genModuleOnRoutingMatrix( FOOTPRINT* Module )
|
||||
void AR_AUTOPLACER::genModuleOnRoutingMatrix( FOOTPRINT* aFootprint )
|
||||
{
|
||||
int ox, oy, fx, fy;
|
||||
LSET layerMask;
|
||||
BOX2I fpBBox = Module->GetBoundingBox();
|
||||
BOX2I fpBBox = aFootprint->GetBoundingBox( false, false );
|
||||
|
||||
fpBBox.Inflate( m_matrix.m_GridRouting / 2 );
|
||||
ox = fpBBox.GetX();
|
||||
@@ -368,28 +368,28 @@ void AR_AUTOPLACER::genModuleOnRoutingMatrix( FOOTPRINT* Module )
|
||||
if( fy > m_matrix.m_BrdBox.GetBottom() )
|
||||
fy = m_matrix.m_BrdBox.GetBottom();
|
||||
|
||||
if( Module->GetLayer() == F_Cu )
|
||||
if( aFootprint->GetLayer() == F_Cu )
|
||||
layerMask.set( F_Cu );
|
||||
|
||||
if( Module->GetLayer() == B_Cu )
|
||||
if( aFootprint->GetLayer() == B_Cu )
|
||||
layerMask.set( B_Cu );
|
||||
|
||||
m_matrix.TraceFilledRectangle( ox, oy, fx, fy, layerMask,
|
||||
CELL_IS_MODULE, AR_MATRIX::WRITE_OR_CELL );
|
||||
|
||||
// Trace pads + clearance areas.
|
||||
for( PAD* pad : Module->Pads() )
|
||||
for( PAD* pad : aFootprint->Pads() )
|
||||
{
|
||||
int margin = (m_matrix.m_GridRouting / 2) + pad->GetOwnClearance( pad->GetLayer() );
|
||||
m_matrix.PlacePad( pad, CELL_IS_MODULE, margin, AR_MATRIX::WRITE_OR_CELL );
|
||||
}
|
||||
|
||||
// Trace clearance.
|
||||
int margin = ( m_matrix.m_GridRouting * Module->GetPadCount() ) / AR_GAIN;
|
||||
int margin = ( m_matrix.m_GridRouting * aFootprint->GetPadCount() ) / AR_GAIN;
|
||||
m_matrix.CreateKeepOutRectangle( ox, oy, fx, fy, margin, AR_KEEPOUT_MARGIN , layerMask );
|
||||
|
||||
// Build the footprint courtyard
|
||||
buildFpAreas( Module, margin );
|
||||
buildFpAreas( aFootprint, margin );
|
||||
|
||||
// Substract the shape to free areas
|
||||
m_topFreeArea.BooleanSubtract( m_fpAreaTop, SHAPE_POLY_SET::PM_FAST );
|
||||
@@ -513,18 +513,14 @@ int AR_AUTOPLACER::testFootprintOnBoard( FOOTPRINT* aFootprint, bool TstOtherSid
|
||||
BOX2I fpBBox = aFootprint->GetBoundingBox( false, false );
|
||||
fpBBox.Move( -1*aOffset );
|
||||
|
||||
buildFpAreas( aFootprint, 0 );
|
||||
|
||||
int diag = //testModuleByPolygon( aFootprint, side, aOffset );
|
||||
testRectangle( fpBBox, side );
|
||||
int diag = testRectangle( fpBBox, side );
|
||||
|
||||
if( diag != AR_FREE_CELL )
|
||||
return diag;
|
||||
|
||||
if( TstOtherSide )
|
||||
{
|
||||
diag = //testModuleByPolygon( aFootprint, otherside, aOffset );
|
||||
testRectangle( fpBBox, otherside );
|
||||
diag = testRectangle( fpBBox, otherside );
|
||||
|
||||
if( diag != AR_FREE_CELL )
|
||||
return diag;
|
||||
|
||||
@@ -23,7 +23,10 @@
|
||||
|
||||
|
||||
#include <board_commit.h>
|
||||
#include <dialogs/dialog_locked_items_query.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tools/pcb_actions.h>
|
||||
#include <tools/pcb_selection_tool.h>
|
||||
#include <widgets/wx_infobar.h>
|
||||
#include <widgets/wx_progress_reporters.h>
|
||||
|
||||
@@ -59,7 +62,7 @@ static int refreshCallback( FOOTPRINT* aFootprint )
|
||||
}
|
||||
|
||||
|
||||
int AUTOPLACE_TOOL::autoplace( std::vector<FOOTPRINT*>& aFootprints, bool aPlaceOffboard )
|
||||
int AUTOPLACE_TOOL::autoplace( std::vector<FOOTPRINT*>& aFootprints )
|
||||
{
|
||||
BOX2I bbox = board()->GetBoardEdgesBoundingBox();
|
||||
|
||||
@@ -73,6 +76,35 @@ int AUTOPLACE_TOOL::autoplace( std::vector<FOOTPRINT*>& aFootprints, bool aPlace
|
||||
return 0;
|
||||
}
|
||||
|
||||
int locked_count = std::count_if( aFootprints.begin(), aFootprints.end(),
|
||||
[](FOOTPRINT* fp) { return fp->IsLocked(); } );
|
||||
|
||||
if( locked_count > 0 )
|
||||
{
|
||||
DIALOG_LOCKED_ITEMS_QUERY dlg( frame(), locked_count );
|
||||
|
||||
switch( dlg.ShowModal() )
|
||||
{
|
||||
case wxID_OK:
|
||||
// Remove locked items from aFootprints
|
||||
aFootprints.erase( std::remove_if( aFootprints.begin(), aFootprints.end(),
|
||||
[]( FOOTPRINT* fp )
|
||||
{
|
||||
return fp->IsLocked();
|
||||
} ),
|
||||
aFootprints.end() );
|
||||
break;
|
||||
|
||||
case wxID_CANCEL:
|
||||
// cancel operation
|
||||
return 0;
|
||||
|
||||
case wxID_APPLY:
|
||||
// Proceed with all items (do nothing)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Activate();
|
||||
|
||||
AR_AUTOPLACER autoplacer( board() );
|
||||
@@ -89,7 +121,7 @@ int AUTOPLACE_TOOL::autoplace( std::vector<FOOTPRINT*>& aFootprints, bool aPlace
|
||||
std::make_unique<WX_PROGRESS_REPORTER>( frame(), _( "Autoplace Components" ), 1 );
|
||||
|
||||
autoplacer.SetProgressReporter( progressReporter.get() );
|
||||
auto result = autoplacer.AutoplaceFootprints( aFootprints, &commit, aPlaceOffboard );
|
||||
auto result = autoplacer.AutoplaceFootprints( aFootprints, &commit, false );
|
||||
|
||||
if( result == AR_COMPLETED )
|
||||
commit.Push( _( "Autoplace components" ) );
|
||||
@@ -107,18 +139,30 @@ int AUTOPLACE_TOOL::autoplaceSelected( const TOOL_EVENT& aEvent )
|
||||
for( EDA_ITEM* item : selection() )
|
||||
{
|
||||
if( item->Type() == PCB_FOOTPRINT_T )
|
||||
footprints.push_back( static_cast<FOOTPRINT*>( item ) );
|
||||
{
|
||||
FOOTPRINT* footprint = static_cast<FOOTPRINT*>( item );
|
||||
footprints.push_back( footprint );
|
||||
}
|
||||
}
|
||||
|
||||
return autoplace( footprints, false );
|
||||
return autoplace( footprints );
|
||||
}
|
||||
|
||||
|
||||
int AUTOPLACE_TOOL::autoplaceOffboard( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
SHAPE_POLY_SET boardShape;
|
||||
board()->GetBoardPolygonOutlines( boardShape );
|
||||
|
||||
std::vector<FOOTPRINT*> footprints;
|
||||
|
||||
return autoplace( footprints, true );
|
||||
for( FOOTPRINT* footprint : board()->Footprints() )
|
||||
{
|
||||
if( !boardShape.Contains( footprint->GetPosition() ) )
|
||||
footprints.push_back( footprint );
|
||||
}
|
||||
|
||||
return autoplace( footprints );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ public:
|
||||
void setTransitions() override;
|
||||
|
||||
private:
|
||||
int autoplace( std::vector<FOOTPRINT*>& aFootprints, bool aPlaceOffboard );
|
||||
int autoplace( std::vector<FOOTPRINT*>& aFootprints );
|
||||
|
||||
int autoplaceSelected( const TOOL_EVENT& aEvent );
|
||||
int autoplaceOffboard( const TOOL_EVENT& aEvent );
|
||||
|
||||
@@ -305,10 +305,10 @@ void SpreadFootprints( std::vector<FOOTPRINT*>* aFootprints, VECTOR2I aTargetBox
|
||||
|
||||
// Avoid too large coordinates: Overlapping components
|
||||
// are better than out of screen components
|
||||
if( (uint64_t) target_pos.x + (uint64_t) target_size.x > INT_MAX / 2 )
|
||||
if( (int64_t) target_pos.x + (int64_t) target_size.x > INT_MAX / 2 )
|
||||
target_pos.x -= INT_MAX / 2;
|
||||
|
||||
if( (uint64_t) target_pos.y + (uint64_t) target_size.y > INT_MAX / 2 )
|
||||
if( (int64_t) target_pos.y + (int64_t) target_size.y > INT_MAX / 2 )
|
||||
target_pos.y -= INT_MAX / 2;
|
||||
|
||||
for( auto& [fpSize, fpPair] : sizeToFpMap )
|
||||
|
||||
@@ -683,7 +683,7 @@ void BOARD_COMMIT::Revert()
|
||||
|
||||
BOARD_ITEM* parent = board->GetItem( ent.m_parent );
|
||||
|
||||
if( parent->Type() == PCB_FOOTPRINT_T )
|
||||
if( parent && parent->Type() == PCB_FOOTPRINT_T )
|
||||
{
|
||||
static_cast<FOOTPRINT*>( parent )->Add( boardItem, ADD_MODE::INSERT );
|
||||
}
|
||||
|
||||
@@ -349,16 +349,14 @@ bool doConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aShapeList, SHAPE_POLY_
|
||||
std::swap( pstart, pend );
|
||||
}
|
||||
|
||||
// Snap the arc start point to avoid potential self-intersections
|
||||
pstart = prevPt;
|
||||
|
||||
SHAPE_ARC sarc( pstart, pmid, pend, 0 );
|
||||
|
||||
SHAPE_LINE_CHAIN arcChain;
|
||||
arcChain.Append( sarc, aErrorMax );
|
||||
|
||||
// if this arc is after another object, pop off the first point
|
||||
// the previous point from the last object should be already close enough as part of chaining
|
||||
if( prevGraphic != nullptr )
|
||||
arcChain.Remove( 0 );
|
||||
|
||||
if( !aAllowUseArcsInPolygons )
|
||||
arcChain.ClearArcs();
|
||||
|
||||
@@ -453,6 +451,47 @@ bool doConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aShapeList, SHAPE_POLY_
|
||||
// Finished, or ran into trouble...
|
||||
if( close_enough( startPt, prevPt, aChainingEpsilon ) )
|
||||
{
|
||||
if( startPt != prevPt && currContour.PointCount() > 2 )
|
||||
{
|
||||
// Snap the last shape's endpoint to the outline startpoint
|
||||
PCB_SHAPE* owner = fetchOwner( currContour.CSegment( -1 ) );
|
||||
|
||||
if( currContour.IsArcEnd( currContour.PointCount() - 1 ) )
|
||||
{
|
||||
SHAPE_ARC arc = currContour.Arc(
|
||||
currContour.ArcIndex( currContour.PointCount() - 1 ) );
|
||||
|
||||
// Snap the arc endpoint
|
||||
SHAPE_ARC sarc( arc.GetP0(), arc.GetArcMid(), startPt, 0 );
|
||||
|
||||
SHAPE_LINE_CHAIN arcChain;
|
||||
arcChain.Append( sarc, aErrorMax );
|
||||
|
||||
if( !aAllowUseArcsInPolygons )
|
||||
arcChain.ClearArcs();
|
||||
|
||||
// Set shapeOwners for arcChain points created by appending the sarc:
|
||||
for( int ii = 1; ii < arcChain.PointCount(); ++ii )
|
||||
{
|
||||
shapeOwners[std::make_pair( arcChain.CPoint( ii - 1 ),
|
||||
arcChain.CPoint( ii ) )] = owner;
|
||||
}
|
||||
|
||||
currContour.RemoveShape( currContour.PointCount() - 1 );
|
||||
currContour.Append( arcChain );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Snap the segment endpoint
|
||||
currContour.SetPoint( -1, startPt );
|
||||
|
||||
shapeOwners[std::make_pair( currContour.CPoint( -2 ),
|
||||
currContour.CPoint( -1 ) )] = owner;
|
||||
}
|
||||
|
||||
prevPt = startPt;
|
||||
}
|
||||
|
||||
currContour.SetClosed( true );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -683,11 +683,11 @@ bool DIALOG_BOARD_REANNOTATE::BuildFootprintList( std::vector<REFDES_INFO>& aBad
|
||||
}
|
||||
else
|
||||
exclude += thischar;
|
||||
|
||||
if( !exclude.empty() )
|
||||
m_excludeArray.push_back( exclude );
|
||||
}
|
||||
|
||||
if( !exclude.empty() ) // last item to exclude
|
||||
m_excludeArray.push_back( exclude );
|
||||
|
||||
REFDES_INFO fpData;
|
||||
bool useModuleLocation = m_locationChoice->GetSelection() == 0;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.0-39-g3487c3cb)
|
||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -161,9 +161,6 @@ DIALOG_BOARD_REANNOTATE_BASE::DIALOG_BOARD_REANNOTATE_BASE( wxWindow* parent, wx
|
||||
|
||||
bSizerOpts->Add( fgSizerLocations, 0, wxEXPAND|wxALL, 10 );
|
||||
|
||||
|
||||
bSizerOpts->Add( 0, 15, 0, wxEXPAND, 5 );
|
||||
|
||||
wxStaticText* stScopeLabel;
|
||||
stScopeLabel = new wxStaticText( m_StandardOptions, wxID_ANY, _("Reannotation Scope"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
stScopeLabel->Wrap( -1 );
|
||||
@@ -232,16 +229,6 @@ DIALOG_BOARD_REANNOTATE_BASE::DIALOG_BOARD_REANNOTATE_BASE( wxWindow* parent, wx
|
||||
|
||||
gbSizer1->Add( m_BackRefDesStart, wxGBPosition( 0, 4 ), wxGBSpan( 1, 1 ), wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_RemoveFrontPrefix = new wxCheckBox( m_Advanced, wxID_ANY, _("Remove front prefix"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_RemoveFrontPrefix->SetToolTip( _("If checked will remove the front side prefix\nin the front prefix box if present") );
|
||||
|
||||
gbSizer1->Add( m_RemoveFrontPrefix, wxGBPosition( 2, 0 ), wxGBSpan( 1, 2 ), wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 );
|
||||
|
||||
m_RemoveBackPrefix = new wxCheckBox( m_Advanced, wxID_ANY, _("Remove back prefix"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_RemoveBackPrefix->SetToolTip( _("If checked will remove the Back side prefix\nin the back prefix box if present") );
|
||||
|
||||
gbSizer1->Add( m_RemoveBackPrefix, wxGBPosition( 2, 3 ), wxGBSpan( 1, 2 ), wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 );
|
||||
|
||||
m_FrontPrefixText = new wxStaticText( m_Advanced, wxID_ANY, _("Front prefix:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_FrontPrefixText->Wrap( -1 );
|
||||
m_FrontPrefixText->SetToolTip( _("Optional prefix for component side reference designations (e.g. F_)") );
|
||||
@@ -264,6 +251,16 @@ DIALOG_BOARD_REANNOTATE_BASE::DIALOG_BOARD_REANNOTATE_BASE( wxWindow* parent, wx
|
||||
|
||||
gbSizer1->Add( m_BackPrefix, wxGBPosition( 1, 4 ), wxGBSpan( 1, 1 ), wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_RemoveFrontPrefix = new wxCheckBox( m_Advanced, wxID_ANY, _("Remove front prefix"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_RemoveFrontPrefix->SetToolTip( _("If checked will remove the front side prefix\nin the front prefix box if present") );
|
||||
|
||||
gbSizer1->Add( m_RemoveFrontPrefix, wxGBPosition( 2, 0 ), wxGBSpan( 1, 2 ), wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 );
|
||||
|
||||
m_RemoveBackPrefix = new wxCheckBox( m_Advanced, wxID_ANY, _("Remove back prefix"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_RemoveBackPrefix->SetToolTip( _("If checked will remove the Back side prefix\nin the back prefix box if present") );
|
||||
|
||||
gbSizer1->Add( m_RemoveBackPrefix, wxGBPosition( 2, 3 ), wxGBSpan( 1, 2 ), wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 );
|
||||
|
||||
m_ExcludeLocked = new wxCheckBox( m_Advanced, wxID_ANY, _("Exclude locked footprints"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_ExcludeLocked->SetToolTip( _("Locked footprints will not be reannotated") );
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.0-39-g3487c3cb)
|
||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -38,7 +38,6 @@ class WX_HTML_REPORT_PANEL;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class DIALOG_BOARD_REANNOTATE_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -80,12 +79,12 @@ class DIALOG_BOARD_REANNOTATE_BASE : public DIALOG_SHIM
|
||||
wxTextCtrl* m_FrontRefDesStart;
|
||||
wxStaticText* m_BottomRefDesStartText;
|
||||
wxTextCtrl* m_BackRefDesStart;
|
||||
wxCheckBox* m_RemoveFrontPrefix;
|
||||
wxCheckBox* m_RemoveBackPrefix;
|
||||
wxStaticText* m_FrontPrefixText;
|
||||
wxTextCtrl* m_FrontPrefix;
|
||||
wxStaticText* m_BackPrefixText;
|
||||
wxTextCtrl* m_BackPrefix;
|
||||
wxCheckBox* m_RemoveFrontPrefix;
|
||||
wxCheckBox* m_RemoveBackPrefix;
|
||||
wxCheckBox* m_ExcludeLocked;
|
||||
wxStaticText* m_ExcludeListText;
|
||||
wxTextCtrl* m_ExcludeList;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user