Compare commits
411 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8a3464bdf1 | |||
| 51646e6605 | |||
| e962686afb | |||
| 9211d60d7b | |||
| 632c03a874 | |||
| 24d2eded07 | |||
| d3a5bf20db | |||
| 099e0d1312 | |||
| 3c1bc31456 | |||
| 2fffc9780b | |||
| 68bfa2001e | |||
| ebdf4c7719 | |||
| f944b662b6 | |||
| 3ac9bace21 | |||
| 98141d0143 | |||
| d90d86775b | |||
| 578d0a5a4a | |||
| 53075ee9f3 | |||
| 7f19d051ed | |||
| 364cf0808f | |||
| d3cce1e35c | |||
| 1b20a932ad | |||
| 3b0dac9491 | |||
| 4433da15b1 | |||
| e4af447855 | |||
| ecd4326533 | |||
| 73854bc9f1 | |||
| 544c035298 | |||
| c8da489b1f | |||
| da6f97b24f | |||
| 464d248b8c | |||
| b790b46c76 | |||
| b4a5422e54 | |||
| 565d54a184 | |||
| ebcf96dcd6 | |||
| e067a8ddc8 | |||
| 4d8feb94bd | |||
| 2374e5e542 | |||
| a3e4a001bb | |||
| edc25f8ba0 | |||
| 10a03972d4 | |||
| 5a3c210b7c | |||
| 239eb5a1ff | |||
| c1a1bbc96b | |||
| c16076a5c3 | |||
| 77ab6c29bf | |||
| 9366902052 | |||
| 86b687bdaf | |||
| 1da4895619 | |||
| fbf9a45a00 | |||
| c6c2d6468d | |||
| b349140112 | |||
| 5dafadb12c | |||
| da1f71684c | |||
| 563a2d20b7 | |||
| f31450018d | |||
| c329ba2b4c | |||
| fe42b1fd6b | |||
| 66628a3501 | |||
| e21ebbff76 | |||
| 7df0a80eed | |||
| 790dee114b | |||
| 3f17abba60 | |||
| dbca140d17 | |||
| d563588b28 | |||
| 4503abdf80 | |||
| d670be0007 | |||
| f55873fc3d | |||
| 330437ee8d | |||
| 61648be38a | |||
| 58584cb227 | |||
| 4cab605fb6 | |||
| 57f6d1c015 | |||
| 57df0435bf | |||
| 46312674c6 | |||
| 32781c3992 | |||
| 48b3408f9a | |||
| e892783109 | |||
| 5865431759 | |||
| d75d0ef686 | |||
| baf4843a45 | |||
| 57309d4a62 | |||
| a9ad99f513 | |||
| 5a459ce982 | |||
| 32626dfa1d | |||
| 3406f20a5c | |||
| 2fedbaac2e | |||
| b3f7e2e827 | |||
| 6430bd6c61 | |||
| cb51d324b7 | |||
| 1eb9accb1e | |||
| fb8716f16a | |||
| 1bdeebf13d | |||
| 3688a9ca61 | |||
| 94370cc6d8 | |||
| 186839b245 | |||
| c70653c9dc | |||
| ed59993fc3 | |||
| fec37a0f79 | |||
| 7a4ab8971c | |||
| 76cff2e7aa | |||
| e95aab5df6 | |||
| 0b1fee9f7f | |||
| 8a5c51d37f | |||
| d288dce1d0 | |||
| 89b92fe3f5 | |||
| cb7385bf0c | |||
| ec6af273bb | |||
| 0dd4d0e46c | |||
| 2d0c5dc8bd | |||
| 95418742e9 | |||
| 53d0d60f33 | |||
| bf1dbde3c3 | |||
| 2b1b1b4fcb | |||
| a1066bac65 | |||
| a30498a572 | |||
| 5403990121 | |||
| 2deacd59ef | |||
| 7d67775f45 | |||
| c5ef10cf2c | |||
| 04d0719269 | |||
| f143ce563f | |||
| 5792a02825 | |||
| 0dc0061d30 | |||
| 2116e272b5 | |||
| 25c14ae7cb | |||
| 3a8fc4dd82 | |||
| 5558dce259 | |||
| 8fe891a475 | |||
| 501b63028b | |||
| b7d7403e6f | |||
| c0648c4728 | |||
| a33003cf62 | |||
| 1d577cf917 | |||
| d189c6ddbf | |||
| f781ec82c9 | |||
| 3a33a5b506 | |||
| 4436d93446 | |||
| 238612d2c2 | |||
| f787c01b47 | |||
| f8e60b11c9 | |||
| 0f07c4ef78 | |||
| 6fcfcd28ca | |||
| 1773eb2b1c | |||
| 45bdde41b3 | |||
| 292faaa48d | |||
| 44c473c1b3 | |||
| 85474345d6 | |||
| fda292bd08 | |||
| c666bf8626 | |||
| 96f20d102b | |||
| f57cdb52dd | |||
| a5d2294ec3 | |||
| 72fdb41b73 | |||
| 2ca04123d4 | |||
| 07a4710363 | |||
| c01e37304f | |||
| 52b57b1145 | |||
| 7b4e444f6c | |||
| a9f4f85746 | |||
| bc7ece44eb | |||
| 51cc22a4f2 | |||
| 38f2541a3f | |||
| a05e3de852 | |||
| 908e7205e7 | |||
| a80e410683 | |||
| fa234e4b58 | |||
| fb82e722e1 | |||
| b45f9e7392 | |||
| d496b281ef | |||
| 2a46ff370a | |||
| 44d0b27544 | |||
| 7d76868c5c | |||
| e4d9d1829f | |||
| e585948861 | |||
| e31b177335 | |||
| 4624d57bc2 | |||
| 4f2d1ec5a1 | |||
| 5bcb3edae1 | |||
| 30fbfd53c1 | |||
| dc979be459 | |||
| 450c4517b5 | |||
| 47cd4d6b7a | |||
| 8842c575c3 | |||
| 858c23f731 | |||
| 1d879d51c5 | |||
| 6e0df489eb | |||
| a9be5c5759 | |||
| 258e2fd46f | |||
| f5852f0869 | |||
| 1d0adbc5d6 | |||
| 34834fd963 | |||
| 2f095aeafb | |||
| 47bb72179f | |||
| 9f7af4a3a7 | |||
| dda127ceec | |||
| 68e6e0a742 | |||
| a844ba713a | |||
| 5d75bd0f0a | |||
| c492565ee8 | |||
| 879d2bef4b | |||
| 05376a39ac | |||
| 9c01c2aeb8 | |||
| 72db7bfedc | |||
| 95cfe2cc2e | |||
| c6f5daf87f | |||
| b1711d692a | |||
| d538182f1f | |||
| b4b87b5c38 | |||
| eed95e612d | |||
| 68d3c7f5c2 | |||
| 848d5484d8 | |||
| d3b84f219c | |||
| 58ccf62d2f | |||
| 021229647f | |||
| 9a812bc63c | |||
| 8a9201b79c | |||
| f8e9b3402f | |||
| 808c645933 | |||
| ea467c1bac | |||
| c51b6a0cd2 | |||
| 10f16ed82e | |||
| ab9cf326e8 | |||
| 4e6087c183 | |||
| e7abf472ba | |||
| f0c6b57ab9 | |||
| e830709cda | |||
| 415aac7fc5 | |||
| 21f15c3b2a | |||
| 0f8df0bcee | |||
| d6ef6252a2 | |||
| f13c9cbd49 | |||
| c2af66a44b | |||
| 40c50c94fb | |||
| 0103f92d0e | |||
| 0f27f8b7fc | |||
| 5631b61dbc | |||
| da659f5d05 | |||
| 2029c5389f | |||
| 4205e70775 | |||
| 4f66225de7 | |||
| 18e4682c3a | |||
| 6b540ae1e3 | |||
| 1f12b6c17d | |||
| e2c23c70f1 | |||
| f60f0394be | |||
| bd64bcf446 | |||
| 176d0f5820 | |||
| 118ee1c072 | |||
| fd15a1108b | |||
| 43b5d4d91f | |||
| d11ab8201f | |||
| 86bae558b4 | |||
| 68991a7644 | |||
| 0701640c5a | |||
| 9fe656a33c | |||
| 3fb8f22fd3 | |||
| 929930fb3a | |||
| 4195b874d5 | |||
| ae0d6c80dd | |||
| 4e2f84727c | |||
| 35889130e8 | |||
| 2e7145cc4b | |||
| e0d955993c | |||
| cd7a646fcc | |||
| cb2a09d17c | |||
| d0cb210427 | |||
| b89d77bf36 | |||
| 7fdeb4796a | |||
| e82088a59b | |||
| 5a5191361f | |||
| b47f8f4504 | |||
| 00ae91d6b5 | |||
| 097e0eadf1 | |||
| c8c293dca8 | |||
| e6cfd1cdcf | |||
| 905170b4f4 | |||
| 57fa8ea2b9 | |||
| c7730a00c4 | |||
| beaaf3b5be | |||
| b644f15d7f | |||
| af398762db | |||
| dfd40b566d | |||
| e056ef2693 | |||
| 02d0944546 | |||
| 1aba70ca37 | |||
| ff8b82d060 | |||
| 68d1e3223a | |||
| 9e64d52a38 | |||
| f7b3c0226b | |||
| 17fc05ec45 | |||
| b64f1f2bd3 | |||
| b32d8862da | |||
| ff061e51a0 | |||
| 6020e6d6f9 | |||
| a3fffc868f | |||
| 9670aa1b8a | |||
| 85ba5ae406 | |||
| faa3287fd6 | |||
| 33ab1d9242 | |||
| 01aa2d7e42 | |||
| b24e2ac00d | |||
| 2bc3ef82dc | |||
| 672ba5cd41 | |||
| 905b9ae6c5 | |||
| f81a203c22 | |||
| 7aa0431a60 | |||
| 57505674f8 | |||
| 558bef00cc | |||
| 28f9bd797a | |||
| 52d6fc66f1 | |||
| ab49e9b29d | |||
| f6710e64de | |||
| 804154e21d | |||
| 03cb8521bc | |||
| 3ee940e3fb | |||
| 8b25c3b0fe | |||
| 529cf246d2 | |||
| 7e7c281a64 | |||
| 350925f10a | |||
| 5e8982600a | |||
| e633af9216 | |||
| b0f21e5452 | |||
| d2d582cc00 | |||
| 4f11681c4a | |||
| 897ebee00f | |||
| be0a42a09a | |||
| 3069799a2d | |||
| ad22e53518 | |||
| 2ef05eb191 | |||
| 235e583182 | |||
| 76ce4ec535 | |||
| 0226481156 | |||
| 8fab2d8ca3 | |||
| 1c6d8b3f5e | |||
| 32e9ab9b75 | |||
| ca0207016e | |||
| 9ca1bf63d9 | |||
| 7e13870ae3 | |||
| 3c907b5589 | |||
| e9efd9971c | |||
| 2bf9a6f5d1 | |||
| 42c67b40b1 | |||
| 5ae3c55a99 | |||
| 54e9a97b26 | |||
| 1e3b879d93 | |||
| 7ca6a93436 | |||
| 05c11d023f | |||
| 996c3d7fa1 | |||
| b204742fe3 | |||
| 2b8e62e0b9 | |||
| c3d122becf | |||
| 43c828474a | |||
| 8073185c36 | |||
| f1ddcfe799 | |||
| 9d6f9c84d0 | |||
| 680a693c04 | |||
| 4f72dd421a | |||
| bc533de0a3 | |||
| c08109d63e | |||
| b11f0a31b9 | |||
| f6fabdc8ee | |||
| 965abb46d0 | |||
| c9f53c607e | |||
| 7b91b51bcf | |||
| a3354dc352 | |||
| 6723964cdd | |||
| df5f4ba541 | |||
| 926f41a0f5 | |||
| db801c8d7e | |||
| ad433b9468 | |||
| 1eefb2b70a | |||
| 3d6527c1be | |||
| 319530ad01 | |||
| 24efca1db1 | |||
| a009d859d0 | |||
| 44a3bb9274 | |||
| 72e1904708 | |||
| 279a30974e | |||
| efc6c3e45e | |||
| f7380ae015 | |||
| 26b6c28bef | |||
| 8cd7b73b2a | |||
| c2d31699bf | |||
| 47c5918c3d | |||
| 12cf3f9301 | |||
| 013aab58d6 | |||
| 316a9511e8 | |||
| 29fadcb931 | |||
| d73fecd2a1 | |||
| 35caf91c31 | |||
| 352cf21ffc | |||
| 21335f604f | |||
| c6b7f90408 | |||
| a5dee0c2b1 | |||
| bf73ad42ca | |||
| 7d905948f5 | |||
| 5c8c0e0648 | |||
| 4cfa2e3a38 | |||
| eecf0cd685 | |||
| 91e5e81bb4 | |||
| 5b3cd96641 | |||
| db0967d5c9 | |||
| 5165ced528 | |||
| eb4f9fa093 | |||
| 47381f3d90 | |||
| e697339bc6 | |||
| 6159cee2b0 | |||
| 3460b33ccf | |||
| 5baaa89131 | |||
| d45a38f086 |
@@ -8,6 +8,7 @@ win64_build:
|
||||
interruptible: false
|
||||
image: registry.gitlab.com/kicad/kicad-ci/windows-build-image/ltsc2022-msvc:latest
|
||||
variables:
|
||||
VCPKG_BINARY_SOURCES: 'nuget,gitlab,readwrite'
|
||||
# Switch the compressor to fastzip and reduce the compression level
|
||||
FF_USE_FASTZIP: "true"
|
||||
CACHE_COMPRESSION_LEVEL: "fast"
|
||||
@@ -23,6 +24,7 @@ win64_build:
|
||||
script:
|
||||
- C:\builder\build.ps1 -Env -Arch x64
|
||||
- $vcpkgCache=Join-Path -Path (Get-Location) -ChildPath ".vcpkgCache";$env:VCPKG_DEFAULT_BINARY_CACHE=$vcpkgCache;New-Item -ItemType Directory -Force -Path $vcpkgCache
|
||||
- nuget.exe sources add -Name gitlab -Source "https://gitlab.com/api/v4/projects/27426693/packages/nuget/index.json" -UserName gitlab-ci-token -Password $env:CI_JOB_TOKEN
|
||||
- mkdir -p build/windows -Force
|
||||
- cd build/windows
|
||||
- cmake `
|
||||
@@ -34,6 +36,8 @@ win64_build:
|
||||
-DKICAD_BUILD_PNS_DEBUG_TOOL=ON `
|
||||
-DKICAD_USE_3DCONNEXION=ON `
|
||||
-DVCPKG_BUILD_TYPE=debug `
|
||||
-DVCPKG_INSTALL_OPTIONS="--x-abi-tools-use-exact-versions" `
|
||||
-DVCPKG_OVERLAY_TRIPLETS="$Env:CI_PROJECT_DIR/tools/custom_vcpkg_triplets" `
|
||||
../../
|
||||
- cmake --build . 2>&1 | tee compilation_log.txt
|
||||
- cd ../../
|
||||
|
||||
@@ -486,9 +486,12 @@ void RENDER_3D_RAYTRACE_BASE::renderBlockTracing( uint8_t* ptrPBO, signed int iB
|
||||
// Initialize ray packets
|
||||
const SFVEC2UI& blockPos = m_blockPositions[iBlock];
|
||||
const SFVEC2I blockPosI = SFVEC2I( blockPos.x + m_xoffset, blockPos.y + m_yoffset );
|
||||
const SFVEC2F randDisp = ( m_camera.GetProjection() == PROJECTION_TYPE::ORTHO ) ?
|
||||
SFVEC2F( 0.0f, 0.0f ) :
|
||||
SFVEC2F( DISP_FACTOR, DISP_FACTOR );
|
||||
|
||||
RAYPACKET blockPacket( m_camera, (SFVEC2F) blockPosI + SFVEC2F( DISP_FACTOR, DISP_FACTOR ),
|
||||
SFVEC2F( DISP_FACTOR, DISP_FACTOR ) /* Displacement random factor */ );
|
||||
RAYPACKET blockPacket( m_camera, (SFVEC2F) blockPosI + randDisp,
|
||||
randDisp /* Displacement random factor */ );
|
||||
|
||||
|
||||
HITINFO_PACKET hitPacket_X0Y0[RAYPACKET_RAYS_PER_PACKET];
|
||||
@@ -566,7 +569,7 @@ void RENDER_3D_RAYTRACE_BASE::renderBlockTracing( uint8_t* ptrPBO, signed int iB
|
||||
HITINFO_PACKET_init( hitPacket_AA_X1Y1 );
|
||||
|
||||
RAYPACKET blockPacket_AA_X1Y1( m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.5f, 0.5f ),
|
||||
SFVEC2F( DISP_FACTOR, DISP_FACTOR ) );
|
||||
randDisp );
|
||||
|
||||
if( !m_accelerator->Intersect( blockPacket_AA_X1Y1, hitPacket_AA_X1Y1 ) )
|
||||
{
|
||||
@@ -603,16 +606,16 @@ void RENDER_3D_RAYTRACE_BASE::renderBlockTracing( uint8_t* ptrPBO, signed int iB
|
||||
RAY blockRayPck_AA_X1Y1_half[RAYPACKET_RAYS_PER_PACKET];
|
||||
|
||||
RAYPACKET_InitRays_with2DDisplacement(
|
||||
m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.5f - DISP_FACTOR, DISP_FACTOR ),
|
||||
SFVEC2F( DISP_FACTOR, DISP_FACTOR ), blockRayPck_AA_X1Y0 );
|
||||
m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.5f - randDisp.x, randDisp.y ),
|
||||
randDisp, blockRayPck_AA_X1Y0 );
|
||||
|
||||
RAYPACKET_InitRays_with2DDisplacement(
|
||||
m_camera, (SFVEC2F) blockPosI + SFVEC2F( DISP_FACTOR, 0.5f - DISP_FACTOR ),
|
||||
SFVEC2F( DISP_FACTOR, DISP_FACTOR ), blockRayPck_AA_X0Y1 );
|
||||
m_camera, (SFVEC2F) blockPosI + SFVEC2F( randDisp.x, 0.5f - randDisp.y ),
|
||||
randDisp, blockRayPck_AA_X0Y1 );
|
||||
|
||||
RAYPACKET_InitRays_with2DDisplacement(
|
||||
m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.25f - DISP_FACTOR, 0.25f - DISP_FACTOR ),
|
||||
SFVEC2F( DISP_FACTOR, DISP_FACTOR ), blockRayPck_AA_X1Y1_half );
|
||||
m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.25f - randDisp.x, 0.25f - randDisp.y ),
|
||||
randDisp, blockRayPck_AA_X1Y1_half );
|
||||
|
||||
renderAntiAliasPackets( bgColor, hitPacket_X0Y0, hitPacket_AA_X1Y1, blockRayPck_AA_X1Y0,
|
||||
hitColor_AA_X1Y0 );
|
||||
|
||||
@@ -657,6 +657,12 @@ void PANEL_PREVIEW_3D_MODEL::UpdateDummyFootprint( bool aReloadRequired )
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREVIEW_3D_MODEL::SetEmbeddedFilesDelegate( EMBEDDED_FILES* aDelegate )
|
||||
{
|
||||
m_dummyBoard->SetEmbeddedFilesDelegate( aDelegate );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREVIEW_3D_MODEL::onModify()
|
||||
{
|
||||
KIWAY_HOLDER* kiwayHolder = dynamic_cast<KIWAY_HOLDER*>( wxGetTopLevelParent( this ) );
|
||||
|
||||
@@ -59,6 +59,7 @@ wxDECLARE_EVENT( wxCUSTOM_PANEL_SHOWN_EVENT, wxCommandEvent );
|
||||
class WX_INFOBAR;
|
||||
class S3D_CACHE;
|
||||
class FILENAME_RESOLVER;
|
||||
class EMBEDDED_FILES;
|
||||
class BOARD;
|
||||
class BOARD_ADAPTER;
|
||||
class FOOTPRINT;
|
||||
@@ -97,6 +98,8 @@ public:
|
||||
*/
|
||||
void UpdateDummyFootprint( bool aRelaodRequired = true );
|
||||
|
||||
void SetEmbeddedFilesDelegate( EMBEDDED_FILES* aDelegate );
|
||||
|
||||
/**
|
||||
* Get the dummy footprint that is used for previewing the 3D model.
|
||||
* We use this to hold the temporary 3D model shapes.
|
||||
|
||||
+6
-1
@@ -22,7 +22,12 @@
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
#
|
||||
|
||||
cmake_minimum_required( VERSION 3.21 FATAL_ERROR )
|
||||
if( MSVC )
|
||||
# CMake 3.28.1 or higher required for MSVC ARM builds for armasm64.exe support
|
||||
cmake_minimum_required( VERSION 3.28.1 FATAL_ERROR )
|
||||
else()
|
||||
cmake_minimum_required( VERSION 3.21 FATAL_ERROR )
|
||||
endif()
|
||||
|
||||
# Generate DEPFILES without transforming relative paths
|
||||
cmake_policy( SET CMP0116 OLD )
|
||||
|
||||
@@ -6,7 +6,12 @@
|
||||
},
|
||||
{
|
||||
"environment": "vcpkg",
|
||||
"VcPkgDir": "D:/vcpkg/"
|
||||
"VcPkgDir": "D:/vcpkg/",
|
||||
"VCPKG_BINARY_SOURCES": "nuget,kicad-gitlab,read"
|
||||
},
|
||||
{
|
||||
"environment": "swig",
|
||||
"SwigExePath": "D:/swigwin-4.1.1/swig.exe"
|
||||
}
|
||||
],
|
||||
"configurations": [
|
||||
@@ -14,7 +19,7 @@
|
||||
"name": "x64-Debug",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Debug",
|
||||
"inheritEnvironments": [ "msvc_x64_x64", "vcpkg" ],
|
||||
"inheritEnvironments": [ "msvc_x64_x64", "vcpkg", "swig"],
|
||||
"buildRoot": "${env.BuildDir}\\${name}",
|
||||
"installRoot": "${env.InstallDir}\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
@@ -30,6 +35,21 @@
|
||||
"name": "KICAD_WIN32_DPI_AWARE",
|
||||
"value": "ON",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "SWIG_EXECUTABLE",
|
||||
"value": "${env.SwigExePath}",
|
||||
"type": "STRING"
|
||||
},
|
||||
{
|
||||
"name": "VCPKG_OVERLAY_TRIPLETS",
|
||||
"value": "${workspaceRoot}/tools/custom_vcpkg_triplets",
|
||||
"type": "STRING"
|
||||
},
|
||||
{
|
||||
"name": "VCPKG_INSTALL_OPTIONS",
|
||||
"value": "--x-abi-tools-use-exact-versions",
|
||||
"type": "STRING"
|
||||
}
|
||||
],
|
||||
"cmakeToolchain": "${env.VcPkgDir}/scripts/buildsystems/vcpkg.cmake"
|
||||
@@ -38,7 +58,7 @@
|
||||
"name": "x64-Release",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "RelWithDebInfo",
|
||||
"inheritEnvironments": [ "msvc_x64_x64", "vcpkg" ],
|
||||
"inheritEnvironments": [ "msvc_x64_x64", "vcpkg", "swig"],
|
||||
"buildRoot": "${env.BuildDir}\\${name}",
|
||||
"installRoot": "${env.InstallDir}\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
@@ -54,6 +74,21 @@
|
||||
"name": "KICAD_WIN32_DPI_AWARE",
|
||||
"value": "ON",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "SWIG_EXECUTABLE",
|
||||
"value": "${env.SwigExePath}",
|
||||
"type": "STRING"
|
||||
},
|
||||
{
|
||||
"name": "VCPKG_OVERLAY_TRIPLETS",
|
||||
"value": "${workspaceRoot}/tools/custom_vcpkg_triplets",
|
||||
"type": "STRING"
|
||||
},
|
||||
{
|
||||
"name": "VCPKG_INSTALL_OPTIONS",
|
||||
"value": "--x-abi-tools-use-exact-versions",
|
||||
"type": "STRING"
|
||||
}
|
||||
],
|
||||
"cmakeToolchain": "${env.VcPkgDir}/scripts/buildsystems/vcpkg.cmake"
|
||||
|
||||
@@ -42,12 +42,45 @@ message BoardStackupResponse
|
||||
kiapi.board.BoardStackup stackup = 1;
|
||||
}
|
||||
|
||||
// Changes the stackup for the given board according to the contents of the message (**not yet implemented**)
|
||||
// WARNING: any existing content on layers that are removed by this call is deleted. This operation cannot be undone.
|
||||
// Returns BoardStackupResponse with the updated stackup, in normalized form
|
||||
message UpdateBoardStackup
|
||||
{
|
||||
kiapi.common.types.DocumentSpecifier board = 1;
|
||||
kiapi.board.BoardStackup stackup = 2;
|
||||
}
|
||||
|
||||
message GetBoardEnabledLayers
|
||||
{
|
||||
kiapi.common.types.DocumentSpecifier board = 1;
|
||||
}
|
||||
|
||||
message BoardEnabledLayersResponse
|
||||
{
|
||||
// The number of copper layers enabled in this board.
|
||||
uint32 copper_layer_count = 1;
|
||||
|
||||
// A list of all layers enabled in this board, including copper layers and ones which cannot be disabled.
|
||||
repeated kiapi.board.types.BoardLayer layers = 2;
|
||||
}
|
||||
|
||||
// Changes which layers are enabled in the board stackup
|
||||
// WARNING: any existing content on layers that are removed by this call is deleted. This operation cannot be undone.
|
||||
// Returns BoardEnabledLayersResponse with the updated layer set.
|
||||
message SetBoardEnabledLayers
|
||||
{
|
||||
kiapi.common.types.DocumentSpecifier board = 1;
|
||||
|
||||
// The number of copper layers to enable in the board. Currently, this must be an even number >= 2.
|
||||
uint32 copper_layer_count = 2;
|
||||
|
||||
// The non-copper layers to enable. Note that any copper layers in this list are ignored; copper layers are enabled
|
||||
// by setting copper_layer_count. Note that the F/B.Courtyard, Edge.Cuts, and Margin layers cannot be disabled and
|
||||
// will be present in the board even if they are omitted from this list.
|
||||
repeated kiapi.board.types.BoardLayer layers = 3;
|
||||
}
|
||||
|
||||
message GetGraphicsDefaults
|
||||
{
|
||||
kiapi.common.types.DocumentSpecifier board = 1;
|
||||
|
||||
@@ -36,7 +36,13 @@ if( MSVC )
|
||||
set( KICAD_HOST_ARCH "x64" )
|
||||
set( KICAD_HOST_ARCH_X64 1 )
|
||||
else()
|
||||
message(FATAL_ERROR "Failed to determine the host architecture: ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
message(FATAL_ERROR "Failed to determine the host architecture: ${CMAKE_HOST_SYSTEM_PROCESSOR}")
|
||||
endif()
|
||||
|
||||
if( NOT KICAD_BUILD_ARCH STREQUAL KICAD_HOST_ARCH )
|
||||
set( CMAKE_CROSSCOMPILING TRUE )
|
||||
|
||||
string(TOUPPER ${KICAD_BUILD_ARCH} CMAKE_SYSTEM_PROCESSOR)
|
||||
endif()
|
||||
else()
|
||||
if ( NOT CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
||||
@@ -58,38 +64,18 @@ if( MSVC )
|
||||
# cmake release AND when MSVC ships said cmake release
|
||||
if(KICAD_BUILD_ARCH_ARM)
|
||||
message( "Configuring ARM assembler" )
|
||||
# Explicitly specify the assembler to be used for Arm32 compile
|
||||
file(TO_CMAKE_PATH "$ENV{VCToolsInstallDir}\\bin\\HostX86\\arm\\armasm.exe" CMAKE_ASM_COMPILER)
|
||||
|
||||
set(CMAKE_ASM_MASM_COMPILER ${CMAKE_ASM_COMPILER})
|
||||
message("CMAKE_ASM_MASM_COMPILER explicitly set to: ${CMAKE_ASM_MASM_COMPILER}")
|
||||
|
||||
# Enable generic assembly compilation to avoid CMake generate VS proj files that explicitly
|
||||
# use ml[64].exe as the assembler.
|
||||
enable_language(ASM)
|
||||
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded "")
|
||||
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL "")
|
||||
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug "")
|
||||
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL "")
|
||||
set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -g <INCLUDES> <FLAGS> -o <OBJECT> <SOURCE>")
|
||||
|
||||
enable_language(ASM_MARMASM)
|
||||
# Bugfix for CMake < 29.1
|
||||
set(ASM_DIALECT "_MARMASM")
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT "<CMAKE_ASM${ASM_DIALECT}_COMPILER> <INCLUDES> <FLAGS> -o <OBJECT> <SOURCE>")
|
||||
elseif(KICAD_BUILD_ARCH_ARM64)
|
||||
message( "Configuring ARM64 assembler" )
|
||||
|
||||
# Explicitly specify the assembler to be used for Arm64 compile
|
||||
file(TO_CMAKE_PATH "$ENV{VCToolsInstallDir}\\bin\\HostX86\\arm64\\armasm64.exe" CMAKE_ASM_COMPILER)
|
||||
|
||||
set(CMAKE_ASM_MASM_COMPILER ${CMAKE_ASM_COMPILER})
|
||||
message("CMAKE_ASM_MASM_COMPILER explicitly set to: ${CMAKE_ASM_MASM_COMPILER}")
|
||||
|
||||
# Enable generic assembly compilation to avoid CMake generate VS proj files that explicitly
|
||||
# use ml[64].exe as the assembler.
|
||||
enable_language(ASM)
|
||||
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded "")
|
||||
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL "")
|
||||
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug "")
|
||||
set(CMAKE_ASM_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL "")
|
||||
set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -g <INCLUDES> <FLAGS> -o <OBJECT> <SOURCE>")
|
||||
enable_language(ASM_MARMASM)
|
||||
# Bugfix for CMake < 29.1
|
||||
set(ASM_DIALECT "_MARMASM")
|
||||
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT "<CMAKE_ASM${ASM_DIALECT}_COMPILER> <INCLUDES> <FLAGS> -o <OBJECT> <SOURCE>")
|
||||
else()
|
||||
message( "Configuring MASM assembler" )
|
||||
if(KICAD_BUILD_ARCH_X86)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# This program source code file is part of KICAD, a free EDA CAD application.
|
||||
#
|
||||
# Copyright (C) 2016 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
# Copyright (C) 2016-2023, 2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
# Copyright (C) 2016-2023, 2024, 2025 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
|
||||
@@ -37,7 +37,7 @@
|
||||
# KiCad.
|
||||
#
|
||||
# Note: This version string should follow the semantic versioning system
|
||||
set( KICAD_SEMANTIC_VERSION "9.0.4" )
|
||||
set( KICAD_SEMANTIC_VERSION "9.0.6" )
|
||||
|
||||
# Default the version to the semantic version.
|
||||
# This is overridden by the git repository tag though (if using git)
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
# compile_asm(TARGET target ASM_FILES file1 [file2 ...] OUTPUT_OBJECTS [variableName])
|
||||
# CMake does not support the ARM or ARM64 assemblers on Windows when using the
|
||||
# MSBuild generator. When the MSBuild generator is in use, we manually compile the assembly files
|
||||
# using this function.
|
||||
#
|
||||
# Borrowed from dotnet/runtime, licensed under MIT
|
||||
# Copyright (c) .NET Foundation and Contributors
|
||||
# https://github.com/dotnet/runtime/blob/main/eng/native/functions.cmake
|
||||
function(compile_asm)
|
||||
set(options "")
|
||||
set(oneValueArgs TARGET OUTPUT_OBJECTS)
|
||||
set(multiValueArgs ASM_FILES)
|
||||
cmake_parse_arguments(COMPILE_ASM "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGV})
|
||||
|
||||
get_include_directories_asm(ASM_INCLUDE_DIRECTORIES)
|
||||
|
||||
set (ASSEMBLED_OBJECTS "")
|
||||
|
||||
foreach(ASM_FILE ${COMPILE_ASM_ASM_FILES})
|
||||
get_filename_component(name ${ASM_FILE} NAME_WE)
|
||||
# Produce object file where CMake would store .obj files for an OBJECT library.
|
||||
# ex: artifacts\obj\coreclr\windows.arm64.Debug\src\vm\wks\cee_wks.dir\Debug\AsmHelpers.obj
|
||||
set (OBJ_FILE "${CMAKE_CURRENT_BINARY_DIR}/${COMPILE_ASM_TARGET}.dir/${CMAKE_CFG_INTDIR}/${name}.obj")
|
||||
|
||||
# Need to compile asm file using custom command as include directories are not provided to asm compiler
|
||||
add_custom_command(OUTPUT ${OBJ_FILE}
|
||||
COMMAND "${CMAKE_ASM_COMPILER}" -g ${ASM_INCLUDE_DIRECTORIES} -o ${OBJ_FILE} ${ASM_FILE}
|
||||
DEPENDS ${ASM_FILE}
|
||||
COMMENT "Assembling ${ASM_FILE} ---> \"${CMAKE_ASM_COMPILER}\" -g ${ASM_INCLUDE_DIRECTORIES} -o ${OBJ_FILE} ${ASM_FILE}")
|
||||
|
||||
# mark obj as source that does not require compile
|
||||
set_source_files_properties(${OBJ_FILE} PROPERTIES EXTERNAL_OBJECT TRUE)
|
||||
|
||||
# Add the generated OBJ in the dependency list so that it gets consumed during linkage
|
||||
list(APPEND ASSEMBLED_OBJECTS ${OBJ_FILE})
|
||||
endforeach()
|
||||
|
||||
set(${COMPILE_ASM_OUTPUT_OBJECTS} ${ASSEMBLED_OBJECTS} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
|
||||
# Build a list of include directories for consumption by the assembler
|
||||
function(get_include_directories_asm IncludeDirectories)
|
||||
get_directory_property(dirs INCLUDE_DIRECTORIES)
|
||||
|
||||
foreach(dir IN LISTS dirs)
|
||||
list(APPEND INC_DIRECTORIES -I${dir};)
|
||||
endforeach()
|
||||
|
||||
set(${IncludeDirectories} ${INC_DIRECTORIES} PARENT_SCOPE)
|
||||
endfunction(get_include_directories_asm)
|
||||
@@ -102,6 +102,7 @@ static const wxChar EnableDesignBlocks[] = wxT( "EnableDesignBlocks" );
|
||||
static const wxChar EnableGenerators[] = wxT( "EnableGenerators" );
|
||||
static const wxChar EnableLibWithText[] = wxT( "EnableLibWithText" );
|
||||
static const wxChar EnableLibDir[] = wxT( "EnableLibDir" );
|
||||
static const wxChar LibraryTableEditor[] = wxT( "LibraryTableEditor" );
|
||||
static const wxChar EnableEeschemaPrintCairo[] = wxT( "EnableEeschemaPrintCairo" );
|
||||
static const wxChar EnableEeschemaExportClipboardCairo[] = wxT( "EnableEeschemaExportClipboardCairo" );
|
||||
static const wxChar DisambiguationTime[] = wxT( "DisambiguationTime" );
|
||||
@@ -120,6 +121,8 @@ static const wxChar EnableExtensionSnaps[] = wxT( "EnableExtensionSnaps" );
|
||||
static const wxChar ExtensionSnapTimeoutMs[] = wxT( "ExtensionSnapTimeoutMs" );
|
||||
static const wxChar ExtensionSnapActivateOnHover[] = wxT( "ExtensionSnapActivateOnHover" );
|
||||
static const wxChar EnableSnapAnchorsDebug[] = wxT( "EnableSnapAnchorsDebug" );
|
||||
static const wxChar SnapHysteresis[] = wxT( "SnapHysteresis" );
|
||||
static const wxChar SnapToAnchorMargin[] = wxT( "SnapToAnchorMargin" );
|
||||
static const wxChar MinParallelAngle[] = wxT( "MinParallelAngle" );
|
||||
static const wxChar HoleWallPaintingMultiplier[] = wxT( "HoleWallPaintingMultiplier" );
|
||||
static const wxChar MsgPanelShowUuids[] = wxT( "MsgPanelShowUuids" );
|
||||
@@ -262,6 +265,7 @@ ADVANCED_CFG::ADVANCED_CFG()
|
||||
m_EnableGenerators = false;
|
||||
m_EnableLibWithText = false;
|
||||
m_EnableLibDir = false;
|
||||
m_LibraryTableEditor = false;
|
||||
|
||||
m_EnableEeschemaPrintCairo = true;
|
||||
m_EnableEeschemaExportClipboardCairo = true;
|
||||
@@ -299,6 +303,8 @@ ADVANCED_CFG::ADVANCED_CFG()
|
||||
m_ExtensionSnapTimeoutMs = 500;
|
||||
m_ExtensionSnapActivateOnHover = true;
|
||||
m_EnableSnapAnchorsDebug = false;
|
||||
m_SnapHysteresis = 5;
|
||||
m_SnapToAnchorMargin = 1.1;
|
||||
|
||||
m_MinParallelAngle = 0.001;
|
||||
m_HoleWallPaintingMultiplier = 1.5;
|
||||
@@ -512,6 +518,9 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg )
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::EnableLibDir,
|
||||
&m_EnableLibDir, m_EnableLibDir ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::LibraryTableEditor,
|
||||
&m_LibraryTableEditor, m_LibraryTableEditor ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::EnableEeschemaPrintCairo,
|
||||
&m_EnableEeschemaPrintCairo,
|
||||
m_EnableEeschemaPrintCairo ) );
|
||||
@@ -577,6 +586,14 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg )
|
||||
&m_EnableSnapAnchorsDebug,
|
||||
m_EnableSnapAnchorsDebug ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::SnapHysteresis,
|
||||
&m_SnapHysteresis, m_SnapHysteresis,
|
||||
0, 100 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::SnapToAnchorMargin,
|
||||
&m_SnapToAnchorMargin, m_SnapToAnchorMargin,
|
||||
1.0, 2.0 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::MinParallelAngle,
|
||||
&m_MinParallelAngle, m_MinParallelAngle,
|
||||
0.0, 45.0 ) );
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "clipboard.h"
|
||||
|
||||
#include <wx/clipbrd.h>
|
||||
#include <wx/dataobj.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/log.h>
|
||||
|
||||
@@ -84,10 +85,10 @@ std::unique_ptr<wxImage> GetImageFromClipboard()
|
||||
{
|
||||
if( wxTheClipboard->IsSupported( wxDF_BITMAP ) )
|
||||
{
|
||||
wxImageDataObject data;
|
||||
wxBitmapDataObject data;
|
||||
if( wxTheClipboard->GetData( data ) )
|
||||
{
|
||||
image = std::make_unique<wxImage>( data.GetImage() );
|
||||
image = std::make_unique<wxImage>( data.GetBitmap().ConvertToImage() );
|
||||
}
|
||||
}
|
||||
else if( wxTheClipboard->IsSupported( wxDF_FILENAME ) )
|
||||
|
||||
@@ -161,7 +161,7 @@ bool DATABASE_CONNECTION::Connect()
|
||||
m_conn = std::make_unique<nanodbc::connection>( cs, m_timeout );
|
||||
}
|
||||
}
|
||||
catch( nanodbc::database_error& e )
|
||||
catch( std::exception& e )
|
||||
{
|
||||
m_lastError = e.what();
|
||||
return false;
|
||||
@@ -188,7 +188,7 @@ bool DATABASE_CONNECTION::Disconnect()
|
||||
{
|
||||
m_conn->disconnect();
|
||||
}
|
||||
catch( boost::locale::conv::conversion_error& exc )
|
||||
catch( std::exception& exc )
|
||||
{
|
||||
wxLogTrace( traceDatabase, wxT( "Disconnect() error \"%s\" occured." ), exc.what() );
|
||||
return false;
|
||||
@@ -250,7 +250,7 @@ bool DATABASE_CONNECTION::CacheTableInfo( const std::string& aTable,
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch( nanodbc::database_error& e )
|
||||
catch( std::exception& e )
|
||||
{
|
||||
m_lastError = e.what();
|
||||
wxLogTrace( traceDatabase, wxT( "Exception while caching table info: %s" ), m_lastError );
|
||||
@@ -277,8 +277,9 @@ bool DATABASE_CONNECTION::getQuoteChar()
|
||||
|
||||
wxLogTrace( traceDatabase, wxT( "Quote char retrieved: %c" ), m_quoteChar );
|
||||
}
|
||||
catch( nanodbc::database_error& )
|
||||
catch( std::exception& e )
|
||||
{
|
||||
m_lastError = e.what();
|
||||
wxLogTrace( traceDatabase, wxT( "Exception while querying quote char: %s" ), m_lastError );
|
||||
return false;
|
||||
}
|
||||
@@ -401,14 +402,14 @@ bool DATABASE_CONNECTION::SelectOne( const std::string& aTable,
|
||||
statement.prepare( *m_conn, query );
|
||||
statement.bind( 0, aWhere.second.c_str() );
|
||||
}
|
||||
catch( nanodbc::database_error& e )
|
||||
catch( std::exception& e )
|
||||
{
|
||||
m_lastError = e.what();
|
||||
wxLogTrace( traceDatabase, wxT( "Exception while preparing statement for SelectOne: %s" ),
|
||||
m_lastError );
|
||||
|
||||
// Exception may be due to a connection error; nanodbc won't auto-reconnect
|
||||
m_conn->disconnect();
|
||||
Disconnect();
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -422,14 +423,14 @@ bool DATABASE_CONNECTION::SelectOne( const std::string& aTable,
|
||||
{
|
||||
results = nanodbc::execute( statement );
|
||||
}
|
||||
catch( nanodbc::database_error& e )
|
||||
catch( std::exception& e )
|
||||
{
|
||||
m_lastError = e.what();
|
||||
wxLogTrace( traceDatabase, wxT( "Exception while executing statement for SelectOne: %s" ),
|
||||
m_lastError );
|
||||
|
||||
// Exception may be due to a connection error; nanodbc won't auto-reconnect
|
||||
m_conn->disconnect();
|
||||
Disconnect();
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -480,7 +481,7 @@ bool DATABASE_CONNECTION::SelectOne( const std::string& aTable,
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( nanodbc::database_error& e )
|
||||
catch( std::exception& e )
|
||||
{
|
||||
m_lastError = e.what();
|
||||
wxLogTrace( traceDatabase, wxT( "Exception while parsing results from SelectOne: %s" ),
|
||||
@@ -507,7 +508,7 @@ bool DATABASE_CONNECTION::selectAllAndCache( const std::string& aTable, const st
|
||||
{
|
||||
statement.prepare( query );
|
||||
}
|
||||
catch( nanodbc::database_error& e )
|
||||
catch( std::exception& e )
|
||||
{
|
||||
m_lastError = e.what();
|
||||
wxLogTrace( traceDatabase,
|
||||
@@ -515,7 +516,7 @@ bool DATABASE_CONNECTION::selectAllAndCache( const std::string& aTable, const st
|
||||
m_lastError );
|
||||
|
||||
// Exception may be due to a connection error; nanodbc won't auto-reconnect
|
||||
m_conn->disconnect();
|
||||
Disconnect();
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -526,7 +527,7 @@ bool DATABASE_CONNECTION::selectAllAndCache( const std::string& aTable, const st
|
||||
{
|
||||
results = nanodbc::execute( statement );
|
||||
}
|
||||
catch( nanodbc::database_error& e )
|
||||
catch( std::exception& e )
|
||||
{
|
||||
m_lastError = e.what();
|
||||
wxLogTrace( traceDatabase,
|
||||
@@ -534,7 +535,7 @@ bool DATABASE_CONNECTION::selectAllAndCache( const std::string& aTable, const st
|
||||
m_lastError );
|
||||
|
||||
// Exception may be due to a connection error; nanodbc won't auto-reconnect
|
||||
m_conn->disconnect();
|
||||
Disconnect();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -631,7 +631,8 @@ bool DESIGN_BLOCK_LIB_TABLE::LoadGlobalTable( DESIGN_BLOCK_LIB_TABLE& aTable )
|
||||
{
|
||||
tableExists = false;
|
||||
|
||||
if( !fn.DirExists() && !fn.Mkdir( 0x777, wxPATH_MKDIR_FULL ) )
|
||||
if( !wxFileName::DirExists( fn.GetPath() )
|
||||
&& !wxFileName::Mkdir( fn.GetPath(), 0x777, wxPATH_MKDIR_FULL ) )
|
||||
{
|
||||
THROW_IO_ERROR( wxString::Format( _( "Cannot create global library table path '%s'." ),
|
||||
fn.GetPath() ) );
|
||||
|
||||
@@ -909,7 +909,13 @@ static void buildKicadAboutBanner( EDA_BASE_FRAME* aParent, ABOUT_APP_INFO& aInf
|
||||
#define FOOTPRINT_LIB_CONTRIBUTION _( "Footprints" )
|
||||
aInfo.AddLibrarian( new CONTRIBUTOR( wxS( "Scripts by Maui" ),
|
||||
MODELS_3D_CONTRIBUTION,
|
||||
wxS( "https://gitlab.com/kicad/libraries/kicad-footprint-generator" ) ) );
|
||||
wxS( "https://github.com/easyw" ) ) );
|
||||
aInfo.AddLibrarian( new CONTRIBUTOR( wxS( "Hasan Yavuz Özderya" ),
|
||||
MODELS_3D_CONTRIBUTION,
|
||||
wxS( "https://bitbucket.org/hyOzd/freecad-macros/src/master/" ) ) );
|
||||
aInfo.AddLibrarian( new CONTRIBUTOR( wxS( "GitHub contributors" ),
|
||||
MODELS_3D_CONTRIBUTION,
|
||||
wxS( "https://github.com/easyw/kicad-3d-models-in-freecad/graphs/contributors" ) ) );
|
||||
aInfo.AddLibrarian( new CONTRIBUTOR( wxS( "GitLab contributors" ),
|
||||
MODELS_3D_CONTRIBUTION,
|
||||
wxS( "https://gitlab.com/kicad/libraries/kicad-packages3D/-/graphs/master" ) ) );
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <build_version.h>
|
||||
#include <eda_base_frame.h>
|
||||
#include <wx/clipbrd.h>
|
||||
@@ -108,8 +107,20 @@ DIALOG_ABOUT::DIALOG_ABOUT( EDA_BASE_FRAME *aParent, ABOUT_APP_INFO& aAppInfo )
|
||||
m_titleName = aParent->GetAboutTitle();
|
||||
m_untranslatedTitleName = aParent->GetUntranslatedAboutTitle();
|
||||
m_staticTextAppTitle->SetLabel( m_titleName );
|
||||
|
||||
// On windows, display the number of GDI objects in use. Can be useful when some GDI objects
|
||||
// are not displayed because the max count of GDI objects (usually 10000) is reached
|
||||
// So displaying this number can help to diagnose strange display issues
|
||||
wxString extraInfo;
|
||||
|
||||
#if defined( _WIN32 )
|
||||
uint32_t gdi_count = GetGuiResources( GetCurrentProcess(), GR_GDIOBJECTS );
|
||||
extraInfo.Printf( _( "GDI objects in use %u" ), gdi_count );
|
||||
extraInfo.Prepend( wxT( "\n" ) );
|
||||
#endif
|
||||
|
||||
m_staticTextBuildVersion->SetLabel( wxS( "Version: " ) + m_info.GetBuildVersion() );
|
||||
m_staticTextLibVersion->SetLabel( m_info.GetLibVersion() );
|
||||
m_staticTextLibVersion->SetLabel( m_info.GetLibVersion() + extraInfo );
|
||||
|
||||
SetTitle( wxString::Format( _( "About %s" ), m_titleName ) );
|
||||
createNotebooks();
|
||||
|
||||
@@ -494,14 +494,17 @@ int DIALOG_SHIM::ShowModal()
|
||||
}
|
||||
|
||||
/*
|
||||
Quasi-Modal Mode Explained:
|
||||
QuasiModal Mode Explained:
|
||||
|
||||
The gtk calls in wxDialog::ShowModal() cause event routing problems if that
|
||||
modal dialog then tries to use KIWAY_PLAYER::ShowModal(). The latter shows up
|
||||
and mostly works but does not respond to the window decoration close button.
|
||||
There is no way to get around this without reversing the gtk calls temporarily.
|
||||
|
||||
Quasi-Modal mode is our own almost modal mode which disables only the parent
|
||||
There are also issues with the Scintilla text editor putting up autocomplete
|
||||
popups, which appear behind the dialog window if QuasiModal is not used.
|
||||
|
||||
QuasiModal mode is our own almost modal mode which disables only the parent
|
||||
of the DIALOG_SHIM, leaving other frames operable and while staying captured in the
|
||||
nested event loop. This avoids the gtk calls and leaves event routing pure
|
||||
and sufficient to operate the KIWAY_PLAYER::ShowModal() properly. When using
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
|
||||
#include "design_block_lib_table.h"
|
||||
|
||||
#include <kiplatform/io.h>
|
||||
|
||||
|
||||
DIALOG_GLOBAL_DESIGN_BLOCK_LIB_TABLE_CONFIG::DIALOG_GLOBAL_DESIGN_BLOCK_LIB_TABLE_CONFIG(
|
||||
wxWindow* aParent ) :
|
||||
@@ -106,8 +108,8 @@ bool DIALOG_GLOBAL_DESIGN_BLOCK_LIB_TABLE_CONFIG::TransferDataFromWindow()
|
||||
// Create the config path if it doesn't already exist.
|
||||
wxFileName designBlockTableFileName = DESIGN_BLOCK_LIB_TABLE::GetGlobalTableFileName();
|
||||
|
||||
if( !designBlockTableFileName.DirExists()
|
||||
&& !designBlockTableFileName.Mkdir( 0x777, wxPATH_MKDIR_FULL ) )
|
||||
if( !wxFileName::DirExists( designBlockTableFileName.GetPath() )
|
||||
&& !wxFileName::Mkdir( designBlockTableFileName.GetPath(), 0x777, wxPATH_MKDIR_FULL ) )
|
||||
{
|
||||
DisplayError( this, wxString::Format( _( "Cannot create global library table '%s'." ),
|
||||
designBlockTableFileName.GetPath() ) );
|
||||
@@ -124,6 +126,9 @@ bool DIALOG_GLOBAL_DESIGN_BLOCK_LIB_TABLE_CONFIG::TransferDataFromWindow()
|
||||
fn.GetFullPath(), designBlockTableFileName.GetFullPath() ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure the copied file is writable
|
||||
KIPLATFORM::IO::MakeWriteable( designBlockTableFileName.GetFullPath() );
|
||||
}
|
||||
|
||||
// Load the successfully copied design block library table file. This should not fail since the
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <eda_item.h>
|
||||
#include <confirm.h>
|
||||
#include <bitmaps.h>
|
||||
#include <dialogs/panel_embedded_files.h>
|
||||
#include <embedded_files.h>
|
||||
@@ -161,9 +163,7 @@ void PANEL_EMBEDDED_FILES::resizeGrid()
|
||||
bool PANEL_EMBEDDED_FILES::TransferDataToWindow()
|
||||
{
|
||||
m_files_grid->ClearGrid();
|
||||
|
||||
if( m_files_grid->GetNumberRows() > 0 )
|
||||
m_files_grid->DeleteRows( 0, m_files_grid->GetNumberRows() );
|
||||
m_files_grid->ClearRows();
|
||||
|
||||
int ii = 0;
|
||||
for( auto& [name, file] : m_localFiles->EmbeddedFileMap() )
|
||||
@@ -187,6 +187,51 @@ bool PANEL_EMBEDDED_FILES::TransferDataToWindow()
|
||||
|
||||
bool PANEL_EMBEDDED_FILES::TransferDataFromWindow()
|
||||
{
|
||||
std::optional<bool> deleteReferences;
|
||||
|
||||
auto confirmDelete =
|
||||
[&]() -> bool
|
||||
{
|
||||
if( EDA_ITEM* parent = dynamic_cast<EDA_ITEM*>( m_files ) )
|
||||
{
|
||||
if( parent->Type() == PCB_T )
|
||||
{
|
||||
return IsOK( m_parent, _( "Deleted embedded files are also referenced in some footprints.\n"
|
||||
"Delete from footprints as well?" ) );
|
||||
}
|
||||
else if( parent->Type() == SCHEMATIC_T )
|
||||
{
|
||||
return IsOK( m_parent, _( "Deleted embedded files are also referenced in some symbols.\n"
|
||||
"Delete from symbols as well?" ) );
|
||||
}
|
||||
}
|
||||
|
||||
wxFAIL_MSG( wxT( "Unexpected embedded files owner" ) );
|
||||
return false;
|
||||
};
|
||||
|
||||
for( const auto& [name, file] : m_files->EmbeddedFileMap() )
|
||||
{
|
||||
if( !m_localFiles->HasFile( name ) )
|
||||
{
|
||||
m_files->RunOnNestedEmbeddedFiles(
|
||||
[&]( EMBEDDED_FILES* nested_files )
|
||||
{
|
||||
if( nested_files->HasFile( name ) )
|
||||
{
|
||||
if( !deleteReferences.has_value() )
|
||||
deleteReferences = confirmDelete();
|
||||
|
||||
if( deleteReferences.value() )
|
||||
nested_files->RemoveFile( name, true );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
if( deleteReferences.has_value() && deleteReferences.value() == false )
|
||||
break;
|
||||
}
|
||||
|
||||
m_files->ClearEmbeddedFiles();
|
||||
|
||||
std::vector<EMBEDDED_FILES::EMBEDDED_FILE*> files;
|
||||
@@ -247,11 +292,6 @@ void PANEL_EMBEDDED_FILES::onFontEmbedClick( wxCommandEvent& event )
|
||||
font->GetFileName() ) );
|
||||
continue;
|
||||
}
|
||||
|
||||
m_files_grid->AppendRows( 1 );
|
||||
int ii = m_files_grid->GetNumberRows() - 1;
|
||||
m_files_grid->SetCellValue( ii, 0, result->name );
|
||||
m_files_grid->SetCellValue( ii, 1, result->GetLink() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -141,6 +141,7 @@ void EDA_BASE_FRAME::commonInit( FRAME_T aFrameType )
|
||||
m_isNonUserClose = false;
|
||||
m_autoSaveTimer = new wxTimer( this, ID_AUTO_SAVE_TIMER );
|
||||
m_autoSaveRequired = false;
|
||||
m_autoSavePermissionError = false;
|
||||
m_mruPath = PATHS::GetDefaultUserProjectsPath();
|
||||
m_frameSize = defaultSize( aFrameType, this );
|
||||
m_displayIndex = -1;
|
||||
|
||||
@@ -2339,10 +2339,10 @@ static struct EDA_SHAPE_DESC
|
||||
|
||||
if( lineStyleEnum.Choices().GetCount() == 0 )
|
||||
{
|
||||
lineStyleEnum.Map( LINE_STYLE::SOLID, _HKI( "Solid" ) )
|
||||
.Map( LINE_STYLE::DASH, _HKI( "Dashed" ) )
|
||||
.Map( LINE_STYLE::DOT, _HKI( "Dotted" ) )
|
||||
.Map( LINE_STYLE::DASHDOT, _HKI( "Dash-Dot" ) )
|
||||
lineStyleEnum.Map( LINE_STYLE::SOLID, _HKI( "Solid" ) )
|
||||
.Map( LINE_STYLE::DASH, _HKI( "Dashed" ) )
|
||||
.Map( LINE_STYLE::DOT, _HKI( "Dotted" ) )
|
||||
.Map( LINE_STYLE::DASHDOT, _HKI( "Dash-Dot" ) )
|
||||
.Map( LINE_STYLE::DASHDOTDOT, _HKI( "Dash-Dot-Dot" ) );
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -1323,18 +1323,18 @@ static struct EDA_TEXT_DESC
|
||||
|
||||
if( h_inst.Choices().GetCount() == 0)
|
||||
{
|
||||
h_inst.Map( GR_TEXT_H_ALIGN_LEFT, _( "Left" ) );
|
||||
h_inst.Map( GR_TEXT_H_ALIGN_CENTER, _( "Center" ) );
|
||||
h_inst.Map( GR_TEXT_H_ALIGN_RIGHT, _( "Right" ) );
|
||||
h_inst.Map( GR_TEXT_H_ALIGN_LEFT, _HKI( "Left" ) );
|
||||
h_inst.Map( GR_TEXT_H_ALIGN_CENTER, _HKI( "Center" ) );
|
||||
h_inst.Map( GR_TEXT_H_ALIGN_RIGHT, _HKI( "Right" ) );
|
||||
}
|
||||
|
||||
auto& v_inst = ENUM_MAP<GR_TEXT_V_ALIGN_T>::Instance();
|
||||
|
||||
if( v_inst.Choices().GetCount() == 0)
|
||||
{
|
||||
v_inst.Map( GR_TEXT_V_ALIGN_TOP, _( "Top" ) );
|
||||
v_inst.Map( GR_TEXT_V_ALIGN_CENTER, _( "Center" ) );
|
||||
v_inst.Map( GR_TEXT_V_ALIGN_BOTTOM, _( "Bottom" ) );
|
||||
v_inst.Map( GR_TEXT_V_ALIGN_TOP, _HKI( "Top" ) );
|
||||
v_inst.Map( GR_TEXT_V_ALIGN_CENTER, _HKI( "Center" ) );
|
||||
v_inst.Map( GR_TEXT_V_ALIGN_BOTTOM, _HKI( "Bottom" ) );
|
||||
}
|
||||
|
||||
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
|
||||
|
||||
@@ -599,6 +599,85 @@ double EDA_UNIT_UTILS::UI::DoubleValueFromString( const EDA_IU_SCALE& aIuScale,
|
||||
}
|
||||
|
||||
|
||||
bool EDA_UNIT_UTILS::UI::DoubleValueFromString( const EDA_IU_SCALE& aIuScale, const wxString& aTextValue,
|
||||
double& aDoubleValue )
|
||||
{
|
||||
double dtmp = 0;
|
||||
|
||||
// Acquire the 'right' decimal point separator
|
||||
const struct lconv* lc = localeconv();
|
||||
|
||||
wxChar decimal_point = lc->decimal_point[0];
|
||||
wxString buf( aTextValue.Strip( wxString::both ) );
|
||||
|
||||
// Convert any entered decimal point separators to the 'right' one
|
||||
buf.Replace( wxT( "." ), wxString( decimal_point, 1 ) );
|
||||
buf.Replace( wxT( "," ), wxString( decimal_point, 1 ) );
|
||||
|
||||
// Find the end of the numeric part
|
||||
unsigned brk_point = 0;
|
||||
|
||||
while( brk_point < buf.Len() )
|
||||
{
|
||||
wxChar ch = buf[brk_point];
|
||||
|
||||
if( !( (ch >= '0' && ch <= '9') || (ch == decimal_point) || (ch == '-') || (ch == '+') ) )
|
||||
break;
|
||||
|
||||
++brk_point;
|
||||
}
|
||||
|
||||
if( brk_point == 0 )
|
||||
return false;
|
||||
|
||||
// Extract the numeric part
|
||||
buf.Left( brk_point ).ToDouble( &dtmp );
|
||||
|
||||
// Check the unit designator
|
||||
wxString unit( buf.Mid( brk_point ).Strip( wxString::both ).Lower() );
|
||||
EDA_UNITS units;
|
||||
|
||||
//check for um, μm (µ is MICRO SIGN) and µm (µ is GREEK SMALL LETTER MU) for micrometre
|
||||
if( unit == wxT( "um" ) || unit == wxT( "\u00B5m" ) || unit == wxT( "\u03BCm" ) )
|
||||
{
|
||||
units = EDA_UNITS::UM;
|
||||
}
|
||||
else if( unit == wxT( "mm" ) )
|
||||
{
|
||||
units = EDA_UNITS::MM;
|
||||
}
|
||||
else if( unit == wxT( "cm" ) )
|
||||
{
|
||||
units = EDA_UNITS::CM;
|
||||
}
|
||||
else if( unit == wxT( "mil" ) || unit == wxT( "mils" ) || unit == wxT( "thou" ) )
|
||||
{
|
||||
units = EDA_UNITS::MILS;
|
||||
}
|
||||
else if( unit == wxT( "in" ) || unit == wxT( "\"" ) )
|
||||
{
|
||||
units = EDA_UNITS::INCH;
|
||||
}
|
||||
else if( unit == wxT( "oz" ) ) // 1 oz = 1.37 mils
|
||||
{
|
||||
units = EDA_UNITS::MILS;
|
||||
dtmp *= 1.37;
|
||||
}
|
||||
else if( unit == wxT( "ra" ) ) // Radians
|
||||
{
|
||||
units = EDA_UNITS::DEGREES;
|
||||
dtmp *= 180.0f / M_PI;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
aDoubleValue = FromUserUnit( aIuScale, units, dtmp );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
long long int EDA_UNIT_UTILS::UI::ValueFromString( const EDA_IU_SCALE& aIuScale, EDA_UNITS aUnits,
|
||||
const wxString& aTextValue, EDA_DATA_TYPE aType )
|
||||
{
|
||||
|
||||
@@ -628,7 +628,8 @@ bool FP_LIB_TABLE::LoadGlobalTable( FP_LIB_TABLE& aTable )
|
||||
{
|
||||
tableExists = false;
|
||||
|
||||
if( !fn.DirExists() && !fn.Mkdir( 0x777, wxPATH_MKDIR_FULL ) )
|
||||
if( !wxFileName::DirExists( fn.GetPath() )
|
||||
&& !wxFileName::Mkdir( fn.GetPath(), 0x777, wxPATH_MKDIR_FULL ) )
|
||||
{
|
||||
THROW_IO_ERROR( wxString::Format( _( "Cannot create global library table path '%s'." ),
|
||||
fn.GetPath() ) );
|
||||
|
||||
@@ -322,6 +322,12 @@ void CAIRO_GAL_BASE::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& a
|
||||
}
|
||||
|
||||
|
||||
void CAIRO_GAL_BASE::DrawHoleWall( const VECTOR2D& aCenterPoint, double aRadius, double aWallWidth )
|
||||
{
|
||||
DrawCircle( aCenterPoint, aRadius + aWallWidth );
|
||||
}
|
||||
|
||||
|
||||
void CAIRO_GAL_BASE::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
|
||||
{
|
||||
syncLineWidth();
|
||||
@@ -1740,6 +1746,8 @@ void CAIRO_GAL_BASE::DrawGrid()
|
||||
return;
|
||||
|
||||
VECTOR2D gridScreenSize( m_gridSize );
|
||||
gridScreenSize = VECTOR2D( std::max( 1.0, gridScreenSize.x ),
|
||||
std::max( 1.0, gridScreenSize.y ) );
|
||||
|
||||
double gridThreshold = KiROUND( computeMinGridSpacing() / m_worldScale );
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ GAL::GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions ) :
|
||||
SetLayerDepth( 0.0 );
|
||||
SetFlip( false, false );
|
||||
SetLineWidth( 1.0f );
|
||||
SetMinLineWidth( 1.0f );
|
||||
computeWorldScale();
|
||||
SetAxesEnabled( false );
|
||||
|
||||
@@ -75,6 +76,8 @@ GAL::GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions ) :
|
||||
SetCoarseGrid( 10 );
|
||||
m_gridLineWidth = 0.5f;
|
||||
m_gridStyle = GRID_STYLE::LINES;
|
||||
m_gridSize = VECTOR2D( 1.0, 1.0 );
|
||||
m_gridOffset = VECTOR2D( 0.0, 0.0 );
|
||||
m_gridMinSpacing = 10;
|
||||
|
||||
// Initialize the cursor shape
|
||||
|
||||
@@ -413,10 +413,13 @@ OPENGL_GAL::OPENGL_GAL( const KIGFX::VC_SETTINGS& aVcSettings, GAL_DISPLAY_OPTIO
|
||||
SetTarget( TARGET_NONCACHED );
|
||||
|
||||
// Avoid uninitialized variables:
|
||||
ufm_worldPixelSize = 1;
|
||||
ufm_screenPixelSize = 1;
|
||||
ufm_pixelSizeMultiplier = 1;
|
||||
ufm_antialiasingOffset = 1;
|
||||
ufm_worldPixelSize = -1;
|
||||
ufm_screenPixelSize = -1;
|
||||
ufm_pixelSizeMultiplier = -1;
|
||||
ufm_antialiasingOffset = -1;
|
||||
ufm_minLinePixelWidth = -1;
|
||||
ufm_fontTexture = -1;
|
||||
ufm_fontTextureWidth = -1;
|
||||
m_swapInterval = 0;
|
||||
}
|
||||
|
||||
@@ -672,14 +675,6 @@ void OPENGL_GAL::BeginDrawing()
|
||||
glActiveTexture( GL_TEXTURE0 );
|
||||
}
|
||||
|
||||
// Set shader parameter
|
||||
GLint ufm_fontTexture = m_shader->AddParameter( "u_fontTexture" );
|
||||
GLint ufm_fontTextureWidth = m_shader->AddParameter( "u_fontTextureWidth" );
|
||||
ufm_worldPixelSize = m_shader->AddParameter( "u_worldPixelSize" );
|
||||
ufm_screenPixelSize = m_shader->AddParameter( "u_screenPixelSize" );
|
||||
ufm_pixelSizeMultiplier = m_shader->AddParameter( "u_pixelSizeMultiplier" );
|
||||
ufm_antialiasingOffset = m_shader->AddParameter( "u_antialiasingOffset" );
|
||||
|
||||
m_shader->Use();
|
||||
m_shader->SetParameter( ufm_fontTexture, (int) FONT_TEXTURE_UNIT );
|
||||
m_shader->SetParameter( ufm_fontTextureWidth, (int) font_image.width );
|
||||
@@ -700,6 +695,7 @@ void OPENGL_GAL::BeginDrawing()
|
||||
renderingOffset.x *= screenPixelSize.x;
|
||||
renderingOffset.y *= screenPixelSize.y;
|
||||
m_shader->SetParameter( ufm_antialiasingOffset, renderingOffset );
|
||||
m_shader->SetParameter( ufm_minLinePixelWidth, GetMinLineWidth() );
|
||||
m_shader->Deactivate();
|
||||
|
||||
// Something between BeginDrawing and EndDrawing seems to depend on
|
||||
@@ -716,6 +712,18 @@ void OPENGL_GAL::BeginDrawing()
|
||||
#endif /* KICAD_GAL_PROFILE */
|
||||
}
|
||||
|
||||
void OPENGL_GAL::SetMinLineWidth( float aLineWidth )
|
||||
{
|
||||
GAL::SetMinLineWidth( aLineWidth );
|
||||
|
||||
if( m_shader && ufm_minLinePixelWidth != -1 )
|
||||
{
|
||||
m_shader->Use();
|
||||
m_shader->SetParameter( ufm_minLinePixelWidth, aLineWidth );
|
||||
m_shader->Deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::EndDrawing()
|
||||
{
|
||||
@@ -907,6 +915,25 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::DrawHoleWall( const VECTOR2D& aCenterPoint, double aHoleRadius,
|
||||
double aWallWidth )
|
||||
{
|
||||
if( m_isFillEnabled )
|
||||
{
|
||||
m_currentManager->Color( m_fillColor.r, m_fillColor.g, m_fillColor.b, m_fillColor.a );
|
||||
|
||||
m_currentManager->Shader( SHADER_HOLE_WALL, 1.0, aHoleRadius, aWallWidth );
|
||||
m_currentManager->Vertex( aCenterPoint.x, aCenterPoint.y, m_layerDepth );
|
||||
|
||||
m_currentManager->Shader( SHADER_HOLE_WALL, 2.0, aHoleRadius, aWallWidth );
|
||||
m_currentManager->Vertex( aCenterPoint.x, aCenterPoint.y, m_layerDepth );
|
||||
|
||||
m_currentManager->Shader( SHADER_HOLE_WALL, 3.0, aHoleRadius, aWallWidth );
|
||||
m_currentManager->Vertex( aCenterPoint.x, aCenterPoint.y, m_layerDepth );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::drawCircle( const VECTOR2D& aCenterPoint, double aRadius, bool aReserve )
|
||||
{
|
||||
if( m_isFillEnabled )
|
||||
@@ -2662,6 +2689,10 @@ void OPENGL_GAL::blitCursor()
|
||||
glLineWidth( 1.0 );
|
||||
glColor4d( color.r, color.g, color.b, color.a );
|
||||
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glPushMatrix();
|
||||
glTranslated( 0, 0, -0.5 );
|
||||
|
||||
glBegin( GL_LINES );
|
||||
glVertex2d( cursorCenter.x, cursorBegin.y );
|
||||
glVertex2d( cursorCenter.x, cursorEnd.y );
|
||||
@@ -2669,6 +2700,8 @@ void OPENGL_GAL::blitCursor()
|
||||
glVertex2d( cursorBegin.x, cursorCenter.y );
|
||||
glVertex2d( cursorEnd.x, cursorCenter.y );
|
||||
glEnd();
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
@@ -2753,6 +2786,9 @@ void OPENGL_GAL::init()
|
||||
if( !m_shader->IsLinked() && !m_shader->Link() )
|
||||
throw std::runtime_error( "Cannot link the shaders!" );
|
||||
|
||||
// Set up shader parameters after linking
|
||||
setupShaderParameters();
|
||||
|
||||
// Check if video card supports textures big enough to fit the font atlas
|
||||
int maxTextureSize;
|
||||
glGetIntegerv( GL_MAX_TEXTURE_SIZE, &maxTextureSize );
|
||||
@@ -2781,6 +2817,19 @@ void OPENGL_GAL::init()
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::setupShaderParameters()
|
||||
{
|
||||
// Initialize shader uniform parameter locations
|
||||
ufm_fontTexture = m_shader->AddParameter( "u_fontTexture" );
|
||||
ufm_fontTextureWidth = m_shader->AddParameter( "u_fontTextureWidth" );
|
||||
ufm_worldPixelSize = m_shader->AddParameter( "u_worldPixelSize" );
|
||||
ufm_screenPixelSize = m_shader->AddParameter( "u_screenPixelSize" );
|
||||
ufm_pixelSizeMultiplier = m_shader->AddParameter( "u_pixelSizeMultiplier" );
|
||||
ufm_antialiasingOffset = m_shader->AddParameter( "u_antialiasingOffset" );
|
||||
ufm_minLinePixelWidth = m_shader->AddParameter( "u_minLinePixelWidth" );
|
||||
}
|
||||
|
||||
|
||||
// Callback functions for the tesselator. Compare Redbook Chapter 11.
|
||||
void CALLBACK VertexCallback( GLvoid* aVertexPtr, void* aData )
|
||||
{
|
||||
|
||||
@@ -35,6 +35,7 @@ const float SHADER_FILLED_CIRCLE = 2.0;
|
||||
const float SHADER_STROKED_CIRCLE = 3.0;
|
||||
const float SHADER_FONT = 4.0;
|
||||
const float SHADER_LINE_A = 5.0;
|
||||
const float SHADER_HOLE_WALL = 11.0;
|
||||
|
||||
varying vec4 v_shaderParams;
|
||||
varying vec2 v_circleCoords;
|
||||
@@ -124,6 +125,10 @@ void main()
|
||||
{
|
||||
strokedCircle( v_circleCoords, v_shaderParams[2], v_shaderParams[3] );
|
||||
}
|
||||
else if( mode == SHADER_HOLE_WALL )
|
||||
{
|
||||
strokedCircle( v_circleCoords, v_shaderParams[2], v_shaderParams[3] );
|
||||
}
|
||||
else if( mode == SHADER_FONT )
|
||||
{
|
||||
vec2 tex = v_shaderParams.yz;
|
||||
|
||||
@@ -36,6 +36,7 @@ const float SHADER_LINE_C = 7.0;
|
||||
const float SHADER_LINE_D = 8.0;
|
||||
const float SHADER_LINE_E = 9.0;
|
||||
const float SHADER_LINE_F = 10.0;
|
||||
const float SHADER_HOLE_WALL = 11.0;
|
||||
|
||||
// Minimum line width
|
||||
const float MIN_WIDTH = 1.0;
|
||||
@@ -72,8 +73,8 @@ void computeLineCoords( bool posture, vec2 vs, vec2 vp, vec2 texcoord, vec2 dir,
|
||||
vec2 s = sign( vec2( gl_ModelViewProjectionMatrix[0][0], gl_ModelViewProjectionMatrix[1][1] ) );
|
||||
|
||||
|
||||
if( pixelWidth < 1.0 )
|
||||
pixelWidth = 1.0;
|
||||
if( pixelWidth < u_minLinePixelWidth )
|
||||
pixelWidth = u_minLinePixelWidth;
|
||||
|
||||
if ( pixelWidth > 1.0 || u_pixelSizeMultiplier > 1.0 )
|
||||
{
|
||||
@@ -126,8 +127,59 @@ void computeCircleCoords( float mode, float vertexIndex, float radius, float lin
|
||||
|
||||
vec4 adjust = vec4(-1, -1, 0, 0);
|
||||
|
||||
if( pixelWidth < 1.0 )
|
||||
pixelWidth = 1.0;
|
||||
if( pixelWidth < u_minLinePixelWidth )
|
||||
pixelWidth = u_minLinePixelWidth;
|
||||
|
||||
if( vertexIndex == 1.0 )
|
||||
{
|
||||
v_circleCoords = vec2( -sqrt( 3.0 ), -1.0 );
|
||||
delta = vec4( -pixelR * sqrt(3.0), -pixelR, 0, 0 );
|
||||
}
|
||||
else if( vertexIndex == 2.0 )
|
||||
{
|
||||
v_circleCoords = vec2( sqrt( 3.0 ), -1.0 );
|
||||
delta = vec4( pixelR * sqrt( 3.0 ), -pixelR, 0, 0 );
|
||||
}
|
||||
else if( vertexIndex == 3.0 )
|
||||
{
|
||||
v_circleCoords = vec2( 0.0, 2.0 );
|
||||
delta = vec4( 0, 2 * pixelR, 0, 0 );
|
||||
}
|
||||
else if( vertexIndex == 4.0 )
|
||||
{
|
||||
v_circleCoords = vec2( -sqrt( 3.0 ), 0.0 );
|
||||
delta = vec4( 0, 0, 0, 0 );
|
||||
}
|
||||
else if( vertexIndex == 5.0 )
|
||||
{
|
||||
v_circleCoords = vec2( sqrt( 3.0 ), 0.0 );
|
||||
delta = vec4( 0, 0, 0, 0 );
|
||||
}
|
||||
else if( vertexIndex == 6.0 )
|
||||
{
|
||||
v_circleCoords = vec2( 0.0, 2.0 );
|
||||
delta = vec4( 0, 0, 0, 0 );
|
||||
}
|
||||
|
||||
v_shaderParams[2] = pixelR;
|
||||
v_shaderParams[3] = pixelWidth;
|
||||
|
||||
delta.x *= u_screenPixelSize.x;
|
||||
delta.y *= u_screenPixelSize.y;
|
||||
|
||||
gl_Position = center + delta + adjust;
|
||||
gl_FrontColor = gl_Color;
|
||||
}
|
||||
|
||||
void computeHoleWallCoords( float vertexIndex, float radius, float lineWidth )
|
||||
{
|
||||
vec4 delta;
|
||||
vec4 center = roundv( gl_ModelViewProjectionMatrix * gl_Vertex + vec4(1, 1, 0, 0), u_screenPixelSize );
|
||||
float pixelWidth = roundr( lineWidth / u_worldPixelSize, 1.0 );
|
||||
if( pixelWidth < u_minLinePixelWidth )
|
||||
pixelWidth = u_minLinePixelWidth;
|
||||
float pixelR = roundr( radius / u_worldPixelSize, 1.0 ) + pixelWidth;
|
||||
vec4 adjust = vec4(-1, -1, 0, 0);
|
||||
|
||||
if( vertexIndex == 1.0 )
|
||||
{
|
||||
@@ -195,6 +247,8 @@ void main()
|
||||
computeLineCoords( posture, vs, vp, vec2( -1, 1 ), vec2( -1, 0 ), lineWidth, true );
|
||||
else if( mode == SHADER_LINE_F )
|
||||
computeLineCoords( posture, -vs, vp, vec2( 1, 1 ), vec2( -1, 0 ), lineWidth, false );
|
||||
else if( mode == SHADER_HOLE_WALL )
|
||||
computeHoleWallCoords( v_shaderParams.y, v_shaderParams.z, v_shaderParams.w );
|
||||
else if( mode == SHADER_FILLED_CIRCLE || mode == SHADER_STROKED_CIRCLE)
|
||||
computeCircleCoords( mode, v_shaderParams.y, v_shaderParams.z, v_shaderParams.w );
|
||||
else
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
KIGIT_COMMON::KIGIT_COMMON( git_repository* aRepo ) :
|
||||
m_repo( aRepo ), m_connType( GIT_CONN_TYPE::GIT_CONN_LOCAL ), m_testedTypes( 0 ),
|
||||
m_nextPublicKey( 0 )
|
||||
m_nextPublicKey( 0 ), m_secretFetched( false )
|
||||
{}
|
||||
|
||||
KIGIT_COMMON::KIGIT_COMMON( const KIGIT_COMMON& aOther ) :
|
||||
@@ -55,7 +55,8 @@ KIGIT_COMMON::KIGIT_COMMON( const KIGIT_COMMON& aOther ) :
|
||||
// The mutex is default-initialized, not copied
|
||||
m_gitActionMutex(),
|
||||
m_publicKeys( aOther.m_publicKeys ),
|
||||
m_nextPublicKey( aOther.m_nextPublicKey )
|
||||
m_nextPublicKey( aOther.m_nextPublicKey ),
|
||||
m_secretFetched( aOther.m_secretFetched )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -100,6 +101,25 @@ wxString KIGIT_COMMON::GetCurrentBranchName() const
|
||||
}
|
||||
|
||||
|
||||
wxString KIGIT_COMMON::GetPassword()
|
||||
{
|
||||
if( !m_secretFetched )
|
||||
{
|
||||
if( m_connType != GIT_CONN_TYPE::GIT_CONN_LOCAL && !m_remote.IsEmpty() )
|
||||
{
|
||||
wxString secret;
|
||||
|
||||
if( KIPLATFORM::SECRETS::GetSecret( m_remote, m_username, secret ) )
|
||||
m_password = secret;
|
||||
}
|
||||
|
||||
m_secretFetched = true;
|
||||
}
|
||||
|
||||
return m_password;
|
||||
}
|
||||
|
||||
|
||||
std::vector<wxString> KIGIT_COMMON::GetBranchNames() const
|
||||
{
|
||||
if( !m_repo )
|
||||
@@ -645,6 +665,10 @@ void KIGIT_COMMON::UpdateCurrentBranchInfo()
|
||||
wxString remote_name = GetRemotename();
|
||||
git_remote* remote = nullptr;
|
||||
|
||||
m_remote.clear();
|
||||
m_password.clear();
|
||||
m_secretFetched = false;
|
||||
|
||||
if( git_remote_lookup( &remote, m_repo, remote_name.ToStdString().c_str() ) == GIT_OK )
|
||||
{
|
||||
const char* url = git_remote_url( remote );
|
||||
@@ -655,9 +679,6 @@ void KIGIT_COMMON::UpdateCurrentBranchInfo()
|
||||
git_remote_free( remote );
|
||||
}
|
||||
|
||||
// Find the stored password if it exists
|
||||
KIPLATFORM::SECRETS::GetSecret( m_remote, m_username, m_password );
|
||||
|
||||
updateConnectionType();
|
||||
updatePublicKeys();
|
||||
}
|
||||
@@ -748,6 +769,8 @@ void KIGIT_COMMON::updateConnectionType()
|
||||
m_hostname = host;
|
||||
}
|
||||
}
|
||||
|
||||
m_secretFetched = !m_password.IsEmpty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -89,11 +89,11 @@ public:
|
||||
};
|
||||
|
||||
wxString GetUsername() const { return m_username; }
|
||||
wxString GetPassword() const { return m_password; }
|
||||
wxString GetPassword();
|
||||
GIT_CONN_TYPE GetConnType() const;
|
||||
|
||||
void SetUsername( const wxString& aUsername ) { m_username = aUsername; }
|
||||
void SetPassword( const wxString& aPassword ) { m_password = aPassword; }
|
||||
void SetUsername( const wxString& aUsername ) { m_username = aUsername; m_secretFetched = false; }
|
||||
void SetPassword( const wxString& aPassword ) { m_password = aPassword; m_secretFetched = true; }
|
||||
void SetSSHKey( const wxString& aSSHKey );
|
||||
|
||||
// Holds a temporary variable that can be used by the authentication callback
|
||||
@@ -127,6 +127,8 @@ public:
|
||||
void SetRemote( const wxString& aRemote )
|
||||
{
|
||||
m_remote = aRemote;
|
||||
m_password.clear();
|
||||
m_secretFetched = false;
|
||||
updateConnectionType();
|
||||
}
|
||||
|
||||
@@ -170,6 +172,7 @@ private:
|
||||
|
||||
std::vector<wxString> m_publicKeys;
|
||||
int m_nextPublicKey;
|
||||
bool m_secretFetched;
|
||||
|
||||
// Create a dummy flag to tell if we have tested ssh agent credentials separately
|
||||
// from the ssh key credentials
|
||||
|
||||
@@ -40,19 +40,11 @@ HTTP_LIB_CONNECTION::HTTP_LIB_CONNECTION( const HTTP_LIB_SOURCE& aSource, bool a
|
||||
m_source = aSource;
|
||||
|
||||
if( aTestConnectionNow )
|
||||
{
|
||||
ValidateHTTPLibraryEndpoints();
|
||||
}
|
||||
validateHttpLibraryEndpoints();
|
||||
}
|
||||
|
||||
|
||||
HTTP_LIB_CONNECTION::~HTTP_LIB_CONNECTION()
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
|
||||
bool HTTP_LIB_CONNECTION::ValidateHTTPLibraryEndpoints()
|
||||
bool HTTP_LIB_CONNECTION::validateHttpLibraryEndpoints()
|
||||
{
|
||||
m_endpointValid = false;
|
||||
std::string res = "";
|
||||
@@ -78,11 +70,8 @@ bool HTTP_LIB_CONNECTION::ValidateHTTPLibraryEndpoints()
|
||||
nlohmann::json response = nlohmann::json::parse( res );
|
||||
|
||||
// Check that the endpoints exist, if not fail.
|
||||
if( !response.at( http_endpoint_categories ).empty()
|
||||
&& !response.at( http_endpoint_parts ).empty() )
|
||||
{
|
||||
if( !response.at( "categories" ).empty() && !response.at( "parts" ).empty() )
|
||||
m_endpointValid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( const std::exception& e )
|
||||
@@ -90,29 +79,19 @@ bool HTTP_LIB_CONNECTION::ValidateHTTPLibraryEndpoints()
|
||||
m_lastError += wxString::Format( _( "Error: %s" ) + "\n" + _( "API Response: %s" ) + "\n",
|
||||
e.what(), res );
|
||||
|
||||
wxLogTrace( traceHTTPLib,
|
||||
wxT( "ValidateHTTPLibraryEndpoints: Exception occurred while testing the API "
|
||||
"connection: %s" ),
|
||||
wxLogTrace( traceHTTPLib, wxT( "validateHttpLibraryEndpoints: Exception while testing API connection: %s" ),
|
||||
m_lastError );
|
||||
|
||||
m_endpointValid = false;
|
||||
}
|
||||
|
||||
if( m_endpointValid )
|
||||
{
|
||||
syncCategories();
|
||||
}
|
||||
|
||||
return m_endpointValid;
|
||||
}
|
||||
|
||||
|
||||
bool HTTP_LIB_CONNECTION::IsValidEndpoint() const
|
||||
{
|
||||
return m_endpointValid;
|
||||
}
|
||||
|
||||
|
||||
bool HTTP_LIB_CONNECTION::syncCategories()
|
||||
{
|
||||
if( !IsValidEndpoint() )
|
||||
@@ -124,7 +103,7 @@ bool HTTP_LIB_CONNECTION::syncCategories()
|
||||
std::string res = "";
|
||||
|
||||
std::unique_ptr<KICAD_CURL_EASY> curl = createCurlEasyObject();
|
||||
curl->SetURL( m_source.root_url + http_endpoint_categories + ".json" );
|
||||
curl->SetURL( m_source.root_url + "categories.json" );
|
||||
|
||||
try
|
||||
{
|
||||
@@ -133,9 +112,7 @@ bool HTTP_LIB_CONNECTION::syncCategories()
|
||||
res = curl->GetBuffer();
|
||||
|
||||
if( !checkServerResponse( curl ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
nlohmann::json response = nlohmann::json::parse( res );
|
||||
|
||||
@@ -162,9 +139,7 @@ bool HTTP_LIB_CONNECTION::syncCategories()
|
||||
m_lastError += wxString::Format( _( "Error: %s" ) + "\n" + _( "API Response: %s" ) + "\n",
|
||||
e.what(), res );
|
||||
|
||||
wxLogTrace( traceHTTPLib,
|
||||
wxT( "syncCategories: Exception occurred while syncing categories: %s" ),
|
||||
m_lastError );
|
||||
wxLogTrace( traceHTTPLib, wxT( "syncCategories: Exception while syncing categories: %s" ), m_lastError );
|
||||
|
||||
m_categories.clear();
|
||||
|
||||
@@ -187,8 +162,7 @@ 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;
|
||||
@@ -198,7 +172,7 @@ bool HTTP_LIB_CONNECTION::SelectOne( const std::string& aPartID, HTTP_LIB_PART&
|
||||
std::string res = "";
|
||||
|
||||
std::unique_ptr<KICAD_CURL_EASY> curl = createCurlEasyObject();
|
||||
std::string url = m_source.root_url + fmt::format( "{}/{}.json", http_endpoint_parts, aPartID );
|
||||
std::string url = m_source.root_url + fmt::format( "parts/{}.json", aPartID );
|
||||
curl->SetURL( url );
|
||||
|
||||
try
|
||||
@@ -208,9 +182,7 @@ bool HTTP_LIB_CONNECTION::SelectOne( const std::string& aPartID, HTTP_LIB_PART&
|
||||
res = curl->GetBuffer();
|
||||
|
||||
if( !checkServerResponse( curl ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
nlohmann::ordered_json response = nlohmann::ordered_json::parse( res );
|
||||
std::string key = "";
|
||||
@@ -225,13 +197,9 @@ bool HTTP_LIB_CONNECTION::SelectOne( const std::string& aPartID, HTTP_LIB_PART&
|
||||
|
||||
// API might not want to return an optional name.
|
||||
if( response.contains( "name" ) )
|
||||
{
|
||||
aFetchedPart.name = response.at( "name" );
|
||||
}
|
||||
else
|
||||
{
|
||||
aFetchedPart.name = aFetchedPart.id;
|
||||
}
|
||||
|
||||
aFetchedPart.symbolIdStr = response.at( "symbolIdStr" );
|
||||
|
||||
@@ -285,18 +253,36 @@ bool HTTP_LIB_CONNECTION::SelectOne( const std::string& aPartID, HTTP_LIB_PART&
|
||||
}
|
||||
|
||||
// Add field to fields list
|
||||
aFetchedPart.fields.push_back(
|
||||
std::make_pair( key, std::make_tuple( value, visible ) ) );
|
||||
aFetchedPart.fields.push_back( std::make_pair( key, std::make_tuple( value, visible ) ) );
|
||||
}
|
||||
|
||||
if( response.contains( "description" ) )
|
||||
aFetchedPart.desc = response.at( "description" );
|
||||
|
||||
if( response.contains( "keywords" ) )
|
||||
aFetchedPart.keywords = response.at( "keywords" );
|
||||
|
||||
if( response.contains( "footprint_filters" ) )
|
||||
{
|
||||
nlohmann::json filters_json = response.at( "footprint_filters" );
|
||||
|
||||
if( filters_json.is_array() )
|
||||
{
|
||||
for( const auto& val : filters_json )
|
||||
aFetchedPart.fp_filters.push_back( val );
|
||||
}
|
||||
else
|
||||
{
|
||||
aFetchedPart.fp_filters.push_back( filters_json );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( const std::exception& e )
|
||||
{
|
||||
m_lastError += wxString::Format( _( "Error: %s" ) + "\n" + _( "API Response: %s" ) + "\n",
|
||||
m_lastError += wxString::Format( _( "Error: %s" ) + "\n" + _( "API Response: %s" ) + "\n",
|
||||
e.what(), res );
|
||||
|
||||
wxLogTrace( traceHTTPLib,
|
||||
wxT( "SelectOne: Exception occurred while retrieving part from REST API: %s" ),
|
||||
m_lastError );
|
||||
wxLogTrace( traceHTTPLib, wxT( "SelectOne: Exception while fetching part: %s" ), m_lastError );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -307,8 +293,7 @@ bool HTTP_LIB_CONNECTION::SelectOne( const std::string& aPartID, HTTP_LIB_PART&
|
||||
}
|
||||
|
||||
|
||||
bool HTTP_LIB_CONNECTION::SelectAll( const HTTP_LIB_CATEGORY& aCategory,
|
||||
std::vector<HTTP_LIB_PART>& aParts )
|
||||
bool HTTP_LIB_CONNECTION::SelectAll( const HTTP_LIB_CATEGORY& aCategory, std::vector<HTTP_LIB_PART>& aParts )
|
||||
{
|
||||
if( !IsValidEndpoint() )
|
||||
{
|
||||
@@ -320,8 +305,7 @@ bool HTTP_LIB_CONNECTION::SelectAll( const HTTP_LIB_CATEGORY& aCategory,
|
||||
|
||||
std::unique_ptr<KICAD_CURL_EASY> curl = createCurlEasyObject();
|
||||
|
||||
curl->SetURL( m_source.root_url
|
||||
+ fmt::format( "{}/category/{}.json", http_endpoint_parts, aCategory.id ) );
|
||||
curl->SetURL( m_source.root_url + fmt::format( "parts/category/{}.json", aCategory.id ) );
|
||||
|
||||
try
|
||||
{
|
||||
@@ -339,21 +323,13 @@ bool HTTP_LIB_CONNECTION::SelectAll( const HTTP_LIB_CATEGORY& aCategory,
|
||||
part.id = item.at( "id" );
|
||||
|
||||
if( item.contains( "description" ) )
|
||||
{
|
||||
// At this point we don't display anything so just set it to false
|
||||
part.fields.push_back( std::make_pair(
|
||||
"description", std::make_tuple( item.at( "description" ), false ) ) );
|
||||
}
|
||||
part.desc = item.at( "description" );
|
||||
|
||||
// API might not want to return an optional name.
|
||||
if( item.contains( "name" ) )
|
||||
{
|
||||
part.name = item.at( "name" );
|
||||
}
|
||||
else
|
||||
{
|
||||
part.name = part.id;
|
||||
}
|
||||
|
||||
// add to cache
|
||||
m_cache[part.name] = std::make_tuple( part.id, aCategory.id );
|
||||
@@ -363,11 +339,10 @@ bool HTTP_LIB_CONNECTION::SelectAll( const HTTP_LIB_CATEGORY& aCategory,
|
||||
}
|
||||
catch( const std::exception& e )
|
||||
{
|
||||
m_lastError += wxString::Format( _( "Error: %s" ) + "\n" + _( "API Response: %s" ) + "\n",
|
||||
m_lastError += wxString::Format( _( "Error: %s" ) + "\n" + _( "API Response: %s" ) + "\n",
|
||||
e.what(), res );
|
||||
|
||||
wxLogTrace( traceHTTPLib, wxT( "Exception occurred while syncing parts from REST API: %s" ),
|
||||
m_lastError );
|
||||
wxLogTrace( traceHTTPLib, wxT( "Exception occurred while syncing parts: %s" ), m_lastError );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -379,6 +354,7 @@ bool HTTP_LIB_CONNECTION::SelectAll( const HTTP_LIB_CATEGORY& aCategory,
|
||||
bool HTTP_LIB_CONNECTION::checkServerResponse( std::unique_ptr<KICAD_CURL_EASY>& aCurl )
|
||||
{
|
||||
int statusCode = aCurl->GetResponseStatusCode();
|
||||
|
||||
if( statusCode != 200 )
|
||||
{
|
||||
m_lastError += wxString::Format( _( "API responded with error code: %s" ) + "\n",
|
||||
|
||||
@@ -35,10 +35,9 @@ const int httplibSchemaVersion = 1;
|
||||
HTTP_LIB_SETTINGS::HTTP_LIB_SETTINGS( const std::string& aFilename ) :
|
||||
JSON_SETTINGS( aFilename, SETTINGS_LOC::NONE, httplibSchemaVersion )
|
||||
{
|
||||
m_params.emplace_back( new PARAM<std::string>( "source.type", &sourceType, "" ) );
|
||||
m_params.emplace_back( new PARAM<std::string>( "source.type", &m_sourceType, "" ) );
|
||||
|
||||
m_params.emplace_back(
|
||||
new PARAM<std::string>( "source.api_version", &m_Source.api_version, "" ) );
|
||||
m_params.emplace_back( new PARAM<std::string>( "source.api_version", &m_Source.api_version, "" ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<std::string>( "source.root_url", &m_Source.root_url, "" ) );
|
||||
|
||||
@@ -46,8 +45,7 @@ HTTP_LIB_SETTINGS::HTTP_LIB_SETTINGS( const std::string& aFilename ) :
|
||||
|
||||
m_params.emplace_back( new PARAM<int>( "source.timeout_parts_seconds", &m_Source.timeout_parts, 30 ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<int>( "source.timeout_categories_seconds",
|
||||
&m_Source.timeout_categories, 600 ) );
|
||||
m_params.emplace_back( new PARAM<int>( "source.timeout_categories_seconds", &m_Source.timeout_categories, 600 ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +119,10 @@ std::map<wxString, wxString> ALTIUM_ASCII_PARSER::ReadProperties()
|
||||
if( canonicalKey == wxT( "DESIGNATOR" ) || canonicalKey == wxT( "NAME" )
|
||||
|| canonicalKey == wxT( "TEXT" ) )
|
||||
{
|
||||
if( kv[ wxT( "RECORD" ) ] != wxT( "4" ) )
|
||||
wxString recordType = kv[ wxT( "RECORD" ) ];
|
||||
|
||||
// RECORD=33 (FILE_NAME) stores Windows-formatted paths; keep the backslashes intact.
|
||||
if( recordType != wxT( "4" ) && recordType != wxT( "33" ) )
|
||||
value = AltiumPropertyToKiCadString( value );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ JOB_EXPORT_PCB_ODB::JOB_EXPORT_PCB_ODB() :
|
||||
m_filename(),
|
||||
m_drawingSheet(),
|
||||
m_units( ODB_UNITS::MM ),
|
||||
m_precision( 2 ),
|
||||
m_precision( 4 ),
|
||||
m_compressionMode( ODB_COMPRESSION::ZIP )
|
||||
{
|
||||
m_params.emplace_back( new JOB_PARAM<wxString>( "drawing_sheet", &m_drawingSheet, m_drawingSheet ) );
|
||||
|
||||
@@ -85,6 +85,7 @@ JOB_PCB_RENDER::JOB_PCB_RENDER() :
|
||||
{
|
||||
m_params.emplace_back( new JOB_PARAM<FORMAT>( "format", &m_format, m_format ) );
|
||||
m_params.emplace_back( new JOB_PARAM<std::string>( "preset", &m_appearancePreset, m_appearancePreset ) );
|
||||
m_params.emplace_back( new JOB_PARAM<bool>( "use_board_stackup_colors", &m_useBoardStackupColors, m_useBoardStackupColors ) );
|
||||
m_params.emplace_back( new JOB_PARAM<QUALITY>( "quality", &m_quality, m_quality ) );
|
||||
m_params.emplace_back( new JOB_PARAM<BG_STYLE>( "bg_style", &m_bgStyle, m_bgStyle ) );
|
||||
m_params.emplace_back( new JOB_PARAM<SIDE>( "side", &m_side, m_side ) );
|
||||
|
||||
@@ -87,6 +87,7 @@ public:
|
||||
int m_width = 0;
|
||||
int m_height = 0;
|
||||
std::string m_appearancePreset;
|
||||
bool m_useBoardStackupColors = true;
|
||||
SIDE m_side = SIDE::TOP;
|
||||
double m_zoom = 1.0;
|
||||
bool m_perspective = false;
|
||||
|
||||
@@ -39,7 +39,7 @@ JOB_RC::JOB_RC( const std::string& aType ) :
|
||||
m_units( JOB_RC::UNITS::MM ),
|
||||
m_severity( RPT_SEVERITY_ERROR | RPT_SEVERITY_WARNING ),
|
||||
m_format( OUTPUT_FORMAT::REPORT ),
|
||||
m_exitCodeViolations( false )
|
||||
m_exitCodeViolations( true ) // this ensures GUI jobs default to treat violations as job failure, cli will default false elsewhere
|
||||
{
|
||||
m_params.emplace_back( new JOB_PARAM<UNITS>( "units", &m_units, m_units ) );
|
||||
m_params.emplace_back( new JOB_PARAM<int>( "severity", &m_severity, m_severity ) );
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <wx/zipstrm.h>
|
||||
#include <gestfich.h>
|
||||
#include <common.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
|
||||
JOBS_OUTPUT_ARCHIVE::JOBS_OUTPUT_ARCHIVE() :
|
||||
JOBS_OUTPUT_HANDLER(),
|
||||
@@ -52,6 +53,8 @@ bool JOBS_OUTPUT_ARCHIVE::HandleOutputs( const wxString& baseTempPath, PROJECT*
|
||||
if( outputPath.StartsWith( "~" ) )
|
||||
outputPath.Replace( "~", wxGetHomeDir(), false );
|
||||
|
||||
outputPath = EnsureFileExtension( outputPath, FILEEXT::ArchiveFileExtension );
|
||||
|
||||
wxFFileOutputStream ostream( outputPath );
|
||||
|
||||
if( !ostream.IsOk() ) // issue to create the file. Perhaps not writable dir
|
||||
|
||||
@@ -134,29 +134,12 @@ LIB_TREE_NODE::LIB_TREE_NODE()
|
||||
|
||||
LIB_TREE_NODE_UNIT::LIB_TREE_NODE_UNIT( LIB_TREE_NODE* aParent, LIB_TREE_ITEM* aItem, int aUnit )
|
||||
{
|
||||
static void* locale = nullptr;
|
||||
static wxString namePrefix;
|
||||
|
||||
// Fetching translations can take a surprising amount of time when loading libraries,
|
||||
// so only do it when necessary.
|
||||
if( Pgm().GetLocale() != locale )
|
||||
{
|
||||
namePrefix = _( "Unit" );
|
||||
locale = Pgm().GetLocale();
|
||||
}
|
||||
|
||||
m_Parent = aParent;
|
||||
m_Type = TYPE::UNIT;
|
||||
|
||||
m_Unit = aUnit;
|
||||
m_LibId = aParent->m_LibId;
|
||||
|
||||
m_Name = namePrefix + " " + aItem->GetUnitReference( aUnit );
|
||||
|
||||
if( aItem->HasUnitDisplayName( aUnit ) )
|
||||
m_Desc = aItem->GetUnitDisplayName( aUnit );
|
||||
else
|
||||
m_Desc = wxEmptyString;
|
||||
m_Name = aItem->GetUnitName( aUnit );
|
||||
|
||||
m_IntrinsicRank = -aUnit;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <wx/wupdlock.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/dc.h>
|
||||
#include <wx/log.h>
|
||||
#include <string_utils.h>
|
||||
|
||||
|
||||
@@ -308,6 +309,15 @@ void LIB_TREE_MODEL_ADAPTER::UpdateSearchString( const wxString& aSearch, bool a
|
||||
|
||||
const LIB_TREE_NODE* firstMatch = ShowResults();
|
||||
|
||||
#ifdef __WXGTK__
|
||||
// Ensure the control is repainted with the updated data. Without an explicit
|
||||
// refresh the Gtk port can display stale rows until the user interacts with
|
||||
// them, leading to mismatched tree contents.
|
||||
m_widget->Refresh();
|
||||
m_widget->Update();
|
||||
wxYield();
|
||||
#endif
|
||||
|
||||
if( firstMatch )
|
||||
{
|
||||
wxDataViewItem item = ToItem( firstMatch );
|
||||
|
||||
@@ -1150,7 +1150,9 @@ void UOP::Exec( CONTEXT* ctx )
|
||||
return;
|
||||
|
||||
case TR_OP_METHOD_CALL:
|
||||
m_func( ctx, m_ref.get() );
|
||||
if( m_func )
|
||||
m_func( ctx, m_ref.get() );
|
||||
|
||||
return;
|
||||
|
||||
default:
|
||||
@@ -1283,9 +1285,8 @@ VALUE* UCODE::Run( CONTEXT* ctx )
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
// rules which fail outright should not be fired
|
||||
std::unique_ptr<VALUE> temp_false = std::make_unique<VALUE>( 0 );
|
||||
return ctx->StoreValue( temp_false.get() );
|
||||
// rules which fail outright should not be fired; return 0/false
|
||||
return ctx->StoreValue( new VALUE( 0 ) );
|
||||
}
|
||||
|
||||
if( ctx->SP() == 1 )
|
||||
@@ -1301,8 +1302,7 @@ VALUE* UCODE::Run( CONTEXT* ctx )
|
||||
wxASSERT( ctx->SP() == 1 );
|
||||
|
||||
// non-well-formed rules should not be fired on a release build
|
||||
std::unique_ptr<VALUE> temp_false = std::make_unique<VALUE>( 0 );
|
||||
return ctx->StoreValue( temp_false.get() );
|
||||
return ctx->StoreValue( new VALUE( 0 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -278,7 +278,7 @@ bool NETCLASS::ContainsNetclassWithName( const wxString& netclass ) const
|
||||
return std::any_of( m_constituents.begin(), m_constituents.end(),
|
||||
[&netclass]( const NETCLASS* nc )
|
||||
{
|
||||
return nc && nc->GetName() == netclass;
|
||||
return nc && nc->GetName().Matches( netclass );
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,31 @@ enum class ELECTRICAL_PINTYPE
|
||||
|
||||
#define ELECTRICAL_PINTYPES_TOTAL ( static_cast<int>( ELECTRICAL_PINTYPE::PT_LAST_OPTION ) + 1 )
|
||||
|
||||
inline wxString GetCanonicalElectricalTypeName( ELECTRICAL_PINTYPE aType )
|
||||
{
|
||||
// These strings are the canonical name of the electrictal type
|
||||
// Not translated, no space in name, only ASCII chars.
|
||||
// to use when the string name must be known and well defined
|
||||
// must have same order than enum ELECTRICAL_PINTYPE (see sch_pin.h)
|
||||
static const wxChar* msgPinElectricType[] =
|
||||
{
|
||||
wxT( "input" ),
|
||||
wxT( "output" ),
|
||||
wxT( "bidirectional" ),
|
||||
wxT( "tri_state" ),
|
||||
wxT( "passive" ),
|
||||
wxT( "free" ),
|
||||
wxT( "unspecified" ),
|
||||
wxT( "power_in" ),
|
||||
wxT( "power_out" ),
|
||||
wxT( "open_collector" ),
|
||||
wxT( "open_emitter" ),
|
||||
wxT( "no_connect" )
|
||||
};
|
||||
|
||||
return msgPinElectricType[static_cast<int>( aType )];
|
||||
}
|
||||
|
||||
enum class GRAPHIC_PINSHAPE
|
||||
{
|
||||
LINE,
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "preview_items/construction_geom.h"
|
||||
|
||||
#include <layer_ids.h>
|
||||
#include <utility>
|
||||
#include <gal/graphics_abstraction_layer.h>
|
||||
#include <geometry/shape_utils.h>
|
||||
#include <preview_items/item_drawing_utils.h>
|
||||
@@ -39,9 +40,15 @@ CONSTRUCTION_GEOM::CONSTRUCTION_GEOM() :
|
||||
}
|
||||
|
||||
|
||||
void CONSTRUCTION_GEOM::AddDrawable( const DRAWABLE& aItem, bool aPersistent )
|
||||
void CONSTRUCTION_GEOM::AddDrawable( const DRAWABLE& aItem, bool aPersistent, int aLineWidth )
|
||||
{
|
||||
m_drawables.push_back( { aItem, aPersistent } );
|
||||
m_drawables.push_back( { aItem, aPersistent, aLineWidth } );
|
||||
}
|
||||
|
||||
|
||||
void CONSTRUCTION_GEOM::SetSnapGuides( std::vector<SNAP_GUIDE> aGuides )
|
||||
{
|
||||
m_snapGuides = std::move( aGuides );
|
||||
}
|
||||
|
||||
|
||||
@@ -90,6 +97,7 @@ void CONSTRUCTION_GEOM::ViewDraw( int aLayer, VIEW* aView ) const
|
||||
for( const DRAWABLE_INFO& drawable : m_drawables )
|
||||
{
|
||||
gal.SetStrokeColor( drawable.IsPersistent ? m_persistentColor : m_color );
|
||||
gal.SetLineWidth( drawable.LineWidth );
|
||||
|
||||
std::visit(
|
||||
[&]( const auto& visited )
|
||||
@@ -139,9 +147,17 @@ void CONSTRUCTION_GEOM::ViewDraw( int aLayer, VIEW* aView ) const
|
||||
drawable.Item );
|
||||
}
|
||||
|
||||
for( const SNAP_GUIDE& guide : m_snapGuides )
|
||||
{
|
||||
gal.SetStrokeColor( guide.Color );
|
||||
gal.SetLineWidth( guide.LineWidth );
|
||||
gal.DrawLine( guide.Segment.A, guide.Segment.B );
|
||||
}
|
||||
|
||||
if( haveSnapLine )
|
||||
{
|
||||
gal.SetStrokeColor( m_persistentColor );
|
||||
gal.SetLineWidth( 2 );
|
||||
|
||||
const int dashSizeBasis = aView->ToWorld( 12 );
|
||||
const int snapOriginMarkerSize = aView->ToWorld( 16 );
|
||||
|
||||
@@ -335,7 +335,86 @@ void RULER_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
|
||||
VECTOR2D rulerVec( end - origin );
|
||||
|
||||
wxArrayString cursorStrings = GetDimensionStrings();
|
||||
DrawTextNextToCursor( aView, end, -rulerVec, cursorStrings, drawingDropShadows );
|
||||
|
||||
// Choose a text quadrant that keeps the measurement text on-screen while avoiding
|
||||
// overlapping the ruler geometry. Start with the preferred direction (away from the
|
||||
// origin) and fall back to other quadrants as needed to keep the label visible.
|
||||
int prefX = rulerVec.y < 0.0 ? -1 : 1;
|
||||
int prefY = rulerVec.x < 0.0 ? 1 : -1;
|
||||
|
||||
double scale = gal->GetWorldScale();
|
||||
|
||||
TEXT_DIMS dims = GetConstantGlyphHeight( gal );
|
||||
KIFONT::FONT* font = KIFONT::FONT::GetFont();
|
||||
double width = 0.0;
|
||||
|
||||
for( const wxString& s : cursorStrings )
|
||||
{
|
||||
VECTOR2I extents = font->StringBoundaryLimits( s, dims.GlyphSize, dims.StrokeWidth, false, false,
|
||||
KIFONT::METRICS::Default() );
|
||||
width = std::max( width, (double) extents.x );
|
||||
}
|
||||
|
||||
double height = dims.LinePitch * cursorStrings.size();
|
||||
|
||||
// Convert to screen coordinates for visibility checks
|
||||
VECTOR2D cursorScreen = gal->ToScreen( end );
|
||||
VECTOR2I screenSize = gal->GetScreenPixelSize();
|
||||
double offsetX = 15.0; // same as DrawTextNextToCursor()
|
||||
double offsetY = dims.LinePitch * scale; // vertical spacing from cursor
|
||||
|
||||
auto fits = [&]( int sx, int sy )
|
||||
{
|
||||
double left, right, top, bottom;
|
||||
double xStart = cursorScreen.x + ( sx < 0 ? offsetX : -offsetX );
|
||||
|
||||
if( sx < 0 )
|
||||
{
|
||||
left = xStart;
|
||||
right = left + width * scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
right = xStart;
|
||||
left = right - width * scale;
|
||||
}
|
||||
|
||||
if( sy > 0 ) // above cursor
|
||||
{
|
||||
bottom = cursorScreen.y - offsetY;
|
||||
top = bottom - height * scale;
|
||||
}
|
||||
else // below cursor
|
||||
{
|
||||
top = cursorScreen.y + offsetY;
|
||||
bottom = top + height * scale;
|
||||
}
|
||||
|
||||
return left >= 0 && right <= screenSize.x && top >= 0 && bottom <= screenSize.y;
|
||||
};
|
||||
|
||||
std::vector<VECTOR2I> candidates = { { prefX, prefY }, { -prefX, prefY },
|
||||
{ prefX, -prefY }, { -prefX, -prefY } };
|
||||
|
||||
VECTOR2I chosen = candidates[0];
|
||||
double bestDot = -1.0;
|
||||
|
||||
for( const VECTOR2I& c : candidates )
|
||||
{
|
||||
double dot = c.x * prefX + c.y * prefY;
|
||||
|
||||
if( dot >= 0 && fits( c.x, c.y ) )
|
||||
{
|
||||
if( dot > bestDot )
|
||||
{
|
||||
bestDot = dot;
|
||||
chosen = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VECTOR2D quadrant( chosen.x, chosen.y );
|
||||
DrawTextNextToCursor( aView, end, quadrant, cursorStrings, drawingDropShadows );
|
||||
|
||||
// basic tick size
|
||||
double minorTickLen = 5.0 / gal->GetWorldScale();
|
||||
|
||||
@@ -254,9 +254,11 @@ wxPGProperty* PGPropertyFactory( const PROPERTY_BASE* aProperty, EDA_DRAW_FRAME*
|
||||
// Enum property
|
||||
if( aProperty->HasChoices() )
|
||||
{
|
||||
const_cast<PROPERTY_BASE*>( aProperty )->TranslateChoices();
|
||||
|
||||
// I do not know why enum property takes a non-const reference to wxPGChoices..
|
||||
ret = new wxEnumProperty( wxPG_LABEL, wxPG_LABEL,
|
||||
const_cast<wxPGChoices&>( aProperty->Choices() ) );
|
||||
const_cast<wxPGChoices&>( aProperty->Choices() ) );
|
||||
}
|
||||
else if( typeId == TYPE_HASH( int ) || typeId == TYPE_HASH( long ) )
|
||||
{
|
||||
|
||||
@@ -25,10 +25,15 @@
|
||||
#include <properties/property.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <ranges>
|
||||
#include <utility>
|
||||
#include <wx/wx.h>
|
||||
|
||||
static wxString EMPTY_STRING( wxEmptyString );
|
||||
|
||||
// Global to prevent simultaneous multi-threaded static initialization
|
||||
static const std::vector<PROPERTY_BASE*> EMPTY_PROP_LIST;
|
||||
static const std::map<PROPERTY_BASE*, int> EMPTY_PROP_DISPLAY_ORDER;
|
||||
std::vector<wxString> EMPTY_GROUP_DISPLAY_ORDER;
|
||||
|
||||
|
||||
void PROPERTY_MANAGER::RegisterType( TYPE_ID aType, const wxString& aName )
|
||||
@@ -38,13 +43,6 @@ void PROPERTY_MANAGER::RegisterType( TYPE_ID aType, const wxString& aName )
|
||||
}
|
||||
|
||||
|
||||
const wxString& PROPERTY_MANAGER::ResolveType( TYPE_ID aType ) const
|
||||
{
|
||||
auto it = m_classNames.find( aType );
|
||||
return it != m_classNames.end() ? it->second : EMPTY_STRING;
|
||||
}
|
||||
|
||||
|
||||
PROPERTY_BASE* PROPERTY_MANAGER::GetProperty( TYPE_ID aType, const wxString& aProperty ) const
|
||||
{
|
||||
if( m_dirty )
|
||||
@@ -67,31 +65,29 @@ PROPERTY_BASE* PROPERTY_MANAGER::GetProperty( TYPE_ID aType, const wxString& aPr
|
||||
}
|
||||
|
||||
|
||||
const PROPERTY_LIST& PROPERTY_MANAGER::GetProperties( TYPE_ID aType ) const
|
||||
const std::vector<PROPERTY_BASE*>& PROPERTY_MANAGER::GetProperties( TYPE_ID aType ) const
|
||||
{
|
||||
if( m_dirty )
|
||||
const_cast<PROPERTY_MANAGER*>( this )->Rebuild();
|
||||
|
||||
static const PROPERTY_LIST empty;
|
||||
auto it = m_classes.find( aType );
|
||||
|
||||
if( it == m_classes.end() )
|
||||
return empty;
|
||||
return EMPTY_PROP_LIST;
|
||||
|
||||
return it->second.m_allProperties;
|
||||
}
|
||||
|
||||
|
||||
const PROPERTY_DISPLAY_ORDER& PROPERTY_MANAGER::GetDisplayOrder( TYPE_ID aType ) const
|
||||
const std::map<PROPERTY_BASE*, int>& PROPERTY_MANAGER::GetDisplayOrder( TYPE_ID aType ) const
|
||||
{
|
||||
if( m_dirty )
|
||||
const_cast<PROPERTY_MANAGER*>( this )->Rebuild();
|
||||
|
||||
static const PROPERTY_DISPLAY_ORDER empty;
|
||||
auto it = m_classes.find( aType );
|
||||
|
||||
if( it == m_classes.end() )
|
||||
return empty;
|
||||
return EMPTY_PROP_DISPLAY_ORDER;
|
||||
|
||||
return it->second.m_displayOrder;
|
||||
}
|
||||
@@ -102,11 +98,10 @@ const std::vector<wxString>& PROPERTY_MANAGER::GetGroupDisplayOrder( TYPE_ID aTy
|
||||
if( m_dirty )
|
||||
const_cast<PROPERTY_MANAGER*>( this )->Rebuild();
|
||||
|
||||
static const std::vector<wxString> empty;
|
||||
auto it = m_classes.find( aType );
|
||||
|
||||
if( it == m_classes.end() )
|
||||
return empty;
|
||||
return EMPTY_GROUP_DISPLAY_ORDER;
|
||||
|
||||
return it->second.m_groupDisplayOrder;
|
||||
}
|
||||
@@ -122,7 +117,7 @@ const void* PROPERTY_MANAGER::TypeCast( const void* aSource, TYPE_ID aBase, TYPE
|
||||
if( classDesc == m_classes.end() )
|
||||
return aSource;
|
||||
|
||||
auto& converters = classDesc->second.m_typeCasts;
|
||||
const std::map<TYPE_ID, std::unique_ptr<TYPE_CAST_BASE>>& converters = classDesc->second.m_typeCasts;
|
||||
auto converter = converters.find( aTarget );
|
||||
|
||||
if( converter == converters.end() ) // explicit type cast not found
|
||||
@@ -135,8 +130,9 @@ const void* PROPERTY_MANAGER::TypeCast( const void* aSource, TYPE_ID aBase, TYPE
|
||||
PROPERTY_BASE& PROPERTY_MANAGER::AddProperty( PROPERTY_BASE* aProperty, const wxString& aGroup )
|
||||
{
|
||||
const wxString& name = aProperty->Name();
|
||||
TYPE_ID hash = aProperty->OwnerHash();
|
||||
CLASS_DESC& classDesc = getClass( hash );
|
||||
TYPE_ID hash = aProperty->OwnerHash();
|
||||
CLASS_DESC& classDesc = getClass( hash );
|
||||
|
||||
classDesc.m_ownProperties.emplace( name, aProperty );
|
||||
classDesc.m_ownDisplayOrder.emplace_back( aProperty );
|
||||
|
||||
@@ -153,8 +149,8 @@ PROPERTY_BASE& PROPERTY_MANAGER::AddProperty( PROPERTY_BASE* aProperty, const wx
|
||||
}
|
||||
|
||||
|
||||
PROPERTY_BASE& PROPERTY_MANAGER::ReplaceProperty( size_t aBase, const wxString& aName,
|
||||
PROPERTY_BASE* aNew, const wxString& aGroup )
|
||||
PROPERTY_BASE& PROPERTY_MANAGER::ReplaceProperty( size_t aBase, const wxString& aName, PROPERTY_BASE* aNew,
|
||||
const wxString& aGroup )
|
||||
{
|
||||
CLASS_DESC& classDesc = getClass( aNew->OwnerHash() );
|
||||
classDesc.m_replaced.insert( std::make_pair( aBase, aName ) );
|
||||
@@ -164,31 +160,30 @@ PROPERTY_BASE& PROPERTY_MANAGER::ReplaceProperty( size_t aBase, const wxString&
|
||||
|
||||
void PROPERTY_MANAGER::AddTypeCast( TYPE_CAST_BASE* aCast )
|
||||
{
|
||||
TYPE_ID derivedHash = aCast->DerivedHash();
|
||||
TYPE_ID derivedHash = aCast->DerivedHash();
|
||||
CLASS_DESC& classDesc = getClass( aCast->BaseHash() );
|
||||
auto& typeCasts = classDesc.m_typeCasts;
|
||||
wxASSERT_MSG( typeCasts.count( derivedHash ) == 0, "Such converter already exists" );
|
||||
typeCasts.emplace( derivedHash, aCast );
|
||||
|
||||
wxASSERT_MSG( classDesc.m_typeCasts.count( derivedHash ) == 0, wxT( "Such converter already exists" ) );
|
||||
classDesc.m_typeCasts.emplace( derivedHash, aCast );
|
||||
}
|
||||
|
||||
|
||||
void PROPERTY_MANAGER::InheritsAfter( TYPE_ID aDerived, TYPE_ID aBase )
|
||||
{
|
||||
wxASSERT_MSG( aDerived != aBase, "Class cannot inherit from itself" );
|
||||
wxASSERT_MSG( aDerived != aBase, wxT( "Class cannot inherit from itself" ) );
|
||||
|
||||
CLASS_DESC& derived = getClass( aDerived );
|
||||
CLASS_DESC& base = getClass( aBase );
|
||||
derived.m_bases.push_back( base );
|
||||
derived.m_bases.push_back( getClass( aBase ) );
|
||||
m_dirty = true;
|
||||
|
||||
wxASSERT_MSG( derived.m_bases.size() == 1 || derived.m_typeCasts.count( aBase ) == 1,
|
||||
"You need to add a TYPE_CAST for classes inheriting from multiple bases" );
|
||||
wxT( "You need to add a TYPE_CAST for classes inheriting from multiple bases" ) );
|
||||
}
|
||||
|
||||
|
||||
void PROPERTY_MANAGER::Mask( TYPE_ID aDerived, TYPE_ID aBase, const wxString& aName )
|
||||
{
|
||||
wxASSERT_MSG( aDerived != aBase, "Class cannot mask from itself" );
|
||||
wxASSERT_MSG( aDerived != aBase, wxT( "Class cannot mask from itself" ) );
|
||||
|
||||
CLASS_DESC& derived = getClass( aDerived );
|
||||
derived.m_maskedBaseProperties.insert( std::make_pair( aBase, aName ) );
|
||||
@@ -196,11 +191,10 @@ void PROPERTY_MANAGER::Mask( TYPE_ID aDerived, TYPE_ID aBase, const wxString& aN
|
||||
}
|
||||
|
||||
|
||||
void PROPERTY_MANAGER::OverrideAvailability( TYPE_ID aDerived, TYPE_ID aBase,
|
||||
const wxString& aName,
|
||||
void PROPERTY_MANAGER::OverrideAvailability( TYPE_ID aDerived, TYPE_ID aBase, const wxString& aName,
|
||||
std::function<bool( INSPECTABLE* )> aFunc )
|
||||
{
|
||||
wxASSERT_MSG( aDerived != aBase, "Class cannot override from itself" );
|
||||
wxASSERT_MSG( aDerived != aBase, wxT( "Class cannot override from itself" ) );
|
||||
|
||||
CLASS_DESC& derived = getClass( aDerived );
|
||||
derived.m_availabilityOverrides[std::make_pair( aBase, aName )] = std::move( aFunc );
|
||||
@@ -208,11 +202,10 @@ void PROPERTY_MANAGER::OverrideAvailability( TYPE_ID aDerived, TYPE_ID aBase,
|
||||
}
|
||||
|
||||
|
||||
void PROPERTY_MANAGER::OverrideWriteability( TYPE_ID aDerived, TYPE_ID aBase,
|
||||
const wxString& aName,
|
||||
void PROPERTY_MANAGER::OverrideWriteability( TYPE_ID aDerived, TYPE_ID aBase, const wxString& aName,
|
||||
std::function<bool( INSPECTABLE* )> aFunc )
|
||||
{
|
||||
wxASSERT_MSG( aDerived != aBase, "Class cannot override from itself" );
|
||||
wxASSERT_MSG( aDerived != aBase, wxT( "Class cannot override from itself" ) );
|
||||
|
||||
CLASS_DESC& derived = getClass( aDerived );
|
||||
derived.m_writeabilityOverrides[std::make_pair( aBase, aName )] = std::move( aFunc );
|
||||
@@ -220,16 +213,14 @@ void PROPERTY_MANAGER::OverrideWriteability( TYPE_ID aDerived, TYPE_ID aBase,
|
||||
}
|
||||
|
||||
|
||||
bool PROPERTY_MANAGER::IsAvailableFor( TYPE_ID aItemClass, PROPERTY_BASE* aProp,
|
||||
INSPECTABLE* aItem )
|
||||
bool PROPERTY_MANAGER::IsAvailableFor( TYPE_ID aItemClass, PROPERTY_BASE* aProp, INSPECTABLE* aItem )
|
||||
{
|
||||
if( !aProp->Available( aItem ) )
|
||||
return false;
|
||||
|
||||
CLASS_DESC& derived = getClass( aItemClass );
|
||||
|
||||
auto it = derived.m_availabilityOverrides.find( std::make_pair( aProp->BaseHash(),
|
||||
aProp->Name() ) );
|
||||
auto it = derived.m_availabilityOverrides.find( std::make_pair( aProp->BaseHash(), aProp->Name() ) );
|
||||
|
||||
if( it != derived.m_availabilityOverrides.end() )
|
||||
return it->second( aItem );
|
||||
@@ -238,16 +229,14 @@ bool PROPERTY_MANAGER::IsAvailableFor( TYPE_ID aItemClass, PROPERTY_BASE* aProp,
|
||||
}
|
||||
|
||||
|
||||
bool PROPERTY_MANAGER::IsWriteableFor( TYPE_ID aItemClass, PROPERTY_BASE* aProp,
|
||||
INSPECTABLE* aItem )
|
||||
bool PROPERTY_MANAGER::IsWriteableFor( TYPE_ID aItemClass, PROPERTY_BASE* aProp, INSPECTABLE* aItem )
|
||||
{
|
||||
if( !aProp->Writeable( aItem ) )
|
||||
return false;
|
||||
|
||||
CLASS_DESC& derived = getClass( aItemClass );
|
||||
|
||||
auto it = derived.m_writeabilityOverrides.find( std::make_pair( aProp->BaseHash(),
|
||||
aProp->Name() ) );
|
||||
auto it = derived.m_writeabilityOverrides.find( std::make_pair( aProp->BaseHash(), aProp->Name() ) );
|
||||
|
||||
if( it != derived.m_writeabilityOverrides.end() )
|
||||
return it->second( aItem );
|
||||
@@ -265,7 +254,7 @@ bool PROPERTY_MANAGER::IsOfType( TYPE_ID aDerived, TYPE_ID aBase ) const
|
||||
wxCHECK( derived != m_classes.end(), false ); // missing class description
|
||||
|
||||
// traverse the hierarchy seeking for the base class
|
||||
for( auto& base : derived->second.m_bases )
|
||||
for( const std::reference_wrapper<CLASS_DESC>& base : derived->second.m_bases )
|
||||
{
|
||||
if( IsOfType( base.get().m_id, aBase ) )
|
||||
return true;
|
||||
@@ -297,8 +286,8 @@ PROPERTY_MANAGER::CLASS_DESC& PROPERTY_MANAGER::getClass( TYPE_ID aTypeId )
|
||||
|
||||
void PROPERTY_MANAGER::CLASS_DESC::rebuild()
|
||||
{
|
||||
PROPERTY_SET replaced;
|
||||
PROPERTY_SET masked;
|
||||
std::set<std::pair<size_t, wxString>> replaced;
|
||||
std::set<std::pair<size_t, wxString>> masked;
|
||||
m_allProperties.clear();
|
||||
collectPropsRecur( m_allProperties, replaced, m_displayOrder, masked );
|
||||
|
||||
@@ -338,10 +327,10 @@ void PROPERTY_MANAGER::CLASS_DESC::rebuild()
|
||||
}
|
||||
|
||||
|
||||
void PROPERTY_MANAGER::CLASS_DESC::collectPropsRecur( PROPERTY_LIST& aResult,
|
||||
PROPERTY_SET& aReplaced,
|
||||
PROPERTY_DISPLAY_ORDER& aDisplayOrder,
|
||||
PROPERTY_SET& aMasked ) const
|
||||
void PROPERTY_MANAGER::CLASS_DESC::collectPropsRecur( std::vector<PROPERTY_BASE*>& aResult,
|
||||
std::set<std::pair<size_t, wxString>>& aReplaced,
|
||||
std::map<PROPERTY_BASE*, int>& aDisplayOrder,
|
||||
std::set<std::pair<size_t, wxString>>& aMasked ) const
|
||||
{
|
||||
for( const std::pair<size_t, wxString>& replacedEntry : m_replaced )
|
||||
aReplaced.emplace( replacedEntry );
|
||||
@@ -371,8 +360,8 @@ void PROPERTY_MANAGER::CLASS_DESC::collectPropsRecur( PROPERTY_LIST& aResult,
|
||||
|
||||
for( PROPERTY_BASE* property : m_ownDisplayOrder )
|
||||
{
|
||||
PROPERTY_SET::key_type propertyKey = std::make_pair( property->OwnerHash(),
|
||||
property->Name() );
|
||||
std::set<std::pair<size_t, wxString>>::key_type propertyKey = std::make_pair( property->OwnerHash(),
|
||||
property->Name() );
|
||||
// Do not store replaced properties
|
||||
if( aReplaced.count( propertyKey ) )
|
||||
continue;
|
||||
@@ -386,28 +375,8 @@ void PROPERTY_MANAGER::CLASS_DESC::collectPropsRecur( PROPERTY_LIST& aResult,
|
||||
}
|
||||
|
||||
// Iterate backwards so that replaced properties appear before base properties
|
||||
for( auto it = m_bases.rbegin(); it != m_bases.rend(); ++it )
|
||||
it->get().collectPropsRecur( aResult, aReplaced, aDisplayOrder, aMasked );
|
||||
}
|
||||
|
||||
|
||||
std::vector<TYPE_ID> PROPERTY_MANAGER::GetMatchingClasses( PROPERTY_BASE* aProperty )
|
||||
{
|
||||
std::vector<TYPE_ID> ids;
|
||||
|
||||
/*
|
||||
for( auto& cls : m_classes )
|
||||
{
|
||||
CLASS_INFO info;
|
||||
|
||||
for( auto prop : cls.second.m_allProperties )
|
||||
info.properties.push_back(prop);
|
||||
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
return ids;
|
||||
for( std::reference_wrapper<CLASS_DESC> base : std::ranges::reverse_view( m_bases ) )
|
||||
base.get().collectPropsRecur( aResult, aReplaced, aDisplayOrder, aMasked );
|
||||
}
|
||||
|
||||
|
||||
@@ -458,7 +427,7 @@ void PROPERTY_MANAGER::PropertyChanged( INSPECTABLE* aObject, PROPERTY_BASE* aPr
|
||||
PROPERTY_COMMIT_HANDLER::PROPERTY_COMMIT_HANDLER( COMMIT* aCommit )
|
||||
{
|
||||
wxCHECK2_MSG( PROPERTY_MANAGER::Instance().m_managedCommit == nullptr,
|
||||
return, "Can't have more than one managed commit at a time!" );
|
||||
return, wxT( "Can't have more than one managed commit at a time!" ) );
|
||||
|
||||
PROPERTY_MANAGER::Instance().m_managedCommit = aCommit;
|
||||
}
|
||||
@@ -467,7 +436,7 @@ PROPERTY_COMMIT_HANDLER::PROPERTY_COMMIT_HANDLER( COMMIT* aCommit )
|
||||
PROPERTY_COMMIT_HANDLER::~PROPERTY_COMMIT_HANDLER()
|
||||
{
|
||||
wxASSERT_MSG( PROPERTY_MANAGER::Instance().m_managedCommit != nullptr,
|
||||
"Something went wrong: m_managedCommit already null!" );
|
||||
wxT( "Something went wrong: m_managedCommit already null!" ) );
|
||||
|
||||
PROPERTY_MANAGER::Instance().m_managedCommit = nullptr;
|
||||
}
|
||||
|
||||
+11
-21
@@ -65,12 +65,6 @@ REPORTER& WX_TEXT_CTRL_REPORTER::Report( const wxString& aText, SEVERITY aSeveri
|
||||
}
|
||||
|
||||
|
||||
bool WX_TEXT_CTRL_REPORTER::HasMessage() const
|
||||
{
|
||||
return !m_textCtrl->IsEmpty();
|
||||
}
|
||||
|
||||
|
||||
REPORTER& WX_STRING_REPORTER::Report( const wxString& aText, SEVERITY aSeverity )
|
||||
{
|
||||
REPORTER::Report( aText, aSeverity );
|
||||
@@ -93,12 +87,6 @@ void WX_STRING_REPORTER::Clear()
|
||||
}
|
||||
|
||||
|
||||
bool WX_STRING_REPORTER::HasMessage() const
|
||||
{
|
||||
return !m_string.IsEmpty();
|
||||
}
|
||||
|
||||
|
||||
REPORTER& NULL_REPORTER::Report( const wxString& aText, SEVERITY aSeverity )
|
||||
{
|
||||
return REPORTER::Report( aText, aSeverity );
|
||||
@@ -211,6 +199,17 @@ REPORTER& WXLOG_REPORTER::GetInstance()
|
||||
}
|
||||
|
||||
|
||||
REPORTER& REDIRECT_REPORTER::Report( const wxString& aText, SEVERITY aSeverity )
|
||||
{
|
||||
REPORTER::Report( aText, aSeverity );
|
||||
|
||||
if( m_redirectTarget )
|
||||
m_redirectTarget->Report( aText, aSeverity );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
REPORTER& STATUSBAR_REPORTER::Report( const wxString& aText, SEVERITY aSeverity )
|
||||
{
|
||||
REPORTER::Report( aText, aSeverity );
|
||||
@@ -220,12 +219,3 @@ REPORTER& STATUSBAR_REPORTER::Report( const wxString& aText, SEVERITY aSeverity
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bool STATUSBAR_REPORTER::HasMessage() const
|
||||
{
|
||||
if( m_statusBar )
|
||||
return !m_statusBar->GetStatusText( m_position ).IsEmpty();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -799,6 +799,12 @@ TOOL_ACTION ACTIONS::unpinLibrary( TOOL_ACTION_ARGS()
|
||||
.FriendlyName( _( "Unpin Library" ) )
|
||||
.Tooltip( _( "No longer keep the library at the top of the list" ) ) );
|
||||
|
||||
TOOL_ACTION ACTIONS::showLibraryTable( TOOL_ACTION_ARGS()
|
||||
.Name( "common.Control.showLibraryTable" )
|
||||
.Scope( AS_GLOBAL )
|
||||
.FriendlyName( _( "Library Table" ) )
|
||||
.Icon( BITMAPS::table ) );
|
||||
|
||||
TOOL_ACTION ACTIONS::showLibraryTree( TOOL_ACTION_ARGS()
|
||||
.Name( "common.Control.showLibraryTree" )
|
||||
.Scope( AS_GLOBAL )
|
||||
|
||||
@@ -23,12 +23,21 @@
|
||||
|
||||
#include "tool/construction_manager.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
#include <utility>
|
||||
|
||||
#include <wx/timer.h>
|
||||
#include <wx/debug.h>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include <advanced_config.h>
|
||||
#include <math/util.h>
|
||||
#include <hash.h>
|
||||
#include <trace_helpers.h>
|
||||
|
||||
|
||||
/**
|
||||
@@ -329,9 +338,9 @@ void CONSTRUCTION_MANAGER::acceptConstructionItems( std::unique_ptr<PENDING_BATC
|
||||
{
|
||||
for( const CONSTRUCTION_ITEM& item : batch )
|
||||
{
|
||||
for( const KIGFX::CONSTRUCTION_GEOM::DRAWABLE& drawable : item.Constructions )
|
||||
for( const CONSTRUCTION_ITEM::DRAWABLE_ENTRY& drawable : item.Constructions )
|
||||
{
|
||||
geom.AddDrawable( drawable, aIsPersistent );
|
||||
geom.AddDrawable( drawable.Drawable, aIsPersistent, drawable.LineWidth );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -383,16 +392,111 @@ bool CONSTRUCTION_MANAGER::HasActiveConstruction() const
|
||||
|
||||
|
||||
SNAP_LINE_MANAGER::SNAP_LINE_MANAGER( CONSTRUCTION_VIEW_HANDLER& aViewHandler ) :
|
||||
m_viewHandler( aViewHandler )
|
||||
m_viewHandler( aViewHandler ), m_snapManager( static_cast<SNAP_MANAGER*>( &aViewHandler ) )
|
||||
{
|
||||
wxASSERT( m_snapManager );
|
||||
SetDirections( { VECTOR2I( 1, 0 ), VECTOR2I( 0, 1 ) } );
|
||||
}
|
||||
|
||||
|
||||
static VECTOR2I normalizeDirection( const VECTOR2I& aDir )
|
||||
{
|
||||
if( aDir.x == 0 && aDir.y == 0 )
|
||||
return VECTOR2I( 0, 0 );
|
||||
|
||||
int dx = aDir.x;
|
||||
int dy = aDir.y;
|
||||
|
||||
int gcd = std::gcd( std::abs( dx ), std::abs( dy ) );
|
||||
|
||||
if( gcd > 0 )
|
||||
{
|
||||
dx /= gcd;
|
||||
dy /= gcd;
|
||||
}
|
||||
|
||||
if( dx < 0 || ( dx == 0 && dy < 0 ) )
|
||||
{
|
||||
dx = -dx;
|
||||
dy = -dy;
|
||||
}
|
||||
|
||||
return VECTOR2I( dx, dy );
|
||||
}
|
||||
|
||||
|
||||
static std::optional<int> findDirectionIndex( const std::vector<VECTOR2I>& aDirections,
|
||||
const VECTOR2I& aDelta )
|
||||
{
|
||||
VECTOR2I normalized = normalizeDirection( aDelta );
|
||||
|
||||
if( normalized.x == 0 && normalized.y == 0 )
|
||||
return std::nullopt;
|
||||
|
||||
for( size_t i = 0; i < aDirections.size(); ++i )
|
||||
{
|
||||
if( aDirections[i] == normalized )
|
||||
return static_cast<int>( i );
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
void SNAP_LINE_MANAGER::SetDirections( const std::vector<VECTOR2I>& aDirections )
|
||||
{
|
||||
std::vector<VECTOR2I> uniqueDirections;
|
||||
uniqueDirections.reserve( aDirections.size() );
|
||||
|
||||
for( const VECTOR2I& direction : aDirections )
|
||||
{
|
||||
VECTOR2I normalized = normalizeDirection( direction );
|
||||
|
||||
if( normalized.x == 0 && normalized.y == 0 )
|
||||
continue;
|
||||
|
||||
if( std::find( uniqueDirections.begin(), uniqueDirections.end(), normalized )
|
||||
== uniqueDirections.end() )
|
||||
{
|
||||
uniqueDirections.push_back( normalized );
|
||||
}
|
||||
}
|
||||
|
||||
if( uniqueDirections != m_directions )
|
||||
{
|
||||
m_directions = std::move( uniqueDirections );
|
||||
m_activeDirection.reset();
|
||||
|
||||
if( m_snapLineOrigin && m_snapLineEnd )
|
||||
{
|
||||
if( !findDirectionIndex( m_directions, *m_snapLineEnd - *m_snapLineOrigin ) )
|
||||
m_snapLineEnd.reset();
|
||||
}
|
||||
|
||||
if( m_directions.empty() )
|
||||
{
|
||||
ClearSnapLine();
|
||||
return;
|
||||
}
|
||||
|
||||
notifyGuideChange();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SNAP_LINE_MANAGER::SetSnapLineOrigin( const VECTOR2I& aOrigin )
|
||||
{
|
||||
// Setting the origin clears the snap line as the end point is no longer valid
|
||||
ClearSnapLine();
|
||||
if( m_snapLineOrigin && *m_snapLineOrigin == aOrigin && !m_snapLineEnd )
|
||||
{
|
||||
notifyGuideChange();
|
||||
return;
|
||||
}
|
||||
|
||||
m_snapLineOrigin = aOrigin;
|
||||
m_snapLineEnd.reset();
|
||||
m_activeDirection.reset();
|
||||
m_viewHandler.GetViewItem().ClearSnapLine();
|
||||
notifyGuideChange();
|
||||
}
|
||||
|
||||
|
||||
@@ -402,12 +506,17 @@ void SNAP_LINE_MANAGER::SetSnapLineEnd( const OPT_VECTOR2I& aSnapEnd )
|
||||
{
|
||||
m_snapLineEnd = aSnapEnd;
|
||||
|
||||
if( m_snapLineEnd )
|
||||
m_activeDirection = findDirectionIndex( m_directions, *m_snapLineEnd - *m_snapLineOrigin );
|
||||
else
|
||||
m_activeDirection.reset();
|
||||
|
||||
if( m_snapLineEnd )
|
||||
m_viewHandler.GetViewItem().SetSnapLine( SEG{ *m_snapLineOrigin, *m_snapLineEnd } );
|
||||
else
|
||||
m_viewHandler.GetViewItem().ClearSnapLine();
|
||||
|
||||
m_viewHandler.updateView();
|
||||
notifyGuideChange();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,8 +525,9 @@ void SNAP_LINE_MANAGER::ClearSnapLine()
|
||||
{
|
||||
m_snapLineOrigin.reset();
|
||||
m_snapLineEnd.reset();
|
||||
m_activeDirection.reset();
|
||||
m_viewHandler.GetViewItem().ClearSnapLine();
|
||||
m_viewHandler.updateView();
|
||||
notifyGuideChange();
|
||||
}
|
||||
|
||||
|
||||
@@ -425,7 +535,7 @@ void SNAP_LINE_MANAGER::SetSnappedAnchor( const VECTOR2I& aAnchorPos )
|
||||
{
|
||||
if( m_snapLineOrigin.has_value() )
|
||||
{
|
||||
if( aAnchorPos.x == m_snapLineOrigin->x || aAnchorPos.y == m_snapLineOrigin->y )
|
||||
if( findDirectionIndex( m_directions, aAnchorPos - *m_snapLineOrigin ) )
|
||||
{
|
||||
SetSnapLineEnd( aAnchorPos );
|
||||
}
|
||||
@@ -444,93 +554,206 @@ void SNAP_LINE_MANAGER::SetSnappedAnchor( const VECTOR2I& aAnchorPos )
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if the cursor has moved far enough away from the snap line origin to escape snapping
|
||||
* in the X direction.
|
||||
*
|
||||
* This is defined as within aEscapeRange of the snap line origin, and within aLongRangeEscapeAngle
|
||||
* of the vertical line passing through the snap line origin.
|
||||
*/
|
||||
static bool pointHasEscapedSnapLineX( const VECTOR2I& aCursor, const VECTOR2I& aSnapLineOrigin,
|
||||
int aEscapeRange, EDA_ANGLE aLongRangeEscapeAngle )
|
||||
{
|
||||
if( std::abs( aCursor.x - aSnapLineOrigin.x ) < aEscapeRange )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
EDA_ANGLE angle = EDA_ANGLE( aCursor - aSnapLineOrigin ) + EDA_ANGLE( 90, DEGREES_T );
|
||||
return std::abs( angle.Normalize90() ) > aLongRangeEscapeAngle;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* As above, but for the Y direction.
|
||||
*/
|
||||
static bool pointHasEscapedSnapLineY( const VECTOR2I& aCursor, const VECTOR2I& aSnapLineOrigin,
|
||||
int aEscapeRange, EDA_ANGLE aLongRangeEscapeAngle )
|
||||
{
|
||||
if( std::abs( aCursor.y - aSnapLineOrigin.y ) < aEscapeRange )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
EDA_ANGLE angle = EDA_ANGLE( aCursor - aSnapLineOrigin );
|
||||
return std::abs( angle.Normalize90() ) > aLongRangeEscapeAngle;
|
||||
}
|
||||
|
||||
|
||||
OPT_VECTOR2I SNAP_LINE_MANAGER::GetNearestSnapLinePoint( const VECTOR2I& aCursor,
|
||||
const VECTOR2I& aNearestGrid,
|
||||
std::optional<int> aDistToNearest,
|
||||
int aSnapRange ) const
|
||||
int aSnapRange,
|
||||
const VECTOR2D& aGridSize,
|
||||
const VECTOR2I& aGridOrigin ) const
|
||||
{
|
||||
// return std::nullopt;
|
||||
if( m_snapLineOrigin )
|
||||
wxLogTrace( traceSnap, "GetNearestSnapLinePoint: cursor=(%d, %d), nearestGrid=(%d, %d), distToNearest=%s, snapRange=%d",
|
||||
aCursor.x, aCursor.y, aNearestGrid.x, aNearestGrid.y,
|
||||
aDistToNearest ? wxString::Format( "%d", *aDistToNearest ) : wxString( "none" ), aSnapRange );
|
||||
|
||||
if( !m_snapLineOrigin || m_directions.empty() )
|
||||
{
|
||||
bool snapLine = false;
|
||||
VECTOR2I bestSnapPoint = aNearestGrid;
|
||||
wxLogTrace( traceSnap, " No snap line origin or no directions, returning nullopt" );
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// If there's no snap anchor, or it's too far away, prefer the grid
|
||||
const bool gridBetterThanNearest = !aDistToNearest || *aDistToNearest > aSnapRange;
|
||||
const bool gridBetterThanNearest = !aDistToNearest || *aDistToNearest > aSnapRange;
|
||||
const bool gridActive = aGridSize.x > 0 && aGridSize.y > 0;
|
||||
|
||||
// The escape range is how far you go before the snap line is de-activated.
|
||||
// Make this a bit more forgiving than the snap range, as you can easily cancel
|
||||
// deliberately with a mouse move.
|
||||
// These are both a bit arbitrary, and can be adjusted as preferred
|
||||
const int escapeRange = 2 * aSnapRange;
|
||||
const EDA_ANGLE longRangeEscapeAngle( 4, DEGREES_T );
|
||||
wxLogTrace( traceSnap, " snapLineOrigin=(%d, %d), directions count=%zu, gridBetterThanNearest=%d, gridActive=%d",
|
||||
m_snapLineOrigin->x, m_snapLineOrigin->y, m_directions.size(), gridBetterThanNearest, gridActive );
|
||||
|
||||
const bool escapedX = pointHasEscapedSnapLineX( aCursor, *m_snapLineOrigin, escapeRange,
|
||||
longRangeEscapeAngle );
|
||||
const bool escapedY = pointHasEscapedSnapLineY( aCursor, *m_snapLineOrigin, escapeRange,
|
||||
longRangeEscapeAngle );
|
||||
if( !gridBetterThanNearest )
|
||||
{
|
||||
wxLogTrace( traceSnap, " Grid not better than nearest, returning nullopt" );
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/// Allows de-snapping from the line if you are closer to another snap point
|
||||
/// Or if you have moved far enough away from the line
|
||||
if( !escapedX && gridBetterThanNearest )
|
||||
const int escapeRange = 2 * aSnapRange;
|
||||
const EDA_ANGLE longRangeEscapeAngle( 4, DEGREES_T );
|
||||
|
||||
wxLogTrace( traceSnap, " escapeRange=%d, longRangeEscapeAngle=%.1f deg",
|
||||
escapeRange, longRangeEscapeAngle.AsDegrees() );
|
||||
|
||||
const VECTOR2D origin( *m_snapLineOrigin );
|
||||
const VECTOR2D cursor( aCursor );
|
||||
const VECTOR2D delta = cursor - origin;
|
||||
|
||||
double bestPerpDistance = std::numeric_limits<double>::max();
|
||||
std::optional<VECTOR2I> bestSnapPoint;
|
||||
|
||||
for( size_t ii = 0; ii < m_directions.size(); ++ii )
|
||||
{
|
||||
const VECTOR2I& direction = m_directions[ii];
|
||||
VECTOR2D dirVector( direction );
|
||||
double dirLength = dirVector.EuclideanNorm();
|
||||
|
||||
if( dirLength == 0.0 )
|
||||
{
|
||||
bestSnapPoint.x = m_snapLineOrigin->x;
|
||||
snapLine = true;
|
||||
wxLogTrace( traceSnap, " Direction %zu: zero length, skipping", ii );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !escapedY && gridBetterThanNearest )
|
||||
VECTOR2D dirUnit = dirVector / dirLength;
|
||||
|
||||
double distanceAlong = delta.Dot( dirUnit );
|
||||
VECTOR2D projection = origin + dirUnit * distanceAlong;
|
||||
VECTOR2D offset = delta - dirUnit * distanceAlong;
|
||||
double perpDistance = offset.EuclideanNorm();
|
||||
|
||||
wxLogTrace( traceSnap, " Direction %zu: dir=(%d, %d), perpDist=%.1f, distAlong=%.1f",
|
||||
ii, direction.x, direction.y, perpDistance, distanceAlong );
|
||||
|
||||
if( perpDistance > aSnapRange )
|
||||
{
|
||||
bestSnapPoint.y = m_snapLineOrigin->y;
|
||||
snapLine = true;
|
||||
wxLogTrace( traceSnap, " perpDistance > snapRange, skipping" );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( snapLine )
|
||||
bool escaped = false;
|
||||
|
||||
if( perpDistance >= escapeRange )
|
||||
{
|
||||
return bestSnapPoint;
|
||||
EDA_ANGLE deltaAngle( delta );
|
||||
EDA_ANGLE directionAngle( dirVector );
|
||||
double angleDiff = ( deltaAngle - directionAngle ).Normalize180().AsDegrees();
|
||||
|
||||
wxLogTrace( traceSnap, " In escape range: deltaAngle=%.1f, dirAngle=%.1f, angleDiff=%.1f",
|
||||
deltaAngle.AsDegrees(), directionAngle.AsDegrees(), angleDiff );
|
||||
|
||||
if( std::abs( angleDiff ) > longRangeEscapeAngle.AsDegrees() )
|
||||
{
|
||||
escaped = true;
|
||||
wxLogTrace( traceSnap, " ESCAPED (angle diff too large)" );
|
||||
}
|
||||
}
|
||||
|
||||
if( escaped )
|
||||
{
|
||||
wxLogTrace( traceSnap, " Not updating (escaped)" );
|
||||
continue;
|
||||
}
|
||||
|
||||
// Now snap the projection to the grid if the grid is active
|
||||
VECTOR2D snapPoint = projection;
|
||||
|
||||
if( gridActive )
|
||||
{
|
||||
// For horizontal/vertical lines, snap to grid intersections
|
||||
if( direction.x == 0 && direction.y != 0 )
|
||||
{
|
||||
// Vertical line: keep origin X, snap Y to grid
|
||||
snapPoint.x = origin.x;
|
||||
snapPoint.y = aNearestGrid.y;
|
||||
wxLogTrace( traceSnap, " Vertical line: snapping to grid Y, snapPoint=(%.1f, %.1f)",
|
||||
snapPoint.x, snapPoint.y );
|
||||
}
|
||||
else if( direction.y == 0 && direction.x != 0 )
|
||||
{
|
||||
// Horizontal line: snap X to grid, keep origin Y
|
||||
snapPoint.x = aNearestGrid.x;
|
||||
snapPoint.y = origin.y;
|
||||
wxLogTrace( traceSnap, " Horizontal line: snapping to grid X, snapPoint=(%.1f, %.1f)",
|
||||
snapPoint.x, snapPoint.y );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Diagonal line: find nearest grid intersection along the line
|
||||
VECTOR2D gridOriginD( aGridOrigin );
|
||||
VECTOR2D relProjection = projection - gridOriginD;
|
||||
|
||||
// Find nearby grid points (check 3x3 grid around projection)
|
||||
double bestGridScore = std::numeric_limits<double>::max();
|
||||
VECTOR2D bestGridPoint = projection;
|
||||
|
||||
for( int dx = -1; dx <= 1; ++dx )
|
||||
{
|
||||
for( int dy = -1; dy <= 1; ++dy )
|
||||
{
|
||||
double gridX = std::round( relProjection.x / aGridSize.x ) * aGridSize.x + dx * aGridSize.x;
|
||||
double gridY = std::round( relProjection.y / aGridSize.y ) * aGridSize.y + dy * aGridSize.y;
|
||||
VECTOR2D gridPt( gridX + gridOriginD.x, gridY + gridOriginD.y );
|
||||
|
||||
// Calculate perpendicular distance from grid point to construction line
|
||||
VECTOR2D gridDelta = gridPt - origin;
|
||||
double gridDistAlong = gridDelta.Dot( dirUnit );
|
||||
VECTOR2D gridProjection = origin + dirUnit * gridDistAlong;
|
||||
double gridPerpDist = ( gridPt - gridProjection ).EuclideanNorm();
|
||||
|
||||
// Also consider distance from cursor
|
||||
double distFromCursor = ( gridPt - cursor ).EuclideanNorm();
|
||||
|
||||
// Prefer grid points that are close to the line and close to cursor
|
||||
double score = gridPerpDist + distFromCursor * 0.1;
|
||||
|
||||
if( score < bestGridScore )
|
||||
{
|
||||
bestGridScore = score;
|
||||
bestGridPoint = gridPt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
snapPoint = bestGridPoint;
|
||||
wxLogTrace( traceSnap, " Diagonal line: snapping to grid intersection, snapPoint=(%.1f, %.1f)",
|
||||
snapPoint.x, snapPoint.y );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( traceSnap, " Grid not active, using projection" );
|
||||
}
|
||||
|
||||
if( perpDistance < bestPerpDistance )
|
||||
{
|
||||
bestPerpDistance = perpDistance;
|
||||
bestSnapPoint = VECTOR2I( KiROUND( snapPoint.x ), KiROUND( snapPoint.y ) );
|
||||
wxLogTrace( traceSnap, " NEW BEST: perpDist=%.1f, snapPoint=(%d, %d)",
|
||||
bestPerpDistance, bestSnapPoint->x, bestSnapPoint->y );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( traceSnap, " Not updating (perpDist=%.1f >= bestPerp=%.1f)",
|
||||
perpDistance, bestPerpDistance );
|
||||
}
|
||||
}
|
||||
|
||||
if( bestSnapPoint )
|
||||
{
|
||||
wxLogTrace( traceSnap, " RETURNING bestSnapPoint=(%d, %d)", bestSnapPoint->x, bestSnapPoint->y );
|
||||
return *bestSnapPoint;
|
||||
}
|
||||
|
||||
wxLogTrace( traceSnap, " RETURNING nullopt (no valid snap found)" );
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
void SNAP_LINE_MANAGER::notifyGuideChange()
|
||||
{
|
||||
if( m_snapManager )
|
||||
m_snapManager->UpdateSnapGuides();
|
||||
}
|
||||
|
||||
|
||||
SNAP_MANAGER::SNAP_MANAGER( KIGFX::CONSTRUCTION_GEOM& aHelper ) :
|
||||
CONSTRUCTION_VIEW_HANDLER( aHelper ), m_snapLineManager( *this ),
|
||||
m_constructionManager( *this )
|
||||
m_constructionManager( *this ), m_snapGuideColor( KIGFX::COLOR4D::WHITE ),
|
||||
m_snapGuideHighlightColor( KIGFX::COLOR4D::WHITE )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -540,13 +763,67 @@ void SNAP_MANAGER::updateView()
|
||||
if( m_updateCallback )
|
||||
{
|
||||
bool showAnything = m_constructionManager.HasActiveConstruction()
|
||||
|| m_snapLineManager.HasCompleteSnapLine();
|
||||
|| m_snapLineManager.HasCompleteSnapLine()
|
||||
|| ( m_snapLineManager.GetSnapLineOrigin()
|
||||
&& !m_snapLineManager.GetDirections().empty() );
|
||||
|
||||
m_updateCallback( showAnything );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SNAP_MANAGER::SetSnapGuideColors( const KIGFX::COLOR4D& aBase, const KIGFX::COLOR4D& aHighlight )
|
||||
{
|
||||
m_snapGuideColor = aBase;
|
||||
m_snapGuideHighlightColor = aHighlight;
|
||||
UpdateSnapGuides();
|
||||
}
|
||||
|
||||
|
||||
void SNAP_MANAGER::UpdateSnapGuides()
|
||||
{
|
||||
std::vector<KIGFX::CONSTRUCTION_GEOM::SNAP_GUIDE> guides;
|
||||
|
||||
const OPT_VECTOR2I& origin = m_snapLineManager.GetSnapLineOrigin();
|
||||
const std::vector<VECTOR2I>& directions = m_snapLineManager.GetDirections();
|
||||
|
||||
if( origin && !directions.empty() )
|
||||
{
|
||||
const std::optional<int> activeDirection = m_snapLineManager.GetActiveDirection();
|
||||
const int guideLength = 500000;
|
||||
|
||||
for( size_t ii = 0; ii < directions.size(); ++ii )
|
||||
{
|
||||
const VECTOR2I& direction = directions[ii];
|
||||
|
||||
if( direction.x == 0 && direction.y == 0 )
|
||||
continue;
|
||||
|
||||
VECTOR2I scaled = direction * guideLength;
|
||||
|
||||
KIGFX::CONSTRUCTION_GEOM::SNAP_GUIDE guide;
|
||||
guide.Segment = SEG( *origin - scaled, *origin + scaled );
|
||||
|
||||
if( activeDirection && *activeDirection == static_cast<int>( ii ) )
|
||||
{
|
||||
guide.LineWidth = 2;
|
||||
guide.Color = m_snapGuideHighlightColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
guide.LineWidth = 1;
|
||||
guide.Color = m_snapGuideColor;
|
||||
}
|
||||
|
||||
guides.push_back( guide );
|
||||
}
|
||||
}
|
||||
|
||||
GetViewItem().SetSnapGuides( std::move( guides ) );
|
||||
updateView();
|
||||
}
|
||||
|
||||
|
||||
std::vector<CONSTRUCTION_MANAGER::CONSTRUCTION_ITEM_BATCH>
|
||||
SNAP_MANAGER::GetConstructionItems() const
|
||||
{
|
||||
@@ -566,13 +843,24 @@ SNAP_MANAGER::GetConstructionItems() const
|
||||
{},
|
||||
} );
|
||||
|
||||
// One horizontal and one vertical infinite line from the snap point
|
||||
snapPointItem.Constructions.push_back(
|
||||
LINE{ *snapLineOrigin, *snapLineOrigin + VECTOR2I( 100000, 0 ) } );
|
||||
snapPointItem.Constructions.push_back(
|
||||
LINE{ *snapLineOrigin, *snapLineOrigin + VECTOR2I( 0, 100000 ) } );
|
||||
const std::vector<VECTOR2I>& directions = m_snapLineManager.GetDirections();
|
||||
const std::optional<int> activeDirection = m_snapLineManager.GetActiveDirection();
|
||||
|
||||
batches.push_back( std::move( batch ) );
|
||||
for( size_t ii = 0; ii < directions.size(); ++ii )
|
||||
{
|
||||
const VECTOR2I& direction = directions[ii];
|
||||
|
||||
VECTOR2I scaledDirection = direction * 100000;
|
||||
|
||||
CONSTRUCTION_MANAGER::CONSTRUCTION_ITEM::DRAWABLE_ENTRY entry;
|
||||
entry.Drawable = LINE{ *snapLineOrigin, *snapLineOrigin + scaledDirection };
|
||||
entry.LineWidth = ( activeDirection && *activeDirection == static_cast<int>( ii ) ) ? 2 : 1;
|
||||
|
||||
snapPointItem.Constructions.push_back( entry );
|
||||
}
|
||||
|
||||
if( !snapPointItem.Constructions.empty() )
|
||||
batches.push_back( std::move( batch ) );
|
||||
}
|
||||
|
||||
return batches;
|
||||
|
||||
@@ -61,7 +61,7 @@ void EC_45DEGREE::Apply( EDIT_POINT& aHandle, const GRID_HELPER& aGrid )
|
||||
VECTOR2I lineVector( aHandle.GetPosition() - m_constrainer.GetPosition() );
|
||||
VECTOR2I newLineVector = GetVectorSnapped45( lineVector );
|
||||
|
||||
if( aHandle.GetGridConstraint() == SNAP_TO_GRID
|
||||
if( aHandle.GetGridConstraint() == SNAP_TO_GRID && !aGrid.GetSnappedPoint()
|
||||
&& ( newLineVector.x == 0 || newLineVector.y == 0 ) )
|
||||
{
|
||||
VECTOR2I snap = aGrid.AlignGrid( m_constrainer.GetPosition() + newLineVector );
|
||||
|
||||
+273
-28
@@ -24,21 +24,23 @@
|
||||
#include "tool/grid_helper.h"
|
||||
|
||||
#include <functional>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
#include <advanced_config.h>
|
||||
#include <trace_helpers.h>
|
||||
#include <wx/log.h>
|
||||
#include <gal/graphics_abstraction_layer.h>
|
||||
#include <gal/painter.h>
|
||||
#include <math/util.h> // for KiROUND
|
||||
#include <math/vector2d.h>
|
||||
#include <render_settings.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tool/tools_holder.h>
|
||||
#include <view/view.h>
|
||||
#include <settings/app_settings.h>
|
||||
|
||||
|
||||
GRID_HELPER::GRID_HELPER( TOOL_MANAGER* aToolMgr, int aConstructionLayer ) :
|
||||
m_toolMgr( aToolMgr ), m_snapManager( m_constructionGeomPreview )
|
||||
GRID_HELPER::GRID_HELPER() :
|
||||
m_toolMgr( nullptr ), m_snapManager( m_constructionGeomPreview )
|
||||
{
|
||||
m_maskTypes = ALL;
|
||||
m_enableSnap = true;
|
||||
@@ -46,12 +48,23 @@ GRID_HELPER::GRID_HELPER( TOOL_MANAGER* aToolMgr, int aConstructionLayer ) :
|
||||
m_enableGrid = true;
|
||||
m_snapItem = std::nullopt;
|
||||
|
||||
KIGFX::VIEW* view = m_toolMgr->GetView();
|
||||
KIGFX::RENDER_SETTINGS* settings = view->GetPainter()->GetSettings();
|
||||
m_manualGrid = VECTOR2D( 1, 1 );
|
||||
m_manualVisibleGrid = VECTOR2D( 1, 1 );
|
||||
m_manualOrigin = VECTOR2I( 0, 0 );
|
||||
m_manualGridSnapping = true;
|
||||
}
|
||||
|
||||
const KIGFX::COLOR4D constructionColour = settings->GetLayerColor( aConstructionLayer );
|
||||
m_constructionGeomPreview.SetPersistentColor( constructionColour );
|
||||
m_constructionGeomPreview.SetColor( constructionColour.WithAlpha( 0.7 ) );
|
||||
|
||||
GRID_HELPER::GRID_HELPER( TOOL_MANAGER* aToolMgr, int aConstructionLayer ) :
|
||||
GRID_HELPER()
|
||||
{
|
||||
m_toolMgr = aToolMgr;
|
||||
|
||||
if( !m_toolMgr )
|
||||
return;
|
||||
|
||||
KIGFX::VIEW* view = m_toolMgr->GetView();
|
||||
wxUnusedVar( aConstructionLayer );
|
||||
|
||||
view->Add( &m_constructionGeomPreview );
|
||||
view->SetVisible( &m_constructionGeomPreview, false );
|
||||
@@ -72,11 +85,20 @@ GRID_HELPER::GRID_HELPER( TOOL_MANAGER* aToolMgr, int aConstructionLayer ) :
|
||||
|
||||
m_toolMgr->GetToolHolder()->RefreshCanvas();
|
||||
} );
|
||||
|
||||
// Initialise manual values from view for compatibility
|
||||
m_manualGrid = view->GetGAL()->GetGridSize();
|
||||
m_manualVisibleGrid = view->GetGAL()->GetVisibleGridSize();
|
||||
m_manualOrigin = VECTOR2I( view->GetGAL()->GetGridOrigin() );
|
||||
m_manualGridSnapping = view->GetGAL()->GetGridSnapping();
|
||||
}
|
||||
|
||||
|
||||
GRID_HELPER::~GRID_HELPER()
|
||||
{
|
||||
if( !m_toolMgr )
|
||||
return;
|
||||
|
||||
KIGFX::VIEW& view = *m_toolMgr->GetView();
|
||||
view.Remove( &m_constructionGeomPreview );
|
||||
|
||||
@@ -89,6 +111,9 @@ KIGFX::ANCHOR_DEBUG* GRID_HELPER::enableAndGetAnchorDebug()
|
||||
{
|
||||
static bool permitted = ADVANCED_CFG::GetCfg().m_EnableSnapAnchorsDebug;
|
||||
|
||||
if( !m_toolMgr )
|
||||
return nullptr;
|
||||
|
||||
if( permitted && !m_anchorDebug )
|
||||
{
|
||||
KIGFX::VIEW& view = *m_toolMgr->GetView();
|
||||
@@ -103,12 +128,223 @@ KIGFX::ANCHOR_DEBUG* GRID_HELPER::enableAndGetAnchorDebug()
|
||||
|
||||
void GRID_HELPER::showConstructionGeometry( bool aShow )
|
||||
{
|
||||
m_toolMgr->GetView()->SetVisible( &m_constructionGeomPreview, aShow );
|
||||
if( m_toolMgr )
|
||||
m_toolMgr->GetView()->SetVisible( &m_constructionGeomPreview, aShow );
|
||||
}
|
||||
|
||||
|
||||
void GRID_HELPER::SetSnapLineDirections( const std::vector<VECTOR2I>& aDirections )
|
||||
{
|
||||
m_snapManager.GetSnapLineManager().SetDirections( aDirections );
|
||||
}
|
||||
|
||||
|
||||
void GRID_HELPER::SetSnapLineOrigin( const VECTOR2I& aOrigin )
|
||||
{
|
||||
m_snapManager.GetSnapLineManager().SetSnapLineOrigin( aOrigin );
|
||||
}
|
||||
|
||||
|
||||
void GRID_HELPER::ClearSnapLine()
|
||||
{
|
||||
m_snapManager.GetSnapLineManager().ClearSnapLine();
|
||||
}
|
||||
|
||||
|
||||
std::optional<VECTOR2I> GRID_HELPER::SnapToConstructionLines( const VECTOR2I& aPoint,
|
||||
const VECTOR2I& aNearestGrid,
|
||||
const VECTOR2D& aGrid,
|
||||
double aSnapRange ) const
|
||||
{
|
||||
const SNAP_LINE_MANAGER& snapLineManager = m_snapManager.GetSnapLineManager();
|
||||
const OPT_VECTOR2I& snapOrigin = snapLineManager.GetSnapLineOrigin();
|
||||
|
||||
wxLogTrace( traceSnap, "SnapToConstructionLines: aPoint=(%d, %d), nearestGrid=(%d, %d), snapRange=%.1f",
|
||||
aPoint.x, aPoint.y, aNearestGrid.x, aNearestGrid.y, aSnapRange );
|
||||
|
||||
if( !snapOrigin || snapLineManager.GetDirections().empty() )
|
||||
{
|
||||
wxLogTrace( traceSnap, " No snap origin or no directions, returning nullopt" );
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const VECTOR2I& origin = *snapOrigin;
|
||||
|
||||
wxLogTrace( traceSnap, " snapOrigin=(%d, %d), directions count=%zu",
|
||||
origin.x, origin.y, snapLineManager.GetDirections().size() );
|
||||
|
||||
const std::vector<VECTOR2I>& directions = snapLineManager.GetDirections();
|
||||
const std::optional<int> activeDirection = snapLineManager.GetActiveDirection();
|
||||
|
||||
if( activeDirection )
|
||||
wxLogTrace( traceSnap, " activeDirection=%d", *activeDirection );
|
||||
|
||||
const VECTOR2D originVec( origin );
|
||||
const VECTOR2D cursorVec( aPoint );
|
||||
const VECTOR2D delta = cursorVec - originVec;
|
||||
|
||||
std::optional<VECTOR2I> bestPoint;
|
||||
double bestPerp = std::numeric_limits<double>::max();
|
||||
double bestDistance = std::numeric_limits<double>::max();
|
||||
|
||||
for( size_t ii = 0; ii < directions.size(); ++ii )
|
||||
{
|
||||
const VECTOR2I& dir = directions[ii];
|
||||
VECTOR2D dirVector( dir );
|
||||
double dirLength = dirVector.EuclideanNorm();
|
||||
|
||||
if( dirLength == 0.0 )
|
||||
{
|
||||
wxLogTrace( traceSnap, " Direction %zu: zero length, skipping", ii );
|
||||
continue;
|
||||
}
|
||||
|
||||
VECTOR2D dirUnit = dirVector / dirLength;
|
||||
|
||||
double distanceAlong = delta.Dot( dirUnit );
|
||||
VECTOR2D projection = originVec + dirUnit * distanceAlong;
|
||||
VECTOR2D offset = delta - dirUnit * distanceAlong;
|
||||
double perpDistance = offset.EuclideanNorm();
|
||||
|
||||
double snapThreshold = aSnapRange;
|
||||
|
||||
if( activeDirection && *activeDirection == static_cast<int>( ii ) )
|
||||
{
|
||||
snapThreshold *= 1.5;
|
||||
wxLogTrace( traceSnap, " Direction %zu: ACTIVE, increased snapThreshold=%.1f", ii, snapThreshold );
|
||||
}
|
||||
|
||||
wxLogTrace( traceSnap, " Direction %zu: dir=(%d, %d), perpDist=%.1f, threshold=%.1f",
|
||||
ii, dir.x, dir.y, perpDistance, snapThreshold );
|
||||
|
||||
if( perpDistance > snapThreshold )
|
||||
{
|
||||
wxLogTrace( traceSnap, " perpDistance > threshold, skipping" );
|
||||
continue;
|
||||
}
|
||||
|
||||
VECTOR2D candidate = projection;
|
||||
|
||||
if( canUseGrid() )
|
||||
{
|
||||
if( dir.x == 0 && dir.y != 0 )
|
||||
{
|
||||
// Vertical construction line: snap to grid intersection
|
||||
candidate.x = origin.x;
|
||||
candidate.y = aNearestGrid.y;
|
||||
wxLogTrace( traceSnap, " Vertical snap: candidate=(%d, %d)",
|
||||
(int)candidate.x, (int)candidate.y );
|
||||
}
|
||||
else if( dir.y == 0 && dir.x != 0 )
|
||||
{
|
||||
// Horizontal construction line: snap to grid intersection
|
||||
candidate.x = aNearestGrid.x;
|
||||
candidate.y = origin.y;
|
||||
wxLogTrace( traceSnap, " Horizontal snap: candidate=(%d, %d)",
|
||||
(int)candidate.x, (int)candidate.y );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Diagonal construction line: find nearest grid intersection along the line
|
||||
// We need to find grid points near the projection point and pick the closest
|
||||
// one that lies on the construction line
|
||||
|
||||
// Get the grid origin for proper alignment
|
||||
VECTOR2D gridOrigin( GetOrigin() );
|
||||
|
||||
// Calculate the projection point relative to grid
|
||||
VECTOR2D relProjection = projection - gridOrigin;
|
||||
|
||||
// Find nearby grid points (check 9 points in a 3x3 grid around the projection)
|
||||
std::vector<VECTOR2D> gridPoints;
|
||||
for( int dx = -1; dx <= 1; ++dx )
|
||||
{
|
||||
for( int dy = -1; dy <= 1; ++dy )
|
||||
{
|
||||
double gridX = std::round( relProjection.x / aGrid.x ) * aGrid.x + dx * aGrid.x;
|
||||
double gridY = std::round( relProjection.y / aGrid.y ) * aGrid.y + dy * aGrid.y;
|
||||
gridPoints.push_back( VECTOR2D( gridX + gridOrigin.x, gridY + gridOrigin.y ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Find the grid point closest to the construction line
|
||||
double bestGridDist = std::numeric_limits<double>::max();
|
||||
VECTOR2D bestGridPt = projection;
|
||||
|
||||
for( const VECTOR2D& gridPt : gridPoints )
|
||||
{
|
||||
// Calculate perpendicular distance from grid point to construction line
|
||||
VECTOR2D gridDelta = gridPt - originVec;
|
||||
double gridDistAlong = gridDelta.Dot( dirUnit );
|
||||
VECTOR2D gridProjection = originVec + dirUnit * gridDistAlong;
|
||||
double gridPerpDist = ( gridPt - gridProjection ).EuclideanNorm();
|
||||
|
||||
// Also consider distance from cursor
|
||||
double distFromCursor = ( gridPt - cursorVec ).EuclideanNorm();
|
||||
|
||||
// Prefer grid points that are close to the line and close to cursor
|
||||
double score = gridPerpDist + distFromCursor * 0.1;
|
||||
|
||||
if( score < bestGridDist )
|
||||
{
|
||||
bestGridDist = score;
|
||||
bestGridPt = gridPt;
|
||||
}
|
||||
}
|
||||
|
||||
candidate = bestGridPt;
|
||||
wxLogTrace( traceSnap, " Diagonal snap: candidate=(%.1f, %.1f), perpDist=%.1f",
|
||||
candidate.x, candidate.y, bestGridDist );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( traceSnap, " Grid disabled, using projection candidate=(%.1f, %.1f)",
|
||||
candidate.x, candidate.y );
|
||||
}
|
||||
|
||||
VECTOR2I candidateInt( KiROUND( candidate.x ), KiROUND( candidate.y ) );
|
||||
|
||||
if( candidateInt == m_skipPoint )
|
||||
{
|
||||
wxLogTrace( traceSnap, " candidateInt matches m_skipPoint, skipping" );
|
||||
continue;
|
||||
}
|
||||
|
||||
VECTOR2D candidateDelta( candidateInt.x - aPoint.x, candidateInt.y - aPoint.y );
|
||||
double candidateDistance = candidateDelta.EuclideanNorm();
|
||||
|
||||
wxLogTrace( traceSnap, " candidateInt=(%d, %d), candidateDist=%.1f",
|
||||
candidateInt.x, candidateInt.y, candidateDistance );
|
||||
|
||||
if( perpDistance < bestPerp
|
||||
|| ( std::abs( perpDistance - bestPerp ) < 1e-9 && candidateDistance < bestDistance ) )
|
||||
{
|
||||
wxLogTrace( traceSnap, " NEW BEST: perpDist=%.1f, candDist=%.1f", perpDistance, candidateDistance );
|
||||
bestPerp = perpDistance;
|
||||
bestDistance = candidateDistance;
|
||||
bestPoint = candidateInt;
|
||||
}
|
||||
}
|
||||
|
||||
if( bestPoint )
|
||||
{
|
||||
wxLogTrace( traceSnap, " RETURNING bestPoint=(%d, %d)", bestPoint->x, bestPoint->y );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( traceSnap, " RETURNING nullopt (no valid snap found)" );
|
||||
}
|
||||
|
||||
return bestPoint;
|
||||
}
|
||||
|
||||
|
||||
void GRID_HELPER::updateSnapPoint( const TYPED_POINT2I& aPoint )
|
||||
{
|
||||
if( !m_toolMgr )
|
||||
return;
|
||||
|
||||
m_viewSnapPoint.SetPosition( aPoint.m_point );
|
||||
m_viewSnapPoint.SetSnapTypes( aPoint.m_types );
|
||||
|
||||
@@ -121,23 +357,26 @@ void GRID_HELPER::updateSnapPoint( const TYPED_POINT2I& aPoint )
|
||||
|
||||
VECTOR2I GRID_HELPER::GetGrid() const
|
||||
{
|
||||
VECTOR2D size = m_toolMgr->GetView()->GetGAL()->GetGridSize();
|
||||
|
||||
VECTOR2D size = m_toolMgr ? m_toolMgr->GetView()->GetGAL()->GetGridSize() : m_manualGrid;
|
||||
return VECTOR2I( KiROUND( size.x ), KiROUND( size.y ) );
|
||||
}
|
||||
|
||||
|
||||
VECTOR2D GRID_HELPER::GetVisibleGrid() const
|
||||
{
|
||||
return m_toolMgr->GetView()->GetGAL()->GetVisibleGridSize();
|
||||
return m_toolMgr ? m_toolMgr->GetView()->GetGAL()->GetVisibleGridSize() : m_manualVisibleGrid;
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I GRID_HELPER::GetOrigin() const
|
||||
{
|
||||
VECTOR2D origin = m_toolMgr->GetView()->GetGAL()->GetGridOrigin();
|
||||
if( m_toolMgr )
|
||||
{
|
||||
VECTOR2D origin = m_toolMgr->GetView()->GetGAL()->GetGridOrigin();
|
||||
return VECTOR2I( origin );
|
||||
}
|
||||
|
||||
return VECTOR2I( origin );
|
||||
return m_manualOrigin;
|
||||
}
|
||||
|
||||
|
||||
@@ -160,7 +399,7 @@ GRID_HELPER_GRIDS GRID_HELPER::GetSelectionGrid( const SELECTION& aSelection ) c
|
||||
|
||||
VECTOR2D GRID_HELPER::GetGridSize( GRID_HELPER_GRIDS aGrid ) const
|
||||
{
|
||||
return m_toolMgr->GetView()->GetGAL()->GetGridSize();
|
||||
return m_toolMgr ? m_toolMgr->GetView()->GetGAL()->GetGridSize() : m_manualGrid;
|
||||
}
|
||||
|
||||
|
||||
@@ -170,47 +409,52 @@ void GRID_HELPER::SetAuxAxes( bool aEnable, const VECTOR2I& aOrigin )
|
||||
{
|
||||
m_auxAxis = aOrigin;
|
||||
m_viewAxis.SetPosition( aOrigin );
|
||||
m_toolMgr->GetView()->SetVisible( &m_viewAxis, true );
|
||||
if( m_toolMgr )
|
||||
m_toolMgr->GetView()->SetVisible( &m_viewAxis, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_auxAxis = std::optional<VECTOR2I>();
|
||||
m_toolMgr->GetView()->SetVisible( &m_viewAxis, false );
|
||||
if( m_toolMgr )
|
||||
m_toolMgr->GetView()->SetVisible( &m_viewAxis, false );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I GRID_HELPER::AlignGrid( const VECTOR2I& aPoint ) const
|
||||
{
|
||||
return computeNearest( aPoint, GetGrid() );
|
||||
return computeNearest( aPoint, GetGrid(), GetOrigin() );
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I GRID_HELPER::AlignGrid( const VECTOR2I& aPoint, const VECTOR2D& aGrid ) const
|
||||
VECTOR2I GRID_HELPER::AlignGrid( const VECTOR2I& aPoint, const VECTOR2D& aGrid,
|
||||
const VECTOR2D& aOffset ) const
|
||||
{
|
||||
return computeNearest( aPoint, aGrid );
|
||||
return computeNearest( aPoint, aGrid, aOffset );
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I GRID_HELPER::computeNearest( const VECTOR2I& aPoint, const VECTOR2I& aGrid ) const
|
||||
VECTOR2I GRID_HELPER::computeNearest( const VECTOR2I& aPoint, const VECTOR2I& aGrid,
|
||||
const VECTOR2I& aOffset ) const
|
||||
{
|
||||
return VECTOR2I( KiROUND( static_cast<double>( aPoint.x ) / aGrid.x ) * aGrid.x,
|
||||
KiROUND( static_cast<double>( aPoint.y ) / aGrid.y ) * aGrid.y );
|
||||
return VECTOR2I( KiROUND( (double) ( aPoint.x - aOffset.x ) / aGrid.x ) * aGrid.x + aOffset.x,
|
||||
KiROUND( (double) ( aPoint.y - aOffset.y ) / aGrid.y ) * aGrid.y + aOffset.y );
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I GRID_HELPER::Align( const VECTOR2I& aPoint ) const
|
||||
{
|
||||
return Align( aPoint, GetGrid() );
|
||||
return Align( aPoint, GetGrid(), GetOrigin() );
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I GRID_HELPER::Align( const VECTOR2I& aPoint, const VECTOR2D& aGrid ) const
|
||||
VECTOR2I GRID_HELPER::Align( const VECTOR2I& aPoint, const VECTOR2D& aGrid,
|
||||
const VECTOR2D& aOffset ) const
|
||||
{
|
||||
if( !canUseGrid() )
|
||||
return aPoint;
|
||||
|
||||
VECTOR2I nearest = AlignGrid( aPoint, aGrid );
|
||||
VECTOR2I nearest = AlignGrid( aPoint, aGrid, aOffset );
|
||||
|
||||
if( !m_auxAxis )
|
||||
return nearest;
|
||||
@@ -227,7 +471,8 @@ VECTOR2I GRID_HELPER::Align( const VECTOR2I& aPoint, const VECTOR2D& aGrid ) con
|
||||
|
||||
bool GRID_HELPER::canUseGrid() const
|
||||
{
|
||||
return m_enableGrid && m_toolMgr->GetView()->GetGAL()->GetGridSnapping();
|
||||
return m_enableGrid && ( m_toolMgr ? m_toolMgr->GetView()->GetGAL()->GetGridSnapping()
|
||||
: m_manualGridSnapping );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -31,6 +31,9 @@ void POLYGON_POINT_EDIT_BEHAVIOR::BuildForPolyOutline( EDIT_POINTS& aPo
|
||||
{
|
||||
const int cornersCount = aOutline.TotalVertices();
|
||||
|
||||
if( cornersCount == 0 )
|
||||
return;
|
||||
|
||||
for( auto iterator = aOutline.CIterateWithHoles(); iterator; iterator++ )
|
||||
{
|
||||
aPoints.AddPoint( *iterator );
|
||||
|
||||
@@ -59,6 +59,8 @@ const wxChar* const traceUiProfile = wxT( "KICAD_UI_PROFILE" );
|
||||
const wxChar* const traceGit = wxT( "KICAD_GIT" );
|
||||
const wxChar* const traceEagleIo = wxT( "KICAD_EAGLE_IO" );
|
||||
const wxChar* const traceDesignBlocks = wxT( "KICAD_DESIGN_BLOCK" );
|
||||
const wxChar* const traceLibFieldTable = wxT( "KICAD_LIB_FIELD_TABLE" );
|
||||
const wxChar* const traceSnap = wxT( "KICAD_SNAP" );
|
||||
|
||||
|
||||
wxString dump( const wxArrayString& aArray )
|
||||
|
||||
+79
-56
@@ -362,18 +362,26 @@ bool FIELD_VALIDATOR::Validate( wxWindow* aParent )
|
||||
}
|
||||
|
||||
|
||||
bool FIELD_VALIDATOR::DoValidate( const wxString& aValue, wxWindow* aParent )
|
||||
wxString GetFieldValidationErrorMessage( int aFieldId, const wxString& aValue )
|
||||
{
|
||||
wxString msg;
|
||||
FIELD_VALIDATOR validator( aFieldId );
|
||||
wxString msg;
|
||||
|
||||
if( HasFlag( wxFILTER_EMPTY ) && aValue.empty() )
|
||||
msg.Printf( _( "The value of the field cannot be empty." ) );
|
||||
if( validator.HasFlag( wxFILTER_EMPTY ) && aValue.empty() )
|
||||
{
|
||||
switch( aFieldId )
|
||||
{
|
||||
case SHEETNAME_V: msg = _( "A sheet must have a name." ); break;
|
||||
case SHEETFILENAME_V: msg = _( "A sheet must have a file specified." ); break;
|
||||
default: msg = _( "The value of the field cannot be empty." ); break;
|
||||
}
|
||||
}
|
||||
|
||||
if( HasFlag( wxFILTER_EXCLUDE_CHAR_LIST ) && ContainsExcludedCharacters( aValue ) )
|
||||
if( msg.empty() && validator.HasFlag( wxFILTER_EXCLUDE_CHAR_LIST ) )
|
||||
{
|
||||
wxArrayString badCharsFound;
|
||||
|
||||
for( const wxUniCharRef& excludeChar : GetCharExcludes() )
|
||||
for( const wxUniCharRef& excludeChar : validator.GetCharExcludes() )
|
||||
{
|
||||
if( aValue.Find( excludeChar ) != wxNOT_FOUND )
|
||||
{
|
||||
@@ -390,68 +398,83 @@ bool FIELD_VALIDATOR::DoValidate( const wxString& aValue, wxWindow* aParent )
|
||||
}
|
||||
}
|
||||
|
||||
wxString badChars;
|
||||
|
||||
for( size_t i = 0; i < badCharsFound.GetCount(); i++ )
|
||||
if( !badCharsFound.IsEmpty() )
|
||||
{
|
||||
if( !badChars.IsEmpty() )
|
||||
wxString badChars;
|
||||
|
||||
for( size_t i = 0; i < badCharsFound.GetCount(); i++ )
|
||||
{
|
||||
if( badCharsFound.GetCount() == 2 )
|
||||
if( !badChars.IsEmpty() )
|
||||
{
|
||||
badChars += _( " or " );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( i < badCharsFound.GetCount() - 2 )
|
||||
badChars += _( ", or " );
|
||||
if( badCharsFound.GetCount() == 2 )
|
||||
{
|
||||
badChars += _( " or " );
|
||||
}
|
||||
else
|
||||
badChars += wxT( ", " );
|
||||
{
|
||||
if( i < badCharsFound.GetCount() - 2 )
|
||||
badChars += _( ", or " );
|
||||
else
|
||||
badChars += wxT( ", " );
|
||||
}
|
||||
}
|
||||
|
||||
badChars += badCharsFound.Item( i );
|
||||
}
|
||||
|
||||
badChars += badCharsFound.Item( i );
|
||||
switch( aFieldId )
|
||||
{
|
||||
case REFERENCE_FIELD:
|
||||
msg.Printf( _( "The reference designator cannot contain %s character(s)." ), badChars );
|
||||
break;
|
||||
|
||||
case VALUE_FIELD:
|
||||
msg.Printf( _( "The value field cannot contain %s character(s)." ), badChars );
|
||||
break;
|
||||
|
||||
case FOOTPRINT_FIELD:
|
||||
msg.Printf( _( "The footprint field cannot contain %s character(s)." ), badChars );
|
||||
break;
|
||||
|
||||
case DATASHEET_FIELD:
|
||||
msg.Printf( _( "The datasheet field cannot contain %s character(s)." ), badChars );
|
||||
break;
|
||||
|
||||
case SHEETNAME_V:
|
||||
msg.Printf( _( "The sheet name cannot contain %s character(s)." ), badChars );
|
||||
break;
|
||||
|
||||
case SHEETFILENAME_V:
|
||||
msg.Printf( _( "The sheet filename cannot contain %s character(s)." ), badChars );
|
||||
break;
|
||||
|
||||
default:
|
||||
msg.Printf( _( "The field cannot contain %s character(s)." ), badChars );
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
switch( m_fieldId )
|
||||
if( msg.empty() )
|
||||
{
|
||||
if( aFieldId == REFERENCE_FIELD && aValue.Contains( wxT( "${" ) ) )
|
||||
{
|
||||
case REFERENCE_FIELD:
|
||||
msg.Printf( _( "The reference designator cannot contain %s character(s)." ), badChars );
|
||||
break;
|
||||
|
||||
case VALUE_FIELD:
|
||||
msg.Printf( _( "The value field cannot contain %s character(s)." ), badChars );
|
||||
break;
|
||||
|
||||
case FOOTPRINT_FIELD:
|
||||
msg.Printf( _( "The footprint field cannot contain %s character(s)." ), badChars );
|
||||
break;
|
||||
|
||||
case DATASHEET_FIELD:
|
||||
msg.Printf( _( "The datasheet field cannot contain %s character(s)." ), badChars );
|
||||
break;
|
||||
|
||||
case SHEETNAME_V:
|
||||
msg.Printf( _( "The sheet name cannot contain %s character(s)." ), badChars );
|
||||
break;
|
||||
|
||||
case SHEETFILENAME_V:
|
||||
msg.Printf( _( "The sheet filename cannot contain %s character(s)." ), badChars );
|
||||
break;
|
||||
|
||||
default:
|
||||
msg.Printf( _( "The field cannot contain %s character(s)." ), badChars );
|
||||
break;
|
||||
};
|
||||
}
|
||||
else if( m_fieldId == REFERENCE_FIELD && aValue.Contains( wxT( "${" ) ) )
|
||||
{
|
||||
msg.Printf( _( "The reference designator cannot contain text variable references" ) );
|
||||
}
|
||||
else if( m_fieldId == REFERENCE_FIELD && UTIL::GetRefDesPrefix( aValue ).IsEmpty() )
|
||||
{
|
||||
msg.Printf( _( "References must start with a letter." ) );
|
||||
msg.Printf( _( "The reference designator cannot contain text variable references" ) );
|
||||
}
|
||||
else if( aFieldId == REFERENCE_FIELD && UTIL::GetRefDesPrefix( aValue ).IsEmpty() )
|
||||
{
|
||||
msg.Printf( _( "References must start with a letter." ) );
|
||||
}
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
bool FIELD_VALIDATOR::DoValidate( const wxString& aValue, wxWindow* aParent )
|
||||
{
|
||||
wxString msg = GetFieldValidationErrorMessage( m_fieldId, aValue );
|
||||
|
||||
if( !msg.empty() )
|
||||
{
|
||||
if( m_validatorWindow )
|
||||
|
||||
@@ -214,6 +214,22 @@ void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
|
||||
int y = mouseRel.y;
|
||||
VECTOR2D mousePos( x, y );
|
||||
|
||||
// Clear keyboard cursor position flag when actual mouse motion is detected
|
||||
// (i.e., not from cursor warping and position has changed)
|
||||
if( !m_cursorWarped && m_settings.m_lastKeyboardCursorPositionValid )
|
||||
{
|
||||
VECTOR2I screenPos( x, y );
|
||||
VECTOR2I keyboardScreenPos = m_view->ToScreen( m_settings.m_lastKeyboardCursorPosition );
|
||||
|
||||
// If mouse has moved to a different position than the keyboard cursor position,
|
||||
// clear the keyboard position flag to allow mouse control
|
||||
if( screenPos != keyboardScreenPos )
|
||||
{
|
||||
m_settings.m_lastKeyboardCursorPositionValid = false;
|
||||
m_settings.m_lastKeyboardCursorPosition = { 0.0, 0.0 };
|
||||
}
|
||||
}
|
||||
|
||||
// Automatic focus switching between SCH and PCB windows on canvas mouse motion
|
||||
if( m_settings.m_focusFollowSchPcb )
|
||||
{
|
||||
|
||||
@@ -326,7 +326,9 @@ void COLOR_SWATCH::GetNewSwatchColor()
|
||||
|
||||
void COLOR_SWATCH::OnDarkModeToggle()
|
||||
{
|
||||
m_checkerboardBg = m_parent->GetBackgroundColour();
|
||||
wxWindow* parent = GetParent();
|
||||
m_checkerboardBg = parent ? parent->GetBackgroundColour() : wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW );
|
||||
|
||||
m_swatch->SetBitmap( makeBitmap() );
|
||||
if( m_swatch )
|
||||
m_swatch->SetBitmap( makeBitmap() );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
|
||||
#include <widgets/grid_striped_renderer.h>
|
||||
|
||||
void STRIPED_CELL_RENDERER::Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc,
|
||||
const wxRect& rect, int row, int col, bool isSelected)
|
||||
{
|
||||
// First draw the striped background for empty cells
|
||||
wxString cellValue = grid.GetCellValue(row, col);
|
||||
if (cellValue.IsEmpty())
|
||||
{
|
||||
DrawStripedBackground(dc, rect, isSelected);
|
||||
}
|
||||
|
||||
// Then draw the text content using the parent class
|
||||
wxGridCellStringRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
|
||||
}
|
||||
|
||||
void STRIPED_CELL_RENDERER::drawStripedBackground(wxDC& dc, const wxRect& rect, bool isSelected) const
|
||||
{
|
||||
if (isSelected)
|
||||
{
|
||||
// For selected cells, use the selection color
|
||||
dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT)));
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.DrawRectangle(rect);
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw horizontal stripes
|
||||
const int stripeHeight = 3;
|
||||
wxColour color1 = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
|
||||
wxColour color2(240, 240, 240); // Light gray
|
||||
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
|
||||
bool useColor1 = true;
|
||||
for (int y = rect.GetTop(); y < rect.GetBottom(); y += stripeHeight)
|
||||
{
|
||||
wxColour currentColor = useColor1 ? color1 : color2;
|
||||
dc.SetBrush(wxBrush(currentColor));
|
||||
|
||||
int stripeBottom = wxMin(y + stripeHeight, rect.GetBottom());
|
||||
dc.DrawRectangle(rect.GetLeft(), y, rect.GetWidth(), stripeBottom - y);
|
||||
|
||||
useColor1 = !useColor1;
|
||||
}
|
||||
}
|
||||
@@ -443,7 +443,8 @@ public:
|
||||
TEXT_BUTTON_FILE_BROWSER( wxWindow* aParent, DIALOG_SHIM* aParentDlg, WX_GRID* aGrid,
|
||||
wxString* aCurrentDir, const wxString& aFileFilter = wxEmptyString,
|
||||
bool aNormalize = false,
|
||||
const wxString& aNormalizeBasePath = wxEmptyString ) :
|
||||
const wxString& aNormalizeBasePath = wxEmptyString,
|
||||
std::function<wxString( const wxString& )> aEmbedCallback = nullptr ) :
|
||||
wxComboCtrl( aParent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 0, 0 ),
|
||||
wxTE_PROCESS_ENTER | wxBORDER_NONE ),
|
||||
m_dlg( aParentDlg ),
|
||||
@@ -451,7 +452,8 @@ public:
|
||||
m_currentDir( aCurrentDir ),
|
||||
m_normalize( aNormalize ),
|
||||
m_normalizeBasePath( aNormalizeBasePath ),
|
||||
m_fileFilter( aFileFilter )
|
||||
m_fileFilter( aFileFilter ),
|
||||
m_embedCallback( std::move( aEmbedCallback ) )
|
||||
{
|
||||
SetButtonBitmaps( KiBitmapBundle( BITMAPS::small_folder ) );
|
||||
|
||||
@@ -463,7 +465,8 @@ public:
|
||||
wxString* aCurrentDir,
|
||||
std::function<wxString( WX_GRID* grid, int row )> aFileFilterFn,
|
||||
bool aNormalize = false,
|
||||
const wxString& aNormalizeBasePath = wxEmptyString ) :
|
||||
const wxString& aNormalizeBasePath = wxEmptyString,
|
||||
std::function<wxString( const wxString& )> aEmbedCallback = nullptr ) :
|
||||
wxComboCtrl( aParent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 0, 0 ),
|
||||
wxTE_PROCESS_ENTER | wxBORDER_NONE ),
|
||||
m_dlg( aParentDlg ),
|
||||
@@ -471,7 +474,8 @@ public:
|
||||
m_currentDir( aCurrentDir ),
|
||||
m_normalize( aNormalize ),
|
||||
m_normalizeBasePath( aNormalizeBasePath ),
|
||||
m_fileFilterFn( std::move( aFileFilterFn ) )
|
||||
m_fileFilterFn( std::move( aFileFilterFn ) ),
|
||||
m_embedCallback( std::move( aEmbedCallback ) )
|
||||
{
|
||||
SetButtonBitmaps( KiBitmapBundle( BITMAPS::small_folder ) );
|
||||
|
||||
@@ -502,16 +506,30 @@ protected:
|
||||
|
||||
if( !m_fileFilter.IsEmpty() )
|
||||
{
|
||||
FILEDLG_OPEN_EMBED_FILE customize( false );
|
||||
wxFileDialog dlg( m_dlg, _( "Select a File" ), fn.GetPath(), fn.GetFullName(),
|
||||
m_fileFilter, wxFD_FILE_MUST_EXIST | wxFD_OPEN );
|
||||
|
||||
if( m_embedCallback )
|
||||
dlg.SetCustomizeHook( customize );
|
||||
|
||||
if( dlg.ShowModal() == wxID_OK )
|
||||
{
|
||||
wxString filePath = dlg.GetPath();
|
||||
wxString lastPath = dlg.GetDirectory();
|
||||
wxString relPath = wxEmptyString;
|
||||
|
||||
if( m_normalize )
|
||||
if( m_embedCallback && customize.GetEmbed() )
|
||||
{
|
||||
relPath = m_embedCallback( filePath );
|
||||
|
||||
if( relPath.IsEmpty() )
|
||||
{
|
||||
m_dlg->CleanupAfterModalSubDialog();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if( m_normalize )
|
||||
{
|
||||
relPath = NormalizePath( filePath, &Pgm().GetLocalEnvVariables(),
|
||||
m_normalizeBasePath );
|
||||
@@ -573,6 +591,7 @@ protected:
|
||||
|
||||
wxString m_fileFilter;
|
||||
std::function<wxString( WX_GRID* aGrid, int aRow )> m_fileFilterFn;
|
||||
std::function<wxString( const wxString& )> m_embedCallback;
|
||||
};
|
||||
|
||||
|
||||
@@ -583,12 +602,13 @@ void GRID_CELL_PATH_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
|
||||
{
|
||||
m_control = new TEXT_BUTTON_FILE_BROWSER( aParent, m_dlg, m_grid, m_currentDir,
|
||||
m_fileFilterFn, m_normalize,
|
||||
m_normalizeBasePath );
|
||||
m_normalizeBasePath, m_embedCallback );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_control = new TEXT_BUTTON_FILE_BROWSER( aParent, m_dlg, m_grid, m_currentDir,
|
||||
m_fileFilter, m_normalize, m_normalizeBasePath );
|
||||
m_fileFilter, m_normalize, m_normalizeBasePath,
|
||||
m_embedCallback );
|
||||
}
|
||||
|
||||
WX_GRID::CellEditorSetMargins( Combo() );
|
||||
|
||||
@@ -122,17 +122,14 @@ PROPERTIES_PANEL::PROPERTIES_PANEL( wxWindow* aParent, EDA_BASE_FRAME* aFrame )
|
||||
m_grid->CenterSplitter();
|
||||
|
||||
Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( PROPERTIES_PANEL::onCharHook ), nullptr, this );
|
||||
Connect( wxEVT_PG_CHANGED, wxPropertyGridEventHandler( PROPERTIES_PANEL::valueChanged ),
|
||||
nullptr, this );
|
||||
Connect( wxEVT_PG_CHANGING, wxPropertyGridEventHandler( PROPERTIES_PANEL::valueChanging ),
|
||||
nullptr, this );
|
||||
Connect( wxEVT_PG_CHANGED, wxPropertyGridEventHandler( PROPERTIES_PANEL::valueChanged ), nullptr, this );
|
||||
Connect( wxEVT_PG_CHANGING, wxPropertyGridEventHandler( PROPERTIES_PANEL::valueChanging ), nullptr, this );
|
||||
Connect( wxEVT_SHOW, wxShowEventHandler( PROPERTIES_PANEL::onShow ), nullptr, this );
|
||||
|
||||
Bind( wxEVT_PG_COL_END_DRAG,
|
||||
[&]( wxPropertyGridEvent& )
|
||||
{
|
||||
m_splitter_key_proportion =
|
||||
static_cast<float>( m_grid->GetSplitterPosition() ) / m_grid->GetSize().x;
|
||||
m_splitter_key_proportion = static_cast<float>( m_grid->GetSplitterPosition() ) / m_grid->GetSize().x;
|
||||
} );
|
||||
|
||||
Bind( wxEVT_SIZE,
|
||||
@@ -225,33 +222,27 @@ void PROPERTIES_PANEL::rebuildProperties( const SELECTION& aSelection )
|
||||
|
||||
wxCHECK( !types.empty(), /* void */ ); // already guarded above, but Coverity doesn't know that
|
||||
|
||||
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
|
||||
std::set<PROPERTY_BASE*> commonProps;
|
||||
const PROPERTY_LIST& allProperties = propMgr.GetProperties( *types.begin() );
|
||||
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
|
||||
std::set<PROPERTY_BASE*> commonProps;
|
||||
const std::vector<PROPERTY_BASE*>& allProperties = propMgr.GetProperties( *types.begin() );
|
||||
|
||||
copy( allProperties.begin(), allProperties.end(),
|
||||
inserter( commonProps, commonProps.begin() ) );
|
||||
copy( allProperties.begin(), allProperties.end(), inserter( commonProps, commonProps.begin() ) );
|
||||
|
||||
PROPERTY_DISPLAY_ORDER displayOrder = propMgr.GetDisplayOrder( *types.begin() );
|
||||
|
||||
std::vector<wxString> groupDisplayOrder = propMgr.GetGroupDisplayOrder( *types.begin() );
|
||||
std::set<wxString> groups( groupDisplayOrder.begin(), groupDisplayOrder.end() );
|
||||
std::map<PROPERTY_BASE*, int> displayOrder = propMgr.GetDisplayOrder( *types.begin() );
|
||||
std::vector<wxString> groupDisplayOrder = propMgr.GetGroupDisplayOrder( *types.begin() );
|
||||
std::set<wxString> groups( groupDisplayOrder.begin(), groupDisplayOrder.end() );
|
||||
|
||||
std::set<PROPERTY_BASE*> availableProps;
|
||||
|
||||
// Get all possible properties
|
||||
for( const TYPE_ID& type : types )
|
||||
{
|
||||
const PROPERTY_LIST& itemProps = propMgr.GetProperties( type );
|
||||
const std::vector<PROPERTY_BASE*>& itemProps = propMgr.GetProperties( type );
|
||||
const std::map<PROPERTY_BASE*, int>& itemDisplayOrder = propMgr.GetDisplayOrder( type );
|
||||
|
||||
const PROPERTY_DISPLAY_ORDER& itemDisplayOrder = propMgr.GetDisplayOrder( type );
|
||||
copy( itemDisplayOrder.begin(), itemDisplayOrder.end(), inserter( displayOrder, displayOrder.begin() ) );
|
||||
|
||||
copy( itemDisplayOrder.begin(), itemDisplayOrder.end(),
|
||||
inserter( displayOrder, displayOrder.begin() ) );
|
||||
|
||||
const std::vector<wxString>& itemGroups = propMgr.GetGroupDisplayOrder( type );
|
||||
|
||||
for( const wxString& group : itemGroups )
|
||||
for( const wxString& group : propMgr.GetGroupDisplayOrder( type ) )
|
||||
{
|
||||
if( !groups.count( group ) )
|
||||
{
|
||||
@@ -305,9 +296,14 @@ void PROPERTIES_PANEL::rebuildProperties( const SELECTION& aSelection )
|
||||
if( !property )
|
||||
continue;
|
||||
|
||||
wxVariant commonVal;
|
||||
wxVariant commonVal;
|
||||
wxPGChoices choices;
|
||||
|
||||
extractValueAndWritability( aSelection, property, commonVal, writeable, choices );
|
||||
|
||||
if( choices.GetCount() > 0 )
|
||||
pgProp->SetChoices( choices );
|
||||
|
||||
extractValueAndWritability( aSelection, property, commonVal, writeable );
|
||||
pgProp->SetValue( commonVal );
|
||||
pgProp->Enable( writeable );
|
||||
|
||||
@@ -326,13 +322,17 @@ void PROPERTIES_PANEL::rebuildProperties( const SELECTION& aSelection )
|
||||
for( PROPERTY_BASE* property : availableProps )
|
||||
{
|
||||
wxPGProperty* pgProp = createPGProperty( property );
|
||||
wxVariant commonVal;
|
||||
wxVariant commonVal;
|
||||
wxPGChoices choices;
|
||||
|
||||
if( !extractValueAndWritability( aSelection, property, commonVal, writeable ) )
|
||||
if( !extractValueAndWritability( aSelection, property, commonVal, writeable, choices ) )
|
||||
continue;
|
||||
|
||||
if( pgProp )
|
||||
{
|
||||
if( choices.GetCount() )
|
||||
pgProp->SetChoices( choices );
|
||||
|
||||
pgProp->SetValue( commonVal );
|
||||
pgProp->Enable( writeable );
|
||||
m_displayed.push_back( property );
|
||||
@@ -403,13 +403,12 @@ bool PROPERTIES_PANEL::getItemValue( EDA_ITEM* aItem, PROPERTY_BASE* aProperty,
|
||||
}
|
||||
|
||||
|
||||
bool PROPERTIES_PANEL::extractValueAndWritability( const SELECTION& aSelection,
|
||||
PROPERTY_BASE* aProperty,
|
||||
wxVariant& aValue, bool& aWritable )
|
||||
bool PROPERTIES_PANEL::extractValueAndWritability( const SELECTION& aSelection, PROPERTY_BASE* aProperty,
|
||||
wxVariant& aValue, bool& aWritable, wxPGChoices& aChoices )
|
||||
{
|
||||
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
|
||||
bool different = false;
|
||||
wxVariant commonVal;
|
||||
bool first = true;
|
||||
|
||||
aWritable = true;
|
||||
|
||||
@@ -421,6 +420,22 @@ bool PROPERTIES_PANEL::extractValueAndWritability( const SELECTION& aSelection,
|
||||
if( aProperty->IsHiddenFromPropertiesManager() )
|
||||
return false;
|
||||
|
||||
wxPGChoices choices = aProperty->GetChoices( item );
|
||||
|
||||
if( first )
|
||||
{
|
||||
aChoices = choices;
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
wxArrayString labels = choices.GetLabels();
|
||||
wxArrayInt values = choices.GetValuesForStrings( labels );
|
||||
|
||||
if( labels != aChoices.GetLabels() || values != aChoices.GetValuesForStrings( labels ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
// If read-only for any of the selection, read-only for the whole selection.
|
||||
if( !propMgr.IsWriteableFor( TYPE_HASH( *item ), aProperty, item ) )
|
||||
aWritable = false;
|
||||
@@ -494,10 +509,15 @@ void PROPERTIES_PANEL::onCharHook( wxKeyEvent& aEvent )
|
||||
}
|
||||
}
|
||||
|
||||
if( aEvent.GetKeyCode() == WXK_RETURN || aEvent.GetKeyCode() == WXK_NUMPAD_ENTER )
|
||||
if( aEvent.GetKeyCode() == WXK_RETURN || aEvent.GetKeyCode() == WXK_NUMPAD_ENTER
|
||||
|| aEvent.GetKeyCode() == WXK_DOWN || aEvent.GetKeyCode() == WXK_UP )
|
||||
{
|
||||
m_grid->CommitChangesFromEditor();
|
||||
/* don't skip this one; if we're not the last property we'll also go to the next row */
|
||||
|
||||
CallAfter( [this]()
|
||||
{
|
||||
m_grid->SelectProperty( m_grid->GetSelectedProperty(), true );
|
||||
} );
|
||||
}
|
||||
|
||||
aEvent.Skip();
|
||||
|
||||
@@ -102,7 +102,7 @@ protected:
|
||||
* @return true if the property is available for all the items in the selection
|
||||
*/
|
||||
bool extractValueAndWritability( const SELECTION& aSelection, PROPERTY_BASE* aProperty,
|
||||
wxVariant& aValue, bool& aWritable );
|
||||
wxVariant& aValue, bool& aWritable, wxPGChoices& aChoices );
|
||||
|
||||
public:
|
||||
int m_SuppressGridChangeEvents;
|
||||
|
||||
@@ -230,7 +230,11 @@ void UNIT_BINDER::onComboBox( wxCommandEvent& aEvent )
|
||||
const long long int conv =
|
||||
EDA_UNIT_UTILS::UI::ValueFromString( *m_iuScale, m_units, value, m_dataType );
|
||||
|
||||
SetValue( conv );
|
||||
CallAfter(
|
||||
[this, conv]
|
||||
{
|
||||
SetValue( conv );
|
||||
} );
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
@@ -124,6 +124,8 @@ set( EESCHEMA_DLGS
|
||||
dialogs/dialog_label_properties_base.cpp
|
||||
dialogs/dialog_lib_edit_pin_table.cpp
|
||||
dialogs/dialog_lib_edit_pin_table_base.cpp
|
||||
dialogs/dialog_lib_fields_base.cpp
|
||||
dialogs/dialog_lib_fields.cpp
|
||||
dialogs/dialog_lib_new_symbol.cpp
|
||||
dialogs/dialog_lib_new_symbol_base.cpp
|
||||
dialogs/dialog_lib_symbol_properties.cpp
|
||||
@@ -369,6 +371,7 @@ set( EESCHEMA_SRCS
|
||||
generate_alias_info.cpp
|
||||
gfx_import_utils.cpp
|
||||
junction_helpers.cpp
|
||||
lib_fields_data_model.cpp
|
||||
lib_symbol.cpp
|
||||
libarch.cpp
|
||||
menubar.cpp
|
||||
|
||||
@@ -253,7 +253,7 @@ HANDLER_RESULT<ItemRequestStatus> API_HANDLER_SCH::handleCreateUpdateItemsIntern
|
||||
if( aCreate )
|
||||
{
|
||||
item->Serialize( newItem );
|
||||
commit->Add( item.release() );
|
||||
commit->Add( item.release(), screen );
|
||||
|
||||
if( !m_activeClients.count( aClientName ) )
|
||||
pushCurrentCommit( aClientName, _( "Added items via API" ) );
|
||||
@@ -266,7 +266,7 @@ HANDLER_RESULT<ItemRequestStatus> API_HANDLER_SCH::handleCreateUpdateItemsIntern
|
||||
{
|
||||
schItem->SwapData( static_cast<SCH_ITEM*>( item.get() ) );
|
||||
schItem->Serialize( newItem );
|
||||
commit->Modify( schItem );
|
||||
commit->Modify( schItem, screen );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+100
-71
@@ -563,12 +563,22 @@ CONNECTION_SUBGRAPH::PRIORITY CONNECTION_SUBGRAPH::GetDriverPriority( SCH_ITEM*
|
||||
if( !aDriver )
|
||||
return PRIORITY::NONE;
|
||||
|
||||
auto libSymbolRef =
|
||||
[]( const SCH_SYMBOL* symbol ) -> wxString
|
||||
{
|
||||
if( const std::unique_ptr<LIB_SYMBOL>& part = symbol->GetLibSymbolRef() )
|
||||
return part->GetReferenceField().GetText();
|
||||
|
||||
return wxEmptyString;
|
||||
};
|
||||
|
||||
switch( aDriver->Type() )
|
||||
{
|
||||
case SCH_SHEET_PIN_T: return PRIORITY::SHEET_PIN;
|
||||
case SCH_HIER_LABEL_T: return PRIORITY::HIER_LABEL;
|
||||
case SCH_LABEL_T: return PRIORITY::LOCAL_LABEL;
|
||||
case SCH_GLOBAL_LABEL_T: return PRIORITY::GLOBAL;
|
||||
|
||||
case SCH_PIN_T:
|
||||
{
|
||||
SCH_PIN* sch_pin = static_cast<SCH_PIN*>( aDriver );
|
||||
@@ -576,14 +586,14 @@ CONNECTION_SUBGRAPH::PRIORITY CONNECTION_SUBGRAPH::GetDriverPriority( SCH_ITEM*
|
||||
|
||||
if( sch_pin->IsGlobalPower() )
|
||||
return PRIORITY::POWER_PIN;
|
||||
else if( !sym || sym->GetExcludedFromBoard()
|
||||
|| sym->GetLibSymbolRef()->GetReferenceField().GetText().StartsWith( '#' ) )
|
||||
else if( !sym || sym->GetExcludedFromBoard() || libSymbolRef( sym ).StartsWith( '#' ) )
|
||||
return PRIORITY::NONE;
|
||||
else
|
||||
return PRIORITY::PIN;
|
||||
}
|
||||
|
||||
default: return PRIORITY::NONE;
|
||||
default:
|
||||
return PRIORITY::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -591,13 +601,13 @@ CONNECTION_SUBGRAPH::PRIORITY CONNECTION_SUBGRAPH::GetDriverPriority( SCH_ITEM*
|
||||
void CONNECTION_GRAPH::Merge( CONNECTION_GRAPH& aGraph )
|
||||
{
|
||||
std::copy( aGraph.m_items.begin(), aGraph.m_items.end(),
|
||||
std::back_inserter( m_items ) );
|
||||
std::back_inserter( m_items ) );
|
||||
|
||||
for( SCH_ITEM* item : aGraph.m_items )
|
||||
item->SetConnectionGraph( this );
|
||||
|
||||
std::copy( aGraph.m_subgraphs.begin(), aGraph.m_subgraphs.end(),
|
||||
std::back_inserter( m_subgraphs ) );
|
||||
std::back_inserter( m_subgraphs ) );
|
||||
|
||||
for( CONNECTION_SUBGRAPH* sg : aGraph.m_subgraphs )
|
||||
{
|
||||
@@ -607,13 +617,11 @@ void CONNECTION_GRAPH::Merge( CONNECTION_GRAPH& aGraph )
|
||||
sg->m_graph = this;
|
||||
}
|
||||
|
||||
std::copy( aGraph.m_driver_subgraphs.begin(),
|
||||
aGraph.m_driver_subgraphs.end(),
|
||||
std::back_inserter( m_driver_subgraphs ) );
|
||||
std::copy( aGraph.m_driver_subgraphs.begin(), aGraph.m_driver_subgraphs.end(),
|
||||
std::back_inserter( m_driver_subgraphs ) );
|
||||
|
||||
std::copy( aGraph.m_global_power_pins.begin(),
|
||||
aGraph.m_global_power_pins.end(),
|
||||
std::back_inserter( m_global_power_pins ) );
|
||||
std::copy( aGraph.m_global_power_pins.begin(), aGraph.m_global_power_pins.end(),
|
||||
std::back_inserter( m_global_power_pins ) );
|
||||
|
||||
for( auto& [key, value] : aGraph.m_net_name_to_subgraphs_map )
|
||||
m_net_name_to_subgraphs_map.insert_or_assign( key, value );
|
||||
@@ -1141,21 +1149,22 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
|
||||
aSheet.Last()->GetFileName(), aItemList.size() );
|
||||
std::map<VECTOR2I, std::vector<SCH_ITEM*>> connection_map;
|
||||
|
||||
auto updatePin = [&]( SCH_PIN* aPin, SCH_CONNECTION* aConn )
|
||||
{
|
||||
aConn->SetType( CONNECTION_TYPE::NET );
|
||||
auto updatePin =
|
||||
[&]( SCH_PIN* aPin, SCH_CONNECTION* aConn )
|
||||
{
|
||||
aConn->SetType( CONNECTION_TYPE::NET );
|
||||
|
||||
// because calling the first time is not thread-safe
|
||||
wxString name = aPin->GetDefaultNetName( aSheet );
|
||||
aPin->ClearConnectedItems( aSheet );
|
||||
// because calling the first time is not thread-safe
|
||||
wxString name = aPin->GetDefaultNetName( aSheet );
|
||||
aPin->ClearConnectedItems( aSheet );
|
||||
|
||||
// power symbol pins need to be post-processed later
|
||||
if( aPin->IsGlobalPower() )
|
||||
{
|
||||
aConn->SetName( name );
|
||||
m_global_power_pins.emplace_back( std::make_pair( aSheet, aPin ) );
|
||||
}
|
||||
};
|
||||
// power symbol pins need to be post-processed later
|
||||
if( aPin->IsGlobalPower() )
|
||||
{
|
||||
aConn->SetName( name );
|
||||
m_global_power_pins.emplace_back( std::make_pair( aSheet, aPin ) );
|
||||
}
|
||||
};
|
||||
|
||||
for( SCH_ITEM* item : aItemList )
|
||||
{
|
||||
@@ -1227,17 +1236,41 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
|
||||
|
||||
for( const VECTOR2I& point : points )
|
||||
connection_map[ point ].push_back( item );
|
||||
|
||||
/// Special case for labels that overlap wires
|
||||
/// While this is an ERC error as there is not an explicit junction,
|
||||
/// we want to enforce connectivity for all items under the label position.
|
||||
if( dynamic_cast<SCH_LABEL_BASE*>( item ) )
|
||||
{
|
||||
VECTOR2I point = item->GetPosition();
|
||||
SCH_SCREEN* screen = aSheet.LastScreen();
|
||||
auto items = screen->Items().Overlapping( point );
|
||||
std::vector<SCH_ITEM*> overlapping_items;
|
||||
|
||||
std::copy_if( items.begin(), items.end(), std::back_inserter( overlapping_items ),
|
||||
[&]( SCH_ITEM* test_item )
|
||||
{
|
||||
return test_item->Type() == SCH_LINE_T
|
||||
&& test_item->HitTest( point, -1 );
|
||||
} );
|
||||
|
||||
// We need at least two connnectable lines that are not the label here
|
||||
// Otherwise, the label will be normally assigned to one or the other
|
||||
if( overlapping_items.size() < 2 ) continue;
|
||||
|
||||
for( SCH_ITEM* test_item : overlapping_items )
|
||||
connection_map[point].push_back( test_item );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( const auto& it : connection_map )
|
||||
for( auto& [point, connection_vec] : connection_map )
|
||||
{
|
||||
std::vector<SCH_ITEM*> connection_vec = it.second;
|
||||
std::sort( connection_vec.begin(), connection_vec.end() );
|
||||
alg::remove_duplicates( connection_vec );
|
||||
|
||||
// Pre-scan to see if we have a bus at this location
|
||||
SCH_LINE* busLine = aSheet.LastScreen()->GetBus( it.first );
|
||||
SCH_LINE* busLine = aSheet.LastScreen()->GetBus( point );
|
||||
|
||||
std::mutex update_mutex;
|
||||
|
||||
@@ -1264,7 +1297,6 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bus-to-bus entries are treated just like bus wires
|
||||
else if( connected_item->Type() == SCH_BUS_BUS_ENTRY_T )
|
||||
{
|
||||
@@ -1274,7 +1306,7 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
|
||||
{
|
||||
auto bus_entry = static_cast<SCH_BUS_BUS_ENTRY*>( connected_item );
|
||||
|
||||
if( it.first == bus_entry->GetPosition() )
|
||||
if( point == bus_entry->GetPosition() )
|
||||
bus_entry->m_connected_bus_items[0] = busLine;
|
||||
else
|
||||
bus_entry->m_connected_bus_items[1] = busLine;
|
||||
@@ -1285,7 +1317,6 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Change junctions to be on bus junction layer if they are touching a bus
|
||||
else if( connected_item->Type() == SCH_JUNCTION_T )
|
||||
{
|
||||
@@ -1321,9 +1352,9 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
|
||||
bus_connection_ok = !busLine || connected_item->GetLayer() == LAYER_BUS;
|
||||
}
|
||||
|
||||
if( connected_item->ConnectionPropagatesTo( test_item ) &&
|
||||
test_item->ConnectionPropagatesTo( connected_item ) &&
|
||||
bus_connection_ok )
|
||||
if( connected_item->ConnectionPropagatesTo( test_item )
|
||||
&& test_item->ConnectionPropagatesTo( connected_item )
|
||||
&& bus_connection_ok )
|
||||
{
|
||||
connected_item->AddConnectionTo( aSheet, test_item );
|
||||
}
|
||||
@@ -1339,7 +1370,7 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
|
||||
if( !bus_entry->m_connected_bus_item )
|
||||
{
|
||||
SCH_SCREEN* screen = aSheet.LastScreen();
|
||||
SCH_LINE* bus = screen->GetBus( it.first );
|
||||
SCH_LINE* bus = screen->GetBus( point );
|
||||
|
||||
if( bus )
|
||||
bus_entry->m_connected_bus_item = bus;
|
||||
@@ -1378,11 +1409,8 @@ void CONNECTION_GRAPH::buildItemSubGraphs()
|
||||
// Build subgraphs from items (on a per-sheet basis)
|
||||
for( SCH_ITEM* item : m_items )
|
||||
{
|
||||
for( const auto& it : item->m_connection_map )
|
||||
for( const auto& [sheet, connection] : item->m_connection_map )
|
||||
{
|
||||
const SCH_SHEET_PATH& sheet = it.first;
|
||||
SCH_CONNECTION* connection = it.second;
|
||||
|
||||
if( connection->SubgraphCode() == 0 )
|
||||
{
|
||||
CONNECTION_SUBGRAPH* subgraph = new CONNECTION_SUBGRAPH( this );
|
||||
@@ -1448,7 +1476,6 @@ void CONNECTION_GRAPH::buildItemSubGraphs()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1467,44 +1494,45 @@ void CONNECTION_GRAPH::resolveAllDrivers()
|
||||
|
||||
std::vector<std::future<size_t>> returns( dirty_graphs.size() );
|
||||
|
||||
auto update_lambda = []( CONNECTION_SUBGRAPH* subgraph ) -> size_t
|
||||
{
|
||||
if( !subgraph->m_dirty )
|
||||
return 0;
|
||||
|
||||
// Special processing for some items
|
||||
for( SCH_ITEM* item : subgraph->m_items )
|
||||
{
|
||||
switch( item->Type() )
|
||||
auto update_lambda =
|
||||
[]( CONNECTION_SUBGRAPH* subgraph ) -> size_t
|
||||
{
|
||||
case SCH_NO_CONNECT_T:
|
||||
subgraph->m_no_connect = item;
|
||||
break;
|
||||
if( !subgraph->m_dirty )
|
||||
return 0;
|
||||
|
||||
case SCH_BUS_WIRE_ENTRY_T:
|
||||
subgraph->m_bus_entry = item;
|
||||
break;
|
||||
// Special processing for some items
|
||||
for( SCH_ITEM* item : subgraph->m_items )
|
||||
{
|
||||
switch( item->Type() )
|
||||
{
|
||||
case SCH_NO_CONNECT_T:
|
||||
subgraph->m_no_connect = item;
|
||||
break;
|
||||
|
||||
case SCH_PIN_T:
|
||||
{
|
||||
auto pin = static_cast<SCH_PIN*>( item );
|
||||
case SCH_BUS_WIRE_ENTRY_T:
|
||||
subgraph->m_bus_entry = item;
|
||||
break;
|
||||
|
||||
if( pin->GetType() == ELECTRICAL_PINTYPE::PT_NC )
|
||||
subgraph->m_no_connect = item;
|
||||
case SCH_PIN_T:
|
||||
{
|
||||
auto pin = static_cast<SCH_PIN*>( item );
|
||||
|
||||
break;
|
||||
}
|
||||
if( pin->GetType() == ELECTRICAL_PINTYPE::PT_NC )
|
||||
subgraph->m_no_connect = item;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
subgraph->ResolveDrivers( true );
|
||||
subgraph->m_dirty = false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
};
|
||||
subgraph->ResolveDrivers( true );
|
||||
subgraph->m_dirty = false;
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
thread_pool& tp = GetKiCadThreadPool();
|
||||
|
||||
@@ -2304,8 +2332,9 @@ void CONNECTION_GRAPH::buildConnectionGraph( std::function<void( SCH_ITEM* )>* a
|
||||
[&]( CONNECTION_SUBGRAPH* subgraph ) -> size_t
|
||||
{
|
||||
// Make sure weakly-driven single-pin nets get the unconnected_ prefix
|
||||
if( !subgraph->m_strong_driver && subgraph->m_drivers.size() == 1 &&
|
||||
subgraph->m_driver->Type() == SCH_PIN_T )
|
||||
if( !subgraph->m_strong_driver
|
||||
&& subgraph->m_drivers.size() == 1
|
||||
&& subgraph->m_driver->Type() == SCH_PIN_T )
|
||||
{
|
||||
SCH_PIN* pin = static_cast<SCH_PIN*>( subgraph->m_driver );
|
||||
wxString name = pin->GetDefaultNetName( subgraph->m_sheet, true );
|
||||
|
||||
@@ -590,7 +590,16 @@ int DIALOG_CHANGE_SYMBOLS::processSymbols( SCH_COMMIT* aCommit,
|
||||
{
|
||||
SCH_SYMBOL* symbol = it->first;
|
||||
|
||||
wxCHECK2( symbol && it->second.m_LibId.IsValid(), continue );
|
||||
wxCHECK2( symbol, ++it; continue );
|
||||
|
||||
if( !it->second.m_LibId.IsValid() )
|
||||
{
|
||||
msg = getSymbolReferences( *symbol, it->second.m_LibId );
|
||||
msg << wxT( ": " ) << _( "*** symbol lib id not valid ***" );
|
||||
m_messagePanel->Report( msg, RPT_SEVERITY_ERROR );
|
||||
it = symbols.erase( it );
|
||||
continue;
|
||||
}
|
||||
|
||||
LIB_SYMBOL* libSymbol = frame->GetLibSymbol( it->second.m_LibId );
|
||||
|
||||
@@ -647,10 +656,13 @@ int DIALOG_CHANGE_SYMBOLS::processSymbols( SCH_COMMIT* aCommit,
|
||||
// Remember initial link before changing for diags purpose
|
||||
wxString initialLibLinkName = UnescapeString( symbol->GetLibId().Format() );
|
||||
|
||||
LIB_SYMBOL* libSymbol = frame->GetLibSymbol( symbol_change_info.m_LibId );
|
||||
|
||||
wxCHECK2( libSymbol, continue );
|
||||
|
||||
if( symbol_change_info.m_LibId != symbol->GetLibId() )
|
||||
symbol->SetLibId( symbol_change_info.m_LibId );
|
||||
|
||||
LIB_SYMBOL* libSymbol = frame->GetLibSymbol( symbol_change_info.m_LibId );
|
||||
std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
|
||||
SCH_SCREEN* screen = symbol_change_info.m_Instances[0].LastScreen();
|
||||
|
||||
|
||||
@@ -195,6 +195,28 @@ void DIALOG_ERC::UpdateAnnotationWarning()
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_ERC::OnCharHook( wxKeyEvent& aEvt )
|
||||
{
|
||||
if( int hotkey = aEvt.GetKeyCode() )
|
||||
{
|
||||
if( aEvt.ControlDown() )
|
||||
hotkey |= MD_CTRL;
|
||||
if( aEvt.ShiftDown() )
|
||||
hotkey |= MD_SHIFT;
|
||||
if( aEvt.AltDown() )
|
||||
hotkey |= MD_ALT;
|
||||
|
||||
if( hotkey == ACTIONS::excludeMarker.GetHotKey() )
|
||||
{
|
||||
ExcludeMarker();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DIALOG_SHIM::OnCharHook( aEvt );
|
||||
}
|
||||
|
||||
|
||||
bool DIALOG_ERC::updateUI()
|
||||
{
|
||||
// If ERC checks ever get slow enough we'll want a progress indicator...
|
||||
@@ -325,6 +347,7 @@ void DIALOG_ERC::OnDeleteAllClick( wxCommandEvent& event )
|
||||
}
|
||||
|
||||
deleteAllMarkers( includeExclusions );
|
||||
m_ercRun = false;
|
||||
|
||||
// redraw the schematic
|
||||
redrawDrawPanel();
|
||||
|
||||
@@ -22,8 +22,7 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _DIALOG_ERC_H_
|
||||
#define _DIALOG_ERC_H_
|
||||
#pragma once
|
||||
|
||||
#include <wx/htmllbox.h>
|
||||
|
||||
@@ -70,6 +69,7 @@ public:
|
||||
|
||||
private:
|
||||
// from DIALOG_ERC_BASE:
|
||||
void OnCharHook( wxKeyEvent& aEvt ) override;
|
||||
void OnCloseErcDialog( wxCloseEvent& event ) override;
|
||||
void OnRunERCClick( wxCommandEvent& event ) override;
|
||||
void OnDeleteOneClick( wxCommandEvent& event ) override;
|
||||
@@ -116,8 +116,3 @@ private:
|
||||
|
||||
int m_severities;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// _DIALOG_ERC_H_
|
||||
|
||||
@@ -53,10 +53,63 @@
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/filedlg.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/process.h>
|
||||
#include <wx/regex.h>
|
||||
#include <wx/txtstrm.h>
|
||||
#include <wx/utils.h>
|
||||
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
std::vector<wxString> SplitCommandLine( const wxString& aCommand )
|
||||
{
|
||||
std::vector<wxString> args;
|
||||
wxString current;
|
||||
bool inSingle = false;
|
||||
bool inDouble = false;
|
||||
bool argStarted = false;
|
||||
|
||||
for( wxUniChar c : aCommand )
|
||||
{
|
||||
if( c == '"' && !inSingle )
|
||||
{
|
||||
inDouble = !inDouble;
|
||||
argStarted = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( c == '\'' && !inDouble )
|
||||
{
|
||||
inSingle = !inSingle;
|
||||
argStarted = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( ( c == ' ' || c == '\t' || c == '\n' || c == '\r' ) && !inSingle && !inDouble )
|
||||
{
|
||||
if( argStarted || !current.IsEmpty() )
|
||||
{
|
||||
args.emplace_back( current );
|
||||
current.clear();
|
||||
argStarted = false;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
current.Append( c );
|
||||
argStarted = true;
|
||||
}
|
||||
|
||||
if( argStarted || !current.IsEmpty() )
|
||||
args.emplace_back( current );
|
||||
|
||||
return args;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
||||
#define CUSTOMPANEL_COUNTMAX 8 // Max number of netlist plugins
|
||||
@@ -232,16 +285,16 @@ DIALOG_EXPORT_NETLIST::DIALOG_EXPORT_NETLIST( SCH_EDIT_FRAME* aEditFrame, wxWind
|
||||
page->m_LeftBoxSizer->Add( label, 0, wxBOTTOM, 10 );
|
||||
m_PanelNetType[PANELALLEGRO] = page;
|
||||
|
||||
page = new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "PADS" ), NET_TYPE_PADS, false );
|
||||
label = new wxStaticText( page, wxID_ANY, _( "Export netlist in PADS format" ) );
|
||||
page->m_LeftBoxSizer->Add( label, 0, wxBOTTOM, 10 );
|
||||
m_PanelNetType[PANELPADS] = page;
|
||||
|
||||
page = new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "CadStar" ), NET_TYPE_CADSTAR, false );
|
||||
label = new wxStaticText( page, wxID_ANY, _( "Export netlist in CadStar format" ) );
|
||||
page->m_LeftBoxSizer->Add( label, 0, wxBOTTOM, 10 );
|
||||
m_PanelNetType[PANELCADSTAR] = page;
|
||||
|
||||
page = new EXPORT_NETLIST_PAGE( m_NoteBook, wxT( "PADS" ), NET_TYPE_PADS, false );
|
||||
label = new wxStaticText( page, wxID_ANY, _( "Export netlist in PADS format" ) );
|
||||
page->m_LeftBoxSizer->Add( label, 0, wxBOTTOM, 10 );
|
||||
m_PanelNetType[PANELPADS] = page;
|
||||
|
||||
InstallPageSpice();
|
||||
InstallPageSpiceModel();
|
||||
|
||||
@@ -616,68 +669,119 @@ bool DIALOG_EXPORT_NETLIST::TransferDataFromWindow()
|
||||
|
||||
if( !commandLine.IsEmpty() )
|
||||
{
|
||||
wxProcess* process = new wxProcess( GetEventHandler(), wxID_ANY );
|
||||
process->Redirect();
|
||||
wxExecute( commandLine, wxEXEC_ASYNC, process );
|
||||
std::vector<wxString> argsStrings = SplitCommandLine( commandLine );
|
||||
|
||||
reporter.ReportHead( commandLine, RPT_SEVERITY_ACTION );
|
||||
process->Activate();
|
||||
|
||||
std::this_thread::sleep_for( std::chrono::seconds( 1 ) ); // give the process time to start and output any data or errors
|
||||
|
||||
if( process->IsInputAvailable() )
|
||||
if( !argsStrings.empty() )
|
||||
{
|
||||
wxInputStream* in = process->GetInputStream();
|
||||
wxTextInputStream textstream( *in );
|
||||
std::vector<const wxChar*> argv;
|
||||
argv.reserve( argsStrings.size() + 1 );
|
||||
|
||||
while( in->CanRead() )
|
||||
for( wxString& arg : argsStrings )
|
||||
argv.emplace_back( arg.wc_str() );
|
||||
|
||||
argv.emplace_back( nullptr );
|
||||
|
||||
wxExecuteEnv env;
|
||||
wxGetEnvMap( &env.env );
|
||||
|
||||
const ENV_VAR_MAP& envVars = Pgm().GetLocalEnvVariables();
|
||||
|
||||
for( const auto& [key, value] : envVars )
|
||||
{
|
||||
wxString line = textstream.ReadLine();
|
||||
|
||||
if( !line.IsEmpty() )
|
||||
reporter.Report( line, RPT_SEVERITY_INFO );
|
||||
if( !value.GetValue().IsEmpty() )
|
||||
env.env[key] = value.GetValue();
|
||||
}
|
||||
}
|
||||
|
||||
if( process->IsErrorAvailable() )
|
||||
{
|
||||
wxInputStream* err = process->GetErrorStream();
|
||||
wxTextInputStream textstream( *err );
|
||||
wxFileName netlistFile( fullpath );
|
||||
|
||||
while( err->CanRead() )
|
||||
if( !netlistFile.IsAbsolute() )
|
||||
netlistFile.MakeAbsolute( Prj().GetProjectPath() );
|
||||
else
|
||||
netlistFile.MakeAbsolute();
|
||||
|
||||
wxString cwd = netlistFile.GetPath();
|
||||
|
||||
if( cwd.IsEmpty() )
|
||||
cwd = Prj().GetProjectPath();
|
||||
|
||||
env.cwd = cwd;
|
||||
|
||||
wxProcess* process = new wxProcess( GetEventHandler(), wxID_ANY );
|
||||
process->Redirect();
|
||||
|
||||
long pid = wxExecute( argv.data(), wxEXEC_ASYNC, process, &env );
|
||||
|
||||
reporter.ReportHead( commandLine, RPT_SEVERITY_ACTION );
|
||||
|
||||
if( pid <= 0 )
|
||||
{
|
||||
wxString line = textstream.ReadLine();
|
||||
reporter.Report( _( "external simulator not found" ), RPT_SEVERITY_ERROR );
|
||||
reporter.Report( _( "Note: command line is usually: "
|
||||
"<tt><path to SPICE binary> \"%I\"</tt>" ),
|
||||
RPT_SEVERITY_INFO );
|
||||
delete process;
|
||||
}
|
||||
else
|
||||
{
|
||||
process->Activate();
|
||||
|
||||
if( !line.IsEmpty() )
|
||||
std::this_thread::sleep_for( std::chrono::seconds( 1 ) ); // give the process time to start and output any data or errors
|
||||
|
||||
if( process->IsInputAvailable() )
|
||||
{
|
||||
if( line.EndsWith( wxS( "failed with error 2!" ) ) ) // ENOENT
|
||||
wxInputStream* in = process->GetInputStream();
|
||||
wxTextInputStream textstream( *in );
|
||||
|
||||
while( in->CanRead() )
|
||||
{
|
||||
reporter.Report( _( "external simulator not found" ), RPT_SEVERITY_ERROR );
|
||||
reporter.Report( _( "Note: command line is usually: "
|
||||
"<tt><path to SPICE binary> \"%I\"</tt>" ),
|
||||
RPT_SEVERITY_INFO );
|
||||
}
|
||||
else if( line.EndsWith( wxS( "failed with error 8!" ) ) ) // ENOEXEC
|
||||
{
|
||||
reporter.Report( _( "external simulator has the wrong format or "
|
||||
"architecture" ), RPT_SEVERITY_ERROR );
|
||||
}
|
||||
else if( line.EndsWith( "failed with error 13!" ) ) // EACCES
|
||||
{
|
||||
reporter.Report( _( "permission denied" ), RPT_SEVERITY_ERROR );
|
||||
}
|
||||
else
|
||||
{
|
||||
reporter.Report( line, RPT_SEVERITY_ERROR );
|
||||
wxString line = textstream.ReadLine();
|
||||
|
||||
if( !line.IsEmpty() )
|
||||
reporter.Report( line, RPT_SEVERITY_INFO );
|
||||
}
|
||||
}
|
||||
|
||||
if( process->IsErrorAvailable() )
|
||||
{
|
||||
wxInputStream* err = process->GetErrorStream();
|
||||
wxTextInputStream textstream( *err );
|
||||
|
||||
while( err->CanRead() )
|
||||
{
|
||||
wxString line = textstream.ReadLine();
|
||||
|
||||
if( !line.IsEmpty() )
|
||||
{
|
||||
if( line.EndsWith( wxS( "failed with error 2!" ) ) ) // ENOENT
|
||||
{
|
||||
reporter.Report( _( "external simulator not found" ), RPT_SEVERITY_ERROR );
|
||||
reporter.Report( _( "Note: command line is usually: "
|
||||
"<tt><path to SPICE binary> \"%I\"</tt>" ),
|
||||
RPT_SEVERITY_INFO );
|
||||
}
|
||||
else if( line.EndsWith( wxS( "failed with error 8!" ) ) ) // ENOEXEC
|
||||
{
|
||||
reporter.Report( _( "external simulator has the wrong format or "
|
||||
"architecture" ), RPT_SEVERITY_ERROR );
|
||||
}
|
||||
else if( line.EndsWith( "failed with error 13!" ) ) // EACCES
|
||||
{
|
||||
reporter.Report( _( "permission denied" ), RPT_SEVERITY_ERROR );
|
||||
}
|
||||
else
|
||||
{
|
||||
reporter.Report( line, RPT_SEVERITY_ERROR );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
process->CloseOutput();
|
||||
process->Detach();
|
||||
|
||||
// Do not delete process, it will delete itself when it terminates
|
||||
}
|
||||
}
|
||||
|
||||
process->CloseOutput();
|
||||
process->Detach();
|
||||
|
||||
// Do not delete process, it will delete itself when it terminates
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -463,12 +463,7 @@ bool DIALOG_FIELD_PROPERTIES::TransferDataToWindow()
|
||||
const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( m_field->GetParentSymbol() );
|
||||
|
||||
for( int ii = 1; ii <= symbol->GetUnitCount(); ii++ )
|
||||
{
|
||||
if( symbol->HasUnitDisplayName( ii ) )
|
||||
m_unitChoice->Append( symbol->GetUnitDisplayName( ii ) );
|
||||
else
|
||||
m_unitChoice->Append( symbol->SubReference( ii, false ) );
|
||||
}
|
||||
m_unitChoice->Append( symbol->GetUnitDisplayName( ii, false ) );
|
||||
|
||||
if( symbol->GetUnit() <= ( int )m_unitChoice->GetCount() )
|
||||
m_unitChoice->SetSelection( symbol->GetUnit() - 1 );
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <kiway.h>
|
||||
#include <macros.h>
|
||||
|
||||
#include <kiplatform/io.h>
|
||||
#include "symbol_lib_table.h"
|
||||
|
||||
|
||||
@@ -102,7 +103,8 @@ bool DIALOG_GLOBAL_SYM_LIB_TABLE_CONFIG::TransferDataFromWindow()
|
||||
// Create the config path if it doesn't already exist.
|
||||
wxFileName symTableFileName = SYMBOL_LIB_TABLE::GetGlobalTableFileName();
|
||||
|
||||
if( !symTableFileName.DirExists() && !symTableFileName.Mkdir( 0x777, wxPATH_MKDIR_FULL ) )
|
||||
if( !wxFileName::DirExists( symTableFileName.GetPath() )
|
||||
&& !wxFileName::Mkdir( symTableFileName.GetPath(), 0x777, wxPATH_MKDIR_FULL ) )
|
||||
{
|
||||
DisplayError( this, wxString::Format( _( "Cannot create global library table '%s'." ),
|
||||
symTableFileName.GetPath() ) );
|
||||
@@ -118,6 +120,9 @@ bool DIALOG_GLOBAL_SYM_LIB_TABLE_CONFIG::TransferDataFromWindow()
|
||||
fn.GetFullPath(), symTableFileName.GetFullPath() ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure the copied file is writable
|
||||
KIPLATFORM::IO::MakeWriteable( symTableFileName.GetFullPath() );
|
||||
}
|
||||
|
||||
// Load the successfully copied symbol library table file. This should not fail since the
|
||||
|
||||
@@ -827,7 +827,7 @@ DIALOG_LIB_EDIT_PIN_TABLE::DIALOG_LIB_EDIT_PIN_TABLE( SYMBOL_EDIT_FRAME* parent,
|
||||
m_unitFilter->Append( UNITS_ALL );
|
||||
|
||||
for( int ii = 0; ii < aSymbol->GetUnitCount(); ++ii )
|
||||
m_unitFilter->Append( aSymbol->GetUnitReference( ii + 1 ) );
|
||||
m_unitFilter->Append( LIB_SYMBOL::LetterSubReference( ii + 1, 'A' ) );
|
||||
|
||||
m_unitFilter->SetSelection( -1 );
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DIALOG_LIB_FIELDS_H
|
||||
#define DIALOG_LIB_FIELDS_H
|
||||
|
||||
#include <dialog_lib_fields_base.h>
|
||||
#include <sch_reference_list.h>
|
||||
#include <widgets/grid_text_button_helpers.h>
|
||||
|
||||
class SYMBOL_EDIT_FRAME;
|
||||
class LIB_FIELDS_EDITOR_GRID_DATA_MODEL;
|
||||
class LIB_SYMBOL;
|
||||
|
||||
class DIALOG_LIB_FIELDS : public DIALOG_LIB_FIELDS_BASE
|
||||
{
|
||||
public:
|
||||
DIALOG_LIB_FIELDS( SYMBOL_EDIT_FRAME* parent, wxString libId, const wxArrayString& aSymbolNames );
|
||||
~DIALOG_LIB_FIELDS() override;
|
||||
|
||||
void OnInit();
|
||||
|
||||
protected:
|
||||
void OnClose( wxCloseEvent& event ) override;
|
||||
void OnColumnItemToggled( wxDataViewEvent& event ) override;
|
||||
void OnFieldsCtrlSelectionChanged( wxDataViewEvent& event ) override;
|
||||
void OnSizeFieldList( wxSizeEvent& event ) override;
|
||||
void OnAddField( wxCommandEvent& event ) override;
|
||||
void OnRenameField( wxCommandEvent& event ) override;
|
||||
void OnRemoveField( wxCommandEvent& event ) override;
|
||||
void OnFilterMouseMoved( wxMouseEvent& event ) override;
|
||||
void OnFilterText( wxCommandEvent& event ) override;
|
||||
void OnRegroupSymbols( wxCommandEvent& event ) override;
|
||||
void OnTableValueChanged( wxGridEvent& event ) override;
|
||||
void OnTableCellClick( wxGridEvent& event ) override;
|
||||
void OnTableItemContextMenu( wxGridEvent& event ) override;
|
||||
void OnTableColSize( wxGridSizeEvent& event ) override;
|
||||
void OnCancel( wxCommandEvent& event ) override;
|
||||
void OnOk( wxCommandEvent& event ) override;
|
||||
void OnApply( wxCommandEvent& event ) override;
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
private:
|
||||
void UpdateFieldList();
|
||||
void AddField( const wxString& aFieldName, const wxString& aLabelValue, bool show, bool groupBy, bool addedByUser = false, bool aIsCheckbox = false );
|
||||
void RemoveField( const wxString& fieldName );
|
||||
void RenameField( const wxString& oldName, const wxString& newName );
|
||||
void RegroupSymbols();
|
||||
|
||||
void OnColSort( wxGridEvent& aEvent );
|
||||
void OnColMove( wxGridEvent& aEvent );
|
||||
void OnColLabelChange( wxDataViewEvent& aEvent );
|
||||
void SetupColumnProperties( int aCol );
|
||||
void SetupAllColumnProperties();
|
||||
|
||||
void loadSymbols( const wxArrayString& aSymbolNames );
|
||||
|
||||
wxString m_libId;
|
||||
SYMBOL_EDIT_FRAME* m_parent;
|
||||
|
||||
int m_fieldNameColWidth;
|
||||
int m_labelColWidth;
|
||||
int m_showColWidth;
|
||||
int m_groupByColWidth;
|
||||
|
||||
LIB_FIELDS_EDITOR_GRID_DATA_MODEL* m_dataModel;
|
||||
std::vector<LIB_SYMBOL*> m_symbolsList;
|
||||
};
|
||||
|
||||
|
||||
#endif // DIALOG_LIB_FIELDS_H
|
||||
@@ -0,0 +1,203 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6a-dirty)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "widgets/std_bitmap_button.h"
|
||||
#include "widgets/wx_grid.h"
|
||||
|
||||
#include "dialog_lib_fields_base.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DIALOG_LIB_FIELDS_BASE::DIALOG_LIB_FIELDS_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style )
|
||||
{
|
||||
this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize );
|
||||
|
||||
wxBoxSizer* bMainSizer;
|
||||
bMainSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxBoxSizer* bEditSizer;
|
||||
bEditSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_splitterMainWindow = new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_3DSASH|wxSP_LIVE_UPDATE|wxSP_NO_XP_THEME );
|
||||
m_splitterMainWindow->SetMinimumPaneSize( 200 );
|
||||
|
||||
m_leftPanel = new wxPanel( m_splitterMainWindow, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
wxBoxSizer* bLeftSizer;
|
||||
bLeftSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_fieldsCtrl = new wxDataViewListCtrl( m_leftPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_fieldsCtrl->SetMinSize( wxSize( -1,250 ) );
|
||||
|
||||
bLeftSizer->Add( m_fieldsCtrl, 1, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 5 );
|
||||
|
||||
wxBoxSizer* bFieldsButtons;
|
||||
bFieldsButtons = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_addFieldButton = new STD_BITMAP_BUTTON( m_leftPanel, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
bFieldsButtons->Add( m_addFieldButton, 0, wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
m_renameFieldButton = new STD_BITMAP_BUTTON( m_leftPanel, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
bFieldsButtons->Add( m_renameFieldButton, 0, wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
|
||||
bFieldsButtons->Add( 15, 0, 0, wxEXPAND, 5 );
|
||||
|
||||
m_removeFieldButton = new STD_BITMAP_BUTTON( m_leftPanel, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
bFieldsButtons->Add( m_removeFieldButton, 0, wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
|
||||
bLeftSizer->Add( bFieldsButtons, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_leftPanel->SetSizer( bLeftSizer );
|
||||
m_leftPanel->Layout();
|
||||
bLeftSizer->Fit( m_leftPanel );
|
||||
m_rightPanel = new wxPanel( m_splitterMainWindow, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
wxBoxSizer* bRightSizer;
|
||||
bRightSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxBoxSizer* bControls;
|
||||
bControls = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_filter = new wxSearchCtrl( m_rightPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
#ifndef __WXMAC__
|
||||
m_filter->ShowSearchButton( true );
|
||||
#endif
|
||||
m_filter->ShowCancelButton( true );
|
||||
m_filter->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
|
||||
m_filter->SetMinSize( wxSize( 140,-1 ) );
|
||||
|
||||
bControls->Add( m_filter, 1, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
|
||||
|
||||
m_staticline31 = new wxStaticLine( m_rightPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
|
||||
bControls->Add( m_staticline31, 0, wxEXPAND | wxALL, 3 );
|
||||
|
||||
m_bRefresh = new STD_BITMAP_BUTTON( m_rightPanel, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_bRefresh->SetMinSize( wxSize( 30,30 ) );
|
||||
|
||||
bControls->Add( m_bRefresh, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
|
||||
bRightSizer->Add( bControls, 0, wxEXPAND|wxLEFT|wxTOP, 5 );
|
||||
|
||||
m_grid = new WX_GRID( m_rightPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
|
||||
// Grid
|
||||
m_grid->CreateGrid( 5, 5 );
|
||||
m_grid->EnableEditing( true );
|
||||
m_grid->EnableGridLines( true );
|
||||
m_grid->EnableDragGridSize( false );
|
||||
m_grid->SetMargins( 0, 0 );
|
||||
|
||||
// Columns
|
||||
m_grid->EnableDragColMove( true );
|
||||
m_grid->EnableDragColSize( true );
|
||||
m_grid->SetColLabelSize( 24 );
|
||||
m_grid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
|
||||
|
||||
// Rows
|
||||
m_grid->EnableDragRowSize( false );
|
||||
m_grid->SetRowLabelSize( 0 );
|
||||
m_grid->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
|
||||
|
||||
// Label Appearance
|
||||
|
||||
// Cell Defaults
|
||||
m_grid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_CENTER );
|
||||
m_grid->SetMinSize( wxSize( 400,200 ) );
|
||||
|
||||
bRightSizer->Add( m_grid, 1, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 5 );
|
||||
|
||||
|
||||
m_rightPanel->SetSizer( bRightSizer );
|
||||
m_rightPanel->Layout();
|
||||
bRightSizer->Fit( m_rightPanel );
|
||||
m_splitterMainWindow->SplitVertically( m_leftPanel, m_rightPanel, -1 );
|
||||
bEditSizer->Add( m_splitterMainWindow, 1, wxEXPAND|wxTOP|wxBOTTOM, 5 );
|
||||
|
||||
|
||||
bMainSizer->Add( bEditSizer, 1, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bButtonsSizer;
|
||||
bButtonsSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
|
||||
bButtonsSizer->Add( 0, 0, 9, wxEXPAND, 5 );
|
||||
|
||||
m_sdbSizer = new wxStdDialogButtonSizer();
|
||||
m_sdbSizerOK = new wxButton( this, wxID_OK );
|
||||
m_sdbSizer->AddButton( m_sdbSizerOK );
|
||||
m_sdbSizerApply = new wxButton( this, wxID_APPLY );
|
||||
m_sdbSizer->AddButton( m_sdbSizerApply );
|
||||
m_sdbSizerCancel = new wxButton( this, wxID_CANCEL );
|
||||
m_sdbSizer->AddButton( m_sdbSizerCancel );
|
||||
m_sdbSizer->Realize();
|
||||
|
||||
bButtonsSizer->Add( m_sdbSizer, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
bMainSizer->Add( bButtonsSizer, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
this->SetSizer( bMainSizer );
|
||||
this->Layout();
|
||||
bMainSizer->Fit( this );
|
||||
|
||||
this->Centre( wxBOTH );
|
||||
|
||||
// Connect Events
|
||||
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_LIB_FIELDS_BASE::OnClose ) );
|
||||
m_fieldsCtrl->Connect( wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED, wxDataViewEventHandler( DIALOG_LIB_FIELDS_BASE::OnColumnItemToggled ), NULL, this );
|
||||
m_fieldsCtrl->Connect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( DIALOG_LIB_FIELDS_BASE::OnFieldsCtrlSelectionChanged ), NULL, this );
|
||||
m_fieldsCtrl->Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_LIB_FIELDS_BASE::OnSizeFieldList ), NULL, this );
|
||||
m_addFieldButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnAddField ), NULL, this );
|
||||
m_renameFieldButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnRenameField ), NULL, this );
|
||||
m_removeFieldButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnRemoveField ), NULL, this );
|
||||
m_filter->Connect( wxEVT_MOTION, wxMouseEventHandler( DIALOG_LIB_FIELDS_BASE::OnFilterMouseMoved ), NULL, this );
|
||||
m_filter->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnFilterText ), NULL, this );
|
||||
m_bRefresh->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnRegroupSymbols ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableValueChanged ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableCellClick ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableCellClick ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableItemContextMenu ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableCmdCellClick ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableCmdCellClick ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_COL_SIZE, wxGridSizeEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableColSize ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_EDITOR_SHOWN, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnEditorShown ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableSelectCell ), NULL, this );
|
||||
m_sdbSizerApply->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnApply ), NULL, this );
|
||||
m_sdbSizerCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnCancel ), NULL, this );
|
||||
m_sdbSizerOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnOk ), NULL, this );
|
||||
}
|
||||
|
||||
DIALOG_LIB_FIELDS_BASE::~DIALOG_LIB_FIELDS_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_LIB_FIELDS_BASE::OnClose ) );
|
||||
m_fieldsCtrl->Disconnect( wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED, wxDataViewEventHandler( DIALOG_LIB_FIELDS_BASE::OnColumnItemToggled ), NULL, this );
|
||||
m_fieldsCtrl->Disconnect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( DIALOG_LIB_FIELDS_BASE::OnFieldsCtrlSelectionChanged ), NULL, this );
|
||||
m_fieldsCtrl->Disconnect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_LIB_FIELDS_BASE::OnSizeFieldList ), NULL, this );
|
||||
m_addFieldButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnAddField ), NULL, this );
|
||||
m_renameFieldButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnRenameField ), NULL, this );
|
||||
m_removeFieldButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnRemoveField ), NULL, this );
|
||||
m_filter->Disconnect( wxEVT_MOTION, wxMouseEventHandler( DIALOG_LIB_FIELDS_BASE::OnFilterMouseMoved ), NULL, this );
|
||||
m_filter->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnFilterText ), NULL, this );
|
||||
m_bRefresh->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnRegroupSymbols ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableValueChanged ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableCellClick ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableCellClick ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableItemContextMenu ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableCmdCellClick ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableCmdCellClick ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_COL_SIZE, wxGridSizeEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableColSize ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_EDITOR_SHOWN, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnEditorShown ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableSelectCell ), NULL, this );
|
||||
m_sdbSizerApply->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnApply ), NULL, this );
|
||||
m_sdbSizerCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnCancel ), NULL, this );
|
||||
m_sdbSizerOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnOk ), NULL, this );
|
||||
|
||||
}
|
||||
@@ -0,0 +1,898 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<wxFormBuilder_Project>
|
||||
<FileVersion major="1" minor="18"/>
|
||||
<object class="Project" expanded="true">
|
||||
<property name="code_generation">C++</property>
|
||||
<property name="cpp_class_decoration"></property>
|
||||
<property name="cpp_disconnect_events">1</property>
|
||||
<property name="cpp_event_generation">connect</property>
|
||||
<property name="cpp_help_provider">none</property>
|
||||
<property name="cpp_namespace"></property>
|
||||
<property name="cpp_precompiled_header"></property>
|
||||
<property name="cpp_use_array_enum">0</property>
|
||||
<property name="cpp_use_enum">0</property>
|
||||
<property name="embedded_files_path">res</property>
|
||||
<property name="encoding">UTF-8</property>
|
||||
<property name="file">dialog_lib_fields_base</property>
|
||||
<property name="first_id">1000</property>
|
||||
<property name="internationalize">1</property>
|
||||
<property name="lua_skip_events">1</property>
|
||||
<property name="lua_ui_table">UI</property>
|
||||
<property name="name">dialog_lib_fields_base</property>
|
||||
<property name="path">.</property>
|
||||
<property name="php_disconnect_events">0</property>
|
||||
<property name="php_disconnect_mode">source_name</property>
|
||||
<property name="php_skip_events">1</property>
|
||||
<property name="python_disconnect_events">0</property>
|
||||
<property name="python_disconnect_mode">source_name</property>
|
||||
<property name="python_image_path_wrapper_function_name"></property>
|
||||
<property name="python_indent_with_spaces"></property>
|
||||
<property name="python_skip_events">1</property>
|
||||
<property name="relative_path">1</property>
|
||||
<property name="use_microsoft_bom">0</property>
|
||||
<property name="use_native_eol">0</property>
|
||||
<object class="Dialog" expanded="true">
|
||||
<property name="aui_managed">0</property>
|
||||
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
|
||||
<property name="bg"></property>
|
||||
<property name="center">wxBOTH</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="event_handler">impl_virtual</property>
|
||||
<property name="extra_style"></property>
|
||||
<property name="fg"></property>
|
||||
<property name="font"></property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="minimum_size">-1,-1</property>
|
||||
<property name="name">DIALOG_LIB_FIELDS_BASE</property>
|
||||
<property name="pos"></property>
|
||||
<property name="size">-1,-1</property>
|
||||
<property name="style">wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER</property>
|
||||
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
|
||||
<property name="title">Library Fields Editor</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="two_step_creation">0</property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnClose">OnClose</event>
|
||||
<object class="wxBoxSizer" expanded="true">
|
||||
<property name="minimum_size">-1,-1</property>
|
||||
<property name="name">bMainSizer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxBoxSizer" expanded="true">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bEditSizer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND|wxTOP|wxBOTTOM</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxSplitterWindow" expanded="true">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer">0</property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position">0</property>
|
||||
<property name="aui_row">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_pane_size">200</property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size">-1,-1</property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_splitterMainWindow</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="sashgravity">0.0</property>
|
||||
<property name="sashpos">-1</property>
|
||||
<property name="sashsize">-1</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="splitmode">wxSPLIT_VERTICAL</property>
|
||||
<property name="style">wxSP_3DSASH|wxSP_LIVE_UPDATE|wxSP_NO_XP_THEME</property>
|
||||
<property name="subclass"></property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<object class="splitteritem" expanded="true">
|
||||
<object class="wxPanel" expanded="true">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer">0</property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position">0</property>
|
||||
<property name="aui_row">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_leftPanel</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="subclass"></property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style">wxTAB_TRAVERSAL</property>
|
||||
<object class="wxBoxSizer" expanded="true">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bLeftSizer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT|wxTOP</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxDataViewListCtrl" expanded="false">
|
||||
<property name="bg"></property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="font"></property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="minimum_size">-1,250</property>
|
||||
<property name="name">m_fieldsCtrl</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pos"></property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass"></property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnDataViewListCtrlItemValueChanged">OnColumnItemToggled</event>
|
||||
<event name="OnDataViewListCtrlSelectionChanged">OnFieldsCtrlSelectionChanged</event>
|
||||
<event name="OnSize">OnSizeFieldList</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBoxSizer" expanded="true">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bFieldsButtons</property>
|
||||
<property name="orient">wxHORIZONTAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxBOTTOM|wxLEFT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBitmapButton" expanded="false">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer">0</property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position">0</property>
|
||||
<property name="aui_row">0</property>
|
||||
<property name="auth_needed">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="bitmap"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="current"></property>
|
||||
<property name="default">0</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="disabled"></property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="focus"></property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">MyButton</property>
|
||||
<property name="margins"></property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_addFieldButton</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="position"></property>
|
||||
<property name="pressed"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnButtonClick">OnAddField</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxBOTTOM|wxLEFT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBitmapButton" expanded="false">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer">0</property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position">0</property>
|
||||
<property name="aui_row">0</property>
|
||||
<property name="auth_needed">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="bitmap"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="current"></property>
|
||||
<property name="default">0</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="disabled"></property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="focus"></property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Rename Field...</property>
|
||||
<property name="margins"></property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_renameFieldButton</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="position"></property>
|
||||
<property name="pressed"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnButtonClick">OnRenameField</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="spacer" expanded="true">
|
||||
<property name="height">0</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="width">15</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxBOTTOM|wxLEFT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBitmapButton" expanded="false">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer">0</property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position">0</property>
|
||||
<property name="aui_row">0</property>
|
||||
<property name="auth_needed">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="bitmap"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="current"></property>
|
||||
<property name="default">0</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="disabled"></property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="focus"></property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Remove Field...</property>
|
||||
<property name="margins"></property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_removeFieldButton</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="position"></property>
|
||||
<property name="pressed"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnButtonClick">OnRemoveField</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="splitteritem" expanded="true">
|
||||
<object class="wxPanel" expanded="true">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer">0</property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position">0</property>
|
||||
<property name="aui_row">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_rightPanel</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="subclass"></property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style">wxTAB_TRAVERSAL</property>
|
||||
<object class="wxBoxSizer" expanded="true">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bRightSizer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND|wxLEFT|wxTOP</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBoxSizer" expanded="true">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bControls</property>
|
||||
<property name="orient">wxHORIZONTAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxSearchCtrl" expanded="false">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer">0</property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position">0</property>
|
||||
<property name="aui_row">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="cancel_button">1</property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font">,90,400,-1,70,0</property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size">140,-1</property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_filter</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="search_button">1</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="value"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnMotion">OnFilterMouseMoved</event>
|
||||
<event name="OnText">OnFilterText</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">3</property>
|
||||
<property name="flag">wxEXPAND | wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticLine" expanded="true">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer">0</property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position">0</property>
|
||||
<property name="aui_row">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_staticline31</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style">wxLI_VERTICAL</property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBitmapButton" expanded="false">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer">0</property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position">0</property>
|
||||
<property name="aui_row">0</property>
|
||||
<property name="auth_needed">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="bitmap"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="current"></property>
|
||||
<property name="default">0</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="disabled"></property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="focus"></property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Refresh Grouping</property>
|
||||
<property name="margins"></property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size">30,30</property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_bRefresh</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="position"></property>
|
||||
<property name="pressed"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnButtonClick">OnRegroupSymbols</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT|wxTOP</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxGrid" expanded="false">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer">0</property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position">0</property>
|
||||
<property name="aui_row">0</property>
|
||||
<property name="autosize_cols">0</property>
|
||||
<property name="autosize_rows">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="cell_bg"></property>
|
||||
<property name="cell_font"></property>
|
||||
<property name="cell_horiz_alignment">wxALIGN_LEFT</property>
|
||||
<property name="cell_text"></property>
|
||||
<property name="cell_vert_alignment">wxALIGN_CENTER</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="col_label_horiz_alignment">wxALIGN_CENTER</property>
|
||||
<property name="col_label_size">24</property>
|
||||
<property name="col_label_values"></property>
|
||||
<property name="col_label_vert_alignment">wxALIGN_CENTER</property>
|
||||
<property name="cols">5</property>
|
||||
<property name="column_sizes"></property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="drag_col_move">1</property>
|
||||
<property name="drag_col_size">1</property>
|
||||
<property name="drag_grid_size">0</property>
|
||||
<property name="drag_row_size">0</property>
|
||||
<property name="editing">1</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="grid_line_color"></property>
|
||||
<property name="grid_lines">1</property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label_bg"></property>
|
||||
<property name="label_font"></property>
|
||||
<property name="label_text"></property>
|
||||
<property name="margin_height">0</property>
|
||||
<property name="margin_width">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size">400,200</property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_grid</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="row_label_horiz_alignment">wxALIGN_CENTER</property>
|
||||
<property name="row_label_size">0</property>
|
||||
<property name="row_label_values"></property>
|
||||
<property name="row_label_vert_alignment">wxALIGN_CENTER</property>
|
||||
<property name="row_sizes"></property>
|
||||
<property name="rows">5</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="subclass">WX_GRID; widgets/wx_grid.h; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnGridCellChange">OnTableValueChanged</event>
|
||||
<event name="OnGridCellLeftClick">OnTableCellClick</event>
|
||||
<event name="OnGridCellLeftDClick">OnTableCellClick</event>
|
||||
<event name="OnGridCellRightClick">OnTableItemContextMenu</event>
|
||||
<event name="OnGridCmdCellLeftClick">OnTableCmdCellClick</event>
|
||||
<event name="OnGridCmdCellLeftDClick">OnTableCmdCellClick</event>
|
||||
<event name="OnGridColSize">OnTableColSize</event>
|
||||
<event name="OnGridEditorShown">OnEditorShown</event>
|
||||
<event name="OnGridSelectCell">OnTableSelectCell</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBoxSizer" expanded="true">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bButtonsSizer</property>
|
||||
<property name="orient">wxHORIZONTAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">9</property>
|
||||
<object class="spacer" expanded="false">
|
||||
<property name="height">0</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="width">0</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStdDialogButtonSizer" expanded="false">
|
||||
<property name="Apply">1</property>
|
||||
<property name="Cancel">1</property>
|
||||
<property name="ContextHelp">0</property>
|
||||
<property name="Help">0</property>
|
||||
<property name="No">0</property>
|
||||
<property name="OK">1</property>
|
||||
<property name="Save">0</property>
|
||||
<property name="Yes">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">m_sdbSizer</property>
|
||||
<property name="permission">protected</property>
|
||||
<event name="OnApplyButtonClick">OnApply</event>
|
||||
<event name="OnCancelButtonClick">OnCancel</event>
|
||||
<event name="OnOKButtonClick">OnOk</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</wxFormBuilder_Project>
|
||||
@@ -0,0 +1,92 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6a-dirty)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <wx/artprov.h>
|
||||
#include <wx/xrc/xmlres.h>
|
||||
#include <wx/intl.h>
|
||||
class STD_BITMAP_BUTTON;
|
||||
class WX_GRID;
|
||||
|
||||
#include "dialog_shim.h"
|
||||
#include <wx/dataview.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/string.h>
|
||||
#include <wx/bmpbuttn.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/srchctrl.h>
|
||||
#include <wx/statline.h>
|
||||
#include <wx/grid.h>
|
||||
#include <wx/splitter.h>
|
||||
#include <wx/dialog.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class DIALOG_LIB_FIELDS_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class DIALOG_LIB_FIELDS_BASE : public DIALOG_SHIM
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxSplitterWindow* m_splitterMainWindow;
|
||||
wxPanel* m_leftPanel;
|
||||
wxDataViewListCtrl* m_fieldsCtrl;
|
||||
STD_BITMAP_BUTTON* m_addFieldButton;
|
||||
STD_BITMAP_BUTTON* m_renameFieldButton;
|
||||
STD_BITMAP_BUTTON* m_removeFieldButton;
|
||||
wxPanel* m_rightPanel;
|
||||
wxSearchCtrl* m_filter;
|
||||
wxStaticLine* m_staticline31;
|
||||
STD_BITMAP_BUTTON* m_bRefresh;
|
||||
WX_GRID* m_grid;
|
||||
wxStdDialogButtonSizer* m_sdbSizer;
|
||||
wxButton* m_sdbSizerOK;
|
||||
wxButton* m_sdbSizerApply;
|
||||
wxButton* m_sdbSizerCancel;
|
||||
|
||||
// Virtual event handlers, override them in your derived class
|
||||
virtual void OnClose( wxCloseEvent& event ) { event.Skip(); }
|
||||
virtual void OnColumnItemToggled( wxDataViewEvent& event ) { event.Skip(); }
|
||||
virtual void OnFieldsCtrlSelectionChanged( wxDataViewEvent& event ) { event.Skip(); }
|
||||
virtual void OnSizeFieldList( wxSizeEvent& event ) { event.Skip(); }
|
||||
virtual void OnAddField( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnRenameField( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnRemoveField( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnFilterMouseMoved( wxMouseEvent& event ) { event.Skip(); }
|
||||
virtual void OnFilterText( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnRegroupSymbols( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnTableValueChanged( wxGridEvent& event ) { event.Skip(); }
|
||||
virtual void OnTableCellClick( wxGridEvent& event ) { event.Skip(); }
|
||||
virtual void OnTableItemContextMenu( wxGridEvent& event ) { event.Skip(); }
|
||||
virtual void OnTableCmdCellClick( wxGridEvent& event ) { event.Skip(); }
|
||||
virtual void OnTableColSize( wxGridSizeEvent& event ) { event.Skip(); }
|
||||
virtual void OnEditorShown( wxGridEvent& event ) { event.Skip(); }
|
||||
virtual void OnTableSelectCell( wxGridEvent& event ) { event.Skip(); }
|
||||
virtual void OnApply( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnOk( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
DIALOG_LIB_FIELDS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Library Fields Editor"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER );
|
||||
|
||||
~DIALOG_LIB_FIELDS_BASE();
|
||||
|
||||
};
|
||||
|
||||
@@ -84,6 +84,7 @@ DIALOG_LIB_SYMBOL_PROPERTIES::DIALOG_LIB_SYMBOL_PROPERTIES( SYMBOL_EDIT_FRAME* a
|
||||
} ) );
|
||||
m_grid->SetSelectionMode( wxGrid::wxGridSelectRows );
|
||||
|
||||
|
||||
// Show/hide columns according to the user's preference
|
||||
SYMBOL_EDITOR_SETTINGS* cfg = m_Parent->GetSettings();
|
||||
m_grid->ShowHideColumns( cfg->m_EditSymbolVisibleColumns );
|
||||
@@ -110,8 +111,11 @@ DIALOG_LIB_SYMBOL_PROPERTIES::DIALOG_LIB_SYMBOL_PROPERTIES( SYMBOL_EDIT_FRAME* a
|
||||
|
||||
// wxFormBuilder doesn't include this event...
|
||||
m_grid->Connect( wxEVT_GRID_CELL_CHANGING,
|
||||
wxGridEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanging ),
|
||||
nullptr, this );
|
||||
wxGridEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanging ), nullptr, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_CHANGED,
|
||||
wxGridEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanged ), nullptr, this );
|
||||
m_grid->GetGridWindow()->Bind( wxEVT_MOTION, &DIALOG_LIB_SYMBOL_PROPERTIES::OnGridMotion, this );
|
||||
|
||||
|
||||
// Forward the delete button to the tricks
|
||||
m_deleteFilterButton->Bind( wxEVT_BUTTON,
|
||||
@@ -161,8 +165,10 @@ DIALOG_LIB_SYMBOL_PROPERTIES::~DIALOG_LIB_SYMBOL_PROPERTIES()
|
||||
m_grid->DestroyTable( m_fields );
|
||||
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_CHANGING,
|
||||
wxGridEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanging ),
|
||||
nullptr, this );
|
||||
wxGridEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanging ), nullptr, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_CHANGED,
|
||||
wxGridEventHandler( DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanged ), nullptr, this );
|
||||
m_grid->GetGridWindow()->Unbind( wxEVT_MOTION, &DIALOG_LIB_SYMBOL_PROPERTIES::OnGridMotion, this );
|
||||
|
||||
// Delete the GRID_TRICKS.
|
||||
m_grid->PopEventHandler( true );
|
||||
@@ -174,9 +180,58 @@ bool DIALOG_LIB_SYMBOL_PROPERTIES::TransferDataToWindow()
|
||||
if( !wxDialog::TransferDataToWindow() )
|
||||
return false;
|
||||
|
||||
// Push a copy of each field into m_updateFields
|
||||
// Ensure the fields vector is empty before (re)loading. Constructor no longer
|
||||
// pre-populates fields to avoid double insertion of mandatory fields.
|
||||
if( m_fields->size() > 0 )
|
||||
{
|
||||
// Clear existing entries; we recreate inheritance metadata via push_back()
|
||||
// Note: We cannot simply reuse existing entries because alias inheritance
|
||||
// state may have changed if the parent was edited prior to dialog open.
|
||||
m_fields->clear();
|
||||
}
|
||||
|
||||
// Load current symbol fields (mandatory first, then user fields)
|
||||
m_libEntry->CopyFields( *m_fields );
|
||||
|
||||
// Handle alias (derived) symbol inherited fields. We only inherit non-mandatory fields
|
||||
// and mark any matching names as inherited rather than duplicating them.
|
||||
if( m_libEntry->IsAlias() )
|
||||
{
|
||||
if( LIB_SYMBOL_SPTR parent = m_libEntry->GetParent().lock() )
|
||||
{
|
||||
std::vector<SCH_FIELD*> parentFields;
|
||||
parent->GetFields( parentFields );
|
||||
|
||||
for( SCH_FIELD* pf : parentFields )
|
||||
{
|
||||
if( pf->IsMandatory() )
|
||||
continue; // Never inherit mandatory fields
|
||||
|
||||
bool found = false;
|
||||
|
||||
for( size_t jj = 0; jj < m_fields->size(); ++jj )
|
||||
{
|
||||
SCH_FIELD& f = m_fields->at( jj );
|
||||
|
||||
if( f.IsMandatory() )
|
||||
continue; // Skip mandatory in child list for inheritance match
|
||||
|
||||
if( f.GetCanonicalName() == pf->GetCanonicalName() )
|
||||
{
|
||||
m_fields->SetFieldInherited( jj, *pf );
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( !found )
|
||||
m_fields->AddInheritedField( *pf );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fields already loaded above; avoid re-copying to prevent duplication.
|
||||
|
||||
std::set<wxString> defined;
|
||||
|
||||
for( SCH_FIELD& field : *m_fields )
|
||||
@@ -416,37 +471,40 @@ bool DIALOG_LIB_SYMBOL_PROPERTIES::TransferDataFromWindow()
|
||||
m_Parent->SaveCopyInUndoList( _( "Edit Symbol Properties" ), m_libEntry );
|
||||
}
|
||||
|
||||
// The Y axis for components in lib is from bottom to top while the screen axis is top
|
||||
// to bottom: we must change the y coord sign when writing back to the library
|
||||
for( int ii = 0; ii < (int) m_fields->size(); ++ii )
|
||||
{
|
||||
VECTOR2I pos = m_fields->at( ii ).GetPosition();
|
||||
pos.y = -pos.y;
|
||||
m_fields->at( ii ).SetPosition( pos );
|
||||
m_fields->at( ii ).SetId( ii );
|
||||
}
|
||||
std::vector<SCH_FIELD> fieldsToSave;
|
||||
|
||||
for( int ii = m_fields->GetNumberRows() - 1; ii >= 0; ii-- )
|
||||
{
|
||||
SCH_FIELD& field = m_fields->at( ii );
|
||||
|
||||
if( field.IsMandatory() )
|
||||
continue;
|
||||
// The Y axis for components in lib is from bottom to top while the screen axis is top
|
||||
// to bottom: we must change the y coord sign when writing back to the library
|
||||
VECTOR2I pos = field.GetPosition();
|
||||
pos.y = -pos.y;
|
||||
field.SetPosition( pos );
|
||||
|
||||
const wxString& fieldName = field.GetCanonicalName();
|
||||
// if( !field.IsMandatory() )
|
||||
field.SetId( ii );
|
||||
|
||||
wxString fieldName = field.GetCanonicalName();
|
||||
|
||||
if( m_fields->IsInherited( ii ) && field == m_fields->ParentField( ii ) )
|
||||
continue; // Skip inherited fields
|
||||
|
||||
if( field.GetText().IsEmpty() )
|
||||
{
|
||||
if( fieldName.IsEmpty() || m_addedTemplateFields.contains( fieldName ) )
|
||||
m_fields->erase( m_fields->begin() + ii );
|
||||
continue; // Skip empty fields that are not mandatory or template fields
|
||||
}
|
||||
else if( fieldName.IsEmpty() )
|
||||
{
|
||||
field.SetName( _( "untitled" ) );
|
||||
field.SetName( _( "untitled" ) ); // Set a default name for unnamed fields
|
||||
}
|
||||
|
||||
fieldsToSave.push_back( field );
|
||||
}
|
||||
|
||||
m_libEntry->SetFields( *m_fields );
|
||||
m_libEntry->SetFields( fieldsToSave );
|
||||
|
||||
// Update the parent for inherited symbols
|
||||
if( m_libEntry->IsAlias() )
|
||||
@@ -517,6 +575,27 @@ bool DIALOG_LIB_SYMBOL_PROPERTIES::TransferDataFromWindow()
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_LIB_SYMBOL_PROPERTIES::OnGridMotion( wxMouseEvent& aEvent )
|
||||
{
|
||||
aEvent.Skip();
|
||||
|
||||
wxPoint pos = aEvent.GetPosition();
|
||||
wxPoint unscolled_pos = m_grid->CalcUnscrolledPosition( pos );
|
||||
int row = m_grid->YToRow( unscolled_pos.y );
|
||||
int col = m_grid->XToCol( unscolled_pos.x );
|
||||
|
||||
if( row == wxNOT_FOUND || col == wxNOT_FOUND || !m_fields->IsInherited( row ) )
|
||||
{
|
||||
m_grid->SetToolTip( "" );
|
||||
return;
|
||||
}
|
||||
|
||||
m_grid->SetToolTip(
|
||||
wxString::Format( _( "This field is inherited from '%s'." ),
|
||||
m_fields->ParentField( row ).GetName() ) );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanging( wxGridEvent& event )
|
||||
{
|
||||
wxGridCellEditor* editor = m_grid->GetCellEditor( event.GetRow(), event.GetCol() );
|
||||
@@ -555,6 +634,13 @@ void DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanging( wxGridEvent& event )
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_LIB_SYMBOL_PROPERTIES::OnGridCellChanged( wxGridEvent& event )
|
||||
{
|
||||
m_grid->ForceRefresh();
|
||||
OnModify();
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_LIB_SYMBOL_PROPERTIES::OnSymbolNameText( wxCommandEvent& event )
|
||||
{
|
||||
if( m_OptionPower->IsChecked() )
|
||||
|
||||
@@ -68,6 +68,8 @@ private:
|
||||
void OnEditFootprintFilter( wxCommandEvent& event ) override;
|
||||
void OnSizeGrid( wxSizeEvent& event ) override;
|
||||
void OnGridCellChanging( wxGridEvent& event );
|
||||
void OnGridCellChanged( wxGridEvent& event );
|
||||
void OnGridMotion( wxMouseEvent& event );
|
||||
void OnEditSpiceModel( wxCommandEvent& event ) override;
|
||||
void OnUpdateUI( wxUpdateUIEvent& event ) override;
|
||||
void OnCancelButtonClick( wxCommandEvent& event ) override;
|
||||
|
||||
@@ -1003,6 +1003,7 @@ void DIALOG_SIM_COMMAND::OnFilterText( wxCommandEvent& aEvent )
|
||||
|
||||
void DIALOG_SIM_COMMAND::OnFilterMouseMoved( wxMouseEvent& aEvent )
|
||||
{
|
||||
#if defined( __WXOSX__ ) || wxCHECK_VERSION( 3, 3, 0 ) // Doesn't work properly on other ports
|
||||
wxPoint pos = aEvent.GetPosition();
|
||||
wxRect ctrlRect = m_inputSignalsFilter->GetScreenRect();
|
||||
int buttonWidth = ctrlRect.GetHeight(); // Presume buttons are square
|
||||
@@ -1014,6 +1015,7 @@ void DIALOG_SIM_COMMAND::OnFilterMouseMoved( wxMouseEvent& aEvent )
|
||||
SetCursor( wxCURSOR_ARROW );
|
||||
else
|
||||
SetCursor( wxCURSOR_IBEAM );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -88,7 +88,8 @@ DIALOG_SIM_MODEL<T>::DIALOG_SIM_MODEL( wxWindow* aParent, EDA_BASE_FRAME* aFrame
|
||||
m_filesStack.push_back( symbol->Schematic()->GetEmbeddedFiles() );
|
||||
}
|
||||
|
||||
m_filesStack.push_back( aSymbol.GetEmbeddedFiles() );
|
||||
if( EMBEDDED_FILES* symbolEmbeddedFiles = aSymbol.GetEmbeddedFiles() )
|
||||
m_filesStack.push_back( symbolEmbeddedFiles );
|
||||
|
||||
m_libraryModelsMgr.SetFilesStack( m_filesStack );
|
||||
m_builtinModelsMgr.SetFilesStack( m_filesStack );
|
||||
|
||||
@@ -878,6 +878,7 @@ void DIALOG_SYMBOL_FIELDS_TABLE::OnFilterText( wxCommandEvent& aEvent )
|
||||
|
||||
void DIALOG_SYMBOL_FIELDS_TABLE::OnFilterMouseMoved( wxMouseEvent& aEvent )
|
||||
{
|
||||
#if defined( __WXOSX__ ) || wxCHECK_VERSION( 3, 3, 0 ) // Doesn't work properly on other ports
|
||||
wxPoint pos = aEvent.GetPosition();
|
||||
wxRect ctrlRect = m_filter->GetScreenRect();
|
||||
int buttonWidth = ctrlRect.GetHeight(); // Presume buttons are square
|
||||
@@ -889,6 +890,7 @@ void DIALOG_SYMBOL_FIELDS_TABLE::OnFilterMouseMoved( wxMouseEvent& aEvent )
|
||||
SetCursor( wxCURSOR_ARROW );
|
||||
else
|
||||
SetCursor( wxCURSOR_IBEAM );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ public:
|
||||
SCH_PIN* lib_pin = pin.GetLibPin();
|
||||
wxGridCellAttr* attr = nullptr;
|
||||
|
||||
if( lib_pin->GetAlternates().empty() )
|
||||
if( !lib_pin || lib_pin->GetAlternates().empty() )
|
||||
{
|
||||
attr = new wxGridCellAttr;
|
||||
attr->SetReadOnly( true );
|
||||
@@ -177,7 +177,7 @@ public:
|
||||
{
|
||||
if( aCol == COL_ALT_NAME )
|
||||
{
|
||||
if( aPin.GetLibPin()->GetAlternates().empty() )
|
||||
if( !aPin.GetLibPin() || aPin.GetLibPin()->GetAlternates().empty() )
|
||||
return wxEmptyString;
|
||||
else if( aPin.GetAlt().IsEmpty() )
|
||||
return aPin.GetName();
|
||||
@@ -188,7 +188,7 @@ public:
|
||||
switch( aCol )
|
||||
{
|
||||
case COL_NUMBER: return aPin.GetNumber();
|
||||
case COL_BASE_NAME: return aPin.GetLibPin()->GetName();
|
||||
case COL_BASE_NAME: return aPin.GetBaseName();
|
||||
case COL_TYPE: return PinTypeNames()[static_cast<int>( aPin.GetType() )];
|
||||
case COL_SHAPE: return PinShapeNames()[static_cast<int>( aPin.GetShape() )];
|
||||
default: wxFAIL; return wxEmptyString;
|
||||
@@ -224,13 +224,15 @@ public:
|
||||
|
||||
void SetValue( int aRow, int aCol, const wxString &aValue ) override
|
||||
{
|
||||
SCH_PIN& pin = at( aRow );
|
||||
|
||||
switch( aCol )
|
||||
{
|
||||
case COL_ALT_NAME:
|
||||
if( aValue == at( aRow ).GetLibPin()->GetName() )
|
||||
at( aRow ).SetAlt( wxEmptyString );
|
||||
if( pin.GetLibPin() && aValue == pin.GetLibPin()->GetName() )
|
||||
pin.SetAlt( wxEmptyString );
|
||||
else
|
||||
at( aRow ).SetAlt( aValue );
|
||||
pin.SetAlt( aValue );
|
||||
break;
|
||||
|
||||
case COL_NUMBER:
|
||||
@@ -484,12 +486,7 @@ bool DIALOG_SYMBOL_PROPERTIES::TransferDataToWindow()
|
||||
m_symbol->SetUnit( m_symbol->GetUnitSelection( &GetParent()->GetCurrentSheet() ) );
|
||||
|
||||
for( int ii = 1; ii <= m_symbol->GetUnitCount(); ii++ )
|
||||
{
|
||||
if( m_symbol->HasUnitDisplayName( ii ) )
|
||||
m_unitChoice->Append( m_symbol->GetUnitDisplayName( ii ) );
|
||||
else
|
||||
m_unitChoice->Append( m_symbol->SubReference( ii, false ) );
|
||||
}
|
||||
m_unitChoice->Append( m_symbol->GetUnitDisplayName( ii, false ) );
|
||||
|
||||
if( m_symbol->GetUnit() <= ( int )m_unitChoice->GetCount() )
|
||||
m_unitChoice->SetSelection( m_symbol->GetUnit() - 1 );
|
||||
|
||||
@@ -131,7 +131,7 @@ void DIALOG_UPDATE_SYMBOL_FIELDS::onOkButtonClicked( wxCommandEvent& aEvent )
|
||||
wxBusyCursor dummy;
|
||||
SCH_COMMIT commit( m_editFrame );
|
||||
|
||||
commit.Modify( m_symbol );
|
||||
commit.Modify( m_symbol, m_editFrame->GetScreen() );
|
||||
|
||||
// Create the set of fields to be updated
|
||||
m_updateFields.clear();
|
||||
|
||||
+31
-39
@@ -112,28 +112,28 @@ const wxString CommentERC_V[] =
|
||||
// i.e. pin type = ELECTRICAL_PINTYPE::PT_INPUT, but not PT_POWER_IN
|
||||
// that need only a PT_POWER_OUT pin type to be driven
|
||||
const std::set<ELECTRICAL_PINTYPE> DrivingPinTypes =
|
||||
{
|
||||
ELECTRICAL_PINTYPE::PT_OUTPUT,
|
||||
ELECTRICAL_PINTYPE::PT_POWER_OUT,
|
||||
ELECTRICAL_PINTYPE::PT_PASSIVE,
|
||||
ELECTRICAL_PINTYPE::PT_TRISTATE,
|
||||
ELECTRICAL_PINTYPE::PT_BIDI
|
||||
};
|
||||
{
|
||||
ELECTRICAL_PINTYPE::PT_OUTPUT,
|
||||
ELECTRICAL_PINTYPE::PT_POWER_OUT,
|
||||
ELECTRICAL_PINTYPE::PT_PASSIVE,
|
||||
ELECTRICAL_PINTYPE::PT_TRISTATE,
|
||||
ELECTRICAL_PINTYPE::PT_BIDI
|
||||
};
|
||||
|
||||
// List of pin types that are considered drivers for power pins
|
||||
// In fact only a ELECTRICAL_PINTYPE::PT_POWER_OUT pin type can drive
|
||||
// power input pins
|
||||
const std::set<ELECTRICAL_PINTYPE> DrivingPowerPinTypes =
|
||||
{
|
||||
ELECTRICAL_PINTYPE::PT_POWER_OUT
|
||||
};
|
||||
{
|
||||
ELECTRICAL_PINTYPE::PT_POWER_OUT
|
||||
};
|
||||
|
||||
// List of pin types that require a driver elsewhere on the net
|
||||
const std::set<ELECTRICAL_PINTYPE> DrivenPinTypes =
|
||||
{
|
||||
ELECTRICAL_PINTYPE::PT_INPUT,
|
||||
ELECTRICAL_PINTYPE::PT_POWER_IN
|
||||
};
|
||||
{
|
||||
ELECTRICAL_PINTYPE::PT_INPUT,
|
||||
ELECTRICAL_PINTYPE::PT_POWER_IN
|
||||
};
|
||||
|
||||
extern void CheckDuplicatePins( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
|
||||
UNITS_PROVIDER* aUnitsProvider );
|
||||
@@ -574,11 +574,11 @@ int ERC_TESTER::TestMissingUnits()
|
||||
{
|
||||
if( ii++ == 3 )
|
||||
{
|
||||
missing_pin_units += wxS( "....." );
|
||||
missing_pin_units += wxS( "..." );
|
||||
break;
|
||||
}
|
||||
|
||||
missing_pin_units += libSymbol->GetUnitDisplayName( missing_unit ) + ", " ;
|
||||
missing_pin_units += libSymbol->GetUnitDisplayName( missing_unit, false ) + ", " ;
|
||||
}
|
||||
|
||||
missing_pin_units.Truncate( missing_pin_units.length() - 2 );
|
||||
@@ -692,8 +692,7 @@ int ERC_TESTER::TestMissingNetclasses()
|
||||
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_UNDEFINED_NETCLASS );
|
||||
|
||||
ercItem->SetItems( item );
|
||||
ercItem->SetErrorMessage( wxString::Format( _( "Netclass %s is not defined" ),
|
||||
netclass ) );
|
||||
ercItem->SetErrorMessage( wxString::Format( _( "Netclass %s is not defined" ), netclass ) );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, item->GetPosition() );
|
||||
sheet.LastScreen()->Append( marker );
|
||||
@@ -886,7 +885,7 @@ int ERC_TESTER::TestNoConnectPins()
|
||||
|
||||
for( SCH_PIN* pin : symbol->GetPins( &sheet ) )
|
||||
{
|
||||
if( pin->GetLibPin()->GetType() == ELECTRICAL_PINTYPE::PT_NC )
|
||||
if( pin->GetType() == ELECTRICAL_PINTYPE::PT_NC )
|
||||
pinMap[pin->GetPosition()].emplace_back( pin );
|
||||
}
|
||||
}
|
||||
@@ -899,7 +898,7 @@ int ERC_TESTER::TestNoConnectPins()
|
||||
|
||||
for( SCH_PIN* pin : symbol->GetPins( &sheet ) )
|
||||
{
|
||||
if( pin->GetLibPin()->GetType() != ELECTRICAL_PINTYPE::PT_NC )
|
||||
if( pin->GetType() != ELECTRICAL_PINTYPE::PT_NC )
|
||||
addOther( pin->GetPosition(), pin );
|
||||
}
|
||||
}
|
||||
@@ -1042,16 +1041,12 @@ int ERC_TESTER::TestPinToPin()
|
||||
|
||||
if( erc != PIN_ERROR::OK && m_settings.IsTestEnabled( ERCE_PIN_TO_PIN_WARNING ) )
|
||||
{
|
||||
pin_mismatches.emplace_back(
|
||||
std::tuple<iterator_t, iterator_t, PIN_ERROR>{ refIt, testIt, erc } );
|
||||
pin_mismatches.emplace_back( std::tuple<iterator_t, iterator_t, PIN_ERROR>{ refIt, testIt, erc } );
|
||||
|
||||
if( m_settings.GetERCSortingMetric() == ERC_PIN_SORTING_METRIC::SM_HEURISTICS )
|
||||
{
|
||||
pin_mismatch_counts[refIt] =
|
||||
m_settings.GetPinTypeWeight( ( *refIt ).Pin()->GetType() );
|
||||
|
||||
pin_mismatch_counts[testIt] =
|
||||
m_settings.GetPinTypeWeight( ( *testIt ).Pin()->GetType() );
|
||||
pin_mismatch_counts[refIt] = m_settings.GetPinTypeWeight( ( *refIt ).Pin()->GetType() );
|
||||
pin_mismatch_counts[testIt] = m_settings.GetPinTypeWeight( ( *testIt ).Pin()->GetType() );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1132,17 +1127,15 @@ int ERC_TESTER::TestPinToPin()
|
||||
{
|
||||
SCH_PIN* other_pin = ( *nearest_pin ).Pin();
|
||||
|
||||
std::shared_ptr<ERC_ITEM> ercItem =
|
||||
ERC_ITEM::Create( erc == PIN_ERROR::WARNING ? ERCE_PIN_TO_PIN_WARNING
|
||||
: ERCE_PIN_TO_PIN_ERROR );
|
||||
auto ercItem = ERC_ITEM::Create( erc == PIN_ERROR::WARNING ? ERCE_PIN_TO_PIN_WARNING
|
||||
: ERCE_PIN_TO_PIN_ERROR );
|
||||
ercItem->SetItems( pin, other_pin );
|
||||
ercItem->SetSheetSpecificPath( ( *pinIt ).Sheet() );
|
||||
ercItem->SetItemsSheetPaths( ( *pinIt ).Sheet(), ( *nearest_pin ).Sheet() );
|
||||
|
||||
ercItem->SetErrorMessage(
|
||||
wxString::Format( _( "Pins of type %s and %s are connected" ),
|
||||
ElectricalPinTypeGetText( pin->GetType() ),
|
||||
ElectricalPinTypeGetText( other_pin->GetType() ) ) );
|
||||
ercItem->SetErrorMessage( wxString::Format( _( "Pins of type %s and %s are connected" ),
|
||||
ElectricalPinTypeGetText( pin->GetType() ),
|
||||
ElectricalPinTypeGetText( other_pin->GetType() ) ) );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, pin->GetPosition() );
|
||||
pinToScreenMap[pin]->Append( marker );
|
||||
@@ -1162,7 +1155,7 @@ int ERC_TESTER::TestPinToPin()
|
||||
ercItem->SetSheetSpecificPath( needsDriver.Sheet() );
|
||||
ercItem->SetItemsSheetPaths( needsDriver.Sheet() );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, needsDriver.Pin()->GetPosition() );
|
||||
SCH_MARKER* marker = new SCH_MARKER( std::move( ercItem ), needsDriver.Pin()->GetPosition() );
|
||||
pinToScreenMap[needsDriver.Pin()]->Append( marker );
|
||||
errors++;
|
||||
}
|
||||
@@ -1195,8 +1188,7 @@ int ERC_TESTER::TestMultUnitPinConflicts()
|
||||
if( !pin->GetLibPin()->GetParentSymbol()->IsMulti() )
|
||||
continue;
|
||||
|
||||
wxString name = pin->GetParentSymbol()->GetRef( &sheet ) +
|
||||
+ ":" + pin->GetShownNumber();
|
||||
wxString name = pin->GetParentSymbol()->GetRef( &sheet ) + ":" + pin->GetShownNumber();
|
||||
|
||||
if( !pinToNetMap.count( name ) )
|
||||
{
|
||||
@@ -1273,7 +1265,7 @@ int ERC_TESTER::TestSameLocalGlobalLabel()
|
||||
ercItem->SetSheetSpecificPath( globalItem.second );
|
||||
ercItem->SetItemsSheetPaths( globalItem.second, localItem.second );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, globalItem.first->GetPosition() );
|
||||
SCH_MARKER* marker = new SCH_MARKER( std::move( ercItem ), globalItem.first->GetPosition() );
|
||||
globalItem.second.LastScreen()->Append( marker );
|
||||
|
||||
errCount++;
|
||||
@@ -1670,7 +1662,7 @@ int ERC_TESTER::TestFootprintFilters()
|
||||
wxJoin( filters, ' ' ) );
|
||||
ercItem->SetErrorMessage( msg );
|
||||
ercItem->SetItems( sch_symbol );
|
||||
markers.emplace_back( new SCH_MARKER( ercItem, sch_symbol->GetPosition() ) );
|
||||
markers.emplace_back( new SCH_MARKER( std::move( ercItem ), sch_symbol->GetPosition() ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <erc/erc_item.h>
|
||||
#include <erc/erc_settings.h>
|
||||
#include <schematic.h>
|
||||
@@ -397,6 +398,13 @@ void SHEETLIST_ERC_ITEMS_PROVIDER::SetSeverities( int aSeverities )
|
||||
if( markerSeverity & m_severities )
|
||||
m_filteredMarkers.push_back( aMarker );
|
||||
} );
|
||||
|
||||
// Sort markers so that errors appear before warnings
|
||||
std::stable_sort( m_filteredMarkers.begin(), m_filteredMarkers.end(),
|
||||
[]( const SCH_MARKER* a, const SCH_MARKER* b )
|
||||
{
|
||||
return a->GetSeverity() > b->GetSeverity();
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
|
||||
+136
-36
@@ -45,8 +45,10 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::AddColumn( const wxString& aFieldName, const
|
||||
|
||||
for( unsigned i = 0; i < m_symbolsList.GetCount(); ++i )
|
||||
{
|
||||
if( SCH_SYMBOL* symbol = m_symbolsList[i].GetSymbol() )
|
||||
updateDataStoreSymbolField( *symbol, aFieldName );
|
||||
const SCH_REFERENCE& ref = m_symbolsList[i];
|
||||
|
||||
if( SCH_SYMBOL* symbol = ref.GetSymbol() )
|
||||
updateDataStoreSymbolField( *symbol, aFieldName, &ref.GetSheetPath() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,30 +56,54 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::AddColumn( const wxString& aFieldName, const
|
||||
void FIELDS_EDITOR_GRID_DATA_MODEL::updateDataStoreSymbolField( const SCH_SYMBOL& aSymbol,
|
||||
const wxString& aFieldName )
|
||||
{
|
||||
// Call the overloaded version with nullptr for sheet path (will use current sheet)
|
||||
updateDataStoreSymbolField( aSymbol, aFieldName, nullptr );
|
||||
}
|
||||
|
||||
|
||||
void FIELDS_EDITOR_GRID_DATA_MODEL::updateDataStoreSymbolField( const SCH_SYMBOL& aSymbol,
|
||||
const wxString& aFieldName,
|
||||
const SCH_SHEET_PATH* aSheetPath )
|
||||
{
|
||||
// Get the sheet path - use the one provided or fall back to m_path
|
||||
const SCH_SHEET_PATH& sheetPath = aSheetPath ? *aSheetPath : m_path;
|
||||
KIID_PATH key = makeDataStoreKey( sheetPath, aSymbol );
|
||||
|
||||
if( isAttribute( aFieldName ) )
|
||||
{
|
||||
m_dataStore[aSymbol.m_Uuid][aFieldName] = getAttributeValue( aSymbol, aFieldName );
|
||||
m_dataStore[key][aFieldName] = getAttributeValue( aSymbol, aFieldName );
|
||||
}
|
||||
else if( const SCH_FIELD* field = aSymbol.GetFieldByName( aFieldName ) )
|
||||
{
|
||||
if( field->IsPrivate() )
|
||||
{
|
||||
m_dataStore[aSymbol.m_Uuid][aFieldName] = wxEmptyString;
|
||||
m_dataStore[key][aFieldName] = wxEmptyString;
|
||||
return;
|
||||
}
|
||||
|
||||
wxString value = aSymbol.Schematic()->ConvertKIIDsToRefs( field->GetText() );
|
||||
m_dataStore[aSymbol.m_Uuid][aFieldName] = value;
|
||||
// Use GetShownText() instead of GetText() to get the properly resolved value
|
||||
// that includes text variable resolution and inherited library symbol values.
|
||||
// This ensures BOM exports show the correct value that users see in the schematic.
|
||||
wxString getText = field->GetText();
|
||||
wxString getShownText = field->GetShownText( aSheetPath, false );
|
||||
wxString value = aSymbol.Schematic()->ConvertKIIDsToRefs( getShownText );
|
||||
|
||||
wxLogTrace( "KICAD_FIELDS",
|
||||
"Fields Table updateDataStore: Symbol %s, Field %s: GetText()='%s', "
|
||||
"GetShownText()='%s', final='%s'",
|
||||
aSymbol.GetRef( aSheetPath ), aFieldName, getText, getShownText, value );
|
||||
|
||||
m_dataStore[key][aFieldName] = value;
|
||||
}
|
||||
else if( IsGeneratedField( aFieldName ) )
|
||||
{
|
||||
// Handle generated fields with variables as names (e.g. ${QUANTITY}) that are not present in
|
||||
// the symbol by giving them the correct value
|
||||
m_dataStore[aSymbol.m_Uuid][aFieldName] = aFieldName;
|
||||
m_dataStore[key][aFieldName] = aFieldName;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dataStore[aSymbol.m_Uuid][aFieldName] = wxEmptyString;
|
||||
m_dataStore[key][aFieldName] = wxEmptyString;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,8 +112,13 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::RemoveColumn( int aCol )
|
||||
{
|
||||
for( unsigned i = 0; i < m_symbolsList.GetCount(); ++i )
|
||||
{
|
||||
if( SCH_SYMBOL* symbol = m_symbolsList[i].GetSymbol() )
|
||||
m_dataStore[symbol->m_Uuid].erase( m_cols[aCol].m_fieldName );
|
||||
const SCH_REFERENCE& ref = m_symbolsList[i];
|
||||
|
||||
if( SCH_SYMBOL* symbol = ref.GetSymbol() )
|
||||
{
|
||||
KIID_PATH key = makeDataStoreKey( ref );
|
||||
m_dataStore[key].erase( m_cols[aCol].m_fieldName );
|
||||
}
|
||||
}
|
||||
|
||||
m_cols.erase( m_cols.begin() + aCol );
|
||||
@@ -98,13 +129,14 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::RenameColumn( int aCol, const wxString& newN
|
||||
{
|
||||
for( unsigned i = 0; i < m_symbolsList.GetCount(); ++i )
|
||||
{
|
||||
SCH_SYMBOL* symbol = m_symbolsList[i].GetSymbol();
|
||||
const SCH_REFERENCE& ref = m_symbolsList[i];
|
||||
KIID_PATH key = makeDataStoreKey( ref );
|
||||
|
||||
// Careful; field may have already been renamed from another sheet instance
|
||||
if( auto node = m_dataStore[symbol->m_Uuid].extract( m_cols[aCol].m_fieldName ) )
|
||||
if( auto node = m_dataStore[key].extract( m_cols[aCol].m_fieldName ) )
|
||||
{
|
||||
node.key() = newName;
|
||||
m_dataStore[symbol->m_Uuid].insert( std::move( node ) );
|
||||
m_dataStore[key].insert( std::move( node ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,15 +252,20 @@ wxString FIELDS_EDITOR_GRID_DATA_MODEL::GetValue( const DATA_MODEL_ROW& group, i
|
||||
}
|
||||
else // Other columns are either a single value or ROW_MULTI_ITEMS
|
||||
{
|
||||
const KIID& symbolID = ref.GetSymbol()->m_Uuid;
|
||||
KIID_PATH key = makeDataStoreKey( ref );
|
||||
|
||||
if( !m_dataStore.count( symbolID )
|
||||
|| !m_dataStore[symbolID].count( m_cols[aCol].m_fieldName ) )
|
||||
if( !m_dataStore.count( key )
|
||||
|| !m_dataStore[key].count( m_cols[aCol].m_fieldName ) )
|
||||
{
|
||||
return INDETERMINATE_STATE;
|
||||
}
|
||||
|
||||
wxString refFieldValue = m_dataStore[symbolID][m_cols[aCol].m_fieldName];
|
||||
wxString refFieldValue = m_dataStore[key][m_cols[aCol].m_fieldName];
|
||||
|
||||
wxLogTrace( "KICAD_FIELDS",
|
||||
"GetValue: Symbol %s (UUID %s, Path %s), Field %s = '%s' (from m_dataStore)",
|
||||
ref.GetRef(), ref.GetSymbol()->m_Uuid.AsString(),
|
||||
ref.GetSheetPath().PathAsString(), m_cols[aCol].m_fieldName, refFieldValue );
|
||||
|
||||
if( resolveVars )
|
||||
{
|
||||
@@ -310,6 +347,10 @@ wxString FIELDS_EDITOR_GRID_DATA_MODEL::GetValue( const DATA_MODEL_ROW& group, i
|
||||
else if( ColIsItemNumber( aCol ) && group.m_Flag != CHILD_ITEM )
|
||||
fieldValue = wxString::Format( wxT( "%d" ), group.m_ItemNumber );
|
||||
|
||||
wxLogTrace( "KICAD_FIELDS",
|
||||
"GetValue returning: Col %d (%s), Group refs=%zu, Final Value = '%s'",
|
||||
aCol, m_cols[aCol].m_fieldName, group.m_Refs.size(), fieldValue );
|
||||
|
||||
return fieldValue;
|
||||
}
|
||||
|
||||
@@ -327,8 +368,45 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::SetValue( int aRow, int aCol, const wxString
|
||||
|
||||
DATA_MODEL_ROW& rowGroup = m_rows[aRow];
|
||||
|
||||
const SCH_SYMBOL* sharedSymbol = nullptr;
|
||||
bool isSharedInstance = false;
|
||||
|
||||
for( const SCH_REFERENCE& ref : rowGroup.m_Refs )
|
||||
m_dataStore[ref.GetSymbol()->m_Uuid][m_cols[aCol].m_fieldName] = aValue;
|
||||
{
|
||||
const SCH_SCREEN* screen = nullptr;
|
||||
|
||||
// Check to see if the symbol associated with this row has more than one instance.
|
||||
if( const SCH_SYMBOL* symbol = ref.GetSymbol() )
|
||||
{
|
||||
screen = static_cast<const SCH_SCREEN*>( symbol->GetParent() );
|
||||
|
||||
isSharedInstance = ( screen && ( screen->GetRefCount() > 1 ) );
|
||||
sharedSymbol = symbol;
|
||||
}
|
||||
|
||||
KIID_PATH key = makeDataStoreKey( ref.GetSheetPath(), *ref.GetSymbol() );
|
||||
m_dataStore[key][m_cols[aCol].m_fieldName] = aValue;
|
||||
}
|
||||
|
||||
// Update all of the other instances for the shared symbol as required.
|
||||
if( isSharedInstance
|
||||
&& ( ( rowGroup.m_Flag == GROUP_SINGLETON ) || ( rowGroup.m_Flag == CHILD_ITEM ) ) )
|
||||
{
|
||||
for( DATA_MODEL_ROW& row : m_rows )
|
||||
{
|
||||
if( row.m_ItemNumber == aRow + 1 )
|
||||
continue;
|
||||
|
||||
for( const SCH_REFERENCE& ref : row.m_Refs )
|
||||
{
|
||||
if( ref.GetSymbol() != sharedSymbol )
|
||||
continue;
|
||||
|
||||
KIID_PATH key = makeDataStoreKey( ref.GetSheetPath(), *ref.GetSymbol() );
|
||||
m_dataStore[key][m_cols[aCol].m_fieldName] = aValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_edited = true;
|
||||
}
|
||||
@@ -436,6 +514,7 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::Sort()
|
||||
|
||||
// Time to renumber the item numbers
|
||||
int itemNumber = 1;
|
||||
|
||||
for( DATA_MODEL_ROW& row : m_rows )
|
||||
{
|
||||
row.m_ItemNumber = itemNumber++;
|
||||
@@ -477,8 +556,8 @@ bool FIELDS_EDITOR_GRID_DATA_MODEL::groupMatch( const SCH_REFERENCE& lhRef,
|
||||
matchFound = true;
|
||||
}
|
||||
|
||||
const KIID& lhRefID = lhRef.GetSymbol()->m_Uuid;
|
||||
const KIID& rhRefID = rhRef.GetSymbol()->m_Uuid;
|
||||
KIID_PATH lhKey = makeDataStoreKey( lhRef );
|
||||
KIID_PATH rhKey = makeDataStoreKey( rhRef );
|
||||
|
||||
// Now check all the other columns.
|
||||
for( size_t i = 0; i < m_cols.size(); ++i )
|
||||
@@ -496,23 +575,23 @@ bool FIELDS_EDITOR_GRID_DATA_MODEL::groupMatch( const SCH_REFERENCE& lhRef,
|
||||
wxString lh, rh;
|
||||
|
||||
if( IsGeneratedField( m_cols[i].m_fieldName )
|
||||
|| IsGeneratedField( m_dataStore[lhRefID][m_cols[i].m_fieldName] ) )
|
||||
|| IsGeneratedField( m_dataStore[lhKey][m_cols[i].m_fieldName] ) )
|
||||
{
|
||||
lh = getFieldShownText( lhRef, m_cols[i].m_fieldName );
|
||||
}
|
||||
else
|
||||
{
|
||||
lh = m_dataStore[lhRefID][m_cols[i].m_fieldName];
|
||||
lh = m_dataStore[lhKey][m_cols[i].m_fieldName];
|
||||
}
|
||||
|
||||
if( IsGeneratedField( m_cols[i].m_fieldName )
|
||||
|| IsGeneratedField( m_dataStore[rhRefID][m_cols[i].m_fieldName] ) )
|
||||
|| IsGeneratedField( m_dataStore[rhKey][m_cols[i].m_fieldName] ) )
|
||||
{
|
||||
rh = getFieldShownText( rhRef, m_cols[i].m_fieldName );
|
||||
}
|
||||
else
|
||||
{
|
||||
rh = m_dataStore[rhRefID][m_cols[i].m_fieldName];
|
||||
rh = m_dataStore[rhKey][m_cols[i].m_fieldName];
|
||||
}
|
||||
|
||||
wxString fieldName = m_cols[i].m_fieldName;
|
||||
@@ -805,11 +884,13 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::ApplyData( SCH_COMMIT& aCommit, TEMPLATES& a
|
||||
{
|
||||
for( unsigned i = 0; i < m_symbolsList.GetCount(); ++i )
|
||||
{
|
||||
SCH_SYMBOL& symbol = *m_symbolsList[i].GetSymbol();
|
||||
const SCH_REFERENCE& ref = m_symbolsList[i];
|
||||
SCH_SYMBOL& symbol = *ref.GetSymbol();
|
||||
|
||||
aCommit.Modify( &symbol, m_symbolsList[i].GetSheetPath().LastScreen() );
|
||||
aCommit.Modify( &symbol, ref.GetSheetPath().LastScreen() );
|
||||
|
||||
const std::map<wxString, wxString>& fieldStore = m_dataStore[symbol.m_Uuid];
|
||||
KIID_PATH key = makeDataStoreKey( ref );
|
||||
const std::map<wxString, wxString>& fieldStore = m_dataStore[key];
|
||||
|
||||
for( const auto& [srcName, srcValue] : fieldStore )
|
||||
{
|
||||
@@ -894,8 +975,8 @@ int FIELDS_EDITOR_GRID_DATA_MODEL::GetDataWidth( int aCol )
|
||||
|
||||
for( unsigned symbolRef = 0; symbolRef < m_symbolsList.GetCount(); ++symbolRef )
|
||||
{
|
||||
const KIID& symbolID = m_symbolsList[symbolRef].GetSymbol()->m_Uuid;
|
||||
wxString text = m_dataStore[symbolID][fieldName];
|
||||
KIID_PATH key = makeDataStoreKey( m_symbolsList[symbolRef] );
|
||||
wxString text = m_dataStore[key][fieldName];
|
||||
|
||||
width = std::max( width, KIUI::GetTextSize( text, GetView() ).x );
|
||||
}
|
||||
@@ -1077,9 +1158,14 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::AddReferences( const SCH_REFERENCE_LIST& aRe
|
||||
if( !field.IsPrivate() )
|
||||
{
|
||||
wxString name = field.GetCanonicalName();
|
||||
wxString value = symbol->Schematic()->ConvertKIIDsToRefs( field.GetText() );
|
||||
// Use GetShownText() instead of GetText() to get the properly resolved value
|
||||
// that includes text variable resolution and inherited library symbol values.
|
||||
// This ensures BOM exports show the correct value that users see in the schematic.
|
||||
wxString value = symbol->Schematic()->ConvertKIIDsToRefs(
|
||||
field.GetShownText( &ref.GetSheetPath(), false ) );
|
||||
|
||||
m_dataStore[symbol->m_Uuid][name] = value;
|
||||
KIID_PATH key = makeDataStoreKey( ref );
|
||||
m_dataStore[key][name] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1092,7 +1178,21 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::RemoveSymbol( const SCH_SYMBOL& aSymbol )
|
||||
// The schematic event listener passes us the symbol after it has been removed,
|
||||
// so we can't just work with a SCH_REFERENCE_LIST like the other handlers as the
|
||||
// references are already gone. Instead we need to prune our list.
|
||||
m_dataStore[aSymbol.m_Uuid].clear();
|
||||
// We need to remove all instances of this symbol from all sheet paths.
|
||||
|
||||
auto it = m_dataStore.begin();
|
||||
|
||||
while( it != m_dataStore.end() )
|
||||
{
|
||||
// The key is a KIID_PATH string; check if it ends with this symbol's UUID
|
||||
// by checking if the key ends with "/" + UUID
|
||||
wxString symbolUuidStr = "/" + aSymbol.m_Uuid.AsString();
|
||||
|
||||
if( it->first.EndsWith( symbolUuidStr ) )
|
||||
it = m_dataStore.erase( it );
|
||||
else
|
||||
++it;
|
||||
}
|
||||
|
||||
// Remove all refs that match this symbol using remove_if
|
||||
m_symbolsList.erase( std::remove_if( m_symbolsList.begin(), m_symbolsList.end(),
|
||||
@@ -1114,9 +1214,9 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::RemoveReferences( const SCH_REFERENCE_LIST&
|
||||
{
|
||||
m_symbolsList.RemoveItem( index );
|
||||
|
||||
// If we're out of instances then remove the symbol, too
|
||||
if( ref.GetSymbol()->GetInstances().empty() )
|
||||
m_dataStore.erase( ref.GetSymbol()->m_Uuid );
|
||||
// Remove this specific instance from the data store
|
||||
KIID_PATH key = makeDataStoreKey( ref );
|
||||
m_dataStore.erase( key );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1130,7 +1230,7 @@ void FIELDS_EDITOR_GRID_DATA_MODEL::UpdateReferences( const SCH_REFERENCE_LIST&
|
||||
// columns; we must have all fields in the symbol added to the data model at this point,
|
||||
// and some of the data model columns may be variables that are not present in the symbol
|
||||
for( const DATA_MODEL_COL& col : m_cols )
|
||||
updateDataStoreSymbolField( *ref.GetSymbol(), col.m_fieldName );
|
||||
updateDataStoreSymbolField( *ref.GetSymbol(), col.m_fieldName, &ref.GetSheetPath() );
|
||||
|
||||
if( !m_symbolsList.Contains( ref ) )
|
||||
m_symbolsList.AddItem( ref );
|
||||
|
||||
@@ -302,11 +302,32 @@ private:
|
||||
* Example: BOM template provides ${DNP} as a field, but they symbol doesn't have the field. */
|
||||
wxString getFieldShownText( const SCH_REFERENCE& aRef, const wxString& aFieldName );
|
||||
|
||||
/**
|
||||
* Create a composite key for the data store using sheet path and symbol UUID.
|
||||
* This is necessary for hierarchical designs where the same symbol (same UUID)
|
||||
* is instantiated in multiple sheets with different field values.
|
||||
*
|
||||
* The key is a string representation of the full KIID_PATH including the symbol's UUID.
|
||||
*/
|
||||
KIID_PATH makeDataStoreKey( const SCH_SHEET_PATH& aSheetPath, const SCH_SYMBOL& aSymbol ) const
|
||||
{
|
||||
KIID_PATH path = aSheetPath.Path();
|
||||
path.push_back( aSymbol.m_Uuid );
|
||||
return path;
|
||||
}
|
||||
|
||||
KIID_PATH makeDataStoreKey( const SCH_REFERENCE& aRef ) const
|
||||
{
|
||||
return makeDataStoreKey( aRef.GetSheetPath(), *aRef.GetSymbol() );
|
||||
}
|
||||
|
||||
void Sort();
|
||||
|
||||
SCH_REFERENCE_LIST getSymbolReferences( SCH_SYMBOL* aSymbol );
|
||||
void storeReferenceFields( SCH_REFERENCE& aRef );
|
||||
void updateDataStoreSymbolField( const SCH_SYMBOL& aSymbol, const wxString& aFieldName );
|
||||
void updateDataStoreSymbolField( const SCH_SYMBOL& aSymbol, const wxString& aFieldName,
|
||||
const SCH_SHEET_PATH* aSheetPath );
|
||||
|
||||
protected:
|
||||
SCH_REFERENCE_LIST m_symbolsList;
|
||||
@@ -329,6 +350,8 @@ protected:
|
||||
|
||||
// Data store
|
||||
// The data model is fundamentally m_componentRefs X m_fieldNames.
|
||||
// A map of compID : fieldSet, where fieldSet is a map of fieldName : fieldValue
|
||||
std::map<KIID, std::map<wxString, wxString>> m_dataStore;
|
||||
// For hierarchical designs, symbols can be instantiated in multiple sheets with the same UUID,
|
||||
// so we use a composite key containing the full KIID_PATH (sheet path + symbol UUID).
|
||||
// This ensures each hierarchical instance maintains its own distinct field values.
|
||||
std::map<KIID_PATH, std::map<wxString, wxString>> m_dataStore;
|
||||
};
|
||||
|
||||
+144
-24
@@ -225,6 +225,15 @@ int FIELDS_GRID_TABLE::GetMandatoryRowCount() const
|
||||
}
|
||||
|
||||
|
||||
void FIELDS_GRID_TABLE::push_back( const SCH_FIELD& aField )
|
||||
{
|
||||
std::vector<SCH_FIELD>::push_back( aField );
|
||||
|
||||
m_isInherited.resize( size() );
|
||||
m_parentFields.resize( size() );
|
||||
}
|
||||
|
||||
|
||||
void FIELDS_GRID_TABLE::initGrid( WX_GRID* aGrid )
|
||||
{
|
||||
// Build the various grid cell attributes.
|
||||
@@ -399,6 +408,9 @@ FIELDS_GRID_TABLE::~FIELDS_GRID_TABLE()
|
||||
m_fontAttr->DecRef();
|
||||
m_colorAttr->DecRef();
|
||||
|
||||
for( SCH_FIELD& field : m_parentFields )
|
||||
field.SetParent( nullptr );
|
||||
|
||||
m_frame->Unbind( EDA_EVT_UNITS_CHANGED, &FIELDS_GRID_TABLE::onUnitsChanged, this );
|
||||
}
|
||||
|
||||
@@ -538,33 +550,34 @@ wxGridCellAttr* FIELDS_GRID_TABLE::GetAttr( int aRow, int aCol, wxGridCellAttr::
|
||||
wxCHECK( aRow < GetNumberRows(), nullptr );
|
||||
|
||||
const SCH_FIELD& field = getField( aRow );
|
||||
wxGridCellAttr* tmp;
|
||||
wxGridCellAttr* attr = nullptr;
|
||||
|
||||
switch( aCol )
|
||||
{
|
||||
case FDC_NAME:
|
||||
if( field.IsMandatory() )
|
||||
{
|
||||
tmp = m_fieldNameAttr->Clone();
|
||||
tmp->SetReadOnly( true );
|
||||
return enhanceAttr( tmp, aRow, aCol, aKind );
|
||||
attr = m_fieldNameAttr->Clone();
|
||||
attr->SetReadOnly( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fieldNameAttr->IncRef();
|
||||
return enhanceAttr( m_fieldNameAttr, aRow, aCol, aKind );
|
||||
attr = m_fieldNameAttr;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case FDC_VALUE:
|
||||
if( m_parentType == SCH_SYMBOL_T && field.GetId() == REFERENCE_FIELD )
|
||||
{
|
||||
m_referenceAttr->IncRef();
|
||||
return enhanceAttr( m_referenceAttr, aRow, aCol, aKind );
|
||||
attr = m_referenceAttr;
|
||||
}
|
||||
else if( m_parentType == SCH_SYMBOL_T && field.GetId() == VALUE_FIELD )
|
||||
{
|
||||
m_valueAttr->IncRef();
|
||||
return enhanceAttr( m_valueAttr, aRow, aCol, aKind );
|
||||
attr = m_valueAttr;
|
||||
}
|
||||
else if( m_parentType == SCH_SYMBOL_T && field.GetId() == FOOTPRINT_FIELD )
|
||||
{
|
||||
@@ -574,34 +587,34 @@ wxGridCellAttr* FIELDS_GRID_TABLE::GetAttr( int aRow, int aCol, wxGridCellAttr::
|
||||
if( m_part && m_part->IsPower() )
|
||||
{
|
||||
m_readOnlyAttr->IncRef();
|
||||
return enhanceAttr( m_readOnlyAttr, aRow, aCol, aKind );
|
||||
attr = m_readOnlyAttr;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_footprintAttr->IncRef();
|
||||
return enhanceAttr( m_footprintAttr, aRow, aCol, aKind );
|
||||
attr = m_footprintAttr;
|
||||
}
|
||||
}
|
||||
else if( m_parentType == SCH_SYMBOL_T && field.GetId() == DATASHEET_FIELD )
|
||||
{
|
||||
m_urlAttr->IncRef();
|
||||
return enhanceAttr( m_urlAttr, aRow, aCol, aKind );
|
||||
attr = m_urlAttr;
|
||||
}
|
||||
else if( m_parentType == SCH_SHEET_T && field.GetId() == SHEETNAME )
|
||||
{
|
||||
m_referenceAttr->IncRef();
|
||||
return enhanceAttr( m_referenceAttr, aRow, aCol, aKind );
|
||||
attr = m_referenceAttr;
|
||||
}
|
||||
else if( m_parentType == SCH_SHEET_T && field.GetId() == SHEETFILENAME )
|
||||
{
|
||||
m_filepathAttr->IncRef();
|
||||
return enhanceAttr( m_filepathAttr, aRow, aCol, aKind );
|
||||
attr = m_filepathAttr;
|
||||
}
|
||||
else if( ( m_parentType == SCH_LABEL_LOCATE_ANY_T )
|
||||
&& field.GetCanonicalName() == wxT( "Netclass" ) )
|
||||
{
|
||||
m_netclassAttr->IncRef();
|
||||
return enhanceAttr( m_netclassAttr, aRow, aCol, aKind );
|
||||
attr = m_netclassAttr;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -615,31 +628,36 @@ wxGridCellAttr* FIELDS_GRID_TABLE::GetAttr( int aRow, int aCol, wxGridCellAttr::
|
||||
if( ( templateFn && templateFn->m_URL ) || field.IsHypertext() )
|
||||
{
|
||||
m_urlAttr->IncRef();
|
||||
return enhanceAttr( m_urlAttr, aRow, aCol, aKind );
|
||||
attr = m_urlAttr;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_nonUrlAttr->IncRef();
|
||||
return enhanceAttr( m_nonUrlAttr, aRow, aCol, aKind );
|
||||
attr = m_nonUrlAttr;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case FDC_TEXT_SIZE:
|
||||
case FDC_POSX:
|
||||
case FDC_POSY:
|
||||
return enhanceAttr( nullptr, aRow, aCol, aKind );
|
||||
break;
|
||||
|
||||
case FDC_H_ALIGN:
|
||||
m_hAlignAttr->IncRef();
|
||||
return enhanceAttr( m_hAlignAttr, aRow, aCol, aKind );
|
||||
attr = m_hAlignAttr;
|
||||
break;
|
||||
|
||||
case FDC_V_ALIGN:
|
||||
m_vAlignAttr->IncRef();
|
||||
return enhanceAttr( m_vAlignAttr, aRow, aCol, aKind );
|
||||
attr = m_vAlignAttr;
|
||||
break;
|
||||
|
||||
case FDC_ORIENTATION:
|
||||
m_orientationAttr->IncRef();
|
||||
return enhanceAttr( m_orientationAttr, aRow, aCol, aKind );
|
||||
attr = m_orientationAttr;
|
||||
break;
|
||||
|
||||
case FDC_SHOWN:
|
||||
case FDC_SHOW_NAME:
|
||||
@@ -648,20 +666,50 @@ wxGridCellAttr* FIELDS_GRID_TABLE::GetAttr( int aRow, int aCol, wxGridCellAttr::
|
||||
case FDC_ALLOW_AUTOPLACE:
|
||||
case FDC_PRIVATE:
|
||||
m_boolAttr->IncRef();
|
||||
return enhanceAttr( m_boolAttr, aRow, aCol, aKind );
|
||||
attr = m_boolAttr;
|
||||
break;
|
||||
|
||||
case FDC_FONT:
|
||||
m_fontAttr->IncRef();
|
||||
return enhanceAttr( m_fontAttr, aRow, aCol, aKind );
|
||||
attr = m_fontAttr;
|
||||
break;
|
||||
|
||||
case FDC_COLOR:
|
||||
m_colorAttr->IncRef();
|
||||
return enhanceAttr( m_colorAttr, aRow, aCol, aKind );
|
||||
attr = m_colorAttr;
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL;
|
||||
return enhanceAttr( nullptr, aRow, aCol, aKind );
|
||||
attr = nullptr;
|
||||
break;
|
||||
}
|
||||
|
||||
if( !attr )
|
||||
return nullptr;
|
||||
|
||||
attr = enhanceAttr( attr, aRow, aCol, aKind );
|
||||
|
||||
if( IsInherited( aRow ) )
|
||||
{
|
||||
wxGridCellAttr* text_attr = attr ? attr->Clone() : new wxGridCellAttr;
|
||||
wxFont font;
|
||||
|
||||
if( !text_attr->HasFont() )
|
||||
font = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
|
||||
else
|
||||
font = text_attr->GetFont();
|
||||
|
||||
font.MakeItalic();
|
||||
text_attr->SetFont( font );
|
||||
text_attr->SetTextColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
|
||||
|
||||
if( attr )
|
||||
attr->DecRef();
|
||||
|
||||
attr = text_attr;
|
||||
}
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
|
||||
@@ -1042,10 +1090,82 @@ bool FIELDS_GRID_TABLE::BoolFromString( const wxString& aValue ) const
|
||||
}
|
||||
|
||||
|
||||
SCH_FIELD* FIELDS_GRID_TABLE::GetField( MANDATORY_FIELD_T aFieldId )
|
||||
{
|
||||
for( SCH_FIELD& field : *this )
|
||||
{
|
||||
if( field.GetId() == aFieldId )
|
||||
return &field;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
int FIELDS_GRID_TABLE::GetFieldRow( MANDATORY_FIELD_T aFieldId )
|
||||
{
|
||||
for( int ii = 0; ii < (int) this->size(); ++ii )
|
||||
{
|
||||
if( this->at( ii ).GetId() == aFieldId )
|
||||
return ii;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void FIELDS_GRID_TABLE::AddInheritedField( const SCH_FIELD& aParent )
|
||||
{
|
||||
push_back( aParent );
|
||||
back().SetParent( m_part );
|
||||
m_isInherited.back() = true;
|
||||
m_parentFields.back() = aParent;
|
||||
}
|
||||
|
||||
|
||||
bool FIELDS_GRID_TABLE::EraseRow( size_t aRow )
|
||||
{
|
||||
if( m_isInherited.size() > aRow )
|
||||
{
|
||||
// You can't erase inherited fields, but you can reset them to the parent value.
|
||||
if( m_isInherited[aRow] )
|
||||
{
|
||||
at( aRow ) = m_parentFields[aRow];
|
||||
return false;
|
||||
}
|
||||
|
||||
m_isInherited.erase( m_isInherited.begin() + aRow );
|
||||
}
|
||||
|
||||
if( m_parentFields.size() > aRow )
|
||||
m_parentFields.erase( m_parentFields.begin() + aRow );
|
||||
|
||||
std::vector<SCH_FIELD>::erase( begin() + aRow );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void FIELDS_GRID_TABLE::SwapRows( size_t a, size_t b )
|
||||
{
|
||||
wxCHECK( a < this->size() && b < this->size(), /*void*/ );
|
||||
|
||||
std::swap( at( a ), at( b ) );
|
||||
|
||||
bool tmpInherited = m_isInherited[a];
|
||||
m_isInherited[a] = m_isInherited[b];
|
||||
m_isInherited[b] = tmpInherited;
|
||||
|
||||
std::swap( m_parentFields[a], m_parentFields[b] );
|
||||
}
|
||||
|
||||
|
||||
void FIELDS_GRID_TABLE::DetachFields()
|
||||
{
|
||||
for( SCH_FIELD& field : *this )
|
||||
field.SetParent( nullptr );
|
||||
|
||||
for( SCH_FIELD& field : m_parentFields )
|
||||
field.SetParent( nullptr );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <sch_symbol.h>
|
||||
#include <grid_tricks.h>
|
||||
#include <validators.h>
|
||||
#include <vector>
|
||||
|
||||
class SCH_BASE_FRAME;
|
||||
class DIALOG_SHIM;
|
||||
@@ -120,6 +121,37 @@ public:
|
||||
wxString StringFromBool( bool aValue ) const;
|
||||
bool BoolFromString( const wxString& aValue ) const;
|
||||
|
||||
SCH_FIELD* GetField( MANDATORY_FIELD_T aFieldId );
|
||||
int GetFieldRow( MANDATORY_FIELD_T aFieldId );
|
||||
|
||||
void AddInheritedField( const SCH_FIELD& aParent );
|
||||
|
||||
void SetFieldInherited( size_t aRow, const SCH_FIELD& aParent )
|
||||
{
|
||||
m_isInherited.resize( aRow + 1, false );
|
||||
m_parentFields.resize( aRow + 1 );
|
||||
m_parentFields[aRow] = aParent;
|
||||
m_isInherited[aRow] = true;
|
||||
}
|
||||
|
||||
|
||||
bool IsInherited( size_t aRow ) const
|
||||
{
|
||||
if( aRow >= m_isInherited.size() || aRow >= m_parentFields.size() )
|
||||
return false;
|
||||
|
||||
return m_isInherited[aRow] && m_parentFields[aRow].GetText() == at( aRow ).GetText();
|
||||
}
|
||||
|
||||
const SCH_FIELD& ParentField( size_t row ) const { return m_parentFields[row]; }
|
||||
|
||||
void push_back( const SCH_FIELD& field );
|
||||
// For std::vector compatibility, but we don't use it directly.
|
||||
void emplace_back( const SCH_FIELD& field ) { push_back( field ); }
|
||||
|
||||
bool EraseRow( size_t row );
|
||||
void SwapRows( size_t a, size_t b );
|
||||
|
||||
void DetachFields();
|
||||
|
||||
protected:
|
||||
@@ -164,6 +196,9 @@ private:
|
||||
wxGridCellAttr* m_fontAttr;
|
||||
wxGridCellAttr* m_colorAttr;
|
||||
|
||||
std::vector<bool> m_isInherited;
|
||||
std::vector<SCH_FIELD> m_parentFields;
|
||||
|
||||
std::unique_ptr<NUMERIC_EVALUATOR> m_eval;
|
||||
std::map< std::pair<int, int>, wxString > m_evalOriginal;
|
||||
};
|
||||
|
||||
+25
-1
@@ -1230,8 +1230,18 @@ bool SCH_EDIT_FRAME::doAutoSave()
|
||||
if( !tmp.IsOk() )
|
||||
return false;
|
||||
|
||||
if( !IsWritable( tmp ) )
|
||||
if( !IsWritable( tmp, false ) )
|
||||
{
|
||||
if( !m_autoSavePermissionError )
|
||||
{
|
||||
DisplayError( this, wxString::Format(
|
||||
_( "Could not autosave files to read-only folder: '%s'" ),
|
||||
tmp.GetPath() ) );
|
||||
m_autoSavePermissionError = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
wxString title = GetTitle(); // Save frame title, that can be modified by the save process
|
||||
|
||||
@@ -1246,6 +1256,20 @@ bool SCH_EDIT_FRAME::doAutoSave()
|
||||
// Auto save file name is the normal file name prefixed with GetAutoSavePrefix().
|
||||
fn.SetName( FILEEXT::AutoSaveFilePrefix + fn.GetName() );
|
||||
|
||||
if( !IsWritable( fn, false ) )
|
||||
{
|
||||
if( !m_autoSavePermissionError )
|
||||
{
|
||||
DisplayError( this, wxString::Format(
|
||||
_( "Could not autosave files to read-only folder: '%s'" ),
|
||||
fn.GetPath() ) );
|
||||
m_autoSavePermissionError = true;
|
||||
}
|
||||
|
||||
autoSaveOk = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( saveSchematicFile( screens.GetSheet( i ), fn.GetFullPath() ) )
|
||||
{
|
||||
// This was only an auto-save, not a real save. Reset the modified flag.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <sch_reference_list.h>
|
||||
#include <wx/grid.h>
|
||||
#include <wx/arrstr.h>
|
||||
#include <widgets/grid_striped_renderer.h>
|
||||
// The field name in the data model (translated)
|
||||
#define DISPLAY_NAME_COLUMN 0
|
||||
|
||||
// The field name's label for exporting (CSV, etc.)
|
||||
#define LABEL_COLUMN 1
|
||||
#define SHOW_FIELD_COLUMN 2
|
||||
#define GROUP_BY_COLUMN 3
|
||||
|
||||
// The internal field name (untranslated)
|
||||
#define FIELD_NAME_COLUMN 4
|
||||
|
||||
struct BOM_FIELD;
|
||||
struct BOM_PRESET;
|
||||
struct BOM_FMT_PRESET;
|
||||
|
||||
enum GROUP_TYPE
|
||||
{
|
||||
GROUP_SINGLETON,
|
||||
GROUP_COLLAPSED,
|
||||
GROUP_COLLAPSED_DURING_SORT,
|
||||
GROUP_EXPANDED,
|
||||
CHILD_ITEM
|
||||
};
|
||||
|
||||
|
||||
struct LIB_DATA_MODEL_ROW
|
||||
{
|
||||
LIB_DATA_MODEL_ROW( const LIB_SYMBOL* aFirstReference, GROUP_TYPE aType )
|
||||
: m_ItemNumber( 0 ), m_Flag( aType ), m_Refs( { aFirstReference } )
|
||||
{
|
||||
}
|
||||
|
||||
int m_ItemNumber;
|
||||
GROUP_TYPE m_Flag;
|
||||
std::vector<const LIB_SYMBOL*> m_Refs;
|
||||
};
|
||||
|
||||
|
||||
struct LIB_DATA_MODEL_COL
|
||||
{
|
||||
wxString m_fieldName;
|
||||
wxString m_label;
|
||||
bool m_userAdded;
|
||||
bool m_show;
|
||||
bool m_group;
|
||||
bool m_isCheckbox;
|
||||
};
|
||||
|
||||
|
||||
struct LIB_DATA_ELEMENT
|
||||
{
|
||||
LIB_DATA_ELEMENT()
|
||||
{
|
||||
m_originalData = wxEmptyString;
|
||||
m_currentData = wxEmptyString;
|
||||
m_originallyEmpty = false;
|
||||
m_currentlyEmpty = false;
|
||||
m_isModified = false;
|
||||
m_isStriped = false;
|
||||
m_createDerivedSymbol = false;
|
||||
m_derivedSymbolName = wxEmptyString;
|
||||
}
|
||||
|
||||
wxString m_originalData;
|
||||
wxString m_currentData;
|
||||
bool m_originallyEmpty;
|
||||
bool m_currentlyEmpty;
|
||||
bool m_isModified;
|
||||
bool m_isStriped;
|
||||
bool m_createDerivedSymbol;
|
||||
wxString m_derivedSymbolName;
|
||||
};
|
||||
|
||||
|
||||
class LIB_FIELDS_EDITOR_GRID_DATA_MODEL : public wxGridTableBase
|
||||
{
|
||||
public:
|
||||
enum SCOPE : int
|
||||
{
|
||||
SCOPE_ALL = 0,
|
||||
SCOPE_SHEET = 1,
|
||||
SCOPE_SHEET_RECURSIVE = 2
|
||||
};
|
||||
|
||||
LIB_FIELDS_EDITOR_GRID_DATA_MODEL( const std::vector<LIB_SYMBOL*>& aSymbolsList ) :
|
||||
m_symbolsList( aSymbolsList ), m_edited( false ), m_sortColumn( 0 ),
|
||||
m_sortAscending( false ), m_filter( wxEmptyString ), m_scope( SCOPE_ALL ),
|
||||
m_path(), m_groupingEnabled( false ), m_cols(), m_rows(),
|
||||
m_dataStore(), m_stripedStringRenderer( nullptr )
|
||||
{
|
||||
}
|
||||
|
||||
~LIB_FIELDS_EDITOR_GRID_DATA_MODEL()
|
||||
{
|
||||
for (auto& pair : m_stripedRenderers)
|
||||
pair.second->DecRef();
|
||||
|
||||
m_stripedRenderers.clear();
|
||||
|
||||
for( const auto& [col, attr] : m_colAttrs )
|
||||
wxSafeDecRef( attr );
|
||||
}
|
||||
|
||||
static const wxString QUANTITY_VARIABLE;
|
||||
static const wxString ITEM_NUMBER_VARIABLE;
|
||||
|
||||
void CreateDerivedSymbol( int aRow, int aCol, wxString& aNewSymbolName );
|
||||
void CreateDerivedSymbolImmediate( int aRow, int aCol, wxString& aNewSymbolName );
|
||||
|
||||
void AddColumn( const wxString& aFieldName, const wxString& aLabel, bool aAddedByUser, bool aIsCheckbox );
|
||||
void RemoveColumn( int aCol );
|
||||
void RenameColumn( int aCol, const wxString& newName );
|
||||
|
||||
void MoveColumn( int aCol, int aNewPos )
|
||||
{
|
||||
wxCHECK_RET( aCol >= 0 && aCol < (int) m_cols.size(), "Invalid Column Number" );
|
||||
|
||||
if( aCol == aNewPos )
|
||||
return;
|
||||
else if( aCol < aNewPos )
|
||||
std::rotate( std::begin( m_cols ) + aCol, std::begin( m_cols ) + aCol + 1,
|
||||
std::begin( m_cols ) + aNewPos + 1 );
|
||||
else
|
||||
std::rotate( std::begin( m_cols ) + aNewPos, std::begin( m_cols ) + aCol,
|
||||
std::begin( m_cols ) + aCol + 1 );
|
||||
}
|
||||
|
||||
int GetNumberRows() override { return (int) m_rows.size(); }
|
||||
int GetNumberCols() override { return (int) m_cols.size(); }
|
||||
|
||||
void SetColLabelValue( int aCol, const wxString& aLabel ) override
|
||||
{
|
||||
wxCHECK_RET( aCol >= 0 && aCol < (int) m_cols.size(), "Invalid Column Number" );
|
||||
m_cols[aCol].m_label = aLabel;
|
||||
}
|
||||
|
||||
|
||||
wxString GetColLabelValue( int aCol ) override
|
||||
{
|
||||
wxCHECK( aCol >= 0 && aCol < (int) m_cols.size(), wxString() );
|
||||
return m_cols[aCol].m_label;
|
||||
}
|
||||
|
||||
wxString GetColFieldName( int aCol )
|
||||
{
|
||||
wxCHECK( aCol >= 0 && aCol < (int) m_cols.size(), wxString() );
|
||||
return m_cols[aCol].m_fieldName;
|
||||
}
|
||||
|
||||
int GetFieldNameCol( wxString aFieldName );
|
||||
|
||||
void SetFieldsOrder( const std::vector<wxString>& aNewOrder );
|
||||
|
||||
bool IsEmptyCell( int aRow, int aCol ) override
|
||||
{
|
||||
return false; // don't allow adjacent cell overflow, even if we are actually empty
|
||||
}
|
||||
|
||||
wxString GetValue( int aRow, int aCol ) override;
|
||||
wxString GetTypeName( int row, int col ) override;
|
||||
wxString GetValue( const LIB_DATA_MODEL_ROW& group, int aCol );
|
||||
void SetValue( int aRow, int aCol, const wxString& aValue ) override;
|
||||
|
||||
wxGridCellAttr* GetAttr( int row, int col, wxGridCellAttr::wxAttrKind kind ) override;
|
||||
void RevertRow( int aRow );
|
||||
void ClearCell( int aRow, int aCol );
|
||||
|
||||
bool ColIsValue( int aCol );
|
||||
bool ColIsCheck( int aCol );
|
||||
|
||||
void SetSorting( int aCol, bool ascending )
|
||||
{
|
||||
wxCHECK_RET( aCol >= 0 && aCol < (int) m_cols.size(), "Invalid Column Number" );
|
||||
m_sortColumn = aCol;
|
||||
m_sortAscending = ascending;
|
||||
}
|
||||
|
||||
int GetSortCol() { return m_sortColumn; }
|
||||
bool GetSortAsc() { return m_sortAscending; }
|
||||
const LIB_SYMBOL* GetSymbolForRow( int aRow )
|
||||
{
|
||||
wxCHECK( aRow >= 0 && aRow < (int) m_rows.size(), nullptr );
|
||||
return m_rows[aRow].m_Refs[0];
|
||||
}
|
||||
|
||||
void GetSymbolNames( wxArrayString& aList )
|
||||
{
|
||||
aList.Clear();
|
||||
for( const LIB_SYMBOL* symbol : m_symbolsList )
|
||||
aList.Add( symbol->GetName() );
|
||||
}
|
||||
void RebuildRows();
|
||||
|
||||
void ExpandRow( int aRow );
|
||||
void CollapseRow( int aRow );
|
||||
void ExpandCollapseRow( int aRow );
|
||||
void CollapseForSort();
|
||||
void ExpandAfterSort();
|
||||
|
||||
void ApplyData( std::function<void( LIB_SYMBOL* )> symbolChangeHandler,
|
||||
std::function<void()> postApplyHandler = nullptr );
|
||||
|
||||
/// Get and clear the list of newly created derived symbols for library manager processing
|
||||
std::vector<std::pair<LIB_SYMBOL*, wxString>> GetAndClearCreatedDerivedSymbols()
|
||||
{
|
||||
auto result = std::move( m_createdDerivedSymbols );
|
||||
m_createdDerivedSymbols.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool IsEdited() { return m_edited; }
|
||||
|
||||
int GetDataWidth( int aCol );
|
||||
|
||||
void SetFilter( const wxString& aFilter ) { m_filter = aFilter; }
|
||||
const wxString& GetFilter() { return m_filter; }
|
||||
|
||||
void SetGroupingEnabled( bool group ) { m_groupingEnabled = group; }
|
||||
bool GetGroupingEnabled() { return m_groupingEnabled; }
|
||||
|
||||
void SetGroupColumn( int aCol, bool group )
|
||||
{
|
||||
wxCHECK_RET( aCol >= 0 && aCol < (int) m_cols.size(), "Invalid Column Number" );
|
||||
m_cols[aCol].m_group = group;
|
||||
}
|
||||
|
||||
bool GetGroupColumn( int aCol )
|
||||
{
|
||||
wxCHECK_MSG( aCol >= 0 && aCol < (int) m_cols.size(), false, "Invalid Column Number" );
|
||||
return m_cols[aCol].m_group;
|
||||
}
|
||||
|
||||
void SetShowColumn( int aCol, bool show )
|
||||
{
|
||||
wxCHECK_RET( aCol >= 0 && aCol < (int) m_cols.size(), "Invalid Column Number" );
|
||||
m_cols[aCol].m_show = show;
|
||||
}
|
||||
|
||||
bool GetShowColumn( int aCol )
|
||||
{
|
||||
wxCHECK_MSG( aCol >= 0 && aCol < (int) m_cols.size(), false, "Invalid Column Number" );
|
||||
return m_cols[aCol].m_show;
|
||||
}
|
||||
|
||||
bool IsRowEditable( int aRow )
|
||||
{
|
||||
wxCHECK_MSG( aRow >= 0 && aRow < (int) m_rows.size(), false, "Invalid Row Number" );
|
||||
return m_rows[aRow].m_Flag == GROUP_SINGLETON || m_rows[aRow].m_Flag == GROUP_SINGLETON;
|
||||
}
|
||||
|
||||
bool IsCellEdited( int aRow, int aCol )
|
||||
{
|
||||
wxCHECK_MSG( aRow >= 0 && aRow < (int) m_rows.size(), false, "Invalid Row Number" );
|
||||
wxCHECK_MSG( aCol >= 0 && aCol < (int) m_cols.size(), false, "Invalid Column Number" );
|
||||
return m_dataStore[m_rows[aRow].m_Refs[0]->m_Uuid][m_cols[aCol].m_fieldName].m_isModified;
|
||||
}
|
||||
|
||||
bool IsCellClear( int aRow, int aCol )
|
||||
{
|
||||
wxCHECK_MSG( aRow >= 0 && aRow < (int) m_rows.size(), false, "Invalid Row Number" );
|
||||
wxCHECK_MSG( aCol >= 0 && aCol < (int) m_cols.size(), false, "Invalid Column Number" );
|
||||
return m_dataStore[m_rows[aRow].m_Refs[0]->m_Uuid][m_cols[aCol].m_fieldName].m_currentlyEmpty;
|
||||
}
|
||||
|
||||
bool IsRowSingleSymbol( int aRow )
|
||||
{
|
||||
wxCHECK_MSG( aRow >= 0 && aRow < (int) m_rows.size(), false, "Invalid Row Number" );
|
||||
return m_rows[aRow].m_Flag == GROUP_SINGLETON || m_rows[aRow].m_Flag == CHILD_ITEM;
|
||||
}
|
||||
|
||||
void SetColAttr( wxGridCellAttr* aAttr, int aCol ) override
|
||||
{
|
||||
wxSafeDecRef( m_colAttrs[aCol] );
|
||||
m_colAttrs[aCol] = aAttr;
|
||||
}
|
||||
|
||||
private:
|
||||
static bool cmp( const LIB_DATA_MODEL_ROW& lhGroup, const LIB_DATA_MODEL_ROW& rhGroup,
|
||||
LIB_FIELDS_EDITOR_GRID_DATA_MODEL* dataModel, int sortCol, bool ascending );
|
||||
bool groupMatch( const LIB_SYMBOL* lhRef, const LIB_SYMBOL* rhRef );
|
||||
wxString getAttributeValue( const LIB_SYMBOL*, const wxString& aAttributeName );
|
||||
void setAttributeValue( LIB_SYMBOL* aSymbol, const wxString& aAttributeName,
|
||||
const wxString& aValue );
|
||||
|
||||
void createActualDerivedSymbol( const LIB_SYMBOL* aParentSymbol, const wxString& aNewSymbolName,
|
||||
const KIID& aNewSymbolUuid );
|
||||
|
||||
void Sort();
|
||||
|
||||
void updateDataStoreSymbolField( const LIB_SYMBOL* aSymbol, const wxString& aFieldName );
|
||||
|
||||
bool isStripeableField( int aCol );
|
||||
wxGridCellRenderer* getStripedRenderer( int aCol ) const;
|
||||
|
||||
protected:
|
||||
std::vector<LIB_SYMBOL*> m_symbolsList;
|
||||
bool m_edited;
|
||||
int m_sortColumn;
|
||||
bool m_sortAscending;
|
||||
wxString m_filter;
|
||||
enum SCOPE m_scope;
|
||||
SCH_SHEET_PATH m_path;
|
||||
bool m_groupingEnabled;
|
||||
|
||||
std::vector<LIB_DATA_MODEL_COL> m_cols;
|
||||
std::vector<LIB_DATA_MODEL_ROW> m_rows;
|
||||
|
||||
// Data store
|
||||
// The data model is fundamentally m_componentRefs X m_fieldNames.
|
||||
// A map of compID : fieldSet, where fieldSet is a map of fieldName : LIB_DATA_ELEMENT
|
||||
std::map<KIID, std::map<wxString, LIB_DATA_ELEMENT>> m_dataStore;
|
||||
|
||||
// Track newly created derived symbols for library manager integration
|
||||
std::vector<std::pair<LIB_SYMBOL*, wxString>> m_createdDerivedSymbols; // symbol, library name
|
||||
|
||||
// stripe bitmap support
|
||||
mutable STRIPED_STRING_RENDERER* m_stripedStringRenderer;
|
||||
mutable std::map<wxString, wxGridCellRenderer*> m_stripedRenderers;
|
||||
|
||||
// Column attributes storage
|
||||
std::map<int, wxGridCellAttr*> m_colAttrs;
|
||||
};
|
||||
+31
-20
@@ -281,24 +281,31 @@ LIB_SYMBOL_SPTR LIB_SYMBOL::GetRootSymbol() const
|
||||
}
|
||||
|
||||
|
||||
wxString LIB_SYMBOL::GetUnitReference( int aUnit )
|
||||
{
|
||||
return LIB_SYMBOL::LetterSubReference( aUnit, 'A' );
|
||||
}
|
||||
|
||||
|
||||
bool LIB_SYMBOL::HasUnitDisplayName( int aUnit )
|
||||
bool LIB_SYMBOL::HasUnitDisplayName( int aUnit ) const
|
||||
{
|
||||
return ( m_unitDisplayNames.count( aUnit ) == 1 );
|
||||
}
|
||||
|
||||
|
||||
wxString LIB_SYMBOL::GetUnitDisplayName( int aUnit )
|
||||
wxString LIB_SYMBOL::GetUnitDisplayName( int aUnit, bool aLabel ) const
|
||||
{
|
||||
if( HasUnitDisplayName( aUnit ) )
|
||||
return m_unitDisplayNames[aUnit];
|
||||
if( m_unitDisplayNames.contains( aUnit ) )
|
||||
return m_unitDisplayNames.at( aUnit );
|
||||
else if( aLabel )
|
||||
return wxString::Format( _( "Unit %s" ), LIB_SYMBOL::LetterSubReference( aUnit, 'A' ) );
|
||||
else
|
||||
return wxString::Format( _( "Unit %s" ), GetUnitReference( aUnit ) );
|
||||
return LIB_SYMBOL::LetterSubReference( aUnit, 'A' );
|
||||
}
|
||||
|
||||
|
||||
wxString LIB_SYMBOL::GetBodyStyleDescription( int aBodyStyle, bool aLabel ) const
|
||||
{
|
||||
if( aBodyStyle == BODY_STYLE::DEMORGAN )
|
||||
return aLabel ? _( "Alternate" ) : wxString( _HKI( "Alternate" ) );
|
||||
else if( aBodyStyle == BODY_STYLE::BASE )
|
||||
return aLabel ? _( "Standard" ) : wxString( _HKI( "Standard" ) );
|
||||
else
|
||||
return wxT( "?" );
|
||||
}
|
||||
|
||||
|
||||
@@ -480,7 +487,7 @@ void LIB_SYMBOL::SetNormal()
|
||||
}
|
||||
|
||||
|
||||
wxString LIB_SYMBOL::LetterSubReference( int aUnit, int aFirstId )
|
||||
wxString LIB_SYMBOL::LetterSubReference( int aUnit, wxChar aInitialLetter )
|
||||
{
|
||||
// use letters as notation. To allow more than 26 units, the sub ref
|
||||
// use one letter if letter = A .. Z or a ... z, and 2 letters otherwise
|
||||
@@ -491,7 +498,7 @@ wxString LIB_SYMBOL::LetterSubReference( int aUnit, int aFirstId )
|
||||
do
|
||||
{
|
||||
u = ( aUnit - 1 ) % 26;
|
||||
suffix = wxChar( aFirstId + u ) + suffix;
|
||||
suffix = wxChar( aInitialLetter + u ) + suffix;
|
||||
aUnit = ( aUnit - u ) / 26;
|
||||
} while( aUnit > 0 );
|
||||
|
||||
@@ -1419,14 +1426,18 @@ void LIB_SYMBOL::SetUnitCount( int aCount, bool aDuplicateDrawItems )
|
||||
|
||||
if( aCount < m_unitCount )
|
||||
{
|
||||
LIB_ITEMS_CONTAINER::ITERATOR i = m_drawings.begin();
|
||||
|
||||
while( i != m_drawings.end() )
|
||||
// Iterate each drawing-type bucket and erase items that belong to units > aCount.
|
||||
for( int type = LIB_ITEMS_CONTAINER::FIRST_TYPE; type <= LIB_ITEMS_CONTAINER::LAST_TYPE; ++type )
|
||||
{
|
||||
if( i->m_unit > aCount )
|
||||
i = m_drawings.erase( i );
|
||||
else
|
||||
++i;
|
||||
auto it = m_drawings.begin( type );
|
||||
|
||||
while( it != m_drawings.end( type ) )
|
||||
{
|
||||
if( it->m_unit > aCount )
|
||||
it = m_drawings.erase( it ); // returns next iterator
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( aDuplicateDrawItems )
|
||||
|
||||
+10
-8
@@ -554,20 +554,22 @@ public:
|
||||
void SetUnitCount( int aCount, bool aDuplicateDrawItems = true );
|
||||
int GetUnitCount() const override;
|
||||
|
||||
/**
|
||||
* Return an identifier for \a aUnit for symbols with units.
|
||||
*/
|
||||
wxString GetUnitReference( int aUnit ) override;
|
||||
|
||||
/**
|
||||
* Return true if the given unit \a aUnit has a display name defined
|
||||
*/
|
||||
bool HasUnitDisplayName( int aUnit ) override;
|
||||
bool HasUnitDisplayName( int aUnit ) const;
|
||||
|
||||
wxString GetUnitName( int aUnit ) const override
|
||||
{
|
||||
return GetUnitDisplayName( aUnit, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the user-defined display name for \a aUnit for symbols with units.
|
||||
*/
|
||||
wxString GetUnitDisplayName( int aUnit ) override;
|
||||
wxString GetUnitDisplayName( int aUnit, bool aLabel ) const override;
|
||||
|
||||
wxString GetBodyStyleDescription( int aBodyStyle, bool aLabel ) const override;
|
||||
|
||||
/**
|
||||
* Copy all unit display names into the given map \a aTarget
|
||||
@@ -585,7 +587,7 @@ public:
|
||||
*/
|
||||
bool IsMulti() const override { return m_unitCount > 1; }
|
||||
|
||||
static wxString LetterSubReference( int aUnit, int aFirstId );
|
||||
static wxString LetterSubReference( int aUnit, wxChar aInitialLetter );
|
||||
|
||||
/**
|
||||
* Set or clear the alternate body style (DeMorgan) for the symbol.
|
||||
|
||||
@@ -34,17 +34,15 @@
|
||||
#include "netlist_exporter_allegro.h"
|
||||
#include "netlist_exporter_xml.h"
|
||||
#include <regex>
|
||||
|
||||
#include <fmt.h>
|
||||
#include <fmt/ranges.h>
|
||||
|
||||
bool NETLIST_EXPORTER_ALLEGRO::WriteNetlist( const wxString& aOutFileName,
|
||||
unsigned /* aNetlistOptions */,
|
||||
REPORTER& aReporter )
|
||||
{
|
||||
m_f = nullptr;
|
||||
wxString field;
|
||||
wxString footprint;
|
||||
int ret = 0; // zero now, OR in the sign bit on error
|
||||
wxString netName;
|
||||
bool success = true;
|
||||
|
||||
// Create the devices directory
|
||||
m_exportPath = wxFileName( aOutFileName ).GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR )
|
||||
@@ -67,31 +65,41 @@ bool NETLIST_EXPORTER_ALLEGRO::WriteNetlist( const wxString& aOutFileName,
|
||||
return false;
|
||||
}
|
||||
|
||||
ret |= fprintf( m_f, "(Source: %s)\n", TO_UTF8( m_schematic->GetFileName() ) );
|
||||
ret |= fprintf( m_f, "(Date: %s)\n", TO_UTF8( GetISO8601CurrentDateTime() ) );
|
||||
try
|
||||
{
|
||||
fmt::print( m_f, "(NETLIST)\n" );
|
||||
fmt::print( m_f, "(Source: {})\n", TO_UTF8( m_schematic->GetFileName() ) );
|
||||
fmt::print( m_f, "(Date: {})\n", TO_UTF8( GetISO8601CurrentDateTime() ) );
|
||||
|
||||
m_packageProperties.clear();
|
||||
m_componentGroups.clear();
|
||||
m_orderedSymbolsSheetpath.clear();
|
||||
m_netNameNodes.clear();
|
||||
m_packageProperties.clear();
|
||||
m_componentGroups.clear();
|
||||
m_orderedSymbolsSheetpath.clear();
|
||||
m_netNameNodes.clear();
|
||||
|
||||
extractComponentsInfo();
|
||||
extractComponentsInfo();
|
||||
|
||||
// Start with package definitions, which we create from component groups.
|
||||
toAllegroPackages();
|
||||
// Start with package definitions, which we create from component groups.
|
||||
toAllegroPackages();
|
||||
|
||||
// Write out nets
|
||||
toAllegroNets();
|
||||
// Write out package properties. NOTE: Allegro doesn't recognize much...
|
||||
toAllegroPackageProperties();
|
||||
|
||||
// Write out package properties. NOTE: Allegro doesn't recognize much...
|
||||
toAllegroPackageProperties();
|
||||
// Write out nets
|
||||
toAllegroNets();
|
||||
|
||||
fmt::print( m_f, "$END\n" );
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
|
||||
// Done with the netlist
|
||||
fclose( m_f );
|
||||
|
||||
m_f = nullptr;
|
||||
|
||||
return ret >= 0;
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
@@ -437,8 +445,8 @@ void NETLIST_EXPORTER_ALLEGRO::toAllegroPackages()
|
||||
}
|
||||
}
|
||||
|
||||
fprintf( d, "PACKAGE '%s'\n", TO_UTF8( formatDevice( footprintText ) ) );
|
||||
fprintf( d, "CLASS IC\n" );
|
||||
fmt::print( d, "PACKAGE '{}'\n", TO_UTF8( formatDevice( footprintText ) ) );
|
||||
fmt::print( d, "CLASS IC\n" );
|
||||
|
||||
std::vector<SCH_PIN*> pinList = sym->GetLibSymbolRef()->GetPins();
|
||||
|
||||
@@ -463,36 +471,26 @@ void NETLIST_EXPORTER_ALLEGRO::toAllegroPackages()
|
||||
}
|
||||
|
||||
unsigned int pinCount = pinList.size();
|
||||
fprintf( d, "PINCOUNT %u\n", pinCount );
|
||||
fmt::print( d, "PINCOUNT {}\n", pinCount );
|
||||
|
||||
if( pinCount > 0 )
|
||||
{
|
||||
fprintf( d, "%s", TO_UTF8( formatFunction( "main", pinList ) ) );
|
||||
fmt::print( d, "{}", TO_UTF8( formatFunction( "main", pinList ) ) );
|
||||
}
|
||||
|
||||
if( !value.IsEmpty() )
|
||||
{
|
||||
fprintf( d, "PACKAGEPROP VALUE %s\n", TO_UTF8( value ) );
|
||||
fmt::print( d, "PACKAGEPROP VALUE {}\n", TO_UTF8( value ) );
|
||||
}
|
||||
|
||||
if( !tol.IsEmpty() )
|
||||
{
|
||||
fprintf( d, "PACKAGEPROP TOL %s\n", TO_UTF8( tol ) );
|
||||
fmt::print( d, "PACKAGEPROP TOL {}\n", TO_UTF8( tol ) );
|
||||
}
|
||||
|
||||
if( !footprintAlt.IsEmpty() )
|
||||
{
|
||||
fprintf( d, "PACKAGEPROP ALT_SYMBOLS '(" );
|
||||
|
||||
wxString footprintAltSymbolsText;
|
||||
|
||||
for( const wxString& fp : footprintAlt )
|
||||
{
|
||||
footprintAltSymbolsText += fp + wxString( "," );
|
||||
}
|
||||
|
||||
footprintAltSymbolsText.Truncate( footprintAltSymbolsText.Length() - 1 );
|
||||
fprintf( d, "%s)'\n", TO_UTF8( footprintAltSymbolsText ) );
|
||||
fmt::print( d, "PACKAGEPROP ALT_SYMBOLS '({})'\n", fmt::join( footprintAlt, "," ) );
|
||||
}
|
||||
|
||||
wxArrayString propArray;
|
||||
@@ -503,7 +501,7 @@ void NETLIST_EXPORTER_ALLEGRO::toAllegroPackages()
|
||||
|
||||
if(!data.IsEmpty())
|
||||
{
|
||||
fprintf( d, "PACKAGEPROP %s %s\n", TO_UTF8( propArray[0] ), TO_UTF8( data ) );
|
||||
fmt::print( d, "PACKAGEPROP {} {}\n", TO_UTF8( propArray[0] ), TO_UTF8( data ) );
|
||||
}
|
||||
|
||||
propArray.clear();
|
||||
@@ -512,14 +510,16 @@ void NETLIST_EXPORTER_ALLEGRO::toAllegroPackages()
|
||||
|
||||
if(!data.IsEmpty())
|
||||
{
|
||||
fprintf( d, "PACKAGEPROP %s %s\n", TO_UTF8( propArray[0] ), TO_UTF8( data ) );
|
||||
fmt::print( d, "PACKAGEPROP {} {}\n", TO_UTF8( propArray[0] ), TO_UTF8( data ) );
|
||||
}
|
||||
|
||||
fprintf( d, "END\n" );
|
||||
fmt::print( d, "END\n" );
|
||||
|
||||
fclose( d );
|
||||
}
|
||||
|
||||
fmt::print( m_f, "$PACKAGES\n" );
|
||||
|
||||
for( auto iter = compPackageMap.begin(); iter != compPackageMap.end(); iter++ )
|
||||
{
|
||||
wxString deviceType = iter->first;
|
||||
@@ -528,25 +528,28 @@ void NETLIST_EXPORTER_ALLEGRO::toAllegroPackages()
|
||||
|
||||
if( value.IsEmpty() && tolerance.IsEmpty() )
|
||||
{
|
||||
fprintf( m_f, "!%s;", TO_UTF8( deviceType ) );
|
||||
fmt::print( m_f, "! '{}' ; ", TO_UTF8( deviceType ) );
|
||||
}
|
||||
else if( tolerance.IsEmpty() )
|
||||
{
|
||||
fprintf( m_f, "!%s!%s;", TO_UTF8( deviceType ), TO_UTF8( value ) );
|
||||
fmt::print( m_f, "! '{}' ! '{}' ; ", TO_UTF8( deviceType ), TO_UTF8( value ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( m_f, "!%s!%s!%s;", TO_UTF8( deviceType ), TO_UTF8( value ),
|
||||
fmt::print( m_f, "! '{}' ! '{}' ! {} ; ", TO_UTF8( deviceType ), TO_UTF8( value ),
|
||||
TO_UTF8( tolerance ) );
|
||||
}
|
||||
|
||||
std::vector<std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>> symbolSheetpaths =
|
||||
iter->second.m_symbolSheetpaths;
|
||||
|
||||
std::vector<wxString> refTexts;
|
||||
for( const auto& [ sym, sheetPath ] : symbolSheetpaths)
|
||||
fprintf( m_f, ",\n\t%s", TO_UTF8( sym->GetRef( &sheetPath ) ) );
|
||||
refTexts.push_back( sym->GetRef( &sheetPath ) );
|
||||
|
||||
fprintf( m_f, "\n" );
|
||||
fmt::print( m_f, "{}", fmt::join( refTexts, ",\n\t" ) );
|
||||
|
||||
fmt::print( m_f, "\n" );
|
||||
}
|
||||
|
||||
if( !deviceFileCreatingError.IsEmpty() )
|
||||
@@ -680,15 +683,14 @@ wxString NETLIST_EXPORTER_ALLEGRO::formatDevice( wxString aString )
|
||||
|
||||
void NETLIST_EXPORTER_ALLEGRO::toAllegroPackageProperties()
|
||||
{
|
||||
fprintf( m_f, "%s\n", "$PACKAGES" );
|
||||
fprintf( m_f, "%s\n", "$A_PROPERTIES" );
|
||||
fmt::print( m_f, "$A_PROPERTIES\n" );
|
||||
|
||||
while( !m_packageProperties.empty() )
|
||||
{
|
||||
std::multimap<wxString, wxString>::iterator iter = m_packageProperties.begin();
|
||||
wxString sheetPathText = iter->first;
|
||||
|
||||
fprintf( m_f, "ROOM %s;", TO_UTF8( formatText( sheetPathText ) ) );
|
||||
fmt::print( m_f, "'ROOM' '{}' ; ", TO_UTF8( formatText( sheetPathText ) ) );
|
||||
|
||||
std::vector<wxString> refTexts;
|
||||
|
||||
@@ -705,17 +707,16 @@ void NETLIST_EXPORTER_ALLEGRO::toAllegroPackageProperties()
|
||||
std::stable_sort( refTexts.begin(), refTexts.end(),
|
||||
NETLIST_EXPORTER_ALLEGRO::CompareSymbolRef );
|
||||
|
||||
for( const wxString& ref : refTexts )
|
||||
fprintf( m_f, ",\n\t%s", TO_UTF8( ref ) );
|
||||
fmt::print( m_f, "{}", fmt::join( refTexts, ",\n\t" ) );
|
||||
|
||||
fprintf( m_f, "\n" );
|
||||
fmt::print( m_f, "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void NETLIST_EXPORTER_ALLEGRO::toAllegroNets()
|
||||
{
|
||||
fprintf( m_f, "%s\n", "$NETS" );
|
||||
fmt::print( m_f, "$NETS\n" );
|
||||
|
||||
while( !m_netNameNodes.empty() )
|
||||
{
|
||||
@@ -724,7 +725,7 @@ void NETLIST_EXPORTER_ALLEGRO::toAllegroNets()
|
||||
|
||||
wxString netName = iter->first;
|
||||
|
||||
fprintf( m_f, "%s;", TO_UTF8( formatText( netName ).MakeUpper() ) );
|
||||
fmt::print( m_f, "{}; ", TO_UTF8( formatText( netName ).MakeUpper() ) );
|
||||
|
||||
auto pairIter = m_netNameNodes.equal_range( netName );
|
||||
|
||||
@@ -738,14 +739,17 @@ void NETLIST_EXPORTER_ALLEGRO::toAllegroNets()
|
||||
|
||||
std::stable_sort( netNodes.begin(), netNodes.end() );
|
||||
|
||||
std::vector<wxString> nets;
|
||||
for( const NET_NODE& netNode : netNodes )
|
||||
{
|
||||
wxString refText = netNode.m_Pin->GetParentSymbol()->GetRef( &netNode.m_Sheet );
|
||||
wxString pinText = netNode.m_Pin->GetShownNumber();
|
||||
fprintf( m_f, ",\n\t%s.%s", TO_UTF8( refText ), TO_UTF8( pinText ) );
|
||||
nets.push_back( refText + wxString( "." ) + pinText );
|
||||
}
|
||||
|
||||
fprintf( m_f, "\n" );
|
||||
fmt::print( m_f, "{}", fmt::join( nets, ",\n\t" ) );
|
||||
|
||||
fmt::print( m_f, "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -119,8 +119,8 @@ void SCH_EDIT_FRAME::SelectUnit( SCH_SYMBOL* aSymbol, int aUnit )
|
||||
|
||||
if( otherSymbolRef )
|
||||
{
|
||||
const wxString targetUnitName = symbol->GetUnitDisplayName( aUnit );
|
||||
const wxString currUnitName = symbol->GetUnitDisplayName( currentUnit );
|
||||
const wxString targetUnitName = symbol->GetUnitDisplayName( aUnit, false );
|
||||
const wxString currUnitName = symbol->GetUnitDisplayName( currentUnit, false );
|
||||
wxString otherSheetName = otherSymbolRef->GetSheetPath().PathHumanReadable( true, true );
|
||||
|
||||
if( otherSheetName.IsEmpty() )
|
||||
|
||||
+25
-30
@@ -82,42 +82,37 @@ void InitTables()
|
||||
{
|
||||
// clang-format off
|
||||
g_pinElectricalTypes = {
|
||||
{ ELECTRICAL_PINTYPE::PT_INPUT, { _( "Input" ), BITMAPS::pintype_input } },
|
||||
{ ELECTRICAL_PINTYPE::PT_OUTPUT, { _( "Output" ), BITMAPS::pintype_output } },
|
||||
{ ELECTRICAL_PINTYPE::PT_BIDI, { _( "Bidirectional" ), BITMAPS::pintype_bidi } },
|
||||
{ ELECTRICAL_PINTYPE::PT_TRISTATE, { _( "Tri-state" ), BITMAPS::pintype_3states } },
|
||||
{ ELECTRICAL_PINTYPE::PT_PASSIVE, { _( "Passive" ), BITMAPS::pintype_passive } },
|
||||
{ ELECTRICAL_PINTYPE::PT_NIC, { _( "Free" ), BITMAPS::pintype_nic } },
|
||||
{ ELECTRICAL_PINTYPE::PT_UNSPECIFIED, { _( "Unspecified" ), BITMAPS::pintype_notspecif } },
|
||||
{ ELECTRICAL_PINTYPE::PT_POWER_IN, { _( "Power input" ), BITMAPS::pintype_powerinput } },
|
||||
{ ELECTRICAL_PINTYPE::PT_POWER_OUT, { _( "Power output" ), BITMAPS::pintype_poweroutput } },
|
||||
{ ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR, { _( "Open collector" ),
|
||||
BITMAPS::pintype_opencoll } },
|
||||
{ ELECTRICAL_PINTYPE::PT_OPENEMITTER, { _( "Open emitter" ), BITMAPS::pintype_openemit } },
|
||||
{ ELECTRICAL_PINTYPE::PT_NC, { _( "Unconnected" ), BITMAPS::pintype_noconnect } },
|
||||
{ ELECTRICAL_PINTYPE::PT_INPUT, { _( "Input" ), BITMAPS::pintype_input } },
|
||||
{ ELECTRICAL_PINTYPE::PT_OUTPUT, { _( "Output" ), BITMAPS::pintype_output } },
|
||||
{ ELECTRICAL_PINTYPE::PT_BIDI, { _( "Bidirectional" ), BITMAPS::pintype_bidi } },
|
||||
{ ELECTRICAL_PINTYPE::PT_TRISTATE, { _( "Tri-state" ), BITMAPS::pintype_3states } },
|
||||
{ ELECTRICAL_PINTYPE::PT_PASSIVE, { _( "Passive" ), BITMAPS::pintype_passive } },
|
||||
{ ELECTRICAL_PINTYPE::PT_NIC, { _( "Free" ), BITMAPS::pintype_nic } },
|
||||
{ ELECTRICAL_PINTYPE::PT_UNSPECIFIED, { _( "Unspecified" ), BITMAPS::pintype_notspecif } },
|
||||
{ ELECTRICAL_PINTYPE::PT_POWER_IN, { _( "Power input" ), BITMAPS::pintype_powerinput } },
|
||||
{ ELECTRICAL_PINTYPE::PT_POWER_OUT, { _( "Power output" ), BITMAPS::pintype_poweroutput } },
|
||||
{ ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR, { _( "Open collector" ), BITMAPS::pintype_opencoll } },
|
||||
{ ELECTRICAL_PINTYPE::PT_OPENEMITTER, { _( "Open emitter" ), BITMAPS::pintype_openemit } },
|
||||
{ ELECTRICAL_PINTYPE::PT_NC, { _( "Unconnected" ), BITMAPS::pintype_noconnect } },
|
||||
};
|
||||
|
||||
g_pinShapes = {
|
||||
{ GRAPHIC_PINSHAPE::LINE, { _( "Line" ), BITMAPS::pinshape_normal } },
|
||||
{ GRAPHIC_PINSHAPE::INVERTED, { _( "Inverted" ), BITMAPS::pinshape_invert } },
|
||||
{ GRAPHIC_PINSHAPE::CLOCK, { _( "Clock" ), BITMAPS::pinshape_clock_normal } },
|
||||
{ GRAPHIC_PINSHAPE::INVERTED_CLOCK, { _( "Inverted clock" ),
|
||||
BITMAPS::pinshape_clock_invert } },
|
||||
{ GRAPHIC_PINSHAPE::INPUT_LOW, { _( "Input low" ), BITMAPS::pinshape_active_low_input } },
|
||||
{ GRAPHIC_PINSHAPE::CLOCK_LOW, { _( "Clock low" ), BITMAPS::pinshape_clock_active_low } },
|
||||
{ GRAPHIC_PINSHAPE::OUTPUT_LOW, { _( "Output low" ),
|
||||
BITMAPS::pinshape_active_low_output } },
|
||||
{ GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK, { _( "Falling edge clock" ),
|
||||
BITMAPS::pinshape_clock_fall } },
|
||||
{ GRAPHIC_PINSHAPE::NONLOGIC, { _( "NonLogic" ),
|
||||
BITMAPS::pinshape_nonlogic } },
|
||||
{ GRAPHIC_PINSHAPE::LINE, { _( "Line" ), BITMAPS::pinshape_normal } },
|
||||
{ GRAPHIC_PINSHAPE::INVERTED, { _( "Inverted" ), BITMAPS::pinshape_invert } },
|
||||
{ GRAPHIC_PINSHAPE::CLOCK, { _( "Clock" ), BITMAPS::pinshape_clock_normal } },
|
||||
{ GRAPHIC_PINSHAPE::INVERTED_CLOCK, { _( "Inverted clock" ), BITMAPS::pinshape_clock_invert } },
|
||||
{ GRAPHIC_PINSHAPE::INPUT_LOW, { _( "Input low" ), BITMAPS::pinshape_active_low_input } },
|
||||
{ GRAPHIC_PINSHAPE::CLOCK_LOW, { _( "Clock low" ), BITMAPS::pinshape_clock_active_low } },
|
||||
{ GRAPHIC_PINSHAPE::OUTPUT_LOW, { _( "Output low" ), BITMAPS::pinshape_active_low_output } },
|
||||
{ GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK, { _( "Falling edge clock" ), BITMAPS::pinshape_clock_fall } },
|
||||
{ GRAPHIC_PINSHAPE::NONLOGIC, { _( "NonLogic" ), BITMAPS::pinshape_nonlogic } },
|
||||
};
|
||||
|
||||
g_pinOrientations = {
|
||||
{ PIN_ORIENTATION::PIN_RIGHT, { _( "Right" ), BITMAPS::pinorient_right } },
|
||||
{ PIN_ORIENTATION::PIN_LEFT, { _( "Left" ), BITMAPS::pinorient_left } },
|
||||
{ PIN_ORIENTATION::PIN_UP, { _( "Up" ), BITMAPS::pinorient_up } },
|
||||
{ PIN_ORIENTATION::PIN_DOWN, { _( "Down" ), BITMAPS::pinorient_down } },
|
||||
{ PIN_ORIENTATION::PIN_RIGHT, { _( "Right" ), BITMAPS::pinorient_right } },
|
||||
{ PIN_ORIENTATION::PIN_LEFT, { _( "Left" ), BITMAPS::pinorient_left } },
|
||||
{ PIN_ORIENTATION::PIN_UP, { _( "Up" ), BITMAPS::pinorient_up } },
|
||||
{ PIN_ORIENTATION::PIN_DOWN, { _( "Down" ), BITMAPS::pinorient_down } },
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -1614,7 +1614,9 @@ void SCH_EDIT_FRAME::RefreshOperatingPointDisplay()
|
||||
{
|
||||
std::vector<EMBEDDED_FILES*> embeddedFilesStack;
|
||||
embeddedFilesStack.push_back( m_schematic->GetEmbeddedFiles() );
|
||||
embeddedFilesStack.push_back( symbol->GetEmbeddedFiles() );
|
||||
|
||||
if( EMBEDDED_FILES* symbolEmbeddedFiles = symbol->GetEmbeddedFiles() )
|
||||
embeddedFilesStack.push_back( symbolEmbeddedFiles );
|
||||
|
||||
simLibMgr.SetFilesStack( embeddedFilesStack );
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user