mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 02:03:12 +02:00
Compare commits
344 Commits
f74f3fb8a0
...
872d2e9724
Author | SHA1 | Date | |
---|---|---|---|
|
872d2e9724 | ||
|
45166bf5c3 | ||
|
6ab6283e2e | ||
|
fc7d91214d | ||
|
dcbadb5857 | ||
|
3b97804cb6 | ||
|
e72def55a9 | ||
|
fcf40deae2 | ||
|
ef602be91f | ||
|
bd5cb76fcd | ||
|
de26550b5a | ||
|
7deff606be | ||
|
6e2b20ed0e | ||
|
2f1a91279f | ||
|
6e316d9faa | ||
|
3c5fb9d90d | ||
|
11cc86e586 | ||
|
5e2fd084b9 | ||
|
a1f816e8be | ||
|
abf3438ed6 | ||
|
cb4c8e6647 | ||
|
d356073798 | ||
|
b38d9d7f81 | ||
|
297ca1bb7b | ||
|
f9e25c2e06 | ||
|
b0a6dc4acf | ||
|
59dcdb4a4f | ||
|
39889f8446 | ||
|
3f8abe3744 | ||
|
0acc659676 | ||
|
78c93ee0fb | ||
|
9622cf8ff1 | ||
|
3cca1e87d8 | ||
|
aac15f4596 | ||
|
ceed9ca5f8 | ||
|
6c4edd178e | ||
|
cfa87cfc2c | ||
|
b3b75270ce | ||
|
f1db857804 | ||
|
cdd43fe5fa | ||
|
836b3267bb | ||
|
66930ea703 | ||
|
0e60722c4b | ||
|
2b3f21b9ff | ||
|
dd8a059925 | ||
|
63fe36847e | ||
|
99a16e4306 | ||
|
5ca8fdb7cd | ||
|
88ee07e910 | ||
|
71907f0888 | ||
|
6397b6d3c6 | ||
|
d1356140fa | ||
|
30d158a60f | ||
|
c674e1749e | ||
|
c783218f93 | ||
|
07885145b3 | ||
|
500da3c15d | ||
|
fbd2e36b79 | ||
|
61fd5e7413 | ||
|
bf8d2d7bf6 | ||
|
2a93e1bfb1 | ||
|
9f097d5ae8 | ||
|
80996e70f8 | ||
|
ec8131c7bf | ||
|
2ad7c345ec | ||
|
a2e0d07c87 | ||
|
4e1dd875ae | ||
|
c737e0b360 | ||
|
c29aa7643c | ||
|
58b2ccb3d5 | ||
|
a05f8b9e36 | ||
|
9f2b84ba52 | ||
|
b345e34423 | ||
|
081b414ad5 | ||
|
58caa5c496 | ||
|
f0f5472e4d | ||
|
0b174b5227 | ||
|
765838ecf7 | ||
|
2276ae05e3 | ||
|
6838d55051 | ||
|
95abb3be8b | ||
|
41425ac32d | ||
|
0b47169387 | ||
|
7b98a8d697 | ||
|
4184e60e24 | ||
|
36eb0e4a11 | ||
|
49c7f62548 | ||
|
35f0213011 | ||
|
cb87f83dfc | ||
|
ead7de69ca | ||
|
dedc10a163 | ||
|
330361d0cb | ||
|
01d32211ba | ||
|
09c40a0e0f | ||
|
fdbf740ee2 | ||
|
93b0004175 | ||
|
0a162ded84 | ||
|
01f6776226 | ||
|
adbc80aade | ||
|
0b102fc085 | ||
|
22288e02a2 | ||
|
58f4ca7ed6 | ||
|
8ae2ad3586 | ||
|
0f97f51ba1 | ||
|
0c35068e8d | ||
|
f66cbaf43a | ||
|
ac1b44715b | ||
|
b98621c8c8 | ||
|
28141ed350 | ||
|
c33da162d6 | ||
|
288c93198a | ||
|
46c8a6ee95 | ||
|
bbecc4eaa8 | ||
|
fef84a2c6a | ||
|
963ec84587 | ||
|
4a87dbe472 | ||
|
7d67f82217 | ||
|
b7fee045e3 | ||
|
0e5a87546b | ||
|
5489daf279 | ||
|
922699f388 | ||
|
702f774a1f | ||
|
264029c8e9 | ||
|
c889a7fa16 | ||
|
fb558eee3c | ||
|
6f352ccd96 | ||
|
c163f0a24c | ||
|
fd7da138fd | ||
|
3bdf44d4a4 | ||
|
168975b0a8 | ||
|
03b3b642b0 | ||
|
f9f5bb9ed1 | ||
|
4254673be5 | ||
|
0ce952e705 | ||
|
9ffb0c8b96 | ||
|
44cc5b8e93 | ||
|
a857ea77d9 | ||
|
bae5d43c45 | ||
|
2cbd441042 | ||
|
9a7088c03c | ||
|
7a09960b46 | ||
|
05d04e665a | ||
|
9f1aa612ec | ||
|
9de2548064 | ||
|
825585847b | ||
|
6c8f25b418 | ||
|
a899da7cb7 | ||
|
a49e3b9cc5 | ||
|
9bc1cf006f | ||
|
dc7e0665c3 | ||
|
344fab5741 | ||
|
9342aea7fa | ||
|
11c5e03890 | ||
|
3deb06bf82 | ||
|
5c865cab36 | ||
|
f7fd832c67 | ||
|
62e220a8db | ||
|
622ddd3a37 | ||
|
9f06d1f66b | ||
|
f84ba3004d | ||
|
e85a8056f5 | ||
|
173e02eff7 | ||
|
876c905e2b | ||
|
5914b5aaa8 | ||
|
2346be9768 | ||
|
d4b08f0a8a | ||
|
f18c4a05fd | ||
|
ad80113f47 | ||
|
8f0b3b59f0 | ||
|
bf82217217 | ||
|
d9741fd46a | ||
|
826f15a103 | ||
|
edf8f45351 | ||
|
202619cd43 | ||
|
8709f73b98 | ||
|
e76b2089bb | ||
|
2e0088593e | ||
|
b34746e06b | ||
|
9b14434fc3 | ||
|
1f1f8699e0 | ||
|
0ede830f54 | ||
|
de8c4d4b01 | ||
|
e01dfd3158 | ||
|
cff261ce2e | ||
|
6a171e11fb | ||
|
1e272ca21b | ||
|
60a5c8b742 | ||
|
9cba910d53 | ||
|
35ffb28335 | ||
|
98b63389c1 | ||
|
ce140d8dfc | ||
|
5e2ec53165 | ||
|
d5e342b64d | ||
|
eedfb7a573 | ||
|
c95c15dd4e | ||
|
4a4725c906 | ||
|
667dccb163 | ||
|
4fb76404bc | ||
|
267ee811a7 | ||
|
e016dc52fd | ||
|
c4d9338097 | ||
|
5d967289ee | ||
|
262f1fdabb | ||
|
c9476caebf | ||
|
a8d6292d61 | ||
|
4953e80122 | ||
|
bd04d508e0 | ||
|
82c61efcbd | ||
|
4024a15a17 | ||
|
0c8e7a7137 | ||
|
1f44417ad0 | ||
|
5b31b11731 | ||
|
5fb55ccb30 | ||
|
2eb7ba2fb9 | ||
|
2c4d792358 | ||
|
77a2330a33 | ||
|
7b4f4540b4 | ||
|
1885f4bdee | ||
|
eba8d0748c | ||
|
f5904cf2ac | ||
|
bbc762a546 | ||
|
c6c8e19e39 | ||
|
1309b436da | ||
|
c47b7459aa | ||
|
a2e98fb53c | ||
|
2321285c16 | ||
|
2cdeb0cd7c | ||
|
4af585c531 | ||
|
8c6f057f6c | ||
|
9d7db3d135 | ||
|
b22f259ccb | ||
|
b86cddbbe9 | ||
|
053c46aa72 | ||
|
4610a49323 | ||
|
68f9b74ae9 | ||
|
814f78f2b2 | ||
|
be57c1a380 | ||
|
194b7f9dc5 | ||
|
c6fcf7e0b8 | ||
|
cf09e8ae88 | ||
|
1ff5f09c3a | ||
|
7610c02fed | ||
|
7fd8b515b5 | ||
|
ba84f50997 | ||
|
acc7b1e508 | ||
|
67feb2e139 | ||
|
6f59821930 | ||
|
6592c75345 | ||
|
1a3f6028f8 | ||
|
fe4ddc66eb | ||
|
e3b550dd13 | ||
|
1baa28a1e6 | ||
|
0f1b514964 | ||
|
aeafbe48fe | ||
|
2b8542861c | ||
|
9dd642b66c | ||
|
d5c0d040b4 | ||
|
b3de964eff | ||
|
8acf5c1a25 | ||
|
e282dca102 | ||
|
a811f61c39 | ||
|
50274352b1 | ||
|
ec7b831be3 | ||
|
9525fae7c8 | ||
|
e8cec41355 | ||
|
8a60893249 | ||
|
7115f9e716 | ||
|
736d87aa35 | ||
|
eb6b2de648 | ||
|
83fab7b02c | ||
|
af852ea15d | ||
|
fd57f637ac | ||
|
5c240efd75 | ||
|
b01c1f39c1 | ||
|
3e019ee4ae | ||
|
4f32146f9a | ||
|
9bc463606a | ||
|
747106ea37 | ||
|
94d83773d0 | ||
|
3a8dd87db4 | ||
|
2cf6ec2411 | ||
|
408e1feae2 | ||
|
ea8206eca5 | ||
|
6dd4e01f16 | ||
|
3eb6caaec6 | ||
|
9725ac2215 | ||
|
b349f1988a | ||
|
963aa47778 | ||
|
2f21414186 | ||
|
8bd6da3ec9 | ||
|
19e4c3f498 | ||
|
57ad779797 | ||
|
46084c04b9 | ||
|
635445c096 | ||
|
394f6be509 | ||
|
fe4de09d71 | ||
|
b832ae7f45 | ||
|
8592b2ee70 | ||
|
1e76f1a11d | ||
|
0a767acb3a | ||
|
29c4d9b197 | ||
|
2db8c6eca0 | ||
|
9c577a4f4c | ||
|
0f0527bd03 | ||
|
3d8803f579 | ||
|
4bebd09bd0 | ||
|
7f4a1bf64a | ||
|
ab93dd8a68 | ||
|
cb620338db | ||
|
dad60f99c0 | ||
|
4660c72c69 | ||
|
b5f3d4cf7b | ||
|
412fc1e6d9 | ||
|
8997b7bcf7 | ||
|
5b86f20476 | ||
|
7841476ed6 | ||
|
a034c30563 | ||
|
6dd03bc735 | ||
|
1df5ad0e4c | ||
|
9013ddae43 | ||
|
bfe805a221 | ||
|
843eea259d | ||
|
cc9ec7c01c | ||
|
537ea6ee0c | ||
|
cc9402ac9d | ||
|
20a80a5f94 | ||
|
ef0ca4840e | ||
|
4e7fa189aa | ||
|
87ee9c4b49 | ||
|
9cabceb773 | ||
|
ba9e9a2368 | ||
|
b709439b65 | ||
|
ad7235e386 | ||
|
3058bc6355 | ||
|
9808889c9c | ||
|
8c3026cf1a | ||
|
0477fb65ec | ||
|
cec87c4096 | ||
|
9778ca739b | ||
|
8cffe509fa | ||
|
47a8701a01 | ||
|
0269851994 | ||
|
2757067986 | ||
|
62d8cfbf9f |
@ -8,6 +8,8 @@ win64_build:
|
|||||||
interruptible: false
|
interruptible: false
|
||||||
image: registry.gitlab.com/kicad/kicad-ci/windows-build-image/ltsc2022-msvc:latest
|
image: registry.gitlab.com/kicad/kicad-ci/windows-build-image/ltsc2022-msvc:latest
|
||||||
variables:
|
variables:
|
||||||
|
VCPKG_BINARY_SOURCES: 'nuget,gitlab,readwrite'
|
||||||
|
VCPKG_DISABLE_COMPILER_TRACKING: '1'
|
||||||
# Switch the compressor to fastzip and reduce the compression level
|
# Switch the compressor to fastzip and reduce the compression level
|
||||||
FF_USE_FASTZIP: "true"
|
FF_USE_FASTZIP: "true"
|
||||||
CACHE_COMPRESSION_LEVEL: "fast"
|
CACHE_COMPRESSION_LEVEL: "fast"
|
||||||
@ -23,6 +25,7 @@ win64_build:
|
|||||||
script:
|
script:
|
||||||
- C:\builder\build.ps1 -Env -Arch x64
|
- 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
|
- $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
|
- mkdir -p build/windows -Force
|
||||||
- cd build/windows
|
- cd build/windows
|
||||||
- cmake `
|
- cmake `
|
||||||
@ -37,8 +40,6 @@ win64_build:
|
|||||||
../../
|
../../
|
||||||
- cmake --build . 2>&1 | tee compilation_log.txt
|
- cmake --build . 2>&1 | tee compilation_log.txt
|
||||||
- cd ../../
|
- cd ../../
|
||||||
after_script:
|
|
||||||
- Get-Content -Path C:\builder\vcpkg\buildtrees\wxpython-33\python3-tool-post-install-err.log
|
|
||||||
artifacts:
|
artifacts:
|
||||||
# Only save the artifacts that are needed for running the tests in the next stage
|
# Only save the artifacts that are needed for running the tests in the next stage
|
||||||
# and the compilation log. The entire build directory is too large to save as an
|
# and the compilation log. The entire build directory is too large to save as an
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
variables:
|
variables:
|
||||||
BOOST_TEST_LOGGER: 'JUNIT,warning,test_results.${TEST}.xml:HRF,message'
|
BOOST_TEST_LOGGER: 'JUNIT,warning,test_results.${TEST}.xml:HRF,message'
|
||||||
CTEST_OUTPUT_ON_FAILURE: 1
|
CTEST_OUTPUT_ON_FAILURE: 1
|
||||||
|
BOOST_TEST_CATCH_SYSTEM_ERRORS: 'no'
|
||||||
script:
|
script:
|
||||||
- cd build/linux/qa
|
- cd build/linux/qa
|
||||||
- ctest -R qa_${TEST}
|
- ctest -R qa_${TEST}
|
||||||
|
@ -368,11 +368,12 @@ private:
|
|||||||
void createTrackWithMargin( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDstContainer,
|
void createTrackWithMargin( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDstContainer,
|
||||||
PCB_LAYER_ID aLayer, int aMargin = 0 );
|
PCB_LAYER_ID aLayer, int aMargin = 0 );
|
||||||
|
|
||||||
|
// Generate the pad shape on board layers. The pad hole is not generated by createPadWithMargin
|
||||||
void createPadWithMargin( const PAD *aPad, CONTAINER_2D_BASE* aDstContainer,
|
void createPadWithMargin( const PAD *aPad, CONTAINER_2D_BASE* aDstContainer,
|
||||||
PCB_LAYER_ID aLayer, const VECTOR2I& aMargin ) const;
|
PCB_LAYER_ID aLayer, const VECTOR2I& aMargin ) const;
|
||||||
|
|
||||||
void createPadWithHole( const PAD* aPad, CONTAINER_2D_BASE* aDstContainer,
|
// Generate the hole shape of aPad, stored in aDstContainer
|
||||||
int aInflateValue );
|
void createPadHoleShape( const PAD* aPad, CONTAINER_2D_BASE* aDstContainer, int aInflateValue );
|
||||||
|
|
||||||
void addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
|
void addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
|
||||||
PCB_LAYER_ID aLayerId );
|
PCB_LAYER_ID aLayerId );
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
#include <geometry/shape_segment.h>
|
#include <geometry/shape_segment.h>
|
||||||
#include <geometry/geometry_utils.h>
|
#include <geometry/geometry_utils.h>
|
||||||
#include <geometry/shape_circle.h>
|
#include <geometry/shape_circle.h>
|
||||||
|
#include <geometry/roundrect.h>
|
||||||
#include <geometry/shape_rect.h>
|
#include <geometry/shape_rect.h>
|
||||||
#include <geometry/shape_simple.h>
|
#include <geometry/shape_simple.h>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@ -473,12 +474,12 @@ void BOARD_ADAPTER::createPadWithMargin( const PAD* aPad, CONTAINER_2D_BASE* aCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BOARD_ADAPTER::createPadWithHole( const PAD* aPad, CONTAINER_2D_BASE* aDstContainer,
|
void BOARD_ADAPTER::createPadHoleShape( const PAD* aPad, CONTAINER_2D_BASE* aDstContainer,
|
||||||
int aInflateValue )
|
int aInflateValue )
|
||||||
{
|
{
|
||||||
if( !aPad->HasHole() )
|
if( !aPad->HasHole() )
|
||||||
{
|
{
|
||||||
wxLogTrace( m_logTrace, wxT( "BOARD_ADAPTER::createPadWithHole - found an invalid pad" ) );
|
wxLogTrace( m_logTrace, wxT( "BOARD_ADAPTER::createPadHole pad has no hole" ) );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -649,16 +650,40 @@ void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aConta
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::vector<VECTOR2I> pts = aShape->GetRectCorners();
|
if( aShape->GetCornerRadius() > 0 )
|
||||||
|
{
|
||||||
|
ROUNDRECT rr( SHAPE_RECT( aShape->GetPosition(),
|
||||||
|
aShape->GetRectangleWidth(),
|
||||||
|
aShape->GetRectangleHeight() ),
|
||||||
|
aShape->GetCornerRadius() );
|
||||||
|
SHAPE_POLY_SET poly;
|
||||||
|
rr.TransformToPolygon( poly );
|
||||||
|
SHAPE_LINE_CHAIN& r_outline = poly.Outline( 0 );
|
||||||
|
r_outline.SetClosed( true );
|
||||||
|
|
||||||
addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( pts[0] ), TO_SFVEC2F( pts[1] ),
|
for( int ii = 0; ii < r_outline.PointCount(); ii++ )
|
||||||
linewidth3DU, *aOwner );
|
{
|
||||||
addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( pts[1] ), TO_SFVEC2F( pts[2] ),
|
addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( r_outline.CPoint( ii ) ),
|
||||||
linewidth3DU, *aOwner );
|
TO_SFVEC2F( r_outline.CPoint( ii+1 ) ),
|
||||||
addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( pts[2] ), TO_SFVEC2F( pts[3] ),
|
linewidth3DU, *aOwner );
|
||||||
linewidth3DU, *aOwner );
|
}
|
||||||
addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( pts[3] ), TO_SFVEC2F( pts[0] ),
|
|
||||||
linewidth3DU, *aOwner );
|
addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( r_outline.CLastPoint() ),
|
||||||
|
TO_SFVEC2F( r_outline.CPoint( 0 ) ), linewidth3DU, *aOwner );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::vector<VECTOR2I> pts = aShape->GetRectCorners();
|
||||||
|
|
||||||
|
addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( pts[0] ), TO_SFVEC2F( pts[1] ),
|
||||||
|
linewidth3DU, *aOwner );
|
||||||
|
addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( pts[1] ), TO_SFVEC2F( pts[2] ),
|
||||||
|
linewidth3DU, *aOwner );
|
||||||
|
addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( pts[2] ), TO_SFVEC2F( pts[3] ),
|
||||||
|
linewidth3DU, *aOwner );
|
||||||
|
addROUND_SEGMENT_2D( aContainer, TO_SFVEC2F( pts[3] ), TO_SFVEC2F( pts[0] ),
|
||||||
|
linewidth3DU, *aOwner );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -507,27 +507,32 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
|||||||
{
|
{
|
||||||
for( PAD* pad : footprint->Pads() )
|
for( PAD* pad : footprint->Pads() )
|
||||||
{
|
{
|
||||||
const VECTOR2I padHole = pad->GetDrillSize();
|
// Note: holes of NPTH are already built by GetBoardPolygonOutlines
|
||||||
|
if( !pad->HasHole() )
|
||||||
if( !padHole.x ) // Not drilled pad like SMD pad
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// The hole in the body is inflated by copper thickness, if not plated, no copper
|
|
||||||
int inflate = 0;
|
|
||||||
|
|
||||||
if( pad->GetAttribute() != PAD_ATTRIB::NPTH )
|
|
||||||
inflate = KiROUND( GetHolePlatingThickness() / 2.0 );
|
|
||||||
|
|
||||||
m_holeCount++;
|
m_holeCount++;
|
||||||
double holeDiameter = ( pad->GetDrillSize().x + pad->GetDrillSize().y ) / 2.0;
|
double holeDiameter = ( pad->GetDrillSize().x + pad->GetDrillSize().y ) / 2.0;
|
||||||
m_averageHoleDiameter += static_cast<float>( holeDiameter * m_biuTo3Dunits );
|
m_averageHoleDiameter += static_cast<float>( holeDiameter * m_biuTo3Dunits );
|
||||||
|
|
||||||
createPadWithHole( pad, &m_TH_ODs, inflate );
|
if( pad->GetAttribute() == PAD_ATTRIB::NPTH )
|
||||||
|
{
|
||||||
|
// Ensure the silk drawings are clipped to the NPTH hole, like other pad/via holes
|
||||||
|
// even if the clip to board body is not activated (remember NPTH holes are part of
|
||||||
|
// the board body)
|
||||||
|
createPadHoleShape( pad, &m_TH_ODs, 0 );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The hole in the body is inflated by copper thickness
|
||||||
|
int inflate = KiROUND( GetHolePlatingThickness() / 2.0 );
|
||||||
|
|
||||||
|
createPadHoleShape( pad, &m_TH_ODs, inflate );
|
||||||
|
|
||||||
if( cfg.clip_silk_on_via_annuli )
|
if( cfg.clip_silk_on_via_annuli )
|
||||||
createPadWithHole( pad, &m_viaAnnuli, inflate );
|
createPadHoleShape( pad, &m_viaAnnuli, inflate );
|
||||||
|
|
||||||
createPadWithHole( pad, &m_TH_IDs, 0 );
|
createPadHoleShape( pad, &m_TH_IDs, 0 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -539,9 +544,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
|||||||
{
|
{
|
||||||
for( PAD* pad : footprint->Pads() )
|
for( PAD* pad : footprint->Pads() )
|
||||||
{
|
{
|
||||||
const VECTOR2I padHole = pad->GetDrillSize();
|
if( !pad->HasHole() )
|
||||||
|
|
||||||
if( !padHole.x ) // Not drilled pad like SMD pad
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// The hole in the body is inflated by copper thickness.
|
// The hole in the body is inflated by copper thickness.
|
||||||
|
@ -35,14 +35,22 @@
|
|||||||
#include <advanced_config.h>
|
#include <advanced_config.h>
|
||||||
#include <build_version.h>
|
#include <build_version.h>
|
||||||
#include <board.h>
|
#include <board.h>
|
||||||
|
#include <pad.h>
|
||||||
|
#include <pcb_field.h>
|
||||||
#include <reporter.h>
|
#include <reporter.h>
|
||||||
#include <gal/opengl/gl_context_mgr.h>
|
#include <gal/opengl/gl_context_mgr.h>
|
||||||
#include <core/profile.h> // To use GetRunningMicroSecs or another profiling utility
|
#include <core/profile.h> // To use GetRunningMicroSecs or another profiling utility
|
||||||
#include <bitmaps.h>
|
#include <bitmaps.h>
|
||||||
|
#include <kiway_holder.h>
|
||||||
|
#include <kiway.h>
|
||||||
#include <macros.h>
|
#include <macros.h>
|
||||||
#include <pgm_base.h>
|
#include <pgm_base.h>
|
||||||
#include <settings/settings_manager.h>
|
#include <settings/settings_manager.h>
|
||||||
#include <tool/tool_dispatcher.h>
|
#include <tool/tool_dispatcher.h>
|
||||||
|
#include <string_utils.h>
|
||||||
|
#include <mail_type.h>
|
||||||
|
#include <kiway_express.h>
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include <widgets/wx_busy_indicator.h>
|
#include <widgets/wx_busy_indicator.h>
|
||||||
|
|
||||||
@ -92,28 +100,12 @@ END_EVENT_TABLE()
|
|||||||
EDA_3D_CANVAS::EDA_3D_CANVAS( wxWindow* aParent, const wxGLAttributes& aGLAttribs,
|
EDA_3D_CANVAS::EDA_3D_CANVAS( wxWindow* aParent, const wxGLAttributes& aGLAttribs,
|
||||||
BOARD_ADAPTER& aBoardAdapter, CAMERA& aCamera,
|
BOARD_ADAPTER& aBoardAdapter, CAMERA& aCamera,
|
||||||
S3D_CACHE* a3DCachePointer ) :
|
S3D_CACHE* a3DCachePointer ) :
|
||||||
HIDPI_GL_3D_CANVAS( EDA_DRAW_PANEL_GAL::GetVcSettings(), aCamera, aParent, aGLAttribs,
|
HIDPI_GL_3D_CANVAS( EDA_DRAW_PANEL_GAL::GetVcSettings(), aCamera, aParent, aGLAttribs,
|
||||||
EDA_3D_CANVAS_ID, wxDefaultPosition,
|
EDA_3D_CANVAS_ID, wxDefaultPosition,
|
||||||
wxDefaultSize, wxFULL_REPAINT_ON_RESIZE ),
|
wxDefaultSize, wxFULL_REPAINT_ON_RESIZE ),
|
||||||
m_eventDispatcher( nullptr ),
|
m_editing_timeout_timer( this, wxID_HIGHEST + 1 ),
|
||||||
m_parentStatusBar( nullptr ),
|
m_redraw_trigger_timer( this, wxID_HIGHEST + 2 ),
|
||||||
m_parentInfoBar( nullptr ),
|
m_boardAdapter( aBoardAdapter )
|
||||||
m_glRC( nullptr ),
|
|
||||||
m_is_opengl_initialized( false ),
|
|
||||||
m_is_opengl_version_supported( true ),
|
|
||||||
m_editing_timeout_timer( this, wxID_HIGHEST + 1 ),
|
|
||||||
m_redraw_trigger_timer( this, wxID_HIGHEST + 2 ),
|
|
||||||
m_render_pivot( false ),
|
|
||||||
m_camera_moving_speed( 1.0f ),
|
|
||||||
m_strtime_camera_movement( 0 ),
|
|
||||||
m_animation_enabled( true ),
|
|
||||||
m_moving_speed_multiplier( 3 ),
|
|
||||||
m_boardAdapter( aBoardAdapter ),
|
|
||||||
m_3d_render( nullptr ),
|
|
||||||
m_opengl_supports_raytracing( true ),
|
|
||||||
m_render_raytracing_was_requested( false ),
|
|
||||||
m_accelerator3DShapes( nullptr ),
|
|
||||||
m_currentRollOverItem( nullptr )
|
|
||||||
{
|
{
|
||||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_CANVAS::EDA_3D_CANVAS" ) );
|
wxLogTrace( m_logTrace, wxT( "EDA_3D_CANVAS::EDA_3D_CANVAS" ) );
|
||||||
|
|
||||||
@ -481,8 +473,10 @@ void EDA_3D_CANVAS::DoRePaint()
|
|||||||
|
|
||||||
if( m_camera_is_moving )
|
if( m_camera_is_moving )
|
||||||
{
|
{
|
||||||
const int64_t curtime_delta = GetRunningMicroSecs() - m_strtime_camera_movement;
|
const int64_t curtime_delta = GetRunningMicroSecs() - m_strtime_camera_movement;
|
||||||
curtime_delta_s = ( curtime_delta / 1e6 ) * m_camera_moving_speed;
|
// Convert microseconds to seconds as float and apply speed multiplier
|
||||||
|
curtime_delta_s = static_cast<float>( static_cast<double>( curtime_delta ) / 1e6 )
|
||||||
|
* m_camera_moving_speed;
|
||||||
m_camera.Interpolate( curtime_delta_s );
|
m_camera.Interpolate( curtime_delta_s );
|
||||||
|
|
||||||
if( curtime_delta_s > 1.0f )
|
if( curtime_delta_s > 1.0f )
|
||||||
@ -751,7 +745,8 @@ void EDA_3D_CANVAS::RenderToFrameBuffer( unsigned char* buffer, int width, int h
|
|||||||
if( m_camera_is_moving )
|
if( m_camera_is_moving )
|
||||||
{
|
{
|
||||||
const int64_t curtime_delta = GetRunningMicroSecs() - m_strtime_camera_movement;
|
const int64_t curtime_delta = GetRunningMicroSecs() - m_strtime_camera_movement;
|
||||||
curtime_delta_s = ( curtime_delta / 1e6 ) * m_camera_moving_speed;
|
curtime_delta_s = static_cast<float>( static_cast<double>( curtime_delta ) / 1e6 )
|
||||||
|
* m_camera_moving_speed;
|
||||||
m_camera.Interpolate( curtime_delta_s );
|
m_camera.Interpolate( curtime_delta_s );
|
||||||
|
|
||||||
if( curtime_delta_s > 1.0f )
|
if( curtime_delta_s > 1.0f )
|
||||||
@ -887,7 +882,7 @@ void EDA_3D_CANVAS::OnZoomGesture( wxZoomGestureEvent& aEvent )
|
|||||||
m_camera.Pan( aEvent.GetPosition() );
|
m_camera.Pan( aEvent.GetPosition() );
|
||||||
m_camera.SetCurMousePosition( aEvent.GetPosition() );
|
m_camera.SetCurMousePosition( aEvent.GetPosition() );
|
||||||
|
|
||||||
m_camera.Zoom( aEvent.GetZoomFactor() / m_gestureLastZoomFactor );
|
m_camera.Zoom( static_cast<float>( aEvent.GetZoomFactor() / m_gestureLastZoomFactor ) );
|
||||||
|
|
||||||
m_gestureLastZoomFactor = aEvent.GetZoomFactor();
|
m_gestureLastZoomFactor = aEvent.GetZoomFactor();
|
||||||
|
|
||||||
@ -930,7 +925,7 @@ void EDA_3D_CANVAS::OnRotateGesture( wxRotateGestureEvent& aEvent )
|
|||||||
if( m_camera_is_moving )
|
if( m_camera_is_moving )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_camera.RotateScreen( m_gestureLastAngle - aEvent.GetRotationAngle() );
|
m_camera.RotateScreen( static_cast<float>( m_gestureLastAngle - aEvent.GetRotationAngle() ) );
|
||||||
m_gestureLastAngle = aEvent.GetRotationAngle();
|
m_gestureLastAngle = aEvent.GetRotationAngle();
|
||||||
|
|
||||||
DisplayStatus();
|
DisplayStatus();
|
||||||
@ -1066,9 +1061,45 @@ void EDA_3D_CANVAS::OnLeftDown( wxMouseEvent& event )
|
|||||||
{
|
{
|
||||||
RAY mouseRay = getRayAtCurrentMousePosition();
|
RAY mouseRay = getRayAtCurrentMousePosition();
|
||||||
|
|
||||||
BOARD_ITEM *intersectedBoardItem = m_3d_render_raytracing->IntersectBoardItem( mouseRay );
|
BOARD_ITEM* intersectedBoardItem = m_3d_render_raytracing->IntersectBoardItem( mouseRay );
|
||||||
|
|
||||||
// !TODO: send a selection item to pcbnew, eg: via kiway?
|
if( intersectedBoardItem )
|
||||||
|
{
|
||||||
|
FOOTPRINT* footprint = nullptr;
|
||||||
|
|
||||||
|
switch( intersectedBoardItem->Type() )
|
||||||
|
{
|
||||||
|
case PCB_FOOTPRINT_T:
|
||||||
|
footprint = static_cast<FOOTPRINT*>( intersectedBoardItem );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PCB_PAD_T:
|
||||||
|
footprint = static_cast<PAD*>( intersectedBoardItem )->GetParentFootprint();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PCB_FIELD_T:
|
||||||
|
footprint = static_cast<PCB_FIELD*>( intersectedBoardItem )->GetParentFootprint();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( footprint )
|
||||||
|
{
|
||||||
|
std::string command =
|
||||||
|
fmt::format( "$SELECT: 0,F{}",
|
||||||
|
EscapeString( footprint->GetReference(), CTX_IPC ).ToStdString() );
|
||||||
|
|
||||||
|
EDA_3D_VIEWER_FRAME* frame = static_cast<EDA_3D_VIEWER_FRAME*>( GetParent() );
|
||||||
|
|
||||||
|
if( frame )
|
||||||
|
{
|
||||||
|
frame->Kiway().ExpressMail( FRAME_PCB_EDITOR, MAIL_SELECTION, command, frame );
|
||||||
|
frame->Kiway().ExpressMail( FRAME_SCH, MAIL_SELECTION, command, frame );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1088,14 +1119,14 @@ void EDA_3D_CANVAS::OnLeftUp( wxMouseEvent& event )
|
|||||||
int logicalW = logicalSize.GetWidth();
|
int logicalW = logicalSize.GetWidth();
|
||||||
int logicalH = logicalSize.GetHeight();
|
int logicalH = logicalSize.GetHeight();
|
||||||
|
|
||||||
int gizmo_x, gizmo_y, gizmo_width, gizmo_height;
|
int gizmo_x = 0, gizmo_y = 0, gizmo_width = 0, gizmo_height = 0;
|
||||||
std::tie( gizmo_x, gizmo_y, gizmo_width, gizmo_height ) = m_3d_render_opengl->getGizmoViewport();
|
std::tie( gizmo_x, gizmo_y, gizmo_width, gizmo_height ) = m_3d_render_opengl->getGizmoViewport();
|
||||||
|
|
||||||
float scaleX = static_cast<float>( gizmo_width ) / logicalW;
|
float scaleX = static_cast<float>( static_cast<double>( gizmo_width ) / static_cast<double>( logicalW ) );
|
||||||
float scaleY = static_cast<float>( gizmo_height ) / logicalH;
|
float scaleY = static_cast<float>( static_cast<double>( gizmo_height ) / static_cast<double>( logicalH ) );
|
||||||
|
|
||||||
int scaledMouseX = static_cast<int>( event.GetX() * scaleX );
|
int scaledMouseX = static_cast<int>( static_cast<float>( event.GetX() ) * scaleX );
|
||||||
int scaledMouseY = static_cast<int>( ( logicalH - event.GetY() ) * scaleY );
|
int scaledMouseY = static_cast<int>( static_cast<float>( logicalH - event.GetY() ) * scaleY );
|
||||||
|
|
||||||
m_3d_render_opengl->handleGizmoMouseInput( scaledMouseX, scaledMouseY );
|
m_3d_render_opengl->handleGizmoMouseInput( scaledMouseX, scaledMouseY );
|
||||||
Refresh();
|
Refresh();
|
||||||
@ -1229,7 +1260,7 @@ void EDA_3D_CANVAS::request_start_moving_camera( float aMovingSpeed, bool aRende
|
|||||||
|
|
||||||
// Map speed multiplier option to actual multiplier value
|
// Map speed multiplier option to actual multiplier value
|
||||||
// [1,2,3,4,5] -> [0.25, 0.5, 1, 2, 4]
|
// [1,2,3,4,5] -> [0.25, 0.5, 1, 2, 4]
|
||||||
aMovingSpeed *= ( 1 << m_moving_speed_multiplier ) / 8.0f;
|
aMovingSpeed *= static_cast<float>( ( 1 << m_moving_speed_multiplier ) ) / 8.0f;
|
||||||
|
|
||||||
m_render_pivot = aRenderPivot;
|
m_render_pivot = aRenderPivot;
|
||||||
m_camera_moving_speed = aMovingSpeed;
|
m_camera_moving_speed = aMovingSpeed;
|
||||||
@ -1249,7 +1280,7 @@ void EDA_3D_CANVAS::move_pivot_based_on_cur_mouse_position()
|
|||||||
{
|
{
|
||||||
RAY mouseRay = getRayAtCurrentMousePosition();
|
RAY mouseRay = getRayAtCurrentMousePosition();
|
||||||
|
|
||||||
float hit_t;
|
float hit_t = 0.0f;
|
||||||
|
|
||||||
// Test it with the board bounding box
|
// Test it with the board bounding box
|
||||||
if( m_boardAdapter.GetBBox().Intersect( mouseRay, &hit_t ) )
|
if( m_boardAdapter.GetBBox().Intersect( mouseRay, &hit_t ) )
|
||||||
|
@ -42,7 +42,7 @@ class RENDER_3D_RAYTRACE_GL;
|
|||||||
class RENDER_3D_OPENGL;
|
class RENDER_3D_OPENGL;
|
||||||
|
|
||||||
|
|
||||||
#define EDA_3D_CANVAS_ID wxID_HIGHEST + 1321
|
#define EDA_3D_CANVAS_ID (wxID_HIGHEST + 1321)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implement a canvas based on a wxGLCanvas
|
* Implement a canvas based on a wxGLCanvas
|
||||||
@ -61,7 +61,7 @@ public:
|
|||||||
EDA_3D_CANVAS( wxWindow* aParent, const wxGLAttributes& aGLAttribs, BOARD_ADAPTER& aSettings,
|
EDA_3D_CANVAS( wxWindow* aParent, const wxGLAttributes& aGLAttribs, BOARD_ADAPTER& aSettings,
|
||||||
CAMERA& aCamera, S3D_CACHE* a3DCachePointer );
|
CAMERA& aCamera, S3D_CACHE* a3DCachePointer );
|
||||||
|
|
||||||
~EDA_3D_CANVAS();
|
~EDA_3D_CANVAS() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a dispatcher that processes events and forwards them to tools.
|
* Set a dispatcher that processes events and forwards them to tools.
|
||||||
@ -302,36 +302,36 @@ private:
|
|||||||
RAY getRayAtCurrentMousePosition();
|
RAY getRayAtCurrentMousePosition();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TOOL_DISPATCHER* m_eventDispatcher;
|
TOOL_DISPATCHER* m_eventDispatcher = nullptr;
|
||||||
wxStatusBar* m_parentStatusBar; // Parent statusbar to report progress
|
wxStatusBar* m_parentStatusBar = nullptr; // Parent statusbar to report progress
|
||||||
WX_INFOBAR* m_parentInfoBar;
|
WX_INFOBAR* m_parentInfoBar = nullptr;
|
||||||
|
|
||||||
wxGLContext* m_glRC; // Current OpenGL context
|
wxGLContext* m_glRC = nullptr; // Current OpenGL context
|
||||||
bool m_is_opengl_initialized;
|
bool m_is_opengl_initialized = false;
|
||||||
bool m_is_opengl_version_supported;
|
bool m_is_opengl_version_supported = true;
|
||||||
|
|
||||||
wxTimer m_editing_timeout_timer; // Expires after some time signaling that
|
wxTimer m_editing_timeout_timer; // Expires after some time signaling that
|
||||||
// the mouse / keyboard movements are over
|
// the mouse / keyboard movements are over
|
||||||
wxTimer m_redraw_trigger_timer; // Used to schedule a redraw event
|
wxTimer m_redraw_trigger_timer; // Used to schedule a redraw event
|
||||||
std::atomic_flag m_is_currently_painting; // Avoid drawing twice at the same time
|
std::atomic_flag m_is_currently_painting = ATOMIC_FLAG_INIT; // Avoid drawing twice at the same time
|
||||||
|
|
||||||
bool m_render_pivot; // Render the pivot while camera moving
|
bool m_render_pivot = false; // Render the pivot while camera moving
|
||||||
float m_camera_moving_speed; // 1.0f will be 1:1
|
float m_camera_moving_speed = 1.0f; // 1.0f will be 1:1
|
||||||
int64_t m_strtime_camera_movement; // Ticktime of camera movement start
|
int64_t m_strtime_camera_movement = 0; // Ticktime of camera movement start
|
||||||
bool m_animation_enabled; // Camera animation enabled
|
bool m_animation_enabled = true; // Camera animation enabled
|
||||||
int m_moving_speed_multiplier; // Camera animation speed multiplier option
|
int m_moving_speed_multiplier = 3; // Camera animation speed multiplier option
|
||||||
|
|
||||||
BOARD_ADAPTER& m_boardAdapter; // Pre-computed 3D info and settings
|
BOARD_ADAPTER& m_boardAdapter; // Pre-computed 3D info and settings
|
||||||
RENDER_3D_BASE* m_3d_render;
|
RENDER_3D_BASE* m_3d_render = nullptr;
|
||||||
RENDER_3D_RAYTRACE_GL* m_3d_render_raytracing;
|
RENDER_3D_RAYTRACE_GL* m_3d_render_raytracing;
|
||||||
RENDER_3D_OPENGL* m_3d_render_opengl;
|
RENDER_3D_OPENGL* m_3d_render_opengl;
|
||||||
|
|
||||||
bool m_opengl_supports_raytracing;
|
bool m_opengl_supports_raytracing = true;
|
||||||
bool m_render_raytracing_was_requested;
|
bool m_render_raytracing_was_requested = false;
|
||||||
|
|
||||||
ACCELERATOR_3D* m_accelerator3DShapes; // used for mouse over searching
|
ACCELERATOR_3D* m_accelerator3DShapes = nullptr; // used for mouse over searching
|
||||||
|
|
||||||
BOARD_ITEM* m_currentRollOverItem;
|
BOARD_ITEM* m_currentRollOverItem = nullptr;
|
||||||
|
|
||||||
bool m_render3dmousePivot = false; // Render the 3dmouse pivot
|
bool m_render3dmousePivot = false; // Render the 3dmouse pivot
|
||||||
SFVEC3F m_3dmousePivotPos; // The position of the 3dmouse pivot
|
SFVEC3F m_3dmousePivotPos; // The position of the 3dmouse pivot
|
||||||
|
@ -819,10 +819,7 @@ void RENDER_3D_OPENGL::generateViasAndPads()
|
|||||||
{
|
{
|
||||||
if( pad->GetAttribute() != PAD_ATTRIB::NPTH )
|
if( pad->GetAttribute() != PAD_ATTRIB::NPTH )
|
||||||
{
|
{
|
||||||
const VECTOR2I drillsize = pad->GetDrillSize();
|
if( !pad->HasHole() )
|
||||||
const bool hasHole = drillsize.x && drillsize.y;
|
|
||||||
|
|
||||||
if( !hasHole )
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
pad->TransformHoleToPolygon( tht_outer_holes_poly, platingThickness,
|
pad->TransformHoleToPolygon( tht_outer_holes_poly, platingThickness,
|
||||||
|
@ -277,7 +277,7 @@ void RENDER_3D_RAYTRACE_BASE::renderTracing( uint8_t* ptrPBO, REPORTER* aStatusR
|
|||||||
BS::multi_future<void> futures;
|
BS::multi_future<void> futures;
|
||||||
|
|
||||||
for( size_t i = 0; i < tp.get_thread_count(); ++i )
|
for( size_t i = 0; i < tp.get_thread_count(); ++i )
|
||||||
futures.push_back( tp.submit( processBlocks ) );
|
futures.push_back( tp.submit_task( processBlocks ) );
|
||||||
|
|
||||||
futures.wait();
|
futures.wait();
|
||||||
|
|
||||||
@ -486,9 +486,12 @@ void RENDER_3D_RAYTRACE_BASE::renderBlockTracing( uint8_t* ptrPBO, signed int iB
|
|||||||
// Initialize ray packets
|
// Initialize ray packets
|
||||||
const SFVEC2UI& blockPos = m_blockPositions[iBlock];
|
const SFVEC2UI& blockPos = m_blockPositions[iBlock];
|
||||||
const SFVEC2I blockPosI = SFVEC2I( blockPos.x + m_xoffset, blockPos.y + m_yoffset );
|
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 ),
|
RAYPACKET blockPacket( m_camera, (SFVEC2F) blockPosI + randDisp,
|
||||||
SFVEC2F( DISP_FACTOR, DISP_FACTOR ) /* Displacement random factor */ );
|
randDisp /* Displacement random factor */ );
|
||||||
|
|
||||||
|
|
||||||
HITINFO_PACKET hitPacket_X0Y0[RAYPACKET_RAYS_PER_PACKET];
|
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 );
|
HITINFO_PACKET_init( hitPacket_AA_X1Y1 );
|
||||||
|
|
||||||
RAYPACKET blockPacket_AA_X1Y1( m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.5f, 0.5f ),
|
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 ) )
|
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];
|
RAY blockRayPck_AA_X1Y1_half[RAYPACKET_RAYS_PER_PACKET];
|
||||||
|
|
||||||
RAYPACKET_InitRays_with2DDisplacement(
|
RAYPACKET_InitRays_with2DDisplacement(
|
||||||
m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.5f - DISP_FACTOR, DISP_FACTOR ),
|
m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.5f - randDisp.x, randDisp.y ),
|
||||||
SFVEC2F( DISP_FACTOR, DISP_FACTOR ), blockRayPck_AA_X1Y0 );
|
randDisp, blockRayPck_AA_X1Y0 );
|
||||||
|
|
||||||
RAYPACKET_InitRays_with2DDisplacement(
|
RAYPACKET_InitRays_with2DDisplacement(
|
||||||
m_camera, (SFVEC2F) blockPosI + SFVEC2F( DISP_FACTOR, 0.5f - DISP_FACTOR ),
|
m_camera, (SFVEC2F) blockPosI + SFVEC2F( randDisp.x, 0.5f - randDisp.y ),
|
||||||
SFVEC2F( DISP_FACTOR, DISP_FACTOR ), blockRayPck_AA_X0Y1 );
|
randDisp, blockRayPck_AA_X0Y1 );
|
||||||
|
|
||||||
RAYPACKET_InitRays_with2DDisplacement(
|
RAYPACKET_InitRays_with2DDisplacement(
|
||||||
m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.25f - DISP_FACTOR, 0.25f - DISP_FACTOR ),
|
m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.25f - randDisp.x, 0.25f - randDisp.y ),
|
||||||
SFVEC2F( DISP_FACTOR, DISP_FACTOR ), blockRayPck_AA_X1Y1_half );
|
randDisp, blockRayPck_AA_X1Y1_half );
|
||||||
|
|
||||||
renderAntiAliasPackets( bgColor, hitPacket_X0Y0, hitPacket_AA_X1Y1, blockRayPck_AA_X1Y0,
|
renderAntiAliasPackets( bgColor, hitPacket_X0Y0, hitPacket_AA_X1Y1, blockRayPck_AA_X1Y0,
|
||||||
hitColor_AA_X1Y0 );
|
hitColor_AA_X1Y0 );
|
||||||
|
@ -86,22 +86,39 @@ void EDA_3D_VIEWER_FRAME::doReCreateMenuBar()
|
|||||||
viewMenu->Add( gridSubmenu );
|
viewMenu->Add( gridSubmenu );
|
||||||
|
|
||||||
viewMenu->AppendSeparator();
|
viewMenu->AppendSeparator();
|
||||||
viewMenu->Add( EDA_3D_ACTIONS::rotateXCW );
|
viewMenu->Add( EDA_3D_ACTIONS::viewTop );
|
||||||
viewMenu->Add( EDA_3D_ACTIONS::rotateXCCW );
|
viewMenu->Add( EDA_3D_ACTIONS::viewBottom );
|
||||||
|
viewMenu->Add( EDA_3D_ACTIONS::viewRight );
|
||||||
|
viewMenu->Add( EDA_3D_ACTIONS::viewLeft );
|
||||||
|
viewMenu->Add( EDA_3D_ACTIONS::viewFront );
|
||||||
|
viewMenu->Add( EDA_3D_ACTIONS::viewBack );
|
||||||
|
|
||||||
|
ACTION_MENU* rotateSubmenu = new ACTION_MENU( false, tool );
|
||||||
|
rotateSubmenu->SetTitle( _( "Rotate Board" ) );
|
||||||
|
rotateSubmenu->SetIcon( BITMAPS::rotate_cw );
|
||||||
|
|
||||||
|
rotateSubmenu->Add( EDA_3D_ACTIONS::rotateXCW );
|
||||||
|
rotateSubmenu->Add( EDA_3D_ACTIONS::rotateXCCW );
|
||||||
|
rotateSubmenu->AppendSeparator();
|
||||||
|
rotateSubmenu->Add( EDA_3D_ACTIONS::rotateYCW );
|
||||||
|
rotateSubmenu->Add( EDA_3D_ACTIONS::rotateYCCW );
|
||||||
|
rotateSubmenu->AppendSeparator();
|
||||||
|
rotateSubmenu->Add( EDA_3D_ACTIONS::rotateZCW );
|
||||||
|
rotateSubmenu->Add( EDA_3D_ACTIONS::rotateZCCW );
|
||||||
|
|
||||||
|
ACTION_MENU* moveSubmenu = new ACTION_MENU( false, tool );
|
||||||
|
moveSubmenu->SetTitle( _( "Move Board" ) );
|
||||||
|
moveSubmenu->SetIcon( BITMAPS::move );
|
||||||
|
|
||||||
|
moveSubmenu->Add( EDA_3D_ACTIONS::moveLeft );
|
||||||
|
moveSubmenu->Add( EDA_3D_ACTIONS::moveRight );
|
||||||
|
moveSubmenu->Add( EDA_3D_ACTIONS::moveUp );
|
||||||
|
moveSubmenu->Add( EDA_3D_ACTIONS::moveDown );
|
||||||
|
|
||||||
viewMenu->AppendSeparator();
|
viewMenu->AppendSeparator();
|
||||||
viewMenu->Add( EDA_3D_ACTIONS::rotateYCW );
|
viewMenu->Add( rotateSubmenu );
|
||||||
viewMenu->Add( EDA_3D_ACTIONS::rotateYCCW );
|
viewMenu->Add( EDA_3D_ACTIONS::flipView );
|
||||||
|
viewMenu->Add( moveSubmenu );
|
||||||
viewMenu->AppendSeparator();
|
|
||||||
viewMenu->Add( EDA_3D_ACTIONS::rotateZCW );
|
|
||||||
viewMenu->Add( EDA_3D_ACTIONS::rotateZCCW );
|
|
||||||
|
|
||||||
viewMenu->AppendSeparator();
|
|
||||||
viewMenu->Add( EDA_3D_ACTIONS::moveLeft );
|
|
||||||
viewMenu->Add( EDA_3D_ACTIONS::moveRight );
|
|
||||||
viewMenu->Add( EDA_3D_ACTIONS::moveUp );
|
|
||||||
viewMenu->Add( EDA_3D_ACTIONS::moveDown );
|
|
||||||
|
|
||||||
viewMenu->AppendSeparator();
|
viewMenu->AppendSeparator();
|
||||||
viewMenu->Add( EDA_3D_ACTIONS::showLayersManager, ACTION_MENU::CHECK );
|
viewMenu->Add( EDA_3D_ACTIONS::showLayersManager, ACTION_MENU::CHECK );
|
||||||
|
@ -38,6 +38,30 @@
|
|||||||
|
|
||||||
bool EDA_3D_CONTROLLER::Init()
|
bool EDA_3D_CONTROLLER::Init()
|
||||||
{
|
{
|
||||||
|
std::shared_ptr<ACTION_MENU> rotateSubmenu = std::make_shared<ACTION_MENU>( true, this );
|
||||||
|
rotateSubmenu->SetTitle( _( "Rotate Board" ) );
|
||||||
|
rotateSubmenu->SetIcon( BITMAPS::rotate_cw );
|
||||||
|
m_menu->RegisterSubMenu( rotateSubmenu );
|
||||||
|
|
||||||
|
rotateSubmenu->Add( EDA_3D_ACTIONS::rotateXCW );
|
||||||
|
rotateSubmenu->Add( EDA_3D_ACTIONS::rotateXCCW );
|
||||||
|
rotateSubmenu->AppendSeparator();
|
||||||
|
rotateSubmenu->Add( EDA_3D_ACTIONS::rotateYCW );
|
||||||
|
rotateSubmenu->Add( EDA_3D_ACTIONS::rotateYCCW );
|
||||||
|
rotateSubmenu->AppendSeparator();
|
||||||
|
rotateSubmenu->Add( EDA_3D_ACTIONS::rotateZCW );
|
||||||
|
rotateSubmenu->Add( EDA_3D_ACTIONS::rotateZCCW );
|
||||||
|
|
||||||
|
std::shared_ptr<ACTION_MENU> moveSubmenu = std::make_shared<ACTION_MENU>( true, this );
|
||||||
|
moveSubmenu->SetTitle( _( "Move Board" ) );
|
||||||
|
moveSubmenu->SetIcon( BITMAPS::move );
|
||||||
|
m_menu->RegisterSubMenu( moveSubmenu );
|
||||||
|
|
||||||
|
moveSubmenu->Add( EDA_3D_ACTIONS::moveLeft );
|
||||||
|
moveSubmenu->Add( EDA_3D_ACTIONS::moveRight );
|
||||||
|
moveSubmenu->Add( EDA_3D_ACTIONS::moveUp );
|
||||||
|
moveSubmenu->Add( EDA_3D_ACTIONS::moveDown );
|
||||||
|
|
||||||
CONDITIONAL_MENU& ctxMenu = m_menu->GetMenu();
|
CONDITIONAL_MENU& ctxMenu = m_menu->GetMenu();
|
||||||
|
|
||||||
ctxMenu.AddItem( ACTIONS::zoomInCenter, SELECTION_CONDITIONS::ShowAlways );
|
ctxMenu.AddItem( ACTIONS::zoomInCenter, SELECTION_CONDITIONS::ShowAlways );
|
||||||
@ -46,23 +70,15 @@ bool EDA_3D_CONTROLLER::Init()
|
|||||||
ctxMenu.AddSeparator();
|
ctxMenu.AddSeparator();
|
||||||
ctxMenu.AddItem( EDA_3D_ACTIONS::viewTop, SELECTION_CONDITIONS::ShowAlways );
|
ctxMenu.AddItem( EDA_3D_ACTIONS::viewTop, SELECTION_CONDITIONS::ShowAlways );
|
||||||
ctxMenu.AddItem( EDA_3D_ACTIONS::viewBottom, SELECTION_CONDITIONS::ShowAlways );
|
ctxMenu.AddItem( EDA_3D_ACTIONS::viewBottom, SELECTION_CONDITIONS::ShowAlways );
|
||||||
|
|
||||||
ctxMenu.AddSeparator();
|
|
||||||
ctxMenu.AddItem( EDA_3D_ACTIONS::viewRight, SELECTION_CONDITIONS::ShowAlways );
|
ctxMenu.AddItem( EDA_3D_ACTIONS::viewRight, SELECTION_CONDITIONS::ShowAlways );
|
||||||
ctxMenu.AddItem( EDA_3D_ACTIONS::viewLeft, SELECTION_CONDITIONS::ShowAlways );
|
ctxMenu.AddItem( EDA_3D_ACTIONS::viewLeft, SELECTION_CONDITIONS::ShowAlways );
|
||||||
|
|
||||||
ctxMenu.AddSeparator();
|
|
||||||
ctxMenu.AddItem( EDA_3D_ACTIONS::viewFront, SELECTION_CONDITIONS::ShowAlways );
|
ctxMenu.AddItem( EDA_3D_ACTIONS::viewFront, SELECTION_CONDITIONS::ShowAlways );
|
||||||
ctxMenu.AddItem( EDA_3D_ACTIONS::viewBack, SELECTION_CONDITIONS::ShowAlways );
|
ctxMenu.AddItem( EDA_3D_ACTIONS::viewBack, SELECTION_CONDITIONS::ShowAlways );
|
||||||
|
|
||||||
ctxMenu.AddSeparator();
|
ctxMenu.AddSeparator();
|
||||||
|
ctxMenu.AddMenu( rotateSubmenu.get(), SELECTION_CONDITIONS::ShowAlways );
|
||||||
ctxMenu.AddItem( EDA_3D_ACTIONS::flipView, SELECTION_CONDITIONS::ShowAlways );
|
ctxMenu.AddItem( EDA_3D_ACTIONS::flipView, SELECTION_CONDITIONS::ShowAlways );
|
||||||
|
ctxMenu.AddMenu( moveSubmenu.get(), SELECTION_CONDITIONS::ShowAlways );
|
||||||
ctxMenu.AddSeparator();
|
|
||||||
ctxMenu.AddItem( EDA_3D_ACTIONS::moveLeft, SELECTION_CONDITIONS::ShowAlways );
|
|
||||||
ctxMenu.AddItem( EDA_3D_ACTIONS::moveRight, SELECTION_CONDITIONS::ShowAlways );
|
|
||||||
ctxMenu.AddItem( EDA_3D_ACTIONS::moveUp, SELECTION_CONDITIONS::ShowAlways );
|
|
||||||
ctxMenu.AddItem( EDA_3D_ACTIONS::moveDown, SELECTION_CONDITIONS::ShowAlways );
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -116,12 +132,6 @@ int EDA_3D_CONTROLLER::UpdateMenu( const TOOL_EVENT& aEvent )
|
|||||||
|
|
||||||
int EDA_3D_CONTROLLER::Main( const TOOL_EVENT& aEvent )
|
int EDA_3D_CONTROLLER::Main( const TOOL_EVENT& aEvent )
|
||||||
{
|
{
|
||||||
// Track right mouse button state and movement
|
|
||||||
VECTOR2D rightButtonDownPos;
|
|
||||||
|
|
||||||
const int DRAG_THRESHOLD = 4; // pixels
|
|
||||||
bool rightButtonDragged = false;
|
|
||||||
|
|
||||||
// Main loop: keep receiving events
|
// Main loop: keep receiving events
|
||||||
while( TOOL_EVENT* evt = Wait() )
|
while( TOOL_EVENT* evt = Wait() )
|
||||||
{
|
{
|
||||||
@ -247,8 +257,7 @@ int EDA_3D_CONTROLLER::ToggleVisibility( const TOOL_EVENT& aEvent )
|
|||||||
auto flipLayer =
|
auto flipLayer =
|
||||||
[&]( int layer )
|
[&]( int layer )
|
||||||
{
|
{
|
||||||
appearanceManager->OnLayerVisibilityChanged( layer,
|
appearanceManager->OnLayerVisibilityChanged( layer, !visibilityFlags.test( layer ) );
|
||||||
!visibilityFlags.test( layer ) );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
|
EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
|
||||||
@ -258,20 +267,13 @@ int EDA_3D_CONTROLLER::ToggleVisibility( const TOOL_EVENT& aEvent )
|
|||||||
|
|
||||||
if( appearanceManager )
|
if( appearanceManager )
|
||||||
{
|
{
|
||||||
if( aEvent.IsAction( &EDA_3D_ACTIONS::showTHT ) )
|
if( aEvent.IsAction( &EDA_3D_ACTIONS::showTHT ) ) flipLayer( LAYER_3D_TH_MODELS );
|
||||||
flipLayer( LAYER_3D_TH_MODELS );
|
else if( aEvent.IsAction( &EDA_3D_ACTIONS::showSMD ) ) flipLayer( LAYER_3D_SMD_MODELS );
|
||||||
else if( aEvent.IsAction( &EDA_3D_ACTIONS::showSMD ) )
|
else if( aEvent.IsAction( &EDA_3D_ACTIONS::showVirtual ) ) flipLayer( LAYER_3D_VIRTUAL_MODELS );
|
||||||
flipLayer( LAYER_3D_SMD_MODELS );
|
else if( aEvent.IsAction( &EDA_3D_ACTIONS::showNotInPosFile ) ) flipLayer( LAYER_3D_MODELS_NOT_IN_POS );
|
||||||
else if( aEvent.IsAction( &EDA_3D_ACTIONS::showVirtual ) )
|
else if( aEvent.IsAction( &EDA_3D_ACTIONS::showDNP ) ) flipLayer( LAYER_3D_MODELS_MARKED_DNP );
|
||||||
flipLayer( LAYER_3D_VIRTUAL_MODELS );
|
else if( aEvent.IsAction( &EDA_3D_ACTIONS::showNavigator ) ) flipLayer( LAYER_3D_NAVIGATOR );
|
||||||
else if( aEvent.IsAction( &EDA_3D_ACTIONS::showNotInPosFile ) )
|
else if( aEvent.IsAction( &EDA_3D_ACTIONS::showBBoxes ) ) flipLayer( LAYER_3D_BOUNDING_BOXES );
|
||||||
flipLayer( LAYER_3D_MODELS_NOT_IN_POS );
|
|
||||||
else if( aEvent.IsAction( &EDA_3D_ACTIONS::showDNP ) )
|
|
||||||
flipLayer( LAYER_3D_MODELS_MARKED_DNP );
|
|
||||||
else if( aEvent.IsAction( &EDA_3D_ACTIONS::showNavigator ) )
|
|
||||||
flipLayer( LAYER_3D_NAVIGATOR );
|
|
||||||
else if( aEvent.IsAction( &EDA_3D_ACTIONS::showBBoxes ) )
|
|
||||||
flipLayer( LAYER_3D_BOUNDING_BOXES );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -325,8 +327,7 @@ int EDA_3D_CONTROLLER::doZoomInOut( bool aDirection, bool aCenterOnCursor )
|
|||||||
{
|
{
|
||||||
if( m_canvas )
|
if( m_canvas )
|
||||||
{
|
{
|
||||||
m_canvas->SetView3D( aDirection ? VIEW3D_TYPE::VIEW3D_ZOOM_IN
|
m_canvas->SetView3D( aDirection ? VIEW3D_TYPE::VIEW3D_ZOOM_IN : VIEW3D_TYPE::VIEW3D_ZOOM_OUT );
|
||||||
: VIEW3D_TYPE::VIEW3D_ZOOM_OUT );
|
|
||||||
m_canvas->DisplayStatus();
|
m_canvas->DisplayStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,8 +22,7 @@
|
|||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _3D_VIEWER_CONTROL_H
|
#pragma once
|
||||||
#define _3D_VIEWER_CONTROL_H
|
|
||||||
|
|
||||||
#include <tool/tool_interactive.h>
|
#include <tool/tool_interactive.h>
|
||||||
|
|
||||||
@ -38,12 +37,12 @@ class BOARD_ADAPTER;
|
|||||||
class EDA_3D_CONTROLLER : public TOOL_INTERACTIVE
|
class EDA_3D_CONTROLLER : public TOOL_INTERACTIVE
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EDA_3D_CONTROLLER()
|
EDA_3D_CONTROLLER() :
|
||||||
: TOOL_INTERACTIVE( "3DViewer.Control" ),
|
TOOL_INTERACTIVE( "3DViewer.Control" ),
|
||||||
m_canvas( nullptr ),
|
m_canvas( nullptr ),
|
||||||
m_boardAdapter( nullptr ),
|
m_boardAdapter( nullptr ),
|
||||||
m_camera( nullptr ),
|
m_camera( nullptr ),
|
||||||
m_rotationIncrement( 10.0 )
|
m_rotationIncrement( 10.0 )
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
~EDA_3D_CONTROLLER() override { }
|
~EDA_3D_CONTROLLER() override { }
|
||||||
@ -63,20 +62,8 @@ public:
|
|||||||
*
|
*
|
||||||
* @param aRotIncrement is the rotation increment in degrees
|
* @param aRotIncrement is the rotation increment in degrees
|
||||||
*/
|
*/
|
||||||
void SetRotationIncrement( double aRotIncrement )
|
void SetRotationIncrement( double aRotIncrement ) { m_rotationIncrement = aRotIncrement; }
|
||||||
{
|
double GetRotationIncrement() { return m_rotationIncrement; }
|
||||||
m_rotationIncrement = aRotIncrement;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the increment used by the RotateView actions.
|
|
||||||
*
|
|
||||||
* @return the rotation increment in degrees
|
|
||||||
*/
|
|
||||||
double GetRotationIncrement()
|
|
||||||
{
|
|
||||||
return m_rotationIncrement;
|
|
||||||
}
|
|
||||||
|
|
||||||
// View controls
|
// View controls
|
||||||
int ZoomRedraw( const TOOL_EVENT& aEvent );
|
int ZoomRedraw( const TOOL_EVENT& aEvent );
|
||||||
@ -112,5 +99,3 @@ private:
|
|||||||
CAMERA* m_camera;
|
CAMERA* m_camera;
|
||||||
double m_rotationIncrement; ///< Rotation increment for the rotate actions (degrees)
|
double m_rotationIncrement; ///< Rotation increment for the rotate actions (degrees)
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -48,6 +48,7 @@ project( kicad )
|
|||||||
|
|
||||||
# Create a default build type for our QA that doesn't include `NDEBUG`
|
# Create a default build type for our QA that doesn't include `NDEBUG`
|
||||||
set(CMAKE_CXX_FLAGS_QABUILD "-Os -g1 -ggdb1")
|
set(CMAKE_CXX_FLAGS_QABUILD "-Os -g1 -ggdb1")
|
||||||
|
string( APPEND CMAKE_EXE_LINKER_FLAGS_QABUILD " -rdynamic" )
|
||||||
|
|
||||||
include( GNUInstallDirs )
|
include( GNUInstallDirs )
|
||||||
include( CMakeDependentOption )
|
include( CMakeDependentOption )
|
||||||
@ -193,7 +194,12 @@ option( KICAD_I18N_UNIX_STRICT_PATH
|
|||||||
cmake_dependent_option( KICAD_WIN32_INSTALL_PDBS
|
cmake_dependent_option( KICAD_WIN32_INSTALL_PDBS
|
||||||
"Installs debug pdb to the bin folder, DO NOT USE (NOR REQUIRED) FOR DEBUGGING THE SOURCE ON MSVC. This is purely for release building.
|
"Installs debug pdb to the bin folder, DO NOT USE (NOR REQUIRED) FOR DEBUGGING THE SOURCE ON MSVC. This is purely for release building.
|
||||||
MSVC can find the PDBs without this."
|
MSVC can find the PDBs without this."
|
||||||
OFF "WIN32"
|
OFF "MSVC"
|
||||||
|
OFF )
|
||||||
|
|
||||||
|
cmake_dependent_option( KICAD_MSVC_DYNDEOPT
|
||||||
|
"Builds release builds with /dynamicdeopt for dynamic debugging."
|
||||||
|
OFF "MSVC"
|
||||||
OFF )
|
OFF )
|
||||||
|
|
||||||
####################################
|
####################################
|
||||||
@ -557,6 +563,11 @@ if( MSVC )
|
|||||||
# but we want to turn it on to enable debug performance improvements available under C++17 in MSVC 17.5+
|
# but we want to turn it on to enable debug performance improvements available under C++17 in MSVC 17.5+
|
||||||
string( APPEND CMAKE_CXX_FLAGS " /permissive-" )
|
string( APPEND CMAKE_CXX_FLAGS " /permissive-" )
|
||||||
|
|
||||||
|
if( KICAD_MSVC_DYNDEOPT )
|
||||||
|
string( APPEND CMAKE_CXX_FLAGS_RELEASE " /dynamicdeopt" )
|
||||||
|
string( APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " /dynamicdeopt" )
|
||||||
|
endif()
|
||||||
|
|
||||||
# Exception handling
|
# Exception handling
|
||||||
# Remove the potential default EHsc option cmake doesn't allow us to remove easily
|
# Remove the potential default EHsc option cmake doesn't allow us to remove easily
|
||||||
string( REPLACE "/EHsc" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} )
|
string( REPLACE "/EHsc" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} )
|
||||||
@ -585,11 +596,20 @@ if( MSVC )
|
|||||||
# /DEBUG: create PDB
|
# /DEBUG: create PDB
|
||||||
string( APPEND CMAKE_${type}_LINKER_FLAGS " /DEBUG /MANIFEST:NO" )
|
string( APPEND CMAKE_${type}_LINKER_FLAGS " /DEBUG /MANIFEST:NO" )
|
||||||
# /OPT:REF: omit unreferenced code
|
# /OPT:REF: omit unreferenced code
|
||||||
string( APPEND CMAKE_${type}_LINKER_FLAGS_RELEASE " /OPT:REF /MANIFEST:NO" )
|
string( APPEND CMAKE_${type}_LINKER_FLAGS_RELEASE " /OPT:REF" )
|
||||||
string( APPEND CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO " /OPT:REF /MANIFEST:NO" )
|
string( APPEND CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO " /OPT:REF" )
|
||||||
# /OPT:ICF: fold common data
|
# /MANIFEST:NO
|
||||||
string( APPEND CMAKE_${type}_LINKER_FLAGS_RELEASE " /OPT:ICF /MANIFEST:NO" )
|
string( APPEND CMAKE_${type}_LINKER_FLAGS_RELEASE " /MANIFEST:NO" )
|
||||||
string( APPEND CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO " /OPT:ICF /MANIFEST:NO" )
|
string( APPEND CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO " /MANIFEST:NO" )
|
||||||
|
|
||||||
|
if( KICAD_MSVC_DYNDEOPT )
|
||||||
|
string( APPEND CMAKE_${type}_LINKER_FLAGS_RELEASE " /dynamicdeopt" )
|
||||||
|
string( APPEND CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO " /dynamicdeopt" )
|
||||||
|
else()
|
||||||
|
# /OPT:ICF: fold common data
|
||||||
|
string( APPEND CMAKE_${type}_LINKER_FLAGS_RELEASE " /OPT:ICF" )
|
||||||
|
string( APPEND CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO " /OPT:ICF" )
|
||||||
|
endif()
|
||||||
|
|
||||||
if( KICAD_WIN32_LTCG )
|
if( KICAD_WIN32_LTCG )
|
||||||
# we are implementing this manually because CMake's LTCG option is incomplete
|
# we are implementing this manually because CMake's LTCG option is incomplete
|
||||||
@ -598,6 +618,11 @@ if( MSVC )
|
|||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
if( KICAD_MSVC_DYNDEOPT )
|
||||||
|
string( APPEND CMAKE_STATIC_LINKER_FLAGS_RELEASE " /dynamicdeopt" )
|
||||||
|
string( APPEND CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO " /dynamicdeopt" )
|
||||||
|
endif()
|
||||||
|
|
||||||
# Let cl.exe parallelize builds
|
# Let cl.exe parallelize builds
|
||||||
if( KICAD_WIN32_BUILD_PARALLEL_CL_MP )
|
if( KICAD_WIN32_BUILD_PARALLEL_CL_MP )
|
||||||
string( APPEND CMAKE_CXX_FLAGS " /MP" )
|
string( APPEND CMAKE_CXX_FLAGS " /MP" )
|
||||||
|
@ -371,6 +371,7 @@ message GraphicRectangleAttributes
|
|||||||
{
|
{
|
||||||
kiapi.common.types.Vector2 top_left = 1;
|
kiapi.common.types.Vector2 top_left = 1;
|
||||||
kiapi.common.types.Vector2 bottom_right = 2;
|
kiapi.common.types.Vector2 bottom_right = 2;
|
||||||
|
kiapi.common.types.Distance corner_radius = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GraphicArcAttributes
|
message GraphicArcAttributes
|
||||||
|
@ -387,8 +387,6 @@ void BITMAPCONV_INFO::createOutputData( const wxString& aLayer )
|
|||||||
|
|
||||||
potrace_dpoint_t( *c )[3];
|
potrace_dpoint_t( *c )[3];
|
||||||
|
|
||||||
LOCALE_IO toggle; // Temporary switch the locale to standard C to r/w floats
|
|
||||||
|
|
||||||
// The layer name has meaning only for .kicad_mod files.
|
// The layer name has meaning only for .kicad_mod files.
|
||||||
// For these files the header creates 2 invisible texts: value and ref
|
// For these files the header creates 2 invisible texts: value and ref
|
||||||
// (needed but not useful) on silk screen layer
|
// (needed but not useful) on silk screen layer
|
||||||
|
@ -103,6 +103,8 @@ set( KICOMMON_SRCS
|
|||||||
jobs/job_sch_erc.cpp
|
jobs/job_sch_erc.cpp
|
||||||
jobs/job_sym_export_svg.cpp
|
jobs/job_sym_export_svg.cpp
|
||||||
jobs/job_sym_upgrade.cpp
|
jobs/job_sym_upgrade.cpp
|
||||||
|
jobs/job_pcb_upgrade.cpp
|
||||||
|
jobs/job_sch_upgrade.cpp
|
||||||
|
|
||||||
kicad_curl/kicad_curl.cpp
|
kicad_curl/kicad_curl.cpp
|
||||||
kicad_curl/kicad_curl_easy.cpp
|
kicad_curl/kicad_curl_easy.cpp
|
||||||
@ -128,6 +130,9 @@ set( KICOMMON_SRCS
|
|||||||
project/project_local_settings.cpp
|
project/project_local_settings.cpp
|
||||||
project/time_domain_parameters.cpp
|
project/time_domain_parameters.cpp
|
||||||
|
|
||||||
|
text_eval/text_eval_wrapper.cpp
|
||||||
|
text_eval/text_eval_parser.cpp
|
||||||
|
|
||||||
# This is basically a settings object, but for the toolbar
|
# This is basically a settings object, but for the toolbar
|
||||||
tool/ui/toolbar_configuration.cpp
|
tool/ui/toolbar_configuration.cpp
|
||||||
|
|
||||||
@ -269,6 +274,7 @@ target_link_libraries( kicommon
|
|||||||
kiplatform
|
kiplatform
|
||||||
nlohmann_json
|
nlohmann_json
|
||||||
nlohmann_json_schema_validator
|
nlohmann_json_schema_validator
|
||||||
|
FastFloat::fast_float
|
||||||
fmt::fmt
|
fmt::fmt
|
||||||
CURL::libcurl
|
CURL::libcurl
|
||||||
picosha2
|
picosha2
|
||||||
@ -430,10 +436,12 @@ set( COMMON_DLG_SRCS
|
|||||||
dialogs/panel_design_block_lib_table.cpp
|
dialogs/panel_design_block_lib_table.cpp
|
||||||
dialogs/panel_embedded_files.cpp
|
dialogs/panel_embedded_files.cpp
|
||||||
dialogs/panel_embedded_files_base.cpp
|
dialogs/panel_embedded_files_base.cpp
|
||||||
dialogs/panel_gal_display_options.cpp
|
dialogs/panel_base_display_options.cpp
|
||||||
dialogs/panel_hotkeys_editor.cpp
|
dialogs/panel_hotkeys_editor.cpp
|
||||||
dialogs/panel_image_editor.cpp
|
dialogs/panel_image_editor.cpp
|
||||||
dialogs/panel_image_editor_base.cpp
|
dialogs/panel_image_editor_base.cpp
|
||||||
|
dialogs/panel_gal_options.cpp
|
||||||
|
dialogs/panel_gal_options_base.cpp
|
||||||
dialogs/panel_grid_settings.cpp
|
dialogs/panel_grid_settings.cpp
|
||||||
dialogs/panel_grid_settings_base.cpp
|
dialogs/panel_grid_settings_base.cpp
|
||||||
dialogs/panel_maintenance.cpp
|
dialogs/panel_maintenance.cpp
|
||||||
@ -477,8 +485,6 @@ set( COMMON_WIDGET_SRCS
|
|||||||
widgets/footprint_diff_widget.cpp
|
widgets/footprint_diff_widget.cpp
|
||||||
widgets/footprint_preview_widget.cpp
|
widgets/footprint_preview_widget.cpp
|
||||||
widgets/footprint_select_widget.cpp
|
widgets/footprint_select_widget.cpp
|
||||||
widgets/gal_options_panel.cpp
|
|
||||||
widgets/gal_options_panel_base.cpp
|
|
||||||
widgets/grid_bitmap_toggle.cpp
|
widgets/grid_bitmap_toggle.cpp
|
||||||
widgets/grid_button.cpp
|
widgets/grid_button.cpp
|
||||||
widgets/grid_checkbox.cpp
|
widgets/grid_checkbox.cpp
|
||||||
@ -523,6 +529,7 @@ set( COMMON_WIDGET_SRCS
|
|||||||
widgets/wx_splitter_window.cpp
|
widgets/wx_splitter_window.cpp
|
||||||
widgets/wx_treebook.cpp
|
widgets/wx_treebook.cpp
|
||||||
widgets/webview_panel.cpp
|
widgets/webview_panel.cpp
|
||||||
|
widgets/zoom_correction_ctrl.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set( COMMON_DRAWING_SHEET_SRCS
|
set( COMMON_DRAWING_SHEET_SRCS
|
||||||
@ -538,6 +545,7 @@ set( COMMON_DRAWING_SHEET_SRCS
|
|||||||
|
|
||||||
set( COMMON_PREVIEW_ITEMS_SRCS
|
set( COMMON_PREVIEW_ITEMS_SRCS
|
||||||
preview_items/anchor_debug.cpp
|
preview_items/anchor_debug.cpp
|
||||||
|
preview_items/angle_item.cpp
|
||||||
preview_items/arc_assistant.cpp
|
preview_items/arc_assistant.cpp
|
||||||
preview_items/arc_geom_manager.cpp
|
preview_items/arc_geom_manager.cpp
|
||||||
preview_items/bezier_assistant.cpp
|
preview_items/bezier_assistant.cpp
|
||||||
@ -625,7 +633,8 @@ set( COMMON_GIT_SRCS
|
|||||||
git/project_git_utils.cpp
|
git/project_git_utils.cpp
|
||||||
git/kicad_git_common.cpp
|
git/kicad_git_common.cpp
|
||||||
git/kicad_git_errors.cpp
|
git/kicad_git_errors.cpp
|
||||||
git/project_git_utils.cpp
|
git/git_backend.cpp
|
||||||
|
git/libgit_backend.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set( COMMON_SRCS
|
set( COMMON_SRCS
|
||||||
@ -872,11 +881,13 @@ set( PCB_COMMON_SRCS
|
|||||||
${CMAKE_SOURCE_DIR}/pcbnew/pcb_marker.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/pcb_marker.cpp
|
||||||
${CMAKE_SOURCE_DIR}/pcbnew/footprint.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/footprint.cpp
|
||||||
${CMAKE_SOURCE_DIR}/pcbnew/fix_board_shape.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/fix_board_shape.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/pcbnew/layer_utils.cpp
|
||||||
${CMAKE_SOURCE_DIR}/pcbnew/netinfo_item.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/netinfo_item.cpp
|
||||||
${CMAKE_SOURCE_DIR}/pcbnew/netinfo_list.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/netinfo_list.cpp
|
||||||
${CMAKE_SOURCE_DIR}/pcbnew/pad.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/pad.cpp
|
||||||
${CMAKE_SOURCE_DIR}/pcbnew/pad_utils.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/pad_utils.cpp
|
||||||
${CMAKE_SOURCE_DIR}/pcbnew/padstack.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/padstack.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/pcbnew/pcb_point.cpp
|
||||||
${CMAKE_SOURCE_DIR}/pcbnew/pcb_target.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/pcb_target.cpp
|
||||||
${CMAKE_SOURCE_DIR}/pcbnew/pcb_reference_image.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/pcb_reference_image.cpp
|
||||||
${CMAKE_SOURCE_DIR}/pcbnew/pcb_field.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/pcb_field.cpp
|
||||||
@ -1007,6 +1018,13 @@ generate_lemon_grammar(
|
|||||||
libeval_compiler/grammar.lemon
|
libeval_compiler/grammar.lemon
|
||||||
)
|
)
|
||||||
|
|
||||||
|
generate_lemon_grammar(
|
||||||
|
kicommon
|
||||||
|
text_eval
|
||||||
|
text_eval/text_eval_wrapper.cpp
|
||||||
|
text_eval/text_eval.lemon
|
||||||
|
)
|
||||||
|
|
||||||
# auto-generate stroke_params_lexer.h and stroke_params_keywords.cpp
|
# auto-generate stroke_params_lexer.h and stroke_params_keywords.cpp
|
||||||
# Called twice one for common and one for gal, to ensure the files are created
|
# Called twice one for common and one for gal, to ensure the files are created
|
||||||
# on all devel tools ( Linux and msys2 )
|
# on all devel tools ( Linux and msys2 )
|
||||||
|
@ -119,6 +119,7 @@ static const wxChar EnableExtensionSnaps[] = wxT( "EnableExtensionSnaps" );
|
|||||||
static const wxChar ExtensionSnapTimeoutMs[] = wxT( "ExtensionSnapTimeoutMs" );
|
static const wxChar ExtensionSnapTimeoutMs[] = wxT( "ExtensionSnapTimeoutMs" );
|
||||||
static const wxChar ExtensionSnapActivateOnHover[] = wxT( "ExtensionSnapActivateOnHover" );
|
static const wxChar ExtensionSnapActivateOnHover[] = wxT( "ExtensionSnapActivateOnHover" );
|
||||||
static const wxChar EnableSnapAnchorsDebug[] = wxT( "EnableSnapAnchorsDebug" );
|
static const wxChar EnableSnapAnchorsDebug[] = wxT( "EnableSnapAnchorsDebug" );
|
||||||
|
static const wxChar SnapHysteresis[] = wxT( "SnapHysteresis" );
|
||||||
static const wxChar MinParallelAngle[] = wxT( "MinParallelAngle" );
|
static const wxChar MinParallelAngle[] = wxT( "MinParallelAngle" );
|
||||||
static const wxChar HoleWallPaintingMultiplier[] = wxT( "HoleWallPaintingMultiplier" );
|
static const wxChar HoleWallPaintingMultiplier[] = wxT( "HoleWallPaintingMultiplier" );
|
||||||
static const wxChar MsgPanelShowUuids[] = wxT( "MsgPanelShowUuids" );
|
static const wxChar MsgPanelShowUuids[] = wxT( "MsgPanelShowUuids" );
|
||||||
@ -131,6 +132,7 @@ static const wxChar ConfigurableToolbars[] = wxT( "ConfigurableToolbars" );
|
|||||||
static const wxChar MaxPastedTextLength[] = wxT( "MaxPastedTextLength" );
|
static const wxChar MaxPastedTextLength[] = wxT( "MaxPastedTextLength" );
|
||||||
static const wxChar PNSProcessClusterTimeout[] = wxT( "PNSProcessClusterTimeout" );
|
static const wxChar PNSProcessClusterTimeout[] = wxT( "PNSProcessClusterTimeout" );
|
||||||
static const wxChar ImportSkipComponentBodies[] = wxT( "ImportSkipComponentBodies" );
|
static const wxChar ImportSkipComponentBodies[] = wxT( "ImportSkipComponentBodies" );
|
||||||
|
static const wxChar ScreenDPI[] = wxT( "ScreenDPI" );
|
||||||
|
|
||||||
} // namespace KEYS
|
} // namespace KEYS
|
||||||
|
|
||||||
@ -260,7 +262,7 @@ ADVANCED_CFG::ADVANCED_CFG()
|
|||||||
m_CompactSave = false;
|
m_CompactSave = false;
|
||||||
m_UpdateUIEventInterval = 0;
|
m_UpdateUIEventInterval = 0;
|
||||||
m_ShowRepairSchematic = false;
|
m_ShowRepairSchematic = false;
|
||||||
m_EnablePcbDesignBlocks = false;
|
m_EnablePcbDesignBlocks = true;
|
||||||
m_EnableGenerators = false;
|
m_EnableGenerators = false;
|
||||||
m_EnableLibWithText = false;
|
m_EnableLibWithText = false;
|
||||||
m_EnableLibDir = false;
|
m_EnableLibDir = false;
|
||||||
@ -298,6 +300,7 @@ ADVANCED_CFG::ADVANCED_CFG()
|
|||||||
m_ExtensionSnapTimeoutMs = 500;
|
m_ExtensionSnapTimeoutMs = 500;
|
||||||
m_ExtensionSnapActivateOnHover = true;
|
m_ExtensionSnapActivateOnHover = true;
|
||||||
m_EnableSnapAnchorsDebug = false;
|
m_EnableSnapAnchorsDebug = false;
|
||||||
|
m_SnapHysteresis = 5;
|
||||||
|
|
||||||
m_MinParallelAngle = 0.001;
|
m_MinParallelAngle = 0.001;
|
||||||
m_HoleWallPaintingMultiplier = 1.5;
|
m_HoleWallPaintingMultiplier = 1.5;
|
||||||
@ -320,6 +323,8 @@ ADVANCED_CFG::ADVANCED_CFG()
|
|||||||
|
|
||||||
m_ImportSkipComponentBodies = false;
|
m_ImportSkipComponentBodies = false;
|
||||||
|
|
||||||
|
m_ScreenDPI = 91;
|
||||||
|
|
||||||
loadFromConfigFile();
|
loadFromConfigFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -589,6 +594,10 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg )
|
|||||||
&m_EnableSnapAnchorsDebug,
|
&m_EnableSnapAnchorsDebug,
|
||||||
m_EnableSnapAnchorsDebug ) );
|
m_EnableSnapAnchorsDebug ) );
|
||||||
|
|
||||||
|
m_entries.push_back( std::make_unique<PARAM_CFG_INT>( true, AC_KEYS::SnapHysteresis,
|
||||||
|
&m_SnapHysteresis, m_SnapHysteresis,
|
||||||
|
0, 100 ) );
|
||||||
|
|
||||||
m_entries.push_back( std::make_unique<PARAM_CFG_DOUBLE>( true, AC_KEYS::MinParallelAngle,
|
m_entries.push_back( std::make_unique<PARAM_CFG_DOUBLE>( true, AC_KEYS::MinParallelAngle,
|
||||||
&m_MinParallelAngle, m_MinParallelAngle,
|
&m_MinParallelAngle, m_MinParallelAngle,
|
||||||
0.0, 45.0 ) );
|
0.0, 45.0 ) );
|
||||||
@ -634,6 +643,10 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg )
|
|||||||
&m_ImportSkipComponentBodies,
|
&m_ImportSkipComponentBodies,
|
||||||
m_ImportSkipComponentBodies ) );
|
m_ImportSkipComponentBodies ) );
|
||||||
|
|
||||||
|
m_entries.push_back( std::make_unique<PARAM_CFG_INT>( true, AC_KEYS::ScreenDPI,
|
||||||
|
&m_ScreenDPI, m_ScreenDPI,
|
||||||
|
50, 500 ) );
|
||||||
|
|
||||||
// Special case for trace mask setting...we just grab them and set them immediately
|
// Special case for trace mask setting...we just grab them and set them immediately
|
||||||
// Because we even use wxLogTrace inside of advanced config
|
// Because we even use wxLogTrace inside of advanced config
|
||||||
m_entries.push_back( std::make_unique<PARAM_CFG_WXSTRING>( true, AC_KEYS::TraceMasks, &m_traceMasks,
|
m_entries.push_back( std::make_unique<PARAM_CFG_WXSTRING>( true, AC_KEYS::TraceMasks, &m_traceMasks,
|
||||||
|
@ -397,6 +397,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
|
|||||||
aBitmapInfoCache[BITMAPS::add_line].emplace_back( BITMAPS::add_line, wxT( "add_line_24.png" ), 24, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_line].emplace_back( BITMAPS::add_line, wxT( "add_line_24.png" ), 24, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_orthogonal_dimension].emplace_back( BITMAPS::add_orthogonal_dimension, wxT( "add_orthogonal_dimension_24.png" ), 24, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_orthogonal_dimension].emplace_back( BITMAPS::add_orthogonal_dimension, wxT( "add_orthogonal_dimension_24.png" ), 24, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_pcb_target].emplace_back( BITMAPS::add_pcb_target, wxT( "add_pcb_target_24.png" ), 24, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_pcb_target].emplace_back( BITMAPS::add_pcb_target, wxT( "add_pcb_target_24.png" ), 24, wxT( "light" ) );
|
||||||
|
aBitmapInfoCache[BITMAPS::add_point].emplace_back( BITMAPS::add_point, wxT( "add_point_24.png" ), 24, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_power].emplace_back( BITMAPS::add_power, wxT( "add_power_24.png" ), 24, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_power].emplace_back( BITMAPS::add_power, wxT( "add_power_24.png" ), 24, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_radial_dimension].emplace_back( BITMAPS::add_radial_dimension, wxT( "add_radial_dimension_24.png" ), 24, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_radial_dimension].emplace_back( BITMAPS::add_radial_dimension, wxT( "add_radial_dimension_24.png" ), 24, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_rectangle].emplace_back( BITMAPS::add_rectangle, wxT( "add_rectangle_24.png" ), 24, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_rectangle].emplace_back( BITMAPS::add_rectangle, wxT( "add_rectangle_24.png" ), 24, wxT( "light" ) );
|
||||||
@ -836,6 +837,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
|
|||||||
aBitmapInfoCache[BITMAPS::add_line].emplace_back( BITMAPS::add_line, wxT( "add_line_dark_24.png" ), 24, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_line].emplace_back( BITMAPS::add_line, wxT( "add_line_dark_24.png" ), 24, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_orthogonal_dimension].emplace_back( BITMAPS::add_orthogonal_dimension, wxT( "add_orthogonal_dimension_dark_24.png" ), 24, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_orthogonal_dimension].emplace_back( BITMAPS::add_orthogonal_dimension, wxT( "add_orthogonal_dimension_dark_24.png" ), 24, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_pcb_target].emplace_back( BITMAPS::add_pcb_target, wxT( "add_pcb_target_dark_24.png" ), 24, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_pcb_target].emplace_back( BITMAPS::add_pcb_target, wxT( "add_pcb_target_dark_24.png" ), 24, wxT( "dark" ) );
|
||||||
|
aBitmapInfoCache[BITMAPS::add_point].emplace_back( BITMAPS::add_point, wxT( "add_point_dark_24.png" ), 24, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_power].emplace_back( BITMAPS::add_power, wxT( "add_power_dark_24.png" ), 24, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_power].emplace_back( BITMAPS::add_power, wxT( "add_power_dark_24.png" ), 24, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_radial_dimension].emplace_back( BITMAPS::add_radial_dimension, wxT( "add_radial_dimension_dark_24.png" ), 24, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_radial_dimension].emplace_back( BITMAPS::add_radial_dimension, wxT( "add_radial_dimension_dark_24.png" ), 24, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_rectangle].emplace_back( BITMAPS::add_rectangle, wxT( "add_rectangle_dark_24.png" ), 24, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_rectangle].emplace_back( BITMAPS::add_rectangle, wxT( "add_rectangle_dark_24.png" ), 24, wxT( "dark" ) );
|
||||||
@ -1275,6 +1277,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
|
|||||||
aBitmapInfoCache[BITMAPS::add_line].emplace_back( BITMAPS::add_line, wxT( "add_line_16.png" ), 16, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_line].emplace_back( BITMAPS::add_line, wxT( "add_line_16.png" ), 16, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_orthogonal_dimension].emplace_back( BITMAPS::add_orthogonal_dimension, wxT( "add_orthogonal_dimension_16.png" ), 16, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_orthogonal_dimension].emplace_back( BITMAPS::add_orthogonal_dimension, wxT( "add_orthogonal_dimension_16.png" ), 16, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_pcb_target].emplace_back( BITMAPS::add_pcb_target, wxT( "add_pcb_target_16.png" ), 16, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_pcb_target].emplace_back( BITMAPS::add_pcb_target, wxT( "add_pcb_target_16.png" ), 16, wxT( "light" ) );
|
||||||
|
aBitmapInfoCache[BITMAPS::add_point].emplace_back( BITMAPS::add_point, wxT( "add_point_16.png" ), 16, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_power].emplace_back( BITMAPS::add_power, wxT( "add_power_16.png" ), 16, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_power].emplace_back( BITMAPS::add_power, wxT( "add_power_16.png" ), 16, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_radial_dimension].emplace_back( BITMAPS::add_radial_dimension, wxT( "add_radial_dimension_16.png" ), 16, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_radial_dimension].emplace_back( BITMAPS::add_radial_dimension, wxT( "add_radial_dimension_16.png" ), 16, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_rectangle].emplace_back( BITMAPS::add_rectangle, wxT( "add_rectangle_16.png" ), 16, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_rectangle].emplace_back( BITMAPS::add_rectangle, wxT( "add_rectangle_16.png" ), 16, wxT( "light" ) );
|
||||||
@ -1714,6 +1717,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
|
|||||||
aBitmapInfoCache[BITMAPS::add_line].emplace_back( BITMAPS::add_line, wxT( "add_line_dark_16.png" ), 16, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_line].emplace_back( BITMAPS::add_line, wxT( "add_line_dark_16.png" ), 16, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_orthogonal_dimension].emplace_back( BITMAPS::add_orthogonal_dimension, wxT( "add_orthogonal_dimension_dark_16.png" ), 16, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_orthogonal_dimension].emplace_back( BITMAPS::add_orthogonal_dimension, wxT( "add_orthogonal_dimension_dark_16.png" ), 16, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_pcb_target].emplace_back( BITMAPS::add_pcb_target, wxT( "add_pcb_target_dark_16.png" ), 16, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_pcb_target].emplace_back( BITMAPS::add_pcb_target, wxT( "add_pcb_target_dark_16.png" ), 16, wxT( "dark" ) );
|
||||||
|
aBitmapInfoCache[BITMAPS::add_point].emplace_back( BITMAPS::add_point, wxT( "add_point_dark_16.png" ), 16, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_power].emplace_back( BITMAPS::add_power, wxT( "add_power_dark_16.png" ), 16, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_power].emplace_back( BITMAPS::add_power, wxT( "add_power_dark_16.png" ), 16, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_radial_dimension].emplace_back( BITMAPS::add_radial_dimension, wxT( "add_radial_dimension_dark_16.png" ), 16, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_radial_dimension].emplace_back( BITMAPS::add_radial_dimension, wxT( "add_radial_dimension_dark_16.png" ), 16, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_rectangle].emplace_back( BITMAPS::add_rectangle, wxT( "add_rectangle_dark_16.png" ), 16, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_rectangle].emplace_back( BITMAPS::add_rectangle, wxT( "add_rectangle_dark_16.png" ), 16, wxT( "dark" ) );
|
||||||
@ -2153,6 +2157,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
|
|||||||
aBitmapInfoCache[BITMAPS::add_line].emplace_back( BITMAPS::add_line, wxT( "add_line_32.png" ), 32, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_line].emplace_back( BITMAPS::add_line, wxT( "add_line_32.png" ), 32, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_orthogonal_dimension].emplace_back( BITMAPS::add_orthogonal_dimension, wxT( "add_orthogonal_dimension_32.png" ), 32, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_orthogonal_dimension].emplace_back( BITMAPS::add_orthogonal_dimension, wxT( "add_orthogonal_dimension_32.png" ), 32, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_pcb_target].emplace_back( BITMAPS::add_pcb_target, wxT( "add_pcb_target_32.png" ), 32, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_pcb_target].emplace_back( BITMAPS::add_pcb_target, wxT( "add_pcb_target_32.png" ), 32, wxT( "light" ) );
|
||||||
|
aBitmapInfoCache[BITMAPS::add_point].emplace_back( BITMAPS::add_point, wxT( "add_point_32.png" ), 32, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_power].emplace_back( BITMAPS::add_power, wxT( "add_power_32.png" ), 32, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_power].emplace_back( BITMAPS::add_power, wxT( "add_power_32.png" ), 32, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_radial_dimension].emplace_back( BITMAPS::add_radial_dimension, wxT( "add_radial_dimension_32.png" ), 32, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_radial_dimension].emplace_back( BITMAPS::add_radial_dimension, wxT( "add_radial_dimension_32.png" ), 32, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_rectangle].emplace_back( BITMAPS::add_rectangle, wxT( "add_rectangle_32.png" ), 32, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_rectangle].emplace_back( BITMAPS::add_rectangle, wxT( "add_rectangle_32.png" ), 32, wxT( "light" ) );
|
||||||
@ -2592,6 +2597,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
|
|||||||
aBitmapInfoCache[BITMAPS::add_line].emplace_back( BITMAPS::add_line, wxT( "add_line_dark_32.png" ), 32, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_line].emplace_back( BITMAPS::add_line, wxT( "add_line_dark_32.png" ), 32, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_orthogonal_dimension].emplace_back( BITMAPS::add_orthogonal_dimension, wxT( "add_orthogonal_dimension_dark_32.png" ), 32, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_orthogonal_dimension].emplace_back( BITMAPS::add_orthogonal_dimension, wxT( "add_orthogonal_dimension_dark_32.png" ), 32, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_pcb_target].emplace_back( BITMAPS::add_pcb_target, wxT( "add_pcb_target_dark_32.png" ), 32, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_pcb_target].emplace_back( BITMAPS::add_pcb_target, wxT( "add_pcb_target_dark_32.png" ), 32, wxT( "dark" ) );
|
||||||
|
aBitmapInfoCache[BITMAPS::add_point].emplace_back( BITMAPS::add_point, wxT( "add_point_dark_32.png" ), 32, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_power].emplace_back( BITMAPS::add_power, wxT( "add_power_dark_32.png" ), 32, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_power].emplace_back( BITMAPS::add_power, wxT( "add_power_dark_32.png" ), 32, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_radial_dimension].emplace_back( BITMAPS::add_radial_dimension, wxT( "add_radial_dimension_dark_32.png" ), 32, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_radial_dimension].emplace_back( BITMAPS::add_radial_dimension, wxT( "add_radial_dimension_dark_32.png" ), 32, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_rectangle].emplace_back( BITMAPS::add_rectangle, wxT( "add_rectangle_dark_32.png" ), 32, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_rectangle].emplace_back( BITMAPS::add_rectangle, wxT( "add_rectangle_dark_32.png" ), 32, wxT( "dark" ) );
|
||||||
@ -3031,6 +3037,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
|
|||||||
aBitmapInfoCache[BITMAPS::add_line].emplace_back( BITMAPS::add_line, wxT( "add_line_48.png" ), 48, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_line].emplace_back( BITMAPS::add_line, wxT( "add_line_48.png" ), 48, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_orthogonal_dimension].emplace_back( BITMAPS::add_orthogonal_dimension, wxT( "add_orthogonal_dimension_48.png" ), 48, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_orthogonal_dimension].emplace_back( BITMAPS::add_orthogonal_dimension, wxT( "add_orthogonal_dimension_48.png" ), 48, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_pcb_target].emplace_back( BITMAPS::add_pcb_target, wxT( "add_pcb_target_48.png" ), 48, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_pcb_target].emplace_back( BITMAPS::add_pcb_target, wxT( "add_pcb_target_48.png" ), 48, wxT( "light" ) );
|
||||||
|
aBitmapInfoCache[BITMAPS::add_point].emplace_back( BITMAPS::add_point, wxT( "add_point_48.png" ), 48, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_power].emplace_back( BITMAPS::add_power, wxT( "add_power_48.png" ), 48, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_power].emplace_back( BITMAPS::add_power, wxT( "add_power_48.png" ), 48, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_radial_dimension].emplace_back( BITMAPS::add_radial_dimension, wxT( "add_radial_dimension_48.png" ), 48, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_radial_dimension].emplace_back( BITMAPS::add_radial_dimension, wxT( "add_radial_dimension_48.png" ), 48, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_rectangle].emplace_back( BITMAPS::add_rectangle, wxT( "add_rectangle_48.png" ), 48, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_rectangle].emplace_back( BITMAPS::add_rectangle, wxT( "add_rectangle_48.png" ), 48, wxT( "light" ) );
|
||||||
@ -3470,6 +3477,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
|
|||||||
aBitmapInfoCache[BITMAPS::add_line].emplace_back( BITMAPS::add_line, wxT( "add_line_dark_48.png" ), 48, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_line].emplace_back( BITMAPS::add_line, wxT( "add_line_dark_48.png" ), 48, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_orthogonal_dimension].emplace_back( BITMAPS::add_orthogonal_dimension, wxT( "add_orthogonal_dimension_dark_48.png" ), 48, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_orthogonal_dimension].emplace_back( BITMAPS::add_orthogonal_dimension, wxT( "add_orthogonal_dimension_dark_48.png" ), 48, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_pcb_target].emplace_back( BITMAPS::add_pcb_target, wxT( "add_pcb_target_dark_48.png" ), 48, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_pcb_target].emplace_back( BITMAPS::add_pcb_target, wxT( "add_pcb_target_dark_48.png" ), 48, wxT( "dark" ) );
|
||||||
|
aBitmapInfoCache[BITMAPS::add_point].emplace_back( BITMAPS::add_point, wxT( "add_point_dark_48.png" ), 48, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_power].emplace_back( BITMAPS::add_power, wxT( "add_power_dark_48.png" ), 48, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_power].emplace_back( BITMAPS::add_power, wxT( "add_power_dark_48.png" ), 48, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_radial_dimension].emplace_back( BITMAPS::add_radial_dimension, wxT( "add_radial_dimension_dark_48.png" ), 48, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_radial_dimension].emplace_back( BITMAPS::add_radial_dimension, wxT( "add_radial_dimension_dark_48.png" ), 48, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_rectangle].emplace_back( BITMAPS::add_rectangle, wxT( "add_rectangle_dark_48.png" ), 48, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_rectangle].emplace_back( BITMAPS::add_rectangle, wxT( "add_rectangle_dark_48.png" ), 48, wxT( "dark" ) );
|
||||||
@ -3909,6 +3917,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
|
|||||||
aBitmapInfoCache[BITMAPS::add_line].emplace_back( BITMAPS::add_line, wxT( "add_line_64.png" ), 64, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_line].emplace_back( BITMAPS::add_line, wxT( "add_line_64.png" ), 64, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_orthogonal_dimension].emplace_back( BITMAPS::add_orthogonal_dimension, wxT( "add_orthogonal_dimension_64.png" ), 64, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_orthogonal_dimension].emplace_back( BITMAPS::add_orthogonal_dimension, wxT( "add_orthogonal_dimension_64.png" ), 64, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_pcb_target].emplace_back( BITMAPS::add_pcb_target, wxT( "add_pcb_target_64.png" ), 64, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_pcb_target].emplace_back( BITMAPS::add_pcb_target, wxT( "add_pcb_target_64.png" ), 64, wxT( "light" ) );
|
||||||
|
aBitmapInfoCache[BITMAPS::add_point].emplace_back( BITMAPS::add_point, wxT( "add_point_64.png" ), 64, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_power].emplace_back( BITMAPS::add_power, wxT( "add_power_64.png" ), 64, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_power].emplace_back( BITMAPS::add_power, wxT( "add_power_64.png" ), 64, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_radial_dimension].emplace_back( BITMAPS::add_radial_dimension, wxT( "add_radial_dimension_64.png" ), 64, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_radial_dimension].emplace_back( BITMAPS::add_radial_dimension, wxT( "add_radial_dimension_64.png" ), 64, wxT( "light" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_rectangle].emplace_back( BITMAPS::add_rectangle, wxT( "add_rectangle_64.png" ), 64, wxT( "light" ) );
|
aBitmapInfoCache[BITMAPS::add_rectangle].emplace_back( BITMAPS::add_rectangle, wxT( "add_rectangle_64.png" ), 64, wxT( "light" ) );
|
||||||
@ -4348,6 +4357,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
|
|||||||
aBitmapInfoCache[BITMAPS::add_line].emplace_back( BITMAPS::add_line, wxT( "add_line_dark_64.png" ), 64, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_line].emplace_back( BITMAPS::add_line, wxT( "add_line_dark_64.png" ), 64, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_orthogonal_dimension].emplace_back( BITMAPS::add_orthogonal_dimension, wxT( "add_orthogonal_dimension_dark_64.png" ), 64, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_orthogonal_dimension].emplace_back( BITMAPS::add_orthogonal_dimension, wxT( "add_orthogonal_dimension_dark_64.png" ), 64, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_pcb_target].emplace_back( BITMAPS::add_pcb_target, wxT( "add_pcb_target_dark_64.png" ), 64, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_pcb_target].emplace_back( BITMAPS::add_pcb_target, wxT( "add_pcb_target_dark_64.png" ), 64, wxT( "dark" ) );
|
||||||
|
aBitmapInfoCache[BITMAPS::add_point].emplace_back( BITMAPS::add_point, wxT( "add_point_dark_64.png" ), 64, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_power].emplace_back( BITMAPS::add_power, wxT( "add_power_dark_64.png" ), 64, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_power].emplace_back( BITMAPS::add_power, wxT( "add_power_dark_64.png" ), 64, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_radial_dimension].emplace_back( BITMAPS::add_radial_dimension, wxT( "add_radial_dimension_dark_64.png" ), 64, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_radial_dimension].emplace_back( BITMAPS::add_radial_dimension, wxT( "add_radial_dimension_dark_64.png" ), 64, wxT( "dark" ) );
|
||||||
aBitmapInfoCache[BITMAPS::add_rectangle].emplace_back( BITMAPS::add_rectangle, wxT( "add_rectangle_dark_64.png" ), 64, wxT( "dark" ) );
|
aBitmapInfoCache[BITMAPS::add_rectangle].emplace_back( BITMAPS::add_rectangle, wxT( "add_rectangle_dark_64.png" ), 64, wxT( "dark" ) );
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "clipboard.h"
|
#include "clipboard.h"
|
||||||
|
|
||||||
#include <wx/clipbrd.h>
|
#include <wx/clipbrd.h>
|
||||||
|
#include <wx/dataobj.h>
|
||||||
#include <wx/image.h>
|
#include <wx/image.h>
|
||||||
#include <wx/log.h>
|
#include <wx/log.h>
|
||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
@ -90,10 +91,10 @@ std::unique_ptr<wxImage> GetImageFromClipboard()
|
|||||||
{
|
{
|
||||||
if( wxTheClipboard->IsSupported( wxDF_BITMAP ) )
|
if( wxTheClipboard->IsSupported( wxDF_BITMAP ) )
|
||||||
{
|
{
|
||||||
wxImageDataObject data;
|
wxBitmapDataObject data;
|
||||||
if( wxTheClipboard->GetData( 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 ) )
|
else if( wxTheClipboard->IsSupported( wxDF_FILENAME ) )
|
||||||
|
@ -190,7 +190,7 @@ void DESIGN_BLOCK_LIST_IMPL::loadDesignBlocks()
|
|||||||
};
|
};
|
||||||
|
|
||||||
for( size_t ii = 0; ii < num_elements; ++ii )
|
for( size_t ii = 0; ii < num_elements; ++ii )
|
||||||
returns[ii] = tp.submit( db_thread );
|
returns[ii] = tp.submit_task( db_thread );
|
||||||
|
|
||||||
for( const std::future<size_t>& ret : returns )
|
for( const std::future<size_t>& ret : returns )
|
||||||
{
|
{
|
||||||
|
@ -41,6 +41,9 @@
|
|||||||
#include <wx/app.h>
|
#include <wx/app.h>
|
||||||
#include <wx/event.h>
|
#include <wx/event.h>
|
||||||
#include <wx/grid.h>
|
#include <wx/grid.h>
|
||||||
|
#include <wx/propgrid/propgrid.h>
|
||||||
|
#include <wx/checklst.h>
|
||||||
|
#include <wx/dataview.h>
|
||||||
#include <wx/bmpbuttn.h>
|
#include <wx/bmpbuttn.h>
|
||||||
#include <wx/textctrl.h>
|
#include <wx/textctrl.h>
|
||||||
#include <wx/stc/stc.h>
|
#include <wx/stc/stc.h>
|
||||||
@ -79,7 +82,8 @@ DIALOG_SHIM::DIALOG_SHIM( wxWindow* aParent, wxWindowID id, const wxString& titl
|
|||||||
m_qmodal_parent_disabler( nullptr ),
|
m_qmodal_parent_disabler( nullptr ),
|
||||||
m_parentFrame( nullptr ),
|
m_parentFrame( nullptr ),
|
||||||
m_userPositioned( false ),
|
m_userPositioned( false ),
|
||||||
m_userResized( false )
|
m_userResized( false ),
|
||||||
|
m_handlingUndoRedo( false )
|
||||||
{
|
{
|
||||||
KIWAY_HOLDER* kiwayHolder = nullptr;
|
KIWAY_HOLDER* kiwayHolder = nullptr;
|
||||||
m_initialSize = size;
|
m_initialSize = size;
|
||||||
@ -174,6 +178,75 @@ DIALOG_SHIM::~DIALOG_SHIM()
|
|||||||
|
|
||||||
disconnectFocusHandlers( GetChildren() );
|
disconnectFocusHandlers( GetChildren() );
|
||||||
|
|
||||||
|
std::function<void( wxWindowList& )> disconnectUndoRedoHandlers =
|
||||||
|
[&]( wxWindowList& children )
|
||||||
|
{
|
||||||
|
for( wxWindow* child : children )
|
||||||
|
{
|
||||||
|
if( wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( child ) )
|
||||||
|
{
|
||||||
|
textCtrl->Unbind( wxEVT_TEXT, &DIALOG_SHIM::onCommandEvent, this );
|
||||||
|
}
|
||||||
|
else if( wxStyledTextCtrl* scintilla = dynamic_cast<wxStyledTextCtrl*>( child ) )
|
||||||
|
{
|
||||||
|
scintilla->Unbind( wxEVT_STC_CHANGE, &DIALOG_SHIM::onStyledTextChanged, this );
|
||||||
|
}
|
||||||
|
else if( wxComboBox* combo = dynamic_cast<wxComboBox*>( child ) )
|
||||||
|
{
|
||||||
|
combo->Unbind( wxEVT_TEXT, &DIALOG_SHIM::onCommandEvent, this );
|
||||||
|
combo->Unbind( wxEVT_COMBOBOX, &DIALOG_SHIM::onCommandEvent, this );
|
||||||
|
}
|
||||||
|
else if( wxChoice* choice = dynamic_cast<wxChoice*>( child ) )
|
||||||
|
{
|
||||||
|
choice->Unbind( wxEVT_CHOICE, &DIALOG_SHIM::onCommandEvent, this );
|
||||||
|
}
|
||||||
|
else if( wxCheckBox* check = dynamic_cast<wxCheckBox*>( child ) )
|
||||||
|
{
|
||||||
|
check->Unbind( wxEVT_CHECKBOX, &DIALOG_SHIM::onCommandEvent, this );
|
||||||
|
}
|
||||||
|
else if( wxSpinCtrl* spin = dynamic_cast<wxSpinCtrl*>( child ) )
|
||||||
|
{
|
||||||
|
spin->Unbind( wxEVT_SPINCTRL, &DIALOG_SHIM::onSpinEvent, this );
|
||||||
|
spin->Unbind( wxEVT_TEXT, &DIALOG_SHIM::onCommandEvent, this );
|
||||||
|
}
|
||||||
|
else if( wxSpinCtrlDouble* spinD = dynamic_cast<wxSpinCtrlDouble*>( child ) )
|
||||||
|
{
|
||||||
|
spinD->Unbind( wxEVT_SPINCTRLDOUBLE, &DIALOG_SHIM::onSpinDoubleEvent, this );
|
||||||
|
spinD->Unbind( wxEVT_TEXT, &DIALOG_SHIM::onCommandEvent, this );
|
||||||
|
}
|
||||||
|
else if( wxRadioButton* radio = dynamic_cast<wxRadioButton*>( child ) )
|
||||||
|
{
|
||||||
|
radio->Unbind( wxEVT_RADIOBUTTON, &DIALOG_SHIM::onCommandEvent, this );
|
||||||
|
}
|
||||||
|
else if( wxRadioBox* radioBox = dynamic_cast<wxRadioBox*>( child ) )
|
||||||
|
{
|
||||||
|
radioBox->Unbind( wxEVT_RADIOBOX, &DIALOG_SHIM::onCommandEvent, this );
|
||||||
|
}
|
||||||
|
else if( wxGrid* grid = dynamic_cast<wxGrid*>( child ) )
|
||||||
|
{
|
||||||
|
grid->Unbind( wxEVT_GRID_CELL_CHANGED, &DIALOG_SHIM::onGridCellChanged, this );
|
||||||
|
}
|
||||||
|
else if( wxPropertyGrid* propGrid = dynamic_cast<wxPropertyGrid*>( child ) )
|
||||||
|
{
|
||||||
|
propGrid->Unbind( wxEVT_PG_CHANGED, &DIALOG_SHIM::onPropertyGridChanged, this );
|
||||||
|
}
|
||||||
|
else if( wxCheckListBox* checkList = dynamic_cast<wxCheckListBox*>( child ) )
|
||||||
|
{
|
||||||
|
checkList->Unbind( wxEVT_CHECKLISTBOX, &DIALOG_SHIM::onCommandEvent, this );
|
||||||
|
}
|
||||||
|
else if( wxDataViewListCtrl* dataList = dynamic_cast<wxDataViewListCtrl*>( child ) )
|
||||||
|
{
|
||||||
|
dataList->Unbind( wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, &DIALOG_SHIM::onDataViewListChanged, this );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
disconnectUndoRedoHandlers( child->GetChildren() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
disconnectUndoRedoHandlers( GetChildren() );
|
||||||
|
|
||||||
// if the dialog is quasi-modal, this will end its event loop
|
// if the dialog is quasi-modal, this will end its event loop
|
||||||
if( IsQuasiModal() )
|
if( IsQuasiModal() )
|
||||||
EndQuasiModal( wxID_CANCEL );
|
EndQuasiModal( wxID_CANCEL );
|
||||||
@ -732,6 +805,373 @@ void DIALOG_SHIM::SelectAllInTextCtrls( wxWindowList& children )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DIALOG_SHIM::registerUndoRedoHandlers( wxWindowList& children )
|
||||||
|
{
|
||||||
|
for( wxWindow* child : children )
|
||||||
|
{
|
||||||
|
if( wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( child ) )
|
||||||
|
{
|
||||||
|
textCtrl->Bind( wxEVT_TEXT, &DIALOG_SHIM::onCommandEvent, this );
|
||||||
|
m_currentValues[ textCtrl ] = textCtrl->GetValue();
|
||||||
|
}
|
||||||
|
else if( wxStyledTextCtrl* scintilla = dynamic_cast<wxStyledTextCtrl*>( child ) )
|
||||||
|
{
|
||||||
|
scintilla->Bind( wxEVT_STC_CHANGE, &DIALOG_SHIM::onStyledTextChanged, this );
|
||||||
|
m_currentValues[ scintilla ] = scintilla->GetText();
|
||||||
|
}
|
||||||
|
else if( wxComboBox* combo = dynamic_cast<wxComboBox*>( child ) )
|
||||||
|
{
|
||||||
|
combo->Bind( wxEVT_TEXT, &DIALOG_SHIM::onCommandEvent, this );
|
||||||
|
combo->Bind( wxEVT_COMBOBOX, &DIALOG_SHIM::onCommandEvent, this );
|
||||||
|
m_currentValues[ combo ] = combo->GetValue();
|
||||||
|
}
|
||||||
|
else if( wxChoice* choice = dynamic_cast<wxChoice*>( child ) )
|
||||||
|
{
|
||||||
|
choice->Bind( wxEVT_CHOICE, &DIALOG_SHIM::onCommandEvent, this );
|
||||||
|
m_currentValues[ choice ] = static_cast<long>( choice->GetSelection() );
|
||||||
|
}
|
||||||
|
else if( wxCheckBox* check = dynamic_cast<wxCheckBox*>( child ) )
|
||||||
|
{
|
||||||
|
check->Bind( wxEVT_CHECKBOX, &DIALOG_SHIM::onCommandEvent, this );
|
||||||
|
m_currentValues[ check ] = check->GetValue();
|
||||||
|
}
|
||||||
|
else if( wxSpinCtrl* spin = dynamic_cast<wxSpinCtrl*>( child ) )
|
||||||
|
{
|
||||||
|
spin->Bind( wxEVT_SPINCTRL, &DIALOG_SHIM::onSpinEvent, this );
|
||||||
|
spin->Bind( wxEVT_TEXT, &DIALOG_SHIM::onCommandEvent, this );
|
||||||
|
m_currentValues[ spin ] = static_cast<long>( spin->GetValue() );
|
||||||
|
}
|
||||||
|
else if( wxSpinCtrlDouble* spinD = dynamic_cast<wxSpinCtrlDouble*>( child ) )
|
||||||
|
{
|
||||||
|
spinD->Bind( wxEVT_SPINCTRLDOUBLE, &DIALOG_SHIM::onSpinDoubleEvent, this );
|
||||||
|
spinD->Bind( wxEVT_TEXT, &DIALOG_SHIM::onCommandEvent, this );
|
||||||
|
m_currentValues[ spinD ] = spinD->GetValue();
|
||||||
|
}
|
||||||
|
else if( wxRadioButton* radio = dynamic_cast<wxRadioButton*>( child ) )
|
||||||
|
{
|
||||||
|
radio->Bind( wxEVT_RADIOBUTTON, &DIALOG_SHIM::onCommandEvent, this );
|
||||||
|
m_currentValues[ radio ] = radio->GetValue();
|
||||||
|
}
|
||||||
|
else if( wxRadioBox* radioBox = dynamic_cast<wxRadioBox*>( child ) )
|
||||||
|
{
|
||||||
|
radioBox->Bind( wxEVT_RADIOBOX, &DIALOG_SHIM::onCommandEvent, this );
|
||||||
|
m_currentValues[ radioBox ] = static_cast<long>( radioBox->GetSelection() );
|
||||||
|
}
|
||||||
|
else if( wxGrid* grid = dynamic_cast<wxGrid*>( child ) )
|
||||||
|
{
|
||||||
|
grid->Bind( wxEVT_GRID_CELL_CHANGED, &DIALOG_SHIM::onGridCellChanged, this );
|
||||||
|
m_currentValues[ grid ] = getControlValue( grid );
|
||||||
|
}
|
||||||
|
else if( wxPropertyGrid* propGrid = dynamic_cast<wxPropertyGrid*>( child ) )
|
||||||
|
{
|
||||||
|
propGrid->Bind( wxEVT_PG_CHANGED, &DIALOG_SHIM::onPropertyGridChanged, this );
|
||||||
|
m_currentValues[ propGrid ] = getControlValue( propGrid );
|
||||||
|
}
|
||||||
|
else if( wxCheckListBox* checkList = dynamic_cast<wxCheckListBox*>( child ) )
|
||||||
|
{
|
||||||
|
checkList->Bind( wxEVT_CHECKLISTBOX, &DIALOG_SHIM::onCommandEvent, this );
|
||||||
|
m_currentValues[ checkList ] = getControlValue( checkList );
|
||||||
|
}
|
||||||
|
else if( wxDataViewListCtrl* dataList = dynamic_cast<wxDataViewListCtrl*>( child ) )
|
||||||
|
{
|
||||||
|
dataList->Bind( wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, &DIALOG_SHIM::onDataViewListChanged, this );
|
||||||
|
m_currentValues[ dataList ] = getControlValue( dataList );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
registerUndoRedoHandlers( child->GetChildren() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DIALOG_SHIM::recordControlChange( wxWindow* aCtrl )
|
||||||
|
{
|
||||||
|
wxVariant before = m_currentValues[ aCtrl ];
|
||||||
|
wxVariant after = getControlValue( aCtrl );
|
||||||
|
|
||||||
|
if( before != after )
|
||||||
|
{
|
||||||
|
m_undoStack.push_back( { aCtrl, before, after } );
|
||||||
|
m_redoStack.clear();
|
||||||
|
m_currentValues[ aCtrl ] = after;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DIALOG_SHIM::onCommandEvent( wxCommandEvent& aEvent )
|
||||||
|
{
|
||||||
|
if( !m_handlingUndoRedo )
|
||||||
|
recordControlChange( static_cast<wxWindow*>( aEvent.GetEventObject() ) );
|
||||||
|
|
||||||
|
aEvent.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DIALOG_SHIM::onSpinEvent( wxSpinEvent& aEvent )
|
||||||
|
{
|
||||||
|
if( !m_handlingUndoRedo )
|
||||||
|
recordControlChange( static_cast<wxWindow*>( aEvent.GetEventObject() ) );
|
||||||
|
|
||||||
|
aEvent.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DIALOG_SHIM::onSpinDoubleEvent( wxSpinDoubleEvent& aEvent )
|
||||||
|
{
|
||||||
|
if( !m_handlingUndoRedo )
|
||||||
|
recordControlChange( static_cast<wxWindow*>( aEvent.GetEventObject() ) );
|
||||||
|
|
||||||
|
aEvent.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DIALOG_SHIM::onStyledTextChanged( wxStyledTextEvent& aEvent )
|
||||||
|
{
|
||||||
|
if( !m_handlingUndoRedo )
|
||||||
|
recordControlChange( static_cast<wxWindow*>( aEvent.GetEventObject() ) );
|
||||||
|
|
||||||
|
aEvent.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DIALOG_SHIM::onGridCellChanged( wxGridEvent& aEvent )
|
||||||
|
{
|
||||||
|
if( !m_handlingUndoRedo )
|
||||||
|
recordControlChange( static_cast<wxWindow*>( aEvent.GetEventObject() ) );
|
||||||
|
|
||||||
|
aEvent.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DIALOG_SHIM::onPropertyGridChanged( wxPropertyGridEvent& aEvent )
|
||||||
|
{
|
||||||
|
if( !m_handlingUndoRedo )
|
||||||
|
recordControlChange( static_cast<wxWindow*>( aEvent.GetEventObject() ) );
|
||||||
|
|
||||||
|
aEvent.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DIALOG_SHIM::onDataViewListChanged( wxDataViewEvent& aEvent )
|
||||||
|
{
|
||||||
|
if( !m_handlingUndoRedo )
|
||||||
|
recordControlChange( static_cast<wxWindow*>( aEvent.GetEventObject() ) );
|
||||||
|
|
||||||
|
aEvent.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
wxVariant DIALOG_SHIM::getControlValue( wxWindow* aCtrl )
|
||||||
|
{
|
||||||
|
if( wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( aCtrl ) )
|
||||||
|
return wxVariant( textCtrl->GetValue() );
|
||||||
|
else if( wxStyledTextCtrl* scintilla = dynamic_cast<wxStyledTextCtrl*>( aCtrl ) )
|
||||||
|
return wxVariant( scintilla->GetText() );
|
||||||
|
else if( wxComboBox* combo = dynamic_cast<wxComboBox*>( aCtrl ) )
|
||||||
|
return wxVariant( combo->GetValue() );
|
||||||
|
else if( wxChoice* choice = dynamic_cast<wxChoice*>( aCtrl ) )
|
||||||
|
return wxVariant( (long) choice->GetSelection() );
|
||||||
|
else if( wxCheckBox* check = dynamic_cast<wxCheckBox*>( aCtrl ) )
|
||||||
|
return wxVariant( check->GetValue() );
|
||||||
|
else if( wxSpinCtrl* spin = dynamic_cast<wxSpinCtrl*>( aCtrl ) )
|
||||||
|
return wxVariant( (long) spin->GetValue() );
|
||||||
|
else if( wxSpinCtrlDouble* spinD = dynamic_cast<wxSpinCtrlDouble*>( aCtrl ) )
|
||||||
|
return wxVariant( spinD->GetValue() );
|
||||||
|
else if( wxRadioButton* radio = dynamic_cast<wxRadioButton*>( aCtrl ) )
|
||||||
|
return wxVariant( radio->GetValue() );
|
||||||
|
else if( wxRadioBox* radioBox = dynamic_cast<wxRadioBox*>( aCtrl ) )
|
||||||
|
return wxVariant( (long) radioBox->GetSelection() );
|
||||||
|
else if( wxGrid* grid = dynamic_cast<wxGrid*>( aCtrl ) )
|
||||||
|
{
|
||||||
|
nlohmann::json j = nlohmann::json::array();
|
||||||
|
int rows = grid->GetNumberRows();
|
||||||
|
int cols = grid->GetNumberCols();
|
||||||
|
|
||||||
|
for( int r = 0; r < rows; ++r )
|
||||||
|
{
|
||||||
|
nlohmann::json row = nlohmann::json::array();
|
||||||
|
|
||||||
|
for( int c = 0; c < cols; ++c )
|
||||||
|
row.push_back( std::string( grid->GetCellValue( r, c ).ToUTF8() ) );
|
||||||
|
|
||||||
|
j.push_back( row );
|
||||||
|
}
|
||||||
|
|
||||||
|
return wxVariant( wxString( j.dump() ) );
|
||||||
|
}
|
||||||
|
else if( wxPropertyGrid* propGrid = dynamic_cast<wxPropertyGrid*>( aCtrl ) )
|
||||||
|
{
|
||||||
|
nlohmann::json j;
|
||||||
|
|
||||||
|
for( wxPropertyGridIterator it = propGrid->GetIterator(); !it.AtEnd(); ++it )
|
||||||
|
{
|
||||||
|
wxPGProperty* prop = *it;
|
||||||
|
j[ prop->GetName().ToStdString() ] = prop->GetValueAsString().ToStdString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return wxVariant( wxString( j.dump() ) );
|
||||||
|
}
|
||||||
|
else if( wxCheckListBox* checkList = dynamic_cast<wxCheckListBox*>( aCtrl ) )
|
||||||
|
{
|
||||||
|
nlohmann::json j = nlohmann::json::array();
|
||||||
|
unsigned int count = checkList->GetCount();
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < count; ++i )
|
||||||
|
{
|
||||||
|
if( checkList->IsChecked( i ) )
|
||||||
|
j.push_back( i );
|
||||||
|
}
|
||||||
|
|
||||||
|
return wxVariant( wxString( j.dump() ) );
|
||||||
|
}
|
||||||
|
else if( wxDataViewListCtrl* dataList = dynamic_cast<wxDataViewListCtrl*>( aCtrl ) )
|
||||||
|
{
|
||||||
|
nlohmann::json j = nlohmann::json::array();
|
||||||
|
unsigned int rows = dataList->GetItemCount();
|
||||||
|
unsigned int cols = dataList->GetColumnCount();
|
||||||
|
|
||||||
|
for( unsigned int r = 0; r < rows; ++r )
|
||||||
|
{
|
||||||
|
nlohmann::json row = nlohmann::json::array();
|
||||||
|
|
||||||
|
for( unsigned int c = 0; c < cols; ++c )
|
||||||
|
{
|
||||||
|
wxVariant val;
|
||||||
|
dataList->GetValue( val, r, c );
|
||||||
|
row.push_back( std::string( val.GetString().ToUTF8() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
j.push_back( row );
|
||||||
|
}
|
||||||
|
|
||||||
|
return wxVariant( wxString( j.dump() ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return wxVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DIALOG_SHIM::setControlValue( wxWindow* aCtrl, const wxVariant& aValue )
|
||||||
|
{
|
||||||
|
if( wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( aCtrl ) )
|
||||||
|
textCtrl->SetValue( aValue.GetString() );
|
||||||
|
else if( wxStyledTextCtrl* scintilla = dynamic_cast<wxStyledTextCtrl*>( aCtrl ) )
|
||||||
|
scintilla->SetText( aValue.GetString() );
|
||||||
|
else if( wxComboBox* combo = dynamic_cast<wxComboBox*>( aCtrl ) )
|
||||||
|
combo->SetValue( aValue.GetString() );
|
||||||
|
else if( wxChoice* choice = dynamic_cast<wxChoice*>( aCtrl ) )
|
||||||
|
choice->SetSelection( (int) aValue.GetLong() );
|
||||||
|
else if( wxCheckBox* check = dynamic_cast<wxCheckBox*>( aCtrl ) )
|
||||||
|
check->SetValue( aValue.GetBool() );
|
||||||
|
else if( wxSpinCtrl* spin = dynamic_cast<wxSpinCtrl*>( aCtrl ) )
|
||||||
|
spin->SetValue( (int) aValue.GetLong() );
|
||||||
|
else if( wxSpinCtrlDouble* spinD = dynamic_cast<wxSpinCtrlDouble*>( aCtrl ) )
|
||||||
|
spinD->SetValue( aValue.GetDouble() );
|
||||||
|
else if( wxRadioButton* radio = dynamic_cast<wxRadioButton*>( aCtrl ) )
|
||||||
|
radio->SetValue( aValue.GetBool() );
|
||||||
|
else if( wxRadioBox* radioBox = dynamic_cast<wxRadioBox*>( aCtrl ) )
|
||||||
|
radioBox->SetSelection( (int) aValue.GetLong() );
|
||||||
|
else if( wxGrid* grid = dynamic_cast<wxGrid*>( aCtrl ) )
|
||||||
|
{
|
||||||
|
nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(), nullptr, false );
|
||||||
|
|
||||||
|
if( j.is_array() )
|
||||||
|
{
|
||||||
|
int rows = std::min( (int) j.size(), grid->GetNumberRows() );
|
||||||
|
|
||||||
|
for( int r = 0; r < rows; ++r )
|
||||||
|
{
|
||||||
|
nlohmann::json row = j[r];
|
||||||
|
int cols = std::min( (int) row.size(), grid->GetNumberCols() );
|
||||||
|
|
||||||
|
for( int c = 0; c < cols; ++c )
|
||||||
|
grid->SetCellValue( r, c, wxString( row[c].get<std::string>() ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( wxPropertyGrid* propGrid = dynamic_cast<wxPropertyGrid*>( aCtrl ) )
|
||||||
|
{
|
||||||
|
nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(), nullptr, false );
|
||||||
|
|
||||||
|
if( j.is_object() )
|
||||||
|
{
|
||||||
|
for( auto it = j.begin(); it != j.end(); ++it )
|
||||||
|
propGrid->SetPropertyValue( wxString( it.key() ), wxString( it.value().get<std::string>() ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( wxCheckListBox* checkList = dynamic_cast<wxCheckListBox*>( aCtrl ) )
|
||||||
|
{
|
||||||
|
nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(), nullptr, false );
|
||||||
|
|
||||||
|
if( j.is_array() )
|
||||||
|
{
|
||||||
|
unsigned int count = checkList->GetCount();
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < count; ++i )
|
||||||
|
checkList->Check( i, false );
|
||||||
|
|
||||||
|
for( auto& idx : j )
|
||||||
|
{
|
||||||
|
unsigned int i = idx.get<unsigned int>();
|
||||||
|
|
||||||
|
if( i < count )
|
||||||
|
checkList->Check( i, true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( wxDataViewListCtrl* dataList = dynamic_cast<wxDataViewListCtrl*>( aCtrl ) )
|
||||||
|
{
|
||||||
|
nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(), nullptr, false );
|
||||||
|
|
||||||
|
if( j.is_array() )
|
||||||
|
{
|
||||||
|
unsigned int rows = std::min( static_cast<unsigned int>( j.size() ),
|
||||||
|
static_cast<unsigned int>( dataList->GetItemCount() ) );
|
||||||
|
|
||||||
|
for( unsigned int r = 0; r < rows; ++r )
|
||||||
|
{
|
||||||
|
nlohmann::json row = j[r];
|
||||||
|
unsigned int cols = std::min( (unsigned int) row.size(), dataList->GetColumnCount() );
|
||||||
|
|
||||||
|
for( unsigned int c = 0; c < cols; ++c )
|
||||||
|
{
|
||||||
|
wxVariant val( wxString( row[c].get<std::string>() ) );
|
||||||
|
dataList->SetValue( val, r, c );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DIALOG_SHIM::doUndo()
|
||||||
|
{
|
||||||
|
if( m_undoStack.empty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_handlingUndoRedo = true;
|
||||||
|
UNDO_STEP step = m_undoStack.back();
|
||||||
|
m_undoStack.pop_back();
|
||||||
|
setControlValue( step.ctrl, step.before );
|
||||||
|
m_currentValues[ step.ctrl ] = step.before;
|
||||||
|
m_redoStack.push_back( step );
|
||||||
|
m_handlingUndoRedo = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DIALOG_SHIM::doRedo()
|
||||||
|
{
|
||||||
|
if( m_redoStack.empty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_handlingUndoRedo = true;
|
||||||
|
UNDO_STEP step = m_redoStack.back();
|
||||||
|
m_redoStack.pop_back();
|
||||||
|
setControlValue( step.ctrl, step.after );
|
||||||
|
m_currentValues[ step.ctrl ] = step.after;
|
||||||
|
m_undoStack.push_back( step );
|
||||||
|
m_handlingUndoRedo = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DIALOG_SHIM::OnPaint( wxPaintEvent &event )
|
void DIALOG_SHIM::OnPaint( wxPaintEvent &event )
|
||||||
{
|
{
|
||||||
if( m_firstPaintEvent )
|
if( m_firstPaintEvent )
|
||||||
@ -739,6 +1179,7 @@ void DIALOG_SHIM::OnPaint( wxPaintEvent &event )
|
|||||||
KIPLATFORM::UI::FixupCancelButtonCmdKeyCollision( this );
|
KIPLATFORM::UI::FixupCancelButtonCmdKeyCollision( this );
|
||||||
|
|
||||||
SelectAllInTextCtrls( GetChildren() );
|
SelectAllInTextCtrls( GetChildren() );
|
||||||
|
registerUndoRedoHandlers( GetChildren() );
|
||||||
|
|
||||||
if( m_initialFocusTarget )
|
if( m_initialFocusTarget )
|
||||||
KIPLATFORM::UI::ForceFocus( m_initialFocusTarget );
|
KIPLATFORM::UI::ForceFocus( m_initialFocusTarget );
|
||||||
@ -966,6 +1407,30 @@ void DIALOG_SHIM::onChildSetFocus( wxFocusEvent& aEvent )
|
|||||||
|
|
||||||
void DIALOG_SHIM::OnCharHook( wxKeyEvent& aEvt )
|
void DIALOG_SHIM::OnCharHook( wxKeyEvent& aEvt )
|
||||||
{
|
{
|
||||||
|
int key = aEvt.GetKeyCode();
|
||||||
|
int mods = 0;
|
||||||
|
|
||||||
|
if( aEvt.ControlDown() )
|
||||||
|
mods |= MD_CTRL;
|
||||||
|
if( aEvt.ShiftDown() )
|
||||||
|
mods |= MD_SHIFT;
|
||||||
|
if( aEvt.AltDown() )
|
||||||
|
mods |= MD_ALT;
|
||||||
|
|
||||||
|
int hotkey = key | mods;
|
||||||
|
|
||||||
|
// Check for standard undo/redo hotkeys
|
||||||
|
if( hotkey == (MD_CTRL + 'Z') )
|
||||||
|
{
|
||||||
|
doUndo();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if( hotkey == (MD_CTRL + MD_SHIFT + 'Z') || hotkey == (MD_CTRL + 'Y') )
|
||||||
|
{
|
||||||
|
doRedo();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if( aEvt.GetKeyCode() == 'U' && aEvt.GetModifiers() == wxMOD_CONTROL )
|
if( aEvt.GetKeyCode() == 'U' && aEvt.GetModifiers() == wxMOD_CONTROL )
|
||||||
{
|
{
|
||||||
if( m_parentFrame )
|
if( m_parentFrame )
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf)
|
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
|
||||||
// http://www.wxformbuilder.org/
|
// http://www.wxformbuilder.org/
|
||||||
//
|
//
|
||||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||||
@ -26,25 +26,6 @@ WX_TEXT_ENTRY_DIALOG_BASE::WX_TEXT_ENTRY_DIALOG_BASE( wxWindow* parent, wxWindow
|
|||||||
|
|
||||||
m_ContentSizer->Add( m_textCtrl, 0, wxEXPAND|wxALL, 5 );
|
m_ContentSizer->Add( m_textCtrl, 0, wxEXPAND|wxALL, 5 );
|
||||||
|
|
||||||
wxBoxSizer* bSizer3;
|
|
||||||
bSizer3 = new wxBoxSizer( wxHORIZONTAL );
|
|
||||||
|
|
||||||
m_choiceLabel = new wxStaticText( this, wxID_ANY, _("MyLabel"), wxDefaultPosition, wxDefaultSize, 0 );
|
|
||||||
m_choiceLabel->Wrap( -1 );
|
|
||||||
m_choiceLabel->Hide();
|
|
||||||
|
|
||||||
bSizer3->Add( m_choiceLabel, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
|
||||||
|
|
||||||
wxArrayString m_choiceChoices;
|
|
||||||
m_choice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceChoices, 0 );
|
|
||||||
m_choice->SetSelection( 0 );
|
|
||||||
m_choice->Hide();
|
|
||||||
|
|
||||||
bSizer3->Add( m_choice, 3, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
|
||||||
|
|
||||||
|
|
||||||
m_ContentSizer->Add( bSizer3, 1, wxEXPAND, 5 );
|
|
||||||
|
|
||||||
|
|
||||||
m_mainSizer->Add( m_ContentSizer, 1, wxALL|wxEXPAND, 5 );
|
m_mainSizer->Add( m_ContentSizer, 1, wxALL|wxEXPAND, 5 );
|
||||||
|
|
||||||
|
@ -1,34 +1,36 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<wxFormBuilder_Project>
|
<wxFormBuilder_Project>
|
||||||
<FileVersion major="1" minor="17"/>
|
<FileVersion major="1" minor="18"/>
|
||||||
<object class="Project" expanded="true">
|
<object class="Project" expanded="true">
|
||||||
<property name="class_decoration"></property>
|
|
||||||
<property name="code_generation">C++</property>
|
<property name="code_generation">C++</property>
|
||||||
<property name="disconnect_events">1</property>
|
<property name="cpp_class_decoration"></property>
|
||||||
<property name="disconnect_mode">source_name</property>
|
<property name="cpp_disconnect_events">1</property>
|
||||||
<property name="disconnect_php_events">0</property>
|
<property name="cpp_event_generation">connect</property>
|
||||||
<property name="disconnect_python_events">0</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="embedded_files_path">res</property>
|
||||||
<property name="encoding">UTF-8</property>
|
<property name="encoding">UTF-8</property>
|
||||||
<property name="event_generation">connect</property>
|
|
||||||
<property name="file">dialog_text_entry_base</property>
|
<property name="file">dialog_text_entry_base</property>
|
||||||
<property name="first_id">1000</property>
|
<property name="first_id">1000</property>
|
||||||
<property name="help_provider">none</property>
|
|
||||||
<property name="image_path_wrapper_function_name"></property>
|
|
||||||
<property name="indent_with_spaces"></property>
|
|
||||||
<property name="internationalize">1</property>
|
<property name="internationalize">1</property>
|
||||||
|
<property name="lua_skip_events">1</property>
|
||||||
|
<property name="lua_ui_table">UI</property>
|
||||||
<property name="name">dialog_text_entry_base</property>
|
<property name="name">dialog_text_entry_base</property>
|
||||||
<property name="namespace"></property>
|
|
||||||
<property name="path">.</property>
|
<property name="path">.</property>
|
||||||
<property name="precompiled_header"></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="relative_path">1</property>
|
||||||
<property name="skip_lua_events">1</property>
|
|
||||||
<property name="skip_php_events">1</property>
|
|
||||||
<property name="skip_python_events">1</property>
|
|
||||||
<property name="ui_table">UI</property>
|
|
||||||
<property name="use_array_enum">0</property>
|
|
||||||
<property name="use_enum">0</property>
|
|
||||||
<property name="use_microsoft_bom">0</property>
|
<property name="use_microsoft_bom">0</property>
|
||||||
|
<property name="use_native_eol">0</property>
|
||||||
<object class="Dialog" expanded="true">
|
<object class="Dialog" expanded="true">
|
||||||
<property name="aui_managed">0</property>
|
<property name="aui_managed">0</property>
|
||||||
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
|
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
|
||||||
@ -80,10 +82,10 @@
|
|||||||
<property name="LeftDockable">1</property>
|
<property name="LeftDockable">1</property>
|
||||||
<property name="RightDockable">1</property>
|
<property name="RightDockable">1</property>
|
||||||
<property name="TopDockable">1</property>
|
<property name="TopDockable">1</property>
|
||||||
<property name="aui_layer"></property>
|
<property name="aui_layer">0</property>
|
||||||
<property name="aui_name"></property>
|
<property name="aui_name"></property>
|
||||||
<property name="aui_position"></property>
|
<property name="aui_position">0</property>
|
||||||
<property name="aui_row"></property>
|
<property name="aui_row">0</property>
|
||||||
<property name="best_size"></property>
|
<property name="best_size"></property>
|
||||||
<property name="bg"></property>
|
<property name="bg"></property>
|
||||||
<property name="caption"></property>
|
<property name="caption"></property>
|
||||||
@ -142,10 +144,10 @@
|
|||||||
<property name="LeftDockable">1</property>
|
<property name="LeftDockable">1</property>
|
||||||
<property name="RightDockable">1</property>
|
<property name="RightDockable">1</property>
|
||||||
<property name="TopDockable">1</property>
|
<property name="TopDockable">1</property>
|
||||||
<property name="aui_layer"></property>
|
<property name="aui_layer">0</property>
|
||||||
<property name="aui_name"></property>
|
<property name="aui_name"></property>
|
||||||
<property name="aui_position"></property>
|
<property name="aui_position">0</property>
|
||||||
<property name="aui_row"></property>
|
<property name="aui_row">0</property>
|
||||||
<property name="best_size"></property>
|
<property name="best_size"></property>
|
||||||
<property name="bg"></property>
|
<property name="bg"></property>
|
||||||
<property name="caption"></property>
|
<property name="caption"></property>
|
||||||
@ -169,7 +171,7 @@
|
|||||||
<property name="max_size"></property>
|
<property name="max_size"></property>
|
||||||
<property name="maximize_button">0</property>
|
<property name="maximize_button">0</property>
|
||||||
<property name="maximum_size"></property>
|
<property name="maximum_size"></property>
|
||||||
<property name="maxlength"></property>
|
<property name="maxlength">0</property>
|
||||||
<property name="min_size"></property>
|
<property name="min_size"></property>
|
||||||
<property name="minimize_button">0</property>
|
<property name="minimize_button">0</property>
|
||||||
<property name="minimum_size">300,-1</property>
|
<property name="minimum_size">300,-1</property>
|
||||||
@ -198,144 +200,6 @@
|
|||||||
<property name="window_style"></property>
|
<property name="window_style"></property>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<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">bSizer3</property>
|
|
||||||
<property name="orient">wxHORIZONTAL</property>
|
|
||||||
<property name="permission">none</property>
|
|
||||||
<object class="sizeritem" expanded="true">
|
|
||||||
<property name="border">5</property>
|
|
||||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT</property>
|
|
||||||
<property name="proportion">0</property>
|
|
||||||
<object class="wxStaticText" 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"></property>
|
|
||||||
<property name="aui_name"></property>
|
|
||||||
<property name="aui_position"></property>
|
|
||||||
<property name="aui_row"></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">1</property>
|
|
||||||
<property name="id">wxID_ANY</property>
|
|
||||||
<property name="label">MyLabel</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_choiceLabel</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"></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>
|
|
||||||
<property name="wrap">-1</property>
|
|
||||||
</object>
|
|
||||||
</object>
|
|
||||||
<object class="sizeritem" expanded="true">
|
|
||||||
<property name="border">5</property>
|
|
||||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT</property>
|
|
||||||
<property name="proportion">3</property>
|
|
||||||
<object class="wxChoice" 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"></property>
|
|
||||||
<property name="aui_name"></property>
|
|
||||||
<property name="aui_position"></property>
|
|
||||||
<property name="aui_row"></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="choices"></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">1</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_choice</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="selection">0</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="window_extra_style"></property>
|
|
||||||
<property name="window_name"></property>
|
|
||||||
<property name="window_style"></property>
|
|
||||||
</object>
|
|
||||||
</object>
|
|
||||||
</object>
|
|
||||||
</object>
|
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="false">
|
<object class="sizeritem" expanded="false">
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf)
|
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
|
||||||
// http://www.wxformbuilder.org/
|
// http://www.wxformbuilder.org/
|
||||||
//
|
//
|
||||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||||
@ -18,14 +18,12 @@
|
|||||||
#include <wx/colour.h>
|
#include <wx/colour.h>
|
||||||
#include <wx/settings.h>
|
#include <wx/settings.h>
|
||||||
#include <wx/textctrl.h>
|
#include <wx/textctrl.h>
|
||||||
#include <wx/choice.h>
|
|
||||||
#include <wx/sizer.h>
|
#include <wx/sizer.h>
|
||||||
#include <wx/button.h>
|
#include <wx/button.h>
|
||||||
#include <wx/dialog.h>
|
#include <wx/dialog.h>
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
/// Class WX_TEXT_ENTRY_DIALOG_BASE
|
/// Class WX_TEXT_ENTRY_DIALOG_BASE
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -37,8 +35,6 @@ class WX_TEXT_ENTRY_DIALOG_BASE : public DIALOG_SHIM
|
|||||||
wxBoxSizer* m_mainSizer;
|
wxBoxSizer* m_mainSizer;
|
||||||
wxStaticText* m_label;
|
wxStaticText* m_label;
|
||||||
wxTextCtrl* m_textCtrl;
|
wxTextCtrl* m_textCtrl;
|
||||||
wxStaticText* m_choiceLabel;
|
|
||||||
wxChoice* m_choice;
|
|
||||||
wxStdDialogButtonSizer* m_sdbSizer1;
|
wxStdDialogButtonSizer* m_sdbSizer1;
|
||||||
wxButton* m_sdbSizer1OK;
|
wxButton* m_sdbSizer1OK;
|
||||||
wxButton* m_sdbSizer1Cancel;
|
wxButton* m_sdbSizer1Cancel;
|
||||||
|
@ -41,8 +41,7 @@ static int DEFAULT_COL_WIDTHS[] = { 200, 300 };
|
|||||||
EDA_LIST_DIALOG::EDA_LIST_DIALOG( wxWindow* aParent, const wxString& aTitle,
|
EDA_LIST_DIALOG::EDA_LIST_DIALOG( wxWindow* aParent, const wxString& aTitle,
|
||||||
const wxArrayString& aItemHeaders,
|
const wxArrayString& aItemHeaders,
|
||||||
const std::vector<wxArrayString>& aItemList,
|
const std::vector<wxArrayString>& aItemList,
|
||||||
const wxString& aPreselectText, bool aSortList,
|
const wxString& aPreselectText, bool aSortList ) :
|
||||||
const std::vector<std::pair<wxString, bool*>>& aExtraCheckboxes ) :
|
|
||||||
EDA_LIST_DIALOG_BASE( aParent, wxID_ANY, aTitle ),
|
EDA_LIST_DIALOG_BASE( aParent, wxID_ANY, aTitle ),
|
||||||
m_sortList( aSortList )
|
m_sortList( aSortList )
|
||||||
{
|
{
|
||||||
@ -63,19 +62,6 @@ EDA_LIST_DIALOG::EDA_LIST_DIALOG( wxWindow* aParent, const wxString& aTitle,
|
|||||||
// columns, different column names, and column widths.
|
// columns, different column names, and column widths.
|
||||||
m_hash_key = TO_UTF8( aTitle );
|
m_hash_key = TO_UTF8( aTitle );
|
||||||
|
|
||||||
if( !aExtraCheckboxes.empty() )
|
|
||||||
{
|
|
||||||
m_ExtrasSizer->AddSpacer( 5 );
|
|
||||||
|
|
||||||
for( const auto& [label, valuePtr] : aExtraCheckboxes )
|
|
||||||
{
|
|
||||||
wxCheckBox* cb = new wxCheckBox( this, wxID_ANY, label );
|
|
||||||
cb->SetValue( *valuePtr );
|
|
||||||
m_ExtrasSizer->Add( cb, 0, wxBOTTOM, 5 );
|
|
||||||
m_extraCheckboxMap[cb] = valuePtr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SetupStandardButtons();
|
SetupStandardButtons();
|
||||||
|
|
||||||
Layout();
|
Layout();
|
||||||
@ -93,6 +79,22 @@ EDA_LIST_DIALOG::EDA_LIST_DIALOG( wxWindow* aParent, const wxString& aTitle, boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDA_LIST_DIALOG::AddExtraCheckbox( const wxString& aLabel, bool* aValuePtr )
|
||||||
|
{
|
||||||
|
wxCHECK2_MSG( aValuePtr, return, wxT( "Null pointer for checkbox value." ) );
|
||||||
|
|
||||||
|
int flags = wxBOTTOM;
|
||||||
|
|
||||||
|
if( m_ExtrasSizer->GetItemCount() > 0 )
|
||||||
|
flags |= wxTOP;
|
||||||
|
|
||||||
|
wxCheckBox* cb = new wxCheckBox( this, wxID_ANY, aLabel );
|
||||||
|
cb->SetValue( *aValuePtr );
|
||||||
|
m_ExtrasSizer->Add( cb, 0, flags, 5 );
|
||||||
|
m_extraCheckboxMap[cb] = aValuePtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool EDA_LIST_DIALOG::Show( bool show )
|
bool EDA_LIST_DIALOG::Show( bool show )
|
||||||
{
|
{
|
||||||
bool retVal = DIALOG_SHIM::Show( show );
|
bool retVal = DIALOG_SHIM::Show( show );
|
||||||
|
@ -26,6 +26,11 @@
|
|||||||
#include <wx/log.h>
|
#include <wx/log.h>
|
||||||
#include <wx/textctrl.h>
|
#include <wx/textctrl.h>
|
||||||
#include <wx/uri.h>
|
#include <wx/uri.h>
|
||||||
|
#include <wx/panel.h>
|
||||||
|
#include <wx/sizer.h>
|
||||||
|
#include <wx/button.h>
|
||||||
|
#include <wx/stattext.h>
|
||||||
|
#include <algorithm>
|
||||||
#include <string_utils.h>
|
#include <string_utils.h>
|
||||||
#include <dialogs/html_message_box.h>
|
#include <dialogs/html_message_box.h>
|
||||||
#include <build_version.h>
|
#include <build_version.h>
|
||||||
@ -38,6 +43,33 @@ HTML_MESSAGE_BOX::HTML_MESSAGE_BOX( wxWindow* aParent, const wxString& aTitle,
|
|||||||
m_htmlWindow->SetLayoutDirection( wxLayout_LeftToRight );
|
m_htmlWindow->SetLayoutDirection( wxLayout_LeftToRight );
|
||||||
ListClear();
|
ListClear();
|
||||||
|
|
||||||
|
m_searchPanel = new wxPanel( this );
|
||||||
|
wxBoxSizer* searchSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
m_matchCount = new wxStaticText( m_searchPanel, wxID_ANY, wxEmptyString );
|
||||||
|
m_searchCtrl = new wxTextCtrl( m_searchPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER );
|
||||||
|
m_prevBtn = new wxButton( m_searchPanel, wxID_ANY, wxS( "∧" ), wxDefaultPosition, wxDefaultSize, wxBORDER_NONE );
|
||||||
|
m_nextBtn = new wxButton( m_searchPanel, wxID_ANY, wxS( "∨" ), wxDefaultPosition, wxDefaultSize, wxBORDER_NONE );
|
||||||
|
|
||||||
|
// Set minimum size for buttons to make them thinner
|
||||||
|
m_prevBtn->SetMinSize( wxSize( 25, -1 ) );
|
||||||
|
m_nextBtn->SetMinSize( wxSize( 25, -1 ) );
|
||||||
|
|
||||||
|
// Set minimum width for match count to ensure it's visible
|
||||||
|
m_matchCount->SetMinSize( wxSize( 60, -1 ) );
|
||||||
|
|
||||||
|
searchSizer->Add( m_matchCount, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
|
||||||
|
searchSizer->Add( m_searchCtrl, 1, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
|
||||||
|
searchSizer->Add( m_prevBtn, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 2 );
|
||||||
|
searchSizer->Add( m_nextBtn, 0, wxALIGN_CENTER_VERTICAL );
|
||||||
|
m_searchPanel->SetSizer( searchSizer );
|
||||||
|
m_searchPanel->Hide();
|
||||||
|
GetSizer()->Insert( 0, m_searchPanel, 0, wxALIGN_RIGHT|wxTOP|wxRIGHT, 5 );
|
||||||
|
|
||||||
|
m_searchCtrl->Bind( wxEVT_TEXT, &HTML_MESSAGE_BOX::OnSearchText, this );
|
||||||
|
m_searchCtrl->Bind( wxEVT_TEXT_ENTER, &HTML_MESSAGE_BOX::OnNext, this );
|
||||||
|
m_prevBtn->Bind( wxEVT_BUTTON, &HTML_MESSAGE_BOX::OnPrev, this );
|
||||||
|
m_nextBtn->Bind( wxEVT_BUTTON, &HTML_MESSAGE_BOX::OnNext, this );
|
||||||
|
|
||||||
// Gives a default logical size (the actual size depends on the display definition)
|
// Gives a default logical size (the actual size depends on the display definition)
|
||||||
if( aSize != wxDefaultSize )
|
if( aSize != wxDefaultSize )
|
||||||
setSizeInDU( aSize.x, aSize.y );
|
setSizeInDU( aSize.x, aSize.y );
|
||||||
@ -162,7 +194,46 @@ void HTML_MESSAGE_BOX::OnHTMLLinkClicked( wxHtmlLinkEvent& event )
|
|||||||
|
|
||||||
void HTML_MESSAGE_BOX::OnCharHook( wxKeyEvent& aEvent )
|
void HTML_MESSAGE_BOX::OnCharHook( wxKeyEvent& aEvent )
|
||||||
{
|
{
|
||||||
// shift-return (Mac default) or Ctrl-Return (GTK) for OK
|
if( m_searchPanel->IsShown() )
|
||||||
|
{
|
||||||
|
if( aEvent.GetKeyCode() == WXK_ESCAPE )
|
||||||
|
{
|
||||||
|
HideSearchBar();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if( aEvent.GetKeyCode() == WXK_RETURN || aEvent.GetKeyCode() == WXK_NUMPAD_ENTER )
|
||||||
|
{
|
||||||
|
wxCommandEvent evt;
|
||||||
|
OnNext( evt );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if( aEvent.GetKeyCode() == WXK_BACK )
|
||||||
|
{
|
||||||
|
long from, to;
|
||||||
|
m_searchCtrl->GetSelection( &from, &to );
|
||||||
|
|
||||||
|
if( from == to )
|
||||||
|
m_searchCtrl->Remove( std::max( 0L, from - 1 ), from );
|
||||||
|
else
|
||||||
|
m_searchCtrl->Remove( from, to );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if( !aEvent.HasModifiers() && wxIsprint( aEvent.GetUnicodeKey() ) )
|
||||||
|
{
|
||||||
|
m_searchCtrl->AppendText( wxString( (wxChar) aEvent.GetUnicodeKey() ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( !aEvent.HasModifiers() && wxIsprint( aEvent.GetUnicodeKey() ) )
|
||||||
|
{
|
||||||
|
ShowSearchBar();
|
||||||
|
m_searchCtrl->SetValue( wxString( (wxChar) aEvent.GetUnicodeKey() ) );
|
||||||
|
m_currentMatch = 0;
|
||||||
|
updateSearch();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if( aEvent.GetKeyCode() == WXK_ESCAPE )
|
if( aEvent.GetKeyCode() == WXK_ESCAPE )
|
||||||
{
|
{
|
||||||
wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
|
wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
|
||||||
@ -189,3 +260,195 @@ void HTML_MESSAGE_BOX::OnCharHook( wxKeyEvent& aEvent )
|
|||||||
|
|
||||||
aEvent.Skip();
|
aEvent.Skip();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HTML_MESSAGE_BOX::OnSearchText( wxCommandEvent& aEvent )
|
||||||
|
{
|
||||||
|
m_currentMatch = 0;
|
||||||
|
updateSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTML_MESSAGE_BOX::OnNext( wxCommandEvent& aEvent )
|
||||||
|
{
|
||||||
|
if( !m_matchPos.empty() )
|
||||||
|
{
|
||||||
|
m_currentMatch = ( m_currentMatch + 1 ) % m_matchPos.size();
|
||||||
|
updateSearch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTML_MESSAGE_BOX::OnPrev( wxCommandEvent& aEvent )
|
||||||
|
{
|
||||||
|
if( !m_matchPos.empty() )
|
||||||
|
{
|
||||||
|
m_currentMatch = ( m_currentMatch + m_matchPos.size() - 1 ) % m_matchPos.size();
|
||||||
|
updateSearch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTML_MESSAGE_BOX::ShowSearchBar()
|
||||||
|
{
|
||||||
|
if( !m_searchPanel->IsShown() )
|
||||||
|
{
|
||||||
|
m_originalSource = m_source;
|
||||||
|
m_searchPanel->Show();
|
||||||
|
Layout();
|
||||||
|
m_searchCtrl->SetFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTML_MESSAGE_BOX::HideSearchBar()
|
||||||
|
{
|
||||||
|
if( m_searchPanel->IsShown() )
|
||||||
|
{
|
||||||
|
m_searchPanel->Hide();
|
||||||
|
Layout();
|
||||||
|
m_source = m_originalSource;
|
||||||
|
reload();
|
||||||
|
|
||||||
|
// Refocus on the main HTML window so user can press Escape again to close the dialog
|
||||||
|
m_htmlWindow->SetFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTML_MESSAGE_BOX::updateSearch()
|
||||||
|
{
|
||||||
|
wxString term = m_searchCtrl->GetValue();
|
||||||
|
|
||||||
|
if( term.IsEmpty() )
|
||||||
|
{
|
||||||
|
m_source = m_originalSource;
|
||||||
|
reload();
|
||||||
|
m_matchPos.clear();
|
||||||
|
m_matchCount->SetLabel( wxEmptyString );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_matchPos.clear();
|
||||||
|
|
||||||
|
// Search only in text content, not in HTML tags
|
||||||
|
wxString termLower = term.Lower();
|
||||||
|
size_t pos = 0;
|
||||||
|
bool insideTag = false;
|
||||||
|
|
||||||
|
while( pos < m_originalSource.length() )
|
||||||
|
{
|
||||||
|
wxChar ch = m_originalSource[pos];
|
||||||
|
|
||||||
|
if( ch == '<' )
|
||||||
|
{
|
||||||
|
insideTag = true;
|
||||||
|
}
|
||||||
|
else if( ch == '>' )
|
||||||
|
{
|
||||||
|
insideTag = false;
|
||||||
|
pos++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only search for matches when we're not inside an HTML tag
|
||||||
|
if( !insideTag )
|
||||||
|
{
|
||||||
|
// Check if we have a match starting at this position
|
||||||
|
if( pos + termLower.length() <= m_originalSource.length() )
|
||||||
|
{
|
||||||
|
wxString candidate = m_originalSource.Mid( pos, termLower.length() ).Lower();
|
||||||
|
if( candidate == termLower )
|
||||||
|
{
|
||||||
|
// Verify that this match doesn't span into an HTML tag
|
||||||
|
bool validMatch = true;
|
||||||
|
for( size_t i = 0; i < termLower.length(); i++ )
|
||||||
|
{
|
||||||
|
if( pos + i < m_originalSource.length() && m_originalSource[pos + i] == '<' )
|
||||||
|
{
|
||||||
|
validMatch = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( validMatch )
|
||||||
|
{
|
||||||
|
m_matchPos.push_back( pos );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_matchPos.empty() )
|
||||||
|
{
|
||||||
|
m_source = m_originalSource;
|
||||||
|
reload();
|
||||||
|
m_matchCount->SetLabel( wxS( "0/0" ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_currentMatch >= (int) m_matchPos.size() )
|
||||||
|
m_currentMatch = 0;
|
||||||
|
|
||||||
|
wxString out;
|
||||||
|
size_t start = 0;
|
||||||
|
|
||||||
|
for( size_t i = 0; i < m_matchPos.size(); ++i )
|
||||||
|
{
|
||||||
|
size_t idx = m_matchPos[i];
|
||||||
|
out += m_originalSource.Mid( start, idx - start );
|
||||||
|
wxString matchStr = m_originalSource.Mid( idx, term.length() );
|
||||||
|
|
||||||
|
// HTML-escape the match string to prevent HTML parsing issues
|
||||||
|
wxString escapedMatchStr = matchStr;
|
||||||
|
escapedMatchStr.Replace( wxS( "&" ), wxS( "&" ) );
|
||||||
|
escapedMatchStr.Replace( wxS( "<" ), wxS( "<" ) );
|
||||||
|
escapedMatchStr.Replace( wxS( ">" ), wxS( ">" ) );
|
||||||
|
escapedMatchStr.Replace( wxS( "\"" ), wxS( """ ) );
|
||||||
|
|
||||||
|
if( (int) i == m_currentMatch )
|
||||||
|
{
|
||||||
|
// Use a unique anchor name for each search to avoid conflicts
|
||||||
|
wxString anchorName = wxString::Format( wxS( "kicad_search_%d" ), m_currentMatch );
|
||||||
|
out += wxString::Format( wxS( "<a name=\"%s\"></a><span style=\"background-color:#DDAAFF;\">%s</span>" ),
|
||||||
|
anchorName, escapedMatchStr );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out += wxString::Format( wxS( "<span style=\"background-color:#FFFFAA;\">%s</span>" ), escapedMatchStr );
|
||||||
|
}
|
||||||
|
|
||||||
|
start = idx + term.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
out += m_originalSource.Mid( start );
|
||||||
|
m_source = out;
|
||||||
|
reload();
|
||||||
|
|
||||||
|
// Use CallAfter to ensure the HTML is fully loaded before scrolling
|
||||||
|
// Only scroll if we have matches and a valid current match
|
||||||
|
if( !m_matchPos.empty() && m_currentMatch >= 0 && m_currentMatch < (int)m_matchPos.size() )
|
||||||
|
{
|
||||||
|
CallAfter( [this]()
|
||||||
|
{
|
||||||
|
// Try to scroll to the anchor, with fallback if it fails
|
||||||
|
wxString anchorName = wxString::Format( wxS( "kicad_search_%d" ), m_currentMatch );
|
||||||
|
if( !m_htmlWindow->ScrollToAnchor( anchorName ) )
|
||||||
|
{
|
||||||
|
// If anchor scrolling fails, try to scroll to approximate position
|
||||||
|
// Calculate approximate scroll position based on match location
|
||||||
|
if( !m_matchPos.empty() && m_currentMatch < (int)m_matchPos.size() )
|
||||||
|
{
|
||||||
|
size_t matchPos = m_matchPos[m_currentMatch];
|
||||||
|
size_t totalLength = m_originalSource.length();
|
||||||
|
if( totalLength > 0 )
|
||||||
|
{
|
||||||
|
// Scroll to approximate percentage of document
|
||||||
|
double ratio = (double)matchPos / (double)totalLength;
|
||||||
|
int scrollPos = (int)(ratio * m_htmlWindow->GetScrollRange( wxVERTICAL ));
|
||||||
|
m_htmlWindow->Scroll( 0, scrollPos );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_matchCount->SetLabel( wxString::Format( wxS( "%d/%zu" ), m_currentMatch + 1, m_matchPos.size() ) );
|
||||||
|
}
|
||||||
|
@ -17,21 +17,19 @@
|
|||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <widgets/gal_options_panel.h>
|
#include <dialogs/panel_gal_options.h>
|
||||||
#include <widgets/paged_dialog.h>
|
#include <widgets/paged_dialog.h>
|
||||||
|
#include <dialogs/panel_base_display_options.h>
|
||||||
#include <dialogs/panel_gal_display_options.h>
|
|
||||||
|
|
||||||
|
|
||||||
PANEL_GAL_DISPLAY_OPTIONS::PANEL_GAL_DISPLAY_OPTIONS( wxWindow* aParent,
|
PANEL_BASE_DISPLAY_OPTIONS::PANEL_BASE_DISPLAY_OPTIONS( wxWindow* aParent, APP_SETTINGS_BASE* aAppSettings ) :
|
||||||
APP_SETTINGS_BASE* aAppSettings ) :
|
wxPanel( aParent, wxID_ANY )
|
||||||
wxPanel( aParent, wxID_ANY )
|
|
||||||
{
|
{
|
||||||
auto mainSizer = new wxBoxSizer( wxHORIZONTAL );
|
auto mainSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||||
SetSizer( mainSizer );
|
SetSizer( mainSizer );
|
||||||
|
|
||||||
// install GAL options pane
|
// install GAL options pane
|
||||||
m_galOptsPanel = new GAL_OPTIONS_PANEL( this, aAppSettings );
|
m_galOptsPanel = new PANEL_GAL_OPTIONS( this, aAppSettings );
|
||||||
mainSizer->Add( m_galOptsPanel, 1, wxEXPAND | wxLEFT, 5 );
|
mainSizer->Add( m_galOptsPanel, 1, wxEXPAND | wxLEFT, 5 );
|
||||||
|
|
||||||
// a spacer to take up the other half of the width
|
// a spacer to take up the other half of the width
|
||||||
@ -40,14 +38,14 @@ PANEL_GAL_DISPLAY_OPTIONS::PANEL_GAL_DISPLAY_OPTIONS( wxWindow* aParent,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PANEL_GAL_DISPLAY_OPTIONS::TransferDataToWindow()
|
bool PANEL_BASE_DISPLAY_OPTIONS::TransferDataToWindow()
|
||||||
{
|
{
|
||||||
m_galOptsPanel->TransferDataToWindow();
|
m_galOptsPanel->TransferDataToWindow();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PANEL_GAL_DISPLAY_OPTIONS::TransferDataFromWindow()
|
bool PANEL_BASE_DISPLAY_OPTIONS::TransferDataFromWindow()
|
||||||
{
|
{
|
||||||
m_galOptsPanel->TransferDataFromWindow();
|
m_galOptsPanel->TransferDataFromWindow();
|
||||||
return true;
|
return true;
|
@ -27,6 +27,8 @@
|
|||||||
#include <bitmaps.h>
|
#include <bitmaps.h>
|
||||||
#include <class_draw_panel_gal.h>
|
#include <class_draw_panel_gal.h>
|
||||||
#include <dpi_scaling_common.h>
|
#include <dpi_scaling_common.h>
|
||||||
|
#include <eda_draw_frame.h>
|
||||||
|
#include <gal/graphics_abstraction_layer.h>
|
||||||
#include <kiface_base.h>
|
#include <kiface_base.h>
|
||||||
#include <kiplatform/ui.h>
|
#include <kiplatform/ui.h>
|
||||||
#include <pgm_base.h>
|
#include <pgm_base.h>
|
||||||
@ -105,6 +107,10 @@ PANEL_COMMON_SETTINGS::PANEL_COMMON_SETTINGS( wxWindow* aParent ) :
|
|||||||
m_canvasScaleAuto->Show( false );
|
m_canvasScaleAuto->Show( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_zoomCorrectionCtrl = new ZOOM_CORRECTION_CTRL( this,
|
||||||
|
Pgm().GetCommonSettings()->m_Appearance.zoom_correction_factor );
|
||||||
|
bLeftSizer->Add( m_zoomCorrectionCtrl, 1, wxEXPAND );
|
||||||
|
|
||||||
// Hide the option of icons in menus for platforms that do not support them
|
// Hide the option of icons in menus for platforms that do not support them
|
||||||
m_checkBoxIconsInMenus->Show( KIPLATFORM::UI::AllowIconsInMenus() );
|
m_checkBoxIconsInMenus->Show( KIPLATFORM::UI::AllowIconsInMenus() );
|
||||||
|
|
||||||
@ -198,6 +204,8 @@ bool PANEL_COMMON_SETTINGS::TransferDataFromWindow()
|
|||||||
|
|
||||||
commonSettings->m_Appearance.grid_striping = m_gridStriping->GetValue();
|
commonSettings->m_Appearance.grid_striping = m_gridStriping->GetValue();
|
||||||
|
|
||||||
|
commonSettings->m_Appearance.zoom_correction_factor = m_zoomCorrectionCtrl->GetValue();
|
||||||
|
|
||||||
double dimmingPercent = 80;
|
double dimmingPercent = 80;
|
||||||
m_highContrastCtrl->GetValue().ToDouble( &dimmingPercent );
|
m_highContrastCtrl->GetValue().ToDouble( &dimmingPercent );
|
||||||
commonSettings->m_Appearance.hicontrast_dimming_factor = dimmingPercent / 100.0f;
|
commonSettings->m_Appearance.hicontrast_dimming_factor = dimmingPercent / 100.0f;
|
||||||
@ -288,6 +296,8 @@ void PANEL_COMMON_SETTINGS::applySettingsToPanel( COMMON_SETTINGS& aSettings )
|
|||||||
|
|
||||||
m_gridStriping->SetValue( aSettings.m_Appearance.grid_striping );
|
m_gridStriping->SetValue( aSettings.m_Appearance.grid_striping );
|
||||||
|
|
||||||
|
m_zoomCorrectionCtrl->SetDisplayedValue( aSettings.m_Appearance.zoom_correction_factor );
|
||||||
|
|
||||||
double dimmingPercent = aSettings.m_Appearance.hicontrast_dimming_factor * 100.0f;
|
double dimmingPercent = aSettings.m_Appearance.hicontrast_dimming_factor * 100.0f;
|
||||||
m_highContrastCtrl->SetValue( wxString::Format( "%.0f", dimmingPercent ) );
|
m_highContrastCtrl->SetValue( wxString::Format( "%.0f", dimmingPercent ) );
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
|
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6a-dirty)
|
||||||
// http://www.wxformbuilder.org/
|
// http://www.wxformbuilder.org/
|
||||||
//
|
//
|
||||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||||
@ -16,7 +16,6 @@ PANEL_COMMON_SETTINGS_BASE::PANEL_COMMON_SETTINGS_BASE( wxWindow* parent, wxWind
|
|||||||
wxBoxSizer* bPanelSizer;
|
wxBoxSizer* bPanelSizer;
|
||||||
bPanelSizer = new wxBoxSizer( wxHORIZONTAL );
|
bPanelSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
|
||||||
wxBoxSizer* bLeftSizer;
|
|
||||||
bLeftSizer = new wxBoxSizer( wxVERTICAL );
|
bLeftSizer = new wxBoxSizer( wxVERTICAL );
|
||||||
|
|
||||||
m_staticText20 = new wxStaticText( this, wxID_ANY, _("Rendering Engine"), wxDefaultPosition, wxDefaultSize, 0 );
|
m_staticText20 = new wxStaticText( this, wxID_ANY, _("Rendering Engine"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
@ -292,6 +291,16 @@ PANEL_COMMON_SETTINGS_BASE::PANEL_COMMON_SETTINGS_BASE( wxWindow* parent, wxWind
|
|||||||
bLeftSizer->Add( bUserInterfaceSizer, 0, wxTOP|wxLEFT|wxEXPAND, 5 );
|
bLeftSizer->Add( bUserInterfaceSizer, 0, wxTOP|wxLEFT|wxEXPAND, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
bLeftSizer->Add( 0, 0, 0, 0, 5 );
|
||||||
|
|
||||||
|
m_staticText251 = new wxStaticText( this, wxID_ANY, _("Scaling"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
m_staticText251->Wrap( -1 );
|
||||||
|
bLeftSizer->Add( m_staticText251, 0, wxLEFT|wxRIGHT|wxTOP, 15 );
|
||||||
|
|
||||||
|
m_staticline7 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||||
|
bLeftSizer->Add( m_staticline7, 0, wxEXPAND | wxALL, 5 );
|
||||||
|
|
||||||
|
|
||||||
bPanelSizer->Add( bLeftSizer, 0, wxRIGHT, 35 );
|
bPanelSizer->Add( bLeftSizer, 0, wxRIGHT, 35 );
|
||||||
|
|
||||||
wxBoxSizer* rightSizer;
|
wxBoxSizer* rightSizer;
|
||||||
|
@ -68,12 +68,12 @@
|
|||||||
<property name="minimum_size"></property>
|
<property name="minimum_size"></property>
|
||||||
<property name="name">bLeftSizer</property>
|
<property name="name">bLeftSizer</property>
|
||||||
<property name="orient">wxVERTICAL</property>
|
<property name="orient">wxVERTICAL</property>
|
||||||
<property name="permission">none</property>
|
<property name="permission">protected</property>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">13</property>
|
<property name="border">13</property>
|
||||||
<property name="flag">wxTOP|wxRIGHT|wxLEFT|wxEXPAND</property>
|
<property name="flag">wxTOP|wxRIGHT|wxLEFT|wxEXPAND</property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="wxStaticText" expanded="true">
|
<object class="wxStaticText" expanded="false">
|
||||||
<property name="BottomDockable">1</property>
|
<property name="BottomDockable">1</property>
|
||||||
<property name="LeftDockable">1</property>
|
<property name="LeftDockable">1</property>
|
||||||
<property name="RightDockable">1</property>
|
<property name="RightDockable">1</property>
|
||||||
@ -131,11 +131,11 @@
|
|||||||
<property name="wrap">-1</property>
|
<property name="wrap">-1</property>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">2</property>
|
<property name="border">2</property>
|
||||||
<property name="flag">wxEXPAND|wxTOP|wxBOTTOM</property>
|
<property name="flag">wxEXPAND|wxTOP|wxBOTTOM</property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="wxStaticLine" expanded="true">
|
<object class="wxStaticLine" expanded="false">
|
||||||
<property name="BottomDockable">1</property>
|
<property name="BottomDockable">1</property>
|
||||||
<property name="LeftDockable">1</property>
|
<property name="LeftDockable">1</property>
|
||||||
<property name="RightDockable">1</property>
|
<property name="RightDockable">1</property>
|
||||||
@ -190,21 +190,21 @@
|
|||||||
<property name="window_style"></property>
|
<property name="window_style"></property>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="flag"></property>
|
<property name="flag"></property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="spacer" expanded="true">
|
<object class="spacer" expanded="false">
|
||||||
<property name="height">3</property>
|
<property name="height">3</property>
|
||||||
<property name="permission">protected</property>
|
<property name="permission">protected</property>
|
||||||
<property name="width">0</property>
|
<property name="width">0</property>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
|
<property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
|
||||||
<property name="proportion">1</property>
|
<property name="proportion">1</property>
|
||||||
<object class="wxFlexGridSizer" expanded="true">
|
<object class="wxFlexGridSizer" expanded="false">
|
||||||
<property name="cols">1</property>
|
<property name="cols">1</property>
|
||||||
<property name="flexible_direction">wxBOTH</property>
|
<property name="flexible_direction">wxBOTH</property>
|
||||||
<property name="growablecols"></property>
|
<property name="growablecols"></property>
|
||||||
@ -216,11 +216,11 @@
|
|||||||
<property name="permission">protected</property>
|
<property name="permission">protected</property>
|
||||||
<property name="rows">0</property>
|
<property name="rows">0</property>
|
||||||
<property name="vgap">4</property>
|
<property name="vgap">4</property>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="flag">wxLEFT</property>
|
<property name="flag">wxLEFT</property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="wxRadioButton" expanded="true">
|
<object class="wxRadioButton" expanded="false">
|
||||||
<property name="BottomDockable">1</property>
|
<property name="BottomDockable">1</property>
|
||||||
<property name="LeftDockable">1</property>
|
<property name="LeftDockable">1</property>
|
||||||
<property name="RightDockable">1</property>
|
<property name="RightDockable">1</property>
|
||||||
@ -281,11 +281,11 @@
|
|||||||
<property name="window_style"></property>
|
<property name="window_style"></property>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="flag">wxLEFT</property>
|
<property name="flag">wxLEFT</property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="wxRadioButton" expanded="true">
|
<object class="wxRadioButton" expanded="false">
|
||||||
<property name="BottomDockable">1</property>
|
<property name="BottomDockable">1</property>
|
||||||
<property name="LeftDockable">1</property>
|
<property name="LeftDockable">1</property>
|
||||||
<property name="RightDockable">1</property>
|
<property name="RightDockable">1</property>
|
||||||
@ -348,21 +348,21 @@
|
|||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="flag"></property>
|
<property name="flag"></property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="spacer" expanded="true">
|
<object class="spacer" expanded="false">
|
||||||
<property name="height">3</property>
|
<property name="height">3</property>
|
||||||
<property name="permission">protected</property>
|
<property name="permission">protected</property>
|
||||||
<property name="width">0</property>
|
<property name="width">0</property>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="flag">wxLEFT</property>
|
<property name="flag">wxLEFT</property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="wxGridBagSizer" expanded="true">
|
<object class="wxGridBagSizer" expanded="false">
|
||||||
<property name="empty_cell_size">-1,2</property>
|
<property name="empty_cell_size">-1,2</property>
|
||||||
<property name="flexible_direction">wxBOTH</property>
|
<property name="flexible_direction">wxBOTH</property>
|
||||||
<property name="growablecols">1</property>
|
<property name="growablecols">1</property>
|
||||||
@ -438,7 +438,7 @@
|
|||||||
<property name="wrap">-1</property>
|
<property name="wrap">-1</property>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="gbsizeritem" expanded="true">
|
<object class="gbsizeritem" expanded="false">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="colspan">1</property>
|
<property name="colspan">1</property>
|
||||||
<property name="column">1</property>
|
<property name="column">1</property>
|
||||||
@ -508,32 +508,32 @@
|
|||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="flag">wxTOP|wxLEFT|wxEXPAND</property>
|
<property name="flag">wxTOP|wxLEFT|wxEXPAND</property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="wxBoxSizer" expanded="true">
|
<object class="wxBoxSizer" expanded="false">
|
||||||
<property name="minimum_size"></property>
|
<property name="minimum_size"></property>
|
||||||
<property name="name">bAntialiasingSizer</property>
|
<property name="name">bAntialiasingSizer</property>
|
||||||
<property name="orient">wxVERTICAL</property>
|
<property name="orient">wxVERTICAL</property>
|
||||||
<property name="permission">none</property>
|
<property name="permission">none</property>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="flag"></property>
|
<property name="flag"></property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="spacer" expanded="true">
|
<object class="spacer" expanded="false">
|
||||||
<property name="height">15</property>
|
<property name="height">15</property>
|
||||||
<property name="permission">protected</property>
|
<property name="permission">protected</property>
|
||||||
<property name="width">0</property>
|
<property name="width">0</property>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">13</property>
|
<property name="border">13</property>
|
||||||
<property name="flag">wxTOP|wxRIGHT|wxLEFT</property>
|
<property name="flag">wxTOP|wxRIGHT|wxLEFT</property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="wxStaticText" expanded="true">
|
<object class="wxStaticText" expanded="false">
|
||||||
<property name="BottomDockable">1</property>
|
<property name="BottomDockable">1</property>
|
||||||
<property name="LeftDockable">1</property>
|
<property name="LeftDockable">1</property>
|
||||||
<property name="RightDockable">1</property>
|
<property name="RightDockable">1</property>
|
||||||
@ -591,11 +591,11 @@
|
|||||||
<property name="wrap">-1</property>
|
<property name="wrap">-1</property>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">2</property>
|
<property name="border">2</property>
|
||||||
<property name="flag">wxEXPAND|wxTOP|wxBOTTOM</property>
|
<property name="flag">wxEXPAND|wxTOP|wxBOTTOM</property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="wxStaticLine" expanded="true">
|
<object class="wxStaticLine" expanded="false">
|
||||||
<property name="BottomDockable">1</property>
|
<property name="BottomDockable">1</property>
|
||||||
<property name="LeftDockable">1</property>
|
<property name="LeftDockable">1</property>
|
||||||
<property name="RightDockable">1</property>
|
<property name="RightDockable">1</property>
|
||||||
@ -650,11 +650,11 @@
|
|||||||
<property name="window_style"></property>
|
<property name="window_style"></property>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="flag">wxTOP|wxLEFT|wxEXPAND</property>
|
<property name="flag">wxTOP|wxLEFT|wxEXPAND</property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="wxBoxSizer" expanded="true">
|
<object class="wxBoxSizer" expanded="false">
|
||||||
<property name="minimum_size"></property>
|
<property name="minimum_size"></property>
|
||||||
<property name="name">bHelperAppsSizer</property>
|
<property name="name">bHelperAppsSizer</property>
|
||||||
<property name="orient">wxVERTICAL</property>
|
<property name="orient">wxVERTICAL</property>
|
||||||
@ -882,20 +882,20 @@
|
|||||||
<property name="width">0</property>
|
<property name="width">0</property>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="flag">wxEXPAND|wxRIGHT|wxTOP</property>
|
<property name="flag">wxEXPAND|wxRIGHT|wxTOP</property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="wxBoxSizer" expanded="true">
|
<object class="wxBoxSizer" expanded="false">
|
||||||
<property name="minimum_size"></property>
|
<property name="minimum_size"></property>
|
||||||
<property name="name">bSizerFileManager</property>
|
<property name="name">bSizerFileManager</property>
|
||||||
<property name="orient">wxHORIZONTAL</property>
|
<property name="orient">wxHORIZONTAL</property>
|
||||||
<property name="permission">protected</property>
|
<property name="permission">protected</property>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT</property>
|
<property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT</property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="wxStaticText" expanded="true">
|
<object class="wxStaticText" expanded="false">
|
||||||
<property name="BottomDockable">1</property>
|
<property name="BottomDockable">1</property>
|
||||||
<property name="LeftDockable">1</property>
|
<property name="LeftDockable">1</property>
|
||||||
<property name="RightDockable">1</property>
|
<property name="RightDockable">1</property>
|
||||||
@ -953,11 +953,11 @@
|
|||||||
<property name="wrap">-1</property>
|
<property name="wrap">-1</property>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
|
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
|
||||||
<property name="proportion">1</property>
|
<property name="proportion">1</property>
|
||||||
<object class="wxTextCtrl" expanded="true">
|
<object class="wxTextCtrl" expanded="false">
|
||||||
<property name="BottomDockable">1</property>
|
<property name="BottomDockable">1</property>
|
||||||
<property name="LeftDockable">1</property>
|
<property name="LeftDockable">1</property>
|
||||||
<property name="RightDockable">1</property>
|
<property name="RightDockable">1</property>
|
||||||
@ -1020,17 +1020,17 @@
|
|||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="flag">wxEXPAND</property>
|
<property name="flag">wxEXPAND</property>
|
||||||
<property name="proportion">1</property>
|
<property name="proportion">1</property>
|
||||||
<object class="spacer" expanded="true">
|
<object class="spacer" expanded="false">
|
||||||
<property name="height">12</property>
|
<property name="height">12</property>
|
||||||
<property name="permission">protected</property>
|
<property name="permission">protected</property>
|
||||||
<property name="width">0</property>
|
<property name="width">0</property>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">2</property>
|
<property name="border">2</property>
|
||||||
<property name="flag">wxBOTTOM|wxEXPAND</property>
|
<property name="flag">wxBOTTOM|wxEXPAND</property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
@ -1107,11 +1107,11 @@
|
|||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="flag">wxBOTTOM|wxRIGHT|wxEXPAND</property>
|
<property name="flag">wxBOTTOM|wxRIGHT|wxEXPAND</property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="wxBoxSizer" expanded="true">
|
<object class="wxBoxSizer" expanded="false">
|
||||||
<property name="minimum_size"></property>
|
<property name="minimum_size"></property>
|
||||||
<property name="name">bSizer7</property>
|
<property name="name">bSizer7</property>
|
||||||
<property name="orient">wxHORIZONTAL</property>
|
<property name="orient">wxHORIZONTAL</property>
|
||||||
@ -1326,21 +1326,21 @@
|
|||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="flag"></property>
|
<property name="flag"></property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="spacer" expanded="true">
|
<object class="spacer" expanded="false">
|
||||||
<property name="height">15</property>
|
<property name="height">15</property>
|
||||||
<property name="permission">protected</property>
|
<property name="permission">protected</property>
|
||||||
<property name="width">0</property>
|
<property name="width">0</property>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">13</property>
|
<property name="border">13</property>
|
||||||
<property name="flag">wxTOP|wxRIGHT|wxLEFT</property>
|
<property name="flag">wxTOP|wxRIGHT|wxLEFT</property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="wxStaticText" expanded="true">
|
<object class="wxStaticText" expanded="false">
|
||||||
<property name="BottomDockable">1</property>
|
<property name="BottomDockable">1</property>
|
||||||
<property name="LeftDockable">1</property>
|
<property name="LeftDockable">1</property>
|
||||||
<property name="RightDockable">1</property>
|
<property name="RightDockable">1</property>
|
||||||
@ -1398,11 +1398,11 @@
|
|||||||
<property name="wrap">-1</property>
|
<property name="wrap">-1</property>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">2</property>
|
<property name="border">2</property>
|
||||||
<property name="flag">wxEXPAND|wxTOP|wxBOTTOM</property>
|
<property name="flag">wxEXPAND|wxTOP|wxBOTTOM</property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="wxStaticLine" expanded="true">
|
<object class="wxStaticLine" expanded="false">
|
||||||
<property name="BottomDockable">1</property>
|
<property name="BottomDockable">1</property>
|
||||||
<property name="LeftDockable">1</property>
|
<property name="LeftDockable">1</property>
|
||||||
<property name="RightDockable">1</property>
|
<property name="RightDockable">1</property>
|
||||||
@ -1457,11 +1457,11 @@
|
|||||||
<property name="window_style"></property>
|
<property name="window_style"></property>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="flag">wxTOP|wxLEFT|wxEXPAND</property>
|
<property name="flag">wxTOP|wxLEFT|wxEXPAND</property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="wxBoxSizer" expanded="true">
|
<object class="wxBoxSizer" expanded="false">
|
||||||
<property name="minimum_size"></property>
|
<property name="minimum_size"></property>
|
||||||
<property name="name">bUserInterfaceSizer</property>
|
<property name="name">bUserInterfaceSizer</property>
|
||||||
<property name="orient">wxVERTICAL</property>
|
<property name="orient">wxVERTICAL</property>
|
||||||
@ -2465,11 +2465,11 @@
|
|||||||
<property name="wrap">-1</property>
|
<property name="wrap">-1</property>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="false">
|
||||||
<property name="border">5</property>
|
<property name="border">5</property>
|
||||||
<property name="flag">wxEXPAND|wxTOP|wxBOTTOM|wxLEFT</property>
|
<property name="flag">wxEXPAND|wxTOP|wxBOTTOM|wxLEFT</property>
|
||||||
<property name="proportion">0</property>
|
<property name="proportion">0</property>
|
||||||
<object class="wxGridBagSizer" expanded="true">
|
<object class="wxGridBagSizer" expanded="false">
|
||||||
<property name="empty_cell_size">-1,-1</property>
|
<property name="empty_cell_size">-1,-1</property>
|
||||||
<property name="flexible_direction">wxVERTICAL</property>
|
<property name="flexible_direction">wxVERTICAL</property>
|
||||||
<property name="growablecols"></property>
|
<property name="growablecols"></property>
|
||||||
@ -2886,6 +2886,137 @@
|
|||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="sizeritem" expanded="true">
|
||||||
|
<property name="border">5</property>
|
||||||
|
<property name="flag"></property>
|
||||||
|
<property name="proportion">0</property>
|
||||||
|
<object class="spacer" expanded="true">
|
||||||
|
<property name="height">0</property>
|
||||||
|
<property name="permission">protected</property>
|
||||||
|
<property name="width">0</property>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem" expanded="true">
|
||||||
|
<property name="border">15</property>
|
||||||
|
<property name="flag">wxLEFT|wxRIGHT|wxTOP</property>
|
||||||
|
<property name="proportion">0</property>
|
||||||
|
<object class="wxStaticText" 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="label">Scaling</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_staticText251</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"></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>
|
||||||
|
<property name="wrap">-1</property>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<object class="sizeritem" expanded="true">
|
||||||
|
<property name="border">5</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_staticline7</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_HORIZONTAL</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>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="true">
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
|
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6a-dirty)
|
||||||
// http://www.wxformbuilder.org/
|
// http://www.wxformbuilder.org/
|
||||||
//
|
//
|
||||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||||
@ -44,6 +44,7 @@ class PANEL_COMMON_SETTINGS_BASE : public RESETTABLE_PANEL
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
wxBoxSizer* bLeftSizer;
|
||||||
wxStaticText* m_staticText20;
|
wxStaticText* m_staticText20;
|
||||||
wxStaticLine* m_staticline3;
|
wxStaticLine* m_staticline3;
|
||||||
wxFlexGridSizer* m_renderingSizer;
|
wxFlexGridSizer* m_renderingSizer;
|
||||||
@ -85,6 +86,8 @@ class PANEL_COMMON_SETTINGS_BASE : public RESETTABLE_PANEL
|
|||||||
wxStaticText* m_highContrastLabel;
|
wxStaticText* m_highContrastLabel;
|
||||||
wxTextCtrl* m_highContrastCtrl;
|
wxTextCtrl* m_highContrastCtrl;
|
||||||
wxStaticText* m_highContrastUnits;
|
wxStaticText* m_highContrastUnits;
|
||||||
|
wxStaticText* m_staticText251;
|
||||||
|
wxStaticLine* m_staticline7;
|
||||||
wxStaticText* m_staticText23;
|
wxStaticText* m_staticText23;
|
||||||
wxStaticLine* m_staticline6;
|
wxStaticLine* m_staticline6;
|
||||||
wxCheckBox* m_warpMouseOnMove;
|
wxCheckBox* m_warpMouseOnMove;
|
||||||
|
@ -167,9 +167,7 @@ void PANEL_EMBEDDED_FILES::resizeGrid()
|
|||||||
bool PANEL_EMBEDDED_FILES::TransferDataToWindow()
|
bool PANEL_EMBEDDED_FILES::TransferDataToWindow()
|
||||||
{
|
{
|
||||||
m_files_grid->ClearGrid();
|
m_files_grid->ClearGrid();
|
||||||
|
m_files_grid->ClearRows();
|
||||||
if( m_files_grid->GetNumberRows() > 0 )
|
|
||||||
m_files_grid->DeleteRows( 0, m_files_grid->GetNumberRows() );
|
|
||||||
|
|
||||||
int ii = 0;
|
int ii = 0;
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <widgets/gal_options_panel.h>
|
#include <dialogs/panel_gal_options.h>
|
||||||
#include <settings/app_settings.h>
|
#include <settings/app_settings.h>
|
||||||
#include <gal/gal_display_options.h>
|
#include <gal/gal_display_options.h>
|
||||||
#include <eda_draw_frame.h>
|
#include <eda_draw_frame.h>
|
||||||
@ -57,8 +57,8 @@ static const UTIL::CFG_MAP<KIGFX::GRID_SNAPPING> gridSnapConfigVals =
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
GAL_OPTIONS_PANEL::GAL_OPTIONS_PANEL( wxWindow* aParent, APP_SETTINGS_BASE* aAppSettings ) :
|
PANEL_GAL_OPTIONS::PANEL_GAL_OPTIONS( wxWindow* aParent, APP_SETTINGS_BASE* aAppSettings ) :
|
||||||
GAL_OPTIONS_PANEL_BASE( aParent ),
|
PANEL_GAL_OPTIONS_BASE( aParent ),
|
||||||
m_cfg( aAppSettings )
|
m_cfg( aAppSettings )
|
||||||
{
|
{
|
||||||
// Grid settings subpanel
|
// Grid settings subpanel
|
||||||
@ -80,7 +80,7 @@ GAL_OPTIONS_PANEL::GAL_OPTIONS_PANEL( wxWindow* aParent, APP_SETTINGS_BASE* aApp
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool GAL_OPTIONS_PANEL::TransferDataToWindow()
|
bool PANEL_GAL_OPTIONS::TransferDataToWindow()
|
||||||
{
|
{
|
||||||
m_gridSnapOptions->SetSelection( m_cfg->m_Window.grid.snap );
|
m_gridSnapOptions->SetSelection( m_cfg->m_Window.grid.snap );
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ bool GAL_OPTIONS_PANEL::TransferDataToWindow()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool GAL_OPTIONS_PANEL::TransferDataFromWindow()
|
bool PANEL_GAL_OPTIONS::TransferDataFromWindow()
|
||||||
{
|
{
|
||||||
m_cfg->m_Window.grid.snap = m_gridSnapOptions->GetSelection();
|
m_cfg->m_Window.grid.snap = m_gridSnapOptions->GetSelection();
|
||||||
|
|
||||||
@ -134,7 +134,7 @@ bool GAL_OPTIONS_PANEL::TransferDataFromWindow()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool GAL_OPTIONS_PANEL::ResetPanel( APP_SETTINGS_BASE* aAppSettings )
|
bool PANEL_GAL_OPTIONS::ResetPanel( APP_SETTINGS_BASE* aAppSettings )
|
||||||
{
|
{
|
||||||
APP_SETTINGS_BASE* saved = m_cfg;
|
APP_SETTINGS_BASE* saved = m_cfg;
|
||||||
|
|
128
common/dialogs/panel_gal_options_base.cpp
Normal file
128
common/dialogs/panel_gal_options_base.cpp
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
|
||||||
|
// http://www.wxformbuilder.org/
|
||||||
|
//
|
||||||
|
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "panel_gal_options_base.h"
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
PANEL_GAL_OPTIONS_BASE::PANEL_GAL_OPTIONS_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
|
||||||
|
{
|
||||||
|
wxBoxSizer* mainSizer;
|
||||||
|
mainSizer = new wxBoxSizer( wxVERTICAL );
|
||||||
|
|
||||||
|
m_staticText1 = new wxStaticText( this, wxID_ANY, _("Grid Display"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
m_staticText1->Wrap( -1 );
|
||||||
|
mainSizer->Add( m_staticText1, 0, wxTOP|wxRIGHT|wxLEFT, 13 );
|
||||||
|
|
||||||
|
m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||||
|
mainSizer->Add( m_staticline1, 0, wxEXPAND|wxTOP|wxBOTTOM, 2 );
|
||||||
|
|
||||||
|
wxBoxSizer* bSizerGridStyle;
|
||||||
|
bSizerGridStyle = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
|
||||||
|
m_gridStyleLabel = new wxStaticText( this, wxID_ANY, _("Style:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
m_gridStyleLabel->Wrap( -1 );
|
||||||
|
bSizerGridStyle->Add( m_gridStyleLabel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
|
||||||
|
|
||||||
|
m_rbDots = new wxRadioButton( this, wxID_ANY, _("Dots"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
|
||||||
|
bSizerGridStyle->Add( m_rbDots, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
|
||||||
|
|
||||||
|
m_rbLines = new wxRadioButton( this, wxID_ANY, _("Lines"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
bSizerGridStyle->Add( m_rbLines, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
|
||||||
|
|
||||||
|
m_rbCrosses = new wxRadioButton( this, wxID_ANY, _("Small crosses"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
bSizerGridStyle->Add( m_rbCrosses, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
mainSizer->Add( bSizerGridStyle, 0, wxEXPAND|wxALL, 5 );
|
||||||
|
|
||||||
|
wxGridBagSizer* gbGridSettings;
|
||||||
|
gbGridSettings = new wxGridBagSizer( 5, 5 );
|
||||||
|
gbGridSettings->SetFlexibleDirection( wxHORIZONTAL );
|
||||||
|
gbGridSettings->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||||
|
|
||||||
|
l_gridLineWidth = new wxStaticText( this, wxID_ANY, _("Grid thickness:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
l_gridLineWidth->Wrap( -1 );
|
||||||
|
gbGridSettings->Add( l_gridLineWidth, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||||
|
|
||||||
|
wxArrayString m_gridLineWidthChoices;
|
||||||
|
m_gridLineWidth = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_gridLineWidthChoices, 0 );
|
||||||
|
m_gridLineWidth->SetSelection( 0 );
|
||||||
|
gbGridSettings->Add( m_gridLineWidth, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
|
||||||
|
|
||||||
|
l_gridLineWidthUnits = new wxStaticText( this, wxID_ANY, _("pixels"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
l_gridLineWidthUnits->Wrap( -1 );
|
||||||
|
gbGridSettings->Add( l_gridLineWidthUnits, wxGBPosition( 0, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
|
||||||
|
|
||||||
|
l_gridMinSpacing = new wxStaticText( this, wxID_ANY, _("Minimum grid spacing:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
l_gridMinSpacing->Wrap( -1 );
|
||||||
|
gbGridSettings->Add( l_gridMinSpacing, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||||
|
|
||||||
|
m_gridMinSpacing = new wxSpinCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 5, 200, 10 );
|
||||||
|
gbGridSettings->Add( m_gridMinSpacing, wxGBPosition( 1, 1 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
|
||||||
|
|
||||||
|
l_gridMinSpacingUnits = new wxStaticText( this, wxID_ANY, _("pixels"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
l_gridMinSpacingUnits->Wrap( -1 );
|
||||||
|
gbGridSettings->Add( l_gridMinSpacingUnits, wxGBPosition( 1, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
|
||||||
|
|
||||||
|
l_gridSnapOptions = new wxStaticText( this, wxID_ANY, _("Snap to grid:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
l_gridSnapOptions->Wrap( -1 );
|
||||||
|
gbGridSettings->Add( l_gridSnapOptions, wxGBPosition( 2, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||||
|
|
||||||
|
wxString m_gridSnapOptionsChoices[] = { _("Always"), _("When grid shown"), _("Never") };
|
||||||
|
int m_gridSnapOptionsNChoices = sizeof( m_gridSnapOptionsChoices ) / sizeof( wxString );
|
||||||
|
m_gridSnapOptions = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_gridSnapOptionsNChoices, m_gridSnapOptionsChoices, 0 );
|
||||||
|
m_gridSnapOptions->SetSelection( 0 );
|
||||||
|
gbGridSettings->Add( m_gridSnapOptions, wxGBPosition( 2, 1 ), wxGBSpan( 1, 2 ), wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
gbGridSettings->AddGrowableCol( 1 );
|
||||||
|
|
||||||
|
mainSizer->Add( gbGridSettings, 0, wxEXPAND|wxALL, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
mainSizer->Add( 0, 5, 0, 0, 5 );
|
||||||
|
|
||||||
|
m_stGridLabel = new wxStaticText( this, wxID_ANY, _("Cursor"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
m_stGridLabel->Wrap( -1 );
|
||||||
|
mainSizer->Add( m_stGridLabel, 0, wxTOP|wxRIGHT|wxLEFT, 13 );
|
||||||
|
|
||||||
|
m_staticline2 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||||
|
mainSizer->Add( m_staticline2, 0, wxEXPAND|wxTOP|wxBOTTOM, 2 );
|
||||||
|
|
||||||
|
wxFlexGridSizer* fgSizer1;
|
||||||
|
fgSizer1 = new wxFlexGridSizer( 0, 1, 3, 0 );
|
||||||
|
fgSizer1->SetFlexibleDirection( wxBOTH );
|
||||||
|
fgSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||||
|
|
||||||
|
m_rbSmallCrosshairs = new wxRadioButton( this, wxID_ANY, _("Small crosshairs"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
|
||||||
|
fgSizer1->Add( m_rbSmallCrosshairs, 0, wxTOP|wxLEFT, 5 );
|
||||||
|
|
||||||
|
m_rbFullWindowCrosshairs = new wxRadioButton( this, wxID_ANY, _("Full window crosshairs"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
fgSizer1->Add( m_rbFullWindowCrosshairs, 0, wxLEFT, 5 );
|
||||||
|
|
||||||
|
m_rb45DegreeCrosshairs = new wxRadioButton( this, wxID_ANY, _("45 degree crosshairs"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
fgSizer1->Add( m_rb45DegreeCrosshairs, 0, wxLEFT, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
fgSizer1->Add( 0, 8, 0, wxEXPAND, 5 );
|
||||||
|
|
||||||
|
m_forceCursorDisplay = new wxCheckBox( this, wxID_ANY, _("Always show crosshairs"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
fgSizer1->Add( m_forceCursorDisplay, 0, wxLEFT, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
mainSizer->Add( fgSizer1, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
this->SetSizer( mainSizer );
|
||||||
|
this->Layout();
|
||||||
|
mainSizer->Fit( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
PANEL_GAL_OPTIONS_BASE::~PANEL_GAL_OPTIONS_BASE()
|
||||||
|
{
|
||||||
|
}
|
@ -13,12 +13,12 @@
|
|||||||
<property name="cpp_use_enum">0</property>
|
<property name="cpp_use_enum">0</property>
|
||||||
<property name="embedded_files_path">res</property>
|
<property name="embedded_files_path">res</property>
|
||||||
<property name="encoding">UTF-8</property>
|
<property name="encoding">UTF-8</property>
|
||||||
<property name="file">gal_options_panel_base</property>
|
<property name="file">panel_gal_options_base</property>
|
||||||
<property name="first_id">1000</property>
|
<property name="first_id">1000</property>
|
||||||
<property name="internationalize">1</property>
|
<property name="internationalize">1</property>
|
||||||
<property name="lua_skip_events">1</property>
|
<property name="lua_skip_events">1</property>
|
||||||
<property name="lua_ui_table">UI</property>
|
<property name="lua_ui_table">UI</property>
|
||||||
<property name="name">GAL_OPTIONS_PANEL_BASE_PRJ</property>
|
<property name="name">PANEL_GAL_OPTIONS_BASE</property>
|
||||||
<property name="path">.</property>
|
<property name="path">.</property>
|
||||||
<property name="php_disconnect_events">0</property>
|
<property name="php_disconnect_events">0</property>
|
||||||
<property name="php_disconnect_mode">source_name</property>
|
<property name="php_disconnect_mode">source_name</property>
|
||||||
@ -46,7 +46,7 @@
|
|||||||
<property name="id">wxID_ANY</property>
|
<property name="id">wxID_ANY</property>
|
||||||
<property name="maximum_size"></property>
|
<property name="maximum_size"></property>
|
||||||
<property name="minimum_size"></property>
|
<property name="minimum_size"></property>
|
||||||
<property name="name">GAL_OPTIONS_PANEL_BASE</property>
|
<property name="name">PANEL_GAL_OPTIONS_BASE</property>
|
||||||
<property name="pos"></property>
|
<property name="pos"></property>
|
||||||
<property name="size">-1,-1</property>
|
<property name="size">-1,-1</property>
|
||||||
<property name="subclass">; ; forward_declare</property>
|
<property name="subclass">; ; forward_declare</property>
|
||||||
@ -1267,7 +1267,7 @@
|
|||||||
<property name="value">0</property>
|
<property name="value">0</property>
|
||||||
<property name="window_extra_style"></property>
|
<property name="window_extra_style"></property>
|
||||||
<property name="window_name"></property>
|
<property name="window_name"></property>
|
||||||
<property name="window_style"></property>
|
<property name="window_style"></property>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="sizeritem" expanded="true">
|
<object class="sizeritem" expanded="true">
|
66
common/dialogs/panel_gal_options_base.h
Normal file
66
common/dialogs/panel_gal_options_base.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
|
||||||
|
// http://www.wxformbuilder.org/
|
||||||
|
//
|
||||||
|
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <wx/artprov.h>
|
||||||
|
#include <wx/xrc/xmlres.h>
|
||||||
|
#include <wx/intl.h>
|
||||||
|
#include <wx/string.h>
|
||||||
|
#include <wx/stattext.h>
|
||||||
|
#include <wx/gdicmn.h>
|
||||||
|
#include <wx/font.h>
|
||||||
|
#include <wx/colour.h>
|
||||||
|
#include <wx/settings.h>
|
||||||
|
#include <wx/statline.h>
|
||||||
|
#include <wx/radiobut.h>
|
||||||
|
#include <wx/sizer.h>
|
||||||
|
#include <wx/choice.h>
|
||||||
|
#include <wx/spinctrl.h>
|
||||||
|
#include <wx/gbsizer.h>
|
||||||
|
#include <wx/checkbox.h>
|
||||||
|
#include <wx/panel.h>
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Class PANEL_GAL_OPTIONS_BASE
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
class PANEL_GAL_OPTIONS_BASE : public wxPanel
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
protected:
|
||||||
|
wxStaticText* m_staticText1;
|
||||||
|
wxStaticLine* m_staticline1;
|
||||||
|
wxStaticText* m_gridStyleLabel;
|
||||||
|
wxRadioButton* m_rbDots;
|
||||||
|
wxRadioButton* m_rbLines;
|
||||||
|
wxRadioButton* m_rbCrosses;
|
||||||
|
wxStaticText* l_gridLineWidth;
|
||||||
|
wxChoice* m_gridLineWidth;
|
||||||
|
wxStaticText* l_gridLineWidthUnits;
|
||||||
|
wxStaticText* l_gridMinSpacing;
|
||||||
|
wxSpinCtrl* m_gridMinSpacing;
|
||||||
|
wxStaticText* l_gridMinSpacingUnits;
|
||||||
|
wxStaticText* l_gridSnapOptions;
|
||||||
|
wxChoice* m_gridSnapOptions;
|
||||||
|
wxStaticText* m_stGridLabel;
|
||||||
|
wxStaticLine* m_staticline2;
|
||||||
|
wxRadioButton* m_rbSmallCrosshairs;
|
||||||
|
wxRadioButton* m_rbFullWindowCrosshairs;
|
||||||
|
wxRadioButton* m_rb45DegreeCrosshairs;
|
||||||
|
wxCheckBox* m_forceCursorDisplay;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
PANEL_GAL_OPTIONS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||||
|
|
||||||
|
~PANEL_GAL_OPTIONS_BASE();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
@ -25,7 +25,6 @@
|
|||||||
#include <gestfich.h>
|
#include <gestfich.h>
|
||||||
#include <hotkeys_basic.h>
|
#include <hotkeys_basic.h>
|
||||||
#include <kiway_player.h>
|
#include <kiway_player.h>
|
||||||
#include <locale_io.h>
|
|
||||||
#include <panel_hotkeys_editor.h>
|
#include <panel_hotkeys_editor.h>
|
||||||
#include <wildcards_and_files_ext.h>
|
#include <wildcards_and_files_ext.h>
|
||||||
#include <tool/tool_manager.h>
|
#include <tool/tool_manager.h>
|
||||||
|
@ -118,6 +118,26 @@ bool PANEL_IMAGE_EDITOR::TransferDataFromWindow()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double PANEL_IMAGE_EDITOR::GetScale() const
|
||||||
|
{
|
||||||
|
return m_scale.GetDoubleValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PANEL_IMAGE_EDITOR::SetScale( double aScale )
|
||||||
|
{
|
||||||
|
m_scale.ChangeDoubleValue( aScale );
|
||||||
|
m_workingImage->SetScale( aScale );
|
||||||
|
m_panelDraw->Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VECTOR2I PANEL_IMAGE_EDITOR::GetImageSize() const
|
||||||
|
{
|
||||||
|
return m_workingImage->GetSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PANEL_IMAGE_EDITOR::OnRedrawPanel( wxPaintEvent& event )
|
void PANEL_IMAGE_EDITOR::OnRedrawPanel( wxPaintEvent& event )
|
||||||
{
|
{
|
||||||
wxPaintDC dc( m_panelDraw );
|
wxPaintDC dc( m_panelDraw );
|
||||||
|
@ -87,6 +87,10 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin
|
|||||||
m_stealsFocus( true ),
|
m_stealsFocus( true ),
|
||||||
m_statusPopup( nullptr )
|
m_statusPopup( nullptr )
|
||||||
{
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
// need to fix broken cairo rendering on Windows with wx 3.3
|
||||||
|
SetDoubleBuffered( false );
|
||||||
|
#endif
|
||||||
m_PaintEventCounter = std::make_unique<PROF_COUNTER>( "Draw panel paint events" );
|
m_PaintEventCounter = std::make_unique<PROF_COUNTER>( "Draw panel paint events" );
|
||||||
|
|
||||||
if( Pgm().GetCommonSettings()->m_Appearance.show_scrollbars )
|
if( Pgm().GetCommonSettings()->m_Appearance.show_scrollbars )
|
||||||
|
@ -333,10 +333,9 @@ bool DS_DRAW_ITEM_POLYPOLYGONS::HitTest( const BOX2I& aRect, bool aContained, in
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
wxString DS_DRAW_ITEM_POLYPOLYGONS::GetItemDescription( UNITS_PROVIDER* aUnitsProvider,
|
wxString DS_DRAW_ITEM_POLYPOLYGONS::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
|
||||||
bool aFull ) const
|
|
||||||
{
|
{
|
||||||
return _( "Imported Shape" );
|
return _( "Imported shape" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -435,10 +434,9 @@ bool DS_DRAW_ITEM_RECT::HitTest( const BOX2I& aRect, bool aContained, int aAccur
|
|||||||
|
|
||||||
wxString DS_DRAW_ITEM_RECT::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
|
wxString DS_DRAW_ITEM_RECT::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
|
||||||
{
|
{
|
||||||
return wxString::Format(
|
return wxString::Format( _( "Rectangle, width %s height %s" ),
|
||||||
_( "Rectangle, width %s height %s" ),
|
aUnitsProvider->MessageTextFromValue( std::abs( GetStart().x - GetEnd().x ) ),
|
||||||
aUnitsProvider->MessageTextFromValue( std::abs( GetStart().x - GetEnd().x ) ),
|
aUnitsProvider->MessageTextFromValue( std::abs( GetStart().y - GetEnd().y ) ) );
|
||||||
aUnitsProvider->MessageTextFromValue( std::abs( GetStart().y - GetEnd().y ) ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -527,7 +525,7 @@ wxString DS_DRAW_ITEM_BITMAP::GetItemDescription( UNITS_PROVIDER* aUnitsProvider
|
|||||||
|
|
||||||
wxString DS_DRAW_ITEM_PAGE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
|
wxString DS_DRAW_ITEM_PAGE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
|
||||||
{
|
{
|
||||||
return _( "Page Limits" );
|
return _( "Page limits" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,6 +60,7 @@ track_segment_length
|
|||||||
version
|
version
|
||||||
via
|
via
|
||||||
via_count
|
via_count
|
||||||
|
via_dangling
|
||||||
via_diameter
|
via_diameter
|
||||||
warning
|
warning
|
||||||
within_diff_pairs
|
within_diff_pairs
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <charconv>
|
#include <fast_float/fast_float.h>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib> // bsearch()
|
#include <cstdlib> // bsearch()
|
||||||
@ -861,43 +861,13 @@ wxArrayString* DSNLEXER::ReadCommentLines()
|
|||||||
|
|
||||||
double DSNLEXER::parseDouble()
|
double DSNLEXER::parseDouble()
|
||||||
{
|
{
|
||||||
// We try here to be locale independent to avoid the need to switch to a "C" locale
|
// Use fast_float::from_chars which is designed to be locale independent and significantly
|
||||||
#if ( defined( __GNUC__ ) && __GNUC__ < 11 ) || ( defined( __clang__ ) && __clang_major__ < 13 )
|
// faster than strtod and std::from_chars
|
||||||
// GCC older than 11 "supports" C++17 without supporting the C++17 std::from_chars for doubles
|
|
||||||
// clang is similar
|
|
||||||
|
|
||||||
// Use wxString::ToCDouble() which is designed to be locale independent
|
|
||||||
wxString tmp = CurStr();
|
|
||||||
double fval;
|
|
||||||
bool success = tmp.ToCDouble( &fval );
|
|
||||||
|
|
||||||
if( !success )
|
|
||||||
{
|
|
||||||
wxString error;
|
|
||||||
error.Printf( _( "Invalid floating point number in\nfile: '%s'\nline: %d\noffset: %d" ),
|
|
||||||
CurSource(), CurLineNumber(), CurOffset() );
|
|
||||||
|
|
||||||
THROW_IO_ERROR( error );
|
|
||||||
}
|
|
||||||
|
|
||||||
return fval;
|
|
||||||
#else
|
|
||||||
// Use std::from_chars which is designed to be locale independent and performance oriented
|
|
||||||
// for data interchange
|
|
||||||
|
|
||||||
const std::string& str = CurStr();
|
const std::string& str = CurStr();
|
||||||
|
|
||||||
// Offset any leading whitespace, this is one thing from_chars does not handle
|
|
||||||
size_t woff = 0;
|
|
||||||
|
|
||||||
while( std::isspace( str[woff] ) && woff < str.length() )
|
|
||||||
{
|
|
||||||
woff++;
|
|
||||||
}
|
|
||||||
|
|
||||||
double dval{};
|
double dval{};
|
||||||
std::from_chars_result res =
|
fast_float::from_chars_result res = fast_float::from_chars( str.data(), str.data() + str.size(), dval,
|
||||||
std::from_chars( str.data() + woff, str.data() + str.size(), dval );
|
fast_float::chars_format::skip_white_space );
|
||||||
|
|
||||||
if( res.ec != std::errc() )
|
if( res.ec != std::errc() )
|
||||||
{
|
{
|
||||||
@ -906,5 +876,4 @@ double DSNLEXER::parseDouble()
|
|||||||
}
|
}
|
||||||
|
|
||||||
return dval;
|
return dval;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
@ -1059,32 +1059,35 @@ std::vector<wxWindow*> EDA_DRAW_FRAME::findDialogs()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void EDA_DRAW_FRAME::FocusOnLocation( const VECTOR2I& aPos )
|
void EDA_DRAW_FRAME::FocusOnLocation( const VECTOR2I& aPos, bool aAllowScroll )
|
||||||
{
|
{
|
||||||
bool centerView = false;
|
bool centerView = false;
|
||||||
BOX2D r = GetCanvas()->GetView()->GetViewport();
|
|
||||||
|
|
||||||
// Center if we're off the current view, or within 10% of its edge
|
|
||||||
r.Inflate( - r.GetWidth() / 10.0 );
|
|
||||||
|
|
||||||
if( !r.Contains( aPos ) )
|
|
||||||
centerView = true;
|
|
||||||
|
|
||||||
std::vector<BOX2D> dialogScreenRects;
|
std::vector<BOX2D> dialogScreenRects;
|
||||||
|
|
||||||
for( wxWindow* dialog : findDialogs() )
|
if( aAllowScroll )
|
||||||
{
|
{
|
||||||
dialogScreenRects.emplace_back( ToVECTOR2D( GetCanvas()->ScreenToClient( dialog->GetScreenPosition() ) ),
|
BOX2D r = GetCanvas()->GetView()->GetViewport();
|
||||||
ToVECTOR2D( dialog->GetSize() ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Center if we're behind an obscuring dialog, or within 10% of its edge
|
// Center if we're off the current view, or within 10% of its edge
|
||||||
for( BOX2D rect : dialogScreenRects )
|
r.Inflate( - r.GetWidth() / 10.0 );
|
||||||
{
|
|
||||||
rect.Inflate( rect.GetWidth() / 10 );
|
|
||||||
|
|
||||||
if( rect.Contains( GetCanvas()->GetView()->ToScreen( aPos ) ) )
|
if( !r.Contains( aPos ) )
|
||||||
centerView = true;
|
centerView = true;
|
||||||
|
|
||||||
|
for( wxWindow* dialog : findDialogs() )
|
||||||
|
{
|
||||||
|
dialogScreenRects.emplace_back( ToVECTOR2D( GetCanvas()->ScreenToClient( dialog->GetScreenPosition() ) ),
|
||||||
|
ToVECTOR2D( dialog->GetSize() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Center if we're behind an obscuring dialog, or within 10% of its edge
|
||||||
|
for( BOX2D rect : dialogScreenRects )
|
||||||
|
{
|
||||||
|
rect.Inflate( rect.GetWidth() / 10 );
|
||||||
|
|
||||||
|
if( rect.Contains( GetCanvas()->GetView()->ToScreen( aPos ) ) )
|
||||||
|
centerView = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( centerView )
|
if( centerView )
|
||||||
|
@ -143,8 +143,7 @@ INSPECT_RESULT EDA_ITEM::Visit( INSPECTOR inspector, void* testData,
|
|||||||
|
|
||||||
wxString EDA_ITEM::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
|
wxString EDA_ITEM::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
|
||||||
{
|
{
|
||||||
wxFAIL_MSG( wxT( "GetItemDescription() was not overridden for schematic item type " ) +
|
wxFAIL_MSG( wxT( "GetItemDescription() was not overridden for schematic item type " ) + GetClass() );
|
||||||
GetClass() );
|
|
||||||
|
|
||||||
return wxString( wxT( "Undefined item description for " ) + GetClass() );
|
return wxString( wxT( "Undefined item description for " ) + GetClass() );
|
||||||
}
|
}
|
||||||
@ -434,6 +433,7 @@ static struct EDA_ITEM_DESC
|
|||||||
.Map( PCB_DIM_RADIAL_T, _HKI( "Dimension" ) )
|
.Map( PCB_DIM_RADIAL_T, _HKI( "Dimension" ) )
|
||||||
.Map( PCB_DIM_LEADER_T, _HKI( "Leader" ) )
|
.Map( PCB_DIM_LEADER_T, _HKI( "Leader" ) )
|
||||||
.Map( PCB_TARGET_T, _HKI( "Target" ) )
|
.Map( PCB_TARGET_T, _HKI( "Target" ) )
|
||||||
|
.Map( PCB_POINT_T, _HKI( "Point" ) )
|
||||||
.Map( PCB_ZONE_T, _HKI( "Zone" ) )
|
.Map( PCB_ZONE_T, _HKI( "Zone" ) )
|
||||||
.Map( PCB_ITEM_LIST_T, _HKI( "ItemList" ) )
|
.Map( PCB_ITEM_LIST_T, _HKI( "ItemList" ) )
|
||||||
.Map( PCB_NETINFO_T, _HKI( "NetInfo" ) )
|
.Map( PCB_NETINFO_T, _HKI( "NetInfo" ) )
|
||||||
|
@ -35,8 +35,11 @@
|
|||||||
#include <geometry/shape_simple.h>
|
#include <geometry/shape_simple.h>
|
||||||
#include <geometry/shape_segment.h>
|
#include <geometry/shape_segment.h>
|
||||||
#include <geometry/shape_rect.h>
|
#include <geometry/shape_rect.h>
|
||||||
|
#include <geometry/roundrect.h>
|
||||||
#include <geometry/geometry_utils.h>
|
#include <geometry/geometry_utils.h>
|
||||||
#include <macros.h>
|
#include <macros.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <properties/property_validators.h>
|
||||||
#include <math/util.h> // for KiROUND
|
#include <math/util.h> // for KiROUND
|
||||||
#include <eda_item.h>
|
#include <eda_item.h>
|
||||||
#include <plotters/plotter.h>
|
#include <plotters/plotter.h>
|
||||||
@ -54,6 +57,7 @@ EDA_SHAPE::EDA_SHAPE( SHAPE_T aType, int aLineWidth, FILL_T aFill ) :
|
|||||||
m_hatchingDirty( true ),
|
m_hatchingDirty( true ),
|
||||||
m_rectangleHeight( 0 ),
|
m_rectangleHeight( 0 ),
|
||||||
m_rectangleWidth( 0 ),
|
m_rectangleWidth( 0 ),
|
||||||
|
m_cornerRadius( 0 ),
|
||||||
m_segmentLength( 0 ),
|
m_segmentLength( 0 ),
|
||||||
m_editState( 0 ),
|
m_editState( 0 ),
|
||||||
m_proxyItem( false )
|
m_proxyItem( false )
|
||||||
@ -73,6 +77,7 @@ EDA_SHAPE::EDA_SHAPE( const SHAPE& aShape ) :
|
|||||||
m_hatchingDirty( true ),
|
m_hatchingDirty( true ),
|
||||||
m_rectangleHeight( 0 ),
|
m_rectangleHeight( 0 ),
|
||||||
m_rectangleWidth( 0 ),
|
m_rectangleWidth( 0 ),
|
||||||
|
m_cornerRadius( 0 ),
|
||||||
m_segmentLength( 0 ),
|
m_segmentLength( 0 ),
|
||||||
m_editState( 0 ),
|
m_editState( 0 ),
|
||||||
m_proxyItem( false )
|
m_proxyItem( false )
|
||||||
@ -188,6 +193,7 @@ void EDA_SHAPE::Serialize( google::protobuf::Any &aContainer ) const
|
|||||||
types::GraphicRectangleAttributes* rectangle = shape.mutable_rectangle();
|
types::GraphicRectangleAttributes* rectangle = shape.mutable_rectangle();
|
||||||
PackVector2( *rectangle->mutable_top_left(), GetStart() );
|
PackVector2( *rectangle->mutable_top_left(), GetStart() );
|
||||||
PackVector2( *rectangle->mutable_bottom_right(), GetEnd() );
|
PackVector2( *rectangle->mutable_bottom_right(), GetEnd() );
|
||||||
|
rectangle->mutable_corner_radius()->set_value_nm( GetCornerRadius() );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,6 +286,7 @@ bool EDA_SHAPE::Deserialize( const google::protobuf::Any &aContainer )
|
|||||||
SetShape( SHAPE_T::RECTANGLE );
|
SetShape( SHAPE_T::RECTANGLE );
|
||||||
SetStart( UnpackVector2( shape.rectangle().top_left() ) );
|
SetStart( UnpackVector2( shape.rectangle().top_left() ) );
|
||||||
SetEnd( UnpackVector2( shape.rectangle().bottom_right() ) );
|
SetEnd( UnpackVector2( shape.rectangle().bottom_right() ) );
|
||||||
|
SetCornerRadius( shape.rectangle().corner_radius().value_nm() );
|
||||||
}
|
}
|
||||||
else if( shape.has_arc() )
|
else if( shape.has_arc() )
|
||||||
{
|
{
|
||||||
@ -433,6 +440,29 @@ int EDA_SHAPE::GetRectangleWidth() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int EDA_SHAPE::GetCornerRadius() const
|
||||||
|
{
|
||||||
|
return m_cornerRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDA_SHAPE::SetCornerRadius( int aRadius )
|
||||||
|
{
|
||||||
|
if( m_shape == SHAPE_T::RECTANGLE )
|
||||||
|
{
|
||||||
|
int width = std::abs( GetRectangleWidth() );
|
||||||
|
int height = std::abs( GetRectangleHeight() );
|
||||||
|
int maxRadius = std::min( width, height ) / 2;
|
||||||
|
|
||||||
|
m_cornerRadius = std::clamp( aRadius, 0, maxRadius );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_cornerRadius = aRadius;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void EDA_SHAPE::SetLength( const double& aLength )
|
void EDA_SHAPE::SetLength( const double& aLength )
|
||||||
{
|
{
|
||||||
switch( m_shape )
|
switch( m_shape )
|
||||||
@ -604,11 +634,11 @@ void EDA_SHAPE::UpdateHatching() const
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case SHAPE_T::RECTANGLE:
|
case SHAPE_T::RECTANGLE:
|
||||||
shapeBuffer.NewOutline();
|
{
|
||||||
|
ROUNDRECT rr( SHAPE_RECT( getPosition(), GetRectangleWidth(), GetRectangleHeight() ),
|
||||||
for( const VECTOR2I& pt : GetRectCorners() )
|
GetCornerRadius() );
|
||||||
shapeBuffer.Append( pt );
|
rr.TransformToPolygon( shapeBuffer );
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SHAPE_T::CIRCLE:
|
case SHAPE_T::CIRCLE:
|
||||||
@ -644,8 +674,8 @@ void EDA_SHAPE::UpdateHatching() const
|
|||||||
// Generate a grid of holes for a cross-hatch. This is about 3X the speed of the above
|
// Generate a grid of holes for a cross-hatch. This is about 3X the speed of the above
|
||||||
// algorithm, even when modified for the 45-degree fracture problem.
|
// algorithm, even when modified for the 45-degree fracture problem.
|
||||||
|
|
||||||
int gridsize = GetHatchLineSpacing();
|
int gridsize = GetHatchLineSpacing();
|
||||||
int hole_size = gridsize - GetHatchLineWidth();
|
int hole_size = gridsize - GetHatchLineWidth();
|
||||||
|
|
||||||
m_hatching = shapeBuffer.CloneDropTriangulation();
|
m_hatching = shapeBuffer.CloneDropTriangulation();
|
||||||
m_hatching.Rotate( -ANGLE_45 );
|
m_hatching.Rotate( -ANGLE_45 );
|
||||||
@ -748,16 +778,11 @@ void EDA_SHAPE::scale( double aScale )
|
|||||||
|
|
||||||
case SHAPE_T::SEGMENT:
|
case SHAPE_T::SEGMENT:
|
||||||
case SHAPE_T::RECTANGLE:
|
case SHAPE_T::RECTANGLE:
|
||||||
|
case SHAPE_T::CIRCLE:
|
||||||
scalePt( m_start );
|
scalePt( m_start );
|
||||||
scalePt( m_end );
|
scalePt( m_end );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SHAPE_T::CIRCLE: // ring or circle
|
|
||||||
scalePt( m_start );
|
|
||||||
m_end.x = m_start.x + KiROUND( GetRadius() * aScale );
|
|
||||||
m_end.y = m_start.y;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SHAPE_T::POLY: // polygon
|
case SHAPE_T::POLY: // polygon
|
||||||
{
|
{
|
||||||
std::vector<VECTOR2I> pts;
|
std::vector<VECTOR2I> pts;
|
||||||
@ -974,10 +999,9 @@ void EDA_SHAPE::SetCenter( const VECTOR2I& aCenter )
|
|||||||
|
|
||||||
VECTOR2I EDA_SHAPE::GetArcMid() const
|
VECTOR2I EDA_SHAPE::GetArcMid() const
|
||||||
{
|
{
|
||||||
// If none of the input data have changed since we loaded the arc,
|
// If none of the input data have changed since we loaded the arc, keep the original mid point data
|
||||||
// keep the original mid point data to minimize churn
|
// to minimize churn
|
||||||
if( m_arcMidData.start == m_start && m_arcMidData.end == m_end
|
if( m_arcMidData.start == m_start && m_arcMidData.end == m_end && m_arcMidData.center == m_arcCenter )
|
||||||
&& m_arcMidData.center == m_arcCenter )
|
|
||||||
return m_arcMidData.mid;
|
return m_arcMidData.mid;
|
||||||
|
|
||||||
VECTOR2I mid = m_start;
|
VECTOR2I mid = m_start;
|
||||||
@ -1179,21 +1203,17 @@ void EDA_SHAPE::ShapeGetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PA
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SHAPE_T::RECTANGLE:
|
case SHAPE_T::RECTANGLE:
|
||||||
aList.emplace_back( _( "Width" ),
|
aList.emplace_back( _( "Width" ), aFrame->MessageTextFromValue( std::abs( GetEnd().x - GetStart().x ) ) );
|
||||||
aFrame->MessageTextFromValue( std::abs( GetEnd().x - GetStart().x ) ) );
|
aList.emplace_back( _( "Height" ), aFrame->MessageTextFromValue( std::abs( GetEnd().y - GetStart().y ) ) );
|
||||||
|
|
||||||
aList.emplace_back( _( "Height" ),
|
|
||||||
aFrame->MessageTextFromValue( std::abs( GetEnd().y - GetStart().y ) ) );
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SHAPE_T::SEGMENT:
|
case SHAPE_T::SEGMENT:
|
||||||
{
|
{
|
||||||
aList.emplace_back( _( "Length" ),
|
aList.emplace_back( _( "Length" ), aFrame->MessageTextFromValue( GetStart().Distance( GetEnd() ) ));
|
||||||
aFrame->MessageTextFromValue( GetStart().Distance( GetEnd() ) ));
|
|
||||||
|
|
||||||
// angle counter-clockwise from 3'o-clock
|
// angle counter-clockwise from 3'o-clock
|
||||||
EDA_ANGLE angle( atan2( (double)( GetStart().y - GetEnd().y ),
|
EDA_ANGLE angle( atan2( (double)( GetStart().y - GetEnd().y ), (double)( GetEnd().x - GetStart().x ) ),
|
||||||
(double)( GetEnd().x - GetStart().x ) ), RADIANS_T );
|
RADIANS_T );
|
||||||
aList.emplace_back( _( "Angle" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( angle ) );
|
aList.emplace_back( _( "Angle" ), EDA_UNIT_UTILS::UI::MessageTextFromValue( angle ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1246,6 +1266,7 @@ const BOX2I EDA_SHAPE::getBoundingBox() const
|
|||||||
// using the bounding box of the curve (not control!) points.
|
// using the bounding box of the curve (not control!) points.
|
||||||
for( const VECTOR2I& pt : m_bezierPoints )
|
for( const VECTOR2I& pt : m_bezierPoints )
|
||||||
bbox.Merge( pt );
|
bbox.Merge( pt );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -1293,9 +1314,9 @@ bool EDA_SHAPE::hitTest( const VECTOR2I& aPosition, int aAccuracy ) const
|
|||||||
if( aPosition.Distance( m_end ) <= maxdist )
|
if( aPosition.Distance( m_end ) <= maxdist )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
double radius = GetRadius();
|
double radius = GetRadius();
|
||||||
VECTOR2D relPos( VECTOR2D( aPosition ) - getCenter() );
|
VECTOR2D relPos( VECTOR2D( aPosition ) - getCenter() );
|
||||||
double dist = relPos.EuclideanNorm();
|
double dist = relPos.EuclideanNorm();
|
||||||
|
|
||||||
if( IsFilledForHitTesting() )
|
if( IsFilledForHitTesting() )
|
||||||
{
|
{
|
||||||
@ -1361,6 +1382,15 @@ bool EDA_SHAPE::hitTest( const VECTOR2I& aPosition, int aAccuracy ) const
|
|||||||
|
|
||||||
return poly.Collide( aPosition, maxdist );
|
return poly.Collide( aPosition, maxdist );
|
||||||
}
|
}
|
||||||
|
else if( m_cornerRadius > 0 )
|
||||||
|
{
|
||||||
|
ROUNDRECT rr( SHAPE_RECT( GetStart(), GetRectangleWidth(), GetRectangleHeight() ), m_cornerRadius );
|
||||||
|
SHAPE_POLY_SET poly;
|
||||||
|
rr.TransformToPolygon( poly );
|
||||||
|
|
||||||
|
if( poly.CollideEdge( aPosition, nullptr, maxdist ) )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::vector<VECTOR2I> pts = GetRectCorners();
|
std::vector<VECTOR2I> pts = GetRectCorners();
|
||||||
@ -1372,13 +1402,13 @@ bool EDA_SHAPE::hitTest( const VECTOR2I& aPosition, int aAccuracy ) const
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( IsHatchedFill() && GetHatching().Collide( aPosition, maxdist ) )
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( IsHatchedFill() && GetHatching().Collide( aPosition, maxdist ) )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
case SHAPE_T::POLY:
|
case SHAPE_T::POLY:
|
||||||
if( IsFilledForHitTesting() )
|
if( IsFilledForHitTesting() )
|
||||||
{
|
{
|
||||||
@ -1420,6 +1450,40 @@ bool EDA_SHAPE::hitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) co
|
|||||||
|
|
||||||
BOX2I bbox = getBoundingBox();
|
BOX2I bbox = getBoundingBox();
|
||||||
|
|
||||||
|
auto checkOutline =
|
||||||
|
[&]( const SHAPE_LINE_CHAIN& outline )
|
||||||
|
{
|
||||||
|
int count = (int) outline.GetPointCount();
|
||||||
|
|
||||||
|
for( int ii = 0; ii < count; ii++ )
|
||||||
|
{
|
||||||
|
VECTOR2I vertex = outline.GetPoint( ii );
|
||||||
|
|
||||||
|
// Test if the point is within aRect
|
||||||
|
if( arect.Contains( vertex ) )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if( ii + 1 < count )
|
||||||
|
{
|
||||||
|
VECTOR2I vertexNext = outline.GetPoint( ii + 1 );
|
||||||
|
|
||||||
|
// Test if this edge intersects aRect
|
||||||
|
if( arect.Intersects( vertex, vertexNext ) )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if( outline.IsClosed() )
|
||||||
|
{
|
||||||
|
VECTOR2I vertexNext = outline.GetPoint( 0 );
|
||||||
|
|
||||||
|
// Test if this edge intersects aRect
|
||||||
|
if( arect.Intersects( vertex, vertexNext ) )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
switch( m_shape )
|
switch( m_shape )
|
||||||
{
|
{
|
||||||
case SHAPE_T::CIRCLE:
|
case SHAPE_T::CIRCLE:
|
||||||
@ -1466,6 +1530,17 @@ bool EDA_SHAPE::hitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) co
|
|||||||
{
|
{
|
||||||
return arect.Contains( bbox );
|
return arect.Contains( bbox );
|
||||||
}
|
}
|
||||||
|
else if( m_cornerRadius > 0 )
|
||||||
|
{
|
||||||
|
ROUNDRECT rr( SHAPE_RECT( GetStart(), GetRectangleWidth(), GetRectangleHeight() ), m_cornerRadius );
|
||||||
|
SHAPE_POLY_SET poly;
|
||||||
|
rr.TransformToPolygon( poly );
|
||||||
|
|
||||||
|
// Account for the width of the line
|
||||||
|
arect.Inflate( GetWidth() / 2 );
|
||||||
|
|
||||||
|
return checkOutline( poly.Outline( 0 ) );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::vector<VECTOR2I> pts = GetRectCorners();
|
std::vector<VECTOR2I> pts = GetRectCorners();
|
||||||
@ -1507,34 +1582,8 @@ bool EDA_SHAPE::hitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) co
|
|||||||
|
|
||||||
for( int ii = 0; ii < m_poly.OutlineCount(); ++ii )
|
for( int ii = 0; ii < m_poly.OutlineCount(); ++ii )
|
||||||
{
|
{
|
||||||
const SHAPE_LINE_CHAIN& poly = m_poly.Outline( ii );
|
if( checkOutline( m_poly.Outline( ii ) ) )
|
||||||
int count = poly.GetPointCount();
|
return true;
|
||||||
|
|
||||||
for( int jj = 0; jj < count; jj++ )
|
|
||||||
{
|
|
||||||
VECTOR2I vertex = poly.GetPoint( jj );
|
|
||||||
|
|
||||||
// Test if the point is within aRect
|
|
||||||
if( arect.Contains( vertex ) )
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if( jj + 1 < count )
|
|
||||||
{
|
|
||||||
VECTOR2I vertexNext = poly.GetPoint( jj + 1 );
|
|
||||||
|
|
||||||
// Test if this edge intersects aRect
|
|
||||||
if( arect.Intersects( vertex, vertexNext ) )
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if( poly.IsClosed() )
|
|
||||||
{
|
|
||||||
VECTOR2I vertexNext = poly.GetPoint( 0 );
|
|
||||||
|
|
||||||
// Test if this edge intersects aRect
|
|
||||||
if( arect.Intersects( vertex, vertexNext ) )
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -1805,17 +1854,42 @@ std::vector<SHAPE*> EDA_SHAPE::makeEffectiveShapes( bool aEdgeOnly, bool aLineCh
|
|||||||
|
|
||||||
case SHAPE_T::RECTANGLE:
|
case SHAPE_T::RECTANGLE:
|
||||||
{
|
{
|
||||||
std::vector<VECTOR2I> pts = GetRectCorners();
|
if( m_cornerRadius > 0 )
|
||||||
|
|
||||||
if( solidFill )
|
|
||||||
effectiveShapes.emplace_back( new SHAPE_SIMPLE( pts ) );
|
|
||||||
|
|
||||||
if( width > 0 || !solidFill )
|
|
||||||
{
|
{
|
||||||
effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[0], pts[1], width ) );
|
ROUNDRECT rr( SHAPE_RECT( GetStart(), GetRectangleWidth(), GetRectangleHeight() ), m_cornerRadius );
|
||||||
effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[1], pts[2], width ) );
|
SHAPE_POLY_SET poly;
|
||||||
effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[2], pts[3], width ) );
|
rr.TransformToPolygon( poly );
|
||||||
effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[3], pts[0], width ) );
|
SHAPE_LINE_CHAIN outline = poly.Outline( 0 );
|
||||||
|
|
||||||
|
if( solidFill )
|
||||||
|
effectiveShapes.emplace_back( new SHAPE_SIMPLE( outline ) );
|
||||||
|
|
||||||
|
if( width > 0 || !solidFill )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < outline.PointCount() - 1; ++i )
|
||||||
|
{
|
||||||
|
effectiveShapes.emplace_back( new SHAPE_SEGMENT( outline.CPoint( i ), outline.CPoint( i + 1 ),
|
||||||
|
width ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
effectiveShapes.emplace_back( new SHAPE_SEGMENT( outline.CPoint( outline.PointCount() - 1 ),
|
||||||
|
outline.CPoint( 0 ), width ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::vector<VECTOR2I> pts = GetRectCorners();
|
||||||
|
|
||||||
|
if( solidFill )
|
||||||
|
effectiveShapes.emplace_back( new SHAPE_SIMPLE( pts ) );
|
||||||
|
|
||||||
|
if( width > 0 || !solidFill )
|
||||||
|
{
|
||||||
|
effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[0], pts[1], width ) );
|
||||||
|
effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[1], pts[2], width ) );
|
||||||
|
effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[2], pts[3], width ) );
|
||||||
|
effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[3], pts[0], width ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1976,7 +2050,7 @@ bool EDA_SHAPE::continueEdit( const VECTOR2I& aPosition )
|
|||||||
SHAPE_LINE_CHAIN& poly = m_poly.Outline( 0 );
|
SHAPE_LINE_CHAIN& poly = m_poly.Outline( 0 );
|
||||||
|
|
||||||
// do not add zero-length segments
|
// do not add zero-length segments
|
||||||
if( poly.CPoint( poly.GetPointCount() - 2 ) != poly.CLastPoint() )
|
if( poly.CPoint( (int) poly.GetPointCount() - 2 ) != poly.CLastPoint() )
|
||||||
poly.Append( aPosition, true );
|
poly.Append( aPosition, true );
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -2010,12 +2084,19 @@ void EDA_SHAPE::calcEdit( const VECTOR2I& aPosition )
|
|||||||
SetBezierC1( aPosition );
|
SetBezierC1( aPosition );
|
||||||
SetBezierC2( aPosition );
|
SetBezierC2( aPosition );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
SetBezierC2( aPosition );
|
SetBezierC2( aPosition );
|
||||||
SetEnd( aPosition );
|
SetEnd( aPosition );
|
||||||
break;
|
break;
|
||||||
case 2: SetBezierC1( aPosition ); break;
|
|
||||||
case 3: SetBezierC2( aPosition ); break;
|
case 2:
|
||||||
|
SetBezierC1( aPosition );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
SetBezierC2( aPosition );
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
RebuildBezierToSegmentsPointsList( getMaxError() );
|
RebuildBezierToSegmentsPointsList( getMaxError() );
|
||||||
@ -2066,16 +2147,16 @@ void EDA_SHAPE::calcEdit( const VECTOR2I& aPosition )
|
|||||||
|
|
||||||
if( ratio != 0 )
|
if( ratio != 0 )
|
||||||
radius = std::max( sqrt( sq( radius ) * ratio ), sqrt( chordAfter ) / 2 );
|
radius = std::max( sqrt( sq( radius ) * ratio ), sqrt( chordAfter ) / 2 );
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
{
|
{
|
||||||
double radialA = m_start.Distance( aPosition );
|
double radialA = m_start.Distance( aPosition );
|
||||||
double radialB = m_end.Distance( aPosition );
|
double radialB = m_end.Distance( aPosition );
|
||||||
radius = ( radialA + radialB ) / 2.0;
|
radius = ( radialA + radialB ) / 2.0;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
SetArcGeometry( GetStart(), aPosition, GetEnd() );
|
SetArcGeometry( GetStart(), aPosition, GetEnd() );
|
||||||
@ -2129,8 +2210,9 @@ void EDA_SHAPE::calcEdit( const VECTOR2I& aPosition )
|
|||||||
m_arcCenter = c1.Distance( aPosition ) < c2.Distance( aPosition ) ? c1 : c2;
|
m_arcCenter = c1.Distance( aPosition ) < c2.Distance( aPosition ) ? c1 : c2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case SHAPE_T::POLY:
|
case SHAPE_T::POLY:
|
||||||
m_poly.Outline( 0 ).SetPoint( m_poly.Outline( 0 ).GetPointCount() - 1, aPosition );
|
m_poly.Outline( 0 ).SetPoint( m_poly.Outline( 0 ).GetPointCount() - 1, aPosition );
|
||||||
@ -2170,8 +2252,9 @@ void EDA_SHAPE::endEdit( bool aClosed )
|
|||||||
poly.Remove( poly.GetPointCount() - 1 );
|
poly.Remove( poly.GetPointCount() - 1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
UNIMPLEMENTED_FOR( SHAPE_T_asString() );
|
UNIMPLEMENTED_FOR( SHAPE_T_asString() );
|
||||||
@ -2194,6 +2277,7 @@ void EDA_SHAPE::SwapShape( EDA_SHAPE* aImage )
|
|||||||
SWAPITEM( m_bezierC2 );
|
SWAPITEM( m_bezierC2 );
|
||||||
SWAPITEM( m_bezierPoints );
|
SWAPITEM( m_bezierPoints );
|
||||||
SWAPITEM( m_poly );
|
SWAPITEM( m_poly );
|
||||||
|
SWAPITEM( m_cornerRadius );
|
||||||
SWAPITEM( m_fill );
|
SWAPITEM( m_fill );
|
||||||
SWAPITEM( m_fillColor );
|
SWAPITEM( m_fillColor );
|
||||||
SWAPITEM( m_editState );
|
SWAPITEM( m_editState );
|
||||||
@ -2217,7 +2301,11 @@ int EDA_SHAPE::Compare( const EDA_SHAPE* aOther ) const
|
|||||||
|
|
||||||
TEST( (int) m_shape, (int) aOther->m_shape );
|
TEST( (int) m_shape, (int) aOther->m_shape );
|
||||||
|
|
||||||
if( m_shape == SHAPE_T::ARC )
|
if( m_shape == SHAPE_T::RECTANGLE )
|
||||||
|
{
|
||||||
|
TEST( m_cornerRadius, aOther->m_cornerRadius );
|
||||||
|
}
|
||||||
|
else if( m_shape == SHAPE_T::ARC )
|
||||||
{
|
{
|
||||||
TEST_PT( GetArcMid(), aOther->GetArcMid() );
|
TEST_PT( GetArcMid(), aOther->GetArcMid() );
|
||||||
}
|
}
|
||||||
@ -2246,8 +2334,7 @@ int EDA_SHAPE::Compare( const EDA_SHAPE* aOther ) const
|
|||||||
|
|
||||||
|
|
||||||
void EDA_SHAPE::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, int aClearance, int aError,
|
void EDA_SHAPE::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, int aClearance, int aError,
|
||||||
ERROR_LOC aErrorLoc, bool ignoreLineWidth,
|
ERROR_LOC aErrorLoc, bool ignoreLineWidth, bool includeFill ) const
|
||||||
bool includeFill ) const
|
|
||||||
{
|
{
|
||||||
bool solidFill = IsSolidFill() || ( IsHatchedFill() && !includeFill ) || IsProxyItem();
|
bool solidFill = IsSolidFill() || ( IsHatchedFill() && !includeFill ) || IsProxyItem();
|
||||||
int width = ignoreLineWidth ? 0 : GetWidth();
|
int width = ignoreLineWidth ? 0 : GetWidth();
|
||||||
@ -2270,23 +2357,53 @@ void EDA_SHAPE::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, int aClearance
|
|||||||
|
|
||||||
case SHAPE_T::RECTANGLE:
|
case SHAPE_T::RECTANGLE:
|
||||||
{
|
{
|
||||||
std::vector<VECTOR2I> pts = GetRectCorners();
|
if( GetCornerRadius() > 0 )
|
||||||
|
|
||||||
if( solidFill )
|
|
||||||
{
|
{
|
||||||
aBuffer.NewOutline();
|
// Use specialized function for rounded rectangles
|
||||||
|
VECTOR2I size( GetRectangleWidth(), GetRectangleHeight() );
|
||||||
|
VECTOR2I position = GetStart() + size / 2; // Center position
|
||||||
|
|
||||||
for( const VECTOR2I& pt : pts )
|
if( solidFill )
|
||||||
aBuffer.Append( pt );
|
{
|
||||||
|
TransformRoundChamferedRectToPolygon( aBuffer, position, size, ANGLE_0, GetCornerRadius(),
|
||||||
|
0.0, 0, width / 2, aError, aErrorLoc );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Export outline as a set of thick segments:
|
||||||
|
SHAPE_POLY_SET poly;
|
||||||
|
TransformRoundChamferedRectToPolygon( poly, position, size, ANGLE_0, GetCornerRadius(),
|
||||||
|
0.0, 0, 0, aError, aErrorLoc );
|
||||||
|
SHAPE_LINE_CHAIN& outline = poly.Outline( 0 );
|
||||||
|
outline.SetClosed( true );
|
||||||
|
|
||||||
|
for( int ii = 0; ii < outline.PointCount(); ii++ )
|
||||||
|
{
|
||||||
|
TransformOvalToPolygon( aBuffer, outline.CPoint( ii ), outline.CPoint( ii+1 ), width,
|
||||||
|
aError, aErrorLoc );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if( width > 0 || !solidFill )
|
|
||||||
{
|
{
|
||||||
// Add in segments
|
std::vector<VECTOR2I> pts = GetRectCorners();
|
||||||
TransformOvalToPolygon( aBuffer, pts[0], pts[1], width, aError, aErrorLoc );
|
|
||||||
TransformOvalToPolygon( aBuffer, pts[1], pts[2], width, aError, aErrorLoc );
|
if( solidFill )
|
||||||
TransformOvalToPolygon( aBuffer, pts[2], pts[3], width, aError, aErrorLoc );
|
{
|
||||||
TransformOvalToPolygon( aBuffer, pts[3], pts[0], width, aError, aErrorLoc );
|
aBuffer.NewOutline();
|
||||||
|
|
||||||
|
for( const VECTOR2I& pt : pts )
|
||||||
|
aBuffer.Append( pt );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( width > 0 || !solidFill )
|
||||||
|
{
|
||||||
|
// Add in segments
|
||||||
|
TransformOvalToPolygon( aBuffer, pts[0], pts[1], width, aError, aErrorLoc );
|
||||||
|
TransformOvalToPolygon( aBuffer, pts[1], pts[2], width, aError, aErrorLoc );
|
||||||
|
TransformOvalToPolygon( aBuffer, pts[2], pts[3], width, aError, aErrorLoc );
|
||||||
|
TransformOvalToPolygon( aBuffer, pts[3], pts[0], width, aError, aErrorLoc );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -2648,6 +2765,37 @@ static struct EDA_SHAPE_DESC
|
|||||||
shapeProps )
|
shapeProps )
|
||||||
.SetAvailableFunc( isRectangle );
|
.SetAvailableFunc( isRectangle );
|
||||||
|
|
||||||
|
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "Corner Radius" ),
|
||||||
|
&EDA_SHAPE::SetCornerRadius, &EDA_SHAPE::GetCornerRadius,
|
||||||
|
PROPERTY_DISPLAY::PT_SIZE, ORIGIN_TRANSFORMS::NOT_A_COORD ),
|
||||||
|
shapeProps )
|
||||||
|
.SetAvailableFunc( isRectangle )
|
||||||
|
.SetValidator( []( const wxAny&& aValue, EDA_ITEM* aItem ) -> VALIDATOR_RESULT
|
||||||
|
{
|
||||||
|
wxASSERT_MSG( aValue.CheckType<int>(),
|
||||||
|
"Expecting int-containing value" );
|
||||||
|
|
||||||
|
int radius = aValue.As<int>();
|
||||||
|
|
||||||
|
EDA_SHAPE* prop_shape = dynamic_cast<EDA_SHAPE*>( aItem );
|
||||||
|
|
||||||
|
if( !prop_shape )
|
||||||
|
{
|
||||||
|
wxLogDebug( wxT( "Corner Radius Validator: Not an EDA_SHAPE" ) );
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
int maxRadius = std::min( prop_shape->GetRectangleWidth(),
|
||||||
|
prop_shape->GetRectangleHeight() ) / 2;
|
||||||
|
|
||||||
|
if( radius > maxRadius )
|
||||||
|
return std::make_unique<VALIDATION_ERROR_TOO_LARGE<int>>( radius, maxRadius );
|
||||||
|
else if( radius < 0 )
|
||||||
|
return std::make_unique<VALIDATION_ERROR_TOO_SMALL<int>>( radius, 0 );
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
} );
|
||||||
|
|
||||||
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "Line Width" ),
|
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "Line Width" ),
|
||||||
&EDA_SHAPE::SetWidth, &EDA_SHAPE::GetWidth, PROPERTY_DISPLAY::PT_SIZE ),
|
&EDA_SHAPE::SetWidth, &EDA_SHAPE::GetWidth, PROPERTY_DISPLAY::PT_SIZE ),
|
||||||
shapeProps );
|
shapeProps );
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include <font/glyph.h>
|
#include <font/glyph.h>
|
||||||
#include <gr_text.h>
|
#include <gr_text.h>
|
||||||
#include <string_utils.h> // for UnescapeString
|
#include <string_utils.h> // for UnescapeString
|
||||||
|
#include <text_eval/text_eval_wrapper.h>
|
||||||
#include <math/util.h> // for KiROUND
|
#include <math/util.h> // for KiROUND
|
||||||
#include <math/vector2d.h>
|
#include <math/vector2d.h>
|
||||||
#include <core/kicad_algo.h>
|
#include <core/kicad_algo.h>
|
||||||
@ -638,6 +639,14 @@ void EDA_TEXT::cacheShownText()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString EDA_TEXT::EvaluateText( const wxString& aText ) const
|
||||||
|
{
|
||||||
|
static EXPRESSION_EVALUATOR evaluator;
|
||||||
|
|
||||||
|
return evaluator.Evaluate( aText );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
KIFONT::FONT* EDA_TEXT::GetDrawFont( const RENDER_SETTINGS* aSettings ) const
|
KIFONT::FONT* EDA_TEXT::GetDrawFont( const RENDER_SETTINGS* aSettings ) const
|
||||||
{
|
{
|
||||||
KIFONT::FONT* font = GetFont();
|
KIFONT::FONT* font = GetFont();
|
||||||
@ -1405,12 +1414,10 @@ static struct EDA_TEXT_DESC
|
|||||||
PROPERTY_DISPLAY::PT_SIZE ),
|
PROPERTY_DISPLAY::PT_SIZE ),
|
||||||
textProps );
|
textProps );
|
||||||
|
|
||||||
propMgr.AddProperty( new PROPERTY_ENUM<EDA_TEXT, GR_TEXT_H_ALIGN_T>(
|
propMgr.AddProperty( new PROPERTY_ENUM<EDA_TEXT, GR_TEXT_H_ALIGN_T>( _HKI( "Horizontal Justification" ),
|
||||||
_HKI( "Horizontal Justification" ),
|
|
||||||
&EDA_TEXT::SetHorizJustify, &EDA_TEXT::GetHorizJustify ),
|
&EDA_TEXT::SetHorizJustify, &EDA_TEXT::GetHorizJustify ),
|
||||||
textProps );
|
textProps );
|
||||||
propMgr.AddProperty( new PROPERTY_ENUM<EDA_TEXT, GR_TEXT_V_ALIGN_T>(
|
propMgr.AddProperty( new PROPERTY_ENUM<EDA_TEXT, GR_TEXT_V_ALIGN_T>( _HKI( "Vertical Justification" ),
|
||||||
_HKI( "Vertical Justification" ),
|
|
||||||
&EDA_TEXT::SetVertJustify, &EDA_TEXT::GetVertJustify ),
|
&EDA_TEXT::SetVertJustify, &EDA_TEXT::GetVertJustify ),
|
||||||
textProps );
|
textProps );
|
||||||
|
|
||||||
|
@ -458,6 +458,28 @@ wxString EDA_UNIT_UTILS::UI::MessageTextFromValue( const EDA_IU_SCALE& aIuScale,
|
|||||||
|
|
||||||
text.Printf( format, value );
|
text.Printf( format, value );
|
||||||
|
|
||||||
|
// Check if the formatted value shows only zeros but the actual value is non-zero
|
||||||
|
// If so, use scientific notation instead
|
||||||
|
if( value != 0.0 )
|
||||||
|
{
|
||||||
|
bool showsOnlyZeros = true;
|
||||||
|
|
||||||
|
// Check if the text contains only zeros (allowing for decimal point, minus sign, etc.)
|
||||||
|
for( auto ch : text )
|
||||||
|
{
|
||||||
|
if( ch >= '1' && ch <= '9' )
|
||||||
|
{
|
||||||
|
showsOnlyZeros = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( showsOnlyZeros )
|
||||||
|
{
|
||||||
|
text.Printf( wxT( "%.3e" ), value );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Trim to 2-1/2 digits after the decimal place for short-form mm
|
// Trim to 2-1/2 digits after the decimal place for short-form mm
|
||||||
if( short_form && aUnits == EDA_UNITS::MM )
|
if( short_form && aUnits == EDA_UNITS::MM )
|
||||||
{
|
{
|
||||||
|
@ -1364,6 +1364,11 @@ CAIRO_GAL::CAIRO_GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions, wxWindow* aParent,
|
|||||||
m_currentTarget = TARGET_NONCACHED;
|
m_currentTarget = TARGET_NONCACHED;
|
||||||
SetTarget( TARGET_NONCACHED );
|
SetTarget( TARGET_NONCACHED );
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
// need to fix broken cairo rendering on Windows with wx 3.3
|
||||||
|
SetDoubleBuffered( false );
|
||||||
|
#endif
|
||||||
|
|
||||||
m_bitmapBuffer = nullptr;
|
m_bitmapBuffer = nullptr;
|
||||||
m_wxOutput = nullptr;
|
m_wxOutput = nullptr;
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <wx/log.h>
|
#include <wx/log.h>
|
||||||
|
#include <advanced_config.h>
|
||||||
#include <gal/graphics_abstraction_layer.h>
|
#include <gal/graphics_abstraction_layer.h>
|
||||||
#include <gal/definitions.h>
|
#include <gal/definitions.h>
|
||||||
#include <font/font.h>
|
#include <font/font.h>
|
||||||
@ -62,7 +62,7 @@ GAL::GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions ) :
|
|||||||
|
|
||||||
// wxDC::GetPPI() reports 96 DPI, but somehow this value
|
// wxDC::GetPPI() reports 96 DPI, but somehow this value
|
||||||
// is the closest match to the legacy renderer
|
// is the closest match to the legacy renderer
|
||||||
SetScreenDPI( 91 );
|
SetScreenDPI( ADVANCED_CFG::GetCfg().m_ScreenDPI );
|
||||||
SetDepthRange( VECTOR2D( GAL::MIN_DEPTH, GAL::MAX_DEPTH ) );
|
SetDepthRange( VECTOR2D( GAL::MIN_DEPTH, GAL::MAX_DEPTH ) );
|
||||||
SetLayerDepth( 0.0 );
|
SetLayerDepth( 0.0 );
|
||||||
SetFlip( false, false );
|
SetFlip( false, false );
|
||||||
|
@ -2700,6 +2700,10 @@ void OPENGL_GAL::blitCursor()
|
|||||||
glLineWidth( 1.0 );
|
glLineWidth( 1.0 );
|
||||||
glColor4d( color.r, color.g, color.b, color.a );
|
glColor4d( color.r, color.g, color.b, color.a );
|
||||||
|
|
||||||
|
glMatrixMode( GL_PROJECTION );
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslated( 0, 0, -0.5 );
|
||||||
|
|
||||||
glBegin( GL_LINES );
|
glBegin( GL_LINES );
|
||||||
|
|
||||||
if( m_crossHairMode == CROSS_HAIR_MODE::FULLSCREEN_DIAGONAL )
|
if( m_crossHairMode == CROSS_HAIR_MODE::FULLSCREEN_DIAGONAL )
|
||||||
@ -2743,6 +2747,8 @@ void OPENGL_GAL::blitCursor()
|
|||||||
|
|
||||||
glEnd();
|
glEnd();
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
if( depthTestEnabled )
|
if( depthTestEnabled )
|
||||||
glEnable( GL_DEPTH_TEST );
|
glEnable( GL_DEPTH_TEST );
|
||||||
}
|
}
|
||||||
|
@ -22,16 +22,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "git_add_to_index_handler.h"
|
#include "git_add_to_index_handler.h"
|
||||||
#include <git/kicad_git_memory.h>
|
#include "git_backend.h"
|
||||||
|
|
||||||
#include <iterator>
|
|
||||||
|
|
||||||
#include <wx/string.h>
|
|
||||||
#include <wx/log.h>
|
#include <wx/log.h>
|
||||||
|
|
||||||
GIT_ADD_TO_INDEX_HANDLER::GIT_ADD_TO_INDEX_HANDLER( git_repository* aRepository )
|
GIT_ADD_TO_INDEX_HANDLER::GIT_ADD_TO_INDEX_HANDLER( git_repository* aRepository ) :
|
||||||
|
KIGIT_COMMON( aRepository )
|
||||||
{
|
{
|
||||||
m_repository = aRepository;
|
|
||||||
m_filesToAdd.clear();
|
m_filesToAdd.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,66 +40,11 @@ GIT_ADD_TO_INDEX_HANDLER::~GIT_ADD_TO_INDEX_HANDLER()
|
|||||||
|
|
||||||
bool GIT_ADD_TO_INDEX_HANDLER::AddToIndex( const wxString& aFilePath )
|
bool GIT_ADD_TO_INDEX_HANDLER::AddToIndex( const wxString& aFilePath )
|
||||||
{
|
{
|
||||||
// Test if file is currently in the index
|
return GetGitBackend()->AddToIndex( this, aFilePath );
|
||||||
|
|
||||||
git_index* index = nullptr;
|
|
||||||
size_t at_pos = 0;
|
|
||||||
|
|
||||||
if( git_repository_index( &index, m_repository ) != 0 )
|
|
||||||
{
|
|
||||||
wxLogError( "Failed to get repository index" );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitIndexPtr indexPtr( index );
|
|
||||||
|
|
||||||
if( git_index_find( &at_pos, index, aFilePath.ToUTF8().data() ) == GIT_OK )
|
|
||||||
{
|
|
||||||
wxLogError( "%s already in index", aFilePath );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add file to index if not already there
|
|
||||||
m_filesToAdd.push_back( aFilePath );
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool GIT_ADD_TO_INDEX_HANDLER::PerformAddToIndex()
|
bool GIT_ADD_TO_INDEX_HANDLER::PerformAddToIndex()
|
||||||
{
|
{
|
||||||
git_index* index = nullptr;
|
return GetGitBackend()->PerformAddToIndex( this );
|
||||||
|
|
||||||
m_filesFailedToAdd.clear();
|
|
||||||
|
|
||||||
if( git_repository_index( &index, m_repository ) != 0 )
|
|
||||||
{
|
|
||||||
wxLogError( "Failed to get repository index" );
|
|
||||||
std::copy( m_filesToAdd.begin(), m_filesToAdd.end(), std::back_inserter( m_filesFailedToAdd ) );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitIndexPtr indexPtr( index );
|
|
||||||
|
|
||||||
for( auto& file : m_filesToAdd )
|
|
||||||
{
|
|
||||||
if( git_index_add_bypath( index, file.ToUTF8().data() ) != 0 )
|
|
||||||
{
|
|
||||||
wxLogError( "Failed to add %s to index", file );
|
|
||||||
m_filesFailedToAdd.push_back( file );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if( git_index_write( index ) != 0 )
|
|
||||||
{
|
|
||||||
wxLogError( "Failed to write index" );
|
|
||||||
m_filesFailedToAdd.clear();
|
|
||||||
std::copy( m_filesToAdd.begin(), m_filesToAdd.end(),
|
|
||||||
std::back_inserter( m_filesFailedToAdd ) );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
@ -24,12 +24,13 @@
|
|||||||
#ifndef GIT_ADD_TO_INDEX_HANDLER_H_
|
#ifndef GIT_ADD_TO_INDEX_HANDLER_H_
|
||||||
#define GIT_ADD_TO_INDEX_HANDLER_H_
|
#define GIT_ADD_TO_INDEX_HANDLER_H_
|
||||||
|
|
||||||
#include <git2.h>
|
#include <git/kicad_git_common.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <wx/string.h>
|
||||||
|
|
||||||
class wxString;
|
class LIBGIT_BACKEND;
|
||||||
|
|
||||||
class GIT_ADD_TO_INDEX_HANDLER
|
class GIT_ADD_TO_INDEX_HANDLER : public KIGIT_COMMON
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GIT_ADD_TO_INDEX_HANDLER( git_repository* aRepository );
|
GIT_ADD_TO_INDEX_HANDLER( git_repository* aRepository );
|
||||||
@ -40,8 +41,7 @@ public:
|
|||||||
bool PerformAddToIndex();
|
bool PerformAddToIndex();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
git_repository* m_repository;
|
friend class LIBGIT_BACKEND;
|
||||||
|
|
||||||
std::vector<wxString> m_filesToAdd;
|
std::vector<wxString> m_filesToAdd;
|
||||||
std::vector<wxString> m_filesFailedToAdd;
|
std::vector<wxString> m_filesFailedToAdd;
|
||||||
};
|
};
|
||||||
|
36
common/git/git_backend.cpp
Normal file
36
common/git/git_backend.cpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright The 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, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 3 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "git_backend.h"
|
||||||
|
|
||||||
|
static GIT_BACKEND* s_backend = nullptr;
|
||||||
|
|
||||||
|
GIT_BACKEND* GetGitBackend()
|
||||||
|
{
|
||||||
|
return s_backend;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetGitBackend( GIT_BACKEND* aBackend )
|
||||||
|
{
|
||||||
|
s_backend = aBackend;
|
||||||
|
}
|
127
common/git/git_backend.h
Normal file
127
common/git/git_backend.h
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright The 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, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 3 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GIT_BACKEND_H_
|
||||||
|
#define GIT_BACKEND_H_
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
#include <wx/string.h>
|
||||||
|
|
||||||
|
class GIT_CLONE_HANDLER;
|
||||||
|
class GIT_COMMIT_HANDLER;
|
||||||
|
class GIT_PUSH_HANDLER;
|
||||||
|
class GIT_STATUS_HANDLER;
|
||||||
|
class GIT_ADD_TO_INDEX_HANDLER;
|
||||||
|
class GIT_REMOVE_FROM_INDEX_HANDLER;
|
||||||
|
class GIT_CONFIG_HANDLER;
|
||||||
|
class GIT_INIT_HANDLER;
|
||||||
|
class GIT_BRANCH_HANDLER;
|
||||||
|
class GIT_PULL_HANDLER;
|
||||||
|
class GIT_REVERT_HANDLER;
|
||||||
|
struct RemoteConfig;
|
||||||
|
struct git_repository;
|
||||||
|
enum class InitResult;
|
||||||
|
enum class BranchResult;
|
||||||
|
enum class PullResult;
|
||||||
|
struct FileStatus;
|
||||||
|
enum class PushResult;
|
||||||
|
|
||||||
|
// Commit result shared across backend and handlers
|
||||||
|
enum class CommitResult
|
||||||
|
{
|
||||||
|
Success,
|
||||||
|
Error,
|
||||||
|
Cancelled
|
||||||
|
};
|
||||||
|
|
||||||
|
class GIT_BACKEND
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~GIT_BACKEND() = default;
|
||||||
|
|
||||||
|
virtual void Init() = 0;
|
||||||
|
virtual void Shutdown() = 0;
|
||||||
|
|
||||||
|
// Whether the libgit2 library is available/initialized enough for use
|
||||||
|
virtual bool IsLibraryAvailable() = 0;
|
||||||
|
|
||||||
|
virtual bool Clone( GIT_CLONE_HANDLER* aHandler ) = 0;
|
||||||
|
|
||||||
|
virtual CommitResult Commit( GIT_COMMIT_HANDLER* aHandler,
|
||||||
|
const std::vector<wxString>& aFiles,
|
||||||
|
const wxString& aMessage,
|
||||||
|
const wxString& aAuthorName,
|
||||||
|
const wxString& aAuthorEmail ) = 0;
|
||||||
|
|
||||||
|
virtual PushResult Push( GIT_PUSH_HANDLER* aHandler ) = 0;
|
||||||
|
|
||||||
|
virtual bool HasChangedFiles( GIT_STATUS_HANDLER* aHandler ) = 0;
|
||||||
|
|
||||||
|
virtual std::map<wxString, FileStatus> GetFileStatus( GIT_STATUS_HANDLER* aHandler,
|
||||||
|
const wxString& aPathspec ) = 0;
|
||||||
|
|
||||||
|
virtual wxString GetCurrentBranchName( GIT_STATUS_HANDLER* aHandler ) = 0;
|
||||||
|
|
||||||
|
virtual void UpdateRemoteStatus( GIT_STATUS_HANDLER* aHandler,
|
||||||
|
const std::set<wxString>& aLocalChanges,
|
||||||
|
const std::set<wxString>& aRemoteChanges,
|
||||||
|
std::map<wxString, FileStatus>& aFileStatus ) = 0;
|
||||||
|
|
||||||
|
virtual wxString GetWorkingDirectory( GIT_STATUS_HANDLER* aHandler ) = 0;
|
||||||
|
|
||||||
|
virtual wxString GetWorkingDirectory( GIT_CONFIG_HANDLER* aHandler ) = 0;
|
||||||
|
virtual bool GetConfigString( GIT_CONFIG_HANDLER* aHandler, const wxString& aKey,
|
||||||
|
wxString& aValue ) = 0;
|
||||||
|
|
||||||
|
virtual bool IsRepository( GIT_INIT_HANDLER* aHandler, const wxString& aPath ) = 0;
|
||||||
|
virtual InitResult InitializeRepository( GIT_INIT_HANDLER* aHandler, const wxString& aPath ) = 0;
|
||||||
|
virtual bool SetupRemote( GIT_INIT_HANDLER* aHandler, const RemoteConfig& aConfig ) = 0;
|
||||||
|
|
||||||
|
virtual BranchResult SwitchToBranch( GIT_BRANCH_HANDLER* aHandler, const wxString& aBranchName ) = 0;
|
||||||
|
virtual bool BranchExists( GIT_BRANCH_HANDLER* aHandler, const wxString& aBranchName ) = 0;
|
||||||
|
|
||||||
|
virtual bool PerformFetch( GIT_PULL_HANDLER* aHandler, bool aSkipLock ) = 0;
|
||||||
|
virtual PullResult PerformPull( GIT_PULL_HANDLER* aHandler ) = 0;
|
||||||
|
|
||||||
|
virtual void PerformRevert( GIT_REVERT_HANDLER* aHandler ) = 0;
|
||||||
|
|
||||||
|
virtual git_repository* GetRepositoryForFile( const char* aFilename ) = 0;
|
||||||
|
virtual int CreateBranch( git_repository* aRepo, const wxString& aBranchName ) = 0;
|
||||||
|
virtual bool RemoveVCS( git_repository*& aRepo, const wxString& aProjectPath,
|
||||||
|
bool aRemoveGitDir, wxString* aErrors ) = 0;
|
||||||
|
|
||||||
|
virtual bool AddToIndex( GIT_ADD_TO_INDEX_HANDLER* aHandler, const wxString& aFilePath ) = 0;
|
||||||
|
|
||||||
|
virtual bool PerformAddToIndex( GIT_ADD_TO_INDEX_HANDLER* aHandler ) = 0;
|
||||||
|
|
||||||
|
virtual bool RemoveFromIndex( GIT_REMOVE_FROM_INDEX_HANDLER* aHandler, const wxString& aFilePath ) = 0;
|
||||||
|
|
||||||
|
virtual void PerformRemoveFromIndex( GIT_REMOVE_FROM_INDEX_HANDLER* aHandler ) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
GIT_BACKEND* GetGitBackend();
|
||||||
|
void SetGitBackend( GIT_BACKEND* aBackend );
|
||||||
|
|
||||||
|
#endif
|
@ -22,6 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "git_branch_handler.h"
|
#include "git_branch_handler.h"
|
||||||
|
#include "git_backend.h"
|
||||||
#include <git/kicad_git_common.h>
|
#include <git/kicad_git_common.h>
|
||||||
#include <git/kicad_git_memory.h>
|
#include <git/kicad_git_memory.h>
|
||||||
#include <trace_helpers.h>
|
#include <trace_helpers.h>
|
||||||
@ -35,89 +36,12 @@ GIT_BRANCH_HANDLER::~GIT_BRANCH_HANDLER()
|
|||||||
|
|
||||||
bool GIT_BRANCH_HANDLER::BranchExists( const wxString& aBranchName )
|
bool GIT_BRANCH_HANDLER::BranchExists( const wxString& aBranchName )
|
||||||
{
|
{
|
||||||
git_repository* repo = GetRepo();
|
return GetGitBackend()->BranchExists( this, aBranchName );
|
||||||
|
|
||||||
if( !repo )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
git_reference* branchRef = nullptr;
|
|
||||||
bool exists = LookupBranchReference( aBranchName, &branchRef );
|
|
||||||
|
|
||||||
if( branchRef )
|
|
||||||
git_reference_free( branchRef );
|
|
||||||
|
|
||||||
return exists;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GIT_BRANCH_HANDLER::LookupBranchReference( const wxString& aBranchName, git_reference** aReference )
|
|
||||||
{
|
|
||||||
git_repository* repo = GetRepo();
|
|
||||||
|
|
||||||
if( !repo )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Try direct lookup first
|
|
||||||
if( git_reference_lookup( aReference, repo, aBranchName.mb_str() ) == GIT_OK )
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Try dwim (Do What I Mean) lookup for short branch names
|
|
||||||
if( git_reference_dwim( aReference, repo, aBranchName.mb_str() ) == GIT_OK )
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BranchResult GIT_BRANCH_HANDLER::SwitchToBranch( const wxString& aBranchName )
|
BranchResult GIT_BRANCH_HANDLER::SwitchToBranch( const wxString& aBranchName )
|
||||||
{
|
{
|
||||||
git_repository* repo = GetRepo();
|
return GetGitBackend()->SwitchToBranch( this, aBranchName );
|
||||||
|
|
||||||
if( !repo )
|
|
||||||
{
|
|
||||||
AddErrorString( _( "No repository available" ) );
|
|
||||||
return BranchResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look up the branch reference
|
|
||||||
git_reference* branchRef = nullptr;
|
|
||||||
|
|
||||||
if( !LookupBranchReference( aBranchName, &branchRef ) )
|
|
||||||
{
|
|
||||||
AddErrorString( wxString::Format( _( "Failed to lookup branch '%s': %s" ),
|
|
||||||
aBranchName, KIGIT_COMMON::GetLastGitError() ) );
|
|
||||||
return BranchResult::BranchNotFound;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitReferencePtr branchRefPtr( branchRef );
|
|
||||||
const char* branchRefName = git_reference_name( branchRef );
|
|
||||||
git_object* branchObj = nullptr;
|
|
||||||
|
|
||||||
if( git_revparse_single( &branchObj, repo, aBranchName.mb_str() ) != GIT_OK )
|
|
||||||
{
|
|
||||||
AddErrorString( wxString::Format( _( "Failed to find branch head for '%s': %s" ),
|
|
||||||
aBranchName, KIGIT_COMMON::GetLastGitError() ) );
|
|
||||||
return BranchResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitObjectPtr branchObjPtr( branchObj );
|
|
||||||
|
|
||||||
// Switch to the branch
|
|
||||||
if( git_checkout_tree( repo, branchObj, nullptr ) != GIT_OK )
|
|
||||||
{
|
|
||||||
AddErrorString( wxString::Format( _( "Failed to switch to branch '%s': %s" ),
|
|
||||||
aBranchName, KIGIT_COMMON::GetLastGitError() ) );
|
|
||||||
return BranchResult::CheckoutFailed;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the HEAD reference
|
|
||||||
if( git_repository_set_head( repo, branchRefName ) != GIT_OK )
|
|
||||||
{
|
|
||||||
AddErrorString( wxString::Format( _( "Failed to update HEAD reference for branch '%s': %s" ),
|
|
||||||
aBranchName, KIGIT_COMMON::GetLastGitError() ) );
|
|
||||||
return BranchResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxLogTrace( traceGit, "Successfully switched to branch '%s'", aBranchName );
|
|
||||||
return BranchResult::Success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GIT_BRANCH_HANDLER::UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage )
|
void GIT_BRANCH_HANDLER::UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage )
|
||||||
|
@ -57,15 +57,6 @@ public:
|
|||||||
bool BranchExists( const wxString& aBranchName );
|
bool BranchExists( const wxString& aBranchName );
|
||||||
|
|
||||||
void UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage ) override;
|
void UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage ) override;
|
||||||
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* Look up a branch reference by name
|
|
||||||
* @param aBranchName Name of the branch
|
|
||||||
* @param aReference Output parameter for the reference
|
|
||||||
* @return True if successful, false otherwise
|
|
||||||
*/
|
|
||||||
bool LookupBranchReference( const wxString& aBranchName, git_reference** aReference );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GIT_BRANCH_HANDLER_H
|
#endif // GIT_BRANCH_HANDLER_H
|
@ -23,13 +23,8 @@
|
|||||||
|
|
||||||
#include "git_clone_handler.h"
|
#include "git_clone_handler.h"
|
||||||
|
|
||||||
#include <git/kicad_git_common.h>
|
|
||||||
#include <git/kicad_git_memory.h>
|
|
||||||
#include <trace_helpers.h>
|
#include <trace_helpers.h>
|
||||||
|
#include "git_backend.h"
|
||||||
#include <git2.h>
|
|
||||||
#include <wx/filename.h>
|
|
||||||
#include <wx/log.h>
|
|
||||||
|
|
||||||
GIT_CLONE_HANDLER::GIT_CLONE_HANDLER( KIGIT_COMMON* aCommon ) : KIGIT_REPO_MIXIN( aCommon )
|
GIT_CLONE_HANDLER::GIT_CLONE_HANDLER( KIGIT_COMMON* aCommon ) : KIGIT_REPO_MIXIN( aCommon )
|
||||||
{}
|
{}
|
||||||
@ -41,55 +36,7 @@ GIT_CLONE_HANDLER::~GIT_CLONE_HANDLER()
|
|||||||
|
|
||||||
bool GIT_CLONE_HANDLER::PerformClone()
|
bool GIT_CLONE_HANDLER::PerformClone()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock( GetCommon()->m_gitActionMutex, std::try_to_lock );
|
return GetGitBackend()->Clone( this );
|
||||||
|
|
||||||
if( !lock.owns_lock() )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "GIT_CLONE_HANDLER::PerformClone() could not lock" );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxFileName clonePath( m_clonePath );
|
|
||||||
|
|
||||||
if( !clonePath.DirExists() )
|
|
||||||
{
|
|
||||||
if( !clonePath.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
|
|
||||||
{
|
|
||||||
AddErrorString( wxString::Format( _( "Could not create directory '%s'" ),
|
|
||||||
m_clonePath ) );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
git_clone_options cloneOptions;
|
|
||||||
git_clone_init_options( &cloneOptions, GIT_CLONE_OPTIONS_VERSION );
|
|
||||||
cloneOptions.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
|
|
||||||
cloneOptions.checkout_opts.progress_cb = clone_progress_cb;
|
|
||||||
cloneOptions.checkout_opts.progress_payload = this;
|
|
||||||
cloneOptions.fetch_opts.callbacks.transfer_progress = transfer_progress_cb;
|
|
||||||
cloneOptions.fetch_opts.callbacks.credentials = credentials_cb;
|
|
||||||
cloneOptions.fetch_opts.callbacks.payload = this;
|
|
||||||
|
|
||||||
TestedTypes() = 0;
|
|
||||||
ResetNextKey();
|
|
||||||
git_repository* newRepo = nullptr;
|
|
||||||
wxString remote = GetCommon()->m_remote;
|
|
||||||
|
|
||||||
if( git_clone( &newRepo, remote.mbc_str(), m_clonePath.mbc_str(),
|
|
||||||
&cloneOptions ) != 0 )
|
|
||||||
{
|
|
||||||
AddErrorString( wxString::Format( _( "Could not clone repository '%s'" ), remote ) );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
GetCommon()->SetRepo( newRepo );
|
|
||||||
|
|
||||||
if( m_progressReporter )
|
|
||||||
m_progressReporter->Hide();
|
|
||||||
|
|
||||||
m_previousProgress = 0;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,8 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "git_commit_handler.h"
|
#include "git_commit_handler.h"
|
||||||
#include <git/kicad_git_memory.h>
|
#include "git_backend.h"
|
||||||
#include <wx/log.h>
|
|
||||||
|
|
||||||
GIT_COMMIT_HANDLER::GIT_COMMIT_HANDLER( git_repository* aRepo ) :
|
GIT_COMMIT_HANDLER::GIT_COMMIT_HANDLER( git_repository* aRepo ) :
|
||||||
KIGIT_COMMON( aRepo )
|
KIGIT_COMMON( aRepo )
|
||||||
@ -34,121 +33,13 @@ GIT_COMMIT_HANDLER::~GIT_COMMIT_HANDLER()
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
GIT_COMMIT_HANDLER::CommitResult
|
CommitResult
|
||||||
GIT_COMMIT_HANDLER::PerformCommit( const std::vector<wxString>& aFiles,
|
GIT_COMMIT_HANDLER::PerformCommit( const std::vector<wxString>& aFiles,
|
||||||
const wxString& aMessage,
|
const wxString& aMessage,
|
||||||
const wxString& aAuthorName,
|
const wxString& aAuthorName,
|
||||||
const wxString& aAuthorEmail )
|
const wxString& aAuthorEmail )
|
||||||
{
|
{
|
||||||
git_repository* repo = GetRepo();
|
return GetGitBackend()->Commit( this, aFiles, aMessage, aAuthorName, aAuthorEmail );
|
||||||
|
|
||||||
if( !repo )
|
|
||||||
return CommitResult::Error;
|
|
||||||
|
|
||||||
git_index* index = nullptr;
|
|
||||||
|
|
||||||
if( git_repository_index( &index, repo ) != 0 )
|
|
||||||
{
|
|
||||||
AddErrorString( wxString::Format( _( "Failed to get repository index: %s" ),
|
|
||||||
KIGIT_COMMON::GetLastGitError() ) );
|
|
||||||
return CommitResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitIndexPtr indexPtr( index );
|
|
||||||
|
|
||||||
for( const wxString& file : aFiles )
|
|
||||||
{
|
|
||||||
if( git_index_add_bypath( index, file.mb_str() ) != 0 )
|
|
||||||
{
|
|
||||||
AddErrorString( wxString::Format( _( "Failed to add file to index: %s" ),
|
|
||||||
KIGIT_COMMON::GetLastGitError() ) );
|
|
||||||
return CommitResult::Error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( git_index_write( index ) != 0 )
|
|
||||||
{
|
|
||||||
AddErrorString( wxString::Format( _( "Failed to write index: %s" ),
|
|
||||||
KIGIT_COMMON::GetLastGitError() ) );
|
|
||||||
return CommitResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
git_oid tree_id;
|
|
||||||
|
|
||||||
if( git_index_write_tree( &tree_id, index ) != 0 )
|
|
||||||
{
|
|
||||||
AddErrorString( wxString::Format( _( "Failed to write tree: %s" ),
|
|
||||||
KIGIT_COMMON::GetLastGitError() ) );
|
|
||||||
return CommitResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
git_tree* tree = nullptr;
|
|
||||||
|
|
||||||
if( git_tree_lookup( &tree, repo, &tree_id ) != 0 )
|
|
||||||
{
|
|
||||||
AddErrorString( wxString::Format( _( "Failed to lookup tree: %s" ),
|
|
||||||
KIGIT_COMMON::GetLastGitError() ) );
|
|
||||||
return CommitResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitTreePtr treePtr( tree );
|
|
||||||
git_commit* parent = nullptr;
|
|
||||||
|
|
||||||
if( git_repository_head_unborn( repo ) == 0 )
|
|
||||||
{
|
|
||||||
git_reference* headRef = nullptr;
|
|
||||||
|
|
||||||
if( git_repository_head( &headRef, repo ) != 0 )
|
|
||||||
{
|
|
||||||
AddErrorString( wxString::Format( _( "Failed to get HEAD reference: %s" ),
|
|
||||||
KIGIT_COMMON::GetLastGitError() ) );
|
|
||||||
return CommitResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitReferencePtr headRefPtr( headRef );
|
|
||||||
|
|
||||||
if( git_reference_peel( (git_object**) &parent, headRef, GIT_OBJECT_COMMIT ) != 0 )
|
|
||||||
{
|
|
||||||
AddErrorString( wxString::Format( _( "Failed to get commit: %s" ),
|
|
||||||
KIGIT_COMMON::GetLastGitError() ) );
|
|
||||||
return CommitResult::Error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitCommitPtr parentPtr( parent );
|
|
||||||
|
|
||||||
git_signature* author = nullptr;
|
|
||||||
|
|
||||||
if( git_signature_now( &author, aAuthorName.mb_str(), aAuthorEmail.mb_str() ) != 0 )
|
|
||||||
{
|
|
||||||
AddErrorString( wxString::Format( _( "Failed to create author signature: %s" ),
|
|
||||||
KIGIT_COMMON::GetLastGitError() ) );
|
|
||||||
return CommitResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitSignaturePtr authorPtr( author );
|
|
||||||
git_oid oid;
|
|
||||||
size_t parentsCount = parent ? 1 : 0;
|
|
||||||
#if( LIBGIT2_VER_MAJOR == 1 && LIBGIT2_VER_MINOR == 8 \
|
|
||||||
&& ( LIBGIT2_VER_REVISION < 2 || LIBGIT2_VER_REVISION == 3 ) )
|
|
||||||
git_commit* const parents[1] = { parent };
|
|
||||||
git_commit** const parentsPtr = parent ? parents : nullptr;
|
|
||||||
#else
|
|
||||||
const git_commit* parents[1] = { parent };
|
|
||||||
const git_commit** parentsPtr = parent ? parents : nullptr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if( git_commit_create( &oid, repo, "HEAD", author, author, nullptr,
|
|
||||||
aMessage.mb_str(), tree, parentsCount, parentsPtr ) != 0 )
|
|
||||||
{
|
|
||||||
AddErrorString( wxString::Format( _( "Failed to create commit: %s" ),
|
|
||||||
KIGIT_COMMON::GetLastGitError() ) );
|
|
||||||
return CommitResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CommitResult::Success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,25 +27,20 @@
|
|||||||
// Define a class to handle git commit operations
|
// Define a class to handle git commit operations
|
||||||
|
|
||||||
#include <git/kicad_git_common.h>
|
#include <git/kicad_git_common.h>
|
||||||
#include <git2.h>
|
#include "git_backend.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
|
|
||||||
|
class LIBGIT_BACKEND;
|
||||||
|
|
||||||
class GIT_COMMIT_HANDLER : public KIGIT_COMMON
|
class GIT_COMMIT_HANDLER : public KIGIT_COMMON
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GIT_COMMIT_HANDLER( git_repository* aRepo );
|
GIT_COMMIT_HANDLER( git_repository* aRepo );
|
||||||
virtual ~GIT_COMMIT_HANDLER();
|
virtual ~GIT_COMMIT_HANDLER();
|
||||||
|
|
||||||
enum class CommitResult
|
|
||||||
{
|
|
||||||
Success,
|
|
||||||
Error,
|
|
||||||
Cancelled
|
|
||||||
};
|
|
||||||
|
|
||||||
CommitResult PerformCommit( const std::vector<wxString>& aFiles,
|
CommitResult PerformCommit( const std::vector<wxString>& aFiles,
|
||||||
const wxString& aMessage,
|
const wxString& aMessage,
|
||||||
const wxString& aAuthorName,
|
const wxString& aAuthorName,
|
||||||
@ -54,6 +49,7 @@ public:
|
|||||||
wxString GetErrorString() const;
|
wxString GetErrorString() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class LIBGIT_BACKEND;
|
||||||
void AddErrorString( const wxString& aErrorString );
|
void AddErrorString( const wxString& aErrorString );
|
||||||
|
|
||||||
wxString m_errorString;
|
wxString m_errorString;
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "git_config_handler.h"
|
#include "git_config_handler.h"
|
||||||
|
#include "git_backend.h"
|
||||||
#include <git/kicad_git_common.h>
|
#include <git/kicad_git_common.h>
|
||||||
#include <git/kicad_git_memory.h>
|
#include <git/kicad_git_memory.h>
|
||||||
#include <pgm_base.h>
|
#include <pgm_base.h>
|
||||||
@ -59,48 +60,12 @@ GitUserConfig GIT_CONFIG_HANDLER::GetUserConfig()
|
|||||||
|
|
||||||
wxString GIT_CONFIG_HANDLER::GetWorkingDirectory()
|
wxString GIT_CONFIG_HANDLER::GetWorkingDirectory()
|
||||||
{
|
{
|
||||||
git_repository* repo = GetRepo();
|
return GetGitBackend()->GetWorkingDirectory( this );
|
||||||
|
|
||||||
if( !repo )
|
|
||||||
return wxEmptyString;
|
|
||||||
|
|
||||||
const char* workdir = git_repository_workdir( repo );
|
|
||||||
|
|
||||||
if( !workdir )
|
|
||||||
return wxEmptyString;
|
|
||||||
|
|
||||||
return wxString( workdir );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GIT_CONFIG_HANDLER::GetConfigString( const wxString& aKey, wxString& aValue )
|
bool GIT_CONFIG_HANDLER::GetConfigString( const wxString& aKey, wxString& aValue )
|
||||||
{
|
{
|
||||||
git_repository* repo = GetRepo();
|
return GetGitBackend()->GetConfigString( this, aKey, aValue );
|
||||||
|
|
||||||
if( !repo )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
git_config* config = nullptr;
|
|
||||||
|
|
||||||
if( git_repository_config( &config, repo ) != GIT_OK )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "Failed to get repository config: %s", KIGIT_COMMON::GetLastGitError() );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitConfigPtr configPtr( config );
|
|
||||||
|
|
||||||
git_config_entry* entry = nullptr;
|
|
||||||
int result = git_config_get_entry( &entry, config, aKey.mb_str() );
|
|
||||||
KIGIT::GitConfigEntryPtr entryPtr( entry );
|
|
||||||
|
|
||||||
if( result != GIT_OK || entry == nullptr )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "Config key '%s' not found", aKey );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
aValue = wxString( entry->value );
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GIT_CONFIG_HANDLER::UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage )
|
void GIT_CONFIG_HANDLER::UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage )
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "git_init_handler.h"
|
#include "git_init_handler.h"
|
||||||
|
#include "git_backend.h"
|
||||||
#include <git/kicad_git_common.h>
|
#include <git/kicad_git_common.h>
|
||||||
#include <git/kicad_git_memory.h>
|
#include <git/kicad_git_memory.h>
|
||||||
#include <trace_helpers.h>
|
#include <trace_helpers.h>
|
||||||
@ -35,118 +36,17 @@ GIT_INIT_HANDLER::~GIT_INIT_HANDLER()
|
|||||||
|
|
||||||
bool GIT_INIT_HANDLER::IsRepository( const wxString& aPath )
|
bool GIT_INIT_HANDLER::IsRepository( const wxString& aPath )
|
||||||
{
|
{
|
||||||
git_repository* repo = nullptr;
|
return GetGitBackend()->IsRepository( this, aPath );
|
||||||
int error = git_repository_open( &repo, aPath.mb_str() );
|
|
||||||
|
|
||||||
if( error == 0 )
|
|
||||||
{
|
|
||||||
git_repository_free( repo );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InitResult GIT_INIT_HANDLER::InitializeRepository( const wxString& aPath )
|
InitResult GIT_INIT_HANDLER::InitializeRepository( const wxString& aPath )
|
||||||
{
|
{
|
||||||
// Check if directory is already a git repository
|
return GetGitBackend()->InitializeRepository( this, aPath );
|
||||||
if( IsRepository( aPath ) )
|
|
||||||
{
|
|
||||||
return InitResult::AlreadyExists;
|
|
||||||
}
|
|
||||||
|
|
||||||
git_repository* repo = nullptr;
|
|
||||||
|
|
||||||
if( git_repository_init( &repo, aPath.mb_str(), 0 ) != GIT_OK )
|
|
||||||
{
|
|
||||||
if( repo )
|
|
||||||
git_repository_free( repo );
|
|
||||||
|
|
||||||
AddErrorString( wxString::Format( _( "Failed to initialize Git repository: %s" ),
|
|
||||||
KIGIT_COMMON::GetLastGitError() ) );
|
|
||||||
return InitResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the common repository pointer
|
|
||||||
GetCommon()->SetRepo( repo );
|
|
||||||
|
|
||||||
wxLogTrace( traceGit, "Successfully initialized Git repository at %s", aPath );
|
|
||||||
return InitResult::Success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GIT_INIT_HANDLER::SetupRemote( const RemoteConfig& aConfig )
|
bool GIT_INIT_HANDLER::SetupRemote( const RemoteConfig& aConfig )
|
||||||
{
|
{
|
||||||
// This is an optional step
|
return GetGitBackend()->SetupRemote( this, aConfig );
|
||||||
if( aConfig.url.IsEmpty() )
|
|
||||||
return true;
|
|
||||||
|
|
||||||
git_repository* repo = GetRepo();
|
|
||||||
|
|
||||||
if( !repo )
|
|
||||||
{
|
|
||||||
AddErrorString( _( "No repository available to set up remote" ) );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update connection settings in common
|
|
||||||
GetCommon()->SetUsername( aConfig.username );
|
|
||||||
GetCommon()->SetPassword( aConfig.password );
|
|
||||||
GetCommon()->SetSSHKey( aConfig.sshKey );
|
|
||||||
|
|
||||||
git_remote* remote = nullptr;
|
|
||||||
wxString fullURL;
|
|
||||||
|
|
||||||
// Build the full URL based on connection type
|
|
||||||
if( aConfig.connType == KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_SSH )
|
|
||||||
{
|
|
||||||
fullURL = aConfig.username + "@" + aConfig.url;
|
|
||||||
}
|
|
||||||
else if( aConfig.connType == KIGIT_COMMON::GIT_CONN_TYPE::GIT_CONN_HTTPS )
|
|
||||||
{
|
|
||||||
fullURL = aConfig.url.StartsWith( "https" ) ? "https://" : "http://";
|
|
||||||
|
|
||||||
if( !aConfig.username.empty() )
|
|
||||||
{
|
|
||||||
fullURL.append( aConfig.username );
|
|
||||||
|
|
||||||
if( !aConfig.password.empty() )
|
|
||||||
{
|
|
||||||
fullURL.append( wxS( ":" ) );
|
|
||||||
fullURL.append( aConfig.password );
|
|
||||||
}
|
|
||||||
|
|
||||||
fullURL.append( wxS( "@" ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract the bare URL (without protocol prefix)
|
|
||||||
wxString bareURL = aConfig.url;
|
|
||||||
if( bareURL.StartsWith( "https://" ) )
|
|
||||||
bareURL = bareURL.Mid( 8 );
|
|
||||||
else if( bareURL.StartsWith( "http://" ) )
|
|
||||||
bareURL = bareURL.Mid( 7 );
|
|
||||||
|
|
||||||
fullURL.append( bareURL );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fullURL = aConfig.url;
|
|
||||||
}
|
|
||||||
|
|
||||||
int error = git_remote_create_with_fetchspec( &remote, repo, "origin",
|
|
||||||
fullURL.ToStdString().c_str(),
|
|
||||||
"+refs/heads/*:refs/remotes/origin/*" );
|
|
||||||
|
|
||||||
KIGIT::GitRemotePtr remotePtr( remote );
|
|
||||||
|
|
||||||
if( error != GIT_OK )
|
|
||||||
{
|
|
||||||
AddErrorString( wxString::Format( _( "Failed to create remote: %s" ),
|
|
||||||
KIGIT_COMMON::GetLastGitError() ) );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxLogTrace( traceGit, "Successfully set up remote origin" );
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GIT_INIT_HANDLER::UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage )
|
void GIT_INIT_HANDLER::UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage )
|
||||||
|
@ -22,188 +22,22 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "git_pull_handler.h"
|
#include "git_pull_handler.h"
|
||||||
#include <git/kicad_git_common.h>
|
#include "git_backend.h"
|
||||||
#include <git/kicad_git_memory.h>
|
|
||||||
#include <trace_helpers.h>
|
|
||||||
|
|
||||||
#include <wx/log.h>
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <time.h>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
GIT_PULL_HANDLER::GIT_PULL_HANDLER( KIGIT_COMMON* aCommon ) : KIGIT_REPO_MIXIN( aCommon )
|
GIT_PULL_HANDLER::GIT_PULL_HANDLER( KIGIT_COMMON* aCommon ) : KIGIT_REPO_MIXIN( aCommon )
|
||||||
{
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
GIT_PULL_HANDLER::~GIT_PULL_HANDLER()
|
GIT_PULL_HANDLER::~GIT_PULL_HANDLER()
|
||||||
{
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool GIT_PULL_HANDLER::PerformFetch( bool aSkipLock )
|
bool GIT_PULL_HANDLER::PerformFetch( bool aSkipLock )
|
||||||
{
|
{
|
||||||
if( !GetRepo() )
|
return GetGitBackend()->PerformFetch( this, aSkipLock );
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "GIT_PULL_HANDLER::PerformFetch() - No repository found" );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lock( GetCommon()->m_gitActionMutex, std::try_to_lock );
|
|
||||||
|
|
||||||
if( !aSkipLock && !lock.owns_lock() )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "GIT_PULL_HANDLER::PerformFetch() - Could not lock mutex" );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch updates from remote repository
|
|
||||||
git_remote* remote = nullptr;
|
|
||||||
|
|
||||||
if( git_remote_lookup( &remote, GetRepo(), "origin" ) != 0 )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "GIT_PULL_HANDLER::PerformFetch() - Failed to lookup remote 'origin'" );
|
|
||||||
AddErrorString( wxString::Format( _( "Could not lookup remote '%s'" ), "origin" ) );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitRemotePtr remotePtr( remote );
|
|
||||||
|
|
||||||
git_remote_callbacks remoteCallbacks;
|
|
||||||
git_remote_init_callbacks( &remoteCallbacks, GIT_REMOTE_CALLBACKS_VERSION );
|
|
||||||
remoteCallbacks.sideband_progress = progress_cb;
|
|
||||||
remoteCallbacks.transfer_progress = transfer_progress_cb;
|
|
||||||
remoteCallbacks.credentials = credentials_cb;
|
|
||||||
remoteCallbacks.payload = this;
|
|
||||||
GetCommon()->SetCancelled( false );
|
|
||||||
|
|
||||||
TestedTypes() = 0;
|
|
||||||
ResetNextKey();
|
|
||||||
|
|
||||||
if( git_remote_connect( remote, GIT_DIRECTION_FETCH, &remoteCallbacks, nullptr, nullptr ) )
|
|
||||||
{
|
|
||||||
wxString errorMsg = KIGIT_COMMON::GetLastGitError();
|
|
||||||
wxLogTrace( traceGit, "GIT_PULL_HANDLER::PerformFetch() - Failed to connect to remote: %s", errorMsg );
|
|
||||||
AddErrorString( wxString::Format( _( "Could not connect to remote '%s': %s" ), "origin", errorMsg ) );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
git_fetch_options fetchOptions;
|
|
||||||
git_fetch_init_options( &fetchOptions, GIT_FETCH_OPTIONS_VERSION );
|
|
||||||
fetchOptions.callbacks = remoteCallbacks;
|
|
||||||
|
|
||||||
if( git_remote_fetch( remote, nullptr, &fetchOptions, nullptr ) )
|
|
||||||
{
|
|
||||||
wxString errorMsg = KIGIT_COMMON::GetLastGitError();
|
|
||||||
wxLogTrace( traceGit, "GIT_PULL_HANDLER::PerformFetch() - Failed to fetch from remote: %s", errorMsg );
|
|
||||||
AddErrorString( wxString::Format( _( "Could not fetch data from remote '%s': %s" ), "origin", errorMsg ) );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxLogTrace( traceGit, "GIT_PULL_HANDLER::PerformFetch() - Fetch completed successfully" );
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PullResult GIT_PULL_HANDLER::PerformPull()
|
PullResult GIT_PULL_HANDLER::PerformPull()
|
||||||
{
|
{
|
||||||
PullResult result = PullResult::Success;
|
return GetGitBackend()->PerformPull( this );
|
||||||
std::unique_lock<std::mutex> lock( GetCommon()->m_gitActionMutex, std::try_to_lock );
|
|
||||||
|
|
||||||
if( !lock.owns_lock() )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "GIT_PULL_HANDLER::PerformPull() - Could not lock mutex" );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !PerformFetch( true ) )
|
|
||||||
return PullResult::Error;
|
|
||||||
|
|
||||||
git_oid pull_merge_oid = {};
|
|
||||||
|
|
||||||
if( git_repository_fetchhead_foreach( GetRepo(), fetchhead_foreach_cb,
|
|
||||||
&pull_merge_oid ) )
|
|
||||||
{
|
|
||||||
AddErrorString( _( "Could not read 'FETCH_HEAD'" ) );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
git_annotated_commit* fetchhead_commit;
|
|
||||||
|
|
||||||
if( git_annotated_commit_lookup( &fetchhead_commit, GetRepo(), &pull_merge_oid ) )
|
|
||||||
{
|
|
||||||
AddErrorString( _( "Could not lookup commit" ) );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitAnnotatedCommitPtr fetchheadCommitPtr( fetchhead_commit );
|
|
||||||
const git_annotated_commit* merge_commits[] = { fetchhead_commit };
|
|
||||||
git_merge_analysis_t merge_analysis;
|
|
||||||
git_merge_preference_t merge_preference = GIT_MERGE_PREFERENCE_NONE;
|
|
||||||
|
|
||||||
if( git_merge_analysis( &merge_analysis, &merge_preference, GetRepo(), merge_commits, 1 ) )
|
|
||||||
{
|
|
||||||
AddErrorString( _( "Could not analyze merge" ) );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( merge_analysis & GIT_MERGE_ANALYSIS_UNBORN )
|
|
||||||
{
|
|
||||||
AddErrorString( _( "Invalid HEAD. Cannot merge." ) );
|
|
||||||
return PullResult::MergeFailed;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nothing to do if the repository is up to date
|
|
||||||
if( merge_analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "GIT_PULL_HANDLER::PerformPull() - Repository is up to date" );
|
|
||||||
git_repository_state_cleanup( GetRepo() );
|
|
||||||
return PullResult::UpToDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fast-forward is easy, just update the local reference
|
|
||||||
if( merge_analysis & GIT_MERGE_ANALYSIS_FASTFORWARD )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "GIT_PULL_HANDLER::PerformPull() - Fast-forward merge" );
|
|
||||||
return handleFastForward();
|
|
||||||
}
|
|
||||||
|
|
||||||
if( merge_analysis & GIT_MERGE_ANALYSIS_NORMAL )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "GIT_PULL_HANDLER::PerformPull() - Normal merge" );
|
|
||||||
|
|
||||||
// Check git config to determine if we should rebase or merge
|
|
||||||
git_config* config = nullptr;
|
|
||||||
|
|
||||||
if( git_repository_config( &config, GetRepo() ) != GIT_OK )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "GIT_PULL_HANDLER::PerformPull() - Failed to get repository config" );
|
|
||||||
AddErrorString( _( "Could not access repository configuration" ) );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitConfigPtr configPtr( config );
|
|
||||||
|
|
||||||
// Check for pull.rebase config
|
|
||||||
int rebase_value = 0;
|
|
||||||
int ret = git_config_get_bool( &rebase_value, config, "pull.rebase" );
|
|
||||||
|
|
||||||
// If pull.rebase is set to true, use rebase; otherwise use merge
|
|
||||||
if( ret == GIT_OK && rebase_value )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "GIT_PULL_HANDLER::PerformPull() - Using rebase based on config" );
|
|
||||||
return handleRebase( merge_commits, 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
wxLogTrace( traceGit, "GIT_PULL_HANDLER::PerformPull() - Using merge based on config" );
|
|
||||||
return handleMerge( merge_commits, 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
wxLogTrace( traceGit, "GIT_PULL_HANDLER::PerformPull() - Merge needs resolution" );
|
|
||||||
//TODO: handle merges when they need to be resolved
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::pair<std::string, std::vector<CommitDetails>>>&
|
const std::vector<std::pair<std::string, std::vector<CommitDetails>>>&
|
||||||
@ -212,384 +46,7 @@ GIT_PULL_HANDLER::GetFetchResults() const
|
|||||||
return m_fetchResults;
|
return m_fetchResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string GIT_PULL_HANDLER::getFirstLineFromCommitMessage( const std::string& aMessage )
|
|
||||||
{
|
|
||||||
if( aMessage.empty() )
|
|
||||||
return aMessage;
|
|
||||||
|
|
||||||
size_t firstLineEnd = aMessage.find_first_of( '\n' );
|
|
||||||
|
|
||||||
if( firstLineEnd != std::string::npos )
|
|
||||||
return aMessage.substr( 0, firstLineEnd );
|
|
||||||
|
|
||||||
return aMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::string GIT_PULL_HANDLER::getFormattedCommitDate( const git_time& aTime )
|
|
||||||
{
|
|
||||||
char dateBuffer[64];
|
|
||||||
time_t time = static_cast<time_t>( aTime.time );
|
|
||||||
struct tm timeInfo;
|
|
||||||
#ifdef _WIN32
|
|
||||||
localtime_s( &timeInfo, &time );
|
|
||||||
#else
|
|
||||||
gmtime_r( &time, &timeInfo );
|
|
||||||
#endif
|
|
||||||
strftime( dateBuffer, sizeof( dateBuffer ), "%Y-%b-%d %H:%M:%S", &timeInfo );
|
|
||||||
return dateBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PullResult GIT_PULL_HANDLER::handleFastForward()
|
|
||||||
{
|
|
||||||
git_reference* rawRef = nullptr;
|
|
||||||
|
|
||||||
// Get the current HEAD reference
|
|
||||||
if( git_repository_head( &rawRef, GetRepo() ) )
|
|
||||||
{
|
|
||||||
AddErrorString( _( "Could not get repository head" ) );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitReferencePtr headRef( rawRef );
|
|
||||||
|
|
||||||
git_oid updatedRefOid;
|
|
||||||
const char* currentBranchName = git_reference_name( rawRef );
|
|
||||||
const char* branch_shorthand = git_reference_shorthand( rawRef );
|
|
||||||
wxString remote_name = GetRemotename();
|
|
||||||
wxString remoteBranchName = wxString::Format( "refs/remotes/%s/%s",
|
|
||||||
remote_name, branch_shorthand );
|
|
||||||
|
|
||||||
// Get the OID of the updated reference (remote-tracking branch)
|
|
||||||
if( git_reference_name_to_id( &updatedRefOid, GetRepo(), remoteBranchName.c_str() ) != GIT_OK )
|
|
||||||
{
|
|
||||||
AddErrorString( wxString::Format( _( "Could not get reference OID for reference '%s'" ),
|
|
||||||
remoteBranchName ) );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the target commit object
|
|
||||||
git_commit* targetCommit = nullptr;
|
|
||||||
|
|
||||||
if( git_commit_lookup( &targetCommit, GetRepo(), &updatedRefOid ) != GIT_OK )
|
|
||||||
{
|
|
||||||
AddErrorString( _( "Could not look up target commit" ) );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitCommitPtr targetCommitPtr( targetCommit );
|
|
||||||
|
|
||||||
// Get the tree from the target commit
|
|
||||||
git_tree* targetTree = nullptr;
|
|
||||||
|
|
||||||
if( git_commit_tree( &targetTree, targetCommit ) != GIT_OK )
|
|
||||||
{
|
|
||||||
git_commit_free( targetCommit );
|
|
||||||
AddErrorString( _( "Could not get tree from target commit" ) );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitTreePtr targetTreePtr( targetTree );
|
|
||||||
|
|
||||||
// Perform a checkout to update the working directory
|
|
||||||
git_checkout_options checkoutOptions;
|
|
||||||
git_checkout_init_options( &checkoutOptions, GIT_CHECKOUT_OPTIONS_VERSION );
|
|
||||||
auto notify_cb = []( git_checkout_notify_t why, const char* path, const git_diff_file* baseline,
|
|
||||||
const git_diff_file* target, const git_diff_file* workdir, void* payload ) -> int
|
|
||||||
{
|
|
||||||
switch( why )
|
|
||||||
{
|
|
||||||
case GIT_CHECKOUT_NOTIFY_CONFLICT:
|
|
||||||
wxLogTrace( traceGit, "Checkout conflict: %s", path ? path : "unknown" );
|
|
||||||
break;
|
|
||||||
case GIT_CHECKOUT_NOTIFY_DIRTY:
|
|
||||||
wxLogTrace( traceGit, "Checkout dirty: %s", path ? path : "unknown" );
|
|
||||||
break;
|
|
||||||
case GIT_CHECKOUT_NOTIFY_UPDATED:
|
|
||||||
wxLogTrace( traceGit, "Checkout updated: %s", path ? path : "unknown" );
|
|
||||||
break;
|
|
||||||
case GIT_CHECKOUT_NOTIFY_UNTRACKED:
|
|
||||||
wxLogTrace( traceGit, "Checkout untracked: %s", path ? path : "unknown" );
|
|
||||||
break;
|
|
||||||
case GIT_CHECKOUT_NOTIFY_IGNORED:
|
|
||||||
wxLogTrace( traceGit, "Checkout ignored: %s", path ? path : "unknown" );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
checkoutOptions.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_ALLOW_CONFLICTS;
|
|
||||||
checkoutOptions.notify_flags = GIT_CHECKOUT_NOTIFY_ALL;
|
|
||||||
checkoutOptions.notify_cb = notify_cb;
|
|
||||||
|
|
||||||
if( git_checkout_tree( GetRepo(), reinterpret_cast<git_object*>( targetTree ), &checkoutOptions ) != GIT_OK )
|
|
||||||
{
|
|
||||||
AddErrorString( _( "Failed to perform checkout operation." ) );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
git_reference* updatedRef = nullptr;
|
|
||||||
|
|
||||||
// Update the current branch to point to the new commit
|
|
||||||
if (git_reference_set_target(&updatedRef, rawRef, &updatedRefOid, nullptr) != GIT_OK)
|
|
||||||
{
|
|
||||||
AddErrorString( wxString::Format( _( "Failed to update reference '%s' to point to '%s'" ), currentBranchName,
|
|
||||||
git_oid_tostr_s( &updatedRefOid ) ) );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitReferencePtr updatedRefPtr( updatedRef );
|
|
||||||
|
|
||||||
// Clean up the repository state
|
|
||||||
if( git_repository_state_cleanup( GetRepo() ) != GIT_OK )
|
|
||||||
{
|
|
||||||
AddErrorString( _( "Failed to clean up repository state after fast-forward." ) );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
git_revwalk* revWalker = nullptr;
|
|
||||||
|
|
||||||
// Collect commit details for updated references
|
|
||||||
if( git_revwalk_new( &revWalker, GetRepo() ) != GIT_OK )
|
|
||||||
{
|
|
||||||
AddErrorString( _( "Failed to initialize revision walker." ) );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitRevWalkPtr revWalkerPtr( revWalker );
|
|
||||||
git_revwalk_sorting( revWalker, GIT_SORT_TIME );
|
|
||||||
|
|
||||||
if( git_revwalk_push_glob( revWalker, currentBranchName ) != GIT_OK )
|
|
||||||
{
|
|
||||||
AddErrorString( _( "Failed to push reference to revision walker." ) );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<std::string, std::vector<CommitDetails>>& branchCommits = m_fetchResults.emplace_back();
|
|
||||||
branchCommits.first = currentBranchName;
|
|
||||||
|
|
||||||
git_oid commitOid;
|
|
||||||
|
|
||||||
while( git_revwalk_next( &commitOid, revWalker ) == GIT_OK )
|
|
||||||
{
|
|
||||||
git_commit* commit = nullptr;
|
|
||||||
|
|
||||||
if( git_commit_lookup( &commit, GetRepo(), &commitOid ) )
|
|
||||||
{
|
|
||||||
AddErrorString( wxString::Format( _( "Could not lookup commit '%s'" ),
|
|
||||||
git_oid_tostr_s( &commitOid ) ) );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitCommitPtr commitPtr( commit );
|
|
||||||
|
|
||||||
CommitDetails details;
|
|
||||||
details.m_sha = git_oid_tostr_s( &commitOid );
|
|
||||||
details.m_firstLine = getFirstLineFromCommitMessage( git_commit_message( commit ) );
|
|
||||||
details.m_author = git_commit_author( commit )->name;
|
|
||||||
details.m_date = getFormattedCommitDate( git_commit_author( commit )->when );
|
|
||||||
|
|
||||||
branchCommits.second.push_back( details );
|
|
||||||
}
|
|
||||||
|
|
||||||
return PullResult::FastForward;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PullResult GIT_PULL_HANDLER::handleMerge( const git_annotated_commit** aMergeHeads,
|
|
||||||
size_t aMergeHeadsCount )
|
|
||||||
{
|
|
||||||
git_merge_options merge_opts;
|
|
||||||
git_merge_options_init( &merge_opts, GIT_MERGE_OPTIONS_VERSION );
|
|
||||||
|
|
||||||
git_checkout_options checkout_opts;
|
|
||||||
git_checkout_init_options( &checkout_opts, GIT_CHECKOUT_OPTIONS_VERSION );
|
|
||||||
|
|
||||||
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
|
|
||||||
|
|
||||||
if( git_merge( GetRepo(), aMergeHeads, aMergeHeadsCount, &merge_opts, &checkout_opts ) )
|
|
||||||
{
|
|
||||||
AddErrorString( _( "Could not merge commits" ) );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the repository index
|
|
||||||
git_index* index = nullptr;
|
|
||||||
|
|
||||||
if( git_repository_index( &index, GetRepo() ) )
|
|
||||||
{
|
|
||||||
AddErrorString( _( "Could not get repository index" ) );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitIndexPtr indexPtr( index );
|
|
||||||
|
|
||||||
// Check for conflicts
|
|
||||||
git_index_conflict_iterator* conflicts = nullptr;
|
|
||||||
|
|
||||||
if( git_index_conflict_iterator_new( &conflicts, index ) )
|
|
||||||
{
|
|
||||||
AddErrorString( _( "Could not get conflict iterator" ) );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitIndexConflictIteratorPtr conflictsPtr( conflicts );
|
|
||||||
|
|
||||||
const git_index_entry* ancestor = nullptr;
|
|
||||||
const git_index_entry* our = nullptr;
|
|
||||||
const git_index_entry* their = nullptr;
|
|
||||||
std::vector<ConflictData> conflict_data;
|
|
||||||
|
|
||||||
while( git_index_conflict_next( &ancestor, &our, &their, conflicts ) == 0 )
|
|
||||||
{
|
|
||||||
// Case 3: Both files have changed
|
|
||||||
if( ancestor && our && their )
|
|
||||||
{
|
|
||||||
ConflictData conflict_datum;
|
|
||||||
conflict_datum.filename = our->path;
|
|
||||||
conflict_datum.our_oid = our->id;
|
|
||||||
conflict_datum.their_oid = their->id;
|
|
||||||
conflict_datum.our_commit_time = our->mtime.seconds;
|
|
||||||
conflict_datum.their_commit_time = their->mtime.seconds;
|
|
||||||
conflict_datum.our_status = _( "Changed" );
|
|
||||||
conflict_datum.their_status = _( "Changed" );
|
|
||||||
conflict_datum.use_ours = true;
|
|
||||||
|
|
||||||
conflict_data.push_back( conflict_datum );
|
|
||||||
}
|
|
||||||
// Case 4: File added in both ours and theirs
|
|
||||||
else if( !ancestor && our && their )
|
|
||||||
{
|
|
||||||
ConflictData conflict_datum;
|
|
||||||
conflict_datum.filename = our->path;
|
|
||||||
conflict_datum.our_oid = our->id;
|
|
||||||
conflict_datum.their_oid = their->id;
|
|
||||||
conflict_datum.our_commit_time = our->mtime.seconds;
|
|
||||||
conflict_datum.their_commit_time = their->mtime.seconds;
|
|
||||||
conflict_datum.our_status = _( "Added" );
|
|
||||||
conflict_datum.their_status = _( "Added" );
|
|
||||||
conflict_datum.use_ours = true;
|
|
||||||
|
|
||||||
conflict_data.push_back( conflict_datum );
|
|
||||||
}
|
|
||||||
// Case 1: Remote file has changed or been added, local file has not
|
|
||||||
else if( their && !our )
|
|
||||||
{
|
|
||||||
// Accept their changes
|
|
||||||
git_index_add( index, their );
|
|
||||||
}
|
|
||||||
// Case 2: Local file has changed or been added, remote file has not
|
|
||||||
else if( our && !their )
|
|
||||||
{
|
|
||||||
// Accept our changes
|
|
||||||
git_index_add( index, our );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
wxLogError( wxS( "Unexpected conflict state" ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( conflict_data.empty() )
|
|
||||||
{
|
|
||||||
git_index_conflict_cleanup( index );
|
|
||||||
git_index_write( index );
|
|
||||||
}
|
|
||||||
|
|
||||||
return conflict_data.empty() ? PullResult::Success : PullResult::MergeFailed;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PullResult GIT_PULL_HANDLER::handleRebase( const git_annotated_commit** aMergeHeads, size_t aMergeHeadsCount )
|
|
||||||
{
|
|
||||||
// Get the current branch reference
|
|
||||||
git_reference* head_ref = nullptr;
|
|
||||||
|
|
||||||
if( git_repository_head( &head_ref, GetRepo() ) )
|
|
||||||
{
|
|
||||||
wxString errorMsg = KIGIT_COMMON::GetLastGitError();
|
|
||||||
wxLogTrace( traceGit, "GIT_PULL_HANDLER::handleRebase() - Failed to get HEAD: %s", errorMsg );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitReferencePtr headRefPtr(head_ref);
|
|
||||||
|
|
||||||
// Initialize rebase operation
|
|
||||||
git_rebase* rebase = nullptr;
|
|
||||||
git_rebase_options rebase_opts = GIT_REBASE_OPTIONS_INIT;
|
|
||||||
rebase_opts.checkout_options.checkout_strategy = GIT_CHECKOUT_SAFE;
|
|
||||||
|
|
||||||
if( git_rebase_init( &rebase, GetRepo(), nullptr, nullptr, aMergeHeads[0], &rebase_opts ) )
|
|
||||||
{
|
|
||||||
wxString errorMsg = KIGIT_COMMON::GetLastGitError();
|
|
||||||
wxLogTrace( traceGit, "GIT_PULL_HANDLER::handleRebase() - Failed to initialize rebase: %s", errorMsg );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitRebasePtr rebasePtr( rebase );
|
|
||||||
git_rebase_operation* operation = nullptr;
|
|
||||||
|
|
||||||
while( git_rebase_next( &operation, rebase ) != GIT_ITEROVER )
|
|
||||||
{
|
|
||||||
// Check for conflicts
|
|
||||||
git_index* index = nullptr;
|
|
||||||
if( git_repository_index( &index, GetRepo() ) )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "GIT_PULL_HANDLER::handleRebase() - Failed to get index: %s",
|
|
||||||
KIGIT_COMMON::GetLastGitError() );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
KIGIT::GitIndexPtr indexPtr( index );
|
|
||||||
|
|
||||||
if( git_index_has_conflicts( index ) )
|
|
||||||
{
|
|
||||||
// Abort the rebase if there are conflicts because we need to merge manually
|
|
||||||
git_rebase_abort( rebase );
|
|
||||||
AddErrorString( _( "Conflicts detected during rebase" ) );
|
|
||||||
return PullResult::MergeFailed;
|
|
||||||
}
|
|
||||||
|
|
||||||
git_oid commit_id;
|
|
||||||
git_signature* committer = nullptr;
|
|
||||||
|
|
||||||
if( git_signature_default( &committer, GetRepo() ) )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "GIT_PULL_HANDLER::handleRebase() - Failed to create signature: %s",
|
|
||||||
KIGIT_COMMON::GetLastGitError() );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitSignaturePtr committerPtr( committer );
|
|
||||||
|
|
||||||
if( git_rebase_commit( &commit_id, rebase, nullptr, committer, nullptr, nullptr ) != GIT_OK )
|
|
||||||
{
|
|
||||||
wxString errorMsg = KIGIT_COMMON::GetLastGitError();
|
|
||||||
wxLogTrace( traceGit, "GIT_PULL_HANDLER::handleRebase() - Failed to commit operation: %s", errorMsg );
|
|
||||||
git_rebase_abort( rebase );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finish the rebase
|
|
||||||
if( git_rebase_finish( rebase, nullptr ) )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "GIT_PULL_HANDLER::handleRebase() - Failed to finish rebase: %s",
|
|
||||||
KIGIT_COMMON::GetLastGitError() );
|
|
||||||
return PullResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxLogTrace( traceGit, "GIT_PULL_HANDLER::handleRebase() - Rebase completed successfully" );
|
|
||||||
git_repository_state_cleanup( GetRepo() );
|
|
||||||
return PullResult::Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void GIT_PULL_HANDLER::UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage )
|
void GIT_PULL_HANDLER::UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage )
|
||||||
{
|
{
|
||||||
|
ReportProgress( aCurrent, aTotal, aMessage );
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
#include <git2.h>
|
|
||||||
|
|
||||||
// Structure to store commit details
|
// Structure to store commit details
|
||||||
struct CommitDetails
|
struct CommitDetails
|
||||||
@ -50,22 +49,12 @@ enum class PullResult : int
|
|||||||
FastForward
|
FastForward
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ConflictData
|
class LIBGIT_BACKEND;
|
||||||
{
|
|
||||||
std::string filename;
|
|
||||||
std::string our_status;
|
|
||||||
std::string their_status;
|
|
||||||
git_oid our_oid;
|
|
||||||
git_oid their_oid;
|
|
||||||
git_time_t our_commit_time;
|
|
||||||
git_time_t their_commit_time;
|
|
||||||
bool use_ours; // Flag indicating user's choice (true = ours, false = theirs)
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class GIT_PULL_HANDLER : public KIGIT_REPO_MIXIN
|
class GIT_PULL_HANDLER : public KIGIT_REPO_MIXIN
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
friend class LIBGIT_BACKEND;
|
||||||
GIT_PULL_HANDLER( KIGIT_COMMON* aCommon );
|
GIT_PULL_HANDLER( KIGIT_COMMON* aCommon );
|
||||||
~GIT_PULL_HANDLER();
|
~GIT_PULL_HANDLER();
|
||||||
|
|
||||||
@ -77,15 +66,8 @@ public:
|
|||||||
// Implementation for progress updates
|
// Implementation for progress updates
|
||||||
void UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage ) override;
|
void UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage ) override;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::pair<std::string, std::vector<CommitDetails>>> m_fetchResults;
|
std::vector<std::pair<std::string, std::vector<CommitDetails>>> m_fetchResults;
|
||||||
|
|
||||||
std::string getFirstLineFromCommitMessage( const std::string& aMessage );
|
|
||||||
std::string getFormattedCommitDate( const git_time& aTime );
|
|
||||||
PullResult handleFastForward();
|
|
||||||
PullResult handleMerge( const git_annotated_commit** aMergeHeads, size_t aMergeHeadsCount );
|
|
||||||
PullResult handleRebase( const git_annotated_commit** aMergeHeads, size_t aMergeHeadsCount );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _GIT_PULL_HANDLER_H_
|
#endif // _GIT_PULL_HANDLER_H_
|
||||||
|
@ -22,13 +22,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "git_push_handler.h"
|
#include "git_push_handler.h"
|
||||||
#include <git/kicad_git_common.h>
|
|
||||||
#include <git/kicad_git_memory.h>
|
|
||||||
#include <trace_helpers.h>
|
#include <trace_helpers.h>
|
||||||
|
#include "git_backend.h"
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <wx/log.h>
|
|
||||||
|
|
||||||
GIT_PUSH_HANDLER::GIT_PUSH_HANDLER( KIGIT_COMMON* aRepo ) : KIGIT_REPO_MIXIN( aRepo )
|
GIT_PUSH_HANDLER::GIT_PUSH_HANDLER( KIGIT_COMMON* aRepo ) : KIGIT_REPO_MIXIN( aRepo )
|
||||||
{}
|
{}
|
||||||
@ -38,79 +33,7 @@ GIT_PUSH_HANDLER::~GIT_PUSH_HANDLER()
|
|||||||
|
|
||||||
PushResult GIT_PUSH_HANDLER::PerformPush()
|
PushResult GIT_PUSH_HANDLER::PerformPush()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock( GetCommon()->m_gitActionMutex, std::try_to_lock );
|
return GetGitBackend()->Push( this );
|
||||||
|
|
||||||
if(!lock.owns_lock())
|
|
||||||
{
|
|
||||||
wxLogTrace(traceGit, "GIT_PUSH_HANDLER::PerformPush: Could not lock mutex");
|
|
||||||
return PushResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
PushResult result = PushResult::Success;
|
|
||||||
|
|
||||||
// Fetch updates from remote repository
|
|
||||||
git_remote* remote = nullptr;
|
|
||||||
|
|
||||||
if(git_remote_lookup(&remote, GetRepo(), "origin") != 0)
|
|
||||||
{
|
|
||||||
AddErrorString(_("Could not lookup remote"));
|
|
||||||
return PushResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitRemotePtr remotePtr(remote);
|
|
||||||
|
|
||||||
git_remote_callbacks remoteCallbacks;
|
|
||||||
git_remote_init_callbacks(&remoteCallbacks, GIT_REMOTE_CALLBACKS_VERSION);
|
|
||||||
remoteCallbacks.sideband_progress = progress_cb;
|
|
||||||
remoteCallbacks.transfer_progress = transfer_progress_cb;
|
|
||||||
remoteCallbacks.update_tips = update_cb;
|
|
||||||
remoteCallbacks.push_transfer_progress = push_transfer_progress_cb;
|
|
||||||
remoteCallbacks.credentials = credentials_cb;
|
|
||||||
remoteCallbacks.payload = this;
|
|
||||||
GetCommon()->SetCancelled( false );
|
|
||||||
|
|
||||||
TestedTypes() = 0;
|
|
||||||
ResetNextKey();
|
|
||||||
|
|
||||||
if( git_remote_connect( remote, GIT_DIRECTION_PUSH, &remoteCallbacks, nullptr, nullptr ) )
|
|
||||||
{
|
|
||||||
AddErrorString( wxString::Format( _( "Could not connect to remote: %s" ),
|
|
||||||
KIGIT_COMMON::GetLastGitError() ) );
|
|
||||||
return PushResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
git_push_options pushOptions;
|
|
||||||
git_push_init_options( &pushOptions, GIT_PUSH_OPTIONS_VERSION );
|
|
||||||
pushOptions.callbacks = remoteCallbacks;
|
|
||||||
|
|
||||||
// Get the current HEAD reference
|
|
||||||
git_reference* head = nullptr;
|
|
||||||
|
|
||||||
if( git_repository_head( &head, GetRepo() ) != 0 )
|
|
||||||
{
|
|
||||||
git_remote_disconnect( remote );
|
|
||||||
AddErrorString( _( "Could not get repository head" ) );
|
|
||||||
return PushResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitReferencePtr headPtr( head );
|
|
||||||
|
|
||||||
// Create refspec for current branch
|
|
||||||
const char* refs[1];
|
|
||||||
refs[0] = git_reference_name( head );
|
|
||||||
const git_strarray refspecs = { (char**) refs, 1 };
|
|
||||||
|
|
||||||
if( git_remote_push( remote, &refspecs, &pushOptions ) )
|
|
||||||
{
|
|
||||||
AddErrorString( wxString::Format( _( "Could not push to remote: %s" ),
|
|
||||||
KIGIT_COMMON::GetLastGitError() ) );
|
|
||||||
git_remote_disconnect( remote );
|
|
||||||
return PushResult::Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
git_remote_disconnect( remote );
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,15 +21,14 @@
|
|||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <wx/string.h>
|
#include "git_remove_from_index_handler.h"
|
||||||
|
#include "git_backend.h"
|
||||||
|
|
||||||
#include <wx/log.h>
|
#include <wx/log.h>
|
||||||
|
|
||||||
#include <git/kicad_git_memory.h>
|
GIT_REMOVE_FROM_INDEX_HANDLER::GIT_REMOVE_FROM_INDEX_HANDLER( git_repository* aRepository ) :
|
||||||
#include "git_remove_from_index_handler.h"
|
KIGIT_COMMON( aRepository )
|
||||||
|
|
||||||
GIT_REMOVE_FROM_INDEX_HANDLER::GIT_REMOVE_FROM_INDEX_HANDLER( git_repository* aRepository )
|
|
||||||
{
|
{
|
||||||
m_repository = aRepository;
|
|
||||||
m_filesToRemove.clear();
|
m_filesToRemove.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,61 +40,11 @@ GIT_REMOVE_FROM_INDEX_HANDLER::~GIT_REMOVE_FROM_INDEX_HANDLER()
|
|||||||
|
|
||||||
bool GIT_REMOVE_FROM_INDEX_HANDLER::RemoveFromIndex( const wxString& aFilePath )
|
bool GIT_REMOVE_FROM_INDEX_HANDLER::RemoveFromIndex( const wxString& aFilePath )
|
||||||
{
|
{
|
||||||
// Test if file is currently in the index
|
return GetGitBackend()->RemoveFromIndex( this, aFilePath );
|
||||||
|
|
||||||
git_index* index = nullptr;
|
|
||||||
size_t at_pos = 0;
|
|
||||||
|
|
||||||
if( git_repository_index( &index, m_repository ) != 0 )
|
|
||||||
{
|
|
||||||
wxLogError( "Failed to get repository index" );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitIndexPtr indexPtr( index );
|
|
||||||
|
|
||||||
if( git_index_find( &at_pos, index, aFilePath.ToUTF8().data() ) != 0 )
|
|
||||||
{
|
|
||||||
wxLogError( "Failed to find index entry for %s", aFilePath );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_filesToRemove.push_back( aFilePath );
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GIT_REMOVE_FROM_INDEX_HANDLER::PerformRemoveFromIndex()
|
void GIT_REMOVE_FROM_INDEX_HANDLER::PerformRemoveFromIndex()
|
||||||
{
|
{
|
||||||
for( auto& file : m_filesToRemove )
|
GetGitBackend()->PerformRemoveFromIndex( this );
|
||||||
{
|
|
||||||
git_index* index = nullptr;
|
|
||||||
git_oid oid;
|
|
||||||
|
|
||||||
if( git_repository_index( &index, m_repository ) != 0 )
|
|
||||||
{
|
|
||||||
wxLogError( "Failed to get repository index" );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitIndexPtr indexPtr( index );
|
|
||||||
|
|
||||||
if( git_index_remove_bypath( index, file.ToUTF8().data() ) != 0 )
|
|
||||||
{
|
|
||||||
wxLogError( "Failed to remove index entry for %s", file );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( git_index_write( index ) != 0 )
|
|
||||||
{
|
|
||||||
wxLogError( "Failed to write index" );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( git_index_write_tree( &oid, index ) != 0 )
|
|
||||||
{
|
|
||||||
wxLogError( "Failed to write index tree" );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -24,12 +24,13 @@
|
|||||||
#ifndef GIT_REMOVE_FROM_INDEX_HANDLER_H_
|
#ifndef GIT_REMOVE_FROM_INDEX_HANDLER_H_
|
||||||
#define GIT_REMOVE_FROM_INDEX_HANDLER_H_
|
#define GIT_REMOVE_FROM_INDEX_HANDLER_H_
|
||||||
|
|
||||||
#include <git2.h>
|
#include <git/kicad_git_common.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <wx/string.h>
|
||||||
|
|
||||||
class wxString;
|
class LIBGIT_BACKEND;
|
||||||
|
|
||||||
class GIT_REMOVE_FROM_INDEX_HANDLER
|
class GIT_REMOVE_FROM_INDEX_HANDLER : public KIGIT_COMMON
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GIT_REMOVE_FROM_INDEX_HANDLER( git_repository* aRepository );
|
GIT_REMOVE_FROM_INDEX_HANDLER( git_repository* aRepository );
|
||||||
@ -41,7 +42,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
git_repository* m_repository;
|
friend class LIBGIT_BACKEND;
|
||||||
|
|
||||||
std::vector<wxString> m_filesToRemove;
|
std::vector<wxString> m_filesToRemove;
|
||||||
};
|
};
|
||||||
|
@ -22,11 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "git_revert_handler.h"
|
#include "git_revert_handler.h"
|
||||||
|
#include "git_backend.h"
|
||||||
#include <wx/log.h>
|
|
||||||
#include <wx/string.h>
|
|
||||||
|
|
||||||
#include <trace_helpers.h>
|
|
||||||
|
|
||||||
|
|
||||||
GIT_REVERT_HANDLER::GIT_REVERT_HANDLER( git_repository* aRepository )
|
GIT_REVERT_HANDLER::GIT_REVERT_HANDLER( git_repository* aRepository )
|
||||||
@ -46,74 +42,8 @@ bool GIT_REVERT_HANDLER::Revert( const wxString& aFilePath )
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void checkout_progress_cb( const char *path, size_t cur, size_t tot, void *payload )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, wxS( "checkout_progress_cb: %s %zu/%zu" ), path, cur, tot );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int checkout_notify_cb( git_checkout_notify_t why, const char *path,
|
|
||||||
const git_diff_file *baseline,
|
|
||||||
const git_diff_file *target,
|
|
||||||
const git_diff_file *workdir, void *payload )
|
|
||||||
{
|
|
||||||
GIT_REVERT_HANDLER* handler = static_cast<GIT_REVERT_HANDLER*>(payload);
|
|
||||||
|
|
||||||
if( why & ( GIT_CHECKOUT_NOTIFY_CONFLICT | GIT_CHECKOUT_NOTIFY_IGNORED
|
|
||||||
| GIT_CHECKOUT_NOTIFY_UPDATED ) )
|
|
||||||
handler->PushFailedFile( path );
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void GIT_REVERT_HANDLER::PerformRevert()
|
void GIT_REVERT_HANDLER::PerformRevert()
|
||||||
{
|
{
|
||||||
git_object* head_commit = NULL;
|
GetGitBackend()->PerformRevert( this );
|
||||||
git_checkout_options opts;
|
|
||||||
git_checkout_init_options( &opts, GIT_CHECKOUT_OPTIONS_VERSION );
|
|
||||||
|
|
||||||
// Get the HEAD commit
|
|
||||||
if( git_revparse_single( &head_commit, m_repository, "HEAD" ) != 0 )
|
|
||||||
{
|
|
||||||
// Handle error. If we cannot get the HEAD, then there's no point proceeding.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
|
||||||
char** paths = new char*[m_filesToRevert.size()];
|
|
||||||
|
|
||||||
for( size_t ii = 0; ii < m_filesToRevert.size(); ii++ )
|
|
||||||
{
|
|
||||||
// Set paths to the specific file
|
|
||||||
paths[ii] = wxStrdup( m_filesToRevert[ii].ToUTF8() );
|
|
||||||
}
|
|
||||||
|
|
||||||
git_strarray arr = { paths, m_filesToRevert.size() };
|
|
||||||
|
|
||||||
opts.paths = arr;
|
|
||||||
opts.progress_cb = checkout_progress_cb;
|
|
||||||
opts.notify_cb = checkout_notify_cb;
|
|
||||||
opts.notify_payload = static_cast<void*>( this );
|
|
||||||
|
|
||||||
// Attempt to checkout the file(s)
|
|
||||||
if( git_checkout_tree(m_repository, head_commit, &opts ) != 0 )
|
|
||||||
{
|
|
||||||
const git_error *e = git_error_last();
|
|
||||||
|
|
||||||
if( e )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, wxS( "Checkout failed: %d: %s" ), e->klass, e->message );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free the HEAD commit
|
|
||||||
for( size_t ii = 0; ii < m_filesToRevert.size(); ii++ )
|
|
||||||
delete( paths[ii] );
|
|
||||||
|
|
||||||
delete[] paths;
|
|
||||||
|
|
||||||
git_object_free( head_commit );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,10 @@
|
|||||||
#include <git2.h>
|
#include <git2.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
|
// TEMPORARY HACKFIX INCLUDE FOR STD::VECTOR EXPORT OUT OF KICOMMON ON WINDOWS
|
||||||
|
#include <settings/parameters.h>
|
||||||
|
|
||||||
|
class LIBGIT_BACKEND;
|
||||||
|
|
||||||
class GIT_REVERT_HANDLER
|
class GIT_REVERT_HANDLER
|
||||||
{
|
{
|
||||||
@ -44,6 +48,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class LIBGIT_BACKEND;
|
||||||
git_repository* m_repository;
|
git_repository* m_repository;
|
||||||
|
|
||||||
std::vector<wxString> m_filesToRevert;
|
std::vector<wxString> m_filesToRevert;
|
||||||
|
@ -22,10 +22,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "git_status_handler.h"
|
#include "git_status_handler.h"
|
||||||
#include <git/kicad_git_common.h>
|
|
||||||
#include <git/kicad_git_memory.h>
|
|
||||||
#include <trace_helpers.h>
|
#include <trace_helpers.h>
|
||||||
#include <wx/log.h>
|
#include "git_backend.h"
|
||||||
|
|
||||||
GIT_STATUS_HANDLER::GIT_STATUS_HANDLER( KIGIT_COMMON* aCommon ) : KIGIT_REPO_MIXIN( aCommon )
|
GIT_STATUS_HANDLER::GIT_STATUS_HANDLER( KIGIT_COMMON* aCommon ) : KIGIT_REPO_MIXIN( aCommon )
|
||||||
{}
|
{}
|
||||||
@ -35,171 +33,29 @@ GIT_STATUS_HANDLER::~GIT_STATUS_HANDLER()
|
|||||||
|
|
||||||
bool GIT_STATUS_HANDLER::HasChangedFiles()
|
bool GIT_STATUS_HANDLER::HasChangedFiles()
|
||||||
{
|
{
|
||||||
git_repository* repo = GetRepo();
|
return GetGitBackend()->HasChangedFiles( this );
|
||||||
|
|
||||||
if( !repo )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
git_status_options opts;
|
|
||||||
git_status_init_options( &opts, GIT_STATUS_OPTIONS_VERSION );
|
|
||||||
|
|
||||||
opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
|
|
||||||
opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX
|
|
||||||
| GIT_STATUS_OPT_SORT_CASE_SENSITIVELY;
|
|
||||||
|
|
||||||
git_status_list* status_list = nullptr;
|
|
||||||
|
|
||||||
if( git_status_list_new( &status_list, repo, &opts ) != GIT_OK )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "Failed to get status list: %s", KIGIT_COMMON::GetLastGitError() );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitStatusListPtr status_list_ptr( status_list );
|
|
||||||
bool hasChanges = ( git_status_list_entrycount( status_list ) > 0 );
|
|
||||||
|
|
||||||
return hasChanges;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<wxString, FileStatus> GIT_STATUS_HANDLER::GetFileStatus( const wxString& aPathspec )
|
std::map<wxString, FileStatus> GIT_STATUS_HANDLER::GetFileStatus( const wxString& aPathspec )
|
||||||
{
|
{
|
||||||
std::map<wxString, FileStatus> fileStatusMap;
|
return GetGitBackend()->GetFileStatus( this, aPathspec );
|
||||||
git_repository* repo = GetRepo();
|
|
||||||
|
|
||||||
if( !repo )
|
|
||||||
return fileStatusMap;
|
|
||||||
|
|
||||||
git_status_options status_options;
|
|
||||||
git_status_init_options( &status_options, GIT_STATUS_OPTIONS_VERSION );
|
|
||||||
status_options.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
|
|
||||||
status_options.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_INCLUDE_UNMODIFIED;
|
|
||||||
|
|
||||||
// Set up pathspec if provided
|
|
||||||
std::string pathspec_str;
|
|
||||||
std::vector<const char*> pathspec_ptrs;
|
|
||||||
|
|
||||||
if( !aPathspec.IsEmpty() )
|
|
||||||
{
|
|
||||||
pathspec_str = aPathspec.ToStdString();
|
|
||||||
pathspec_ptrs.push_back( pathspec_str.c_str() );
|
|
||||||
|
|
||||||
status_options.pathspec.strings = const_cast<char**>( pathspec_ptrs.data() );
|
|
||||||
status_options.pathspec.count = pathspec_ptrs.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
git_status_list* status_list = nullptr;
|
|
||||||
|
|
||||||
if( git_status_list_new( &status_list, repo, &status_options ) != GIT_OK )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "Failed to get git status list: %s", KIGIT_COMMON::GetLastGitError() );
|
|
||||||
return fileStatusMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitStatusListPtr statusListPtr( status_list );
|
|
||||||
|
|
||||||
size_t count = git_status_list_entrycount( status_list );
|
|
||||||
wxString repoWorkDir( git_repository_workdir( repo ) );
|
|
||||||
|
|
||||||
for( size_t ii = 0; ii < count; ++ii )
|
|
||||||
{
|
|
||||||
const git_status_entry* entry = git_status_byindex( status_list, ii );
|
|
||||||
std::string path( entry->head_to_index ? entry->head_to_index->old_file.path
|
|
||||||
: entry->index_to_workdir->old_file.path );
|
|
||||||
|
|
||||||
wxString absPath = repoWorkDir + path;
|
|
||||||
|
|
||||||
FileStatus fileStatus;
|
|
||||||
fileStatus.filePath = absPath;
|
|
||||||
fileStatus.gitStatus = entry->status;
|
|
||||||
fileStatus.status = ConvertStatus( entry->status );
|
|
||||||
|
|
||||||
fileStatusMap[absPath] = fileStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fileStatusMap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString GIT_STATUS_HANDLER::GetCurrentBranchName()
|
wxString GIT_STATUS_HANDLER::GetCurrentBranchName()
|
||||||
{
|
{
|
||||||
git_repository* repo = GetRepo();
|
return GetGitBackend()->GetCurrentBranchName( this );
|
||||||
|
|
||||||
if( !repo )
|
|
||||||
return wxEmptyString;
|
|
||||||
|
|
||||||
git_reference* currentBranchReference = nullptr;
|
|
||||||
int rc = git_repository_head( ¤tBranchReference, repo );
|
|
||||||
KIGIT::GitReferencePtr currentBranchReferencePtr( currentBranchReference );
|
|
||||||
|
|
||||||
if( currentBranchReference )
|
|
||||||
{
|
|
||||||
return git_reference_shorthand( currentBranchReference );
|
|
||||||
}
|
|
||||||
else if( rc == GIT_EUNBORNBRANCH )
|
|
||||||
{
|
|
||||||
// Unborn branch - could return empty or a default name
|
|
||||||
return wxEmptyString;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "Failed to lookup current branch: %s", KIGIT_COMMON::GetLastGitError() );
|
|
||||||
return wxEmptyString;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GIT_STATUS_HANDLER::UpdateRemoteStatus( const std::set<wxString>& aLocalChanges,
|
void GIT_STATUS_HANDLER::UpdateRemoteStatus( const std::set<wxString>& aLocalChanges,
|
||||||
const std::set<wxString>& aRemoteChanges,
|
const std::set<wxString>& aRemoteChanges,
|
||||||
std::map<wxString, FileStatus>& aFileStatus )
|
std::map<wxString, FileStatus>& aFileStatus )
|
||||||
{
|
{
|
||||||
git_repository* repo = GetRepo();
|
GetGitBackend()->UpdateRemoteStatus( this, aLocalChanges, aRemoteChanges, aFileStatus );
|
||||||
|
|
||||||
if( !repo )
|
|
||||||
return;
|
|
||||||
|
|
||||||
wxString repoWorkDir( git_repository_workdir( repo ) );
|
|
||||||
|
|
||||||
// Update status based on local/remote changes
|
|
||||||
for( auto& [absPath, fileStatus] : aFileStatus )
|
|
||||||
{
|
|
||||||
// Convert absolute path to relative path for comparison
|
|
||||||
wxString relativePath = absPath;
|
|
||||||
if( relativePath.StartsWith( repoWorkDir ) )
|
|
||||||
{
|
|
||||||
relativePath = relativePath.Mid( repoWorkDir.length() );
|
|
||||||
#ifdef _WIN32
|
|
||||||
relativePath.Replace( wxS( "\\" ), wxS( "/" ) );
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string relativePathStd = relativePath.ToStdString();
|
|
||||||
|
|
||||||
// Only update if the file is not already modified/added/deleted
|
|
||||||
if( fileStatus.status == KIGIT_COMMON::GIT_STATUS::GIT_STATUS_CURRENT )
|
|
||||||
{
|
|
||||||
if( aLocalChanges.count( relativePathStd ) )
|
|
||||||
{
|
|
||||||
fileStatus.status = KIGIT_COMMON::GIT_STATUS::GIT_STATUS_AHEAD;
|
|
||||||
}
|
|
||||||
else if( aRemoteChanges.count( relativePathStd ) )
|
|
||||||
{
|
|
||||||
fileStatus.status = KIGIT_COMMON::GIT_STATUS::GIT_STATUS_BEHIND;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString GIT_STATUS_HANDLER::GetWorkingDirectory()
|
wxString GIT_STATUS_HANDLER::GetWorkingDirectory()
|
||||||
{
|
{
|
||||||
git_repository* repo = GetRepo();
|
return GetGitBackend()->GetWorkingDirectory( this );
|
||||||
|
|
||||||
if( !repo )
|
|
||||||
return wxEmptyString;
|
|
||||||
|
|
||||||
const char* workdir = git_repository_workdir( repo );
|
|
||||||
|
|
||||||
if( !workdir )
|
|
||||||
return wxEmptyString;
|
|
||||||
|
|
||||||
return wxString( workdir );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KIGIT_COMMON::GIT_STATUS GIT_STATUS_HANDLER::ConvertStatus( unsigned int aGitStatus )
|
KIGIT_COMMON::GIT_STATUS GIT_STATUS_HANDLER::ConvertStatus( unsigned int aGitStatus )
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
class LIBGIT_BACKEND;
|
||||||
|
|
||||||
struct FileStatus
|
struct FileStatus
|
||||||
{
|
{
|
||||||
wxString filePath;
|
wxString filePath;
|
||||||
@ -80,6 +82,7 @@ public:
|
|||||||
void UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage ) override;
|
void UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage ) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class LIBGIT_BACKEND;
|
||||||
/**
|
/**
|
||||||
* Convert git status flags to KIGIT_COMMON::GIT_STATUS
|
* Convert git status flags to KIGIT_COMMON::GIT_STATUS
|
||||||
* @param aGitStatus Raw git status flags
|
* @param aGitStatus Raw git status flags
|
||||||
|
@ -33,6 +33,8 @@
|
|||||||
|
|
||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
|
|
||||||
|
class LIBGIT_BACKEND;
|
||||||
|
|
||||||
class KIGIT_COMMON
|
class KIGIT_COMMON
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -174,6 +176,7 @@ protected:
|
|||||||
friend class GIT_PUSH_HANDLER;
|
friend class GIT_PUSH_HANDLER;
|
||||||
friend class GIT_PULL_HANDLER;
|
friend class GIT_PULL_HANDLER;
|
||||||
friend class GIT_CLONE_HANDLER;
|
friend class GIT_CLONE_HANDLER;
|
||||||
|
friend class LIBGIT_BACKEND;
|
||||||
friend class PROJECT_TREE_PANE;
|
friend class PROJECT_TREE_PANE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
1358
common/git/libgit_backend.cpp
Normal file
1358
common/git/libgit_backend.cpp
Normal file
File diff suppressed because it is too large
Load Diff
100
common/git/libgit_backend.h
Normal file
100
common/git/libgit_backend.h
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright The 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, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 3 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBGIT_BACKEND_H_
|
||||||
|
#define LIBGIT_BACKEND_H_
|
||||||
|
|
||||||
|
#include "git_backend.h"
|
||||||
|
|
||||||
|
// Forward declarations to avoid exposing libgit2 headers
|
||||||
|
struct git_annotated_commit;
|
||||||
|
|
||||||
|
class LIBGIT_BACKEND : public GIT_BACKEND
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Init() override;
|
||||||
|
void Shutdown() override;
|
||||||
|
bool IsLibraryAvailable() override;
|
||||||
|
|
||||||
|
bool Clone( GIT_CLONE_HANDLER* aHandler ) override;
|
||||||
|
|
||||||
|
CommitResult Commit( GIT_COMMIT_HANDLER* aHandler,
|
||||||
|
const std::vector<wxString>& aFiles,
|
||||||
|
const wxString& aMessage,
|
||||||
|
const wxString& aAuthorName,
|
||||||
|
const wxString& aAuthorEmail ) override;
|
||||||
|
|
||||||
|
PushResult Push( GIT_PUSH_HANDLER* aHandler ) override;
|
||||||
|
|
||||||
|
bool HasChangedFiles( GIT_STATUS_HANDLER* aHandler ) override;
|
||||||
|
|
||||||
|
std::map<wxString, FileStatus> GetFileStatus( GIT_STATUS_HANDLER* aHandler,
|
||||||
|
const wxString& aPathspec ) override;
|
||||||
|
|
||||||
|
wxString GetCurrentBranchName( GIT_STATUS_HANDLER* aHandler ) override;
|
||||||
|
|
||||||
|
void UpdateRemoteStatus( GIT_STATUS_HANDLER* aHandler,
|
||||||
|
const std::set<wxString>& aLocalChanges,
|
||||||
|
const std::set<wxString>& aRemoteChanges,
|
||||||
|
std::map<wxString, FileStatus>& aFileStatus ) override;
|
||||||
|
|
||||||
|
wxString GetWorkingDirectory( GIT_STATUS_HANDLER* aHandler ) override;
|
||||||
|
|
||||||
|
wxString GetWorkingDirectory( GIT_CONFIG_HANDLER* aHandler ) override;
|
||||||
|
bool GetConfigString( GIT_CONFIG_HANDLER* aHandler, const wxString& aKey,
|
||||||
|
wxString& aValue ) override;
|
||||||
|
|
||||||
|
bool IsRepository( GIT_INIT_HANDLER* aHandler, const wxString& aPath ) override;
|
||||||
|
InitResult InitializeRepository( GIT_INIT_HANDLER* aHandler, const wxString& aPath ) override;
|
||||||
|
bool SetupRemote( GIT_INIT_HANDLER* aHandler, const RemoteConfig& aConfig ) override;
|
||||||
|
|
||||||
|
BranchResult SwitchToBranch( GIT_BRANCH_HANDLER* aHandler, const wxString& aBranchName ) override;
|
||||||
|
bool BranchExists( GIT_BRANCH_HANDLER* aHandler, const wxString& aBranchName ) override;
|
||||||
|
|
||||||
|
bool PerformFetch( GIT_PULL_HANDLER* aHandler, bool aSkipLock ) override;
|
||||||
|
PullResult PerformPull( GIT_PULL_HANDLER* aHandler ) override;
|
||||||
|
|
||||||
|
void PerformRevert( GIT_REVERT_HANDLER* aHandler ) override;
|
||||||
|
|
||||||
|
git_repository* GetRepositoryForFile( const char* aFilename ) override;
|
||||||
|
int CreateBranch( git_repository* aRepo, const wxString& aBranchName ) override;
|
||||||
|
bool RemoveVCS( git_repository*& aRepo, const wxString& aProjectPath,
|
||||||
|
bool aRemoveGitDir, wxString* aErrors ) override;
|
||||||
|
|
||||||
|
bool AddToIndex( GIT_ADD_TO_INDEX_HANDLER* aHandler, const wxString& aFilePath ) override;
|
||||||
|
|
||||||
|
bool PerformAddToIndex( GIT_ADD_TO_INDEX_HANDLER* aHandler ) override;
|
||||||
|
|
||||||
|
bool RemoveFromIndex( GIT_REMOVE_FROM_INDEX_HANDLER* aHandler, const wxString& aFilePath ) override;
|
||||||
|
|
||||||
|
void PerformRemoveFromIndex( GIT_REMOVE_FROM_INDEX_HANDLER* aHandler ) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PullResult handleFastForward( GIT_PULL_HANDLER* aHandler );
|
||||||
|
PullResult handleMerge( GIT_PULL_HANDLER* aHandler, const git_annotated_commit** aMergeHeads,
|
||||||
|
size_t aMergeHeadsCount );
|
||||||
|
PullResult handleRebase( GIT_PULL_HANDLER* aHandler, const git_annotated_commit** aMergeHeads,
|
||||||
|
size_t aMergeHeadsCount );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -22,105 +22,25 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "project_git_utils.h"
|
#include "project_git_utils.h"
|
||||||
#include "kicad_git_common.h"
|
#include "git_backend.h"
|
||||||
#include "kicad_git_memory.h"
|
|
||||||
#include <git/kicad_git_compat.h>
|
|
||||||
#include <trace_helpers.h>
|
|
||||||
#include <wx/log.h>
|
|
||||||
#include <wx/filename.h>
|
|
||||||
#include <gestfich.h>
|
|
||||||
|
|
||||||
namespace KIGIT
|
namespace KIGIT
|
||||||
{
|
{
|
||||||
|
|
||||||
git_repository* PROJECT_GIT_UTILS::GetRepositoryForFile( const char* aFilename )
|
git_repository* PROJECT_GIT_UTILS::GetRepositoryForFile( const char* aFilename )
|
||||||
{
|
{
|
||||||
git_repository* repo = nullptr;
|
return GetGitBackend()->GetRepositoryForFile( aFilename );
|
||||||
git_buf repo_path = GIT_BUF_INIT;
|
|
||||||
|
|
||||||
if( git_repository_discover( &repo_path, aFilename, 0, nullptr ) != GIT_OK )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "Can't repo discover %s: %s", aFilename,
|
|
||||||
KIGIT_COMMON::GetLastGitError() );
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitBufPtr repo_path_ptr( &repo_path );
|
|
||||||
|
|
||||||
if( git_repository_open( &repo, repo_path.ptr ) != GIT_OK )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "Can't open repo for %s: %s", repo_path.ptr,
|
|
||||||
KIGIT_COMMON::GetLastGitError() );
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return repo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int PROJECT_GIT_UTILS::CreateBranch( git_repository* aRepo, const wxString& aBranchName )
|
int PROJECT_GIT_UTILS::CreateBranch( git_repository* aRepo, const wxString& aBranchName )
|
||||||
{
|
{
|
||||||
git_oid head_oid;
|
return GetGitBackend()->CreateBranch( aRepo, aBranchName );
|
||||||
|
|
||||||
if( int error = git_reference_name_to_id( &head_oid, aRepo, "HEAD" ); error != GIT_OK )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "Failed to lookup HEAD reference: %s",
|
|
||||||
KIGIT_COMMON::GetLastGitError() );
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
git_commit* commit = nullptr;
|
|
||||||
|
|
||||||
if( int error = git_commit_lookup( &commit, aRepo, &head_oid ); error != GIT_OK )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "Failed to lookup commit: %s",
|
|
||||||
KIGIT_COMMON::GetLastGitError() );
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
KIGIT::GitCommitPtr commitPtr( commit );
|
|
||||||
git_reference* branchRef = nullptr;
|
|
||||||
|
|
||||||
if( int error = git_branch_create( &branchRef, aRepo, aBranchName.mb_str(), commit, 0 ); error != GIT_OK )
|
|
||||||
{
|
|
||||||
wxLogTrace( traceGit, "Failed to create branch: %s",
|
|
||||||
KIGIT_COMMON::GetLastGitError() );
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
git_reference_free( branchRef );
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PROJECT_GIT_UTILS::RemoveVCS( git_repository*& aRepo, const wxString& aProjectPath,
|
bool PROJECT_GIT_UTILS::RemoveVCS( git_repository*& aRepo, const wxString& aProjectPath,
|
||||||
bool aRemoveGitDir, wxString* aErrors )
|
bool aRemoveGitDir, wxString* aErrors )
|
||||||
{
|
{
|
||||||
if( aRepo )
|
return GetGitBackend()->RemoveVCS( aRepo, aProjectPath, aRemoveGitDir, aErrors );
|
||||||
{
|
|
||||||
git_repository_free( aRepo );
|
|
||||||
aRepo = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( aRemoveGitDir )
|
|
||||||
{
|
|
||||||
wxFileName gitDir( aProjectPath, wxEmptyString );
|
|
||||||
gitDir.AppendDir( ".git" );
|
|
||||||
|
|
||||||
if( gitDir.DirExists() )
|
|
||||||
{
|
|
||||||
wxString errors;
|
|
||||||
if( !RmDirRecursive( gitDir.GetPath(), &errors ) )
|
|
||||||
{
|
|
||||||
if( aErrors )
|
|
||||||
*aErrors = errors;
|
|
||||||
|
|
||||||
wxLogTrace( traceGit, "Failed to remove .git directory: %s", errors );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wxLogTrace( traceGit, "Successfully removed VCS from project" );
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace KIGIT
|
} // namespace KIGIT
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include <trigo.h>
|
#include <trigo.h>
|
||||||
#include <math/util.h> // for KiROUND
|
#include <math/util.h> // for KiROUND
|
||||||
#include <font/font.h>
|
#include <font/font.h>
|
||||||
|
#include <text_eval/text_eval_wrapper.h>
|
||||||
|
|
||||||
#include <callback_gal.h>
|
#include <callback_gal.h>
|
||||||
|
|
||||||
@ -100,8 +101,15 @@ int GRTextWidth( const wxString& aText, KIFONT::FONT* aFont, const VECTOR2I& aSi
|
|||||||
{
|
{
|
||||||
if( !aFont )
|
if( !aFont )
|
||||||
aFont = KIFONT::FONT::GetFont();
|
aFont = KIFONT::FONT::GetFont();
|
||||||
|
wxString evaluated( aText );
|
||||||
|
|
||||||
return KiROUND( aFont->StringBoundaryLimits( aText, aSize, aThickness, aBold, aItalic,
|
if( evaluated.Contains( wxS( "@{" ) ) )
|
||||||
|
{
|
||||||
|
EXPRESSION_EVALUATOR evaluator;
|
||||||
|
evaluated = evaluator.Evaluate( evaluated );
|
||||||
|
}
|
||||||
|
|
||||||
|
return KiROUND( aFont->StringBoundaryLimits( evaluated, aSize, aThickness, aBold, aItalic,
|
||||||
aFontMetrics ).x );
|
aFontMetrics ).x );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,6 +122,13 @@ void GRPrintText( wxDC* aDC, const VECTOR2I& aPos, const COLOR4D& aColor, const
|
|||||||
{
|
{
|
||||||
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
|
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
|
||||||
bool fill_mode = true;
|
bool fill_mode = true;
|
||||||
|
wxString evaluatedText( aText );
|
||||||
|
|
||||||
|
if( evaluatedText.Contains( wxS( "@{" ) ) )
|
||||||
|
{
|
||||||
|
EXPRESSION_EVALUATOR evaluator;
|
||||||
|
evaluatedText = evaluator.Evaluate( evaluatedText );
|
||||||
|
}
|
||||||
|
|
||||||
if( !aFont )
|
if( !aFont )
|
||||||
aFont = KIFONT::FONT::GetFont();
|
aFont = KIFONT::FONT::GetFont();
|
||||||
@ -156,7 +171,7 @@ void GRPrintText( wxDC* aDC, const VECTOR2I& aPos, const COLOR4D& aColor, const
|
|||||||
attributes.m_Valign = aV_justify;
|
attributes.m_Valign = aV_justify;
|
||||||
attributes.m_Size = aSize;
|
attributes.m_Size = aSize;
|
||||||
|
|
||||||
aFont->Draw( &callback_gal, aText, aPos, attributes, aFontMetrics );
|
aFont->Draw( &callback_gal, evaluatedText, aPos, attributes, aFontMetrics );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#include <wx/txtstrm.h>
|
#include <wx/txtstrm.h>
|
||||||
#include <wx/wfstream.h>
|
#include <wx/wfstream.h>
|
||||||
#include <tool/tool_action.h>
|
#include <tool/tool_action.h>
|
||||||
|
#include <tool/tool_event.h>
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -159,6 +160,10 @@ static struct hotkey_name_descr hotkeyNameList[] =
|
|||||||
#define MODIFIER_CMD_MAC wxT( "Cmd+" )
|
#define MODIFIER_CMD_MAC wxT( "Cmd+" )
|
||||||
#define MODIFIER_CTRL_BASE wxT( "Ctrl+" )
|
#define MODIFIER_CTRL_BASE wxT( "Ctrl+" )
|
||||||
#define MODIFIER_SHIFT wxT( "Shift+" )
|
#define MODIFIER_SHIFT wxT( "Shift+" )
|
||||||
|
#define MODIFIER_META wxT( "Meta+" )
|
||||||
|
#define MODIFIER_WIN wxT( "Win+" )
|
||||||
|
#define MODIFIER_SUPER wxT( "Super+" )
|
||||||
|
#define MODIFIER_ALTGR wxT( "AltGr+" )
|
||||||
|
|
||||||
|
|
||||||
wxString KeyNameFromKeyCode( int aKeycode, bool* aIsFound )
|
wxString KeyNameFromKeyCode( int aKeycode, bool* aIsFound )
|
||||||
@ -175,6 +180,14 @@ wxString KeyNameFromKeyCode( int aKeycode, bool* aIsFound )
|
|||||||
return wxString( MODIFIER_SHIFT ).BeforeFirst( '+' );
|
return wxString( MODIFIER_SHIFT ).BeforeFirst( '+' );
|
||||||
else if( aKeycode == WXK_ALT )
|
else if( aKeycode == WXK_ALT )
|
||||||
return wxString( MODIFIER_ALT ).BeforeFirst( '+' );
|
return wxString( MODIFIER_ALT ).BeforeFirst( '+' );
|
||||||
|
#ifdef WXK_WINDOWS_LEFT
|
||||||
|
else if( aKeycode == WXK_WINDOWS_LEFT || aKeycode == WXK_WINDOWS_RIGHT )
|
||||||
|
return wxString( MODIFIER_WIN ).BeforeFirst( '+' );
|
||||||
|
#endif
|
||||||
|
#ifdef WXK_META
|
||||||
|
else if( aKeycode == WXK_META )
|
||||||
|
return wxString( MODIFIER_META ).BeforeFirst( '+' );
|
||||||
|
#endif
|
||||||
|
|
||||||
// Assume keycode of 0 is "unassigned"
|
// Assume keycode of 0 is "unassigned"
|
||||||
if( (aKeycode & MD_CTRL) != 0 )
|
if( (aKeycode & MD_CTRL) != 0 )
|
||||||
@ -186,7 +199,16 @@ wxString KeyNameFromKeyCode( int aKeycode, bool* aIsFound )
|
|||||||
if( (aKeycode & MD_SHIFT) != 0 )
|
if( (aKeycode & MD_SHIFT) != 0 )
|
||||||
modifier << MODIFIER_SHIFT;
|
modifier << MODIFIER_SHIFT;
|
||||||
|
|
||||||
aKeycode &= ~( MD_CTRL | MD_ALT | MD_SHIFT );
|
if( (aKeycode & MD_META) != 0 )
|
||||||
|
modifier << MODIFIER_META;
|
||||||
|
|
||||||
|
if( (aKeycode & MD_SUPER) != 0 )
|
||||||
|
modifier << MODIFIER_WIN;
|
||||||
|
|
||||||
|
if( (aKeycode & MD_ALTGR) != 0 )
|
||||||
|
modifier << MODIFIER_ALTGR;
|
||||||
|
|
||||||
|
aKeycode &= ~MD_MODIFIER_MASK;
|
||||||
|
|
||||||
if( (aKeycode > ' ') && (aKeycode < 0x7F ) )
|
if( (aKeycode > ' ') && (aKeycode < 0x7F ) )
|
||||||
{
|
{
|
||||||
@ -262,7 +284,7 @@ int KeyCodeFromKeyName( const wxString& keyname )
|
|||||||
{
|
{
|
||||||
int ii, keycode = KEY_NON_FOUND;
|
int ii, keycode = KEY_NON_FOUND;
|
||||||
|
|
||||||
// Search for modifiers: Ctrl+ Alt+ and Shift+
|
// Search for modifiers: Ctrl+ Alt+ Shift+ and others
|
||||||
// Note: on Mac OSX, the Cmd key is equiv here to Ctrl
|
// Note: on Mac OSX, the Cmd key is equiv here to Ctrl
|
||||||
wxString key = keyname;
|
wxString key = keyname;
|
||||||
wxString prefix;
|
wxString prefix;
|
||||||
@ -292,6 +314,26 @@ int KeyCodeFromKeyName( const wxString& keyname )
|
|||||||
modifier |= MD_SHIFT;
|
modifier |= MD_SHIFT;
|
||||||
prefix = MODIFIER_SHIFT;
|
prefix = MODIFIER_SHIFT;
|
||||||
}
|
}
|
||||||
|
else if( key.StartsWith( MODIFIER_META ) )
|
||||||
|
{
|
||||||
|
modifier |= MD_META;
|
||||||
|
prefix = MODIFIER_META;
|
||||||
|
}
|
||||||
|
else if( key.StartsWith( MODIFIER_WIN ) )
|
||||||
|
{
|
||||||
|
modifier |= MD_SUPER;
|
||||||
|
prefix = MODIFIER_WIN;
|
||||||
|
}
|
||||||
|
else if( key.StartsWith( MODIFIER_SUPER ) )
|
||||||
|
{
|
||||||
|
modifier |= MD_SUPER;
|
||||||
|
prefix = MODIFIER_SUPER;
|
||||||
|
}
|
||||||
|
else if( key.StartsWith( MODIFIER_ALTGR ) )
|
||||||
|
{
|
||||||
|
modifier |= MD_ALTGR;
|
||||||
|
prefix = MODIFIER_ALTGR;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
@ -40,8 +40,7 @@ JOB_EXPORT_SCH_BOM::JOB_EXPORT_SCH_BOM() :
|
|||||||
m_sortField(),
|
m_sortField(),
|
||||||
m_sortAsc( true ),
|
m_sortAsc( true ),
|
||||||
m_filterString(),
|
m_filterString(),
|
||||||
m_excludeDNP( false ),
|
m_excludeDNP( false )
|
||||||
m_includeExcludedFromBOM( false )
|
|
||||||
{
|
{
|
||||||
m_params.emplace_back( new JOB_PARAM<wxString>( "field_delimiter",
|
m_params.emplace_back( new JOB_PARAM<wxString>( "field_delimiter",
|
||||||
&m_fieldDelimiter,
|
&m_fieldDelimiter,
|
||||||
@ -70,13 +69,8 @@ JOB_EXPORT_SCH_BOM::JOB_EXPORT_SCH_BOM() :
|
|||||||
m_fieldsGroupBy ) );
|
m_fieldsGroupBy ) );
|
||||||
m_params.emplace_back( new JOB_PARAM<wxString>( "sort_field", &m_sortField, m_sortField ) );
|
m_params.emplace_back( new JOB_PARAM<wxString>( "sort_field", &m_sortField, m_sortField ) );
|
||||||
m_params.emplace_back( new JOB_PARAM<bool>( "sort_asc", &m_sortAsc, m_sortAsc ) );
|
m_params.emplace_back( new JOB_PARAM<bool>( "sort_asc", &m_sortAsc, m_sortAsc ) );
|
||||||
m_params.emplace_back( new JOB_PARAM<wxString>( "filter_string",
|
m_params.emplace_back( new JOB_PARAM<wxString>( "filter_string", &m_filterString, m_filterString ) );
|
||||||
&m_filterString,
|
|
||||||
m_filterString ) );
|
|
||||||
m_params.emplace_back( new JOB_PARAM<bool>( "exclude_dnp", &m_excludeDNP, m_excludeDNP ) );
|
m_params.emplace_back( new JOB_PARAM<bool>( "exclude_dnp", &m_excludeDNP, m_excludeDNP ) );
|
||||||
m_params.emplace_back( new JOB_PARAM<bool>( "include_excluded_from_bom",
|
|
||||||
&m_includeExcludedFromBOM,
|
|
||||||
m_includeExcludedFromBOM ) );
|
|
||||||
|
|
||||||
m_params.emplace_back( new JOB_PARAM<wxString>( "bom_preset_name",
|
m_params.emplace_back( new JOB_PARAM<wxString>( "bom_preset_name",
|
||||||
&m_bomPresetName,
|
&m_bomPresetName,
|
||||||
|
@ -55,7 +55,6 @@ public:
|
|||||||
bool m_sortAsc;
|
bool m_sortAsc;
|
||||||
wxString m_filterString;
|
wxString m_filterString;
|
||||||
bool m_excludeDNP;
|
bool m_excludeDNP;
|
||||||
bool m_includeExcludedFromBOM;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
27
common/jobs/job_pcb_upgrade.cpp
Normal file
27
common/jobs/job_pcb_upgrade.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright The 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 <jobs/job_pcb_upgrade.h>
|
||||||
|
|
||||||
|
JOB_PCB_UPGRADE::JOB_PCB_UPGRADE() :
|
||||||
|
JOB( "upgrade", false ),
|
||||||
|
m_filename(),
|
||||||
|
m_force( false )
|
||||||
|
{
|
||||||
|
}
|
35
common/jobs/job_pcb_upgrade.h
Normal file
35
common/jobs/job_pcb_upgrade.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright The 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 JOB_PCB_UPGRADE_H
|
||||||
|
#define JOB_PCB_UPGRADE_H
|
||||||
|
|
||||||
|
#include <kicommon.h>
|
||||||
|
#include "job.h"
|
||||||
|
|
||||||
|
class KICOMMON_API JOB_PCB_UPGRADE : public JOB
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
JOB_PCB_UPGRADE();
|
||||||
|
|
||||||
|
wxString m_filename;
|
||||||
|
bool m_force;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
27
common/jobs/job_sch_upgrade.cpp
Normal file
27
common/jobs/job_sch_upgrade.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright The 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 <jobs/job_sch_upgrade.h>
|
||||||
|
|
||||||
|
JOB_SCH_UPGRADE::JOB_SCH_UPGRADE() :
|
||||||
|
JOB( "upgrade", false ),
|
||||||
|
m_filename(),
|
||||||
|
m_force( false )
|
||||||
|
{
|
||||||
|
}
|
35
common/jobs/job_sch_upgrade.h
Normal file
35
common/jobs/job_sch_upgrade.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright The 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 JOB_SCH_UPGRADE_H
|
||||||
|
#define JOB_SCH_UPGRADE_H
|
||||||
|
|
||||||
|
#include <kicommon.h>
|
||||||
|
#include "job.h"
|
||||||
|
|
||||||
|
class KICOMMON_API JOB_SCH_UPGRADE : public JOB
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
JOB_SCH_UPGRADE();
|
||||||
|
|
||||||
|
wxString m_filename;
|
||||||
|
bool m_force;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -142,6 +142,7 @@ wxString LayerName( int aLayer )
|
|||||||
case LAYER_DRC_EXCLUSION: return _( "DRC exclusions" );
|
case LAYER_DRC_EXCLUSION: return _( "DRC exclusions" );
|
||||||
case LAYER_MARKER_SHADOWS: return _( "DRC marker shadows" );
|
case LAYER_MARKER_SHADOWS: return _( "DRC marker shadows" );
|
||||||
case LAYER_ANCHOR: return _( "Anchors" );
|
case LAYER_ANCHOR: return _( "Anchors" );
|
||||||
|
case LAYER_POINTS: return _( "Points" );
|
||||||
case LAYER_DRAWINGSHEET: return _( "Drawing sheet" );
|
case LAYER_DRAWINGSHEET: return _( "Drawing sheet" );
|
||||||
case LAYER_PAGE_LIMITS: return _( "Page limits" );
|
case LAYER_PAGE_LIMITS: return _( "Page limits" );
|
||||||
case LAYER_CURSOR: return _( "Cursor" );
|
case LAYER_CURSOR: return _( "Cursor" );
|
||||||
|
@ -19,11 +19,23 @@
|
|||||||
|
|
||||||
#include "lib_table_grid_tricks.h"
|
#include "lib_table_grid_tricks.h"
|
||||||
#include "lib_table_grid.h"
|
#include "lib_table_grid.h"
|
||||||
|
#include <wx/clipbrd.h>
|
||||||
|
#include <wx/log.h>
|
||||||
|
|
||||||
|
|
||||||
LIB_TABLE_GRID_TRICKS::LIB_TABLE_GRID_TRICKS( WX_GRID* aGrid ) :
|
LIB_TABLE_GRID_TRICKS::LIB_TABLE_GRID_TRICKS( WX_GRID* aGrid ) :
|
||||||
GRID_TRICKS( aGrid )
|
GRID_TRICKS( aGrid )
|
||||||
{
|
{
|
||||||
|
m_grid->Disconnect( wxEVT_CHAR_HOOK );
|
||||||
|
m_grid->Connect( wxEVT_CHAR_HOOK, wxCharEventHandler( LIB_TABLE_GRID_TRICKS::onCharHook ), nullptr, this );
|
||||||
|
}
|
||||||
|
|
||||||
|
LIB_TABLE_GRID_TRICKS::LIB_TABLE_GRID_TRICKS( WX_GRID* aGrid,
|
||||||
|
std::function<void( wxCommandEvent& )> aAddHandler ) :
|
||||||
|
GRID_TRICKS( aGrid, aAddHandler )
|
||||||
|
{
|
||||||
|
m_grid->Disconnect( wxEVT_CHAR_HOOK );
|
||||||
|
m_grid->Connect( wxEVT_CHAR_HOOK, wxCharEventHandler( LIB_TABLE_GRID_TRICKS::onCharHook ), nullptr, this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -134,6 +146,61 @@ void LIB_TABLE_GRID_TRICKS::doPopupSelection( wxCommandEvent& event )
|
|||||||
GRID_TRICKS::doPopupSelection( event );
|
GRID_TRICKS::doPopupSelection( event );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void LIB_TABLE_GRID_TRICKS::onCharHook( wxKeyEvent& ev )
|
||||||
|
{
|
||||||
|
if( ev.GetModifiers() == wxMOD_CONTROL && ev.GetKeyCode() == 'V' && m_grid->IsCellEditControlShown() )
|
||||||
|
{
|
||||||
|
wxLogNull doNotLog;
|
||||||
|
|
||||||
|
if( wxTheClipboard->Open() )
|
||||||
|
{
|
||||||
|
if( wxTheClipboard->IsSupported( wxDF_TEXT ) || wxTheClipboard->IsSupported( wxDF_UNICODETEXT ) )
|
||||||
|
{
|
||||||
|
wxTextDataObject data;
|
||||||
|
wxTheClipboard->GetData( data );
|
||||||
|
|
||||||
|
wxString text = data.GetText();
|
||||||
|
|
||||||
|
if( !text.Contains( '\t' ) && text.Contains( ',' ) )
|
||||||
|
text.Replace( ',', '\t' );
|
||||||
|
|
||||||
|
if( text.Contains( '\t' ) || text.Contains( '\n' ) || text.Contains( '\r' ) )
|
||||||
|
{
|
||||||
|
m_grid->CancelPendingChanges();
|
||||||
|
int row = m_grid->GetGridCursorRow();
|
||||||
|
|
||||||
|
// Check if the current row already has data (has a nickname)
|
||||||
|
wxGridTableBase* table = m_grid->GetTable();
|
||||||
|
if( table && row >= 0 && row < table->GetNumberRows() )
|
||||||
|
{
|
||||||
|
// Check if the row has a nickname (indicating it has existing data)
|
||||||
|
wxString nickname = table->GetValue( row, COL_NICKNAME );
|
||||||
|
if( !nickname.IsEmpty() )
|
||||||
|
{
|
||||||
|
// Row already has data, don't allow pasting over it
|
||||||
|
wxTheClipboard->Close();
|
||||||
|
wxBell(); // Provide audio feedback
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_grid->ClearSelection();
|
||||||
|
m_grid->SelectRow( row );
|
||||||
|
m_grid->SetGridCursor( row, 0 );
|
||||||
|
getSelectedArea();
|
||||||
|
paste_text( text );
|
||||||
|
wxTheClipboard->Close();
|
||||||
|
m_grid->ForceRefresh();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wxTheClipboard->Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GRID_TRICKS::onCharHook( ev );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool LIB_TABLE_GRID_TRICKS::handleDoubleClick( wxGridEvent& aEvent )
|
bool LIB_TABLE_GRID_TRICKS::handleDoubleClick( wxGridEvent& aEvent )
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <wx/wupdlock.h>
|
#include <wx/wupdlock.h>
|
||||||
#include <wx/settings.h>
|
#include <wx/settings.h>
|
||||||
#include <wx/dc.h>
|
#include <wx/dc.h>
|
||||||
|
#include <wx/log.h>
|
||||||
#include <string_utils.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();
|
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 )
|
if( firstMatch )
|
||||||
{
|
{
|
||||||
wxDataViewItem item = ToItem( firstMatch );
|
wxDataViewItem item = ToItem( firstMatch );
|
||||||
|
@ -857,7 +857,12 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
|
|||||||
case TR_OP_FUNC_CALL:
|
case TR_OP_FUNC_CALL:
|
||||||
// Function call's uop was generated inside TR_STRUCT_REF
|
// Function call's uop was generated inside TR_STRUCT_REF
|
||||||
if( !node->uop )
|
if( !node->uop )
|
||||||
reportError( CST_CODEGEN, _( "Unknown parent of function parameters" ), node->srcPos );
|
{
|
||||||
|
// This function call is bare so we don't know who to apply it to
|
||||||
|
// Set a safe default value to exit gracefully with an error
|
||||||
|
reportError( CST_CODEGEN, _( "Unknown parent of function parameters" ), node->srcPos );
|
||||||
|
node->SetUop( TR_UOP_PUSH_VALUE, 0.0, EDA_UNITS::UNSCALED );
|
||||||
|
}
|
||||||
|
|
||||||
node->isTerminal = true;
|
node->isTerminal = true;
|
||||||
break;
|
break;
|
||||||
@ -1095,7 +1100,6 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
|
|||||||
{
|
{
|
||||||
stack.push_back( node->leaf[0] );
|
stack.push_back( node->leaf[0] );
|
||||||
node->leaf[0]->isVisited = true;
|
node->leaf[0]->isVisited = true;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
else if( node->leaf[1] && !node->leaf[1]->isVisited )
|
else if( node->leaf[1] && !node->leaf[1]->isVisited )
|
||||||
{
|
{
|
||||||
@ -1156,7 +1160,9 @@ void UOP::Exec( CONTEXT* ctx )
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case TR_OP_METHOD_CALL:
|
case TR_OP_METHOD_CALL:
|
||||||
m_func( ctx, m_ref.get() );
|
if( m_func )
|
||||||
|
m_func( ctx, m_ref.get() );
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -1317,9 +1323,8 @@ VALUE* UCODE::Run( CONTEXT* ctx )
|
|||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
// rules which fail outright should not be fired
|
// rules which fail outright should not be fired; return 0/false
|
||||||
std::unique_ptr<VALUE> temp_false = std::make_unique<VALUE>( 0 );
|
return ctx->StoreValue( new VALUE( 0 ) );
|
||||||
return ctx->StoreValue( temp_false.get() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ctx->SP() == 1 )
|
if( ctx->SP() == 1 )
|
||||||
@ -1335,8 +1340,7 @@ VALUE* UCODE::Run( CONTEXT* ctx )
|
|||||||
wxASSERT( ctx->SP() == 1 );
|
wxASSERT( ctx->SP() == 1 );
|
||||||
|
|
||||||
// non-well-formed rules should not be fired on a release build
|
// 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( new VALUE( 0 ) );
|
||||||
return ctx->StoreValue( temp_false.get() );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -806,7 +806,8 @@ GAL_SET GAL_SET::DefaultVisible()
|
|||||||
LAYER_FILLED_SHAPES,
|
LAYER_FILLED_SHAPES,
|
||||||
LAYER_LOCKED_ITEM_SHADOW,
|
LAYER_LOCKED_ITEM_SHADOW,
|
||||||
// LAYER_BOARD_OUTLINE_AREA, // currently hidden by default
|
// LAYER_BOARD_OUTLINE_AREA, // currently hidden by default
|
||||||
LAYER_CONFLICTS_SHADOW
|
LAYER_CONFLICTS_SHADOW,
|
||||||
|
LAYER_POINTS
|
||||||
};
|
};
|
||||||
|
|
||||||
static const GAL_SET saved( visible, arrayDim( visible ) );
|
static const GAL_SET saved( visible, arrayDim( visible ) );
|
||||||
|
@ -280,6 +280,7 @@ pintype
|
|||||||
placed
|
placed
|
||||||
placement
|
placement
|
||||||
plus
|
plus
|
||||||
|
point
|
||||||
polygon
|
polygon
|
||||||
portrait
|
portrait
|
||||||
precision
|
precision
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include <macros.h>
|
#include <macros.h>
|
||||||
#include <string_utils.h>
|
#include <string_utils.h>
|
||||||
#include <convert_basic_shapes_to_polygon.h>
|
#include <convert_basic_shapes_to_polygon.h>
|
||||||
|
#include <geometry/shape_rect.h>
|
||||||
#include <trigo.h>
|
#include <trigo.h>
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
|
|
||||||
@ -446,10 +447,21 @@ void DXF_PLOTTER::SetColor( const COLOR4D& color )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DXF_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill, int width )
|
void DXF_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill, int width,
|
||||||
|
int aCornerRadius )
|
||||||
{
|
{
|
||||||
wxASSERT( m_outputFile );
|
wxASSERT( m_outputFile );
|
||||||
|
|
||||||
|
if( aCornerRadius > 0 )
|
||||||
|
{
|
||||||
|
BOX2I box( p1, VECTOR2I( p2.x - p1.x, p2.y - p1.y ) );
|
||||||
|
box.Normalize();
|
||||||
|
SHAPE_RECT rect( box );
|
||||||
|
rect.SetRadius( aCornerRadius );
|
||||||
|
PlotPoly( rect.Outline(), fill, width, nullptr );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if( p1 != p2 )
|
if( p1 != p2 )
|
||||||
{
|
{
|
||||||
MoveTo( p1 );
|
MoveTo( p1 );
|
||||||
@ -605,6 +617,22 @@ void DXF_PLOTTER::PlotPoly( const std::vector<VECTOR2I>& aCornerList, FILL_T aFi
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DXF_PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aCornerList, FILL_T aFill, int aWidth,
|
||||||
|
void* aData )
|
||||||
|
{
|
||||||
|
std::vector<VECTOR2I> cornerList;
|
||||||
|
cornerList.reserve( aCornerList.PointCount() );
|
||||||
|
|
||||||
|
for( int ii = 0; ii < aCornerList.PointCount(); ii++ )
|
||||||
|
cornerList.emplace_back( aCornerList.CPoint( ii ) );
|
||||||
|
|
||||||
|
if( aCornerList.IsClosed() && cornerList.front() != cornerList.back() )
|
||||||
|
cornerList.emplace_back( aCornerList.CPoint( 0 ) );
|
||||||
|
|
||||||
|
PlotPoly( cornerList, aFill, aWidth, aData );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DXF_PLOTTER::PenTo( const VECTOR2I& pos, char plume )
|
void DXF_PLOTTER::PenTo( const VECTOR2I& pos, char plume )
|
||||||
{
|
{
|
||||||
wxASSERT( m_outputFile );
|
wxASSERT( m_outputFile );
|
||||||
@ -735,17 +763,17 @@ void DXF_PLOTTER::ThickRect( const VECTOR2I& p1, const VECTOR2I& p2, int width,
|
|||||||
{
|
{
|
||||||
VECTOR2I offsetp1( p1.x - width/2, p1.y - width/2 );
|
VECTOR2I offsetp1( p1.x - width/2, p1.y - width/2 );
|
||||||
VECTOR2I offsetp2( p2.x + width/2, p2.y + width/2 );
|
VECTOR2I offsetp2( p2.x + width/2, p2.y + width/2 );
|
||||||
Rect( offsetp1, offsetp2, FILL_T::NO_FILL, DXF_LINE_WIDTH );
|
Rect( offsetp1, offsetp2, FILL_T::NO_FILL, DXF_LINE_WIDTH, 0 );
|
||||||
|
|
||||||
offsetp1.x += width;
|
offsetp1.x += width;
|
||||||
offsetp1.y += width;
|
offsetp1.y += width;
|
||||||
offsetp2.x -= width;
|
offsetp2.x -= width;
|
||||||
offsetp2.y -= width;
|
offsetp2.y -= width;
|
||||||
Rect( offsetp1, offsetp2, FILL_T::NO_FILL, DXF_LINE_WIDTH );
|
Rect( offsetp1, offsetp2, FILL_T::NO_FILL, DXF_LINE_WIDTH, 0 );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Rect( p1, p2, FILL_T::NO_FILL, DXF_LINE_WIDTH );
|
Rect( p1, p2, FILL_T::NO_FILL, DXF_LINE_WIDTH, 0 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include <string_utils.h>
|
#include <string_utils.h>
|
||||||
#include <convert_basic_shapes_to_polygon.h>
|
#include <convert_basic_shapes_to_polygon.h>
|
||||||
|
#include <geometry/shape_rect.h>
|
||||||
#include <macros.h>
|
#include <macros.h>
|
||||||
#include <math/util.h> // for KiROUND
|
#include <math/util.h> // for KiROUND
|
||||||
#include <trigo.h>
|
#include <trigo.h>
|
||||||
@ -846,8 +847,19 @@ void GERBER_PLOTTER::PenTo( const VECTOR2I& aPos, char plume )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GERBER_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill, int width )
|
void GERBER_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill, int width,
|
||||||
|
int aCornerRadius )
|
||||||
{
|
{
|
||||||
|
if( aCornerRadius > 0 )
|
||||||
|
{
|
||||||
|
BOX2I box( p1, VECTOR2I( p2.x - p1.x, p2.y - p1.y ) );
|
||||||
|
box.Normalize();
|
||||||
|
SHAPE_RECT rect( box );
|
||||||
|
rect.SetRadius( aCornerRadius );
|
||||||
|
PlotPoly( rect.Outline(), fill, width, nullptr );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<VECTOR2I> cornerList;
|
std::vector<VECTOR2I> cornerList;
|
||||||
|
|
||||||
cornerList.reserve( 5 );
|
cornerList.reserve( 5 );
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
#include <fmt/ranges.h>
|
#include <fmt/ranges.h>
|
||||||
|
|
||||||
#include <plotters/plotters_pslike.h>
|
#include <plotters/plotters_pslike.h>
|
||||||
|
#include <geometry/shape_rect.h>
|
||||||
|
|
||||||
|
|
||||||
std::string PDF_PLOTTER::encodeStringForPlotter( const wxString& aText )
|
std::string PDF_PLOTTER::encodeStringForPlotter( const wxString& aText )
|
||||||
@ -227,7 +228,8 @@ void PDF_PLOTTER::SetDash( int aLineWidth, LINE_STYLE aLineStyle )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PDF_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill, int width )
|
void PDF_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill, int width,
|
||||||
|
int aCornerRadius )
|
||||||
{
|
{
|
||||||
wxASSERT( m_workFile );
|
wxASSERT( m_workFile );
|
||||||
|
|
||||||
@ -236,6 +238,16 @@ void PDF_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill, int
|
|||||||
|
|
||||||
SetCurrentLineWidth( width );
|
SetCurrentLineWidth( width );
|
||||||
|
|
||||||
|
if( aCornerRadius > 0 )
|
||||||
|
{
|
||||||
|
BOX2I box( p1, VECTOR2I( p2.x - p1.x, p2.y - p1.y ) );
|
||||||
|
box.Normalize();
|
||||||
|
SHAPE_RECT rect( box );
|
||||||
|
rect.SetRadius( aCornerRadius );
|
||||||
|
PlotPoly( rect.Outline(), fill, width, nullptr );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
VECTOR2I size = p2 - p1;
|
VECTOR2I size = p2 - p1;
|
||||||
|
|
||||||
if( size.x == 0 && size.y == 0 )
|
if( size.x == 0 && size.y == 0 )
|
||||||
@ -429,6 +441,22 @@ void PDF_PLOTTER::PlotPoly( const std::vector<VECTOR2I>& aCornerList, FILL_T aFi
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PDF_PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aCornerList, FILL_T aFill, int aWidth,
|
||||||
|
void* aData )
|
||||||
|
{
|
||||||
|
std::vector<VECTOR2I> cornerList;
|
||||||
|
cornerList.reserve( aCornerList.PointCount() );
|
||||||
|
|
||||||
|
for( int ii = 0; ii < aCornerList.PointCount(); ii++ )
|
||||||
|
cornerList.emplace_back( aCornerList.CPoint( ii ) );
|
||||||
|
|
||||||
|
if( aCornerList.IsClosed() && cornerList.front() != cornerList.back() )
|
||||||
|
cornerList.emplace_back( aCornerList.CPoint( 0 ) );
|
||||||
|
|
||||||
|
PlotPoly( cornerList, aFill, aWidth, aData );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PDF_PLOTTER::PenTo( const VECTOR2I& pos, char plume )
|
void PDF_PLOTTER::PenTo( const VECTOR2I& pos, char plume )
|
||||||
{
|
{
|
||||||
wxASSERT( m_workFile );
|
wxASSERT( m_workFile );
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <convert_basic_shapes_to_polygon.h>
|
#include <convert_basic_shapes_to_polygon.h>
|
||||||
#include <macros.h>
|
#include <macros.h>
|
||||||
#include <math/util.h> // for KiROUND
|
#include <math/util.h> // for KiROUND
|
||||||
|
#include <geometry/shape_rect.h>
|
||||||
#include <string_utils.h>
|
#include <string_utils.h>
|
||||||
#include <trigo.h>
|
#include <trigo.h>
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
@ -457,13 +458,24 @@ void PS_PLOTTER::SetDash( int aLineWidth, LINE_STYLE aLineStyle )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PS_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill, int width )
|
void PS_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill, int width,
|
||||||
|
int aCornerRadius )
|
||||||
{
|
{
|
||||||
SetCurrentLineWidth( width );
|
SetCurrentLineWidth( width );
|
||||||
|
|
||||||
if( fill == FILL_T::NO_FILL && GetCurrentLineWidth() <= 0 )
|
if( fill == FILL_T::NO_FILL && GetCurrentLineWidth() <= 0 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if( aCornerRadius > 0 )
|
||||||
|
{
|
||||||
|
BOX2I box( p1, VECTOR2I( p2.x - p1.x, p2.y - p1.y ) );
|
||||||
|
box.Normalize();
|
||||||
|
SHAPE_RECT rect( box );
|
||||||
|
rect.SetRadius( aCornerRadius );
|
||||||
|
PlotPoly( rect.Outline(), fill, width, nullptr );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
VECTOR2D p1_dev = userToDeviceCoordinates( p1 );
|
VECTOR2D p1_dev = userToDeviceCoordinates( p1 );
|
||||||
VECTOR2D p2_dev = userToDeviceCoordinates( p2 );
|
VECTOR2D p2_dev = userToDeviceCoordinates( p2 );
|
||||||
|
|
||||||
@ -556,6 +568,22 @@ void PS_PLOTTER::PlotPoly( const std::vector<VECTOR2I>& aCornerList, FILL_T aFil
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PS_PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aCornerList, FILL_T aFill, int aWidth,
|
||||||
|
void* aData )
|
||||||
|
{
|
||||||
|
std::vector<VECTOR2I> cornerList;
|
||||||
|
cornerList.reserve( aCornerList.PointCount() );
|
||||||
|
|
||||||
|
for( int ii = 0; ii < aCornerList.PointCount(); ii++ )
|
||||||
|
cornerList.emplace_back( aCornerList.CPoint( ii ) );
|
||||||
|
|
||||||
|
if( aCornerList.IsClosed() && cornerList.front() != cornerList.back() )
|
||||||
|
cornerList.emplace_back( aCornerList.CPoint( 0 ) );
|
||||||
|
|
||||||
|
PlotPoly( cornerList, aFill, aWidth, aData );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PS_PLOTTER::PlotImage( const wxImage& aImage, const VECTOR2I& aPos, double aScaleFactor )
|
void PS_PLOTTER::PlotImage( const wxImage& aImage, const VECTOR2I& aPos, double aScaleFactor )
|
||||||
{
|
{
|
||||||
VECTOR2I pix_size; // size of the bitmap in pixels
|
VECTOR2I pix_size; // size of the bitmap in pixels
|
||||||
|
@ -372,7 +372,8 @@ void SVG_PLOTTER::SetDash( int aLineWidth, LINE_STYLE aLineStyle )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SVG_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill, int width )
|
void SVG_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill, int width,
|
||||||
|
int aCornerRadius )
|
||||||
{
|
{
|
||||||
BOX2I rect( p1, VECTOR2I( p2.x - p1.x, p2.y - p1.y ) );
|
BOX2I rect( p1, VECTOR2I( p2.x - p1.x, p2.y - p1.y ) );
|
||||||
rect.Normalize();
|
rect.Normalize();
|
||||||
@ -412,7 +413,7 @@ void SVG_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill, int
|
|||||||
rect_dev.GetPosition().y,
|
rect_dev.GetPosition().y,
|
||||||
rect_dev.GetSize().x,
|
rect_dev.GetSize().x,
|
||||||
rect_dev.GetSize().y,
|
rect_dev.GetSize().y,
|
||||||
0.0 /* radius of rounded corners */ );
|
userToDeviceSize( aCornerRadius ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
#include <trigo.h>
|
#include <trigo.h>
|
||||||
#include <plotters/plotter.h>
|
#include <plotters/plotter.h>
|
||||||
|
#include <text_eval/text_eval_wrapper.h>
|
||||||
#include <geometry/shape_line_chain.h>
|
#include <geometry/shape_line_chain.h>
|
||||||
#include <bezier_curves.h>
|
#include <bezier_curves.h>
|
||||||
#include <callback_gal.h>
|
#include <callback_gal.h>
|
||||||
@ -267,7 +268,7 @@ void PLOTTER::PlotImage( const wxImage& aImage, const VECTOR2I& aPos, double aSc
|
|||||||
end.x += size.x;
|
end.x += size.x;
|
||||||
end.y += size.y;
|
end.y += size.y;
|
||||||
|
|
||||||
Rect( start, end, FILL_T::NO_FILL, USE_DEFAULT_LINE_WIDTH );
|
Rect( start, end, FILL_T::NO_FILL, USE_DEFAULT_LINE_WIDTH, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -584,7 +585,7 @@ void PLOTTER::ThickArc( const EDA_SHAPE& aArcShape, void* aData, int aWidth )
|
|||||||
|
|
||||||
void PLOTTER::ThickRect( const VECTOR2I& p1, const VECTOR2I& p2, int width, void* aData )
|
void PLOTTER::ThickRect( const VECTOR2I& p1, const VECTOR2I& p2, int width, void* aData )
|
||||||
{
|
{
|
||||||
Rect( p1, p2, FILL_T::NO_FILL, width );
|
Rect( p1, p2, FILL_T::NO_FILL, width, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -637,6 +638,13 @@ void PLOTTER::Text( const VECTOR2I& aPos,
|
|||||||
void* aData )
|
void* aData )
|
||||||
{
|
{
|
||||||
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
|
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
|
||||||
|
wxString text( aText );
|
||||||
|
|
||||||
|
if( text.Contains( wxS( "@{" ) ) )
|
||||||
|
{
|
||||||
|
EXPRESSION_EVALUATOR evaluator;
|
||||||
|
text = evaluator.Evaluate( text );
|
||||||
|
}
|
||||||
|
|
||||||
SetColor( aColor );
|
SetColor( aColor );
|
||||||
|
|
||||||
@ -680,7 +688,7 @@ void PLOTTER::Text( const VECTOR2I& aPos,
|
|||||||
if( !aFont )
|
if( !aFont )
|
||||||
aFont = KIFONT::FONT::GetFont( m_renderSettings->GetDefaultFont() );
|
aFont = KIFONT::FONT::GetFont( m_renderSettings->GetDefaultFont() );
|
||||||
|
|
||||||
aFont->Draw( &callback_gal, aText, aPos, attributes, aFontMetrics );
|
aFont->Draw( &callback_gal, text, aPos, attributes, aFontMetrics );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -693,6 +701,13 @@ void PLOTTER::PlotText( const VECTOR2I& aPos,
|
|||||||
void* aData )
|
void* aData )
|
||||||
{
|
{
|
||||||
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
|
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
|
||||||
|
wxString text( aText );
|
||||||
|
|
||||||
|
if( text.Contains( wxS( "@{" ) ) )
|
||||||
|
{
|
||||||
|
EXPRESSION_EVALUATOR evaluator;
|
||||||
|
text = evaluator.Evaluate( text );
|
||||||
|
}
|
||||||
|
|
||||||
TEXT_ATTRIBUTES attributes = aAttributes;
|
TEXT_ATTRIBUTES attributes = aAttributes;
|
||||||
int penWidth = attributes.m_StrokeWidth;
|
int penWidth = attributes.m_StrokeWidth;
|
||||||
@ -725,5 +740,5 @@ void PLOTTER::PlotText( const VECTOR2I& aPos,
|
|||||||
if( !aFont )
|
if( !aFont )
|
||||||
aFont = KIFONT::FONT::GetFont( m_renderSettings->GetDefaultFont() );
|
aFont = KIFONT::FONT::GetFont( m_renderSettings->GetDefaultFont() );
|
||||||
|
|
||||||
aFont->Draw( &callback_gal, aText, aPos, attributes, aFontMetrics );
|
aFont->Draw( &callback_gal, text, aPos, attributes, aFontMetrics );
|
||||||
}
|
}
|
||||||
|
208
common/preview_items/angle_item.cpp
Normal file
208
common/preview_items/angle_item.cpp
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024 The KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <preview_items/angle_item.h>
|
||||||
|
#include <tool/edit_points.h>
|
||||||
|
#include <gal/graphics_abstraction_layer.h>
|
||||||
|
#include <gal/painter.h>
|
||||||
|
#include <view/view.h>
|
||||||
|
#include <geometry/seg.h>
|
||||||
|
#include <preview_items/preview_utils.h>
|
||||||
|
#include <font/font.h>
|
||||||
|
#include <wx/string.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
using namespace KIGFX::PREVIEW;
|
||||||
|
|
||||||
|
ANGLE_ITEM::ANGLE_ITEM( EDIT_POINTS* aPoints ) :
|
||||||
|
SIMPLE_OVERLAY_ITEM(),
|
||||||
|
m_points( aPoints )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const BOX2I ANGLE_ITEM::ViewBBox() const
|
||||||
|
{
|
||||||
|
if( m_points )
|
||||||
|
return m_points->ViewBBox();
|
||||||
|
else
|
||||||
|
return BOX2I();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ANGLE_ITEM::drawPreviewShape( KIGFX::VIEW* aView ) const
|
||||||
|
{
|
||||||
|
if( !m_points )
|
||||||
|
return;
|
||||||
|
|
||||||
|
KIGFX::GAL* gal = aView->GetGAL();
|
||||||
|
KIGFX::RENDER_SETTINGS* settings = aView->GetPainter()->GetSettings();
|
||||||
|
KIGFX::COLOR4D drawColor = settings->GetLayerColor( LAYER_AUX_ITEMS );
|
||||||
|
|
||||||
|
double size = aView->ToWorld( EDIT_POINT::POINT_SIZE ) / 2.0;
|
||||||
|
double borderSize = aView->ToWorld( EDIT_POINT::BORDER_SIZE );
|
||||||
|
double radius = size * 10.0;
|
||||||
|
|
||||||
|
gal->SetStrokeColor( drawColor );
|
||||||
|
gal->SetFillColor( drawColor );
|
||||||
|
gal->SetIsFill( false );
|
||||||
|
gal->SetLineWidth( borderSize * 2.0 );
|
||||||
|
gal->SetGlyphSize( VECTOR2I( radius / 2, radius / 2 ) );
|
||||||
|
|
||||||
|
std::vector<const EDIT_POINT*> anglePoints;
|
||||||
|
|
||||||
|
for( unsigned i = 0; i < m_points->PointsSize(); ++i )
|
||||||
|
{
|
||||||
|
const EDIT_POINT& point = m_points->Point( i );
|
||||||
|
|
||||||
|
if( point.IsActive() || point.IsHover() )
|
||||||
|
{
|
||||||
|
anglePoints.push_back( &point );
|
||||||
|
|
||||||
|
EDIT_POINT* prev = m_points->Previous( point );
|
||||||
|
EDIT_POINT* next = m_points->Next( point );
|
||||||
|
|
||||||
|
if( prev )
|
||||||
|
anglePoints.push_back( prev );
|
||||||
|
|
||||||
|
if( next )
|
||||||
|
anglePoints.push_back( next );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort( anglePoints.begin(), anglePoints.end() );
|
||||||
|
anglePoints.erase( std::unique( anglePoints.begin(), anglePoints.end() ), anglePoints.end() );
|
||||||
|
|
||||||
|
// First pass: collect all angles and identify congruent ones
|
||||||
|
struct AngleInfo
|
||||||
|
{
|
||||||
|
const EDIT_POINT* point;
|
||||||
|
EDA_ANGLE angle;
|
||||||
|
VECTOR2D center;
|
||||||
|
VECTOR2D v1, v2;
|
||||||
|
EDA_ANGLE start;
|
||||||
|
EDA_ANGLE sweep;
|
||||||
|
EDA_ANGLE mid;
|
||||||
|
bool isRightAngle;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<AngleInfo> angles;
|
||||||
|
std::map<int, int> angleCount; // Map angle (in tenths of degree) to count
|
||||||
|
|
||||||
|
for( const EDIT_POINT* pt : anglePoints )
|
||||||
|
{
|
||||||
|
EDIT_POINT* prev = m_points->Previous( *pt );
|
||||||
|
EDIT_POINT* next = m_points->Next( *pt );
|
||||||
|
|
||||||
|
if( !( prev && next ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SEG seg1( pt->GetPosition(), prev->GetPosition() );
|
||||||
|
SEG seg2( pt->GetPosition(), next->GetPosition() );
|
||||||
|
|
||||||
|
// Calculate the interior angle (0-180 degrees) instead of the smallest angle
|
||||||
|
VECTOR2I c = pt->GetPosition();
|
||||||
|
VECTOR2I v1 = prev->GetPosition() - c;
|
||||||
|
VECTOR2I v2 = next->GetPosition() - c;
|
||||||
|
EDA_ANGLE angle = seg2.Angle( seg1 );
|
||||||
|
|
||||||
|
EDA_ANGLE start = EDA_ANGLE( VECTOR2D( v1 ) );
|
||||||
|
EDA_ANGLE sweep = ( EDA_ANGLE( VECTOR2D( v2 ) ) - start ).Normalize180();
|
||||||
|
EDA_ANGLE mid = start + sweep / 2.0;
|
||||||
|
VECTOR2D center( c );
|
||||||
|
|
||||||
|
AngleInfo info;
|
||||||
|
info.point = pt;
|
||||||
|
info.angle = angle;
|
||||||
|
info.center = center;
|
||||||
|
info.v1 = v1;
|
||||||
|
info.v2 = v2;
|
||||||
|
info.start = start;
|
||||||
|
info.sweep = sweep;
|
||||||
|
info.mid = mid;
|
||||||
|
info.isRightAngle = ( angle.AsTenthsOfADegree() == 900 );
|
||||||
|
|
||||||
|
angles.push_back( info );
|
||||||
|
angleCount[angle.AsTenthsOfADegree()]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second pass: draw the angles with congruence markings
|
||||||
|
for( const AngleInfo& angleInfo : angles )
|
||||||
|
{
|
||||||
|
bool isCongruent = angleCount[angleInfo.angle.AsTenthsOfADegree()] > 1;
|
||||||
|
|
||||||
|
if( angleInfo.isRightAngle )
|
||||||
|
{
|
||||||
|
VECTOR2D u1 = VECTOR2D( angleInfo.v1 ).Resize( radius );
|
||||||
|
VECTOR2D u2 = VECTOR2D( angleInfo.v2 ).Resize( radius );
|
||||||
|
VECTOR2D p1 = angleInfo.center + u1;
|
||||||
|
VECTOR2D p2 = angleInfo.center + u2;
|
||||||
|
VECTOR2D corner = angleInfo.center + u1 + u2;
|
||||||
|
|
||||||
|
// Draw the primary right angle marker
|
||||||
|
gal->DrawLine( p1, corner );
|
||||||
|
gal->DrawLine( p2, corner );
|
||||||
|
|
||||||
|
// Draw congruence marking for right angles
|
||||||
|
if( isCongruent )
|
||||||
|
{
|
||||||
|
double innerRadius = radius * 0.6;
|
||||||
|
VECTOR2D u1_inner = VECTOR2D( angleInfo.v1 ).Resize( innerRadius );
|
||||||
|
VECTOR2D u2_inner = VECTOR2D( angleInfo.v2 ).Resize( innerRadius );
|
||||||
|
VECTOR2D p1_inner = angleInfo.center + u1_inner;
|
||||||
|
VECTOR2D p2_inner = angleInfo.center + u2_inner;
|
||||||
|
VECTOR2D corner_inner = angleInfo.center + u1_inner + u2_inner;
|
||||||
|
|
||||||
|
gal->DrawLine( p1_inner, corner_inner );
|
||||||
|
gal->DrawLine( p2_inner, corner_inner );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Draw the primary arc
|
||||||
|
gal->DrawArc( angleInfo.center, radius, angleInfo.start, angleInfo.sweep );
|
||||||
|
|
||||||
|
// Draw congruence marking for non-right angles
|
||||||
|
if( isCongruent )
|
||||||
|
{
|
||||||
|
double innerRadius = radius * 0.7;
|
||||||
|
gal->DrawArc( angleInfo.center, innerRadius, angleInfo.start, angleInfo.sweep );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VECTOR2D textDir( angleInfo.mid.Cos(), angleInfo.mid.Sin() );
|
||||||
|
wxString label = wxString::Format( wxT( "%.1f°" ), angleInfo.angle.AsDegrees() );
|
||||||
|
|
||||||
|
// Calculate actual text dimensions to ensure proper clearance
|
||||||
|
KIFONT::FONT* font = KIFONT::FONT::GetFont();
|
||||||
|
VECTOR2I textSize = font->StringBoundaryLimits( label, gal->GetGlyphSize(), 0, false, false,
|
||||||
|
KIFONT::METRICS::Default() );
|
||||||
|
|
||||||
|
// Calculate offset based on text direction - use width for horizontal, height for vertical
|
||||||
|
double absX = std::abs( textDir.x );
|
||||||
|
double absY = std::abs( textDir.y );
|
||||||
|
double textClearance = ( absX * textSize.x + absY * textSize.y ) / 2.0;
|
||||||
|
double textOffset = radius + borderSize + textClearance;
|
||||||
|
VECTOR2I textPos = angleInfo.center + VECTOR2I( textDir * textOffset );
|
||||||
|
gal->BitmapText( label, textPos, ANGLE_HORIZONTAL );
|
||||||
|
}
|
||||||
|
}
|
@ -24,6 +24,16 @@
|
|||||||
#include <properties/pg_properties.h>
|
#include <properties/pg_properties.h>
|
||||||
#include <widgets/color_swatch.h>
|
#include <widgets/color_swatch.h>
|
||||||
#include <widgets/unit_binder.h>
|
#include <widgets/unit_binder.h>
|
||||||
|
#include <bitmaps.h>
|
||||||
|
#include <frame_type.h>
|
||||||
|
#include <kiway_player.h>
|
||||||
|
#include <kiway.h>
|
||||||
|
#include <wx/filedlg.h>
|
||||||
|
#include <wx/intl.h>
|
||||||
|
#include <eda_doc.h>
|
||||||
|
|
||||||
|
#include <wx/button.h>
|
||||||
|
#include <wx/bmpbuttn.h>
|
||||||
|
|
||||||
#include <wx/log.h>
|
#include <wx/log.h>
|
||||||
|
|
||||||
@ -31,6 +41,8 @@ const wxString PG_UNIT_EDITOR::EDITOR_NAME = wxS( "KiCadUnitEditor" );
|
|||||||
const wxString PG_CHECKBOX_EDITOR::EDITOR_NAME = wxS( "KiCadCheckboxEditor" );
|
const wxString PG_CHECKBOX_EDITOR::EDITOR_NAME = wxS( "KiCadCheckboxEditor" );
|
||||||
const wxString PG_COLOR_EDITOR::EDITOR_NAME = wxS( "KiCadColorEditor" );
|
const wxString PG_COLOR_EDITOR::EDITOR_NAME = wxS( "KiCadColorEditor" );
|
||||||
const wxString PG_RATIO_EDITOR::EDITOR_NAME = wxS( "KiCadRatioEditor" );
|
const wxString PG_RATIO_EDITOR::EDITOR_NAME = wxS( "KiCadRatioEditor" );
|
||||||
|
const wxString PG_FPID_EDITOR::EDITOR_NAME = wxS( "KiCadFpidEditor" );
|
||||||
|
const wxString PG_URL_EDITOR::EDITOR_NAME = wxS( "KiCadUrlEditor" );
|
||||||
|
|
||||||
|
|
||||||
PG_UNIT_EDITOR::PG_UNIT_EDITOR( EDA_DRAW_FRAME* aFrame ) :
|
PG_UNIT_EDITOR::PG_UNIT_EDITOR( EDA_DRAW_FRAME* aFrame ) :
|
||||||
@ -51,6 +63,9 @@ PG_UNIT_EDITOR::~PG_UNIT_EDITOR()
|
|||||||
|
|
||||||
wxString PG_UNIT_EDITOR::BuildEditorName( EDA_DRAW_FRAME* aFrame )
|
wxString PG_UNIT_EDITOR::BuildEditorName( EDA_DRAW_FRAME* aFrame )
|
||||||
{
|
{
|
||||||
|
if( !aFrame )
|
||||||
|
return EDITOR_NAME + "NoFrame";
|
||||||
|
|
||||||
return EDITOR_NAME + aFrame->GetName();
|
return EDITOR_NAME + aFrame->GetName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -458,3 +473,164 @@ void PG_RATIO_EDITOR::UpdateControl( wxPGProperty* aProperty, wxWindow* aCtrl )
|
|||||||
"properties!" ) );
|
"properties!" ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PG_FPID_EDITOR::PG_FPID_EDITOR( EDA_DRAW_FRAME* aFrame ) : m_frame( aFrame )
|
||||||
|
{
|
||||||
|
m_editorName = BuildEditorName( aFrame );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PG_FPID_EDITOR::UpdateFrame( EDA_DRAW_FRAME* aFrame )
|
||||||
|
{
|
||||||
|
m_frame = aFrame;
|
||||||
|
m_editorName = BuildEditorName( aFrame );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString PG_FPID_EDITOR::BuildEditorName( EDA_DRAW_FRAME* aFrame )
|
||||||
|
{
|
||||||
|
if( !aFrame )
|
||||||
|
return EDITOR_NAME + "NoFrame";
|
||||||
|
|
||||||
|
return EDITOR_NAME + aFrame->GetName();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxPGWindowList PG_FPID_EDITOR::CreateControls( wxPropertyGrid* aGrid, wxPGProperty* aProperty,
|
||||||
|
const wxPoint& aPos, const wxSize& aSize ) const
|
||||||
|
{
|
||||||
|
wxPGMultiButton* buttons = new wxPGMultiButton( aGrid, aSize );
|
||||||
|
buttons->Add( KiBitmap( BITMAPS::small_library ) );
|
||||||
|
buttons->Finalize( aGrid, aPos );
|
||||||
|
wxSize textSize = buttons->GetPrimarySize();
|
||||||
|
wxWindow* textCtrl = aGrid->GenerateEditorTextCtrl( aPos, textSize,
|
||||||
|
aProperty->GetValueAsString(), nullptr, 0,
|
||||||
|
aProperty->GetMaxLength() );
|
||||||
|
wxPGWindowList ret( textCtrl, buttons );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PG_FPID_EDITOR::OnEvent( wxPropertyGrid* aGrid, wxPGProperty* aProperty, wxWindow* aCtrl,
|
||||||
|
wxEvent& aEvent ) const
|
||||||
|
{
|
||||||
|
if( aEvent.GetEventType() == wxEVT_BUTTON )
|
||||||
|
{
|
||||||
|
wxString fpid = aProperty->GetValue().GetString();
|
||||||
|
|
||||||
|
if( KIWAY_PLAYER* frame = m_frame->Kiway().Player( FRAME_FOOTPRINT_CHOOSER, true, m_frame ) )
|
||||||
|
{
|
||||||
|
if( frame->ShowModal( &fpid, m_frame ) )
|
||||||
|
aGrid->ChangePropertyValue( aProperty, fpid );
|
||||||
|
|
||||||
|
frame->Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wxPGTextCtrlEditor::OnEvent( aGrid, aProperty, aCtrl, aEvent );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PG_URL_EDITOR::PG_URL_EDITOR( EDA_DRAW_FRAME* aFrame ) : m_frame( aFrame )
|
||||||
|
{
|
||||||
|
m_editorName = BuildEditorName( aFrame );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PG_URL_EDITOR::UpdateFrame( EDA_DRAW_FRAME* aFrame )
|
||||||
|
{
|
||||||
|
m_frame = aFrame;
|
||||||
|
m_editorName = BuildEditorName( aFrame );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString PG_URL_EDITOR::BuildEditorName( EDA_DRAW_FRAME* aFrame )
|
||||||
|
{
|
||||||
|
if( !aFrame )
|
||||||
|
return EDITOR_NAME + "NoFrame";
|
||||||
|
|
||||||
|
return EDITOR_NAME + aFrame->GetName();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxPGWindowList PG_URL_EDITOR::CreateControls( wxPropertyGrid* aGrid, wxPGProperty* aProperty,
|
||||||
|
const wxPoint& aPos, const wxSize& aSize ) const
|
||||||
|
{
|
||||||
|
wxPGMultiButton* buttons = new wxPGMultiButton( aGrid, aSize );
|
||||||
|
// Use a folder icon when no datasheet is set; otherwise use a globe icon.
|
||||||
|
wxString urlValue = aProperty->GetValueAsString();
|
||||||
|
bool hasUrl = !( urlValue.IsEmpty() || urlValue == wxS( "~" ) );
|
||||||
|
buttons->Add( KiBitmap( hasUrl ? BITMAPS::www : BITMAPS::small_folder ) );
|
||||||
|
buttons->Finalize( aGrid, aPos );
|
||||||
|
wxSize textSize = buttons->GetPrimarySize();
|
||||||
|
wxWindow* textCtrl = aGrid->GenerateEditorTextCtrl( aPos, textSize,
|
||||||
|
aProperty->GetValueAsString(), nullptr, 0,
|
||||||
|
aProperty->GetMaxLength() );
|
||||||
|
wxPGWindowList ret( textCtrl, buttons );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PG_URL_EDITOR::OnEvent( wxPropertyGrid* aGrid, wxPGProperty* aProperty, wxWindow* aCtrl,
|
||||||
|
wxEvent& aEvent ) const
|
||||||
|
{
|
||||||
|
if( aEvent.GetEventType() == wxEVT_BUTTON )
|
||||||
|
{
|
||||||
|
wxString filename = aProperty->GetValue().GetString();
|
||||||
|
|
||||||
|
if( filename.IsEmpty() || filename == wxS( "~" ) )
|
||||||
|
{
|
||||||
|
wxFileDialog openFileDialog( m_frame, _( "Open file" ), wxS( "" ), wxS( "" ),
|
||||||
|
_( "All Files" ) + wxS( " (*.*)|*.*" ),
|
||||||
|
wxFD_OPEN | wxFD_FILE_MUST_EXIST );
|
||||||
|
|
||||||
|
if( openFileDialog.ShowModal() == wxID_OK )
|
||||||
|
{
|
||||||
|
filename = openFileDialog.GetPath();
|
||||||
|
aGrid->ChangePropertyValue( aProperty, wxString::Format( wxS( "file://%s" ),
|
||||||
|
filename ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GetAssociatedDocument( m_frame, filename, &m_frame->Prj() );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the button icon to reflect presence/absence of URL
|
||||||
|
if( wxObject* src = aEvent.GetEventObject() )
|
||||||
|
{
|
||||||
|
wxString newUrl = aProperty->GetValueAsString();
|
||||||
|
bool hasUrl = !( newUrl.IsEmpty() || newUrl == wxS( "~" ) );
|
||||||
|
auto bmp = KiBitmap( hasUrl ? BITMAPS::www : BITMAPS::small_folder );
|
||||||
|
|
||||||
|
if( wxWindow* win = wxDynamicCast( src, wxWindow ) )
|
||||||
|
{
|
||||||
|
if( wxBitmapButton* bb = wxDynamicCast( win, wxBitmapButton ) )
|
||||||
|
{
|
||||||
|
bb->SetBitmap( bmp );
|
||||||
|
}
|
||||||
|
else if( wxButton* b = wxDynamicCast( win, wxButton ) )
|
||||||
|
{
|
||||||
|
b->SetBitmap( bmp );
|
||||||
|
}
|
||||||
|
else if( wxWindow* parent = win->GetParent() )
|
||||||
|
{
|
||||||
|
if( wxPGMultiButton* buttons = wxDynamicCast( parent, wxPGMultiButton ) )
|
||||||
|
{
|
||||||
|
wxWindow* btn0 = buttons->GetButton( 0 );
|
||||||
|
if( wxBitmapButton* bb0 = wxDynamicCast( btn0, wxBitmapButton ) )
|
||||||
|
bb0->SetBitmap( bmp );
|
||||||
|
else if( wxButton* b0 = wxDynamicCast( btn0, wxButton ) )
|
||||||
|
b0->SetBitmap( bmp );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wxPGTextCtrlEditor::OnEvent( aGrid, aProperty, aCtrl, aEvent );
|
||||||
|
}
|
||||||
|
@ -247,6 +247,10 @@ wxPGProperty* PGPropertyFactory( const PROPERTY_BASE* aProperty, EDA_DRAW_FRAME*
|
|||||||
ret = new PGPROPERTY_RATIO();
|
ret = new PGPROPERTY_RATIO();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROPERTY_DISPLAY::PT_NET:
|
||||||
|
ret = new PGPROPERTY_NET( aProperty->Choices() );
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
wxFAIL;
|
wxFAIL;
|
||||||
KI_FALLTHROUGH;
|
KI_FALLTHROUGH;
|
||||||
@ -692,7 +696,9 @@ PGPROPERTY_COLOR4D::PGPROPERTY_COLOR4D( const wxString& aLabel, const wxString&
|
|||||||
m_backgroundColor( aBackgroundColor )
|
m_backgroundColor( aBackgroundColor )
|
||||||
{
|
{
|
||||||
SetEditor( PG_COLOR_EDITOR::EDITOR_NAME );
|
SetEditor( PG_COLOR_EDITOR::EDITOR_NAME );
|
||||||
#if wxCHECK_VERSION( 3, 3, 0 )
|
#if wxCHECK_VERSION( 3, 3, 1 )
|
||||||
|
SetFlag( wxPGFlags::NoEditor );
|
||||||
|
#elif wxCHECK_VERSION( 3, 3, 0 )
|
||||||
SetFlag( wxPGPropertyFlags::NoEditor );
|
SetFlag( wxPGPropertyFlags::NoEditor );
|
||||||
#else
|
#else
|
||||||
SetFlag( wxPG_PROP_NOEDITOR );
|
SetFlag( wxPG_PROP_NOEDITOR );
|
||||||
@ -792,3 +798,19 @@ wxValidator* PGPROPERTY_TIME::DoGetValidator() const
|
|||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PGPROPERTY_NET::PGPROPERTY_NET( const wxPGChoices& aChoices ) :
|
||||||
|
wxEnumProperty( wxPG_LABEL, wxPG_LABEL, const_cast<wxPGChoices&>( aChoices ) )
|
||||||
|
{
|
||||||
|
SetEditor( wxS( "PG_NET_SELECTOR_EDITOR" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const wxPGEditor* PGPROPERTY_NET::DoGetEditorClass() const
|
||||||
|
{
|
||||||
|
wxCHECK_MSG( m_customEditor, wxPGEditor_Choice,
|
||||||
|
wxT( "Make sure to RegisterEditorClass() for PGPROPERTY_NET!" ) );
|
||||||
|
|
||||||
|
return m_customEditor;
|
||||||
|
}
|
||||||
|
@ -280,6 +280,9 @@ APP_SETTINGS_BASE::APP_SETTINGS_BASE( const std::string& aFilename, int aSchemaV
|
|||||||
|
|
||||||
m_params.emplace_back( new PARAM<bool>( "cross_probing.auto_highlight",
|
m_params.emplace_back( new PARAM<bool>( "cross_probing.auto_highlight",
|
||||||
&m_CrossProbing.auto_highlight, true ) );
|
&m_CrossProbing.auto_highlight, true ) );
|
||||||
|
|
||||||
|
m_params.emplace_back( new PARAM<bool>( "cross_probing.flash_selection",
|
||||||
|
&m_CrossProbing.flash_selection, false ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -175,6 +175,7 @@ static const std::map<int, COLOR4D> s_defaultTheme =
|
|||||||
{ NETNAMES_LAYER_ID_START, CSS_COLOR( 255, 255, 255, 0.7 ) },
|
{ NETNAMES_LAYER_ID_START, CSS_COLOR( 255, 255, 255, 0.7 ) },
|
||||||
{ LAYER_PAD_NETNAMES, CSS_COLOR( 255, 255, 255, 0.9 ) },
|
{ LAYER_PAD_NETNAMES, CSS_COLOR( 255, 255, 255, 0.9 ) },
|
||||||
{ LAYER_VIA_NETNAMES, CSS_COLOR( 50, 50, 50, 0.9 ) },
|
{ LAYER_VIA_NETNAMES, CSS_COLOR( 50, 50, 50, 0.9 ) },
|
||||||
|
{ LAYER_POINTS, CSS_COLOR( 255, 38, 226, 1 ) },
|
||||||
|
|
||||||
{ F_Cu, CSS_COLOR( 200, 52, 52, 1 ) },
|
{ F_Cu, CSS_COLOR( 200, 52, 52, 1 ) },
|
||||||
{ In1_Cu, CSS_COLOR( 127, 200, 127, 1 ) },
|
{ In1_Cu, CSS_COLOR( 127, 200, 127, 1 ) },
|
||||||
@ -450,6 +451,7 @@ static const std::map<int, COLOR4D> s_classicTheme =
|
|||||||
{ NETNAMES_LAYER_ID_START, CSS_COLOR( 255, 255, 255, 0.7 ) },
|
{ NETNAMES_LAYER_ID_START, CSS_COLOR( 255, 255, 255, 0.7 ) },
|
||||||
{ LAYER_PAD_NETNAMES, CSS_COLOR( 255, 255, 255, 0.9 ) },
|
{ LAYER_PAD_NETNAMES, CSS_COLOR( 255, 255, 255, 0.9 ) },
|
||||||
{ LAYER_VIA_NETNAMES, CSS_COLOR( 50, 50, 50, 0.9 ) },
|
{ LAYER_VIA_NETNAMES, CSS_COLOR( 50, 50, 50, 0.9 ) },
|
||||||
|
{ LAYER_POINTS, COLOR4D( BLUE ) },
|
||||||
|
|
||||||
{ F_Cu, COLOR4D( RED ) },
|
{ F_Cu, COLOR4D( RED ) },
|
||||||
{ In1_Cu, COLOR4D( YELLOW ) },
|
{ In1_Cu, COLOR4D( YELLOW ) },
|
||||||
|
@ -142,6 +142,7 @@ COLOR_SETTINGS::COLOR_SETTINGS( const wxString& aFilename, bool aAbsolutePath )
|
|||||||
CLR( "board.track_net_names", NETNAMES_LAYER_ID_START );
|
CLR( "board.track_net_names", NETNAMES_LAYER_ID_START );
|
||||||
CLR( "board.pad_net_names", LAYER_PAD_NETNAMES );
|
CLR( "board.pad_net_names", LAYER_PAD_NETNAMES );
|
||||||
CLR( "board.via_net_names", LAYER_VIA_NETNAMES );
|
CLR( "board.via_net_names", LAYER_VIA_NETNAMES );
|
||||||
|
CLR( "board.points", LAYER_POINTS );
|
||||||
|
|
||||||
CLR( "board.copper.f", F_Cu );
|
CLR( "board.copper.f", F_Cu );
|
||||||
CLR( "board.copper.in1", In1_Cu );
|
CLR( "board.copper.in1", In1_Cu );
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user