mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-13 17:53:11 +02:00
Compare commits
173 Commits
266e5cbbd5
...
f20f3d3819
Author | SHA1 | Date | |
---|---|---|---|
|
f20f3d3819 | ||
|
c64f99c57a | ||
|
5952c2fb9a | ||
|
0b6de964fd | ||
|
976278e5a6 | ||
|
8d8bd7253f | ||
|
5dc6d43f43 | ||
|
98dd5a68eb | ||
|
18b56539a6 | ||
|
9b006c4f3b | ||
|
8035a66152 | ||
|
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 | ||
|
59ea32eef6 |
@ -8,6 +8,7 @@ win64_build:
|
||||
interruptible: false
|
||||
image: registry.gitlab.com/kicad/kicad-ci/windows-build-image/ltsc2022-msvc:latest
|
||||
variables:
|
||||
VCPKG_BINARY_SOURCES: 'nuget,gitlab,readwrite'
|
||||
# Switch the compressor to fastzip and reduce the compression level
|
||||
FF_USE_FASTZIP: "true"
|
||||
CACHE_COMPRESSION_LEVEL: "fast"
|
||||
@ -23,6 +24,7 @@ win64_build:
|
||||
script:
|
||||
- C:\builder\build.ps1 -Env -Arch x64
|
||||
- $vcpkgCache=Join-Path -Path (Get-Location) -ChildPath ".vcpkgCache";$env:VCPKG_DEFAULT_BINARY_CACHE=$vcpkgCache;New-Item -ItemType Directory -Force -Path $vcpkgCache
|
||||
- nuget.exe sources add -Name gitlab -Source "https://gitlab.com/api/v4/projects/27426693/packages/nuget/index.json" -UserName gitlab-ci-token -Password $env:CI_JOB_TOKEN
|
||||
- mkdir -p build/windows -Force
|
||||
- cd build/windows
|
||||
- cmake `
|
||||
@ -34,11 +36,11 @@ win64_build:
|
||||
-DKICAD_BUILD_PNS_DEBUG_TOOL=ON `
|
||||
-DKICAD_USE_3DCONNEXION=ON `
|
||||
-DVCPKG_BUILD_TYPE=debug `
|
||||
-DVCPKG_INSTALL_OPTIONS="--x-abi-tools-use-exact-versions" `
|
||||
-DVCPKG_OVERLAY_TRIPLETS="$Env:CI_PROJECT_DIR/tools/custom_vcpkg_triplets" `
|
||||
../../
|
||||
- cmake --build . 2>&1 | tee compilation_log.txt
|
||||
- cd ../../
|
||||
after_script:
|
||||
- Get-Content -Path C:\builder\vcpkg\buildtrees\wxpython-33\python3-tool-post-install-err.log
|
||||
artifacts:
|
||||
# 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
|
||||
|
@ -368,11 +368,12 @@ private:
|
||||
void createTrackWithMargin( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDstContainer,
|
||||
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,
|
||||
PCB_LAYER_ID aLayer, const VECTOR2I& aMargin ) const;
|
||||
|
||||
void createPadWithHole( const PAD* aPad, CONTAINER_2D_BASE* aDstContainer,
|
||||
int aInflateValue );
|
||||
// Generate the hole shape of aPad, stored in aDstContainer
|
||||
void createPadHoleShape( const PAD* aPad, CONTAINER_2D_BASE* aDstContainer, int aInflateValue );
|
||||
|
||||
void addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
|
||||
PCB_LAYER_ID aLayerId );
|
||||
|
@ -474,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,
|
||||
int aInflateValue )
|
||||
void BOARD_ADAPTER::createPadHoleShape( const PAD* aPad, CONTAINER_2D_BASE* aDstContainer,
|
||||
int aInflateValue )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -507,27 +507,32 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||
{
|
||||
for( PAD* pad : footprint->Pads() )
|
||||
{
|
||||
const VECTOR2I padHole = pad->GetDrillSize();
|
||||
|
||||
if( !padHole.x ) // Not drilled pad like SMD pad
|
||||
// Note: holes of NPTH are already built by GetBoardPolygonOutlines
|
||||
if( !pad->HasHole() )
|
||||
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++;
|
||||
double holeDiameter = ( pad->GetDrillSize().x + pad->GetDrillSize().y ) / 2.0;
|
||||
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 )
|
||||
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() )
|
||||
{
|
||||
const VECTOR2I padHole = pad->GetDrillSize();
|
||||
|
||||
if( !padHole.x ) // Not drilled pad like SMD pad
|
||||
if( !pad->HasHole() )
|
||||
continue;
|
||||
|
||||
// The hole in the body is inflated by copper thickness.
|
||||
|
@ -35,14 +35,22 @@
|
||||
#include <advanced_config.h>
|
||||
#include <build_version.h>
|
||||
#include <board.h>
|
||||
#include <pad.h>
|
||||
#include <pcb_field.h>
|
||||
#include <reporter.h>
|
||||
#include <gal/opengl/gl_context_mgr.h>
|
||||
#include <core/profile.h> // To use GetRunningMicroSecs or another profiling utility
|
||||
#include <bitmaps.h>
|
||||
#include <kiway_holder.h>
|
||||
#include <kiway.h>
|
||||
#include <macros.h>
|
||||
#include <pgm_base.h>
|
||||
#include <settings/settings_manager.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>
|
||||
|
||||
@ -92,28 +100,12 @@ END_EVENT_TABLE()
|
||||
EDA_3D_CANVAS::EDA_3D_CANVAS( wxWindow* aParent, const wxGLAttributes& aGLAttribs,
|
||||
BOARD_ADAPTER& aBoardAdapter, CAMERA& aCamera,
|
||||
S3D_CACHE* a3DCachePointer ) :
|
||||
HIDPI_GL_3D_CANVAS( EDA_DRAW_PANEL_GAL::GetVcSettings(), aCamera, aParent, aGLAttribs,
|
||||
EDA_3D_CANVAS_ID, wxDefaultPosition,
|
||||
wxDefaultSize, wxFULL_REPAINT_ON_RESIZE ),
|
||||
m_eventDispatcher( nullptr ),
|
||||
m_parentStatusBar( nullptr ),
|
||||
m_parentInfoBar( nullptr ),
|
||||
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 )
|
||||
HIDPI_GL_3D_CANVAS( EDA_DRAW_PANEL_GAL::GetVcSettings(), aCamera, aParent, aGLAttribs,
|
||||
EDA_3D_CANVAS_ID, wxDefaultPosition,
|
||||
wxDefaultSize, wxFULL_REPAINT_ON_RESIZE ),
|
||||
m_editing_timeout_timer( this, wxID_HIGHEST + 1 ),
|
||||
m_redraw_trigger_timer( this, wxID_HIGHEST + 2 ),
|
||||
m_boardAdapter( aBoardAdapter )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_CANVAS::EDA_3D_CANVAS" ) );
|
||||
|
||||
@ -481,8 +473,10 @@ void EDA_3D_CANVAS::DoRePaint()
|
||||
|
||||
if( m_camera_is_moving )
|
||||
{
|
||||
const int64_t curtime_delta = GetRunningMicroSecs() - m_strtime_camera_movement;
|
||||
curtime_delta_s = ( curtime_delta / 1e6 ) * m_camera_moving_speed;
|
||||
const int64_t curtime_delta = GetRunningMicroSecs() - m_strtime_camera_movement;
|
||||
// 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 );
|
||||
|
||||
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 )
|
||||
{
|
||||
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 );
|
||||
|
||||
if( curtime_delta_s > 1.0f )
|
||||
@ -887,7 +882,7 @@ void EDA_3D_CANVAS::OnZoomGesture( wxZoomGestureEvent& aEvent )
|
||||
m_camera.Pan( 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();
|
||||
|
||||
@ -930,7 +925,7 @@ void EDA_3D_CANVAS::OnRotateGesture( wxRotateGestureEvent& aEvent )
|
||||
if( m_camera_is_moving )
|
||||
return;
|
||||
|
||||
m_camera.RotateScreen( m_gestureLastAngle - aEvent.GetRotationAngle() );
|
||||
m_camera.RotateScreen( static_cast<float>( m_gestureLastAngle - aEvent.GetRotationAngle() ) );
|
||||
m_gestureLastAngle = aEvent.GetRotationAngle();
|
||||
|
||||
DisplayStatus();
|
||||
@ -1066,9 +1061,45 @@ void EDA_3D_CANVAS::OnLeftDown( wxMouseEvent& event )
|
||||
{
|
||||
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 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();
|
||||
|
||||
float scaleX = static_cast<float>( gizmo_width ) / logicalW;
|
||||
float scaleY = static_cast<float>( gizmo_height ) / logicalH;
|
||||
float scaleX = static_cast<float>( static_cast<double>( gizmo_width ) / static_cast<double>( logicalW ) );
|
||||
float scaleY = static_cast<float>( static_cast<double>( gizmo_height ) / static_cast<double>( logicalH ) );
|
||||
|
||||
int scaledMouseX = static_cast<int>( event.GetX() * scaleX );
|
||||
int scaledMouseY = static_cast<int>( ( logicalH - event.GetY() ) * scaleY );
|
||||
int scaledMouseX = static_cast<int>( static_cast<float>( event.GetX() ) * scaleX );
|
||||
int scaledMouseY = static_cast<int>( static_cast<float>( logicalH - event.GetY() ) * scaleY );
|
||||
|
||||
m_3d_render_opengl->handleGizmoMouseInput( scaledMouseX, scaledMouseY );
|
||||
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
|
||||
// [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_camera_moving_speed = aMovingSpeed;
|
||||
@ -1249,7 +1280,7 @@ void EDA_3D_CANVAS::move_pivot_based_on_cur_mouse_position()
|
||||
{
|
||||
RAY mouseRay = getRayAtCurrentMousePosition();
|
||||
|
||||
float hit_t;
|
||||
float hit_t = 0.0f;
|
||||
|
||||
// Test it with the board bounding box
|
||||
if( m_boardAdapter.GetBBox().Intersect( mouseRay, &hit_t ) )
|
||||
|
@ -42,7 +42,7 @@ class RENDER_3D_RAYTRACE_GL;
|
||||
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
|
||||
@ -61,7 +61,7 @@ public:
|
||||
EDA_3D_CANVAS( wxWindow* aParent, const wxGLAttributes& aGLAttribs, BOARD_ADAPTER& aSettings,
|
||||
CAMERA& aCamera, S3D_CACHE* a3DCachePointer );
|
||||
|
||||
~EDA_3D_CANVAS();
|
||||
~EDA_3D_CANVAS() override;
|
||||
|
||||
/**
|
||||
* Set a dispatcher that processes events and forwards them to tools.
|
||||
@ -302,36 +302,36 @@ private:
|
||||
RAY getRayAtCurrentMousePosition();
|
||||
|
||||
private:
|
||||
TOOL_DISPATCHER* m_eventDispatcher;
|
||||
wxStatusBar* m_parentStatusBar; // Parent statusbar to report progress
|
||||
WX_INFOBAR* m_parentInfoBar;
|
||||
TOOL_DISPATCHER* m_eventDispatcher = nullptr;
|
||||
wxStatusBar* m_parentStatusBar = nullptr; // Parent statusbar to report progress
|
||||
WX_INFOBAR* m_parentInfoBar = nullptr;
|
||||
|
||||
wxGLContext* m_glRC; // Current OpenGL context
|
||||
bool m_is_opengl_initialized;
|
||||
bool m_is_opengl_version_supported;
|
||||
wxGLContext* m_glRC = nullptr; // Current OpenGL context
|
||||
bool m_is_opengl_initialized = false;
|
||||
bool m_is_opengl_version_supported = true;
|
||||
|
||||
wxTimer m_editing_timeout_timer; // Expires after some time signaling that
|
||||
// the mouse / keyboard movements are over
|
||||
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
|
||||
float m_camera_moving_speed; // 1.0f will be 1:1
|
||||
int64_t m_strtime_camera_movement; // Ticktime of camera movement start
|
||||
bool m_animation_enabled; // Camera animation enabled
|
||||
int m_moving_speed_multiplier; // Camera animation speed multiplier option
|
||||
bool m_render_pivot = false; // Render the pivot while camera moving
|
||||
float m_camera_moving_speed = 1.0f; // 1.0f will be 1:1
|
||||
int64_t m_strtime_camera_movement = 0; // Ticktime of camera movement start
|
||||
bool m_animation_enabled = true; // Camera animation enabled
|
||||
int m_moving_speed_multiplier = 3; // Camera animation speed multiplier option
|
||||
|
||||
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_OPENGL* m_3d_render_opengl;
|
||||
|
||||
bool m_opengl_supports_raytracing;
|
||||
bool m_render_raytracing_was_requested;
|
||||
bool m_opengl_supports_raytracing = true;
|
||||
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
|
||||
SFVEC3F m_3dmousePivotPos; // The position of the 3dmouse pivot
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "render_3d_opengl.h"
|
||||
#include <board.h>
|
||||
#include <footprint.h>
|
||||
#include <pcb_track.h>
|
||||
#include "../../3d_math.h"
|
||||
#include "convert_basic_shapes_to_polygon.h"
|
||||
#include <lset.h>
|
||||
@ -726,6 +727,54 @@ void RENDER_3D_OPENGL::generateCylinder( const SFVEC2F& aCenter, float aInnerRad
|
||||
}
|
||||
|
||||
|
||||
void RENDER_3D_OPENGL::generateDisk( const SFVEC2F& aCenter, float aRadius, float aZ,
|
||||
unsigned int aNr_sides_per_circle, TRIANGLE_DISPLAY_LIST* aDstLayer,
|
||||
bool aTop )
|
||||
{
|
||||
const float delta = 2.0f * glm::pi<float>() / (float) aNr_sides_per_circle;
|
||||
|
||||
for( unsigned int i = 0; i < aNr_sides_per_circle; ++i )
|
||||
{
|
||||
float a0 = delta * i;
|
||||
float a1 = delta * ( i + 1 );
|
||||
const SFVEC3F p0( aCenter.x + cosf( a0 ) * aRadius,
|
||||
aCenter.y + sinf( a0 ) * aRadius, aZ );
|
||||
const SFVEC3F p1( aCenter.x + cosf( a1 ) * aRadius,
|
||||
aCenter.y + sinf( a1 ) * aRadius, aZ );
|
||||
const SFVEC3F c( aCenter.x, aCenter.y, aZ );
|
||||
|
||||
if( aTop )
|
||||
aDstLayer->m_layer_top_triangles->AddTriangle( p1, p0, c );
|
||||
else
|
||||
aDstLayer->m_layer_bot_triangles->AddTriangle( p0, p1, c );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RENDER_3D_OPENGL::generateDimple( const SFVEC2F& aCenter, float aRadius, float aZ,
|
||||
float aDepth, unsigned int aNr_sides_per_circle,
|
||||
TRIANGLE_DISPLAY_LIST* aDstLayer, bool aTop )
|
||||
{
|
||||
const float delta = 2.0f * glm::pi<float>() / (float) aNr_sides_per_circle;
|
||||
const SFVEC3F c( aCenter.x, aCenter.y, aTop ? aZ - aDepth : aZ + aDepth );
|
||||
|
||||
for( unsigned int i = 0; i < aNr_sides_per_circle; ++i )
|
||||
{
|
||||
float a0 = delta * i;
|
||||
float a1 = delta * ( i + 1 );
|
||||
const SFVEC3F p0( aCenter.x + cosf( a0 ) * aRadius,
|
||||
aCenter.y + sinf( a0 ) * aRadius, aZ );
|
||||
const SFVEC3F p1( aCenter.x + cosf( a1 ) * aRadius,
|
||||
aCenter.y + sinf( a1 ) * aRadius, aZ );
|
||||
|
||||
if( aTop )
|
||||
aDstLayer->m_layer_top_triangles->AddTriangle( p0, p1, c );
|
||||
else
|
||||
aDstLayer->m_layer_bot_triangles->AddTriangle( p1, p0, c );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RENDER_3D_OPENGL::generateViasAndPads()
|
||||
{
|
||||
if( !m_boardAdapter.GetBoard() )
|
||||
@ -819,10 +868,7 @@ void RENDER_3D_OPENGL::generateViasAndPads()
|
||||
{
|
||||
if( pad->GetAttribute() != PAD_ATTRIB::NPTH )
|
||||
{
|
||||
const VECTOR2I drillsize = pad->GetDrillSize();
|
||||
const bool hasHole = drillsize.x && drillsize.y;
|
||||
|
||||
if( !hasHole )
|
||||
if( !pad->HasHole() )
|
||||
continue;
|
||||
|
||||
pad->TransformHoleToPolygon( tht_outer_holes_poly, platingThickness,
|
||||
@ -885,6 +931,63 @@ void RENDER_3D_OPENGL::generateViasAndPads()
|
||||
delete layerTriangles;
|
||||
}
|
||||
}
|
||||
|
||||
TRIANGLE_DISPLAY_LIST* frontCover = new TRIANGLE_DISPLAY_LIST( m_boardAdapter.GetViaCount() );
|
||||
TRIANGLE_DISPLAY_LIST* backCover = new TRIANGLE_DISPLAY_LIST( m_boardAdapter.GetViaCount() );
|
||||
|
||||
for( const PCB_TRACK* track : m_boardAdapter.GetBoard()->Tracks() )
|
||||
{
|
||||
if( track->Type() != PCB_VIA_T )
|
||||
continue;
|
||||
|
||||
const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
|
||||
|
||||
const float holediameter = via->GetDrillValue() * m_boardAdapter.BiuTo3dUnits();
|
||||
const float hole_radius = holediameter / 2.0f + 2.0 * platingThickness3d;
|
||||
const SFVEC2F center( via->GetStart().x * m_boardAdapter.BiuTo3dUnits(),
|
||||
-via->GetStart().y * m_boardAdapter.BiuTo3dUnits() );
|
||||
unsigned int seg = m_boardAdapter.GetCircleSegmentCount( via->GetDrillValue() );
|
||||
|
||||
PCB_LAYER_ID top_layer, bottom_layer;
|
||||
via->LayerPair( &top_layer, &bottom_layer );
|
||||
float ztop, zbot, dummy;
|
||||
getLayerZPos( top_layer, ztop, dummy );
|
||||
getLayerZPos( bottom_layer, dummy, zbot );
|
||||
|
||||
bool frontCovering = via->GetFrontCoveringMode() == COVERING_MODE::COVERED || via->IsTented( F_Mask );
|
||||
bool backCovering = via->GetBackCoveringMode() == COVERING_MODE::COVERED || via->IsTented( B_Mask );
|
||||
bool frontPlugged = via->GetFrontPluggingMode() == PLUGGING_MODE::PLUGGED;
|
||||
bool backPlugged = via->GetBackPluggingMode() == PLUGGING_MODE::PLUGGED;
|
||||
bool filled = via->GetFillingMode() == FILLING_MODE::FILLED
|
||||
|| via->GetCappingMode() == CAPPING_MODE::CAPPED;
|
||||
|
||||
const float depth = hole_radius * 0.3f;
|
||||
|
||||
if( frontCovering )
|
||||
{
|
||||
if( filled || !frontPlugged )
|
||||
generateDisk( center, hole_radius, ztop, seg, frontCover, true );
|
||||
else
|
||||
generateDimple( center, hole_radius, ztop, depth, seg, frontCover, true );
|
||||
}
|
||||
|
||||
if( backCovering )
|
||||
{
|
||||
if( filled || !backPlugged )
|
||||
generateDisk( center, hole_radius, zbot, seg, backCover, false );
|
||||
else
|
||||
generateDimple( center, hole_radius, zbot, depth, seg, backCover, false );
|
||||
}
|
||||
}
|
||||
|
||||
if( frontCover->m_layer_top_triangles->GetVertexSize() > 0 )
|
||||
m_viaFrontCover = new OPENGL_RENDER_LIST( *frontCover, 0, 0.0f, 0.0f );
|
||||
|
||||
if( backCover->m_layer_bot_triangles->GetVertexSize() > 0 )
|
||||
m_viaBackCover = new OPENGL_RENDER_LIST( *backCover, 0, 0.0f, 0.0f );
|
||||
|
||||
delete frontCover;
|
||||
delete backCover;
|
||||
}
|
||||
|
||||
|
||||
|
@ -72,6 +72,8 @@ RENDER_3D_OPENGL::RENDER_3D_OPENGL( EDA_3D_CANVAS* aCanvas, BOARD_ADAPTER& aAdap
|
||||
m_outerViaThroughHoles = nullptr;
|
||||
m_microviaHoles = nullptr;
|
||||
m_padHoles = nullptr;
|
||||
m_viaFrontCover = nullptr;
|
||||
m_viaBackCover = nullptr;
|
||||
|
||||
m_circleTexture = 0;
|
||||
m_grid = 0;
|
||||
@ -947,6 +949,8 @@ void RENDER_3D_OPENGL::freeAllLists()
|
||||
|
||||
DELETE_AND_FREE( m_microviaHoles )
|
||||
DELETE_AND_FREE( m_padHoles )
|
||||
DELETE_AND_FREE( m_viaFrontCover )
|
||||
DELETE_AND_FREE( m_viaBackCover )
|
||||
}
|
||||
|
||||
|
||||
@ -968,6 +972,17 @@ void RENDER_3D_OPENGL::renderSolderMaskLayer( PCB_LAYER_ID aLayerID, float aZPos
|
||||
setLayerMaterial( aLayerID );
|
||||
m_board->SetItIsTransparent( true );
|
||||
m_board->DrawCulled( aShowThickness, solder_mask, via_holes );
|
||||
|
||||
if( aLayerID == F_Mask && m_viaFrontCover )
|
||||
{
|
||||
m_viaFrontCover->ApplyScalePosition( aZPos, 4 * m_boardAdapter.GetNonCopperLayerThickness() );
|
||||
m_viaFrontCover->DrawTop();
|
||||
}
|
||||
else if( aLayerID == B_Mask && m_viaBackCover )
|
||||
{
|
||||
m_viaBackCover->ApplyScalePosition( aZPos, 4 * m_boardAdapter.GetNonCopperLayerThickness() );
|
||||
m_viaBackCover->DrawBot();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,6 +123,14 @@ private:
|
||||
float aZtop, float aZbot, unsigned int aNr_sides_per_circle,
|
||||
TRIANGLE_DISPLAY_LIST* aDstLayer );
|
||||
|
||||
void generateDisk( const SFVEC2F& aCenter, float aRadius, float aZ,
|
||||
unsigned int aNr_sides_per_circle, TRIANGLE_DISPLAY_LIST* aDstLayer,
|
||||
bool aTop );
|
||||
|
||||
void generateDimple( const SFVEC2F& aCenter, float aRadius, float aZ, float aDepth,
|
||||
unsigned int aNr_sides_per_circle, TRIANGLE_DISPLAY_LIST* aDstLayer,
|
||||
bool aTop );
|
||||
|
||||
void generateViasAndPads();
|
||||
|
||||
/**
|
||||
@ -236,6 +244,8 @@ private:
|
||||
|
||||
OPENGL_RENDER_LIST* m_microviaHoles;
|
||||
OPENGL_RENDER_LIST* m_padHoles;
|
||||
OPENGL_RENDER_LIST* m_viaFrontCover;
|
||||
OPENGL_RENDER_LIST* m_viaBackCover;
|
||||
|
||||
// Caches
|
||||
std::map<wxString, MODEL_3D*> m_3dModelMap;
|
||||
|
@ -277,7 +277,7 @@ void RENDER_3D_RAYTRACE_BASE::renderTracing( uint8_t* ptrPBO, REPORTER* aStatusR
|
||||
BS::multi_future<void> futures;
|
||||
|
||||
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();
|
||||
|
||||
@ -486,9 +486,12 @@ void RENDER_3D_RAYTRACE_BASE::renderBlockTracing( uint8_t* ptrPBO, signed int iB
|
||||
// Initialize ray packets
|
||||
const SFVEC2UI& blockPos = m_blockPositions[iBlock];
|
||||
const SFVEC2I blockPosI = SFVEC2I( blockPos.x + m_xoffset, blockPos.y + m_yoffset );
|
||||
const SFVEC2F randDisp = ( m_camera.GetProjection() == PROJECTION_TYPE::ORTHO ) ?
|
||||
SFVEC2F( 0.0f, 0.0f ) :
|
||||
SFVEC2F( DISP_FACTOR, DISP_FACTOR );
|
||||
|
||||
RAYPACKET blockPacket( m_camera, (SFVEC2F) blockPosI + SFVEC2F( DISP_FACTOR, DISP_FACTOR ),
|
||||
SFVEC2F( DISP_FACTOR, DISP_FACTOR ) /* Displacement random factor */ );
|
||||
RAYPACKET blockPacket( m_camera, (SFVEC2F) blockPosI + randDisp,
|
||||
randDisp /* Displacement random factor */ );
|
||||
|
||||
|
||||
HITINFO_PACKET hitPacket_X0Y0[RAYPACKET_RAYS_PER_PACKET];
|
||||
@ -566,7 +569,7 @@ void RENDER_3D_RAYTRACE_BASE::renderBlockTracing( uint8_t* ptrPBO, signed int iB
|
||||
HITINFO_PACKET_init( hitPacket_AA_X1Y1 );
|
||||
|
||||
RAYPACKET blockPacket_AA_X1Y1( m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.5f, 0.5f ),
|
||||
SFVEC2F( DISP_FACTOR, DISP_FACTOR ) );
|
||||
randDisp );
|
||||
|
||||
if( !m_accelerator->Intersect( blockPacket_AA_X1Y1, hitPacket_AA_X1Y1 ) )
|
||||
{
|
||||
@ -603,16 +606,16 @@ void RENDER_3D_RAYTRACE_BASE::renderBlockTracing( uint8_t* ptrPBO, signed int iB
|
||||
RAY blockRayPck_AA_X1Y1_half[RAYPACKET_RAYS_PER_PACKET];
|
||||
|
||||
RAYPACKET_InitRays_with2DDisplacement(
|
||||
m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.5f - DISP_FACTOR, DISP_FACTOR ),
|
||||
SFVEC2F( DISP_FACTOR, DISP_FACTOR ), blockRayPck_AA_X1Y0 );
|
||||
m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.5f - randDisp.x, randDisp.y ),
|
||||
randDisp, blockRayPck_AA_X1Y0 );
|
||||
|
||||
RAYPACKET_InitRays_with2DDisplacement(
|
||||
m_camera, (SFVEC2F) blockPosI + SFVEC2F( DISP_FACTOR, 0.5f - DISP_FACTOR ),
|
||||
SFVEC2F( DISP_FACTOR, DISP_FACTOR ), blockRayPck_AA_X0Y1 );
|
||||
m_camera, (SFVEC2F) blockPosI + SFVEC2F( randDisp.x, 0.5f - randDisp.y ),
|
||||
randDisp, blockRayPck_AA_X0Y1 );
|
||||
|
||||
RAYPACKET_InitRays_with2DDisplacement(
|
||||
m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.25f - DISP_FACTOR, 0.25f - DISP_FACTOR ),
|
||||
SFVEC2F( DISP_FACTOR, DISP_FACTOR ), blockRayPck_AA_X1Y1_half );
|
||||
m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.25f - randDisp.x, 0.25f - randDisp.y ),
|
||||
randDisp, blockRayPck_AA_X1Y1_half );
|
||||
|
||||
renderAntiAliasPackets( bgColor, hitPacket_X0Y0, hitPacket_AA_X1Y1, blockRayPck_AA_X1Y0,
|
||||
hitColor_AA_X1Y0 );
|
||||
|
@ -6,7 +6,12 @@
|
||||
},
|
||||
{
|
||||
"environment": "vcpkg",
|
||||
"VcPkgDir": "D:/vcpkg/"
|
||||
"VcPkgDir": "D:/vcpkg/",
|
||||
"VCPKG_BINARY_SOURCES": "nuget,kicad-gitlab,read"
|
||||
},
|
||||
{
|
||||
"environment": "swig",
|
||||
"SwigExePath": "D:/swigwin-4.1.1/swig.exe"
|
||||
}
|
||||
],
|
||||
"configurations": [
|
||||
@ -14,7 +19,7 @@
|
||||
"name": "x64-Debug",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Debug",
|
||||
"inheritEnvironments": [ "msvc_x64_x64", "vcpkg" ],
|
||||
"inheritEnvironments": [ "msvc_x64_x64", "vcpkg", "swig"],
|
||||
"buildRoot": "${env.BuildDir}\\${name}",
|
||||
"installRoot": "${env.InstallDir}\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
@ -30,6 +35,21 @@
|
||||
"name": "KICAD_WIN32_DPI_AWARE",
|
||||
"value": "ON",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "SWIG_EXECUTABLE",
|
||||
"value": "${env.SwigExePath}",
|
||||
"type": "STRING"
|
||||
},
|
||||
{
|
||||
"name": "VCPKG_OVERLAY_TRIPLETS",
|
||||
"value": "${workspaceRoot}/tools/custom_vcpkg_triplets",
|
||||
"type": "STRING"
|
||||
},
|
||||
{
|
||||
"name": "VCPKG_INSTALL_OPTIONS",
|
||||
"value": "--x-abi-tools-use-exact-versions",
|
||||
"type": "STRING"
|
||||
}
|
||||
],
|
||||
"cmakeToolchain": "${env.VcPkgDir}/scripts/buildsystems/vcpkg.cmake"
|
||||
@ -38,7 +58,7 @@
|
||||
"name": "x64-Release",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "RelWithDebInfo",
|
||||
"inheritEnvironments": [ "msvc_x64_x64", "vcpkg" ],
|
||||
"inheritEnvironments": [ "msvc_x64_x64", "vcpkg", "swig"],
|
||||
"buildRoot": "${env.BuildDir}\\${name}",
|
||||
"installRoot": "${env.InstallDir}\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
@ -54,6 +74,21 @@
|
||||
"name": "KICAD_WIN32_DPI_AWARE",
|
||||
"value": "ON",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "SWIG_EXECUTABLE",
|
||||
"value": "${env.SwigExePath}",
|
||||
"type": "STRING"
|
||||
},
|
||||
{
|
||||
"name": "VCPKG_OVERLAY_TRIPLETS",
|
||||
"value": "${workspaceRoot}/tools/custom_vcpkg_triplets",
|
||||
"type": "STRING"
|
||||
},
|
||||
{
|
||||
"name": "VCPKG_INSTALL_OPTIONS",
|
||||
"value": "--x-abi-tools-use-exact-versions",
|
||||
"type": "STRING"
|
||||
}
|
||||
],
|
||||
"cmakeToolchain": "${env.VcPkgDir}/scripts/buildsystems/vcpkg.cmake"
|
||||
|
@ -130,6 +130,9 @@ set( KICOMMON_SRCS
|
||||
project/project_local_settings.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
|
||||
tool/ui/toolbar_configuration.cpp
|
||||
|
||||
@ -630,7 +633,8 @@ set( COMMON_GIT_SRCS
|
||||
git/project_git_utils.cpp
|
||||
git/kicad_git_common.cpp
|
||||
git/kicad_git_errors.cpp
|
||||
git/project_git_utils.cpp
|
||||
git/git_backend.cpp
|
||||
git/libgit_backend.cpp
|
||||
)
|
||||
|
||||
set( COMMON_SRCS
|
||||
@ -1014,6 +1018,13 @@ generate_lemon_grammar(
|
||||
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
|
||||
# Called twice one for common and one for gal, to ensure the files are created
|
||||
# on all devel tools ( Linux and msys2 )
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "clipboard.h"
|
||||
|
||||
#include <wx/clipbrd.h>
|
||||
#include <wx/dataobj.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/string.h>
|
||||
@ -90,10 +91,10 @@ std::unique_ptr<wxImage> GetImageFromClipboard()
|
||||
{
|
||||
if( wxTheClipboard->IsSupported( wxDF_BITMAP ) )
|
||||
{
|
||||
wxImageDataObject data;
|
||||
wxBitmapDataObject data;
|
||||
if( wxTheClipboard->GetData( data ) )
|
||||
{
|
||||
image = std::make_unique<wxImage>( data.GetImage() );
|
||||
image = std::make_unique<wxImage>( data.GetBitmap().ConvertToImage() );
|
||||
}
|
||||
}
|
||||
else if( wxTheClipboard->IsSupported( wxDF_FILENAME ) )
|
||||
|
@ -190,7 +190,7 @@ void DESIGN_BLOCK_LIST_IMPL::loadDesignBlocks()
|
||||
};
|
||||
|
||||
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 )
|
||||
{
|
||||
|
@ -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/
|
||||
//
|
||||
// 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 );
|
||||
|
||||
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 );
|
||||
|
||||
|
@ -1,34 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<wxFormBuilder_Project>
|
||||
<FileVersion major="1" minor="17"/>
|
||||
<FileVersion major="1" minor="18"/>
|
||||
<object class="Project" expanded="true">
|
||||
<property name="class_decoration"></property>
|
||||
<property name="code_generation">C++</property>
|
||||
<property name="disconnect_events">1</property>
|
||||
<property name="disconnect_mode">source_name</property>
|
||||
<property name="disconnect_php_events">0</property>
|
||||
<property name="disconnect_python_events">0</property>
|
||||
<property name="cpp_class_decoration"></property>
|
||||
<property name="cpp_disconnect_events">1</property>
|
||||
<property name="cpp_event_generation">connect</property>
|
||||
<property name="cpp_help_provider">none</property>
|
||||
<property name="cpp_namespace"></property>
|
||||
<property name="cpp_precompiled_header"></property>
|
||||
<property name="cpp_use_array_enum">0</property>
|
||||
<property name="cpp_use_enum">0</property>
|
||||
<property name="embedded_files_path">res</property>
|
||||
<property name="encoding">UTF-8</property>
|
||||
<property name="event_generation">connect</property>
|
||||
<property name="file">dialog_text_entry_base</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="lua_skip_events">1</property>
|
||||
<property name="lua_ui_table">UI</property>
|
||||
<property name="name">dialog_text_entry_base</property>
|
||||
<property name="namespace"></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="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_native_eol">0</property>
|
||||
<object class="Dialog" expanded="true">
|
||||
<property name="aui_managed">0</property>
|
||||
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
|
||||
@ -80,10 +82,10 @@
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">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_position"></property>
|
||||
<property name="aui_row"></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>
|
||||
@ -142,10 +144,10 @@
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">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_position"></property>
|
||||
<property name="aui_row"></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>
|
||||
@ -169,7 +171,7 @@
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="maxlength"></property>
|
||||
<property name="maxlength">0</property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size">300,-1</property>
|
||||
@ -198,144 +200,6 @@
|
||||
<property name="window_style"></property>
|
||||
</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 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/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@ -18,14 +18,12 @@
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/choice.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/dialog.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class WX_TEXT_ENTRY_DIALOG_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -37,8 +35,6 @@ class WX_TEXT_ENTRY_DIALOG_BASE : public DIALOG_SHIM
|
||||
wxBoxSizer* m_mainSizer;
|
||||
wxStaticText* m_label;
|
||||
wxTextCtrl* m_textCtrl;
|
||||
wxStaticText* m_choiceLabel;
|
||||
wxChoice* m_choice;
|
||||
wxStdDialogButtonSizer* m_sdbSizer1;
|
||||
wxButton* m_sdbSizer1OK;
|
||||
wxButton* m_sdbSizer1Cancel;
|
||||
|
@ -167,9 +167,7 @@ void PANEL_EMBEDDED_FILES::resizeGrid()
|
||||
bool PANEL_EMBEDDED_FILES::TransferDataToWindow()
|
||||
{
|
||||
m_files_grid->ClearGrid();
|
||||
|
||||
if( m_files_grid->GetNumberRows() > 0 )
|
||||
m_files_grid->DeleteRows( 0, m_files_grid->GetNumberRows() );
|
||||
m_files_grid->ClearRows();
|
||||
|
||||
int ii = 0;
|
||||
|
||||
|
@ -87,6 +87,10 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin
|
||||
m_stealsFocus( true ),
|
||||
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" );
|
||||
|
||||
if( Pgm().GetCommonSettings()->m_Appearance.show_scrollbars )
|
||||
|
@ -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;
|
||||
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;
|
||||
|
||||
bool centerView = false;
|
||||
std::vector<BOX2D> dialogScreenRects;
|
||||
|
||||
for( wxWindow* dialog : findDialogs() )
|
||||
if( aAllowScroll )
|
||||
{
|
||||
dialogScreenRects.emplace_back( ToVECTOR2D( GetCanvas()->ScreenToClient( dialog->GetScreenPosition() ) ),
|
||||
ToVECTOR2D( dialog->GetSize() ) );
|
||||
}
|
||||
BOX2D r = GetCanvas()->GetView()->GetViewport();
|
||||
|
||||
// Center if we're behind an obscuring dialog, or within 10% of its edge
|
||||
for( BOX2D rect : dialogScreenRects )
|
||||
{
|
||||
rect.Inflate( rect.GetWidth() / 10 );
|
||||
// Center if we're off the current view, or within 10% of its edge
|
||||
r.Inflate( - r.GetWidth() / 10.0 );
|
||||
|
||||
if( rect.Contains( GetCanvas()->GetView()->ToScreen( aPos ) ) )
|
||||
if( !r.Contains( aPos ) )
|
||||
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 )
|
||||
|
@ -1382,6 +1382,15 @@ bool EDA_SHAPE::hitTest( const VECTOR2I& aPosition, int aAccuracy ) const
|
||||
|
||||
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
|
||||
{
|
||||
std::vector<VECTOR2I> pts = GetRectCorners();
|
||||
@ -1393,13 +1402,13 @@ bool EDA_SHAPE::hitTest( const VECTOR2I& aPosition, int aAccuracy ) const
|
||||
{
|
||||
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:
|
||||
if( IsFilledForHitTesting() )
|
||||
{
|
||||
@ -1441,6 +1450,40 @@ bool EDA_SHAPE::hitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) co
|
||||
|
||||
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 )
|
||||
{
|
||||
case SHAPE_T::CIRCLE:
|
||||
@ -1487,6 +1530,17 @@ bool EDA_SHAPE::hitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) co
|
||||
{
|
||||
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
|
||||
{
|
||||
std::vector<VECTOR2I> pts = GetRectCorners();
|
||||
@ -1528,34 +1582,8 @@ bool EDA_SHAPE::hitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) co
|
||||
|
||||
for( int ii = 0; ii < m_poly.OutlineCount(); ++ii )
|
||||
{
|
||||
const SHAPE_LINE_CHAIN& poly = m_poly.Outline( ii );
|
||||
int count = (int) poly.GetPointCount();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
if( checkOutline( m_poly.Outline( ii ) ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <font/glyph.h>
|
||||
#include <gr_text.h>
|
||||
#include <string_utils.h> // for UnescapeString
|
||||
#include <text_eval/text_eval_wrapper.h>
|
||||
#include <math/util.h> // for KiROUND
|
||||
#include <math/vector2d.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* font = GetFont();
|
||||
|
@ -1364,6 +1364,11 @@ CAIRO_GAL::CAIRO_GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions, wxWindow* aParent,
|
||||
m_currentTarget = 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_wxOutput = nullptr;
|
||||
|
||||
|
@ -22,16 +22,13 @@
|
||||
*/
|
||||
|
||||
#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>
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@ -43,66 +40,11 @@ GIT_ADD_TO_INDEX_HANDLER::~GIT_ADD_TO_INDEX_HANDLER()
|
||||
|
||||
bool GIT_ADD_TO_INDEX_HANDLER::AddToIndex( const wxString& aFilePath )
|
||||
{
|
||||
// Test if file is currently in the index
|
||||
|
||||
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;
|
||||
return GetGitBackend()->AddToIndex( this, aFilePath );
|
||||
}
|
||||
|
||||
|
||||
bool GIT_ADD_TO_INDEX_HANDLER::PerformAddToIndex()
|
||||
{
|
||||
git_index* index = nullptr;
|
||||
|
||||
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;
|
||||
return GetGitBackend()->PerformAddToIndex( this );
|
||||
}
|
||||
|
@ -24,12 +24,13 @@
|
||||
#ifndef 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 <wx/string.h>
|
||||
|
||||
class wxString;
|
||||
class LIBGIT_BACKEND;
|
||||
|
||||
class GIT_ADD_TO_INDEX_HANDLER
|
||||
class GIT_ADD_TO_INDEX_HANDLER : public KIGIT_COMMON
|
||||
{
|
||||
public:
|
||||
GIT_ADD_TO_INDEX_HANDLER( git_repository* aRepository );
|
||||
@ -40,8 +41,7 @@ public:
|
||||
bool PerformAddToIndex();
|
||||
|
||||
private:
|
||||
git_repository* m_repository;
|
||||
|
||||
friend class LIBGIT_BACKEND;
|
||||
std::vector<wxString> m_filesToAdd;
|
||||
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_backend.h"
|
||||
#include <git/kicad_git_common.h>
|
||||
#include <git/kicad_git_memory.h>
|
||||
#include <trace_helpers.h>
|
||||
@ -35,89 +36,12 @@ GIT_BRANCH_HANDLER::~GIT_BRANCH_HANDLER()
|
||||
|
||||
bool GIT_BRANCH_HANDLER::BranchExists( const wxString& aBranchName )
|
||||
{
|
||||
git_repository* repo = GetRepo();
|
||||
|
||||
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;
|
||||
return GetGitBackend()->BranchExists( this, aBranchName );
|
||||
}
|
||||
|
||||
BranchResult GIT_BRANCH_HANDLER::SwitchToBranch( const wxString& aBranchName )
|
||||
{
|
||||
git_repository* repo = GetRepo();
|
||||
|
||||
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;
|
||||
return GetGitBackend()->SwitchToBranch( this, aBranchName );
|
||||
}
|
||||
|
||||
void GIT_BRANCH_HANDLER::UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage )
|
||||
|
@ -57,15 +57,6 @@ public:
|
||||
bool BranchExists( const wxString& aBranchName );
|
||||
|
||||
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
|
@ -23,13 +23,8 @@
|
||||
|
||||
#include "git_clone_handler.h"
|
||||
|
||||
#include <git/kicad_git_common.h>
|
||||
#include <git/kicad_git_memory.h>
|
||||
#include <trace_helpers.h>
|
||||
|
||||
#include <git2.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/log.h>
|
||||
#include "git_backend.h"
|
||||
|
||||
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()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock( GetCommon()->m_gitActionMutex, std::try_to_lock );
|
||||
|
||||
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;
|
||||
return GetGitBackend()->Clone( this );
|
||||
}
|
||||
|
||||
|
||||
|
@ -22,8 +22,7 @@
|
||||
*/
|
||||
|
||||
#include "git_commit_handler.h"
|
||||
#include <git/kicad_git_memory.h>
|
||||
#include <wx/log.h>
|
||||
#include "git_backend.h"
|
||||
|
||||
GIT_COMMIT_HANDLER::GIT_COMMIT_HANDLER( git_repository* 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,
|
||||
const wxString& aMessage,
|
||||
const wxString& aAuthorName,
|
||||
const wxString& aAuthorEmail )
|
||||
{
|
||||
git_repository* repo = GetRepo();
|
||||
|
||||
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;
|
||||
return GetGitBackend()->Commit( this, aFiles, aMessage, aAuthorName, aAuthorEmail );
|
||||
}
|
||||
|
||||
|
||||
|
@ -27,25 +27,20 @@
|
||||
// Define a class to handle git commit operations
|
||||
|
||||
#include <git/kicad_git_common.h>
|
||||
#include <git2.h>
|
||||
#include "git_backend.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <wx/string.h>
|
||||
|
||||
class LIBGIT_BACKEND;
|
||||
|
||||
class GIT_COMMIT_HANDLER : public KIGIT_COMMON
|
||||
{
|
||||
public:
|
||||
GIT_COMMIT_HANDLER( git_repository* aRepo );
|
||||
virtual ~GIT_COMMIT_HANDLER();
|
||||
|
||||
enum class CommitResult
|
||||
{
|
||||
Success,
|
||||
Error,
|
||||
Cancelled
|
||||
};
|
||||
|
||||
CommitResult PerformCommit( const std::vector<wxString>& aFiles,
|
||||
const wxString& aMessage,
|
||||
const wxString& aAuthorName,
|
||||
@ -54,6 +49,7 @@ public:
|
||||
wxString GetErrorString() const;
|
||||
|
||||
private:
|
||||
friend class LIBGIT_BACKEND;
|
||||
void AddErrorString( const wxString& aErrorString );
|
||||
|
||||
wxString m_errorString;
|
||||
|
@ -22,6 +22,7 @@
|
||||
*/
|
||||
|
||||
#include "git_config_handler.h"
|
||||
#include "git_backend.h"
|
||||
#include <git/kicad_git_common.h>
|
||||
#include <git/kicad_git_memory.h>
|
||||
#include <pgm_base.h>
|
||||
@ -59,48 +60,12 @@ GitUserConfig GIT_CONFIG_HANDLER::GetUserConfig()
|
||||
|
||||
wxString GIT_CONFIG_HANDLER::GetWorkingDirectory()
|
||||
{
|
||||
git_repository* repo = GetRepo();
|
||||
|
||||
if( !repo )
|
||||
return wxEmptyString;
|
||||
|
||||
const char* workdir = git_repository_workdir( repo );
|
||||
|
||||
if( !workdir )
|
||||
return wxEmptyString;
|
||||
|
||||
return wxString( workdir );
|
||||
return GetGitBackend()->GetWorkingDirectory( this );
|
||||
}
|
||||
|
||||
bool GIT_CONFIG_HANDLER::GetConfigString( const wxString& aKey, wxString& aValue )
|
||||
{
|
||||
git_repository* repo = GetRepo();
|
||||
|
||||
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;
|
||||
return GetGitBackend()->GetConfigString( this, aKey, aValue );
|
||||
}
|
||||
|
||||
void GIT_CONFIG_HANDLER::UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage )
|
||||
|
@ -22,6 +22,7 @@
|
||||
*/
|
||||
|
||||
#include "git_init_handler.h"
|
||||
#include "git_backend.h"
|
||||
#include <git/kicad_git_common.h>
|
||||
#include <git/kicad_git_memory.h>
|
||||
#include <trace_helpers.h>
|
||||
@ -35,118 +36,17 @@ GIT_INIT_HANDLER::~GIT_INIT_HANDLER()
|
||||
|
||||
bool GIT_INIT_HANDLER::IsRepository( const wxString& aPath )
|
||||
{
|
||||
git_repository* repo = nullptr;
|
||||
int error = git_repository_open( &repo, aPath.mb_str() );
|
||||
|
||||
if( error == 0 )
|
||||
{
|
||||
git_repository_free( repo );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return GetGitBackend()->IsRepository( this, aPath );
|
||||
}
|
||||
|
||||
InitResult GIT_INIT_HANDLER::InitializeRepository( const wxString& aPath )
|
||||
{
|
||||
// Check if directory is already a git repository
|
||||
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;
|
||||
return GetGitBackend()->InitializeRepository( this, aPath );
|
||||
}
|
||||
|
||||
bool GIT_INIT_HANDLER::SetupRemote( const RemoteConfig& aConfig )
|
||||
{
|
||||
// This is an optional step
|
||||
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;
|
||||
return GetGitBackend()->SetupRemote( this, aConfig );
|
||||
}
|
||||
|
||||
void GIT_INIT_HANDLER::UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage )
|
||||
|
@ -22,188 +22,22 @@
|
||||
*/
|
||||
|
||||
#include "git_pull_handler.h"
|
||||
#include <git/kicad_git_common.h>
|
||||
#include <git/kicad_git_memory.h>
|
||||
#include <trace_helpers.h>
|
||||
|
||||
#include <wx/log.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <time.h>
|
||||
#include <memory>
|
||||
#include "git_backend.h"
|
||||
|
||||
GIT_PULL_HANDLER::GIT_PULL_HANDLER( KIGIT_COMMON* aCommon ) : KIGIT_REPO_MIXIN( aCommon )
|
||||
{
|
||||
}
|
||||
|
||||
{}
|
||||
|
||||
GIT_PULL_HANDLER::~GIT_PULL_HANDLER()
|
||||
{
|
||||
}
|
||||
|
||||
{}
|
||||
|
||||
bool GIT_PULL_HANDLER::PerformFetch( bool aSkipLock )
|
||||
{
|
||||
if( !GetRepo() )
|
||||
{
|
||||
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;
|
||||
return GetGitBackend()->PerformFetch( this, aSkipLock );
|
||||
}
|
||||
|
||||
|
||||
PullResult GIT_PULL_HANDLER::PerformPull()
|
||||
{
|
||||
PullResult result = PullResult::Success;
|
||||
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;
|
||||
return GetGitBackend()->PerformPull( this );
|
||||
}
|
||||
|
||||
const std::vector<std::pair<std::string, std::vector<CommitDetails>>>&
|
||||
@ -212,384 +46,7 @@ GIT_PULL_HANDLER::GetFetchResults() const
|
||||
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 )
|
||||
{
|
||||
|
||||
ReportProgress( aCurrent, aTotal, aMessage );
|
||||
}
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <wx/string.h>
|
||||
#include <git2.h>
|
||||
|
||||
// Structure to store commit details
|
||||
struct CommitDetails
|
||||
@ -50,22 +49,12 @@ enum class PullResult : int
|
||||
FastForward
|
||||
};
|
||||
|
||||
struct ConflictData
|
||||
{
|
||||
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 LIBGIT_BACKEND;
|
||||
|
||||
class GIT_PULL_HANDLER : public KIGIT_REPO_MIXIN
|
||||
{
|
||||
public:
|
||||
friend class LIBGIT_BACKEND;
|
||||
GIT_PULL_HANDLER( KIGIT_COMMON* aCommon );
|
||||
~GIT_PULL_HANDLER();
|
||||
|
||||
@ -77,15 +66,8 @@ public:
|
||||
// Implementation for progress updates
|
||||
void UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage ) override;
|
||||
|
||||
|
||||
private:
|
||||
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_
|
||||
|
@ -22,13 +22,8 @@
|
||||
*/
|
||||
|
||||
#include "git_push_handler.h"
|
||||
#include <git/kicad_git_common.h>
|
||||
#include <git/kicad_git_memory.h>
|
||||
#include <trace_helpers.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <wx/log.h>
|
||||
#include "git_backend.h"
|
||||
|
||||
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()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock( GetCommon()->m_gitActionMutex, std::try_to_lock );
|
||||
|
||||
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;
|
||||
return GetGitBackend()->Push( this );
|
||||
}
|
||||
|
||||
|
||||
|
@ -21,15 +21,14 @@
|
||||
* 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 <git/kicad_git_memory.h>
|
||||
#include "git_remove_from_index_handler.h"
|
||||
|
||||
GIT_REMOVE_FROM_INDEX_HANDLER::GIT_REMOVE_FROM_INDEX_HANDLER( git_repository* aRepository )
|
||||
GIT_REMOVE_FROM_INDEX_HANDLER::GIT_REMOVE_FROM_INDEX_HANDLER( git_repository* aRepository ) :
|
||||
KIGIT_COMMON( aRepository )
|
||||
{
|
||||
m_repository = aRepository;
|
||||
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 )
|
||||
{
|
||||
// Test if file is currently in the index
|
||||
|
||||
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;
|
||||
return GetGitBackend()->RemoveFromIndex( this, aFilePath );
|
||||
}
|
||||
|
||||
|
||||
void GIT_REMOVE_FROM_INDEX_HANDLER::PerformRemoveFromIndex()
|
||||
{
|
||||
for( auto& file : m_filesToRemove )
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
GetGitBackend()->PerformRemoveFromIndex( this );
|
||||
}
|
||||
|
@ -24,12 +24,13 @@
|
||||
#ifndef 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 <wx/string.h>
|
||||
|
||||
class wxString;
|
||||
class LIBGIT_BACKEND;
|
||||
|
||||
class GIT_REMOVE_FROM_INDEX_HANDLER
|
||||
class GIT_REMOVE_FROM_INDEX_HANDLER : public KIGIT_COMMON
|
||||
{
|
||||
public:
|
||||
GIT_REMOVE_FROM_INDEX_HANDLER( git_repository* aRepository );
|
||||
@ -41,7 +42,7 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
git_repository* m_repository;
|
||||
friend class LIBGIT_BACKEND;
|
||||
|
||||
std::vector<wxString> m_filesToRemove;
|
||||
};
|
||||
|
@ -22,11 +22,7 @@
|
||||
*/
|
||||
|
||||
#include "git_revert_handler.h"
|
||||
|
||||
#include <wx/log.h>
|
||||
#include <wx/string.h>
|
||||
|
||||
#include <trace_helpers.h>
|
||||
#include "git_backend.h"
|
||||
|
||||
|
||||
GIT_REVERT_HANDLER::GIT_REVERT_HANDLER( git_repository* aRepository )
|
||||
@ -46,74 +42,8 @@ bool GIT_REVERT_HANDLER::Revert( const wxString& aFilePath )
|
||||
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()
|
||||
{
|
||||
git_object* head_commit = NULL;
|
||||
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 );
|
||||
GetGitBackend()->PerformRevert( this );
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,10 @@
|
||||
#include <git2.h>
|
||||
#include <vector>
|
||||
#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
|
||||
{
|
||||
@ -44,6 +48,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
friend class LIBGIT_BACKEND;
|
||||
git_repository* m_repository;
|
||||
|
||||
std::vector<wxString> m_filesToRevert;
|
||||
|
@ -22,10 +22,8 @@
|
||||
*/
|
||||
|
||||
#include "git_status_handler.h"
|
||||
#include <git/kicad_git_common.h>
|
||||
#include <git/kicad_git_memory.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 )
|
||||
{}
|
||||
@ -35,171 +33,29 @@ GIT_STATUS_HANDLER::~GIT_STATUS_HANDLER()
|
||||
|
||||
bool GIT_STATUS_HANDLER::HasChangedFiles()
|
||||
{
|
||||
git_repository* repo = GetRepo();
|
||||
|
||||
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;
|
||||
return GetGitBackend()->HasChangedFiles( this );
|
||||
}
|
||||
|
||||
std::map<wxString, FileStatus> GIT_STATUS_HANDLER::GetFileStatus( const wxString& aPathspec )
|
||||
{
|
||||
std::map<wxString, FileStatus> fileStatusMap;
|
||||
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;
|
||||
return GetGitBackend()->GetFileStatus( this, aPathspec );
|
||||
}
|
||||
|
||||
wxString GIT_STATUS_HANDLER::GetCurrentBranchName()
|
||||
{
|
||||
git_repository* repo = GetRepo();
|
||||
|
||||
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;
|
||||
}
|
||||
return GetGitBackend()->GetCurrentBranchName( this );
|
||||
}
|
||||
|
||||
void GIT_STATUS_HANDLER::UpdateRemoteStatus( const std::set<wxString>& aLocalChanges,
|
||||
const std::set<wxString>& aRemoteChanges,
|
||||
std::map<wxString, FileStatus>& aFileStatus )
|
||||
const std::set<wxString>& aRemoteChanges,
|
||||
std::map<wxString, FileStatus>& aFileStatus )
|
||||
{
|
||||
git_repository* repo = GetRepo();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
GetGitBackend()->UpdateRemoteStatus( this, aLocalChanges, aRemoteChanges, aFileStatus );
|
||||
}
|
||||
|
||||
wxString GIT_STATUS_HANDLER::GetWorkingDirectory()
|
||||
{
|
||||
git_repository* repo = GetRepo();
|
||||
|
||||
if( !repo )
|
||||
return wxEmptyString;
|
||||
|
||||
const char* workdir = git_repository_workdir( repo );
|
||||
|
||||
if( !workdir )
|
||||
return wxEmptyString;
|
||||
|
||||
return wxString( workdir );
|
||||
return GetGitBackend()->GetWorkingDirectory( this );
|
||||
}
|
||||
|
||||
KIGIT_COMMON::GIT_STATUS GIT_STATUS_HANDLER::ConvertStatus( unsigned int aGitStatus )
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
class LIBGIT_BACKEND;
|
||||
|
||||
struct FileStatus
|
||||
{
|
||||
wxString filePath;
|
||||
@ -80,6 +82,7 @@ public:
|
||||
void UpdateProgress( int aCurrent, int aTotal, const wxString& aMessage ) override;
|
||||
|
||||
private:
|
||||
friend class LIBGIT_BACKEND;
|
||||
/**
|
||||
* Convert git status flags to KIGIT_COMMON::GIT_STATUS
|
||||
* @param aGitStatus Raw git status flags
|
||||
|
@ -33,6 +33,8 @@
|
||||
|
||||
#include <wx/string.h>
|
||||
|
||||
class LIBGIT_BACKEND;
|
||||
|
||||
class KIGIT_COMMON
|
||||
{
|
||||
|
||||
@ -174,6 +176,7 @@ protected:
|
||||
friend class GIT_PUSH_HANDLER;
|
||||
friend class GIT_PULL_HANDLER;
|
||||
friend class GIT_CLONE_HANDLER;
|
||||
friend class LIBGIT_BACKEND;
|
||||
friend class PROJECT_TREE_PANE;
|
||||
|
||||
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,58 @@
|
||||
*/
|
||||
|
||||
#include "project_git_utils.h"
|
||||
#include "kicad_git_common.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>
|
||||
#include "git_backend.h"
|
||||
|
||||
#include <wx/string.h>
|
||||
#include <string_utils.h>
|
||||
|
||||
namespace KIGIT
|
||||
{
|
||||
|
||||
git_repository* PROJECT_GIT_UTILS::GetRepositoryForFile( const char* aFilename )
|
||||
{
|
||||
git_repository* repo = nullptr;
|
||||
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;
|
||||
return GetGitBackend()->GetRepositoryForFile( aFilename );
|
||||
}
|
||||
|
||||
int PROJECT_GIT_UTILS::CreateBranch( git_repository* aRepo, const wxString& aBranchName )
|
||||
{
|
||||
git_oid head_oid;
|
||||
|
||||
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;
|
||||
return GetGitBackend()->CreateBranch( aRepo, aBranchName );
|
||||
}
|
||||
|
||||
bool PROJECT_GIT_UTILS::RemoveVCS( git_repository*& aRepo, const wxString& aProjectPath,
|
||||
bool aRemoveGitDir, wxString* aErrors )
|
||||
{
|
||||
if( aRepo )
|
||||
{
|
||||
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;
|
||||
return GetGitBackend()->RemoveVCS( aRepo, aProjectPath, aRemoveGitDir, aErrors );
|
||||
}
|
||||
|
||||
} // namespace KIGIT
|
||||
wxString PROJECT_GIT_UTILS::GetCurrentHash( const wxString& aProjectFile, bool aShort )
|
||||
{
|
||||
wxString result = wxT( "no hash" );
|
||||
git_repository* repo = PROJECT_GIT_UTILS::GetRepositoryForFile( TO_UTF8( aProjectFile ) );
|
||||
|
||||
if( repo )
|
||||
{
|
||||
git_reference* head = nullptr;
|
||||
|
||||
if( git_repository_head( &head, repo ) == 0 )
|
||||
{
|
||||
const git_oid* oid = git_reference_target( head );
|
||||
|
||||
if( oid )
|
||||
{
|
||||
char buf[41];
|
||||
size_t len = aShort ? 8 : 41;
|
||||
git_oid_tostr( buf, len, oid );
|
||||
result = wxString::FromUTF8( buf );
|
||||
}
|
||||
|
||||
git_reference_free( head );
|
||||
}
|
||||
|
||||
git_repository_free( repo );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace KIGIT
|
||||
|
@ -51,6 +51,16 @@ public:
|
||||
*/
|
||||
static int CreateBranch( git_repository* aRepo, const wxString& aBranchName );
|
||||
|
||||
/**
|
||||
* Return the current HEAD commit hash for the repository containing aProjectFile.
|
||||
*
|
||||
* @param aProjectFile Absolute path to any file within the repository (typically the
|
||||
* project file path).
|
||||
* @param aShort If true, return the short (8 char) hash, otherwise full hash.
|
||||
* @return wxString containing the hash or "no hash" if unavailable.
|
||||
*/
|
||||
static wxString GetCurrentHash( const wxString& aProjectFile, bool aShort );
|
||||
|
||||
/**
|
||||
* Remove version control from a directory by freeing the repository and
|
||||
* optionally removing the .git directory.
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <trigo.h>
|
||||
#include <math/util.h> // for KiROUND
|
||||
#include <font/font.h>
|
||||
#include <text_eval/text_eval_wrapper.h>
|
||||
|
||||
#include <callback_gal.h>
|
||||
|
||||
@ -100,8 +101,15 @@ int GRTextWidth( const wxString& aText, KIFONT::FONT* aFont, const VECTOR2I& aSi
|
||||
{
|
||||
if( !aFont )
|
||||
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 );
|
||||
}
|
||||
|
||||
@ -114,6 +122,13 @@ void GRPrintText( wxDC* aDC, const VECTOR2I& aPos, const COLOR4D& aColor, const
|
||||
{
|
||||
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
|
||||
bool fill_mode = true;
|
||||
wxString evaluatedText( aText );
|
||||
|
||||
if( evaluatedText.Contains( wxS( "@{" ) ) )
|
||||
{
|
||||
EXPRESSION_EVALUATOR evaluator;
|
||||
evaluatedText = evaluator.Evaluate( evaluatedText );
|
||||
}
|
||||
|
||||
if( !aFont )
|
||||
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_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/wfstream.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_CTRL_BASE wxT( "Ctrl+" )
|
||||
#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 )
|
||||
@ -175,6 +180,14 @@ wxString KeyNameFromKeyCode( int aKeycode, bool* aIsFound )
|
||||
return wxString( MODIFIER_SHIFT ).BeforeFirst( '+' );
|
||||
else if( aKeycode == WXK_ALT )
|
||||
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"
|
||||
if( (aKeycode & MD_CTRL) != 0 )
|
||||
@ -186,7 +199,16 @@ wxString KeyNameFromKeyCode( int aKeycode, bool* aIsFound )
|
||||
if( (aKeycode & MD_SHIFT) != 0 )
|
||||
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 ) )
|
||||
{
|
||||
@ -262,7 +284,7 @@ int KeyCodeFromKeyName( const wxString& keyname )
|
||||
{
|
||||
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
|
||||
wxString key = keyname;
|
||||
wxString prefix;
|
||||
@ -292,6 +314,26 @@ int KeyCodeFromKeyName( const wxString& keyname )
|
||||
modifier |= MD_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
|
||||
{
|
||||
break;
|
||||
|
@ -40,8 +40,7 @@ JOB_EXPORT_SCH_BOM::JOB_EXPORT_SCH_BOM() :
|
||||
m_sortField(),
|
||||
m_sortAsc( true ),
|
||||
m_filterString(),
|
||||
m_excludeDNP( false ),
|
||||
m_includeExcludedFromBOM( false )
|
||||
m_excludeDNP( false )
|
||||
{
|
||||
m_params.emplace_back( new JOB_PARAM<wxString>( "field_delimiter",
|
||||
&m_fieldDelimiter,
|
||||
@ -70,13 +69,8 @@ JOB_EXPORT_SCH_BOM::JOB_EXPORT_SCH_BOM() :
|
||||
m_fieldsGroupBy ) );
|
||||
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<wxString>( "filter_string",
|
||||
&m_filterString,
|
||||
m_filterString ) );
|
||||
m_params.emplace_back( new JOB_PARAM<wxString>( "filter_string", &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>( "include_excluded_from_bom",
|
||||
&m_includeExcludedFromBOM,
|
||||
m_includeExcludedFromBOM ) );
|
||||
|
||||
m_params.emplace_back( new JOB_PARAM<wxString>( "bom_preset_name",
|
||||
&m_bomPresetName,
|
||||
|
@ -55,7 +55,6 @@ public:
|
||||
bool m_sortAsc;
|
||||
wxString m_filterString;
|
||||
bool m_excludeDNP;
|
||||
bool m_includeExcludedFromBOM;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -19,11 +19,23 @@
|
||||
|
||||
#include "lib_table_grid_tricks.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 ) :
|
||||
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 );
|
||||
}
|
||||
}
|
||||
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 )
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <wx/wupdlock.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/dc.h>
|
||||
#include <wx/log.h>
|
||||
#include <string_utils.h>
|
||||
|
||||
|
||||
@ -308,6 +309,15 @@ void LIB_TREE_MODEL_ADAPTER::UpdateSearchString( const wxString& aSearch, bool a
|
||||
|
||||
const LIB_TREE_NODE* firstMatch = ShowResults();
|
||||
|
||||
#ifdef __WXGTK__
|
||||
// Ensure the control is repainted with the updated data. Without an explicit
|
||||
// refresh the Gtk port can display stale rows until the user interacts with
|
||||
// them, leading to mismatched tree contents.
|
||||
m_widget->Refresh();
|
||||
m_widget->Update();
|
||||
wxYield();
|
||||
#endif
|
||||
|
||||
if( firstMatch )
|
||||
{
|
||||
wxDataViewItem item = ToItem( firstMatch );
|
||||
|
@ -1160,7 +1160,9 @@ void UOP::Exec( CONTEXT* ctx )
|
||||
return;
|
||||
|
||||
case TR_OP_METHOD_CALL:
|
||||
m_func( ctx, m_ref.get() );
|
||||
if( m_func )
|
||||
m_func( ctx, m_ref.get() );
|
||||
|
||||
return;
|
||||
|
||||
default:
|
||||
@ -1321,9 +1323,8 @@ VALUE* UCODE::Run( CONTEXT* ctx )
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
// rules which fail outright should not be fired
|
||||
std::unique_ptr<VALUE> temp_false = std::make_unique<VALUE>( 0 );
|
||||
return ctx->StoreValue( temp_false.get() );
|
||||
// rules which fail outright should not be fired; return 0/false
|
||||
return ctx->StoreValue( new VALUE( 0 ) );
|
||||
}
|
||||
|
||||
if( ctx->SP() == 1 )
|
||||
@ -1339,8 +1340,7 @@ VALUE* UCODE::Run( CONTEXT* ctx )
|
||||
wxASSERT( ctx->SP() == 1 );
|
||||
|
||||
// non-well-formed rules should not be fired on a release build
|
||||
std::unique_ptr<VALUE> temp_false = std::make_unique<VALUE>( 0 );
|
||||
return ctx->StoreValue( temp_false.get() );
|
||||
return ctx->StoreValue( new VALUE( 0 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,7 @@
|
||||
|
||||
#include <trigo.h>
|
||||
#include <plotters/plotter.h>
|
||||
#include <text_eval/text_eval_wrapper.h>
|
||||
#include <geometry/shape_line_chain.h>
|
||||
#include <bezier_curves.h>
|
||||
#include <callback_gal.h>
|
||||
@ -637,6 +638,13 @@ void PLOTTER::Text( const VECTOR2I& aPos,
|
||||
void* aData )
|
||||
{
|
||||
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
|
||||
wxString text( aText );
|
||||
|
||||
if( text.Contains( wxS( "@{" ) ) )
|
||||
{
|
||||
EXPRESSION_EVALUATOR evaluator;
|
||||
text = evaluator.Evaluate( text );
|
||||
}
|
||||
|
||||
SetColor( aColor );
|
||||
|
||||
@ -680,7 +688,7 @@ void PLOTTER::Text( const VECTOR2I& aPos,
|
||||
if( !aFont )
|
||||
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 )
|
||||
{
|
||||
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
|
||||
wxString text( aText );
|
||||
|
||||
if( text.Contains( wxS( "@{" ) ) )
|
||||
{
|
||||
EXPRESSION_EVALUATOR evaluator;
|
||||
text = evaluator.Evaluate( text );
|
||||
}
|
||||
|
||||
TEXT_ATTRIBUTES attributes = aAttributes;
|
||||
int penWidth = attributes.m_StrokeWidth;
|
||||
@ -725,5 +740,5 @@ void PLOTTER::PlotText( const VECTOR2I& aPos,
|
||||
if( !aFont )
|
||||
aFont = KIFONT::FONT::GetFont( m_renderSettings->GetDefaultFont() );
|
||||
|
||||
aFont->Draw( &callback_gal, aText, aPos, attributes, aFontMetrics );
|
||||
aFont->Draw( &callback_gal, text, aPos, attributes, aFontMetrics );
|
||||
}
|
||||
|
@ -36,6 +36,8 @@
|
||||
#include <kiway.h>
|
||||
#include <lockfile.h>
|
||||
#include <macros.h>
|
||||
#include <git/project_git_utils.h>
|
||||
#include <git2.h>
|
||||
#include <project.h>
|
||||
#include <project/project_file.h>
|
||||
#include <trace_helpers.h>
|
||||
@ -45,6 +47,7 @@
|
||||
#include <title_block.h>
|
||||
|
||||
|
||||
|
||||
PROJECT::PROJECT() :
|
||||
m_readOnly( false ),
|
||||
m_textVarsTicker( 0 ),
|
||||
@ -85,6 +88,16 @@ bool PROJECT::TextVarResolver( wxString* aToken ) const
|
||||
*aToken = TITLE_BLOCK::GetCurrentDate();
|
||||
return true;
|
||||
}
|
||||
else if( aToken->IsSameAs( wxT( "VCSHASH" ) ) )
|
||||
{
|
||||
*aToken = KIGIT::PROJECT_GIT_UTILS::GetCurrentHash( GetProjectFullName(), false );
|
||||
return true;
|
||||
}
|
||||
else if( aToken->IsSameAs( wxT( "VCSSHORTHASH" ) ) )
|
||||
{
|
||||
*aToken = KIGIT::PROJECT_GIT_UTILS::GetCurrentHash( GetProjectFullName(), true );
|
||||
return true;
|
||||
}
|
||||
else if( GetTextVars().count( *aToken ) > 0 )
|
||||
{
|
||||
*aToken = GetTextVars().at( *aToken );
|
||||
|
@ -24,6 +24,16 @@
|
||||
#include <properties/pg_properties.h>
|
||||
#include <widgets/color_swatch.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>
|
||||
|
||||
@ -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_COLOR_EDITOR::EDITOR_NAME = wxS( "KiCadColorEditor" );
|
||||
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 ) :
|
||||
@ -51,6 +63,9 @@ PG_UNIT_EDITOR::~PG_UNIT_EDITOR()
|
||||
|
||||
wxString PG_UNIT_EDITOR::BuildEditorName( EDA_DRAW_FRAME* aFrame )
|
||||
{
|
||||
if( !aFrame )
|
||||
return EDITOR_NAME + "NoFrame";
|
||||
|
||||
return EDITOR_NAME + aFrame->GetName();
|
||||
}
|
||||
|
||||
@ -458,3 +473,164 @@ void PG_RATIO_EDITOR::UpdateControl( wxPGProperty* aProperty, wxWindow* aCtrl )
|
||||
"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 );
|
||||
}
|
||||
|
@ -696,7 +696,9 @@ PGPROPERTY_COLOR4D::PGPROPERTY_COLOR4D( const wxString& aLabel, const wxString&
|
||||
m_backgroundColor( aBackgroundColor )
|
||||
{
|
||||
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 );
|
||||
#else
|
||||
SetFlag( wxPG_PROP_NOEDITOR );
|
||||
|
@ -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_CrossProbing.auto_highlight, true ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<bool>( "cross_probing.flash_selection",
|
||||
&m_CrossProbing.flash_selection, false ) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -72,7 +72,7 @@ GAL_LAYER_ID RenderLayerFromVisibilityLayer( VISIBILITY_LAYER aLayer )
|
||||
case VISIBILITY_LAYER::FOOTPRINT_REFERENCES: return LAYER_FP_REFERENCES;
|
||||
case VISIBILITY_LAYER::FOOTPRINT_TEXT: return LAYER_FP_TEXT;
|
||||
case VISIBILITY_LAYER::FOOTPRINT_ANCHORS: return LAYER_ANCHOR;
|
||||
case VISIBILITY_LAYER::POINTS: return LAYER_POINTS;
|
||||
case VISIBILITY_LAYER::LY_POINTS: return LAYER_POINTS;
|
||||
case VISIBILITY_LAYER::RATSNEST: return LAYER_RATSNEST;
|
||||
case VISIBILITY_LAYER::DRC_WARNINGS: return LAYER_DRC_WARNING;
|
||||
case VISIBILITY_LAYER::DRC_ERRORS: return LAYER_DRC_ERROR;
|
||||
@ -104,7 +104,7 @@ std::optional<VISIBILITY_LAYER> VisibilityLayerFromRenderLayer( GAL_LAYER_ID aLa
|
||||
case LAYER_FP_REFERENCES: return VISIBILITY_LAYER::FOOTPRINT_REFERENCES;
|
||||
case LAYER_FP_TEXT: return VISIBILITY_LAYER::FOOTPRINT_TEXT;
|
||||
case LAYER_ANCHOR: return VISIBILITY_LAYER::FOOTPRINT_ANCHORS;
|
||||
case LAYER_POINTS: return VISIBILITY_LAYER::POINTS;
|
||||
case LAYER_POINTS: return VISIBILITY_LAYER::LY_POINTS;
|
||||
case LAYER_RATSNEST: return VISIBILITY_LAYER::RATSNEST;
|
||||
case LAYER_DRC_WARNING: return VISIBILITY_LAYER::DRC_WARNINGS;
|
||||
case LAYER_DRC_ERROR: return VISIBILITY_LAYER::DRC_ERRORS;
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <fmt/chrono.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/regex.h>
|
||||
#include <wx/tokenzr.h>
|
||||
#include "locale_io.h"
|
||||
|
||||
|
||||
@ -1503,3 +1504,124 @@ wxString NormalizeFileUri( const wxString& aFileUri )
|
||||
|
||||
return retv;
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// Extract (prefix, numericValue) where numericValue = -1 if no numeric suffix
|
||||
std::pair<wxString, long> ParseAlphaNumericPin( const wxString& pinNum )
|
||||
{
|
||||
wxString prefix;
|
||||
long numValue = -1;
|
||||
|
||||
size_t numStart = pinNum.length();
|
||||
for( int i = static_cast<int>( pinNum.length() ) - 1; i >= 0; --i )
|
||||
{
|
||||
if( !wxIsdigit( pinNum[i] ) )
|
||||
{
|
||||
numStart = i + 1;
|
||||
break;
|
||||
}
|
||||
if( i == 0 )
|
||||
numStart = 0; // all digits
|
||||
}
|
||||
|
||||
if( numStart < pinNum.length() )
|
||||
{
|
||||
prefix = pinNum.Left( numStart );
|
||||
wxString numericPart = pinNum.Mid( numStart );
|
||||
numericPart.ToLong( &numValue );
|
||||
}
|
||||
|
||||
return { prefix, numValue };
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<wxString> ExpandStackedPinNotation( const wxString& aPinName, bool* aValid )
|
||||
{
|
||||
if( aValid )
|
||||
*aValid = true;
|
||||
|
||||
std::vector<wxString> expanded;
|
||||
|
||||
const bool hasOpenBracket = aPinName.Contains( wxT( "[" ) );
|
||||
const bool hasCloseBracket = aPinName.Contains( wxT( "]" ) );
|
||||
|
||||
if( hasOpenBracket || hasCloseBracket )
|
||||
{
|
||||
if( !aPinName.StartsWith( wxT( "[" ) ) || !aPinName.EndsWith( wxT( "]" ) ) )
|
||||
{
|
||||
if( aValid )
|
||||
*aValid = false;
|
||||
expanded.push_back( aPinName );
|
||||
return expanded;
|
||||
}
|
||||
}
|
||||
|
||||
if( !aPinName.StartsWith( wxT( "[" ) ) || !aPinName.EndsWith( wxT( "]" ) ) )
|
||||
{
|
||||
expanded.push_back( aPinName );
|
||||
return expanded;
|
||||
}
|
||||
|
||||
const wxString inner = aPinName.Mid( 1, aPinName.Length() - 2 );
|
||||
|
||||
size_t start = 0;
|
||||
while( start < inner.length() )
|
||||
{
|
||||
size_t comma = inner.find( ',', start );
|
||||
wxString part = ( comma == wxString::npos ) ? inner.Mid( start ) : inner.Mid( start, comma - start );
|
||||
part.Trim( true ).Trim( false );
|
||||
if( part.empty() )
|
||||
{
|
||||
start = ( comma == wxString::npos ) ? inner.length() : comma + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
int dashPos = part.Find( '-' );
|
||||
if( dashPos != wxNOT_FOUND )
|
||||
{
|
||||
wxString startTxt = part.Left( dashPos );
|
||||
wxString endTxt = part.Mid( dashPos + 1 );
|
||||
startTxt.Trim( true ).Trim( false );
|
||||
endTxt.Trim( true ).Trim( false );
|
||||
|
||||
auto [startPrefix, startVal] = ParseAlphaNumericPin( startTxt );
|
||||
auto [endPrefix, endVal] = ParseAlphaNumericPin( endTxt );
|
||||
|
||||
if( startPrefix != endPrefix || startVal == -1 || endVal == -1 || startVal > endVal )
|
||||
{
|
||||
if( aValid )
|
||||
*aValid = false;
|
||||
expanded.clear();
|
||||
expanded.push_back( aPinName );
|
||||
return expanded;
|
||||
}
|
||||
|
||||
for( long ii = startVal; ii <= endVal; ++ii )
|
||||
{
|
||||
if( startPrefix.IsEmpty() )
|
||||
expanded.emplace_back( wxString::Format( wxT( "%ld" ), ii ) );
|
||||
else
|
||||
expanded.emplace_back( wxString::Format( wxT( "%s%ld" ), startPrefix, ii ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
expanded.push_back( part );
|
||||
}
|
||||
|
||||
if( comma == wxString::npos )
|
||||
break;
|
||||
start = comma + 1;
|
||||
}
|
||||
|
||||
if( expanded.empty() )
|
||||
{
|
||||
expanded.push_back( aPinName );
|
||||
if( aValid )
|
||||
*aValid = false;
|
||||
}
|
||||
|
||||
return expanded;
|
||||
}
|
||||
|
200
common/text_eval/text_eval.lemon
Normal file
200
common/text_eval/text_eval.lemon
Normal file
@ -0,0 +1,200 @@
|
||||
%include {
|
||||
#include <text_eval/text_eval_parser.h>
|
||||
using namespace calc_parser;
|
||||
}
|
||||
|
||||
%token_type {calc_parser::TOKEN_TYPE}
|
||||
%token_prefix KI_EVAL_
|
||||
%default_type {calc_parser::NODE*}
|
||||
%extra_argument {calc_parser::DOC** pDocument}
|
||||
|
||||
%type document {calc_parser::DOC*}
|
||||
%type content_list {calc_parser::DOC*}
|
||||
%type content_item {calc_parser::NODE*}
|
||||
%type calculation {calc_parser::NODE*}
|
||||
%type expression {calc_parser::NODE*}
|
||||
%type term {calc_parser::NODE*}
|
||||
%type factor {calc_parser::NODE*}
|
||||
%type variable {calc_parser::NODE*}
|
||||
%type function_call {calc_parser::NODE*}
|
||||
%type arg_list {std::vector<std::unique_ptr<NODE>>*}
|
||||
|
||||
%destructor document { delete $$; }
|
||||
%destructor content_list { delete $$; }
|
||||
%destructor content_item { delete $$; }
|
||||
%destructor calculation { delete $$; }
|
||||
%destructor expression { delete $$; }
|
||||
%destructor term { delete $$; }
|
||||
%destructor factor { delete $$; }
|
||||
%destructor variable { delete $$; }
|
||||
%destructor function_call { delete $$; }
|
||||
%destructor arg_list { delete $$; }
|
||||
|
||||
%left LT GT LE GE EQ NE.
|
||||
%left PLUS MINUS.
|
||||
%left MULTIPLY DIVIDE MODULO.
|
||||
%right UMINUS.
|
||||
%right POWER.
|
||||
%token COMMA.
|
||||
|
||||
%start_symbol document
|
||||
|
||||
// Main document structure
|
||||
document(D) ::= content_list(L). {
|
||||
D = L;
|
||||
*pDocument = D; // Store the result in the extra argument
|
||||
}
|
||||
|
||||
content_list(L) ::= . {
|
||||
L = new DOC();
|
||||
}
|
||||
|
||||
content_list(L) ::= content_list(L) content_item(I). {
|
||||
L->AddNodeRaw(I);
|
||||
}
|
||||
|
||||
content_item(I) ::= TEXT(T). {
|
||||
I = NODE::CreateTextRaw(GetTokenString(T));
|
||||
}
|
||||
|
||||
content_item(I) ::= calculation(C). {
|
||||
I = C;
|
||||
}
|
||||
|
||||
content_item(I) ::= variable(V). {
|
||||
I = NODE::CreateCalcRaw(V);
|
||||
}
|
||||
|
||||
calculation(C) ::= AT_OPEN expression(E) CLOSE_BRACE. {
|
||||
C = NODE::CreateCalcRaw(E);
|
||||
}
|
||||
|
||||
// Mathematical expressions with proper precedence
|
||||
expression(E) ::= expression(L) LT expression(R). {
|
||||
E = NODE::CreateBinOpRaw(L, '<', R);
|
||||
}
|
||||
|
||||
expression(E) ::= expression(L) GT expression(R). {
|
||||
E = NODE::CreateBinOpRaw(L, '>', R);
|
||||
}
|
||||
|
||||
expression(E) ::= expression(L) LE expression(R). {
|
||||
E = NODE::CreateBinOpRaw(L, 1, R); // Using 1 for <=
|
||||
}
|
||||
|
||||
expression(E) ::= expression(L) GE expression(R). {
|
||||
E = NODE::CreateBinOpRaw(L, 2, R); // Using 2 for >=
|
||||
}
|
||||
|
||||
expression(E) ::= expression(L) EQ expression(R). {
|
||||
E = NODE::CreateBinOpRaw(L, 3, R); // Using 3 for ==
|
||||
}
|
||||
|
||||
expression(E) ::= expression(L) NE expression(R). {
|
||||
E = NODE::CreateBinOpRaw(L, 4, R); // Using 4 for !=
|
||||
}
|
||||
|
||||
expression(E) ::= expression(L) PLUS expression(R). {
|
||||
E = NODE::CreateBinOpRaw(L, '+', R);
|
||||
}
|
||||
|
||||
expression(E) ::= expression(L) MINUS expression(R). {
|
||||
E = NODE::CreateBinOpRaw(L, '-', R);
|
||||
}
|
||||
|
||||
expression(E) ::= term(T). {
|
||||
E = T;
|
||||
}
|
||||
|
||||
term(T) ::= term(L) MULTIPLY term(R). {
|
||||
T = NODE::CreateBinOpRaw(L, '*', R);
|
||||
}
|
||||
|
||||
term(T) ::= term(L) DIVIDE term(R). {
|
||||
T = NODE::CreateBinOpRaw(L, '/', R);
|
||||
}
|
||||
|
||||
term(T) ::= term(L) MODULO term(R). {
|
||||
T = NODE::CreateBinOpRaw(L, '%', R);
|
||||
}
|
||||
|
||||
term(T) ::= factor(F). {
|
||||
T = F;
|
||||
}
|
||||
|
||||
factor(F) ::= factor(L) POWER factor(R). {
|
||||
F = NODE::CreateBinOpRaw(L, '^', R);
|
||||
}
|
||||
|
||||
factor(F) ::= MINUS factor(R). [UMINUS] {
|
||||
F = NODE::CreateBinOpRaw(NODE::CreateNumberRaw(0.0), '-', R);
|
||||
}
|
||||
|
||||
factor(F) ::= PLUS factor(R). [UMINUS] {
|
||||
F = R;
|
||||
}
|
||||
|
||||
factor(F) ::= LPAREN expression(E) RPAREN. {
|
||||
F = E;
|
||||
}
|
||||
|
||||
factor(F) ::= NUMBER(N). {
|
||||
try
|
||||
{
|
||||
F = NODE::CreateNumberRaw( N.isString ? std::stod( GetTokenString( N ) ) : GetTokenDouble( N ) );
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
if (g_errorCollector)
|
||||
{
|
||||
g_errorCollector->AddError( fmt::format( "Invalid number format: {}", GetTokenString( N ) ) );
|
||||
}
|
||||
F = NODE::CreateNumberRaw( 0.0 );
|
||||
}
|
||||
}
|
||||
|
||||
factor(F) ::= STRING(S). {
|
||||
F = NODE::CreateStringRaw( GetTokenString( S ) );
|
||||
}
|
||||
|
||||
factor(F) ::= variable(V). {
|
||||
F = V;
|
||||
}
|
||||
|
||||
factor(F) ::= function_call(FC). {
|
||||
F = FC;
|
||||
}
|
||||
|
||||
function_call(FC) ::= IDENTIFIER(I) LPAREN RPAREN. {
|
||||
auto empty_args = new std::vector<std::unique_ptr<NODE>>();
|
||||
FC = NODE::CreateFunctionRaw(GetTokenString(I), empty_args);
|
||||
}
|
||||
|
||||
function_call(FC) ::= IDENTIFIER(I) LPAREN arg_list(AL) RPAREN. {
|
||||
FC = NODE::CreateFunctionRaw(GetTokenString(I), AL);
|
||||
}
|
||||
|
||||
arg_list(AL) ::= expression(E). {
|
||||
AL = new std::vector<std::unique_ptr<NODE>>();
|
||||
AL->emplace_back(std::unique_ptr<NODE>(E));
|
||||
}
|
||||
|
||||
arg_list(AL) ::= arg_list(AL) COMMA expression(E). {
|
||||
AL->emplace_back(std::unique_ptr<NODE>(E));
|
||||
}
|
||||
|
||||
variable(V) ::= DOLLAR_OPEN IDENTIFIER(I) CLOSE_BRACE. {
|
||||
V = NODE::CreateVarRaw(GetTokenString(I));
|
||||
}
|
||||
|
||||
%syntax_error {
|
||||
if (g_errorCollector) {
|
||||
g_errorCollector->AddSyntaxError();
|
||||
}
|
||||
}
|
||||
|
||||
%parse_failure {
|
||||
if (g_errorCollector) {
|
||||
g_errorCollector->AddParseFailure();
|
||||
}
|
||||
}
|
637
common/text_eval/text_eval_parser.cpp
Normal file
637
common/text_eval/text_eval_parser.cpp
Normal file
@ -0,0 +1,637 @@
|
||||
/*
|
||||
* 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 <text_eval/text_eval_parser.h>
|
||||
#include <fmt/format.h>
|
||||
#include <array>
|
||||
#include <cctype>
|
||||
|
||||
namespace calc_parser
|
||||
{
|
||||
thread_local ERROR_COLLECTOR* g_errorCollector = nullptr;
|
||||
|
||||
class DATE_UTILS
|
||||
{
|
||||
private:
|
||||
static constexpr int epochYear = 1970;
|
||||
static constexpr std::array<int, 12> daysInMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
static constexpr std::array<const char*, 12> monthNames = {
|
||||
"January", "February", "March", "April", "May", "June",
|
||||
"July", "August", "September", "October", "November", "December"
|
||||
};
|
||||
static constexpr std::array<const char*, 12> monthAbbrev = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
static constexpr std::array<const char*, 7> weekdayNames = {
|
||||
"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"
|
||||
};
|
||||
|
||||
static auto isLeapYear( int aYear ) -> bool
|
||||
{
|
||||
return ( aYear % 4 == 0 && aYear % 100 != 0 ) || ( aYear % 400 == 0 );
|
||||
}
|
||||
|
||||
static auto daysInYear( int aYear ) -> int
|
||||
{
|
||||
return isLeapYear( aYear ) ? 366 : 365;
|
||||
}
|
||||
|
||||
static auto daysInMonthForYear( int aMonth, int aYear ) -> int
|
||||
{
|
||||
if( aMonth == 2 && isLeapYear( aYear ) )
|
||||
return 29;
|
||||
|
||||
return daysInMonth[aMonth - 1];
|
||||
}
|
||||
|
||||
public:
|
||||
static auto DaysToYmd( int aDaysSinceEpoch ) -> std::tuple<int, int, int>
|
||||
{
|
||||
int year = epochYear;
|
||||
int remainingDays = aDaysSinceEpoch;
|
||||
|
||||
if( remainingDays >= 0 )
|
||||
{
|
||||
while( remainingDays >= daysInYear( year ) )
|
||||
{
|
||||
remainingDays -= daysInYear( year );
|
||||
year++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while( remainingDays < 0 )
|
||||
{
|
||||
year--;
|
||||
remainingDays += daysInYear( year );
|
||||
}
|
||||
}
|
||||
|
||||
int month = 1;
|
||||
while( month <= 12 && remainingDays >= daysInMonthForYear( month, year ) )
|
||||
{
|
||||
remainingDays -= daysInMonthForYear( month, year );
|
||||
month++;
|
||||
}
|
||||
|
||||
int day = remainingDays + 1;
|
||||
return {year, month, day};
|
||||
}
|
||||
|
||||
static auto YmdToDays( int aYear, int aMonth, int aDay ) -> int
|
||||
{
|
||||
int totalDays = 0;
|
||||
|
||||
if( aYear >= epochYear )
|
||||
{
|
||||
for( int y = epochYear; y < aYear; ++y )
|
||||
totalDays += daysInYear( y );
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int y = aYear; y < epochYear; ++y )
|
||||
totalDays -= daysInYear( y );
|
||||
}
|
||||
|
||||
for( int m = 1; m < aMonth; ++m )
|
||||
totalDays += daysInMonthForYear( m, aYear );
|
||||
|
||||
totalDays += aDay - 1;
|
||||
return totalDays;
|
||||
}
|
||||
|
||||
static auto ParseDate( const std::string& aDateStr ) -> std::optional<int>
|
||||
{
|
||||
std::istringstream iss( aDateStr );
|
||||
std::string token;
|
||||
std::vector<int> parts;
|
||||
|
||||
char separator = 0;
|
||||
bool isCjkFormat = false;
|
||||
|
||||
// Check for CJK date formats first (Chinese, Korean, or mixed)
|
||||
bool hasChineseYear = aDateStr.find( "年" ) != std::string::npos;
|
||||
bool hasChineseMonth = aDateStr.find( "月" ) != std::string::npos;
|
||||
bool hasChineseDay = aDateStr.find( "日" ) != std::string::npos;
|
||||
bool hasKoreanYear = aDateStr.find( "년" ) != std::string::npos;
|
||||
bool hasKoreanMonth = aDateStr.find( "월" ) != std::string::npos;
|
||||
bool hasKoreanDay = aDateStr.find( "일" ) != std::string::npos;
|
||||
|
||||
// Check if we have any CJK date format (pure or mixed)
|
||||
if( (hasChineseYear || hasKoreanYear) &&
|
||||
(hasChineseMonth || hasKoreanMonth) &&
|
||||
(hasChineseDay || hasKoreanDay) )
|
||||
{
|
||||
// CJK format: Support pure Chinese, pure Korean, or mixed formats
|
||||
isCjkFormat = true;
|
||||
|
||||
size_t yearPos, monthPos, dayPos;
|
||||
|
||||
// Find year position and marker
|
||||
if( hasChineseYear )
|
||||
yearPos = aDateStr.find( "年" );
|
||||
else
|
||||
yearPos = aDateStr.find( "년" );
|
||||
|
||||
// Find month position and marker
|
||||
if( hasChineseMonth )
|
||||
monthPos = aDateStr.find( "月" );
|
||||
else
|
||||
monthPos = aDateStr.find( "월" );
|
||||
|
||||
// Find day position and marker
|
||||
if( hasChineseDay )
|
||||
dayPos = aDateStr.find( "日" );
|
||||
else
|
||||
dayPos = aDateStr.find( "일" );
|
||||
|
||||
try
|
||||
{
|
||||
int year = std::stoi( aDateStr.substr( 0, yearPos ) );
|
||||
int month = std::stoi( aDateStr.substr( yearPos + 3, monthPos - yearPos - 3 ) ); // 3 bytes for CJK year marker
|
||||
int day = std::stoi( aDateStr.substr( monthPos + 3, dayPos - monthPos - 3 ) ); // 3 bytes for CJK month marker
|
||||
|
||||
parts = { year, month, day };
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
else if( aDateStr.find( '-' ) != std::string::npos )
|
||||
separator = '-';
|
||||
else if( aDateStr.find( '/' ) != std::string::npos )
|
||||
separator = '/';
|
||||
else if( aDateStr.find( '.' ) != std::string::npos )
|
||||
separator = '.';
|
||||
|
||||
if( separator )
|
||||
{
|
||||
while( std::getline( iss, token, separator ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
parts.push_back( std::stoi( token ) );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( !isCjkFormat && aDateStr.length() == 8 )
|
||||
{
|
||||
try
|
||||
{
|
||||
int dateNum = std::stoi( aDateStr );
|
||||
int year = dateNum / 10000;
|
||||
int month = ( dateNum / 100 ) % 100;
|
||||
int day = dateNum % 100;
|
||||
return YmdToDays( year, month, day );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
else if( !isCjkFormat )
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if( parts.empty() || parts.size() > 3 )
|
||||
return std::nullopt;
|
||||
|
||||
int year, month, day;
|
||||
|
||||
if( parts.size() == 1 )
|
||||
{
|
||||
year = parts[0];
|
||||
month = 1;
|
||||
day = 1;
|
||||
}
|
||||
else if( parts.size() == 2 )
|
||||
{
|
||||
year = parts[0];
|
||||
month = parts[1];
|
||||
day = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( isCjkFormat )
|
||||
{
|
||||
// CJK formats are always in YYYY年MM月DD日 or YYYY년 MM월 DD일 order
|
||||
year = parts[0];
|
||||
month = parts[1];
|
||||
day = parts[2];
|
||||
}
|
||||
else if( separator == '/' && parts[0] <= 12 && parts[1] <= 31 )
|
||||
{
|
||||
month = parts[0];
|
||||
day = parts[1];
|
||||
year = parts[2];
|
||||
}
|
||||
else if( separator == '/' && parts[1] <= 12 )
|
||||
{
|
||||
day = parts[0];
|
||||
month = parts[1];
|
||||
year = parts[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
year = parts[0];
|
||||
month = parts[1];
|
||||
day = parts[2];
|
||||
}
|
||||
}
|
||||
|
||||
if( month < 1 || month > 12 )
|
||||
return std::nullopt;
|
||||
if( day < 1 || day > daysInMonthForYear( month, year ) )
|
||||
return std::nullopt;
|
||||
|
||||
return YmdToDays( year, month, day );
|
||||
}
|
||||
|
||||
static auto FormatDate( int aDaysSinceEpoch, const std::string& aFormat ) -> std::string
|
||||
{
|
||||
auto [year, month, day] = DaysToYmd( aDaysSinceEpoch );
|
||||
|
||||
if( aFormat == "ISO" || aFormat == "iso" )
|
||||
return fmt::format( "{:04d}-{:02d}-{:02d}", year, month, day );
|
||||
else if( aFormat == "US" || aFormat == "us" )
|
||||
return fmt::format( "{:02d}/{:02d}/{:04d}", month, day, year );
|
||||
else if( aFormat == "EU" || aFormat == "european" )
|
||||
return fmt::format( "{:02d}/{:02d}/{:04d}", day, month, year );
|
||||
else if( aFormat == "long" )
|
||||
return fmt::format( "{} {}, {}", monthNames[month-1], day, year );
|
||||
else if( aFormat == "short" )
|
||||
return fmt::format( "{} {}, {}", monthAbbrev[month-1], day, year );
|
||||
else if( aFormat == "Chinese" || aFormat == "chinese" || aFormat == "CN" || aFormat == "cn" || aFormat == "中文" )
|
||||
return fmt::format( "{}年{:02d}月{:02d}日", year, month, day );
|
||||
else if( aFormat == "Japanese" || aFormat == "japanese" || aFormat == "JP" || aFormat == "jp" || aFormat == "日本語" )
|
||||
return fmt::format( "{}年{:02d}月{:02d}日", year, month, day );
|
||||
else if( aFormat == "Korean" || aFormat == "korean" || aFormat == "KR" || aFormat == "kr" || aFormat == "한국어" )
|
||||
return fmt::format( "{}년 {:02d}월 {:02d}일", year, month, day );
|
||||
else
|
||||
return fmt::format( "{:04d}-{:02d}-{:02d}", year, month, day );
|
||||
}
|
||||
|
||||
static auto GetWeekdayName( int aDaysSinceEpoch ) -> std::string
|
||||
{
|
||||
int weekday = ( ( aDaysSinceEpoch + 3 ) % 7 ); // +3 because epoch was Thursday (Monday = 0)
|
||||
|
||||
if( weekday < 0 )
|
||||
weekday += 7;
|
||||
|
||||
return std::string{ weekdayNames[weekday] };
|
||||
}
|
||||
|
||||
static auto GetCurrentDays() -> int
|
||||
{
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto timeT = std::chrono::system_clock::to_time_t( now );
|
||||
return static_cast<int>( timeT / ( 24 * 3600 ) );
|
||||
}
|
||||
|
||||
static auto GetCurrentTimestamp() -> double
|
||||
{
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto timeT = std::chrono::system_clock::to_time_t( now );
|
||||
return static_cast<double>( timeT );
|
||||
}
|
||||
};
|
||||
|
||||
EVAL_VISITOR::EVAL_VISITOR( VariableCallback aVariableCallback, ERROR_COLLECTOR& aErrorCollector ) :
|
||||
m_variableCallback( std::move( aVariableCallback ) ),
|
||||
m_errors( aErrorCollector ),
|
||||
m_gen( m_rd() )
|
||||
{}
|
||||
|
||||
auto EVAL_VISITOR::operator()( const NODE& aNode ) const -> Result<Value>
|
||||
{
|
||||
switch( aNode.type )
|
||||
{
|
||||
case NodeType::Number:
|
||||
return MakeValue<Value>( std::get<double>( aNode.data ) );
|
||||
|
||||
case NodeType::String:
|
||||
return MakeValue<Value>( std::get<std::string>( aNode.data ) );
|
||||
|
||||
case NodeType::Var:
|
||||
{
|
||||
const auto& varName = std::get<std::string>( aNode.data );
|
||||
|
||||
// Use callback to resolve variable
|
||||
if( m_variableCallback )
|
||||
return m_variableCallback( varName );
|
||||
|
||||
return MakeError<Value>( fmt::format( "No variable resolver configured for: {}", varName ) );
|
||||
}
|
||||
|
||||
case NodeType::BinOp:
|
||||
{
|
||||
const auto& binop = std::get<BIN_OP_DATA>( aNode.data );
|
||||
auto leftResult = binop.left->Accept( *this );
|
||||
if( !leftResult )
|
||||
return leftResult;
|
||||
|
||||
auto rightResult = binop.right ?
|
||||
binop.right->Accept( *this ) : MakeValue<Value>( 0.0 );
|
||||
if( !rightResult )
|
||||
return rightResult;
|
||||
|
||||
// Special handling for string concatenation with +
|
||||
if( binop.op == '+' )
|
||||
{
|
||||
const auto& leftVal = leftResult.GetValue();
|
||||
const auto& rightVal = rightResult.GetValue();
|
||||
|
||||
// If either operand is a string, concatenate
|
||||
if( std::holds_alternative<std::string>( leftVal ) ||
|
||||
std::holds_alternative<std::string>( rightVal ) )
|
||||
{
|
||||
return MakeValue<Value>( VALUE_UTILS::ConcatStrings( leftVal, rightVal ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, perform arithmetic
|
||||
return VALUE_UTILS::ArithmeticOp( leftResult.GetValue(), rightResult.GetValue(), binop.op );
|
||||
}
|
||||
|
||||
case NodeType::Function:
|
||||
{
|
||||
const auto& func = std::get<FUNC_DATA>( aNode.data );
|
||||
return evaluateFunction( func );
|
||||
}
|
||||
|
||||
default:
|
||||
return MakeError<Value>( "Cannot evaluate this node type" );
|
||||
}
|
||||
}
|
||||
|
||||
auto EVAL_VISITOR::evaluateFunction( const FUNC_DATA& aFunc ) const -> Result<Value>
|
||||
{
|
||||
const auto& name = aFunc.name;
|
||||
const auto& args = aFunc.args;
|
||||
|
||||
// Zero-argument functions
|
||||
if( args.empty() )
|
||||
{
|
||||
if( name == "today" )
|
||||
return MakeValue<Value>( static_cast<double>( DATE_UTILS::GetCurrentDays() ) );
|
||||
else if( name == "now" )
|
||||
return MakeValue<Value>( DATE_UTILS::GetCurrentTimestamp() );
|
||||
else if( name == "random" )
|
||||
{
|
||||
std::uniform_real_distribution<double> dis( 0.0, 1.0 );
|
||||
return MakeValue<Value>( dis( m_gen ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate arguments to mixed types
|
||||
std::vector<Value> argValues;
|
||||
argValues.reserve( args.size() );
|
||||
|
||||
for( const auto& arg : args )
|
||||
{
|
||||
auto result = arg->Accept( *this );
|
||||
if( !result )
|
||||
return result;
|
||||
|
||||
argValues.push_back( result.GetValue() );
|
||||
}
|
||||
|
||||
const auto argc = argValues.size();
|
||||
|
||||
// String formatting functions (return strings!)
|
||||
if( name == "format" && argc >= 1 )
|
||||
{
|
||||
auto numResult = VALUE_UTILS::ToDouble( argValues[0] );
|
||||
if( !numResult )
|
||||
return MakeError<Value>( numResult.GetError() );
|
||||
|
||||
const auto value = numResult.GetValue();
|
||||
int decimals = 2;
|
||||
if( argc > 1 )
|
||||
{
|
||||
auto decResult = VALUE_UTILS::ToDouble( argValues[1] );
|
||||
if( decResult )
|
||||
decimals = static_cast<int>( decResult.GetValue() );
|
||||
}
|
||||
|
||||
return MakeValue<Value>( fmt::format( "{:.{}f}", value, decimals ) );
|
||||
}
|
||||
else if( name == "currency" && argc >= 1 )
|
||||
{
|
||||
auto numResult = VALUE_UTILS::ToDouble( argValues[0] );
|
||||
if( !numResult )
|
||||
return MakeError<Value>( numResult.GetError() );
|
||||
|
||||
const auto amount = numResult.GetValue();
|
||||
const auto symbol = argc > 1 ? VALUE_UTILS::ToString( argValues[1] ) : "$";
|
||||
|
||||
return MakeValue<Value>( fmt::format( "{}{:.2f}", symbol, amount ) );
|
||||
}
|
||||
else if( name == "fixed" && argc >= 1 )
|
||||
{
|
||||
auto numResult = VALUE_UTILS::ToDouble( argValues[0] );
|
||||
if( !numResult )
|
||||
return MakeError<Value>( numResult.GetError() );
|
||||
|
||||
const auto value = numResult.GetValue();
|
||||
int decimals = 2;
|
||||
if( argc > 1 )
|
||||
{
|
||||
auto decResult = VALUE_UTILS::ToDouble( argValues[1] );
|
||||
if( decResult )
|
||||
decimals = static_cast<int>( decResult.GetValue() );
|
||||
}
|
||||
|
||||
return MakeValue<Value>( fmt::format( "{:.{}f}", value, decimals ) );
|
||||
}
|
||||
|
||||
// Date formatting functions (return strings!)
|
||||
else if( name == "dateformat" && argc >= 1 )
|
||||
{
|
||||
auto dateResult = VALUE_UTILS::ToDouble( argValues[0] );
|
||||
if( !dateResult )
|
||||
return MakeError<Value>( dateResult.GetError() );
|
||||
|
||||
const auto days = static_cast<int>( dateResult.GetValue() );
|
||||
const auto format = argc > 1 ? VALUE_UTILS::ToString( argValues[1] ) : "ISO";
|
||||
|
||||
return MakeValue<Value>( DATE_UTILS::FormatDate( days, format ) );
|
||||
}
|
||||
else if( name == "datestring" && argc == 1 )
|
||||
{
|
||||
auto dateStr = VALUE_UTILS::ToString( argValues[0] );
|
||||
auto daysResult = DATE_UTILS::ParseDate( dateStr );
|
||||
|
||||
if( !daysResult )
|
||||
return MakeError<Value>( "Invalid date format: " + dateStr );
|
||||
|
||||
return MakeValue<Value>( static_cast<double>( daysResult.value() ) );
|
||||
}
|
||||
else if( name == "weekdayname" && argc == 1 )
|
||||
{
|
||||
auto dateResult = VALUE_UTILS::ToDouble( argValues[0] );
|
||||
if( !dateResult )
|
||||
return MakeError<Value>( dateResult.GetError() );
|
||||
|
||||
const auto days = static_cast<int>( dateResult.GetValue() );
|
||||
return MakeValue<Value>( DATE_UTILS::GetWeekdayName( days ) );
|
||||
}
|
||||
|
||||
// String functions (return strings!)
|
||||
else if( name == "upper" && argc == 1 )
|
||||
{
|
||||
auto str = VALUE_UTILS::ToString( argValues[0] );
|
||||
std::transform( str.begin(), str.end(), str.begin(), ::toupper );
|
||||
return MakeValue<Value>( str );
|
||||
}
|
||||
else if( name == "lower" && argc == 1 )
|
||||
{
|
||||
auto str = VALUE_UTILS::ToString( argValues[0] );
|
||||
std::transform( str.begin(), str.end(), str.begin(), ::tolower );
|
||||
return MakeValue<Value>( str );
|
||||
}
|
||||
else if( name == "concat" && argc >= 2 )
|
||||
{
|
||||
std::string result;
|
||||
for( const auto& val : argValues )
|
||||
result += VALUE_UTILS::ToString( val );
|
||||
|
||||
return MakeValue<Value>( result );
|
||||
}
|
||||
|
||||
// Conditional functions (handle mixed types)
|
||||
if( name == "if" && argc == 3 )
|
||||
{
|
||||
// Convert only the condition to a number
|
||||
auto conditionResult = VALUE_UTILS::ToDouble( argValues[0] );
|
||||
if( !conditionResult )
|
||||
return MakeError<Value>( conditionResult.GetError() );
|
||||
|
||||
const auto condition = conditionResult.GetValue() != 0.0;
|
||||
return MakeValue<Value>( condition ? argValues[1] : argValues[2] );
|
||||
}
|
||||
|
||||
// Mathematical functions (return numbers) - convert args to doubles first
|
||||
std::vector<double> numArgs;
|
||||
for( const auto& val : argValues )
|
||||
{
|
||||
auto numResult = VALUE_UTILS::ToDouble( val );
|
||||
if( !numResult )
|
||||
return MakeError<Value>( numResult.GetError() );
|
||||
|
||||
numArgs.push_back( numResult.GetValue() );
|
||||
}
|
||||
|
||||
// Mathematical function implementations
|
||||
if( name == "abs" && argc == 1 )
|
||||
return MakeValue<Value>( std::abs( numArgs[0] ) );
|
||||
else if( name == "sum" && argc >= 1 )
|
||||
return MakeValue<Value>( std::accumulate( numArgs.begin(), numArgs.end(), 0.0 ) );
|
||||
else if( name == "round" && argc >= 1 )
|
||||
{
|
||||
const auto value = numArgs[0];
|
||||
const auto precision = argc > 1 ? static_cast<int>( numArgs[1] ) : 0;
|
||||
const auto multiplier = std::pow( 10.0, precision );
|
||||
return MakeValue<Value>( std::round( value * multiplier ) / multiplier );
|
||||
}
|
||||
else if( name == "sqrt" && argc == 1 )
|
||||
{
|
||||
if( numArgs[0] < 0 )
|
||||
return MakeError<Value>( "Square root of negative number" );
|
||||
|
||||
return MakeValue<Value>( std::sqrt( numArgs[0] ) );
|
||||
}
|
||||
else if( name == "pow" && argc == 2 )
|
||||
return MakeValue<Value>( std::pow( numArgs[0], numArgs[1] ) );
|
||||
else if( name == "floor" && argc == 1 )
|
||||
return MakeValue<Value>( std::floor( numArgs[0] ) );
|
||||
else if( name == "ceil" && argc == 1 )
|
||||
return MakeValue<Value>( std::ceil( numArgs[0] ) );
|
||||
else if( name == "min" && argc >= 1 )
|
||||
return MakeValue<Value>( *std::min_element( numArgs.begin(), numArgs.end() ) );
|
||||
else if( name == "max" && argc >= 1 )
|
||||
return MakeValue<Value>( *std::max_element( numArgs.begin(), numArgs.end() ) );
|
||||
else if( name == "avg" && argc >= 1 )
|
||||
{
|
||||
const auto sum = std::accumulate( numArgs.begin(), numArgs.end(), 0.0 );
|
||||
return MakeValue<Value>( sum / static_cast<double>( argc ) );
|
||||
}
|
||||
|
||||
return MakeError<Value>( fmt::format( "Unknown function: {} with {} arguments", name, argc ) );
|
||||
}
|
||||
|
||||
auto DOC_PROCESSOR::Process( const DOC& aDoc, VariableCallback aVariableCallback )
|
||||
-> std::pair<std::string, bool>
|
||||
{
|
||||
std::string result;
|
||||
auto localErrors = ERROR_COLLECTOR{};
|
||||
EVAL_VISITOR evaluator{ std::move( aVariableCallback ), localErrors };
|
||||
bool hadErrors = aDoc.HasErrors();
|
||||
|
||||
for( const auto& node : aDoc.GetNodes() )
|
||||
{
|
||||
switch( node->type )
|
||||
{
|
||||
case NodeType::Text:
|
||||
result += std::get<std::string>( node->data );
|
||||
break;
|
||||
|
||||
case NodeType::Calc:
|
||||
{
|
||||
const auto& calcData = std::get<BIN_OP_DATA>( node->data );
|
||||
auto evalResult = calcData.left->Accept( evaluator );
|
||||
|
||||
if( evalResult )
|
||||
result += VALUE_UTILS::ToString( evalResult.GetValue() );
|
||||
else
|
||||
{
|
||||
// Don't add error formatting to result - errors go to error vector only
|
||||
// The higher level will return original input unchanged if there are errors
|
||||
hadErrors = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
result += "[Unknown node type]";
|
||||
hadErrors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return { std::move( result ), hadErrors || localErrors.HasErrors() };
|
||||
}
|
||||
|
||||
auto DOC_PROCESSOR::ProcessWithDetails( const DOC& aDoc, VariableCallback aVariableCallback )
|
||||
-> std::tuple<std::string, std::vector<std::string>, bool>
|
||||
{
|
||||
auto [result, hadErrors] = Process( aDoc, std::move( aVariableCallback ) );
|
||||
auto allErrors = aDoc.GetErrors();
|
||||
|
||||
return { std::move( result ), std::move( allErrors ), hadErrors };
|
||||
}
|
||||
|
||||
} // namespace calc_parser
|
2067
common/text_eval/text_eval_wrapper.cpp
Normal file
2067
common/text_eval/text_eval_wrapper.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -953,17 +953,17 @@ TOOL_ACTION ACTIONS::unpinLibrary( TOOL_ACTION_ARGS()
|
||||
.FriendlyName( _( "Unpin Library" ) )
|
||||
.Tooltip( _( "No longer keep the library at the top of the list" ) ) );
|
||||
|
||||
TOOL_ACTION ACTIONS::showLibraryTable( TOOL_ACTION_ARGS()
|
||||
.Name( "common.Control.showLibraryTable" )
|
||||
TOOL_ACTION ACTIONS::showLibraryFieldsTable( TOOL_ACTION_ARGS()
|
||||
.Name( "common.Control.showLibraryFieldsTable" )
|
||||
.Scope( AS_GLOBAL )
|
||||
.FriendlyName( _( "Library Table" ) )
|
||||
.FriendlyName( _( "Library Fields Table" ) )
|
||||
.Icon( BITMAPS::table ) );
|
||||
|
||||
TOOL_ACTION ACTIONS::showRelatedLibraryTable( TOOL_ACTION_ARGS()
|
||||
.Name( "common.Control.showRelatedLibraryTable" )
|
||||
TOOL_ACTION ACTIONS::showRelatedLibraryFieldsTable( TOOL_ACTION_ARGS()
|
||||
.Name( "common.Control.showRelatedLibraryFieldsTable" )
|
||||
.Scope( AS_GLOBAL )
|
||||
.FriendlyName( _( "Edit Related Symbols as Table" ) )
|
||||
.Tooltip( _( "Edit all symbols related to the selected symbol in a table" ) )
|
||||
.FriendlyName( _( "Library Fields Table of Related Symbols" ) )
|
||||
.Tooltip( _( "Edit a table of fields of all symbols related to the selected symbol" ) )
|
||||
.Icon( BITMAPS::table ) );
|
||||
|
||||
TOOL_ACTION ACTIONS::showLibraryTree( TOOL_ACTION_ARGS()
|
||||
|
@ -61,11 +61,8 @@ EDIT_POINT* EDIT_POINTS::FindPoint( const VECTOR2I& aLocation, KIGFX::VIEW *aVie
|
||||
|
||||
if( m_allowPoints )
|
||||
{
|
||||
// Check from the end so that we get the topmost point
|
||||
for( auto r_it = m_points.rbegin(); r_it != m_points.rend(); ++r_it )
|
||||
for( EDIT_POINT& point : m_points )
|
||||
{
|
||||
EDIT_POINT& point = *r_it;
|
||||
|
||||
if( point.WithinPoint( aLocation, size ) )
|
||||
return &point;
|
||||
}
|
||||
|
@ -158,6 +158,43 @@ TOOL_DISPATCHER::~TOOL_DISPATCHER()
|
||||
delete st;
|
||||
}
|
||||
|
||||
int TOOL_DISPATCHER::decodeModifiers( const wxKeyboardState* aState )
|
||||
{
|
||||
int mods = 0;
|
||||
int wxmods = aState->GetModifiers();
|
||||
|
||||
// Returns the state of key modifiers (Alt, Ctrl and so on). Be carefull:
|
||||
// the flag wxMOD_ALTGR is defined in wxWidgets as wxMOD_CONTROL|wxMOD_ALT
|
||||
// So AltGr key cannot used as modifier key because it is the same as Alt key + Ctrl key.
|
||||
#if CAN_USE_ALTGR_KEY
|
||||
if( wxmods & wxMOD_ALTGR )
|
||||
mods |= MD_ALTGR;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if( wxmods & wxMOD_CONTROL )
|
||||
mods |= MD_CTRL;
|
||||
|
||||
if( wxmods & wxMOD_ALT )
|
||||
mods |= MD_ALT;
|
||||
}
|
||||
|
||||
if( wxmods & wxMOD_SHIFT )
|
||||
mods |= MD_SHIFT;
|
||||
|
||||
#ifdef wxMOD_META
|
||||
if( wxmods & wxMOD_META )
|
||||
mods |= MD_META;
|
||||
#endif
|
||||
|
||||
#ifdef wxMOD_WIN
|
||||
if( wxmods & wxMOD_WIN )
|
||||
mods |= MD_SUPER;
|
||||
#endif
|
||||
|
||||
return mods;
|
||||
}
|
||||
|
||||
|
||||
void TOOL_DISPATCHER::ResetState()
|
||||
{
|
||||
@ -297,7 +334,19 @@ static bool isKeyModifierOnly( int aKeyCode )
|
||||
{
|
||||
static std::vector<enum wxKeyCode> special_keys =
|
||||
{
|
||||
WXK_CONTROL, WXK_RAW_CONTROL, WXK_SHIFT, WXK_ALT
|
||||
WXK_CONTROL, WXK_RAW_CONTROL, WXK_SHIFT, WXK_ALT,
|
||||
#ifdef WXK_WINDOWS_LEFT
|
||||
WXK_WINDOWS_LEFT, WXK_WINDOWS_RIGHT,
|
||||
#endif
|
||||
#ifdef WXK_MENU
|
||||
WXK_MENU,
|
||||
#endif
|
||||
#ifdef WXK_COMMAND
|
||||
WXK_COMMAND,
|
||||
#endif
|
||||
#ifdef WXK_META
|
||||
WXK_META,
|
||||
#endif
|
||||
};
|
||||
|
||||
return alg::contains( special_keys, aKeyCode );
|
||||
@ -515,7 +564,7 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
|
||||
if( !evt && me->GetWheelRotation() != 0 )
|
||||
{
|
||||
const unsigned modBits =
|
||||
static_cast<unsigned>( mods ) & ( MD_CTRL | MD_ALT | MD_SHIFT );
|
||||
static_cast<unsigned>( mods ) & MD_MODIFIER_MASK;
|
||||
const bool shouldHandle = std::popcount( modBits ) > 1;
|
||||
|
||||
if( shouldHandle )
|
||||
|
@ -149,6 +149,9 @@ const std::string TOOL_EVENT::Format() const
|
||||
{ MD_SHIFT, "shift" },
|
||||
{ MD_CTRL, "ctrl" },
|
||||
{ MD_ALT, "alt" },
|
||||
{ MD_SUPER, "super" },
|
||||
{ MD_META, "meta" },
|
||||
{ MD_ALTGR, "altgr" },
|
||||
{ 0, "" }
|
||||
};
|
||||
|
||||
|
@ -19,54 +19,225 @@
|
||||
|
||||
#include <widgets/font_choice.h>
|
||||
#include <kiplatform/ui.h>
|
||||
#include <wx/fontenum.h>
|
||||
#include <font/fontconfig.h>
|
||||
#include <pgm_base.h>
|
||||
|
||||
#include <wx/dc.h>
|
||||
#include <wx/event.h>
|
||||
#include <wx/fontenum.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/textctrl.h>
|
||||
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <algorithm>
|
||||
#include <cwctype>
|
||||
|
||||
// The "official" name of the building Kicad stroke font (always existing)
|
||||
#include <font/kicad_font_name.h>
|
||||
|
||||
|
||||
FONT_CHOICE::FONT_CHOICE( wxWindow* aParent, int aId, wxPoint aPosition, wxSize aSize,
|
||||
int nChoices, wxString* aChoices, int aStyle ) :
|
||||
wxChoice( aParent, aId, aPosition, aSize, nChoices, aChoices, aStyle )
|
||||
class FONT_LIST_MANAGER : public wxEvtHandler
|
||||
{
|
||||
m_systemFontCount = wxChoice::GetCount();
|
||||
public:
|
||||
static FONT_LIST_MANAGER& Get();
|
||||
wxArrayString GetFonts() const;
|
||||
void Register( FONT_CHOICE* aCtrl );
|
||||
void Unregister( FONT_CHOICE* aCtrl );
|
||||
|
||||
private:
|
||||
FONT_LIST_MANAGER();
|
||||
~FONT_LIST_MANAGER();
|
||||
void Poll();
|
||||
void UpdateFonts();
|
||||
|
||||
std::thread m_thread;
|
||||
mutable std::mutex m_mutex;
|
||||
std::condition_variable m_cv;
|
||||
wxArrayString m_fonts;
|
||||
std::vector<FONT_CHOICE*> m_controls;
|
||||
std::atomic<bool> m_quit;
|
||||
};
|
||||
|
||||
FONT_LIST_MANAGER& FONT_LIST_MANAGER::Get()
|
||||
{
|
||||
static FONT_LIST_MANAGER mgr;
|
||||
return mgr;
|
||||
}
|
||||
|
||||
wxArrayString FONT_LIST_MANAGER::GetFonts() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( m_mutex );
|
||||
return m_fonts;
|
||||
}
|
||||
|
||||
void FONT_LIST_MANAGER::Register( FONT_CHOICE* aCtrl )
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( m_mutex );
|
||||
m_controls.push_back( aCtrl );
|
||||
}
|
||||
|
||||
void FONT_LIST_MANAGER::Unregister( FONT_CHOICE* aCtrl )
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( m_mutex );
|
||||
auto it = std::find( m_controls.begin(), m_controls.end(), aCtrl );
|
||||
|
||||
if( it != m_controls.end() )
|
||||
m_controls.erase( it );
|
||||
}
|
||||
|
||||
FONT_LIST_MANAGER::FONT_LIST_MANAGER()
|
||||
{
|
||||
m_quit = false;
|
||||
UpdateFonts();
|
||||
|
||||
// It appears that the polling mechanism does not work correctly
|
||||
// for mingw (hangs on exit)
|
||||
#ifndef __MINGW32__
|
||||
m_thread = std::thread( &FONT_LIST_MANAGER::Poll, this );
|
||||
#endif
|
||||
}
|
||||
|
||||
FONT_LIST_MANAGER::~FONT_LIST_MANAGER()
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( m_mutex );
|
||||
m_quit = true;
|
||||
}
|
||||
|
||||
#ifndef __MINGW32__
|
||||
m_cv.notify_one();
|
||||
|
||||
if( m_thread.joinable() )
|
||||
m_thread.join();
|
||||
#endif
|
||||
}
|
||||
|
||||
void FONT_LIST_MANAGER::Poll()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock( m_mutex );
|
||||
|
||||
while( !m_quit )
|
||||
{
|
||||
// N.B. wait_for will unlock the mutex while waiting but lock it before continuing
|
||||
// so we need to relock before continuing in the loop
|
||||
m_cv.wait_for( lock, std::chrono::seconds( 30 ), [&] { return m_quit.load(); } );
|
||||
|
||||
if( !m_quit )
|
||||
{
|
||||
lock.unlock();
|
||||
UpdateFonts();
|
||||
lock.lock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FONT_LIST_MANAGER::UpdateFonts()
|
||||
{
|
||||
std::vector<std::string> fontNames;
|
||||
Fontconfig()->ListFonts( fontNames, std::string( Pgm().GetLanguageTag().utf8_str() ) );
|
||||
|
||||
wxArrayString menuList;
|
||||
|
||||
// The initial list of fonts has on top 1 or 2 options
|
||||
// only "KiCad Font" (KICAD_FONT_NAME)
|
||||
// "Default Font" and "KiCad Font" (KICAD_FONT_NAME)
|
||||
// "KiCad Font" is also a keyword, and cannot be translated.
|
||||
// So rebuilt the starting list
|
||||
wxChoice::Clear();
|
||||
|
||||
if( m_systemFontCount > 1 )
|
||||
Append( _( "Default Font" ) );
|
||||
|
||||
Append( KICAD_FONT_NAME );
|
||||
m_systemFontCount = wxChoice::GetCount();
|
||||
|
||||
for( const std::string& name : fontNames )
|
||||
menuList.Add( wxString( name ) );
|
||||
|
||||
menuList.Sort();
|
||||
|
||||
Freeze();
|
||||
Append( menuList );
|
||||
KIPLATFORM::UI::LargeChoiceBoxHack( this );
|
||||
Thaw();
|
||||
// Check if fonts changed and update controls
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( m_mutex );
|
||||
|
||||
if( menuList == m_fonts )
|
||||
return;
|
||||
|
||||
m_fonts = menuList;
|
||||
}
|
||||
|
||||
CallAfter( [this]() {
|
||||
std::vector<FONT_CHOICE*> controlsCopy;
|
||||
|
||||
// Copy controls list under lock protection
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( m_mutex );
|
||||
controlsCopy = m_controls;
|
||||
}
|
||||
|
||||
// Update controls without holding lock
|
||||
for( FONT_CHOICE* ctrl : controlsCopy )
|
||||
{
|
||||
if( ctrl && !ctrl->IsShownOnScreen() )
|
||||
ctrl->RefreshFonts();
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
FONT_CHOICE::FONT_CHOICE( wxWindow* aParent, int aId, wxPoint aPosition, wxSize aSize,
|
||||
int nChoices, wxString* aChoices, int aStyle ) :
|
||||
wxOwnerDrawnComboBox( aParent, aId, wxEmptyString, aPosition, aSize, 0, nullptr, aStyle )
|
||||
{
|
||||
m_systemFontCount = nChoices;
|
||||
m_notFound = wxS( " " ) + _( "<not found>" );
|
||||
m_isFiltered = false;
|
||||
m_lastText = wxEmptyString;
|
||||
m_originalSelection = wxEmptyString;
|
||||
|
||||
FONT_LIST_MANAGER::Get().Register( this );
|
||||
RefreshFonts();
|
||||
|
||||
// Bind only essential events to restore functionality
|
||||
Bind( wxEVT_KEY_DOWN, &FONT_CHOICE::OnKeyDown, this );
|
||||
Bind( wxEVT_CHAR_HOOK, &FONT_CHOICE::OnCharHook, this );
|
||||
Bind( wxEVT_COMMAND_TEXT_UPDATED, &FONT_CHOICE::OnTextCtrl, this );
|
||||
Bind( wxEVT_COMBOBOX_DROPDOWN, &FONT_CHOICE::OnDropDown, this );
|
||||
Bind( wxEVT_COMBOBOX_CLOSEUP, &FONT_CHOICE::OnCloseUp, this );
|
||||
Bind( wxEVT_SET_FOCUS, &FONT_CHOICE::OnSetFocus, this );
|
||||
Bind( wxEVT_KILL_FOCUS, &FONT_CHOICE::OnKillFocus, this );
|
||||
}
|
||||
|
||||
|
||||
FONT_CHOICE::~FONT_CHOICE()
|
||||
{
|
||||
FONT_LIST_MANAGER::Get().Unregister( this );
|
||||
}
|
||||
|
||||
|
||||
void FONT_CHOICE::RefreshFonts()
|
||||
{
|
||||
wxArrayString menuList = FONT_LIST_MANAGER::Get().GetFonts();
|
||||
|
||||
wxString selection = GetValue();
|
||||
|
||||
// Store the full font list for filtering
|
||||
m_fullFontList.Clear();
|
||||
|
||||
if( m_systemFontCount > 1 )
|
||||
m_fullFontList.Add( _( "Default Font" ) );
|
||||
|
||||
m_fullFontList.Add( KICAD_FONT_NAME );
|
||||
|
||||
for( const wxString& font : menuList )
|
||||
m_fullFontList.Add( font );
|
||||
|
||||
Freeze();
|
||||
Clear();
|
||||
|
||||
if( m_systemFontCount > 1 )
|
||||
Append( _( "Default Font" ) );
|
||||
|
||||
Append( KICAD_FONT_NAME );
|
||||
m_systemFontCount = GetCount();
|
||||
|
||||
Append( menuList );
|
||||
|
||||
if( !selection.IsEmpty() )
|
||||
SetStringSelection( selection );
|
||||
|
||||
m_isFiltered = false;
|
||||
Thaw();
|
||||
}
|
||||
|
||||
|
||||
@ -86,9 +257,6 @@ void FONT_CHOICE::SetFontSelection( KIFONT::FONT* aFont, bool aSilentMode )
|
||||
SetSelection( GetCount() - 1 );
|
||||
}
|
||||
}
|
||||
|
||||
if( !aSilentMode )
|
||||
SendSelectionChangedEvent( wxEVT_CHOICE );
|
||||
}
|
||||
|
||||
|
||||
@ -118,8 +286,602 @@ KIFONT::FONT* FONT_CHOICE::GetFontSelection( bool aBold, bool aItalic, bool aFor
|
||||
}
|
||||
else
|
||||
{
|
||||
return KIFONT::FONT::GetFont( GetStringSelection(), aBold, aItalic, nullptr,
|
||||
return KIFONT::FONT::GetFont( GetValue(), aBold, aItalic, nullptr,
|
||||
aForDrawingSheet );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FONT_CHOICE::OnDrawItem( wxDC& dc, const wxRect& rect, int item, int flags ) const
|
||||
{
|
||||
if( item == wxNOT_FOUND )
|
||||
return;
|
||||
|
||||
wxString name = GetString( item );
|
||||
|
||||
dc.SetFont( wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ) );
|
||||
dc.DrawText( name, rect.x + 2, rect.y + 2 );
|
||||
|
||||
if( item >= m_systemFontCount )
|
||||
{
|
||||
wxCoord w, h;
|
||||
dc.GetTextExtent( name, &w, &h );
|
||||
wxFont sampleFont( wxFontInfo( dc.GetFont().GetPointSize() ).FaceName( name ) );
|
||||
dc.SetFont( sampleFont );
|
||||
dc.SetTextForeground( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
|
||||
dc.DrawText( wxS( "AaBbCcDd123456" ), rect.x + w + 15, rect.y + 2 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
wxString FONT_CHOICE::GetStringSelection() const
|
||||
{
|
||||
return GetValue();
|
||||
}
|
||||
|
||||
|
||||
void FONT_CHOICE::OnKeyDown( wxKeyEvent& aEvent )
|
||||
{
|
||||
int keyCode = aEvent.GetKeyCode();
|
||||
|
||||
if( keyCode == WXK_RETURN || keyCode == WXK_NUMPAD_ENTER || keyCode == WXK_ESCAPE )
|
||||
{
|
||||
if( IsPopupShown() )
|
||||
{
|
||||
// Accept current text and close popup
|
||||
Dismiss();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if( keyCode == WXK_BACK && !IsPopupShown() )
|
||||
{
|
||||
// Handle backspace when popup is not shown
|
||||
// This allows normal character-by-character deletion instead of selecting all text
|
||||
|
||||
wxString currentText = GetValue();
|
||||
long selStart, selEnd;
|
||||
GetSelection( &selStart, &selEnd );
|
||||
|
||||
if( selStart != selEnd )
|
||||
{
|
||||
// There's a selection - delete the selected text
|
||||
wxString newText = currentText.Left( selStart ) + currentText.Mid( selEnd );
|
||||
m_lastText = newText; // Prevent recursive calls
|
||||
ChangeValue( newText );
|
||||
SetInsertionPoint( selStart );
|
||||
return; // Don't skip this event
|
||||
}
|
||||
else if( selStart > 0 )
|
||||
{
|
||||
// No selection - delete character before cursor
|
||||
wxString newText = currentText.Left( selStart - 1 ) + currentText.Mid( selStart );
|
||||
m_lastText = newText; // Prevent recursive calls
|
||||
ChangeValue( newText );
|
||||
SetInsertionPoint( selStart - 1 );
|
||||
return; // Don't skip this event
|
||||
}
|
||||
// If at beginning of text, let default behavior handle it
|
||||
}
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
void FONT_CHOICE::OnCharHook( wxKeyEvent& aEvent )
|
||||
{
|
||||
int keyCode = aEvent.GetUnicodeKey();
|
||||
wchar_t wc = static_cast<wchar_t>( keyCode );
|
||||
|
||||
// When popup is not shown, let normal text processing handle printable characters
|
||||
// The OnTextCtrl method will handle filtering and autocomplete
|
||||
if( !IsPopupShown() )
|
||||
{
|
||||
aEvent.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
if( std::iswprint( wc ) && !std::iswcntrl( wc ) )
|
||||
{
|
||||
// Get current text and check if there's a selection
|
||||
wxString currentText = GetValue();
|
||||
long selStart, selEnd;
|
||||
GetSelection( &selStart, &selEnd );
|
||||
|
||||
wxChar newChar = (wxChar)keyCode;
|
||||
wxString newText;
|
||||
|
||||
if( selStart != selEnd )
|
||||
{
|
||||
// There's a selection - replace it with the new character
|
||||
newText = currentText.Left( selStart ) + newChar + currentText.Mid( selEnd );
|
||||
}
|
||||
else
|
||||
{
|
||||
// No selection - append to current insertion point
|
||||
long insertionPoint = GetInsertionPoint();
|
||||
newText = currentText.Left( insertionPoint ) + newChar + currentText.Mid( insertionPoint );
|
||||
}
|
||||
|
||||
// Update the text control
|
||||
m_lastText = newText; // Prevent recursive calls
|
||||
ChangeValue( newText );
|
||||
SetInsertionPoint( selStart + 1 ); // Position cursor after new character
|
||||
|
||||
// Filter the font list based on new text (will handle trimming internally)
|
||||
FilterFontList( newText );
|
||||
|
||||
// Try autocomplete
|
||||
DoAutoComplete( newText );
|
||||
|
||||
return; // Don't skip this event
|
||||
}
|
||||
|
||||
switch (keyCode)
|
||||
{
|
||||
case WXK_BACK:
|
||||
{
|
||||
wxString currentText = GetValue();
|
||||
long selStart, selEnd;
|
||||
GetSelection( &selStart, &selEnd );
|
||||
|
||||
wxString newText;
|
||||
long newInsertionPoint;
|
||||
|
||||
if( selStart != selEnd )
|
||||
{
|
||||
// There's a selection - delete the selected text
|
||||
newText = currentText.Left( selStart ) + currentText.Mid( selEnd );
|
||||
newInsertionPoint = selStart;
|
||||
}
|
||||
else if( selStart > 0 )
|
||||
{
|
||||
// No selection - delete character before cursor
|
||||
newText = currentText.Left( selStart - 1 ) + currentText.Mid( selStart );
|
||||
newInsertionPoint = selStart - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return; // At beginning, can't delete
|
||||
}
|
||||
|
||||
m_lastText = newText; // Prevent recursive calls
|
||||
ChangeValue( newText );
|
||||
SetInsertionPoint( newInsertionPoint );
|
||||
|
||||
// Check if trimmed text is empty
|
||||
wxString trimmedNewText = newText;
|
||||
trimmedNewText.Trim().Trim( false );
|
||||
|
||||
if( trimmedNewText.IsEmpty() )
|
||||
{
|
||||
RestoreFullFontList();
|
||||
}
|
||||
else
|
||||
{
|
||||
FilterFontList( newText );
|
||||
// Don't call DoAutoComplete for backspace to avoid the loop
|
||||
}
|
||||
|
||||
return; // Don't skip this event
|
||||
}
|
||||
case WXK_RETURN:
|
||||
case WXK_NUMPAD_ENTER:
|
||||
{
|
||||
Dismiss();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case WXK_ESCAPE:
|
||||
{
|
||||
// Restore to original selection or default font if original doesn't exist
|
||||
if( !m_originalSelection.IsEmpty() && FindBestMatch( m_originalSelection ) != wxNOT_FOUND )
|
||||
{
|
||||
SetStringSelection( m_originalSelection );
|
||||
m_lastText = m_originalSelection;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Original font doesn't exist anymore, select default font
|
||||
wxString defaultFont = GetDefaultFontName();
|
||||
SetStringSelection( defaultFont );
|
||||
m_lastText = defaultFont;
|
||||
}
|
||||
|
||||
// Restore full font list if filtered
|
||||
if( m_isFiltered )
|
||||
{
|
||||
RestoreFullFontList();
|
||||
}
|
||||
|
||||
// Only dismiss if popup is actually shown
|
||||
if( IsPopupShown() )
|
||||
{
|
||||
Dismiss();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
void FONT_CHOICE::OnTextCtrl( wxCommandEvent& aEvent )
|
||||
{
|
||||
wxString currentText = GetValue();
|
||||
|
||||
// Avoid recursive calls
|
||||
if( currentText == m_lastText )
|
||||
{
|
||||
aEvent.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
m_lastText = currentText;
|
||||
|
||||
// If popup is shown, OnCharHook handles the text input, so just skip
|
||||
if( IsPopupShown() )
|
||||
{
|
||||
aEvent.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
// Trim whitespace for processing
|
||||
wxString trimmedText = currentText;
|
||||
trimmedText.Trim().Trim(false);
|
||||
|
||||
// If text is empty or all whitespace, restore full list
|
||||
if( trimmedText.IsEmpty() )
|
||||
{
|
||||
RestoreFullFontList();
|
||||
aEvent.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
// Filter the font list based on the text input
|
||||
FilterFontList( currentText );
|
||||
|
||||
// Try to find a match for autocomplete (only when popup is not shown)
|
||||
int bestMatch = FindBestMatch( trimmedText );
|
||||
|
||||
if( bestMatch != wxNOT_FOUND )
|
||||
{
|
||||
DoAutoComplete( trimmedText );
|
||||
}
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
void FONT_CHOICE::OnDropDown( wxCommandEvent& aEvent )
|
||||
{
|
||||
// Store the original selection when dropdown opens
|
||||
m_originalSelection = GetValue();
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
void FONT_CHOICE::OnCloseUp( wxCommandEvent& aEvent )
|
||||
{
|
||||
// When dropdown closes, we should only restore the full font list
|
||||
// but NOT change the current text value unless explicitly selected
|
||||
// The OnKillFocus handler will handle text validation when focus is lost
|
||||
|
||||
// Reset to full font list if filtered
|
||||
if( m_isFiltered )
|
||||
{
|
||||
RestoreFullFontList();
|
||||
}
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
void FONT_CHOICE::OnSetFocus( wxFocusEvent& aEvent )
|
||||
{
|
||||
// When the control gains focus, select all text so user can quickly replace it
|
||||
// Only do this if we're not already showing the popup (which would indicate
|
||||
// the user is actively interacting with the dropdown)
|
||||
if( !GetValue().IsEmpty() && !IsPopupShown() )
|
||||
{
|
||||
// Use CallAfter to ensure the focus event is fully processed first
|
||||
CallAfter( [this]() {
|
||||
if( HasFocus() && !IsPopupShown() )
|
||||
SelectAll();
|
||||
} );
|
||||
}
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
void FONT_CHOICE::OnKillFocus( wxFocusEvent& aEvent )
|
||||
{
|
||||
// When losing focus, deselect text and validate/correct the font name
|
||||
|
||||
// First, deselect any selected text
|
||||
if( GetInsertionPoint() != GetLastPosition() )
|
||||
{
|
||||
SetInsertionPointEnd();
|
||||
}
|
||||
|
||||
// Get current text and trim whitespace
|
||||
wxString currentText = GetValue();
|
||||
currentText.Trim().Trim(false);
|
||||
|
||||
// If text is empty, set to default font
|
||||
if( currentText.IsEmpty() )
|
||||
{
|
||||
wxString defaultFont = GetDefaultFontName();
|
||||
SetStringSelection( defaultFont );
|
||||
m_lastText = defaultFont;
|
||||
aEvent.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to find exact match first
|
||||
if( FindBestMatch( currentText ) != wxNOT_FOUND )
|
||||
{
|
||||
// Exact match found, keep the current text but ensure it's properly set
|
||||
SetStringSelection( currentText );
|
||||
m_lastText = currentText;
|
||||
aEvent.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
// No exact match, try to find best partial match
|
||||
wxString partialMatch = FindBestPartialMatch( currentText );
|
||||
|
||||
if( !partialMatch.IsEmpty() )
|
||||
{
|
||||
SetStringSelection( partialMatch );
|
||||
m_lastText = partialMatch;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No decent partial match, fall back to default font
|
||||
wxString defaultFont = GetDefaultFontName();
|
||||
SetStringSelection( defaultFont );
|
||||
m_lastText = defaultFont;
|
||||
}
|
||||
|
||||
// Ensure we restore full font list if it was filtered
|
||||
if( m_isFiltered )
|
||||
{
|
||||
RestoreFullFontList();
|
||||
}
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
void FONT_CHOICE::DoAutoComplete( const wxString& aText )
|
||||
{
|
||||
if( aText.IsEmpty() )
|
||||
return;
|
||||
|
||||
// Find the best matching font
|
||||
int bestMatch = FindBestMatch( aText );
|
||||
|
||||
if( bestMatch == wxNOT_FOUND )
|
||||
return;
|
||||
|
||||
|
||||
wxString matchText = GetString( bestMatch );
|
||||
|
||||
// Only do autocomplete if the match is longer than what we typed
|
||||
if( matchText.Length() > aText.Length() && matchText.Lower().StartsWith( aText.Lower() ) )
|
||||
{
|
||||
// Set the text with the autocompleted portion selected
|
||||
m_lastText = matchText; // Update to prevent recursive calls
|
||||
ChangeValue( matchText );
|
||||
SetInsertionPoint( aText.Length() );
|
||||
SetSelection( aText.Length(), matchText.Length() );
|
||||
|
||||
if( IsPopupShown() )
|
||||
{
|
||||
SetSelection( bestMatch );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FONT_CHOICE::FilterFontList( const wxString& aFilter )
|
||||
{
|
||||
// Trim whitespace from filter
|
||||
wxString trimmedFilter = aFilter;
|
||||
trimmedFilter.Trim().Trim(false);
|
||||
|
||||
if( trimmedFilter.IsEmpty() )
|
||||
{
|
||||
RestoreFullFontList();
|
||||
return;
|
||||
}
|
||||
|
||||
wxArrayString filteredList;
|
||||
|
||||
// Add system fonts first
|
||||
for( int i = 0; i < m_systemFontCount; i++ )
|
||||
{
|
||||
wxString fontName = m_fullFontList[i];
|
||||
|
||||
if( fontName.Lower().StartsWith( trimmedFilter.Lower() ) )
|
||||
filteredList.Add( fontName );
|
||||
}
|
||||
|
||||
// Add matching fonts from the full list
|
||||
for( size_t i = m_systemFontCount; i < m_fullFontList.GetCount(); i++ )
|
||||
{
|
||||
wxString fontName = m_fullFontList[i];
|
||||
|
||||
if( fontName.Lower().StartsWith( trimmedFilter.Lower() ) )
|
||||
filteredList.Add( fontName );
|
||||
}
|
||||
|
||||
// Preserve the current text value
|
||||
wxString currentText = GetValue();
|
||||
|
||||
// Check if we had items before and now have none - this indicates we need to force refresh
|
||||
bool hadItemsBefore = GetCount() > 0;
|
||||
bool haveItemsNow = filteredList.GetCount() > 0;
|
||||
bool needsPopupRefresh = hadItemsBefore && !haveItemsNow && IsPopupShown();
|
||||
|
||||
// Update the combo box with filtered list (even if empty)
|
||||
Freeze();
|
||||
Clear();
|
||||
|
||||
if( haveItemsNow )
|
||||
{
|
||||
Append( filteredList );
|
||||
}
|
||||
// If no matches, leave the dropdown empty
|
||||
|
||||
m_isFiltered = true;
|
||||
|
||||
// Restore the text value after filtering
|
||||
if( !currentText.IsEmpty() )
|
||||
{
|
||||
ChangeValue( currentText );
|
||||
SetInsertionPointEnd();
|
||||
}
|
||||
|
||||
Thaw();
|
||||
|
||||
// Handle popup display
|
||||
if( needsPopupRefresh )
|
||||
{
|
||||
// We had items before but now have none - dismiss the popup
|
||||
Dismiss();
|
||||
}
|
||||
else if( !IsPopupShown() && haveItemsNow )
|
||||
{
|
||||
// Only show popup if we have items to display and control has focus
|
||||
// This prevents popup from showing during programmatic text changes
|
||||
if( HasFocus() )
|
||||
{
|
||||
Popup();
|
||||
}
|
||||
}
|
||||
else if( IsPopupShown() && !haveItemsNow )
|
||||
{
|
||||
// If popup is shown but we have no items, dismiss it
|
||||
Dismiss();
|
||||
}
|
||||
|
||||
// Force a refresh to ensure the popup displays correctly only if it's shown and has items
|
||||
if( IsPopupShown() && haveItemsNow )
|
||||
{
|
||||
Update();
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FONT_CHOICE::RestoreFullFontList()
|
||||
{
|
||||
if( !m_isFiltered )
|
||||
return;
|
||||
|
||||
wxString selection = GetValue();
|
||||
|
||||
Freeze();
|
||||
Clear();
|
||||
Append( m_fullFontList );
|
||||
m_isFiltered = false;
|
||||
|
||||
if( !selection.IsEmpty() )
|
||||
{
|
||||
ChangeValue( selection );
|
||||
SetInsertionPointEnd();
|
||||
}
|
||||
|
||||
Thaw();
|
||||
}
|
||||
|
||||
|
||||
int FONT_CHOICE::FindBestMatch( const wxString& aText )
|
||||
{
|
||||
if( aText.IsEmpty() )
|
||||
return wxNOT_FOUND;
|
||||
|
||||
// Trim whitespace from search text
|
||||
wxString trimmedText = aText;
|
||||
trimmedText.Trim().Trim(false);
|
||||
|
||||
if( trimmedText.IsEmpty() )
|
||||
return wxNOT_FOUND;
|
||||
|
||||
wxString lowerText = trimmedText.Lower();
|
||||
|
||||
// Search in the full font list to find matches, then map to current list
|
||||
for( size_t i = 0; i < m_fullFontList.GetCount(); i++ )
|
||||
{
|
||||
wxString itemText = m_fullFontList[i].Lower();
|
||||
|
||||
if( itemText.StartsWith( lowerText ) )
|
||||
{
|
||||
// Find this font in the current displayed list
|
||||
wxString fullFontName = m_fullFontList[i];
|
||||
|
||||
for( unsigned int j = 0; j < GetCount(); j++ )
|
||||
{
|
||||
if( GetString( j ) == fullFontName )
|
||||
return j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return wxNOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
wxString FONT_CHOICE::FindBestPartialMatch( const wxString& aText )
|
||||
{
|
||||
if( aText.IsEmpty() )
|
||||
return wxEmptyString;
|
||||
|
||||
// Trim whitespace from search text
|
||||
wxString trimmedText = aText;
|
||||
trimmedText.Trim().Trim(false);
|
||||
|
||||
if( trimmedText.IsEmpty() )
|
||||
return wxEmptyString;
|
||||
|
||||
wxString testText = trimmedText;
|
||||
|
||||
// Try progressively shorter versions of the text by removing characters from the end
|
||||
// Don't go below a minimum length of 2 characters for meaningful partial matches
|
||||
while( testText.Length() >= 2 )
|
||||
{
|
||||
wxString lowerTestText = testText.Lower();
|
||||
|
||||
// Search in the full font list for a match
|
||||
for( size_t i = 0; i < m_fullFontList.GetCount(); i++ )
|
||||
{
|
||||
wxString itemText = m_fullFontList[i].Lower();
|
||||
|
||||
if( itemText.StartsWith( lowerTestText ) )
|
||||
{
|
||||
// Found a match, return the full font name
|
||||
return m_fullFontList[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the last character and try again
|
||||
testText = testText.Left( testText.Length() - 1 );
|
||||
}
|
||||
|
||||
// No decent partial match found (need at least 2 characters for a meaningful match)
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
|
||||
wxString FONT_CHOICE::GetDefaultFontName() const
|
||||
{
|
||||
// Return KiCad font name as the default
|
||||
return KICAD_FONT_NAME;
|
||||
}
|
@ -640,15 +640,36 @@ void LIB_TREE::onQueryCharHook( wxKeyEvent& aKeyStroke )
|
||||
{
|
||||
int hotkey = aKeyStroke.GetKeyCode();
|
||||
|
||||
if( aKeyStroke.GetModifiers() & wxMOD_CONTROL )
|
||||
hotkey += MD_CTRL;
|
||||
int mods = aKeyStroke.GetModifiers();
|
||||
|
||||
if( aKeyStroke.GetModifiers() & wxMOD_ALT )
|
||||
hotkey += MD_ALT;
|
||||
// the flag wxMOD_ALTGR is defined in wxWidgets as wxMOD_CONTROL|wxMOD_ALT
|
||||
// So AltGr key cannot used as modifier key because it is the same as Alt key + Ctrl key.
|
||||
#if CAN_USE_ALTGR_KEY
|
||||
if( wxmods & wxMOD_ALTGR )
|
||||
mods |= MD_ALTGR;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if( mods & wxMOD_CONTROL )
|
||||
hotkey += MD_CTRL;
|
||||
|
||||
if( aKeyStroke.GetModifiers() & wxMOD_SHIFT )
|
||||
if( mods & wxMOD_ALT )
|
||||
hotkey += MD_ALT;
|
||||
}
|
||||
|
||||
if( mods & wxMOD_SHIFT )
|
||||
hotkey += MD_SHIFT;
|
||||
|
||||
#ifdef wxMOD_META
|
||||
if( mods & wxMOD_META )
|
||||
hotkey += MD_META;
|
||||
#endif
|
||||
|
||||
#ifdef wxMOD_WIN
|
||||
if( mods & wxMOD_WIN )
|
||||
hotkey += MD_SUPER;
|
||||
#endif
|
||||
|
||||
if( hotkey == ACTIONS::expandAll.GetHotKey()
|
||||
|| hotkey == ACTIONS::expandAll.GetHotKeyAlt() )
|
||||
{
|
||||
@ -860,14 +881,31 @@ void LIB_TREE::onTreeCharHook( wxKeyEvent& aKeyStroke )
|
||||
{
|
||||
int hotkey = aKeyStroke.GetKeyCode();
|
||||
|
||||
if( aKeyStroke.ShiftDown() )
|
||||
int mods = aKeyStroke.GetModifiers();
|
||||
|
||||
if( mods & wxMOD_ALTGR )
|
||||
hotkey |= MD_ALTGR;
|
||||
else
|
||||
{
|
||||
if( mods & wxMOD_ALT )
|
||||
hotkey |= MD_ALT;
|
||||
|
||||
if( mods & wxMOD_CONTROL )
|
||||
hotkey |= MD_CTRL;
|
||||
}
|
||||
|
||||
if( mods & wxMOD_SHIFT )
|
||||
hotkey |= MD_SHIFT;
|
||||
|
||||
if( aKeyStroke.AltDown() )
|
||||
hotkey |= MD_ALT;
|
||||
#ifdef wxMOD_META
|
||||
if( mods & wxMOD_META )
|
||||
hotkey |= MD_META;
|
||||
#endif
|
||||
|
||||
if( aKeyStroke.ControlDown() )
|
||||
hotkey |= MD_CTRL;
|
||||
#ifdef wxMOD_WIN
|
||||
if( mods & wxMOD_WIN )
|
||||
hotkey |= MD_SUPER;
|
||||
#endif
|
||||
|
||||
if( tool->GetManager()->GetActionManager()->RunHotKey( hotkey ) )
|
||||
aKeyStroke.Skip( false );
|
||||
|
@ -235,7 +235,11 @@ void UNIT_BINDER::onComboBox( wxCommandEvent& aEvent )
|
||||
const wxString value = combo->GetStringSelection();
|
||||
const long long int conv = ValueFromString( *m_iuScale, m_units, value, m_dataType );
|
||||
|
||||
SetValue( conv );
|
||||
CallAfter(
|
||||
[this, conv]
|
||||
{
|
||||
SetValue( conv );
|
||||
} );
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
@ -670,7 +670,7 @@ long WIDGET_HOTKEY_LIST::MapKeypressToKeycode( const wxKeyEvent& aEvent )
|
||||
{
|
||||
long key = aEvent.GetKeyCode();
|
||||
bool is_tab = aEvent.IsKeyInCategory( WXK_CATEGORY_TAB );
|
||||
|
||||
printf("key %lX mod %X\n", key, aEvent.GetModifiers());
|
||||
if( key == WXK_ESCAPE )
|
||||
{
|
||||
return 0;
|
||||
@ -693,14 +693,35 @@ long WIDGET_HOTKEY_LIST::MapKeypressToKeycode( const wxKeyEvent& aEvent )
|
||||
*/
|
||||
bool keyIsLetter = key >= 'A' && key <= 'Z';
|
||||
|
||||
if( aEvent.ShiftDown() && ( keyIsLetter || key > 256 || key == 9 || key == 32 ) )
|
||||
int mods = aEvent.GetModifiers();
|
||||
|
||||
if( ( mods & wxMOD_SHIFT ) && ( keyIsLetter || key > 256 || key == 9 || key == 32 ) )
|
||||
key |= MD_SHIFT;
|
||||
|
||||
if( aEvent.ControlDown() )
|
||||
key |= MD_CTRL;
|
||||
// the flag wxMOD_ALTGR is defined in wxWidgets as wxMOD_CONTROL|wxMOD_ALT
|
||||
// So AltGr key cannot used as modifier key because it is the same as Alt key + Ctrl key.
|
||||
#if CAN_USE_ALTGR_KEY
|
||||
if( wxmods & wxMOD_ALTGR )
|
||||
mods |= MD_ALTGR;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if( mods & wxMOD_CONTROL )
|
||||
key |= MD_CTRL;
|
||||
|
||||
if( aEvent.AltDown() )
|
||||
key |= MD_ALT;
|
||||
if( mods & wxMOD_ALT )
|
||||
key |= MD_ALT;
|
||||
}
|
||||
|
||||
#ifdef wxMOD_META
|
||||
if( mods & wxMOD_META )
|
||||
key |= MD_META;
|
||||
#endif
|
||||
|
||||
#ifdef wxMOD_WIN
|
||||
if( mods & wxMOD_WIN )
|
||||
key |= MD_SUPER;
|
||||
#endif
|
||||
|
||||
return key;
|
||||
}
|
||||
|
@ -62,6 +62,7 @@
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/ffile.h>
|
||||
|
||||
|
||||
CVPCB_MAINFRAME::CVPCB_MAINFRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||
@ -796,7 +797,12 @@ void CVPCB_MAINFRAME::DisplayStatus()
|
||||
msg.Empty();
|
||||
|
||||
if( symbol )
|
||||
msg = wxString::Format( wxT( "%i" ), symbol->GetPinCount() );
|
||||
{
|
||||
int pc = symbol->GetPinCount();
|
||||
wxLogTrace( "CVPCB_PINCOUNT", wxT( "DisplayStatus: selected '%s' pinCount=%d" ),
|
||||
symbol->GetReference(), pc );
|
||||
msg = wxString::Format( wxT( "%i" ), pc );
|
||||
}
|
||||
|
||||
if( !filters.IsEmpty() )
|
||||
filters += wxT( ", " );
|
||||
@ -957,6 +963,12 @@ int CVPCB_MAINFRAME::readSchematicNetlist( const std::string& aNetlist )
|
||||
|
||||
m_netlist.Clear();
|
||||
|
||||
// Trace basic payload characteristics to verify libparts are present and visible here
|
||||
wxLogTrace( "CVPCB_PINCOUNT",
|
||||
wxT( "readSchematicNetlist: payload size=%zu has_libparts=%d has_libpart=%d" ),
|
||||
aNetlist.size(), aNetlist.find( "(libparts" ) != std::string::npos,
|
||||
aNetlist.find( "(libpart" ) != std::string::npos );
|
||||
|
||||
try
|
||||
{
|
||||
netlistReader.LoadNetlist();
|
||||
|
@ -132,7 +132,13 @@ void FOOTPRINTS_LISTBOX::SetFootprints( FOOTPRINT_LIST& aList, const wxString& a
|
||||
filter.FilterByFootprintFilters( aComponent->GetFootprintFilters() );
|
||||
|
||||
if( aFilterType & FILTERING_BY_PIN_COUNT && aComponent )
|
||||
filter.FilterByPinCount( aComponent->GetPinCount() );
|
||||
{
|
||||
int pc = aComponent->GetPinCount();
|
||||
wxLogTrace( "CVPCB_PINCOUNT",
|
||||
wxT( "FOOTPRINTS_LISTBOX::SetFootprints: ref='%s' pinCount filter=%d" ),
|
||||
aComponent->GetReference(), pc );
|
||||
filter.FilterByPinCount( pc );
|
||||
}
|
||||
|
||||
if( aFilterType & FILTERING_BY_LIBRARY )
|
||||
filter.FilterByLibrary( aLibName );
|
||||
|
@ -122,8 +122,8 @@ set( EESCHEMA_DLGS
|
||||
dialogs/dialog_label_properties_base.cpp
|
||||
dialogs/dialog_lib_edit_pin_table.cpp
|
||||
dialogs/dialog_lib_edit_pin_table_base.cpp
|
||||
dialogs/dialog_lib_fields_base.cpp
|
||||
dialogs/dialog_lib_fields.cpp
|
||||
dialogs/dialog_lib_fields_table_base.cpp
|
||||
dialogs/dialog_lib_fields_table.cpp
|
||||
dialogs/dialog_lib_new_symbol.cpp
|
||||
dialogs/dialog_lib_new_symbol_base.cpp
|
||||
dialogs/dialog_lib_symbol_properties.cpp
|
||||
|
@ -1614,11 +1614,10 @@ void CONNECTION_GRAPH::resolveAllDrivers()
|
||||
|
||||
thread_pool& tp = GetKiCadThreadPool();
|
||||
|
||||
auto results = tp.parallelize_loop( dirty_graphs.size(),
|
||||
[&]( const int a, const int b)
|
||||
auto results = tp.submit_loop( 0, dirty_graphs.size(),
|
||||
[&]( const int ii )
|
||||
{
|
||||
for( int ii = a; ii < b; ++ii )
|
||||
update_lambda( dirty_graphs[ii] );
|
||||
update_lambda( dirty_graphs[ii] );
|
||||
});
|
||||
results.wait();
|
||||
|
||||
@ -2257,11 +2256,10 @@ void CONNECTION_GRAPH::buildConnectionGraph( std::function<void( SCH_ITEM* )>* a
|
||||
|
||||
thread_pool& tp = GetKiCadThreadPool();
|
||||
|
||||
auto results = tp.parallelize_loop( m_driver_subgraphs.size(),
|
||||
[&]( const int a, const int b)
|
||||
auto results = tp.submit_loop( 0, m_driver_subgraphs.size(),
|
||||
[&]( const int ii )
|
||||
{
|
||||
for( int ii = a; ii < b; ++ii )
|
||||
m_driver_subgraphs[ii]->UpdateItemConnections();
|
||||
m_driver_subgraphs[ii]->UpdateItemConnections();
|
||||
});
|
||||
|
||||
results.wait();
|
||||
@ -2464,12 +2462,11 @@ void CONNECTION_GRAPH::buildConnectionGraph( std::function<void( SCH_ITEM* )>* a
|
||||
return 1;
|
||||
};
|
||||
|
||||
auto results2 = tp.parallelize_loop( m_driver_subgraphs.size(),
|
||||
[&]( const int a, const int b)
|
||||
auto results2 = tp.submit_loop( 0, m_driver_subgraphs.size(),
|
||||
[&]( const int ii )
|
||||
{
|
||||
for( int ii = a; ii < b; ++ii )
|
||||
updateItemConnectionsTask( m_driver_subgraphs[ii] );
|
||||
});
|
||||
updateItemConnectionsTask( m_driver_subgraphs[ii] );
|
||||
} );
|
||||
results2.wait();
|
||||
|
||||
m_net_code_to_subgraphs_map.clear();
|
||||
|
@ -931,6 +931,26 @@ void SCH_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
|
||||
items );
|
||||
|
||||
m_syncingPcbToSchSelection = false;
|
||||
|
||||
if( eeconfig()->m_CrossProbing.flash_selection )
|
||||
{
|
||||
wxLogTrace( "CROSS_PROBE_FLASH", "MAIL_SELECTION(_FORCE): flash enabled, items=%zu", items.size() );
|
||||
if( items.empty() )
|
||||
{
|
||||
wxLogTrace( "CROSS_PROBE_FLASH", "MAIL_SELECTION(_FORCE): nothing to flash" );
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<SCH_ITEM*> itemPtrs;
|
||||
std::copy( items.begin(), items.end(), std::back_inserter( itemPtrs ) );
|
||||
|
||||
StartCrossProbeFlash( itemPtrs );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( "CROSS_PROBE_FLASH", "MAIL_SELECTION(_FORCE): flash disabled" );
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <id.h>
|
||||
#include <confirm.h>
|
||||
#include <widgets/wx_html_report_box.h>
|
||||
#include <widgets/std_bitmap_button.h>
|
||||
#include <dialogs/dialog_text_entry.h>
|
||||
#include <string_utils.h>
|
||||
#include <kiplatform/ui.h>
|
||||
@ -76,15 +77,15 @@ DIALOG_ERC::DIALOG_ERC( SCH_EDIT_FRAME* parent ) :
|
||||
m_running( false ),
|
||||
m_ercRun( false ),
|
||||
m_centerMarkerOnIdle( nullptr ),
|
||||
m_severities( 0 )
|
||||
m_crossprobe( true ),
|
||||
m_scroll_on_crossprobe( true )
|
||||
{
|
||||
m_currentSchematic = &parent->Schematic();
|
||||
|
||||
SetName( DIALOG_ERC_WINDOW_NAME ); // Set a window name to be able to find it
|
||||
KIPLATFORM::UI::SetFloatLevel( this );
|
||||
|
||||
if( EESCHEMA_SETTINGS* cfg = GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" ) )
|
||||
m_severities = cfg->m_Appearance.erc_severities;
|
||||
m_bMenu->SetBitmap( KiBitmapBundle( BITMAPS::config ) );
|
||||
|
||||
m_messages->SetImmediateMode();
|
||||
|
||||
@ -92,7 +93,7 @@ DIALOG_ERC::DIALOG_ERC( SCH_EDIT_FRAME* parent ) :
|
||||
|
||||
m_markerTreeModel = new ERC_TREE_MODEL( parent, m_markerDataView );
|
||||
m_markerDataView->AssociateModel( m_markerTreeModel );
|
||||
m_markerTreeModel->Update( m_markerProvider, m_severities );
|
||||
m_markerTreeModel->Update( m_markerProvider, getSeverities() );
|
||||
|
||||
m_ignoredList->InsertColumn( 0, wxEmptyString, wxLIST_FORMAT_LEFT, DEFAULT_SINGLE_COL_WIDTH );
|
||||
|
||||
@ -129,8 +130,11 @@ DIALOG_ERC::DIALOG_ERC( SCH_EDIT_FRAME* parent ) :
|
||||
|
||||
SetFocus();
|
||||
|
||||
syncCheckboxes();
|
||||
updateDisplayedCounts();
|
||||
if( EESCHEMA_SETTINGS* cfg = GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" ) )
|
||||
{
|
||||
m_crossprobe = cfg->m_ERCDialog.crossprobe;
|
||||
m_scroll_on_crossprobe = cfg->m_ERCDialog.scroll_on_crossprobe;
|
||||
}
|
||||
|
||||
// Now all widgets have the size fixed, call FinishDialogSettings
|
||||
finishDialogSettings();
|
||||
@ -148,7 +152,10 @@ DIALOG_ERC::~DIALOG_ERC()
|
||||
g_lastERCIgnored.push_back( { m_ignoredList->GetItemText( ii ), m_ignoredList->GetItemData( ii ) } );
|
||||
|
||||
if( EESCHEMA_SETTINGS* cfg = GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" ) )
|
||||
cfg->m_Appearance.erc_severities = m_severities;
|
||||
{
|
||||
cfg->m_ERCDialog.crossprobe = m_crossprobe;
|
||||
cfg->m_ERCDialog.scroll_on_crossprobe = m_scroll_on_crossprobe;
|
||||
}
|
||||
|
||||
m_markerTreeModel->DecRef();
|
||||
}
|
||||
@ -189,6 +196,59 @@ void DIALOG_ERC::UpdateAnnotationWarning()
|
||||
}
|
||||
|
||||
|
||||
int DIALOG_ERC::getSeverities()
|
||||
{
|
||||
int severities = 0;
|
||||
|
||||
if( m_showErrors->GetValue() )
|
||||
severities |= RPT_SEVERITY_ERROR;
|
||||
|
||||
if( m_showWarnings->GetValue() )
|
||||
severities |= RPT_SEVERITY_WARNING;
|
||||
|
||||
if( m_showExclusions->GetValue() )
|
||||
severities |= RPT_SEVERITY_EXCLUSION;
|
||||
|
||||
return severities;
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_ERC::OnMenu( wxCommandEvent& event )
|
||||
{
|
||||
// Build a pop menu:
|
||||
wxMenu menu;
|
||||
|
||||
menu.Append( 4206, _( "Cross-probe Selected Items" ),
|
||||
_( "Highlight corresponding items on canvas when selected in the ERC list" ),
|
||||
wxITEM_CHECK );
|
||||
menu.Check( 4206, m_crossprobe );
|
||||
|
||||
menu.Append( 4207, _( "Center on Cross-probe" ),
|
||||
_( "When cross-probing, scroll the canvas so that the item is visible" ),
|
||||
wxITEM_CHECK );
|
||||
menu.Check( 4207, m_scroll_on_crossprobe );
|
||||
|
||||
// menu_id is the selected submenu id from the popup menu or wxID_NONE
|
||||
int menu_id = m_bMenu->GetPopupMenuSelectionFromUser( menu );
|
||||
|
||||
if( menu_id == 0 || menu_id == 4206 )
|
||||
{
|
||||
m_crossprobe = !m_crossprobe;
|
||||
}
|
||||
else if( menu_id == 1 || menu_id == 4207 )
|
||||
{
|
||||
m_scroll_on_crossprobe = !m_scroll_on_crossprobe;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DIALOG_ERC::TransferDataToWindow()
|
||||
{
|
||||
UpdateData();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DIALOG_ERC::updateUI()
|
||||
{
|
||||
// If ERC checks ever get slow enough we'll want a progress indicator...
|
||||
@ -217,6 +277,13 @@ void DIALOG_ERC::Report( const wxString& aMessage )
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_ERC::UpdateData()
|
||||
{
|
||||
m_markerTreeModel->Update( m_markerProvider, getSeverities() );
|
||||
updateDisplayedCounts();
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_ERC::updateDisplayedCounts()
|
||||
{
|
||||
int numErrors = 0;
|
||||
@ -348,30 +415,14 @@ void DIALOG_ERC::OnCloseErcDialog( wxCloseEvent& aEvent )
|
||||
// Dialog is mode-less so let the parent know that it needs to be destroyed.
|
||||
if( !IsModal() && !IsQuasiModal() )
|
||||
{
|
||||
wxCommandEvent* evt = new wxCommandEvent( EDA_EVT_CLOSE_ERC_DIALOG, wxID_ANY );
|
||||
|
||||
wxWindow* parent = GetParent();
|
||||
|
||||
if( parent )
|
||||
wxQueueEvent( parent, evt );
|
||||
if( wxWindow* parent = GetParent() )
|
||||
wxQueueEvent( parent, new wxCommandEvent( EDA_EVT_CLOSE_ERC_DIALOG, wxID_ANY ) );
|
||||
}
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
static int RPT_SEVERITY_ALL = RPT_SEVERITY_WARNING | RPT_SEVERITY_ERROR | RPT_SEVERITY_EXCLUSION;
|
||||
|
||||
|
||||
void DIALOG_ERC::syncCheckboxes()
|
||||
{
|
||||
m_showAll->SetValue( m_severities == RPT_SEVERITY_ALL );
|
||||
m_showErrors->SetValue( m_severities & RPT_SEVERITY_ERROR );
|
||||
m_showWarnings->SetValue( m_severities & RPT_SEVERITY_WARNING );
|
||||
m_showExclusions->SetValue( m_severities & RPT_SEVERITY_EXCLUSION );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_ERC::OnLinkClicked( wxHtmlLinkEvent& event )
|
||||
{
|
||||
m_parent->OnAnnotate();
|
||||
@ -446,8 +497,7 @@ void DIALOG_ERC::OnRunERCClick( wxCommandEvent& event )
|
||||
}
|
||||
|
||||
if( m_cancelled )
|
||||
// @spellingerror
|
||||
m_messages->Report( _( "-------- ERC canceled by user.<br><br>" ), RPT_SEVERITY_INFO );
|
||||
m_messages->Report( _( "-------- ERC cancelled by user.<br><br>" ), RPT_SEVERITY_INFO );
|
||||
else
|
||||
m_messages->Report( _( "Done.<br><br>" ), RPT_SEVERITY_INFO );
|
||||
|
||||
@ -508,7 +558,7 @@ void DIALOG_ERC::testErc()
|
||||
}
|
||||
|
||||
// Update marker list:
|
||||
m_markerTreeModel->Update( m_markerProvider, m_severities );
|
||||
m_markerTreeModel->Update( m_markerProvider, getSeverities() );
|
||||
|
||||
// Display new markers from the current screen:
|
||||
for( SCH_ITEM* marker : m_parent->GetScreen()->Items().OfType( SCH_MARKER_T ) )
|
||||
@ -523,6 +573,12 @@ void DIALOG_ERC::testErc()
|
||||
|
||||
void DIALOG_ERC::OnERCItemSelected( wxDataViewEvent& aEvent )
|
||||
{
|
||||
if( !m_crossprobe )
|
||||
{
|
||||
aEvent.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
const KIID& itemID = RC_TREE_MODEL::ToUUID( aEvent.GetItem() );
|
||||
SCH_SHEET_PATH sheet;
|
||||
SCH_ITEM* item = m_parent->Schematic().ResolveItem( itemID, &sheet, true );
|
||||
@ -568,7 +624,7 @@ void DIALOG_ERC::OnERCItemSelected( wxDataViewEvent& aEvent )
|
||||
m_parent->RedrawScreen( m_parent->GetScreen()->m_ScrollCenter, false );
|
||||
}
|
||||
|
||||
m_parent->FocusOnItem( item );
|
||||
m_parent->FocusOnItem( item, m_scroll_on_crossprobe );
|
||||
redrawDrawPanel();
|
||||
}
|
||||
|
||||
@ -762,7 +818,7 @@ void DIALOG_ERC::OnERCItemRClick( wxDataViewEvent& aEvent )
|
||||
m_parent->GetCanvas()->GetView()->Update( marker );
|
||||
|
||||
// Update view
|
||||
if( m_severities & RPT_SEVERITY_EXCLUSION )
|
||||
if( getSeverities() & RPT_SEVERITY_EXCLUSION )
|
||||
static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
|
||||
else
|
||||
static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->DeleteCurrentItem( false );
|
||||
@ -788,7 +844,7 @@ void DIALOG_ERC::OnERCItemRClick( wxDataViewEvent& aEvent )
|
||||
}
|
||||
|
||||
// Rebuild model and view
|
||||
static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markerProvider, m_severities );
|
||||
static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markerProvider, getSeverities() );
|
||||
modified = true;
|
||||
break;
|
||||
|
||||
@ -804,7 +860,7 @@ void DIALOG_ERC::OnERCItemRClick( wxDataViewEvent& aEvent )
|
||||
}
|
||||
|
||||
// Rebuild model and view
|
||||
static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markerProvider, m_severities );
|
||||
static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markerProvider, getSeverities() );
|
||||
modified = true;
|
||||
break;
|
||||
|
||||
@ -830,7 +886,7 @@ void DIALOG_ERC::OnERCItemRClick( wxDataViewEvent& aEvent )
|
||||
ScreenList.DeleteMarkers( MARKER_BASE::MARKER_ERC, rcItem->GetErrorCode() );
|
||||
|
||||
// Rebuild model and view
|
||||
static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markerProvider, m_severities );
|
||||
static_cast<RC_TREE_MODEL*>( aEvent.GetModel() )->Update( m_markerProvider, getSeverities() );
|
||||
modified = true;
|
||||
}
|
||||
break;
|
||||
@ -956,7 +1012,7 @@ void DIALOG_ERC::ExcludeMarker( SCH_MARKER* aMarker )
|
||||
m_parent->GetCanvas()->GetView()->Update( marker );
|
||||
|
||||
// Update view
|
||||
if( m_severities & RPT_SEVERITY_EXCLUSION )
|
||||
if( getSeverities() & RPT_SEVERITY_EXCLUSION )
|
||||
m_markerTreeModel->ValueChanged( node );
|
||||
else
|
||||
m_markerTreeModel->DeleteCurrentItem( false );
|
||||
@ -976,28 +1032,14 @@ void DIALOG_ERC::OnEditViolationSeverities( wxHyperlinkEvent& aEvent )
|
||||
|
||||
void DIALOG_ERC::OnSeverity( wxCommandEvent& aEvent )
|
||||
{
|
||||
int flag = 0;
|
||||
|
||||
if( aEvent.GetEventObject() == m_showAll )
|
||||
flag = RPT_SEVERITY_ALL;
|
||||
else if( aEvent.GetEventObject() == m_showErrors )
|
||||
flag = RPT_SEVERITY_ERROR;
|
||||
else if( aEvent.GetEventObject() == m_showWarnings )
|
||||
flag = RPT_SEVERITY_WARNING;
|
||||
else if( aEvent.GetEventObject() == m_showExclusions )
|
||||
flag = RPT_SEVERITY_EXCLUSION;
|
||||
{
|
||||
m_showErrors->SetValue( true );
|
||||
m_showWarnings->SetValue( aEvent.IsChecked() );
|
||||
m_showExclusions->SetValue( aEvent.IsChecked() );
|
||||
}
|
||||
|
||||
if( aEvent.IsChecked() )
|
||||
m_severities |= flag;
|
||||
else if( aEvent.GetEventObject() == m_showAll )
|
||||
m_severities = RPT_SEVERITY_ERROR;
|
||||
else
|
||||
m_severities &= ~flag;
|
||||
|
||||
syncCheckboxes();
|
||||
|
||||
m_markerTreeModel->Update( m_markerProvider, m_severities );
|
||||
updateDisplayedCounts();
|
||||
UpdateData();
|
||||
}
|
||||
|
||||
|
||||
|
@ -49,6 +49,8 @@ public:
|
||||
DIALOG_ERC( SCH_EDIT_FRAME* parent );
|
||||
~DIALOG_ERC();
|
||||
|
||||
bool TransferDataToWindow() override;
|
||||
|
||||
// PROGRESS_REPORTER_BASE calls
|
||||
bool updateUI() override;
|
||||
void AdvancePhase( const wxString& aMessage ) override;
|
||||
@ -66,10 +68,14 @@ public:
|
||||
*/
|
||||
void ExcludeMarker( SCH_MARKER* aMarker = nullptr );
|
||||
|
||||
void UpdateData();
|
||||
void UpdateAnnotationWarning();
|
||||
|
||||
private:
|
||||
int getSeverities();
|
||||
|
||||
// from DIALOG_ERC_BASE:
|
||||
void OnMenu( wxCommandEvent& aEvent ) override;
|
||||
void OnCloseErcDialog( wxCloseEvent& event ) override;
|
||||
void OnRunERCClick( wxCommandEvent& event ) override;
|
||||
void OnDeleteOneClick( wxCommandEvent& event ) override;
|
||||
@ -92,8 +98,6 @@ private:
|
||||
|
||||
void testErc();
|
||||
|
||||
bool writeReport( const wxString& aFullFileName );
|
||||
|
||||
void deleteAllMarkers( bool aIncludeExclusions );
|
||||
|
||||
void syncCheckboxes();
|
||||
@ -114,7 +118,8 @@ private:
|
||||
|
||||
const SCH_MARKER* m_centerMarkerOnIdle;
|
||||
|
||||
int m_severities;
|
||||
bool m_crossprobe;
|
||||
bool m_scroll_on_crossprobe;
|
||||
};
|
||||
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "widgets/std_bitmap_button.h"
|
||||
#include "widgets/wx_html_report_box.h"
|
||||
#include "widgets/wx_infobar.h"
|
||||
|
||||
@ -29,6 +30,24 @@ DIALOG_ERC_BASE::DIALOG_ERC_BASE( wxWindow* parent, wxWindowID id, const wxStrin
|
||||
wxBoxSizer* bMainSizer;
|
||||
bMainSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxGridBagSizer* gbSizerOptions;
|
||||
gbSizerOptions = new wxGridBagSizer( 0, 0 );
|
||||
gbSizerOptions->SetFlexibleDirection( wxBOTH );
|
||||
gbSizerOptions->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_bMenu = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_bMenu->SetMinSize( wxSize( 30,30 ) );
|
||||
|
||||
gbSizerOptions->Add( m_bMenu, wxGBPosition( 0, 2 ), wxGBSpan( 2, 1 ), wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
|
||||
gbSizerOptions->AddGrowableCol( 0 );
|
||||
gbSizerOptions->AddGrowableCol( 1 );
|
||||
gbSizerOptions->AddGrowableRow( 0 );
|
||||
gbSizerOptions->AddGrowableRow( 1 );
|
||||
|
||||
bMainSizer->Add( gbSizerOptions, 0, wxEXPAND|wxLEFT, 5 );
|
||||
|
||||
m_runningResultsBook = new wxSimplebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
running = new wxPanel( m_runningResultsBook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
wxBoxSizer* bSizer14;
|
||||
@ -195,6 +214,7 @@ DIALOG_ERC_BASE::DIALOG_ERC_BASE( wxWindow* parent, wxWindowID id, const wxStrin
|
||||
|
||||
// Connect Events
|
||||
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_ERC_BASE::OnCloseErcDialog ) );
|
||||
m_bMenu->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_ERC_BASE::OnMenu ), NULL, this );
|
||||
m_messages->Connect( wxEVT_COMMAND_HTML_LINK_CLICKED, wxHtmlLinkEventHandler( DIALOG_ERC_BASE::OnLinkClicked ), NULL, this );
|
||||
m_markerDataView->Connect( wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, wxDataViewEventHandler( DIALOG_ERC_BASE::OnERCItemDClick ), NULL, this );
|
||||
m_markerDataView->Connect( wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, wxDataViewEventHandler( DIALOG_ERC_BASE::OnERCItemRClick ), NULL, this );
|
||||
@ -216,6 +236,7 @@ DIALOG_ERC_BASE::~DIALOG_ERC_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_ERC_BASE::OnCloseErcDialog ) );
|
||||
m_bMenu->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_ERC_BASE::OnMenu ), NULL, this );
|
||||
m_messages->Disconnect( wxEVT_COMMAND_HTML_LINK_CLICKED, wxHtmlLinkEventHandler( DIALOG_ERC_BASE::OnLinkClicked ), NULL, this );
|
||||
m_markerDataView->Disconnect( wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, wxDataViewEventHandler( DIALOG_ERC_BASE::OnERCItemDClick ), NULL, this );
|
||||
m_markerDataView->Disconnect( wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, wxDataViewEventHandler( DIALOG_ERC_BASE::OnERCItemRClick ), NULL, this );
|
||||
|
@ -14,7 +14,7 @@
|
||||
<property name="embedded_files_path">res</property>
|
||||
<property name="encoding">UTF-8</property>
|
||||
<property name="file">dialog_erc_base</property>
|
||||
<property name="first_id">1000</property>
|
||||
<property name="first_id">7100</property>
|
||||
<property name="internationalize">1</property>
|
||||
<property name="lua_skip_events">1</property>
|
||||
<property name="lua_ui_table">UI</property>
|
||||
@ -135,6 +135,101 @@
|
||||
<property name="name">bMainSizer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND|wxLEFT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxGridBagSizer" expanded="true">
|
||||
<property name="empty_cell_size"></property>
|
||||
<property name="flexible_direction">wxBOTH</property>
|
||||
<property name="growablecols">0,1</property>
|
||||
<property name="growablerows">0,1</property>
|
||||
<property name="hgap">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">gbSizerOptions</property>
|
||||
<property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
|
||||
<property name="permission">none</property>
|
||||
<property name="vgap">0</property>
|
||||
<object class="gbsizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="colspan">1</property>
|
||||
<property name="column">2</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
|
||||
<property name="row">0</property>
|
||||
<property name="rowspan">2</property>
|
||||
<object class="wxBitmapButton" 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="auth_needed">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="bitmap"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="current"></property>
|
||||
<property name="default">0</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="disabled"></property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="focus"></property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Refresh Grouping</property>
|
||||
<property name="margins"></property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size">30,30</property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_bMenu</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="position"></property>
|
||||
<property name="pressed"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnButtonClick">OnMenu</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND|wxTOP|wxRIGHT</property>
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <wx/artprov.h>
|
||||
#include <wx/xrc/xmlres.h>
|
||||
#include <wx/intl.h>
|
||||
class STD_BITMAP_BUTTON;
|
||||
class WX_HTML_REPORT_BOX;
|
||||
class WX_INFOBAR;
|
||||
|
||||
@ -20,13 +21,16 @@ class WX_INFOBAR;
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/string.h>
|
||||
#include <wx/bmpbuttn.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/gbsizer.h>
|
||||
#include <wx/html/htmlwin.h>
|
||||
#include <wx/gauge.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/dataview.h>
|
||||
#include <wx/listctrl.h>
|
||||
@ -35,12 +39,11 @@ class WX_INFOBAR;
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <widgets/number_badge.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/dialog.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define ID_ERASE_DRC_MARKERS 1000
|
||||
#define ID_ERASE_DRC_MARKERS 7100
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class DIALOG_ERC_BASE
|
||||
@ -51,6 +54,7 @@ class DIALOG_ERC_BASE : public DIALOG_SHIM
|
||||
|
||||
protected:
|
||||
WX_INFOBAR* m_infoBar;
|
||||
STD_BITMAP_BUTTON* m_bMenu;
|
||||
wxSimplebook* m_runningResultsBook;
|
||||
wxPanel* running;
|
||||
wxNotebook* m_runningNotebook;
|
||||
@ -82,6 +86,7 @@ class DIALOG_ERC_BASE : public DIALOG_SHIM
|
||||
|
||||
// Virtual event handlers, override them in your derived class
|
||||
virtual void OnCloseErcDialog( wxCloseEvent& event ) { event.Skip(); }
|
||||
virtual void OnMenu( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnLinkClicked( wxHtmlLinkEvent& event ) { event.Skip(); }
|
||||
virtual void OnERCItemDClick( wxDataViewEvent& event ) { event.Skip(); }
|
||||
virtual void OnERCItemRClick( wxDataViewEvent& event ) { event.Skip(); }
|
||||
|
@ -175,11 +175,28 @@ DIALOG_FIELD_PROPERTIES::DIALOG_FIELD_PROPERTIES( SCH_BASE_FRAME* aParent, const
|
||||
wxString netlist;
|
||||
wxArrayString pins;
|
||||
|
||||
for( SCH_PIN* pin : symbol->GetPins( 0 /* all units */, 1 /* single bodyStyle */ ) )
|
||||
pins.push_back( pin->GetNumber() + ' ' + pin->GetShownName() );
|
||||
for( SCH_PIN* pin : symbol->GetGraphicalPins( 0 /* all units */, 1 /* single bodyStyle */ ) )
|
||||
{
|
||||
bool valid = false;
|
||||
auto expanded = pin->GetStackedPinNumbers( &valid );
|
||||
|
||||
if( valid && !expanded.empty() )
|
||||
{
|
||||
for( const wxString& num : expanded )
|
||||
pins.push_back( num + ' ' + pin->GetShownName() );
|
||||
}
|
||||
else
|
||||
{
|
||||
pins.push_back( pin->GetNumber() + ' ' + pin->GetShownName() );
|
||||
}
|
||||
}
|
||||
|
||||
if( !pins.IsEmpty() )
|
||||
netlist << EscapeString( wxJoin( pins, '\t' ), CTX_LINE );
|
||||
{
|
||||
wxString dbg = wxJoin( pins, '\t' );
|
||||
wxLogTrace( "FOOTPRINT_CHOOSER", wxS( "Chooser payload pins (LIB_SYMBOL): %s" ), dbg );
|
||||
netlist << EscapeString( dbg, CTX_LINE );
|
||||
}
|
||||
|
||||
netlist << wxS( "\r" );
|
||||
|
||||
@ -213,12 +230,28 @@ DIALOG_FIELD_PROPERTIES::DIALOG_FIELD_PROPERTIES( SCH_BASE_FRAME* aParent, const
|
||||
|
||||
if( lib_symbol )
|
||||
{
|
||||
for( SCH_PIN* pin : lib_symbol->GetPins( 0 /* all units */, 1 /* single bodyStyle */ ) )
|
||||
pins.push_back( pin->GetNumber() + ' ' + pin->GetShownName() );
|
||||
for( SCH_PIN* pin : lib_symbol->GetGraphicalPins( 0 /* all units */, 1 /* single bodyStyle */ ) )
|
||||
{
|
||||
bool valid = false;
|
||||
auto expanded = pin->GetStackedPinNumbers( &valid );
|
||||
if( valid && !expanded.empty() )
|
||||
{
|
||||
for( const wxString& num : expanded )
|
||||
pins.push_back( num + ' ' + pin->GetShownName() );
|
||||
}
|
||||
else
|
||||
{
|
||||
pins.push_back( pin->GetNumber() + ' ' + pin->GetShownName() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !pins.IsEmpty() )
|
||||
netlist << EscapeString( wxJoin( pins, '\t' ), CTX_LINE );
|
||||
{
|
||||
wxString dbg = wxJoin( pins, '\t' );
|
||||
wxLogTrace( "FOOTPRINT_CHOOSER", wxS( "Chooser payload pins (SCH_SYMBOL): %s" ), dbg );
|
||||
netlist << EscapeString( dbg, CTX_LINE );
|
||||
}
|
||||
|
||||
netlist << wxS( "\r" );
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -17,70 +17,77 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DIALOG_LIB_FIELDS_H
|
||||
#define DIALOG_LIB_FIELDS_H
|
||||
#pragma once
|
||||
|
||||
#include <dialog_lib_fields_base.h>
|
||||
#include <dialog_lib_fields_table_base.h>
|
||||
#include <sch_reference_list.h>
|
||||
#include <lib_fields_data_model.h>
|
||||
|
||||
class SYMBOL_EDIT_FRAME;
|
||||
class LIB_FIELDS_EDITOR_GRID_DATA_MODEL;
|
||||
class LIB_SYMBOL;
|
||||
|
||||
class DIALOG_LIB_FIELDS : public DIALOG_LIB_FIELDS_BASE
|
||||
|
||||
class DIALOG_LIB_FIELDS_TABLE : public DIALOG_LIB_FIELDS_TABLE_BASE
|
||||
{
|
||||
public:
|
||||
DIALOG_LIB_FIELDS( SYMBOL_EDIT_FRAME* parent, wxString libId, const wxArrayString& aSymbolNames );
|
||||
~DIALOG_LIB_FIELDS() override;
|
||||
enum SCOPE : int
|
||||
{
|
||||
SCOPE_LIBRARY = 0,
|
||||
SCOPE_RELATED_SYMBOLS
|
||||
};
|
||||
|
||||
void OnInit();
|
||||
DIALOG_LIB_FIELDS_TABLE( SYMBOL_EDIT_FRAME* parent, DIALOG_LIB_FIELDS_TABLE::SCOPE aScope );
|
||||
~DIALOG_LIB_FIELDS_TABLE() override;
|
||||
|
||||
protected:
|
||||
void OnClose( wxCloseEvent& event ) override;
|
||||
void OnColumnItemToggled( wxDataViewEvent& event ) override;
|
||||
void OnFieldsCtrlSelectionChanged( wxDataViewEvent& event ) override;
|
||||
void OnSizeFieldList( wxSizeEvent& event ) override;
|
||||
void OnAddField( wxCommandEvent& event ) override;
|
||||
void OnRenameField( wxCommandEvent& event ) override;
|
||||
void OnRemoveField( wxCommandEvent& event ) override;
|
||||
void OnFilterMouseMoved( wxMouseEvent& event ) override;
|
||||
void OnFilterText( wxCommandEvent& event ) override;
|
||||
void OnRegroupSymbols( wxCommandEvent& event ) override;
|
||||
void OnTableValueChanged( wxGridEvent& event ) override;
|
||||
void OnTableCellClick( wxGridEvent& event ) override;
|
||||
void OnTableItemContextMenu( wxGridEvent& event ) override;
|
||||
void OnTableColSize( wxGridSizeEvent& event ) override;
|
||||
void OnCancel( wxCommandEvent& event ) override;
|
||||
void OnOk( wxCommandEvent& event ) override;
|
||||
void OnApply( wxCommandEvent& event ) override;
|
||||
bool TransferDataToWindow() override;
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
void ShowHideColumn( int aCol, bool aShow );
|
||||
|
||||
private:
|
||||
void UpdateFieldList();
|
||||
void AddField( const wxString& aFieldName, const wxString& aLabelValue, bool show, bool groupBy, bool addedByUser = false, bool aIsCheckbox = false );
|
||||
void AddField( const wxString& aFieldName, const wxString& aLabelValue, bool show, bool groupBy,
|
||||
bool addedByUser = false, bool aIsCheckbox = false );
|
||||
void RemoveField( const wxString& fieldName );
|
||||
void RenameField( const wxString& oldName, const wxString& newName );
|
||||
void RegroupSymbols();
|
||||
|
||||
void OnColSort( wxGridEvent& aEvent );
|
||||
void OnColMove( wxGridEvent& aEvent );
|
||||
void OnColLabelChange( wxDataViewEvent& aEvent );
|
||||
void SetupColumnProperties( int aCol );
|
||||
void SetupAllColumnProperties();
|
||||
void setScope( SCOPE aScope );
|
||||
|
||||
void loadSymbols( const wxArrayString& aSymbolNames );
|
||||
|
||||
wxString m_libId;
|
||||
SYMBOL_EDIT_FRAME* m_parent;
|
||||
void OnViewControlsCellChanged( wxGridEvent& aEvent ) override;
|
||||
void OnSizeViewControlsGrid( wxSizeEvent& event ) override;
|
||||
void OnAddField( wxCommandEvent& event ) override;
|
||||
void OnRenameField( wxCommandEvent& event ) override;
|
||||
void OnRemoveField( wxCommandEvent& event ) override;
|
||||
|
||||
int m_fieldNameColWidth;
|
||||
int m_labelColWidth;
|
||||
int m_showColWidth;
|
||||
int m_groupByColWidth;
|
||||
void OnFilterMouseMoved( wxMouseEvent& event ) override;
|
||||
void OnFilterText( wxCommandEvent& event ) override;
|
||||
void OnScope( wxCommandEvent& event ) override;
|
||||
void OnRegroupSymbols( wxCommandEvent& event ) override;
|
||||
|
||||
void OnTableValueChanged( wxGridEvent& event ) override;
|
||||
void OnTableCellClick( wxGridEvent& event ) override;
|
||||
void OnTableItemContextMenu( wxGridEvent& event ) override;
|
||||
void OnTableColSize( wxGridSizeEvent& event ) override;
|
||||
|
||||
void OnSidebarToggle( wxCommandEvent& event ) override;
|
||||
void OnCancel( wxCommandEvent& event ) override;
|
||||
void OnOk( wxCommandEvent& event ) override;
|
||||
void OnApply( wxCommandEvent& event ) override;
|
||||
void OnClose( wxCloseEvent& event ) override;
|
||||
|
||||
private:
|
||||
SYMBOL_EDIT_FRAME* m_parent;
|
||||
SCOPE m_scope;
|
||||
|
||||
VIEW_CONTROLS_GRID_DATA_MODEL* m_viewControlsDataModel;
|
||||
|
||||
LIB_FIELDS_EDITOR_GRID_DATA_MODEL* m_dataModel;
|
||||
std::vector<LIB_SYMBOL*> m_symbolsList;
|
||||
};
|
||||
|
||||
|
||||
#endif // DIALOG_LIB_FIELDS_H
|
@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6a-dirty)
|
||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@ -8,11 +8,11 @@
|
||||
#include "widgets/std_bitmap_button.h"
|
||||
#include "widgets/wx_grid.h"
|
||||
|
||||
#include "dialog_lib_fields_base.h"
|
||||
#include "dialog_lib_fields_table_base.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DIALOG_LIB_FIELDS_BASE::DIALOG_LIB_FIELDS_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style )
|
||||
DIALOG_LIB_FIELDS_TABLE_BASE::DIALOG_LIB_FIELDS_TABLE_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style )
|
||||
{
|
||||
this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize );
|
||||
|
||||
@ -29,10 +29,41 @@ DIALOG_LIB_FIELDS_BASE::DIALOG_LIB_FIELDS_BASE( wxWindow* parent, wxWindowID id,
|
||||
wxBoxSizer* bLeftSizer;
|
||||
bLeftSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_fieldsCtrl = new wxDataViewListCtrl( m_leftPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_fieldsCtrl->SetMinSize( wxSize( -1,250 ) );
|
||||
m_viewControlsGrid = new WX_GRID( m_leftPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
|
||||
bLeftSizer->Add( m_fieldsCtrl, 1, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 5 );
|
||||
// Grid
|
||||
m_viewControlsGrid->CreateGrid( 1, 4 );
|
||||
m_viewControlsGrid->EnableEditing( true );
|
||||
m_viewControlsGrid->EnableGridLines( false );
|
||||
m_viewControlsGrid->EnableDragGridSize( false );
|
||||
m_viewControlsGrid->SetMargins( 0, 0 );
|
||||
|
||||
// Columns
|
||||
m_viewControlsGrid->SetColSize( 0, 60 );
|
||||
m_viewControlsGrid->SetColSize( 1, 60 );
|
||||
m_viewControlsGrid->SetColSize( 2, 46 );
|
||||
m_viewControlsGrid->SetColSize( 3, 56 );
|
||||
m_viewControlsGrid->EnableDragColMove( false );
|
||||
m_viewControlsGrid->EnableDragColSize( false );
|
||||
m_viewControlsGrid->SetColLabelValue( 0, _("Field") );
|
||||
m_viewControlsGrid->SetColLabelValue( 1, _("BOM Name") );
|
||||
m_viewControlsGrid->SetColLabelValue( 2, _("Include") );
|
||||
m_viewControlsGrid->SetColLabelValue( 3, _("Group By") );
|
||||
m_viewControlsGrid->SetColLabelSize( 24 );
|
||||
m_viewControlsGrid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
|
||||
|
||||
// Rows
|
||||
m_viewControlsGrid->EnableDragRowSize( false );
|
||||
m_viewControlsGrid->SetRowLabelSize( 0 );
|
||||
m_viewControlsGrid->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
|
||||
|
||||
// Label Appearance
|
||||
|
||||
// Cell Defaults
|
||||
m_viewControlsGrid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
|
||||
m_viewControlsGrid->SetMinSize( wxSize( -1,250 ) );
|
||||
|
||||
bLeftSizer->Add( m_viewControlsGrid, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
wxBoxSizer* bFieldsButtons;
|
||||
bFieldsButtons = new wxBoxSizer( wxHORIZONTAL );
|
||||
@ -50,7 +81,7 @@ DIALOG_LIB_FIELDS_BASE::DIALOG_LIB_FIELDS_BASE( wxWindow* parent, wxWindowID id,
|
||||
bFieldsButtons->Add( m_removeFieldButton, 0, wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
|
||||
bLeftSizer->Add( bFieldsButtons, 0, wxEXPAND, 5 );
|
||||
bLeftSizer->Add( bFieldsButtons, 0, wxEXPAND|wxTOP|wxBOTTOM, 2 );
|
||||
|
||||
|
||||
m_leftPanel->SetSizer( bLeftSizer );
|
||||
@ -76,6 +107,15 @@ DIALOG_LIB_FIELDS_BASE::DIALOG_LIB_FIELDS_BASE( wxWindow* parent, wxWindowID id,
|
||||
m_staticline31 = new wxStaticLine( m_rightPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
|
||||
bControls->Add( m_staticline31, 0, wxEXPAND | wxALL, 3 );
|
||||
|
||||
wxString m_choiceScopeChoices[] = { _("Whole Library"), _("Related Symbols Only") };
|
||||
int m_choiceScopeNChoices = sizeof( m_choiceScopeChoices ) / sizeof( wxString );
|
||||
m_choiceScope = new wxChoice( m_rightPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceScopeNChoices, m_choiceScopeChoices, 0 );
|
||||
m_choiceScope->SetSelection( 0 );
|
||||
bControls->Add( m_choiceScope, 0, wxALL, 5 );
|
||||
|
||||
m_staticline311 = new wxStaticLine( m_rightPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
|
||||
bControls->Add( m_staticline311, 0, wxEXPAND | wxALL, 5 );
|
||||
|
||||
m_bRefresh = new STD_BITMAP_BUTTON( m_rightPanel, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_bRefresh->SetMinSize( wxSize( 30,30 ) );
|
||||
|
||||
@ -112,35 +152,38 @@ DIALOG_LIB_FIELDS_BASE::DIALOG_LIB_FIELDS_BASE( wxWindow* parent, wxWindowID id,
|
||||
|
||||
bRightSizer->Add( m_grid, 1, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 5 );
|
||||
|
||||
|
||||
m_rightPanel->SetSizer( bRightSizer );
|
||||
m_rightPanel->Layout();
|
||||
bRightSizer->Fit( m_rightPanel );
|
||||
m_splitterMainWindow->SplitVertically( m_leftPanel, m_rightPanel, -1 );
|
||||
bEditSizer->Add( m_splitterMainWindow, 1, wxEXPAND|wxTOP|wxBOTTOM, 5 );
|
||||
|
||||
|
||||
bMainSizer->Add( bEditSizer, 1, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bButtonsSizer;
|
||||
bButtonsSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_sidebarButton = new STD_BITMAP_BUTTON( m_rightPanel, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
bButtonsSizer->Add( m_sidebarButton, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
|
||||
bButtonsSizer->Add( 0, 0, 9, wxEXPAND, 5 );
|
||||
|
||||
m_sdbSizer = new wxStdDialogButtonSizer();
|
||||
m_sdbSizerOK = new wxButton( this, wxID_OK );
|
||||
m_sdbSizerOK = new wxButton( m_rightPanel, wxID_OK );
|
||||
m_sdbSizer->AddButton( m_sdbSizerOK );
|
||||
m_sdbSizerApply = new wxButton( this, wxID_APPLY );
|
||||
m_sdbSizerApply = new wxButton( m_rightPanel, wxID_APPLY );
|
||||
m_sdbSizer->AddButton( m_sdbSizerApply );
|
||||
m_sdbSizerCancel = new wxButton( this, wxID_CANCEL );
|
||||
m_sdbSizerCancel = new wxButton( m_rightPanel, wxID_CANCEL );
|
||||
m_sdbSizer->AddButton( m_sdbSizerCancel );
|
||||
m_sdbSizer->Realize();
|
||||
|
||||
bButtonsSizer->Add( m_sdbSizer, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
bMainSizer->Add( bButtonsSizer, 0, wxEXPAND, 5 );
|
||||
bRightSizer->Add( bButtonsSizer, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_rightPanel->SetSizer( bRightSizer );
|
||||
m_rightPanel->Layout();
|
||||
bRightSizer->Fit( m_rightPanel );
|
||||
m_splitterMainWindow->SplitVertically( m_leftPanel, m_rightPanel, -1 );
|
||||
bEditSizer->Add( m_splitterMainWindow, 1, wxEXPAND|wxALL, 5 );
|
||||
|
||||
|
||||
bMainSizer->Add( bEditSizer, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
this->SetSizer( bMainSizer );
|
||||
@ -150,54 +193,56 @@ DIALOG_LIB_FIELDS_BASE::DIALOG_LIB_FIELDS_BASE( wxWindow* parent, wxWindowID id,
|
||||
this->Centre( wxBOTH );
|
||||
|
||||
// Connect Events
|
||||
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_LIB_FIELDS_BASE::OnClose ) );
|
||||
m_fieldsCtrl->Connect( wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED, wxDataViewEventHandler( DIALOG_LIB_FIELDS_BASE::OnColumnItemToggled ), NULL, this );
|
||||
m_fieldsCtrl->Connect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( DIALOG_LIB_FIELDS_BASE::OnFieldsCtrlSelectionChanged ), NULL, this );
|
||||
m_fieldsCtrl->Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_LIB_FIELDS_BASE::OnSizeFieldList ), NULL, this );
|
||||
m_addFieldButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnAddField ), NULL, this );
|
||||
m_renameFieldButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnRenameField ), NULL, this );
|
||||
m_removeFieldButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnRemoveField ), NULL, this );
|
||||
m_filter->Connect( wxEVT_MOTION, wxMouseEventHandler( DIALOG_LIB_FIELDS_BASE::OnFilterMouseMoved ), NULL, this );
|
||||
m_filter->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnFilterText ), NULL, this );
|
||||
m_bRefresh->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnRegroupSymbols ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableValueChanged ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableCellClick ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableCellClick ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableItemContextMenu ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableCmdCellClick ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableCmdCellClick ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_COL_SIZE, wxGridSizeEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableColSize ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_EDITOR_SHOWN, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnEditorShown ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableSelectCell ), NULL, this );
|
||||
m_sdbSizerApply->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnApply ), NULL, this );
|
||||
m_sdbSizerCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnCancel ), NULL, this );
|
||||
m_sdbSizerOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnOk ), NULL, this );
|
||||
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnClose ) );
|
||||
m_viewControlsGrid->Connect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnViewControlsCellChanged ), NULL, this );
|
||||
m_viewControlsGrid->Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnSizeViewControlsGrid ), NULL, this );
|
||||
m_addFieldButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnAddField ), NULL, this );
|
||||
m_renameFieldButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnRenameField ), NULL, this );
|
||||
m_removeFieldButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnRemoveField ), NULL, this );
|
||||
m_filter->Connect( wxEVT_MOTION, wxMouseEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnFilterMouseMoved ), NULL, this );
|
||||
m_filter->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnFilterText ), NULL, this );
|
||||
m_choiceScope->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnScope ), NULL, this );
|
||||
m_bRefresh->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnRegroupSymbols ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnTableValueChanged ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnTableCellClick ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnTableCellClick ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnTableItemContextMenu ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnTableCmdCellClick ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnTableCmdCellClick ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_COL_SIZE, wxGridSizeEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnTableColSize ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_EDITOR_SHOWN, wxGridEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnEditorShown ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnTableSelectCell ), NULL, this );
|
||||
m_sidebarButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnSidebarToggle ), NULL, this );
|
||||
m_sdbSizerApply->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnApply ), NULL, this );
|
||||
m_sdbSizerCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnCancel ), NULL, this );
|
||||
m_sdbSizerOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnOk ), NULL, this );
|
||||
}
|
||||
|
||||
DIALOG_LIB_FIELDS_BASE::~DIALOG_LIB_FIELDS_BASE()
|
||||
DIALOG_LIB_FIELDS_TABLE_BASE::~DIALOG_LIB_FIELDS_TABLE_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_LIB_FIELDS_BASE::OnClose ) );
|
||||
m_fieldsCtrl->Disconnect( wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED, wxDataViewEventHandler( DIALOG_LIB_FIELDS_BASE::OnColumnItemToggled ), NULL, this );
|
||||
m_fieldsCtrl->Disconnect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( DIALOG_LIB_FIELDS_BASE::OnFieldsCtrlSelectionChanged ), NULL, this );
|
||||
m_fieldsCtrl->Disconnect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_LIB_FIELDS_BASE::OnSizeFieldList ), NULL, this );
|
||||
m_addFieldButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnAddField ), NULL, this );
|
||||
m_renameFieldButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnRenameField ), NULL, this );
|
||||
m_removeFieldButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnRemoveField ), NULL, this );
|
||||
m_filter->Disconnect( wxEVT_MOTION, wxMouseEventHandler( DIALOG_LIB_FIELDS_BASE::OnFilterMouseMoved ), NULL, this );
|
||||
m_filter->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnFilterText ), NULL, this );
|
||||
m_bRefresh->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnRegroupSymbols ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableValueChanged ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableCellClick ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableCellClick ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableItemContextMenu ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableCmdCellClick ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableCmdCellClick ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_COL_SIZE, wxGridSizeEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableColSize ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_EDITOR_SHOWN, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnEditorShown ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( DIALOG_LIB_FIELDS_BASE::OnTableSelectCell ), NULL, this );
|
||||
m_sdbSizerApply->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnApply ), NULL, this );
|
||||
m_sdbSizerCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnCancel ), NULL, this );
|
||||
m_sdbSizerOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_BASE::OnOk ), NULL, this );
|
||||
this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnClose ) );
|
||||
m_viewControlsGrid->Disconnect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnViewControlsCellChanged ), NULL, this );
|
||||
m_viewControlsGrid->Disconnect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnSizeViewControlsGrid ), NULL, this );
|
||||
m_addFieldButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnAddField ), NULL, this );
|
||||
m_renameFieldButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnRenameField ), NULL, this );
|
||||
m_removeFieldButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnRemoveField ), NULL, this );
|
||||
m_filter->Disconnect( wxEVT_MOTION, wxMouseEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnFilterMouseMoved ), NULL, this );
|
||||
m_filter->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnFilterText ), NULL, this );
|
||||
m_choiceScope->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnScope ), NULL, this );
|
||||
m_bRefresh->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnRegroupSymbols ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnTableValueChanged ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnTableCellClick ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnTableCellClick ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnTableItemContextMenu ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnTableCmdCellClick ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnTableCmdCellClick ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_COL_SIZE, wxGridSizeEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnTableColSize ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_EDITOR_SHOWN, wxGridEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnEditorShown ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnTableSelectCell ), NULL, this );
|
||||
m_sidebarButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnSidebarToggle ), NULL, this );
|
||||
m_sdbSizerApply->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnApply ), NULL, this );
|
||||
m_sdbSizerCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnCancel ), NULL, this );
|
||||
m_sdbSizerOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LIB_FIELDS_TABLE_BASE::OnOk ), NULL, this );
|
||||
|
||||
}
|
@ -13,12 +13,12 @@
|
||||
<property name="cpp_use_enum">0</property>
|
||||
<property name="embedded_files_path">res</property>
|
||||
<property name="encoding">UTF-8</property>
|
||||
<property name="file">dialog_lib_fields_base</property>
|
||||
<property name="file">dialog_lib_fields_table_base</property>
|
||||
<property name="first_id">1000</property>
|
||||
<property name="internationalize">1</property>
|
||||
<property name="lua_skip_events">1</property>
|
||||
<property name="lua_ui_table">UI</property>
|
||||
<property name="name">dialog_lib_fields_base</property>
|
||||
<property name="name">dialog_lib_fields_table_base</property>
|
||||
<property name="path">.</property>
|
||||
<property name="php_disconnect_events">0</property>
|
||||
<property name="php_disconnect_mode">source_name</property>
|
||||
@ -48,12 +48,12 @@
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="minimum_size">-1,-1</property>
|
||||
<property name="name">DIALOG_LIB_FIELDS_BASE</property>
|
||||
<property name="name">DIALOG_LIB_FIELDS_TABLE_BASE</property>
|
||||
<property name="pos"></property>
|
||||
<property name="size">-1,-1</property>
|
||||
<property name="style">wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER</property>
|
||||
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
|
||||
<property name="title">Library Fields Editor</property>
|
||||
<property name="title">Library Fields Table (%s)</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="two_step_creation">0</property>
|
||||
<property name="window_extra_style"></property>
|
||||
@ -76,7 +76,7 @@
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND|wxTOP|wxBOTTOM</property>
|
||||
<property name="flag">wxEXPAND|wxALL</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxSplitterWindow" expanded="true">
|
||||
<property name="BottomDockable">1</property>
|
||||
@ -194,40 +194,100 @@
|
||||
<property name="name">bLeftSizer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT|wxTOP</property>
|
||||
<property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxDataViewListCtrl" expanded="false">
|
||||
<object class="wxGrid" 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="autosize_cols">0</property>
|
||||
<property name="autosize_rows">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="cell_bg"></property>
|
||||
<property name="cell_font"></property>
|
||||
<property name="cell_horiz_alignment">wxALIGN_LEFT</property>
|
||||
<property name="cell_text"></property>
|
||||
<property name="cell_vert_alignment">wxALIGN_TOP</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="col_label_horiz_alignment">wxALIGN_CENTER</property>
|
||||
<property name="col_label_size">24</property>
|
||||
<property name="col_label_values">"Field" "BOM Name" "Include" "Group By"</property>
|
||||
<property name="col_label_vert_alignment">wxALIGN_CENTER</property>
|
||||
<property name="cols">4</property>
|
||||
<property name="column_sizes">60,60,46,56</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="drag_col_move">0</property>
|
||||
<property name="drag_col_size">0</property>
|
||||
<property name="drag_grid_size">0</property>
|
||||
<property name="drag_row_size">0</property>
|
||||
<property name="editing">1</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="grid_line_color"></property>
|
||||
<property name="grid_lines">0</property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label_bg"></property>
|
||||
<property name="label_font"></property>
|
||||
<property name="label_text"></property>
|
||||
<property name="margin_height">0</property>
|
||||
<property name="margin_width">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size">-1,250</property>
|
||||
<property name="name">m_fieldsCtrl</property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_viewControlsGrid</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="row_label_horiz_alignment">wxALIGN_CENTER</property>
|
||||
<property name="row_label_size">0</property>
|
||||
<property name="row_label_values"></property>
|
||||
<property name="row_label_vert_alignment">wxALIGN_CENTER</property>
|
||||
<property name="row_sizes"></property>
|
||||
<property name="rows">1</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass"></property>
|
||||
<property name="subclass">WX_GRID; widgets/wx_grid.h; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnDataViewListCtrlItemValueChanged">OnColumnItemToggled</event>
|
||||
<event name="OnDataViewListCtrlSelectionChanged">OnFieldsCtrlSelectionChanged</event>
|
||||
<event name="OnSize">OnSizeFieldList</event>
|
||||
<event name="OnGridCellChange">OnViewControlsCellChanged</event>
|
||||
<event name="OnSize">OnSizeViewControlsGrid</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="border">2</property>
|
||||
<property name="flag">wxEXPAND|wxTOP|wxBOTTOM</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBoxSizer" expanded="true">
|
||||
<property name="minimum_size"></property>
|
||||
@ -668,6 +728,131 @@
|
||||
<property name="window_style"></property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</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">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="choices">"Whole Library" "Related Symbols Only"</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_choiceScope</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>
|
||||
<event name="OnChoice">OnScope</event>
|
||||
</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_staticline311</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style">wxLI_VERTICAL</property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT</property>
|
||||
@ -843,6 +1028,123 @@
|
||||
<event name="OnGridSelectCell">OnTableSelectCell</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBoxSizer" expanded="true">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bButtonsSizer</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|wxRIGHT|wxLEFT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBitmapButton" 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="auth_needed">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="bitmap"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="current"></property>
|
||||
<property name="default">0</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="disabled"></property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="focus"></property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Remove Field...</property>
|
||||
<property name="margins"></property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_sidebarButton</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="position"></property>
|
||||
<property name="pressed"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnButtonClick">OnSidebarToggle</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">9</property>
|
||||
<object class="spacer" expanded="false">
|
||||
<property name="height">0</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="width">0</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStdDialogButtonSizer" expanded="false">
|
||||
<property name="Apply">1</property>
|
||||
<property name="Cancel">1</property>
|
||||
<property name="ContextHelp">0</property>
|
||||
<property name="Help">0</property>
|
||||
<property name="No">0</property>
|
||||
<property name="OK">1</property>
|
||||
<property name="Save">0</property>
|
||||
<property name="Yes">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">m_sdbSizer</property>
|
||||
<property name="permission">protected</property>
|
||||
<event name="OnApplyButtonClick">OnApply</event>
|
||||
<event name="OnCancelButtonClick">OnCancel</event>
|
||||
<event name="OnOKButtonClick">OnOk</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
@ -850,48 +1152,6 @@
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBoxSizer" expanded="true">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bButtonsSizer</property>
|
||||
<property name="orient">wxHORIZONTAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">9</property>
|
||||
<object class="spacer" expanded="false">
|
||||
<property name="height">0</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="width">0</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStdDialogButtonSizer" expanded="false">
|
||||
<property name="Apply">1</property>
|
||||
<property name="Cancel">1</property>
|
||||
<property name="ContextHelp">0</property>
|
||||
<property name="Help">0</property>
|
||||
<property name="No">0</property>
|
||||
<property name="OK">1</property>
|
||||
<property name="Save">0</property>
|
||||
<property name="Yes">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">m_sdbSizer</property>
|
||||
<property name="permission">protected</property>
|
||||
<event name="OnApplyButtonClick">OnApply</event>
|
||||
<event name="OnCancelButtonClick">OnCancel</event>
|
||||
<event name="OnOKButtonClick">OnOk</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6a-dirty)
|
||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@ -14,12 +14,12 @@ class STD_BITMAP_BUTTON;
|
||||
class WX_GRID;
|
||||
|
||||
#include "dialog_shim.h"
|
||||
#include <wx/dataview.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/string.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/grid.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/bmpbuttn.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
@ -29,31 +29,34 @@ class WX_GRID;
|
||||
#include <wx/panel.h>
|
||||
#include <wx/srchctrl.h>
|
||||
#include <wx/statline.h>
|
||||
#include <wx/grid.h>
|
||||
#include <wx/choice.h>
|
||||
#include <wx/splitter.h>
|
||||
#include <wx/dialog.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class DIALOG_LIB_FIELDS_BASE
|
||||
/// Class DIALOG_LIB_FIELDS_TABLE_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class DIALOG_LIB_FIELDS_BASE : public DIALOG_SHIM
|
||||
class DIALOG_LIB_FIELDS_TABLE_BASE : public DIALOG_SHIM
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxSplitterWindow* m_splitterMainWindow;
|
||||
wxPanel* m_leftPanel;
|
||||
wxDataViewListCtrl* m_fieldsCtrl;
|
||||
WX_GRID* m_viewControlsGrid;
|
||||
STD_BITMAP_BUTTON* m_addFieldButton;
|
||||
STD_BITMAP_BUTTON* m_renameFieldButton;
|
||||
STD_BITMAP_BUTTON* m_removeFieldButton;
|
||||
wxPanel* m_rightPanel;
|
||||
wxSearchCtrl* m_filter;
|
||||
wxStaticLine* m_staticline31;
|
||||
wxChoice* m_choiceScope;
|
||||
wxStaticLine* m_staticline311;
|
||||
STD_BITMAP_BUTTON* m_bRefresh;
|
||||
WX_GRID* m_grid;
|
||||
STD_BITMAP_BUTTON* m_sidebarButton;
|
||||
wxStdDialogButtonSizer* m_sdbSizer;
|
||||
wxButton* m_sdbSizerOK;
|
||||
wxButton* m_sdbSizerApply;
|
||||
@ -61,14 +64,14 @@ class DIALOG_LIB_FIELDS_BASE : public DIALOG_SHIM
|
||||
|
||||
// Virtual event handlers, override them in your derived class
|
||||
virtual void OnClose( wxCloseEvent& event ) { event.Skip(); }
|
||||
virtual void OnColumnItemToggled( wxDataViewEvent& event ) { event.Skip(); }
|
||||
virtual void OnFieldsCtrlSelectionChanged( wxDataViewEvent& event ) { event.Skip(); }
|
||||
virtual void OnSizeFieldList( wxSizeEvent& event ) { event.Skip(); }
|
||||
virtual void OnViewControlsCellChanged( wxGridEvent& event ) { event.Skip(); }
|
||||
virtual void OnSizeViewControlsGrid( wxSizeEvent& event ) { event.Skip(); }
|
||||
virtual void OnAddField( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnRenameField( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnRemoveField( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnFilterMouseMoved( wxMouseEvent& event ) { event.Skip(); }
|
||||
virtual void OnFilterText( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnScope( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnRegroupSymbols( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnTableValueChanged( wxGridEvent& event ) { event.Skip(); }
|
||||
virtual void OnTableCellClick( wxGridEvent& event ) { event.Skip(); }
|
||||
@ -77,6 +80,7 @@ class DIALOG_LIB_FIELDS_BASE : public DIALOG_SHIM
|
||||
virtual void OnTableColSize( wxGridSizeEvent& event ) { event.Skip(); }
|
||||
virtual void OnEditorShown( wxGridEvent& event ) { event.Skip(); }
|
||||
virtual void OnTableSelectCell( wxGridEvent& event ) { event.Skip(); }
|
||||
virtual void OnSidebarToggle( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnApply( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnOk( wxCommandEvent& event ) { event.Skip(); }
|
||||
@ -84,9 +88,9 @@ class DIALOG_LIB_FIELDS_BASE : public DIALOG_SHIM
|
||||
|
||||
public:
|
||||
|
||||
DIALOG_LIB_FIELDS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Library Fields Editor"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER );
|
||||
DIALOG_LIB_FIELDS_TABLE_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Library Fields Table (%s)"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER );
|
||||
|
||||
~DIALOG_LIB_FIELDS_BASE();
|
||||
~DIALOG_LIB_FIELDS_TABLE_BASE();
|
||||
|
||||
};
|
||||
|
@ -133,21 +133,16 @@ void DIALOG_SCH_FIND::onShowSearchPanel( wxHyperlinkEvent& event )
|
||||
{
|
||||
wxCHECK2( m_frame->GetFrameType() == FRAME_SCH, /* void */ );
|
||||
|
||||
if( static_cast<SCH_EDIT_FRAME*>( m_frame )->IsSearchPaneShown() )
|
||||
{
|
||||
EndModal( wxID_CANCEL );
|
||||
m_frame->GetToolManager()->RunAction( ACTIONS::showSearch );
|
||||
|
||||
CallAfter(
|
||||
[]()
|
||||
{
|
||||
if( wxWindow* frame = wxWindow::FindWindowByName( SCH_EDIT_FRAME_NAME ) )
|
||||
static_cast<SCH_EDIT_FRAME*>( frame )->FocusSearch();
|
||||
} );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_frame->GetToolManager()->RunAction( ACTIONS::showSearch );
|
||||
}
|
||||
EndModal( wxID_CANCEL );
|
||||
|
||||
CallAfter(
|
||||
[]()
|
||||
{
|
||||
if( wxWindow* frame = wxWindow::FindWindowByName( SCH_EDIT_FRAME_NAME ) )
|
||||
static_cast<SCH_EDIT_FRAME*>( frame )->FocusSearch();
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
|
@ -149,7 +149,7 @@ DIALOG_SCH_FIND_BASE::DIALOG_SCH_FIND_BASE( wxWindow* parent, wxWindowID id, con
|
||||
m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
bSizer6->Add( m_staticline1, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 );
|
||||
|
||||
m_searchPanelLink = new wxHyperlinkCtrl( this, wxID_ANY, _("Show search panel"), wxT("http://www.wxformbuilder.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
|
||||
m_searchPanelLink = new wxHyperlinkCtrl( this, wxID_ANY, _("Show search panel"), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
|
||||
bSizer6->Add( m_searchPanelLink, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_RIGHT, 5 );
|
||||
|
||||
|
||||
|
@ -1648,7 +1648,7 @@
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="url">http://www.wxformbuilder.org</property>
|
||||
<property name="url"></property>
|
||||
<property name="visited_color"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
|
@ -77,8 +77,8 @@ public:
|
||||
*/
|
||||
std::vector<std::pair<FIELD_T, wxString>> GetFields() const;
|
||||
|
||||
bool GetKeepSymbol() { return m_keepSymbol; }
|
||||
bool GetPlaceAllUnits() { return m_useUnits; }
|
||||
bool GetKeepSymbol() { return m_keepSymbol->GetValue(); }
|
||||
bool GetPlaceAllUnits() { return m_useUnits->GetValue(); }
|
||||
|
||||
public:
|
||||
static std::mutex g_Mutex;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -22,21 +22,17 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef DIALOG_SYMBOL_FIELDS_TABLE_H
|
||||
#define DIALOG_SYMBOL_FIELDS_TABLE_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <dialog_symbol_fields_table_base.h>
|
||||
#include <sch_reference_list.h>
|
||||
#include <schematic.h>
|
||||
#include <fields_data_model.h>
|
||||
|
||||
wxDECLARE_EVENT( EDA_EVT_CLOSE_DIALOG_SYMBOL_FIELDS_TABLE, wxCommandEvent );
|
||||
|
||||
class SCHEMATIC_SETTINGS;
|
||||
struct BOM_PRESET;
|
||||
struct BOM_FMT_PRESET;
|
||||
class SCH_EDIT_FRAME;
|
||||
class FIELDS_EDITOR_GRID_DATA_MODEL;
|
||||
class JOB_EXPORT_SCH_BOM;
|
||||
|
||||
|
||||
@ -44,19 +40,21 @@ class DIALOG_SYMBOL_FIELDS_TABLE : public DIALOG_SYMBOL_FIELDS_TABLE_BASE, publi
|
||||
{
|
||||
public:
|
||||
DIALOG_SYMBOL_FIELDS_TABLE( SCH_EDIT_FRAME* parent, JOB_EXPORT_SCH_BOM* aJob = nullptr );
|
||||
virtual ~DIALOG_SYMBOL_FIELDS_TABLE();
|
||||
~DIALOG_SYMBOL_FIELDS_TABLE() override;
|
||||
|
||||
bool TransferDataToWindow() override;
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
void ShowEditTab();
|
||||
void ShowExportTab();
|
||||
void ShowHideColumn( int aCol, bool aShow );
|
||||
|
||||
private:
|
||||
void SetupColumnProperties( int aCol );
|
||||
void SetupAllColumnProperties();
|
||||
void AddField( const wxString& displayName, const wxString& aCanonicalName, bool show,
|
||||
bool groupBy, bool addedByUser = false );
|
||||
void setScope( FIELDS_EDITOR_GRID_DATA_MODEL::SCOPE aScope );
|
||||
|
||||
/**
|
||||
* Construct the rows of m_fieldsCtrl and the columns of m_dataModel from a union of all
|
||||
@ -64,33 +62,33 @@ private:
|
||||
*/
|
||||
void LoadFieldNames();
|
||||
|
||||
void OnColSort( wxGridEvent& aEvent );
|
||||
void OnColMove( wxGridEvent& aEvent );
|
||||
void OnColLabelChange( wxDataViewEvent& aEvent );
|
||||
void OnTableRangeSelected( wxGridRangeSelectEvent& aEvent );
|
||||
|
||||
void OnColumnItemToggled( wxDataViewEvent& event ) override;
|
||||
void OnGroupSymbolsToggled( wxCommandEvent& event ) override;
|
||||
void OnExcludeDNPToggled( wxCommandEvent& event ) override;
|
||||
void OnShowExcludedToggled( wxCommandEvent& event ) override;
|
||||
void OnRegroupSymbols( wxCommandEvent& aEvent ) override;
|
||||
void OnScopeChanged( wxCommandEvent& aEvent ) override;
|
||||
void UpdateScope();
|
||||
void OnTableValueChanged( wxGridEvent& event ) override;
|
||||
void OnTableCellClick( wxGridEvent& event ) override;
|
||||
void OnTableItemContextMenu( wxGridEvent& event ) override;
|
||||
void OnTableColSize( wxGridSizeEvent& event ) override;
|
||||
void OnSizeFieldList( wxSizeEvent& event ) override;
|
||||
void OnViewControlsCellChanged( wxGridEvent& aEvent ) override;
|
||||
void OnSizeViewControlsGrid( wxSizeEvent& event ) override;
|
||||
void OnAddField( wxCommandEvent& event ) override;
|
||||
void OnRemoveField( wxCommandEvent& event ) override;
|
||||
void OnRenameField( wxCommandEvent& event ) override;
|
||||
|
||||
void OnColSort( wxGridEvent& aEvent );
|
||||
void OnColMove( wxGridEvent& aEvent );
|
||||
void OnTableRangeSelected( wxGridRangeSelectEvent& aEvent );
|
||||
|
||||
void OnFilterText( wxCommandEvent& aEvent ) override;
|
||||
void OnFilterMouseMoved( wxMouseEvent& event ) override;
|
||||
void OnScope( wxCommandEvent& event ) override;
|
||||
void OnGroupSymbolsToggled( wxCommandEvent& event ) override;
|
||||
void OnRegroupSymbols( wxCommandEvent& aEvent ) override;
|
||||
void OnMenu( wxCommandEvent& event ) override;
|
||||
|
||||
void OnTableValueChanged( wxGridEvent& event ) override;
|
||||
void OnTableCellClick( wxGridEvent& event ) override;
|
||||
void OnTableColSize( wxGridSizeEvent& event ) override;
|
||||
|
||||
void OnSidebarToggle( wxCommandEvent& event ) override;
|
||||
void OnExport( wxCommandEvent& aEvent ) override;
|
||||
void OnSaveAndContinue( wxCommandEvent& aEvent ) override;
|
||||
void OnCancel( wxCommandEvent& aEvent ) override;
|
||||
void OnClose( wxCloseEvent& aEvent ) override;
|
||||
void OnOk( wxCommandEvent& aEvent ) override;
|
||||
void OnFilterText( wxCommandEvent& aEvent ) override;
|
||||
void OnFilterMouseMoved( wxMouseEvent& event ) override;
|
||||
void OnClose( wxCloseEvent& aEvent ) override;
|
||||
|
||||
void OnOutputFileBrowseClicked( wxCommandEvent& event ) override;
|
||||
void OnPageChanged( wxNotebookEvent& event ) override;
|
||||
@ -155,10 +153,7 @@ private:
|
||||
// Index in the fields list control for each MANDATORY_FIELD type
|
||||
std::map<FIELD_T, int> m_mandatoryFieldListIndexes;
|
||||
|
||||
int m_fieldNameColWidth;
|
||||
int m_labelColWidth;
|
||||
int m_showColWidth;
|
||||
int m_groupByColWidth;
|
||||
VIEW_CONTROLS_GRID_DATA_MODEL* m_viewControlsDataModel;
|
||||
|
||||
SCH_REFERENCE_LIST m_symbolsList;
|
||||
FIELDS_EDITOR_GRID_DATA_MODEL* m_dataModel;
|
||||
@ -167,5 +162,3 @@ private:
|
||||
|
||||
JOB_EXPORT_SCH_BOM* m_job;
|
||||
};
|
||||
|
||||
#endif /* DIALOG_SYMBOL_FIELDS_TABLE_H */
|
||||
|
@ -19,22 +19,51 @@ DIALOG_SYMBOL_FIELDS_TABLE_BASE::DIALOG_SYMBOL_FIELDS_TABLE_BASE( wxWindow* pare
|
||||
wxBoxSizer* bMainSizer;
|
||||
bMainSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_nbPages = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_panelEdit = new wxPanel( m_nbPages, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
wxBoxSizer* bEditSizer;
|
||||
bEditSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_splitterMainWindow = new wxSplitterWindow( m_panelEdit, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_3DSASH|wxSP_LIVE_UPDATE|wxSP_NO_XP_THEME );
|
||||
m_splitterMainWindow->SetMinimumPaneSize( 200 );
|
||||
m_splitterMainWindow = new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_3DSASH|wxSP_LIVE_UPDATE|wxSP_NO_XP_THEME );
|
||||
m_splitterMainWindow->SetMinimumPaneSize( 120 );
|
||||
|
||||
m_leftPanel = new wxPanel( m_splitterMainWindow, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
wxBoxSizer* bLeftSizer;
|
||||
bLeftSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_fieldsCtrl = new wxDataViewListCtrl( m_leftPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_fieldsCtrl->SetMinSize( wxSize( -1,250 ) );
|
||||
wxBoxSizer* bMargins;
|
||||
bMargins = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
bLeftSizer->Add( m_fieldsCtrl, 1, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 5 );
|
||||
m_viewControlsGrid = new WX_GRID( m_leftPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
|
||||
// Grid
|
||||
m_viewControlsGrid->CreateGrid( 1, 4 );
|
||||
m_viewControlsGrid->EnableEditing( true );
|
||||
m_viewControlsGrid->EnableGridLines( false );
|
||||
m_viewControlsGrid->EnableDragGridSize( false );
|
||||
m_viewControlsGrid->SetMargins( 0, 0 );
|
||||
|
||||
// Columns
|
||||
m_viewControlsGrid->SetColSize( 0, 60 );
|
||||
m_viewControlsGrid->SetColSize( 1, 60 );
|
||||
m_viewControlsGrid->SetColSize( 2, 46 );
|
||||
m_viewControlsGrid->SetColSize( 3, 56 );
|
||||
m_viewControlsGrid->EnableDragColMove( false );
|
||||
m_viewControlsGrid->EnableDragColSize( false );
|
||||
m_viewControlsGrid->SetColLabelValue( 0, _("Field") );
|
||||
m_viewControlsGrid->SetColLabelValue( 1, _("BOM Name") );
|
||||
m_viewControlsGrid->SetColLabelValue( 2, _("Include") );
|
||||
m_viewControlsGrid->SetColLabelValue( 3, _("Group By") );
|
||||
m_viewControlsGrid->SetColLabelSize( 24 );
|
||||
m_viewControlsGrid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
|
||||
|
||||
// Rows
|
||||
m_viewControlsGrid->EnableDragRowSize( false );
|
||||
m_viewControlsGrid->SetRowLabelSize( 0 );
|
||||
m_viewControlsGrid->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
|
||||
|
||||
// Label Appearance
|
||||
|
||||
// Cell Defaults
|
||||
m_viewControlsGrid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
|
||||
m_viewControlsGrid->SetMinSize( wxSize( -1,250 ) );
|
||||
|
||||
bMargins->Add( m_viewControlsGrid, 1, wxEXPAND|wxTOP|wxLEFT, 5 );
|
||||
|
||||
wxBoxSizer* bFieldsButtons;
|
||||
bFieldsButtons = new wxBoxSizer( wxHORIZONTAL );
|
||||
@ -58,26 +87,32 @@ DIALOG_SYMBOL_FIELDS_TABLE_BASE::DIALOG_SYMBOL_FIELDS_TABLE_BASE( wxWindow* pare
|
||||
bFieldsButtons->Add( m_removeFieldButton, 0, wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
|
||||
bLeftSizer->Add( bFieldsButtons, 0, wxEXPAND, 5 );
|
||||
bMargins->Add( bFieldsButtons, 0, wxEXPAND|wxTOP, 5 );
|
||||
|
||||
wxBoxSizer* bPresets;
|
||||
bPresets = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_staticline1 = new wxStaticLine( m_leftPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
bPresets->Add( m_staticline1, 0, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 );
|
||||
m_staticline11 = new wxStaticLine( m_leftPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
bPresets->Add( m_staticline11, 0, wxEXPAND|wxBOTTOM, 5 );
|
||||
|
||||
m_bomPresetsLabel = new wxStaticText( m_leftPanel, wxID_ANY, _("View presets:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_bomPresetsLabel->Wrap( -1 );
|
||||
bPresets->Add( m_bomPresetsLabel, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
bPresets->Add( m_bomPresetsLabel, 0, 0, 5 );
|
||||
|
||||
|
||||
bPresets->Add( 0, 2, 0, 0, 5 );
|
||||
|
||||
wxString m_cbBomPresetsChoices[] = { _("Default"), _("(unsaved)") };
|
||||
int m_cbBomPresetsNChoices = sizeof( m_cbBomPresetsChoices ) / sizeof( wxString );
|
||||
m_cbBomPresets = new wxChoice( m_leftPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_cbBomPresetsNChoices, m_cbBomPresetsChoices, 0 );
|
||||
m_cbBomPresets->SetSelection( 0 );
|
||||
bPresets->Add( m_cbBomPresets, 0, wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 4 );
|
||||
bPresets->Add( m_cbBomPresets, 0, wxEXPAND|wxBOTTOM, 2 );
|
||||
|
||||
|
||||
bLeftSizer->Add( bPresets, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 );
|
||||
bMargins->Add( bPresets, 0, wxEXPAND|wxTOP|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
|
||||
bLeftSizer->Add( bMargins, 1, wxEXPAND|wxALL, 5 );
|
||||
|
||||
|
||||
m_leftPanel->SetSizer( bLeftSizer );
|
||||
@ -87,50 +122,59 @@ DIALOG_SYMBOL_FIELDS_TABLE_BASE::DIALOG_SYMBOL_FIELDS_TABLE_BASE( wxWindow* pare
|
||||
wxBoxSizer* bRightSizer;
|
||||
bRightSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_nbPages = new wxNotebook( m_rightPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_panelEdit = new wxPanel( m_nbPages, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
wxBoxSizer* bEditSizer;
|
||||
bEditSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxBoxSizer* bControls;
|
||||
bControls = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_filter = new wxSearchCtrl( m_rightPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_filter = new wxSearchCtrl( m_panelEdit, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
#ifndef __WXMAC__
|
||||
m_filter->ShowSearchButton( true );
|
||||
#endif
|
||||
m_filter->ShowCancelButton( true );
|
||||
m_filter->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
|
||||
m_filter->SetMinSize( wxSize( 140,-1 ) );
|
||||
m_filter->SetMinSize( wxSize( 240,-1 ) );
|
||||
|
||||
bControls->Add( m_filter, 1, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
|
||||
|
||||
m_staticline31 = new wxStaticLine( m_rightPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
|
||||
m_staticline31 = new wxStaticLine( m_panelEdit, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
|
||||
bControls->Add( m_staticline31, 0, wxEXPAND | wxALL, 3 );
|
||||
|
||||
m_checkExcludeDNP = new wxCheckBox( m_rightPanel, wxID_ANY, _("Exclude DNP"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bControls->Add( m_checkExcludeDNP, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
wxString m_scopeChoices[] = { _("Entire Project"), _("Current Sheet Only"), _("Current Sheet and Down") };
|
||||
int m_scopeNChoices = sizeof( m_scopeChoices ) / sizeof( wxString );
|
||||
m_scope = new wxChoice( m_panelEdit, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_scopeNChoices, m_scopeChoices, 0 );
|
||||
m_scope->SetSelection( 0 );
|
||||
bControls->Add( m_scope, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_checkShowExcluded = new wxCheckBox( m_rightPanel, wxID_ANY, _("Show 'Exclude from BOM'"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_checkShowExcluded->SetValue(true);
|
||||
bControls->Add( m_checkShowExcluded, 0, wxALL, 5 );
|
||||
m_staticline311 = new wxStaticLine( m_panelEdit, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
|
||||
bControls->Add( m_staticline311, 0, wxEXPAND | wxALL, 5 );
|
||||
|
||||
m_staticline32 = new wxStaticLine( m_rightPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
|
||||
bControls->Add( m_staticline32, 0, wxEXPAND | wxALL, 3 );
|
||||
|
||||
m_groupSymbolsBox = new wxCheckBox( m_rightPanel, wxID_ANY, _("Group symbols"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_groupSymbolsBox = new wxCheckBox( m_panelEdit, wxID_ANY, _("Group symbols"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_groupSymbolsBox->SetValue(true);
|
||||
m_groupSymbolsBox->SetToolTip( _("Group symbols together based on common properties") );
|
||||
|
||||
bControls->Add( m_groupSymbolsBox, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
bControls->Add( m_groupSymbolsBox, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 8 );
|
||||
|
||||
m_staticline3 = new wxStaticLine( m_rightPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
|
||||
bControls->Add( m_staticline3, 0, wxEXPAND | wxALL, 3 );
|
||||
m_staticline3 = new wxStaticLine( m_panelEdit, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
|
||||
bControls->Add( m_staticline3, 0, wxEXPAND|wxTOP|wxBOTTOM|wxRIGHT, 3 );
|
||||
|
||||
m_bRefresh = new STD_BITMAP_BUTTON( m_rightPanel, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_bRefresh = new STD_BITMAP_BUTTON( m_panelEdit, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_bRefresh->SetMinSize( wxSize( 30,30 ) );
|
||||
|
||||
bControls->Add( m_bRefresh, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
m_bMenu = new STD_BITMAP_BUTTON( m_panelEdit, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_bMenu->SetMinSize( wxSize( 30,30 ) );
|
||||
|
||||
bRightSizer->Add( bControls, 0, wxEXPAND|wxLEFT|wxTOP, 5 );
|
||||
bControls->Add( m_bMenu, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_grid = new WX_GRID( m_rightPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
|
||||
bEditSizer->Add( bControls, 0, wxEXPAND|wxLEFT|wxTOP, 5 );
|
||||
|
||||
m_grid = new WX_GRID( m_panelEdit, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
|
||||
// Grid
|
||||
m_grid->CreateGrid( 5, 5 );
|
||||
@ -156,51 +200,7 @@ DIALOG_SYMBOL_FIELDS_TABLE_BASE::DIALOG_SYMBOL_FIELDS_TABLE_BASE( wxWindow* pare
|
||||
m_grid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_CENTER );
|
||||
m_grid->SetMinSize( wxSize( 400,200 ) );
|
||||
|
||||
bRightSizer->Add( m_grid, 1, wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 5 );
|
||||
|
||||
m_staticline7 = new wxStaticLine( m_rightPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
bRightSizer->Add( m_staticline7, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
wxFlexGridSizer* fgSizer1;
|
||||
fgSizer1 = new wxFlexGridSizer( 0, 4, 0, 0 );
|
||||
fgSizer1->SetFlexibleDirection( wxBOTH );
|
||||
fgSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_scopeLabel = new wxStaticText( m_rightPanel, wxID_ANY, _("Scope:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_scopeLabel->Wrap( -1 );
|
||||
fgSizer1->Add( m_scopeLabel, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_radioProject = new wxRadioButton( m_rightPanel, wxID_ANY, _("Entire project"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
|
||||
fgSizer1->Add( m_radioProject, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
m_radioCurrentSheet = new wxRadioButton( m_rightPanel, wxID_ANY, _("Current sheet only"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer1->Add( m_radioCurrentSheet, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
m_radioRecursive = new wxRadioButton( m_rightPanel, wxID_ANY, _("Recursive"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer1->Add( m_radioRecursive, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_crossProbeLabel = new wxStaticText( m_rightPanel, wxID_ANY, _("Cross-probe action:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_crossProbeLabel->Wrap( -1 );
|
||||
fgSizer1->Add( m_crossProbeLabel, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_radioHighlight = new wxRadioButton( m_rightPanel, wxID_ANY, _("Highlight"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
|
||||
fgSizer1->Add( m_radioHighlight, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
m_radioSelect = new wxRadioButton( m_rightPanel, wxID_ANY, _("Select"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer1->Add( m_radioSelect, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
m_radioOff = new wxRadioButton( m_rightPanel, wxID_ANY, _("None"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer1->Add( m_radioOff, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
bRightSizer->Add( fgSizer1, 0, 0, 5 );
|
||||
|
||||
|
||||
m_rightPanel->SetSizer( bRightSizer );
|
||||
m_rightPanel->Layout();
|
||||
bRightSizer->Fit( m_rightPanel );
|
||||
m_splitterMainWindow->SplitVertically( m_leftPanel, m_rightPanel, -1 );
|
||||
bEditSizer->Add( m_splitterMainWindow, 1, wxEXPAND|wxTOP|wxBOTTOM, 5 );
|
||||
bEditSizer->Add( m_grid, 1, wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 5 );
|
||||
|
||||
|
||||
m_panelEdit->SetSizer( bEditSizer );
|
||||
@ -327,31 +327,43 @@ DIALOG_SYMBOL_FIELDS_TABLE_BASE::DIALOG_SYMBOL_FIELDS_TABLE_BASE( wxWindow* pare
|
||||
gbExport->Fit( m_panelExport );
|
||||
m_nbPages->AddPage( m_panelExport, _("Export"), false );
|
||||
|
||||
bMainSizer->Add( m_nbPages, 1, wxEXPAND | wxALL, 5 );
|
||||
bRightSizer->Add( m_nbPages, 1, wxEXPAND|wxALL, 5 );
|
||||
|
||||
wxBoxSizer* bButtonsSizer;
|
||||
bButtonsSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_sidebarButton = new STD_BITMAP_BUTTON( m_rightPanel, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_sidebarButton->SetToolTip( _("Add a new field") );
|
||||
|
||||
bButtonsSizer->Add( m_sidebarButton, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
|
||||
bButtonsSizer->Add( 0, 0, 9, wxEXPAND, 5 );
|
||||
|
||||
m_buttonExport = new wxButton( this, wxID_ANY, _("Export"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_buttonExport = new wxButton( m_rightPanel, wxID_ANY, _("Export"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bButtonsSizer->Add( m_buttonExport, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 10 );
|
||||
|
||||
m_buttonApply = new wxButton( this, wxID_ANY, _("Apply, Save Schematic && Continue"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_buttonApply = new wxButton( m_rightPanel, wxID_ANY, _("Apply, Save Schematic && Continue"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bButtonsSizer->Add( m_buttonApply, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 10 );
|
||||
|
||||
m_sdbSizer = new wxStdDialogButtonSizer();
|
||||
m_sdbSizerOK = new wxButton( this, wxID_OK );
|
||||
m_sdbSizerOK = new wxButton( m_rightPanel, wxID_OK );
|
||||
m_sdbSizer->AddButton( m_sdbSizerOK );
|
||||
m_sdbSizerCancel = new wxButton( this, wxID_CANCEL );
|
||||
m_sdbSizerCancel = new wxButton( m_rightPanel, wxID_CANCEL );
|
||||
m_sdbSizer->AddButton( m_sdbSizerCancel );
|
||||
m_sdbSizer->Realize();
|
||||
|
||||
bButtonsSizer->Add( m_sdbSizer, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
bMainSizer->Add( bButtonsSizer, 0, wxEXPAND, 5 );
|
||||
bRightSizer->Add( bButtonsSizer, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_rightPanel->SetSizer( bRightSizer );
|
||||
m_rightPanel->Layout();
|
||||
bRightSizer->Fit( m_rightPanel );
|
||||
m_splitterMainWindow->SplitVertically( m_leftPanel, m_rightPanel, -1 );
|
||||
bMainSizer->Add( m_splitterMainWindow, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
this->SetSizer( bMainSizer );
|
||||
@ -362,26 +374,22 @@ DIALOG_SYMBOL_FIELDS_TABLE_BASE::DIALOG_SYMBOL_FIELDS_TABLE_BASE( wxWindow* pare
|
||||
|
||||
// Connect Events
|
||||
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnClose ) );
|
||||
m_nbPages->Connect( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, wxNotebookEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnPageChanged ), NULL, this );
|
||||
m_fieldsCtrl->Connect( wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED, wxDataViewEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnColumnItemToggled ), NULL, this );
|
||||
m_fieldsCtrl->Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnSizeFieldList ), NULL, this );
|
||||
m_viewControlsGrid->Connect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnViewControlsCellChanged ), NULL, this );
|
||||
m_viewControlsGrid->Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnSizeViewControlsGrid ), NULL, this );
|
||||
m_addFieldButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnAddField ), NULL, this );
|
||||
m_renameFieldButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnRenameField ), NULL, this );
|
||||
m_removeFieldButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnRemoveField ), NULL, this );
|
||||
m_nbPages->Connect( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, wxNotebookEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnPageChanged ), NULL, this );
|
||||
m_filter->Connect( wxEVT_MOTION, wxMouseEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnFilterMouseMoved ), NULL, this );
|
||||
m_filter->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnFilterText ), NULL, this );
|
||||
m_checkExcludeDNP->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnExcludeDNPToggled ), NULL, this );
|
||||
m_checkShowExcluded->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnShowExcludedToggled ), NULL, this );
|
||||
m_scope->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnScope ), NULL, this );
|
||||
m_groupSymbolsBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnGroupSymbolsToggled ), NULL, this );
|
||||
m_bRefresh->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnRegroupSymbols ), NULL, this );
|
||||
m_bMenu->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnMenu ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnTableValueChanged ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnTableCellClick ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnTableCellClick ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnTableItemContextMenu ), NULL, this );
|
||||
m_grid->Connect( wxEVT_GRID_COL_SIZE, wxGridSizeEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnTableColSize ), NULL, this );
|
||||
m_radioProject->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnScopeChanged ), NULL, this );
|
||||
m_radioCurrentSheet->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnScopeChanged ), NULL, this );
|
||||
m_radioRecursive->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnScopeChanged ), NULL, this );
|
||||
m_textFieldDelimiter->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnPreviewRefresh ), NULL, this );
|
||||
m_textStringDelimiter->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnPreviewRefresh ), NULL, this );
|
||||
m_textRefDelimiter->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnPreviewRefresh ), NULL, this );
|
||||
@ -390,6 +398,7 @@ DIALOG_SYMBOL_FIELDS_TABLE_BASE::DIALOG_SYMBOL_FIELDS_TABLE_BASE( wxWindow* pare
|
||||
m_checkKeepLineBreaks->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnPreviewRefresh ), NULL, this );
|
||||
m_browseButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnOutputFileBrowseClicked ), NULL, this );
|
||||
m_bRefreshPreview->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnPreviewRefresh ), NULL, this );
|
||||
m_sidebarButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnSidebarToggle ), NULL, this );
|
||||
m_buttonExport->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnExport ), NULL, this );
|
||||
m_buttonApply->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnSaveAndContinue ), NULL, this );
|
||||
m_sdbSizerCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnCancel ), NULL, this );
|
||||
@ -400,26 +409,22 @@ DIALOG_SYMBOL_FIELDS_TABLE_BASE::~DIALOG_SYMBOL_FIELDS_TABLE_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnClose ) );
|
||||
m_nbPages->Disconnect( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, wxNotebookEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnPageChanged ), NULL, this );
|
||||
m_fieldsCtrl->Disconnect( wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED, wxDataViewEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnColumnItemToggled ), NULL, this );
|
||||
m_fieldsCtrl->Disconnect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnSizeFieldList ), NULL, this );
|
||||
m_viewControlsGrid->Disconnect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnViewControlsCellChanged ), NULL, this );
|
||||
m_viewControlsGrid->Disconnect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnSizeViewControlsGrid ), NULL, this );
|
||||
m_addFieldButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnAddField ), NULL, this );
|
||||
m_renameFieldButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnRenameField ), NULL, this );
|
||||
m_removeFieldButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnRemoveField ), NULL, this );
|
||||
m_nbPages->Disconnect( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, wxNotebookEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnPageChanged ), NULL, this );
|
||||
m_filter->Disconnect( wxEVT_MOTION, wxMouseEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnFilterMouseMoved ), NULL, this );
|
||||
m_filter->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnFilterText ), NULL, this );
|
||||
m_checkExcludeDNP->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnExcludeDNPToggled ), NULL, this );
|
||||
m_checkShowExcluded->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnShowExcludedToggled ), NULL, this );
|
||||
m_scope->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnScope ), NULL, this );
|
||||
m_groupSymbolsBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnGroupSymbolsToggled ), NULL, this );
|
||||
m_bRefresh->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnRegroupSymbols ), NULL, this );
|
||||
m_bMenu->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnMenu ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_CHANGED, wxGridEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnTableValueChanged ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnTableCellClick ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnTableCellClick ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnTableItemContextMenu ), NULL, this );
|
||||
m_grid->Disconnect( wxEVT_GRID_COL_SIZE, wxGridSizeEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnTableColSize ), NULL, this );
|
||||
m_radioProject->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnScopeChanged ), NULL, this );
|
||||
m_radioCurrentSheet->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnScopeChanged ), NULL, this );
|
||||
m_radioRecursive->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnScopeChanged ), NULL, this );
|
||||
m_textFieldDelimiter->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnPreviewRefresh ), NULL, this );
|
||||
m_textStringDelimiter->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnPreviewRefresh ), NULL, this );
|
||||
m_textRefDelimiter->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnPreviewRefresh ), NULL, this );
|
||||
@ -428,6 +433,7 @@ DIALOG_SYMBOL_FIELDS_TABLE_BASE::~DIALOG_SYMBOL_FIELDS_TABLE_BASE()
|
||||
m_checkKeepLineBreaks->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnPreviewRefresh ), NULL, this );
|
||||
m_browseButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnOutputFileBrowseClicked ), NULL, this );
|
||||
m_bRefreshPreview->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnPreviewRefresh ), NULL, this );
|
||||
m_sidebarButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnSidebarToggle ), NULL, this );
|
||||
m_buttonExport->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnExport ), NULL, this );
|
||||
m_buttonApply->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnSaveAndContinue ), NULL, this );
|
||||
m_sdbSizerCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SYMBOL_FIELDS_TABLE_BASE::OnCancel ), NULL, this );
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -14,12 +14,12 @@ class STD_BITMAP_BUTTON;
|
||||
class WX_GRID;
|
||||
|
||||
#include "dialog_shim.h"
|
||||
#include <wx/dataview.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/string.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/grid.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/bmpbuttn.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
@ -32,12 +32,10 @@ class WX_GRID;
|
||||
#include <wx/panel.h>
|
||||
#include <wx/srchctrl.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/grid.h>
|
||||
#include <wx/radiobut.h>
|
||||
#include <wx/splitter.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/gbsizer.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/splitter.h>
|
||||
#include <wx/dialog.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -50,36 +48,27 @@ class DIALOG_SYMBOL_FIELDS_TABLE_BASE : public DIALOG_SHIM
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxNotebook* m_nbPages;
|
||||
wxPanel* m_panelEdit;
|
||||
wxSplitterWindow* m_splitterMainWindow;
|
||||
wxPanel* m_leftPanel;
|
||||
wxDataViewListCtrl* m_fieldsCtrl;
|
||||
WX_GRID* m_viewControlsGrid;
|
||||
STD_BITMAP_BUTTON* m_addFieldButton;
|
||||
STD_BITMAP_BUTTON* m_renameFieldButton;
|
||||
STD_BITMAP_BUTTON* m_removeFieldButton;
|
||||
wxStaticLine* m_staticline1;
|
||||
wxStaticLine* m_staticline11;
|
||||
wxStaticText* m_bomPresetsLabel;
|
||||
wxChoice* m_cbBomPresets;
|
||||
wxPanel* m_rightPanel;
|
||||
wxNotebook* m_nbPages;
|
||||
wxPanel* m_panelEdit;
|
||||
wxSearchCtrl* m_filter;
|
||||
wxStaticLine* m_staticline31;
|
||||
wxCheckBox* m_checkExcludeDNP;
|
||||
wxCheckBox* m_checkShowExcluded;
|
||||
wxStaticLine* m_staticline32;
|
||||
wxChoice* m_scope;
|
||||
wxStaticLine* m_staticline311;
|
||||
wxCheckBox* m_groupSymbolsBox;
|
||||
wxStaticLine* m_staticline3;
|
||||
STD_BITMAP_BUTTON* m_bRefresh;
|
||||
STD_BITMAP_BUTTON* m_bMenu;
|
||||
WX_GRID* m_grid;
|
||||
wxStaticLine* m_staticline7;
|
||||
wxStaticText* m_scopeLabel;
|
||||
wxRadioButton* m_radioProject;
|
||||
wxRadioButton* m_radioCurrentSheet;
|
||||
wxRadioButton* m_radioRecursive;
|
||||
wxStaticText* m_crossProbeLabel;
|
||||
wxRadioButton* m_radioHighlight;
|
||||
wxRadioButton* m_radioSelect;
|
||||
wxRadioButton* m_radioOff;
|
||||
wxPanel* m_panelExport;
|
||||
wxStaticText* m_labelFieldDelimiter;
|
||||
wxTextCtrl* m_textFieldDelimiter;
|
||||
@ -100,6 +89,7 @@ class DIALOG_SYMBOL_FIELDS_TABLE_BASE : public DIALOG_SHIM
|
||||
wxStaticText* m_labelPreview;
|
||||
STD_BITMAP_BUTTON* m_bRefreshPreview;
|
||||
wxTextCtrl* m_textOutput;
|
||||
STD_BITMAP_BUTTON* m_sidebarButton;
|
||||
wxButton* m_buttonExport;
|
||||
wxButton* m_buttonApply;
|
||||
wxStdDialogButtonSizer* m_sdbSizer;
|
||||
@ -108,25 +98,24 @@ class DIALOG_SYMBOL_FIELDS_TABLE_BASE : public DIALOG_SHIM
|
||||
|
||||
// Virtual event handlers, override them in your derived class
|
||||
virtual void OnClose( wxCloseEvent& event ) { event.Skip(); }
|
||||
virtual void OnPageChanged( wxNotebookEvent& event ) { event.Skip(); }
|
||||
virtual void OnColumnItemToggled( wxDataViewEvent& event ) { event.Skip(); }
|
||||
virtual void OnSizeFieldList( wxSizeEvent& event ) { event.Skip(); }
|
||||
virtual void OnViewControlsCellChanged( wxGridEvent& event ) { event.Skip(); }
|
||||
virtual void OnSizeViewControlsGrid( wxSizeEvent& event ) { event.Skip(); }
|
||||
virtual void OnAddField( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnRenameField( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnRemoveField( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnPageChanged( wxNotebookEvent& event ) { event.Skip(); }
|
||||
virtual void OnFilterMouseMoved( wxMouseEvent& event ) { event.Skip(); }
|
||||
virtual void OnFilterText( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnExcludeDNPToggled( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnShowExcludedToggled( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnScope( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnGroupSymbolsToggled( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnRegroupSymbols( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnMenu( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnTableValueChanged( wxGridEvent& event ) { event.Skip(); }
|
||||
virtual void OnTableCellClick( wxGridEvent& event ) { event.Skip(); }
|
||||
virtual void OnTableItemContextMenu( wxGridEvent& event ) { event.Skip(); }
|
||||
virtual void OnTableColSize( wxGridSizeEvent& event ) { event.Skip(); }
|
||||
virtual void OnScopeChanged( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnPreviewRefresh( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnOutputFileBrowseClicked( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnSidebarToggle( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnExport( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnSaveAndContinue( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
@ -75,6 +75,7 @@ void PANEL_EESCHEMA_DISPLAY_OPTIONS::loadEEschemaSettings( EESCHEMA_SETTINGS* cf
|
||||
m_checkCrossProbeCenter->SetValue( cfg->m_CrossProbing.center_on_items );
|
||||
m_checkCrossProbeZoom->SetValue( cfg->m_CrossProbing.zoom_to_fit );
|
||||
m_checkCrossProbeAutoHighlight->SetValue( cfg->m_CrossProbing.auto_highlight );
|
||||
m_checkCrossProbeFlash->SetValue( cfg->m_CrossProbing.flash_selection );
|
||||
}
|
||||
|
||||
|
||||
@ -117,6 +118,7 @@ bool PANEL_EESCHEMA_DISPLAY_OPTIONS::TransferDataFromWindow()
|
||||
cfg->m_CrossProbing.center_on_items = m_checkCrossProbeCenter->GetValue();
|
||||
cfg->m_CrossProbing.zoom_to_fit = m_checkCrossProbeZoom->GetValue();
|
||||
cfg->m_CrossProbing.auto_highlight = m_checkCrossProbeAutoHighlight->GetValue();
|
||||
cfg->m_CrossProbing.flash_selection = m_checkCrossProbeFlash->GetValue();
|
||||
}
|
||||
|
||||
m_galOptsPanel->TransferDataFromWindow();
|
||||
|
@ -62,6 +62,10 @@ PANEL_EESCHEMA_DISPLAY_OPTIONS_BASE::PANEL_EESCHEMA_DISPLAY_OPTIONS_BASE( wxWind
|
||||
|
||||
bCrossProbingSizer->Add( m_checkCrossProbeAutoHighlight, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_checkCrossProbeFlash = new wxCheckBox( this, wxID_ANY, _("Flash cross-probed selection"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_checkCrossProbeFlash->SetToolTip( _("Temporarily flash the newly cross-probed selection 3 times") );
|
||||
bCrossProbingSizer->Add( m_checkCrossProbeFlash, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
|
||||
bSizer8->Add( bCrossProbingSizer, 0, wxEXPAND|wxTOP|wxLEFT, 5 );
|
||||
|
||||
|
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