mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-13 17:53:11 +02:00
Compare commits
12 Commits
8f5e8b90a3
...
c8e061ab64
Author | SHA1 | Date | |
---|---|---|---|
|
c8e061ab64 | ||
|
56ad08cdd8 | ||
|
accbee3c6e | ||
|
29025882fc | ||
|
c64f99c57a | ||
|
5952c2fb9a | ||
|
0b6de964fd | ||
|
976278e5a6 | ||
|
8d8bd7253f | ||
|
5dc6d43f43 | ||
|
98dd5a68eb | ||
|
10cc6f353e |
@ -9,7 +9,6 @@ win64_build:
|
||||
image: registry.gitlab.com/kicad/kicad-ci/windows-build-image/ltsc2022-msvc:latest
|
||||
variables:
|
||||
VCPKG_BINARY_SOURCES: 'nuget,gitlab,readwrite'
|
||||
VCPKG_DISABLE_COMPILER_TRACKING: '1'
|
||||
# Switch the compressor to fastzip and reduce the compression level
|
||||
FF_USE_FASTZIP: "true"
|
||||
CACHE_COMPRESSION_LEVEL: "fast"
|
||||
@ -37,6 +36,8 @@ win64_build:
|
||||
-DKICAD_BUILD_PNS_DEBUG_TOOL=ON `
|
||||
-DKICAD_USE_3DCONNEXION=ON `
|
||||
-DVCPKG_BUILD_TYPE=debug `
|
||||
-DVCPKG_INSTALL_OPTIONS="--x-abi-tools-use-exact-versions" `
|
||||
-DVCPKG_OVERLAY_TRIPLETS="$Env:CI_PROJECT_DIR/tools/custom_vcpkg_triplets" `
|
||||
../../
|
||||
- cmake --build . 2>&1 | tee compilation_log.txt
|
||||
- cd ../../
|
||||
|
@ -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() )
|
||||
@ -882,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;
|
||||
|
@ -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"
|
||||
|
@ -67,6 +67,30 @@ set( KICOMMON_SRCS
|
||||
# Gal
|
||||
gal/color4d.cpp
|
||||
gal/opengl/gl_context_mgr.cpp
|
||||
|
||||
# Git
|
||||
git/git_add_to_index_handler.cpp
|
||||
git/git_branch_handler.cpp
|
||||
git/git_clone_handler.cpp
|
||||
git/git_commit_handler.cpp
|
||||
git/git_config_handler.cpp
|
||||
git/git_compare_handler.cpp
|
||||
git/git_init_handler.cpp
|
||||
git/project_git_utils.cpp
|
||||
git/git_pull_handler.cpp
|
||||
git/git_push_handler.cpp
|
||||
git/git_remove_from_index_handler.cpp
|
||||
git/git_remove_vcs_handler.cpp
|
||||
git/git_resolve_conflict_handler.cpp
|
||||
git/git_revert_handler.cpp
|
||||
git/git_status_handler.cpp
|
||||
git/git_switch_branch_handler.cpp
|
||||
git/git_sync_handler.cpp
|
||||
git/kicad_git_common.cpp
|
||||
git/kicad_git_errors.cpp
|
||||
git/git_backend.cpp
|
||||
git/libgit_backend.cpp
|
||||
|
||||
# Jobs
|
||||
jobs/job.cpp
|
||||
jobs/job_dispatcher.cpp
|
||||
@ -616,26 +640,6 @@ set( COMMON_IMPORT_GFX_SRCS
|
||||
import_gfx/svg_import_plugin.cpp
|
||||
)
|
||||
|
||||
set( COMMON_GIT_SRCS
|
||||
git/git_add_to_index_handler.cpp
|
||||
git/git_branch_handler.cpp
|
||||
git/git_clone_handler.cpp
|
||||
git/git_commit_handler.cpp
|
||||
git/git_config_handler.cpp
|
||||
git/git_init_handler.cpp
|
||||
git/git_pull_handler.cpp
|
||||
git/git_push_handler.cpp
|
||||
git/git_remove_from_index_handler.cpp
|
||||
git/git_resolve_conflict_handler.cpp
|
||||
git/git_revert_handler.cpp
|
||||
git/git_status_handler.cpp
|
||||
git/git_sync_handler.cpp
|
||||
git/project_git_utils.cpp
|
||||
git/kicad_git_common.cpp
|
||||
git/kicad_git_errors.cpp
|
||||
git/git_backend.cpp
|
||||
git/libgit_backend.cpp
|
||||
)
|
||||
|
||||
set( COMMON_SRCS
|
||||
${LIB_KICAD_SRCS}
|
||||
@ -648,7 +652,6 @@ set( COMMON_SRCS
|
||||
${COMMON_IO_SRCS}
|
||||
${FONT_SRCS}
|
||||
${COMMON_IMPORT_GFX_SRCS}
|
||||
${COMMON_GIT_SRCS}
|
||||
${COMMON_TRANSLINE_CALCULATION_SRCS}
|
||||
base_screen.cpp
|
||||
bin_mod.cpp
|
||||
|
@ -25,12 +25,13 @@
|
||||
#define GIT_ADD_TO_INDEX_HANDLER_H_
|
||||
|
||||
#include <git/kicad_git_common.h>
|
||||
#include <import_export.h>
|
||||
#include <vector>
|
||||
#include <wx/string.h>
|
||||
|
||||
class LIBGIT_BACKEND;
|
||||
|
||||
class GIT_ADD_TO_INDEX_HANDLER : public KIGIT_COMMON
|
||||
class APIEXPORT GIT_ADD_TO_INDEX_HANDLER : public KIGIT_COMMON
|
||||
{
|
||||
public:
|
||||
GIT_ADD_TO_INDEX_HANDLER( git_repository* aRepository );
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define GIT_BACKEND_H_
|
||||
|
||||
#include <map>
|
||||
#include <import_export.h>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <wx/string.h>
|
||||
@ -56,7 +57,7 @@ enum class CommitResult
|
||||
Cancelled
|
||||
};
|
||||
|
||||
class GIT_BACKEND
|
||||
class APIEXPORT GIT_BACKEND
|
||||
{
|
||||
public:
|
||||
virtual ~GIT_BACKEND() = default;
|
||||
@ -121,7 +122,7 @@ public:
|
||||
virtual void PerformRemoveFromIndex( GIT_REMOVE_FROM_INDEX_HANDLER* aHandler ) = 0;
|
||||
};
|
||||
|
||||
GIT_BACKEND* GetGitBackend();
|
||||
void SetGitBackend( GIT_BACKEND* aBackend );
|
||||
APIEXPORT GIT_BACKEND* GetGitBackend();
|
||||
APIEXPORT void SetGitBackend( GIT_BACKEND* aBackend );
|
||||
|
||||
#endif
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define GIT_BRANCH_HANDLER_H
|
||||
|
||||
#include <git/git_repo_mixin.h>
|
||||
#include <import_export.h>
|
||||
#include <wx/string.h>
|
||||
#include <vector>
|
||||
|
||||
@ -36,7 +37,7 @@ enum class BranchResult
|
||||
Error
|
||||
};
|
||||
|
||||
class GIT_BRANCH_HANDLER : public KIGIT_REPO_MIXIN
|
||||
class APIEXPORT GIT_BRANCH_HANDLER : public KIGIT_REPO_MIXIN
|
||||
{
|
||||
public:
|
||||
GIT_BRANCH_HANDLER( KIGIT_COMMON* aCommon );
|
||||
|
@ -25,10 +25,11 @@
|
||||
#define GIT_CLONE_HANDLER_H_
|
||||
|
||||
#include "kicad_git_common.h"
|
||||
#include <import_export.h>
|
||||
#include "git_repo_mixin.h"
|
||||
#include "git_progress.h"
|
||||
|
||||
class GIT_CLONE_HANDLER : public KIGIT_REPO_MIXIN
|
||||
class APIEXPORT GIT_CLONE_HANDLER : public KIGIT_REPO_MIXIN
|
||||
{
|
||||
public:
|
||||
GIT_CLONE_HANDLER( KIGIT_COMMON* aCommon );
|
||||
|
@ -27,6 +27,7 @@
|
||||
// Define a class to handle git commit operations
|
||||
|
||||
#include <git/kicad_git_common.h>
|
||||
#include <import_export.h>
|
||||
#include "git_backend.h"
|
||||
|
||||
#include <string>
|
||||
@ -35,7 +36,7 @@
|
||||
|
||||
class LIBGIT_BACKEND;
|
||||
|
||||
class GIT_COMMIT_HANDLER : public KIGIT_COMMON
|
||||
class APIEXPORT GIT_COMMIT_HANDLER : public KIGIT_COMMON
|
||||
{
|
||||
public:
|
||||
GIT_COMMIT_HANDLER( git_repository* aRepo );
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define GIT_CONFIG_HANDLER_H
|
||||
|
||||
#include <git/git_repo_mixin.h>
|
||||
#include <import_export.h>
|
||||
#include <wx/string.h>
|
||||
|
||||
struct GitUserConfig
|
||||
@ -35,7 +36,7 @@ struct GitUserConfig
|
||||
bool hasEmail = false;
|
||||
};
|
||||
|
||||
class GIT_CONFIG_HANDLER : public KIGIT_REPO_MIXIN
|
||||
class APIEXPORT GIT_CONFIG_HANDLER : public KIGIT_REPO_MIXIN
|
||||
{
|
||||
public:
|
||||
GIT_CONFIG_HANDLER( KIGIT_COMMON* aCommon );
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define GIT_INIT_HANDLER_H
|
||||
|
||||
#include <git/git_repo_mixin.h>
|
||||
#include <import_export.h>
|
||||
#include <wx/string.h>
|
||||
|
||||
enum class InitResult
|
||||
@ -43,7 +44,7 @@ struct RemoteConfig
|
||||
KIGIT_COMMON::GIT_CONN_TYPE connType;
|
||||
};
|
||||
|
||||
class GIT_INIT_HANDLER : public KIGIT_REPO_MIXIN
|
||||
class APIEXPORT GIT_INIT_HANDLER : public KIGIT_REPO_MIXIN
|
||||
{
|
||||
public:
|
||||
GIT_INIT_HANDLER( KIGIT_COMMON* aCommon );
|
||||
|
@ -25,10 +25,11 @@
|
||||
#define GIT_PROGRESS_H_
|
||||
|
||||
#include <widgets/wx_progress_reporters.h>
|
||||
#include <import_export.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class GIT_PROGRESS
|
||||
class APIEXPORT GIT_PROGRESS
|
||||
{
|
||||
public:
|
||||
GIT_PROGRESS() :
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define _GIT_PULL_HANDLER_H_
|
||||
|
||||
#include <git/git_repo_mixin.h>
|
||||
#include <import_export.h>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
@ -51,7 +52,7 @@ enum class PullResult : int
|
||||
|
||||
class LIBGIT_BACKEND;
|
||||
|
||||
class GIT_PULL_HANDLER : public KIGIT_REPO_MIXIN
|
||||
class APIEXPORT GIT_PULL_HANDLER : public KIGIT_REPO_MIXIN
|
||||
{
|
||||
public:
|
||||
friend class LIBGIT_BACKEND;
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include <git/git_progress.h>
|
||||
#include <git/git_repo_mixin.h>
|
||||
#include <import_export.h>
|
||||
#include <git/kicad_git_errors.h>
|
||||
#include <wx/string.h>
|
||||
|
||||
@ -37,7 +38,7 @@ enum class PushResult
|
||||
Error
|
||||
};
|
||||
|
||||
class GIT_PUSH_HANDLER : public KIGIT_REPO_MIXIN
|
||||
class APIEXPORT GIT_PUSH_HANDLER : public KIGIT_REPO_MIXIN
|
||||
{
|
||||
public:
|
||||
GIT_PUSH_HANDLER( KIGIT_COMMON* aCommon );
|
||||
|
@ -25,12 +25,13 @@
|
||||
#define GIT_REMOVE_FROM_INDEX_HANDLER_H_
|
||||
|
||||
#include <git/kicad_git_common.h>
|
||||
#include <import_export.h>
|
||||
#include <vector>
|
||||
#include <wx/string.h>
|
||||
|
||||
class LIBGIT_BACKEND;
|
||||
|
||||
class GIT_REMOVE_FROM_INDEX_HANDLER : public KIGIT_COMMON
|
||||
class APIEXPORT GIT_REMOVE_FROM_INDEX_HANDLER : public KIGIT_COMMON
|
||||
{
|
||||
public:
|
||||
GIT_REMOVE_FROM_INDEX_HANDLER( git_repository* aRepository );
|
||||
|
@ -17,8 +17,9 @@
|
||||
#include "kicad_git_common.h"
|
||||
#include "kicad_git_errors.h"
|
||||
#include "git_progress.h"
|
||||
#include <import_export.h>
|
||||
|
||||
class KIGIT_REPO_MIXIN: public KIGIT_ERRORS, public GIT_PROGRESS
|
||||
class APIEXPORT KIGIT_REPO_MIXIN: public KIGIT_ERRORS, public GIT_PROGRESS
|
||||
{
|
||||
public:
|
||||
KIGIT_REPO_MIXIN( KIGIT_COMMON* aCommon ) : m_common( aCommon )
|
||||
|
@ -25,10 +25,11 @@
|
||||
#define GIT_RESOLVE_CONFLICT_HANDLER_H
|
||||
|
||||
#include <git2.h>
|
||||
#include <import_export.h>
|
||||
|
||||
class wxString;
|
||||
|
||||
class GIT_RESOLVE_CONFLICT_HANDLER
|
||||
class APIEXPORT GIT_RESOLVE_CONFLICT_HANDLER
|
||||
{
|
||||
public:
|
||||
GIT_RESOLVE_CONFLICT_HANDLER( git_repository* aRepository );
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define GIT_REVERT_HANDLER_H_
|
||||
|
||||
#include <git2.h>
|
||||
#include <import_export.h>
|
||||
#include <vector>
|
||||
#include <wx/string.h>
|
||||
// TEMPORARY HACKFIX INCLUDE FOR STD::VECTOR EXPORT OUT OF KICOMMON ON WINDOWS
|
||||
@ -32,7 +33,7 @@
|
||||
|
||||
class LIBGIT_BACKEND;
|
||||
|
||||
class GIT_REVERT_HANDLER
|
||||
class APIEXPORT GIT_REVERT_HANDLER
|
||||
{
|
||||
public:
|
||||
GIT_REVERT_HANDLER( git_repository* aRepository );
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define GIT_STATUS_HANDLER_H
|
||||
|
||||
#include <git/git_repo_mixin.h>
|
||||
#include <import_export.h>
|
||||
#include <wx/string.h>
|
||||
#include <map>
|
||||
#include <set>
|
||||
@ -38,7 +39,7 @@ struct FileStatus
|
||||
unsigned int gitStatus; // Raw git status flags
|
||||
};
|
||||
|
||||
class GIT_STATUS_HANDLER : public KIGIT_REPO_MIXIN
|
||||
class APIEXPORT GIT_STATUS_HANDLER : public KIGIT_REPO_MIXIN
|
||||
{
|
||||
public:
|
||||
GIT_STATUS_HANDLER( KIGIT_COMMON* aCommon );
|
||||
|
@ -25,10 +25,11 @@
|
||||
#define GIT_SYNC_HANDLER_H_
|
||||
|
||||
#include <git2.h>
|
||||
#include <import_export.h>
|
||||
|
||||
class wxString;
|
||||
|
||||
class GIT_SYNC_HANDLER
|
||||
class APIEXPORT GIT_SYNC_HANDLER
|
||||
{
|
||||
public:
|
||||
GIT_SYNC_HANDLER( git_repository* aRepository );
|
||||
|
@ -25,11 +25,12 @@
|
||||
#include <istream>
|
||||
#include <string>
|
||||
#include <git2.h>
|
||||
#include <import_export.h>
|
||||
|
||||
#include <richio.h>
|
||||
|
||||
|
||||
class BLOB_BUFFER_STREAM : public std::streambuf
|
||||
class APIEXPORT BLOB_BUFFER_STREAM : public std::streambuf
|
||||
{
|
||||
public:
|
||||
BLOB_BUFFER_STREAM( git_blob* aBlob )
|
||||
@ -57,7 +58,7 @@ public:
|
||||
};
|
||||
|
||||
// Build a class that implements LINE_READER for git_blobs
|
||||
class BLOB_READER : public LINE_READER
|
||||
class APIEXPORT BLOB_READER : public LINE_READER
|
||||
{
|
||||
public:
|
||||
BLOB_READER( git_blob* aBlob ) : m_blob( aBlob )
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define _GIT_COMMON_H_
|
||||
|
||||
#include <git/kicad_git_errors.h>
|
||||
#include <import_export.h>
|
||||
|
||||
#include <git2.h>
|
||||
#include <atomic>
|
||||
@ -35,7 +36,7 @@
|
||||
|
||||
class LIBGIT_BACKEND;
|
||||
|
||||
class KIGIT_COMMON
|
||||
class APIEXPORT KIGIT_COMMON
|
||||
{
|
||||
|
||||
public:
|
||||
@ -193,19 +194,19 @@ private:
|
||||
static const unsigned KIGIT_CREDENTIAL_SSH_AGENT = 1 << sizeof( m_testedTypes - 1 );
|
||||
};
|
||||
|
||||
extern "C" int progress_cb( const char* str, int len, void* data );
|
||||
extern "C" void clone_progress_cb( const char* str, size_t len, size_t total, void* data );
|
||||
extern "C" int transfer_progress_cb( const git_transfer_progress* aStats, void* aPayload );
|
||||
extern "C" int update_cb( const char* aRefname, const git_oid* aFirst, const git_oid* aSecond,
|
||||
void* aPayload );
|
||||
extern "C" int push_transfer_progress_cb( unsigned int aCurrent, unsigned int aTotal,
|
||||
size_t aBytes, void* aPayload );
|
||||
extern "C" int push_update_reference_cb( const char* aRefname, const char* aStatus,
|
||||
void* aPayload );
|
||||
extern "C" APIEXPORT int progress_cb( const char* str, int len, void* data );
|
||||
extern "C" APIEXPORT void clone_progress_cb( const char* str, size_t len, size_t total, void* data );
|
||||
extern "C" APIEXPORT int transfer_progress_cb( const git_transfer_progress* aStats, void* aPayload );
|
||||
extern "C" APIEXPORT int update_cb( const char* aRefname, const git_oid* aFirst, const git_oid* aSecond,
|
||||
void* aPayload );
|
||||
extern "C" APIEXPORT int push_transfer_progress_cb( unsigned int aCurrent, unsigned int aTotal,
|
||||
size_t aBytes, void* aPayload );
|
||||
extern "C" APIEXPORT int push_update_reference_cb( const char* aRefname, const char* aStatus,
|
||||
void* aPayload );
|
||||
|
||||
extern "C" int fetchhead_foreach_cb( const char*, const char*,
|
||||
const git_oid* aOID, unsigned int aIsMerge, void* aPayload );
|
||||
extern "C" int credentials_cb( git_cred** aOut, const char* aUrl, const char* aUsername,
|
||||
unsigned int aAllowedTypes, void* aPayload );
|
||||
extern "C" APIEXPORT int fetchhead_foreach_cb( const char*, const char*,
|
||||
const git_oid* aOID, unsigned int aIsMerge, void* aPayload );
|
||||
extern "C" APIEXPORT int credentials_cb( git_cred** aOut, const char* aUrl, const char* aUsername,
|
||||
unsigned int aAllowedTypes, void* aPayload );
|
||||
|
||||
#endif // _GIT_COMMON_H_
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
#include <wx/translation.h>
|
||||
|
||||
class KIGIT_ERRORS
|
||||
class APIEXPORT KIGIT_ERRORS
|
||||
{
|
||||
public:
|
||||
|
||||
|
@ -25,11 +25,12 @@
|
||||
#define LIBGIT_BACKEND_H_
|
||||
|
||||
#include "git_backend.h"
|
||||
#include <import_export.h>
|
||||
|
||||
// Forward declarations to avoid exposing libgit2 headers
|
||||
struct git_annotated_commit;
|
||||
|
||||
class LIBGIT_BACKEND : public GIT_BACKEND
|
||||
class APIEXPORT LIBGIT_BACKEND : public GIT_BACKEND
|
||||
{
|
||||
public:
|
||||
void Init() override;
|
||||
|
@ -24,6 +24,9 @@
|
||||
#include "project_git_utils.h"
|
||||
#include "git_backend.h"
|
||||
|
||||
#include <wx/string.h>
|
||||
#include <string_utils.h>
|
||||
|
||||
namespace KIGIT
|
||||
{
|
||||
|
||||
@ -43,4 +46,34 @@ bool PROJECT_GIT_UTILS::RemoveVCS( git_repository*& aRepo, const wxString& aProj
|
||||
return GetGitBackend()->RemoveVCS( aRepo, aProjectPath, aRemoveGitDir, aErrors );
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -26,12 +26,13 @@
|
||||
|
||||
#include <git2.h>
|
||||
#include <wx/string.h>
|
||||
#include <import_export.h>
|
||||
|
||||
namespace KIGIT
|
||||
{
|
||||
|
||||
/** Utility class with helper functions for project level git operations. */
|
||||
class PROJECT_GIT_UTILS
|
||||
class APIEXPORT PROJECT_GIT_UTILS
|
||||
{
|
||||
public:
|
||||
/**
|
||||
@ -51,6 +52,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.
|
||||
|
@ -46,11 +46,19 @@ int32_t ALTIUM_PROPS_UTILS::ConvertToKicadUnit( const double aValue )
|
||||
}
|
||||
|
||||
|
||||
std::optional<int> ALTIUM_PROPS_UTILS::ReadOptInt( const std::map<wxString, wxString>& aProps,
|
||||
const wxString& aKey )
|
||||
{
|
||||
const std::map<wxString, wxString>::const_iterator& value = aProps.find( aKey );
|
||||
return value == aProps.end() ? std::optional<int>{} : wxAtoi( value->second );
|
||||
}
|
||||
|
||||
|
||||
int ALTIUM_PROPS_UTILS::ReadInt( const std::map<wxString, wxString>& aProps, const wxString& aKey,
|
||||
int aDefault )
|
||||
{
|
||||
const std::map<wxString, wxString>::const_iterator& value = aProps.find( aKey );
|
||||
return value == aProps.end() ? aDefault : wxAtoi( value->second );
|
||||
std::optional<int> opt = ReadOptInt(aProps, aKey);
|
||||
return opt.has_value() ? opt.value() : aDefault;
|
||||
}
|
||||
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
|
||||
#include <wx/string.h>
|
||||
|
||||
@ -36,6 +37,9 @@ class ALTIUM_PROPS_UTILS
|
||||
public:
|
||||
static int32_t ConvertToKicadUnit( const double aValue );
|
||||
|
||||
static std::optional<int> ReadOptInt( const std::map<wxString, wxString>& aProps,
|
||||
const wxString& aKey );
|
||||
|
||||
static int ReadInt( const std::map<wxString, wxString>& aProps, const wxString& aKey,
|
||||
int aDefault );
|
||||
|
||||
|
@ -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 );
|
||||
|
@ -152,10 +152,10 @@ const wxAuiPaneInfo& defaultDesignBlocksPaneInfo( wxWindow* aWindow )
|
||||
EESCHEMA_SETTINGS::EESCHEMA_SETTINGS() :
|
||||
APP_SETTINGS_BASE( "eeschema", eeschemaSchemaVersion ),
|
||||
m_Appearance(),
|
||||
m_AutoplaceFields(),
|
||||
m_Drawing(),
|
||||
m_FindReplaceExtra(),
|
||||
m_Input(),
|
||||
m_AutoplaceFields(),
|
||||
m_Selection(),
|
||||
m_PageSettings(),
|
||||
m_AnnotatePanel(),
|
||||
m_BomPanel(),
|
||||
@ -163,8 +163,9 @@ EESCHEMA_SETTINGS::EESCHEMA_SETTINGS() :
|
||||
m_LibViewPanel(),
|
||||
m_NetlistPanel(),
|
||||
m_SymChooserPanel(),
|
||||
m_FindReplaceExtra(),
|
||||
m_ERCDialog(),
|
||||
m_ImportGraphics(),
|
||||
m_Selection(),
|
||||
m_Simulator(),
|
||||
m_RescueNeverShow( false )
|
||||
{
|
||||
|
@ -1542,7 +1542,7 @@ std::vector<LIB_SYMBOL_UNIT> LIB_SYMBOL::GetUnitDrawItems()
|
||||
|
||||
|
||||
#define REPORT( msg ) { if( aReporter ) aReporter->Report( msg ); }
|
||||
#define ITEM_DESC( item ) ( item )->GetItemDescription( &unitsProvider, true )
|
||||
#define ITEM_DESC( item ) ( item )->GetItemDescription( &unitsProvider, false )
|
||||
|
||||
int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags, REPORTER* aReporter ) const
|
||||
{
|
||||
@ -1586,35 +1586,34 @@ int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags, REPORTER* aR
|
||||
return retv;
|
||||
}
|
||||
|
||||
// Make sure shapes and pins are sorted. No need with fields as those are
|
||||
// matched by id/name.
|
||||
// Make sure shapes are sorted. No need with fields or pins as those are matched by id/name and number.
|
||||
|
||||
std::set<const SCH_ITEM*, SCH_ITEM::cmp_items> aShapes;
|
||||
std::set<const SCH_ITEM*> aFields;
|
||||
std::set<const SCH_ITEM*, SCH_ITEM::cmp_items> aPins;
|
||||
std::set<const SCH_FIELD*> aFields;
|
||||
std::set<const SCH_PIN*> aPins;
|
||||
|
||||
for( auto it = m_drawings.begin(); it != m_drawings.end(); ++it )
|
||||
{
|
||||
if( it->Type() == SCH_SHAPE_T )
|
||||
aShapes.insert( &(*it) );
|
||||
else if( it->Type() == SCH_FIELD_T )
|
||||
aFields.insert( &(*it) );
|
||||
aFields.insert( static_cast<const SCH_FIELD*>( &(*it) ) );
|
||||
else if( it->Type() == SCH_PIN_T )
|
||||
aPins.insert( &(*it) );
|
||||
aPins.insert( static_cast<const SCH_PIN*>( &(*it) ) );
|
||||
}
|
||||
|
||||
std::set<const SCH_ITEM*, SCH_ITEM::cmp_items> bShapes;
|
||||
std::set<const SCH_ITEM*> bFields;
|
||||
std::set<const SCH_ITEM*, SCH_ITEM::cmp_items> bPins;
|
||||
std::set<const SCH_FIELD*> bFields;
|
||||
std::set<const SCH_PIN*> bPins;
|
||||
|
||||
for( auto it = aRhs.m_drawings.begin(); it != aRhs.m_drawings.end(); ++it )
|
||||
{
|
||||
if( it->Type() == SCH_SHAPE_T )
|
||||
bShapes.insert( &(*it) );
|
||||
else if( it->Type() == SCH_FIELD_T )
|
||||
bFields.insert( &(*it) );
|
||||
bFields.insert( static_cast<const SCH_FIELD*>( &(*it) ) );
|
||||
else if( it->Type() == SCH_PIN_T )
|
||||
bPins.insert( &(*it) );
|
||||
bPins.insert( static_cast<const SCH_PIN*>( &(*it) ) );
|
||||
}
|
||||
|
||||
if( int tmp = static_cast<int>( aShapes.size() - bShapes.size() ) )
|
||||
@ -1632,7 +1631,9 @@ int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags, REPORTER* aR
|
||||
if( int tmp2 = (*aIt)->compare( *(*bIt), aCompareFlags ) )
|
||||
{
|
||||
retv = tmp2;
|
||||
REPORT( wxString::Format( _( "%s differs." ), ITEM_DESC( *aIt ) ) );
|
||||
REPORT( wxString::Format( _( "Graphic item differs: %s; %s." ),
|
||||
ITEM_DESC( *aIt ),
|
||||
ITEM_DESC( *bIt ) ) );
|
||||
|
||||
if( !aReporter )
|
||||
return retv;
|
||||
@ -1640,46 +1641,48 @@ int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags, REPORTER* aR
|
||||
}
|
||||
}
|
||||
|
||||
if( int tmp = static_cast<int>( aPins.size() - bPins.size() ) )
|
||||
for( const SCH_PIN* aPin : aPins )
|
||||
{
|
||||
retv = tmp;
|
||||
REPORT( _( "Pin count differs." ) );
|
||||
const SCH_PIN* bPin = aRhs.GetPin( aPin->GetNumber(), aPin->GetUnit(), aPin->GetBodyStyle() );
|
||||
|
||||
if( !aReporter )
|
||||
return retv;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( const SCH_ITEM* aPinItem : aPins )
|
||||
if( !bPin )
|
||||
{
|
||||
const SCH_PIN* aPin = static_cast<const SCH_PIN*>( aPinItem );
|
||||
const SCH_PIN* bPin = aRhs.GetPin( aPin->GetNumber(), aPin->GetUnit(),
|
||||
aPin->GetBodyStyle() );
|
||||
retv = 1;
|
||||
REPORT( wxString::Format( _( "Extra pin in schematic symbol: %s." ), ITEM_DESC( aPin ) ) );
|
||||
|
||||
if( !bPin )
|
||||
{
|
||||
retv = 1;
|
||||
REPORT( wxString::Format( _( "Pin %s not found." ), aPin->GetNumber() ) );
|
||||
if( !aReporter )
|
||||
return retv;
|
||||
}
|
||||
else if( int tmp = aPin->SCH_ITEM::compare( *bPin, aCompareFlags ) )
|
||||
{
|
||||
retv = tmp;
|
||||
REPORT( wxString::Format( _( "Pin %s differs: %s; %s" ),
|
||||
aPin->GetNumber(),
|
||||
ITEM_DESC( aPin ),
|
||||
ITEM_DESC( bPin ) ) );
|
||||
|
||||
if( !aReporter )
|
||||
return retv;
|
||||
}
|
||||
else if( int tmp2 = aPinItem->compare( *bPin, aCompareFlags ) )
|
||||
{
|
||||
retv = tmp2;
|
||||
REPORT( wxString::Format( _( "Pin %s differs." ), aPin->GetNumber() ) );
|
||||
|
||||
if( !aReporter )
|
||||
return retv;
|
||||
}
|
||||
if( !aReporter )
|
||||
return retv;
|
||||
}
|
||||
}
|
||||
|
||||
for( const SCH_ITEM* aFieldItem : aFields )
|
||||
for( const SCH_PIN* bPin : bPins )
|
||||
{
|
||||
const SCH_PIN* aPin = aRhs.GetPin( bPin->GetNumber(), bPin->GetUnit(), bPin->GetBodyStyle() );
|
||||
|
||||
if( !aPin )
|
||||
{
|
||||
retv = 1;
|
||||
REPORT( wxString::Format( _( "Missing pin in schematic symbol: %s." ), ITEM_DESC( bPin ) ) );
|
||||
|
||||
if( !aReporter )
|
||||
return retv;
|
||||
}
|
||||
}
|
||||
|
||||
for( const SCH_FIELD* aField : aFields )
|
||||
{
|
||||
const SCH_FIELD* aField = static_cast<const SCH_FIELD*>( aFieldItem );
|
||||
const SCH_FIELD* bField = nullptr;
|
||||
int tmp = 0;
|
||||
|
||||
if( aField->IsMandatory() )
|
||||
bField = aRhs.GetField( aField->GetId() );
|
||||
@ -1687,33 +1690,49 @@ int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags, REPORTER* aR
|
||||
bField = aRhs.GetField( aField->GetName() );
|
||||
|
||||
if( !bField )
|
||||
tmp = 1;
|
||||
else
|
||||
tmp = aFieldItem->compare( *bField, aCompareFlags );
|
||||
{
|
||||
retv = 1;
|
||||
REPORT( wxString::Format( _( "Extra field in schematic symbol: %s." ), ITEM_DESC( aField ) ) );
|
||||
|
||||
if( tmp )
|
||||
if( !aReporter )
|
||||
return retv;
|
||||
}
|
||||
else if( int tmp = aField->SCH_ITEM::compare( *bField, aCompareFlags ) )
|
||||
{
|
||||
retv = tmp;
|
||||
REPORT( wxString::Format( _( "%s field differs." ), aField->GetName( false ) ) );
|
||||
REPORT( wxString::Format( _( "Field '%s' differs: %s; %s." ),
|
||||
aField->GetName( false ),
|
||||
ITEM_DESC( aField ),
|
||||
ITEM_DESC( bField ) ) );
|
||||
|
||||
if( !aReporter )
|
||||
return retv;
|
||||
}
|
||||
}
|
||||
|
||||
if( int tmp = static_cast<int>( aFields.size() - bFields.size() ) )
|
||||
for( const SCH_FIELD* bField : bFields )
|
||||
{
|
||||
retv = tmp;
|
||||
REPORT( _( "Field count differs." ) );
|
||||
const SCH_FIELD* aField = nullptr;
|
||||
|
||||
if( !aReporter )
|
||||
return retv;
|
||||
if( bField->IsMandatory() )
|
||||
aField = aRhs.GetField( bField->GetId() );
|
||||
else
|
||||
aField = aRhs.GetField( bField->GetName() );
|
||||
|
||||
if( !aField )
|
||||
{
|
||||
retv = 1;
|
||||
REPORT( wxString::Format( _( "Missing field in schematic symbol: %s." ), ITEM_DESC( bField ) ) );
|
||||
|
||||
if( !aReporter )
|
||||
return retv;
|
||||
}
|
||||
}
|
||||
|
||||
if( int tmp = static_cast<int>( m_fpFilters.GetCount() - aRhs.m_fpFilters.GetCount() ) )
|
||||
{
|
||||
retv = tmp;
|
||||
REPORT( _( "Footprint filters differs." ) );
|
||||
REPORT( _( "Footprint filter count differs." ) );
|
||||
|
||||
if( !aReporter )
|
||||
return retv;
|
||||
|
@ -974,9 +974,19 @@ void SCH_FIELD::CalcEdit( const VECTOR2I& aPosition )
|
||||
|
||||
wxString SCH_FIELD::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
|
||||
{
|
||||
return wxString::Format( _( "Field %s '%s'" ),
|
||||
UnescapeString( GetName() ),
|
||||
aFull ? GetShownText( false ) : KIUI::EllipsizeMenuText( GetText() ) );
|
||||
wxString content = aFull ? GetShownText( false ) : KIUI::EllipsizeMenuText( GetText() );
|
||||
|
||||
if( content.IsEmpty() )
|
||||
{
|
||||
return wxString::Format( _( "Field %s (empty)" ),
|
||||
UnescapeString( GetName() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return wxString::Format( _( "Field %s '%s'" ),
|
||||
UnescapeString( GetName() ),
|
||||
content );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1937,10 +1937,20 @@ wxString SCH_DIRECTIVE_LABEL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider
|
||||
}
|
||||
else
|
||||
{
|
||||
return wxString::Format( _( "Directive Label [%s %s]" ),
|
||||
UnescapeString( m_fields[0].GetName() ),
|
||||
aFull ? m_fields[0].GetShownText( false )
|
||||
: KIUI::EllipsizeMenuText( m_fields[0].GetText() ) );
|
||||
const SCH_FIELD& firstField = m_fields[0];
|
||||
wxString content = aFull ? firstField.GetShownText( false ) : KIUI::EllipsizeMenuText( firstField.GetText() );
|
||||
|
||||
if( content.IsEmpty() )
|
||||
{
|
||||
return wxString::Format( _( "Directive Label [%s (empty)]" ),
|
||||
UnescapeString( m_fields[0].GetName() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return wxString::Format( _( "Directive Label [%s %s]" ),
|
||||
UnescapeString( m_fields[0].GetName() ),
|
||||
content );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1169,7 +1169,7 @@ wxString SCH_SHEET::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFu
|
||||
{
|
||||
const SCH_FIELD* sheetnameField = GetField( FIELD_T::SHEET_NAME );
|
||||
|
||||
return wxString::Format( _( "Hierarchical Sheet %s" ),
|
||||
return wxString::Format( _( "Hierarchical Sheet '%s'" ),
|
||||
aFull ? sheetnameField->GetShownText( false )
|
||||
: KIUI::EllipsizeMenuText( sheetnameField->GetText() ) );
|
||||
}
|
||||
|
@ -328,7 +328,7 @@ void SCH_SHEET_PIN::GetEndPoints( std::vector<DANGLING_END_ITEM>& aItemList )
|
||||
|
||||
wxString SCH_SHEET_PIN::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
|
||||
{
|
||||
return wxString::Format( _( "Hierarchical Sheet Pin %s" ),
|
||||
return wxString::Format( _( "Hierarchical Sheet Pin '%s'" ),
|
||||
aFull ? GetShownText( false ) : KIUI::EllipsizeMenuText( GetText() ) );
|
||||
}
|
||||
|
||||
|
@ -384,7 +384,8 @@ void BACK_ANNOTATE::applyChangelist()
|
||||
if( !m_dryRun )
|
||||
commit.Modify( symbol, screen, RECURSE_MODE::NO_RECURSE );
|
||||
|
||||
if( m_processReferences && ref.GetRef() != fpData.m_ref && !skip )
|
||||
if( m_processReferences && ref.GetRef() != fpData.m_ref && !skip
|
||||
&& !symbol->GetField( FIELD_T::REFERENCE )->HasTextVars() )
|
||||
{
|
||||
++m_changesCount;
|
||||
msg.Printf( _( "Change %s reference designator to '%s'." ),
|
||||
@ -397,7 +398,8 @@ void BACK_ANNOTATE::applyChangelist()
|
||||
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
|
||||
}
|
||||
|
||||
if( m_processFootprints && oldFootprint != fpData.m_footprint && !skip )
|
||||
if( m_processFootprints && oldFootprint != fpData.m_footprint && !skip
|
||||
&& !symbol->GetField( FIELD_T::FOOTPRINT )->HasTextVars() )
|
||||
{
|
||||
++m_changesCount;
|
||||
msg.Printf( _( "Change %s footprint assignment from '%s' to '%s'." ),
|
||||
@ -411,7 +413,8 @@ void BACK_ANNOTATE::applyChangelist()
|
||||
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
|
||||
}
|
||||
|
||||
if( m_processValues && oldValue != fpData.m_value && !skip )
|
||||
if( m_processValues && oldValue != fpData.m_value && !skip
|
||||
&& !symbol->GetField( FIELD_T::VALUE )->HasTextVars() )
|
||||
{
|
||||
++m_changesCount;
|
||||
msg.Printf( _( "Change %s value from '%s' to '%s'." ),
|
||||
@ -502,6 +505,7 @@ void BACK_ANNOTATE::applyChangelist()
|
||||
// with all the variables resolved. The footprints field value gets the symbol's
|
||||
// resolved value when the PCB is updated from the schematic.
|
||||
if( symField
|
||||
&& !symField->HasTextVars()
|
||||
&& symField->GetShownText( &ref.GetSheetPath(), false ) != fpFieldValue )
|
||||
{
|
||||
m_changesCount++;
|
||||
|
@ -120,6 +120,7 @@ set( PCBNEW_DIALOGS
|
||||
dialogs/dialog_outset_items_base.cpp
|
||||
dialogs/dialog_pad_properties.cpp
|
||||
dialogs/dialog_pad_properties_base.cpp
|
||||
dialogs/dialog_fp_edit_pad_table.cpp
|
||||
dialogs/dialog_plot.cpp
|
||||
dialogs/dialog_plot_base.cpp
|
||||
dialogs/dialog_pns_diff_pair_dimensions.cpp
|
||||
|
689
pcbnew/dialogs/dialog_fp_edit_pad_table.cpp
Normal file
689
pcbnew/dialogs/dialog_fp_edit_pad_table.cpp
Normal file
@ -0,0 +1,689 @@
|
||||
/*
|
||||
* 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "dialog_fp_edit_pad_table.h"
|
||||
|
||||
#include <wx/button.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/dcclient.h>
|
||||
#include <pcb_shape.h>
|
||||
#include <widgets/wx_grid.h>
|
||||
#include <widgets/grid_text_helpers.h>
|
||||
#include <widgets/grid_combobox.h>
|
||||
#include <base_units.h>
|
||||
#include <units_provider.h>
|
||||
#include <board.h>
|
||||
#include <footprint.h>
|
||||
#include <footprint_edit_frame.h>
|
||||
|
||||
// Helper to map shape string to PAD_SHAPE
|
||||
static PAD_SHAPE ShapeFromString( const wxString& shape )
|
||||
{
|
||||
if( shape == _( "Oval" ) ) return PAD_SHAPE::OVAL;
|
||||
if( shape == _( "Rectangle" ) ) return PAD_SHAPE::RECTANGLE;
|
||||
if( shape == _( "Trapezoid" ) ) return PAD_SHAPE::TRAPEZOID;
|
||||
if( shape == _( "Rounded rectangle" ) ) return PAD_SHAPE::ROUNDRECT;
|
||||
if( shape == _( "Chamfered rectangle" ) ) return PAD_SHAPE::CHAMFERED_RECT;
|
||||
if( shape == _( "Custom shape" ) ) return PAD_SHAPE::CUSTOM;
|
||||
return PAD_SHAPE::CIRCLE;
|
||||
}
|
||||
|
||||
DIALOG_FP_EDIT_PAD_TABLE::DIALOG_FP_EDIT_PAD_TABLE( PCB_BASE_FRAME* aParent, FOOTPRINT* aFootprint ) :
|
||||
DIALOG_SHIM( (wxWindow*)aParent, wxID_ANY, _( "Pad Table" ), wxDefaultPosition, wxDefaultSize,
|
||||
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ),
|
||||
m_grid( nullptr ),
|
||||
m_footprint( aFootprint ),
|
||||
m_unitsProvider( std::make_unique<UNITS_PROVIDER>( pcbIUScale, GetUserUnits() ) )
|
||||
{
|
||||
wxBoxSizer* topSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_grid = new WX_GRID( this, wxID_ANY );
|
||||
m_grid->CreateGrid( 0, 11 );
|
||||
m_grid->SetColLabelValue( COL_NUMBER, _( "Number" ) );
|
||||
m_grid->SetColLabelValue( COL_TYPE, _( "Type" ) );
|
||||
m_grid->SetColLabelValue( COL_SHAPE, _( "Shape" ) );
|
||||
m_grid->SetColLabelValue( COL_POS_X, _( "X Position" ) );
|
||||
m_grid->SetColLabelValue( COL_POS_Y, _( "Y Position" ) );
|
||||
m_grid->SetColLabelValue( COL_SIZE_X, _( "Size X" ) );
|
||||
m_grid->SetColLabelValue( COL_SIZE_Y, _( "Size Y" ) );
|
||||
m_grid->SetColLabelValue( COL_DRILL_X, _( "Drill X" ) );
|
||||
m_grid->SetColLabelValue( COL_DRILL_Y, _( "Drill Y" ) );
|
||||
m_grid->SetColLabelValue( COL_P2D_LENGTH, _( "Pad->Die Length" ) );
|
||||
m_grid->SetColLabelValue( COL_P2D_DELAY, _( "Pad->Die Delay" ) );
|
||||
m_grid->EnableEditing( true );
|
||||
|
||||
wxGridCellAttr* attr;
|
||||
|
||||
// Type column editor (attribute)
|
||||
attr = new wxGridCellAttr;
|
||||
{
|
||||
wxArrayString typeNames;
|
||||
typeNames.push_back( _( "Through-hole" ) ); // PTH
|
||||
typeNames.push_back( _( "SMD" ) ); // SMD
|
||||
typeNames.push_back( _( "Connector" ) ); // CONN SMD? (use CONN?)
|
||||
typeNames.push_back( _( "NPTH" ) ); // NPTH
|
||||
typeNames.push_back( _( "Aperture" ) ); // inferred copper-less
|
||||
attr->SetEditor( new GRID_CELL_COMBOBOX( typeNames ) );
|
||||
}
|
||||
m_grid->SetColAttr( COL_TYPE, attr );
|
||||
|
||||
attr = new wxGridCellAttr;
|
||||
wxArrayString shapeNames;
|
||||
shapeNames.push_back( _( "Circle" ) );
|
||||
shapeNames.push_back( _( "Oval" ) );
|
||||
shapeNames.push_back( _( "Rectangle" ) );
|
||||
shapeNames.push_back( _( "Trapezoid" ) );
|
||||
shapeNames.push_back( _( "Rounded rectangle" ) );
|
||||
shapeNames.push_back( _( "Chamfered rectangle" ) );
|
||||
shapeNames.push_back( _( "Custom shape" ) );
|
||||
attr->SetEditor( new GRID_CELL_COMBOBOX( shapeNames ) );
|
||||
m_grid->SetColAttr( COL_SHAPE, attr );
|
||||
|
||||
attr = new wxGridCellAttr;
|
||||
attr->SetEditor( new GRID_CELL_TEXT_EDITOR() );
|
||||
m_grid->SetColAttr( COL_POS_X, attr );
|
||||
|
||||
attr = new wxGridCellAttr;
|
||||
attr->SetEditor( new GRID_CELL_TEXT_EDITOR() );
|
||||
m_grid->SetColAttr( COL_POS_Y, attr );
|
||||
|
||||
attr = new wxGridCellAttr;
|
||||
attr->SetEditor( new GRID_CELL_TEXT_EDITOR() );
|
||||
m_grid->SetColAttr( COL_SIZE_X, attr );
|
||||
|
||||
attr = new wxGridCellAttr;
|
||||
attr->SetEditor( new GRID_CELL_TEXT_EDITOR() );
|
||||
m_grid->SetColAttr( COL_SIZE_Y, attr );
|
||||
|
||||
// Drill X
|
||||
attr = new wxGridCellAttr;
|
||||
attr->SetEditor( new GRID_CELL_TEXT_EDITOR() );
|
||||
m_grid->SetColAttr( COL_DRILL_X, attr );
|
||||
|
||||
// Drill Y
|
||||
attr = new wxGridCellAttr;
|
||||
attr->SetEditor( new GRID_CELL_TEXT_EDITOR() );
|
||||
m_grid->SetColAttr( COL_DRILL_Y, attr );
|
||||
|
||||
// Pad->Die Length
|
||||
attr = new wxGridCellAttr;
|
||||
attr->SetEditor( new GRID_CELL_TEXT_EDITOR() );
|
||||
m_grid->SetColAttr( COL_P2D_LENGTH, attr );
|
||||
|
||||
// Pad->Die Delay
|
||||
attr = new wxGridCellAttr;
|
||||
attr->SetEditor( new GRID_CELL_TEXT_EDITOR() );
|
||||
m_grid->SetColAttr( COL_P2D_DELAY, attr );
|
||||
|
||||
m_grid->SetUnitsProvider( m_unitsProvider.get(), COL_POS_X );
|
||||
m_grid->SetUnitsProvider( m_unitsProvider.get(), COL_POS_Y );
|
||||
m_grid->SetUnitsProvider( m_unitsProvider.get(), COL_SIZE_X );
|
||||
m_grid->SetUnitsProvider( m_unitsProvider.get(), COL_SIZE_Y );
|
||||
m_grid->SetUnitsProvider( m_unitsProvider.get(), COL_DRILL_X );
|
||||
m_grid->SetUnitsProvider( m_unitsProvider.get(), COL_DRILL_Y );
|
||||
m_grid->SetAutoEvalCols( { COL_POS_X, COL_POS_Y, COL_SIZE_X, COL_SIZE_Y, COL_DRILL_X, COL_DRILL_Y } );
|
||||
|
||||
topSizer->Add( m_grid, 1, wxEXPAND | wxALL, 5 );
|
||||
|
||||
wxStdDialogButtonSizer* buttons = new wxStdDialogButtonSizer();
|
||||
buttons->AddButton( new wxButton( this, wxID_OK ) );
|
||||
buttons->AddButton( new wxButton( this, wxID_CANCEL ) );
|
||||
buttons->Realize();
|
||||
topSizer->Add( buttons, 0, wxALIGN_RIGHT | wxALL, 5 );
|
||||
|
||||
SetSizerAndFit( topSizer );
|
||||
|
||||
CaptureOriginalPadState();
|
||||
Populate();
|
||||
|
||||
// Bind cell change handlers for real-time updates
|
||||
m_grid->Bind( wxEVT_GRID_CELL_CHANGED, &DIALOG_FP_EDIT_PAD_TABLE::OnCellChanged, this );
|
||||
m_grid->Bind( wxEVT_GRID_SELECT_CELL, &DIALOG_FP_EDIT_PAD_TABLE::OnSelectCell, this );
|
||||
|
||||
// Listen for cancel
|
||||
Bind(
|
||||
wxEVT_BUTTON,
|
||||
[this]( wxCommandEvent& aEvt )
|
||||
{
|
||||
m_cancelled = true;
|
||||
aEvt.Skip();
|
||||
},
|
||||
wxID_CANCEL );
|
||||
|
||||
finishDialogSettings();
|
||||
}
|
||||
|
||||
DIALOG_FP_EDIT_PAD_TABLE::~DIALOG_FP_EDIT_PAD_TABLE()
|
||||
{
|
||||
if( m_cancelled )
|
||||
RestoreOriginalPadState();
|
||||
}
|
||||
|
||||
void DIALOG_FP_EDIT_PAD_TABLE::Populate()
|
||||
{
|
||||
if( !m_footprint )
|
||||
return;
|
||||
|
||||
int row = 0;
|
||||
|
||||
for( PAD* pad : m_footprint->Pads() )
|
||||
{
|
||||
m_grid->AppendRows( 1 );
|
||||
m_grid->SetCellValue( row, COL_NUMBER, pad->GetNumber() );
|
||||
|
||||
// Pad attribute to string
|
||||
wxString attrStr;
|
||||
|
||||
switch( pad->GetAttribute() )
|
||||
{
|
||||
case PAD_ATTRIB::PTH: attrStr = _( "Through-hole" ); break;
|
||||
case PAD_ATTRIB::SMD: attrStr = _( "SMD" ); break;
|
||||
case PAD_ATTRIB::CONN: attrStr = _( "Connector" ); break;
|
||||
case PAD_ATTRIB::NPTH: attrStr = _( "NPTH" ); break;
|
||||
default: attrStr = _( "Through-hole" ); break;
|
||||
}
|
||||
|
||||
VECTOR2I size = pad->GetSize( PADSTACK::ALL_LAYERS );
|
||||
|
||||
if( pad->IsAperturePad() )
|
||||
attrStr = _( "Aperture" );
|
||||
|
||||
m_grid->SetCellValue( row, COL_TYPE, attrStr );
|
||||
m_grid->SetCellValue( row, COL_SHAPE, pad->ShowPadShape( PADSTACK::ALL_LAYERS ) );
|
||||
m_grid->SetCellValue( row, COL_POS_X, m_unitsProvider->StringFromValue( pad->GetPosition().x, true ) );
|
||||
m_grid->SetCellValue( row, COL_POS_Y, m_unitsProvider->StringFromValue( pad->GetPosition().y, true ) );
|
||||
m_grid->SetCellValue( row, COL_SIZE_X, m_unitsProvider->StringFromValue( size.x, true ) );
|
||||
m_grid->SetCellValue( row, COL_SIZE_Y, m_unitsProvider->StringFromValue( size.y, true ) );
|
||||
|
||||
// Drill values (only meaningful for PTH or NPTH). Leave empty otherwise.
|
||||
if( pad->GetAttribute() == PAD_ATTRIB::PTH || pad->GetAttribute() == PAD_ATTRIB::NPTH )
|
||||
{
|
||||
VECTOR2I drill = pad->GetDrillSize();
|
||||
|
||||
if( drill.x > 0 )
|
||||
m_grid->SetCellValue( row, COL_DRILL_X, m_unitsProvider->StringFromValue( drill.x, true ) );
|
||||
if( drill.y > 0 )
|
||||
m_grid->SetCellValue( row, COL_DRILL_Y, m_unitsProvider->StringFromValue( drill.y, true ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// For non-PTH pads, drill columns are not applicable.
|
||||
m_grid->SetReadOnly( row, COL_DRILL_X, true );
|
||||
m_grid->SetReadOnly( row, COL_DRILL_Y, true );
|
||||
}
|
||||
|
||||
// Pad to die metrics
|
||||
if( pad->GetPadToDieLength() )
|
||||
m_grid->SetCellValue( row, COL_P2D_LENGTH, m_unitsProvider->StringFromValue( pad->GetPadToDieLength(), true ) );
|
||||
if( pad->GetPadToDieDelay() )
|
||||
m_grid->SetCellValue( row, COL_P2D_DELAY, wxString::Format( "%d", pad->GetPadToDieDelay() ) );
|
||||
row++;
|
||||
}
|
||||
|
||||
// Hide row labels per requirements
|
||||
m_grid->HideRowLabels();
|
||||
|
||||
// Auto size the data columns first to get reasonable initial widths
|
||||
m_grid->AutoSizeColumns();
|
||||
|
||||
// Ensure the Shape column (index 1) is wide enough for the longest translated
|
||||
// shape text plus the dropdown arrow / padding. We compute a max text width
|
||||
// using a device context and add a platform neutral padding.
|
||||
{
|
||||
wxClientDC dc( m_grid );
|
||||
dc.SetFont( m_grid->GetFont() );
|
||||
|
||||
wxArrayString shapeNames;
|
||||
shapeNames.push_back( _( "Circle" ) );
|
||||
shapeNames.push_back( _( "Oval" ) );
|
||||
shapeNames.push_back( _( "Rectangle" ) );
|
||||
shapeNames.push_back( _( "Trapezoid" ) );
|
||||
shapeNames.push_back( _( "Rounded rectangle" ) );
|
||||
shapeNames.push_back( _( "Chamfered rectangle" ) );
|
||||
shapeNames.push_back( _( "Custom shape" ) );
|
||||
|
||||
int maxWidth = 0;
|
||||
for( const wxString& str : shapeNames )
|
||||
{
|
||||
int w, h;
|
||||
dc.GetTextExtent( str, &w, &h );
|
||||
maxWidth = std::max( maxWidth, w );
|
||||
}
|
||||
|
||||
// Add padding for internal cell margins + dropdown control.
|
||||
int padding = FromDIP( 30 ); // heuristic: 2*margin + arrow button
|
||||
m_grid->SetColSize( COL_SHAPE, maxWidth + padding );
|
||||
}
|
||||
|
||||
// Record initial proportions for proportional resizing later.
|
||||
InitColumnProportions();
|
||||
Bind( wxEVT_SIZE, &DIALOG_FP_EDIT_PAD_TABLE::OnSize, this );
|
||||
|
||||
// Run an initial proportional resize using current client size so columns
|
||||
// respect proportions immediately.
|
||||
wxSizeEvent sizeEvt( GetSize(), GetId() );
|
||||
CallAfter(
|
||||
[this, sizeEvt]
|
||||
{
|
||||
wxSizeEvent evt( sizeEvt );
|
||||
this->OnSize( evt );
|
||||
} );
|
||||
|
||||
// If pads exist, select the first row to show initial highlight
|
||||
if( m_grid->GetNumberRows() > 0 )
|
||||
{
|
||||
m_grid->SetGridCursor( 0, 0 );
|
||||
// Construct event with required parameters (id, type, obj, row, col,...)
|
||||
wxGridEvent ev( m_grid->GetId(), wxEVT_GRID_SELECT_CELL, m_grid, 0, 0, -1, -1, true );
|
||||
OnSelectCell( ev );
|
||||
}
|
||||
}
|
||||
|
||||
void DIALOG_FP_EDIT_PAD_TABLE::CaptureOriginalPadState()
|
||||
{
|
||||
m_originalPads.clear();
|
||||
if( !m_footprint )
|
||||
return;
|
||||
|
||||
for( PAD* pad : m_footprint->Pads() )
|
||||
{
|
||||
PAD_SNAPSHOT snap;
|
||||
snap.number = pad->GetNumber();
|
||||
snap.shape = pad->GetShape( PADSTACK::ALL_LAYERS );
|
||||
snap.position = pad->GetPosition();
|
||||
snap.size = pad->GetSize( PADSTACK::ALL_LAYERS );
|
||||
snap.attribute = pad->GetAttribute();
|
||||
snap.drillSize = pad->GetDrillSize();
|
||||
snap.padToDieLength= pad->GetPadToDieLength();
|
||||
snap.padToDieDelay = pad->GetPadToDieDelay();
|
||||
m_originalPads.push_back( snap );
|
||||
}
|
||||
}
|
||||
|
||||
void DIALOG_FP_EDIT_PAD_TABLE::RestoreOriginalPadState()
|
||||
{
|
||||
if( !m_footprint )
|
||||
return;
|
||||
|
||||
size_t idx = 0;
|
||||
PCB_BASE_FRAME* base = dynamic_cast<PCB_BASE_FRAME*>( GetParent() );
|
||||
PCB_DRAW_PANEL_GAL* canvas = base ? base->GetCanvas() : nullptr;
|
||||
|
||||
for( PAD* pad : m_footprint->Pads() )
|
||||
{
|
||||
if( idx >= m_originalPads.size() )
|
||||
break;
|
||||
|
||||
const PAD_SNAPSHOT& snap = m_originalPads[idx++];
|
||||
pad->SetNumber( snap.number );
|
||||
pad->SetShape( PADSTACK::ALL_LAYERS, snap.shape );
|
||||
pad->SetAttribute( snap.attribute );
|
||||
pad->SetPosition( snap.position );
|
||||
pad->SetSize( PADSTACK::ALL_LAYERS, snap.size );
|
||||
pad->SetDrillSize( snap.drillSize );
|
||||
pad->SetPadToDieLength( snap.padToDieLength );
|
||||
pad->SetPadToDieDelay( snap.padToDieDelay );
|
||||
pad->ClearBrightened();
|
||||
|
||||
if( canvas )
|
||||
canvas->GetView()->Update( pad, KIGFX::REPAINT );
|
||||
}
|
||||
|
||||
if( canvas )
|
||||
{
|
||||
canvas->GetView()->MarkTargetDirty( KIGFX::TARGET_OVERLAY );
|
||||
canvas->ForceRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DIALOG_FP_EDIT_PAD_TABLE::TransferDataFromWindow()
|
||||
{
|
||||
if( !m_grid->CommitPendingChanges() )
|
||||
return false;
|
||||
|
||||
if( !m_footprint )
|
||||
return true;
|
||||
|
||||
int row = 0;
|
||||
|
||||
for( PAD* pad : m_footprint->Pads() )
|
||||
{
|
||||
pad->SetNumber( m_grid->GetCellValue( row, COL_NUMBER ) );
|
||||
|
||||
wxString typeStr = m_grid->GetCellValue( row, COL_TYPE );
|
||||
if( typeStr == _( "Through-hole" ) )
|
||||
pad->SetAttribute( PAD_ATTRIB::PTH );
|
||||
else if( typeStr == _( "SMD" ) )
|
||||
pad->SetAttribute( PAD_ATTRIB::SMD );
|
||||
else if( typeStr == _( "Connector" ) )
|
||||
pad->SetAttribute( PAD_ATTRIB::CONN );
|
||||
else if( typeStr == _( "NPTH" ) )
|
||||
pad->SetAttribute( PAD_ATTRIB::NPTH );
|
||||
// Aperture derived by copper-less layers; do not overwrite attribute here.
|
||||
|
||||
wxString shape = m_grid->GetCellValue( row, COL_SHAPE );
|
||||
PAD_SHAPE newShape = ShapeFromString( shape );
|
||||
|
||||
pad->SetShape( PADSTACK::ALL_LAYERS, newShape );
|
||||
|
||||
VECTOR2I pos;
|
||||
pos.x = m_grid->GetUnitValue( row, COL_POS_X );
|
||||
pos.y = m_grid->GetUnitValue( row, COL_POS_Y );
|
||||
pad->SetPosition( pos );
|
||||
|
||||
VECTOR2I size;
|
||||
size.x = m_grid->GetUnitValue( row, COL_SIZE_X );
|
||||
size.y = m_grid->GetUnitValue( row, COL_SIZE_Y );
|
||||
pad->SetSize( PADSTACK::ALL_LAYERS, size );
|
||||
|
||||
// Drill sizes (only if attribute allows)
|
||||
if( pad->GetAttribute() == PAD_ATTRIB::PTH || pad->GetAttribute() == PAD_ATTRIB::NPTH )
|
||||
{
|
||||
int dx = m_grid->GetUnitValue( row, COL_DRILL_X );
|
||||
int dy = m_grid->GetUnitValue( row, COL_DRILL_Y );
|
||||
if( dx > 0 || dy > 0 )
|
||||
{
|
||||
if( dx <= 0 ) dx = dy;
|
||||
if( dy <= 0 ) dy = dx;
|
||||
pad->SetDrillSize( { dx, dy } );
|
||||
}
|
||||
}
|
||||
|
||||
// Pad->Die
|
||||
wxString delayStr = m_grid->GetCellValue( row, COL_P2D_DELAY );
|
||||
wxString lenStr = m_grid->GetCellValue( row, COL_P2D_LENGTH );
|
||||
|
||||
if( !lenStr.IsEmpty() )
|
||||
pad->SetPadToDieLength( m_grid->GetUnitValue( row, COL_P2D_LENGTH ) );
|
||||
else
|
||||
pad->SetPadToDieLength( 0 );
|
||||
|
||||
if( !delayStr.IsEmpty() )
|
||||
{
|
||||
long delayVal;
|
||||
|
||||
if( delayStr.ToLong( &delayVal ) )
|
||||
pad->SetPadToDieDelay( (int) delayVal );
|
||||
else
|
||||
pad->SetPadToDieDelay( 0 );
|
||||
}
|
||||
else
|
||||
pad->SetPadToDieDelay( 0 );
|
||||
|
||||
row++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DIALOG_FP_EDIT_PAD_TABLE::InitColumnProportions()
|
||||
{
|
||||
m_colProportions.clear();
|
||||
m_minColWidths.clear();
|
||||
|
||||
if( !m_grid )
|
||||
return;
|
||||
|
||||
// Only consider the actual data columns (all of them since row labels are hidden)
|
||||
int cols = m_grid->GetNumberCols();
|
||||
int total = 0;
|
||||
std::vector<int> widths;
|
||||
widths.reserve( cols );
|
||||
|
||||
for( int c = 0; c < cols; ++c )
|
||||
{
|
||||
int w = m_grid->GetColSize( c );
|
||||
widths.push_back( w );
|
||||
total += w;
|
||||
}
|
||||
|
||||
if( total <= 0 )
|
||||
return;
|
||||
|
||||
for( int w : widths )
|
||||
{
|
||||
m_colProportions.push_back( (double) w / (double) total );
|
||||
m_minColWidths.push_back( w );
|
||||
}
|
||||
}
|
||||
|
||||
void DIALOG_FP_EDIT_PAD_TABLE::OnSize( wxSizeEvent& aEvent )
|
||||
{
|
||||
if( m_colProportions.empty() )
|
||||
{
|
||||
aEvent.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
// Compute available total width for columns and resize keeping proportions.
|
||||
int cols = m_grid->GetNumberCols();
|
||||
int available = 0;
|
||||
|
||||
for( int c = 0; c < cols; ++c )
|
||||
available += m_grid->GetColSize( c );
|
||||
|
||||
// Use client size of grid minus scrollbar estimate to better distribute.
|
||||
int clientW = m_grid->GetClientSize().x;
|
||||
|
||||
if( clientW > 0 )
|
||||
available = clientW; // prefer actual client width
|
||||
|
||||
int used = 0;
|
||||
for( int c = 0; c < cols; ++c )
|
||||
{
|
||||
int target = (int) std::round( m_colProportions[c] * available );
|
||||
target = std::max( target, m_minColWidths[c] );
|
||||
|
||||
// Defer last column to absorb rounding diff.
|
||||
if( c == cols - 1 )
|
||||
target = std::max( available - used, m_minColWidths[c] );
|
||||
|
||||
m_grid->SetColSize( c, target );
|
||||
used += target;
|
||||
}
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
void DIALOG_FP_EDIT_PAD_TABLE::OnCellChanged( wxGridEvent& aEvent )
|
||||
{
|
||||
int row = aEvent.GetRow();
|
||||
int col = aEvent.GetCol();
|
||||
|
||||
if( !m_footprint )
|
||||
return;
|
||||
|
||||
// row -> pad mapping is current order of Pads() iteration; rebuild each time (pads count small)
|
||||
int idx = 0;
|
||||
PAD* target = nullptr;
|
||||
|
||||
for( PAD* pad : m_footprint->Pads() )
|
||||
{
|
||||
if( idx == row ) { target = pad; break; }
|
||||
++idx;
|
||||
}
|
||||
|
||||
if( !target )
|
||||
return;
|
||||
bool needCanvasRefresh = false;
|
||||
|
||||
switch( col )
|
||||
{
|
||||
case COL_NUMBER:
|
||||
target->SetNumber( m_grid->GetCellValue( row, col ) );
|
||||
break;
|
||||
|
||||
case COL_TYPE:
|
||||
{
|
||||
wxString typeStr = m_grid->GetCellValue( row, col );
|
||||
PAD_ATTRIB newAttr = target->GetAttribute();
|
||||
|
||||
if( typeStr == _( "Through-hole" ) )
|
||||
newAttr = PAD_ATTRIB::PTH;
|
||||
else if( typeStr == _( "SMD" ) )
|
||||
newAttr = PAD_ATTRIB::SMD;
|
||||
else if( typeStr == _( "Connector" ) )
|
||||
newAttr = PAD_ATTRIB::CONN;
|
||||
else if( typeStr == _( "NPTH" ) )
|
||||
newAttr = PAD_ATTRIB::NPTH;
|
||||
|
||||
if( newAttr != target->GetAttribute() )
|
||||
{
|
||||
target->SetAttribute( newAttr );
|
||||
|
||||
// Toggle drill columns read-only state dynamically.
|
||||
bool drillsEditable = ( newAttr == PAD_ATTRIB::PTH || newAttr == PAD_ATTRIB::NPTH );
|
||||
m_grid->SetReadOnly( row, COL_DRILL_X, !drillsEditable );
|
||||
m_grid->SetReadOnly( row, COL_DRILL_Y, !drillsEditable );
|
||||
needCanvasRefresh = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case COL_SHAPE:
|
||||
target->SetShape( PADSTACK::ALL_LAYERS, ShapeFromString( m_grid->GetCellValue( row, col ) ) );
|
||||
needCanvasRefresh = true;
|
||||
break;
|
||||
|
||||
case COL_POS_X:
|
||||
case COL_POS_Y:
|
||||
{
|
||||
VECTOR2I pos = target->GetPosition();
|
||||
|
||||
if( col == COL_POS_X )
|
||||
pos.x = m_grid->GetUnitValue( row, col );
|
||||
else
|
||||
pos.y = m_grid->GetUnitValue( row, col );
|
||||
|
||||
target->SetPosition( pos );
|
||||
needCanvasRefresh = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case COL_SIZE_X:
|
||||
case COL_SIZE_Y:
|
||||
{
|
||||
VECTOR2I size = target->GetSize( PADSTACK::ALL_LAYERS );
|
||||
|
||||
if( col == COL_SIZE_X )
|
||||
size.x = m_grid->GetUnitValue( row, col );
|
||||
else
|
||||
size.y = m_grid->GetUnitValue( row, col );
|
||||
|
||||
target->SetSize( PADSTACK::ALL_LAYERS, size );
|
||||
needCanvasRefresh = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case COL_DRILL_X:
|
||||
case COL_DRILL_Y:
|
||||
{
|
||||
if( target->GetAttribute() == PAD_ATTRIB::PTH || target->GetAttribute() == PAD_ATTRIB::NPTH )
|
||||
{
|
||||
int dx = m_grid->GetUnitValue( row, COL_DRILL_X );
|
||||
int dy = m_grid->GetUnitValue( row, COL_DRILL_Y );
|
||||
if( dx > 0 || dy > 0 )
|
||||
{
|
||||
if( dx <= 0 ) dx = dy;
|
||||
if( dy <= 0 ) dy = dx;
|
||||
target->SetDrillSize( { dx, dy } );
|
||||
needCanvasRefresh = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case COL_P2D_LENGTH:
|
||||
if( !m_grid->GetCellValue( row, col ).IsEmpty() )
|
||||
target->SetPadToDieLength( m_grid->GetUnitValue( row, col ) );
|
||||
break;
|
||||
|
||||
case COL_P2D_DELAY:
|
||||
{
|
||||
wxString d = m_grid->GetCellValue( row, col );
|
||||
long val;
|
||||
|
||||
if( d.ToLong( &val ) )
|
||||
target->SetPadToDieDelay( (int) val );
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Request redraw (simple approach)
|
||||
target->SetDirty();
|
||||
|
||||
if( needCanvasRefresh )
|
||||
{
|
||||
if( PCB_BASE_FRAME* base = dynamic_cast<PCB_BASE_FRAME*>( GetParent() ) )
|
||||
base->GetCanvas()->ForceRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
void DIALOG_FP_EDIT_PAD_TABLE::OnSelectCell( wxGridEvent& aEvent )
|
||||
{
|
||||
int row = aEvent.GetRow();
|
||||
|
||||
if( !m_footprint )
|
||||
return;
|
||||
|
||||
PCB_BASE_FRAME* base = dynamic_cast<PCB_BASE_FRAME*>( GetParent() );
|
||||
PCB_DRAW_PANEL_GAL* canvas = base ? base->GetCanvas() : nullptr;
|
||||
|
||||
// Clear existing pad selections
|
||||
for( PAD* pad : m_footprint->Pads() )
|
||||
{
|
||||
if( pad->IsBrightened() )
|
||||
{
|
||||
pad->ClearBrightened();
|
||||
|
||||
if( canvas )
|
||||
canvas->GetView()->Update( pad, KIGFX::REPAINT );
|
||||
}
|
||||
}
|
||||
|
||||
int idx = 0;
|
||||
|
||||
for( PAD* pad : m_footprint->Pads() )
|
||||
{
|
||||
if( idx == row )
|
||||
{
|
||||
pad->SetBrightened();
|
||||
|
||||
if( canvas )
|
||||
{
|
||||
canvas->GetView()->Update( pad, KIGFX::REPAINT );
|
||||
canvas->ForceRefresh();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
++idx;
|
||||
}
|
||||
|
||||
}
|
||||
|
59
pcbnew/dialogs/dialog_fp_edit_pad_table.h
Normal file
59
pcbnew/dialogs/dialog_fp_edit_pad_table.h
Normal file
@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include "dialog_shim.h"
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <pad.h>
|
||||
|
||||
class PCB_BASE_FRAME;
|
||||
class FOOTPRINT;
|
||||
class WX_GRID;
|
||||
class UNITS_PROVIDER;
|
||||
|
||||
class DIALOG_FP_EDIT_PAD_TABLE : public DIALOG_SHIM
|
||||
{
|
||||
public:
|
||||
DIALOG_FP_EDIT_PAD_TABLE( PCB_BASE_FRAME* aParent, FOOTPRINT* aFootprint );
|
||||
~DIALOG_FP_EDIT_PAD_TABLE() override;
|
||||
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
private:
|
||||
void Populate();
|
||||
|
||||
void OnSize( wxSizeEvent& aEvent );
|
||||
|
||||
// Proportional resize support
|
||||
std::vector<double> m_colProportions; // relative widths captured after init
|
||||
std::vector<int> m_minColWidths; // initial (minimum) widths
|
||||
void InitColumnProportions();
|
||||
|
||||
struct PAD_SNAPSHOT
|
||||
{
|
||||
wxString number;
|
||||
PAD_SHAPE shape;
|
||||
VECTOR2I position;
|
||||
VECTOR2I size;
|
||||
PAD_ATTRIB attribute;
|
||||
VECTOR2I drillSize;
|
||||
int padToDieLength = 0;
|
||||
int padToDieDelay = 0;
|
||||
};
|
||||
|
||||
std::vector<PAD_SNAPSHOT> m_originalPads; // original pad data for cancel rollback
|
||||
bool m_cancelled = false; // set if user hit cancel
|
||||
void CaptureOriginalPadState();
|
||||
void RestoreOriginalPadState();
|
||||
|
||||
void OnCellChanged( wxGridEvent& aEvent );
|
||||
void OnSelectCell( wxGridEvent& aEvent );
|
||||
|
||||
// Column indices (after adding Type column)
|
||||
enum COLS { COL_NUMBER = 0, COL_TYPE, COL_SHAPE, COL_POS_X, COL_POS_Y, COL_SIZE_X, COL_SIZE_Y,
|
||||
COL_DRILL_X, COL_DRILL_Y, COL_P2D_LENGTH, COL_P2D_DELAY };
|
||||
|
||||
WX_GRID* m_grid;
|
||||
FOOTPRINT* m_footprint;
|
||||
std::unique_ptr<UNITS_PROVIDER> m_unitsProvider;
|
||||
};
|
||||
|
@ -542,7 +542,8 @@ void DRC_ENGINE::compileRules()
|
||||
}
|
||||
|
||||
if( error_semaphore.HasMessageOfSeverity( RPT_SEVERITY_ERROR ) )
|
||||
THROW_PARSE_ERROR( wxT( "Parse error" ), rule->m_Name, rule->m_Condition->GetExpression(), 0, 0 );
|
||||
THROW_PARSE_ERROR( wxT( "Parse error" ), rule->m_Name,
|
||||
TO_UTF8( rule->m_Condition->GetExpression() ), 0, 0 );
|
||||
|
||||
for( const DRC_CONSTRAINT& constraint : rule->m_Constraints )
|
||||
{
|
||||
|
@ -1421,6 +1421,7 @@ void FOOTPRINT_EDIT_FRAME::setupUIConditions()
|
||||
mgr->SetConditions( PCB_ACTIONS::placeImportedGraphics, ENABLE( haveFootprintCond ) );
|
||||
|
||||
mgr->SetConditions( PCB_ACTIONS::footprintProperties, ENABLE( haveFootprintCond ) );
|
||||
mgr->SetConditions( PCB_ACTIONS::padTable, ENABLE( haveFootprintCond ) );
|
||||
mgr->SetConditions( PCB_ACTIONS::editTextAndGraphics, ENABLE( haveFootprintCond ) );
|
||||
mgr->SetConditions( PCB_ACTIONS::checkFootprint, ENABLE( haveFootprintCond ) );
|
||||
mgr->SetConditions( PCB_ACTIONS::repairFootprint, ENABLE( haveFootprintCond ) );
|
||||
|
@ -119,6 +119,7 @@ void FOOTPRINT_EDIT_FRAME::doReCreateMenuBar()
|
||||
|
||||
editMenu->AppendSeparator();
|
||||
editMenu->Add( PCB_ACTIONS::editTextAndGraphics );
|
||||
editMenu->Add( PCB_ACTIONS::padTable );
|
||||
editMenu->Add( PCB_ACTIONS::defaultPadProperties );
|
||||
editMenu->Add( PCB_ACTIONS::enumeratePads );
|
||||
editMenu->Add( ACTIONS::gridOrigin );
|
||||
|
@ -1192,6 +1192,8 @@ AREGION6::AREGION6( ALTIUM_BINARY_PARSER& aReader, bool aExtendedVertices )
|
||||
int pkind = ALTIUM_PROPS_UTILS::ReadInt( properties, wxT( "KIND" ), 0 );
|
||||
bool is_cutout = ALTIUM_PROPS_UTILS::ReadBool( properties, wxT( "ISBOARDCUTOUT" ), false );
|
||||
|
||||
v7layer = ALTIUM_PROPS_UTILS::ReadString( properties, wxT( "V7_LAYER" ), wxEmptyString );
|
||||
name = ALTIUM_PROPS_UTILS::ReadString( properties, wxT( "NAME" ), wxEmptyString );
|
||||
is_shapebased = ALTIUM_PROPS_UTILS::ReadBool( properties, wxT( "ISSHAPEBASED" ), false );
|
||||
keepoutrestrictions = static_cast<uint8_t>(
|
||||
ALTIUM_PROPS_UTILS::ReadInt( properties, wxT( "KEEPOUTRESTRIC" ), 0x1F ) );
|
||||
@ -1201,6 +1203,25 @@ AREGION6::AREGION6( ALTIUM_BINARY_PARSER& aReader, bool aExtendedVertices )
|
||||
subpolyindex = static_cast<uint16_t>(
|
||||
ALTIUM_PROPS_UTILS::ReadInt( properties, "SUBPOLYINDEX", ALTIUM_POLYGON_NONE ) );
|
||||
|
||||
unionindex = ALTIUM_PROPS_UTILS::ReadOptInt( properties, "UNIONINDEX" );
|
||||
padindex = ALTIUM_PROPS_UTILS::ReadOptInt( properties, "PADINDEX" );
|
||||
arc_resolution = ALTIUM_PROPS_UTILS::ReadKicadUnit( properties, "ARCRESOLUTION", "0.1mil");
|
||||
cavity_height = ALTIUM_PROPS_UTILS::ReadKicadUnit( properties, "CAVITYHEIGHT", "0mil");
|
||||
|
||||
// Note RFB:
|
||||
// Sometimes the format could have vertices in the properties region, e.g. like below. In these
|
||||
// cases a property "MAINCONTOURVERTEXCOUNT" will also be present containing the number of
|
||||
// vertices. For now, I decided it is not worth it to parse it since the same data is present in
|
||||
// the binary stream in all samples I have seen.
|
||||
// KIND0=0
|
||||
// VX0=-27mil
|
||||
// VY0=-15mil
|
||||
// CX0=0mil
|
||||
// CY0=0mil
|
||||
// SA0= 0.00000000000000E+0000
|
||||
// EA0= 0.00000000000000E+0000
|
||||
// R0=0mil
|
||||
|
||||
switch( pkind )
|
||||
{
|
||||
case 0:
|
||||
|
@ -562,8 +562,16 @@ struct AREGION6
|
||||
uint8_t keepoutrestrictions;
|
||||
uint16_t holecount;
|
||||
|
||||
wxString name;
|
||||
wxString v7layer; ///< duplicate data? seems identical to 'layer' in the binary stream
|
||||
|
||||
std::optional<int> unionindex; ///< Unclear what unionindex refers to
|
||||
std::optional<int> padindex;
|
||||
|
||||
ALTIUM_REGION_KIND kind; // I assume this means if normal or keepout?
|
||||
|
||||
std::optional<int32_t> cavity_height; ///< Unclear what cavity height is
|
||||
std::optional<int32_t> arc_resolution;
|
||||
std::vector<ALTIUM_VERTICE> outline;
|
||||
std::vector<std::vector<ALTIUM_VERTICE>> holes;
|
||||
|
||||
|
@ -76,6 +76,29 @@ bool IsAltiumLayerAPlane( ALTIUM_LAYER aLayer )
|
||||
return aLayer >= ALTIUM_LAYER::INTERNAL_PLANE_1 && aLayer <= ALTIUM_LAYER::INTERNAL_PLANE_16;
|
||||
}
|
||||
|
||||
|
||||
PAD* ALTIUM_PCB::HelperGetPad( int aPadIndex ) const
|
||||
{
|
||||
if( !m_padIndexMap.contains( aPadIndex ) )
|
||||
{
|
||||
THROW_IO_ERROR( wxString::Format( wxT( "Component creator tries to access pad id "
|
||||
"%d, which does not exist" ),
|
||||
aPadIndex ) );
|
||||
}
|
||||
|
||||
BOARD_CONNECTED_ITEM* padBoardItem = m_padIndexMap.at( aPadIndex );
|
||||
|
||||
if( padBoardItem->Type() != PCB_PAD_T )
|
||||
{
|
||||
// Todo: graceful handling?
|
||||
THROW_IO_ERROR( wxString::Format( wxT( "Pad %d is not on a copper layer, unexpected" ),
|
||||
aPadIndex ) );
|
||||
}
|
||||
|
||||
return static_cast<PAD*>( padBoardItem );
|
||||
}
|
||||
|
||||
|
||||
FOOTPRINT* ALTIUM_PCB::HelperGetFootprint( uint16_t aComponent ) const
|
||||
{
|
||||
if( aComponent == ALTIUM_COMPONENT_NONE || m_components.size() <= aComponent )
|
||||
@ -793,7 +816,7 @@ FOOTPRINT* ALTIUM_PCB::ParseFootprint( ALTIUM_PCB_COMPOUND_FILE& altiumLibFile,
|
||||
case ALTIUM_RECORD::PAD:
|
||||
{
|
||||
APAD6 pad( parser );
|
||||
ConvertPads6ToFootprintItem( footprint.get(), pad );
|
||||
ConvertPads6ToFootprintItem( footprint.get(), pad, primitiveIndex );
|
||||
break;
|
||||
}
|
||||
case ALTIUM_RECORD::VIA:
|
||||
@ -2685,6 +2708,11 @@ void ALTIUM_PCB::ConvertShapeBasedRegions6ToFootprintItem( FOOTPRINT* aFoot
|
||||
void ALTIUM_PCB::ConvertShapeBasedRegions6ToBoardItemOnLayer( const AREGION6& aElem,
|
||||
PCB_LAYER_ID aLayer )
|
||||
{
|
||||
wxASSERT_MSG( !aElem.padindex.has_value(),
|
||||
wxT( "ConvertShapeBasedRegions6ToBoardItemOnLayer was called for a Region with a "
|
||||
"pad index! ConvertShapeBasedRegions6ToFootprintItemOnLayer should be "
|
||||
"called instead" ) );
|
||||
|
||||
SHAPE_LINE_CHAIN linechain;
|
||||
HelperShapeLineChainFromAltiumVertices( linechain, aElem.outline );
|
||||
|
||||
@ -2758,9 +2786,24 @@ void ALTIUM_PCB::ConvertShapeBasedRegions6ToFootprintItemOnLayer( FOOTPRINT*
|
||||
polySet.AddHole( hole_linechain );
|
||||
}
|
||||
|
||||
if( aLayer == F_Cu || aLayer == B_Cu )
|
||||
if( aElem.padindex.has_value() && LSET::AllCuMask().Contains( aLayer ) )
|
||||
{
|
||||
// Replace shape on layer of existing pad
|
||||
int actualPadindex=aElem.padindex.value() - 1; // altium seems to index starting at 1?
|
||||
PAD* pad = HelperGetPad( actualPadindex ); // throws if pad doesn't exist
|
||||
|
||||
pad->SetShape( aLayer, PAD_SHAPE::CUSTOM );
|
||||
polySet.Move( -pad->GetPosition() );
|
||||
polySet.Rotate( -pad->Padstack().GetOrientation() );
|
||||
pad->AddPrimitivePoly( aLayer, polySet, 0, true );
|
||||
|
||||
// Ignore extended primitive information from the region - this appears to mean nothing
|
||||
// for regions used in pads. It should have already been set correctly when the pad was
|
||||
// loaded
|
||||
|
||||
}
|
||||
else if( aLayer == F_Cu || aLayer == B_Cu )
|
||||
{
|
||||
// TODO(JE) padstacks -- not sure what should happen here yet
|
||||
std::unique_ptr<PAD> pad = std::make_unique<PAD>( aFootprint );
|
||||
|
||||
LSET padLayers;
|
||||
@ -3158,6 +3201,8 @@ void ALTIUM_PCB::ParsePads6Data( const ALTIUM_PCB_COMPOUND_FILE& aAltiumPcbF
|
||||
|
||||
ALTIUM_BINARY_PARSER reader( aAltiumPcbFile, aEntry );
|
||||
|
||||
int padindex = 0;
|
||||
|
||||
while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
|
||||
{
|
||||
checkpoint();
|
||||
@ -3165,12 +3210,12 @@ void ALTIUM_PCB::ParsePads6Data( const ALTIUM_PCB_COMPOUND_FILE& aAltiumPcbF
|
||||
|
||||
if( elem.component == ALTIUM_COMPONENT_NONE )
|
||||
{
|
||||
ConvertPads6ToBoardItem( elem );
|
||||
ConvertPads6ToBoardItem( elem, padindex++ );
|
||||
}
|
||||
else
|
||||
{
|
||||
FOOTPRINT* footprint = HelperGetFootprint( elem.component );
|
||||
ConvertPads6ToFootprintItem( footprint, elem );
|
||||
ConvertPads6ToFootprintItem( footprint, elem, padindex++ );
|
||||
}
|
||||
}
|
||||
|
||||
@ -3179,13 +3224,13 @@ void ALTIUM_PCB::ParsePads6Data( const ALTIUM_PCB_COMPOUND_FILE& aAltiumPcbF
|
||||
}
|
||||
|
||||
|
||||
void ALTIUM_PCB::ConvertPads6ToBoardItem( const APAD6& aElem )
|
||||
void ALTIUM_PCB::ConvertPads6ToBoardItem( const APAD6& aElem, const int aPadIndex )
|
||||
{
|
||||
// It is possible to place altium pads on non-copper layers -> we need to interpolate them using drawings!
|
||||
if( !IsAltiumLayerCopper( aElem.layer ) && !IsAltiumLayerAPlane( aElem.layer )
|
||||
&& aElem.layer != ALTIUM_LAYER::MULTI_LAYER )
|
||||
{
|
||||
ConvertPads6ToBoardItemOnNonCopper( aElem );
|
||||
ConvertPads6ToBoardItemOnNonCopper( aElem, aPadIndex );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3193,7 +3238,7 @@ void ALTIUM_PCB::ConvertPads6ToBoardItem( const APAD6& aElem )
|
||||
std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>( m_board );
|
||||
footprint->SetPosition( aElem.position );
|
||||
|
||||
ConvertPads6ToFootprintItemOnCopper( footprint.get(), aElem );
|
||||
ConvertPads6ToFootprintItemOnCopper( footprint.get(), aElem, aPadIndex );
|
||||
|
||||
m_board->Add( footprint.release(), ADD_MODE::APPEND );
|
||||
}
|
||||
@ -3274,22 +3319,24 @@ void ALTIUM_PCB::ConvertVias6ToFootprintItem( FOOTPRINT* aFootprint, const AVIA6
|
||||
}
|
||||
|
||||
|
||||
void ALTIUM_PCB::ConvertPads6ToFootprintItem( FOOTPRINT* aFootprint, const APAD6& aElem )
|
||||
void ALTIUM_PCB::ConvertPads6ToFootprintItem( FOOTPRINT* aFootprint, const APAD6& aElem,
|
||||
const int aPadIndex )
|
||||
{
|
||||
// It is possible to place altium pads on non-copper layers -> we need to interpolate them using drawings!
|
||||
if( !IsAltiumLayerCopper( aElem.layer ) && !IsAltiumLayerAPlane( aElem.layer )
|
||||
&& aElem.layer != ALTIUM_LAYER::MULTI_LAYER )
|
||||
{
|
||||
ConvertPads6ToFootprintItemOnNonCopper( aFootprint, aElem );
|
||||
ConvertPads6ToFootprintItemOnNonCopper( aFootprint, aElem, aPadIndex );
|
||||
}
|
||||
else
|
||||
{
|
||||
ConvertPads6ToFootprintItemOnCopper( aFootprint, aElem );
|
||||
ConvertPads6ToFootprintItemOnCopper( aFootprint, aElem, aPadIndex );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ALTIUM_PCB::ConvertPads6ToFootprintItemOnCopper( FOOTPRINT* aFootprint, const APAD6& aElem )
|
||||
void ALTIUM_PCB::ConvertPads6ToFootprintItemOnCopper( FOOTPRINT* aFootprint, const APAD6& aElem,
|
||||
const int aPadIndex )
|
||||
{
|
||||
std::unique_ptr<PAD> pad = std::make_unique<PAD>( aFootprint );
|
||||
|
||||
@ -3617,11 +3664,13 @@ void ALTIUM_PCB::ConvertPads6ToFootprintItemOnCopper( FOOTPRINT* aFootprint, con
|
||||
if( aElem.is_tent_bottom )
|
||||
pad->SetLayerSet( pad->GetLayerSet().reset( B_Mask ) );
|
||||
|
||||
aFootprint->Add( pad.release(), ADD_MODE::APPEND );
|
||||
PAD* pad_ptr = pad.release();
|
||||
m_padIndexMap.emplace( aPadIndex, pad_ptr );
|
||||
aFootprint->Add( pad_ptr, ADD_MODE::APPEND );
|
||||
}
|
||||
|
||||
|
||||
void ALTIUM_PCB::ConvertPads6ToBoardItemOnNonCopper( const APAD6& aElem )
|
||||
void ALTIUM_PCB::ConvertPads6ToBoardItemOnNonCopper( const APAD6& aElem, const int aPadIndex )
|
||||
{
|
||||
PCB_LAYER_ID klayer = GetKicadLayer( aElem.layer );
|
||||
|
||||
@ -3643,11 +3692,14 @@ void ALTIUM_PCB::ConvertPads6ToBoardItemOnNonCopper( const APAD6& aElem )
|
||||
|
||||
HelperParsePad6NonCopper( aElem, klayer, pad.get() );
|
||||
|
||||
m_board->Add( pad.release(), ADD_MODE::APPEND );
|
||||
PCB_SHAPE* pad_ptr = pad.release();
|
||||
m_padIndexMap.emplace( aPadIndex, pad_ptr );
|
||||
m_board->Add( pad_ptr, ADD_MODE::APPEND );
|
||||
}
|
||||
|
||||
|
||||
void ALTIUM_PCB::ConvertPads6ToFootprintItemOnNonCopper( FOOTPRINT* aFootprint, const APAD6& aElem )
|
||||
void ALTIUM_PCB::ConvertPads6ToFootprintItemOnNonCopper( FOOTPRINT* aFootprint, const APAD6& aElem,
|
||||
const int aPadIndex )
|
||||
{
|
||||
PCB_LAYER_ID klayer = GetKicadLayer( aElem.layer );
|
||||
|
||||
@ -3689,7 +3741,9 @@ void ALTIUM_PCB::ConvertPads6ToFootprintItemOnNonCopper( FOOTPRINT* aFootprint,
|
||||
|
||||
HelperParsePad6NonCopper( aElem, klayer, pad.get() );
|
||||
|
||||
aFootprint->Add( pad.release(), ADD_MODE::APPEND );
|
||||
PCB_SHAPE* pad_ptr = pad.release();
|
||||
m_padIndexMap.emplace( aPadIndex, pad_ptr );
|
||||
aFootprint->Add( pad_ptr, ADD_MODE::APPEND );
|
||||
}
|
||||
|
||||
|
||||
|
@ -85,6 +85,8 @@ enum class ALTIUM_PCB_DIR
|
||||
|
||||
|
||||
class BOARD;
|
||||
class BOARD_CONNECTED_ITEM;
|
||||
class PAD;
|
||||
class FP_SHAPE;
|
||||
class PCB_SHAPE;
|
||||
class PCB_TEXTBOX;
|
||||
@ -182,11 +184,14 @@ private:
|
||||
const ACOMPONENTBODY6& aElem );
|
||||
void ParsePads6Data( const ALTIUM_PCB_COMPOUND_FILE& aAltiumPcbFile,
|
||||
const CFB::COMPOUND_FILE_ENTRY* aEntry );
|
||||
void ConvertPads6ToBoardItem( const APAD6& aElem );
|
||||
void ConvertPads6ToFootprintItem( FOOTPRINT* aFootprint, const APAD6& aElem );
|
||||
void ConvertPads6ToBoardItemOnNonCopper( const APAD6& aElem );
|
||||
void ConvertPads6ToFootprintItemOnCopper( FOOTPRINT* aFootprint, const APAD6& aElem );
|
||||
void ConvertPads6ToFootprintItemOnNonCopper( FOOTPRINT* aFootprint, const APAD6& aElem );
|
||||
void ConvertPads6ToBoardItem( const APAD6& aElem, const int aPadIndex );
|
||||
void ConvertPads6ToFootprintItem( FOOTPRINT* aFootprint, const APAD6& aElem,
|
||||
const int aPadIndex );
|
||||
void ConvertPads6ToBoardItemOnNonCopper( const APAD6& aElem, const int aPadIndex );
|
||||
void ConvertPads6ToFootprintItemOnCopper( FOOTPRINT* aFootprint, const APAD6& aElem,
|
||||
const int aPadIndex );
|
||||
void ConvertPads6ToFootprintItemOnNonCopper( FOOTPRINT* aFootprint, const APAD6& aElem,
|
||||
const int aPadIndex );
|
||||
void ParseVias6Data( const ALTIUM_PCB_COMPOUND_FILE& aAltiumPcbFile,
|
||||
const CFB::COMPOUND_FILE_ENTRY* aEntry );
|
||||
void ConvertVias6ToFootprintItem( FOOTPRINT* aFootprint, const AVIA6& aElem );
|
||||
@ -261,6 +266,7 @@ private:
|
||||
const ALTIUM_LAYER aAltiumLayer );
|
||||
|
||||
FOOTPRINT* HelperGetFootprint( uint16_t aComponent ) const;
|
||||
PAD* HelperGetPad( int aPadIndex ) const;
|
||||
|
||||
void remapUnsureLayers( std::vector<ABOARD6_LAYER_STACKUP>& aStackup );
|
||||
|
||||
@ -277,6 +283,7 @@ private:
|
||||
std::map<ALTIUM_RULE_KIND, std::vector<ARULE6>> m_rules;
|
||||
std::map<ALTIUM_RECORD, std::multimap<int, const AEXTENDED_PRIMITIVE_INFORMATION>>
|
||||
m_extendedPrimitiveInformationMaps;
|
||||
std::map<int, BOARD_CONNECTED_ITEM*> m_padIndexMap;
|
||||
|
||||
std::map<ALTIUM_LAYER, ZONE*> m_outer_plane;
|
||||
|
||||
|
@ -166,6 +166,7 @@ std::optional<TOOLBAR_CONFIGURATION> FOOTPRINT_EDIT_TOOLBAR_SETTINGS::DefaultToo
|
||||
|
||||
config.AppendSeparator()
|
||||
.AppendAction( PCB_ACTIONS::footprintProperties )
|
||||
.AppendAction( PCB_ACTIONS::padTable )
|
||||
.AppendAction( PCB_ACTIONS::defaultPadProperties )
|
||||
.AppendAction( ACTIONS::showDatasheet )
|
||||
.AppendAction( PCB_ACTIONS::checkFootprint );
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <pcbnew_settings.h>
|
||||
#include <board_commit.h>
|
||||
#include <dialogs/dialog_push_pad_properties.h>
|
||||
#include <dialogs/dialog_fp_edit_pad_table.h>
|
||||
#include <tools/pcb_actions.h>
|
||||
#include <tools/pcb_grid_helper.h>
|
||||
#include <tools/pcb_selection_tool.h>
|
||||
@ -109,6 +110,7 @@ bool PAD_TOOL::Init()
|
||||
|
||||
if( m_isFootprintEditor )
|
||||
{
|
||||
menu.AddItem( PCB_ACTIONS::padTable, SELECTION_CONDITIONS::ShowAlways, 400 );
|
||||
menu.AddItem( PCB_ACTIONS::enumeratePads, SELECTION_CONDITIONS::ShowAlways, 400 );
|
||||
menu.AddItem( PCB_ACTIONS::recombinePad, recombineCondition, 400 );
|
||||
menu.AddItem( PCB_ACTIONS::explodePad, explodeCondition, 400 );
|
||||
@ -911,6 +913,22 @@ std::vector<PCB_SHAPE*> PAD_TOOL::RecombinePad( PAD* aPad, bool aIsDryRun )
|
||||
return aPad->Recombine( aIsDryRun, maxError );
|
||||
}
|
||||
|
||||
int PAD_TOOL::PadTable( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
if( !m_isFootprintEditor || InPadEditMode() )
|
||||
return 0;
|
||||
|
||||
FOOTPRINT* footprint = board()->GetFirstFootprint();
|
||||
|
||||
if( !footprint )
|
||||
return 0;
|
||||
|
||||
DIALOG_FP_EDIT_PAD_TABLE dlg( frame(), footprint );
|
||||
dlg.ShowQuasiModal();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void PAD_TOOL::setTransitions()
|
||||
{
|
||||
@ -920,6 +938,7 @@ void PAD_TOOL::setTransitions()
|
||||
|
||||
Go( &PAD_TOOL::PlacePad, PCB_ACTIONS::placePad.MakeEvent() );
|
||||
Go( &PAD_TOOL::EnumeratePads, PCB_ACTIONS::enumeratePads.MakeEvent() );
|
||||
Go( &PAD_TOOL::PadTable, PCB_ACTIONS::padTable.MakeEvent() );
|
||||
|
||||
Go( &PAD_TOOL::EditPad, PCB_ACTIONS::explodePad.MakeEvent() );
|
||||
Go( &PAD_TOOL::EditPad, PCB_ACTIONS::recombinePad.MakeEvent() );
|
||||
|
@ -46,6 +46,8 @@ public:
|
||||
*/
|
||||
int EnumeratePads( const TOOL_EVENT& aEvent );
|
||||
|
||||
int PadTable( const TOOL_EVENT& aEvent );
|
||||
|
||||
/**
|
||||
* Place a pad in footprint editor.
|
||||
*/
|
||||
|
@ -899,6 +899,13 @@ TOOL_ACTION PCB_ACTIONS::footprintProperties( TOOL_ACTION_ARGS()
|
||||
.FriendlyName( _( "Footprint Properties..." ) )
|
||||
.Icon( BITMAPS::module_options ) );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::padTable( TOOL_ACTION_ARGS()
|
||||
.Name( "pcbnew.ModuleEditor.padTable" )
|
||||
.Scope( AS_GLOBAL )
|
||||
.FriendlyName( _( "Pad Table..." ) )
|
||||
.Tooltip( _( "Displays pad table for bulk editing of pads" ) )
|
||||
.Icon( BITMAPS::pin_table ) );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::checkFootprint( TOOL_ACTION_ARGS()
|
||||
.Name( "pcbnew.ModuleEditor.checkFootprint" )
|
||||
.Scope( AS_GLOBAL )
|
||||
|
@ -488,6 +488,7 @@ public:
|
||||
|
||||
static TOOL_ACTION footprintProperties;
|
||||
static TOOL_ACTION defaultPadProperties;
|
||||
static TOOL_ACTION padTable;
|
||||
|
||||
static TOOL_ACTION checkFootprint;
|
||||
|
||||
|
3
tools/custom_vcpkg_triplets/x64-windows.cmake
Normal file
3
tools/custom_vcpkg_triplets/x64-windows.cmake
Normal file
@ -0,0 +1,3 @@
|
||||
include("${VCPKG_ROOT_DIR}/triplets/x64-windows.cmake")
|
||||
|
||||
set(VCPKG_DISABLE_COMPILER_TRACKING ON)
|
Loading…
x
Reference in New Issue
Block a user