Compare commits
260 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2c061ed67a | |||
| 9bfbe3acd8 | |||
| 40bdd26e39 | |||
| b0f8055377 | |||
| 33f4fc9873 | |||
| c90842dd08 | |||
| 310b4cdf75 | |||
| 2208e0db16 | |||
| cf4c403094 | |||
| dd55ffb75c | |||
| d34faf30cc | |||
| 3720a52ecb | |||
| 47de9f8f04 | |||
| 14378812be | |||
| 0070a4686e | |||
| 5c63df28e4 | |||
| e5ea37507c | |||
| 53bd87d792 | |||
| 02252be29d | |||
| 9e9598af5f | |||
| 9dc35b575c | |||
| 3cd24f656b | |||
| 73eac90922 | |||
| 70e5c9f7c6 | |||
| d820a7fe42 | |||
| b9d7a0565f | |||
| ad2486b09f | |||
| 4742043a7e | |||
| 9e56c7e5c9 | |||
| 674fbfa889 | |||
| ae1cc29dc6 | |||
| f1c772ba55 | |||
| 6f6505f6a1 | |||
| af4a4cbc08 | |||
| 40462012ee | |||
| 70514be11f | |||
| 7558dad915 | |||
| 5e9b982ddf | |||
| 17539a564e | |||
| 43aa0bfdc3 | |||
| 7ab4bf3823 | |||
| ae01dc8ef1 | |||
| 187aa1c171 | |||
| 17b1b68ac7 | |||
| 35f15f016d | |||
| 70277e5514 | |||
| 2874688281 | |||
| 826096790d | |||
| a2e66f6667 | |||
| c241032a3b | |||
| 9ca35cbcee | |||
| 9c386026a8 | |||
| 012a9bb7cb | |||
| 563aa3ed74 | |||
| e8ef863861 | |||
| a24cdcb3f0 | |||
| 5314ba6440 | |||
| c465a6ebc7 | |||
| 4e5038eb3e | |||
| 2372359aaa | |||
| 5e0251c2ba | |||
| fd5eeceb4f | |||
| da480aba47 | |||
| 63f4f42e6a | |||
| 8d246dbee0 | |||
| 79517e44ce | |||
| a940607524 | |||
| 0cf1a67e29 | |||
| f4cdb97141 | |||
| 0cfa88ca9a | |||
| 2535237c31 | |||
| 4c86a5ce64 | |||
| c75c7d084a | |||
| dd154c155f | |||
| 0838543745 | |||
| bd1f01f7ee | |||
| 8ab1d91f3c | |||
| 35a7490342 | |||
| d0314aab88 | |||
| 812aba6065 | |||
| 6abcfeeb0f | |||
| 703b18519f | |||
| 1199af0d52 | |||
| 2f1ebebba3 | |||
| 19f4852280 | |||
| 0be07689a7 | |||
| f227ccfd5d | |||
| fd9804a3dc | |||
| 502f2dab11 | |||
| 8e46ae5ce8 | |||
| 8a863cdf54 | |||
| 493e733f0c | |||
| 38ac1b2f2d | |||
| 1394509734 | |||
| 1ffe0da204 | |||
| 46d423a164 | |||
| 7aebc4b11f | |||
| c1dcfdffb1 | |||
| 191558e2d7 | |||
| 912c2eac09 | |||
| 802d20c409 | |||
| 8f75841c85 | |||
| c3f8d8b5a1 | |||
| 79b6991d7b | |||
| 17dc324e85 | |||
| 23479821e3 | |||
| 9396735733 | |||
| 901c330478 | |||
| 354c320329 | |||
| 0ea559e3b8 | |||
| 6fd898d1b3 | |||
| d20c2fe5c5 | |||
| 3585c184cc | |||
| 429544c188 | |||
| 8385ce3021 | |||
| 0b98acfe12 | |||
| acb5ce7108 | |||
| 63b06af6b1 | |||
| e5a85b107f | |||
| e2982a0e47 | |||
| 5396bb970f | |||
| d4937f1b3e | |||
| 1c6f3f8f0d | |||
| 6341548939 | |||
| a91dd68444 | |||
| a8175f49a6 | |||
| 05110b7bdc | |||
| aadcc43dbb | |||
| ff6f398607 | |||
| a30ad0b54a | |||
| ab835937a7 | |||
| b17eb3a584 | |||
| 9c2bc98fd3 | |||
| 96bd27ef0f | |||
| 23351b2046 | |||
| 69bd4218f7 | |||
| f27f001fcb | |||
| be772ecd18 | |||
| 48ba236851 | |||
| 5120566c77 | |||
| 7789857e30 | |||
| 89d85800ab | |||
| 43dcf09747 | |||
| a372594dea | |||
| 414e6dc43e | |||
| f34d146c38 | |||
| d9f5d1d865 | |||
| b15d6bd10a | |||
| 54f621c570 | |||
| d29d981784 | |||
| 3801a8adc0 | |||
| 7d4cb91f39 | |||
| 0f497d1b7a | |||
| 5f1976f341 | |||
| 6036331b25 | |||
| 5129143bcb | |||
| d7d31e4b76 | |||
| b00f855c26 | |||
| 4b0177c8fe | |||
| b11ec85706 | |||
| de48f41184 | |||
| 55bdef9bd2 | |||
| 5cc2bef954 | |||
| 8ce9f08268 | |||
| 6ccaf5e27d | |||
| a24912d01d | |||
| 8ad0f24031 | |||
| 2498655cc5 | |||
| b2ac4b2c65 | |||
| 899c2d9080 | |||
| b4ac59d9d3 | |||
| a5305aa235 | |||
| 680163f8a8 | |||
| 0fdd1df208 | |||
| 9367b7f309 | |||
| f8d15a641a | |||
| d56e488f2d | |||
| cf9fafaba5 | |||
| d5ca09dffc | |||
| b24f51908b | |||
| 15fd0aa989 | |||
| 246b6fcdd6 | |||
| 2b7c79541b | |||
| 7f40cac4b0 | |||
| 7978c8c291 | |||
| fc6ec23ac1 | |||
| 02ec87b036 | |||
| da82ba00e4 | |||
| b041a77cfa | |||
| 9fcd4113b0 | |||
| 762258203c | |||
| 75a4036e45 | |||
| f0d7a09af9 | |||
| 7be3a6b3c5 | |||
| 08bc14ccf2 | |||
| 5781cb0ce5 | |||
| ed2148d634 | |||
| 8e9d44942f | |||
| 8b1f1c0296 | |||
| 4eb9440a42 | |||
| 7cf7270738 | |||
| 9c48707c88 | |||
| ff21a16f7d | |||
| 3b072ca8b4 | |||
| e56355fc17 | |||
| cfae33e7a8 | |||
| c6c4f9ae4b | |||
| 46f7223dd9 | |||
| 75bba51b0b | |||
| 34ed850a23 | |||
| 266ee381d5 | |||
| 15a44d75fb | |||
| f93304b144 | |||
| 5fe583e195 | |||
| 9153fcd04a | |||
| 0f5219ad92 | |||
| 5b90195dfa | |||
| 28c6ac53b7 | |||
| 79e8c8df67 | |||
| f02722b7a7 | |||
| 34e116c18b | |||
| 1a5e00254d | |||
| f36a0eeb95 | |||
| f8b3f5b02f | |||
| dca9df1908 | |||
| f2e1b8cc7a | |||
| 9c4eab9677 | |||
| 470d7d228d | |||
| 71eefc8322 | |||
| ef96ee4a99 | |||
| 35968dfe18 | |||
| b3965c014c | |||
| c3cc615f37 | |||
| bc232a7b6b | |||
| 880098d659 | |||
| 1640c27cd2 | |||
| 96fc0feb4d | |||
| fdae390c52 | |||
| 2cb5643556 | |||
| d689d1a866 | |||
| 76c690c819 | |||
| 3c601180c2 | |||
| 3c83040c4b | |||
| 6147e997ff | |||
| e88bef0023 | |||
| 54a3ca06c0 | |||
| 0cb82a0985 | |||
| b7f8f95725 | |||
| 30276fb5f7 | |||
| f37531ed39 | |||
| fd4ac7c5df | |||
| b8b9f646c6 | |||
| f561f85ebb | |||
| 7cba8e847d | |||
| f8ac6df0cd | |||
| 310e339c39 | |||
| 6b6d97e726 | |||
| 7c910c2d0b | |||
| 1b8f25235c | |||
| f7133168c1 |
@@ -29,6 +29,7 @@
|
||||
#include <kiface_base.h>
|
||||
#include <tools/eda_3d_controller.h>
|
||||
#include "eda_3d_actions.h"
|
||||
#include "dialogs/panel_preview_3d_model.h"
|
||||
#include <3d_rendering/opengl/render_3d_opengl.h>
|
||||
|
||||
|
||||
@@ -113,10 +114,36 @@ int EDA_3D_CONTROLLER::Main( const TOOL_EVENT& aEvent )
|
||||
// Main loop: keep receiving events
|
||||
while( TOOL_EVENT* evt = Wait() )
|
||||
{
|
||||
if( evt->IsClick( BUT_RIGHT ) )
|
||||
if( evt->IsCancelInteractive() )
|
||||
{
|
||||
wxWindow* canvas = m_toolMgr->GetToolHolder()->GetToolCanvas();
|
||||
wxWindow* topLevelParent = canvas->GetParent();
|
||||
|
||||
while( topLevelParent && !topLevelParent->IsTopLevel() )
|
||||
topLevelParent = topLevelParent->GetParent();
|
||||
|
||||
if( topLevelParent && dynamic_cast<DIALOG_SHIM*>( topLevelParent ) )
|
||||
{
|
||||
DIALOG_SHIM* dialog = static_cast<DIALOG_SHIM*>( topLevelParent );
|
||||
|
||||
if( dialog->IsQuasiModal() )
|
||||
dialog->EndQuasiModal( wxID_CANCEL );
|
||||
else
|
||||
dialog->EndModal( wxID_CANCEL );
|
||||
}
|
||||
else
|
||||
{
|
||||
evt->SetPassEvent();
|
||||
}
|
||||
}
|
||||
else if( evt->IsClick( BUT_RIGHT ) )
|
||||
{
|
||||
m_menu.ShowContextMenu();
|
||||
}
|
||||
else
|
||||
{
|
||||
evt->SetPassEvent();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2015-2021 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
|
||||
@@ -124,8 +124,10 @@ PANEL_PREVIEW_3D_MODEL::PANEL_PREVIEW_3D_MODEL( wxWindow* aParent, PCB_BASE_FRAM
|
||||
m_SizerPanelView->Add( m_previewPane, 1, wxEXPAND, 5 );
|
||||
|
||||
for( wxEventType eventType : { wxEVT_MENU_OPEN, wxEVT_MENU_CLOSE, wxEVT_MENU_HIGHLIGHT } )
|
||||
{
|
||||
Connect( eventType, wxMenuEventHandler( PANEL_PREVIEW_3D_MODEL::OnMenuEvent ), nullptr,
|
||||
this );
|
||||
}
|
||||
|
||||
#ifdef __WXOSX__
|
||||
// Call layout once to get the proper button sizes after the bitmaps have been set
|
||||
|
||||
+17
-4
@@ -156,6 +156,11 @@ option( KICAD_STEP_EXPORT_LIB
|
||||
"Build and use kicad2step as a library, meant for debugging"
|
||||
OFF )
|
||||
|
||||
cmake_dependent_option( KICAD_WIN32_VERIFY_CODESIGN
|
||||
"When enabled, verifies the code signing signature of certain DLLs loaded during runtime."
|
||||
OFF "WIN32"
|
||||
OFF )
|
||||
|
||||
# Global setting: exports are explicit
|
||||
set( CMAKE_CXX_VISIBILITY_PRESET "hidden" )
|
||||
set( CMAKE_VISIBILITY_INLINES_HIDDEN ON )
|
||||
@@ -177,6 +182,10 @@ if( KICAD_GAL_PROFILE )
|
||||
add_definitions( -DKICAD_GAL_PROFILE )
|
||||
endif()
|
||||
|
||||
if( KICAD_WIN32_VERIFY_CODESIGN )
|
||||
add_definitions( -DKICAD_WIN32_VERIFY_CODESIGN )
|
||||
endif()
|
||||
|
||||
# Ensure DEBUG is defined for all platforms in Debug builds
|
||||
# change to add_compile_definitions() after minimum required CMake version is 3.12
|
||||
set_property( DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$<CONFIG:Debug>:DEBUG> )
|
||||
@@ -490,9 +499,10 @@ endif()
|
||||
# KIFACE_SUFFIX is the file extension used for top level program modules which
|
||||
# implement the KIFACE interface. A valid suffix starts with a period '.'.
|
||||
|
||||
if( false )
|
||||
# This is the eventual situation near milestone C) of modular-kicad blueprint.
|
||||
# Until then we use .kiface extension so we don't collide with python DSO.
|
||||
if( WIN32 )
|
||||
# We use .kiface extension so we don't collide with python DSO. (Linux/mac issue?)
|
||||
# Windows works fine with the native dll extension
|
||||
# which also resolves metadata issues because windows wants to see the dll extension
|
||||
set( KIFACE_SUFFIX ${CMAKE_SHARED_MODULE_SUFFIX} )
|
||||
else()
|
||||
# Temporary situation until we can dovetail the python DSO into the kiface DSO.
|
||||
@@ -1000,7 +1010,10 @@ add_subdirectory( cvpcb ) # must be after pcbnew
|
||||
add_subdirectory( kicad ) # should follow pcbnew, eeschema
|
||||
add_subdirectory( tools )
|
||||
add_subdirectory( utils )
|
||||
add_subdirectory( qa )
|
||||
|
||||
if( KICAD_BUILD_QA_TESTS )
|
||||
add_subdirectory( qa )
|
||||
endif()
|
||||
|
||||
# Demos
|
||||
if( KICAD_INSTALL_DEMOS )
|
||||
|
||||
@@ -46,7 +46,7 @@ if( CMAKE_MATCH_COUNT EQUAL 3 )
|
||||
|
||||
set( KICAD_WIN32_RC_FILEVER_STR "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}.${KICAD_GIT_REV}\\0" )
|
||||
set( KICAD_WIN32_RC_FILEVER "${CMAKE_MATCH_1}, ${CMAKE_MATCH_2}, ${CMAKE_MATCH_3}, ${KICAD_GIT_REV}" )
|
||||
set( KICAD_WIN32_RC_PRODVER_STR "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}\\0" )
|
||||
set( KICAD_WIN32_RC_PRODVER_STR "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}\\0" )
|
||||
set( KICAD_WIN32_RC_PRODVER "${CMAKE_MATCH_1}, ${CMAKE_MATCH_2}, ${CMAKE_MATCH_3}, ${KICAD_GIT_REV}" )
|
||||
else()
|
||||
message( FATAL_ERROR "Unable to extract major, minor and patch version string" )
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
# KiCad.
|
||||
#
|
||||
# Note: This version string should follow the semantic versioning system
|
||||
set( KICAD_SEMANTIC_VERSION "6.0.2" )
|
||||
set( KICAD_SEMANTIC_VERSION "6.0.4" )
|
||||
|
||||
# Default the version to the semantic version.
|
||||
# This is overridden by the git repository tag though (if using git)
|
||||
|
||||
@@ -16,9 +16,6 @@ KiCad uses a host of CI resources.
|
||||
|
||||
GitLab CI pipeline status can be viewed for Linux and Windows builds of the latest commits.
|
||||
|
||||
Additional status is available for builds:
|
||||
[<img alt="Jenkins" src="https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fjenkins.simonrichter.eu%2Fjob%2Fwindows-kicad-ps-pipeline%2F&label=Windows%2C%20MSVC%Nightly&style=plastic">](https://jenkins.simonrichter.eu/job/windows-kicad-ps-pipeline/)
|
||||
|
||||
## Release status
|
||||
[](https://repology.org/project/kicad/versions)
|
||||
[](https://repology.org/metapackage/kicad/versions)
|
||||
|
||||
+28
-28
@@ -266,12 +266,12 @@ ADVANCED_CFG::ADVANCED_CFG()
|
||||
m_DrawArcAccuracy = 10.0;
|
||||
m_DrawArcCenterMaxAngle = 50.0;
|
||||
m_MaxTangentAngleDeviation = 1.0;
|
||||
m_MaxTrackLengthToKeep = 0.0001;
|
||||
m_MaxTrackLengthToKeep = 0.0005;
|
||||
m_ExtraZoneDisplayModes = false;
|
||||
m_DrawTriangulationOutlines = false;
|
||||
|
||||
m_ExtraClearance = 0.0001;
|
||||
m_DRCEpsilon = 0.0001; // 0.1um is small enough not to materially violate
|
||||
m_ExtraClearance = 0.0005;
|
||||
m_DRCEpsilon = 0.0005; // 0.5um is small enough not to materially violate
|
||||
// any constraints.
|
||||
|
||||
m_HoleWallThickness = 0.020; // IPC-6012 says 15-18um; Cadence says at least
|
||||
@@ -334,83 +334,83 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg )
|
||||
std::vector<PARAM_CFG*> configParams;
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::RealtimeConnectivity,
|
||||
&m_RealTimeConnectivity, true ) );
|
||||
&m_RealTimeConnectivity, m_RealTimeConnectivity ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::ExtraFillMargin,
|
||||
&m_ExtraClearance, 0.0005, 0.0, 1.0 ) );
|
||||
&m_ExtraClearance, m_ExtraClearance, 0.0, 1.0 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::DRCEpsilon,
|
||||
&m_DRCEpsilon, 0.0005, 0.0, 1.0 ) );
|
||||
&m_DRCEpsilon, m_DRCEpsilon, 0.0, 1.0 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::HoleWallThickness,
|
||||
&m_HoleWallThickness, 0.020, 0.0, 1.0 ) );
|
||||
&m_HoleWallThickness, m_HoleWallThickness, 0.0, 1.0 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::CoroutineStackSize,
|
||||
&m_CoroutineStackSize, AC_STACK::default_stack,
|
||||
AC_STACK::min_stack, AC_STACK::max_stack ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ShowRouterDebugGraphics,
|
||||
&m_ShowRouterDebugGraphics, false ) );
|
||||
&m_ShowRouterDebugGraphics, m_ShowRouterDebugGraphics ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::CompactFileSave,
|
||||
&m_CompactSave, false ) );
|
||||
&m_CompactSave, m_CompactSave ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::DrawArcAccuracy,
|
||||
&m_DrawArcAccuracy, 10.0, 0.0, 100000.0 ) );
|
||||
&m_DrawArcAccuracy, m_DrawArcAccuracy, 0.0, 100000.0 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::DrawArcCenterStartEndMaxAngle,
|
||||
&m_DrawArcCenterMaxAngle, 50.0, 0.0, 100000.0 ) );
|
||||
&m_DrawArcCenterMaxAngle, m_DrawArcCenterMaxAngle, 0.0, 100000.0 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::MaxTangentTrackAngleDeviation,
|
||||
&m_MaxTangentAngleDeviation, 1.0, 0.0, 90.0 ) );
|
||||
&m_MaxTangentAngleDeviation, m_MaxTangentAngleDeviation, 0.0, 90.0 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::MaxTrackLengthToKeep,
|
||||
&m_MaxTrackLengthToKeep, 0.0005, 0.0, 1.0 ) );
|
||||
&m_MaxTrackLengthToKeep, m_MaxTrackLengthToKeep, 0.0, 1.0 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ExtraZoneDisplayModes,
|
||||
&m_ExtraZoneDisplayModes, false ) );
|
||||
&m_ExtraZoneDisplayModes, m_ExtraZoneDisplayModes ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::StrokeTriangulation,
|
||||
&m_DrawTriangulationOutlines, false ) );
|
||||
&m_DrawTriangulationOutlines, m_DrawTriangulationOutlines ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::MinPlotPenWidth,
|
||||
&m_MinPlotPenWidth, 0.0212, 0.0, 1.0 ) );
|
||||
&m_MinPlotPenWidth, m_MinPlotPenWidth, 0.0, 1.0 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::DebugZoneFiller,
|
||||
&m_DebugZoneFiller, false ) );
|
||||
&m_DebugZoneFiller, m_DebugZoneFiller ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::DebugPDFWriter,
|
||||
&m_DebugPDFWriter, false ) );
|
||||
&m_DebugPDFWriter, m_DebugPDFWriter ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::SmallDrillMarkSize,
|
||||
&m_SmallDrillMarkSize, 0.35, 0.0, 3.0 ) );
|
||||
&m_SmallDrillMarkSize, m_SmallDrillMarkSize, 0.0, 3.0 ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::HotkeysDumper,
|
||||
&m_HotkeysDumper, false ) );
|
||||
&m_HotkeysDumper, m_HotkeysDumper ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::DrawBoundingBoxes,
|
||||
&m_DrawBoundingBoxes, false ) );
|
||||
&m_DrawBoundingBoxes, m_DrawBoundingBoxes ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ShowPcbnewExportNetlist,
|
||||
&m_ShowPcbnewExportNetlist, false ) );
|
||||
&m_ShowPcbnewExportNetlist, m_ShowPcbnewExportNetlist ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::Skip3DModelFileCache,
|
||||
&m_Skip3DModelFileCache, false ) );
|
||||
&m_Skip3DModelFileCache, m_Skip3DModelFileCache ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::Skip3DModelMemoryCache,
|
||||
&m_Skip3DModelMemoryCache, false ) );
|
||||
&m_Skip3DModelMemoryCache, m_Skip3DModelMemoryCache ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::HideVersionFromTitle,
|
||||
&m_HideVersionFromTitle, false ) );
|
||||
&m_HideVersionFromTitle, m_HideVersionFromTitle ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ShowRepairSchematic,
|
||||
&m_ShowRepairSchematic, false ) );
|
||||
&m_ShowRepairSchematic, m_ShowRepairSchematic ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ShowEventCounters,
|
||||
&m_ShowEventCounters, false ) );
|
||||
&m_ShowEventCounters, m_ShowEventCounters ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::AllowManualCanvasScale,
|
||||
&m_AllowManualCanvasScale, false ) );
|
||||
&m_AllowManualCanvasScale, m_AllowManualCanvasScale ) );
|
||||
|
||||
// Special case for trace mask setting...we just grab them and set them immediately
|
||||
// Because we even use wxLogTrace inside of advanced config
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2009 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2009 Jean-Pierre Charras, jean-pierre.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2018 CERN
|
||||
* Author: Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
@@ -70,6 +70,7 @@ BOARD_PRINTOUT::BOARD_PRINTOUT( const BOARD_PRINTOUT_SETTINGS& aParams,
|
||||
m_settings( aParams )
|
||||
{
|
||||
m_view = aView;
|
||||
m_gerbviewPrint = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,12 +86,12 @@ void BOARD_PRINTOUT::GetPageInfo( int* minPage, int* maxPage, int* selPageFrom,
|
||||
|
||||
void BOARD_PRINTOUT::DrawPage( const wxString& aLayerName, int aPageNum, int aPageCount )
|
||||
{
|
||||
auto dc = GetDC();
|
||||
wxDC* dc = GetDC();
|
||||
KIGFX::GAL_DISPLAY_OPTIONS options;
|
||||
auto galPrint = KIGFX::GAL_PRINT::Create( options, dc );
|
||||
auto gal = galPrint->GetGAL();
|
||||
auto printCtx = galPrint->GetPrintCtx();
|
||||
auto painter = getPainter( gal );
|
||||
std::unique_ptr<KIGFX::GAL_PRINT> galPrint = KIGFX::GAL_PRINT::Create( options, dc );
|
||||
KIGFX::GAL* gal = galPrint->GetGAL();
|
||||
KIGFX::PRINT_CONTEXT* printCtx = galPrint->GetPrintCtx();
|
||||
std::unique_ptr<KIGFX::PAINTER> painter = getPainter( gal );
|
||||
std::unique_ptr<KIGFX::VIEW> view( m_view->DataReference() );
|
||||
|
||||
// Target paper size
|
||||
@@ -175,6 +176,11 @@ void BOARD_PRINTOUT::DrawPage( const wxString& aLayerName, int aPageNum, int aPa
|
||||
gal->SetClearColor( dstSettings->GetBackgroundColor() );
|
||||
gal->ClearScreen();
|
||||
|
||||
if( m_gerbviewPrint )
|
||||
// Mandatory in Gerbview to use the same order for printing as for screen redraw
|
||||
// due to negative objects that need a specific order
|
||||
view->UseDrawPriority( true );
|
||||
|
||||
{
|
||||
KIGFX::GAL_DRAWING_CONTEXT ctx( gal );
|
||||
view->Redraw();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2010 Rafael Sokolowski <Rafael.Sokolowski@web.de>
|
||||
* Copyright (C) 2010-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2010-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
|
||||
@@ -64,7 +64,7 @@ static void buildKicadAboutBanner( EDA_BASE_FRAME* aParent, ABOUT_APP_INFO& aInf
|
||||
aInfo.SetAppName( Pgm().App().GetAppName() );
|
||||
|
||||
/* Copyright information */
|
||||
aInfo.SetCopyright( "(C) 1992-2021 KiCad Developers Team" );
|
||||
aInfo.SetCopyright( "(C) 1992-2022 KiCad Developers Team" );
|
||||
|
||||
/* KiCad build version */
|
||||
wxString version;
|
||||
|
||||
@@ -419,7 +419,7 @@ void DIALOG_ABOUT::createNotebookHtmlPage( wxNotebook* aParent, const wxString&
|
||||
wxStaticText* DIALOG_ABOUT::wxStaticTextRef( wxScrolledWindow* aParent, const wxString& aReference )
|
||||
{
|
||||
wxStaticText* text = new wxStaticText( aParent, wxID_ANY,
|
||||
wxT( "(wxT( " ) + aReference + wxT( " ))" ) );
|
||||
wxT( "(" ) + aReference + wxT( ")" ) );
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
@@ -213,6 +213,7 @@ void EDA_DRAW_PANEL_GAL::DoRePaint()
|
||||
try
|
||||
{
|
||||
cntUpd.Start();
|
||||
|
||||
try
|
||||
{
|
||||
m_view->UpdateItems();
|
||||
@@ -229,9 +230,7 @@ void EDA_DRAW_PANEL_GAL::DoRePaint()
|
||||
cntUpd.Stop();
|
||||
|
||||
cntCtx.Start();
|
||||
int cookie = rand();
|
||||
m_gal->LockContext( cookie );
|
||||
m_gal->BeginDrawing();
|
||||
KIGFX::GAL_DRAWING_CONTEXT ctx( m_gal );
|
||||
cntCtx.Stop();
|
||||
|
||||
if( m_view->IsTargetDirty( KIGFX::TARGET_OVERLAY )
|
||||
@@ -273,9 +272,6 @@ void EDA_DRAW_PANEL_GAL::DoRePaint()
|
||||
m_gal->DrawCursor( m_viewControls->GetCursorPosition() );
|
||||
|
||||
cntCtxDestroy.Start();
|
||||
m_gal->EndDrawing();
|
||||
m_gal->UnlockContext( cookie );
|
||||
cntCtxDestroy.Stop();
|
||||
}
|
||||
catch( std::exception& err )
|
||||
{
|
||||
@@ -294,6 +290,9 @@ void EDA_DRAW_PANEL_GAL::DoRePaint()
|
||||
}
|
||||
}
|
||||
|
||||
// ctx goes out of scope here so destructor would be called
|
||||
cntCtxDestroy.Stop();
|
||||
|
||||
|
||||
if( isDirty )
|
||||
{
|
||||
|
||||
+27
-5
@@ -436,6 +436,12 @@ void EDA_SHAPE::SetCenter( const wxPoint& aCenter )
|
||||
|
||||
wxPoint EDA_SHAPE::GetArcMid() const
|
||||
{
|
||||
// If none of the input data have changed since we loaded the arc,
|
||||
// keep the original mid point data to minimize churn
|
||||
if( m_arcMidData.start == m_start && m_arcMidData.end == m_end
|
||||
&& m_arcMidData.center == m_arcCenter )
|
||||
return m_arcMidData.mid;
|
||||
|
||||
wxPoint mid = m_start;
|
||||
RotatePoint( &mid, m_arcCenter, -GetArcAngle() / 2.0 );
|
||||
return mid;
|
||||
@@ -486,19 +492,35 @@ int EDA_SHAPE::GetRadius() const
|
||||
}
|
||||
|
||||
|
||||
void EDA_SHAPE::SetCachedArcData( const wxPoint& aStart, const wxPoint& aMid, const wxPoint& aEnd, const wxPoint& aCenter )
|
||||
{
|
||||
m_arcMidData.start = aStart;
|
||||
m_arcMidData.end = aEnd;
|
||||
m_arcMidData.center = aCenter;
|
||||
m_arcMidData.mid = aMid;
|
||||
}
|
||||
|
||||
|
||||
void EDA_SHAPE::SetArcGeometry( const wxPoint& aStart, const wxPoint& aMid, const wxPoint& aEnd )
|
||||
{
|
||||
m_arcMidData = {};
|
||||
m_start = aStart;
|
||||
m_end = aEnd;
|
||||
m_arcCenter = CalcArcCenter( aStart, aMid, aEnd );
|
||||
wxPoint new_mid = GetArcMid();
|
||||
|
||||
m_endsSwapped = false;
|
||||
|
||||
/**
|
||||
* If the input winding doesn't match our internal winding, the calculated midpoint will end up
|
||||
* on the other side of the arc. In this case, we need to flip the start/end points and flag this
|
||||
* change for the system
|
||||
// Watch the ordering here. GetArcMid above needs to be called prior to initializing the
|
||||
// m_arcMidData structure in order to ensure we get the calculated variant, not the cached
|
||||
SetCachedArcData( aStart, aMid, aEnd, m_arcCenter );
|
||||
|
||||
/*
|
||||
* If the input winding doesn't match our internal winding, the calculated midpoint will end
|
||||
* up on the other side of the arc. In this case, we need to flip the start/end points and
|
||||
* flag this change for the system.
|
||||
*/
|
||||
wxPoint new_mid = GetArcMid();
|
||||
|
||||
VECTOR2D dist( new_mid - aMid );
|
||||
VECTOR2D dist2( new_mid - m_arcCenter );
|
||||
|
||||
|
||||
+4
-2
@@ -188,7 +188,7 @@ bool EDA_TEXT::Replace( const wxFindReplaceData& aSearchData )
|
||||
|
||||
void EDA_TEXT::cacheShownText()
|
||||
{
|
||||
if( m_text.IsEmpty() || m_text == wxT( "~" ) ) // ~ is legacy empty-string token
|
||||
if( m_text.IsEmpty() )
|
||||
{
|
||||
m_shown_text = wxEmptyString;
|
||||
m_shown_text_has_text_var_refs = false;
|
||||
@@ -316,7 +316,9 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, bool aInvertY ) const
|
||||
|
||||
// interline spacing is only *between* lines, so total height is the height of the first
|
||||
// line plus the interline distance (with interline spacing) for all subsequent lines
|
||||
textsize.y += KiROUND( ( strings.GetCount() - 1 ) * interline );
|
||||
// Don't add interline spacing to empty textboxes
|
||||
if( strings.GetCount() )
|
||||
textsize.y += KiROUND( ( strings.GetCount() - 1 ) * interline );
|
||||
}
|
||||
|
||||
rect.SetSize( textsize );
|
||||
|
||||
@@ -465,10 +465,10 @@ bool FILENAME_RESOLVER::addPath( const SEARCH_PATH& aPath )
|
||||
wxString msg = _( "Alias: " );
|
||||
msg.append( tpath.m_Alias );
|
||||
msg.append( wxT( "\n" ) );
|
||||
msg.append( _( "This path:wxT( " ) + wxS( " ) " ) );
|
||||
msg.append( _( "This path:" ) + wxS( " " ) );
|
||||
msg.append( tpath.m_Pathvar );
|
||||
msg.append( wxT( "\n" ) );
|
||||
msg.append( _( "Existing path:wxT( " ) + wxS( " ) " ) );
|
||||
msg.append( _( "Existing path:" ) + wxS( " " ) );
|
||||
msg.append( sPL->m_Pathvar );
|
||||
wxMessageBox( msg, _( "Bad alias (duplicate name)" ) );
|
||||
|
||||
|
||||
@@ -642,9 +642,8 @@ void GRID_TRICKS::paste_text( const wxString& cb_text )
|
||||
|
||||
for( int row = start_row; row < end_row; ++row )
|
||||
{
|
||||
// If number of selected rows bigger than count of rows in
|
||||
// the clipboard, paste from the clipboard again and again
|
||||
// while end of the selection is reached.
|
||||
// If number of selected rows is larger than the count of rows on the clipboard, paste
|
||||
// again and again until the end of the selection is reached.
|
||||
if( !rows.HasMoreTokens() )
|
||||
rows.SetString( cb_text, ROW_SEP, wxTOKEN_RET_EMPTY );
|
||||
|
||||
@@ -662,9 +661,12 @@ void GRID_TRICKS::paste_text( const wxString& cb_text )
|
||||
|
||||
for( int col = start_col; col < end_col; ++col )
|
||||
{
|
||||
// If number of selected columns bigger than count of columns in
|
||||
// the clipboard, paste from the clipboard again and again while
|
||||
// end of the selection is reached.
|
||||
// Skip hidden columns
|
||||
if( !m_grid->IsColShown( col ) )
|
||||
continue;
|
||||
|
||||
// If number of selected cols is larger than the count of cols on the clipboard,
|
||||
// paste again and again until the end of the selection is reached.
|
||||
if( !cols.HasMoreTokens() )
|
||||
cols.SetString( rowTxt, COL_SEP, wxTOKEN_RET_EMPTY );
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <core/arraydim.h>
|
||||
#include <id.h>
|
||||
#include <kiplatform/app.h>
|
||||
#include <kiplatform/environment.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <logging.h>
|
||||
|
||||
@@ -230,6 +231,15 @@ KIFACE* KIWAY::KiFACE( FACE_T aFaceId, bool doLoad )
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef KICAD_WIN32_VERIFY_CODESIGN
|
||||
bool codeSignOk = KIPLATFORM::ENV::VerifyFileSignature( dname );
|
||||
if( !codeSignOk )
|
||||
{
|
||||
msg.Printf( _( "Failed to verify kiface library '%s' signature." ), dname );
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
#endif
|
||||
|
||||
wxDynamicLibrary dso;
|
||||
|
||||
void* addr = nullptr;
|
||||
|
||||
@@ -239,6 +239,26 @@ wxString PATHS::GetStockScriptingPath()
|
||||
}
|
||||
|
||||
|
||||
wxString PATHS::GetStockTemplatesPath()
|
||||
{
|
||||
wxString path;
|
||||
|
||||
path = GetStockDataPath() + wxT( "/template" );
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
wxString PATHS::GetLocaleDataPath()
|
||||
{
|
||||
wxString path;
|
||||
|
||||
path = GetStockDataPath() + wxT( "/internat" );
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
wxString PATHS::GetStockPluginsPath()
|
||||
{
|
||||
wxFileName fn;
|
||||
|
||||
+2
-42
@@ -56,6 +56,7 @@
|
||||
#include <settings/settings_manager.h>
|
||||
#include <systemdirsappend.h>
|
||||
#include <trace_helpers.h>
|
||||
#include <paths.h>
|
||||
|
||||
|
||||
/**
|
||||
@@ -540,48 +541,7 @@ void PGM_BASE::SetLanguageIdentifier( int menu_id )
|
||||
|
||||
void PGM_BASE::SetLanguagePath()
|
||||
{
|
||||
SEARCH_STACK guesses;
|
||||
|
||||
SystemDirsAppend( &guesses );
|
||||
|
||||
// Add our internat dir to the wxLocale catalog of paths
|
||||
for( unsigned i = 0; i < guesses.GetCount(); i++ )
|
||||
{
|
||||
wxFileName fn( guesses[i], wxEmptyString );
|
||||
|
||||
// Append path for Windows and unix KiCad package install
|
||||
fn.AppendDir( wxT( "share" ) );
|
||||
fn.AppendDir( wxT( "internat" ) );
|
||||
|
||||
if( fn.IsDirReadable() )
|
||||
{
|
||||
wxLogTrace( traceLocale, wxT( "Adding locale lookup path: " ) + fn.GetPath() );
|
||||
wxLocale::AddCatalogLookupPathPrefix( fn.GetPath() );
|
||||
}
|
||||
|
||||
// Append path for unix standard install
|
||||
fn.RemoveLastDir();
|
||||
fn.AppendDir( wxT( "kicad" ) );
|
||||
fn.AppendDir( wxT( "internat" ) );
|
||||
|
||||
if( fn.IsDirReadable() )
|
||||
{
|
||||
wxLogTrace( traceLocale, wxT( "Adding locale lookup path: " ) + fn.GetPath() );
|
||||
wxLocale::AddCatalogLookupPathPrefix( fn.GetPath() );
|
||||
}
|
||||
|
||||
// Append path for macOS install
|
||||
fn.RemoveLastDir();
|
||||
fn.RemoveLastDir();
|
||||
fn.RemoveLastDir();
|
||||
fn.AppendDir( wxT( "internat" ) );
|
||||
|
||||
if( fn.IsDirReadable() )
|
||||
{
|
||||
wxLogTrace( traceLocale, wxT( "Adding locale lookup path: " ) + fn.GetPath() );
|
||||
wxLocale::AddCatalogLookupPathPrefix( fn.GetPath() );
|
||||
}
|
||||
}
|
||||
wxLocale::AddCatalogLookupPathPrefix( PATHS::GetLocaleDataPath() );
|
||||
|
||||
if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 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 as published by the
|
||||
@@ -842,8 +842,6 @@ void GERBER_PLOTTER::plotArc( const SHAPE_ARC& aArc, bool aPlotInRegion )
|
||||
wxPoint start( aArc.GetP0() );
|
||||
wxPoint end( aArc.GetP1() );
|
||||
wxPoint center( aArc.GetCenter() );
|
||||
double start_angle = aArc.GetStartAngle();
|
||||
double end_angle = aArc.GetEndAngle();
|
||||
|
||||
if( !aPlotInRegion )
|
||||
MoveTo( start);
|
||||
@@ -851,14 +849,20 @@ void GERBER_PLOTTER::plotArc( const SHAPE_ARC& aArc, bool aPlotInRegion )
|
||||
LineTo( start );
|
||||
|
||||
DPOINT devEnd = userToDeviceCoordinates( end );
|
||||
DPOINT devCenter = userToDeviceCoordinates( center ) - userToDeviceCoordinates( start );
|
||||
DPOINT devCenter = userToDeviceCoordinates( center - start );
|
||||
VECTOR2I arcMidPoint = aArc.GetArcMid();
|
||||
|
||||
// We need to know if the arc is CW or CCW in device coordinates, so build this arc.
|
||||
SHAPE_ARC deviceArc( userToDeviceCoordinates( start ),
|
||||
userToDeviceCoordinates( wxPoint( arcMidPoint.x, arcMidPoint.y ) ),
|
||||
devEnd, 0 );
|
||||
|
||||
fprintf( m_outputFile, "G75*\n" ); // Multiquadrant (360 degrees) mode
|
||||
|
||||
if( start_angle < end_angle )
|
||||
fprintf( m_outputFile, "G03*\n" ); // Active circular interpolation, CCW
|
||||
else
|
||||
if( deviceArc.IsClockwise() )
|
||||
fprintf( m_outputFile, "G02*\n" ); // Active circular interpolation, CW
|
||||
else
|
||||
fprintf( m_outputFile, "G03*\n" ); // Active circular interpolation, CCW
|
||||
|
||||
fprintf( m_outputFile, "X%dY%dI%dJ%dD01*\n",
|
||||
KiROUND( devEnd.x ), KiROUND( devEnd.y ),
|
||||
@@ -1010,6 +1014,10 @@ void GERBER_PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aPoly, FILL_T aFill, int
|
||||
const SHAPE_ARC& arc = aPoly.Arc( arcindex );
|
||||
|
||||
plotArc( arc, ii > 0 );
|
||||
|
||||
// skip points on arcs, since we plot the arc itself
|
||||
while( ii+1 < aPoly.PointCount() && arcindex == aPoly.ArcIndex( ii+1 ) )
|
||||
ii++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1040,12 +1048,17 @@ void GERBER_PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aPoly, FILL_T aFill, int
|
||||
const SHAPE_ARC& arc = aPoly.Arc( arcindex );
|
||||
|
||||
plotArc( arc, ii > 0 );
|
||||
|
||||
// skip points on arcs, since we plot the arc itself
|
||||
while( ii+1 < aPoly.PointCount() && arcindex == aPoly.ArcIndex( ii+1 ) )
|
||||
ii++;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the thick outline is closed for filled polygons
|
||||
// (if not filled, could be only a polyline)
|
||||
if( aFill != FILL_T::NO_FILL && ( aPoly.CPoint( 0 ) != aPoly.CPoint( -1 ) ) )
|
||||
if( ( aPoly.CPoint( 0 ) != aPoly.CPoint( -1 ) )
|
||||
&& ( aPoly.IsClosed() || aFill != FILL_T::NO_FILL ) )
|
||||
LineTo( wxPoint( aPoly.CPoint( 0 ) ) );
|
||||
|
||||
PenFinish();
|
||||
|
||||
@@ -83,7 +83,7 @@ void POLYGON_GEOM_MANAGER::SetLeaderMode( LEADER_MODE aMode )
|
||||
|
||||
bool POLYGON_GEOM_MANAGER::IsSelfIntersecting( bool aIncludeLeaderPts ) const
|
||||
{
|
||||
auto pts( m_lockedPoints );
|
||||
SHAPE_LINE_CHAIN pts( m_lockedPoints );
|
||||
|
||||
if( aIncludeLeaderPts )
|
||||
{
|
||||
|
||||
@@ -509,44 +509,7 @@ void COMMON_SETTINGS::InitializeEnvironment()
|
||||
path.AppendDir( wxT( "3dmodels" ) );
|
||||
addVar( wxT( "KICAD6_3DMODEL_DIR" ), path.GetFullPath() );
|
||||
|
||||
// We don't have just one default template path, so use this logic that originally was in
|
||||
// PGM_BASE::InitPgm to determine the best default template path
|
||||
{
|
||||
// Attempt to find the best default template path.
|
||||
SEARCH_STACK bases;
|
||||
SEARCH_STACK templatePaths;
|
||||
|
||||
SystemDirsAppend( &bases );
|
||||
|
||||
for( unsigned i = 0; i < bases.GetCount(); ++i )
|
||||
{
|
||||
wxFileName fn( bases[i], wxEmptyString );
|
||||
|
||||
// Add KiCad template file path to search path list.
|
||||
fn.AppendDir( "template" );
|
||||
|
||||
// Only add path if exists and can be read by the user.
|
||||
if( fn.DirExists() && fn.IsDirReadable() )
|
||||
{
|
||||
wxLogTrace( tracePathsAndFiles, "Checking template path '%s' exists",
|
||||
fn.GetPath() );
|
||||
templatePaths.AddPaths( fn.GetPath() );
|
||||
}
|
||||
}
|
||||
|
||||
if( templatePaths.IsEmpty() )
|
||||
{
|
||||
path = basePath;
|
||||
path.AppendDir( "template" );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Take the first one. There may be more but this will likely be the best option.
|
||||
path.AssignDir( templatePaths[0] );
|
||||
}
|
||||
|
||||
addVar( wxT( "KICAD6_TEMPLATE_DIR" ), path.GetFullPath() );
|
||||
}
|
||||
addVar( wxT( "KICAD6_TEMPLATE_DIR" ), PATHS::GetStockTemplatesPath() );
|
||||
|
||||
addVar( wxT( "KICAD_USER_TEMPLATE_DIR" ), PATHS::GetUserTemplatesPath() );
|
||||
|
||||
|
||||
@@ -387,6 +387,7 @@ wxString SETTINGS_MANAGER::GetPathForSettingsFile( JSON_SETTINGS* aSettings )
|
||||
return GetUserSettingsPath();
|
||||
|
||||
case SETTINGS_LOC::PROJECT:
|
||||
// TODO: MDI support
|
||||
return Prj().GetProjectPath();
|
||||
|
||||
case SETTINGS_LOC::COLORS:
|
||||
@@ -954,42 +955,48 @@ std::vector<wxString> SETTINGS_MANAGER::GetOpenProjects() const
|
||||
}
|
||||
|
||||
|
||||
bool SETTINGS_MANAGER::SaveProject( const wxString& aFullPath )
|
||||
bool SETTINGS_MANAGER::SaveProject( const wxString& aFullPath, PROJECT* aProject )
|
||||
{
|
||||
if( !aProject )
|
||||
aProject = &Prj();
|
||||
|
||||
wxString path = aFullPath;
|
||||
|
||||
if( path.empty() )
|
||||
path = Prj().GetProjectFullName();
|
||||
path = aProject->GetProjectFullName();
|
||||
|
||||
// TODO: refactor for MDI
|
||||
if( Prj().IsReadOnly() )
|
||||
if( aProject->IsReadOnly() )
|
||||
return false;
|
||||
|
||||
if( !m_project_files.count( path ) )
|
||||
return false;
|
||||
|
||||
PROJECT_FILE* project = m_project_files.at( path );
|
||||
wxString projectPath = GetPathForSettingsFile( project );
|
||||
wxString projectPath = aProject->GetProjectPath();
|
||||
|
||||
project->SaveToFile( projectPath );
|
||||
Prj().GetLocalSettings().SaveToFile( projectPath );
|
||||
aProject->GetLocalSettings().SaveToFile( projectPath );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SETTINGS_MANAGER::SaveProjectAs( const wxString& aFullPath )
|
||||
void SETTINGS_MANAGER::SaveProjectAs( const wxString& aFullPath, PROJECT* aProject )
|
||||
{
|
||||
wxString oldName = Prj().GetProjectFullName();
|
||||
if( !aProject )
|
||||
aProject = &Prj();
|
||||
|
||||
wxString oldName = aProject->GetProjectFullName();
|
||||
|
||||
if( aFullPath.IsSameAs( oldName ) )
|
||||
{
|
||||
SaveProject( aFullPath );
|
||||
SaveProject( aFullPath, aProject );
|
||||
return;
|
||||
}
|
||||
|
||||
// Changing this will cause UnloadProject to not save over the "old" project when loading below
|
||||
Prj().setProjectFullName( aFullPath );
|
||||
aProject->setProjectFullName( aFullPath );
|
||||
|
||||
wxFileName fn( aFullPath );
|
||||
|
||||
@@ -997,14 +1004,14 @@ void SETTINGS_MANAGER::SaveProjectAs( const wxString& aFullPath )
|
||||
|
||||
// Ensure read-only flags are copied; this allows doing a "Save As" on a standalong board/sch
|
||||
// without creating project files if the checkbox is turned off
|
||||
project->SetReadOnly( Prj().IsReadOnly() );
|
||||
Prj().GetLocalSettings().SetReadOnly( Prj().IsReadOnly() );
|
||||
project->SetReadOnly( aProject->IsReadOnly() );
|
||||
aProject->GetLocalSettings().SetReadOnly( aProject->IsReadOnly() );
|
||||
|
||||
project->SetFilename( fn.GetName() );
|
||||
project->SaveToFile( fn.GetPath() );
|
||||
|
||||
Prj().GetLocalSettings().SetFilename( fn.GetName() );
|
||||
Prj().GetLocalSettings().SaveToFile( fn.GetPath() );
|
||||
aProject->GetLocalSettings().SetFilename( fn.GetName() );
|
||||
aProject->GetLocalSettings().SaveToFile( fn.GetPath() );
|
||||
|
||||
m_project_files[fn.GetFullPath()] = project;
|
||||
m_project_files.erase( oldName );
|
||||
@@ -1014,9 +1021,12 @@ void SETTINGS_MANAGER::SaveProjectAs( const wxString& aFullPath )
|
||||
}
|
||||
|
||||
|
||||
void SETTINGS_MANAGER::SaveProjectCopy( const wxString& aFullPath )
|
||||
void SETTINGS_MANAGER::SaveProjectCopy( const wxString& aFullPath, PROJECT* aProject )
|
||||
{
|
||||
PROJECT_FILE* project = m_project_files.at( Prj().GetProjectFullName() );
|
||||
if( !aProject )
|
||||
aProject = &Prj();
|
||||
|
||||
PROJECT_FILE* project = m_project_files.at( aProject->GetProjectFullName() );
|
||||
wxString oldName = project->GetFilename();
|
||||
wxFileName fn( aFullPath );
|
||||
|
||||
@@ -1027,9 +1037,11 @@ void SETTINGS_MANAGER::SaveProjectCopy( const wxString& aFullPath )
|
||||
project->SaveToFile( fn.GetPath() );
|
||||
project->SetFilename( oldName );
|
||||
|
||||
Prj().GetLocalSettings().SetFilename( fn.GetName() );
|
||||
Prj().GetLocalSettings().SaveToFile( fn.GetPath() );
|
||||
Prj().GetLocalSettings().SetFilename( oldName );
|
||||
PROJECT_LOCAL_SETTINGS& localSettings = aProject->GetLocalSettings();
|
||||
|
||||
localSettings.SetFilename( fn.GetName() );
|
||||
localSettings.SaveToFile( fn.GetPath() );
|
||||
localSettings.SetFilename( oldName );
|
||||
|
||||
project->SetReadOnly( readOnly );
|
||||
}
|
||||
|
||||
+19
-1
@@ -50,6 +50,8 @@ wxString ConvertToNewOverbarNotation( const wxString& aOldStr )
|
||||
if( aOldStr == wxT( "~" ) )
|
||||
return aOldStr;
|
||||
|
||||
newStr.reserve( aOldStr.length() );
|
||||
|
||||
for( wxString::const_iterator chIt = aOldStr.begin(); chIt != aOldStr.end(); ++chIt )
|
||||
{
|
||||
if( *chIt == '~' )
|
||||
@@ -142,6 +144,8 @@ wxString EscapeString( const wxString& aSource, ESCAPE_CONTEXT aContext )
|
||||
{
|
||||
wxString converted;
|
||||
|
||||
converted.reserve( aSource.length() );
|
||||
|
||||
for( wxUniChar c: aSource )
|
||||
{
|
||||
if( aContext == CTX_NETNAME )
|
||||
@@ -232,8 +236,16 @@ wxString EscapeString( const wxString& aSource, ESCAPE_CONTEXT aContext )
|
||||
|
||||
wxString UnescapeString( const wxString& aSource )
|
||||
{
|
||||
size_t sourceLen = aSource.length();
|
||||
|
||||
// smallest escape string is three characters, shortcut everything else
|
||||
if( sourceLen <= 2 )
|
||||
{
|
||||
return aSource;
|
||||
}
|
||||
|
||||
wxString newbuf;
|
||||
size_t sourceLen = aSource.length();
|
||||
newbuf.reserve( sourceLen );
|
||||
|
||||
for( size_t i = 0; i < sourceLen; ++i )
|
||||
{
|
||||
@@ -305,6 +317,8 @@ wxString TitleCaps( const wxString& aString )
|
||||
|
||||
wxStringSplit( aString, words, ' ' );
|
||||
|
||||
result.reserve( aString.length() );
|
||||
|
||||
for( const wxString& word : words )
|
||||
{
|
||||
if( !result.IsEmpty() )
|
||||
@@ -423,6 +437,8 @@ std::string EscapedUTF8( const wxString& aString )
|
||||
|
||||
std::string ret;
|
||||
|
||||
ret.reserve( utf8.length() + 2 );
|
||||
|
||||
ret += '"';
|
||||
|
||||
for( std::string::const_iterator it = utf8.begin(); it!=utf8.end(); ++it )
|
||||
@@ -454,6 +470,8 @@ wxString EscapeHTML( const wxString& aString )
|
||||
{
|
||||
wxString converted;
|
||||
|
||||
converted.reserve( aString.length() );
|
||||
|
||||
for( wxUniChar c : aString )
|
||||
{
|
||||
if( c == '\"' )
|
||||
|
||||
@@ -144,20 +144,21 @@ void CONDITIONAL_MENU::Evaluate( SELECTION& aSelection )
|
||||
switch( entry.Type() )
|
||||
{
|
||||
case ENTRY::ACTION:
|
||||
menuItem = Add( *entry.Action(), entry.IsCheckmarkEntry() );
|
||||
Add( *entry.Action(), entry.IsCheckmarkEntry() );
|
||||
menu_count++;
|
||||
break;
|
||||
|
||||
case ENTRY::MENU:
|
||||
menuItem = Add( entry.Menu() );
|
||||
entry.Menu()->UpdateTitle();
|
||||
Add( entry.Menu() );
|
||||
menu_count++;
|
||||
break;
|
||||
|
||||
case ENTRY::WXITEM:
|
||||
menuItem = new wxMenuItem( this,
|
||||
entry.wxItem()->GetId(),
|
||||
entry.wxItem()->GetItemLabel(),
|
||||
entry.wxItem()->GetHelp(),
|
||||
wxGetTranslation( entry.wxItem()->GetItemLabel() ),
|
||||
wxGetTranslation( entry.wxItem()->GetHelp() ),
|
||||
entry.wxItem()->GetKind() );
|
||||
|
||||
if( !!entry.GetIcon() )
|
||||
@@ -171,7 +172,7 @@ void CONDITIONAL_MENU::Evaluate( SELECTION& aSelection )
|
||||
|
||||
case ENTRY::SEPARATOR:
|
||||
if( menu_count )
|
||||
menuItem = AppendSeparator();
|
||||
AppendSeparator();
|
||||
|
||||
menu_count = 0;
|
||||
break;
|
||||
|
||||
@@ -37,7 +37,7 @@ GRID_MENU::GRID_MENU( EDA_DRAW_FRAME* aParent ) :
|
||||
ACTION_MENU( true ),
|
||||
m_parent( aParent )
|
||||
{
|
||||
SetTitle( _( "Grid" ) );
|
||||
UpdateTitle();
|
||||
SetIcon( BITMAPS::grid_select );
|
||||
|
||||
APP_SETTINGS_BASE* settings = m_parent->config();
|
||||
@@ -59,6 +59,12 @@ OPT_TOOL_EVENT GRID_MENU::eventHandler( const wxMenuEvent& aEvent )
|
||||
}
|
||||
|
||||
|
||||
void GRID_MENU::UpdateTitle()
|
||||
{
|
||||
SetTitle( _( "Grid" ) );
|
||||
}
|
||||
|
||||
|
||||
void GRID_MENU::update()
|
||||
{
|
||||
APP_SETTINGS_BASE* settings = m_parent->config();
|
||||
|
||||
@@ -40,13 +40,8 @@ ZOOM_MENU::ZOOM_MENU( EDA_DRAW_FRAME* aParent ) :
|
||||
ACTION_MENU( true ),
|
||||
m_parent( aParent )
|
||||
{
|
||||
SetTitle( _( "Zoom" ) );
|
||||
UpdateTitle();
|
||||
SetIcon( BITMAPS::zoom_selection );
|
||||
|
||||
int i = ID_POPUP_ZOOM_LEVEL_START + 1; // 0 reserved for menus which support auto-zoom
|
||||
|
||||
for( double factor : m_parent->config()->m_Window.zoom_factors )
|
||||
Append( i++, wxString::Format( _( "Zoom: %.2f" ), factor ), wxEmptyString, wxITEM_CHECK );
|
||||
}
|
||||
|
||||
|
||||
@@ -58,17 +53,30 @@ OPT_TOOL_EVENT ZOOM_MENU::eventHandler( const wxMenuEvent& aEvent )
|
||||
}
|
||||
|
||||
|
||||
void ZOOM_MENU::UpdateTitle()
|
||||
{
|
||||
SetTitle( _( "Zoom" ) );
|
||||
}
|
||||
|
||||
|
||||
void ZOOM_MENU::update()
|
||||
{
|
||||
Clear();
|
||||
|
||||
int ii = ID_POPUP_ZOOM_LEVEL_START + 1; // 0 reserved for menus which support auto-zoom
|
||||
|
||||
for( double factor : m_parent->config()->m_Window.zoom_factors )
|
||||
Append( ii++, wxString::Format( _( "Zoom: %.2f" ), factor ), wxEmptyString, wxITEM_CHECK );
|
||||
|
||||
double zoom = m_parent->GetCanvas()->GetGAL()->GetZoomFactor();
|
||||
|
||||
const std::vector<double>& zoomList = m_parent->config()->m_Window.zoom_factors;
|
||||
|
||||
for( size_t i = 0; i < zoomList.size(); ++i )
|
||||
for( size_t jj = 0; jj < zoomList.size(); ++jj )
|
||||
{
|
||||
// Search for a value near the current zoom setting:
|
||||
double rel_error = std::fabs( zoomList[i] - zoom ) / zoom;
|
||||
double rel_error = std::fabs( zoomList[jj] - zoom ) / zoom;
|
||||
// IDs start with 1 (leaving 0 for auto-zoom)
|
||||
Check( ID_POPUP_ZOOM_LEVEL_START + i + 1, rel_error < 0.1 );
|
||||
Check( ID_POPUP_ZOOM_LEVEL_START + jj + 1, rel_error < 0.1 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* @author Jon Evans <jon@craftyjon.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/statbmp.h>
|
||||
#include <wx/timer.h>
|
||||
|
||||
wxDEFINE_EVENT( TOGGLE_CHANGED, wxCommandEvent );
|
||||
|
||||
@@ -35,7 +36,8 @@ BITMAP_TOGGLE::BITMAP_TOGGLE( wxWindow *aParent, wxWindowID aId, const wxBitmap&
|
||||
wxPanel( aParent, aId ),
|
||||
m_checked( aChecked ),
|
||||
m_unchecked_bitmap( aUncheckedBitmap ),
|
||||
m_checked_bitmap( aCheckedBitmap )
|
||||
m_checked_bitmap( aCheckedBitmap ),
|
||||
m_debounce( 0 )
|
||||
{
|
||||
wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
SetSizer( sizer );
|
||||
@@ -47,13 +49,21 @@ BITMAP_TOGGLE::BITMAP_TOGGLE( wxWindow *aParent, wxWindowID aId, const wxBitmap&
|
||||
sizer->Add( m_bitmap, 0, 0 );
|
||||
|
||||
m_bitmap->Bind( wxEVT_LEFT_UP,
|
||||
[&]( wxMouseEvent& )
|
||||
[&]( wxMouseEvent& event )
|
||||
{
|
||||
wxLongLong now = wxGetLocalTimeMillis();
|
||||
|
||||
if( now - m_debounce < 50 )
|
||||
return;
|
||||
else
|
||||
m_debounce = now;
|
||||
|
||||
SetValue( !GetValue() );
|
||||
wxCommandEvent event( TOGGLE_CHANGED );
|
||||
event.SetInt( m_checked );
|
||||
event.SetEventObject( this );
|
||||
wxPostEvent( this, event );
|
||||
|
||||
wxCommandEvent command( TOGGLE_CHANGED );
|
||||
command.SetInt( m_checked );
|
||||
command.SetEventObject( this );
|
||||
wxPostEvent( this, command );
|
||||
} );
|
||||
|
||||
auto passOnEvent =
|
||||
|
||||
@@ -59,10 +59,17 @@ wxString GRID_CELL_TEXT_BUTTON::GetValue() const
|
||||
void GRID_CELL_TEXT_BUTTON::SetSize( const wxRect& aRect )
|
||||
{
|
||||
wxRect rect( aRect );
|
||||
rect.Inflate( -1 );
|
||||
|
||||
#if defined( __WXMAC__ )
|
||||
rect.Inflate( 3 ); // no FOCUS_RING, even on Mac
|
||||
rect.Inflate( 2 ); // ignore FOCUS_RING
|
||||
#elif defined( __WXGTK__ )
|
||||
rect.Inflate( -3 ); // The -3 is a very sad hack here. Some GTK themes overrun the
|
||||
// default -1, preventing display. Unfortunately, we don't appear to
|
||||
// have a good method of finding the current margin needed.
|
||||
// Some GTK resize events seem to update the cell size but not all and
|
||||
// not consistently.
|
||||
#else
|
||||
rect.Inflate( -1 );
|
||||
#endif
|
||||
|
||||
Combo()->SetSize( rect, wxSIZE_ALLOW_MINUS_ONE );
|
||||
|
||||
@@ -63,7 +63,7 @@ EDA_MSG_PANEL::~EDA_MSG_PANEL()
|
||||
int EDA_MSG_PANEL::GetRequiredHeight( wxWindow* aWindow )
|
||||
{
|
||||
wxSize fontSizeInPixels;
|
||||
wxScreenDC dc;
|
||||
wxWindowDC dc( aWindow );
|
||||
|
||||
dc.SetFont( KIUI::GetControlFont( aWindow ) );
|
||||
dc.GetTextExtent( wxT( "W" ), &fontSizeInPixels.x, &fontSizeInPixels.y );
|
||||
|
||||
@@ -335,7 +335,12 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
std::sort( netNames.begin(), netNames.end() );
|
||||
std::sort( netNames.begin(), netNames.end(),
|
||||
[]( const wxString& lhs, const wxString& rhs )
|
||||
{
|
||||
return StrNumCmp( lhs, rhs, true /* ignore case */ ) < 0;
|
||||
} );
|
||||
|
||||
|
||||
// Special handling for <no net>
|
||||
if( filter.IsEmpty() || wxString( NO_NET ).MakeLower().Matches( filter ) )
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 CERN
|
||||
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
*
|
||||
@@ -121,7 +121,7 @@ bool PROGRESS_REPORTER_BASE::KeepRefreshing( bool aWait )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxMilliSleep( 20 );
|
||||
wxMilliSleep( 33 /* 30 FPS refresh rate */ );
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -175,7 +175,7 @@ set( EESCHEMA_SRCS
|
||||
fields_grid_table.cpp
|
||||
files-io.cpp
|
||||
generate_alias_info.cpp
|
||||
getpart.cpp
|
||||
picksymbol.cpp
|
||||
hierarch.cpp
|
||||
lib_shape.cpp
|
||||
lib_item.cpp
|
||||
|
||||
@@ -144,14 +144,14 @@ public:
|
||||
*/
|
||||
void DoAutoplace( bool aManual )
|
||||
{
|
||||
bool force_wire_spacing = false;
|
||||
bool forceWireSpacing = false;
|
||||
SIDE_AND_NPINS sideandpins = chooseSideForFields( aManual );
|
||||
SIDE field_side = sideandpins.side;
|
||||
wxPoint fbox_pos = fieldBoxPlacement( sideandpins );
|
||||
EDA_RECT field_box( fbox_pos, m_fbox_size );
|
||||
|
||||
if( aManual )
|
||||
force_wire_spacing = fitFieldsBetweenWires( &field_box, field_side );
|
||||
forceWireSpacing = fitFieldsBetweenWires( &field_box, field_side );
|
||||
|
||||
// Move the fields
|
||||
int last_y_coord = field_box.GetTop();
|
||||
@@ -160,6 +160,9 @@ public:
|
||||
{
|
||||
SCH_FIELD* field = m_fields[field_idx];
|
||||
|
||||
if( !field->IsVisible() )
|
||||
continue;
|
||||
|
||||
if( m_allow_rejustify )
|
||||
{
|
||||
if( sideandpins.pins > 0 )
|
||||
@@ -175,8 +178,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
wxPoint pos( fieldHorizPlacement( field, field_box ),
|
||||
fieldVertPlacement( field, field_box, &last_y_coord, !force_wire_spacing ) );
|
||||
wxPoint pos( fieldHPlacement( field, field_box ),
|
||||
fieldVPlacement( field, field_box, &last_y_coord, !forceWireSpacing ) );
|
||||
|
||||
if( m_align_to_grid )
|
||||
{
|
||||
@@ -201,7 +204,15 @@ protected:
|
||||
int max_field_width = 0;
|
||||
int total_height = 0;
|
||||
|
||||
std::vector<SCH_FIELD*> visibleFields;
|
||||
|
||||
for( SCH_FIELD* field : m_fields )
|
||||
{
|
||||
if( field->IsVisible() )
|
||||
visibleFields.push_back( field );
|
||||
}
|
||||
|
||||
for( SCH_FIELD* field : visibleFields )
|
||||
{
|
||||
if( m_symbol->GetTransform().y1 )
|
||||
field->SetTextAngle( TEXT_ANGLE_VERT );
|
||||
@@ -215,7 +226,7 @@ protected:
|
||||
max_field_width = std::max( max_field_width, field_width );
|
||||
|
||||
// Remove interline spacing from field_height for last line.
|
||||
if( field == m_fields[ m_fields.size() - 1 ] )
|
||||
if( field == visibleFields.back() )
|
||||
field_height *= 0.62;
|
||||
|
||||
if( !aDynamic )
|
||||
@@ -322,6 +333,7 @@ protected:
|
||||
if( item_box.Intersects( aRect ) )
|
||||
filtered.push_back( item );
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
@@ -642,7 +654,7 @@ protected:
|
||||
*
|
||||
* @return Correct field horizontal position
|
||||
*/
|
||||
int fieldHorizPlacement( SCH_FIELD *aField, const EDA_RECT &aFieldBox )
|
||||
int fieldHPlacement( SCH_FIELD *aField, const EDA_RECT &aFieldBox )
|
||||
{
|
||||
int field_hjust;
|
||||
int field_xcoord;
|
||||
@@ -677,13 +689,13 @@ protected:
|
||||
*
|
||||
* @param aField - the field to place.
|
||||
* @param aFieldBox - box in which fields will be placed.
|
||||
* @param aPosAccum - pointer to a position accumulator
|
||||
* @param aAccumulatedPosition - pointer to a position accumulator
|
||||
* @param aDynamic - use dynamic spacing
|
||||
*
|
||||
* @return Correct field vertical position
|
||||
*/
|
||||
int fieldVertPlacement( SCH_FIELD *aField, const EDA_RECT &aFieldBox, int *aPosAccum,
|
||||
bool aDynamic )
|
||||
int fieldVPlacement( SCH_FIELD *aField, const EDA_RECT &aFieldBox, int *aAccumulatedPosition,
|
||||
bool aDynamic )
|
||||
{
|
||||
int field_height;
|
||||
int padding;
|
||||
@@ -704,9 +716,9 @@ protected:
|
||||
padding = FIELD_PADDING;
|
||||
}
|
||||
|
||||
int placement = *aPosAccum + padding / 2 + field_height / 2;
|
||||
int placement = *aAccumulatedPosition + padding / 2 + field_height / 2;
|
||||
|
||||
*aPosAccum += padding + field_height;
|
||||
*aAccumulatedPosition += padding + field_height;
|
||||
|
||||
return placement;
|
||||
}
|
||||
|
||||
+114
-64
@@ -366,6 +366,9 @@ void CONNECTION_SUBGRAPH::UpdateItemConnections()
|
||||
{
|
||||
SCH_CONNECTION* item_conn = item->GetOrInitConnection( m_sheet, m_graph );
|
||||
|
||||
if( !item_conn )
|
||||
continue;
|
||||
|
||||
if( ( m_driver_connection->IsBus() && item_conn->IsNet() ) ||
|
||||
( m_driver_connection->IsNet() && item_conn->IsBus() ) )
|
||||
{
|
||||
@@ -625,8 +628,8 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
|
||||
else
|
||||
bus_entry->m_connected_bus_items[1] = busLine;
|
||||
|
||||
bus_entry->ConnectedItems( aSheet ).insert( busLine );
|
||||
busLine->ConnectedItems( aSheet ).insert( bus_entry );
|
||||
bus_entry->AddConnectionTo( aSheet, busLine );
|
||||
busLine->AddConnectionTo( aSheet, bus_entry );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -670,8 +673,8 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
|
||||
test_item->ConnectionPropagatesTo( connected_item ) &&
|
||||
bus_connection_ok )
|
||||
{
|
||||
connected_item->ConnectedItems( aSheet ).insert( test_item );
|
||||
test_item->ConnectedItems( aSheet ).insert( connected_item );
|
||||
connected_item->AddConnectionTo( aSheet, test_item );
|
||||
test_item->AddConnectionTo( aSheet, connected_item );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -696,31 +699,8 @@ void CONNECTION_GRAPH::updateItemConnectivity( const SCH_SHEET_PATH& aSheet,
|
||||
}
|
||||
|
||||
|
||||
// TODO(JE) This won't give the same subgraph IDs (and eventually net/graph codes)
|
||||
// to the same subgraph necessarily if it runs over and over again on the same
|
||||
// sheet. We need:
|
||||
//
|
||||
// a) a cache of net/bus codes, like used before
|
||||
// b) to persist the CONNECTION_GRAPH globally so the cache is persistent,
|
||||
// c) some way of trying to avoid changing net names. so we should keep track
|
||||
// of the previous driver of a net, and if it comes down to choosing between
|
||||
// equally-prioritized drivers, choose the one that already exists as a driver
|
||||
// on some portion of the items.
|
||||
|
||||
|
||||
void CONNECTION_GRAPH::buildConnectionGraph()
|
||||
void CONNECTION_GRAPH::buildItemSubGraphs()
|
||||
{
|
||||
// Recache all bus aliases for later use
|
||||
wxCHECK_RET( m_schematic, wxT( "Connection graph cannot be built without schematic pointer" ) );
|
||||
|
||||
SCH_SHEET_LIST all_sheets = m_schematic->GetSheets();
|
||||
|
||||
for( unsigned i = 0; i < all_sheets.size(); i++ )
|
||||
{
|
||||
for( const auto& alias : all_sheets[i].LastScreen()->GetBusAliases() )
|
||||
m_bus_alias_cache[ alias->GetName() ] = alias;
|
||||
}
|
||||
|
||||
// Build subgraphs from items (on a per-sheet basis)
|
||||
|
||||
for( SCH_ITEM* item : m_items )
|
||||
@@ -742,21 +722,26 @@ void CONNECTION_GRAPH::buildConnectionGraph()
|
||||
connection->SetSubgraphCode( subgraph->m_code );
|
||||
m_item_to_subgraph_map[item] = subgraph;
|
||||
|
||||
std::list<SCH_ITEM*> members;
|
||||
std::list<SCH_ITEM*> memberlist;
|
||||
|
||||
auto get_items =
|
||||
[&]( SCH_ITEM* aItem ) -> bool
|
||||
{
|
||||
SCH_CONNECTION* conn = aItem->GetOrInitConnection( sheet, this );
|
||||
bool unique = !( aItem->GetFlags() & CANDIDATE );
|
||||
|
||||
return ( conn->SubgraphCode() == 0 );
|
||||
if( conn && !conn->SubgraphCode() )
|
||||
aItem->SetFlags( CANDIDATE );
|
||||
|
||||
return ( unique && conn && ( conn->SubgraphCode() == 0 ) );
|
||||
};
|
||||
|
||||
|
||||
std::copy_if( item->ConnectedItems( sheet ).begin(),
|
||||
item->ConnectedItems( sheet ).end(),
|
||||
std::back_inserter( members ), get_items );
|
||||
std::back_inserter( memberlist ), get_items );
|
||||
|
||||
for( SCH_ITEM* connected_item : members )
|
||||
for( SCH_ITEM* connected_item : memberlist )
|
||||
{
|
||||
if( connected_item->Type() == SCH_NO_CONNECT_T )
|
||||
subgraph->m_no_connect = connected_item;
|
||||
@@ -770,24 +755,26 @@ void CONNECTION_GRAPH::buildConnectionGraph()
|
||||
connected_conn->SetSubgraphCode( subgraph->m_code );
|
||||
m_item_to_subgraph_map[connected_item] = subgraph;
|
||||
subgraph->AddItem( connected_item );
|
||||
SCH_ITEM_SET citemset = connected_item->ConnectedItems( sheet );
|
||||
|
||||
std::copy_if( connected_item->ConnectedItems( sheet ).begin(),
|
||||
connected_item->ConnectedItems( sheet ).end(),
|
||||
std::back_inserter( members ), get_items );
|
||||
std::copy_if( citemset.begin(), citemset.end(),
|
||||
std::back_inserter( memberlist ), get_items );
|
||||
}
|
||||
}
|
||||
|
||||
for( SCH_ITEM* connected_item : memberlist )
|
||||
connected_item->ClearFlags( CANDIDATE );
|
||||
|
||||
subgraph->m_dirty = true;
|
||||
m_subgraphs.push_back( subgraph );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO(JE): Net codes are non-deterministic. Fortunately, they are also not really used for
|
||||
* anything. We should consider removing them entirely and just using net names everywhere.
|
||||
*/
|
||||
}
|
||||
|
||||
void CONNECTION_GRAPH::resolveAllDrivers()
|
||||
{
|
||||
// Resolve drivers for subgraphs and propagate connectivity info
|
||||
|
||||
// We don't want to spin up a new thread for fewer than 8 nets (overhead costs)
|
||||
@@ -867,7 +854,11 @@ void CONNECTION_GRAPH::buildConnectionGraph()
|
||||
{
|
||||
return candidate->m_driver;
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
void CONNECTION_GRAPH::collectAllDriverValues()
|
||||
{
|
||||
// Check for subgraphs with the same net name but only weak drivers.
|
||||
// For example, two wires that are both connected to hierarchical
|
||||
// sheet pins that happen to have the same name, but are not the same.
|
||||
@@ -922,7 +913,11 @@ void CONNECTION_GRAPH::buildConnectionGraph()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CONNECTION_GRAPH::generateInvisiblePinSubGraphs()
|
||||
{
|
||||
// Generate subgraphs for invisible power pins. These will be merged with other subgraphs
|
||||
// on the same sheet in the next loop.
|
||||
|
||||
@@ -942,7 +937,7 @@ void CONNECTION_GRAPH::buildConnectionGraph()
|
||||
SCH_CONNECTION* connection = pin->GetOrInitConnection( sheet, this );
|
||||
|
||||
// If this pin already has a subgraph, don't need to process
|
||||
if( connection->SubgraphCode() > 0 )
|
||||
if( !connection || connection->SubgraphCode() > 0 )
|
||||
continue;
|
||||
|
||||
connection->SetName( pin->GetShownName() );
|
||||
@@ -979,7 +974,11 @@ void CONNECTION_GRAPH::buildConnectionGraph()
|
||||
|
||||
connection->SetSubgraphCode( subgraph->m_code );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CONNECTION_GRAPH::processSubGraphs()
|
||||
{
|
||||
// Here we do all the local (sheet) processing of each subgraph, including assigning net
|
||||
// codes, merging subgraphs together that use label connections, etc.
|
||||
|
||||
@@ -1306,6 +1305,49 @@ void CONNECTION_GRAPH::buildConnectionGraph()
|
||||
subgraph->m_driver_connection->Name() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// TODO(JE) This won't give the same subgraph IDs (and eventually net/graph codes)
|
||||
// to the same subgraph necessarily if it runs over and over again on the same
|
||||
// sheet. We need:
|
||||
//
|
||||
// a) a cache of net/bus codes, like used before
|
||||
// b) to persist the CONNECTION_GRAPH globally so the cache is persistent,
|
||||
// c) some way of trying to avoid changing net names. so we should keep track
|
||||
// of the previous driver of a net, and if it comes down to choosing between
|
||||
// equally-prioritized drivers, choose the one that already exists as a driver
|
||||
// on some portion of the items.
|
||||
|
||||
|
||||
void CONNECTION_GRAPH::buildConnectionGraph()
|
||||
{
|
||||
// Recache all bus aliases for later use
|
||||
wxCHECK_RET( m_schematic, wxT( "Connection graph cannot be built without schematic pointer" ) );
|
||||
|
||||
SCH_SHEET_LIST all_sheets = m_schematic->GetSheets();
|
||||
|
||||
for( unsigned i = 0; i < all_sheets.size(); i++ )
|
||||
{
|
||||
for( const auto& alias : all_sheets[i].LastScreen()->GetBusAliases() )
|
||||
m_bus_alias_cache[ alias->GetName() ] = alias;
|
||||
}
|
||||
|
||||
buildItemSubGraphs();
|
||||
|
||||
/**
|
||||
* TODO(JE): Net codes are non-deterministic. Fortunately, they are also not really used for
|
||||
* anything. We should consider removing them entirely and just using net names everywhere.
|
||||
*/
|
||||
|
||||
resolveAllDrivers();
|
||||
|
||||
collectAllDriverValues();
|
||||
|
||||
generateInvisiblePinSubGraphs();
|
||||
|
||||
processSubGraphs();
|
||||
|
||||
// Absorbed subgraphs should no longer be considered
|
||||
alg::delete_if( m_driver_subgraphs, [&]( const CONNECTION_SUBGRAPH* candidate ) -> bool
|
||||
{
|
||||
@@ -1328,7 +1370,13 @@ void CONNECTION_GRAPH::buildConnectionGraph()
|
||||
m_sheet_to_subgraphs_map[ subgraph->m_sheet ].emplace_back( subgraph );
|
||||
|
||||
// Update item connections at this point so that neighbor propagation works
|
||||
nextSubgraph.store( 0 );
|
||||
std::atomic<size_t> nextSubgraph( 0 );
|
||||
|
||||
// We don't want to spin up a new thread for fewer than 8 nets (overhead costs)
|
||||
size_t parallelThreadCount = std::min<size_t>( std::thread::hardware_concurrency(),
|
||||
( m_subgraphs.size() + 3 ) / 4 );
|
||||
|
||||
std::vector<std::future<size_t>> returns( parallelThreadCount );
|
||||
|
||||
auto preliminaryUpdateTask =
|
||||
[&]() -> size_t
|
||||
@@ -1901,7 +1949,7 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
|
||||
// member to have the correct connection info
|
||||
if( conn->IsBus() && !stale_bus_members.empty() )
|
||||
{
|
||||
for( auto stale_member : stale_bus_members )
|
||||
for( SCH_CONNECTION* stale_member : stale_bus_members )
|
||||
{
|
||||
for( CONNECTION_SUBGRAPH* subgraph : visited )
|
||||
{
|
||||
@@ -1933,13 +1981,13 @@ void CONNECTION_GRAPH::propagateToNeighbors( CONNECTION_SUBGRAPH* aSubgraph )
|
||||
std::shared_ptr<SCH_CONNECTION> CONNECTION_GRAPH::getDefaultConnection( SCH_ITEM* aItem,
|
||||
CONNECTION_SUBGRAPH* aSubgraph )
|
||||
{
|
||||
auto c = std::shared_ptr<SCH_CONNECTION>( nullptr );
|
||||
std::shared_ptr<SCH_CONNECTION> c = std::shared_ptr<SCH_CONNECTION>( nullptr );
|
||||
|
||||
switch( aItem->Type() )
|
||||
{
|
||||
case SCH_PIN_T:
|
||||
{
|
||||
auto pin = static_cast<SCH_PIN*>( aItem );
|
||||
SCH_PIN* pin = static_cast<SCH_PIN*>( aItem );
|
||||
|
||||
if( pin->IsPowerConnection() )
|
||||
c = std::make_shared<SCH_CONNECTION>( aItem, aSubgraph->m_sheet );
|
||||
@@ -1981,7 +2029,7 @@ SCH_CONNECTION* CONNECTION_GRAPH::matchBusMember( SCH_CONNECTION* aBusConnection
|
||||
// Vector bus: compare against index, because we allow the name
|
||||
// to be different
|
||||
|
||||
for( const auto& bus_member : aBusConnection->Members() )
|
||||
for( const std::shared_ptr<SCH_CONNECTION>& bus_member : aBusConnection->Members() )
|
||||
{
|
||||
if( bus_member->VectorIndex() == aSearch->VectorIndex() )
|
||||
{
|
||||
@@ -1993,14 +2041,14 @@ SCH_CONNECTION* CONNECTION_GRAPH::matchBusMember( SCH_CONNECTION* aBusConnection
|
||||
else
|
||||
{
|
||||
// Group bus
|
||||
for( const auto& c : aBusConnection->Members() )
|
||||
for( const std::shared_ptr<SCH_CONNECTION>& c : aBusConnection->Members() )
|
||||
{
|
||||
// Vector inside group: compare names, because for bus groups
|
||||
// we expect the naming to be consistent across all usages
|
||||
// TODO(JE) explain this in the docs
|
||||
if( c->Type() == CONNECTION_TYPE::BUS )
|
||||
{
|
||||
for( const auto& bus_member : c->Members() )
|
||||
for( const std::shared_ptr<SCH_CONNECTION>& bus_member : c->Members() )
|
||||
{
|
||||
if( bus_member->LocalName() == aSearch->LocalName() )
|
||||
{
|
||||
@@ -2051,7 +2099,7 @@ std::vector<const CONNECTION_SUBGRAPH*> CONNECTION_GRAPH::GetBusesNeedingMigrati
|
||||
{
|
||||
std::vector<const CONNECTION_SUBGRAPH*> ret;
|
||||
|
||||
for( auto&& subgraph : m_subgraphs )
|
||||
for( CONNECTION_SUBGRAPH* subgraph : m_subgraphs )
|
||||
{
|
||||
// Graph is supposed to be up-to-date before calling this
|
||||
wxASSERT( !subgraph->m_dirty );
|
||||
@@ -2313,8 +2361,8 @@ bool CONNECTION_GRAPH::ercCheckMultipleDrivers( const CONNECTION_SUBGRAPH* aSubg
|
||||
|
||||
bool CONNECTION_GRAPH::ercCheckBusToNetConflicts( const CONNECTION_SUBGRAPH* aSubgraph )
|
||||
{
|
||||
auto sheet = aSubgraph->m_sheet;
|
||||
auto screen = sheet.LastScreen();
|
||||
const SCH_SHEET_PATH& sheet = aSubgraph->m_sheet;
|
||||
SCH_SCREEN* screen = sheet.LastScreen();
|
||||
|
||||
SCH_ITEM* net_item = nullptr;
|
||||
SCH_ITEM* bus_item = nullptr;
|
||||
@@ -2371,8 +2419,8 @@ bool CONNECTION_GRAPH::ercCheckBusToNetConflicts( const CONNECTION_SUBGRAPH* aSu
|
||||
bool CONNECTION_GRAPH::ercCheckBusToBusConflicts( const CONNECTION_SUBGRAPH* aSubgraph )
|
||||
{
|
||||
wxString msg;
|
||||
auto sheet = aSubgraph->m_sheet;
|
||||
auto screen = sheet.LastScreen();
|
||||
const SCH_SHEET_PATH& sheet = aSubgraph->m_sheet;
|
||||
SCH_SCREEN* screen = sheet.LastScreen();
|
||||
|
||||
SCH_ITEM* label = nullptr;
|
||||
SCH_ITEM* port = nullptr;
|
||||
@@ -2440,8 +2488,8 @@ bool CONNECTION_GRAPH::ercCheckBusToBusConflicts( const CONNECTION_SUBGRAPH* aSu
|
||||
bool CONNECTION_GRAPH::ercCheckBusToBusEntryConflicts( const CONNECTION_SUBGRAPH* aSubgraph )
|
||||
{
|
||||
bool conflict = false;
|
||||
auto sheet = aSubgraph->m_sheet;
|
||||
auto screen = sheet.LastScreen();
|
||||
const SCH_SHEET_PATH& sheet = aSubgraph->m_sheet;
|
||||
SCH_SCREEN* screen = sheet.LastScreen();
|
||||
|
||||
SCH_BUS_WIRE_ENTRY* bus_entry = nullptr;
|
||||
SCH_ITEM* bus_wire = nullptr;
|
||||
@@ -2453,7 +2501,7 @@ bool CONNECTION_GRAPH::ercCheckBusToBusEntryConflicts( const CONNECTION_SUBGRAPH
|
||||
return true;
|
||||
}
|
||||
|
||||
for( auto item : aSubgraph->m_items )
|
||||
for( SCH_ITEM* item : aSubgraph->m_items )
|
||||
{
|
||||
switch( item->Type() )
|
||||
{
|
||||
@@ -2509,7 +2557,9 @@ bool CONNECTION_GRAPH::ercCheckBusToBusEntryConflicts( const CONNECTION_SUBGRAPH
|
||||
// or global label
|
||||
if( conflict && CONNECTION_SUBGRAPH::GetDriverPriority( aSubgraph->m_driver )
|
||||
>= CONNECTION_SUBGRAPH::PRIORITY::POWER_PIN )
|
||||
{
|
||||
conflict = false;
|
||||
}
|
||||
|
||||
if( conflict )
|
||||
{
|
||||
@@ -2653,8 +2703,8 @@ bool CONNECTION_GRAPH::ercCheckNoConnects( const CONNECTION_SUBGRAPH* aSubgraph
|
||||
wxString name = pin->Connection( &sheet )->Name();
|
||||
wxString local_name = pin->Connection( &sheet )->Name( true );
|
||||
|
||||
if( m_global_label_cache.count( name ) ||
|
||||
( m_local_label_cache.count( std::make_pair( sheet, local_name ) ) ) )
|
||||
if( m_global_label_cache.count( name )
|
||||
|| m_local_label_cache.count( std::make_pair( sheet, local_name ) ) )
|
||||
{
|
||||
has_other_connections = true;
|
||||
}
|
||||
@@ -2787,7 +2837,7 @@ bool CONNECTION_GRAPH::ercCheckLabels( const CONNECTION_SUBGRAPH* aSubgraph )
|
||||
return false;
|
||||
};
|
||||
|
||||
for( auto item : aSubgraph->m_items )
|
||||
for( SCH_ITEM* item : aSubgraph->m_items )
|
||||
{
|
||||
switch( item->Type() )
|
||||
{
|
||||
@@ -2837,9 +2887,9 @@ bool CONNECTION_GRAPH::ercCheckLabels( const CONNECTION_SUBGRAPH* aSubgraph )
|
||||
|
||||
if( isGlobal )
|
||||
{
|
||||
// This will be set to true if the global is connected to a pin above, but we
|
||||
// want to reset this to false so that globals get flagged if they only have a
|
||||
// single instance connected to a single pin
|
||||
// This will be set to true if the global is connected to a pin above, but we want to
|
||||
// reset this to false so that globals get flagged if they only have a single instance
|
||||
// connected to a single pin
|
||||
hasOtherConnections = ( pinCount > 1 );
|
||||
|
||||
auto it = m_net_name_to_subgraphs_map.find( name );
|
||||
@@ -2853,9 +2903,9 @@ bool CONNECTION_GRAPH::ercCheckLabels( const CONNECTION_SUBGRAPH* aSubgraph )
|
||||
else if( text->Type() == SCH_HIER_LABEL_T )
|
||||
{
|
||||
// For a hier label, check if the parent pin is connected
|
||||
if( aSubgraph->m_hier_parent &&
|
||||
( aSubgraph->m_hier_parent->m_strong_driver ||
|
||||
aSubgraph->m_hier_parent->m_drivers.size() > 1) )
|
||||
if( aSubgraph->m_hier_parent
|
||||
&& ( aSubgraph->m_hier_parent->m_strong_driver
|
||||
|| aSubgraph->m_hier_parent->m_drivers.size() > 1) )
|
||||
{
|
||||
// For now, a simple check: if there is more than one driver, the parent is probably
|
||||
// connected elsewhere (because at least one driver will be the hier pin itself)
|
||||
|
||||
@@ -370,6 +370,33 @@ private:
|
||||
*/
|
||||
void buildConnectionGraph();
|
||||
|
||||
/**
|
||||
* Generates individual item subgraphs on a per-sheet basis
|
||||
*/
|
||||
void buildItemSubGraphs();
|
||||
|
||||
/**
|
||||
* Finds all subgraphs in the connection graph and calls ResolveDrivers() in
|
||||
* parallel
|
||||
*/
|
||||
void resolveAllDrivers();
|
||||
|
||||
/**
|
||||
* Maps the driver values for each subgraph
|
||||
*/
|
||||
void collectAllDriverValues();
|
||||
|
||||
/**
|
||||
* Iterate through the invisible power pins to collect the global labels
|
||||
* as drivers
|
||||
*/
|
||||
void generateInvisiblePinSubGraphs();
|
||||
|
||||
/**
|
||||
* Process all subgraphs to assign netcodes and merge subgraphs based on labels
|
||||
*/
|
||||
void processSubGraphs();
|
||||
|
||||
/**
|
||||
* Helper to assign a new net code to a connection
|
||||
*
|
||||
|
||||
@@ -621,6 +621,7 @@ void DIALOG_LIB_EDIT_PIN_TABLE::OnAddRow( wxCommandEvent& event )
|
||||
newPin->SetOrientation( last->GetOrientation() );
|
||||
newPin->SetType( last->GetType() );
|
||||
newPin->SetShape( last->GetShape() );
|
||||
newPin->SetParent( last->GetParent() );
|
||||
|
||||
wxPoint pos = last->GetPosition();
|
||||
|
||||
|
||||
@@ -455,10 +455,16 @@ void DIALOG_LIB_SYMBOL_PROPERTIES::OnSymbolNameText( wxCommandEvent& event )
|
||||
|
||||
void DIALOG_LIB_SYMBOL_PROPERTIES::OnSymbolNameKillFocus( wxFocusEvent& event )
|
||||
{
|
||||
if( !m_delayedFocusCtrl && !m_SymbolNameCtrl->GetValidator()->Validate( m_SymbolNameCtrl ) )
|
||||
if( !m_delayedFocusCtrl )
|
||||
{
|
||||
// If the validation fails and we throw up a dialog then GTK will give us another
|
||||
// KillFocus event and we end up in infinite recursion. So we use m_delayedFocusCtrl
|
||||
// as a re-entrancy block and then clear it again if validation passes.
|
||||
m_delayedFocusCtrl = m_SymbolNameCtrl;
|
||||
m_delayedFocusPage = 0;
|
||||
|
||||
if( m_SymbolNameCtrl->GetValidator()->Validate( m_SymbolNameCtrl ) )
|
||||
m_delayedFocusCtrl = nullptr;
|
||||
}
|
||||
|
||||
event.Skip();
|
||||
@@ -593,7 +599,7 @@ void DIALOG_LIB_SYMBOL_PROPERTIES::OnEditSpiceModel( wxCommandEvent& event )
|
||||
{
|
||||
#ifdef KICAD_SPICE
|
||||
int diff = m_fields->size();
|
||||
auto symbol = SCH_SYMBOL( *m_libEntry, m_libEntry->GetLibId(), nullptr );
|
||||
auto symbol = SCH_SYMBOL( *m_libEntry, m_libEntry->GetLibId(), nullptr, 0 );
|
||||
|
||||
DIALOG_SPICE_MODEL dialog( this, symbol, m_fields );
|
||||
|
||||
|
||||
@@ -168,7 +168,6 @@ private:
|
||||
|
||||
public:
|
||||
SCH_EDIT_FRAME* m_Parent;
|
||||
wxString m_DefaultNetFmtName;
|
||||
NETLIST_PAGE_DIALOG* m_PanelNetType[4 + CUSTOMPANEL_COUNTMAX];
|
||||
};
|
||||
|
||||
@@ -217,11 +216,7 @@ NETLIST_PAGE_DIALOG::NETLIST_PAGE_DIALOG( wxNotebook* parent, const wxString& ti
|
||||
m_TitleStringCtrl = nullptr;
|
||||
m_AdjustPassiveValues = nullptr;
|
||||
|
||||
wxString netfmtName = static_cast<NETLIST_DIALOG*>( parent->GetParent() )->m_DefaultNetFmtName;
|
||||
|
||||
bool selected = m_pageNetFmtName == netfmtName;
|
||||
|
||||
parent->AddPage( this, title, selected );
|
||||
parent->AddPage( this, title, false );
|
||||
|
||||
wxBoxSizer* MainBoxSizer = new wxBoxSizer( wxVERTICAL );
|
||||
SetSizer( MainBoxSizer );
|
||||
@@ -246,8 +241,6 @@ NETLIST_DIALOG::NETLIST_DIALOG( SCH_EDIT_FRAME* parent ) :
|
||||
|
||||
SCHEMATIC_SETTINGS& settings = m_Parent->Schematic().Settings();
|
||||
|
||||
m_DefaultNetFmtName = settings.m_NetFormatName;
|
||||
|
||||
for( NETLIST_PAGE_DIALOG*& page : m_PanelNetType)
|
||||
page = nullptr;
|
||||
|
||||
@@ -271,6 +264,15 @@ NETLIST_DIALOG::NETLIST_DIALOG( SCH_EDIT_FRAME* parent ) :
|
||||
|
||||
m_sdbSizer2OK->SetDefault();
|
||||
|
||||
for( int ii = 0; m_PanelNetType[ii] && ii < 4 + CUSTOMPANEL_COUNTMAX; ++ii )
|
||||
{
|
||||
if( m_PanelNetType[ii]->GetPageNetFmtName() == settings.m_NetFormatName )
|
||||
{
|
||||
m_NoteBook->ChangeSelection( ii );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Now all widgets have the size fixed, call FinishDialogSettings
|
||||
finishDialogSettings();
|
||||
}
|
||||
@@ -416,8 +418,6 @@ void NETLIST_DIALOG::OnNetlistTypeSelection( wxNotebookEvent& event )
|
||||
if( currPage == nullptr )
|
||||
return;
|
||||
|
||||
m_DefaultNetFmtName = currPage->GetPageNetFmtName();
|
||||
|
||||
m_buttonDelGenerator->Enable( currPage->m_IdNetType >= NET_TYPE_CUSTOM1 );
|
||||
}
|
||||
|
||||
@@ -431,8 +431,7 @@ void NETLIST_DIALOG::NetlistUpdateOpt()
|
||||
|
||||
settings.m_SpiceAdjustPassiveValues = adjust;
|
||||
settings.m_SpiceCommandString = spice_cmd_string;
|
||||
settings.m_NetFormatName = wxEmptyString;
|
||||
settings.m_NetFormatName = m_DefaultNetFmtName;
|
||||
settings.m_NetFormatName = m_PanelNetType[m_NoteBook->GetSelection()]->GetPageNetFmtName();
|
||||
}
|
||||
|
||||
|
||||
@@ -591,7 +590,6 @@ void NETLIST_DIALOG::OnDelGenerator( wxCommandEvent& event )
|
||||
|
||||
currPage->m_CommandStringCtrl->SetValue( wxEmptyString );
|
||||
currPage->m_TitleStringCtrl->SetValue( wxEmptyString );
|
||||
m_DefaultNetFmtName = m_PanelNetType[PANELPCBNEW]->GetPageNetFmtName();
|
||||
|
||||
WriteCurrentNetlistSetup();
|
||||
|
||||
@@ -718,17 +716,8 @@ int InvokeDialogNetList( SCH_EDIT_FRAME* aCaller )
|
||||
{
|
||||
NETLIST_DIALOG dlg( aCaller );
|
||||
|
||||
SCHEMATIC_SETTINGS& settings = aCaller->Schematic().Settings();
|
||||
|
||||
wxString curr_default_netformat = settings.m_NetFormatName;
|
||||
|
||||
int ret = dlg.ShowModal();
|
||||
|
||||
// Update the default netlist and store it in prj config if it was explicitly changed.
|
||||
settings.m_NetFormatName = dlg.m_DefaultNetFmtName; // can have temporary changed
|
||||
|
||||
if( curr_default_netformat != dlg.m_DefaultNetFmtName )
|
||||
aCaller->SaveProjectSettings();
|
||||
aCaller->SaveProjectSettings();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -700,8 +700,19 @@ bool DIALOG_SYMBOL_PROPERTIES::TransferDataFromWindow()
|
||||
m_symbol->SetIncludeInBom( !m_cbExcludeFromBom->IsChecked() );
|
||||
m_symbol->SetIncludeOnBoard( !m_cbExcludeFromBoard->IsChecked() );
|
||||
|
||||
// The value, footprint and datasheet fields and exclude from bill of materials setting
|
||||
// should be kept in sync in multi-unit parts.
|
||||
// Update any assignments
|
||||
if( m_dataModel )
|
||||
{
|
||||
for( const SCH_PIN& model_pin : *m_dataModel )
|
||||
{
|
||||
// map from the edited copy back to the "real" pin in the symbol.
|
||||
SCH_PIN* src_pin = m_symbol->GetPin( model_pin.GetLibPin() );
|
||||
src_pin->SetAlt( model_pin.GetAlt() );
|
||||
}
|
||||
}
|
||||
|
||||
// Keep fields other than the reference, include/exclude flags, and alternate pin assignements
|
||||
// in sync in multi-unit parts.
|
||||
if( m_symbol->GetUnitCount() > 1 && m_symbol->IsAnnotated( &GetParent()->GetCurrentSheet() ) )
|
||||
{
|
||||
wxString ref = m_symbol->GetRef( &GetParent()->GetCurrentSheet() );
|
||||
@@ -722,25 +733,49 @@ bool DIALOG_SYMBOL_PROPERTIES::TransferDataFromWindow()
|
||||
appendUndo );
|
||||
otherUnit->SetValue( m_fields->at( VALUE_FIELD ).GetText() );
|
||||
otherUnit->SetFootprint( m_fields->at( FOOTPRINT_FIELD ).GetText() );
|
||||
otherUnit->GetField( DATASHEET_FIELD )->SetText( m_fields->at( DATASHEET_FIELD ).GetText() );
|
||||
|
||||
for( size_t ii = DATASHEET_FIELD; ii < m_fields->size(); ++ii )
|
||||
{
|
||||
SCH_FIELD* otherField = otherUnit->FindField( m_fields->at( ii ).GetName() );
|
||||
|
||||
if( otherField )
|
||||
{
|
||||
otherField->SetText( m_fields->at( ii ).GetText() );
|
||||
}
|
||||
else
|
||||
{
|
||||
SCH_FIELD* newField = otherUnit->AddField( m_fields->at( ii ) );
|
||||
const_cast<KIID&>( newField->m_Uuid ) = KIID();
|
||||
}
|
||||
}
|
||||
|
||||
for( size_t ii = otherUnit->GetFields().size() - 1; ii > DATASHEET_FIELD; ii-- )
|
||||
{
|
||||
SCH_FIELD& otherField = otherUnit->GetFields().at( ii );
|
||||
|
||||
if( !m_symbol->FindField( otherField.GetName() ) )
|
||||
otherUnit->GetFields().erase( otherUnit->GetFields().begin() + ii );
|
||||
}
|
||||
|
||||
otherUnit->SetIncludeInBom( !m_cbExcludeFromBom->IsChecked() );
|
||||
otherUnit->SetIncludeOnBoard( !m_cbExcludeFromBoard->IsChecked() );
|
||||
|
||||
if( m_dataModel )
|
||||
{
|
||||
for( const SCH_PIN& model_pin : *m_dataModel )
|
||||
{
|
||||
SCH_PIN* src_pin = otherUnit->GetPin( model_pin.GetNumber() );
|
||||
|
||||
if( src_pin )
|
||||
src_pin->SetAlt( model_pin.GetAlt() );
|
||||
}
|
||||
}
|
||||
|
||||
GetParent()->UpdateItem( otherUnit, false, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update any assignments
|
||||
if( m_dataModel )
|
||||
{
|
||||
for( const SCH_PIN& model_pin : *m_dataModel )
|
||||
{
|
||||
// map from the edited copy back to the "real" pin in the symbol.
|
||||
SCH_PIN* src_pin = m_symbol->GetPin( model_pin.GetLibPin() );
|
||||
src_pin->SetAlt( model_pin.GetAlt() );
|
||||
}
|
||||
}
|
||||
|
||||
currentScreen->Append( m_symbol );
|
||||
GetParent()->TestDanglingEnds();
|
||||
GetParent()->UpdateItem( m_symbol, false, true );
|
||||
|
||||
@@ -146,48 +146,8 @@ void EE_COLLECTOR::Collect( SCH_SCREEN* aScreen, const KICAD_T aFilterList[], co
|
||||
|
||||
if( aScreen )
|
||||
{
|
||||
// Symbols and sheets own their own children so have to be visited even if
|
||||
// they're not in the filter list
|
||||
bool symbolsVisited = false;
|
||||
bool sheetsVisited = false;
|
||||
bool globalLabelsVisited = false;
|
||||
|
||||
EE_RTREE& items = aScreen->Items();
|
||||
|
||||
for( const KICAD_T *filter = aFilterList; *filter != EOT; ++filter )
|
||||
{
|
||||
for( SCH_ITEM *item : items.Overlapping( *filter, aPos, m_Threshold ) )
|
||||
{
|
||||
if( *filter == SCH_SYMBOL_T || *filter == SCH_LOCATE_ANY_T )
|
||||
symbolsVisited = true;
|
||||
|
||||
if( *filter == SCH_SHEET_T || *filter == SCH_LOCATE_ANY_T )
|
||||
sheetsVisited = true;
|
||||
|
||||
if( *filter == SCH_GLOBAL_LABEL_T || *filter == SCH_LOCATE_ANY_T )
|
||||
globalLabelsVisited = true;
|
||||
|
||||
item->Visit( m_inspector, nullptr, m_scanTypes );
|
||||
}
|
||||
}
|
||||
|
||||
if( !symbolsVisited )
|
||||
{
|
||||
for( SCH_ITEM *item : items.Overlapping( SCH_SYMBOL_T, aPos, m_Threshold ) )
|
||||
item->Visit( m_inspector, nullptr, m_scanTypes );
|
||||
}
|
||||
|
||||
if( !sheetsVisited )
|
||||
{
|
||||
for( SCH_ITEM *item : items.Overlapping( SCH_SHEET_T, aPos, m_Threshold ) )
|
||||
item->Visit( m_inspector, nullptr, m_scanTypes );
|
||||
}
|
||||
|
||||
if( !globalLabelsVisited )
|
||||
{
|
||||
for( SCH_ITEM *item : items.Overlapping( SCH_GLOBAL_LABEL_T, aPos, m_Threshold ) )
|
||||
item->Visit( m_inspector, nullptr, m_scanTypes );
|
||||
}
|
||||
for( SCH_ITEM *item : aScreen->Items().Overlapping( SCH_LOCATE_ANY_T, aPos, m_Threshold ) )
|
||||
item->Visit( m_inspector, nullptr, m_scanTypes );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -192,7 +192,7 @@ void SCH_EDIT_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
|
||||
|
||||
void SCH_BASE_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
|
||||
{
|
||||
wxCHECK_RET( aCfg, wxT( "Call to SCH_BASE_FRAME::SaveSettings with null settings" ) );
|
||||
wxCHECK_RET( aCfg, wxT( "Call to SCH_BASE_FRAME::LoadSettings with null settings" ) );
|
||||
|
||||
EDA_DRAW_FRAME::LoadSettings( aCfg );
|
||||
|
||||
|
||||
+2
-1
@@ -744,8 +744,9 @@ int ERC_TESTER::TestLibSymbolIssues()
|
||||
}
|
||||
|
||||
std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
|
||||
constexpr int flags = LIB_ITEM::COMPARE_FLAGS::EQUALITY | LIB_ITEM::COMPARE_FLAGS::ERC;
|
||||
|
||||
if( *flattenedSymbol != *libSymbolInSchematic )
|
||||
if( flattenedSymbol->Compare( *libSymbolInSchematic, flags ) != 0 )
|
||||
{
|
||||
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_LIB_SYMBOL_ISSUES );
|
||||
ercItem->SetItems( symbol );
|
||||
|
||||
+11
-9
@@ -62,6 +62,7 @@
|
||||
#include <wx/ffile.h>
|
||||
#include <wx/filedlg.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/stdpaths.h>
|
||||
#include <tools/ee_inspection_tool.h>
|
||||
#include <paths.h>
|
||||
#include <wx_filename.h> // For ::ResolvePossibleSymlinks
|
||||
@@ -693,9 +694,9 @@ bool SCH_EDIT_FRAME::saveSchematicFile( SCH_SHEET* aSheet, const wxString& aSave
|
||||
if( !IsWritable( schematicFileName ) )
|
||||
return false;
|
||||
|
||||
wxFileName tempFile( schematicFileName );
|
||||
tempFile.SetName( wxT( "." ) + tempFile.GetName() );
|
||||
tempFile.SetExt( tempFile.GetExt() + wxT( "$" ) );
|
||||
wxStandardPaths& paths = wxStandardPaths::Get();
|
||||
wxString tempFile = wxFileName::CreateTempFileName(
|
||||
paths.GetTempDir() + wxFileName::GetPathSeparator() + wxT( "eeschema" ) );
|
||||
|
||||
// Save
|
||||
wxLogTrace( traceAutoSave, "Saving file " + schematicFileName.GetFullPath() );
|
||||
@@ -706,7 +707,7 @@ bool SCH_EDIT_FRAME::saveSchematicFile( SCH_SHEET* aSheet, const wxString& aSave
|
||||
|
||||
try
|
||||
{
|
||||
pi->Save( tempFile.GetFullPath(), aSheet, &Schematic() );
|
||||
pi->Save( tempFile, aSheet, &Schematic() );
|
||||
success = true;
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
@@ -717,11 +718,11 @@ bool SCH_EDIT_FRAME::saveSchematicFile( SCH_SHEET* aSheet, const wxString& aSave
|
||||
DisplayError( this, msg );
|
||||
|
||||
msg.Printf( _( "Failed to create temporary file '%s'." ),
|
||||
tempFile.GetFullPath() );
|
||||
tempFile );
|
||||
SetMsgPanel( wxEmptyString, msg );
|
||||
|
||||
// In case we started a file but didn't fully write it, clean up
|
||||
wxRemoveFile( tempFile.GetFullPath() );
|
||||
wxRemoveFile( tempFile );
|
||||
|
||||
success = false;
|
||||
}
|
||||
@@ -729,18 +730,18 @@ bool SCH_EDIT_FRAME::saveSchematicFile( SCH_SHEET* aSheet, const wxString& aSave
|
||||
if( success )
|
||||
{
|
||||
// Replace the original with the temporary file we just wrote
|
||||
success = wxRenameFile( tempFile.GetFullPath(), schematicFileName.GetFullPath() );
|
||||
success = wxRenameFile( tempFile, schematicFileName.GetFullPath() );
|
||||
|
||||
if( !success )
|
||||
{
|
||||
msg.Printf( _( "Error saving schematic file '%s'.\n"
|
||||
"Failed to rename temporary file '%s'." ),
|
||||
schematicFileName.GetFullPath(),
|
||||
tempFile.GetFullPath() );
|
||||
tempFile );
|
||||
DisplayError( this, msg );
|
||||
|
||||
msg.Printf( _( "Failed to rename temporary file '%s'." ),
|
||||
tempFile.GetFullPath() );
|
||||
tempFile );
|
||||
SetMsgPanel( wxEmptyString, msg );
|
||||
}
|
||||
}
|
||||
@@ -1080,6 +1081,7 @@ bool SCH_EDIT_FRAME::SaveProject( bool aSaveAs )
|
||||
}
|
||||
else
|
||||
{
|
||||
RecordERCExclusions(); // ensure ERC Exclusions list is up to date
|
||||
GetSettingsManager()->SaveProject();
|
||||
}
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ void LIB_FIELD::Copy( LIB_FIELD* aTarget ) const
|
||||
}
|
||||
|
||||
|
||||
int LIB_FIELD::compare( const LIB_ITEM& aOther, LIB_ITEM::COMPARE_FLAGS aCompareFlags ) const
|
||||
int LIB_FIELD::compare( const LIB_ITEM& aOther, int aCompareFlags ) const
|
||||
{
|
||||
wxASSERT( aOther.Type() == LIB_FIELD_T );
|
||||
|
||||
|
||||
@@ -185,8 +185,7 @@ private:
|
||||
* - Field width.
|
||||
* - Field height.
|
||||
*/
|
||||
int compare( const LIB_ITEM& aOther,
|
||||
LIB_ITEM::COMPARE_FLAGS aCompareFlags = LIB_ITEM::COMPARE_FLAGS::NORMAL ) const override;
|
||||
int compare( const LIB_ITEM& aOther, int aCompareFlags = 0 ) const override;
|
||||
|
||||
/**
|
||||
* Print the field.
|
||||
|
||||
@@ -64,7 +64,7 @@ void LIB_ITEM::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_IT
|
||||
}
|
||||
|
||||
|
||||
int LIB_ITEM::compare( const LIB_ITEM& aOther, LIB_ITEM::COMPARE_FLAGS aCompareFlags ) const
|
||||
int LIB_ITEM::compare( const LIB_ITEM& aOther, int aCompareFlags ) const
|
||||
{
|
||||
if( Type() != aOther.Type() )
|
||||
return Type() - aOther.Type();
|
||||
|
||||
+13
-6
@@ -73,11 +73,19 @@ public:
|
||||
/**
|
||||
* The list of flags used by the #compare function.
|
||||
*
|
||||
* - NORMAL This compares everything between two #LIB_ITEM objects.
|
||||
* - UNIT This compare flag ignores unit and convert and pin number information when
|
||||
* comparing #LIB_ITEM objects for unit comparison.
|
||||
* - UNIT This flag relaxes unit, conversion and pin number constraints. It is used for
|
||||
* #LIB_ITEM object unit comparisons.
|
||||
* - EQUALITY This flag relaxes ordering contstraints so that fields, etc. don't have to
|
||||
* appear in the same order to be considered equal.
|
||||
* - ERC This flag relaxes constraints on data that is settable in the schematic editor. It
|
||||
* compares only symbol-editor-only data.
|
||||
*/
|
||||
enum COMPARE_FLAGS : int { NORMAL = 0x00, UNIT = 0x01, EQUALITY = 0x02 };
|
||||
enum COMPARE_FLAGS : int
|
||||
{
|
||||
UNIT = 0x01,
|
||||
EQUALITY = 0x02,
|
||||
ERC = 0x04
|
||||
};
|
||||
|
||||
/**
|
||||
* Provide a user-consumable name of the object type. Perform localization when
|
||||
@@ -285,8 +293,7 @@ protected:
|
||||
* zero if the object is equal to \a aOther object, or greater than 0 if the
|
||||
* object is greater than \a aOther object.
|
||||
*/
|
||||
virtual int compare( const LIB_ITEM& aOther,
|
||||
LIB_ITEM::COMPARE_FLAGS aCompareFlags = LIB_ITEM::COMPARE_FLAGS::NORMAL ) const;
|
||||
virtual int compare( const LIB_ITEM& aOther, int aCompareFlags = 0 ) const;
|
||||
|
||||
/**
|
||||
* Print the item to \a aDC.
|
||||
|
||||
+12
-1
@@ -870,7 +870,7 @@ EDA_ITEM* LIB_PIN::Clone() const
|
||||
}
|
||||
|
||||
|
||||
int LIB_PIN::compare( const LIB_ITEM& aOther, LIB_ITEM::COMPARE_FLAGS aCompareFlags ) const
|
||||
int LIB_PIN::compare( const LIB_ITEM& aOther, int aCompareFlags ) const
|
||||
{
|
||||
wxASSERT( aOther.Type() == LIB_PIN_T );
|
||||
|
||||
@@ -1061,6 +1061,17 @@ void LIB_PIN::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITE
|
||||
}
|
||||
|
||||
|
||||
void LIB_PIN::ViewGetLayers( int aLayers[], int& aCount ) const
|
||||
{
|
||||
aCount = 3;
|
||||
aLayers[0] = LAYER_DANGLING; // We don't really show dangling vs non-dangling (since there
|
||||
// are no connections in the symbol editor), but it's still
|
||||
// a good visual indication of which end of the pin is which.
|
||||
aLayers[1] = LAYER_DEVICE;
|
||||
aLayers[2] = LAYER_SELECTION_SHADOWS;
|
||||
}
|
||||
|
||||
|
||||
const EDA_RECT LIB_PIN::GetBoundingBox( bool aIncludeInvisibles, bool aPinOnly ) const
|
||||
{
|
||||
EDA_RECT bbox;
|
||||
|
||||
+3
-2
@@ -170,6 +170,8 @@ public:
|
||||
|
||||
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
|
||||
|
||||
void ViewGetLayers( int aLayers[], int& aCount ) const override;
|
||||
|
||||
/* Cannot use a default parameter here as it will not be compatible with the virtual. */
|
||||
const EDA_RECT GetBoundingBox() const override { return GetBoundingBox( false ); }
|
||||
|
||||
@@ -271,8 +273,7 @@ private:
|
||||
* - Pin horizontal (X) position.
|
||||
* - Pin vertical (Y) position.
|
||||
*/
|
||||
int compare( const LIB_ITEM& aOther,
|
||||
LIB_ITEM::COMPARE_FLAGS aCompareFlags = LIB_ITEM::COMPARE_FLAGS::NORMAL ) const override;
|
||||
int compare( const LIB_ITEM& aOther, int aCompareFlags = 0 ) const override;
|
||||
|
||||
protected:
|
||||
wxPoint m_position; // Position of the pin.
|
||||
|
||||
@@ -66,7 +66,7 @@ EDA_ITEM* LIB_SHAPE::Clone() const
|
||||
}
|
||||
|
||||
|
||||
int LIB_SHAPE::compare( const LIB_ITEM& aOther, LIB_ITEM::COMPARE_FLAGS aCompareFlags ) const
|
||||
int LIB_SHAPE::compare( const LIB_ITEM& aOther, int aCompareFlags ) const
|
||||
{
|
||||
int retv = LIB_ITEM::compare( aOther, aCompareFlags );
|
||||
|
||||
@@ -256,7 +256,12 @@ void LIB_SHAPE::print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset,
|
||||
|
||||
CalcArcAngles( t1, t2 );
|
||||
|
||||
if( aTransform.MapAngles( &t1, &t2 ) == ( NormalizeAngle180( t1 - t2 ) > 0 ) )
|
||||
// N.B. The order of evaluation is critical here as MapAngles will modify t1, t2
|
||||
// and the Normalize routine depends on these modifications for the correct output
|
||||
bool transformed = aTransform.MapAngles( &t1, &t2 );
|
||||
bool transformed2 = ( NormalizeAngle180( t1 - t2 ) > 0 );
|
||||
|
||||
if( transformed == transformed2 )
|
||||
std::swap( pt1, pt2 );
|
||||
}
|
||||
|
||||
|
||||
@@ -113,8 +113,7 @@ private:
|
||||
* - Circle vertical (Y) position.
|
||||
* - Circle radius.
|
||||
*/
|
||||
int compare( const LIB_ITEM& aOther,
|
||||
LIB_ITEM::COMPARE_FLAGS aCompareFlags = LIB_ITEM::COMPARE_FLAGS::NORMAL ) const override;
|
||||
int compare( const LIB_ITEM& aOther, int aCompareFlags = 0 ) const override;
|
||||
|
||||
void print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset, void* aData,
|
||||
const TRANSFORM& aTransform ) override;
|
||||
|
||||
+14
-11
@@ -209,7 +209,7 @@ const LIB_SYMBOL& LIB_SYMBOL::operator=( const LIB_SYMBOL& aSymbol )
|
||||
}
|
||||
|
||||
|
||||
int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, LIB_ITEM::COMPARE_FLAGS aCompareFlags ) const
|
||||
int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags ) const
|
||||
{
|
||||
if( m_me == aRhs.m_me )
|
||||
return 0;
|
||||
@@ -322,17 +322,20 @@ int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, LIB_ITEM::COMPARE_FLAGS aCompar
|
||||
if( m_unitsLocked != aRhs.m_unitsLocked )
|
||||
return ( m_unitsLocked ) ? 1 : -1;
|
||||
|
||||
if( m_showPinNames != aRhs.m_showPinNames )
|
||||
return ( m_showPinNames ) ? 1 : -1;
|
||||
if( ( aCompareFlags & LIB_ITEM::COMPARE_FLAGS::ERC ) == 0 )
|
||||
{
|
||||
if( m_showPinNames != aRhs.m_showPinNames )
|
||||
return ( m_showPinNames ) ? 1 : -1;
|
||||
|
||||
if( m_showPinNumbers != aRhs.m_showPinNumbers )
|
||||
return ( m_showPinNumbers ) ? 1 : -1;
|
||||
if( m_showPinNumbers != aRhs.m_showPinNumbers )
|
||||
return ( m_showPinNumbers ) ? 1 : -1;
|
||||
|
||||
if( m_includeInBom != aRhs.m_includeInBom )
|
||||
return ( m_includeInBom ) ? 1 : -1;
|
||||
if( m_includeInBom != aRhs.m_includeInBom )
|
||||
return ( m_includeInBom ) ? 1 : -1;
|
||||
|
||||
if( m_includeOnBoard != aRhs.m_includeOnBoard )
|
||||
return ( m_includeOnBoard ) ? 1 : -1;
|
||||
if( m_includeOnBoard != aRhs.m_includeOnBoard )
|
||||
return ( m_includeOnBoard ) ? 1 : -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -917,10 +920,10 @@ const EDA_RECT LIB_SYMBOL::GetBodyBoundingBox( int aUnit, int aConvert, bool aIn
|
||||
{
|
||||
const LIB_PIN& pin = static_cast<const LIB_PIN&>( item );
|
||||
|
||||
// Note: the roots of the pins are always inlcuded for symbols that don't have a
|
||||
// Note: the roots of the pins are always included for symbols that don't have a
|
||||
// well-defined body.
|
||||
|
||||
if( aIncludePins )
|
||||
if( aIncludePins && pin.IsVisible() )
|
||||
bbox.Merge( pin.GetBoundingBox( false, true ) );
|
||||
else
|
||||
bbox.Merge( pin.GetPinRoot() );
|
||||
|
||||
@@ -612,8 +612,7 @@ public:
|
||||
* 1 if this symbol is greater than \a aRhs
|
||||
* 0 if this symbol is the same as \a aRhs
|
||||
*/
|
||||
int Compare( const LIB_SYMBOL& aRhs,
|
||||
LIB_ITEM::COMPARE_FLAGS aCompareFlags = LIB_ITEM::COMPARE_FLAGS::NORMAL ) const;
|
||||
int Compare( const LIB_SYMBOL& aRhs, int aCompareFlags = 0 ) const;
|
||||
|
||||
bool operator==( const LIB_SYMBOL* aSymbol ) const { return this == aSymbol; }
|
||||
bool operator==( const LIB_SYMBOL& aSymbol ) const
|
||||
|
||||
@@ -84,7 +84,7 @@ EDA_ITEM* LIB_TEXT::Clone() const
|
||||
}
|
||||
|
||||
|
||||
int LIB_TEXT::compare( const LIB_ITEM& aOther, LIB_ITEM::COMPARE_FLAGS aCompareFlags ) const
|
||||
int LIB_TEXT::compare( const LIB_ITEM& aOther, int aCompareFlags ) const
|
||||
{
|
||||
wxASSERT( aOther.Type() == LIB_TEXT_T );
|
||||
|
||||
|
||||
+1
-2
@@ -117,8 +117,7 @@ private:
|
||||
* - Text width.
|
||||
* - Text height.
|
||||
*/
|
||||
int compare( const LIB_ITEM& aOther,
|
||||
LIB_ITEM::COMPARE_FLAGS aCompareFlags = LIB_ITEM::COMPARE_FLAGS::NORMAL ) const override;
|
||||
int compare( const LIB_ITEM& aOther, int aCompareFlags = 0 ) const override;
|
||||
|
||||
void print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset, void* aData,
|
||||
const TRANSFORM& aTransform ) override;
|
||||
|
||||
@@ -105,7 +105,10 @@ PICKED_SYMBOL SCH_BASE_FRAME::PickSymbolFromLibTree( const SCHLIB_FILTER* aFilte
|
||||
Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>();
|
||||
Pgm().GetSettingsManager().GetAppSettings<SYMBOL_EDITOR_SETTINGS>();
|
||||
|
||||
wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER> adapter = SYMBOL_TREE_MODEL_ADAPTER::Create( this, libs );
|
||||
wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER> dataPtr
|
||||
= SYMBOL_TREE_MODEL_ADAPTER::Create( this, libs );
|
||||
SYMBOL_TREE_MODEL_ADAPTER* modelAdapter
|
||||
= static_cast<SYMBOL_TREE_MODEL_ADAPTER*>( dataPtr.get() );
|
||||
bool loaded = false;
|
||||
|
||||
if( aFilter )
|
||||
@@ -117,14 +120,14 @@ PICKED_SYMBOL SCH_BASE_FRAME::PickSymbolFromLibTree( const SCHLIB_FILTER* aFilte
|
||||
if( libs->HasLibrary( liblist[ii], true ) )
|
||||
{
|
||||
loaded = true;
|
||||
static_cast<SYMBOL_TREE_MODEL_ADAPTER*>( adapter.get() )->AddLibrary( liblist[ii] );
|
||||
modelAdapter->AddLibrary( liblist[ii] );
|
||||
}
|
||||
}
|
||||
|
||||
adapter->AssignIntrinsicRanks();
|
||||
modelAdapter->AssignIntrinsicRanks();
|
||||
|
||||
if( aFilter->GetFilterPowerSymbols() )
|
||||
adapter->SetFilter( SYMBOL_TREE_MODEL_ADAPTER::SYM_FILTER_POWER );
|
||||
modelAdapter->SetFilter( SYMBOL_TREE_MODEL_ADAPTER::SYM_FILTER_POWER );
|
||||
}
|
||||
|
||||
std::vector< LIB_TREE_ITEM* > history_list;
|
||||
@@ -138,29 +141,34 @@ PICKED_SYMBOL SCH_BASE_FRAME::PickSymbolFromLibTree( const SCHLIB_FILTER* aFilte
|
||||
history_list.push_back( symbol );
|
||||
}
|
||||
|
||||
adapter->DoAddLibrary( wxT( "-- " ) + _( "Recently Used" ) + " --", wxEmptyString, history_list,
|
||||
true );
|
||||
modelAdapter->DoAddLibrary( wxT( "-- " ) + _( "Recently Used" ) + wxT( " --" ), wxEmptyString,
|
||||
history_list, true );
|
||||
|
||||
if( !aHistoryList.empty() )
|
||||
adapter->SetPreselectNode( aHistoryList[0].LibId, aHistoryList[0].Unit );
|
||||
modelAdapter->SetPreselectNode( aHistoryList[0].LibId, aHistoryList[0].Unit );
|
||||
|
||||
const std::vector< wxString > libNicknames = libs->GetLogicalLibs();
|
||||
|
||||
if( !loaded )
|
||||
static_cast<SYMBOL_TREE_MODEL_ADAPTER*>( adapter.get() )->AddLibraries( libNicknames,
|
||||
this );
|
||||
{
|
||||
if( !modelAdapter->AddLibraries( libNicknames, this ) )
|
||||
{
|
||||
// loading cancelled by user
|
||||
return PICKED_SYMBOL();
|
||||
}
|
||||
}
|
||||
|
||||
if( aHighlight && aHighlight->IsValid() )
|
||||
adapter->SetPreselectNode( *aHighlight, /* aUnit */ 0 );
|
||||
modelAdapter->SetPreselectNode( *aHighlight, /* aUnit */ 0 );
|
||||
|
||||
wxString dialogTitle;
|
||||
|
||||
if( adapter->GetFilter() == SYMBOL_TREE_MODEL_ADAPTER::SYM_FILTER_POWER )
|
||||
dialogTitle.Printf( _( "Choose Power Symbol (%d items loaded)" ), adapter->GetItemCount() );
|
||||
if( modelAdapter->GetFilter() == SYMBOL_TREE_MODEL_ADAPTER::SYM_FILTER_POWER )
|
||||
dialogTitle.Printf( _( "Choose Power Symbol (%d items loaded)" ), dataPtr->GetItemCount() );
|
||||
else
|
||||
dialogTitle.Printf( _( "Choose Symbol (%d items loaded)" ), adapter->GetItemCount() );
|
||||
dialogTitle.Printf( _( "Choose Symbol (%d items loaded)" ), dataPtr->GetItemCount() );
|
||||
|
||||
DIALOG_CHOOSE_SYMBOL dlg( this, dialogTitle, adapter, aConvert, aAllowFields, aShowFootprints,
|
||||
DIALOG_CHOOSE_SYMBOL dlg( this, dialogTitle, dataPtr, aConvert, aAllowFields, aShowFootprints,
|
||||
aUseLibBrowser );
|
||||
|
||||
if( dlg.ShowModal() == wxID_CANCEL )
|
||||
@@ -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-2021 KiCad Developers, see change_log.txt for contributors.
|
||||
* Copyright (C) 2015-2022 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
|
||||
@@ -89,7 +89,6 @@ static void getSymbols( SCHEMATIC* aSchematic, std::vector<SCH_SYMBOL*>& aSymbol
|
||||
static LIB_SYMBOL* findSymbol( const wxString& aName, SYMBOL_LIBS* aLibs, bool aCached )
|
||||
{
|
||||
LIB_SYMBOL *symbol = nullptr;
|
||||
// wxString new_name = LIB_ID::FixIllegalChars( aName, false );
|
||||
|
||||
for( SYMBOL_LIB& each_lib : *aLibs )
|
||||
{
|
||||
@@ -101,6 +100,17 @@ static LIB_SYMBOL* findSymbol( const wxString& aName, SYMBOL_LIBS* aLibs, bool a
|
||||
|
||||
symbol = each_lib.FindSymbol( aName );
|
||||
|
||||
// At some point during V5 development, the LIB_ID delimiter character ':' was
|
||||
// replaced by '_' when writing the symbol cache library so we have to test for
|
||||
// the LIB_NICKNAME_LIB_SYMBOL_NAME case.
|
||||
if( symbol == nullptr && each_lib.IsCache() )
|
||||
{
|
||||
wxString name = aName;
|
||||
|
||||
if( name.Replace( wxT( ":" ), wxT( "_" ) ) )
|
||||
symbol = each_lib.FindSymbol( name );
|
||||
}
|
||||
|
||||
if( symbol )
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -412,7 +412,7 @@ void SCH_CONNECTION::AppendInfoToMsgPanel( std::vector<MSG_PANEL_ITEM>& aList )
|
||||
// CONNECTION_GRAPH entirely in the future, as they are mostly only useful for netlist exports.
|
||||
#if 0
|
||||
if( !IsBus() )
|
||||
aList.emplace_back( _( "Net CodewxT( " ), wxString::Format( " )%d", m_net_code ) );
|
||||
aList.emplace_back( _( "Net Code" ), wxString::Format( "%d", m_net_code ) );
|
||||
#endif
|
||||
|
||||
if( auto alias = m_graph->GetBusAlias( m_name ) )
|
||||
@@ -474,7 +474,7 @@ bool SCH_CONNECTION::MightBeBusLabel( const wxString& aLabel )
|
||||
// Weak heuristic for performance reasons. Stronger test will be used for connectivity
|
||||
wxString label = UnescapeString( aLabel );
|
||||
|
||||
return label.Contains( wxT( "[wxT( " ) ) || label.Contains( wxT( " ){" ) );
|
||||
return label.Contains( wxT( "[" ) ) || label.Contains( wxT( "{" ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
+11
-2
@@ -140,7 +140,7 @@ SCH_CONNECTION* SCH_ITEM::Connection( const SCH_SHEET_PATH* aSheet ) const
|
||||
if( !IsConnectable() )
|
||||
return nullptr;
|
||||
|
||||
wxASSERT_MSG( !IsConnectivityDirty(),
|
||||
wxCHECK_MSG( !IsConnectivityDirty(), nullptr,
|
||||
wxT( "Shouldn't be asking for connection if connectivity is dirty!" ) );
|
||||
|
||||
if( !aSheet )
|
||||
@@ -182,7 +182,13 @@ SCH_ITEM_SET& SCH_ITEM::ConnectedItems( const SCH_SHEET_PATH& aSheet )
|
||||
|
||||
void SCH_ITEM::AddConnectionTo( const SCH_SHEET_PATH& aSheet, SCH_ITEM* aItem )
|
||||
{
|
||||
m_connected_items[ aSheet ].insert( aItem );
|
||||
SCH_ITEM_SET& set = m_connected_items[ aSheet ];
|
||||
|
||||
// The vector elements are small, so reserve 1k at a time to prevent re-allocations
|
||||
if( set.size() == set.capacity() )
|
||||
set.reserve( set.size() + 4096 );
|
||||
|
||||
set.emplace_back( aItem );
|
||||
}
|
||||
|
||||
|
||||
@@ -212,6 +218,9 @@ SCH_CONNECTION* SCH_ITEM::InitializeConnection( const SCH_SHEET_PATH& aSheet,
|
||||
SCH_CONNECTION* SCH_ITEM::GetOrInitConnection( const SCH_SHEET_PATH& aSheet,
|
||||
CONNECTION_GRAPH* aGraph )
|
||||
{
|
||||
if( !IsConnectable() )
|
||||
return nullptr;
|
||||
|
||||
SetConnectivityDirty( false );
|
||||
|
||||
SCH_CONNECTION* connection = Connection( &aSheet );
|
||||
|
||||
+2
-2
@@ -26,7 +26,7 @@
|
||||
#define SCH_ITEM_H
|
||||
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <set>
|
||||
|
||||
#include <eda_item.h>
|
||||
#include <plotters/plotter.h> // for PLOT_DASH_TYPE definition
|
||||
@@ -131,7 +131,7 @@ private:
|
||||
};
|
||||
|
||||
|
||||
typedef std::unordered_set<SCH_ITEM*> SCH_ITEM_SET;
|
||||
typedef std::vector<SCH_ITEM*> SCH_ITEM_SET;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -447,10 +447,12 @@ void SCH_LINE::MirrorHorizontally( int aCenter )
|
||||
|
||||
void SCH_LINE::Rotate( const wxPoint& aCenter )
|
||||
{
|
||||
// When we allow off grid items, the
|
||||
// else if should become a plain if to allow
|
||||
// rotation around the center of the line
|
||||
if( m_flags & STARTPOINT )
|
||||
RotatePoint( &m_start, aCenter, 900 );
|
||||
|
||||
if( m_flags & ENDPOINT )
|
||||
else if( m_flags & ENDPOINT )
|
||||
RotatePoint( &m_end, aCenter, 900 );
|
||||
}
|
||||
|
||||
|
||||
@@ -1352,11 +1352,20 @@ void SCH_EAGLE_PLUGIN::loadInstance( wxXmlNode* aInstanceNode )
|
||||
// with a hash character to mute netlist updater complaints
|
||||
wxString reference = package.IsEmpty() ? '#' + einstance.part : einstance.part;
|
||||
|
||||
// reference must end with a number but EAGLE does not enforce this
|
||||
if( reference.find_last_not_of( "0123456789" ) == (reference.Length()-1) )
|
||||
reference.Append( "0" );
|
||||
|
||||
// EAGLE allows references to be single digits. This breaks KiCad netlisting, which requires
|
||||
// parts to have non-digit + digit annotation. If the reference begins with a number,
|
||||
// we prepend 'UNK' (unknown) for the symbol designator
|
||||
if( reference.find_first_not_of( wxT( "0123456789" ) ) == wxString::npos )
|
||||
reference.Prepend( wxT( "UNK" ) );
|
||||
if( reference.find_first_not_of( "0123456789" ) != 0 )
|
||||
reference.Prepend( "UNK" );
|
||||
|
||||
// EAGLE allows designator to start with # but that is used in KiCad
|
||||
// for symbols which do not have a footprint
|
||||
if( einstance.part.find_first_not_of( "#" ) != 0 )
|
||||
reference.Prepend( "UNK" );
|
||||
|
||||
SCH_SHEET_PATH sheetpath;
|
||||
m_rootSheet->LocatePathOfScreen( screen, &sheetpath );
|
||||
|
||||
@@ -1013,15 +1013,15 @@ LIB_SHAPE* SCH_SEXPR_PARSER::parseArc()
|
||||
}
|
||||
}
|
||||
|
||||
arc->SetStart( startPoint );
|
||||
arc->SetEnd( endPoint );
|
||||
|
||||
if( hasMidPoint )
|
||||
{
|
||||
arc->SetCenter( (wxPoint) CalcArcCenter( arc->GetStart(), midPoint, arc->GetEnd() ) );
|
||||
arc->SetArcGeometry( startPoint, midPoint, endPoint);
|
||||
}
|
||||
else if( hasAngles )
|
||||
{
|
||||
arc->SetStart( startPoint );
|
||||
arc->SetEnd( endPoint );
|
||||
|
||||
/**
|
||||
* This accounts for an oddity in the old library format, where the symbol is overdefined.
|
||||
* The previous draw (based on wxwidgets) used start point and end point and always drew
|
||||
@@ -1035,6 +1035,7 @@ LIB_SHAPE* SCH_SEXPR_PARSER::parseArc()
|
||||
arc->SetStart( arc->GetEnd() );
|
||||
arc->SetEnd( temp );
|
||||
}
|
||||
|
||||
arc->SetCenter( center );
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1090,14 +1090,11 @@ void SCH_SEXPR_PLUGIN::saveSymbol( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aSheetPa
|
||||
m_out->Print( 0, ")" );
|
||||
}
|
||||
|
||||
int unit = -1;
|
||||
int unit = ( aSymbol->GetInstanceReferences().size() == 0 ) ?
|
||||
aSymbol->GetUnit() :
|
||||
aSymbol->GetInstanceReferences()[0].m_Unit;
|
||||
|
||||
if( !( aSymbol->GetInstanceReferences().size() > 1 ) )
|
||||
unit = aSymbol->GetUnit();
|
||||
else if( aSheetPath != nullptr )
|
||||
unit = aSymbol->GetUnitSelection( aSheetPath );
|
||||
if ( unit >= 0 )
|
||||
m_out->Print( 0, " (unit %d)", unit );
|
||||
m_out->Print( 0, " (unit %d)", unit );
|
||||
|
||||
if( aSymbol->GetConvert() == LIB_ITEM::LIB_CONVERT::DEMORGAN )
|
||||
m_out->Print( 0, " (convert %d)", aSymbol->GetConvert() );
|
||||
@@ -1118,10 +1115,49 @@ void SCH_SEXPR_PLUGIN::saveSymbol( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aSheetPa
|
||||
|
||||
for( SCH_FIELD& field : aSymbol->GetFields() )
|
||||
{
|
||||
saveField( &field, aNestLevel + 1 );
|
||||
int id = field.GetId();
|
||||
wxString value = field.GetText();
|
||||
|
||||
// The instance fields are always set to the first sheet instance of the project to
|
||||
// schematic file changes when switching sheet instances with the current project
|
||||
// schematic. It does not solve the problem for schematics shared between projects.
|
||||
if( id == REFERENCE_FIELD )
|
||||
{
|
||||
field.SetText( ( aSymbol->GetInstanceReferences().size() == 0 ) ?
|
||||
value :
|
||||
aSymbol->GetInstanceReferences()[0].m_Reference );
|
||||
}
|
||||
else if( id == VALUE_FIELD )
|
||||
{
|
||||
field.SetText( ( aSymbol->GetInstanceReferences().size() == 0 ) ?
|
||||
value :
|
||||
aSymbol->GetInstanceReferences()[0].m_Value );
|
||||
}
|
||||
else if( id == FOOTPRINT_FIELD )
|
||||
{
|
||||
field.SetText( ( aSymbol->GetInstanceReferences().size() == 0 ) ?
|
||||
value :
|
||||
aSymbol->GetInstanceReferences()[0].m_Footprint );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
saveField( &field, aNestLevel + 1 );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
// Restore the changed field text on write error.
|
||||
if( id == REFERENCE_FIELD || id == VALUE_FIELD || id == FOOTPRINT_FIELD )
|
||||
field.SetText( value );
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
if( id == REFERENCE_FIELD || id == VALUE_FIELD || id == FOOTPRINT_FIELD )
|
||||
field.SetText( value );
|
||||
}
|
||||
|
||||
for( const SCH_PIN* pin : aSymbol->GetPins() )
|
||||
for( const std::unique_ptr<SCH_PIN>& pin : aSymbol->GetRawPins() )
|
||||
{
|
||||
if( pin->GetAlt().IsEmpty() )
|
||||
{
|
||||
|
||||
+25
-1
@@ -248,7 +248,9 @@ bool SCH_SHEET::ResolveTextVar( wxString* token, int aDepth ) const
|
||||
|
||||
PROJECT *project = &Schematic()->Prj();
|
||||
|
||||
if( m_screen->GetTitleBlock().TextVarResolver( token, project ) )
|
||||
// We cannot resolve text variables initially on load as we need to first load the screen and
|
||||
// then parse the hierarchy. So skip the resolution if the screen isn't set yet
|
||||
if( m_screen && m_screen->GetTitleBlock().TextVarResolver( token, project ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -315,6 +317,28 @@ void SCH_SHEET::SwapData( SCH_ITEM* aItem )
|
||||
}
|
||||
|
||||
|
||||
void SCH_SHEET::SetFields( const std::vector<SCH_FIELD>& aFields )
|
||||
{
|
||||
m_fields = aFields;
|
||||
int next_id = SHEET_MANDATORY_FIELDS;
|
||||
|
||||
for( int ii = 0; ii < int( m_fields.size() ); )
|
||||
{
|
||||
if( m_fields[ii].GetId() < 0 || m_fields[ii].GetId() >= ssize_t( m_fields.size() ) )
|
||||
m_fields[ii].SetId( next_id++ );
|
||||
|
||||
if( m_fields[ii].GetId() != ii )
|
||||
std::swap( m_fields[ii], m_fields[m_fields[ii].GetId()]);
|
||||
|
||||
if( m_fields[ii].GetId() == ii )
|
||||
++ii;
|
||||
}
|
||||
|
||||
// Make sure that we get the UNIX variant of the file path
|
||||
SetFileName( m_fields[SHEETFILENAME].GetText() );
|
||||
}
|
||||
|
||||
|
||||
void SCH_SHEET::AddPin( SCH_SHEET_PIN* aSheetPin )
|
||||
{
|
||||
wxASSERT( aSheetPin != nullptr );
|
||||
|
||||
@@ -95,10 +95,7 @@ public:
|
||||
*
|
||||
* @param aFields are the fields to set in this symbol.
|
||||
*/
|
||||
void SetFields( const std::vector<SCH_FIELD>& aFields )
|
||||
{
|
||||
m_fields = aFields; // vector copying, length is changed possibly
|
||||
}
|
||||
void SetFields( const std::vector<SCH_FIELD>& aFields );
|
||||
|
||||
wxString GetName() const { return m_fields[ SHEETNAME ].GetText(); }
|
||||
|
||||
|
||||
@@ -580,8 +580,15 @@ const wxString SCH_SYMBOL::GetValue( const SCH_SHEET_PATH* sheet, bool aResolve
|
||||
{
|
||||
if( instance.m_Path == path && !instance.m_Value.IsEmpty() )
|
||||
{
|
||||
// This can only be an override from an Update Schematic from PCB, and therefore
|
||||
// will always be fully resolved.
|
||||
// This can only be overridden by a new value but if we are resolving,
|
||||
// make sure that the symbol returns the fully resolved text
|
||||
if( aResolve )
|
||||
{
|
||||
SCH_SYMBOL new_sym( *this );
|
||||
new_sym.GetField( VALUE_FIELD )->SetText( instance.m_Value );
|
||||
return new_sym.GetField( VALUE_FIELD )->GetShownText();
|
||||
}
|
||||
|
||||
return instance.m_Value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ public:
|
||||
* @param setNewItemFlag is used to set the symbol #IS_NEW and #IS_MOVING flags.
|
||||
*/
|
||||
SCH_SYMBOL( const LIB_SYMBOL& aSymbol, const LIB_ID& aLibId, const SCH_SHEET_PATH* aSheet,
|
||||
int unit = 0, int convert = 0, const wxPoint& pos = wxPoint( 0, 0 ) );
|
||||
int unit, int convert = 0, const wxPoint& pos = wxPoint( 0, 0 ) );
|
||||
|
||||
SCH_SYMBOL( const LIB_SYMBOL& aSymbol, const SCH_SHEET_PATH* aSheet, const PICKED_SYMBOL& aSel,
|
||||
const wxPoint& pos = wxPoint( 0, 0 ) );
|
||||
@@ -694,13 +694,13 @@ private:
|
||||
*/
|
||||
wxString m_schLibSymbolName;
|
||||
|
||||
TRANSFORM m_transform; ///< The rotation/mirror transformation matrix.
|
||||
SCH_FIELDS m_fields; ///< Variable length list of fields.
|
||||
TRANSFORM m_transform; ///< The rotation/mirror transformation.
|
||||
std::vector<SCH_FIELD> m_fields; ///< Variable length list of fields.
|
||||
|
||||
std::unique_ptr< LIB_SYMBOL > m_part; // a flattened copy of the LIB_SYMBOL from
|
||||
// the PROJECT's libraries.
|
||||
std::vector<std::unique_ptr<SCH_PIN>> m_pins; // a SCH_PIN for every LIB_PIN (all units)
|
||||
std::unordered_map<LIB_PIN*, unsigned> m_pinMap; // library pin pointer to SCH_PIN's index
|
||||
std::unique_ptr< LIB_SYMBOL > m_part; ///< a flattened copy of the LIB_SYMBOL
|
||||
///< from the PROJECT's libraries.
|
||||
std::vector<std::unique_ptr<SCH_PIN>> m_pins; ///< a SCH_PIN for every LIB_PIN (all units)
|
||||
std::unordered_map<LIB_PIN*, unsigned> m_pinMap; ///< library pin pointer : SCH_PIN's index
|
||||
|
||||
bool m_isInNetlist; ///< True if the symbol should appear in the netlist
|
||||
bool m_inBom; ///< True to include in bill of materials export.
|
||||
|
||||
@@ -492,7 +492,7 @@ bool SCH_TEXT::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
m_isDangling = false;
|
||||
|
||||
if( aPath && item.GetType() != PIN_END )
|
||||
m_connected_items[ *aPath ].insert( static_cast<SCH_ITEM*>( item.GetItem() ) );
|
||||
AddConnectionTo( *aPath, static_cast<SCH_ITEM*>( item.GetItem() ) );
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -861,15 +861,18 @@ bool SCH_LABEL::IsType( const KICAD_T aScanTypes[] ) const
|
||||
|
||||
wxCHECK_MSG( Schematic(), false, wxT( "No parent SCHEMATIC set for SCH_LABEL!" ) );
|
||||
|
||||
SCH_SHEET_PATH current = Schematic()->CurrentSheet();
|
||||
// Ensure m_connected_items for Schematic()->CurrentSheet() exists.
|
||||
// Can be not the case when "this" is living in clipboard
|
||||
if( m_connected_items.find( Schematic()->CurrentSheet() ) == m_connected_items.end() )
|
||||
return false;
|
||||
|
||||
const SCH_ITEM_SET& item_set = m_connected_items.at( Schematic()->CurrentSheet() );
|
||||
|
||||
for( const KICAD_T* p = aScanTypes; *p != EOT; ++p )
|
||||
{
|
||||
if( *p == SCH_LABEL_LOCATE_WIRE_T )
|
||||
{
|
||||
wxASSERT( m_connected_items.count( current ) );
|
||||
|
||||
for( SCH_ITEM* connection : m_connected_items.at( current ) )
|
||||
for( SCH_ITEM* connection : item_set )
|
||||
{
|
||||
if( connection->IsType( wireTypes ) )
|
||||
return true;
|
||||
@@ -877,9 +880,7 @@ bool SCH_LABEL::IsType( const KICAD_T aScanTypes[] ) const
|
||||
}
|
||||
else if ( *p == SCH_LABEL_LOCATE_BUS_T )
|
||||
{
|
||||
wxASSERT( m_connected_items.count( current ) );
|
||||
|
||||
for( SCH_ITEM* connection : m_connected_items.at( current ) )
|
||||
for( SCH_ITEM* connection : item_set )
|
||||
{
|
||||
if( connection->IsType( busTypes ) )
|
||||
return true;
|
||||
|
||||
@@ -350,9 +350,6 @@ void SCH_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList )
|
||||
}
|
||||
}
|
||||
|
||||
// Bitmaps are cached in Opengl: clear the cache, because
|
||||
// the cache data can be invalid
|
||||
GetCanvas()->GetView()->RecacheAllItems();
|
||||
GetCanvas()->GetView()->ClearHiddenFlags();
|
||||
}
|
||||
|
||||
@@ -383,7 +380,6 @@ void SCH_EDIT_FRAME::RollbackSchematicFromUndo()
|
||||
m_toolManager->GetTool<EE_SELECTION_TOOL>()->RebuildSelection();
|
||||
}
|
||||
|
||||
SyncView();
|
||||
GetCanvas()->Refresh();
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -264,7 +264,7 @@ bool SCH_EDIT_FRAME::LoadSheetFromFile( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHier
|
||||
msg.Printf( _( "The project library table '%s' does not exist or cannot "
|
||||
"be read. This may result in broken symbol links for the "
|
||||
"schematic. Do you wish to continue?" ),
|
||||
fileName.GetFullPath() );
|
||||
symLibTableFn.GetFullPath() );
|
||||
wxMessageDialog msgDlg4( this, msg, _( "Continue Load Schematic" ),
|
||||
wxOK | wxCANCEL | wxCANCEL_DEFAULT |
|
||||
wxCENTER | wxICON_QUESTION );
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Jon Evans <jon@craftyjon.com>
|
||||
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2021-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 as published by the
|
||||
@@ -35,8 +35,7 @@ SYMBOL_ASYNC_LOADER::SYMBOL_ASYNC_LOADER( const std::vector<wxString>& aNickname
|
||||
m_onlyPowerSymbols( aOnlyPowerSymbols ),
|
||||
m_output( aOutput ),
|
||||
m_reporter( aReporter ),
|
||||
m_nextLibrary( 0 ),
|
||||
m_canceled( false )
|
||||
m_nextLibrary( 0 )
|
||||
{
|
||||
wxASSERT( m_table );
|
||||
m_threadCount = std::max<size_t>( 1, std::thread::hardware_concurrency() );
|
||||
@@ -48,7 +47,7 @@ SYMBOL_ASYNC_LOADER::SYMBOL_ASYNC_LOADER( const std::vector<wxString>& aNickname
|
||||
|
||||
SYMBOL_ASYNC_LOADER::~SYMBOL_ASYNC_LOADER()
|
||||
{
|
||||
Abort();
|
||||
Join();
|
||||
}
|
||||
|
||||
|
||||
@@ -88,13 +87,6 @@ bool SYMBOL_ASYNC_LOADER::Join()
|
||||
}
|
||||
|
||||
|
||||
void SYMBOL_ASYNC_LOADER::Abort()
|
||||
{
|
||||
m_canceled.store( true );
|
||||
Join();
|
||||
}
|
||||
|
||||
|
||||
bool SYMBOL_ASYNC_LOADER::Done()
|
||||
{
|
||||
return m_nextLibrary.load() >= m_nicknames.size();
|
||||
@@ -110,11 +102,15 @@ std::vector<SYMBOL_ASYNC_LOADER::LOADED_PAIR> SYMBOL_ASYNC_LOADER::worker()
|
||||
for( size_t libraryIndex = m_nextLibrary++; libraryIndex < m_nicknames.size();
|
||||
libraryIndex = m_nextLibrary++ )
|
||||
{
|
||||
if( m_canceled.load() )
|
||||
const wxString& nickname = m_nicknames[libraryIndex];
|
||||
|
||||
if( m_reporter )
|
||||
m_reporter->AdvancePhase( wxString::Format( _( "Loading library %s..." ), nickname ) );
|
||||
|
||||
if( m_reporter && m_reporter->IsCancelled() )
|
||||
break;
|
||||
|
||||
const wxString& nickname = m_nicknames[libraryIndex];
|
||||
LOADED_PAIR pair( nickname, {} );
|
||||
LOADED_PAIR pair( nickname, {} );
|
||||
|
||||
try
|
||||
{
|
||||
@@ -129,9 +125,6 @@ std::vector<SYMBOL_ASYNC_LOADER::LOADED_PAIR> SYMBOL_ASYNC_LOADER::worker()
|
||||
std::lock_guard<std::mutex> lock( m_errorMutex );
|
||||
m_errors += msg;
|
||||
}
|
||||
|
||||
if( m_reporter )
|
||||
m_reporter->AdvancePhase( wxString::Format( _( "Loading library %s..." ), nickname ) );
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Jon Evans <jon@craftyjon.com>
|
||||
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2021-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 as published by the
|
||||
@@ -62,11 +62,6 @@ public:
|
||||
*/
|
||||
bool Join();
|
||||
|
||||
/**
|
||||
* Cancels a load in-progress
|
||||
*/
|
||||
void Abort();
|
||||
|
||||
///< Return true if loading is done
|
||||
bool Done();
|
||||
|
||||
@@ -97,7 +92,6 @@ private:
|
||||
|
||||
size_t m_threadCount;
|
||||
std::atomic<size_t> m_nextLibrary;
|
||||
std::atomic_bool m_canceled;
|
||||
wxString m_errors;
|
||||
std::mutex m_errorMutex;
|
||||
|
||||
|
||||
@@ -127,13 +127,20 @@ SYMBOL_EDIT_FRAME::SYMBOL_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||
LoadSettings( m_settings );
|
||||
|
||||
m_libMgr = new SYMBOL_LIBRARY_MANAGER( *this );
|
||||
bool loadingCancelled = false;
|
||||
|
||||
// Preload libraries before using SyncLibraries the first time, as the preload is threaded
|
||||
WX_PROGRESS_REPORTER reporter( this, _( "Loading Symbol Libraries" ),
|
||||
m_libMgr->GetLibraryCount(), true );
|
||||
m_libMgr->Preload( reporter );
|
||||
{
|
||||
// Preload libraries before using SyncLibraries the first time, as the preload is
|
||||
// multi-threaded
|
||||
WX_PROGRESS_REPORTER reporter( this, _( "Loading Symbol Libraries" ),
|
||||
m_libMgr->GetLibraryCount(), true );
|
||||
m_libMgr->Preload( reporter );
|
||||
|
||||
SyncLibraries( false );
|
||||
loadingCancelled = reporter.IsCancelled();
|
||||
wxSafeYield();
|
||||
}
|
||||
|
||||
SyncLibraries( false, loadingCancelled );
|
||||
m_treePane = new SYMBOL_TREE_PANE( this, m_libMgr );
|
||||
|
||||
resolveCanvasType();
|
||||
@@ -235,6 +242,9 @@ SYMBOL_EDIT_FRAME::SYMBOL_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||
|
||||
// Ensure the window is on top
|
||||
Raise();
|
||||
|
||||
if( loadingCancelled )
|
||||
ShowInfoBarWarning( _( "Symbol library loading was cancelled by user." ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -922,7 +932,8 @@ wxString SYMBOL_EDIT_FRAME::getTargetLib() const
|
||||
}
|
||||
|
||||
|
||||
void SYMBOL_EDIT_FRAME::SyncLibraries( bool aShowProgress, const wxString& aForceRefresh )
|
||||
void SYMBOL_EDIT_FRAME::SyncLibraries( bool aShowProgress, bool aPreloadCancelled,
|
||||
const wxString& aForceRefresh )
|
||||
{
|
||||
LIB_ID selected;
|
||||
|
||||
@@ -941,7 +952,7 @@ void SYMBOL_EDIT_FRAME::SyncLibraries( bool aShowProgress, const wxString& aForc
|
||||
libName ) );
|
||||
} );
|
||||
}
|
||||
else
|
||||
else if( !aPreloadCancelled )
|
||||
{
|
||||
m_libMgr->Sync( aForceRefresh,
|
||||
[&]( int progress, int max, const wxString& libName )
|
||||
|
||||
@@ -296,7 +296,8 @@ public:
|
||||
* Synchronize the library manager to the symbol library table, and then the symbol tree
|
||||
* to the library manager. Optionally displays a progress dialog.
|
||||
*/
|
||||
void SyncLibraries( bool aShowProgress, const wxString& aForceRefresh = wxEmptyString );
|
||||
void SyncLibraries( bool aShowProgress, bool aPreloadCancelled = false,
|
||||
const wxString& aForceRefresh = wxEmptyString );
|
||||
|
||||
/**
|
||||
* Filter, sort, and redisplay the library tree.
|
||||
|
||||
@@ -828,8 +828,7 @@ void SYMBOL_EDIT_FRAME::CopySymbolToClipboard()
|
||||
|
||||
void SYMBOL_EDIT_FRAME::DuplicateSymbol( bool aFromClipboard )
|
||||
{
|
||||
int dummyUnit;
|
||||
LIB_ID libId = m_treePane->GetLibTree()->GetSelectedLibId( &dummyUnit );
|
||||
LIB_ID libId = GetTargetLibId();
|
||||
wxString lib = libId.GetLibNickname();
|
||||
|
||||
if( !m_libMgr->LibraryExists( lib ) )
|
||||
@@ -1119,7 +1118,7 @@ bool SYMBOL_EDIT_FRAME::saveLibrary( const wxString& aLibrary, bool aNewFile )
|
||||
if( resyncLibTree )
|
||||
{
|
||||
FreezeLibraryTree();
|
||||
SyncLibraries( true, forceRefresh );
|
||||
SyncLibraries( true, false, forceRefresh );
|
||||
ThawLibraryTree();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,8 +74,6 @@ void SYMBOL_LIBRARY_MANAGER::Sync( const wxString& aForceRefresh,
|
||||
|
||||
void SYMBOL_LIBRARY_MANAGER::Preload( PROGRESS_REPORTER& aReporter )
|
||||
{
|
||||
const int progressIntervalMillis = 60;
|
||||
|
||||
SYMBOL_ASYNC_LOADER loader( symTable()->GetLogicalLibs(), symTable(), false, nullptr,
|
||||
&aReporter );
|
||||
|
||||
@@ -85,19 +83,13 @@ void SYMBOL_LIBRARY_MANAGER::Preload( PROGRESS_REPORTER& aReporter )
|
||||
|
||||
while( !loader.Done() )
|
||||
{
|
||||
aReporter.KeepRefreshing();
|
||||
if( !aReporter.KeepRefreshing() )
|
||||
break;
|
||||
|
||||
wxMilliSleep( progressIntervalMillis );
|
||||
wxMilliSleep( 33 /* 30 FPS refresh rate */ );
|
||||
}
|
||||
|
||||
if( aReporter.IsCancelled() )
|
||||
{
|
||||
loader.Abort();
|
||||
}
|
||||
else
|
||||
{
|
||||
loader.Join();
|
||||
}
|
||||
loader.Join();
|
||||
|
||||
if( !loader.GetErrors().IsEmpty() )
|
||||
{
|
||||
@@ -116,7 +108,7 @@ void SYMBOL_LIBRARY_MANAGER::Preload( PROGRESS_REPORTER& aReporter )
|
||||
|
||||
bool SYMBOL_LIBRARY_MANAGER::HasModifications() const
|
||||
{
|
||||
for( const auto& lib : m_libs )
|
||||
for( const std::pair<const wxString, LIB_BUFFER>& lib : m_libs )
|
||||
{
|
||||
if( lib.second.IsModified() )
|
||||
return true;
|
||||
@@ -130,7 +122,7 @@ int SYMBOL_LIBRARY_MANAGER::GetHash() const
|
||||
{
|
||||
int hash = symTable()->GetModifyHash();
|
||||
|
||||
for( const auto& lib : m_libs )
|
||||
for( const std::pair<const wxString, LIB_BUFFER>& lib : m_libs )
|
||||
hash += lib.second.GetHash();
|
||||
|
||||
return hash;
|
||||
@@ -144,7 +136,7 @@ int SYMBOL_LIBRARY_MANAGER::GetLibraryHash( const wxString& aLibrary ) const
|
||||
if( libBufIt != m_libs.end() )
|
||||
return libBufIt->second.GetHash();
|
||||
|
||||
auto row = GetLibrary( aLibrary );
|
||||
SYMBOL_LIB_TABLE_ROW* row = GetLibrary( aLibrary );
|
||||
|
||||
// return -1 if library does not exist or 0 if not modified
|
||||
return row ? std::hash<std::string>{}( aLibrary.ToStdString() +
|
||||
@@ -156,7 +148,7 @@ wxArrayString SYMBOL_LIBRARY_MANAGER::GetLibraryNames() const
|
||||
{
|
||||
wxArrayString res;
|
||||
|
||||
for( const auto& libName : symTable()->GetLogicalLibs() )
|
||||
for( const wxString& libName : symTable()->GetLogicalLibs() )
|
||||
res.Add( libName );
|
||||
|
||||
return res;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2017 Chris Pavlina <pavlina.chris@gmail.com>
|
||||
* Copyright (C) 2014 Henner Zeller <h.zeller@acm.org>
|
||||
* Copyright (C) 2014-2021 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 as published by the
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
bool SYMBOL_TREE_MODEL_ADAPTER::m_show_progress = true;
|
||||
|
||||
#define PROGRESS_INTERVAL_MILLIS 66
|
||||
#define PROGRESS_INTERVAL_MILLIS 33 // 30 FPS refresh rate
|
||||
|
||||
|
||||
wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER>
|
||||
@@ -56,7 +56,7 @@ SYMBOL_TREE_MODEL_ADAPTER::~SYMBOL_TREE_MODEL_ADAPTER()
|
||||
{}
|
||||
|
||||
|
||||
void SYMBOL_TREE_MODEL_ADAPTER::AddLibraries( const std::vector<wxString>& aNicknames,
|
||||
bool SYMBOL_TREE_MODEL_ADAPTER::AddLibraries( const std::vector<wxString>& aNicknames,
|
||||
wxWindow* aParent )
|
||||
{
|
||||
std::unique_ptr<WX_PROGRESS_REPORTER> prg = nullptr;
|
||||
@@ -82,20 +82,18 @@ void SYMBOL_TREE_MODEL_ADAPTER::AddLibraries( const std::vector<wxString>& aNick
|
||||
|
||||
while( !loader.Done() )
|
||||
{
|
||||
if( prg )
|
||||
prg->KeepRefreshing();
|
||||
if( prg && !prg->KeepRefreshing() )
|
||||
break;
|
||||
|
||||
wxMilliSleep( PROGRESS_INTERVAL_MILLIS );
|
||||
}
|
||||
|
||||
if( prg && prg->IsCancelled() )
|
||||
{
|
||||
loader.Abort();
|
||||
}
|
||||
else
|
||||
{
|
||||
loader.Join();
|
||||
}
|
||||
loader.Join();
|
||||
|
||||
bool cancelled = false;
|
||||
|
||||
if( prg )
|
||||
cancelled = prg->IsCancelled();
|
||||
|
||||
if( !loader.GetErrors().IsEmpty() )
|
||||
{
|
||||
@@ -134,6 +132,8 @@ void SYMBOL_TREE_MODEL_ADAPTER::AddLibraries( const std::vector<wxString>& aNick
|
||||
prg.reset();
|
||||
m_show_progress = false;
|
||||
}
|
||||
|
||||
return !cancelled;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2017 Chris Pavlina <pavlina.chris@gmail.com>
|
||||
* Copyright (C) 2014 Henner Zeller <h.zeller@acm.org>
|
||||
* Copyright (C) 2014-2021 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 as published by the
|
||||
@@ -49,8 +49,9 @@ public:
|
||||
*
|
||||
* @param aNicknames is the list of library nicknames
|
||||
* @param aParent is the parent window to display the progress dialog
|
||||
* @return false if loading was cancelled by the user
|
||||
*/
|
||||
void AddLibraries( const std::vector<wxString>& aNicknames, wxWindow* aParent );
|
||||
bool AddLibraries( const std::vector<wxString>& aNicknames, wxWindow* aParent );
|
||||
|
||||
void AddLibrary( wxString const& aLibNickname );
|
||||
|
||||
|
||||
@@ -835,11 +835,16 @@ void SYMBOL_VIEWER_FRAME::OnSelectSymbol( wxCommandEvent& aEvent )
|
||||
|
||||
// Container doing search-as-you-type.
|
||||
SYMBOL_LIB_TABLE* libs = Prj().SchSymbolLibTable();
|
||||
wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER> adapter =
|
||||
SYMBOL_TREE_MODEL_ADAPTER::Create( this, libs );
|
||||
wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER> dataPtr
|
||||
= SYMBOL_TREE_MODEL_ADAPTER::Create( this, libs );
|
||||
SYMBOL_TREE_MODEL_ADAPTER* modelAdapter
|
||||
= static_cast<SYMBOL_TREE_MODEL_ADAPTER*>( dataPtr.get() );
|
||||
|
||||
const auto libNicknames = libs->GetLogicalLibs();
|
||||
static_cast<SYMBOL_TREE_MODEL_ADAPTER*>( adapter.get() )->AddLibraries( libNicknames, this );
|
||||
if( !modelAdapter->AddLibraries( libs->GetLogicalLibs(), this ) )
|
||||
{
|
||||
// loading cancelled by user
|
||||
return;
|
||||
}
|
||||
|
||||
LIB_SYMBOL* current = GetSelectedSymbol();
|
||||
LIB_ID id;
|
||||
@@ -848,13 +853,13 @@ void SYMBOL_VIEWER_FRAME::OnSelectSymbol( wxCommandEvent& aEvent )
|
||||
if( current )
|
||||
{
|
||||
id = current->GetLibId();
|
||||
adapter->SetPreselectNode( id, unit );
|
||||
modelAdapter->SetPreselectNode( id, unit );
|
||||
}
|
||||
|
||||
wxString dialogTitle;
|
||||
dialogTitle.Printf( _( "Choose Symbol (%d items loaded)" ), adapter->GetItemCount() );
|
||||
dialogTitle.Printf( _( "Choose Symbol (%d items loaded)" ), modelAdapter->GetItemCount() );
|
||||
|
||||
DIALOG_CHOOSE_SYMBOL dlg( this, dialogTitle, adapter, m_convert, false, false, false );
|
||||
DIALOG_CHOOSE_SYMBOL dlg( this, dialogTitle, dataPtr, m_convert, false, false, false );
|
||||
|
||||
if( dlg.ShowQuasiModal() == wxID_CANCEL )
|
||||
return;
|
||||
|
||||
@@ -692,6 +692,11 @@ TOOL_ACTION EE_ACTIONS::addNeededJunctions( "eeschema.InteractiveDrawingLineWire
|
||||
_( "Add Junctions to Selection where needed" ), "",
|
||||
BITMAPS::INVALID_BITMAP, AF_ACTIVATE );
|
||||
|
||||
TOOL_ACTION EE_ACTIONS::trimOverlappingWires( "eeschema.InteractiveDrawingLineWireBus.trimOverlappingWires",
|
||||
AS_ACTIVE, 0, "",
|
||||
"", "",
|
||||
BITMAPS::INVALID_BITMAP, AF_ACTIVATE );
|
||||
|
||||
|
||||
const DRAW_SEGMENT_EVENT_PARAMS drawWireActionParam = { LAYER_WIRE, false };
|
||||
TOOL_ACTION EE_ACTIONS::drawWire( "eeschema.InteractiveDrawingLineWireBus.drawWires",
|
||||
|
||||
@@ -73,6 +73,7 @@ public:
|
||||
|
||||
// Schematic Tools
|
||||
static TOOL_ACTION addNeededJunctions;
|
||||
static TOOL_ACTION trimOverlappingWires;
|
||||
static TOOL_ACTION pickerTool;
|
||||
static TOOL_ACTION placeSymbol;
|
||||
static TOOL_ACTION placePower;
|
||||
|
||||
@@ -517,13 +517,18 @@ int EE_INSPECTION_TOOL::ShowDatasheet( const TOOL_EVENT& aEvent )
|
||||
|
||||
SCH_SYMBOL* symbol = (SCH_SYMBOL*) selection.Front();
|
||||
|
||||
datasheet = symbol->GetField( DATASHEET_FIELD )->GetText();
|
||||
// Use GetShownText() to resolve any text variables
|
||||
datasheet = symbol->GetField( DATASHEET_FIELD )->GetShownText();
|
||||
}
|
||||
|
||||
if( datasheet.IsEmpty() || datasheet == wxT( "~" ) )
|
||||
{
|
||||
m_frame->ShowInfoBarError( _( "No datasheet defined." ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
GetAssociatedDocument( m_frame, datasheet, &m_frame->Prj() );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -165,11 +165,11 @@ bool EE_SELECTION_TOOL::Init()
|
||||
SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T, SCH_LABEL_T,
|
||||
SCH_SHEET_PIN_T, SCH_PIN_T, EOT };
|
||||
|
||||
auto wireSelection = E_C::MoreThan( 0 ) && E_C::OnlyType( SCH_LINE_LOCATE_WIRE_T );
|
||||
auto busSelection = E_C::MoreThan( 0 ) && E_C::OnlyType( SCH_LINE_LOCATE_BUS_T );
|
||||
auto wireOrBusSelection = E_C::MoreThan( 0 ) && E_C::OnlyTypes( wireOrBusTypes );
|
||||
auto connectedSelection = E_C::MoreThan( 0 ) && E_C::OnlyTypes( connectedTypes );
|
||||
auto sheetSelection = E_C::Count( 1 ) && E_C::OnlyType( SCH_SHEET_T );
|
||||
auto wireSelection = E_C::Count( 1 ) && E_C::OnlyType( SCH_LINE_LOCATE_WIRE_T );
|
||||
auto busSelection = E_C::Count( 1 ) && E_C::OnlyType( SCH_LINE_LOCATE_BUS_T );
|
||||
auto wireOrBusSelection = E_C::Count( 1 ) && E_C::OnlyTypes( wireOrBusTypes );
|
||||
auto connectedSelection = E_C::Count( 1 ) && E_C::OnlyTypes( connectedTypes );
|
||||
auto sheetSelection = E_C::Count( 1 ) && E_C::OnlyType( SCH_SHEET_T );
|
||||
|
||||
auto schEditSheetPageNumberCondition =
|
||||
[&] ( const SELECTION& aSel )
|
||||
@@ -219,7 +219,7 @@ bool EE_SELECTION_TOOL::Init()
|
||||
menu.AddItem( EE_ACTIONS::finishBus, SCH_LINE_WIRE_BUS_TOOL::IsDrawingBus, 100 );
|
||||
|
||||
menu.AddSeparator( 200 );
|
||||
menu.AddItem( EE_ACTIONS::selectConnection, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
|
||||
menu.AddItem( EE_ACTIONS::selectConnection, connectedSelection && EE_CONDITIONS::Idle, 250 );
|
||||
menu.AddItem( EE_ACTIONS::placeJunction, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
|
||||
menu.AddItem( EE_ACTIONS::placeLabel, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
|
||||
menu.AddItem( EE_ACTIONS::placeGlobalLabel, wireOrBusSelection && EE_CONDITIONS::Idle, 250 );
|
||||
@@ -754,6 +754,11 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
|
||||
int EE_SELECTION_TOOL::disambiguateCursor( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
wxMouseState keyboardState = wxGetMouseState();
|
||||
|
||||
setModifiersState( keyboardState.ShiftDown(), keyboardState.ControlDown(),
|
||||
keyboardState.AltDown() );
|
||||
|
||||
m_skip_heuristics = true;
|
||||
SelectPoint( m_originalCursor, EE_COLLECTOR::AllItems, nullptr, &m_canceledMenu, false,
|
||||
m_additive, m_subtractive, m_exclusive_or );
|
||||
@@ -853,10 +858,6 @@ void EE_SELECTION_TOOL::narrowSelection( EE_COLLECTOR& collector, const VECTOR2I
|
||||
else
|
||||
line->SetFlags( STARTPOINT | ENDPOINT );
|
||||
}
|
||||
else if( collector[i]->Type() == SCH_LINE_T )
|
||||
{
|
||||
static_cast<SCH_LINE*>( collector[i] )->SetFlags( STARTPOINT | ENDPOINT );
|
||||
}
|
||||
}
|
||||
|
||||
// Apply some ugly heuristics to avoid disambiguation menus whenever possible
|
||||
|
||||
@@ -62,6 +62,7 @@ SCH_DRAWING_TOOLS::SCH_DRAWING_TOOLS() :
|
||||
m_lastTextOrientation( LABEL_SPIN_STYLE::RIGHT ),
|
||||
m_lastTextBold( false ),
|
||||
m_lastTextItalic( false ),
|
||||
m_mruPath( wxEmptyString ),
|
||||
m_inPlaceSymbol( false ),
|
||||
m_inPlaceImage( false ),
|
||||
m_inSingleClickPlace( false ),
|
||||
@@ -191,6 +192,8 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
|
||||
|
||||
if( evt->IsCancelInteractive() )
|
||||
{
|
||||
m_frame->GetInfoBar()->Dismiss();
|
||||
|
||||
if( symbol )
|
||||
{
|
||||
cleanup();
|
||||
@@ -278,12 +281,14 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
|
||||
symbol->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
|
||||
|
||||
symbol->ClearEditFlags();
|
||||
m_view->Update( symbol );
|
||||
m_frame->GetScreen()->Update( symbol );
|
||||
|
||||
m_toolMgr->RunAction( EE_ACTIONS::trimOverlappingWires, true,
|
||||
&m_selectionTool->GetSelection() );
|
||||
m_toolMgr->RunAction( EE_ACTIONS::addNeededJunctions, true,
|
||||
&m_selectionTool->GetSelection() );
|
||||
|
||||
m_view->Update( symbol );
|
||||
m_frame->GetScreen()->Update( symbol );
|
||||
m_frame->OnModify();
|
||||
|
||||
SCH_SYMBOL* nextSymbol = nullptr;
|
||||
@@ -427,6 +432,8 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
|
||||
|
||||
if( evt->IsCancelInteractive() )
|
||||
{
|
||||
m_frame->GetInfoBar()->Dismiss();
|
||||
|
||||
if( image )
|
||||
{
|
||||
cleanup();
|
||||
@@ -487,7 +494,7 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
|
||||
// having an auto-pan
|
||||
EDA_RECT canvas_area = GetCanvasFreeAreaPixels();
|
||||
|
||||
wxFileDialog dlg( m_frame, _( "Choose Image" ), wxEmptyString, wxEmptyString,
|
||||
wxFileDialog dlg( m_frame, _( "Choose Image" ), m_mruPath, wxEmptyString,
|
||||
_( "Image Files" ) + wxS( " " ) + wxImage::GetImageExtWildcard(),
|
||||
wxFD_OPEN );
|
||||
|
||||
@@ -508,6 +515,7 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
|
||||
cursorPos = controls->GetMousePosition( true );
|
||||
|
||||
wxString fullFilename = dlg.GetPath();
|
||||
m_mruPath = wxPathOnly( fullFilename );
|
||||
|
||||
if( wxFileExists( fullFilename ) )
|
||||
image = new SCH_BITMAP( (wxPoint)cursorPos );
|
||||
@@ -1059,6 +1067,8 @@ int SCH_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
|
||||
|
||||
if( evt->IsCancelInteractive() )
|
||||
{
|
||||
m_frame->GetInfoBar()->Dismiss();
|
||||
|
||||
if( item )
|
||||
{
|
||||
cleanup();
|
||||
@@ -1286,6 +1296,8 @@ int SCH_DRAWING_TOOLS::DrawSheet( const TOOL_EVENT& aEvent )
|
||||
|
||||
if( evt->IsCancelInteractive() )
|
||||
{
|
||||
m_frame->GetInfoBar()->Dismiss();
|
||||
|
||||
if( sheet )
|
||||
{
|
||||
cleanup();
|
||||
|
||||
@@ -88,6 +88,7 @@ private:
|
||||
LABEL_SPIN_STYLE m_lastTextOrientation;
|
||||
bool m_lastTextBold;
|
||||
bool m_lastTextItalic;
|
||||
wxString m_mruPath;
|
||||
|
||||
///< Re-entrancy guards
|
||||
bool m_inPlaceSymbol;
|
||||
|
||||
@@ -97,8 +97,8 @@ private:
|
||||
|
||||
if( !symbol )
|
||||
{
|
||||
Append( ID_POPUP_SCH_UNFOLD_BUS, _( "no symbol selected" ), wxEmptyString );
|
||||
Enable( ID_POPUP_SCH_UNFOLD_BUS, false );
|
||||
Append( ID_POPUP_SCH_SELECT_UNIT_CMP, _( "no symbol selected" ), wxEmptyString );
|
||||
Enable( ID_POPUP_SCH_SELECT_UNIT_CMP, false );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -106,8 +106,8 @@ private:
|
||||
|
||||
if( !symbol->GetLibSymbolRef() || symbol->GetLibSymbolRef()->GetUnitCount() < 2 )
|
||||
{
|
||||
Append( ID_POPUP_SCH_UNFOLD_BUS, _( "symbol is not multi-unit" ), wxEmptyString );
|
||||
Enable( ID_POPUP_SCH_UNFOLD_BUS, false );
|
||||
Append( ID_POPUP_SCH_SELECT_UNIT_CMP, _( "symbol is not multi-unit" ), wxEmptyString );
|
||||
Enable( ID_POPUP_SCH_SELECT_UNIT_CMP, false );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -445,7 +445,6 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
|
||||
int principalItemCount = 0; // User-selected items (as opposed to connected wires)
|
||||
wxPoint rotPoint;
|
||||
bool moving = false;
|
||||
bool connections = false;
|
||||
|
||||
for( unsigned ii = 0; ii < selection.GetSize(); ii++ )
|
||||
{
|
||||
@@ -511,6 +510,28 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
|
||||
}
|
||||
|
||||
case SCH_LINE_T:
|
||||
{
|
||||
SCH_LINE* line = static_cast<SCH_LINE*>( head );
|
||||
|
||||
// Equal checks for both and neither. We need this because on undo
|
||||
// the item will have both flags cleared, but will be selected, so it is possible
|
||||
// for the user to get a selected line with neither endpoint selected. We
|
||||
// set flags to make sure Rotate() works when we call it.
|
||||
if( line->HasFlag( STARTPOINT ) == line->HasFlag( ENDPOINT ) )
|
||||
{
|
||||
line->SetFlags( STARTPOINT | ENDPOINT );
|
||||
// When we allow off grid items, the rotPoint should be set to the midpoint
|
||||
// of the line to allow rotation around the center, and the next if
|
||||
// should become an else-if
|
||||
}
|
||||
|
||||
if( line->HasFlag( STARTPOINT ) )
|
||||
rotPoint = line->GetEndPoint();
|
||||
else if( line->HasFlag( ENDPOINT ) )
|
||||
rotPoint = line->GetStartPoint();
|
||||
}
|
||||
|
||||
KI_FALLTHROUGH;
|
||||
case SCH_BUS_BUS_ENTRY_T:
|
||||
case SCH_BUS_WIRE_ENTRY_T:
|
||||
for( int i = 0; clockwise ? i < 3 : i < 1; ++i )
|
||||
@@ -557,7 +578,6 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
|
||||
break;
|
||||
}
|
||||
|
||||
connections = head->IsConnectable();
|
||||
m_frame->UpdateItem( head, false, true );
|
||||
}
|
||||
else
|
||||
@@ -636,7 +656,6 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
|
||||
}
|
||||
}
|
||||
|
||||
connections |= item->IsConnectable();
|
||||
m_frame->UpdateItem( item, false, true );
|
||||
updateItem( item, true );
|
||||
}
|
||||
@@ -652,8 +671,8 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
|
||||
if( selection.IsHover() )
|
||||
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
|
||||
|
||||
if( connections )
|
||||
m_frame->TestDanglingEnds();
|
||||
m_frame->RecalculateConnections( LOCAL_CLEANUP );
|
||||
m_frame->TestDanglingEnds();
|
||||
|
||||
m_frame->OnModify();
|
||||
}
|
||||
@@ -893,6 +912,7 @@ int SCH_EDIT_TOOL::RepeatDrawItem( const TOOL_EVENT& aEvent )
|
||||
EE_SELECTION new_sel;
|
||||
new_sel.Add( newItem );
|
||||
|
||||
m_toolMgr->RunAction( EE_ACTIONS::trimOverlappingWires, true, &new_sel );
|
||||
m_toolMgr->RunAction( EE_ACTIONS::addNeededJunctions, true, &new_sel );
|
||||
|
||||
m_frame->RecalculateConnections( LOCAL_CLEANUP );
|
||||
@@ -1680,7 +1700,12 @@ int SCH_EDIT_TOOL::BreakWire( const TOOL_EVENT& aEvent )
|
||||
m_frame->OnModify();
|
||||
m_frame->GetCanvas()->Refresh();
|
||||
|
||||
m_toolMgr->RunAction( EE_ACTIONS::drag );
|
||||
SCH_MOVE_TOOL_PARAMS params;
|
||||
|
||||
params.appendToLastUndo = true;
|
||||
params.placingNewItems = false;
|
||||
|
||||
m_toolMgr->RunAction( EE_ACTIONS::drag, true, ¶ms );
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -559,6 +559,10 @@ int SCH_EDITOR_CONTROL::ReplaceAndFindNext( const TOOL_EVENT& aEvent )
|
||||
|
||||
if( item && item->Matches( data, sheet ) )
|
||||
{
|
||||
SCH_ITEM* sch_item = static_cast<SCH_ITEM*>( item );
|
||||
|
||||
m_frame->SaveCopyInUndoList( sheet->LastScreen(), sch_item, UNDO_REDO::CHANGED, false );
|
||||
|
||||
if( item->Replace( data, sheet ) )
|
||||
{
|
||||
m_frame->UpdateItem( item, false, true );
|
||||
@@ -585,6 +589,9 @@ int SCH_EDITOR_CONTROL::ReplaceAll( const TOOL_EVENT& aEvent )
|
||||
auto doReplace =
|
||||
[&]( SCH_ITEM* aItem, SCH_SHEET_PATH* aSheet, wxFindReplaceData& aData )
|
||||
{
|
||||
m_frame->SaveCopyInUndoList( aSheet->LastScreen(), aItem, UNDO_REDO::CHANGED,
|
||||
modified );
|
||||
|
||||
if( aItem->Replace( aData, aSheet ) )
|
||||
{
|
||||
m_frame->UpdateItem( aItem, false, true );
|
||||
@@ -1527,19 +1534,16 @@ void SCH_EDITOR_CONTROL::updatePastedSymbol( SCH_SYMBOL* aSymbol, SCH_SCREEN* aP
|
||||
}
|
||||
|
||||
if( aForceKeepAnnotations && !reference.IsEmpty() )
|
||||
{
|
||||
aSymbol->SetRef( &aPastePath, reference );
|
||||
aSymbol->SetValue( &aPastePath, value );
|
||||
aSymbol->SetFootprint( &aPastePath, footprint );
|
||||
}
|
||||
else
|
||||
{
|
||||
aSymbol->ClearAnnotation( &aPastePath );
|
||||
}
|
||||
|
||||
// We might clear annotations but always leave the original unit number from the paste
|
||||
// We might clear annotations but always leave the original unit number, value and footprint
|
||||
// from the paste
|
||||
aSymbol->SetUnitSelection( &aPastePath, unit );
|
||||
aSymbol->SetUnit( unit );
|
||||
aSymbol->SetValue( &aPastePath, value );
|
||||
aSymbol->SetFootprint( &aPastePath, footprint );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -164,7 +164,8 @@ private:
|
||||
|
||||
|
||||
SCH_LINE_WIRE_BUS_TOOL::SCH_LINE_WIRE_BUS_TOOL() :
|
||||
EE_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.InteractiveDrawingLineWireBus" )
|
||||
EE_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.InteractiveDrawingLineWireBus" ),
|
||||
m_inDrawingTool( false )
|
||||
{
|
||||
m_busUnfold = {};
|
||||
m_wires.reserve( 16 );
|
||||
@@ -278,6 +279,11 @@ bool SCH_LINE_WIRE_BUS_TOOL::IsDrawingLineWireOrBus( const SELECTION& aSelection
|
||||
|
||||
int SCH_LINE_WIRE_BUS_TOOL::DrawSegments( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
if( m_inDrawingTool )
|
||||
return 0;
|
||||
|
||||
REENTRANCY_GUARD guard( &m_inDrawingTool );
|
||||
|
||||
DRAW_SEGMENT_EVENT_PARAMS* params = aEvent.Parameter<DRAW_SEGMENT_EVENT_PARAMS*>();
|
||||
|
||||
std::string tool = aEvent.GetCommandStr().get();
|
||||
@@ -300,6 +306,11 @@ int SCH_LINE_WIRE_BUS_TOOL::DrawSegments( const TOOL_EVENT& aEvent )
|
||||
|
||||
int SCH_LINE_WIRE_BUS_TOOL::UnfoldBus( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
if( m_inDrawingTool )
|
||||
return 0;
|
||||
|
||||
REENTRANCY_GUARD guard( &m_inDrawingTool );
|
||||
|
||||
wxString* netPtr = aEvent.Parameter<wxString*>();
|
||||
wxString net;
|
||||
SCH_LINE* segment = nullptr;
|
||||
@@ -472,6 +483,7 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const std::string& aTool, int aType,
|
||||
SCH_LINE* segment = nullptr;
|
||||
EE_GRID_HELPER grid( m_toolMgr );
|
||||
KIGFX::VIEW_CONTROLS* controls = getViewControls();
|
||||
bool forceHV = m_frame->eeconfig()->m_Drawing.hv_lines_only;
|
||||
|
||||
auto setCursor =
|
||||
[&]()
|
||||
@@ -554,13 +566,44 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const std::string& aTool, int aType,
|
||||
cursorPos = (wxPoint) grid.BestSnapAnchor( cursorPos, LAYER_CONNECTABLE, segment );
|
||||
controls->ForceCursorPosition( true, cursorPos );
|
||||
|
||||
bool forceHV = m_frame->eeconfig()->m_Drawing.hv_lines_only;
|
||||
// Need to handle change in H/V mode while drawing
|
||||
if( forceHV != m_frame->eeconfig()->m_Drawing.hv_lines_only )
|
||||
{
|
||||
forceHV = m_frame->eeconfig()->m_Drawing.hv_lines_only;
|
||||
|
||||
// Need to delete extra segment if we have one
|
||||
if( !forceHV && m_wires.size() >= 2 && segment != nullptr )
|
||||
{
|
||||
m_wires.pop_back();
|
||||
m_selectionTool->RemoveItemFromSel( segment );
|
||||
delete segment;
|
||||
|
||||
segment = m_wires.back();
|
||||
segment->SetEndPoint( cursorPos );
|
||||
}
|
||||
// Add a segment so we can move orthogonally
|
||||
else if( forceHV && segment )
|
||||
{
|
||||
segment->SetEndPoint( cursorPos );
|
||||
|
||||
// Create a new segment, and chain it after the current segment.
|
||||
segment = static_cast<SCH_LINE*>( segment->Duplicate() );
|
||||
segment->SetFlags( IS_NEW | IS_MOVING );
|
||||
segment->SetStartPoint( cursorPos );
|
||||
m_wires.push_back( segment );
|
||||
|
||||
m_selectionTool->AddItemToSel( segment, true /*quiet mode*/ );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Handle cancel:
|
||||
//
|
||||
if( evt->IsCancelInteractive() )
|
||||
{
|
||||
m_frame->GetInfoBar()->Dismiss();
|
||||
|
||||
if( segment || m_busUnfold.in_progress )
|
||||
{
|
||||
cleanup();
|
||||
@@ -757,6 +800,9 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const std::string& aTool, int aType,
|
||||
segment = doUnfoldBus( net, contextMenuPos );
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------
|
||||
// Handle TOOL_ACTION special cases
|
||||
//
|
||||
else if( evt->IsAction( &EE_ACTIONS::rotateCW ) || evt->IsAction( &EE_ACTIONS::rotateCCW ) )
|
||||
{
|
||||
if( m_busUnfold.in_progress )
|
||||
@@ -973,6 +1019,50 @@ void SCH_LINE_WIRE_BUS_TOOL::finishSegments()
|
||||
}
|
||||
|
||||
|
||||
int SCH_LINE_WIRE_BUS_TOOL::TrimOverLappingWires( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
EE_SELECTION* aSelection = aEvent.Parameter<EE_SELECTION*>();
|
||||
SCHEMATIC* sch = getModel<SCHEMATIC>();
|
||||
SCH_SCREEN* screen = sch->CurrentSheet().LastScreen();
|
||||
|
||||
std::set<SCH_LINE*> lines;
|
||||
EDA_RECT bb = aSelection->GetBoundingBox();
|
||||
|
||||
for( EDA_ITEM* item : screen->Items().Overlapping( SCH_LINE_T, bb ) )
|
||||
lines.insert( static_cast<SCH_LINE*>( item ) );
|
||||
|
||||
for( unsigned ii = 0; ii < aSelection->GetSize(); ii++ )
|
||||
{
|
||||
SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aSelection->GetItem( ii ) );
|
||||
std::vector<wxPoint> pts = item->GetConnectionPoints();
|
||||
|
||||
if( !item || !item->IsConnectable() || ( item->Type() == SCH_LINE_T ) )
|
||||
continue;
|
||||
|
||||
/// If the line intersects with an item in the selection at only two points,
|
||||
/// then we can remove the line between the two points.
|
||||
for( SCH_LINE* line : lines )
|
||||
{
|
||||
std::vector<wxPoint> conn_pts;
|
||||
|
||||
for( wxPoint pt : pts )
|
||||
{
|
||||
if( IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), pt ) )
|
||||
conn_pts.push_back( pt );
|
||||
|
||||
if( conn_pts.size() > 2 )
|
||||
break;
|
||||
}
|
||||
|
||||
if( conn_pts.size() == 2 )
|
||||
m_frame->TrimWire( conn_pts[0], conn_pts[1] );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int SCH_LINE_WIRE_BUS_TOOL::AddJunctionsIfNeeded( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
EE_SELECTION* aSelection = aEvent.Parameter<EE_SELECTION*>();
|
||||
@@ -980,6 +1070,12 @@ int SCH_LINE_WIRE_BUS_TOOL::AddJunctionsIfNeeded( const TOOL_EVENT& aEvent )
|
||||
std::vector<wxPoint> pts;
|
||||
std::vector<wxPoint> connections = m_frame->GetSchematicConnections();
|
||||
|
||||
std::set<SCH_LINE*> lines;
|
||||
EDA_RECT bb = aSelection->GetBoundingBox();
|
||||
|
||||
for( EDA_ITEM* item : m_frame->GetScreen()->Items().Overlapping( SCH_LINE_T, bb ) )
|
||||
lines.insert( static_cast<SCH_LINE*>( item ) );
|
||||
|
||||
for( unsigned ii = 0; ii < aSelection->GetSize(); ii++ )
|
||||
{
|
||||
SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aSelection->GetItem( ii ) );
|
||||
@@ -1002,15 +1098,6 @@ int SCH_LINE_WIRE_BUS_TOOL::AddJunctionsIfNeeded( const TOOL_EVENT& aEvent )
|
||||
pts.push_back( pt );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clean up any wires that short non-wire connections in the list
|
||||
for( auto pt = new_pts.begin(); pt != new_pts.end(); pt++ )
|
||||
{
|
||||
for( auto secondPt = pt + 1; secondPt != new_pts.end(); secondPt++ )
|
||||
m_frame->TrimWire( *pt, *secondPt );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We always have some overlapping connection points. Drop duplicates here
|
||||
@@ -1035,6 +1122,7 @@ int SCH_LINE_WIRE_BUS_TOOL::AddJunctionsIfNeeded( const TOOL_EVENT& aEvent )
|
||||
void SCH_LINE_WIRE_BUS_TOOL::setTransitions()
|
||||
{
|
||||
Go( &SCH_LINE_WIRE_BUS_TOOL::AddJunctionsIfNeeded, EE_ACTIONS::addNeededJunctions.MakeEvent() );
|
||||
Go( &SCH_LINE_WIRE_BUS_TOOL::TrimOverLappingWires, EE_ACTIONS::trimOverlappingWires.MakeEvent() );
|
||||
Go( &SCH_LINE_WIRE_BUS_TOOL::DrawSegments, EE_ACTIONS::drawWire.MakeEvent() );
|
||||
Go( &SCH_LINE_WIRE_BUS_TOOL::DrawSegments, EE_ACTIONS::drawBus.MakeEvent() );
|
||||
Go( &SCH_LINE_WIRE_BUS_TOOL::DrawSegments, EE_ACTIONS::drawLines.MakeEvent() );
|
||||
|
||||
@@ -93,6 +93,11 @@ public:
|
||||
*/
|
||||
int AddJunctionsIfNeeded( const TOOL_EVENT& aEvent );
|
||||
|
||||
/**
|
||||
* Logic to remove wires when overlapping correct items
|
||||
*/
|
||||
int TrimOverLappingWires( const TOOL_EVENT& aEvent );
|
||||
|
||||
private:
|
||||
int doDrawSegments( const std::string& aTool, int aType, bool aQuitOnDraw );
|
||||
SCH_LINE* startSegments( int aType, const VECTOR2D& aPos );
|
||||
@@ -128,11 +133,10 @@ private:
|
||||
void computeBreakPoint( const std::pair<SCH_LINE*, SCH_LINE*>& aSegments, wxPoint& aPosition );
|
||||
|
||||
private:
|
||||
/// Data related to bus unfolding tool.
|
||||
BUS_UNFOLDING_T m_busUnfold;
|
||||
bool m_inDrawingTool; // Reentrancy guard
|
||||
|
||||
/// Storage for the line segments while drawing
|
||||
std::vector<SCH_LINE*> m_wires;
|
||||
BUS_UNFOLDING_T m_busUnfold;
|
||||
std::vector<SCH_LINE*> m_wires; // Lines being drawn
|
||||
};
|
||||
|
||||
#endif /* SCH_LINE_WIRE_BUS_TOOL_H */
|
||||
|
||||
@@ -88,6 +88,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
KIGFX::VIEW_CONTROLS* controls = getViewControls();
|
||||
EE_GRID_HELPER grid( m_toolMgr );
|
||||
bool wasDragging = m_moveInProgress && m_isDrag;
|
||||
SCH_MOVE_TOOL_PARAMS* params = aEvent.Parameter<SCH_MOVE_TOOL_PARAMS*>();
|
||||
|
||||
m_anchorPos.reset();
|
||||
|
||||
@@ -174,8 +175,11 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
if( !m_moveInProgress ) // Prepare to start moving/dragging
|
||||
{
|
||||
SCH_ITEM* sch_item = (SCH_ITEM*) selection.Front();
|
||||
bool appendUndo = sch_item && sch_item->IsNew();
|
||||
bool placingNewItems = sch_item && sch_item->IsNew();
|
||||
bool appendUndo =
|
||||
params ? params->appendToLastUndo : ( sch_item && sch_item->IsNew() );
|
||||
bool placingNewItems =
|
||||
params ? params->placingNewItems : ( sch_item && sch_item->IsNew() );
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Setup a drag or a move
|
||||
@@ -380,6 +384,9 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
//
|
||||
else if( evt->IsCancelInteractive() || evt->IsActivate() )
|
||||
{
|
||||
if( evt->IsCancelInteractive() )
|
||||
m_frame->GetInfoBar()->Dismiss();
|
||||
|
||||
if( m_moveInProgress )
|
||||
{
|
||||
if( evt->IsActivate() )
|
||||
@@ -446,6 +453,11 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( evt->IsAction( &EE_ACTIONS::highlightNet )
|
||||
|| evt->IsAction( &EE_ACTIONS::explicitCrossProbe ) )
|
||||
{
|
||||
// These don't make any sense during a move. Eat them.
|
||||
}
|
||||
//------------------------------------------------------------------------
|
||||
// Handle context menu
|
||||
//
|
||||
@@ -505,6 +517,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
m_frame->AddJunction( m_frame->GetScreen(), it.GetPosition(), true, false );
|
||||
}
|
||||
|
||||
m_toolMgr->RunAction( EE_ACTIONS::trimOverlappingWires, true, &selectionCopy );
|
||||
m_toolMgr->RunAction( EE_ACTIONS::addNeededJunctions, true, &selectionCopy );
|
||||
|
||||
m_frame->RecalculateConnections( LOCAL_CLEANUP );
|
||||
@@ -917,6 +930,7 @@ int SCH_MOVE_TOOL::AlignElements( const TOOL_EVENT& aEvent )
|
||||
}
|
||||
|
||||
m_toolMgr->PostEvent( EVENTS::SelectedItemsMoved );
|
||||
m_toolMgr->RunAction( EE_ACTIONS::trimOverlappingWires, true, &selection );
|
||||
m_toolMgr->RunAction( EE_ACTIONS::addNeededJunctions, true, &selection );
|
||||
|
||||
m_frame->RecalculateConnections( LOCAL_CLEANUP );
|
||||
|
||||
@@ -40,6 +40,13 @@ struct SPECIAL_CASE_LABEL_INFO
|
||||
};
|
||||
|
||||
|
||||
struct SCH_MOVE_TOOL_PARAMS
|
||||
{
|
||||
bool appendToLastUndo;
|
||||
bool placingNewItems;
|
||||
};
|
||||
|
||||
|
||||
class SCH_MOVE_TOOL : public EE_TOOL_BASE<SCH_EDIT_FRAME>
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -160,7 +160,7 @@ int SYMBOL_EDITOR_CONTROL::AddSymbol( const TOOL_EVENT& aEvent )
|
||||
|
||||
if( libName.IsEmpty() )
|
||||
{
|
||||
msg.Printf( _( "No symbol library selected." ), libName );
|
||||
msg.Printf( _( "No symbol library selected." ) );
|
||||
m_frame->ShowInfoBarError( msg );
|
||||
return 0;
|
||||
}
|
||||
@@ -255,10 +255,17 @@ int SYMBOL_EDITOR_CONTROL::DuplicateSymbol( const TOOL_EVENT& aEvent )
|
||||
if( m_frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) )
|
||||
{
|
||||
SYMBOL_EDIT_FRAME* editFrame = static_cast<SYMBOL_EDIT_FRAME*>( m_frame );
|
||||
LIB_ID sel = editFrame->GetTargetLibId();
|
||||
wxString msg;
|
||||
|
||||
if( !sel.IsValid() )
|
||||
{
|
||||
msg.Printf( _( "No symbol selected" ) );
|
||||
m_frame->ShowInfoBarError( msg );
|
||||
return 0;
|
||||
}
|
||||
|
||||
LIB_ID sel = editFrame->GetTreeLIBID();
|
||||
const wxString& libName = sel.GetLibNickname();
|
||||
wxString msg;
|
||||
|
||||
if( editFrame->GetLibManager().IsLibraryReadOnly( libName ) )
|
||||
{
|
||||
|
||||
@@ -118,6 +118,8 @@ int SYMBOL_EDITOR_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
|
||||
|
||||
if( evt->IsCancelInteractive() )
|
||||
{
|
||||
m_frame->GetInfoBar()->Dismiss();
|
||||
|
||||
if( item )
|
||||
{
|
||||
cleanup();
|
||||
|
||||
@@ -445,7 +445,7 @@ int SYMBOL_EDITOR_EDIT_TOOL::Properties( const TOOL_EVENT& aEvent )
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( wxT( "Unhandled item <wxT( " ) + item->GetClass() + wxT( " )>" ) );
|
||||
wxFAIL_MSG( wxT( "Unhandled item <" ) + item->GetClass() + wxT( ">" ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ int SYMBOL_EDITOR_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
if( !selection.Front()->IsNew() )
|
||||
saveCopyInUndoList( m_frame->GetCurSymbol(), UNDO_REDO::LIBEDIT );
|
||||
|
||||
m_cursor = controls->GetCursorPosition();
|
||||
m_cursor = controls->GetCursorPosition( !aEvent.DisableGridSnapping() );
|
||||
|
||||
// Main loop: keep receiving events
|
||||
do
|
||||
@@ -188,7 +188,7 @@ int SYMBOL_EDITOR_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
|
||||
// Set up the starting position and move/drag offset
|
||||
//
|
||||
m_cursor = controls->GetCursorPosition();
|
||||
m_cursor = controls->GetCursorPosition( !evt->DisableGridSnapping() );
|
||||
|
||||
if( lib_item->IsNew() )
|
||||
{
|
||||
@@ -214,7 +214,7 @@ int SYMBOL_EDITOR_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cursor = getViewControls()->GetCursorPosition( true );
|
||||
m_cursor = controls->GetCursorPosition( !evt->DisableGridSnapping() );
|
||||
m_anchorPos = m_cursor;
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@ int SYMBOL_EDITOR_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
//------------------------------------------------------------------------
|
||||
// Follow the mouse
|
||||
//
|
||||
m_cursor = controls->GetCursorPosition();
|
||||
m_cursor = controls->GetCursorPosition( !evt->DisableGridSnapping() );
|
||||
VECTOR2I delta( m_cursor - prevPos );
|
||||
m_anchorPos = m_cursor;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2011-2014 Jean-Pierre Charras jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-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
|
||||
@@ -76,6 +76,7 @@ BEGIN_EVENT_TABLE( GERBVIEW_FRAME, EDA_DRAW_FRAME )
|
||||
GERBVIEW_FRAME::OnSelectHighlightChoice )
|
||||
EVT_CHOICE( ID_ON_ZOOM_SELECT, GERBVIEW_FRAME::OnSelectZoom )
|
||||
EVT_CHOICE( ID_ON_GRID_SELECT, GERBVIEW_FRAME::OnSelectGrid )
|
||||
EVT_MENU( ID_GRID_SETTINGS, GERBVIEW_FRAME::OnGridSettings )
|
||||
|
||||
EVT_UPDATE_UI( ID_ON_GRID_SELECT, GERBVIEW_FRAME::OnUpdateSelectGrid )
|
||||
EVT_UPDATE_UI( ID_TOOLBARH_GERBER_SELECT_ACTIVE_DCODE, GERBVIEW_FRAME::OnUpdateSelectDCode )
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-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
|
||||
@@ -38,6 +38,7 @@ GERBVIEW_PRINTOUT::GERBVIEW_PRINTOUT( GBR_LAYOUT* aLayout, const BOARD_PRINTOUT_
|
||||
BOARD_PRINTOUT( aParams, aView, aTitle )
|
||||
{
|
||||
m_layout = aLayout;
|
||||
m_gerbviewPrint = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2009 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
|
||||
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2009 Jean-Pierre Charras, jean-pierre.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2018 CERN
|
||||
* Author: Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
@@ -119,6 +119,9 @@ protected:
|
||||
|
||||
///< Printout parameters
|
||||
BOARD_PRINTOUT_SETTINGS m_settings;
|
||||
|
||||
/// True if the caller is Gerbview, false for Pcbnew
|
||||
bool m_gerbviewPrint;
|
||||
};
|
||||
|
||||
#endif // BOARD_PRINTOUT_H
|
||||
|
||||
+25
-6
@@ -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-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-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
|
||||
@@ -59,6 +59,15 @@ enum class FILL_T : int
|
||||
};
|
||||
|
||||
|
||||
// Holding struct to keep originating midpoint
|
||||
struct ARC_MID
|
||||
{
|
||||
wxPoint mid;
|
||||
wxPoint start;
|
||||
wxPoint end;
|
||||
wxPoint center;
|
||||
};
|
||||
|
||||
class EDA_SHAPE
|
||||
{
|
||||
public:
|
||||
@@ -187,6 +196,17 @@ public:
|
||||
*/
|
||||
void SetArcGeometry( const wxPoint& aStart, const wxPoint& aMid, const wxPoint& aEnd );
|
||||
|
||||
/**
|
||||
* Set the data used for mid point caching. If the controlling points remain constant, then
|
||||
* we keep the midpoint the same as it was when read in. This minimizes VCS churn
|
||||
*
|
||||
* @param aStart Cached start point
|
||||
* @param aMid Cached mid point
|
||||
* @param aEnd Cached end point
|
||||
* @param aCenter Calculated center point using the preceeding three
|
||||
*/
|
||||
void SetCachedArcData( const wxPoint& aStart, const wxPoint& aMid, const wxPoint& aEnd, const wxPoint& aCenter );
|
||||
|
||||
const std::vector<wxPoint>& GetBezierPoints() const { return m_bezierPoints; }
|
||||
|
||||
/**
|
||||
@@ -214,11 +234,11 @@ public:
|
||||
|
||||
void SetPolyShape( const SHAPE_POLY_SET& aShape ) { m_poly = aShape; }
|
||||
|
||||
void SetBezierPoints( const std::vector<wxPoint>& aPoints ) { m_bezierPoints = aPoints; }
|
||||
void SetPolyPoints( const std::vector<wxPoint>& aPoints );
|
||||
|
||||
/**
|
||||
* Rebuild the m_BezierPoints vertex list that approximate the Bezier curve
|
||||
* by a list of segments.
|
||||
* Rebuild the m_bezierPoints vertex list that approximate the Bezier curve by a list of
|
||||
* segments.
|
||||
*
|
||||
* Has meaning only for BEZIER shape.
|
||||
*
|
||||
@@ -228,8 +248,6 @@ public:
|
||||
*/
|
||||
void RebuildBezierToSegmentsPointsList( int aMinSegLen );
|
||||
|
||||
void SetPolyPoints( const std::vector<wxPoint>& aPoints );
|
||||
|
||||
/**
|
||||
* Make a set of SHAPE objects representing the EDA_SHAPE. Caller owns the objects.
|
||||
*/
|
||||
@@ -305,6 +323,7 @@ protected:
|
||||
wxPoint m_end; // Line end point or Circle 3 o'clock point
|
||||
|
||||
wxPoint m_arcCenter; // Used only for Arcs: arc end point
|
||||
ARC_MID m_arcMidData; // Used to store originating data
|
||||
|
||||
wxPoint m_bezierC1; // Bezier Control Point 1
|
||||
wxPoint m_bezierC2; // Bezier Control Point 2
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user