Compare commits
136 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2bc8c0ace5 | |||
| f439dfb6ea | |||
| 9fdc1257a1 | |||
| 95828ff2e2 | |||
| 98e55c0a04 | |||
| 2757d81231 | |||
| 985ceb365b | |||
| cdf04d5582 | |||
| a1ff9134f4 | |||
| cc0b51c81a | |||
| 4e34bdb621 | |||
| 6d96059917 | |||
| 99cfa1fad7 | |||
| b2a6f12645 | |||
| b33cf23bda | |||
| 5a36c3685e | |||
| 5991842ae4 | |||
| 6c0a30e2f3 | |||
| c0eee45876 | |||
| 6ebd970f88 | |||
| 5e3b74aee5 | |||
| 316087c468 | |||
| 1b1586696f | |||
| 339a349a58 | |||
| 1a161858fc | |||
| 12abcd6ece | |||
| 5e64fb1415 | |||
| 7616461e61 | |||
| 968406c6b5 | |||
| 5144186fca | |||
| c0fb041be6 | |||
| 45e15f2394 | |||
| f5b592e38c | |||
| 60a8eee515 | |||
| 38e09789e5 | |||
| f993e51fba | |||
| 7600f45d11 | |||
| 48d8c149a8 | |||
| 131115e19f | |||
| cd7cab9794 | |||
| 22bece0922 | |||
| 01cff24e4e | |||
| 948071183c | |||
| ee05b67599 | |||
| c07043e762 | |||
| bd9c37aa5f | |||
| 6e6a748320 | |||
| 61c0cac22d | |||
| 3c973a788d | |||
| 048436f0ef | |||
| 491e0cac6a | |||
| cf1d0a9667 | |||
| 3ae39f9614 | |||
| 45d9a58bc7 | |||
| 1a8d974520 | |||
| 8ea00c42d9 | |||
| be8750ad1c | |||
| 350d0323e1 | |||
| 2c7aee057a | |||
| fb6c89358b | |||
| d790e85fe4 | |||
| 7f08356a48 | |||
| 045633626c | |||
| 5de05312d5 | |||
| ecfd74c1be | |||
| cdeb539254 | |||
| 540c5d2b16 | |||
| 38886c998b | |||
| 46b3188737 | |||
| f663b42d77 | |||
| 9ac87132af | |||
| 8af64fb326 | |||
| be86e9f57f | |||
| 3253bd9a3d | |||
| 994dd570de | |||
| c171f5b1b0 | |||
| 36bbe733a8 | |||
| 3400b567b1 | |||
| 28d6c17e42 | |||
| 0df81f67ed | |||
| 30f08024b7 | |||
| d93364268b | |||
| 11531471c6 | |||
| 1626ba3f58 | |||
| 76479f40ef | |||
| 4c9e409df9 | |||
| b4b4f1f3ca | |||
| ed684cd92e | |||
| 3f99dae704 | |||
| 7e72a3c993 | |||
| 2960e9c1b4 | |||
| 0f5e12a535 | |||
| acf62122c8 | |||
| bf9db4d4f8 | |||
| e09212ccad | |||
| 390effe3c6 | |||
| eaafa5d8f0 | |||
| c558144c7b | |||
| b7713dbf0d | |||
| 9b21712ea0 | |||
| 6f7b0cb240 | |||
| ea1aed2fc9 | |||
| 88ad0e5a50 | |||
| 15ead17cea | |||
| 92356b4805 | |||
| cec810a452 | |||
| ec92def539 | |||
| 2dd04ea43a | |||
| d7a7ddd80e | |||
| 27676f4388 | |||
| 2f47857abc | |||
| ede21ed6ae | |||
| a09a3dfe68 | |||
| e083cbaf50 | |||
| 9d401b00d8 | |||
| 25e3b6c1bf | |||
| 2029fc4e8f | |||
| c9cc29593a | |||
| 42bd43407a | |||
| de05a513f3 | |||
| 554d82b2a4 | |||
| 3b3e86b968 | |||
| f6ca98061c | |||
| cca7f1dbda | |||
| 2cf4cb937f | |||
| c3b9c65fd6 | |||
| d9a1703bcc | |||
| a22c466639 | |||
| 9a2f83537d | |||
| f136f3d7ee | |||
| 61d4a5bfbe | |||
| 6289a82a18 | |||
| 6ca2f6a6e1 | |||
| 2ff3fac7b3 | |||
| 08452433e8 | |||
| 39b9b3e570 |
@@ -54,6 +54,15 @@ common/pcb_keywords.cpp
|
||||
include/pcb_lexer.h
|
||||
fp-info-cache
|
||||
|
||||
# .md generated files
|
||||
eeschema/dialogs/dialog_bom_help_md.h
|
||||
pcb_calculator/attenuators/bridget_tee_formula.h
|
||||
pcb_calculator/attenuators/pi_formula.h
|
||||
pcb_calculator/attenuators/splitter_formula.h
|
||||
pcb_calculator/attenuators/tee_formula.h
|
||||
pcb_calculator/eserie_help.h
|
||||
pcb_calculator/tracks_width_versus_current_formula.h
|
||||
|
||||
# demo project auxiliary files
|
||||
demos/**/*-bak
|
||||
demos/**/_autosave-*
|
||||
|
||||
@@ -43,3 +43,4 @@ include:
|
||||
- local: '/.gitlab/Windows-CI.yml'
|
||||
- local: '/.gitlab/coverity.yml'
|
||||
- local: '/.gitlab/linux-metadata-validate.yml'
|
||||
- local: '/.gitlab/doxygen.yml'
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
build_doxygen_docker:
|
||||
image: docker:stable
|
||||
services:
|
||||
- docker:dind
|
||||
stage: build
|
||||
tags:
|
||||
- docker
|
||||
before_script:
|
||||
- docker info
|
||||
- docker login -u gitlab-ci-token -p "$CI_BUILD_TOKEN" "$CI_REGISTRY"
|
||||
script:
|
||||
- docker build -t "${CI_REGISTRY_IMAGE}/doxygen:$CI_COMMIT_BRANCH" -f ./Documentation/doxygen.Dockerfile .
|
||||
- docker push "${CI_REGISTRY_IMAGE}/doxygen:$CI_COMMIT_BRANCH"
|
||||
only:
|
||||
refs:
|
||||
- schedules
|
||||
variables:
|
||||
- $SCHEDULED_JOB_NAME == "doxygen"
|
||||
@@ -27,6 +27,7 @@
|
||||
* 3d models that come in the original data from the files without any transformations.
|
||||
*/
|
||||
|
||||
#include <gal/opengl/kiglew.h> // Must be included first
|
||||
#include <iostream>
|
||||
#include "3d_rendering/opengl/3d_model.h"
|
||||
#include "eda_3d_model_viewer.h"
|
||||
@@ -38,6 +39,7 @@
|
||||
#include <settings/common_settings.h>
|
||||
#include <pgm_base.h>
|
||||
#include <gal/dpi_scaling.h>
|
||||
#include <macros.h>
|
||||
|
||||
/**
|
||||
* Scale conversion from 3d model units to pcb units
|
||||
@@ -182,6 +184,20 @@ void EDA_3D_MODEL_VIEWER::Clear3DModel()
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::ogl_initialize()
|
||||
{
|
||||
const GLenum err = glewInit();
|
||||
|
||||
if( GLEW_OK != err )
|
||||
{
|
||||
const wxString msgError = (const char*) glewGetErrorString( err );
|
||||
|
||||
wxLogMessage( msgError );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::ogl_initialize Using GLEW version %s" ),
|
||||
FROM_UTF8( (char*) glewGetString( GLEW_VERSION ) ) );
|
||||
}
|
||||
|
||||
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
|
||||
glHint( GL_LINE_SMOOTH_HINT, GL_NICEST );
|
||||
glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );
|
||||
|
||||
@@ -38,8 +38,8 @@ macro( create_git_version_header _git_src_path )
|
||||
${GIT_EXECUTABLE} describe --dirty
|
||||
WORKING_DIRECTORY ${_git_src_path}
|
||||
OUTPUT_VARIABLE _git_DESCRIBE
|
||||
ERROR_VARIABLE _git_log_error
|
||||
RESULT_VARIABLE _git_log_result
|
||||
ERROR_VARIABLE _git_describe_error
|
||||
RESULT_VARIABLE _git_describe_result
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
execute_process(
|
||||
@@ -47,8 +47,8 @@ macro( create_git_version_header _git_src_path )
|
||||
${GIT_EXECUTABLE} rev-list --count --first-parent HEAD
|
||||
WORKING_DIRECTORY ${_git_src_path}
|
||||
OUTPUT_VARIABLE _git_REV_COUNT
|
||||
ERROR_VARIABLE _git_log_error
|
||||
RESULT_VARIABLE _git_log_result
|
||||
ERROR_VARIABLE _git_rev_count_error
|
||||
RESULT_VARIABLE _git_rev_count_result
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
set( ENV{LC_ALL} ${_Git_SAVED_LC_ALL} )
|
||||
@@ -56,11 +56,11 @@ macro( create_git_version_header _git_src_path )
|
||||
|
||||
# Check to make sure 'git' command did not fail. Otherwise fallback
|
||||
# to KiCadVersion.cmake as the revision level.
|
||||
if( _git_DESCRIBE )
|
||||
if( _git_describe_result EQUAL 0 )
|
||||
set( KICAD_VERSION "(${_git_DESCRIBE})" )
|
||||
endif()
|
||||
|
||||
if( _git_REV_COUNT )
|
||||
if( _git_rev_count_result EQUAL 0 )
|
||||
set( KICAD_GIT_REV "${_git_REV_COUNT}" )
|
||||
|
||||
# Sanity check
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# This program source code file is part of KICAD, a free EDA CAD application.
|
||||
#
|
||||
# Copyright (C) 2016 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
# Copyright (C) 2016-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
# Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@@ -37,7 +37,7 @@
|
||||
# KiCad.
|
||||
#
|
||||
# Note: This version string should follow the semantic versioning system
|
||||
set( KICAD_SEMANTIC_VERSION "6.0.9" )
|
||||
set( KICAD_SEMANTIC_VERSION "6.0.11-unknown" )
|
||||
|
||||
# Default the version to the semantic version.
|
||||
# This is overridden by the git repository tag though (if using git)
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
FROM registry.gitlab.com/kicad/kicad-ci/source_containers/master/ubuntu:22.04 as build-doxygen-env
|
||||
USER root
|
||||
|
||||
WORKDIR /src
|
||||
COPY . ./
|
||||
|
||||
RUN ls
|
||||
RUN mkdir build && cd build
|
||||
|
||||
WORKDIR /src/build
|
||||
|
||||
RUN cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DKICAD_USE_OCC=ON \
|
||||
-DKICAD_SCRIPTING_WXPYTHON=ON \
|
||||
-DKICAD_SPICE=ON
|
||||
RUN make doxygen-docs
|
||||
RUN make doxygen-python
|
||||
|
||||
|
||||
FROM scratch as output-image
|
||||
|
||||
COPY --from=build-doxygen-env /src/Documentation/doxygen/html /doxygen-docs_html
|
||||
COPY --from=build-doxygen-env /src/build/pcbnew/doxygen-python/html /doxygen-python_html
|
||||
@@ -0,0 +1,6 @@
|
||||
doxygen.Dockerfile.dockerignore.git
|
||||
.gitlab
|
||||
.github
|
||||
.idea
|
||||
.vs
|
||||
build
|
||||
@@ -82,13 +82,6 @@ static const wxChar DRCEpsilon[] = wxT( "DRCEpsilon" );
|
||||
*/
|
||||
static const wxChar HoleWallThickness[] = wxT( "HoleWallPlatingThickness" );
|
||||
|
||||
/**
|
||||
* Testing mode for new connectivity algorithm. Setting this to on will cause all modifications
|
||||
* to the netlist to be recalculated on the fly. This may be slower than the standard process
|
||||
* at the moment
|
||||
*/
|
||||
static const wxChar RealtimeConnectivity[] = wxT( "RealtimeConnectivity" );
|
||||
|
||||
/**
|
||||
* Configure the coroutine stack size in bytes. This should be allocated in multiples of
|
||||
* the system page size (n*4096 is generally safe)
|
||||
@@ -260,7 +253,6 @@ ADVANCED_CFG::ADVANCED_CFG()
|
||||
|
||||
// Init defaults - this is done in case the config doesn't exist,
|
||||
// then the values will remain as set here.
|
||||
m_RealTimeConnectivity = true;
|
||||
m_CoroutineStackSize = AC_STACK::default_stack;
|
||||
m_ShowRouterDebugGraphics = false;
|
||||
m_DrawArcAccuracy = 10.0;
|
||||
@@ -333,9 +325,6 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg )
|
||||
{
|
||||
std::vector<PARAM_CFG*> configParams;
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::RealtimeConnectivity,
|
||||
&m_RealTimeConnectivity, m_RealTimeConnectivity ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::ExtraFillMargin,
|
||||
&m_ExtraClearance, m_ExtraClearance, 0.0, 1.0 ) );
|
||||
|
||||
|
||||
@@ -121,6 +121,13 @@ wxBitmap KiBitmap( const BITMAP_OPAQUE* aBitmap )
|
||||
|
||||
int KiIconScale( wxWindow* aWindow )
|
||||
{
|
||||
#if defined( __WXMSW__) && wxCHECK_VERSION( 3, 1, 6 )
|
||||
// Basically don't try and scale within kicad and let wx do its thing
|
||||
// with wx introducing bitmap bundles, it will auto scale automatically with dpi
|
||||
// the issue is, none of the scaling factors have any tie to system scaling
|
||||
// this means wx is actually going to scale again causing even more distorted icons
|
||||
return 4;
|
||||
#else
|
||||
const int vert_size = aWindow->ConvertDialogToPixels( wxSize( 0, 8 ) ).y;
|
||||
|
||||
// Autoscale won't exceed unity until the system has quite high resolution,
|
||||
@@ -131,6 +138,7 @@ int KiIconScale( wxWindow* aWindow )
|
||||
else if( vert_size > 29 ) return 7;
|
||||
else if( vert_size > 24 ) return 6;
|
||||
else return 4;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -465,7 +465,10 @@ bool KIWAY::PlayerClose( FRAME_T aFrameType, bool doForce )
|
||||
return true;
|
||||
|
||||
if( frame->NonUserClose( doForce ) )
|
||||
{
|
||||
m_playerFrameId[aFrameType] = wxID_NONE;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -249,6 +249,7 @@ COMPILER::~COMPILER()
|
||||
if( m_tree )
|
||||
{
|
||||
freeTree( m_tree );
|
||||
m_tree = nullptr;
|
||||
}
|
||||
|
||||
// Allow explicit call to destructor
|
||||
@@ -693,6 +694,7 @@ void COMPILER::freeTree( LIBEVAL::TREE_NODE *tree )
|
||||
freeTree( tree->leaf[1] );
|
||||
|
||||
delete tree->uop;
|
||||
tree->uop = nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -1006,10 +1008,13 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.Printf( _( "Missing units for '%s'| (%s)" ),
|
||||
*node->value.str,
|
||||
m_unitResolver->GetSupportedUnitsMessage() );
|
||||
reportError( CST_CODEGEN, msg, node->srcPos );
|
||||
if( !m_unitResolver->GetSupportedUnitsMessage().empty() )
|
||||
{
|
||||
msg.Printf( _( "Missing units for '%s'| (%s)" ),
|
||||
*node->value.str,
|
||||
m_unitResolver->GetSupportedUnitsMessage() );
|
||||
reportError( CST_CODEGEN, msg, node->srcPos );
|
||||
}
|
||||
|
||||
value = DoubleValueFromString( EDA_UNITS::UNSCALED, *node->value.str );
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <macros.h>
|
||||
#include <trigo.h>
|
||||
|
||||
#include <basic_gal.h>
|
||||
#include <plotters/plotters_pslike.h>
|
||||
|
||||
|
||||
@@ -837,6 +838,7 @@ void PDF_PLOTTER::Text( const wxPoint& aPos,
|
||||
// be pixel-accurate, but it doesn't matter for searching.
|
||||
int render_mode = 3; // invisible
|
||||
|
||||
wxPoint pos( aPos );
|
||||
const char *fontname = aItalic ? ( aBold ? "/KicadFontBI" : "/KicadFontI" )
|
||||
: ( aBold ? "/KicadFontB" : "/KicadFont" );
|
||||
|
||||
@@ -844,28 +846,64 @@ void PDF_PLOTTER::Text( const wxPoint& aPos,
|
||||
double ctm_a, ctm_b, ctm_c, ctm_d, ctm_e, ctm_f;
|
||||
double wideningFactor, heightFactor;
|
||||
|
||||
computeTextParameters( aPos, aText, aOrient, aSize, m_plotMirror, aH_justify,
|
||||
aV_justify, aWidth, aItalic, aBold,
|
||||
&wideningFactor, &ctm_a, &ctm_b, &ctm_c,
|
||||
&ctm_d, &ctm_e, &ctm_f, &heightFactor );
|
||||
|
||||
SetColor( aColor );
|
||||
SetCurrentLineWidth( aWidth, aData );
|
||||
|
||||
/* We use the full CTM instead of the text matrix because the same
|
||||
coordinate system will be used for the overlining. Also the %f
|
||||
for the trig part of the matrix to avoid %g going in exponential
|
||||
format (which is not supported) */
|
||||
fprintf( workFile, "q %f %f %f %f %g %g cm BT %s %g Tf %d Tr %g Tz ",
|
||||
ctm_a, ctm_b, ctm_c, ctm_d, ctm_e, ctm_f,
|
||||
fontname, heightFactor, render_mode, wideningFactor * 100 );
|
||||
const auto& font = basic_gal.GetStrokeFont();
|
||||
VECTOR2D fontSize( aSize.x, aSize.y );
|
||||
double penWidth( aWidth );
|
||||
VECTOR2D extents = font.ComputeStringBoundaryLimits( aText, fontSize, penWidth );
|
||||
|
||||
// The text must be escaped correctly
|
||||
std:: string txt_pdf = encodeStringForPlotter( aText );
|
||||
fprintf( workFile, "%s Tj ET\n", txt_pdf.c_str() );
|
||||
wxPoint box_x( KiROUND( extents.x ), 0 );
|
||||
wxPoint box_y( 0, KiROUND( extents.y ) );
|
||||
|
||||
// Restore the CTM
|
||||
fputs( "Q\n", workFile );
|
||||
RotatePoint( &box_x, aOrient );
|
||||
RotatePoint( &box_y, aOrient );
|
||||
|
||||
if( aH_justify == GR_TEXT_HJUSTIFY_CENTER )
|
||||
pos -= box_x / 2;
|
||||
else if( aH_justify == GR_TEXT_HJUSTIFY_RIGHT )
|
||||
pos -= box_x;
|
||||
|
||||
if( aV_justify == GR_TEXT_VJUSTIFY_CENTER )
|
||||
pos += box_y / 2;
|
||||
else if( aV_justify == GR_TEXT_VJUSTIFY_TOP )
|
||||
pos += box_y;
|
||||
|
||||
wxStringTokenizer str_tok( aText, " ", wxTOKEN_RET_DELIMS );
|
||||
|
||||
while( str_tok.HasMoreTokens() )
|
||||
{
|
||||
wxString word = str_tok.GetNextToken();
|
||||
|
||||
computeTextParameters( pos, word, aOrient, aSize, m_plotMirror, GR_TEXT_HJUSTIFY_LEFT,
|
||||
GR_TEXT_VJUSTIFY_BOTTOM, aWidth, aItalic, aBold, &wideningFactor, &ctm_a,
|
||||
&ctm_b, &ctm_c, &ctm_d, &ctm_e, &ctm_f, &heightFactor );
|
||||
|
||||
// Extract the changed width and rotate by the orientation to get the offset for the
|
||||
// next word
|
||||
extents = font.ComputeStringBoundaryLimits( word, fontSize, penWidth );
|
||||
wxPoint bbox( KiROUND( extents.x ), 0 );
|
||||
RotatePoint( &bbox, aOrient );
|
||||
pos += bbox;
|
||||
|
||||
// Don't try to output a blank string
|
||||
if( word.Trim( false ).Trim( true ).empty() )
|
||||
continue;
|
||||
|
||||
/* We use the full CTM instead of the text matrix because the same
|
||||
coordinate system will be used for the overlining. Also the %f
|
||||
for the trig part of the matrix to avoid %g going in exponential
|
||||
format (which is not supported) */
|
||||
fprintf( workFile, "q %f %f %f %f %g %g cm BT %s %g Tf %d Tr %g Tz ",
|
||||
ctm_a, ctm_b, ctm_c, ctm_d, ctm_e, ctm_f,
|
||||
fontname, heightFactor, render_mode, wideningFactor * 100 );
|
||||
|
||||
std::string txt_pdf = encodeStringForPlotter( word );
|
||||
fprintf( workFile, "%s Tj ET\n", txt_pdf.c_str() );
|
||||
// Restore the CTM
|
||||
fputs( "Q\n", workFile );
|
||||
}
|
||||
|
||||
// Plot the stroked text (if requested)
|
||||
PLOTTER::Text( aPos, aColor, aText, aOrient, aSize, aH_justify, aV_justify, aWidth,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2015-2020 KiCad Developers, see AUTHORS.TXT for contributors.
|
||||
* Copyright (C) 2015-2022 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
|
||||
@@ -35,18 +35,9 @@ using namespace TFIELD_T;
|
||||
#define FOOTPRINT_CANONICAL "Footprint"
|
||||
#define DATASHEET_CANONICAL "Datasheet"
|
||||
|
||||
static std::mutex s_defaultFieldMutex;
|
||||
|
||||
const wxString TEMPLATE_FIELDNAME::GetDefaultFieldName( int aFieldNdx, bool aTranslate )
|
||||
const wxString TEMPLATE_FIELDNAME::GetDefaultFieldName( int aFieldNdx, bool aTranslateForHI )
|
||||
{
|
||||
static void* locale = nullptr;
|
||||
static wxString referenceDefault;
|
||||
static wxString valueDefault;
|
||||
static wxString footprintDefault;
|
||||
static wxString datasheetDefault;
|
||||
static wxString fieldDefault;
|
||||
|
||||
if( !aTranslate )
|
||||
if( !aTranslateForHI )
|
||||
{
|
||||
switch( aFieldNdx )
|
||||
{
|
||||
@@ -54,42 +45,20 @@ const wxString TEMPLATE_FIELDNAME::GetDefaultFieldName( int aFieldNdx, bool aTra
|
||||
case VALUE_FIELD: return VALUE_CANONICAL; // The symbol value
|
||||
case FOOTPRINT_FIELD: return FOOTPRINT_CANONICAL; // The footprint for use with Pcbnew
|
||||
case DATASHEET_FIELD: return DATASHEET_CANONICAL; // Link to a datasheet for symbol
|
||||
default: return wxString::Format( wxT( "Field%d" ), aFieldNdx );
|
||||
}
|
||||
}
|
||||
|
||||
// Mutex protection is needed so that multiple loader threads don't write to the static
|
||||
// variables at once
|
||||
std::lock_guard<std::mutex> lock( s_defaultFieldMutex );
|
||||
|
||||
// Fetching translations can take a surprising amount of time when loading libraries,
|
||||
// so only do it when necessary.
|
||||
if( Pgm().GetLocale() != locale )
|
||||
{
|
||||
referenceDefault = _( REFERENCE_CANONICAL );
|
||||
valueDefault = _( VALUE_CANONICAL );
|
||||
footprintDefault = _( FOOTPRINT_CANONICAL );
|
||||
datasheetDefault = _( DATASHEET_CANONICAL );
|
||||
fieldDefault = _( "Field%d" );
|
||||
locale = Pgm().GetLocale();
|
||||
}
|
||||
|
||||
// Fixed values for the mandatory fields
|
||||
switch( aFieldNdx )
|
||||
{
|
||||
case REFERENCE_FIELD: return referenceDefault; // The symbol reference, R1, C1, etc.
|
||||
case VALUE_FIELD: return valueDefault; // The symbol value
|
||||
case FOOTPRINT_FIELD: return footprintDefault; // The footprint for use with Pcbnew
|
||||
case DATASHEET_FIELD: return datasheetDefault; // Link to a datasheet for symbol
|
||||
default: return wxString::Format( fieldDefault, aFieldNdx );
|
||||
case REFERENCE_FIELD: return _( REFERENCE_CANONICAL ); // The symbol reference, R1, C1, etc.
|
||||
case VALUE_FIELD: return _( VALUE_CANONICAL ); // The symbol value
|
||||
case FOOTPRINT_FIELD: return _( FOOTPRINT_CANONICAL ); // The footprint for use with Pcbnew
|
||||
case DATASHEET_FIELD: return _( DATASHEET_CANONICAL ); // Link to a datasheet for symbol
|
||||
default: return wxString::Format( _( "Field%d" ), aFieldNdx );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#undef REFERENCE_CANONICAL
|
||||
#undef VALUE_CANONICAL
|
||||
#undef FOOTPRINT_CANONICAL
|
||||
#undef DATASHEET_CANONICAL
|
||||
|
||||
|
||||
void TEMPLATE_FIELDNAME::Format( OUTPUTFORMATTER* out, int nestLevel ) const
|
||||
{
|
||||
|
||||
@@ -91,6 +91,7 @@ void TITLE_BLOCK::GetContextualTextVars( wxArrayString* aVars )
|
||||
bool TITLE_BLOCK::TextVarResolver( wxString* aToken, const PROJECT* aProject ) const
|
||||
{
|
||||
bool tokenUpdated = false;
|
||||
wxString originalToken = *aToken;
|
||||
|
||||
if( aToken->IsSameAs( wxT( "ISSUE_DATE" ) ) )
|
||||
{
|
||||
@@ -146,7 +147,12 @@ bool TITLE_BLOCK::TextVarResolver( wxString* aToken, const PROJECT* aProject ) c
|
||||
|
||||
if( tokenUpdated )
|
||||
{
|
||||
*aToken = ExpandTextVars( *aToken, aProject );
|
||||
*aToken = ExpandTextVars( *aToken, aProject );
|
||||
|
||||
// This is the default fallback, so don't claim we resolved it
|
||||
if( *aToken == wxT( "${" ) + originalToken + wxT( "}" ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2020-2022 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
|
||||
@@ -117,8 +117,11 @@ bool TOOLS_HOLDER::IsCurrentTool( const TOOL_ACTION& aAction ) const
|
||||
|
||||
void TOOLS_HOLDER::ShowChangedLanguage()
|
||||
{
|
||||
if( !GetToolManager() )
|
||||
return;
|
||||
|
||||
std::string actionName = CurrentToolName();
|
||||
TOOL_ACTION* action = m_toolManager->GetActionManager()->FindAction( actionName );
|
||||
TOOL_ACTION* action = GetToolManager()->GetActionManager()->FindAction( actionName );
|
||||
|
||||
if( action )
|
||||
DisplayToolMsg( action->GetLabel() );
|
||||
|
||||
@@ -39,6 +39,7 @@ const wxChar* const kicadTraceCoroutineStack = wxT( "KICAD_COROUTINE_STACK" );
|
||||
const wxChar* const traceSchLibMem = wxT( "KICAD_SCH_LIB_MEM" );
|
||||
const wxChar* const traceFindItem = wxT( "KICAD_FIND_ITEM" );
|
||||
const wxChar* const traceSchLegacyPlugin = wxT( "KICAD_SCH_LEGACY_PLUGIN" );
|
||||
const wxChar* const traceSchPlugin = wxT( "KICAD_SCH_PLUGIN" );
|
||||
const wxChar* const traceGedaPcbPlugin = wxT( "KICAD_GEDA_PLUGIN" );
|
||||
const wxChar* const traceKicadPcbPlugin = wxT( "KICAD_PCB_PLUGIN" );
|
||||
const wxChar* const tracePrinting = wxT( "KICAD_PRINT" );
|
||||
|
||||
@@ -148,7 +148,7 @@ void VIEW_GROUP::ViewDraw( int aLayer, VIEW* aView ) const
|
||||
{
|
||||
int layer = layers[i];
|
||||
|
||||
if( IsZoneLayer( layer ) )
|
||||
if( IsZoneFillLayer( layer ) )
|
||||
layer = layer - LAYER_ZONE_START;
|
||||
|
||||
bool draw = aView->IsLayerVisible( layer );
|
||||
|
||||
@@ -353,7 +353,7 @@ void WX_VIEW_CONTROLS::onWheel( wxMouseEvent& aEvent )
|
||||
|
||||
// Refresh the zoom level and mouse position on message panel
|
||||
// (mouse position has not changed, only the zoom level has changed):
|
||||
refreshMouse();
|
||||
refreshMouse( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -371,7 +371,7 @@ void WX_VIEW_CONTROLS::onWheel( wxMouseEvent& aEvent )
|
||||
VECTOR2D delta( scrollX, scrollY );
|
||||
|
||||
m_view->SetCenter( m_view->GetCenter() + delta );
|
||||
refreshMouse();
|
||||
refreshMouse( true );
|
||||
}
|
||||
|
||||
// Do not skip this event, otherwise wxWidgets will fire
|
||||
@@ -545,7 +545,7 @@ void WX_VIEW_CONTROLS::onTimer( wxTimerEvent& aEvent )
|
||||
dir = m_view->ToWorld( dir, false );
|
||||
m_view->SetCenter( m_view->GetCenter() + dir );
|
||||
|
||||
refreshMouse();
|
||||
refreshMouse( true );
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -766,7 +766,9 @@ void WX_VIEW_CONTROLS::WarpCursor( const VECTOR2D& aPosition, bool aWorldCoordin
|
||||
KIPLATFORM::UI::WarpPointer( m_parentPanel, aPosition.x, aPosition.y );
|
||||
}
|
||||
|
||||
refreshMouse();
|
||||
// If we are not refreshing because of mouse movement, don't set the modifiers
|
||||
// because we are refreshing for keyboard movement, which uses the same modifiers for other actions
|
||||
refreshMouse( m_updateCursor );
|
||||
}
|
||||
|
||||
|
||||
@@ -894,7 +896,7 @@ void WX_VIEW_CONTROLS::handleCursorCapture( int x, int y )
|
||||
}
|
||||
|
||||
|
||||
void WX_VIEW_CONTROLS::refreshMouse()
|
||||
void WX_VIEW_CONTROLS::refreshMouse( bool aSetModifiers )
|
||||
{
|
||||
// Notify tools that the cursor position has changed in the world coordinates
|
||||
wxMouseEvent moveEvent( EVT_REFRESH_MOUSE );
|
||||
@@ -902,10 +904,13 @@ void WX_VIEW_CONTROLS::refreshMouse()
|
||||
moveEvent.SetX( msp.x );
|
||||
moveEvent.SetY( msp.y );
|
||||
|
||||
// Set the modifiers state
|
||||
moveEvent.SetControlDown( wxGetKeyState( WXK_CONTROL ) );
|
||||
moveEvent.SetShiftDown( wxGetKeyState( WXK_SHIFT ) );
|
||||
moveEvent.SetAltDown( wxGetKeyState( WXK_ALT ) );
|
||||
if( aSetModifiers )
|
||||
{
|
||||
// Set the modifiers state
|
||||
moveEvent.SetControlDown( wxGetKeyState( WXK_CONTROL ) );
|
||||
moveEvent.SetShiftDown( wxGetKeyState( WXK_SHIFT ) );
|
||||
moveEvent.SetAltDown( wxGetKeyState( WXK_ALT ) );
|
||||
}
|
||||
|
||||
m_cursorPos = GetClampedCoords( m_view->ToWorld( VECTOR2D( msp.x, msp.y ) ) );
|
||||
wxPostEvent( m_parentPanel, moveEvent );
|
||||
@@ -954,7 +959,7 @@ void WX_VIEW_CONTROLS::UpdateScrollbars()
|
||||
// Trigger a mouse refresh to get the canvas update in GTK (re-draws the scrollbars).
|
||||
// Note that this causes an infinite loop on OSX and Windows (in certain cases) as it
|
||||
// generates a paint event.
|
||||
refreshMouse();
|
||||
refreshMouse( false );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ BITMAP_TOGGLE::BITMAP_TOGGLE( wxWindow *aParent, wxWindowID aId, const wxBitmap&
|
||||
|
||||
const wxBitmap& bitmap = aChecked ? m_checked_bitmap : m_unchecked_bitmap;
|
||||
|
||||
m_bitmap = new wxStaticBitmap( this, aId, bitmap, wxDefaultPosition, bitmap.GetSize() );
|
||||
m_bitmap = new wxStaticBitmap( this, aId, bitmap, wxDefaultPosition );
|
||||
|
||||
sizer->Add( m_bitmap, 0, 0 );
|
||||
|
||||
|
||||
@@ -437,7 +437,6 @@ void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId, int
|
||||
}
|
||||
|
||||
int LastReferenceNumber = 0;
|
||||
int NumberOfUnits, Unit;
|
||||
|
||||
/* calculate index of the first symbol with the same reference prefix
|
||||
* than the current symbol. All symbols having the same reference
|
||||
@@ -518,9 +517,6 @@ void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId, int
|
||||
continue;
|
||||
}
|
||||
|
||||
// Annotation of multi-unit parts ( n units per part ) (complex case)
|
||||
NumberOfUnits = ref_unit.GetLibPart()->GetUnitCount();
|
||||
|
||||
// If this symbol is in aLockedUnitMap, copy the annotation to all
|
||||
// symbols that are not it
|
||||
if( lockedList != nullptr )
|
||||
|
||||
+151
-157
@@ -410,9 +410,6 @@ CONNECTION_SUBGRAPH::PRIORITY CONNECTION_SUBGRAPH::GetDriverPriority( SCH_ITEM*
|
||||
}
|
||||
|
||||
|
||||
bool CONNECTION_GRAPH::m_allowRealTime = true;
|
||||
|
||||
|
||||
void CONNECTION_GRAPH::Reset()
|
||||
{
|
||||
for( auto& subgraph : m_subgraphs )
|
||||
@@ -481,17 +478,6 @@ void CONNECTION_GRAPH::Recalculate( const SCH_SHEET_LIST& aSheetList, bool aUnco
|
||||
|
||||
if( wxLog::IsAllowedTraceMask( ConnProfileMask ) )
|
||||
recalc_time.Show();
|
||||
|
||||
#ifndef DEBUG
|
||||
// Pressure relief valve for release builds
|
||||
const double max_recalc_time_msecs = 250.;
|
||||
|
||||
if( m_allowRealTime && ADVANCED_CFG::GetCfg().m_RealTimeConnectivity &&
|
||||
recalc_time.msecs() > max_recalc_time_msecs )
|
||||
{
|
||||
m_allowRealTime = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -2205,6 +2191,31 @@ CONNECTION_SUBGRAPH* CONNECTION_GRAPH::FindSubgraphByName( const wxString& aNetN
|
||||
}
|
||||
|
||||
|
||||
wxString CONNECTION_GRAPH::GetResolvedSubgraphName( const CONNECTION_SUBGRAPH* aSubGraph ) const
|
||||
{
|
||||
wxString retval = aSubGraph->GetNetName();
|
||||
bool found = false;
|
||||
|
||||
// This is a hacky way to find the true subgraph net name (why do we not store it?)
|
||||
// TODO: Remove once the actual netname of the subgraph is stored with the subgraph
|
||||
|
||||
for( auto it = m_net_name_to_subgraphs_map.begin(); it != m_net_name_to_subgraphs_map.end() && !found; ++it )
|
||||
{
|
||||
for( CONNECTION_SUBGRAPH* graph : it->second )
|
||||
{
|
||||
if( graph == aSubGraph )
|
||||
{
|
||||
retval = it->first;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
CONNECTION_SUBGRAPH* CONNECTION_GRAPH::FindFirstSubgraphByName( const wxString& aNetName )
|
||||
{
|
||||
auto it = m_net_name_to_subgraphs_map.find( aNetName );
|
||||
@@ -2630,68 +2641,96 @@ bool CONNECTION_GRAPH::ercCheckBusToBusEntryConflicts( const CONNECTION_SUBGRAPH
|
||||
bool CONNECTION_GRAPH::ercCheckNoConnects( const CONNECTION_SUBGRAPH* aSubgraph )
|
||||
{
|
||||
ERC_SETTINGS& settings = m_schematic->ErcSettings();
|
||||
wxString msg;
|
||||
const SCH_SHEET_PATH& sheet = aSubgraph->m_sheet;
|
||||
SCH_SCREEN* screen = sheet.LastScreen();
|
||||
bool ok = true;
|
||||
SCH_PIN* pin = nullptr;
|
||||
|
||||
if( aSubgraph->m_no_connect != nullptr )
|
||||
std::set<SCH_PIN*> unique_pins;
|
||||
std::set<SCH_TEXT*> unique_labels;
|
||||
|
||||
wxString netName = GetResolvedSubgraphName( aSubgraph );
|
||||
|
||||
auto process_subgraph = [&]( const CONNECTION_SUBGRAPH* aProcessGraph )
|
||||
{
|
||||
bool has_invalid_items = false;
|
||||
bool has_other_items = false;
|
||||
SCH_PIN* pin = nullptr;
|
||||
std::vector<SCH_ITEM*> invalid_items;
|
||||
wxPoint noConnectPos = aSubgraph->m_no_connect->GetPosition();
|
||||
double minDist = 0;
|
||||
// Any subgraph that contains a no-connect should not
|
||||
// more than one pin (which would indicate it is connected
|
||||
|
||||
// Any subgraph that contains both a pin and a no-connect should not
|
||||
// contain any other driving items.
|
||||
|
||||
for( SCH_ITEM* item : aSubgraph->m_items )
|
||||
for( SCH_ITEM* item : aProcessGraph->m_items )
|
||||
{
|
||||
switch( item->Type() )
|
||||
{
|
||||
case SCH_PIN_T:
|
||||
{
|
||||
SCH_PIN* candidate = static_cast<SCH_PIN*>( item );
|
||||
double dist = VECTOR2I( candidate->GetTransformedPosition() - noConnectPos )
|
||||
.SquaredEuclideanNorm();
|
||||
SCH_PIN* test_pin = static_cast<SCH_PIN*>( item );
|
||||
|
||||
if( !pin || dist < minDist )
|
||||
// Only link NC to pin on the current subgraph being checked
|
||||
if( aProcessGraph == aSubgraph )
|
||||
pin = test_pin;
|
||||
|
||||
if( std::none_of( unique_pins.begin(), unique_pins.end(),
|
||||
[test_pin]( SCH_PIN* aPin )
|
||||
{
|
||||
return test_pin->IsStacked( aPin );
|
||||
}
|
||||
) )
|
||||
{
|
||||
pin = candidate;
|
||||
minDist = dist;
|
||||
unique_pins.insert( test_pin );
|
||||
}
|
||||
|
||||
has_invalid_items |= has_other_items;
|
||||
has_other_items = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case SCH_LINE_T:
|
||||
case SCH_JUNCTION_T:
|
||||
case SCH_NO_CONNECT_T:
|
||||
break;
|
||||
|
||||
case SCH_LABEL_T:
|
||||
case SCH_GLOBAL_LABEL_T:
|
||||
case SCH_HIER_LABEL_T:
|
||||
unique_labels.insert( static_cast<SCH_TEXT*>( item ) );
|
||||
KI_FALLTHROUGH;
|
||||
default:
|
||||
has_invalid_items = true;
|
||||
has_other_items = true;
|
||||
invalid_items.push_back( item );
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if( pin && has_invalid_items && settings.IsTestEnabled( ERCE_NOCONNECT_CONNECTED ) )
|
||||
auto it = m_net_name_to_subgraphs_map.find( netName );
|
||||
|
||||
if( it != m_net_name_to_subgraphs_map.end() )
|
||||
{
|
||||
for( const CONNECTION_SUBGRAPH* subgraph : it->second )
|
||||
{
|
||||
process_subgraph( subgraph );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
process_subgraph( aSubgraph );
|
||||
}
|
||||
|
||||
if( aSubgraph->m_no_connect != nullptr )
|
||||
{
|
||||
if( unique_pins.size() > 1 && settings.IsTestEnabled( ERCE_NOCONNECT_CONNECTED ) )
|
||||
{
|
||||
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_NOCONNECT_CONNECTED );
|
||||
ercItem->SetItems( pin );
|
||||
wxPoint pos;
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, pin->GetTransformedPosition() );
|
||||
if( pin )
|
||||
{
|
||||
ercItem->SetItems( pin, aSubgraph->m_no_connect );
|
||||
pos = pin->GetTransformedPosition();
|
||||
}
|
||||
else
|
||||
{
|
||||
ercItem->SetItems( aSubgraph->m_no_connect );
|
||||
pos = aSubgraph->m_no_connect->GetPosition();
|
||||
}
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, pos );
|
||||
screen->Append( marker );
|
||||
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if( !has_other_items && settings.IsTestEnabled( ERCE_NOCONNECT_NOT_CONNECTED ) )
|
||||
if( unique_pins.empty() && unique_labels.empty() && settings.IsTestEnabled( ERCE_NOCONNECT_NOT_CONNECTED ) )
|
||||
{
|
||||
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_NOCONNECT_NOT_CONNECTED );
|
||||
ercItem->SetItems( aSubgraph->m_no_connect );
|
||||
@@ -2719,12 +2758,11 @@ bool CONNECTION_GRAPH::ercCheckNoConnects( const CONNECTION_SUBGRAPH* aSubgraph
|
||||
// Stacked pins do not count as other connections but non-stacked pins do
|
||||
if( !has_other_connections && !pins.empty() )
|
||||
{
|
||||
SCH_PIN* pin = static_cast<SCH_PIN*>( item );
|
||||
SCH_PIN* test_pin = static_cast<SCH_PIN*>( item );
|
||||
|
||||
for( SCH_PIN* other_pin : pins )
|
||||
{
|
||||
if( other_pin->GetParent() != pin->GetParent()
|
||||
|| other_pin->GetPosition() != pin->GetPosition() )
|
||||
if( !test_pin->IsStacked( other_pin ) )
|
||||
{
|
||||
has_other_connections = true;
|
||||
break;
|
||||
@@ -2746,7 +2784,17 @@ bool CONNECTION_GRAPH::ercCheckNoConnects( const CONNECTION_SUBGRAPH* aSubgraph
|
||||
}
|
||||
|
||||
// For many checks, we can just use the first pin
|
||||
SCH_PIN* pin = pins.empty() ? nullptr : pins[0];
|
||||
pin = pins.empty() ? nullptr : pins[0];
|
||||
|
||||
// But if there is a power pin, it might be connected elsewhere
|
||||
for( SCH_PIN* test_pin : pins )
|
||||
{
|
||||
if( test_pin->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN )
|
||||
{
|
||||
pin = test_pin;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if invisible power input pins connect to anything else via net name,
|
||||
// but not for power symbols as the ones in the standard library all have invisible pins
|
||||
@@ -2868,9 +2916,10 @@ bool CONNECTION_GRAPH::ercCheckLabels( const CONNECTION_SUBGRAPH* aSubgraph )
|
||||
if( aSubgraph->m_driver_connection->IsBus() )
|
||||
return true;
|
||||
|
||||
ERC_SETTINGS& settings = m_schematic->ErcSettings();
|
||||
bool ok = true;
|
||||
int pinCount = 0;
|
||||
ERC_SETTINGS& settings = m_schematic->ErcSettings();
|
||||
bool ok = true;
|
||||
int pinCount = 0;
|
||||
bool has_nc = !!aSubgraph->m_no_connect;
|
||||
|
||||
std::map<KICAD_T, std::vector<SCH_TEXT*>> label_map;
|
||||
|
||||
@@ -2878,22 +2927,9 @@ bool CONNECTION_GRAPH::ercCheckLabels( const CONNECTION_SUBGRAPH* aSubgraph )
|
||||
auto hasPins =
|
||||
[]( const CONNECTION_SUBGRAPH* aLocSubgraph ) -> int
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
for( const SCH_ITEM* item : aLocSubgraph->m_items )
|
||||
{
|
||||
switch( item->Type() )
|
||||
{
|
||||
case SCH_PIN_T:
|
||||
case SCH_SHEET_PIN_T:
|
||||
++retval;
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
return
|
||||
std::count_if( aLocSubgraph->m_items.begin(), aLocSubgraph->m_items.end(), []( const SCH_ITEM* item )
|
||||
{ return item->Type() == SCH_PIN_T; } );
|
||||
};
|
||||
|
||||
auto reportError = [&]( SCH_TEXT* aText, int errCode )
|
||||
@@ -2934,11 +2970,6 @@ bool CONNECTION_GRAPH::ercCheckLabels( const CONNECTION_SUBGRAPH* aSubgraph )
|
||||
break;
|
||||
}
|
||||
|
||||
// If this subgraph has a no-connect, do not continue processing as we do not
|
||||
// submit no-connect errors for nets explicitly designated as no-connect
|
||||
case SCH_NO_CONNECT_T:
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -2947,105 +2978,68 @@ bool CONNECTION_GRAPH::ercCheckLabels( const CONNECTION_SUBGRAPH* aSubgraph )
|
||||
if( label_map.empty() )
|
||||
return true;
|
||||
|
||||
wxCHECK_MSG( m_schematic, true, wxT( "Null m_schematic in CONNECTION_GRAPH::ercCheckLabels" ) );
|
||||
wxString netName = GetResolvedSubgraphName( aSubgraph );
|
||||
|
||||
wxCHECK_MSG( m_schematic, true, "Null m_schematic in CONNECTION_GRAPH::ercCheckLabels" );
|
||||
|
||||
// Labels that have multiple pins connected are not dangling (may be used for naming segments)
|
||||
// so leave them without errors here
|
||||
if( pinCount > 1 )
|
||||
return true;
|
||||
|
||||
for( const auto& label_pair : label_map )
|
||||
for( auto label_el : label_map )
|
||||
{
|
||||
const KICAD_T type = label_pair.first;
|
||||
std::vector<SCH_TEXT*> label_vec = label_pair.second;
|
||||
KICAD_T type = label_el.first;
|
||||
std::vector<SCH_TEXT*>& label_vec = label_el.second;
|
||||
|
||||
switch( type )
|
||||
{
|
||||
case SCH_GLOBAL_LABEL_T:
|
||||
if( !settings.IsTestEnabled( ERCE_GLOBLABEL ) )
|
||||
break;
|
||||
|
||||
for( SCH_TEXT* text : label_vec )
|
||||
{
|
||||
wxString name = EscapeString( text->GetShownText(), CTX_NETNAME );
|
||||
int allPins = pinCount;
|
||||
|
||||
// If the global label is connected to a subgraph but is not the driver
|
||||
// then there is a driver conflict somewhere that is handled by a different
|
||||
// ERC check. Here, we are just looking for unconnected elements
|
||||
if( name != aSubgraph->m_driver_connection->Name() )
|
||||
continue;
|
||||
|
||||
// Global labels are connected if there is another instance of
|
||||
// their name in the circuit
|
||||
auto it = m_net_name_to_subgraphs_map.find( name );
|
||||
|
||||
for( const CONNECTION_SUBGRAPH* neighbor : it->second )
|
||||
{
|
||||
if( neighbor == aSubgraph )
|
||||
continue;
|
||||
|
||||
allPins += hasPins( neighbor );
|
||||
}
|
||||
|
||||
if( allPins < 2 )
|
||||
{
|
||||
reportError( text, ERCE_GLOBLABEL );
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case SCH_HIER_LABEL_T:
|
||||
if( !settings.IsTestEnabled( ERCE_LABEL_NOT_CONNECTED ) )
|
||||
break;
|
||||
|
||||
for( SCH_TEXT* text : label_vec )
|
||||
{
|
||||
if( !aSubgraph->m_hier_parent
|
||||
|| ( !aSubgraph->m_hier_parent->m_strong_driver
|
||||
&& aSubgraph->m_hier_parent->m_drivers.size() <= 1 ) )
|
||||
{
|
||||
reportError( text, ERCE_LABEL_NOT_CONNECTED );
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case SCH_LABEL_T:
|
||||
|
||||
if( !settings.IsTestEnabled( ERCE_LABEL_NOT_CONNECTED ) )
|
||||
break;
|
||||
|
||||
for( SCH_TEXT* text : label_vec )
|
||||
{
|
||||
int allPins = pinCount;
|
||||
wxString name = EscapeString( text->GetShownText(), CTX_NETNAME );
|
||||
|
||||
auto pair = std::make_pair( aSubgraph->m_sheet, name );
|
||||
auto it = m_local_label_cache.find( pair );
|
||||
|
||||
if( it == m_local_label_cache.end() )
|
||||
continue;
|
||||
|
||||
for( const CONNECTION_SUBGRAPH* neighbor : it->second )
|
||||
{
|
||||
if( neighbor == aSubgraph )
|
||||
continue;
|
||||
|
||||
allPins += hasPins( neighbor );
|
||||
}
|
||||
|
||||
if( allPins < 2 )
|
||||
{
|
||||
reportError( text, ERCE_LABEL_NOT_CONNECTED );
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
|
||||
break;
|
||||
default:
|
||||
if( !settings.IsTestEnabled( ERCE_LABEL_NOT_CONNECTED ) )
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
for( SCH_TEXT* text : label_vec )
|
||||
{
|
||||
int allPins = pinCount;
|
||||
|
||||
auto net_it = m_net_name_to_subgraphs_map.find( netName );
|
||||
|
||||
if( net_it != m_net_name_to_subgraphs_map.end() )
|
||||
{
|
||||
for( const CONNECTION_SUBGRAPH* neighbor : net_it->second )
|
||||
{
|
||||
if( neighbor == aSubgraph )
|
||||
continue;
|
||||
|
||||
if( neighbor->m_no_connect )
|
||||
has_nc = true;
|
||||
|
||||
allPins += hasPins( neighbor );
|
||||
}
|
||||
}
|
||||
|
||||
if( allPins == 1 && !has_nc )
|
||||
{
|
||||
reportError( text,
|
||||
type == SCH_GLOBAL_LABEL_T ? ERCE_GLOBLABEL : ERCE_LABEL_NOT_CONNECTED );
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if( allPins == 0 )
|
||||
{
|
||||
reportError( text,
|
||||
type == SCH_GLOBAL_LABEL_T ? ERCE_GLOBLABEL : ERCE_LABEL_NOT_CONNECTED );
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ok;
|
||||
|
||||
@@ -324,6 +324,13 @@ public:
|
||||
|
||||
CONNECTION_SUBGRAPH* GetSubgraphForItem( SCH_ITEM* aItem );
|
||||
|
||||
/**
|
||||
* Returns the fully-resolved netname for a given subgraph
|
||||
* @param aSubGraph Reference to the subgraph
|
||||
* @return Netname string usable with m_net_name_to_subgraphs_map
|
||||
*/
|
||||
wxString GetResolvedSubgraphName( const CONNECTION_SUBGRAPH* aSubGraph ) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Updates the graphical connectivity between items (i.e. where they touch)
|
||||
@@ -530,10 +537,6 @@ private:
|
||||
*/
|
||||
int ercCheckHierSheets();
|
||||
|
||||
public:
|
||||
// TODO(JE) Remove this when pressure valve is removed
|
||||
static bool m_allowRealTime;
|
||||
|
||||
private:
|
||||
// All the sheets in the schematic (as long as we don't have partial updates)
|
||||
SCH_SHEET_LIST m_sheetList;
|
||||
|
||||
@@ -578,11 +578,6 @@ void SCH_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
|
||||
NETLIST_EXPORTER_KICAD exporter( &Schematic() );
|
||||
STRING_FORMATTER formatter;
|
||||
|
||||
// TODO remove once real-time connectivity is a given
|
||||
if( !ADVANCED_CFG::GetCfg().m_RealTimeConnectivity || !CONNECTION_GRAPH::m_allowRealTime )
|
||||
// Ensure the netlist data is up to date:
|
||||
RecalculateConnections( NO_CLEANUP );
|
||||
|
||||
exporter.Format( &formatter, GNL_ALL | GNL_OPT_KICAD );
|
||||
|
||||
payload = formatter.GetString();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2020-2021 CERN
|
||||
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2021-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Wayne Stambaugh <stambaughw@gmail.com>
|
||||
*
|
||||
@@ -25,14 +25,12 @@
|
||||
#include <bitmaps.h>
|
||||
#include <string_utils.h> // WildCompareString
|
||||
#include <kiway.h>
|
||||
#include <lib_id.h>
|
||||
#include <refdes_utils.h>
|
||||
#include <core/kicad_algo.h>
|
||||
#include <dialog_change_symbols.h>
|
||||
#include <sch_symbol.h>
|
||||
#include <sch_edit_frame.h>
|
||||
#include <sch_screen.h>
|
||||
#include <sch_sheet_path.h>
|
||||
#include <schematic.h>
|
||||
#include <template_fieldnames.h>
|
||||
#include <wx_html_report_panel.h>
|
||||
@@ -100,7 +98,7 @@ DIALOG_CHANGE_SYMBOLS::DIALOG_CHANGE_SYMBOLS( SCH_EDIT_FRAME* aParent, SCH_SYMBO
|
||||
|
||||
for( int i = 0; i < MANDATORY_FIELDS; ++i )
|
||||
{
|
||||
m_fieldsBox->Append( TEMPLATE_FIELDNAME::GetDefaultFieldName( i ) );
|
||||
m_fieldsBox->Append( TEMPLATE_FIELDNAME::GetDefaultFieldName( i, DO_TRANSLATE ) );
|
||||
|
||||
if( i == REFERENCE_FIELD )
|
||||
m_fieldsBox->Check( i, g_selectRefDes );
|
||||
@@ -399,7 +397,9 @@ void DIALOG_CHANGE_SYMBOLS::onOkButtonClicked( wxCommandEvent& aEvent )
|
||||
m_updateFields.insert( dummy_field.GetCanonicalName() );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_updateFields.insert( m_fieldsBox->GetString( i ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,15 +451,16 @@ bool DIALOG_CHANGE_SYMBOLS::isMatch( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aInsta
|
||||
}
|
||||
|
||||
|
||||
bool DIALOG_CHANGE_SYMBOLS::processMatchingSymbols()
|
||||
int DIALOG_CHANGE_SYMBOLS::processMatchingSymbols()
|
||||
{
|
||||
SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
|
||||
|
||||
wxCHECK( frame, false );
|
||||
|
||||
LIB_ID newId;
|
||||
bool appendToUndo = false;
|
||||
bool changed = false;
|
||||
wxString msg;
|
||||
int matchesProcessed = 0;
|
||||
SCH_SYMBOL* symbol = nullptr;
|
||||
SCH_SHEET_LIST hierarchy = frame->Schematic().GetSheets();
|
||||
|
||||
if( m_mode == MODE::CHANGE )
|
||||
@@ -470,70 +471,258 @@ bool DIALOG_CHANGE_SYMBOLS::processMatchingSymbols()
|
||||
return false;
|
||||
}
|
||||
|
||||
std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO> symbols;
|
||||
|
||||
for( SCH_SHEET_PATH& instance : hierarchy )
|
||||
{
|
||||
SCH_SCREEN* screen = instance.LastScreen();
|
||||
|
||||
wxCHECK2( screen, continue );
|
||||
|
||||
std::vector<SCH_SYMBOL*> symbols;
|
||||
|
||||
// Fetch all the symbols that meet the change criteria.
|
||||
for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
|
||||
symbols.push_back( static_cast<SCH_SYMBOL*>( item ) );
|
||||
|
||||
for( SCH_SYMBOL* symbol : symbols )
|
||||
{
|
||||
symbol = static_cast<SCH_SYMBOL*>( item );
|
||||
|
||||
wxCHECK2( symbol, continue );
|
||||
|
||||
if( !isMatch( symbol, &instance ) )
|
||||
continue;
|
||||
|
||||
if( m_mode == MODE::UPDATE )
|
||||
newId = symbol->GetLibId();
|
||||
|
||||
auto it = symbols.find( symbol );
|
||||
|
||||
if( it == symbols.end() )
|
||||
{
|
||||
if( processSymbol( symbol, &instance, symbol->GetLibId(), appendToUndo ) )
|
||||
changed = true;
|
||||
SYMBOL_CHANGE_INFO info;
|
||||
|
||||
info.m_Instances.emplace_back( instance );
|
||||
info.m_LibId = newId;
|
||||
symbols.insert( { symbol, info } );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( processSymbol( symbol, &instance, newId, appendToUndo ) )
|
||||
changed = true;
|
||||
it->second.m_Instances.emplace_back( instance );
|
||||
}
|
||||
|
||||
if( changed )
|
||||
appendToUndo = true;
|
||||
}
|
||||
}
|
||||
|
||||
matchesProcessed += processSymbols( symbols );
|
||||
|
||||
frame->GetCurrentSheet().UpdateAllScreenReferences();
|
||||
|
||||
return changed;
|
||||
return matchesProcessed;
|
||||
}
|
||||
|
||||
|
||||
bool DIALOG_CHANGE_SYMBOLS::processSymbol( SCH_SYMBOL* aSymbol, const SCH_SHEET_PATH* aInstance,
|
||||
const LIB_ID& aNewId, bool aAppendToUndo )
|
||||
int DIALOG_CHANGE_SYMBOLS::processSymbols( const std::map<SCH_SYMBOL*,
|
||||
SYMBOL_CHANGE_INFO>& aSymbols )
|
||||
{
|
||||
wxCHECK( aSymbol, false );
|
||||
wxCHECK( aNewId.IsValid(), false );
|
||||
wxCHECK( !aSymbols.empty(), 0 );
|
||||
|
||||
SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
|
||||
SCH_SCREEN* screen = aInstance->LastScreen();
|
||||
int matchesProcessed = 0;
|
||||
SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
|
||||
SCH_SCREEN* screen = nullptr;
|
||||
SCH_SYMBOL* symbol = nullptr;
|
||||
LIB_SYMBOL* libSymbol = nullptr;
|
||||
std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO> symbols = aSymbols;
|
||||
|
||||
wxCHECK( frame, false );
|
||||
wxCHECK( frame, 0 );
|
||||
|
||||
LIB_ID oldId = aSymbol->GetLibId();
|
||||
wxString msg;
|
||||
wxString references;
|
||||
|
||||
for( SYMBOL_INSTANCE_REFERENCE instance : aSymbol->GetInstanceReferences() )
|
||||
auto it = symbols.begin();
|
||||
|
||||
// Remove all symbols that don't have a valid library symbol link or enough units to
|
||||
// satify the library symbol update.
|
||||
while( it != symbols.end() )
|
||||
{
|
||||
symbol = it->first;
|
||||
|
||||
wxCHECK2( symbol && it->second.m_LibId.IsValid(), continue );
|
||||
|
||||
libSymbol = frame->GetLibSymbol( it->second.m_LibId );
|
||||
|
||||
if( !libSymbol )
|
||||
{
|
||||
msg = getSymbolReferences( *symbol, it->second.m_LibId );
|
||||
msg << wxT( ": " ) << _( "*** symbol not found ***" );
|
||||
m_messagePanel->Report( msg, RPT_SEVERITY_ERROR );
|
||||
it = symbols.erase( it );
|
||||
continue;
|
||||
}
|
||||
|
||||
std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
|
||||
|
||||
if( flattenedSymbol->GetUnitCount() < symbol->GetUnit() )
|
||||
{
|
||||
msg = getSymbolReferences( *symbol, it->second.m_LibId );
|
||||
msg << wxT( ": " ) << _( "*** new symbol has too few units ***" );
|
||||
m_messagePanel->Report( msg, RPT_SEVERITY_ERROR );
|
||||
it = symbols.erase( it );
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
// Removing the symbol needs to be done before the LIB_SYMBOL is changed to prevent stale
|
||||
// library symbols in the schematic file.
|
||||
for( auto& pair : symbols )
|
||||
{
|
||||
symbol = pair.first;
|
||||
|
||||
wxCHECK( symbol && !pair.second.m_Instances.empty(), 0 );
|
||||
|
||||
screen = pair.second.m_Instances[0].LastScreen();
|
||||
|
||||
wxCHECK( screen, 0 );
|
||||
|
||||
screen->Remove( symbol );
|
||||
frame->SaveCopyInUndoList( screen, symbol, UNDO_REDO::CHANGED, true );
|
||||
}
|
||||
|
||||
for( auto& pair : symbols )
|
||||
{
|
||||
symbol = pair.first;
|
||||
|
||||
if( pair.second.m_LibId != symbol->GetLibId() )
|
||||
symbol->SetLibId( pair.second.m_LibId );
|
||||
|
||||
libSymbol = frame->GetLibSymbol( pair.second.m_LibId );
|
||||
std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
|
||||
|
||||
symbol->SetLibSymbol( flattenedSymbol.release() );
|
||||
|
||||
if( m_resetAttributes->GetValue() )
|
||||
{
|
||||
symbol->SetIncludeInBom( libSymbol->GetIncludeInBom() );
|
||||
symbol->SetIncludeOnBoard( libSymbol->GetIncludeOnBoard() );
|
||||
}
|
||||
|
||||
bool removeExtras = m_removeExtraBox->GetValue();
|
||||
bool resetVis = m_resetFieldVisibilities->GetValue();
|
||||
bool resetEffects = m_resetFieldEffects->GetValue();
|
||||
bool resetPositions = m_resetFieldPositions->GetValue();
|
||||
|
||||
for( unsigned i = 0; i < symbol->GetFields().size(); ++i )
|
||||
{
|
||||
SCH_FIELD& field = symbol->GetFields()[i];
|
||||
LIB_FIELD* libField = nullptr;
|
||||
|
||||
// Mandatory fields always exist in m_updateFields, but these names can be translated.
|
||||
// so use GetCanonicalName().
|
||||
if( !alg::contains( m_updateFields, field.GetCanonicalName() ) )
|
||||
continue;
|
||||
|
||||
if( i < MANDATORY_FIELDS )
|
||||
libField = libSymbol->GetFieldById( (int) i );
|
||||
else
|
||||
libField = libSymbol->FindField( field.GetName() );
|
||||
|
||||
if( libField )
|
||||
{
|
||||
bool resetText = libField->GetText().IsEmpty() ? m_resetEmptyFields->GetValue()
|
||||
: m_resetFieldText->GetValue();
|
||||
|
||||
if( resetText )
|
||||
{
|
||||
for( const SCH_SHEET_PATH& instance : pair.second.m_Instances )
|
||||
{
|
||||
if( i == REFERENCE_FIELD )
|
||||
symbol->SetRef( &instance,
|
||||
UTIL::GetRefDesUnannotated( libField->GetText() ) );
|
||||
else if( i == VALUE_FIELD )
|
||||
symbol->SetValue( &instance, UnescapeString( libField->GetText() ) );
|
||||
else if( i == FOOTPRINT_FIELD )
|
||||
symbol->SetFootprint( &instance, libField->GetText() );
|
||||
else
|
||||
field.SetText( libField->GetText() );
|
||||
}
|
||||
}
|
||||
|
||||
if( resetVis )
|
||||
field.SetVisible( libField->IsVisible() );
|
||||
|
||||
if( resetEffects )
|
||||
{
|
||||
// Careful: the visible bit and position are also in Effects
|
||||
bool visible = field.IsVisible();
|
||||
wxPoint pos = field.GetPosition();
|
||||
|
||||
field.SetEffects( *libField );
|
||||
|
||||
field.SetVisible( visible );
|
||||
field.SetPosition( pos );
|
||||
}
|
||||
|
||||
if( resetPositions )
|
||||
field.SetTextPos( symbol->GetPosition() + libField->GetTextPos() );
|
||||
}
|
||||
else if( i >= MANDATORY_FIELDS && removeExtras )
|
||||
{
|
||||
symbol->RemoveField( field.GetName() );
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<LIB_FIELD*> libFields;
|
||||
libSymbol->GetFields( libFields );
|
||||
|
||||
for( unsigned i = MANDATORY_FIELDS; i < libFields.size(); ++i )
|
||||
{
|
||||
const LIB_FIELD& libField = *libFields[i];
|
||||
|
||||
if( !alg::contains( m_updateFields, libField.GetCanonicalName() ) )
|
||||
continue;
|
||||
|
||||
if( !symbol->FindField( libField.GetName(), false ) )
|
||||
{
|
||||
wxString fieldName = libField.GetCanonicalName();
|
||||
SCH_FIELD newField( wxPoint( 0, 0 ), symbol->GetFieldCount(), symbol,
|
||||
fieldName );
|
||||
SCH_FIELD* schField = symbol->AddField( newField );
|
||||
|
||||
schField->SetEffects( libField );
|
||||
schField->SetText( libField.GetText() );
|
||||
schField->SetTextPos( symbol->GetPosition() + libField.GetTextPos() );
|
||||
}
|
||||
}
|
||||
|
||||
symbol->SetSchSymbolLibraryName( wxEmptyString );
|
||||
screen = pair.second.m_Instances[0].LastScreen();
|
||||
screen->Append( symbol );
|
||||
frame->GetCanvas()->GetView()->Update( symbol );
|
||||
|
||||
msg = getSymbolReferences( *symbol, pair.second.m_LibId );
|
||||
msg += wxS( ": OK" );
|
||||
m_messagePanel->Report( msg, RPT_SEVERITY_ACTION );
|
||||
matchesProcessed +=1;
|
||||
}
|
||||
|
||||
return matchesProcessed;
|
||||
}
|
||||
|
||||
|
||||
wxString DIALOG_CHANGE_SYMBOLS::getSymbolReferences( SCH_SYMBOL& aSymbol, const LIB_ID& aNewId )
|
||||
{
|
||||
wxString msg;
|
||||
wxString references;
|
||||
LIB_ID oldId = aSymbol.GetLibId();
|
||||
|
||||
for( const SYMBOL_INSTANCE_REFERENCE& instance : aSymbol.GetInstanceReferences() )
|
||||
{
|
||||
if( references.IsEmpty() )
|
||||
references = instance.m_Reference;
|
||||
else
|
||||
references += wxT( " " ) + instance.m_Reference;
|
||||
}
|
||||
|
||||
if( m_mode == MODE::UPDATE )
|
||||
{
|
||||
if( aSymbol->GetInstanceReferences().size() == 1 )
|
||||
if( aSymbol.GetInstanceReferences().size() == 1 )
|
||||
{
|
||||
msg.Printf( _( "Update symbol %s from '%s' to '%s'" ),
|
||||
references,
|
||||
@@ -550,7 +739,7 @@ bool DIALOG_CHANGE_SYMBOLS::processSymbol( SCH_SYMBOL* aSymbol, const SCH_SHEET_
|
||||
}
|
||||
else
|
||||
{
|
||||
if( aSymbol->GetInstanceReferences().size() == 1 )
|
||||
if( aSymbol.GetInstanceReferences().size() == 1 )
|
||||
{
|
||||
msg.Printf( _( "Change symbol %s from '%s' to '%s'" ),
|
||||
references,
|
||||
@@ -566,132 +755,5 @@ bool DIALOG_CHANGE_SYMBOLS::processSymbol( SCH_SYMBOL* aSymbol, const SCH_SHEET_
|
||||
}
|
||||
}
|
||||
|
||||
LIB_SYMBOL* libSymbol = frame->GetLibSymbol( aNewId );
|
||||
|
||||
if( !libSymbol )
|
||||
{
|
||||
msg << wxT( ": " ) << _( "*** symbol not found ***" );
|
||||
m_messagePanel->Report( msg, RPT_SEVERITY_ERROR );
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
|
||||
|
||||
if( flattenedSymbol->GetUnitCount() < aSymbol->GetUnit() )
|
||||
{
|
||||
msg << wxT( ": " ) << _( "*** new symbol has too few units ***" );
|
||||
m_messagePanel->Report( msg, RPT_SEVERITY_ERROR );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Removing the symbol needs to be done before the LIB_SYMBOL is changed to prevent stale
|
||||
// library symbols in the schematic file.
|
||||
screen->Remove( aSymbol );
|
||||
frame->SaveCopyInUndoList( screen, aSymbol, UNDO_REDO::CHANGED, aAppendToUndo );
|
||||
|
||||
if( aNewId != aSymbol->GetLibId() )
|
||||
aSymbol->SetLibId( aNewId );
|
||||
|
||||
aSymbol->SetLibSymbol( flattenedSymbol.release() );
|
||||
|
||||
if( m_resetAttributes->GetValue() )
|
||||
{
|
||||
aSymbol->SetIncludeInBom( libSymbol->GetIncludeInBom() );
|
||||
aSymbol->SetIncludeOnBoard( libSymbol->GetIncludeOnBoard() );
|
||||
}
|
||||
|
||||
bool removeExtras = m_removeExtraBox->GetValue();
|
||||
bool resetVis = m_resetFieldVisibilities->GetValue();
|
||||
bool resetEffects = m_resetFieldEffects->GetValue();
|
||||
bool resetPositions = m_resetFieldPositions->GetValue();
|
||||
|
||||
for( unsigned i = 0; i < aSymbol->GetFields().size(); ++i )
|
||||
{
|
||||
SCH_FIELD& field = aSymbol->GetFields()[i];
|
||||
LIB_FIELD* libField = nullptr;
|
||||
|
||||
// Mandatory fields always exist in m_updateFields, but these names can be translated.
|
||||
// so use GetCanonicalName().
|
||||
if( !alg::contains( m_updateFields, field.GetCanonicalName() ) )
|
||||
continue;
|
||||
|
||||
if( i < MANDATORY_FIELDS )
|
||||
libField = libSymbol->GetFieldById( (int) i );
|
||||
else
|
||||
libField = libSymbol->FindField( field.GetName() );
|
||||
|
||||
if( libField )
|
||||
{
|
||||
bool resetText = libField->GetText().IsEmpty() ? m_resetEmptyFields->GetValue()
|
||||
: m_resetFieldText->GetValue();
|
||||
|
||||
if( resetText )
|
||||
{
|
||||
if( i == REFERENCE_FIELD )
|
||||
aSymbol->SetRef( aInstance, UTIL::GetRefDesUnannotated( libField->GetText() ) );
|
||||
else if( i == VALUE_FIELD )
|
||||
aSymbol->SetValue( aInstance, UnescapeString( libField->GetText() ) );
|
||||
else if( i == FOOTPRINT_FIELD )
|
||||
aSymbol->SetFootprint( aInstance, libField->GetText() );
|
||||
else
|
||||
field.SetText( libField->GetText() );
|
||||
}
|
||||
|
||||
if( resetVis )
|
||||
field.SetVisible( libField->IsVisible() );
|
||||
|
||||
if( resetEffects )
|
||||
{
|
||||
// Careful: the visible bit and position are also in Effects
|
||||
bool visible = field.IsVisible();
|
||||
wxPoint pos = field.GetPosition();
|
||||
|
||||
field.SetEffects( *libField );
|
||||
|
||||
field.SetVisible( visible );
|
||||
field.SetPosition( pos );
|
||||
}
|
||||
|
||||
if( resetPositions )
|
||||
field.SetTextPos( aSymbol->GetPosition() + libField->GetTextPos() );
|
||||
}
|
||||
else if( i >= MANDATORY_FIELDS && removeExtras )
|
||||
{
|
||||
aSymbol->RemoveField( field.GetName() );
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<LIB_FIELD*> libFields;
|
||||
libSymbol->GetFields( libFields );
|
||||
|
||||
for( unsigned i = MANDATORY_FIELDS; i < libFields.size(); ++i )
|
||||
{
|
||||
const LIB_FIELD& libField = *libFields[i];
|
||||
|
||||
if( !alg::contains( m_updateFields, libField.GetCanonicalName() ) )
|
||||
continue;
|
||||
|
||||
if( !aSymbol->FindField( libField.GetName(), false ) )
|
||||
{
|
||||
wxString fieldName = libField.GetCanonicalName();
|
||||
SCH_FIELD newField( wxPoint( 0, 0), aSymbol->GetFieldCount(), aSymbol, fieldName );
|
||||
SCH_FIELD* schField = aSymbol->AddField( newField );
|
||||
|
||||
schField->SetEffects( libField );
|
||||
schField->SetText( libField.GetText() );
|
||||
schField->SetTextPos( aSymbol->GetPosition() + libField.GetTextPos() );
|
||||
}
|
||||
}
|
||||
|
||||
aSymbol->SetSchSymbolLibraryName( wxEmptyString );
|
||||
screen->Append( aSymbol );
|
||||
frame->GetCanvas()->GetView()->Update( aSymbol );
|
||||
|
||||
msg += wxT( ": OK" );
|
||||
m_messagePanel->Report( msg, RPT_SEVERITY_ACTION );
|
||||
|
||||
return true;
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2020 CERN
|
||||
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2021-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Wayne Stambaugh <stambaughw@gmail.com>
|
||||
*
|
||||
@@ -25,11 +25,21 @@
|
||||
|
||||
#include <dialog_change_symbols_base.h>
|
||||
|
||||
class LIB_ID;
|
||||
#include <lib_id.h>
|
||||
#include <sch_sheet_path.h>
|
||||
|
||||
|
||||
class SCH_SYMBOL;
|
||||
class SCH_EDIT_FRAME;
|
||||
class SCH_SCREEN;
|
||||
class SCH_SHEET_PATH;
|
||||
|
||||
|
||||
struct SYMBOL_CHANGE_INFO
|
||||
{
|
||||
std::vector<SCH_SHEET_PATH> m_Instances;
|
||||
LIB_ID m_LibId;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Dialog to update or change schematic library symbols.
|
||||
@@ -73,9 +83,9 @@ private:
|
||||
void updateFieldsList();
|
||||
|
||||
bool isMatch( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aInstance );
|
||||
bool processMatchingSymbols();
|
||||
bool processSymbol( SCH_SYMBOL* aSymbol, const SCH_SHEET_PATH* aInstance,
|
||||
const LIB_ID& aNewId, bool aAppendToUndo );
|
||||
int processMatchingSymbols();
|
||||
int processSymbols( const std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO>& aSymbols );
|
||||
wxString getSymbolReferences( SCH_SYMBOL& aSymbol, const LIB_ID& aNewId );
|
||||
|
||||
SCH_SYMBOL* m_symbol;
|
||||
MODE m_mode;
|
||||
|
||||
@@ -53,8 +53,6 @@ DIALOG_FIELD_PROPERTIES::DIALOG_FIELD_PROPERTIES( SCH_BASE_FRAME* aParent, const
|
||||
{
|
||||
wxASSERT( aTextItem );
|
||||
|
||||
SetTitle( aTitle );
|
||||
|
||||
m_note->SetFont( KIUI::GetInfoFont( this ).Italic() );
|
||||
m_note->Show( false );
|
||||
|
||||
@@ -348,7 +346,14 @@ DIALOG_SCH_FIELD_PROPERTIES::DIALOG_SCH_FIELD_PROPERTIES( SCH_BASE_FRAME* aParen
|
||||
|
||||
m_isPower = false;
|
||||
|
||||
m_textLabel->SetLabel( m_field->GetName() + wxT( ":" ) );
|
||||
wxString translated_fieldname;
|
||||
|
||||
if( m_field->GetId() < MANDATORY_FIELDS )
|
||||
translated_fieldname = TEMPLATE_FIELDNAME::GetDefaultFieldName( m_field->GetId(), DO_TRANSLATE );
|
||||
else
|
||||
translated_fieldname = m_field->GetName();
|
||||
|
||||
m_textLabel->SetLabel( translated_fieldname + ":" );
|
||||
|
||||
m_position = m_field->GetPosition();
|
||||
|
||||
|
||||
@@ -109,10 +109,6 @@ DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS( SCH_
|
||||
m_parent = parent;
|
||||
m_appendUndo = false;
|
||||
|
||||
// TODO(JE) remove once real-time connectivity is a given
|
||||
if( !ADVANCED_CFG::GetCfg().m_RealTimeConnectivity || !CONNECTION_GRAPH::m_allowRealTime )
|
||||
m_parent->RecalculateConnections( NO_CLEANUP );
|
||||
|
||||
m_lineStyle->Append( DEFAULT_STYLE );
|
||||
m_lineStyle->Append( INDETERMINATE_ACTION );
|
||||
|
||||
|
||||
@@ -556,7 +556,9 @@ DIALOG_LIB_EDIT_PIN_TABLE::~DIALOG_LIB_EDIT_PIN_TABLE()
|
||||
bool DIALOG_LIB_EDIT_PIN_TABLE::TransferDataToWindow()
|
||||
{
|
||||
// Make a copy of the pins for editing
|
||||
for( LIB_PIN* pin = m_part->GetNextPin( nullptr ); pin; pin = m_part->GetNextPin( pin ) )
|
||||
std::vector<LIB_PIN*> pins = m_part->GetAllLibPins();
|
||||
|
||||
for( LIB_PIN* pin : pins )
|
||||
m_pins.push_back( new LIB_PIN( *pin ) );
|
||||
|
||||
m_dataModel->RebuildRows( m_pins, m_cbGroup->GetValue() );
|
||||
@@ -573,7 +575,9 @@ bool DIALOG_LIB_EDIT_PIN_TABLE::TransferDataFromWindow()
|
||||
return false;
|
||||
|
||||
// Delete the part's pins
|
||||
while( LIB_PIN* pin = m_part->GetNextPin( nullptr ) )
|
||||
std::vector<LIB_PIN*> pins = m_part->GetAllLibPins();
|
||||
|
||||
for( LIB_PIN* pin : pins )
|
||||
m_part->RemoveDrawItem( pin );
|
||||
|
||||
// Transfer our pins to the part
|
||||
|
||||
@@ -233,6 +233,10 @@ public:
|
||||
if( aCol == QUANTITY_COLUMN )
|
||||
return _( "Qty" );
|
||||
else if( aCol < MANDATORY_FIELDS )
|
||||
// FIX ME: the column label should be displayed translated.
|
||||
// but when translated, and the DATASHEET column is shown, a new field
|
||||
// with the translated DATASHEET field name is added when saving fields
|
||||
// return TEMPLATE_FIELDNAME::GetDefaultFieldName( aCol, DO_TRANSLATE );
|
||||
return TEMPLATE_FIELDNAME::GetDefaultFieldName( aCol );
|
||||
else
|
||||
return m_fieldNames[ aCol ];
|
||||
@@ -615,19 +619,21 @@ public:
|
||||
const wxString& srcValue = srcData.second;
|
||||
SCH_FIELD* destField = symbol.FindField( srcName );
|
||||
|
||||
if( !destField && !srcValue.IsEmpty() )
|
||||
// Add a not existing field if it has a value for this symbol
|
||||
bool createField = !destField && !srcValue.IsEmpty();
|
||||
|
||||
if( createField )
|
||||
{
|
||||
const wxPoint symbolPos = symbol.GetPosition();
|
||||
destField = symbol.AddField( SCH_FIELD( symbolPos, -1, &symbol, srcName ) );
|
||||
}
|
||||
|
||||
if( !destField )
|
||||
continue;
|
||||
|
||||
if( destField->GetId() == REFERENCE_FIELD )
|
||||
{
|
||||
symbol.RemoveField( srcName );
|
||||
}
|
||||
else if( destField->GetId() == REFERENCE_FIELD )
|
||||
{
|
||||
// Reference is not editable
|
||||
// Reference is not editable from this dialog
|
||||
}
|
||||
else if( destField->GetId() == VALUE_FIELD )
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 Oliver Walters
|
||||
* Copyright (C) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2017-2022 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
|
||||
@@ -74,6 +74,8 @@ private:
|
||||
|
||||
SCH_REFERENCE_LIST m_symbolsList;
|
||||
FIELDS_EDITOR_GRID_DATA_MODEL* m_dataModel;
|
||||
static int m_newFieldsOption; // Store the option choice for new fields
|
||||
// during a session:
|
||||
};
|
||||
|
||||
#endif /* DIALOG_SYMBOL_FIELDS_TABLE_H */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.0-4761b0c5)
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -32,7 +32,7 @@ DIALOG_SYMBOL_FIELDS_TABLE_BASE::DIALOG_SYMBOL_FIELDS_TABLE_BASE( wxWindow* pare
|
||||
m_groupSymbolsBox->SetValue(true);
|
||||
m_groupSymbolsBox->SetToolTip( _("Group symbols together based on common properties") );
|
||||
|
||||
bGroupSizer->Add( m_groupSymbolsBox, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxLEFT|wxRIGHT, 5 );
|
||||
bGroupSizer->Add( m_groupSymbolsBox, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
|
||||
bGroupSizer->Add( 0, 0, 1, wxEXPAND|wxRIGHT|wxLEFT, 10 );
|
||||
@@ -103,7 +103,7 @@ DIALOG_SYMBOL_FIELDS_TABLE_BASE::DIALOG_SYMBOL_FIELDS_TABLE_BASE( wxWindow* pare
|
||||
bButtonsSizer->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_buttonApply = new wxButton( this, wxID_ANY, _("Apply, Save Schematic && Continue"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bButtonsSizer->Add( m_buttonApply, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 );
|
||||
bButtonsSizer->Add( m_buttonApply, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
|
||||
|
||||
m_sdbSizer = new wxStdDialogButtonSizer();
|
||||
m_sdbSizerOK = new wxButton( this, wxID_OK );
|
||||
@@ -112,10 +112,10 @@ DIALOG_SYMBOL_FIELDS_TABLE_BASE::DIALOG_SYMBOL_FIELDS_TABLE_BASE( wxWindow* pare
|
||||
m_sdbSizer->AddButton( m_sdbSizerCancel );
|
||||
m_sdbSizer->Realize();
|
||||
|
||||
bButtonsSizer->Add( m_sdbSizer, 0, wxBOTTOM|wxEXPAND|wxLEFT, 5 );
|
||||
bButtonsSizer->Add( m_sdbSizer, 0, wxEXPAND|wxLEFT, 5 );
|
||||
|
||||
|
||||
bMainSizer->Add( bButtonsSizer, 0, wxEXPAND, 5 );
|
||||
bMainSizer->Add( bButtonsSizer, 0, wxBOTTOM|wxEXPAND|wxTOP, 5 );
|
||||
|
||||
|
||||
this->SetSizer( bMainSizer );
|
||||
|
||||
@@ -191,7 +191,7 @@
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="0">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxEXPAND|wxLEFT|wxRIGHT</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxCheckBox" expanded="0">
|
||||
<property name="BottomDockable">1</property>
|
||||
@@ -603,7 +603,7 @@
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="flag">wxBOTTOM|wxEXPAND|wxTOP</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
@@ -622,7 +622,7 @@
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxButton" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
@@ -696,7 +696,7 @@
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxBOTTOM|wxEXPAND|wxLEFT</property>
|
||||
<property name="flag">wxEXPAND|wxLEFT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStdDialogButtonSizer" expanded="1">
|
||||
<property name="Apply">0</property>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.0-4761b0c5)
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
|
||||
@@ -867,7 +867,7 @@ void DIALOG_SYMBOL_PROPERTIES::OnAddField( wxCommandEvent& event )
|
||||
SCHEMATIC_SETTINGS& settings = m_symbol->Schematic()->Settings();
|
||||
int fieldID = m_fields->size();
|
||||
SCH_FIELD newField( wxPoint( 0, 0 ), fieldID, m_symbol,
|
||||
TEMPLATE_FIELDNAME::GetDefaultFieldName( fieldID ) );
|
||||
TEMPLATE_FIELDNAME::GetDefaultFieldName( fieldID, DO_TRANSLATE ) );
|
||||
|
||||
newField.SetTextAngle( m_fields->at( REFERENCE_FIELD ).GetTextAngle() );
|
||||
newField.SetTextSize( wxSize( settings.m_DefaultTextSize, settings.m_DefaultTextSize ) );
|
||||
|
||||
@@ -47,7 +47,7 @@ DIALOG_UPDATE_SYMBOL_FIELDS::DIALOG_UPDATE_SYMBOL_FIELDS( SYMBOL_EDIT_FRAME* aPa
|
||||
|
||||
for( int i = 0; i < MANDATORY_FIELDS; ++i )
|
||||
{
|
||||
m_fieldsBox->Append( TEMPLATE_FIELDNAME::GetDefaultFieldName( i ) );
|
||||
m_fieldsBox->Append( TEMPLATE_FIELDNAME::GetDefaultFieldName( i, DO_TRANSLATE ) );
|
||||
m_fieldsBox->Check( i, true );
|
||||
}
|
||||
|
||||
|
||||
@@ -356,7 +356,10 @@ void IFACE::SaveFileAs( const wxString& aProjectBasePath, const wxString& aProje
|
||||
ext == KiCadSymbolLibFileExtension )
|
||||
{
|
||||
if( destFile.GetName() == aProjectName + wxT( "-cache" ) )
|
||||
destFile.SetName( aNewProjectName + wxT( "-cache" ) );
|
||||
destFile.SetName( aNewProjectName + wxT( "-cache" ) );
|
||||
|
||||
if( destFile.GetName() == aProjectName + wxT( "-rescue" ) )
|
||||
destFile.SetName( aNewProjectName + wxT( "-rescue" ) );
|
||||
|
||||
KiCopyFile( aSrcFilePath, destFile.GetFullPath(), aErrors );
|
||||
}
|
||||
|
||||
@@ -389,7 +389,7 @@ wxString FIELDS_GRID_TABLE<T>::GetValue( int aRow, int aCol )
|
||||
if( aRow < m_mandatoryFieldCount )
|
||||
{
|
||||
if( m_parentType == SCH_SYMBOL_T )
|
||||
return TEMPLATE_FIELDNAME::GetDefaultFieldName( aRow );
|
||||
return TEMPLATE_FIELDNAME::GetDefaultFieldName( aRow, DO_TRANSLATE );
|
||||
else if( m_parentType == SCH_SHEET_T )
|
||||
return SCH_SHEET::GetDefaultFieldName( aRow );
|
||||
}
|
||||
|
||||
+12
-10
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2013 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 2013 CERN (www.cern.ch)
|
||||
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2023 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
|
||||
@@ -456,7 +456,6 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
||||
// Legacy schematic can have duplicate time stamps so fix that before converting
|
||||
// to the s-expression format.
|
||||
schematic.ReplaceDuplicateTimeStamps();
|
||||
schematic.SetLegacySymbolInstanceData();
|
||||
|
||||
// Allow the schematic to be saved to new file format without making any edits.
|
||||
OnModify();
|
||||
@@ -490,7 +489,6 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
||||
{
|
||||
DIALOG_MIGRATE_BUSES dlg( this );
|
||||
dlg.ShowQuasiModal();
|
||||
RecalculateConnections( NO_CLEANUP );
|
||||
OnModify();
|
||||
}
|
||||
|
||||
@@ -627,7 +625,8 @@ void SCH_EDIT_FRAME::OnImportProject( wxCommandEvent& aEvent )
|
||||
allWildcards += "*." + formatWildcardExt( plugin->GetFileExtension() ) + ";";
|
||||
}
|
||||
|
||||
fileFilters = _( "All supported formats|" ) + allWildcards + "|" + fileFilters;
|
||||
fileFilters = _( "All supported formats" ) + wxS( "|" ) + allWildcards + wxS( "|" ) +
|
||||
fileFilters;
|
||||
|
||||
wxFileDialog dlg( this, _( "Import Schematic" ), path, wxEmptyString, fileFilters,
|
||||
wxFD_OPEN | wxFD_FILE_MUST_EXIST ); // TODO
|
||||
@@ -1422,12 +1421,17 @@ void SCH_EDIT_FRAME::CheckForAutoSaveFile( const wxFileName& aFileName )
|
||||
" Auto save file: '%s'" ),
|
||||
recoveredFn.GetFullPath(), backupFn.GetFullPath(), fn );
|
||||
|
||||
// Attempt to back up the last schematic file before overwriting it with the auto
|
||||
// save file.
|
||||
if( !wxCopyFile( recoveredFn.GetFullPath(), backupFn.GetFullPath() ) )
|
||||
if( !wxFileExists( fn ) )
|
||||
{
|
||||
unrecoveredFiles.Add( recoveredFn.GetFullPath() );
|
||||
}
|
||||
// Attempt to back up the last schematic file before overwriting it with the auto
|
||||
// save file.
|
||||
else if( !wxCopyFile( recoveredFn.GetFullPath(), backupFn.GetFullPath() ) )
|
||||
{
|
||||
unrecoveredFiles.Add( recoveredFn.GetFullPath() );
|
||||
}
|
||||
// Attempt to replace last saved file with auto save file
|
||||
else if( !wxRenameFile( fn, recoveredFn.GetFullPath() ) )
|
||||
{
|
||||
unrecoveredFiles.Add( recoveredFn.GetFullPath() );
|
||||
@@ -1455,10 +1459,8 @@ void SCH_EDIT_FRAME::CheckForAutoSaveFile( const wxFileName& aFileName )
|
||||
{
|
||||
wxLogTrace( traceAutoSave, wxT( "Removing auto save file " ) + fn );
|
||||
|
||||
if( !wxRemoveFile( fn ) )
|
||||
{
|
||||
if( wxFileExists( fn ) && !wxRemoveFile( fn ) )
|
||||
unremovedFiles.Add( fn );
|
||||
}
|
||||
}
|
||||
|
||||
if( !unremovedFiles.IsEmpty() )
|
||||
|
||||
@@ -403,10 +403,11 @@ wxString LIB_FIELD::GetCanonicalName() const
|
||||
{
|
||||
switch( m_id )
|
||||
{
|
||||
case REFERENCE_FIELD: return wxT( "Reference" );
|
||||
case VALUE_FIELD: return wxT( "Value" );
|
||||
case FOOTPRINT_FIELD: return wxT( "Footprint" );
|
||||
case DATASHEET_FIELD: return wxT( "Datasheet" );
|
||||
case REFERENCE_FIELD:
|
||||
case VALUE_FIELD:
|
||||
case FOOTPRINT_FIELD:
|
||||
case DATASHEET_FIELD:
|
||||
return TEMPLATE_FIELDNAME::GetDefaultFieldName( m_id );
|
||||
}
|
||||
|
||||
return m_name;
|
||||
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
void Init( int aId );
|
||||
|
||||
/**
|
||||
* Return the field name.
|
||||
* Return the field name (not translated).
|
||||
*
|
||||
* The first four field IDs are reserved and therefore always return their respective
|
||||
* names.
|
||||
|
||||
+9
-29
@@ -732,35 +732,6 @@ void LIB_SYMBOL::AddDrawItem( LIB_ITEM* aItem, bool aSort )
|
||||
}
|
||||
|
||||
|
||||
LIB_ITEM* LIB_SYMBOL::GetNextDrawItem( const LIB_ITEM* aItem, KICAD_T aType )
|
||||
{
|
||||
if( aItem == nullptr )
|
||||
{
|
||||
LIB_ITEMS_CONTAINER::ITERATOR it1 = m_drawings.begin( aType );
|
||||
|
||||
return (it1 != m_drawings.end( aType ) ) ? &( *( m_drawings.begin( aType ) ) ) : nullptr;
|
||||
}
|
||||
|
||||
// Search for the last item, assume aItem is of type aType
|
||||
wxASSERT( ( aType == TYPE_NOT_INIT ) || ( aType == aItem->Type() ) );
|
||||
LIB_ITEMS_CONTAINER::ITERATOR it = m_drawings.begin( aType );
|
||||
|
||||
while( ( it != m_drawings.end( aType ) ) && ( aItem != &( *it ) ) )
|
||||
++it;
|
||||
|
||||
// Search the next item
|
||||
if( it != m_drawings.end( aType ) )
|
||||
{
|
||||
++it;
|
||||
|
||||
if( it != m_drawings.end( aType ) )
|
||||
return &( *it );
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
void LIB_SYMBOL::GetPins( LIB_PINS& aList, int aUnit, int aConvert ) const
|
||||
{
|
||||
/* Notes:
|
||||
@@ -788,6 +759,15 @@ void LIB_SYMBOL::GetPins( LIB_PINS& aList, int aUnit, int aConvert ) const
|
||||
}
|
||||
|
||||
|
||||
std::vector<LIB_PIN*> LIB_SYMBOL::GetAllLibPins() const
|
||||
{
|
||||
std::vector<LIB_PIN*> pinList;
|
||||
|
||||
GetPins( pinList, 0, 0 );
|
||||
return pinList;
|
||||
}
|
||||
|
||||
|
||||
LIB_PIN* LIB_SYMBOL::GetPin( const wxString& aNumber, int aUnit, int aConvert ) const
|
||||
{
|
||||
LIB_PINS pinList;
|
||||
|
||||
+6
-25
@@ -367,35 +367,10 @@ public:
|
||||
*/
|
||||
void RemoveDrawItem( LIB_ITEM* aItem );
|
||||
|
||||
/**
|
||||
* Return the next draw object pointer.
|
||||
*
|
||||
* @param aItem - Pointer to the current draw item. Setting item NULL
|
||||
* with return the first item of type in the list.
|
||||
* @param aType - type of searched item (filter).
|
||||
* if TYPE_NOT_INIT search for all items types
|
||||
* @return - The next drawing object in the list if found, otherwise NULL.
|
||||
*/
|
||||
LIB_ITEM* GetNextDrawItem( const LIB_ITEM* aItem = nullptr, KICAD_T aType = TYPE_NOT_INIT );
|
||||
|
||||
size_t GetPinCount() const { return m_drawings.size( LIB_PIN_T ); }
|
||||
|
||||
size_t GetFieldCount() const { return m_drawings.size( LIB_FIELD_T ); }
|
||||
|
||||
/**
|
||||
* Return the next pin object from the draw list.
|
||||
*
|
||||
* This is just a pin object specific version of GetNextDrawItem().
|
||||
*
|
||||
* @param aItem - Pointer to the previous pin item, or NULL to get the
|
||||
* first pin in the draw object list.
|
||||
* @return - The next pin object in the list if found, otherwise NULL.
|
||||
*/
|
||||
LIB_PIN* GetNextPin( LIB_PIN* aItem = nullptr )
|
||||
{
|
||||
return (LIB_PIN*) GetNextDrawItem( (LIB_ITEM*) aItem, LIB_PIN_T );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of pin object pointers from the draw item list.
|
||||
*
|
||||
@@ -411,6 +386,12 @@ public:
|
||||
*/
|
||||
void GetPins( LIB_PINS& aList, int aUnit = 0, int aConvert = 0 ) const;
|
||||
|
||||
/**
|
||||
* Return a list of pin pointers for all units / converts. Used primarily for SPICE where
|
||||
* we want to treat all unit as a single part.
|
||||
*/
|
||||
std::vector<LIB_PIN*> GetAllLibPins() const;
|
||||
|
||||
/**
|
||||
* Return pin object with the requested pin \a aNumber.
|
||||
*
|
||||
|
||||
@@ -48,9 +48,6 @@ bool SCH_EDIT_FRAME::WriteNetListFile( int aFormat, const wxString& aFullFileNam
|
||||
// Ensure all power symbols have a valid reference
|
||||
Schematic().GetSheets().AnnotatePowerSymbols();
|
||||
|
||||
// Ensure the netlist data is up to date:
|
||||
RecalculateConnections( NO_CLEANUP );
|
||||
|
||||
if( !ReadyToNetlist( _( "Exporting netlist requires a fully annotated schematic." ) ) )
|
||||
return false;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Chris Pavlina <pavlina.chris@gmail.com>
|
||||
* Copyright (C) 2015-2022 KiCad Developers, see change_log.txt for contributors.
|
||||
* Copyright (C) 2015-2023 KiCad Developers, see change_log.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
|
||||
@@ -164,9 +164,22 @@ void RESCUE_CASE_CANDIDATE::FindRescues( RESCUER& aRescuer,
|
||||
case_sensitive_match = aRescuer.GetPrj()->SchLibs()->FindLibSymbol( id );
|
||||
|
||||
// If the case sensitive match failed, try a case insensitive match.
|
||||
if( !case_sensitive_match )
|
||||
aRescuer.GetPrj()->SchLibs()->FindLibraryNearEntries( case_insensitive_matches,
|
||||
search_name );
|
||||
if( case_sensitive_match )
|
||||
continue;
|
||||
|
||||
aRescuer.GetPrj()->SchLibs()->FindLibraryNearEntries( case_insensitive_matches,
|
||||
symbol_name );
|
||||
|
||||
// If there are not case insensitive matches either, the symbol cannot be rescued.
|
||||
if( !case_insensitive_matches.size() )
|
||||
continue;
|
||||
|
||||
RESCUE_CASE_CANDIDATE candidate( symbol_name, case_insensitive_matches[0]->GetName(),
|
||||
case_insensitive_matches[0],
|
||||
eachSymbol->GetUnit(),
|
||||
eachSymbol->GetConvert() );
|
||||
|
||||
candidate_map[symbol_name] = candidate;
|
||||
}
|
||||
|
||||
if( case_sensitive_match || !( case_insensitive_matches.size() ) )
|
||||
@@ -198,6 +211,12 @@ wxString RESCUE_CASE_CANDIDATE::GetActionDescription() const
|
||||
|
||||
bool RESCUE_CASE_CANDIDATE::PerformAction( RESCUER* aRescuer )
|
||||
{
|
||||
wxCHECK( m_lib_candidate, true );
|
||||
|
||||
std::unique_ptr<LIB_SYMBOL> new_symbol = m_lib_candidate->Flatten();
|
||||
new_symbol->SetName( m_new_name );
|
||||
aRescuer->AddSymbol( new_symbol.get() );
|
||||
|
||||
for( SCH_SYMBOL* eachSymbol : *aRescuer->GetSymbols() )
|
||||
{
|
||||
if( eachSymbol->GetLibId().GetLibItemName() != UTF8( m_requested_name ) )
|
||||
@@ -316,7 +335,9 @@ bool RESCUE_CACHE_CANDIDATE::PerformAction( RESCUER* aRescuer )
|
||||
{
|
||||
LIB_SYMBOL* tmp = ( m_cache_candidate ) ? m_cache_candidate : m_lib_candidate;
|
||||
|
||||
wxCHECK_MSG( tmp, false, wxT( "Both cache and library symbols undefined." ) );
|
||||
// A symbol that cannot be rescued is a valid condition so just bail out here.
|
||||
if( !tmp )
|
||||
return true;
|
||||
|
||||
std::unique_ptr<LIB_SYMBOL> new_symbol = tmp->Flatten();
|
||||
new_symbol->SetName( m_new_name );
|
||||
|
||||
@@ -443,9 +443,6 @@ void SCH_CONNECTION::AppendInfoToMsgPanel( std::vector<MSG_PANEL_ITEM>& aList )
|
||||
#if defined(DEBUG)
|
||||
// These messages are not flagged as translatable, because they are only debug messages
|
||||
|
||||
if( !ADVANCED_CFG::GetCfg().m_RealTimeConnectivity || !CONNECTION_GRAPH::m_allowRealTime )
|
||||
return;
|
||||
|
||||
if( IsBus() )
|
||||
aList.emplace_back( wxT( "Bus Code" ), wxString::Format( wxT( "%d" ), m_bus_code ) );
|
||||
|
||||
|
||||
@@ -614,7 +614,8 @@ void SCH_EDIT_FRAME::SetCurrentSheet( const SCH_SHEET_PATH& aSheet )
|
||||
|
||||
void SCH_EDIT_FRAME::HardRedraw()
|
||||
{
|
||||
RecalculateConnections( LOCAL_CLEANUP );
|
||||
if( Schematic().Settings().m_IntersheetRefsShow )
|
||||
RecomputeIntersheetRefs();
|
||||
|
||||
FocusOnItem( nullptr );
|
||||
|
||||
@@ -838,10 +839,7 @@ void SCH_EDIT_FRAME::OnModify()
|
||||
|
||||
GetScreen()->SetContentModified();
|
||||
|
||||
if( ADVANCED_CFG::GetCfg().m_RealTimeConnectivity && CONNECTION_GRAPH::m_allowRealTime )
|
||||
RecalculateConnections( NO_CLEANUP );
|
||||
else
|
||||
GetScreen()->SetConnectivityDirty();
|
||||
RecalculateConnections( NO_CLEANUP );
|
||||
|
||||
GetCanvas()->Refresh();
|
||||
UpdateHierarchyNavigator();
|
||||
@@ -1252,7 +1250,7 @@ void SCH_EDIT_FRAME::AddItemToScreenAndUndoList( SCH_SCREEN* aScreen, SCH_ITEM*
|
||||
}
|
||||
|
||||
// Update connectivity info for new item
|
||||
if( !aItem->IsMoving() )
|
||||
if( !aItem->IsMoving() && aItem->IsConnectable() )
|
||||
{
|
||||
RecalculateConnections( LOCAL_CLEANUP );
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ public:
|
||||
void DoHypertextMenu( EDA_DRAW_FRAME* aFrame ) override;
|
||||
|
||||
/**
|
||||
* Return the field name.
|
||||
* Return the field name (not translated)..
|
||||
*
|
||||
* @param aUseDefaultName When true return the default field name if the field name is
|
||||
* empty. Otherwise the default field name is returned.
|
||||
|
||||
@@ -233,6 +233,16 @@ void SCH_PIN::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITE
|
||||
}
|
||||
|
||||
|
||||
bool SCH_PIN::IsStacked( const SCH_PIN* aPin ) const
|
||||
{
|
||||
return m_parent == aPin->GetParent()
|
||||
&& GetTransformedPosition() == aPin->GetTransformedPosition()
|
||||
&& ( ( GetType() == aPin->GetType() )
|
||||
|| ( GetType() == ELECTRICAL_PINTYPE::PT_PASSIVE )
|
||||
|| ( aPin->GetType() == ELECTRICAL_PINTYPE::PT_PASSIVE ) );
|
||||
}
|
||||
|
||||
|
||||
void SCH_PIN::ClearDefaultNetName( const SCH_SHEET_PATH* aPath )
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock( m_netmap_mutex );
|
||||
|
||||
@@ -98,6 +98,12 @@ public:
|
||||
|
||||
void SetIsDangling( bool isDangling ) { m_isDangling = isDangling; }
|
||||
|
||||
/**
|
||||
* @param aPin Comparison Pin
|
||||
* @return True if aPin is stacked with this pin
|
||||
*/
|
||||
bool IsStacked( const SCH_PIN* aPin ) const;
|
||||
|
||||
bool IsPointClickableAnchor( const wxPoint& aPos ) const override
|
||||
{
|
||||
return m_isDangling && GetPosition() == aPos;
|
||||
|
||||
@@ -650,7 +650,8 @@ void SCH_SEXPR_PARSER::parseEDA_TEXT( EDA_TEXT* aText, bool aConvertOverbarSynta
|
||||
case T_right: aText->SetHorizJustify( GR_TEXT_HJUSTIFY_RIGHT ); break;
|
||||
case T_top: aText->SetVertJustify( GR_TEXT_VJUSTIFY_TOP ); break;
|
||||
case T_bottom: aText->SetVertJustify( GR_TEXT_VJUSTIFY_BOTTOM ); break;
|
||||
case T_mirror: aText->SetMirrored( true ); break;
|
||||
// Do not set mirror property for schematic text elements
|
||||
case T_mirror: break;
|
||||
default: Expecting( "left, right, top, bottom, or mirror" );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -536,7 +536,7 @@ SCH_SHEET* SCH_SEXPR_PLUGIN::Load( const wxString& aFileName, SCHEMATIC* aSchema
|
||||
|
||||
if( aAppendToMe )
|
||||
{
|
||||
wxLogTrace( traceSchLegacyPlugin, "Append \"%s\" to sheet \"%s\".",
|
||||
wxLogTrace( traceSchPlugin, "Append \"%s\" to sheet \"%s\".",
|
||||
aFileName, aAppendToMe->GetFileName() );
|
||||
|
||||
wxFileName normedFn = aAppendToMe->GetFileName();
|
||||
@@ -550,7 +550,7 @@ SCH_SHEET* SCH_SEXPR_PLUGIN::Load( const wxString& aFileName, SCHEMATIC* aSchema
|
||||
if( m_path.IsEmpty() )
|
||||
m_path = aSchematic->Prj().GetProjectPath();
|
||||
|
||||
wxLogTrace( traceSchLegacyPlugin, "Normalized append path \"%s\".", m_path );
|
||||
wxLogTrace( traceSchPlugin, "Normalized append path \"%s\".", m_path );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -598,6 +598,8 @@ SCH_SHEET* SCH_SEXPR_PLUGIN::Load( const wxString& aFileName, SCHEMATIC* aSchema
|
||||
|
||||
void SCH_SEXPR_PLUGIN::loadHierarchy( const SCH_SHEET_PATH& aParentSheetPath, SCH_SHEET* aSheet )
|
||||
{
|
||||
m_currentSheetPath.push_back( aSheet );
|
||||
|
||||
SCH_SCREEN* screen = nullptr;
|
||||
|
||||
if( !aSheet->GetScreen() )
|
||||
@@ -613,10 +615,10 @@ void SCH_SEXPR_PLUGIN::loadHierarchy( const SCH_SHEET_PATH& aParentSheetPath, SC
|
||||
// Save the current path so that it gets restored when descending and ascending the
|
||||
// sheet hierarchy which allows for sheet schematic files to be nested in folders
|
||||
// relative to the last path a schematic was loaded from.
|
||||
wxLogTrace( traceSchLegacyPlugin, "Saving path '%s'", m_currentPath.top() );
|
||||
wxLogTrace( traceSchPlugin, "Saving path '%s'", m_currentPath.top() );
|
||||
m_currentPath.push( fileName.GetPath() );
|
||||
wxLogTrace( traceSchLegacyPlugin, "Current path '%s'", m_currentPath.top() );
|
||||
wxLogTrace( traceSchLegacyPlugin, "Loading '%s'", fileName.GetFullPath() );
|
||||
wxLogTrace( traceSchPlugin, "Current path '%s'", m_currentPath.top() );
|
||||
wxLogTrace( traceSchPlugin, "Loading '%s'", fileName.GetFullPath() );
|
||||
|
||||
SCH_SHEET_PATH ancestorSheetPath = aParentSheetPath;
|
||||
|
||||
@@ -645,7 +647,12 @@ void SCH_SEXPR_PLUGIN::loadHierarchy( const SCH_SHEET_PATH& aParentSheetPath, SC
|
||||
}
|
||||
|
||||
if( ancestorSheetPath.empty() )
|
||||
m_rootSheet->SearchHierarchy( fileName.GetFullPath(), &screen );
|
||||
{
|
||||
// Existing schematics could be either in the root sheet path or the current sheet
|
||||
// load path so we have to check both.
|
||||
if( !m_rootSheet->SearchHierarchy( fileName.GetFullPath(), &screen ) )
|
||||
m_currentSheetPath.at( 0 )->SearchHierarchy( fileName.GetFullPath(), &screen );
|
||||
}
|
||||
|
||||
if( screen )
|
||||
{
|
||||
@@ -702,8 +709,10 @@ void SCH_SEXPR_PLUGIN::loadHierarchy( const SCH_SHEET_PATH& aParentSheetPath, SC
|
||||
}
|
||||
|
||||
m_currentPath.pop();
|
||||
wxLogTrace( traceSchLegacyPlugin, "Restoring path \"%s\"", m_currentPath.top() );
|
||||
wxLogTrace( traceSchPlugin, "Restoring path \"%s\"", m_currentPath.top() );
|
||||
}
|
||||
|
||||
m_currentSheetPath.pop_back();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -167,6 +167,7 @@ protected:
|
||||
wxString m_path; ///< Root project path for loading child sheets.
|
||||
std::stack<wxString> m_currentPath; ///< Stack to maintain nested sheet paths
|
||||
SCH_SHEET* m_rootSheet; ///< The root sheet of the schematic being loaded.
|
||||
SCH_SHEET_PATH m_currentSheetPath;
|
||||
SCHEMATIC* m_schematic;
|
||||
OUTPUTFORMATTER* m_out; ///< The formatter for saving SCH_SCREEN objects.
|
||||
SCH_SEXPR_PLUGIN_CACHE* m_cache;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 CERN
|
||||
* Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2016-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Wayne Stambaugh <stambaughw@gmail.com>
|
||||
*
|
||||
@@ -4024,14 +4024,20 @@ void SCH_LEGACY_PLUGIN_CACHE::saveBezier( LIB_SHAPE* aBezier, OUTPUTFORMATTER& a
|
||||
{
|
||||
wxCHECK_RET( aBezier && aBezier->GetShape() == SHAPE_T::BEZIER, "Invalid BEZIER object." );
|
||||
|
||||
aFormatter.Print( 0, "B %u %d %d %d",
|
||||
(unsigned)aBezier->GetBezierPoints().size(),
|
||||
aFormatter.Print( 0, "B 4 %d %d %d",
|
||||
aBezier->GetUnit(),
|
||||
aBezier->GetConvert(),
|
||||
Iu2Mils( aBezier->GetWidth() ) );
|
||||
|
||||
for( const wxPoint& pt : aBezier->GetBezierPoints() )
|
||||
aFormatter.Print( 0, " %d %d", Iu2Mils( pt.x ), Iu2Mils( pt.y ) );
|
||||
aFormatter.Print( 0, " %d %d %d %d %d %d %d %d",
|
||||
Iu2Mils( aBezier->GetStart().x ),
|
||||
Iu2Mils( aBezier->GetStart().y ),
|
||||
Iu2Mils( aBezier->GetBezierC1().x ),
|
||||
Iu2Mils( aBezier->GetBezierC1().y ),
|
||||
Iu2Mils( aBezier->GetBezierC2().x ),
|
||||
Iu2Mils( aBezier->GetBezierC2().y ),
|
||||
Iu2Mils( aBezier->GetEnd().x ),
|
||||
Iu2Mils( aBezier->GetEnd().y ) );
|
||||
|
||||
aFormatter.Print( 0, " %c\n", fill_tab[ static_cast<int>( aBezier->GetFillType() ) - 1 ] );
|
||||
}
|
||||
|
||||
+87
-35
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2023 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
|
||||
@@ -145,14 +145,14 @@ bool SCH_SCREEN::ClassOf( const EDA_ITEM* aItem )
|
||||
}
|
||||
|
||||
|
||||
void SCH_SCREEN::Append( SCH_ITEM* aItem )
|
||||
void SCH_SCREEN::Append( SCH_ITEM* aItem, bool aUpdateLibSymbol )
|
||||
{
|
||||
if( aItem->Type() != SCH_SHEET_PIN_T && aItem->Type() != SCH_FIELD_T )
|
||||
{
|
||||
// Ensure the item can reach the SCHEMATIC through this screen
|
||||
aItem->SetParent( this );
|
||||
|
||||
if( aItem->Type() == SCH_SYMBOL_T )
|
||||
if( aItem->Type() == SCH_SYMBOL_T && aUpdateLibSymbol )
|
||||
{
|
||||
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( aItem );
|
||||
|
||||
@@ -179,30 +179,63 @@ void SCH_SCREEN::Append( SCH_ITEM* aItem )
|
||||
|
||||
if( *foundSymbol != *symbol->GetLibSymbolRef() )
|
||||
{
|
||||
int cnt = 1;
|
||||
wxString newName;
|
||||
std::vector<wxString> matches;
|
||||
|
||||
newName.Printf( wxT( "%s_%d" ), symbol->GetLibId().GetUniStringLibItemName(),
|
||||
cnt );
|
||||
getLibSymbolNameMatches( *symbol, matches );
|
||||
foundSymbol = nullptr;
|
||||
|
||||
while( m_libSymbols.find( newName ) != m_libSymbols.end() )
|
||||
for( const wxString& libSymbolName : matches )
|
||||
{
|
||||
cnt += 1;
|
||||
newName.Printf( wxT( "%s_%d" ), symbol->GetLibId().GetUniStringLibItemName(),
|
||||
cnt );
|
||||
it = m_libSymbols.find( libSymbolName );
|
||||
|
||||
if( it == m_libSymbols.end() )
|
||||
continue;
|
||||
|
||||
foundSymbol = it->second;
|
||||
|
||||
wxCHECK2( foundSymbol, continue );
|
||||
|
||||
if( *foundSymbol == *symbol->GetLibSymbolRef() )
|
||||
{
|
||||
newName = libSymbolName;
|
||||
break;
|
||||
}
|
||||
|
||||
foundSymbol = nullptr;
|
||||
}
|
||||
|
||||
if( !foundSymbol )
|
||||
{
|
||||
int cnt = 1;
|
||||
|
||||
newName.Printf( wxT( "%s_%d" ),
|
||||
symbol->GetLibId().GetUniStringLibItemName(),
|
||||
cnt );
|
||||
|
||||
while( m_libSymbols.find( newName ) != m_libSymbols.end() )
|
||||
{
|
||||
cnt += 1;
|
||||
newName.Printf( wxT( "%s_%d" ),
|
||||
symbol->GetLibId().GetUniStringLibItemName(),
|
||||
cnt );
|
||||
}
|
||||
}
|
||||
|
||||
// Update the schematic symbol library link as this symbol only exists
|
||||
// in the schematic.
|
||||
symbol->SetSchSymbolLibraryName( newName );
|
||||
|
||||
LIB_SYMBOL* newLibSymbol = new LIB_SYMBOL( *symbol->GetLibSymbolRef() );
|
||||
LIB_ID newLibId( wxEmptyString, newName );
|
||||
if( !foundSymbol )
|
||||
{
|
||||
// Update the schematic symbol library link as this symbol does not
|
||||
// exist in any symbol library.
|
||||
LIB_ID newLibId( wxEmptyString, newName );
|
||||
LIB_SYMBOL* newLibSymbol = new LIB_SYMBOL( *symbol->GetLibSymbolRef() );
|
||||
|
||||
newLibSymbol->SetLibId( newLibId );
|
||||
newLibSymbol->SetName( newName );
|
||||
symbol->SetLibSymbol( newLibSymbol->Flatten().release() );
|
||||
m_libSymbols[newName] = newLibSymbol;
|
||||
newLibSymbol->SetLibId( newLibId );
|
||||
newLibSymbol->SetName( newName );
|
||||
symbol->SetLibSymbol( newLibSymbol->Flatten().release() );
|
||||
m_libSymbols[newName] = newLibSymbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -265,19 +298,19 @@ void SCH_SCREEN::FreeDrawList()
|
||||
}
|
||||
|
||||
|
||||
void SCH_SCREEN::Update( SCH_ITEM* aItem )
|
||||
void SCH_SCREEN::Update( SCH_ITEM* aItem, bool aUpdateLibSymbol )
|
||||
{
|
||||
if( Remove( aItem ) )
|
||||
Append( aItem );
|
||||
if( Remove( aItem, aUpdateLibSymbol ) )
|
||||
Append( aItem, aUpdateLibSymbol );
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SCREEN::Remove( SCH_ITEM* aItem )
|
||||
bool SCH_SCREEN::Remove( SCH_ITEM* aItem, bool aUpdateLibSymbol )
|
||||
{
|
||||
bool retv = m_rtree.remove( aItem );
|
||||
|
||||
// Check if the library symbol for the removed schematic symbol is still required.
|
||||
if( retv && aItem->Type() == SCH_SYMBOL_T )
|
||||
if( retv && aItem->Type() == SCH_SYMBOL_T && aUpdateLibSymbol )
|
||||
{
|
||||
SCH_SYMBOL* removedSymbol = static_cast<SCH_SYMBOL*>( aItem );
|
||||
|
||||
@@ -947,20 +980,16 @@ LIB_PIN* SCH_SCREEN::GetPin( const wxPoint& aPosition, SCH_SYMBOL** aSymbol,
|
||||
if( !candidate->GetLibSymbolRef() )
|
||||
continue;
|
||||
|
||||
for( pin = candidate->GetLibSymbolRef()->GetNextPin(); pin;
|
||||
pin = candidate->GetLibSymbolRef()->GetNextPin( pin ) )
|
||||
std::vector<LIB_PIN*> pins;
|
||||
candidate->GetLibPins( pins );
|
||||
|
||||
for( LIB_PIN* test_pin : pins )
|
||||
{
|
||||
// Skip items not used for this part.
|
||||
if( candidate->GetUnit() && pin->GetUnit() &&
|
||||
( pin->GetUnit() != candidate->GetUnit() ) )
|
||||
continue;
|
||||
|
||||
if( candidate->GetConvert() && pin->GetConvert() &&
|
||||
( pin->GetConvert() != candidate->GetConvert() ) )
|
||||
continue;
|
||||
|
||||
if( candidate->GetPinPhysicalPosition( pin ) == aPosition )
|
||||
if( candidate->GetPinPhysicalPosition( test_pin ) == aPosition )
|
||||
{
|
||||
pin = test_pin;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( pin )
|
||||
@@ -1202,6 +1231,29 @@ void SCH_SCREEN::SetLegacySymbolInstanceData()
|
||||
}
|
||||
|
||||
|
||||
size_t SCH_SCREEN::getLibSymbolNameMatches( const SCH_SYMBOL& aSymbol,
|
||||
std::vector<wxString>& aMatches )
|
||||
{
|
||||
wxString searchName = aSymbol.GetLibId().GetUniStringLibId();
|
||||
|
||||
if( m_libSymbols.find( searchName ) != m_libSymbols.end() )
|
||||
aMatches.emplace_back( searchName );
|
||||
|
||||
searchName = aSymbol.GetLibId().GetUniStringLibItemName() + wxS( "_" );
|
||||
|
||||
long tmp;
|
||||
wxString suffix;
|
||||
|
||||
for( auto pair : m_libSymbols )
|
||||
{
|
||||
if( pair.first.StartsWith( searchName, &suffix ) && suffix.ToLong( &tmp ) )
|
||||
aMatches.emplace_back( pair.first );
|
||||
}
|
||||
|
||||
return aMatches.size();
|
||||
}
|
||||
|
||||
|
||||
#if defined(DEBUG)
|
||||
void SCH_SCREEN::Show( int nestLevel, std::ostream& os ) const
|
||||
{
|
||||
|
||||
+23
-6
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
|
||||
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2023 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
|
||||
@@ -181,7 +181,7 @@ public:
|
||||
return m_clientSheetPathList;
|
||||
}
|
||||
|
||||
void Append( SCH_ITEM* aItem );
|
||||
void Append( SCH_ITEM* aItem, bool aUpdateLibSymbol = true );
|
||||
|
||||
/**
|
||||
* Copy the contents of \a aScreen into this #SCH_SCREEN object.
|
||||
@@ -264,16 +264,18 @@ public:
|
||||
*
|
||||
* @note The removed item is not deleted. It is only unlinked from the item list.
|
||||
* @param[in] aItem Item to be removed from schematic.
|
||||
* @param aUpdateLibSymbol removes the library symbol as required when true.
|
||||
* @return True if we successfully removed the item
|
||||
*/
|
||||
bool Remove( SCH_ITEM* aItem );
|
||||
bool Remove( SCH_ITEM* aItem, bool aUpdateLibSymbol = true );
|
||||
|
||||
/**
|
||||
* Update \a aItem's bounding box in the tree
|
||||
*
|
||||
* @param[in] aItem Item that needs to be updated.
|
||||
* @param aUpdateLibSymbol removes the library symbol as required when true.
|
||||
*/
|
||||
void Update( SCH_ITEM* aItem );
|
||||
void Update( SCH_ITEM* aItem, bool aUpdateLibSymbol = true );
|
||||
|
||||
/**
|
||||
* Removes \a aItem from the linked list and deletes the object.
|
||||
@@ -516,13 +518,28 @@ private:
|
||||
bool doIsJunction( const wxPoint& aPosition, bool aBreakCrossings,
|
||||
bool* aHasExplicitJunctionDot, bool* aHasBusEntry ) const;
|
||||
|
||||
void clearLibSymbols();
|
||||
|
||||
/**
|
||||
* Return a list of potential library symbol matches for \a aSymbol.
|
||||
*
|
||||
* When and existing library symbol named with the full #LIB_ID object is found, there may
|
||||
* be more potential matches if the #SCH_SCREEN::Append() method need to create an alternate
|
||||
* symbol due to differences from the original symbol. This process creates a new library
|
||||
* symbol name by adding a "_#" suffix to the existing #LIB_ID item name.
|
||||
*
|
||||
* @param[in] aSymbol is the schematic symbol to search for potential library symbol matches.
|
||||
* @param[out] aMatches contains library cache names of all of the potential matches.
|
||||
*
|
||||
* @return the number of potential matches found for \a aSymbol.
|
||||
*/
|
||||
size_t getLibSymbolNameMatches( const SCH_SYMBOL& aSymbol, std::vector<wxString>& aMatches );
|
||||
|
||||
private:
|
||||
friend SCH_EDIT_FRAME; // Only to populate m_symbolInstances.
|
||||
friend SCH_SEXPR_PARSER; // Only to load instance information from schematic file.
|
||||
friend SCH_SEXPR_PLUGIN; // Only to save the loaded instance information to schematic file.
|
||||
|
||||
void clearLibSymbols();
|
||||
|
||||
wxString m_fileName; // File used to load the screen.
|
||||
int m_fileFormatVersionAtLoad;
|
||||
int m_refCount; // Number of sheets referencing this screen.
|
||||
|
||||
+3
-18
@@ -52,11 +52,6 @@
|
||||
|
||||
const wxString SCH_SHEET::GetDefaultFieldName( int aFieldNdx, bool aTranslated )
|
||||
{
|
||||
static void* locale = nullptr;
|
||||
static wxString sheetnameDefault;
|
||||
static wxString sheetfilenameDefault;
|
||||
static wxString userFieldDefault;
|
||||
|
||||
if( !aTranslated )
|
||||
{
|
||||
switch( aFieldNdx )
|
||||
@@ -67,22 +62,12 @@ const wxString SCH_SHEET::GetDefaultFieldName( int aFieldNdx, bool aTranslated )
|
||||
}
|
||||
}
|
||||
|
||||
// Fetching translations can take a surprising amount of time when loading libraries,
|
||||
// so only do it when necessary.
|
||||
if( Pgm().GetLocale() != locale )
|
||||
{
|
||||
sheetnameDefault = _( SHEET_NAME_CANONICAL );
|
||||
sheetfilenameDefault = _( SHEET_FILE_CANONICAL );
|
||||
userFieldDefault = _( USER_FIELD_CANONICAL );
|
||||
locale = Pgm().GetLocale();
|
||||
}
|
||||
|
||||
// Fixed values for the mandatory fields
|
||||
switch( aFieldNdx )
|
||||
{
|
||||
case SHEETNAME: return sheetnameDefault;
|
||||
case SHEETFILENAME: return sheetfilenameDefault;
|
||||
default: return wxString::Format( userFieldDefault, aFieldNdx );
|
||||
case SHEETNAME: return _( SHEET_NAME_CANONICAL );
|
||||
case SHEETFILENAME: return _( SHEET_FILE_CANONICAL );
|
||||
default: return wxString::Format( _( USER_FIELD_CANONICAL ), aFieldNdx );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2023 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
|
||||
@@ -310,7 +310,7 @@ void SCH_SHEET_PATH::UpdateAllScreenReferences()
|
||||
symbol->GetField( VALUE_FIELD )->SetText( symbol->GetValue( this, false ) );
|
||||
symbol->GetField( FOOTPRINT_FIELD )->SetText( symbol->GetFootprint( this, false ) );
|
||||
symbol->UpdateUnit( symbol->GetUnitSelection( this ) );
|
||||
LastScreen()->Update( item );
|
||||
LastScreen()->Update( item, false );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -335,10 +335,12 @@ void SCH_SYMBOL::UpdatePins()
|
||||
|
||||
unsigned i = 0;
|
||||
|
||||
for( LIB_PIN* libPin = m_part->GetNextPin(); libPin; libPin = m_part->GetNextPin( libPin ) )
|
||||
{
|
||||
wxASSERT( libPin->Type() == LIB_PIN_T );
|
||||
std::vector<LIB_PIN*> pins = m_part->GetAllLibPins();
|
||||
|
||||
for( LIB_PIN* libPin : pins )
|
||||
{
|
||||
// NW: Don't filter by unit: this data-structure is used for all instances,
|
||||
// some if which might have different units.
|
||||
if( libPin->GetConvert() && m_convert && ( m_convert != libPin->GetConvert() ) )
|
||||
continue;
|
||||
|
||||
|
||||
@@ -665,6 +665,26 @@ wxString SCH_TEXT::GetShownText( int aDepth, bool aAllowExtraText ) const
|
||||
}
|
||||
|
||||
|
||||
bool SCH_TEXT::Matches( const wxFindReplaceData& aSearchData, void* aAuxData ) const
|
||||
{
|
||||
return SCH_ITEM::Matches( UnescapeString( GetText() ), aSearchData );
|
||||
}
|
||||
|
||||
|
||||
bool SCH_TEXT::Replace( const wxFindReplaceData& aSearchData, void* aAuxData )
|
||||
{
|
||||
wxFindReplaceData localSearchData( aSearchData );
|
||||
|
||||
if( Type() == SCH_LABEL_T || Type() == SCH_HIER_LABEL_T || Type() == SCH_GLOBAL_LABEL_T )
|
||||
{
|
||||
localSearchData.SetFindString( EscapeString( aSearchData.GetFindString(), CTX_NETNAME ) );
|
||||
localSearchData.SetReplaceString( EscapeString( aSearchData.GetReplaceString(), CTX_NETNAME ) );
|
||||
}
|
||||
|
||||
return EDA_TEXT::Replace( localSearchData );
|
||||
}
|
||||
|
||||
|
||||
wxString SCH_TEXT::GetSelectMenuText( EDA_UNITS aUnits ) const
|
||||
{
|
||||
return wxString::Format( _( "Graphic Text '%s'" ), ShortenedShownText() );
|
||||
|
||||
+2
-9
@@ -210,15 +210,8 @@ public:
|
||||
virtual void Rotate90( bool aClockwise );
|
||||
virtual void MirrorSpinStyle( bool aLeftRight );
|
||||
|
||||
bool Matches( const wxFindReplaceData& aSearchData, void* aAuxData ) const override
|
||||
{
|
||||
return SCH_ITEM::Matches( GetText(), aSearchData );
|
||||
}
|
||||
|
||||
bool Replace( const wxFindReplaceData& aSearchData, void* aAuxData ) override
|
||||
{
|
||||
return EDA_TEXT::Replace( aSearchData );
|
||||
}
|
||||
bool Matches( const wxFindReplaceData& aSearchData, void* aAuxData ) const override;
|
||||
bool Replace( const wxFindReplaceData& aSearchData, void* aAuxData ) override;
|
||||
|
||||
virtual bool IsReplaceable() const override { return true; }
|
||||
|
||||
|
||||
@@ -714,6 +714,8 @@ void SYMBOL_EDIT_FRAME::saveSymbolAs()
|
||||
return;
|
||||
}
|
||||
|
||||
new_name = EscapeString( new_name, CTX_LIBID );
|
||||
|
||||
// Test if there is a symbol with this name already.
|
||||
if( m_libMgr->SymbolExists( new_name, new_lib ) )
|
||||
{
|
||||
|
||||
@@ -676,7 +676,7 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
|
||||
m_toolMgr->RunAction( EE_ACTIONS::trimOverlappingWires, true, &selectionCopy );
|
||||
m_toolMgr->RunAction( EE_ACTIONS::addNeededJunctions, true, &selectionCopy );
|
||||
|
||||
m_frame->RecalculateConnections( LOCAL_CLEANUP );
|
||||
m_frame->SchematicCleanUp();
|
||||
m_frame->TestDanglingEnds();
|
||||
|
||||
m_frame->OnModify();
|
||||
@@ -920,7 +920,7 @@ int SCH_EDIT_TOOL::RepeatDrawItem( const TOOL_EVENT& aEvent )
|
||||
m_toolMgr->RunAction( EE_ACTIONS::trimOverlappingWires, true, &new_sel );
|
||||
m_toolMgr->RunAction( EE_ACTIONS::addNeededJunctions, true, &new_sel );
|
||||
|
||||
m_frame->RecalculateConnections( LOCAL_CLEANUP );
|
||||
m_frame->SchematicCleanUp();
|
||||
m_frame->TestDanglingEnds();
|
||||
}
|
||||
|
||||
@@ -1122,7 +1122,11 @@ void SCH_EDIT_TOOL::editFieldText( SCH_FIELD* aField )
|
||||
|
||||
// Use title caps for mandatory fields. "Edit Sheet name Field" looks dorky.
|
||||
if( parentType == SCH_SYMBOL_T && aField->GetId() < MANDATORY_FIELDS )
|
||||
caption.Printf( _( "Edit %s Field" ), TitleCaps( aField->GetName() ) );
|
||||
{
|
||||
wxString translated_fieldname;
|
||||
translated_fieldname = TEMPLATE_FIELDNAME::GetDefaultFieldName( aField->GetId(), DO_TRANSLATE );
|
||||
caption.Printf( _( "Edit %s Field" ), TitleCaps( translated_fieldname ) );
|
||||
}
|
||||
else if( parentType == SCH_SHEET_T && aField->GetId() < SHEET_MANDATORY_FIELDS )
|
||||
caption.Printf( _( "Edit %s Field" ), TitleCaps( aField->GetName() ) );
|
||||
else
|
||||
|
||||
@@ -228,9 +228,6 @@ int SCH_EDITOR_CONTROL::RemapSymbols( const TOOL_EVENT& aEvent )
|
||||
|
||||
int SCH_EDITOR_CONTROL::Print( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
if( !ADVANCED_CFG::GetCfg().m_RealTimeConnectivity || !CONNECTION_GRAPH::m_allowRealTime )
|
||||
m_frame->RecalculateConnections( NO_CLEANUP );
|
||||
|
||||
InvokeDialogPrintUsingPrinter( m_frame );
|
||||
|
||||
wxFileName fn = m_frame->Prj().AbsolutePath( m_frame->Schematic().RootScreen()->GetFileName() );
|
||||
@@ -244,9 +241,6 @@ int SCH_EDITOR_CONTROL::Print( const TOOL_EVENT& aEvent )
|
||||
|
||||
int SCH_EDITOR_CONTROL::Plot( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
if( !ADVANCED_CFG::GetCfg().m_RealTimeConnectivity || !CONNECTION_GRAPH::m_allowRealTime )
|
||||
m_frame->RecalculateConnections( NO_CLEANUP );
|
||||
|
||||
DIALOG_PLOT_SCHEMATIC dlg( m_frame );
|
||||
|
||||
dlg.ShowModal();
|
||||
@@ -346,15 +340,32 @@ SCH_ITEM* SCH_EDITOR_CONTROL::nextMatch( SCH_SCREEN* aScreen, SCH_SHEET_PATH* aS
|
||||
if( aAfter != nullptr )
|
||||
{
|
||||
past_item = false;
|
||||
|
||||
if( aAfter->Type() == SCH_PIN_T || aAfter->Type() == SCH_FIELD_T )
|
||||
aAfter = static_cast<SCH_ITEM*>( aAfter->GetParent() );
|
||||
}
|
||||
|
||||
std::vector<SCH_ITEM*> sorted_items;
|
||||
|
||||
for( SCH_ITEM* item : aScreen->Items() )
|
||||
{
|
||||
if( SCH_SYMBOL* sym = dyn_cast<SCH_SYMBOL*>( item ) )
|
||||
{
|
||||
for( SCH_FIELD& field : sym->GetFields() )
|
||||
sorted_items.push_back( &field );
|
||||
|
||||
for( SCH_PIN* pin : sym->GetPins() )
|
||||
sorted_items.push_back( pin );
|
||||
}
|
||||
|
||||
if( SCH_SHEET* sheet = dyn_cast<SCH_SHEET*>( item ) )
|
||||
{
|
||||
for( SCH_FIELD& field : sheet->GetFields() )
|
||||
sorted_items.push_back( &field );
|
||||
|
||||
for( SCH_SHEET_PIN* pin : sheet->GetPins() )
|
||||
sorted_items.push_back( pin );
|
||||
}
|
||||
|
||||
sorted_items.push_back( item );
|
||||
}
|
||||
|
||||
std::sort( sorted_items.begin(), sorted_items.end(),
|
||||
[&]( SCH_ITEM* a, SCH_ITEM* b )
|
||||
@@ -385,40 +396,6 @@ SCH_ITEM* SCH_EDITOR_CONTROL::nextMatch( SCH_SCREEN* aScreen, SCH_SHEET_PATH* aS
|
||||
|
||||
if( item->Matches( aData, aSheet ) )
|
||||
return item;
|
||||
|
||||
if( item->Type() == SCH_SYMBOL_T )
|
||||
{
|
||||
SCH_SYMBOL* cmp = static_cast<SCH_SYMBOL*>( item );
|
||||
|
||||
for( SCH_FIELD& field : cmp->GetFields() )
|
||||
{
|
||||
if( field.Matches( aData, aSheet ) )
|
||||
return &field;
|
||||
}
|
||||
|
||||
for( SCH_PIN* pin : cmp->GetPins() )
|
||||
{
|
||||
if( pin->Matches( aData, aSheet ) )
|
||||
return pin;
|
||||
}
|
||||
}
|
||||
|
||||
if( item->Type() == SCH_SHEET_T )
|
||||
{
|
||||
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
|
||||
|
||||
for( SCH_FIELD& field : sheet->GetFields() )
|
||||
{
|
||||
if( field.Matches( aData, aSheet ) )
|
||||
return &field;
|
||||
}
|
||||
|
||||
for( SCH_SHEET_PIN* pin : sheet->GetPins() )
|
||||
{
|
||||
if( pin->Matches( aData, aSheet ) )
|
||||
return pin;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1061,10 +1038,6 @@ int SCH_EDITOR_CONTROL::AssignNetclass( const TOOL_EVENT& aEvent )
|
||||
KIGFX::VIEW_CONTROLS* controls = getViewControls();
|
||||
VECTOR2D cursorPos = controls->GetCursorPosition( !aEvent.DisableGridSnapping() );
|
||||
|
||||
// TODO remove once real-time connectivity is a given
|
||||
if( !ADVANCED_CFG::GetCfg().m_RealTimeConnectivity || !CONNECTION_GRAPH::m_allowRealTime )
|
||||
// Ensure the netlist data is up to date:
|
||||
m_frame->RecalculateConnections( NO_CLEANUP );
|
||||
|
||||
// Remove selection in favor of highlighting so the whole net is highlighted
|
||||
selectionTool->ClearSelection();
|
||||
@@ -1314,10 +1287,6 @@ int SCH_EDITOR_CONTROL::UpdateNetHighlighting( const TOOL_EVENT& aEvent )
|
||||
|
||||
int SCH_EDITOR_CONTROL::HighlightNetCursor( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
// TODO(JE) remove once real-time connectivity is a given
|
||||
if( !ADVANCED_CFG::GetCfg().m_RealTimeConnectivity || !CONNECTION_GRAPH::m_allowRealTime )
|
||||
m_frame->RecalculateConnections( NO_CLEANUP );
|
||||
|
||||
std::string tool = aEvent.GetCommandStr().get();
|
||||
PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>();
|
||||
|
||||
@@ -2090,9 +2059,7 @@ int SCH_EDITOR_CONTROL::GenerateBOM( const TOOL_EVENT& aEvent )
|
||||
|
||||
int SCH_EDITOR_CONTROL::DrawSheetOnClipboard( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
if( !ADVANCED_CFG::GetCfg().m_RealTimeConnectivity || !CONNECTION_GRAPH::m_allowRealTime )
|
||||
m_frame->RecalculateConnections( LOCAL_CLEANUP );
|
||||
|
||||
m_frame->RecalculateConnections( LOCAL_CLEANUP );
|
||||
m_frame->DrawCurrentSheetToClipboard();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -93,7 +93,6 @@ protected:
|
||||
private:
|
||||
void update() override
|
||||
{
|
||||
SCH_EDIT_FRAME* frame = (SCH_EDIT_FRAME*) getToolManager()->GetToolHolder();
|
||||
EE_SELECTION_TOOL* selTool = getToolManager()->GetTool<EE_SELECTION_TOOL>();
|
||||
KICAD_T busType[] = { SCH_LINE_LOCATE_BUS_T, EOT };
|
||||
EE_SELECTION& selection = selTool->RequestSelection( busType );
|
||||
@@ -101,16 +100,6 @@ private:
|
||||
|
||||
Clear();
|
||||
|
||||
// TODO(JE) remove once real-time is enabled
|
||||
if( !ADVANCED_CFG::GetCfg().m_RealTimeConnectivity || !CONNECTION_GRAPH::m_allowRealTime )
|
||||
{
|
||||
frame->RecalculateConnections( NO_CLEANUP );
|
||||
|
||||
// Pick up the pointer again because it may have been changed by SchematicCleanUp
|
||||
selection = selTool->RequestSelection( busType );
|
||||
bus = (SCH_LINE*) selection.Front();
|
||||
}
|
||||
|
||||
if( !bus )
|
||||
{
|
||||
Append( ID_POPUP_SCH_UNFOLD_BUS, _( "No bus selected" ), wxEmptyString );
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
|
||||
SCH_MOVE_TOOL::SCH_MOVE_TOOL() :
|
||||
EE_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.InteractiveMove" ),
|
||||
m_inMoveTool( false ),
|
||||
m_moveInProgress( false ),
|
||||
m_isDrag( false ),
|
||||
m_moveOffset( 0, 0 )
|
||||
@@ -126,6 +127,11 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( m_inMoveTool ) // Must come after m_moveInProgress checks above...
|
||||
return 0;
|
||||
|
||||
REENTRANCY_GUARD guard( &m_inMoveTool );
|
||||
|
||||
// Be sure that there is at least one item that we can move. If there's no selection try
|
||||
// looking for the stuff under mouse cursor (i.e. Kicad old-style hover selection).
|
||||
EE_SELECTION& selection = m_selectionTool->RequestSelection( EE_COLLECTOR::MovableItems );
|
||||
@@ -528,7 +534,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
m_toolMgr->RunAction( EE_ACTIONS::trimOverlappingWires, true, &selectionCopy );
|
||||
m_toolMgr->RunAction( EE_ACTIONS::addNeededJunctions, true, &selectionCopy );
|
||||
|
||||
m_frame->RecalculateConnections( LOCAL_CLEANUP );
|
||||
m_frame->SchematicCleanUp();
|
||||
m_frame->TestDanglingEnds();
|
||||
|
||||
m_frame->OnModify();
|
||||
@@ -1003,7 +1009,7 @@ int SCH_MOVE_TOOL::AlignElements( const TOOL_EVENT& aEvent )
|
||||
m_toolMgr->RunAction( EE_ACTIONS::trimOverlappingWires, true, &selection );
|
||||
m_toolMgr->RunAction( EE_ACTIONS::addNeededJunctions, true, &selection );
|
||||
|
||||
m_frame->RecalculateConnections( LOCAL_CLEANUP );
|
||||
m_frame->SchematicCleanUp();
|
||||
m_frame->TestDanglingEnds();
|
||||
|
||||
m_frame->OnModify();
|
||||
|
||||
@@ -81,6 +81,9 @@ private:
|
||||
void setTransitions() override;
|
||||
|
||||
private:
|
||||
///< Re-entrancy guard
|
||||
bool m_inMoveTool;
|
||||
|
||||
///< Flag determining if anything is being dragged right now
|
||||
bool m_moveInProgress;
|
||||
bool m_isDrag;
|
||||
|
||||
@@ -457,8 +457,8 @@ int SYMBOL_EDITOR_CONTROL::ExportSymbolAsSVG( const TOOL_EVENT& aEvent )
|
||||
editFrame->GetConvert() ).GetSize();
|
||||
|
||||
// Add a small margin to the plot bounding box
|
||||
pageTemp.SetWidthMils( int( symbolSize.x * 1.2 ) );
|
||||
pageTemp.SetHeightMils( int( symbolSize.y * 1.2 ) );
|
||||
pageTemp.SetWidthMils( Iu2Mils( symbolSize.x * 1.2 ) );
|
||||
pageTemp.SetHeightMils( Iu2Mils( symbolSize.y * 1.2 ) );
|
||||
|
||||
editFrame->GetScreen()->SetPageSettings( pageTemp );
|
||||
editFrame->SVGPlotSymbol( fullFileName );
|
||||
|
||||
@@ -536,10 +536,15 @@ int SYMBOL_EDITOR_DRAWING_TOOLS::RepeatDrawItem( const TOOL_EVENT& aEvent )
|
||||
return 0;
|
||||
|
||||
// See if we have a pin matching our weak ptr
|
||||
for( LIB_PIN* test = symbol->GetNextPin(); test; test = symbol->GetNextPin( test ) )
|
||||
std::vector<LIB_PIN*> pins = symbol->GetAllLibPins();
|
||||
|
||||
for( LIB_PIN* test : pins )
|
||||
{
|
||||
if( (void*) test == g_lastPinWeakPtr )
|
||||
{
|
||||
sourcePin = test;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( sourcePin )
|
||||
|
||||
@@ -282,30 +282,27 @@ int SYMBOL_EDITOR_EDIT_TOOL::DoDelete( const TOOL_EVENT& aEvent )
|
||||
int curr_convert = pin->GetConvert();
|
||||
ELECTRICAL_PINTYPE etype = pin->GetType();
|
||||
wxString name = pin->GetName();
|
||||
LIB_PIN* next_pin = symbol->GetNextPin();
|
||||
std::vector<LIB_PIN*> pins = symbol->GetAllLibPins();
|
||||
|
||||
while( next_pin != nullptr )
|
||||
for( LIB_PIN* test_pin : pins )
|
||||
{
|
||||
pin = next_pin;
|
||||
next_pin = symbol->GetNextPin( pin );
|
||||
|
||||
if( got_unit[pin->GetUnit()] )
|
||||
if( got_unit[test_pin->GetUnit()] )
|
||||
continue;
|
||||
|
||||
if( pin->GetPosition() != pos )
|
||||
if( test_pin->GetPosition() != pos )
|
||||
continue;
|
||||
|
||||
if( pin->GetConvert() != curr_convert )
|
||||
if( test_pin->GetConvert() != curr_convert )
|
||||
continue;
|
||||
|
||||
if( pin->GetType() != etype )
|
||||
if( test_pin->GetType() != etype )
|
||||
continue;
|
||||
|
||||
if( pin->GetName() != name )
|
||||
if( test_pin->GetName() != name )
|
||||
continue;
|
||||
|
||||
toDelete.insert( pin );
|
||||
got_unit[pin->GetUnit()] = true;
|
||||
toDelete.insert( test_pin );
|
||||
got_unit[test_pin->GetUnit()] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,8 +160,9 @@ int SYMBOL_EDITOR_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
|
||||
got_unit[cur_pin->GetUnit()] = true;
|
||||
|
||||
for( LIB_PIN* pin = symbol->GetNextPin(); pin;
|
||||
pin = symbol->GetNextPin( pin ) )
|
||||
std::vector<LIB_PIN*> pins = symbol->GetAllLibPins();
|
||||
|
||||
for( LIB_PIN* pin : pins )
|
||||
{
|
||||
if( !got_unit[pin->GetUnit()]
|
||||
&& pin->GetPosition() == cur_pin->GetPosition()
|
||||
|
||||
@@ -221,7 +221,9 @@ bool SYMBOL_EDITOR_PIN_TOOL::PlacePin( LIB_PIN* aPin )
|
||||
LIB_SYMBOL* symbol = m_frame->GetCurSymbol();
|
||||
bool ask_for_pin = true; // Test for another pin in same position in other units
|
||||
|
||||
for( LIB_PIN* test = symbol->GetNextPin(); test; test = symbol->GetNextPin( test ) )
|
||||
std::vector<LIB_PIN*> pins = symbol->GetAllLibPins();
|
||||
|
||||
for( LIB_PIN* test : pins )
|
||||
{
|
||||
if( test == aPin || aPin->GetPosition() != test->GetPosition() || test->GetEditFlags() )
|
||||
continue;
|
||||
@@ -270,7 +272,7 @@ bool SYMBOL_EDITOR_PIN_TOOL::PlacePin( LIB_PIN* aPin )
|
||||
}
|
||||
|
||||
// Put linked pins in new position, and clear flags
|
||||
for( LIB_PIN* pin = symbol->GetNextPin(); pin; pin = symbol->GetNextPin( pin ) )
|
||||
for( LIB_PIN* pin : pins )
|
||||
{
|
||||
if( ( pin->GetEditFlags() & IS_LINKED ) == 0 )
|
||||
continue;
|
||||
@@ -383,8 +385,9 @@ int SYMBOL_EDITOR_PIN_TOOL::PushPinProperties( const TOOL_EVENT& aEvent )
|
||||
return 0;
|
||||
|
||||
saveCopyInUndoList( symbol, UNDO_REDO::LIBEDIT );
|
||||
std::vector<LIB_PIN*> pins = symbol->GetAllLibPins();
|
||||
|
||||
for( LIB_PIN* pin = symbol->GetNextPin(); pin; pin = symbol->GetNextPin( pin ) )
|
||||
for( LIB_PIN* pin : pins )
|
||||
{
|
||||
if( pin == sourcePin )
|
||||
continue;
|
||||
|
||||
@@ -506,6 +506,9 @@ bool GERBVIEW_FRAME::unarchiveFiles( const wxString& aFullFileName, REPORTER* aR
|
||||
|
||||
while( ( entry = zipArchive.GetNextEntry() ) )
|
||||
{
|
||||
if( entry->IsDir() )
|
||||
continue;
|
||||
|
||||
wxString fname = entry->GetName();
|
||||
wxFileName uzfn = fname;
|
||||
wxString curr_ext = uzfn.GetExt().Lower();
|
||||
|
||||
@@ -107,11 +107,6 @@ public:
|
||||
*/
|
||||
double m_HoleWallThickness;
|
||||
|
||||
/**
|
||||
* Do real-time connectivity
|
||||
*/
|
||||
bool m_RealTimeConnectivity;
|
||||
|
||||
/**
|
||||
* Set the stack size for coroutines
|
||||
*/
|
||||
|
||||
+1
-1
@@ -980,7 +980,7 @@ inline bool IsNetnameLayer( LAYER_NUM aLayer )
|
||||
}
|
||||
|
||||
|
||||
inline bool IsZoneLayer( LAYER_NUM aLayer )
|
||||
inline bool IsZoneFillLayer( int aLayer )
|
||||
{
|
||||
return aLayer >= LAYER_ZONE_START && aLayer <= LAYER_ZONE_END;
|
||||
}
|
||||
|
||||
@@ -221,6 +221,13 @@ public:
|
||||
*/
|
||||
void RunOnDescendants( const std::function<void( BOARD_ITEM* )>& aFunction ) const;
|
||||
|
||||
/**
|
||||
* Check if the proposed type can be added to a group
|
||||
* @param aType KICAD_T type to check
|
||||
* @return true if the type can belong to a group, false otherwise
|
||||
*/
|
||||
static bool IsGroupableType( KICAD_T aType );
|
||||
|
||||
private:
|
||||
std::unordered_set<BOARD_ITEM*> m_items; // Members of the group
|
||||
wxString m_name; // Optional group name
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2014-2020 KiCad Developers, see AUTHORS.TXT for contributors.
|
||||
* Copyright (C) 2014-2022 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
|
||||
@@ -50,6 +50,9 @@ enum MANDATORY_FIELD_T {
|
||||
MANDATORY_FIELDS
|
||||
};
|
||||
|
||||
// A helper to call GetDefaultFieldName with or without translation.
|
||||
// Translation should be used only to display field names in dialogs
|
||||
#define DO_TRANSLATE true
|
||||
|
||||
/**
|
||||
* Hold a name of a symbol's field, field value, and default visibility.
|
||||
@@ -103,9 +106,10 @@ struct TEMPLATE_FIELDNAME
|
||||
* These field names are not modifiable but template field names are.
|
||||
*
|
||||
* @param aFieldNdx The field number index, > 0.
|
||||
* @param aTranslate If true, return the translated field name, else get the canonical name.
|
||||
* @param aTranslateForHI If true, return the translated field name,
|
||||
* else get the canonical name (defualt). Translation is intended only for dialogs
|
||||
*/
|
||||
static const wxString GetDefaultFieldName( int aFieldNdx, bool aTranslate = true );
|
||||
static const wxString GetDefaultFieldName( int aFieldNdx, bool aTranslateForHI = false );
|
||||
|
||||
wxString m_Name; // The field name
|
||||
bool m_Visible; // Field defaults to being visible in schematic.
|
||||
|
||||
@@ -106,6 +106,13 @@ extern const wxChar* const traceAutoSave;
|
||||
*/
|
||||
extern const wxChar* const traceSchLibMem;
|
||||
|
||||
/**
|
||||
* Flag to enable legacy schematic plugin debug output.
|
||||
*
|
||||
* Use "KICAD_SCH_PLUGIN" to enable.
|
||||
*/
|
||||
extern const wxChar* const traceSchPlugin;
|
||||
|
||||
/**
|
||||
* Flag to enable legacy schematic plugin debug output.
|
||||
*
|
||||
|
||||
@@ -151,8 +151,9 @@ private:
|
||||
* It is mostly used for notifying the tools that the cursor position in the world
|
||||
* coordinates has changed, whereas the screen coordinates remained the same (e.g.
|
||||
* frame edge autopanning).
|
||||
* @param aSetModifiers If false, don't change the modifiers (they were set using the keyboard motion)
|
||||
*/
|
||||
void refreshMouse();
|
||||
void refreshMouse( bool aSetModifiers);
|
||||
|
||||
/**
|
||||
* Get the cursor position in the screen coordinates.
|
||||
|
||||
@@ -69,7 +69,8 @@ void KICAD_MANAGER_FRAME::ImportNonKiCadProject( const wxString& aWindowTitle,
|
||||
// OK, we got a new project to open. Time to close any existing project before we go on
|
||||
// to collect info about where to put the new one, etc. Otherwise the workflow is kind of
|
||||
// disjoint.
|
||||
CloseProject( true );
|
||||
if( !CloseProject( true ) )
|
||||
return;
|
||||
|
||||
wxFileName sch( schdlg.GetPath() );
|
||||
sch.SetExt( aSchFileExtension );
|
||||
|
||||
@@ -438,6 +438,12 @@ double SHAPE_ARC::GetLength() const
|
||||
|
||||
double SHAPE_ARC::GetCentralAngle() const
|
||||
{
|
||||
// Arcs with same start and end points can be 0 deg or 360 deg arcs.
|
||||
// However, they are expected to be circles.
|
||||
// So return 360 degrees as central arc:
|
||||
if( m_start == m_end )
|
||||
return 360.0;
|
||||
|
||||
VECTOR2I center = GetCenter();
|
||||
VECTOR2I p0 = m_start - center;
|
||||
VECTOR2I p1 = m_mid - center;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
+4
-2
@@ -239,13 +239,15 @@ std::vector<PCB_MARKER*> BOARD::ResolveDRCExclusions()
|
||||
|
||||
bool BOARD::ResolveTextVar( wxString* token, int aDepth ) const
|
||||
{
|
||||
wxString var = *token;
|
||||
|
||||
if( GetTitleBlock().TextVarResolver( token, m_project ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if( m_properties.count( *token ) )
|
||||
else if( m_properties.count( var ) )
|
||||
{
|
||||
*token = m_properties.at( *token );
|
||||
*token = m_properties.at( var );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -165,8 +165,11 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
|
||||
{
|
||||
case CHT_ADD:
|
||||
{
|
||||
if( selTool->GetEnteredGroup() && !boardItem->GetParentGroup() )
|
||||
if( selTool && selTool->GetEnteredGroup() && !boardItem->GetParentGroup()
|
||||
&& PCB_GROUP::IsGroupableType( boardItem->Type() ) )
|
||||
{
|
||||
selTool->GetEnteredGroup()->AddItem( boardItem );
|
||||
}
|
||||
|
||||
if( m_isFootprintEditor )
|
||||
{
|
||||
|
||||
@@ -70,6 +70,7 @@ DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR(
|
||||
m_solderPasteRatio( aParent, m_PasteMarginRatioLabel, m_PasteMarginRatioCtrl,
|
||||
m_PasteMarginRatioUnits )
|
||||
{
|
||||
SetEvtHandlerEnabled( false );
|
||||
// Create the 3D models page
|
||||
m_3dPanel = new PANEL_FP_PROPERTIES_3D_MODEL( m_frame, m_footprint, this, m_NoteBook );
|
||||
m_NoteBook->AddPage( m_3dPanel, _("3D Models"), false );
|
||||
@@ -145,6 +146,7 @@ DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR(
|
||||
nullptr, this );
|
||||
|
||||
finishDialogSettings();
|
||||
SetEvtHandlerEnabled( true );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ bool DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM
|
||||
|
||||
bool DRC_RULE_CONDITION::Compile( REPORTER* aReporter, int aSourceLine, int aSourceOffset )
|
||||
{
|
||||
PCB_EXPR_COMPILER compiler;
|
||||
PCB_EXPR_COMPILER compiler( new PCB_UNIT_RESOLVER() );
|
||||
|
||||
if( aReporter )
|
||||
{
|
||||
|
||||
@@ -297,6 +297,8 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
|
||||
reportError( msg );
|
||||
}
|
||||
|
||||
bool unitless = c.m_Type == VIA_COUNT_CONSTRAINT;
|
||||
|
||||
if( c.m_Type == DISALLOW_CONSTRAINT )
|
||||
{
|
||||
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
|
||||
@@ -355,7 +357,7 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
|
||||
break;
|
||||
}
|
||||
|
||||
parseValueWithUnits( FromUTF8(), value );
|
||||
parseValueWithUnits( FromUTF8(), value, unitless );
|
||||
c.m_Value.SetMin( value );
|
||||
|
||||
if( (int) NextTok() != DSN_RIGHT )
|
||||
@@ -375,7 +377,8 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
|
||||
break;
|
||||
}
|
||||
|
||||
parseValueWithUnits( FromUTF8(), value );
|
||||
parseValueWithUnits( FromUTF8(), value, unitless );
|
||||
|
||||
c.m_Value.SetMax( value );
|
||||
|
||||
if( (int) NextTok() != DSN_RIGHT )
|
||||
@@ -395,7 +398,7 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
|
||||
break;
|
||||
}
|
||||
|
||||
parseValueWithUnits( FromUTF8(), value );
|
||||
parseValueWithUnits( FromUTF8(), value, unitless );
|
||||
c.m_Value.SetOpt( value );
|
||||
|
||||
if( (int) NextTok() != DSN_RIGHT )
|
||||
@@ -426,7 +429,7 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
|
||||
}
|
||||
|
||||
|
||||
void DRC_RULES_PARSER::parseValueWithUnits( const wxString& aExpr, int& aResult )
|
||||
void DRC_RULES_PARSER::parseValueWithUnits( const wxString& aExpr, int& aResult, bool aUnitless )
|
||||
{
|
||||
auto errorHandler = [&]( const wxString& aMessage, int aOffset )
|
||||
{
|
||||
@@ -449,7 +452,8 @@ void DRC_RULES_PARSER::parseValueWithUnits( const wxString& aExpr, int& aResult
|
||||
}
|
||||
};
|
||||
|
||||
PCB_EXPR_EVALUATOR evaluator;
|
||||
PCB_EXPR_EVALUATOR evaluator( aUnitless ? (LIBEVAL::UNIT_RESOLVER*) new PCB_UNITLESS_RESOLVER()
|
||||
: (LIBEVAL::UNIT_RESOLVER*) new PCB_UNIT_RESOLVER() );
|
||||
evaluator.SetErrorCallback( errorHandler );
|
||||
|
||||
evaluator.Evaluate( aExpr );
|
||||
|
||||
@@ -49,7 +49,7 @@ private:
|
||||
DRC_RULE* parseDRC_RULE();
|
||||
|
||||
void parseConstraint( DRC_RULE* aRule );
|
||||
void parseValueWithUnits( const wxString& aExpr, int& aResult );
|
||||
void parseValueWithUnits( const wxString& aExpr, int& aResult, bool aUnitless = false );
|
||||
LSET parseLayer();
|
||||
void parseUnknown();
|
||||
|
||||
|
||||
@@ -83,6 +83,14 @@ public:
|
||||
int GetNumPhases() const override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Checks for track/via/hole <-> clearance
|
||||
* @param track Track to text
|
||||
* @param trackShape Primitive track shape
|
||||
* @param layer Which layer to test (in case of vias this can be multiple
|
||||
* @param other item against which to test the track item
|
||||
* @return false if there is a clearance violation reported, true if there is none
|
||||
*/
|
||||
bool testTrackAgainstItem( PCB_TRACK* track, SHAPE* trackShape, PCB_LAYER_ID layer,
|
||||
BOARD_ITEM* other );
|
||||
|
||||
@@ -96,6 +104,18 @@ private:
|
||||
|
||||
void testItemAgainstZones( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer );
|
||||
|
||||
typedef struct checked
|
||||
{
|
||||
checked()
|
||||
: layers(), has_error( false ) {}
|
||||
|
||||
checked( PCB_LAYER_ID aLayer )
|
||||
: layers( aLayer ), has_error( false ) {}
|
||||
|
||||
LSET layers;
|
||||
bool has_error;
|
||||
} layers_checked;
|
||||
|
||||
private:
|
||||
DRC_RTREE m_copperTree;
|
||||
int m_drcEpsilon;
|
||||
@@ -267,6 +287,7 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackAgainstItem( PCB_TRACK* track,
|
||||
int clearance = -1;
|
||||
int actual;
|
||||
VECTOR2I pos;
|
||||
bool has_error = false;
|
||||
|
||||
std::shared_ptr<SHAPE> otherShape = DRC_ENGINE::GetShape( other, layer );
|
||||
|
||||
@@ -300,7 +321,7 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackAgainstItem( PCB_TRACK* track,
|
||||
|
||||
reportViolation( drcItem, (wxPoint) intersection.get() );
|
||||
|
||||
return m_drcEngine->GetReportAllTrackErrors();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,6 +340,7 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackAgainstItem( PCB_TRACK* track,
|
||||
drce->SetViolatingRule( constraint.GetParentRule() );
|
||||
|
||||
reportViolation( drce, (wxPoint) pos );
|
||||
has_error = true;
|
||||
|
||||
if( !m_drcEngine->GetReportAllTrackErrors() )
|
||||
return false;
|
||||
@@ -330,14 +352,12 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackAgainstItem( PCB_TRACK* track,
|
||||
std::array<BOARD_ITEM*, 2> a{ track, other };
|
||||
std::array<BOARD_ITEM*, 2> b{ other, track };
|
||||
std::array<SHAPE*, 2> a_shape{ trackShape, otherShape.get() };
|
||||
|
||||
bool has_error = false;
|
||||
|
||||
for( size_t ii = 0; ii < 2 && !has_error; ++ii )
|
||||
for( size_t ii = 0; ii < 2; ++ii )
|
||||
{
|
||||
std::unique_ptr<SHAPE_SEGMENT> holeShape;
|
||||
|
||||
bool has_hole = b[ii]->Type() == PCB_VIA_T ||
|
||||
bool has_hole = b[ii]->Type() == PCB_VIA_T ||
|
||||
( b[ii]->Type() == PCB_PAD_T && static_cast<PAD*>( b[ii] )->GetDrillSize().x );
|
||||
|
||||
// We only test a track item here against an item with a hole.
|
||||
@@ -385,16 +405,13 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackAgainstItem( PCB_TRACK* track,
|
||||
drce->SetViolatingRule( constraint.GetParentRule() );
|
||||
|
||||
reportViolation( drce, (wxPoint) pos );
|
||||
has_error = true;
|
||||
|
||||
if( !m_drcEngine->GetReportAllTrackErrors() )
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return !has_error;
|
||||
}
|
||||
|
||||
|
||||
@@ -532,7 +549,8 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackClearances()
|
||||
|
||||
reportAux( wxT( "Testing %d tracks & vias..." ), m_board->Tracks().size() );
|
||||
|
||||
std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, LSET> checkedPairs;
|
||||
std::map<BOARD_ITEM*, int> freePadsUsageMap;
|
||||
std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, layers_checked> checkedPairs;
|
||||
|
||||
for( PCB_TRACK* track : m_board->Tracks() )
|
||||
{
|
||||
@@ -567,20 +585,59 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackClearances()
|
||||
|
||||
auto it = checkedPairs.find( { a, b } );
|
||||
|
||||
if( it != checkedPairs.end() && it->second.test( layer ) )
|
||||
if( it != checkedPairs.end() && ( it->second.layers.test( layer )
|
||||
|| ( it->second.has_error && !m_drcEngine->GetReportAllTrackErrors() ) ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
checkedPairs[ { a, b } ].set( layer );
|
||||
checkedPairs[ { a, b } ].layers.set( layer );
|
||||
return true;
|
||||
}
|
||||
},
|
||||
// Visitor:
|
||||
[&]( BOARD_ITEM* other ) -> bool
|
||||
{
|
||||
return testTrackAgainstItem( track, trackShape.get(), layer, other );
|
||||
if( other->Type() == PCB_PAD_T && static_cast<PAD*>( other )->IsFreePad() )
|
||||
{
|
||||
if( other->GetEffectiveShape( layer )->Collide( trackShape.get() ) )
|
||||
{
|
||||
auto it = freePadsUsageMap.find( other );
|
||||
|
||||
if( it == freePadsUsageMap.end() )
|
||||
{
|
||||
freePadsUsageMap[ other ] = track->GetNetCode();
|
||||
return false;
|
||||
}
|
||||
else if( it->second == track->GetNetCode() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOARD_ITEM* a = track;
|
||||
BOARD_ITEM* b = other;
|
||||
|
||||
// store canonical order so we don't collide in both directions
|
||||
// (a:b and b:a)
|
||||
if( static_cast<void*>( a ) > static_cast<void*>( b ) )
|
||||
std::swap( a, b );
|
||||
|
||||
auto it = checkedPairs.find( { a, b } );
|
||||
|
||||
// If we get an error, mark the pair as having a clearance error already
|
||||
// Only continue if we are reporting all track errors
|
||||
if( !testTrackAgainstItem( track, trackShape.get(), layer, other ) )
|
||||
{
|
||||
if( it != checkedPairs.end() )
|
||||
it->second.has_error = true;
|
||||
|
||||
return m_drcEngine->GetReportAllTrackErrors();
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
m_largestClearance );
|
||||
|
||||
|
||||
@@ -161,18 +161,22 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
|
||||
edges.back()->SetShape( SHAPE_T::SEGMENT );
|
||||
edges.back()->SetEndX( shape->GetStartX() );
|
||||
edges.back()->SetWidth( 0 );
|
||||
edges.back()->SetParentGroup( nullptr );
|
||||
edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
|
||||
edges.back()->SetShape( SHAPE_T::SEGMENT );
|
||||
edges.back()->SetEndY( shape->GetStartY() );
|
||||
edges.back()->SetWidth( 0 );
|
||||
edges.back()->SetParentGroup( nullptr );
|
||||
edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
|
||||
edges.back()->SetShape( SHAPE_T::SEGMENT );
|
||||
edges.back()->SetStartX( shape->GetEndX() );
|
||||
edges.back()->SetWidth( 0 );
|
||||
edges.back()->SetParentGroup( nullptr );
|
||||
edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
|
||||
edges.back()->SetShape( SHAPE_T::SEGMENT );
|
||||
edges.back()->SetStartY( shape->GetEndY() );
|
||||
edges.back()->SetWidth( 0 );
|
||||
edges.back()->SetParentGroup( nullptr );
|
||||
return true;
|
||||
}
|
||||
else if( shape->GetShape() == SHAPE_T::POLY )
|
||||
@@ -189,11 +193,13 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
|
||||
edges.back()->SetStart((wxPoint) seg.A );
|
||||
edges.back()->SetEnd((wxPoint) seg.B );
|
||||
edges.back()->SetWidth( 0 );
|
||||
edges.back()->SetParentGroup( nullptr );
|
||||
}
|
||||
}
|
||||
|
||||
edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
|
||||
edges.back()->SetWidth( 0 );
|
||||
edges.back()->SetParentGroup( nullptr );
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
+5
-3
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2016-2023 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
|
||||
@@ -157,10 +157,12 @@ bool AskLoadBoardFileName( PCB_EDIT_FRAME* aParent, int* aCtl, wxString* aFileNa
|
||||
|
||||
PLUGIN::RELEASER plugin( IO_MGR::PluginFind( loaders[ii].pluginType ) );
|
||||
wxCHECK( plugin, false );
|
||||
allWildcards += wxT( "*." ) + formatWildcardExt( plugin->GetFileExtension() ) + wxT( ";" );
|
||||
allWildcards += wxT( "*." ) + formatWildcardExt( plugin->GetFileExtension() ) +
|
||||
wxT( ";" );
|
||||
}
|
||||
|
||||
fileFilters = _( "All supported formats|" ) + allWildcards + wxT( "|" ) + fileFilters;
|
||||
fileFilters = _( "All supported formats" ) + wxT( "|" ) + allWildcards + wxT( "|" ) +
|
||||
fileFilters;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -734,6 +734,19 @@ EDA_RECT FOOTPRINT::GetFpPadsLocalBbox() const
|
||||
}
|
||||
|
||||
|
||||
LSET FOOTPRINT::GetLayerSet() const
|
||||
{
|
||||
LSET retval;
|
||||
|
||||
RunOnChildren( [&retval]( BOARD_ITEM* aItem )
|
||||
{
|
||||
retval |= aItem->GetLayerSet();
|
||||
} );
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
const EDA_RECT FOOTPRINT::GetBoundingBox() const
|
||||
{
|
||||
return GetBoundingBox( true, true );
|
||||
|
||||
@@ -166,6 +166,8 @@ public:
|
||||
const EDA_RECT GetBoundingBox() const override;
|
||||
const EDA_RECT GetBoundingBox( bool aIncludeText, bool aIncludeInvisibleText ) const;
|
||||
|
||||
LSET GetLayerSet() const override;
|
||||
|
||||
PADS& Pads() { return m_pads; }
|
||||
const PADS& Pads() const { return m_pads; }
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2023 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
|
||||
@@ -275,7 +275,7 @@ void DIALOG_IMPORT_GFX::onBrowseFiles( wxCommandEvent& event )
|
||||
allWildcards += plugin->GetWildcards() + wxT( ";" );
|
||||
}
|
||||
|
||||
wildcardsDesc = _( "All supported formats|" ) + allWildcards + wildcardsDesc;
|
||||
wildcardsDesc = _( "All supported formats" ) + wxT( "|" ) + allWildcards + wildcardsDesc;
|
||||
|
||||
wxFileDialog dlg( m_parent, _( "Open File" ), path, filename, wildcardsDesc,
|
||||
wxFD_OPEN | wxFD_FILE_MUST_EXIST );
|
||||
|
||||
@@ -56,8 +56,11 @@ bool SVG_IMPORT_PLUGIN::Load( const wxString& aFileName )
|
||||
{
|
||||
wxCHECK( m_importer, false );
|
||||
|
||||
// wxFopen takes care of unicode filenames across platforms
|
||||
FILE* fp = wxFopen( aFileName, wxT( "rt" ) );
|
||||
// 1- wxFopen takes care of unicode filenames across platforms
|
||||
// 2 - nanosvg (exactly nsvgParseFromFile) expects a binary file (exactly the CRLF eof must
|
||||
// not be replaced by LF and changes the byte count) in one validity test,
|
||||
// so open it in binary mode.
|
||||
FILE* fp = wxFopen( aFileName, wxT( "rb" ) );
|
||||
|
||||
if( fp == nullptr )
|
||||
return false;
|
||||
|
||||
@@ -1144,49 +1144,57 @@ BOARD* PCB_EXPR_CONTEXT::GetBoard() const
|
||||
}
|
||||
|
||||
|
||||
class PCB_UNIT_RESOLVER : public LIBEVAL::UNIT_RESOLVER
|
||||
const std::vector<wxString>& PCB_UNIT_RESOLVER::GetSupportedUnits() const
|
||||
{
|
||||
public:
|
||||
virtual ~PCB_UNIT_RESOLVER()
|
||||
{
|
||||
}
|
||||
static const std::vector<wxString> pcbUnits = { wxT( "mil" ), wxT( "mm" ), wxT( "in" ) };
|
||||
|
||||
virtual const std::vector<wxString>& GetSupportedUnits() const override
|
||||
{
|
||||
static const std::vector<wxString> pcbUnits = { wxT( "mil" ), wxT( "mm" ), wxT( "in" ) };
|
||||
|
||||
return pcbUnits;
|
||||
}
|
||||
|
||||
virtual wxString GetSupportedUnitsMessage() const override
|
||||
{
|
||||
return _( "must be mm, in, or mil" );
|
||||
}
|
||||
|
||||
virtual double Convert( const wxString& aString, int unitId ) const override
|
||||
{
|
||||
double v = wxAtof( aString );
|
||||
|
||||
switch( unitId )
|
||||
{
|
||||
case 0: return DoubleValueFromString( EDA_UNITS::MILS, aString );
|
||||
case 1: return DoubleValueFromString( EDA_UNITS::MILLIMETRES, aString );
|
||||
case 2: return DoubleValueFromString( EDA_UNITS::INCHES, aString );
|
||||
default: return v;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
PCB_EXPR_COMPILER::PCB_EXPR_COMPILER()
|
||||
{
|
||||
m_unitResolver = std::make_unique<PCB_UNIT_RESOLVER>();
|
||||
return pcbUnits;
|
||||
}
|
||||
|
||||
|
||||
PCB_EXPR_EVALUATOR::PCB_EXPR_EVALUATOR() :
|
||||
wxString PCB_UNIT_RESOLVER::GetSupportedUnitsMessage() const
|
||||
{
|
||||
return _( "must be mm, in, or mil" );
|
||||
}
|
||||
|
||||
|
||||
double PCB_UNIT_RESOLVER::Convert( const wxString& aString, int unitId ) const
|
||||
{
|
||||
double v = wxAtof( aString );
|
||||
|
||||
switch( unitId )
|
||||
{
|
||||
case 0: return DoubleValueFromString( EDA_UNITS::MILS, aString );
|
||||
case 1: return DoubleValueFromString( EDA_UNITS::MILLIMETRES, aString );
|
||||
case 2: return DoubleValueFromString( EDA_UNITS::INCHES, aString );
|
||||
default: return v;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const std::vector<wxString>& PCB_UNITLESS_RESOLVER::GetSupportedUnits() const
|
||||
{
|
||||
static const std::vector<wxString> emptyUnits;
|
||||
|
||||
return emptyUnits;
|
||||
}
|
||||
|
||||
|
||||
double PCB_UNITLESS_RESOLVER::Convert( const wxString& aString, int unitId ) const
|
||||
{
|
||||
return wxAtof( aString );
|
||||
};
|
||||
|
||||
|
||||
PCB_EXPR_COMPILER::PCB_EXPR_COMPILER( LIBEVAL::UNIT_RESOLVER* aUnitResolver )
|
||||
{
|
||||
m_unitResolver.reset( aUnitResolver );
|
||||
}
|
||||
|
||||
|
||||
PCB_EXPR_EVALUATOR::PCB_EXPR_EVALUATOR( LIBEVAL::UNIT_RESOLVER* aUnitResolver ) :
|
||||
m_result( 0 ),
|
||||
m_compiler(),
|
||||
m_compiler( aUnitResolver ),
|
||||
m_ucode(),
|
||||
m_errorStatus()
|
||||
{
|
||||
|
||||
@@ -196,17 +196,37 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class PCB_UNIT_RESOLVER : public LIBEVAL::UNIT_RESOLVER
|
||||
{
|
||||
public:
|
||||
const std::vector<wxString>& GetSupportedUnits() const override;
|
||||
|
||||
wxString GetSupportedUnitsMessage() const override;
|
||||
|
||||
double Convert( const wxString& aString, int unitId ) const override;
|
||||
};
|
||||
|
||||
|
||||
class PCB_UNITLESS_RESOLVER : public LIBEVAL::UNIT_RESOLVER
|
||||
{
|
||||
public:
|
||||
const std::vector<wxString>& GetSupportedUnits() const override;
|
||||
|
||||
double Convert( const wxString& aString, int unitId ) const override;
|
||||
};
|
||||
|
||||
|
||||
class PCB_EXPR_COMPILER : public LIBEVAL::COMPILER
|
||||
{
|
||||
public:
|
||||
PCB_EXPR_COMPILER();
|
||||
PCB_EXPR_COMPILER( LIBEVAL::UNIT_RESOLVER* aUnitResolver );
|
||||
};
|
||||
|
||||
|
||||
class PCB_EXPR_EVALUATOR
|
||||
{
|
||||
public:
|
||||
PCB_EXPR_EVALUATOR( );
|
||||
PCB_EXPR_EVALUATOR( LIBEVAL::UNIT_RESOLVER* aUnitResolver );
|
||||
~PCB_EXPR_EVALUATOR();
|
||||
|
||||
bool Evaluate( const wxString& aExpr );
|
||||
|
||||
@@ -30,14 +30,48 @@
|
||||
#include <widgets/msgpanel.h>
|
||||
#include <view/view.h>
|
||||
|
||||
#include <wx/debug.h>
|
||||
|
||||
PCB_GROUP::PCB_GROUP( BOARD_ITEM* aParent ) :
|
||||
BOARD_ITEM( aParent, PCB_GROUP_T )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool PCB_GROUP::IsGroupableType( KICAD_T aType )
|
||||
{
|
||||
switch ( aType )
|
||||
{
|
||||
case PCB_FOOTPRINT_T:
|
||||
case PCB_PAD_T:
|
||||
case PCB_SHAPE_T:
|
||||
case PCB_TEXT_T:
|
||||
case PCB_FP_TEXT_T:
|
||||
case PCB_FP_SHAPE_T:
|
||||
case PCB_FP_ZONE_T:
|
||||
case PCB_GROUP_T:
|
||||
case PCB_TRACE_T:
|
||||
case PCB_VIA_T:
|
||||
case PCB_ARC_T:
|
||||
case PCB_DIMENSION_T:
|
||||
case PCB_DIM_ALIGNED_T:
|
||||
case PCB_DIM_LEADER_T:
|
||||
case PCB_DIM_CENTER_T:
|
||||
case PCB_DIM_ORTHOGONAL_T:
|
||||
case PCB_ZONE_T:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool PCB_GROUP::AddItem( BOARD_ITEM* aItem )
|
||||
{
|
||||
wxCHECK_MSG( IsGroupableType( aItem->Type() ), false,
|
||||
wxT( "Invalid item type added to group: " )
|
||||
+ aItem->GetSelectMenuText( EDA_UNITS::MILLIMETRES ) );
|
||||
|
||||
// Items can only be in one group at a time
|
||||
if( aItem->GetParentGroup() )
|
||||
aItem->GetParentGroup()->RemoveItem( aItem );
|
||||
|
||||
+36
-28
@@ -262,7 +262,7 @@ COLOR4D PCB_RENDER_SETTINGS::GetColor( const VIEW_ITEM* aItem, int aLayer ) cons
|
||||
// Zones should pull from the copper layer
|
||||
if( item && ( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T ) )
|
||||
{
|
||||
if( IsZoneLayer( aLayer ) )
|
||||
if( IsZoneFillLayer( aLayer ) )
|
||||
aLayer = aLayer - LAYER_ZONE_START;
|
||||
}
|
||||
|
||||
@@ -1742,8 +1742,12 @@ void PCB_PAINTER::draw( const ZONE* aZone, int aLayer )
|
||||
* The color for the zone comes from the associated copper layer ( aLayer - LAYER_ZONE_START )
|
||||
* and the visibility comes from the combination of that copper layer and LAYER_ZONES
|
||||
*/
|
||||
wxASSERT( IsZoneLayer( aLayer ) );
|
||||
PCB_LAYER_ID layer = static_cast<PCB_LAYER_ID>( aLayer - LAYER_ZONE_START );
|
||||
PCB_LAYER_ID layer;
|
||||
|
||||
if( IsZoneFillLayer( aLayer ) )
|
||||
layer = ToLAYER_ID( aLayer - LAYER_ZONE_START );
|
||||
else
|
||||
layer = ToLAYER_ID( aLayer );
|
||||
|
||||
if( !aZone->IsOnLayer( layer ) )
|
||||
return;
|
||||
@@ -1753,41 +1757,45 @@ void PCB_PAINTER::draw( const ZONE* aZone, int aLayer )
|
||||
ZONE_DISPLAY_MODE displayMode = m_pcbSettings.m_zoneDisplayMode;
|
||||
|
||||
// Draw the outline
|
||||
const SHAPE_POLY_SET* outline = aZone->Outline();
|
||||
|
||||
if( m_pcbSettings.m_zoneOutlines && outline && outline->OutlineCount() > 0 )
|
||||
if( !IsZoneFillLayer( aLayer ) )
|
||||
{
|
||||
m_gal->SetStrokeColor( color.a > 0.0 ? color.WithAlpha( 1.0 ) : color );
|
||||
m_gal->SetIsFill( false );
|
||||
m_gal->SetIsStroke( true );
|
||||
m_gal->SetLineWidth( m_pcbSettings.m_outlineWidth );
|
||||
const SHAPE_POLY_SET* outline = aZone->Outline();
|
||||
|
||||
// Draw each contour (main contour and holes)
|
||||
if( !m_pcbSettings.m_isPrinting && outline && outline->OutlineCount() > 0 )
|
||||
{
|
||||
m_gal->SetStrokeColor( color.a > 0.0 ? color.WithAlpha( 1.0 ) : color );
|
||||
m_gal->SetIsFill( false );
|
||||
m_gal->SetIsStroke( true );
|
||||
m_gal->SetLineWidth( m_pcbSettings.m_outlineWidth );
|
||||
|
||||
/*
|
||||
* m_gal->DrawPolygon( *outline );
|
||||
* should be enough, but currently does not work to draw holes contours in a complex
|
||||
* polygon so each contour is draw as a simple polygon
|
||||
*/
|
||||
// Draw each contour (main contour and holes)
|
||||
|
||||
// Draw the main contour
|
||||
m_gal->DrawPolyline( outline->COutline( 0 ) );
|
||||
/*
|
||||
* m_gal->DrawPolygon( *outline );
|
||||
* should be enough, but currently does not work to draw holes contours in a complex
|
||||
* polygon so each contour is draw as a simple polygon
|
||||
*/
|
||||
|
||||
// Draw holes
|
||||
int holes_count = outline->HoleCount( 0 );
|
||||
// Draw the main contour
|
||||
m_gal->DrawPolyline( outline->COutline( 0 ) );
|
||||
|
||||
for( int ii = 0; ii < holes_count; ++ii )
|
||||
m_gal->DrawPolyline( outline->CHole( 0, ii ) );
|
||||
// Draw holes
|
||||
int holes_count = outline->HoleCount( 0 );
|
||||
|
||||
// Draw hatch lines
|
||||
for( const SEG& hatchLine : aZone->GetHatchLines() )
|
||||
m_gal->DrawLine( hatchLine.A, hatchLine.B );
|
||||
for( int ii = 0; ii < holes_count; ++ii )
|
||||
m_gal->DrawPolyline( outline->CHole( 0, ii ) );
|
||||
|
||||
// Draw hatch lines
|
||||
for( const SEG& hatchLine : aZone->GetHatchLines() )
|
||||
m_gal->DrawLine( hatchLine.A, hatchLine.B );
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the filling
|
||||
if( displayMode == ZONE_DISPLAY_MODE::SHOW_FILLED
|
||||
|| displayMode == ZONE_DISPLAY_MODE::SHOW_FRACTURE_BORDERS
|
||||
|| displayMode == ZONE_DISPLAY_MODE::SHOW_TRIANGULATION )
|
||||
if( IsZoneFillLayer( aLayer )
|
||||
&& ( displayMode == ZONE_DISPLAY_MODE::SHOW_FILLED
|
||||
|| displayMode == ZONE_DISPLAY_MODE::SHOW_FRACTURE_BORDERS
|
||||
|| displayMode == ZONE_DISPLAY_MODE::SHOW_TRIANGULATION ) )
|
||||
{
|
||||
const SHAPE_POLY_SET& polySet = aZone->GetFilledPolysList( layer );
|
||||
|
||||
|
||||
@@ -138,8 +138,8 @@ void DP_MEANDER_PLACER::release()
|
||||
|
||||
long long int DP_MEANDER_PLACER::origPathLength() const
|
||||
{
|
||||
long long int totalP = m_padToDieLength + lineLength( m_tunedPathP, m_startPad_p, m_endPad_p );
|
||||
long long int totalN = m_padToDieLength + lineLength( m_tunedPathN, m_startPad_n, m_endPad_n );
|
||||
long long int totalP = m_padToDieP + lineLength( m_tunedPathP, m_startPad_p, m_endPad_p );
|
||||
long long int totalN = m_padToDieN + lineLength( m_tunedPathN, m_startPad_n, m_endPad_n );
|
||||
return std::max( totalP, totalN );
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user