Compare commits
422 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8ad2755ae3 | |||
| c90d9b7ebe | |||
| 613f13c576 | |||
| 4d8269c5fd | |||
| 99ac73630a | |||
| bec70ff39d | |||
| cd5827a694 | |||
| a32e7a44e3 | |||
| 8c3c82153d | |||
| 28e433cc54 | |||
| 3fd353d837 | |||
| f238e09990 | |||
| b0b523bfdb | |||
| e5ef33d227 | |||
| f67945aae9 | |||
| f74e4fa73e | |||
| efaa3b5ca8 | |||
| 0ad919d043 | |||
| dc2b87aa75 | |||
| b65d3c80a3 | |||
| 12e03b0fcf | |||
| e964ccb6b5 | |||
| 994cabf4c0 | |||
| 5f9f31605f | |||
| db2b94e1c6 | |||
| a37ffabd27 | |||
| de8b22ac10 | |||
| 30f6135ad6 | |||
| 9e50e37fdd | |||
| 50d8178482 | |||
| e4cf45edce | |||
| b6b85fa652 | |||
| dad2e485da | |||
| 63999f25fa | |||
| f23f43961f | |||
| 16594a65a2 | |||
| de32417df1 | |||
| bb779c87f3 | |||
| 3dedd899f7 | |||
| 5eb265080f | |||
| 3329affc12 | |||
| fce66a0372 | |||
| 780df7262b | |||
| 8a3a11e2f8 | |||
| 5878ac5aaf | |||
| 22cebd8e71 | |||
| 0f2f953476 | |||
| 205db57971 | |||
| d607249e81 | |||
| 5b9b49cf2b | |||
| 045b00bac7 | |||
| c297a4e2b3 | |||
| 4c9273206a | |||
| 8530b71833 | |||
| 67cca8db25 | |||
| 84cc67c9df | |||
| 044a7ca39e | |||
| 1d09917e3e | |||
| b5658962be | |||
| 0a1d209255 | |||
| dbf0150cec | |||
| 8871b0385d | |||
| 9f20816b24 | |||
| f3566a987d | |||
| a6210da126 | |||
| ebad7dfc0d | |||
| ab82dc5839 | |||
| cfc1f14282 | |||
| 479b3e6c72 | |||
| 27c573ca42 | |||
| e28381841a | |||
| 37ac2ee0a3 | |||
| 42397a6ce1 | |||
| e29131f265 | |||
| b4d03e2eeb | |||
| 5bd565211b | |||
| dd654ddd9a | |||
| 303a90eb65 | |||
| 7be9021ba3 | |||
| 843d01f27b | |||
| bdc1cbda27 | |||
| 51e094eb34 | |||
| ccec31da71 | |||
| fe3bbee807 | |||
| 12cb6fc043 | |||
| 1c3efdf212 | |||
| 5d4f66a613 | |||
| 711184ef62 | |||
| 9b4809e10f | |||
| 9109c4cd27 | |||
| 20c68f9c8d | |||
| 9950d046cb | |||
| ff44242682 | |||
| f671f4db51 | |||
| 406e7acaac | |||
| a3eca13ad3 | |||
| 73053a2177 | |||
| 5992d7331a | |||
| 9767a083cc | |||
| 07c9aee1ea | |||
| fc0911f55e | |||
| b74fef1b10 | |||
| 127874a7b9 | |||
| ecce28a472 | |||
| e93dacb788 | |||
| 6c4734c370 | |||
| 93a63a61ec | |||
| 57b9c1bdaf | |||
| b166e866e0 | |||
| 9fa2549d7a | |||
| f9cb5a26a3 | |||
| cbd40cb5e4 | |||
| 352672f8bf | |||
| 6dc5c2b24a | |||
| fa63bd24f4 | |||
| 10750bc460 | |||
| afb4b1411d | |||
| 74d7711e37 | |||
| 585693f0b3 | |||
| 186f5e65a7 | |||
| 1fd1cde3bf | |||
| dcadff46b7 | |||
| 62bb553460 | |||
| 0f32217cf0 | |||
| 0ec479c17f | |||
| 4ede3b3f2b | |||
| 22feba7bbf | |||
| b6eef921a4 | |||
| 567d0dca95 | |||
| 7a869fc503 | |||
| 8b6274af16 | |||
| 581715f7aa | |||
| 1c7a64b0ea | |||
| 8fb25f5577 | |||
| 88ae436249 | |||
| bf6bcba7bb | |||
| 10205bb432 | |||
| aa1fc43048 | |||
| 9c12ba60aa | |||
| 3c21938295 | |||
| 8d9e254e0c | |||
| e52dafcaaf | |||
| 676b7d1739 | |||
| 490d3152ab | |||
| 1b68a4f98e | |||
| 58fac19a5c | |||
| 65850682a8 | |||
| 6c4df9aca9 | |||
| b110861ba1 | |||
| 13fcb571f7 | |||
| 9738a71922 | |||
| f45e3ca339 | |||
| c579e11db4 | |||
| 819f75e17c | |||
| 0828ee3b10 | |||
| 35094a786d | |||
| add2215e5a | |||
| efa99b1e71 | |||
| 1ebc66b9e2 | |||
| c852055ae1 | |||
| 8fb2cecd64 | |||
| 5d2952cd24 | |||
| 4a1fe267ca | |||
| 694b37b852 | |||
| 253f7deb62 | |||
| 3e62bbf561 | |||
| 0f9c75749d | |||
| 9c7f1d261f | |||
| 44a4800383 | |||
| 2e6f01b871 | |||
| 41bb627ef2 | |||
| b2fa06b5f5 | |||
| 69e9aa917a | |||
| 507bebda80 | |||
| e4a66c8a11 | |||
| ecdee78368 | |||
| 763ee75856 | |||
| 07fb0804ac | |||
| ced1c742c8 | |||
| 029b0e709a | |||
| 43ffccc67f | |||
| 23e9b733ee | |||
| f4ffa8123b | |||
| fd9e976346 | |||
| 85db61b8d3 | |||
| a2e1ac3972 | |||
| 0c3f2fd4b4 | |||
| b71f32e1b4 | |||
| f478643411 | |||
| 39cf1fea22 | |||
| f967d6ab43 | |||
| 448da01cea | |||
| a25888b4ba | |||
| 7f3508b8b3 | |||
| 1d880cdcf6 | |||
| c855702918 | |||
| 51023a1ae4 | |||
| 35364bd8ad | |||
| 0f715223e9 | |||
| 9ceace2a47 | |||
| 6e93c08ff2 | |||
| 3744cfd987 | |||
| 245abd5f16 | |||
| f559b49f44 | |||
| 8e9f50f465 | |||
| ae39cfb1be | |||
| 259c34d12b | |||
| fbeeadfd0f | |||
| 9ed89a324b | |||
| 49c17a0ce5 | |||
| a11211ecd1 | |||
| 8d2c04b287 | |||
| 7834fc9214 | |||
| 6bebfdc65d | |||
| c35f4a0988 | |||
| 86660d055c | |||
| 59dae982d4 | |||
| 8a3bf672e7 | |||
| cc05e9d8fb | |||
| ada4f107e7 | |||
| 3db58c533b | |||
| 480e4290a0 | |||
| 89c96d50ef | |||
| dfc3a7bf5c | |||
| 10f0fa65f3 | |||
| d23a449d57 | |||
| 753c7ae666 | |||
| ac7fa777a6 | |||
| 2b63d9f175 | |||
| 744a3463b2 | |||
| f70fdad9ae | |||
| 42df6cbca2 | |||
| c2e39cbc5d | |||
| ed0046fcd0 | |||
| 5e2f979f36 | |||
| 0b1065ff55 | |||
| 7db48b81b6 | |||
| f0ce3167c0 | |||
| ace6439758 | |||
| e38b948f0b | |||
| 2f74d1466e | |||
| 85c324b5d7 | |||
| edddf8a660 | |||
| 193e7f894d | |||
| 32cc486d89 | |||
| 0aec789659 | |||
| f92cedab9a | |||
| f84f93b167 | |||
| d33fbd8e47 | |||
| 3ab23201b4 | |||
| 39236ae68f | |||
| 5ee89b41ac | |||
| ec0ff4ffc2 | |||
| 1b6b2d7896 | |||
| 036241c819 | |||
| 2dc81999ef | |||
| 3f8a5874e6 | |||
| 838674c4a7 | |||
| 98a8781d70 | |||
| 85f4ab3944 | |||
| 25db3032ee | |||
| d638f4cad0 | |||
| 32fe612045 | |||
| 76d463dcc8 | |||
| 2daa432261 | |||
| d7b2c81db5 | |||
| b597a4559f | |||
| 18e3227c9a | |||
| 41b847b3c9 | |||
| ae2aea8fc0 | |||
| 567c5bc8db | |||
| 1fdf7d0cf4 | |||
| 5ffe28eec2 | |||
| 4e855b4cb0 | |||
| ae886c824c | |||
| 46b5442214 | |||
| c3deafd271 | |||
| de2da52941 | |||
| 8aa3d183ef | |||
| 6623b19b70 | |||
| 7a40b6e484 | |||
| d63dc32e71 | |||
| 54aa3bc5d4 | |||
| 6ebd616049 | |||
| c0439feef8 | |||
| 0e550322db | |||
| 7398d47728 | |||
| 9f0f7e8641 | |||
| f26e36440d | |||
| 8ff0aca6b4 | |||
| d4b564ee7a | |||
| 22a6bf999f | |||
| 09bae9bb14 | |||
| 874f7fbdff | |||
| 6d17d7d7a1 | |||
| 98dc21360a | |||
| 0d330051ed | |||
| f17c4cceac | |||
| a3072ffade | |||
| f60c544478 | |||
| fc320e0ab4 | |||
| 91c861e8d6 | |||
| 2640f4ad41 | |||
| 06f5828990 | |||
| 85604e1707 | |||
| ad7bc215d0 | |||
| f005676c90 | |||
| 17961165cf | |||
| 6ba2230804 | |||
| cacfaac52e | |||
| 4f09e18894 | |||
| 05f1912d19 | |||
| e15306464f | |||
| 28f75d5ad3 | |||
| 3021764401 | |||
| 2766e90fe0 | |||
| 10d5baa862 | |||
| 28a8997603 | |||
| 83d4771e6b | |||
| 0f4cd449b9 | |||
| 27843728d7 | |||
| 676ad491fe | |||
| 9a91537968 | |||
| 3eba0d9bab | |||
| b4995aa711 | |||
| 55353536e5 | |||
| e3d45fb37b | |||
| e3369608fd | |||
| 1c6390f829 | |||
| df64a6c583 | |||
| 59c638c64c | |||
| 9850541433 | |||
| 5140fd7819 | |||
| 5ae1b271e7 | |||
| c5cdff6213 | |||
| e05b3955a5 | |||
| e1c0bddff3 | |||
| 62297e63a2 | |||
| 54c325a631 | |||
| af99c9da34 | |||
| dbf5455656 | |||
| 4cb9edd9f0 | |||
| 60d23b14e7 | |||
| 12fdeac31c | |||
| 69a1a4611b | |||
| a46501b279 | |||
| bc1953dded | |||
| 789a695737 | |||
| 5f8a0b0728 | |||
| 9fdda223f5 | |||
| 1ff4b2b4eb | |||
| 0751a3ae7f | |||
| e6e08c111b | |||
| 004b96ec21 | |||
| 7cb98f6856 | |||
| fc86de34f8 | |||
| fe69da4cb8 | |||
| 27434e38f9 | |||
| 60ddafa4ff | |||
| ef8b6bf9e1 | |||
| 59cc7b2d3e | |||
| 6245bbff50 | |||
| 6331a0ab7a | |||
| c43ae314e0 | |||
| 250720ca4a | |||
| a5ac1fc34f | |||
| 1740aeca5e | |||
| 4f060d9384 | |||
| acd244f873 | |||
| dfef20658c | |||
| 8255e091f0 | |||
| 96037591c5 | |||
| 692949fd0a | |||
| 4bf75de6fd | |||
| 05890480e2 | |||
| 70d7bc2099 | |||
| e2d8d53a10 | |||
| 402c139957 | |||
| 31e79ef54f | |||
| 39788e7e6c | |||
| 932c908075 | |||
| 443da9943a | |||
| cc1071fe7a | |||
| 3ac4fd59c5 | |||
| 5e93814283 | |||
| d29c07a663 | |||
| a558a67fbd | |||
| 153e1190ea | |||
| a80a641427 | |||
| acd7d5ad2f | |||
| 81ba4fa9a6 | |||
| 57f007c46e | |||
| d513640572 | |||
| 8c695e5044 | |||
| 395a966802 | |||
| 643894c882 | |||
| c7c28c0471 | |||
| 20ada81d43 | |||
| 07736e59bd | |||
| 3195ba646f | |||
| 2deee01592 | |||
| 890b09499e | |||
| 01c5fab84b | |||
| e9b7737692 | |||
| fe1072a06b | |||
| 59f308850e | |||
| e775a7581a | |||
| ec99e10b31 | |||
| 240d7921ba | |||
| 9ac006b114 | |||
| c3fef1cae2 | |||
| ca1c99a0d1 | |||
| 06ae7a20df | |||
| f536ecdc00 | |||
| a4bdd38367 | |||
| 6fb6d3e444 | |||
| a3952c37bf | |||
| c24ee72fe3 | |||
| f988b807c4 | |||
| cb1a596b10 | |||
| c41cd75b62 | |||
| 0df48f3002 |
@@ -49,6 +49,7 @@
|
||||
#include <dialogs/dialog_color_picker.h>
|
||||
|
||||
class COLOR_SETTINGS;
|
||||
class PCB_TEXTBOX;
|
||||
|
||||
/// A type that stores a container of 2d objects for each layer id
|
||||
typedef std::map<PCB_LAYER_ID, BVH_CONTAINER_2D*> MAP_CONTAINER_2D_BASE;
|
||||
@@ -356,6 +357,9 @@ private:
|
||||
void addShape( const PCB_DIMENSION_BASE* aDimension, CONTAINER_2D_BASE* aDstContainer,
|
||||
const BOARD_ITEM* aOwner );
|
||||
|
||||
void addShape( const PCB_TEXTBOX* aTextBox, CONTAINER_2D_BASE* aContainer,
|
||||
const BOARD_ITEM* aOwner );
|
||||
|
||||
void addSolidAreasShapes( const ZONE* aZone, CONTAINER_2D_BASE* aDstContainer,
|
||||
PCB_LAYER_ID aLayerId );
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <pcb_painter.h> // for PCB_RENDER_SETTINGS
|
||||
#include <zone.h>
|
||||
#include <fp_text.h>
|
||||
#include <pcb_textbox.h>
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
#include <trigo.h>
|
||||
#include <geometry/shape_segment.h>
|
||||
@@ -720,6 +721,11 @@ void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aConta
|
||||
aShape->TransformShapeToPolygon( polyList, UNDEFINED_LAYER, 0, ARC_HIGH_DEF,
|
||||
ERROR_INSIDE );
|
||||
|
||||
// Some polygons can be a bit complex (especially when coming from a
|
||||
// picture ot a text converted to a polygon
|
||||
// So call Simplify before calling ConvertPolygonToTriangles, just in case.
|
||||
polyList.Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
if( polyList.IsEmpty() ) // Just for caution
|
||||
break;
|
||||
|
||||
@@ -767,6 +773,32 @@ void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aConta
|
||||
}
|
||||
|
||||
|
||||
void BOARD_ADAPTER::addShape( const PCB_TEXTBOX* aTextBox, CONTAINER_2D_BASE* aContainer,
|
||||
const BOARD_ITEM* aOwner )
|
||||
{
|
||||
addText( aTextBox, aContainer, aOwner );
|
||||
|
||||
if( !aTextBox->IsBorderEnabled() )
|
||||
return;
|
||||
|
||||
// We cannot use PCB_TEXTBOX::TransformShapeToPolygon because it convert the textbox
|
||||
// as filled polygon even if there's no background colour.
|
||||
// So for polygon, we use PCB_SHAPE::TransformShapeToPolygon
|
||||
|
||||
if( aTextBox->GetShape() == SHAPE_T::RECT )
|
||||
addShape( static_cast<const PCB_SHAPE*>( aTextBox ), aContainer, aOwner );
|
||||
else
|
||||
{
|
||||
SHAPE_POLY_SET polyList;
|
||||
|
||||
aTextBox->PCB_SHAPE::TransformShapeToPolygon( polyList, UNDEFINED_LAYER, 0,
|
||||
ARC_HIGH_DEF, ERROR_INSIDE );
|
||||
|
||||
ConvertPolygonToTriangles( polyList, *aContainer, m_biuTo3Dunits, *aOwner );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BOARD_ADAPTER::addSolidAreasShapes( const ZONE* aZone, CONTAINER_2D_BASE* aContainer,
|
||||
PCB_LAYER_ID aLayerId )
|
||||
{
|
||||
|
||||
@@ -604,9 +604,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||
break;
|
||||
|
||||
case PCB_TEXTBOX_T:
|
||||
addText( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
|
||||
if( static_cast<PCB_TEXTBOX*>( item )->IsBorderEnabled() )
|
||||
addShape( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
|
||||
addShape( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
|
||||
break;
|
||||
|
||||
case PCB_DIM_ALIGNED_T:
|
||||
@@ -924,7 +922,6 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||
break;
|
||||
|
||||
case PCB_TEXTBOX_T:
|
||||
addText( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
|
||||
addShape( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
|
||||
break;
|
||||
|
||||
|
||||
@@ -637,6 +637,9 @@ void EDA_3D_CANVAS::OnMagnify( wxMouseEvent& event )
|
||||
|
||||
void EDA_3D_CANVAS::OnMouseMove( wxMouseEvent& event )
|
||||
{
|
||||
if( m_3d_render && m_3d_render->IsReloadRequestPending() )
|
||||
return; // Prevents using invalid m_3d_render_raytracing data
|
||||
|
||||
if( m_camera_is_moving )
|
||||
return;
|
||||
|
||||
|
||||
@@ -208,12 +208,6 @@ public:
|
||||
m_3dmousePivotPos = aPos;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Called by a wxPaintEvent event
|
||||
*/
|
||||
void OnPaint( wxPaintEvent& aEvent );
|
||||
|
||||
/**
|
||||
* The actual function to repaint the canvas.
|
||||
*
|
||||
@@ -222,6 +216,10 @@ private:
|
||||
*/
|
||||
void DoRePaint();
|
||||
|
||||
private:
|
||||
// The wxPaintEvent event. mainly calls DoRePaint()
|
||||
void OnPaint( wxPaintEvent& aEvent );
|
||||
|
||||
void OnEraseBackground( wxEraseEvent& event );
|
||||
|
||||
void OnRefreshRequest( wxEvent& aEvent );
|
||||
|
||||
@@ -794,8 +794,13 @@ void EDA_3D_VIEWER_FRAME::takeScreenshot( wxCommandEvent& event )
|
||||
}
|
||||
|
||||
// Be sure we have the latest 3D view (remember 3D view is buffered)
|
||||
m_canvas->Request_refresh( true );
|
||||
wxYield();
|
||||
// Also ensure any highlighted item is not highlighted when creating screen shot
|
||||
EDA_3D_VIEWER_SETTINGS::RENDER_SETTINGS& cfg = m_boardAdapter.m_Cfg->m_Render;
|
||||
bool allow_highlight = cfg.opengl_highlight_on_rollover;
|
||||
cfg.opengl_highlight_on_rollover = false;
|
||||
|
||||
m_canvas->DoRePaint(); // init first buffer
|
||||
m_canvas->DoRePaint(); // init second buffer
|
||||
|
||||
// Build image from the 3D buffer
|
||||
wxWindowUpdateLocker noUpdates( this );
|
||||
@@ -805,6 +810,8 @@ void EDA_3D_VIEWER_FRAME::takeScreenshot( wxCommandEvent& event )
|
||||
if( m_canvas )
|
||||
m_canvas->GetScreenshot( screenshotImage );
|
||||
|
||||
cfg.opengl_highlight_on_rollover = allow_highlight;
|
||||
|
||||
if( event.GetId() == ID_TOOL_SCREENCOPY_TOCLIBBOARD )
|
||||
{
|
||||
wxBitmap bitmap( screenshotImage );
|
||||
|
||||
@@ -167,7 +167,11 @@ BM2CMP_FRAME::BM2CMP_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||
wxIcon icon;
|
||||
wxIconBundle icon_bundle;
|
||||
|
||||
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_bitmap2component ) );
|
||||
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_bitmap2component, 48 ) );
|
||||
icon_bundle.AddIcon( icon );
|
||||
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_bitmap2component, 128 ) );
|
||||
icon_bundle.AddIcon( icon );
|
||||
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_bitmap2component, 256 ) );
|
||||
icon_bundle.AddIcon( icon );
|
||||
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_bitmap2component_32 ) );
|
||||
icon_bundle.AddIcon( icon );
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
# KiCad.
|
||||
#
|
||||
# Note: This version string should follow the semantic versioning system
|
||||
set( KICAD_SEMANTIC_VERSION "7.0.8-unknown" )
|
||||
set( KICAD_SEMANTIC_VERSION "7.0.11-unknown" )
|
||||
|
||||
# Default the version to the semantic version.
|
||||
# This is overridden by the git repository tag though (if using git)
|
||||
|
||||
@@ -83,6 +83,8 @@
|
||||
/// Allows scripts install directory to be referenced by the program code.
|
||||
#define PYTHON_DEST "@PYTHON_DEST@"
|
||||
|
||||
#define PYTHON_SITE_PACKAGE_PATH "@PYTHON_SITE_PACKAGE_PATH@"
|
||||
|
||||
/// Allows scripts install directory to be referenced by the program code.
|
||||
#define KICAD_DATA "@KICAD_DATA@"
|
||||
|
||||
|
||||
@@ -1013,6 +1013,28 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
|
||||
aBitmapInfoCache[BITMAPS::icon_pagelayout_editor].emplace_back( BITMAPS::icon_pagelayout_editor, wxT( "icon_pagelayout_editor_dark_128.png" ), 128, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_bitmap2component].emplace_back( BITMAPS::icon_bitmap2component, wxT( "icon_bitmap2component_dark_128.png" ), 128, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_pcbcalculator].emplace_back( BITMAPS::icon_pcbcalculator, wxT( "icon_pcbcalculator_dark_128.png" ), 128, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_cvpcb].emplace_back( BITMAPS::icon_cvpcb, wxT( "icon_cvpcb_256.png" ), 256, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_eeschema].emplace_back( BITMAPS::icon_eeschema, wxT( "icon_eeschema_256.png" ), 256, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_gerbview].emplace_back( BITMAPS::icon_gerbview, wxT( "icon_gerbview_256.png" ), 256, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_kicad].emplace_back( BITMAPS::icon_kicad, wxT( "icon_kicad_256.png" ), 256, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_kicad_nightly].emplace_back( BITMAPS::icon_kicad_nightly, wxT( "icon_kicad_nightly_256.png" ), 256, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_libedit].emplace_back( BITMAPS::icon_libedit, wxT( "icon_libedit_256.png" ), 256, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_modedit].emplace_back( BITMAPS::icon_modedit, wxT( "icon_modedit_256.png" ), 256, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_pcbnew].emplace_back( BITMAPS::icon_pcbnew, wxT( "icon_pcbnew_256.png" ), 256, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_pagelayout_editor].emplace_back( BITMAPS::icon_pagelayout_editor, wxT( "icon_pagelayout_editor_256.png" ), 256, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_bitmap2component].emplace_back( BITMAPS::icon_bitmap2component, wxT( "icon_bitmap2component_256.png" ), 256, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_pcbcalculator].emplace_back( BITMAPS::icon_pcbcalculator, wxT( "icon_pcbcalculator_256.png" ), 256, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_cvpcb].emplace_back( BITMAPS::icon_cvpcb, wxT( "icon_cvpcb_dark_256.png" ), 256, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_eeschema].emplace_back( BITMAPS::icon_eeschema, wxT( "icon_eeschema_dark_256.png" ), 256, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_gerbview].emplace_back( BITMAPS::icon_gerbview, wxT( "icon_gerbview_dark_256.png" ), 256, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_kicad].emplace_back( BITMAPS::icon_kicad, wxT( "icon_kicad_dark_256.png" ), 256, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_kicad_nightly].emplace_back( BITMAPS::icon_kicad_nightly, wxT( "icon_kicad_nightly_dark_256.png" ), 256, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_libedit].emplace_back( BITMAPS::icon_libedit, wxT( "icon_libedit_dark_256.png" ), 256, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_modedit].emplace_back( BITMAPS::icon_modedit, wxT( "icon_modedit_dark_256.png" ), 256, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_pcbnew].emplace_back( BITMAPS::icon_pcbnew, wxT( "icon_pcbnew_dark_256.png" ), 256, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_pagelayout_editor].emplace_back( BITMAPS::icon_pagelayout_editor, wxT( "icon_pagelayout_editor_dark_256.png" ), 256, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_bitmap2component].emplace_back( BITMAPS::icon_bitmap2component, wxT( "icon_bitmap2component_dark_256.png" ), 256, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_pcbcalculator].emplace_back( BITMAPS::icon_pcbcalculator, wxT( "icon_pcbcalculator_dark_256.png" ), 256, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::dialog_warning].emplace_back( BITMAPS::dialog_warning, wxT( "dialog_warning_48.png" ), 48, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_3d].emplace_back( BITMAPS::icon_3d, wxT( "icon_3d_48.png" ), 48, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::icon_cvpcb].emplace_back( BITMAPS::icon_cvpcb, wxT( "icon_cvpcb_48.png" ), 48, wxT( "light" ) );
|
||||
|
||||
@@ -444,7 +444,16 @@ bool DATABASE_CONNECTION::SelectOne( const std::string& aTable,
|
||||
case SQL_DECIMAL:
|
||||
case SQL_NUMERIC:
|
||||
{
|
||||
aResult[column] = fmt::format( "{:G}", results.get<double>( i ) );
|
||||
try
|
||||
{
|
||||
aResult[column] = fmt::format( "{:G}", results.get<double>( i ) );
|
||||
}
|
||||
catch( nanodbc::null_access_error& e )
|
||||
{
|
||||
// Column was empty (null)
|
||||
aResult[column] = std::string();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -540,43 +549,92 @@ bool DATABASE_CONNECTION::SelectAll( const std::string& aTable, const std::strin
|
||||
|
||||
timer.Stop();
|
||||
|
||||
try
|
||||
{
|
||||
while( results.next() )
|
||||
{
|
||||
ROW result;
|
||||
|
||||
for( short j = 0; j < results.columns(); ++j )
|
||||
auto handleException =
|
||||
[&]( std::runtime_error& aException, const std::string& aExtraContext = "" )
|
||||
{
|
||||
std::string column = toUTF8( results.column_name( j ) );
|
||||
m_lastError = aException.what();
|
||||
std::string extra = aExtraContext.empty() ? "" : ": " + aExtraContext;
|
||||
wxLogTrace( traceDatabase,
|
||||
wxT( "Exception while parsing result %d from SelectAll: %s%s" ),
|
||||
aResults.size(), m_lastError, extra );
|
||||
};
|
||||
|
||||
switch( results.column_datatype( j ) )
|
||||
{
|
||||
case SQL_DOUBLE:
|
||||
case SQL_FLOAT:
|
||||
case SQL_REAL:
|
||||
case SQL_DECIMAL:
|
||||
case SQL_NUMERIC:
|
||||
while( results.next() )
|
||||
{
|
||||
short columnCount = 0;
|
||||
ROW result;
|
||||
|
||||
try
|
||||
{
|
||||
columnCount = results.columns();
|
||||
}
|
||||
catch( nanodbc::database_error& e )
|
||||
{
|
||||
handleException( e );
|
||||
return false;
|
||||
}
|
||||
|
||||
for( short j = 0; j < columnCount; ++j )
|
||||
{
|
||||
std::string column;
|
||||
std::string columnExtraDbgInfo;
|
||||
int datatype = SQL_UNKNOWN_TYPE;
|
||||
|
||||
try
|
||||
{
|
||||
column = toUTF8( results.column_name( j ) );
|
||||
datatype = results.column_datatype( j );
|
||||
columnExtraDbgInfo = fmt::format( "column index {}, name '{}', type {}", j, column,
|
||||
datatype );
|
||||
}
|
||||
catch( nanodbc::index_range_error& e )
|
||||
{
|
||||
handleException( e, columnExtraDbgInfo );
|
||||
return false;
|
||||
}
|
||||
|
||||
switch( datatype )
|
||||
{
|
||||
case SQL_DOUBLE:
|
||||
case SQL_FLOAT:
|
||||
case SQL_REAL:
|
||||
case SQL_DECIMAL:
|
||||
case SQL_NUMERIC:
|
||||
{
|
||||
try
|
||||
{
|
||||
result[column] = fmt::format( "{:G}", results.get<double>( j ) );
|
||||
break;
|
||||
}
|
||||
catch( nanodbc::null_access_error& e )
|
||||
{
|
||||
// Column was empty (null)
|
||||
result[column] = std::string();
|
||||
}
|
||||
catch( std::runtime_error& e )
|
||||
{
|
||||
handleException( e, columnExtraDbgInfo );
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
default:
|
||||
{
|
||||
try
|
||||
{
|
||||
result[column] = toUTF8( results.get<nanodbc::string>( j,
|
||||
NANODBC_TEXT( "" ) ) );
|
||||
}
|
||||
catch( std::runtime_error& e )
|
||||
{
|
||||
handleException( e, columnExtraDbgInfo );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aResults.emplace_back( std::move( result ) );
|
||||
}
|
||||
}
|
||||
catch( nanodbc::database_error& e )
|
||||
{
|
||||
m_lastError = e.what();
|
||||
wxLogTrace( traceDatabase, wxT( "Exception while parsing results from SelectAll: %s" ),
|
||||
m_lastError );
|
||||
return false;
|
||||
|
||||
aResults.emplace_back( std::move( result ) );
|
||||
}
|
||||
|
||||
wxLogTrace( traceDatabase, wxT( "SelectAll from %s completed in %0.1f ms" ), aTable,
|
||||
|
||||
@@ -288,6 +288,14 @@ bool DIALOG_SHIM::Show( bool show )
|
||||
std::max( wxDialog::GetSize().y, savedDialogRect.GetSize().y ),
|
||||
0 );
|
||||
}
|
||||
#ifdef __WXMAC__
|
||||
if( m_parent != nullptr )
|
||||
{
|
||||
if( wxDisplay::GetFromPoint( m_parent->GetPosition() )
|
||||
!= wxDisplay::GetFromPoint( savedDialogRect.GetPosition() ) )
|
||||
Centre();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if( m_initialSize != wxDefaultSize )
|
||||
SetSize( m_initialSize );
|
||||
|
||||
@@ -29,7 +29,7 @@ static PASTE_MODE g_paste_mode = PASTE_MODE::UNIQUE_ANNOTATIONS;
|
||||
|
||||
DIALOG_PASTE_SPECIAL::DIALOG_PASTE_SPECIAL( wxWindow* aParent,
|
||||
PASTE_MODE* aMode,
|
||||
wxString aReplacement ) :
|
||||
const wxString& aReplacement ) :
|
||||
DIALOG_PASTE_SPECIAL_BASE( aParent ),
|
||||
m_mode( aMode )
|
||||
{
|
||||
@@ -45,7 +45,7 @@ DIALOG_PASTE_SPECIAL::DIALOG_PASTE_SPECIAL( wxWindow* aParent,
|
||||
"with '%s'." ),
|
||||
aReplacement ) );
|
||||
|
||||
m_sdbSizerOK->SetFocus();
|
||||
m_pasteOptions->SetFocus();
|
||||
|
||||
// Now all widgets have the size fixed, call FinishDialogSettings
|
||||
finishDialogSettings();
|
||||
@@ -64,3 +64,11 @@ bool DIALOG_PASTE_SPECIAL::TransferDataFromWindow()
|
||||
g_paste_mode = *m_mode = static_cast<PASTE_MODE>( m_pasteOptions->GetSelection() );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PASTE_SPECIAL::onRadioBoxEvent( wxCommandEvent& event )
|
||||
{
|
||||
event.Skip();
|
||||
|
||||
m_sdbSizerOK->SetFocus();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||
// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -45,12 +45,12 @@ DIALOG_PASTE_SPECIAL_BASE::DIALOG_PASTE_SPECIAL_BASE( wxWindow* parent, wxWindow
|
||||
this->Centre( wxBOTH );
|
||||
|
||||
// Connect Events
|
||||
m_sdbSizerOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PASTE_SPECIAL_BASE::onOKButton ), NULL, this );
|
||||
m_pasteOptions->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_PASTE_SPECIAL_BASE::onRadioBoxEvent ), NULL, this );
|
||||
}
|
||||
|
||||
DIALOG_PASTE_SPECIAL_BASE::~DIALOG_PASTE_SPECIAL_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
m_sdbSizerOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PASTE_SPECIAL_BASE::onOKButton ), NULL, this );
|
||||
m_pasteOptions->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_PASTE_SPECIAL_BASE::onRadioBoxEvent ), NULL, this );
|
||||
|
||||
}
|
||||
|
||||
@@ -1,163 +1,165 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<wxFormBuilder_Project>
|
||||
<FileVersion major="1" minor="16" />
|
||||
<object class="Project" expanded="1">
|
||||
<property name="class_decoration"></property>
|
||||
<property name="code_generation">C++</property>
|
||||
<property name="disconnect_events">1</property>
|
||||
<property name="disconnect_mode">source_name</property>
|
||||
<property name="disconnect_php_events">0</property>
|
||||
<property name="disconnect_python_events">0</property>
|
||||
<property name="embedded_files_path">res</property>
|
||||
<property name="encoding">UTF-8</property>
|
||||
<property name="event_generation">connect</property>
|
||||
<property name="file">dialog_paste_special_base</property>
|
||||
<property name="first_id">1000</property>
|
||||
<property name="help_provider">none</property>
|
||||
<property name="image_path_wrapper_function_name"></property>
|
||||
<property name="indent_with_spaces"></property>
|
||||
<property name="internationalize">1</property>
|
||||
<property name="name">dialog_paste_special</property>
|
||||
<property name="namespace"></property>
|
||||
<property name="path">.</property>
|
||||
<property name="precompiled_header"></property>
|
||||
<property name="relative_path">1</property>
|
||||
<property name="skip_lua_events">1</property>
|
||||
<property name="skip_php_events">1</property>
|
||||
<property name="skip_python_events">1</property>
|
||||
<property name="ui_table">UI</property>
|
||||
<property name="use_array_enum">0</property>
|
||||
<property name="use_enum">0</property>
|
||||
<property name="use_microsoft_bom">0</property>
|
||||
<object class="Dialog" expanded="1">
|
||||
<property name="aui_managed">0</property>
|
||||
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
|
||||
<property name="bg"></property>
|
||||
<property name="center">wxBOTH</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="event_handler">impl_virtual</property>
|
||||
<property name="extra_style"></property>
|
||||
<property name="fg"></property>
|
||||
<property name="font"></property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="minimum_size">-1,-1</property>
|
||||
<property name="name">DIALOG_PASTE_SPECIAL_BASE</property>
|
||||
<property name="pos"></property>
|
||||
<property name="size">-1,-1</property>
|
||||
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
|
||||
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
|
||||
<property name="title">Paste Special</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="two_step_creation">0</property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<FileVersion major="1" minor="17"/>
|
||||
<object class="Project" expanded="true">
|
||||
<property name="class_decoration"></property>
|
||||
<property name="code_generation">C++</property>
|
||||
<property name="disconnect_events">1</property>
|
||||
<property name="disconnect_mode">source_name</property>
|
||||
<property name="disconnect_php_events">0</property>
|
||||
<property name="disconnect_python_events">0</property>
|
||||
<property name="embedded_files_path">res</property>
|
||||
<property name="encoding">UTF-8</property>
|
||||
<property name="event_generation">connect</property>
|
||||
<property name="file">dialog_paste_special_base</property>
|
||||
<property name="first_id">1000</property>
|
||||
<property name="help_provider">none</property>
|
||||
<property name="image_path_wrapper_function_name"></property>
|
||||
<property name="indent_with_spaces"></property>
|
||||
<property name="internationalize">1</property>
|
||||
<property name="name">dialog_paste_special</property>
|
||||
<property name="namespace"></property>
|
||||
<property name="path">.</property>
|
||||
<property name="precompiled_header"></property>
|
||||
<property name="relative_path">1</property>
|
||||
<property name="skip_lua_events">1</property>
|
||||
<property name="skip_php_events">1</property>
|
||||
<property name="skip_python_events">1</property>
|
||||
<property name="ui_table">UI</property>
|
||||
<property name="use_array_enum">0</property>
|
||||
<property name="use_enum">0</property>
|
||||
<property name="use_microsoft_bom">0</property>
|
||||
<object class="Dialog" expanded="true">
|
||||
<property name="aui_managed">0</property>
|
||||
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
|
||||
<property name="bg"></property>
|
||||
<property name="center">wxBOTH</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="event_handler">impl_virtual</property>
|
||||
<property name="extra_style"></property>
|
||||
<property name="fg"></property>
|
||||
<property name="font"></property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="minimum_size">-1,-1</property>
|
||||
<property name="name">DIALOG_PASTE_SPECIAL_BASE</property>
|
||||
<property name="pos"></property>
|
||||
<property name="size">-1,-1</property>
|
||||
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
|
||||
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
|
||||
<property name="title">Paste Special</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="two_step_creation">0</property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<object class="wxBoxSizer" expanded="true">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">m_mainSizer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">10</property>
|
||||
<property name="flag">wxALL|wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxBoxSizer" expanded="true">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">optionsSizer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxRadioBox" expanded="true">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="choices">"Assign unique reference designators to pasted symbols" "Keep existing reference designators, even if they are duplicated" "Clear reference designators on all pasted symbols"</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Paste Options</property>
|
||||
<property name="majorDimension">1</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">m_mainSizer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">10</property>
|
||||
<property name="flag">wxALL|wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">optionsSizer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxRadioBox" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="choices">"Assign unique reference designators to pasted symbols" "Keep existing reference designators, even if they are duplicated" "Clear reference designators on all pasted symbols"</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Paste Options</property>
|
||||
<property name="majorDimension">1</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_pasteOptions</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="selection">1</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style">wxRA_SPECIFY_COLS</property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">6</property>
|
||||
<property name="flag">wxALL|wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStdDialogButtonSizer" expanded="1">
|
||||
<property name="Apply">0</property>
|
||||
<property name="Cancel">1</property>
|
||||
<property name="ContextHelp">0</property>
|
||||
<property name="Help">0</property>
|
||||
<property name="No">0</property>
|
||||
<property name="OK">1</property>
|
||||
<property name="Save">0</property>
|
||||
<property name="Yes">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">m_sdbSizer</property>
|
||||
<property name="permission">protected</property>
|
||||
<event name="OnOKButtonClick">onOKButton</event>
|
||||
</object>
|
||||
</object>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_pasteOptions</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="selection">1</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style">wxRA_SPECIFY_COLS</property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnRadioBox">onRadioBoxEvent</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">6</property>
|
||||
<property name="flag">wxALL|wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStdDialogButtonSizer" expanded="true">
|
||||
<property name="Apply">0</property>
|
||||
<property name="Cancel">1</property>
|
||||
<property name="ContextHelp">0</property>
|
||||
<property name="Help">0</property>
|
||||
<property name="No">0</property>
|
||||
<property name="OK">1</property>
|
||||
<property name="Save">0</property>
|
||||
<property name="Yes">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">m_sdbSizer</property>
|
||||
<property name="permission">protected</property>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</wxFormBuilder_Project>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||
// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -38,7 +38,7 @@ class DIALOG_PASTE_SPECIAL_BASE : public DIALOG_SHIM
|
||||
wxButton* m_sdbSizerCancel;
|
||||
|
||||
// Virtual event handlers, override them in your derived class
|
||||
virtual void onOKButton( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void onRadioBoxEvent( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
@@ -113,7 +113,7 @@ void DS_DRAW_ITEM_LIST::GetTextVars( wxArrayString* aVars )
|
||||
wxString DS_DRAW_ITEM_LIST::BuildFullText( const wxString& aTextbase )
|
||||
{
|
||||
std::function<bool( wxString* )> wsResolver =
|
||||
[ this ]( wxString* token ) -> bool
|
||||
[&]( wxString* token ) -> bool
|
||||
{
|
||||
bool tokenUpdated = false;
|
||||
|
||||
@@ -166,10 +166,24 @@ wxString DS_DRAW_ITEM_LIST::BuildFullText( const wxString& aTextbase )
|
||||
}
|
||||
else if( m_titleBlock )
|
||||
{
|
||||
// no need for tokenUpdated; TITLE_BLOCK::TextVarResolver() does a full
|
||||
// resolve
|
||||
if( m_titleBlock->TextVarResolver( token, m_project ) )
|
||||
{
|
||||
// No need for tokenUpdated; TITLE_BLOCK::TextVarResolver() already goes
|
||||
// up to the project.
|
||||
//
|
||||
// However, the title block may have variables in it itself, so we need
|
||||
// to run the worksheet resolver again.
|
||||
//
|
||||
const TITLE_BLOCK* savedTitleBlock = m_titleBlock;
|
||||
|
||||
m_titleBlock = nullptr;
|
||||
{
|
||||
*token = ExpandTextVars( *token, &wsResolver );
|
||||
}
|
||||
m_titleBlock = savedTitleBlock;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if( m_properties && m_properties->count( *token ) )
|
||||
{
|
||||
@@ -356,5 +370,6 @@ void KIGFX::DS_PAINTER::DrawBorder( const PAGE_INFO* aPageInfo, int aScaleFactor
|
||||
// Use a gray color for the border color
|
||||
m_gal->SetStrokeColor( m_renderSettings.m_pageBorderColor );
|
||||
m_gal->SetIsFill( false );
|
||||
m_gal->SetLineWidth( m_renderSettings.GetDefaultPenWidth() );
|
||||
m_gal->DrawRectangle( origin, end );
|
||||
}
|
||||
|
||||
@@ -26,9 +26,15 @@
|
||||
#include <macros.h>
|
||||
#include <font/fontconfig.h>
|
||||
|
||||
#ifdef __WIN32__
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
using namespace fontconfig;
|
||||
|
||||
static FONTCONFIG* g_config = nullptr;
|
||||
static bool g_fcInitSuccess = false;
|
||||
|
||||
/**
|
||||
* A simple wrapper to avoid exporing fontconfig in the header
|
||||
@@ -50,11 +56,41 @@ FONTCONFIG::FONTCONFIG()
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This is simply a wrapper to call FcInit() with SEH for Windows
|
||||
* SEH on Windows can only be used in functions without objects that might be unwinded
|
||||
* (basically objects with destructors)
|
||||
* For example, new FONTCONFIG() in Fontconfig() is creating a object with a destructor
|
||||
* that *might* need to be unwinded. MSVC catches this and throws a compile error
|
||||
*/
|
||||
static void bootstrapFc()
|
||||
{
|
||||
#if defined( _MSC_VER )
|
||||
__try
|
||||
{
|
||||
#endif
|
||||
FcInit();
|
||||
g_fcInitSuccess = true;
|
||||
#if defined( _MSC_VER )
|
||||
}
|
||||
__except( GetExceptionCode() == STATUS_IN_PAGE_ERROR ? EXCEPTION_EXECUTE_HANDLER
|
||||
: EXCEPTION_CONTINUE_SEARCH )
|
||||
{
|
||||
g_fcInitSuccess = false;
|
||||
// We have documented cases that fontconfig while trying to cache fonts
|
||||
// ends up using freetype to try and get font info
|
||||
// freetype itself reads fonts through memory mapping instead of normal file APIs
|
||||
// there are crashes reading fonts sometimes as a result that return STATUS_IN_PAGE_ERROR
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
FONTCONFIG* Fontconfig()
|
||||
{
|
||||
if( !g_config )
|
||||
{
|
||||
FcInit();
|
||||
bootstrapFc();
|
||||
g_config = new FONTCONFIG();
|
||||
}
|
||||
|
||||
@@ -154,6 +190,10 @@ FONTCONFIG::FF_RESULT FONTCONFIG::FindFont( const wxString &aFontName, wxString
|
||||
int& aFaceIndex, bool aBold, bool aItalic )
|
||||
{
|
||||
FF_RESULT retval = FF_RESULT::FF_ERROR;
|
||||
|
||||
if( !g_fcInitSuccess )
|
||||
return retval;
|
||||
|
||||
wxString qualifiedFontName = aFontName;
|
||||
|
||||
wxScopedCharBuffer const fcBuffer = qualifiedFontName.ToUTF8();
|
||||
@@ -271,6 +311,9 @@ FONTCONFIG::FF_RESULT FONTCONFIG::FindFont( const wxString &aFontName, wxString
|
||||
|
||||
void FONTCONFIG::ListFonts( std::vector<std::string>& aFonts, const std::string& aDesiredLang )
|
||||
{
|
||||
if( !g_fcInitSuccess )
|
||||
return;
|
||||
|
||||
// be sure to cache bust if the language changed
|
||||
if( m_fontInfoCache.empty() || m_fontCacheLastLang != aDesiredLang )
|
||||
{
|
||||
|
||||
@@ -349,14 +349,14 @@ VECTOR2I OUTLINE_FONT::getTextAsGlyphsUnlocked( BOX2I* aBBox,
|
||||
hb_buffer_guess_segment_properties( buf ); // guess direction, script, and language based on
|
||||
// contents
|
||||
|
||||
unsigned int glyphCount;
|
||||
hb_glyph_info_t* glyphInfo = hb_buffer_get_glyph_infos( buf, &glyphCount );
|
||||
hb_glyph_position_t* glyphPos = hb_buffer_get_glyph_positions( buf, &glyphCount );
|
||||
|
||||
hb_font_t* referencedFont = hb_ft_font_create_referenced( face );
|
||||
hb_ft_font_set_funcs( referencedFont );
|
||||
hb_shape( referencedFont, buf, nullptr, 0 );
|
||||
|
||||
unsigned int glyphCount;
|
||||
hb_glyph_info_t* glyphInfo = hb_buffer_get_glyph_infos( buf, &glyphCount );
|
||||
hb_glyph_position_t* glyphPos = hb_buffer_get_glyph_positions( buf, &glyphCount );
|
||||
|
||||
VECTOR2D scaleFactor( glyphSize.x / faceSize(), -glyphSize.y / faceSize() );
|
||||
scaleFactor = scaleFactor * m_outlineFontSizeCompensation;
|
||||
|
||||
|
||||
+6
-6
@@ -191,22 +191,22 @@ int ExecuteFile( const wxString& aEditorName, const wxString& aFileName, wxProce
|
||||
if( wxFileExists( fullEditorName ) )
|
||||
{
|
||||
int i = 0;
|
||||
const wchar_t* args[4];
|
||||
std::vector<const wchar_t*> args;
|
||||
|
||||
args[i++] = fullEditorName.wc_str();
|
||||
args.emplace_back( fullEditorName.wc_str() );
|
||||
|
||||
if( !params.empty() )
|
||||
{
|
||||
for( const wxString& p : params )
|
||||
args[i++] = p.wc_str();
|
||||
args.emplace_back( p.wc_str() );
|
||||
}
|
||||
|
||||
if( !aFileName.IsEmpty() )
|
||||
args[i++] = aFileName.wc_str();
|
||||
args.emplace_back( aFileName.wc_str() );
|
||||
|
||||
args[i] = nullptr;
|
||||
args.emplace_back( nullptr );
|
||||
|
||||
return wxExecute( const_cast<wchar_t**>( args ), wxEXEC_ASYNC, aCallback );
|
||||
return wxExecute( const_cast<wchar_t**>( args.data() ), wxEXEC_ASYNC, aCallback );
|
||||
}
|
||||
|
||||
wxString msg;
|
||||
|
||||
+5
-2
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2020 Ian McInerney <ian.s.mcinerney@ieee.org>
|
||||
* Copyright (C) 2007-2014 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.TXT for contributors.
|
||||
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.TXT for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -324,8 +324,11 @@ bool KIID_PATH::MakeRelativeTo( const KIID_PATH& aPath )
|
||||
|
||||
for( size_t i = 0; i < aPath.size(); ++i )
|
||||
{
|
||||
if( copy.at( i ).AsString() != aPath.at( i ).AsString() )
|
||||
if( copy.at( i ) != aPath.at( i ) )
|
||||
{
|
||||
*this = copy;
|
||||
return false; // this path is not contained within aPath
|
||||
}
|
||||
}
|
||||
|
||||
for( size_t i = aPath.size(); i < copy.size(); ++i )
|
||||
|
||||
@@ -322,6 +322,8 @@ LIB_TREE_NODE_LIB_ID& LIB_TREE_NODE_LIB::AddItem( LIB_TREE_ITEM* aItem )
|
||||
|
||||
void LIB_TREE_NODE_LIB::UpdateScore( EDA_COMBINED_MATCHER& aMatcher, const wxString& aLib )
|
||||
{
|
||||
m_Score = 0;
|
||||
|
||||
// We need to score leaf nodes, which are usually (but not always) children.
|
||||
|
||||
if( m_Children.size() )
|
||||
|
||||
+11
-1
@@ -183,6 +183,17 @@ wxString PATHS::GetStockDataPath( bool aRespectRunFromBuildDir )
|
||||
}
|
||||
|
||||
|
||||
#ifdef __WXMSW__
|
||||
/**
|
||||
* Gets the stock (install) data path, which is the base path for things like scripting, etc
|
||||
*/
|
||||
wxString PATHS::GetWindowsBaseSharePath()
|
||||
{
|
||||
return getWindowsKiCadRoot() + wxT( "share\\" );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
wxString PATHS::GetStockEDALibraryPath()
|
||||
{
|
||||
wxString path;
|
||||
@@ -388,7 +399,6 @@ void PATHS::EnsureUserPathsExist()
|
||||
{
|
||||
EnsurePathExists( GetUserCachePath() );
|
||||
EnsurePathExists( GetUserPluginsPath() );
|
||||
EnsurePathExists( GetUserPlugins3DPath() );
|
||||
EnsurePathExists( GetUserScriptingPath() );
|
||||
EnsurePathExists( GetUserTemplatesPath() );
|
||||
EnsurePathExists( GetDefaultUserProjectsPath() );
|
||||
|
||||
@@ -814,6 +814,10 @@ wxString PGM_BASE::GetLanguageTag()
|
||||
|
||||
void PGM_BASE::SetLanguagePath()
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
wxLocale::AddCatalogLookupPathPrefix( PATHS::GetWindowsBaseSharePath()
|
||||
+ wxT( "locale" ) );
|
||||
#endif
|
||||
wxLocale::AddCatalogLookupPathPrefix( PATHS::GetLocaleDataPath() );
|
||||
|
||||
if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
|
||||
|
||||
@@ -821,7 +821,8 @@ void GERBER_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill,
|
||||
|
||||
void GERBER_PLOTTER::Circle( const VECTOR2I& aCenter, int aDiameter, FILL_T aFill, int aWidth )
|
||||
{
|
||||
Arc( aCenter, ANGLE_0, ANGLE_360, aDiameter / 2, aFill, aWidth );
|
||||
Arc( aCenter, ANGLE_0, ANGLE_180, aDiameter / 2, aFill, aWidth );
|
||||
Arc( aCenter, ANGLE_180, ANGLE_360, aDiameter / 2, aFill, aWidth );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1409,10 +1409,11 @@ void PDF_PLOTTER::Text( const VECTOR2I& aPos,
|
||||
double wideningFactor, heightFactor;
|
||||
|
||||
VECTOR2I t_size( std::abs( aSize.x ), std::abs( aSize.y ) );
|
||||
bool textMirrored = aSize.x < 0;
|
||||
|
||||
computeTextParameters( aPos, aText, aOrient, t_size, m_plotMirror, aH_justify,
|
||||
aV_justify, aWidth, aItalic, aBold, &wideningFactor, &ctm_a,
|
||||
&ctm_b, &ctm_c, &ctm_d, &ctm_e, &ctm_f, &heightFactor );
|
||||
computeTextParameters( aPos, aText, aOrient, t_size, textMirrored, aH_justify, aV_justify,
|
||||
aWidth, aItalic, aBold, &wideningFactor, &ctm_a, &ctm_b, &ctm_c, &ctm_d,
|
||||
&ctm_e, &ctm_f, &heightFactor );
|
||||
|
||||
SetColor( aColor );
|
||||
SetCurrentLineWidth( aWidth, aData );
|
||||
@@ -1424,6 +1425,10 @@ void PDF_PLOTTER::Text( const VECTOR2I& aPos,
|
||||
aFont = KIFONT::FONT::GetFont();
|
||||
|
||||
VECTOR2I full_box( aFont->StringBoundaryLimits( aText, t_size, aWidth, aBold, aItalic ) );
|
||||
|
||||
if( textMirrored )
|
||||
full_box.x *= -1;
|
||||
|
||||
VECTOR2I box_x( full_box.x, 0 );
|
||||
VECTOR2I box_y( 0, full_box.y );
|
||||
|
||||
@@ -1444,13 +1449,17 @@ void PDF_PLOTTER::Text( const VECTOR2I& aPos,
|
||||
{
|
||||
wxString word = str_tok.GetNextToken();
|
||||
|
||||
computeTextParameters( pos, word, aOrient, t_size, m_plotMirror, GR_TEXT_H_ALIGN_LEFT,
|
||||
GR_TEXT_V_ALIGN_BOTTOM, aWidth, aItalic, aBold, &wideningFactor, &ctm_a,
|
||||
&ctm_b, &ctm_c, &ctm_d, &ctm_e, &ctm_f, &heightFactor );
|
||||
computeTextParameters( pos, word, aOrient, t_size, textMirrored, GR_TEXT_H_ALIGN_LEFT,
|
||||
GR_TEXT_V_ALIGN_BOTTOM, aWidth, aItalic, aBold, &wideningFactor,
|
||||
&ctm_a, &ctm_b, &ctm_c, &ctm_d, &ctm_e, &ctm_f, &heightFactor );
|
||||
|
||||
// Extract the changed width and rotate by the orientation to get the offset for the
|
||||
// next word
|
||||
VECTOR2I bbox( aFont->StringBoundaryLimits( word, t_size, aWidth, aBold, aItalic ).x, 0 );
|
||||
|
||||
if( textMirrored )
|
||||
bbox.x *= -1;
|
||||
|
||||
RotatePoint( bbox, aOrient );
|
||||
pos += bbox;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -423,7 +423,7 @@ void PSLIKE_PLOTTER::computeTextParameters( const VECTOR2I& aPos,
|
||||
// This is an approximation of the text bounds (in IUs)
|
||||
int tw = returnPostscriptTextWidth( aText, aSize.x, aItalic, aWidth );
|
||||
int th = aSize.y;
|
||||
int dx, dy;
|
||||
int dx = 0, dy = 0;
|
||||
|
||||
switch( aH_justify )
|
||||
{
|
||||
@@ -450,7 +450,7 @@ void PSLIKE_PLOTTER::computeTextParameters( const VECTOR2I& aPos,
|
||||
*wideningFactor = sz_dev.x / sz_dev.y;
|
||||
|
||||
// Mirrored texts must be plotted as mirrored!
|
||||
if( m_plotMirror )
|
||||
if( m_plotMirror ^ aMirror )
|
||||
*wideningFactor = -*wideningFactor;
|
||||
|
||||
// The CTM transformation matrix
|
||||
|
||||
@@ -357,7 +357,7 @@ void SVG_PLOTTER::emitSetRGBColor( double r, double g, double b, double a )
|
||||
int blue = (int) ( 255.0 * b );
|
||||
long rgb_color = (red << 16) | (green << 8) | blue;
|
||||
|
||||
if( m_pen_rgb_color != rgb_color )
|
||||
if( m_pen_rgb_color != rgb_color || m_brush_alpha != a )
|
||||
{
|
||||
m_graphics_changed = true;
|
||||
m_pen_rgb_color = rgb_color;
|
||||
@@ -825,16 +825,16 @@ void SVG_PLOTTER::Text( const VECTOR2I& aPos,
|
||||
|
||||
if( !aOrient.IsZero() )
|
||||
{
|
||||
fprintf( m_outputFile,
|
||||
"<g transform=\"rotate(%f %.*f %.*f)\">\n",
|
||||
- aOrient.AsDegrees(), m_precision, anchor_pos_dev.x, m_precision, anchor_pos_dev.y );
|
||||
fprintf( m_outputFile, "<g transform=\"rotate(%f %.*f %.*f)\">\n",
|
||||
m_plotMirror ? aOrient.AsDegrees() : -aOrient.AsDegrees(), m_precision,
|
||||
anchor_pos_dev.x, m_precision, anchor_pos_dev.y );
|
||||
}
|
||||
|
||||
fprintf( m_outputFile, "<text x=\"%.*f\" y=\"%.*f\"\n",
|
||||
m_precision, text_pos_dev.x, m_precision, text_pos_dev.y );
|
||||
|
||||
/// If the text is mirrored, we should also mirror the hidden text to match
|
||||
if( aSize.x < 0 )
|
||||
if( m_plotMirror != ( aSize.x < 0 ) )
|
||||
fprintf( m_outputFile, "transform=\"scale(-1 1) translate(%f 0)\"\n", -2 * text_pos_dev.x );
|
||||
|
||||
fprintf( m_outputFile,
|
||||
|
||||
@@ -30,9 +30,10 @@
|
||||
|
||||
LIB_ID AltiumToKiCadLibID( const wxString& aLibName, const wxString& aLibReference )
|
||||
{
|
||||
wxString libName = LIB_ID::FixIllegalChars( aLibName, true );
|
||||
wxString libReference = EscapeString( aLibReference, CTX_LIBID );
|
||||
|
||||
wxString key = !aLibName.empty() ? ( aLibName + ":" + libReference ) : libReference;
|
||||
wxString key = !libName.empty() ? ( libName + ":" + libReference ) : libReference;
|
||||
|
||||
LIB_ID libId;
|
||||
libId.Parse( key, true );
|
||||
|
||||
@@ -177,8 +177,16 @@ bool PROJECT_ARCHIVER::Archive( const wxString& aSrcDir, const wxString& aDestFi
|
||||
|
||||
unsigned long uncompressedBytes = 0;
|
||||
|
||||
// Our filename collector can store duplicate filenames. for instance *.gm2
|
||||
// matches both *.g?? and *.gm??.
|
||||
// So skip duplicate filenames (they are sorted, so it is easy).
|
||||
wxString lastStoredFile;
|
||||
|
||||
for( unsigned ii = 0; ii < files.GetCount(); ii++ )
|
||||
{
|
||||
if( lastStoredFile == files[ii] ) // duplicate name: already stored
|
||||
continue;
|
||||
|
||||
wxFileSystem fsfile;
|
||||
|
||||
wxFileName curr_fn( files[ii] );
|
||||
|
||||
@@ -569,7 +569,7 @@ TOOL_ACTION ACTIONS::selectionTool( "common.InteractiveSelection.selectionTool",
|
||||
_( "Select item(s)" ), _( "Select item(s)" ),
|
||||
BITMAPS::cursor, AF_ACTIVATE );
|
||||
|
||||
TOOL_ACTION ACTIONS::measureTool( "common.InteractiveEdit.measureTool",
|
||||
TOOL_ACTION ACTIONS::measureTool( "common.Interactive.measureTool",
|
||||
AS_GLOBAL,
|
||||
// Don't be tempted to remove "Modern Toolset only". It's in the legacy property name.
|
||||
MD_CTRL + MD_SHIFT + 'M', LEGACY_HK_NAME( "Measure Distance (Modern Toolset only)" ),
|
||||
|
||||
@@ -41,8 +41,12 @@ bool EDIT_POINT::WithinPoint( const VECTOR2I& aPoint, unsigned int aSize ) const
|
||||
}
|
||||
|
||||
|
||||
EDIT_POINTS::EDIT_POINTS( EDA_ITEM* aParent )
|
||||
: EDA_ITEM( NOT_USED ), m_parent( aParent ), m_allowPoints( true )
|
||||
EDIT_POINTS::EDIT_POINTS( EDA_ITEM* aParent ) :
|
||||
EDA_ITEM( NOT_USED ),
|
||||
m_parent( aParent ),
|
||||
m_swapX( false ),
|
||||
m_swapY( false ),
|
||||
m_allowPoints( true )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -538,6 +538,23 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
|
||||
}
|
||||
else if( type == wxEVT_MENU_OPEN || type == wxEVT_MENU_CLOSE || type == wxEVT_MENU_HIGHLIGHT )
|
||||
{
|
||||
wxMenuEvent* tmp = dynamic_cast<wxMenuEvent*>( &aEvent );
|
||||
|
||||
// Something is amiss if the event has these types and isn't a menu event, so bail out on
|
||||
// its processing
|
||||
if( !tmp )
|
||||
{
|
||||
aEvent.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
wxMenuEvent& menuEvent = *tmp;
|
||||
|
||||
#if wxCHECK_VERSION( 3, 2, 0 )
|
||||
// Forward the event to the menu for processing
|
||||
if( ACTION_MENU* currentMenu = dynamic_cast<ACTION_MENU*>( menuEvent.GetMenu() ) )
|
||||
currentMenu->OnMenuEvent( menuEvent );
|
||||
#else
|
||||
//
|
||||
// wxWidgets has several issues that we have to work around:
|
||||
//
|
||||
@@ -546,16 +563,13 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
|
||||
// (FWIW, this one is fixed in wxWidgets 3.1.x.)
|
||||
//
|
||||
// 2) wxWidgets doesn't pass the menu pointer for wxEVT_MENU_HIGHLIGHT events. So we
|
||||
// store the menu pointer from the wxEVT_MENU_OPEN call.
|
||||
// store the menu pointer from the wxEVT_MENU_OPEN call (fixed in 3.1.3).
|
||||
//
|
||||
// 3) wxWidgets has no way to tell whether a command is from a menu selection or a
|
||||
// hotkey. So we keep track of menu highlighting so we can differentiate.
|
||||
//
|
||||
|
||||
static ACTION_MENU* currentMenu;
|
||||
|
||||
wxMenuEvent& menuEvent = *dynamic_cast<wxMenuEvent*>( &aEvent );
|
||||
|
||||
if( type == wxEVT_MENU_OPEN )
|
||||
{
|
||||
currentMenu = dynamic_cast<ACTION_MENU*>( menuEvent.GetMenu() );
|
||||
@@ -575,6 +589,7 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
|
||||
|
||||
currentMenu = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2018 jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2021-2024 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
|
||||
@@ -96,6 +96,22 @@ bool PICKED_ITEMS_LIST::ContainsItem( const EDA_ITEM* aItem ) const
|
||||
}
|
||||
|
||||
|
||||
bool PICKED_ITEMS_LIST::ContainsItemType( KICAD_T aItemType ) const
|
||||
{
|
||||
for( const ITEM_PICKER& picker : m_ItemsList )
|
||||
{
|
||||
const EDA_ITEM* item = picker.GetItem();
|
||||
|
||||
wxCHECK2( item, continue );
|
||||
|
||||
if( item->Type() == aItemType )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int PICKED_ITEMS_LIST::FindItem( const EDA_ITEM* aItem ) const
|
||||
{
|
||||
for( size_t i = 0; i < m_ItemsList.size(); i++ )
|
||||
|
||||
@@ -360,7 +360,8 @@ void PAGED_DIALOG::onCharHook( wxKeyEvent& aEvent )
|
||||
{
|
||||
if( dynamic_cast<wxTextEntry*>( aEvent.GetEventObject() )
|
||||
|| dynamic_cast<wxStyledTextCtrl*>( aEvent.GetEventObject() )
|
||||
|| dynamic_cast<wxListView*>( aEvent.GetEventObject() ) )
|
||||
|| dynamic_cast<wxListView*>( aEvent.GetEventObject() )
|
||||
|| dynamic_cast<wxGrid*>( FindFocus() ) )
|
||||
{
|
||||
aEvent.Skip();
|
||||
return;
|
||||
@@ -378,7 +379,7 @@ void PAGED_DIALOG::onCharHook( wxKeyEvent& aEvent )
|
||||
m_treebook->SetSelection( page - 1 );
|
||||
}
|
||||
|
||||
m_treebook->GetTreeCtrl()->SetFocus(); // Don't allow preview canvas to steal focus
|
||||
m_treebook->GetTreeCtrl()->SetFocus(); // Don't allow preview canvas to steal gridFocus
|
||||
}
|
||||
else if( aEvent.GetKeyCode() == WXK_DOWN )
|
||||
{
|
||||
@@ -386,7 +387,7 @@ void PAGED_DIALOG::onCharHook( wxKeyEvent& aEvent )
|
||||
|
||||
m_treebook->SetSelection( std::min<int>( page + 1, m_treebook->GetPageCount() - 1 ) );
|
||||
|
||||
m_treebook->GetTreeCtrl()->SetFocus(); // Don't allow preview canvas to steal focus
|
||||
m_treebook->GetTreeCtrl()->SetFocus(); // Don't allow preview canvas to steal gridFocus
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -184,6 +184,9 @@ bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits )
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
// we didnt get anywhere deregister the settings
|
||||
aProgram->GetSettingsManager().FlushAndRelease( KifaceSettings(), false );
|
||||
|
||||
DisplayErrorMessage( nullptr, _( "An error occurred attempting to load the global "
|
||||
"footprint library table." ),
|
||||
ioe.What() );
|
||||
|
||||
@@ -185,6 +185,28 @@ bool SCH_EDIT_FRAME::SchematicCleanUp( SCH_SCREEN* aScreen )
|
||||
} );
|
||||
|
||||
|
||||
auto minX = []( const SCH_LINE* l )
|
||||
{
|
||||
return std::min( l->GetStartPoint().x, l->GetEndPoint().x );
|
||||
};
|
||||
|
||||
auto maxX = []( const SCH_LINE* l )
|
||||
{
|
||||
return std::max( l->GetStartPoint().x, l->GetEndPoint().x );
|
||||
};
|
||||
|
||||
auto minY = []( const SCH_LINE* l )
|
||||
{
|
||||
return std::min( l->GetStartPoint().y, l->GetEndPoint().y );
|
||||
};
|
||||
|
||||
auto maxY = []( const SCH_LINE* l )
|
||||
{
|
||||
return std::max( l->GetStartPoint().y, l->GetEndPoint().y );
|
||||
};
|
||||
|
||||
// Would be nice to put lines in a canonical form here by swapping
|
||||
// start <-> end as needed but I don't know what swapping breaks.
|
||||
while( changed )
|
||||
{
|
||||
changed = false;
|
||||
@@ -196,6 +218,13 @@ bool SCH_EDIT_FRAME::SchematicCleanUp( SCH_SCREEN* aScreen )
|
||||
lines.push_back( static_cast<SCH_LINE*>( item ) );
|
||||
}
|
||||
|
||||
// Sort by minimum X position
|
||||
std::sort( lines.begin(), lines.end(),
|
||||
[&]( const SCH_LINE* a, const SCH_LINE* b )
|
||||
{
|
||||
return minX( a ) < minX( b );
|
||||
} );
|
||||
|
||||
for( auto it1 = lines.begin(); it1 != lines.end(); ++it1 )
|
||||
{
|
||||
SCH_LINE* firstLine = *it1;
|
||||
@@ -209,11 +238,24 @@ bool SCH_EDIT_FRAME::SchematicCleanUp( SCH_SCREEN* aScreen )
|
||||
continue;
|
||||
}
|
||||
|
||||
int firstRightXEdge = maxX( firstLine );
|
||||
auto it2 = it1;
|
||||
|
||||
for( ++it2; it2 != lines.end(); ++it2 )
|
||||
{
|
||||
SCH_LINE* secondLine = *it2;
|
||||
int secondLeftXEdge = minX( secondLine );
|
||||
|
||||
// impossible to overlap remaining lines
|
||||
if( secondLeftXEdge > firstRightXEdge )
|
||||
break;
|
||||
|
||||
// No Y axis overlap
|
||||
if( !( std::max( minY( firstLine ), minY( secondLine ) )
|
||||
<= std::min( maxY( firstLine ), maxY( secondLine ) ) ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( secondLine->GetFlags() & STRUCT_DELETED )
|
||||
continue;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2018 CERN
|
||||
* Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2021-2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Jon Evans <jon@craftyjon.com>
|
||||
*
|
||||
@@ -127,16 +127,9 @@ bool CONNECTION_SUBGRAPH::ResolveDrivers( bool aCheckMultipleDrivers )
|
||||
return a_name < b_name;
|
||||
};
|
||||
|
||||
auto strong_cmp = [this]( SCH_ITEM* a, SCH_ITEM* b ) -> bool
|
||||
{
|
||||
const wxString& a_name = GetNameForDriver( a );
|
||||
const wxString& b_name = GetNameForDriver( b );
|
||||
return a_name < b_name;
|
||||
};
|
||||
|
||||
PRIORITY highest_priority = PRIORITY::INVALID;
|
||||
std::set<SCH_ITEM*, decltype( candidate_cmp )> candidates( candidate_cmp );
|
||||
std::set<SCH_ITEM*, decltype( strong_cmp )> strong_drivers( strong_cmp );
|
||||
std::set<SCH_ITEM*> strong_drivers;
|
||||
|
||||
m_driver = nullptr;
|
||||
|
||||
@@ -3004,6 +2997,7 @@ bool CONNECTION_GRAPH::ercCheckBusToNetConflicts( const CONNECTION_SUBGRAPH* aSu
|
||||
if( net_item && bus_item )
|
||||
{
|
||||
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_BUS_TO_NET_CONFLICT );
|
||||
ercItem->SetSheetSpecificPath( sheet );
|
||||
ercItem->SetItems( net_item, bus_item );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, net_item->GetPosition() );
|
||||
@@ -3071,6 +3065,7 @@ bool CONNECTION_GRAPH::ercCheckBusToBusConflicts( const CONNECTION_SUBGRAPH* aSu
|
||||
if( !match )
|
||||
{
|
||||
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_BUS_TO_BUS_CONFLICT );
|
||||
ercItem->SetSheetSpecificPath( sheet );
|
||||
ercItem->SetItems( label, port );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, label->GetPosition() );
|
||||
@@ -3174,6 +3169,7 @@ bool CONNECTION_GRAPH::ercCheckBusToBusEntryConflicts( const CONNECTION_SUBGRAPH
|
||||
UnescapeString( netName ),
|
||||
UnescapeString( bus_name ) );
|
||||
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_BUS_ENTRY_CONFLICT );
|
||||
ercItem->SetSheetSpecificPath( sheet );
|
||||
ercItem->SetItems( bus_entry, bus_wire );
|
||||
ercItem->SetErrorMessage( msg );
|
||||
|
||||
@@ -3187,7 +3183,6 @@ bool CONNECTION_GRAPH::ercCheckBusToBusEntryConflicts( const CONNECTION_SUBGRAPH
|
||||
}
|
||||
|
||||
|
||||
// TODO(JE) Check sheet pins here too?
|
||||
bool CONNECTION_GRAPH::ercCheckNoConnects( const CONNECTION_SUBGRAPH* aSubgraph )
|
||||
{
|
||||
ERC_SETTINGS& settings = m_schematic->ErcSettings();
|
||||
@@ -3258,9 +3253,29 @@ bool CONNECTION_GRAPH::ercCheckNoConnects( const CONNECTION_SUBGRAPH* aSubgraph
|
||||
|
||||
if( aSubgraph->m_no_connect != nullptr )
|
||||
{
|
||||
// Special case: If the subgraph being checked consists of only a hier port/pin and
|
||||
// a no-connect, we don't issue a "no-connect connected" warning just because
|
||||
// connections exist on the sheet on the other side of the link.
|
||||
VECTOR2I noConnectPos = aSubgraph->m_no_connect->GetPosition();
|
||||
|
||||
for( SCH_SHEET_PIN* hierPin : aSubgraph->m_hier_pins )
|
||||
{
|
||||
if( hierPin->GetPosition() == noConnectPos )
|
||||
return true;
|
||||
}
|
||||
|
||||
for( SCH_HIERLABEL* hierLabel : aSubgraph->m_hier_ports )
|
||||
{
|
||||
if( hierLabel->GetPosition() == noConnectPos )
|
||||
return true;
|
||||
}
|
||||
|
||||
if( unique_pins.size() > 1 && settings.IsTestEnabled( ERCE_NOCONNECT_CONNECTED ) )
|
||||
{
|
||||
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_NOCONNECT_CONNECTED );
|
||||
ercItem->SetSheetSpecificPath( sheet );
|
||||
ercItem->SetItemsSheetPaths( sheet );
|
||||
|
||||
VECTOR2I pos;
|
||||
|
||||
if( pin )
|
||||
@@ -3284,6 +3299,8 @@ bool CONNECTION_GRAPH::ercCheckNoConnects( const CONNECTION_SUBGRAPH* aSubgraph
|
||||
{
|
||||
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_NOCONNECT_NOT_CONNECTED );
|
||||
ercItem->SetItems( aSubgraph->m_no_connect );
|
||||
ercItem->SetSheetSpecificPath( sheet );
|
||||
ercItem->SetItemsSheetPaths( sheet );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, aSubgraph->m_no_connect->GetPosition() );
|
||||
screen->Append( marker );
|
||||
@@ -3372,6 +3389,8 @@ bool CONNECTION_GRAPH::ercCheckNoConnects( const CONNECTION_SUBGRAPH* aSubgraph
|
||||
&& settings.IsTestEnabled( ERCE_PIN_NOT_CONNECTED ) )
|
||||
{
|
||||
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_PIN_NOT_CONNECTED );
|
||||
ercItem->SetSheetSpecificPath( sheet );
|
||||
ercItem->SetItemsSheetPaths( sheet );
|
||||
ercItem->SetItems( pin );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, pin->GetTransformedPosition() );
|
||||
@@ -3395,6 +3414,8 @@ bool CONNECTION_GRAPH::ercCheckNoConnects( const CONNECTION_SUBGRAPH* aSubgraph
|
||||
&& settings.IsTestEnabled( ERCE_PIN_NOT_CONNECTED ) )
|
||||
{
|
||||
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_PIN_NOT_CONNECTED );
|
||||
ercItem->SetSheetSpecificPath( sheet );
|
||||
ercItem->SetItemsSheetPaths( sheet );
|
||||
ercItem->SetItems( testPin );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem,
|
||||
@@ -3416,6 +3437,7 @@ bool CONNECTION_GRAPH::ercCheckFloatingWires( const CONNECTION_SUBGRAPH* aSubgra
|
||||
if( aSubgraph->m_driver )
|
||||
return true;
|
||||
|
||||
const SCH_SHEET_PATH& sheet = aSubgraph->m_sheet;
|
||||
std::vector<SCH_ITEM*> wires;
|
||||
|
||||
// We've gotten this far, so we know we have no valid driver. All we need to do is check
|
||||
@@ -3434,6 +3456,7 @@ bool CONNECTION_GRAPH::ercCheckFloatingWires( const CONNECTION_SUBGRAPH* aSubgra
|
||||
SCH_SCREEN* screen = aSubgraph->m_sheet.LastScreen();
|
||||
|
||||
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_WIRE_DANGLING );
|
||||
ercItem->SetSheetSpecificPath( sheet );
|
||||
ercItem->SetItems( wires[0],
|
||||
wires.size() > 1 ? wires[1] : nullptr,
|
||||
wires.size() > 2 ? wires[2] : nullptr,
|
||||
@@ -3466,6 +3489,7 @@ bool CONNECTION_GRAPH::ercCheckLabels( const CONNECTION_SUBGRAPH* aSubgraph )
|
||||
if( aSubgraph->m_driver_connection->IsBus() )
|
||||
return true;
|
||||
|
||||
const SCH_SHEET_PATH& sheet = aSubgraph->m_sheet;
|
||||
ERC_SETTINGS& settings = m_schematic->ErcSettings();
|
||||
bool ok = true;
|
||||
int pinCount = 0;
|
||||
@@ -3487,6 +3511,7 @@ bool CONNECTION_GRAPH::ercCheckLabels( const CONNECTION_SUBGRAPH* aSubgraph )
|
||||
if( settings.IsTestEnabled( errCode ) )
|
||||
{
|
||||
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( errCode );
|
||||
ercItem->SetSheetSpecificPath( sheet );
|
||||
ercItem->SetItems( aText );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, aText->GetPosition() );
|
||||
@@ -3621,6 +3646,8 @@ int CONNECTION_GRAPH::ercCheckHierSheets()
|
||||
{
|
||||
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_PIN_NOT_CONNECTED );
|
||||
ercItem->SetItems( pin );
|
||||
ercItem->SetSheetSpecificPath( sheet );
|
||||
ercItem->SetItemsSheetPaths( sheet );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, pin->GetPosition() );
|
||||
sheet.LastScreen()->Append( marker );
|
||||
|
||||
@@ -350,14 +350,35 @@ void DIALOG_CHANGE_SYMBOLS::updateFieldsList()
|
||||
}
|
||||
|
||||
// Update the listbox widget
|
||||
for( unsigned i = m_fieldsBox->GetCount() - 1; i >= MANDATORY_FIELDS; --i )
|
||||
m_fieldsBox->Delete( i );
|
||||
wxArrayInt checkedItems;
|
||||
wxArrayString checkedNames;
|
||||
|
||||
m_fieldsBox->GetCheckedItems( checkedItems );
|
||||
|
||||
for( int ii : checkedItems )
|
||||
checkedNames.push_back( m_fieldsBox->GetString( ii ) );
|
||||
|
||||
bool allChecked = true;
|
||||
|
||||
for( unsigned ii = 0; ii < m_fieldsBox->GetCount(); ++ii )
|
||||
{
|
||||
if( ii == REFERENCE_FIELD || ii == VALUE_FIELD )
|
||||
continue;
|
||||
|
||||
if( !m_fieldsBox->IsChecked( ii ) )
|
||||
allChecked = false;
|
||||
}
|
||||
|
||||
for( unsigned ii = m_fieldsBox->GetCount() - 1; ii >= MANDATORY_FIELDS; --ii )
|
||||
m_fieldsBox->Delete( ii );
|
||||
|
||||
for( const wxString& fieldName : fieldNames )
|
||||
{
|
||||
m_fieldsBox->Append( fieldName );
|
||||
|
||||
for( unsigned i = MANDATORY_FIELDS; i < m_fieldsBox->GetCount(); ++i )
|
||||
m_fieldsBox->Check( i, true );
|
||||
if( allChecked || alg::contains( checkedNames, fieldName ) )
|
||||
m_fieldsBox->Check( m_fieldsBox->GetCount() - 1, true );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -361,6 +361,12 @@ bool DIALOG_LIB_SYMBOL_PROPERTIES::TransferDataFromWindow()
|
||||
wxString newName = EscapeString( m_SymbolNameCtrl->GetValue(), CTX_LIBID );
|
||||
wxString oldName = m_libEntry->GetName();
|
||||
|
||||
if( newName.IsEmpty() )
|
||||
{
|
||||
wxMessageBox( _( "Symbol must have a name." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( oldName != newName )
|
||||
{
|
||||
wxString libName = m_Parent->GetCurLib();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2009 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 2014-2023 KiCad Developers, see CHANGELOG.txt for contributors.
|
||||
* Copyright (C) 2014-2024 KiCad Developers, see CHANGELOG.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
|
||||
@@ -667,6 +667,9 @@ bool DIALOG_SHEET_PROPERTIES::onSheetFilenameChanged( const wxString& aNewFilena
|
||||
if( m_clearAnnotationNewItems )
|
||||
*m_clearAnnotationNewItems = clearAnnotation;
|
||||
|
||||
// Rebuild the entire connection graph.
|
||||
m_frame->RecalculateConnections( GLOBAL_CLEANUP );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems()
|
||||
{
|
||||
KIGFX::VIEW* view = m_preview->GetView();
|
||||
|
||||
std::vector<DANGLING_END_ITEM> endPoints;
|
||||
std::vector<DANGLING_END_ITEM> endPointsByType;
|
||||
|
||||
m_page = new PAGE_INFO( PAGE_INFO::Custom );
|
||||
m_titleBlock = new TITLE_BLOCK;
|
||||
@@ -396,7 +396,7 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems()
|
||||
pin->SetNumber( wxT( "1" ) );
|
||||
pin->SetName( wxT( "-" ) );
|
||||
|
||||
endPoints.emplace_back( PIN_END, pin, mapLibItemPosition( pin->GetPosition() ) );
|
||||
endPointsByType.emplace_back( PIN_END, pin, mapLibItemPosition( pin->GetPosition() ) );
|
||||
symbol->AddDrawItem( pin );
|
||||
|
||||
pin = new LIB_PIN( symbol );
|
||||
@@ -408,7 +408,7 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems()
|
||||
pin->SetNumber( wxT( "2" ) );
|
||||
pin->SetName( wxT( "+" ) );
|
||||
|
||||
endPoints.emplace_back( PIN_END, pin, mapLibItemPosition( pin->GetPosition() ) );
|
||||
endPointsByType.emplace_back( PIN_END, pin, mapLibItemPosition( pin->GetPosition() ) );
|
||||
symbol->AddDrawItem( pin );
|
||||
|
||||
pin = new LIB_PIN( symbol );
|
||||
@@ -420,7 +420,7 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems()
|
||||
pin->SetNumber( wxT( "3" ) );
|
||||
pin->SetName( wxT( "OUT" ) );
|
||||
|
||||
endPoints.emplace_back( PIN_END, pin, mapLibItemPosition( pin->GetPosition() ) );
|
||||
endPointsByType.emplace_back( PIN_END, pin, mapLibItemPosition( pin->GetPosition() ) );
|
||||
symbol->AddDrawItem( pin );
|
||||
|
||||
addItem( symbol );
|
||||
@@ -445,16 +445,19 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems()
|
||||
if( sch_item && sch_item->IsConnectable() )
|
||||
{
|
||||
sch_item->AutoplaceFields( nullptr, false );
|
||||
sch_item->GetEndPoints( endPoints );
|
||||
sch_item->GetEndPoints( endPointsByType );
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<DANGLING_END_ITEM> endPointsByPos = endPointsByType;
|
||||
DANGLING_END_ITEM_HELPER::sort_dangling_end_items( endPointsByType, endPointsByPos );
|
||||
|
||||
for( EDA_ITEM* item : m_previewItems )
|
||||
{
|
||||
SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( item );
|
||||
|
||||
if( sch_item && sch_item->IsConnectable() )
|
||||
sch_item->UpdateDanglingState( endPoints, nullptr );
|
||||
sch_item->UpdateDanglingState( endPointsByType, endPointsByPos, nullptr );
|
||||
}
|
||||
|
||||
zoomFitPreview();
|
||||
|
||||
@@ -334,7 +334,8 @@ bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits )
|
||||
InitSettings( new EESCHEMA_SETTINGS );
|
||||
// Register the symbol editor settings as well because they share a KiFACE and need to be
|
||||
// loaded prior to use to avoid threading deadlocks
|
||||
aProgram->GetSettingsManager().RegisterSettings( new SYMBOL_EDITOR_SETTINGS );
|
||||
SYMBOL_EDITOR_SETTINGS* symSettings = new SYMBOL_EDITOR_SETTINGS();
|
||||
aProgram->GetSettingsManager().RegisterSettings( symSettings ); // manager takes ownership
|
||||
|
||||
// We intentionally register KifaceSettings after SYMBOL_EDITOR_SETTINGS
|
||||
// In legacy configs, many settings were in a single editor config nd the migration routine
|
||||
@@ -345,7 +346,12 @@ bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits )
|
||||
start_common( aCtlBits );
|
||||
|
||||
if( !loadGlobalLibTable() )
|
||||
{
|
||||
// we didnt get anywhere deregister the settings
|
||||
aProgram->GetSettingsManager().FlushAndRelease( symSettings, false );
|
||||
aProgram->GetSettingsManager().FlushAndRelease( KifaceSettings(), false );
|
||||
return false;
|
||||
}
|
||||
|
||||
m_jobHandler = std::make_unique<EESCHEMA_JOBS_HANDLER>();
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ void EESCHEMA_JOBS_HANDLER::InitRenderSettings( KIGFX::SCH_RENDER_SETTINGS* aRen
|
||||
aSch->Prj().GetProjectPath() );
|
||||
|
||||
if( !DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( filename ) )
|
||||
wxFprintf( stderr, _( "Error loading drawing sheet." ) );
|
||||
wxFprintf( stderr, _( "Error loading drawing sheet." ) + wxS( "\n" ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -379,7 +379,7 @@ int EESCHEMA_JOBS_HANDLER::doSymExportSvg( JOB_SYM_EXPORT_SVG* aSvgJob,
|
||||
|
||||
if( !plotter->OpenFile( fn.GetFullPath() ) )
|
||||
{
|
||||
wxFprintf( stderr, _( "Unable to open destination '%s'" ), fn.GetFullPath() );
|
||||
wxFprintf( stderr, _( "Unable to open destination '%s'" ) + wxS( "\n" ), fn.GetFullPath() );
|
||||
|
||||
delete plotter;
|
||||
return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
|
||||
@@ -442,7 +442,7 @@ int EESCHEMA_JOBS_HANDLER::JobSymExportSvg( JOB* aJob )
|
||||
|
||||
if( !symbol )
|
||||
{
|
||||
wxFprintf( stderr, _( "There is no symbol selected to save." ) );
|
||||
wxFprintf( stderr, _( "There is no symbol selected to save." ) + wxS( "\n" ) );
|
||||
return CLI::EXIT_CODES::ERR_ARGS;
|
||||
}
|
||||
}
|
||||
|
||||
+8
-1
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2024 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
|
||||
@@ -215,6 +215,7 @@ void ERC_TESTER::TestTextVars( DS_PROXY_VIEW_ITEM* aDrawingSheet )
|
||||
std::shared_ptr<ERC_ITEM> ercItem =
|
||||
ERC_ITEM::Create( ERCE_UNRESOLVED_VARIABLE );
|
||||
ercItem->SetItems( &field );
|
||||
ercItem->SetSheetSpecificPath( sheet );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, pos );
|
||||
screen->Append( marker );
|
||||
@@ -232,6 +233,7 @@ void ERC_TESTER::TestTextVars( DS_PROXY_VIEW_ITEM* aDrawingSheet )
|
||||
std::shared_ptr<ERC_ITEM> ercItem =
|
||||
ERC_ITEM::Create( ERCE_UNRESOLVED_VARIABLE );
|
||||
ercItem->SetItems( &field );
|
||||
ercItem->SetSheetSpecificPath( sheet );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, field.GetPosition() );
|
||||
screen->Append( marker );
|
||||
@@ -245,6 +247,7 @@ void ERC_TESTER::TestTextVars( DS_PROXY_VIEW_ITEM* aDrawingSheet )
|
||||
std::shared_ptr<ERC_ITEM> ercItem =
|
||||
ERC_ITEM::Create( ERCE_UNRESOLVED_VARIABLE );
|
||||
ercItem->SetItems( pin );
|
||||
ercItem->SetSheetSpecificPath( sheet );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, pin->GetPosition() );
|
||||
screen->Append( marker );
|
||||
@@ -258,6 +261,7 @@ void ERC_TESTER::TestTextVars( DS_PROXY_VIEW_ITEM* aDrawingSheet )
|
||||
std::shared_ptr<ERC_ITEM> ercItem =
|
||||
ERC_ITEM::Create( ERCE_UNRESOLVED_VARIABLE );
|
||||
ercItem->SetItems( text );
|
||||
ercItem->SetSheetSpecificPath( sheet );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, text->GetPosition() );
|
||||
screen->Append( marker );
|
||||
@@ -270,6 +274,7 @@ void ERC_TESTER::TestTextVars( DS_PROXY_VIEW_ITEM* aDrawingSheet )
|
||||
std::shared_ptr<ERC_ITEM> ercItem =
|
||||
ERC_ITEM::Create( ERCE_UNRESOLVED_VARIABLE );
|
||||
ercItem->SetItems( textBox );
|
||||
ercItem->SetSheetSpecificPath( sheet );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, textBox->GetPosition() );
|
||||
screen->Append( marker );
|
||||
@@ -285,6 +290,7 @@ void ERC_TESTER::TestTextVars( DS_PROXY_VIEW_ITEM* aDrawingSheet )
|
||||
{
|
||||
std::shared_ptr<ERC_ITEM> erc = ERC_ITEM::Create( ERCE_UNRESOLVED_VARIABLE );
|
||||
erc->SetErrorMessage( _( "Unresolved text variable in drawing sheet" ) );
|
||||
erc->SetSheetSpecificPath( sheet );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( erc, text->GetPosition() );
|
||||
screen->Append( marker );
|
||||
@@ -580,6 +586,7 @@ int ERC_TESTER::TestNoConnectPins()
|
||||
pair.second.size() > 2 ? pair.second[2] : nullptr,
|
||||
pair.second.size() > 3 ? pair.second[3] : nullptr );
|
||||
ercItem->SetErrorMessage( _( "Pins with 'no connection' type are connected" ) );
|
||||
ercItem->SetSheetSpecificPath( sheet );
|
||||
|
||||
SCH_MARKER* marker = new SCH_MARKER( ercItem, pair.first );
|
||||
sheet.LastScreen()->Append( marker );
|
||||
|
||||
@@ -465,6 +465,9 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
||||
screen->MigrateSimModels();
|
||||
}
|
||||
|
||||
schematic.PruneOrphanedSymbolInstances( Prj().GetProjectName(), Schematic().GetSheets() );
|
||||
schematic.PruneOrphanedSheetInstances( Prj().GetProjectName(), Schematic().GetSheets() );
|
||||
|
||||
Schematic().ConnectionGraph()->Reset();
|
||||
|
||||
SetScreen( GetCurrentSheet().LastScreen() );
|
||||
|
||||
+29
-15
@@ -1369,49 +1369,63 @@ BITMAPS LIB_PIN::GetMenuImage() const
|
||||
}
|
||||
|
||||
|
||||
wxString LIB_PIN::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, ALT* aAlt ) const
|
||||
{
|
||||
return getItemDescription( aAlt );
|
||||
}
|
||||
|
||||
|
||||
wxString LIB_PIN::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
|
||||
{
|
||||
// This code previously checked "m_name.IsEmpty()" to choose the correct
|
||||
return getItemDescription( nullptr );
|
||||
}
|
||||
|
||||
|
||||
wxString LIB_PIN::getItemDescription( ALT* aAlt ) const
|
||||
{
|
||||
// This code previously checked "m_name.IsEmpty()" to choose the correct
|
||||
// formatting path, but that check fails if the pin is called "~" which is
|
||||
// the default for an empty pin name. Instead we get the final display string
|
||||
// the default for an empty pin name. Instead we get the final display string
|
||||
// that will be shown and check if it's empty.
|
||||
|
||||
wxString shownName = UnescapeString( GetShownName() );
|
||||
wxString name = UnescapeString( aAlt ? aAlt->m_Name : GetShownName() );
|
||||
wxString electricalTypeName = ElectricalPinTypeGetText( aAlt ? aAlt->m_Type : m_type );
|
||||
wxString pinShapeName = PinShapeGetText( aAlt ? aAlt->m_Shape : m_shape );
|
||||
|
||||
if( IsVisible() )
|
||||
{
|
||||
if ( !shownName.IsEmpty() )
|
||||
if ( !name.IsEmpty() )
|
||||
{
|
||||
return wxString::Format( _( "Pin %s [%s, %s, %s]" ),
|
||||
GetShownNumber(),
|
||||
shownName,
|
||||
GetElectricalTypeName(),
|
||||
PinShapeGetText( m_shape ) );
|
||||
name,
|
||||
electricalTypeName,
|
||||
pinShapeName );
|
||||
}
|
||||
else
|
||||
{
|
||||
return wxString::Format( _( "Pin %s [%s, %s]" ),
|
||||
GetShownNumber(),
|
||||
GetElectricalTypeName(),
|
||||
PinShapeGetText( m_shape ) );
|
||||
electricalTypeName,
|
||||
pinShapeName );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !shownName.IsEmpty() )
|
||||
if( !name.IsEmpty() )
|
||||
{
|
||||
return wxString::Format( _( "Hidden pin %s [%s, %s, %s]" ),
|
||||
GetShownNumber(),
|
||||
shownName,
|
||||
GetElectricalTypeName(),
|
||||
PinShapeGetText( m_shape ) );
|
||||
name,
|
||||
electricalTypeName,
|
||||
pinShapeName );
|
||||
}
|
||||
else
|
||||
{
|
||||
return wxString::Format( _( "Hidden pin %s [%s, %s]" ),
|
||||
GetShownNumber(),
|
||||
GetElectricalTypeName(),
|
||||
PinShapeGetText( m_shape ) );
|
||||
electricalTypeName,
|
||||
pinShapeName );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,6 +244,7 @@ public:
|
||||
BITMAPS GetMenuImage() const override;
|
||||
|
||||
wxString GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const override;
|
||||
wxString GetItemDescription( UNITS_PROVIDER* aUnitsProvider, ALT* aAlt ) const;
|
||||
|
||||
EDA_ITEM* Clone() const override;
|
||||
|
||||
@@ -260,6 +261,8 @@ public:
|
||||
static const wxString GetCanonicalElectricalTypeName( ELECTRICAL_PINTYPE aType );
|
||||
|
||||
protected:
|
||||
wxString getItemDescription( ALT* aAlt ) const;
|
||||
|
||||
struct EXTENTS_CACHE
|
||||
{
|
||||
KIFONT::FONT* m_Font = nullptr;
|
||||
|
||||
@@ -414,7 +414,7 @@ void LIB_TEXTBOX::Plot( PLOTTER* aPlotter, bool aBackground, const VECTOR2I& aOf
|
||||
color = renderSettings->GetLayerColor( LAYER_DEVICE );
|
||||
|
||||
if( lineStyle == PLOT_DASH_TYPE::DEFAULT )
|
||||
lineStyle = PLOT_DASH_TYPE::DASH;
|
||||
lineStyle = PLOT_DASH_TYPE::SOLID;
|
||||
|
||||
if( aDimmed )
|
||||
{
|
||||
@@ -465,7 +465,7 @@ void LIB_TEXTBOX::Plot( PLOTTER* aPlotter, bool aBackground, const VECTOR2I& aOf
|
||||
|
||||
text.GetLinePositions( positions, (int) strings_list.Count() );
|
||||
|
||||
TEXT_ATTRIBUTES attrs = GetAttributes();
|
||||
TEXT_ATTRIBUTES attrs = text.GetAttributes();
|
||||
attrs.m_StrokeWidth = penWidth;
|
||||
attrs.m_Multiline = false;
|
||||
|
||||
|
||||
+13
-10
@@ -304,8 +304,9 @@ void SCH_BUS_ENTRY_BASE::Rotate( const VECTOR2I& aCenter )
|
||||
}
|
||||
|
||||
|
||||
bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
{
|
||||
bool previousStateStart = m_isDanglingStart;
|
||||
bool previousStateEnd = m_isDanglingEnd;
|
||||
@@ -316,9 +317,9 @@ bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aI
|
||||
bool has_wire[2] = { false };
|
||||
bool has_bus[2] = { false };
|
||||
|
||||
for( unsigned ii = 0; ii < aItemList.size(); ii++ )
|
||||
for( unsigned ii = 0; ii < aItemListByType.size(); ii++ )
|
||||
{
|
||||
DANGLING_END_ITEM& item = aItemList[ii];
|
||||
DANGLING_END_ITEM& item = aItemListByType[ii];
|
||||
|
||||
if( item.GetItem() == this )
|
||||
continue;
|
||||
@@ -336,7 +337,7 @@ bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aI
|
||||
case BUS_END:
|
||||
{
|
||||
// The bus has created 2 DANGLING_END_ITEMs, one per end.
|
||||
DANGLING_END_ITEM& nextItem = aItemList[++ii];
|
||||
DANGLING_END_ITEM& nextItem = aItemListByType[++ii];
|
||||
|
||||
if( IsPointOnSegment( item.GetPosition(), nextItem.GetPosition(), m_pos ) )
|
||||
has_bus[0] = true;
|
||||
@@ -363,17 +364,19 @@ bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aI
|
||||
}
|
||||
|
||||
|
||||
bool SCH_BUS_BUS_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
bool SCH_BUS_BUS_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
{
|
||||
bool previousStateStart = m_isDanglingStart;
|
||||
bool previousStateEnd = m_isDanglingEnd;
|
||||
|
||||
m_isDanglingStart = m_isDanglingEnd = true;
|
||||
|
||||
for( unsigned ii = 0; ii < aItemList.size(); ii++ )
|
||||
// TODO: filter using get_lower as we only use one item type
|
||||
for( unsigned ii = 0; ii < aItemListByType.size(); ii++ )
|
||||
{
|
||||
DANGLING_END_ITEM& item = aItemList[ii];
|
||||
DANGLING_END_ITEM& item = aItemListByType[ii];
|
||||
|
||||
if( item.GetItem() == this )
|
||||
continue;
|
||||
@@ -383,7 +386,7 @@ bool SCH_BUS_BUS_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aIt
|
||||
case BUS_END:
|
||||
{
|
||||
// The bus has created 2 DANGLING_END_ITEMs, one per end.
|
||||
DANGLING_END_ITEM& nextItem = aItemList[++ii];
|
||||
DANGLING_END_ITEM& nextItem = aItemListByType[++ii];
|
||||
|
||||
if( IsPointOnSegment( item.GetPosition(), nextItem.GetPosition(), m_pos ) )
|
||||
m_isDanglingStart = false;
|
||||
|
||||
@@ -188,8 +188,9 @@ public:
|
||||
|
||||
BITMAPS GetMenuImage() const override;
|
||||
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
|
||||
/**
|
||||
* Pointer to the bus item (usually a bus wire) connected to this bus-wire
|
||||
@@ -233,8 +234,9 @@ public:
|
||||
|
||||
BITMAPS GetMenuImage() const override;
|
||||
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
|
||||
/**
|
||||
* Pointer to the bus items (usually bus wires) connected to this bus-bus
|
||||
|
||||
@@ -180,7 +180,7 @@ void SCH_CONNECTION::ConfigureFromLabel( const wxString& aLabel )
|
||||
auto member = std::make_shared< SCH_CONNECTION >( m_parent, m_sheet );
|
||||
member->SetPrefix( prefix );
|
||||
member->SetGraph( m_graph );
|
||||
member->ConfigureFromLabel( alias_member );
|
||||
member->ConfigureFromLabel( EscapeString( alias_member, CTX_NETNAME ) );
|
||||
m_members.push_back( member );
|
||||
}
|
||||
}
|
||||
|
||||
+39
-19
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2024 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
|
||||
@@ -51,6 +51,7 @@
|
||||
#include <sch_painter.h>
|
||||
#include <sch_sheet.h>
|
||||
#include <sch_marker.h>
|
||||
#include <sch_sheet_pin.h>
|
||||
#include <schematic.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <advanced_config.h>
|
||||
@@ -133,7 +134,11 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||
wxIcon icon;
|
||||
wxIconBundle icon_bundle;
|
||||
|
||||
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_eeschema ) );
|
||||
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_eeschema, 48 ) );
|
||||
icon_bundle.AddIcon( icon );
|
||||
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_eeschema, 128 ) );
|
||||
icon_bundle.AddIcon( icon );
|
||||
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_eeschema, 256 ) );
|
||||
icon_bundle.AddIcon( icon );
|
||||
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_eeschema_32 ) );
|
||||
icon_bundle.AddIcon( icon );
|
||||
@@ -950,7 +955,6 @@ void SCH_EDIT_FRAME::OnModify()
|
||||
RecalculateConnections( NO_CLEANUP );
|
||||
|
||||
GetCanvas()->Refresh();
|
||||
UpdateHierarchyNavigator();
|
||||
|
||||
if( !GetTitle().StartsWith( wxS( "*" ) ) )
|
||||
updateTitle();
|
||||
@@ -1113,6 +1117,10 @@ void SCH_EDIT_FRAME::OnClearFileHistory( wxCommandEvent& aEvent )
|
||||
|
||||
void SCH_EDIT_FRAME::NewProject()
|
||||
{
|
||||
// Only standalone mode can directly load a new document
|
||||
if( !Kiface().IsSingle() )
|
||||
return;
|
||||
|
||||
wxString pro_dir = m_mruPath;
|
||||
|
||||
wxFileDialog dlg( this, _( "New Schematic" ), pro_dir, wxEmptyString,
|
||||
@@ -1143,6 +1151,10 @@ void SCH_EDIT_FRAME::NewProject()
|
||||
|
||||
void SCH_EDIT_FRAME::LoadProject()
|
||||
{
|
||||
// Only standalone mode can directly load a new document
|
||||
if( !Kiface().IsSingle() )
|
||||
return;
|
||||
|
||||
wxString pro_dir = m_mruPath;
|
||||
wxString wildcards = AllSchematicFilesWildcard()
|
||||
+ wxS( "|" ) + KiCadSchematicFileWildcard()
|
||||
@@ -1503,37 +1515,46 @@ void SCH_EDIT_FRAME::RecalculateConnections( SCH_CLEANUP_FLAGS aCleanupFlags )
|
||||
|
||||
for( unsigned ii = 0; ii < changed_list->GetCount(); ++ii )
|
||||
{
|
||||
EDA_ITEM* item = changed_list->GetPickedItem( ii );
|
||||
SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( changed_list->GetPickedItem( ii ) );
|
||||
|
||||
if( !item || !IsEeschemaType( item->Type() ) )
|
||||
// Ignore non SCH_ITEM objects and objects that are not connectable.
|
||||
if( !item || !item->IsConnectable() )
|
||||
continue;
|
||||
|
||||
SCH_SCREEN* screen = static_cast<SCH_SCREEN*>( changed_list->GetScreenForItem( ii ) );
|
||||
SCH_ITEM* sch_item = static_cast<SCH_ITEM*>( item );
|
||||
SCH_SHEET_PATHS& paths = screen->GetClientSheetPaths();
|
||||
|
||||
std::vector<VECTOR2I> tmp_pts = sch_item->GetConnectionPoints();
|
||||
std::vector<VECTOR2I> tmp_pts = item->GetConnectionPoints();
|
||||
pts.insert( pts.end(), tmp_pts.begin(), tmp_pts.end() );
|
||||
changed_items.insert( sch_item );
|
||||
changed_items.insert( item );
|
||||
|
||||
for( SCH_SHEET_PATH& path : paths )
|
||||
item_paths.insert( std::make_pair( path, sch_item ) );
|
||||
item_paths.insert( std::make_pair( path, item ) );
|
||||
}
|
||||
|
||||
for( VECTOR2I& pt: pts )
|
||||
{
|
||||
for( SCH_ITEM* item : GetScreen()->Items().Overlapping(pt ) )
|
||||
{
|
||||
if( !item->IsConnectable() )
|
||||
continue;
|
||||
|
||||
if( SCH_LINE* line = dyn_cast<SCH_LINE*>( item ) )
|
||||
if( item->Type() == SCH_LINE_T )
|
||||
{
|
||||
if( line->HitTest( pt ) )
|
||||
{
|
||||
if( item->HitTest( pt ) )
|
||||
changed_items.insert( item );
|
||||
}
|
||||
else if( item->Type() == SCH_SHEET_T )
|
||||
{
|
||||
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
|
||||
|
||||
wxCHECK2( sheet, continue );
|
||||
|
||||
std::vector<SCH_SHEET_PIN*> sheetPins = sheet->GetPins();
|
||||
changed_items.insert( sheetPins.begin(), sheetPins.end() );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Non-connectable objects have already been pruned.
|
||||
if( item->IsConnected( pt ) )
|
||||
changed_items.insert( item );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if( SCH_SYMBOL* sym = dyn_cast<SCH_SYMBOL*>( item ) )
|
||||
@@ -1549,8 +1570,7 @@ void SCH_EDIT_FRAME::RecalculateConnections( SCH_CLEANUP_FLAGS aCleanupFlags )
|
||||
}
|
||||
|
||||
std::set<std::pair<SCH_SHEET_PATH, SCH_ITEM*>> all_items =
|
||||
Schematic().ConnectionGraph()->ExtractAffectedItems(
|
||||
changed_items );
|
||||
Schematic().ConnectionGraph()->ExtractAffectedItems( changed_items );
|
||||
|
||||
all_items.insert( item_paths.begin(), item_paths.end() );
|
||||
|
||||
|
||||
@@ -316,3 +316,50 @@ void SCH_ITEM::Plot( PLOTTER* aPlotter, bool aBackground ) const
|
||||
{
|
||||
wxFAIL_MSG( wxT( "Plot() method not implemented for class " ) + GetClass() );
|
||||
}
|
||||
|
||||
|
||||
static bool lessYX( const DANGLING_END_ITEM& a, const DANGLING_END_ITEM& b )
|
||||
{
|
||||
const auto aPos = a.GetPosition();
|
||||
const auto bPos = b.GetPosition();
|
||||
return aPos.y < bPos.y ? true : ( aPos.y > bPos.y ? false : aPos.x < bPos.x );
|
||||
};
|
||||
|
||||
|
||||
static bool lessType( const DANGLING_END_ITEM& a, const DANGLING_END_ITEM& b )
|
||||
{
|
||||
return a.GetType() < b.GetType();
|
||||
};
|
||||
|
||||
|
||||
std::vector<DANGLING_END_ITEM>::iterator
|
||||
DANGLING_END_ITEM_HELPER::get_lower_pos( std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const VECTOR2I& aPos )
|
||||
{
|
||||
DANGLING_END_ITEM needle = DANGLING_END_ITEM( PIN_END, nullptr, aPos );
|
||||
auto start = aItemListByPos.begin();
|
||||
auto end = aItemListByPos.end();
|
||||
return std::lower_bound( start, end, needle, lessYX );
|
||||
}
|
||||
|
||||
|
||||
std::vector<DANGLING_END_ITEM>::iterator
|
||||
DANGLING_END_ITEM_HELPER::get_lower_type( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
const DANGLING_END_T& aType )
|
||||
{
|
||||
DANGLING_END_ITEM needle = DANGLING_END_ITEM( aType, nullptr, VECTOR2I{} );
|
||||
auto start = aItemListByType.begin();
|
||||
auto end = aItemListByType.end();
|
||||
return std::lower_bound( start, end, needle, lessType );
|
||||
}
|
||||
|
||||
|
||||
void DANGLING_END_ITEM_HELPER::sort_dangling_end_items(
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos )
|
||||
{
|
||||
// WIRE_END pairs must be kept together. Hence stable sort.
|
||||
std::stable_sort( aItemListByType.begin(), aItemListByType.end(), lessType );
|
||||
// Sort by y first, pins are more likely to share x than y.
|
||||
std::sort( aItemListByPos.begin(), aItemListByPos.end(), lessYX );
|
||||
}
|
||||
|
||||
+20
-3
@@ -133,6 +133,20 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class DANGLING_END_ITEM_HELPER
|
||||
{
|
||||
public:
|
||||
static std::vector<DANGLING_END_ITEM>::iterator
|
||||
get_lower_pos( std::vector<DANGLING_END_ITEM>& aItemListByPos, const VECTOR2I& aPos );
|
||||
|
||||
static std::vector<DANGLING_END_ITEM>::iterator
|
||||
get_lower_type( std::vector<DANGLING_END_ITEM>& aItemListByType, const DANGLING_END_T& aType );
|
||||
|
||||
/** Both contain the same information */
|
||||
static void sort_dangling_end_items( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos );
|
||||
};
|
||||
|
||||
typedef std::vector<SCH_ITEM*> SCH_ITEM_SET;
|
||||
|
||||
|
||||
@@ -329,12 +343,15 @@ public:
|
||||
* If aSheet is passed a non-null pointer to a SCH_SHEET_PATH, the overridden method can
|
||||
* optionally use it to update sheet-local connectivity information
|
||||
*
|
||||
* @param aItemList is the list of items to test item against.
|
||||
* @param aItemListByType is the list of items to test item against. It's sorted
|
||||
* by item type, keeping WIRE_END pairs together.
|
||||
* @param aItemListByPos is the same list but sorted first by Y then by X.
|
||||
* @param aSheet is the sheet path to update connections for.
|
||||
* @return True if the dangling state has changed from it's current setting.
|
||||
*/
|
||||
virtual bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath = nullptr )
|
||||
virtual bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath = nullptr )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
+58
-27
@@ -868,16 +868,19 @@ bool SCH_LABEL_BASE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy
|
||||
}
|
||||
|
||||
|
||||
bool SCH_LABEL_BASE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
bool SCH_LABEL_BASE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
{
|
||||
bool previousState = m_isDangling;
|
||||
m_isDangling = true;
|
||||
bool previousState = m_isDangling;
|
||||
VECTOR2I text_pos = GetTextPos();
|
||||
m_isDangling = true;
|
||||
m_connectionType = CONNECTION_TYPE::NONE;
|
||||
|
||||
for( unsigned ii = 0; ii < aItemList.size(); ii++ )
|
||||
for( auto it = DANGLING_END_ITEM_HELPER::get_lower_pos( aItemListByPos, text_pos );
|
||||
it < aItemListByPos.end() && it->GetPosition() == text_pos; it++ )
|
||||
{
|
||||
DANGLING_END_ITEM& item = aItemList[ii];
|
||||
DANGLING_END_ITEM& item = *it;
|
||||
|
||||
if( item.GetItem() == this )
|
||||
continue;
|
||||
@@ -888,33 +891,68 @@ bool SCH_LABEL_BASE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemL
|
||||
case LABEL_END:
|
||||
case SHEET_LABEL_END:
|
||||
case NO_CONNECT_END:
|
||||
if( GetTextPos() == item.GetPosition() )
|
||||
if( text_pos == item.GetPosition() )
|
||||
{
|
||||
m_isDangling = false;
|
||||
|
||||
if( aPath && item.GetType() != PIN_END )
|
||||
AddConnectionTo( *aPath, static_cast<SCH_ITEM*>( item.GetItem() ) );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case BUS_END:
|
||||
m_connectionType = CONNECTION_TYPE::BUS;
|
||||
KI_FALLTHROUGH;
|
||||
default: break;
|
||||
}
|
||||
|
||||
case WIRE_END:
|
||||
if( !m_isDangling )
|
||||
break;
|
||||
}
|
||||
|
||||
if( m_isDangling )
|
||||
{
|
||||
for( auto it = DANGLING_END_ITEM_HELPER::get_lower_type( aItemListByType, BUS_END );
|
||||
it < aItemListByType.end() && it->GetType() == BUS_END; it++ )
|
||||
{
|
||||
DANGLING_END_ITEM& nextItem = aItemList[++ii];
|
||||
DANGLING_END_ITEM& item = *it;
|
||||
DANGLING_END_ITEM& nextItem = *( ++it );
|
||||
|
||||
int accuracy = 1; // We have rounding issues with an accuracy of 0
|
||||
int accuracy = 1; // We have rounding issues with an accuracy of 0
|
||||
|
||||
m_isDangling = !TestSegmentHit( GetTextPos(), item.GetPosition(),
|
||||
nextItem.GetPosition(), accuracy );
|
||||
m_isDangling = !TestSegmentHit( text_pos, item.GetPosition(), nextItem.GetPosition(),
|
||||
accuracy );
|
||||
|
||||
if( !m_isDangling )
|
||||
if( m_isDangling )
|
||||
continue;
|
||||
|
||||
m_connectionType = CONNECTION_TYPE::BUS;
|
||||
|
||||
// Add the line to the connected items, since it won't be picked
|
||||
// up by a search of intersecting connection points
|
||||
if( aPath )
|
||||
{
|
||||
if( m_connectionType != CONNECTION_TYPE::BUS )
|
||||
m_connectionType = CONNECTION_TYPE::NET;
|
||||
auto sch_item = static_cast<SCH_ITEM*>( item.GetItem() );
|
||||
AddConnectionTo( *aPath, sch_item );
|
||||
sch_item->AddConnectionTo( *aPath, this );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if( m_isDangling )
|
||||
{
|
||||
for( auto it = DANGLING_END_ITEM_HELPER::get_lower_type( aItemListByType, WIRE_END );
|
||||
it < aItemListByType.end() && it->GetType() == WIRE_END; it++ )
|
||||
{
|
||||
DANGLING_END_ITEM& item = *it;
|
||||
DANGLING_END_ITEM& nextItem = *( ++it );
|
||||
|
||||
int accuracy = 1; // We have rounding issues with an accuracy of 0
|
||||
|
||||
m_isDangling = !TestSegmentHit( text_pos, item.GetPosition(),
|
||||
nextItem.GetPosition(), accuracy );
|
||||
|
||||
if( m_isDangling )
|
||||
continue;
|
||||
|
||||
m_connectionType = CONNECTION_TYPE::NET;
|
||||
|
||||
// Add the line to the connected items, since it won't be picked
|
||||
// up by a search of intersecting connection points
|
||||
@@ -924,16 +962,9 @@ bool SCH_LABEL_BASE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemL
|
||||
AddConnectionTo( *aPath, sch_item );
|
||||
sch_item->AddConnectionTo( *aPath, this );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if( !m_isDangling )
|
||||
break;
|
||||
}
|
||||
|
||||
if( m_isDangling )
|
||||
|
||||
@@ -187,8 +187,9 @@ public:
|
||||
|
||||
void GetEndPoints( std::vector< DANGLING_END_ITEM >& aItemList ) override;
|
||||
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
|
||||
bool IsDangling() const override { return m_isDangling; }
|
||||
void SetIsDangling( bool aIsDangling ) { m_isDangling = aIsDangling; }
|
||||
|
||||
+42
-30
@@ -580,44 +580,56 @@ void SCH_LINE::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
|
||||
}
|
||||
|
||||
|
||||
bool SCH_LINE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
bool SCH_LINE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
{
|
||||
if( IsConnectable() )
|
||||
if( !IsConnectable() )
|
||||
return false;
|
||||
|
||||
bool previousStartState = m_startIsDangling;
|
||||
bool previousEndState = m_endIsDangling;
|
||||
|
||||
m_startIsDangling = m_endIsDangling = true;
|
||||
|
||||
for( auto it = DANGLING_END_ITEM_HELPER::get_lower_pos( aItemListByPos, m_start );
|
||||
it < aItemListByPos.end() && it->GetPosition() == m_start; it++ )
|
||||
{
|
||||
bool previousStartState = m_startIsDangling;
|
||||
bool previousEndState = m_endIsDangling;
|
||||
DANGLING_END_ITEM& item = *it;
|
||||
|
||||
m_startIsDangling = m_endIsDangling = true;
|
||||
if( item.GetItem() == this )
|
||||
continue;
|
||||
|
||||
for( DANGLING_END_ITEM item : aItemList )
|
||||
if( ( IsWire() && item.GetType() != BUS_END && item.GetType() != BUS_ENTRY_END )
|
||||
|| ( IsBus() && item.GetType() != WIRE_END && item.GetType() != PIN_END ) )
|
||||
{
|
||||
if( item.GetItem() == this )
|
||||
continue;
|
||||
|
||||
if( ( IsWire() && item.GetType() != BUS_END && item.GetType() != BUS_ENTRY_END )
|
||||
|| ( IsBus() && item.GetType() != WIRE_END && item.GetType() != PIN_END ) )
|
||||
{
|
||||
if( m_start == item.GetPosition() )
|
||||
m_startIsDangling = false;
|
||||
|
||||
if( m_end == item.GetPosition() )
|
||||
m_endIsDangling = false;
|
||||
|
||||
if( !m_startIsDangling && !m_endIsDangling )
|
||||
break;
|
||||
}
|
||||
m_startIsDangling = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// We only use the bus dangling state for automatic line starting, so we don't care if it
|
||||
// has changed or not (and returning true will result in extra work)
|
||||
if( IsBus() )
|
||||
return false;
|
||||
|
||||
return previousStartState != m_startIsDangling || previousEndState != m_endIsDangling;
|
||||
}
|
||||
|
||||
return false;
|
||||
for( auto it = DANGLING_END_ITEM_HELPER::get_lower_pos( aItemListByPos, m_end );
|
||||
it < aItemListByPos.end() && it->GetPosition() == m_end; it++ )
|
||||
{
|
||||
DANGLING_END_ITEM& item = *it;
|
||||
|
||||
if( item.GetItem() == this )
|
||||
continue;
|
||||
|
||||
if( ( IsWire() && item.GetType() != BUS_END && item.GetType() != BUS_ENTRY_END )
|
||||
|| ( IsBus() && item.GetType() != WIRE_END && item.GetType() != PIN_END ) )
|
||||
{
|
||||
m_endIsDangling = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We only use the bus dangling state for automatic line starting, so we don't care if it
|
||||
// has changed or not (and returning true will result in extra work)
|
||||
if( IsBus() )
|
||||
return false;
|
||||
|
||||
return previousStartState != m_startIsDangling || previousEndState != m_endIsDangling;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+3
-2
@@ -251,8 +251,9 @@ public:
|
||||
|
||||
void GetEndPoints( std::vector<DANGLING_END_ITEM>& aItemList ) override;
|
||||
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
|
||||
bool IsStartDangling() const { return m_startIsDangling; }
|
||||
bool IsEndDangling() const { return m_endIsDangling; }
|
||||
|
||||
@@ -843,12 +843,9 @@ void SCH_PAINTER::draw( const LIB_SHAPE *aShape, int aLayer, bool aDimmed )
|
||||
|
||||
case SHAPE_T::BEZIER:
|
||||
{
|
||||
std::deque<VECTOR2D> mappedPts;
|
||||
|
||||
for( const VECTOR2I& p : shape->GetBezierPoints() )
|
||||
mappedPts.push_back( mapCoords( p ) );
|
||||
|
||||
m_gal->DrawPolygon( mappedPts );
|
||||
m_gal->DrawCurve(
|
||||
mapCoords( shape->GetStart() ), mapCoords( shape->GetBezierC1() ),
|
||||
mapCoords( shape->GetBezierC2() ), mapCoords( shape->GetEnd() ) );
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1851,12 +1848,8 @@ void SCH_PAINTER::draw( const SCH_SHAPE* aShape, int aLayer )
|
||||
|
||||
case SHAPE_T::BEZIER:
|
||||
{
|
||||
std::deque<VECTOR2D> pts;
|
||||
|
||||
for( const VECTOR2I &p : shape->GetPolyShape().Outline( 0 ).CPoints() )
|
||||
pts.push_back( p );
|
||||
|
||||
m_gal->DrawPolygon( pts );
|
||||
m_gal->DrawCurve( shape->GetStart(), shape->GetBezierC1(), shape->GetBezierC2(),
|
||||
shape->GetEnd() );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+10
-1
@@ -193,9 +193,18 @@ SCH_SYMBOL* SCH_PIN::GetParentSymbol() const
|
||||
|
||||
wxString SCH_PIN::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
|
||||
{
|
||||
LIB_PIN::ALT localStorage;
|
||||
LIB_PIN::ALT* alt = nullptr;
|
||||
|
||||
if( !m_alt.IsEmpty() )
|
||||
{
|
||||
localStorage = m_libPin->GetAlt( m_alt );
|
||||
alt = &localStorage;
|
||||
}
|
||||
|
||||
return wxString::Format( "Symbol %s %s",
|
||||
UnescapeString( GetParentSymbol()->GetField( REFERENCE_FIELD )->GetText() ),
|
||||
m_libPin->GetItemDescription( aUnitsProvider ) );
|
||||
m_libPin->GetItemDescription( aUnitsProvider, alt ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -773,7 +773,6 @@ bool SCH_PLOTTER::plotOneSheetHpgl( const wxString& aFileName,
|
||||
plotter->SetPageSettings( aPageInfo );
|
||||
plotter->SetRenderSettings( aRenderSettings );
|
||||
plotter->RenderSettings()->LoadColors( m_colorSettings );
|
||||
plotter->SetColorMode( !aPlotSettings.m_blackAndWhite );
|
||||
plotter->SetViewport( aPlot0ffset, schIUScale.IU_PER_MILS/10, aScale, false );
|
||||
|
||||
// TODO this could be configurable
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
#include <wx/log.h>
|
||||
#include <wx/zstream.h>
|
||||
#include <wx/wfstream.h>
|
||||
#include <wx/dir.h>
|
||||
#include <trigo.h>
|
||||
|
||||
// Harness port object itself does not contain color information about itself
|
||||
@@ -367,6 +368,24 @@ void SCH_ALTIUM_PLUGIN::ParseAltiumSch( const wxString& aFileName )
|
||||
// path as the parent sheet path.
|
||||
wxFileName loadAltiumFileName( parentFileName.GetPath(), sheet->GetFileName() );
|
||||
|
||||
if( !loadAltiumFileName.IsFileReadable() )
|
||||
{
|
||||
// Try case-insensitive search
|
||||
wxArrayString files;
|
||||
wxDir::GetAllFiles( parentFileName.GetPath(), &files, wxEmptyString, wxDIR_FILES | wxDIR_HIDDEN );
|
||||
|
||||
for( const wxString& candidate : files )
|
||||
{
|
||||
wxFileName candidateFname( candidate );
|
||||
|
||||
if( candidateFname.GetFullName().IsSameAs( sheet->GetFileName(), false ) )
|
||||
{
|
||||
loadAltiumFileName = candidateFname;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( loadAltiumFileName.GetFullName().IsEmpty() || !loadAltiumFileName.IsFileReadable() )
|
||||
{
|
||||
wxString msg;
|
||||
@@ -1411,21 +1430,28 @@ void SCH_ALTIUM_PLUGIN::ParsePolyline( const std::map<wxString, wxString>& aProp
|
||||
{
|
||||
ASCH_POLYLINE elem( aProperties );
|
||||
|
||||
if( elem.Points.size() < 2 )
|
||||
return;
|
||||
|
||||
SCH_SCREEN* screen = getCurrentScreen();
|
||||
wxCHECK( screen, /* void */ );
|
||||
|
||||
if( elem.OwnerPartID == ALTIUM_COMPONENT_NONE )
|
||||
{
|
||||
SCH_SHAPE* poly = new SCH_SHAPE( SHAPE_T::POLY );
|
||||
for( size_t i = 1; i < elem.Points.size(); i++ )
|
||||
{
|
||||
SCH_LINE* line = new SCH_LINE;
|
||||
|
||||
for( VECTOR2I& point : elem.Points )
|
||||
poly->AddPoint( point + m_sheetOffset );
|
||||
line->SetStartPoint( elem.Points[i - 1] + m_sheetOffset );
|
||||
line->SetEndPoint( elem.Points[i] + m_sheetOffset );
|
||||
|
||||
poly->SetStroke( STROKE_PARAMS( elem.LineWidth, GetPlotDashType( elem.LineStyle ),
|
||||
GetColorFromInt( elem.Color ) ) );
|
||||
poly->SetFlags( IS_NEW );
|
||||
line->SetStroke( STROKE_PARAMS( elem.LineWidth, GetPlotDashType( elem.LineStyle ),
|
||||
GetColorFromInt( elem.Color ) ) );
|
||||
|
||||
screen->Append( poly );
|
||||
line->SetFlags( IS_NEW );
|
||||
|
||||
screen->Append( line );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2151,10 +2177,10 @@ VECTOR2I HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_
|
||||
LIB_SHAPE* bezier = new LIB_SHAPE( aKsymbol, SHAPE_T::BEZIER );
|
||||
aKsymbol->AddDrawItem( bezier );
|
||||
bezier->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 5 ), PLOT_DASH_TYPE::SOLID ) );
|
||||
bezier->AddPoint( { schIUScale.MilsToIU( 30 ), schIUScale.MilsToIU( -50 ) } );
|
||||
bezier->AddPoint( { schIUScale.MilsToIU( 30 ), schIUScale.MilsToIU( -87 ) } );
|
||||
bezier->AddPoint( { schIUScale.MilsToIU( -30 ), schIUScale.MilsToIU( -63 ) } );
|
||||
bezier->AddPoint( { schIUScale.MilsToIU( -30 ), schIUScale.MilsToIU( -100 ) } );
|
||||
bezier->SetStart( { schIUScale.MilsToIU( 30 ), schIUScale.MilsToIU( -50 ) } );
|
||||
bezier->SetBezierC1( { schIUScale.MilsToIU( 30 ), schIUScale.MilsToIU( -87 ) } );
|
||||
bezier->SetBezierC2( { schIUScale.MilsToIU( -30 ), schIUScale.MilsToIU( -63 ) } );
|
||||
bezier->SetEnd( { schIUScale.MilsToIU( -30 ), schIUScale.MilsToIU( -100 ) } );
|
||||
|
||||
return { 0, schIUScale.MilsToIU( 150 ) };
|
||||
}
|
||||
@@ -2317,10 +2343,17 @@ VECTOR2I HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_
|
||||
void SCH_ALTIUM_PLUGIN::ParsePowerPort( const std::map<wxString, wxString>& aProperties )
|
||||
{
|
||||
ASCH_POWER_PORT elem( aProperties );
|
||||
LIB_ID libId = AltiumToKiCadLibID( getLibName(), elem.text );
|
||||
LIB_SYMBOL* libSymbol = nullptr;
|
||||
|
||||
const auto& powerSymbolIt = m_powerSymbols.find( elem.text );
|
||||
wxString symName( elem.text );
|
||||
wxString styleName = wxString( "Style" ) << static_cast<int>( elem.style );
|
||||
|
||||
if( !styleName.empty() )
|
||||
symName << '_' << styleName;
|
||||
|
||||
LIB_ID libId = AltiumToKiCadLibID( getLibName(), symName );
|
||||
LIB_SYMBOL* libSymbol = nullptr;
|
||||
|
||||
const auto& powerSymbolIt = m_powerSymbols.find( symName );
|
||||
|
||||
if( powerSymbolIt != m_powerSymbols.end() )
|
||||
{
|
||||
@@ -2358,7 +2391,7 @@ void SCH_ALTIUM_PLUGIN::ParsePowerPort( const std::map<wxString, wxString>& aPro
|
||||
|
||||
// this has to be done after parsing the LIB_SYMBOL!
|
||||
m_pi->SaveSymbol( getLibFileName().GetFullPath(), libSymbol, m_properties.get() );
|
||||
m_powerSymbols.insert( { elem.text, libSymbol } );
|
||||
m_powerSymbols.insert( { symName, libSymbol } );
|
||||
}
|
||||
|
||||
SCH_SCREEN* screen = getCurrentScreen();
|
||||
|
||||
@@ -499,8 +499,17 @@ LIB_SYMBOL* SCH_DATABASE_PLUGIN::loadSymbolFromRow( const wxString& aSymbolName,
|
||||
continue;
|
||||
}
|
||||
|
||||
wxString value( std::any_cast<std::string>( aRow.at( mapping.column ) ).c_str(),
|
||||
wxConvUTF8 );
|
||||
std:: string strValue;
|
||||
|
||||
try
|
||||
{
|
||||
strValue = std::any_cast<std::string>( aRow.at( mapping.column ) );
|
||||
}
|
||||
catch( std::bad_any_cast& e )
|
||||
{
|
||||
}
|
||||
|
||||
wxString value( strValue.c_str(), wxConvUTF8 );
|
||||
|
||||
if( mapping.name == wxT( "Value" ) )
|
||||
{
|
||||
|
||||
@@ -1694,6 +1694,8 @@ LIB_TEXTBOX* SCH_SEXPR_PARSER::parseTextBox()
|
||||
FILL_PARAMS fill;
|
||||
std::unique_ptr<LIB_TEXTBOX> textBox = std::make_unique<LIB_TEXTBOX>( nullptr );
|
||||
|
||||
textBox->SetUnit( m_unit );
|
||||
textBox->SetConvert( m_convert );
|
||||
token = NextTok();
|
||||
|
||||
if( token == T_private )
|
||||
@@ -3389,6 +3391,11 @@ SCH_SHAPE* SCH_SEXPR_PARSER::parseSchPolyLine()
|
||||
|
||||
case T_stroke:
|
||||
parseStroke( stroke );
|
||||
|
||||
// In 6.0, the default schematic line style was Dashed.
|
||||
if( m_requiredVersion <= 20211123 && stroke.GetPlotStyle() == PLOT_DASH_TYPE::DEFAULT )
|
||||
stroke.SetPlotStyle( PLOT_DASH_TYPE::DASH );
|
||||
|
||||
polyline->SetStroke( stroke );
|
||||
break;
|
||||
|
||||
|
||||
@@ -550,10 +550,6 @@ void SCH_SEXPR_PLUGIN::Format( EE_SELECTION* aSelection, SCH_SHEET_PATH* aSelect
|
||||
m_out->Print( 0, ")\n\n" );
|
||||
}
|
||||
|
||||
// Store the selected sheets instance information
|
||||
SCH_SHEET_LIST selectedSheets;
|
||||
SCH_REFERENCE_LIST selectedSymbols;
|
||||
|
||||
for( i = 0; i < aSelection->GetSize(); ++i )
|
||||
{
|
||||
item = (SCH_ITEM*) aSelection->GetItem( i );
|
||||
@@ -561,10 +557,8 @@ void SCH_SEXPR_PLUGIN::Format( EE_SELECTION* aSelection, SCH_SHEET_PATH* aSelect
|
||||
switch( item->Type() )
|
||||
{
|
||||
case SCH_SYMBOL_T:
|
||||
saveSymbol( static_cast<SCH_SYMBOL*>( item ), aSchematic, 0, aForClipboard );
|
||||
|
||||
aSelectionPath->AppendSymbol( selectedSymbols, static_cast<SCH_SYMBOL*>( item ),
|
||||
true, true );
|
||||
saveSymbol( static_cast<SCH_SYMBOL*>( item ), aSchematic, 0, aForClipboard,
|
||||
aSelectionPath );
|
||||
break;
|
||||
|
||||
case SCH_BITMAP_T:
|
||||
@@ -573,15 +567,6 @@ void SCH_SEXPR_PLUGIN::Format( EE_SELECTION* aSelection, SCH_SHEET_PATH* aSelect
|
||||
|
||||
case SCH_SHEET_T:
|
||||
saveSheet( static_cast< SCH_SHEET* >( item ), 0 );
|
||||
|
||||
{
|
||||
SCH_SHEET_PATH subSheetPath = *aSelectionPath;
|
||||
subSheetPath.push_back( static_cast<SCH_SHEET*>( item ) );
|
||||
|
||||
fullHierarchy.GetSheetsWithinPath( selectedSheets, subSheetPath );
|
||||
fullHierarchy.GetSymbolsWithinPath( selectedSymbols, subSheetPath, true, true );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SCH_JUNCTION_T:
|
||||
@@ -621,33 +606,12 @@ void SCH_SEXPR_PLUGIN::Format( EE_SELECTION* aSelection, SCH_SHEET_PATH* aSelect
|
||||
wxASSERT( "Unexpected schematic object type in SCH_SEXPR_PLUGIN::Format()" );
|
||||
}
|
||||
}
|
||||
|
||||
// Make all instance information relative to the selection path
|
||||
KIID_PATH selectionPath = aSelectionPath->Path();
|
||||
|
||||
selectedSheets.SortByPageNumbers();
|
||||
std::vector<SCH_SHEET_INSTANCE> sheetinstances = selectedSheets.GetSheetInstances();
|
||||
|
||||
for( SCH_SHEET_INSTANCE& sheetInstance : sheetinstances )
|
||||
{
|
||||
wxASSERT_MSG( sheetInstance.m_Path.MakeRelativeTo( selectionPath ),
|
||||
"Sheet is not inside the selection path?" );
|
||||
}
|
||||
|
||||
selectionPath = aSelectionPath->Path();
|
||||
selectedSymbols.SortByReferenceOnly();
|
||||
std::vector<SCH_SYMBOL_INSTANCE> symbolInstances = selectedSymbols.GetSymbolInstances();
|
||||
|
||||
for( SCH_SYMBOL_INSTANCE& symbolInstance : symbolInstances )
|
||||
{
|
||||
wxASSERT_MSG( symbolInstance.m_Path.MakeRelativeTo( selectionPath ),
|
||||
"Symbol is not inside the selection path?" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SCH_SEXPR_PLUGIN::saveSymbol( SCH_SYMBOL* aSymbol, const SCHEMATIC& aSchematic,
|
||||
int aNestLevel, bool aForClipboard )
|
||||
int aNestLevel, bool aForClipboard,
|
||||
const SCH_SHEET_PATH* aRelativePath )
|
||||
{
|
||||
wxCHECK_RET( aSymbol != nullptr && m_out != nullptr, "" );
|
||||
|
||||
@@ -717,6 +681,14 @@ void SCH_SEXPR_PLUGIN::saveSymbol( SCH_SYMBOL* aSymbol, const SCHEMATIC& aSchema
|
||||
aSymbol->GetUnit() :
|
||||
aSymbol->GetInstanceReferences()[0].m_Unit;
|
||||
|
||||
if( aForClipboard && aRelativePath )
|
||||
{
|
||||
SCH_SYMBOL_INSTANCE unitInstance;
|
||||
|
||||
if( aSymbol->GetInstance( unitInstance, aRelativePath->Path() ) )
|
||||
unit = unitInstance.m_Unit;
|
||||
}
|
||||
|
||||
m_out->Print( 0, " (unit %d)", unit );
|
||||
|
||||
if( aSymbol->GetConvert() == LIB_ITEM::LIB_CONVERT::DEMORGAN )
|
||||
@@ -759,6 +731,14 @@ void SCH_SEXPR_PLUGIN::saveSymbol( SCH_SYMBOL* aSymbol, const SCHEMATIC& aSchema
|
||||
field.SetText( aSymbol->GetField( FOOTPRINT_FIELD )->GetText() );
|
||||
}
|
||||
}
|
||||
else if( aForClipboard && aSymbol->GetInstanceReferences().size() && aRelativePath
|
||||
&& ( id == REFERENCE_FIELD ) )
|
||||
{
|
||||
SCH_SYMBOL_INSTANCE instance;
|
||||
|
||||
if( aSymbol->GetInstance( instance, aRelativePath->Path() ) )
|
||||
field.SetText( instance.m_Reference );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
@@ -805,6 +785,9 @@ void SCH_SEXPR_PLUGIN::saveSymbol( SCH_SYMBOL* aSymbol, const SCHEMATIC& aSchema
|
||||
|
||||
for( size_t i = 0; i < aSymbol->GetInstanceReferences().size(); i++ )
|
||||
{
|
||||
// Zero length KIID_PATH objects are not valid and will cause a crash below.
|
||||
wxCHECK2( aSymbol->GetInstanceReferences()[i].m_Path.size(), continue );
|
||||
|
||||
// If the instance data is part of this design but no longer has an associated sheet
|
||||
// path, don't save it. This prevents large amounts of orphaned instance data for the
|
||||
// current project from accumulating in the schematic files.
|
||||
@@ -839,7 +822,13 @@ void SCH_SEXPR_PLUGIN::saveSymbol( SCH_SYMBOL* aSymbol, const SCHEMATIC& aSchema
|
||||
project_open = true;
|
||||
}
|
||||
|
||||
wxString path = aSymbol->GetInstanceReferences()[i].m_Path.AsString();
|
||||
wxString path;
|
||||
KIID_PATH tmp = aSymbol->GetInstanceReferences()[i].m_Path;
|
||||
|
||||
if( aForClipboard && aRelativePath )
|
||||
tmp.MakeRelativeTo( aRelativePath->Path() );
|
||||
|
||||
path = tmp.AsString();
|
||||
|
||||
m_out->Print( aNestLevel + 3, "(path %s\n",
|
||||
m_out->Quotew( path ).c_str() );
|
||||
|
||||
@@ -146,7 +146,7 @@ private:
|
||||
void loadFile( const wxString& aFileName, SCH_SHEET* aSheet );
|
||||
|
||||
void saveSymbol( SCH_SYMBOL* aSymbol, const SCHEMATIC& aSchematic, int aNestLevel,
|
||||
bool aForClipboard );
|
||||
bool aForClipboard, const SCH_SHEET_PATH* aRelativePath = nullptr );
|
||||
void saveField( SCH_FIELD* aField, int aNestLevel );
|
||||
void saveBitmap( SCH_BITMAP* aBitmap, int aNestLevel );
|
||||
void saveSheet( SCH_SHEET* aSheet, int aNestLevel );
|
||||
|
||||
@@ -95,12 +95,23 @@ void SCH_LEGACY_PLUGIN_CACHE::Load()
|
||||
|
||||
m_versionMajor = parseInt( reader, line, &line );
|
||||
|
||||
if( *line != '.' )
|
||||
SCH_PARSE_ERROR( "invalid file version formatting in header", reader, line );
|
||||
if( *line == '/' )
|
||||
{
|
||||
// Some old libraries use a version syntax like
|
||||
// EESchema-LIBRARY Version 2/10/2006-18:49:15
|
||||
// use 2.3 version numer to read the file
|
||||
m_versionMajor = 2;
|
||||
m_versionMinor = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( *line != '.' )
|
||||
SCH_PARSE_ERROR( "invalid file version formatting in header", reader, line );
|
||||
|
||||
line++;
|
||||
line++;
|
||||
|
||||
m_versionMinor = parseInt( reader, line, &line );
|
||||
m_versionMinor = parseInt( reader, line, &line );
|
||||
}
|
||||
|
||||
if( m_versionMajor < 1 || m_versionMinor < 0 || m_versionMinor > 99 )
|
||||
SCH_PARSE_ERROR( "invalid file version in header", reader, line );
|
||||
@@ -658,7 +669,20 @@ void SCH_LEGACY_PLUGIN_CACHE::loadField( std::unique_ptr<LIB_SYMBOL>& aSymbol,
|
||||
}
|
||||
else
|
||||
{
|
||||
parseQuotedString( field->m_name, aReader, line, &line, true ); // Optional.
|
||||
wxString fieldName = wxEmptyString;
|
||||
parseQuotedString( fieldName, aReader, line, &line, true ); // Optional.
|
||||
|
||||
if( fieldName.IsEmpty() )
|
||||
return;
|
||||
|
||||
wxString candidateFieldName = fieldName;
|
||||
int suffix = 0;
|
||||
|
||||
//Deduplicate field name
|
||||
while( aSymbol->FindField( candidateFieldName ) != nullptr )
|
||||
candidateFieldName = wxString::Format( "%s_%d", fieldName, ++suffix );
|
||||
|
||||
field->m_name = candidateFieldName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -746,6 +770,68 @@ FILL_T SCH_LEGACY_PLUGIN_CACHE::parseFillMode( LINE_READER& aReader, const char*
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function based on version 6.0 is required for reading legacy arcs.
|
||||
* Changing it in any way will likely break arcs.
|
||||
*/
|
||||
static bool MapAnglesV6( int* aAngle1, int* aAngle2 )
|
||||
{
|
||||
auto DECIDEG2RAD = []( double deg ) -> double
|
||||
{
|
||||
return deg * M_PI / 1800.0;
|
||||
};
|
||||
|
||||
int angle, delta;
|
||||
double x, y;
|
||||
bool swap = false;
|
||||
|
||||
delta = *aAngle2 - *aAngle1;
|
||||
|
||||
if( delta >= 1800 )
|
||||
{
|
||||
*aAngle1 -= 1;
|
||||
*aAngle2 += 1;
|
||||
}
|
||||
|
||||
x = cos( DECIDEG2RAD( *aAngle1 ) );
|
||||
y = -sin( DECIDEG2RAD( *aAngle1 ) );
|
||||
*aAngle1 = KiROUND( RAD2DECIDEG( atan2( y, x ) ) );
|
||||
|
||||
x = cos( DECIDEG2RAD( *aAngle2 ) );
|
||||
y = -sin( DECIDEG2RAD( *aAngle2 ) );
|
||||
*aAngle2 = KiROUND( RAD2DECIDEG( atan2( y, x ) ) );
|
||||
|
||||
NORMALIZE_ANGLE_POS( *aAngle1 );
|
||||
NORMALIZE_ANGLE_POS( *aAngle2 );
|
||||
|
||||
if( *aAngle2 < *aAngle1 )
|
||||
*aAngle2 += 3600;
|
||||
|
||||
if( *aAngle2 - *aAngle1 > 1800 ) // Need to swap the two angles
|
||||
{
|
||||
angle = ( *aAngle1 );
|
||||
*aAngle1 = ( *aAngle2 );
|
||||
*aAngle2 = angle;
|
||||
|
||||
NORMALIZE_ANGLE_POS( *aAngle1 );
|
||||
NORMALIZE_ANGLE_POS( *aAngle2 );
|
||||
|
||||
if( *aAngle2 < *aAngle1 )
|
||||
*aAngle2 += 3600;
|
||||
|
||||
swap = true;
|
||||
}
|
||||
|
||||
if( delta >= 1800 )
|
||||
{
|
||||
*aAngle1 += 1;
|
||||
*aAngle2 -= 1;
|
||||
}
|
||||
|
||||
return swap;
|
||||
}
|
||||
|
||||
|
||||
LIB_SHAPE* SCH_LEGACY_PLUGIN_CACHE::loadArc( std::unique_ptr<LIB_SYMBOL>& aSymbol,
|
||||
LINE_READER& aReader )
|
||||
{
|
||||
@@ -762,10 +848,12 @@ LIB_SHAPE* SCH_LEGACY_PLUGIN_CACHE::loadArc( std::unique_ptr<LIB_SYMBOL>& aSymbo
|
||||
|
||||
arc->SetPosition( center );
|
||||
|
||||
(void) schIUScale.MilsToIU( parseInt( aReader, line, &line ) );
|
||||
int radius = schIUScale.MilsToIU( parseInt( aReader, line, &line ) );
|
||||
int angle1 = parseInt( aReader, line, &line );
|
||||
int angle2 = parseInt( aReader, line, &line );
|
||||
|
||||
EDA_ANGLE angle1( parseInt( aReader, line, &line ), TENTHS_OF_A_DEGREE_T );
|
||||
EDA_ANGLE angle2( parseInt( aReader, line, &line ), TENTHS_OF_A_DEGREE_T );
|
||||
NORMALIZE_ANGLE_POS( angle1 );
|
||||
NORMALIZE_ANGLE_POS( angle2 );
|
||||
|
||||
arc->SetUnit( parseInt( aReader, line, &line ) );
|
||||
arc->SetConvert( parseInt( aReader, line, &line ) );
|
||||
@@ -792,38 +880,33 @@ LIB_SHAPE* SCH_LEGACY_PLUGIN_CACHE::loadArc( std::unique_ptr<LIB_SYMBOL>& aSymbo
|
||||
arc->SetStart( arcStart );
|
||||
arc->SetEnd( arcEnd );
|
||||
}
|
||||
// Actual Coordinates of arc ends are not read from file (old library), calculate them
|
||||
else
|
||||
{
|
||||
arc->SetArcAngleAndEnd( angle2 - angle1, true );
|
||||
// Actual Coordinates of arc ends are not read from file
|
||||
// (old library), calculate them
|
||||
VECTOR2I arcStart( radius, 0 );
|
||||
VECTOR2I arcEnd( radius, 0 );
|
||||
|
||||
RotatePoint( arcStart, EDA_ANGLE( -angle1, EDA_ANGLE_T::TENTHS_OF_A_DEGREE_T ) );
|
||||
arcStart += arc->GetCenter();
|
||||
arc->SetStart( arcStart );
|
||||
RotatePoint( arcEnd, EDA_ANGLE( -angle2, EDA_ANGLE_T::TENTHS_OF_A_DEGREE_T ) );
|
||||
arcEnd += arc->GetCenter();
|
||||
arc->SetEnd( arcEnd );
|
||||
}
|
||||
|
||||
/*
|
||||
* Current file format stores start-mid-end and so doesn't care about winding. We
|
||||
* store start-end with an implied winding internally though.
|
||||
* This issue is only for 180 deg arcs, because 180 deg are a limit to handle arcs in
|
||||
* legacy libs.
|
||||
*
|
||||
* So a workaround is to slightly change the arc angle to
|
||||
* avoid 180 deg arc after correction
|
||||
/**
|
||||
* 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
|
||||
* counter-clockwise. The new GAL draw takes center, radius and start/end angles. All of
|
||||
* these points were stored in the file, so we need to mimic the swapping of start/end
|
||||
* points rather than using the stored angles in order to properly map edge cases.
|
||||
*/
|
||||
EDA_ANGLE arc_angle = arc->GetArcAngle();
|
||||
|
||||
if( arc_angle == ANGLE_180 )
|
||||
if( !MapAnglesV6( &angle1, &angle2 ) )
|
||||
{
|
||||
VECTOR2I new_center = CalcArcCenter( arc->GetStart(), arc->GetEnd(),
|
||||
EDA_ANGLE( 179.5, DEGREES_T ) );
|
||||
arc->SetCenter( new_center );
|
||||
}
|
||||
|
||||
// In legacy libraries, an arc angle is always <= 180.0 degrees
|
||||
// So if the created arc is > 180 degrees, swap arc ends to have a < 180 deg arc.
|
||||
if( arc->GetArcAngle() > ANGLE_180 )
|
||||
{
|
||||
VECTOR2I new_end = arc->GetStart();
|
||||
VECTOR2I new_start = arc->GetEnd();
|
||||
arc->SetStart( new_start );
|
||||
arc->SetEnd( new_end );
|
||||
VECTOR2I temp = arc->GetStart();
|
||||
arc->SetStart( arc->GetEnd() );
|
||||
arc->SetEnd( temp );
|
||||
}
|
||||
|
||||
return arc;
|
||||
|
||||
@@ -802,6 +802,10 @@ SCH_LINE* SCH_LEGACY_PLUGIN::loadWire( LINE_READER& aReader )
|
||||
if( !strCompare( "Line", line, &line ) )
|
||||
SCH_PARSE_ERROR( "invalid wire definition", aReader, line );
|
||||
|
||||
// The default graphical line style was Dashed.
|
||||
if( wire->GetLayer() == LAYER_NOTES )
|
||||
wire->SetLineStyle( PLOT_DASH_TYPE::DASH );
|
||||
|
||||
// Since Sept 15, 2017, a line style is alloved (width, style, color)
|
||||
// Only non default values are stored
|
||||
while( !is_eol( *line ) )
|
||||
|
||||
+138
-10
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2024 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
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <project.h>
|
||||
#include <reporter.h>
|
||||
#include <sch_draw_panel.h>
|
||||
#include <trace_helpers.h>
|
||||
#include <sch_edit_frame.h>
|
||||
#include <sch_item.h>
|
||||
|
||||
@@ -1029,7 +1030,8 @@ void SCH_SCREEN::UpdateSymbolLinks( REPORTER* aReporter )
|
||||
}
|
||||
}
|
||||
|
||||
symbol->SetLibSymbol( libSymbol.release() );
|
||||
if( libSymbol.get() ) // Only change the old link if the new link exists
|
||||
symbol->SetLibSymbol( libSymbol.release() );
|
||||
}
|
||||
|
||||
// Changing the symbol may adjust the bbox of the symbol. This re-inserts the
|
||||
@@ -1368,36 +1370,46 @@ void SCH_SCREEN::TestDanglingEnds( const SCH_SHEET_PATH* aPath,
|
||||
{
|
||||
PROF_TIMER timer( __FUNCTION__ );
|
||||
|
||||
std::vector<DANGLING_END_ITEM> endPoints;
|
||||
std::vector<DANGLING_END_ITEM> endPointsByPos;
|
||||
std::vector<DANGLING_END_ITEM> endPointsByType;
|
||||
|
||||
auto getends =
|
||||
auto get_ends =
|
||||
[&]( SCH_ITEM* item )
|
||||
{
|
||||
if( item->IsConnectable() )
|
||||
item->GetEndPoints( endPoints );
|
||||
item->GetEndPoints( endPointsByType );
|
||||
};
|
||||
|
||||
auto update_state =
|
||||
[&]( SCH_ITEM* item )
|
||||
{
|
||||
if( item->UpdateDanglingState( endPoints, aPath ) )
|
||||
if( item->UpdateDanglingState( endPointsByType, endPointsByPos, aPath ) )
|
||||
{
|
||||
if( aChangedHandler )
|
||||
(*aChangedHandler)( item );
|
||||
( *aChangedHandler )( item );
|
||||
}
|
||||
};
|
||||
|
||||
for( SCH_ITEM* item : Items() )
|
||||
{
|
||||
|
||||
getends( item );
|
||||
item->RunOnChildren( getends );
|
||||
get_ends( item );
|
||||
item->RunOnChildren( get_ends );
|
||||
}
|
||||
|
||||
PROF_TIMER sortTimer( "SCH_SCREEN::TestDanglingEnds pre-sort" );
|
||||
endPointsByPos = endPointsByType;
|
||||
DANGLING_END_ITEM_HELPER::sort_dangling_end_items( endPointsByType, endPointsByPos );
|
||||
sortTimer.Stop();
|
||||
|
||||
if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
|
||||
sortTimer.Show();
|
||||
|
||||
for( SCH_ITEM* item : Items() )
|
||||
{
|
||||
update_state( item );
|
||||
item->RunOnChildren( update_state );
|
||||
}
|
||||
|
||||
if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
|
||||
timer.Show();
|
||||
}
|
||||
@@ -1626,6 +1638,100 @@ size_t SCH_SCREEN::getLibSymbolNameMatches( const SCH_SYMBOL& aSymbol,
|
||||
}
|
||||
|
||||
|
||||
void SCH_SCREEN::PruneOrphanedSymbolInstances( const wxString& aProjectName,
|
||||
const SCH_SHEET_LIST& aValidSheetPaths )
|
||||
{
|
||||
// The project name cannot be empty. Projects older than 7.0 did not save project names
|
||||
// when saving instance data. Running this algorithm with an empty project name would
|
||||
// clobber all instance data for projects other than the current one when a schematic
|
||||
// file is shared across multiple projects. Because running the schematic editor in
|
||||
// stand alone mode can result in an empty project name, do not assert here.
|
||||
if( aProjectName.IsEmpty() )
|
||||
return;
|
||||
|
||||
for( SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
|
||||
{
|
||||
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
|
||||
|
||||
wxCHECK2( symbol, continue );
|
||||
|
||||
std::set<KIID_PATH> pathsToPrune;
|
||||
const std::vector<SCH_SYMBOL_INSTANCE> instances = symbol->GetInstanceReferences();
|
||||
|
||||
for( const SCH_SYMBOL_INSTANCE& instance : instances )
|
||||
{
|
||||
// Ignore instance paths from other projects.
|
||||
if( aProjectName != instance.m_ProjectName )
|
||||
continue;
|
||||
|
||||
std::optional<SCH_SHEET_PATH> pathFound =
|
||||
aValidSheetPaths.GetSheetPathByKIIDPath( instance.m_Path );
|
||||
|
||||
// Check for paths that do not exist in the current project and paths that do
|
||||
// not contain the current symbol.
|
||||
if( !pathFound )
|
||||
pathsToPrune.emplace( instance.m_Path );
|
||||
else if( pathFound.value().LastScreen() != this )
|
||||
pathsToPrune.emplace( pathFound.value().Path() );
|
||||
}
|
||||
|
||||
for( const KIID_PATH& sheetPath : pathsToPrune )
|
||||
{
|
||||
wxLogTrace( traceSchSheetPaths, wxS( "Pruning project '%s' symbol instance %s." ),
|
||||
aProjectName, sheetPath.AsString() );
|
||||
symbol->RemoveInstance( sheetPath );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SCH_SCREEN::PruneOrphanedSheetInstances( const wxString& aProjectName,
|
||||
const SCH_SHEET_LIST& aValidSheetPaths )
|
||||
{
|
||||
// The project name cannot be empty. Projects older than 7.0 did not save project names
|
||||
// when saving instance data. Running this algorithm with an empty project name would
|
||||
// clobber all instance data for projects other than the current one when a schematic
|
||||
// file is shared across multiple projects. Because running the schematic editor in
|
||||
// stand alone mode can result in an empty project name, do not assert here.
|
||||
if( aProjectName.IsEmpty() )
|
||||
return;
|
||||
|
||||
for( SCH_ITEM* item : Items().OfType( SCH_SHEET_T ) )
|
||||
{
|
||||
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
|
||||
|
||||
wxCHECK2( sheet, continue );
|
||||
|
||||
std::set<KIID_PATH> pathsToPrune;
|
||||
const std::vector<SCH_SHEET_INSTANCE> instances = sheet->GetInstances();
|
||||
|
||||
for( const SCH_SHEET_INSTANCE& instance : instances )
|
||||
{
|
||||
// Ignore instance paths from other projects.
|
||||
if( aProjectName != instance.m_ProjectName )
|
||||
continue;
|
||||
|
||||
std::optional<SCH_SHEET_PATH> pathFound =
|
||||
aValidSheetPaths.GetSheetPathByKIIDPath( instance.m_Path );
|
||||
|
||||
// Check for paths that do not exist in the current project and paths that do
|
||||
// not contain the current symbol.
|
||||
if( !pathFound )
|
||||
pathsToPrune.emplace( instance.m_Path );
|
||||
else if( pathFound.value().LastScreen() != this )
|
||||
pathsToPrune.emplace( pathFound.value().Path() );
|
||||
}
|
||||
|
||||
for( const KIID_PATH& sheetPath : pathsToPrune )
|
||||
{
|
||||
wxLogTrace( traceSchSheetPaths, wxS( "Pruning project '%s' sheet instance %s." ),
|
||||
aProjectName, sheetPath.AsString() );
|
||||
sheet->RemoveInstance( sheetPath );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined(DEBUG)
|
||||
void SCH_SCREEN::Show( int nestLevel, std::ostream& os ) const
|
||||
{
|
||||
@@ -2042,3 +2148,25 @@ void SCH_SCREEN::MigrateSimModels()
|
||||
SIM_MODEL::MigrateSimModel<SCH_SYMBOL, SCH_FIELD>( *symbol, &Schematic()->Prj() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SCH_SCREENS::PruneOrphanedSymbolInstances( const wxString& aProjectName,
|
||||
const SCH_SHEET_LIST& aValidSheetPaths )
|
||||
{
|
||||
if( aProjectName.IsEmpty() )
|
||||
return;
|
||||
|
||||
for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
|
||||
screen->PruneOrphanedSymbolInstances( aProjectName, aValidSheetPaths );
|
||||
}
|
||||
|
||||
|
||||
void SCH_SCREENS::PruneOrphanedSheetInstances( const wxString& aProjectName,
|
||||
const SCH_SHEET_LIST& aValidSheetPaths )
|
||||
{
|
||||
if( aProjectName.IsEmpty() )
|
||||
return;
|
||||
|
||||
for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
|
||||
screen->PruneOrphanedSheetInstances( aProjectName, aValidSheetPaths );
|
||||
}
|
||||
|
||||
+41
-4
@@ -545,6 +545,36 @@ public:
|
||||
*/
|
||||
void MigrateSimModels();
|
||||
|
||||
/**
|
||||
* Remove all invalid symbol instance data in this screen object for the project defined
|
||||
* by \a aProjectName and the list of \a aValidSheetPaths.
|
||||
*
|
||||
* @warning This method will assert and exit on debug builds when \a aProjectName is empty.
|
||||
*
|
||||
* @note This method does not affect instance data for any other projects.
|
||||
*
|
||||
* @param aProjectName is the name of the current project.
|
||||
* @param aValidSheetPaths is the list of valid #SCH_SHEET_PATH objects for the current
|
||||
* project.
|
||||
*/
|
||||
void PruneOrphanedSymbolInstances( const wxString& aProjectName,
|
||||
const SCH_SHEET_LIST& aValidSheetPaths );
|
||||
|
||||
/**
|
||||
* Remove all invalid sheet instance data in this screen object for the project defined
|
||||
* by \a aProjectName and the list of \a aValidSheetPaths.
|
||||
*
|
||||
* @warning This method will assert and exit on debug builds when \a aProjectName is empty.
|
||||
*
|
||||
* @note This method does not affect instance data for any other projects.
|
||||
*
|
||||
* @param aProjectName is the name of the current project.
|
||||
* @param aValidSheetPaths is the list of valid #SCH_SHEET_PATH objects for the current
|
||||
* project.
|
||||
*/
|
||||
void PruneOrphanedSheetInstances( const wxString& aProjectName,
|
||||
const SCH_SHEET_LIST& aValidSheetPaths );
|
||||
|
||||
private:
|
||||
friend SCH_EDIT_FRAME; // Only to populate m_symbolInstances.
|
||||
friend SCH_SEXPR_PARSER; // Only to load instance information from schematic file.
|
||||
@@ -572,12 +602,13 @@ private:
|
||||
size_t getLibSymbolNameMatches( const SCH_SYMBOL& aSymbol, std::vector<wxString>& aMatches );
|
||||
|
||||
|
||||
/**
|
||||
* Compare two #BUS_ALIAS objects by name. For sorting in the set.
|
||||
*/
|
||||
/**
|
||||
* Compare two #BUS_ALIAS objects by name. For sorting in the set.
|
||||
*/
|
||||
struct BusAliasCmp
|
||||
{
|
||||
bool operator()( const std::shared_ptr<BUS_ALIAS>& a, const std::shared_ptr<BUS_ALIAS>& b ) const
|
||||
bool operator()( const std::shared_ptr<BUS_ALIAS>& a,
|
||||
const std::shared_ptr<BUS_ALIAS>& b ) const
|
||||
{
|
||||
return a->GetName() < b->GetName();
|
||||
}
|
||||
@@ -793,6 +824,12 @@ public:
|
||||
*/
|
||||
void SetLegacySymbolInstanceData();
|
||||
|
||||
void PruneOrphanedSymbolInstances( const wxString& aProjectName,
|
||||
const SCH_SHEET_LIST& aValidSheetPaths );
|
||||
|
||||
void PruneOrphanedSheetInstances( const wxString& aProjectName,
|
||||
const SCH_SHEET_LIST& aValidSheetPaths );
|
||||
|
||||
private:
|
||||
void addScreenToList( SCH_SCREEN* aScreen, SCH_SHEET* aSheet );
|
||||
void buildScreenList( SCH_SHEET* aSheet);
|
||||
|
||||
@@ -128,7 +128,7 @@ void SCH_SHAPE::Plot( PLOTTER* aPlotter, bool aBackground ) const
|
||||
if( !aPlotter->GetColorMode() )
|
||||
return;
|
||||
|
||||
if( m_fill == FILL_T::FILLED_WITH_COLOR && GetFillColor() != COLOR4D::UNSPECIFIED )
|
||||
if( IsFilled() )
|
||||
{
|
||||
if( GetFillColor() != COLOR4D::UNSPECIFIED )
|
||||
aPlotter->SetColor( GetFillColor() );
|
||||
|
||||
+37
-3
@@ -984,13 +984,14 @@ void SCH_SHEET::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SHEET::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
bool SCH_SHEET::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
for( SCH_SHEET_PIN* sheetPin : m_pins )
|
||||
changed |= sheetPin->UpdateDanglingState( aItemList );
|
||||
changed |= sheetPin->UpdateDanglingState( aItemListByType, aItemListByPos );
|
||||
|
||||
return changed;
|
||||
}
|
||||
@@ -1222,6 +1223,39 @@ bool SCH_SHEET::operator <( const SCH_ITEM& aItem ) const
|
||||
}
|
||||
|
||||
|
||||
void SCH_SHEET::RemoveInstance( const KIID_PATH& aInstancePath )
|
||||
{
|
||||
// Search for an existing path and remove it if found (should not occur)
|
||||
for( unsigned ii = 0; ii < m_instances.size(); ii++ )
|
||||
{
|
||||
if( m_instances[ii].m_Path == aInstancePath )
|
||||
{
|
||||
wxLogTrace( traceSchSheetPaths, "Removing sheet instance:\n"
|
||||
" sheet path %s\n"
|
||||
" page %s, from project %s.",
|
||||
aInstancePath.AsString(),
|
||||
m_instances[ii].m_PageNumber,
|
||||
m_instances[ii].m_ProjectName );
|
||||
|
||||
m_instances.erase( m_instances.begin() + ii );
|
||||
ii--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SCH_SHEET::AddInstance( const SCH_SHEET_INSTANCE& aInstance )
|
||||
{
|
||||
SCH_SHEET_INSTANCE oldInstance;
|
||||
|
||||
if( getInstance( oldInstance, aInstance.m_Path ) )
|
||||
RemoveInstance( aInstance.m_Path );
|
||||
|
||||
m_instances.emplace_back( aInstance );
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SHEET::addInstance( const SCH_SHEET_PATH& aSheetPath )
|
||||
{
|
||||
wxCHECK( aSheetPath.IsFullPath(), false );
|
||||
|
||||
@@ -343,8 +343,9 @@ public:
|
||||
|
||||
void GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList ) override;
|
||||
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
|
||||
bool IsConnectable() const override { return true; }
|
||||
|
||||
@@ -409,6 +410,10 @@ public:
|
||||
*/
|
||||
const SCH_SHEET_INSTANCE& GetRootInstance() const;
|
||||
|
||||
void RemoveInstance( const KIID_PATH& aInstancePath );
|
||||
|
||||
void AddInstance( const SCH_SHEET_INSTANCE& aInstance );
|
||||
|
||||
/**
|
||||
* Compares page numbers of schematic sheets.
|
||||
*
|
||||
|
||||
@@ -698,6 +698,11 @@ void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet, bool aCheckIntegrity )
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we are not performing a full recursion test, at least check if we are in
|
||||
// a simple recursion scenario to prevent stack overflow crashes
|
||||
wxCHECK2_MSG( sheet->GetFileName() != aSheet->GetFileName(), continue,
|
||||
wxT( "Recursion prevented in SCH_SHEET_LIST::BuildSheetList" ) );
|
||||
|
||||
BuildSheetList( sheet, false );
|
||||
}
|
||||
}
|
||||
@@ -1313,3 +1318,18 @@ bool SCH_SHEET_LIST::HasPath( const KIID_PATH& aPath ) const
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SHEET_LIST::ContainsSheet( const SCH_SHEET* aSheet ) const
|
||||
{
|
||||
for( const SCH_SHEET_PATH& path : *this )
|
||||
{
|
||||
for( size_t i = 0; i < path.size(); i++ )
|
||||
{
|
||||
if( path.at( i ) == aSheet )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -674,6 +674,8 @@ public:
|
||||
|
||||
bool HasPath( const KIID_PATH& aPath ) const;
|
||||
|
||||
bool ContainsSheet( const SCH_SHEET* aSheet ) const;
|
||||
|
||||
private:
|
||||
SCH_SHEET_PATH m_currentSheetPath;
|
||||
};
|
||||
|
||||
+45
-21
@@ -547,6 +547,17 @@ void SCH_SYMBOL::Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffse
|
||||
tempPin->SetShape( symbolPin->GetShape() );
|
||||
}
|
||||
|
||||
for( LIB_ITEM& item : tempSymbol.GetDrawItems() )
|
||||
{
|
||||
if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( &item ) )
|
||||
{
|
||||
// Use SCH_FIELD's text resolver
|
||||
SCH_FIELD dummy( (SCH_ITEM*) this, -1 );
|
||||
dummy.SetText( text->GetText() );
|
||||
text->SetText( dummy.GetShownText( false ) );
|
||||
}
|
||||
}
|
||||
|
||||
tempSymbol.Print( aSettings, m_pos + aOffset, m_unit, m_convert, opts, GetDNP() );
|
||||
}
|
||||
else // Use dummy() part if the actual cannot be found.
|
||||
@@ -600,16 +611,22 @@ bool SCH_SYMBOL::GetInstance( SCH_SYMBOL_INSTANCE& aInstance,
|
||||
|
||||
|
||||
void SCH_SYMBOL::RemoveInstance( const SCH_SHEET_PATH& aInstancePath )
|
||||
{
|
||||
RemoveInstance( aInstancePath.Path() );
|
||||
}
|
||||
|
||||
|
||||
void SCH_SYMBOL::RemoveInstance( const KIID_PATH& aInstancePath )
|
||||
{
|
||||
// Search for an existing path and remove it if found (should not occur)
|
||||
for( unsigned ii = 0; ii < m_instanceReferences.size(); ii++ )
|
||||
{
|
||||
if( m_instanceReferences[ii].m_Path == aInstancePath.Path() )
|
||||
if( m_instanceReferences[ii].m_Path == aInstancePath )
|
||||
{
|
||||
wxLogTrace( traceSchSheetPaths, "Removing symbol instance:\n"
|
||||
" sheet path %s\n"
|
||||
" reference %s, unit %d from symbol %s.",
|
||||
aInstancePath.Path().AsString(),
|
||||
aInstancePath.AsString(),
|
||||
m_instanceReferences[ii].m_Reference,
|
||||
m_instanceReferences[ii].m_Unit,
|
||||
m_Uuid.AsString() );
|
||||
@@ -624,7 +641,8 @@ void SCH_SYMBOL::RemoveInstance( const SCH_SHEET_PATH& aInstancePath )
|
||||
void SCH_SYMBOL::SortInstances( bool (*aSortFunction)( const SCH_SYMBOL_INSTANCE& aLhs,
|
||||
const SCH_SYMBOL_INSTANCE& aRhs ) )
|
||||
{
|
||||
std::sort( m_instanceReferences.begin(), m_instanceReferences.end(), aSortFunction );
|
||||
if( m_instanceReferences.size() > 1 )
|
||||
std::sort( m_instanceReferences.begin(), m_instanceReferences.end(), aSortFunction );
|
||||
}
|
||||
|
||||
|
||||
@@ -1146,8 +1164,11 @@ std::vector<SCH_PIN*> SCH_SYMBOL::GetPins( const SCH_SHEET_PATH* aSheet ) const
|
||||
|
||||
for( const std::unique_ptr<SCH_PIN>& p : m_pins )
|
||||
{
|
||||
if( unit && p->GetLibPin()->GetUnit() && ( p->GetLibPin()->GetUnit() != unit ) )
|
||||
if( unit && p->GetLibPin() && p->GetLibPin()->GetUnit()
|
||||
&& ( p->GetLibPin()->GetUnit() != unit ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
pins.push_back( p.get() );
|
||||
}
|
||||
@@ -1924,7 +1945,7 @@ void SCH_SYMBOL::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
|
||||
{
|
||||
LIB_PIN* lib_pin = pin->GetLibPin();
|
||||
|
||||
if( lib_pin->GetUnit() && m_unit && ( m_unit != lib_pin->GetUnit() ) )
|
||||
if( lib_pin && lib_pin->GetUnit() && m_unit && ( m_unit != lib_pin->GetUnit() ) )
|
||||
continue;
|
||||
|
||||
DANGLING_END_ITEM item( PIN_END, lib_pin, GetPinPhysicalPosition( lib_pin ), this );
|
||||
@@ -1933,8 +1954,9 @@ void SCH_SYMBOL::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SYMBOL::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
bool SCH_SYMBOL::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
@@ -1945,8 +1967,12 @@ bool SCH_SYMBOL::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
|
||||
VECTOR2I pos = m_transform.TransformCoordinate( pin->GetLocalPosition() ) + m_pos;
|
||||
|
||||
for( DANGLING_END_ITEM& each_item : aItemList )
|
||||
auto lower = DANGLING_END_ITEM_HELPER::get_lower_pos( aItemListByPos, pos );
|
||||
bool do_break = false;
|
||||
|
||||
for( auto it = lower; it < aItemListByPos.end() && it->GetPosition() == pos; it++ )
|
||||
{
|
||||
DANGLING_END_ITEM& each_item = *it;
|
||||
// Some people like to stack pins on top of each other in a symbol to indicate
|
||||
// internal connection. While technically connected, it is not particularly useful
|
||||
// to display them that way, so skip any pins that are in the same symbol as this
|
||||
@@ -1962,17 +1988,15 @@ bool SCH_SYMBOL::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
case WIRE_END:
|
||||
case NO_CONNECT_END:
|
||||
case JUNCTION_END:
|
||||
|
||||
if( pos == each_item.GetPosition() )
|
||||
pin->SetIsDangling( false );
|
||||
|
||||
pin->SetIsDangling( false );
|
||||
do_break = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if( !pin->IsDangling() )
|
||||
if( do_break )
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2000,8 +2024,8 @@ std::vector<VECTOR2I> SCH_SYMBOL::GetConnectionPoints() const
|
||||
{
|
||||
// Collect only pins attached to the current unit and convert.
|
||||
// others are not associated to this symbol instance
|
||||
int pin_unit = pin->GetLibPin()->GetUnit();
|
||||
int pin_convert = pin->GetLibPin()->GetConvert();
|
||||
int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit() : GetUnit();
|
||||
int pin_convert = pin->GetLibPin() ? pin->GetLibPin()->GetConvert() : GetConvert();
|
||||
|
||||
if( pin_unit > 0 && pin_unit != GetUnit() )
|
||||
continue;
|
||||
@@ -2091,8 +2115,8 @@ INSPECT_RESULT SCH_SYMBOL::Visit( INSPECTOR aInspector, void* aTestData,
|
||||
{
|
||||
// Collect only pins attached to the current unit and convert.
|
||||
// others are not associated to this symbol instance
|
||||
int pin_unit = pin->GetLibPin()->GetUnit();
|
||||
int pin_convert = pin->GetLibPin()->GetConvert();
|
||||
int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit() : GetUnit();
|
||||
int pin_convert = pin->GetLibPin() ? pin->GetLibPin()->GetConvert() : GetConvert();
|
||||
|
||||
if( pin_unit > 0 && pin_unit != GetUnit() )
|
||||
continue;
|
||||
@@ -2229,8 +2253,8 @@ bool SCH_SYMBOL::doIsConnected( const VECTOR2I& aPosition ) const
|
||||
|
||||
// Collect only pins attached to the current unit and convert.
|
||||
// others are not associated to this symbol instance
|
||||
int pin_unit = pin->GetLibPin()->GetUnit();
|
||||
int pin_convert = pin->GetLibPin()->GetConvert();
|
||||
int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit() : GetUnit();
|
||||
int pin_convert = pin->GetLibPin() ? pin->GetLibPin()->GetConvert() : GetConvert();
|
||||
|
||||
if( pin_unit > 0 && pin_unit != GetUnit() )
|
||||
continue;
|
||||
@@ -2412,8 +2436,8 @@ bool SCH_SYMBOL::IsPointClickableAnchor( const VECTOR2I& aPos ) const
|
||||
{
|
||||
for( const std::unique_ptr<SCH_PIN>& pin : m_pins )
|
||||
{
|
||||
int pin_unit = pin->GetLibPin()->GetUnit();
|
||||
int pin_convert = pin->GetLibPin()->GetConvert();
|
||||
int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit() : GetUnit();
|
||||
int pin_convert = pin->GetLibPin() ? pin->GetLibPin()->GetConvert() : GetConvert();
|
||||
|
||||
if( pin_unit > 0 && pin_unit != GetUnit() )
|
||||
continue;
|
||||
|
||||
@@ -146,6 +146,7 @@ public:
|
||||
const KIID_PATH& aSheetPath, bool aTestFromEnd = false ) const;
|
||||
|
||||
void RemoveInstance( const SCH_SHEET_PATH& aInstancePath );
|
||||
void RemoveInstance( const KIID_PATH& aInstancePath );
|
||||
|
||||
void RemoveAllInstances() { m_instanceReferences.clear(); }
|
||||
|
||||
@@ -661,8 +662,9 @@ public:
|
||||
* @param aItemList is list of all #DANGLING_END_ITEM items to be tested.
|
||||
* @return true if any pin's state has changed.
|
||||
*/
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
|
||||
VECTOR2I GetPinPhysicalPosition( const LIB_PIN* Pin ) const;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
|
||||
* Copyright (C) 2004-2022 KiCad Developers, see change_log.txt for contributors.
|
||||
* Copyright (C) 2004-2024 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
|
||||
@@ -392,10 +392,17 @@ void SCH_EDIT_FRAME::RollbackSchematicFromUndo()
|
||||
{
|
||||
delete aItem;
|
||||
} );
|
||||
|
||||
// Only rebuild the hierarchy navigator if there are sheet changes.
|
||||
bool hasSheets = undo->ContainsItemType( SCH_SHEET_T );
|
||||
|
||||
delete undo;
|
||||
|
||||
SetSheetNumberAndCount();
|
||||
UpdateHierarchyNavigator();
|
||||
if( hasSheets )
|
||||
{
|
||||
SetSheetNumberAndCount();
|
||||
UpdateHierarchyNavigator();
|
||||
}
|
||||
|
||||
TestDanglingEnds();
|
||||
|
||||
|
||||
@@ -1135,8 +1135,8 @@ bool IbisParser::readString( std::string& aDest )
|
||||
|
||||
if( len < 1 )
|
||||
{
|
||||
Report( _( "Unable to read string, input is empty." ), RPT_SEVERITY_ERROR );
|
||||
return false;
|
||||
// The data is likely on the next line. Skip.
|
||||
return true;
|
||||
}
|
||||
|
||||
char c = aDest[len - 1];
|
||||
@@ -1436,6 +1436,20 @@ bool IbisParser::readRamp()
|
||||
}
|
||||
|
||||
|
||||
bool IbisParser::readModelSpec()
|
||||
{
|
||||
bool status = true;
|
||||
|
||||
m_continue = IBIS_PARSER_CONTINUE::MODEL_SPEC;
|
||||
|
||||
// TODO
|
||||
// readTypMinMaxValueSubparam( std::string( "Vmeas" ), m_currentModel->... )
|
||||
// ...
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
bool IbisParser::parseModel( std::string& aKeyword )
|
||||
{
|
||||
bool status = false;
|
||||
@@ -1458,6 +1472,8 @@ bool IbisParser::parseModel( std::string& aKeyword )
|
||||
status = readWaveform( nullptr, IBIS_WAVEFORM_TYPE::FALLING );
|
||||
else if( compareIbisWord( aKeyword.c_str(), "Ramp" ) )
|
||||
status = readRamp();
|
||||
else if( compareIbisWord( aKeyword.c_str(), "Model_Spec" ) )
|
||||
status = readModelSpec();
|
||||
else if( compareIbisWord( aKeyword.c_str(), "Pullup_Reference" ) )
|
||||
status = readTypMinMaxValue( m_currentModel->m_pullupReference );
|
||||
else if( compareIbisWord( aKeyword.c_str(), "Pulldown_Reference" ) )
|
||||
@@ -1930,39 +1946,39 @@ bool IbisParser::readModel()
|
||||
{
|
||||
if( readWord( subparam ) )
|
||||
{
|
||||
if( !compareIbisWord( subparam.c_str(), "Input" ) )
|
||||
if( compareIbisWord( subparam.c_str(), "Input" ) )
|
||||
m_currentModel->m_type = IBIS_MODEL_TYPE::INPUT_STD;
|
||||
else if( !compareIbisWord( subparam.c_str(), "Output" ) )
|
||||
else if( compareIbisWord( subparam.c_str(), "Output" ) )
|
||||
m_currentModel->m_type = IBIS_MODEL_TYPE::OUTPUT;
|
||||
else if( !compareIbisWord( subparam.c_str(), "I/O" ) )
|
||||
else if( compareIbisWord( subparam.c_str(), "I/O" ) )
|
||||
m_currentModel->m_type = IBIS_MODEL_TYPE::IO;
|
||||
else if( !compareIbisWord( subparam.c_str(), "3-state" ) )
|
||||
else if( compareIbisWord( subparam.c_str(), "3-state" ) )
|
||||
m_currentModel->m_type = IBIS_MODEL_TYPE::THREE_STATE;
|
||||
else if( !compareIbisWord( subparam.c_str(), "Open_drain" ) )
|
||||
else if( compareIbisWord( subparam.c_str(), "Open_drain" ) )
|
||||
m_currentModel->m_type = IBIS_MODEL_TYPE::OPEN_DRAIN;
|
||||
else if( !compareIbisWord( subparam.c_str(), "I/O_Open_drain" ) )
|
||||
else if( compareIbisWord( subparam.c_str(), "I/O_Open_drain" ) )
|
||||
m_currentModel->m_type = IBIS_MODEL_TYPE::IO_OPEN_DRAIN;
|
||||
else if( !compareIbisWord( subparam.c_str(), "Open_sink" ) )
|
||||
else if( compareIbisWord( subparam.c_str(), "Open_sink" ) )
|
||||
m_currentModel->m_type = IBIS_MODEL_TYPE::OPEN_SINK;
|
||||
else if( !compareIbisWord( subparam.c_str(), "I/O_open_sink" ) )
|
||||
else if( compareIbisWord( subparam.c_str(), "I/O_open_sink" ) )
|
||||
m_currentModel->m_type = IBIS_MODEL_TYPE::IO_OPEN_SINK;
|
||||
else if( !compareIbisWord( subparam.c_str(), "Open_source" ) )
|
||||
else if( compareIbisWord( subparam.c_str(), "Open_source" ) )
|
||||
m_currentModel->m_type = IBIS_MODEL_TYPE::OPEN_SOURCE;
|
||||
else if( !compareIbisWord( subparam.c_str(), "I/O_open_source" ) )
|
||||
else if( compareIbisWord( subparam.c_str(), "I/O_open_source" ) )
|
||||
m_currentModel->m_type = IBIS_MODEL_TYPE::IO_OPEN_SOURCE;
|
||||
else if( !compareIbisWord( subparam.c_str(), "Input_ECL" ) )
|
||||
else if( compareIbisWord( subparam.c_str(), "Input_ECL" ) )
|
||||
m_currentModel->m_type = IBIS_MODEL_TYPE::INPUT_ECL;
|
||||
else if( !compareIbisWord( subparam.c_str(), "Output_ECL" ) )
|
||||
else if( compareIbisWord( subparam.c_str(), "Output_ECL" ) )
|
||||
m_currentModel->m_type = IBIS_MODEL_TYPE::OUTPUT_ECL;
|
||||
else if( !compareIbisWord( subparam.c_str(), "I/O_ECL" ) )
|
||||
else if( compareIbisWord( subparam.c_str(), "I/O_ECL" ) )
|
||||
m_currentModel->m_type = IBIS_MODEL_TYPE::IO_ECL;
|
||||
else if( !compareIbisWord( subparam.c_str(), "3-state_ECL" ) )
|
||||
else if( compareIbisWord( subparam.c_str(), "3-state_ECL" ) )
|
||||
m_currentModel->m_type = IBIS_MODEL_TYPE::THREE_STATE_ECL;
|
||||
else if( !compareIbisWord( subparam.c_str(), "Terminator" ) )
|
||||
else if( compareIbisWord( subparam.c_str(), "Terminator" ) )
|
||||
m_currentModel->m_type = IBIS_MODEL_TYPE::TERMINATOR;
|
||||
else if( !compareIbisWord( subparam.c_str(), "Series" ) )
|
||||
else if( compareIbisWord( subparam.c_str(), "Series" ) )
|
||||
m_currentModel->m_type = IBIS_MODEL_TYPE::SERIES;
|
||||
else if( !compareIbisWord( subparam.c_str(), "Series_switch" ) )
|
||||
else if( compareIbisWord( subparam.c_str(), "Series_switch" ) )
|
||||
m_currentModel->m_type = IBIS_MODEL_TYPE::SERIES_SWITCH;
|
||||
else
|
||||
{
|
||||
@@ -2577,6 +2593,7 @@ bool IbisParser::onNewLine()
|
||||
status &= readWaveform( m_currentWaveform, m_currentWaveform->m_type );
|
||||
break;
|
||||
case IBIS_PARSER_CONTINUE::RAMP: status &= readRamp(); break;
|
||||
case IBIS_PARSER_CONTINUE::MODEL_SPEC: status &= readModelSpec(); break;
|
||||
case IBIS_PARSER_CONTINUE::PACKAGEMODEL_PINS: status &= readPackageModelPins(); break;
|
||||
case IBIS_PARSER_CONTINUE::MATRIX: status &= readMatrix( m_currentMatrix ); break;
|
||||
case IBIS_PARSER_CONTINUE::NONE:
|
||||
|
||||
@@ -632,6 +632,7 @@ enum class IBIS_PARSER_CONTINUE
|
||||
MATRIX,
|
||||
MODELSELECTOR,
|
||||
MODEL,
|
||||
MODEL_SPEC,
|
||||
IV_TABLE,
|
||||
VT_TABLE,
|
||||
RAMP,
|
||||
@@ -772,6 +773,7 @@ private:
|
||||
bool readMatrixSparse( std::string, IBIS_MATRIX_SPARSE& aDest );
|
||||
bool readRampdvdt( dvdtTypMinMax& aDest );
|
||||
bool readRamp();
|
||||
bool readModelSpec();
|
||||
bool readWaveform( IbisWaveform* aDest, IBIS_WAVEFORM_TYPE aType );
|
||||
bool readString( std::string& aDest );
|
||||
bool storeString( std::string& aDest, bool aMultiline );
|
||||
|
||||
@@ -187,17 +187,20 @@ bool SIM_STRING_PROPERTY::StringToValue( wxVariant& aVariant, const wxString& aT
|
||||
|
||||
wxString text = aText;
|
||||
|
||||
if( !aText.IsEmpty() && allowEval() && m_needsEval && m_eval.Process( aText ) )
|
||||
if( allowEval() && m_needsEval && m_eval.Process( aText ) )
|
||||
{
|
||||
double value = SIM_VALUE::ToDouble( m_eval.Result().ToStdString() );
|
||||
if( !aText.IsEmpty() )
|
||||
{
|
||||
double value = SIM_VALUE::ToDouble( m_eval.Result().ToStdString() );
|
||||
|
||||
if( isnan( value ) || SIM_VALUE::Equal( value, aText.ToStdString() ) )
|
||||
{
|
||||
// Don't mess up user formatting if eval'ing didn't actually change the value.
|
||||
}
|
||||
else
|
||||
{
|
||||
text = SIM_VALUE::Normalize( value );
|
||||
if( std::isnan( value ) || SIM_VALUE::Equal( value, aText.ToStdString() ) )
|
||||
{
|
||||
// Don't mess up user formatting if eval'ing didn't actually change the value.
|
||||
}
|
||||
else
|
||||
{
|
||||
text = SIM_VALUE::Normalize( value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -125,6 +125,14 @@ std::vector<SYMBOL_ASYNC_LOADER::LOADED_PAIR> SYMBOL_ASYNC_LOADER::worker()
|
||||
std::lock_guard<std::mutex> lock( m_errorMutex );
|
||||
m_errors += msg;
|
||||
}
|
||||
catch( std::exception& e )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Error loading symbol library %s.\n\n%s\n" ),
|
||||
nickname, e.what() );
|
||||
|
||||
std::lock_guard<std::mutex> lock( m_errorMutex );
|
||||
m_errors += msg;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -116,7 +116,11 @@ SYMBOL_EDIT_FRAME::SYMBOL_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||
wxIcon icon;
|
||||
wxIconBundle icon_bundle;
|
||||
|
||||
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_libedit ) );
|
||||
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_libedit, 48 ) );
|
||||
icon_bundle.AddIcon( icon );
|
||||
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_libedit, 256 ) );
|
||||
icon_bundle.AddIcon( icon );
|
||||
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_libedit, 128 ) );
|
||||
icon_bundle.AddIcon( icon );
|
||||
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_libedit_32 ) );
|
||||
icon_bundle.AddIcon( icon );
|
||||
|
||||
@@ -1252,7 +1252,7 @@ void SYMBOL_VIEWER_FRAME::onSelectNextSymbol( wxCommandEvent& aEvent )
|
||||
int ii = m_symbolList->GetSelection();
|
||||
|
||||
// Select the next symbol or stop at the end of the list.
|
||||
if( ii != wxNOT_FOUND || ii != (int) m_symbolList->GetCount() - 1 )
|
||||
if( ii != wxNOT_FOUND && ii < (int)(m_symbolList->GetCount() - 1) )
|
||||
ii += 1;
|
||||
|
||||
m_symbolList->SetSelection( ii );
|
||||
|
||||
@@ -1956,6 +1956,9 @@ void EE_SELECTION_TOOL::unhighlight( EDA_ITEM* aItem, int aMode, SELECTION* aGro
|
||||
aChild->ClearSelected();
|
||||
else if( aMode == BRIGHTENED )
|
||||
aChild->ClearBrightened();
|
||||
|
||||
if( aGroup )
|
||||
aGroup->Remove( aChild );
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2019 CERN
|
||||
* Copyright (C) 2019-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2019-2024 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,12 +76,7 @@ SCH_DRAWING_TOOLS::SCH_DRAWING_TOOLS() :
|
||||
m_lastTextboxStroke( 0, PLOT_DASH_TYPE::DEFAULT, COLOR4D::UNSPECIFIED ),
|
||||
m_mruPath( wxEmptyString ),
|
||||
m_lastAutoLabelRotateOnPlacement( false ),
|
||||
m_inPlaceSymbol( false ),
|
||||
m_inDrawShape( false ),
|
||||
m_inPlaceImage( false ),
|
||||
m_inSingleClickPlace( false ),
|
||||
m_inTwoClickPlace( false ),
|
||||
m_inDrawSheet( false )
|
||||
m_inDrawingTool( false )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -112,10 +107,10 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
|
||||
COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
|
||||
EE_GRID_HELPER grid( m_toolMgr );
|
||||
|
||||
if( m_inPlaceSymbol )
|
||||
if( m_inDrawingTool )
|
||||
return 0;
|
||||
|
||||
REENTRANCY_GUARD guard( &m_inPlaceSymbol );
|
||||
REENTRANCY_GUARD guard( &m_inDrawingTool );
|
||||
|
||||
// First we need to get all instances of this sheet so we can annotate
|
||||
// whatever symbols we place on all copies
|
||||
@@ -473,10 +468,10 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
|
||||
bool ignorePrimePosition = false;
|
||||
COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
|
||||
|
||||
if( m_inPlaceImage )
|
||||
if( m_inDrawingTool )
|
||||
return 0;
|
||||
|
||||
REENTRANCY_GUARD guard( &m_inPlaceImage );
|
||||
REENTRANCY_GUARD guard( &m_inDrawingTool );
|
||||
|
||||
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
|
||||
|
||||
@@ -709,10 +704,10 @@ int SCH_DRAWING_TOOLS::SingleClickPlace( const TOOL_EVENT& aEvent )
|
||||
SCH_ITEM* previewItem;
|
||||
bool loggedInfoBarError = false;
|
||||
|
||||
if( m_inSingleClickPlace )
|
||||
if( m_inDrawingTool )
|
||||
return 0;
|
||||
|
||||
REENTRANCY_GUARD guard( &m_inSingleClickPlace );
|
||||
REENTRANCY_GUARD guard( &m_inDrawingTool );
|
||||
|
||||
if( type == SCH_JUNCTION_T && aEvent.HasPosition() )
|
||||
{
|
||||
@@ -1129,10 +1124,10 @@ int SCH_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
|
||||
COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
|
||||
SCH_SHEET* sheet = nullptr;
|
||||
|
||||
if( m_inTwoClickPlace )
|
||||
if( m_inDrawingTool )
|
||||
return 0;
|
||||
|
||||
REENTRANCY_GUARD guard( &m_inTwoClickPlace );
|
||||
REENTRANCY_GUARD guard( &m_inDrawingTool );
|
||||
|
||||
bool isText = aEvent.IsAction( &EE_ACTIONS::placeSchematicText );
|
||||
bool isGlobalLabel = aEvent.IsAction( &EE_ACTIONS::placeGlobalLabel );
|
||||
@@ -1520,10 +1515,10 @@ int SCH_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
|
||||
bool isTextBox = aEvent.IsAction( &EE_ACTIONS::drawTextBox );
|
||||
SHAPE_T type = aEvent.Parameter<SHAPE_T>();
|
||||
|
||||
if( m_inDrawShape )
|
||||
if( m_inDrawingTool )
|
||||
return 0;
|
||||
|
||||
REENTRANCY_GUARD guard( &m_inDrawShape );
|
||||
REENTRANCY_GUARD guard( &m_inDrawingTool );
|
||||
|
||||
// We might be running as the same shape in another co-routine. Make sure that one
|
||||
// gets whacked.
|
||||
@@ -1739,10 +1734,10 @@ int SCH_DRAWING_TOOLS::DrawSheet( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
SCH_SHEET* sheet = nullptr;
|
||||
|
||||
if( m_inDrawSheet )
|
||||
if( m_inDrawingTool )
|
||||
return 0;
|
||||
|
||||
REENTRANCY_GUARD guard( &m_inDrawSheet );
|
||||
REENTRANCY_GUARD guard( &m_inDrawingTool );
|
||||
|
||||
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
|
||||
|
||||
|
||||
@@ -94,14 +94,7 @@ private:
|
||||
wxString m_mruPath;
|
||||
bool m_lastAutoLabelRotateOnPlacement;
|
||||
|
||||
///< Re-entrancy guards
|
||||
bool m_inPlaceSymbol;
|
||||
bool m_inDrawShape;
|
||||
bool m_inPlaceImage;
|
||||
bool m_inSingleClickPlace;
|
||||
bool m_inTwoClickPlace;
|
||||
bool m_inDrawSheet;
|
||||
|
||||
bool m_inDrawingTool; // Re-entrancy guard
|
||||
std::unique_ptr<STATUS_TEXT_POPUP> m_statusPopup;
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2019 CERN
|
||||
* Copyright (C) 2019-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2019-2024 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
|
||||
@@ -1119,7 +1119,28 @@ int SCH_EDIT_TOOL::RepeatDrawItem( const TOOL_EVENT& aEvent )
|
||||
schIUScale.MilsToIU( cfg->m_Drawing.default_repeat_offset_y ) ) );
|
||||
}
|
||||
|
||||
// If cloning a sheet, check that we aren't going to create recursion
|
||||
if( newItem->Type() == SCH_SHEET_T )
|
||||
{
|
||||
SCH_SHEET_PATH* currentSheet = &m_frame->GetCurrentSheet();
|
||||
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( newItem );
|
||||
|
||||
if( m_frame->CheckSheetForRecursion( sheet, currentSheet ) )
|
||||
{
|
||||
// Clear out the filename so that the user can pick a new one
|
||||
sheet->SetFileName( wxEmptyString );
|
||||
|
||||
if( !m_frame->EditSheetProperties( sheet, currentSheet, nullptr ) )
|
||||
{
|
||||
// User canceled renaming the sheet; skip it
|
||||
delete newItem;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_toolMgr->RunAction( EE_ACTIONS::addItemToSel, true, newItem );
|
||||
|
||||
newItem->SetFlags( IS_NEW );
|
||||
m_frame->AddToScreen( newItem, m_frame->GetScreen() );
|
||||
m_frame->SaveCopyInUndoList( m_frame->GetScreen(), newItem, UNDO_REDO::NEWITEM, appendUndo );
|
||||
@@ -1197,9 +1218,10 @@ static std::vector<KICAD_T> deletableItems =
|
||||
|
||||
int SCH_EDIT_TOOL::DoDelete( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
SCH_SCREEN* screen = m_frame->GetScreen();
|
||||
auto items = m_selectionTool->RequestSelection( deletableItems ).GetItems();
|
||||
bool appendToUndo = false;
|
||||
SCH_SCREEN* screen = m_frame->GetScreen();
|
||||
auto items = m_selectionTool->RequestSelection( deletableItems ).GetItems();
|
||||
bool appendToUndo = false;
|
||||
bool rebuildHierarchyNavigator = false;
|
||||
std::vector<VECTOR2I> pts;
|
||||
|
||||
if( items.empty() )
|
||||
@@ -1264,7 +1286,7 @@ int SCH_EDIT_TOOL::DoDelete( const TOOL_EVENT& aEvent )
|
||||
m_frame->RemoveFromScreen( sch_item, m_frame->GetScreen() );
|
||||
|
||||
if( sch_item->Type() == SCH_SHEET_T )
|
||||
m_frame->UpdateHierarchyNavigator();
|
||||
rebuildHierarchyNavigator = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1279,8 +1301,10 @@ int SCH_EDIT_TOOL::DoDelete( const TOOL_EVENT& aEvent )
|
||||
m_frame->DeleteJunction( junction, appendToUndo );
|
||||
}
|
||||
|
||||
m_frame->TestDanglingEnds();
|
||||
if( rebuildHierarchyNavigator )
|
||||
m_frame->UpdateHierarchyNavigator();
|
||||
|
||||
m_frame->TestDanglingEnds();
|
||||
m_frame->GetCanvas()->Refresh();
|
||||
m_frame->OnModify();
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2019 CERN
|
||||
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2024 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
|
||||
@@ -75,6 +75,14 @@
|
||||
#include <wx/filedlg.h>
|
||||
|
||||
|
||||
/**
|
||||
* Flag to enable schematic paste debugging output.
|
||||
*
|
||||
* @ingroup trace_env_vars
|
||||
*/
|
||||
static const wxChar traceSchPaste[] = wxT( "KICAD_SCH_PASTE" );
|
||||
|
||||
|
||||
int SCH_EDITOR_CONTROL::New( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
m_frame->NewProject();
|
||||
@@ -332,10 +340,13 @@ void SCH_EDITOR_CONTROL::doCrossProbeSchToPcb( const TOOL_EVENT& aEvent, bool aF
|
||||
|
||||
int SCH_EDITOR_CONTROL::ExportSymbolsToLibrary( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
bool savePowerSymbols = IsOK( m_frame,
|
||||
_( "Include power symbols in schematic to the library?" ) );
|
||||
|
||||
bool createNew = aEvent.IsAction( &EE_ACTIONS::exportSymbolsToNewLibrary );
|
||||
|
||||
SCH_REFERENCE_LIST symbols;
|
||||
m_frame->Schematic().GetSheets().GetSymbols( symbols, false );
|
||||
m_frame->Schematic().GetSheets().GetSymbols( symbols, savePowerSymbols );
|
||||
|
||||
std::map<LIB_ID, LIB_SYMBOL*> libSymbols;
|
||||
std::map<LIB_ID, std::vector<SCH_SYMBOL*>> symbolMap;
|
||||
@@ -423,17 +434,29 @@ int SCH_EDITOR_CONTROL::ExportSymbolsToLibrary( const TOOL_EVENT& aEvent )
|
||||
LIB_SYMBOL* origSym = it.second;
|
||||
LIB_SYMBOL* newSym = origSym->Flatten().release();
|
||||
|
||||
pi->SaveSymbol( dest.GetFullPath(), newSym );
|
||||
try
|
||||
{
|
||||
pi->SaveSymbol( dest.GetFullPath(), newSym );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
wxString msg;
|
||||
msg.Printf( _( "Error saving symbol %s to library '%s'." ),
|
||||
newSym->GetName(), row->GetNickName() );
|
||||
msg += wxS( "\n\n" ) + ioe.What();
|
||||
wxLogWarning( msg );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( map )
|
||||
{
|
||||
LIB_ID id = it.first;
|
||||
id.SetLibNickname( targetLib );
|
||||
|
||||
|
||||
for( SCH_SYMBOL* symbol : symbolMap[it.first] )
|
||||
{
|
||||
m_frame->SaveCopyInUndoList( m_frame->GetScreen(), symbol, UNDO_REDO::CHANGED, append, false);
|
||||
m_frame->SaveCopyInUndoList( m_frame->GetScreen(), symbol, UNDO_REDO::CHANGED,
|
||||
append, false );
|
||||
symbol->SetLibId( id );
|
||||
append = true;
|
||||
}
|
||||
@@ -487,6 +510,7 @@ int SCH_EDITOR_CONTROL::ExportSymbolsToLibrary( const TOOL_EVENT& aEvent )
|
||||
for( SCH_SHEET_PATH& sheet : sheets )
|
||||
{
|
||||
SCH_SCREEN* screen = sheet.LastScreen();
|
||||
|
||||
if( processedScreens.find( ( screen ) ) == processedScreens.end() )
|
||||
{
|
||||
processedScreens.insert( screen );
|
||||
@@ -806,18 +830,27 @@ static bool highlightNet( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition )
|
||||
}
|
||||
}
|
||||
|
||||
wxString connectionName = ( conn ) ? conn->Name() : wxS( "" );
|
||||
wxString connectionName = ( conn ) ? conn->Name() : wxString( wxS( "" ) );
|
||||
|
||||
if( !conn || connectionName == editFrame->GetHighlightedConnection() )
|
||||
if( !conn )
|
||||
{
|
||||
editFrame->SetStatusText( wxT( "" ) );
|
||||
editFrame->SendCrossProbeClearHighlight();
|
||||
editFrame->SetHighlightedConnection( wxEmptyString );
|
||||
editorControl->SetHighlightBusMembers( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
editFrame->SetCrossProbeConnection( conn );
|
||||
editFrame->SetHighlightedConnection( connectionName );
|
||||
if( connectionName != editFrame->GetHighlightedConnection() )
|
||||
{
|
||||
editorControl->SetHighlightBusMembers( false );
|
||||
editFrame->SetCrossProbeConnection( conn );
|
||||
editFrame->SetHighlightedConnection( connectionName );
|
||||
}
|
||||
else
|
||||
{
|
||||
editorControl->SetHighlightBusMembers( !editorControl->GetHighlightBusMembers() );
|
||||
}
|
||||
}
|
||||
|
||||
editFrame->UpdateNetHighlightStatus();
|
||||
@@ -1014,155 +1047,162 @@ int SCH_EDITOR_CONTROL::AssignNetclass( const TOOL_EVENT& aEvent )
|
||||
|
||||
int SCH_EDITOR_CONTROL::UpdateNetHighlighting( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
wxCHECK( m_frame, 0 );
|
||||
|
||||
const SCH_SHEET_PATH& sheetPath = m_frame->GetCurrentSheet();
|
||||
SCH_SCREEN* screen = m_frame->GetCurrentSheet().LastScreen();
|
||||
CONNECTION_GRAPH* connectionGraph = m_frame->Schematic().ConnectionGraph();
|
||||
wxString selectedName = m_frame->GetHighlightedConnection();
|
||||
|
||||
std::set<wxString> connNames;
|
||||
std::vector<EDA_ITEM*> itemsToRedraw;
|
||||
|
||||
wxCHECK( screen && connectionGraph, 0 );
|
||||
|
||||
bool selectedIsBus = false;
|
||||
wxString selectedName = m_frame->GetHighlightedConnection();
|
||||
|
||||
bool selectedIsNoNet = false;
|
||||
CONNECTION_SUBGRAPH* selectedSubgraph = nullptr;
|
||||
|
||||
for( SCH_ITEM* item : screen->Items() )
|
||||
if( !selectedName.IsEmpty() )
|
||||
{
|
||||
bool redraw = item->IsBrightened();
|
||||
bool highlight = false;
|
||||
connNames.emplace( selectedName );
|
||||
|
||||
if( !selectedName.IsEmpty() )
|
||||
CONNECTION_SUBGRAPH* sg = connectionGraph->FindSubgraphByName( selectedName, sheetPath );
|
||||
|
||||
if( sg && m_highlightBusMembers )
|
||||
{
|
||||
SCH_CONNECTION* itemConn = nullptr;
|
||||
SCH_SYMBOL* symbol = nullptr;
|
||||
|
||||
if( item->Type() == SCH_SYMBOL_T )
|
||||
symbol = static_cast<SCH_SYMBOL*>( item );
|
||||
|
||||
if( symbol && symbol->GetLibSymbolRef() && symbol->GetLibSymbolRef()->IsPower() )
|
||||
itemConn = symbol->Connection();
|
||||
else
|
||||
itemConn = item->Connection();
|
||||
|
||||
if( itemConn && ( selectedName == itemConn->Name() ) )
|
||||
for( const SCH_ITEM* item : sg->GetItems() )
|
||||
{
|
||||
selectedIsBus = itemConn->IsBus();
|
||||
wxCHECK2( item, continue );
|
||||
|
||||
if( itemConn->Driver() == nullptr )
|
||||
{
|
||||
selectedIsNoNet = true;
|
||||
selectedSubgraph = connectionGraph->GetSubgraphForItem( itemConn->Parent() );
|
||||
}
|
||||
SCH_CONNECTION* connection = item->Connection();
|
||||
|
||||
if( selectedIsNoNet && selectedSubgraph )
|
||||
wxCHECK2( connection, continue );
|
||||
|
||||
for( const std::shared_ptr<SCH_CONNECTION>& member : connection->AllMembers() )
|
||||
{
|
||||
for( SCH_ITEM* subgraphItem : selectedSubgraph->GetItems() )
|
||||
{
|
||||
if( item == subgraphItem )
|
||||
{
|
||||
highlight = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( selectedIsBus && itemConn && itemConn->IsNet() )
|
||||
{
|
||||
for( const std::shared_ptr<SCH_CONNECTION>& member : itemConn->Members() )
|
||||
{
|
||||
if( member->Name() == itemConn->Name() )
|
||||
{
|
||||
highlight = true;
|
||||
break;
|
||||
}
|
||||
else if( member->IsBus() )
|
||||
{
|
||||
for( const std::shared_ptr<SCH_CONNECTION>& bus_member :
|
||||
member->Members() )
|
||||
{
|
||||
if( bus_member->Name() == itemConn->Name() )
|
||||
{
|
||||
highlight = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( !selectedName.IsEmpty() && itemConn
|
||||
&& ( selectedName == itemConn->Name() ) )
|
||||
{
|
||||
highlight = true;
|
||||
if( member )
|
||||
connNames.emplace( member->Name() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( highlight )
|
||||
item->SetBrightened();
|
||||
else
|
||||
item->ClearBrightened();
|
||||
for( SCH_ITEM* item : screen->Items() )
|
||||
{
|
||||
wxCHECK2( item, continue );
|
||||
|
||||
redraw |= item->IsBrightened();
|
||||
if( !item->IsConnectable() )
|
||||
continue;
|
||||
|
||||
SCH_ITEM* redrawItem = nullptr;
|
||||
|
||||
if( item->Type() == SCH_SYMBOL_T )
|
||||
{
|
||||
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
|
||||
|
||||
redraw |= symbol->HasBrightenedPins();
|
||||
|
||||
symbol->ClearBrightenedPins();
|
||||
wxCHECK2( symbol, continue );
|
||||
|
||||
for( SCH_PIN* pin : symbol->GetPins() )
|
||||
{
|
||||
SCH_CONNECTION* pin_conn = pin->Connection();
|
||||
|
||||
if( pin_conn && pin_conn->Name() == selectedName )
|
||||
wxCHECK2( pin_conn, continue );
|
||||
|
||||
if( !pin->IsBrightened() && connNames.count( pin_conn->Name() ) )
|
||||
{
|
||||
pin->SetBrightened();
|
||||
redraw = true;
|
||||
redrawItem = symbol;
|
||||
}
|
||||
else if( pin->IsBrightened() && !connNames.count( pin_conn->Name() ) )
|
||||
{
|
||||
pin->ClearBrightened();
|
||||
redrawItem = symbol;
|
||||
}
|
||||
}
|
||||
|
||||
if( symbol->GetLibSymbolRef() && symbol->GetLibSymbolRef()->IsPower() )
|
||||
if( symbol->IsPower() )
|
||||
{
|
||||
wxCHECK2( symbol->GetPins().size(), continue );
|
||||
|
||||
SCH_CONNECTION* pinConn = symbol->GetPins()[0]->Connection();
|
||||
|
||||
wxCHECK2( pinConn, continue );
|
||||
|
||||
std::vector<SCH_FIELD>& fields = symbol->GetFields();
|
||||
|
||||
for( int id : { REFERENCE_FIELD, VALUE_FIELD } )
|
||||
{
|
||||
if( item->IsBrightened() && fields[id].IsVisible() )
|
||||
if( !fields[id].IsVisible() )
|
||||
continue;
|
||||
|
||||
if( !fields[id].IsBrightened() && connNames.count( pinConn->Name() ) )
|
||||
{
|
||||
fields[id].SetBrightened();
|
||||
else
|
||||
redrawItem = symbol;
|
||||
}
|
||||
else if( fields[id].IsBrightened() && !connNames.count( pinConn->Name() ) )
|
||||
{
|
||||
fields[id].ClearBrightened();
|
||||
redrawItem = symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( item->Type() == SCH_SHEET_T )
|
||||
{
|
||||
for( SCH_SHEET_PIN* pin : static_cast<SCH_SHEET*>( item )->GetPins() )
|
||||
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
|
||||
|
||||
wxCHECK2( sheet, continue );
|
||||
|
||||
for( SCH_SHEET_PIN* pin : sheet->GetPins() )
|
||||
{
|
||||
wxCHECK2( pin, continue );
|
||||
|
||||
SCH_CONNECTION* pin_conn = pin->Connection();
|
||||
bool redrawPin = pin->IsBrightened();
|
||||
|
||||
if( pin_conn && pin_conn->Name() == selectedName )
|
||||
wxCHECK2( pin_conn, continue );
|
||||
|
||||
if( !pin->IsBrightened() && connNames.count( pin_conn->Name() ) )
|
||||
{
|
||||
pin->SetBrightened();
|
||||
else
|
||||
redrawItem = sheet;
|
||||
}
|
||||
else if( pin->IsBrightened() && !connNames.count( pin_conn->Name() ) )
|
||||
{
|
||||
pin->ClearBrightened();
|
||||
redrawItem = sheet;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SCH_CONNECTION* itemConn = item->Connection();
|
||||
|
||||
redrawPin ^= pin->IsBrightened();
|
||||
redraw |= redrawPin;
|
||||
wxCHECK2( itemConn, continue );
|
||||
|
||||
if( !item->IsBrightened() && connNames.count( itemConn->Name() ) )
|
||||
{
|
||||
item->SetBrightened();
|
||||
redrawItem = item;
|
||||
}
|
||||
else if( item->IsBrightened() && !connNames.count( itemConn->Name() ) )
|
||||
{
|
||||
item->ClearBrightened();
|
||||
redrawItem = item;
|
||||
}
|
||||
}
|
||||
|
||||
if( redraw )
|
||||
itemsToRedraw.push_back( item );
|
||||
if( redrawItem )
|
||||
itemsToRedraw.push_back( redrawItem );
|
||||
}
|
||||
|
||||
// Be sure highlight change will be redrawn
|
||||
KIGFX::VIEW* view = getView();
|
||||
if( itemsToRedraw.size() )
|
||||
{
|
||||
// Be sure highlight change will be redrawn
|
||||
KIGFX::VIEW* view = getView();
|
||||
|
||||
for( EDA_ITEM* redrawItem : itemsToRedraw )
|
||||
view->Update( (KIGFX::VIEW_ITEM*)redrawItem, KIGFX::VIEW_UPDATE_FLAGS::REPAINT );
|
||||
for( EDA_ITEM* redrawItem : itemsToRedraw )
|
||||
view->Update( (KIGFX::VIEW_ITEM*)redrawItem, KIGFX::VIEW_UPDATE_FLAGS::REPAINT );
|
||||
|
||||
m_frame->GetCanvas()->Refresh();
|
||||
m_frame->GetCanvas()->Refresh();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1199,7 +1239,10 @@ int SCH_EDITOR_CONTROL::Undo( const TOOL_EVENT& aEvent )
|
||||
m_toolMgr->ProcessEvent( { TC_MESSAGE, TA_UNDO_REDO_PRE, AS_GLOBAL } );
|
||||
|
||||
// Get the old list
|
||||
PICKED_ITEMS_LIST* List = m_frame->PopCommandFromUndoList();
|
||||
PICKED_ITEMS_LIST* list = m_frame->PopCommandFromUndoList();
|
||||
|
||||
wxCHECK( m_frame && list, 0 );
|
||||
|
||||
size_t num_undos = m_frame->m_undoList.m_CommandsList.size();
|
||||
|
||||
// The cleanup routines normally run after an operation and so attempt to append their
|
||||
@@ -1208,9 +1251,15 @@ int SCH_EDITOR_CONTROL::Undo( const TOOL_EVENT& aEvent )
|
||||
PICKED_ITEMS_LIST* dummy = new PICKED_ITEMS_LIST();
|
||||
m_frame->PushCommandToUndoList( dummy );
|
||||
|
||||
m_frame->PutDataInPreviousState( List );
|
||||
m_frame->PutDataInPreviousState( list );
|
||||
|
||||
// Only rebuild the hierarchy navigator if there are sheet changes.
|
||||
if( list->ContainsItemType( SCH_SHEET_T ) )
|
||||
{
|
||||
m_frame->SetSheetNumberAndCount();
|
||||
m_frame->UpdateHierarchyNavigator();
|
||||
}
|
||||
|
||||
m_frame->SetSheetNumberAndCount();
|
||||
m_frame->TestDanglingEnds();
|
||||
m_frame->OnPageSettingsChange();
|
||||
|
||||
@@ -1220,8 +1269,8 @@ int SCH_EDITOR_CONTROL::Undo( const TOOL_EVENT& aEvent )
|
||||
delete m_frame->PopCommandFromUndoList();
|
||||
|
||||
// Now push the old command to the RedoList
|
||||
List->ReversePickersListOrder();
|
||||
m_frame->PushCommandToRedoList( List );
|
||||
list->ReversePickersListOrder();
|
||||
m_frame->PushCommandToRedoList( list );
|
||||
|
||||
m_toolMgr->GetTool<EE_SELECTION_TOOL>()->RebuildSelection();
|
||||
|
||||
@@ -1235,6 +1284,8 @@ int SCH_EDITOR_CONTROL::Undo( const TOOL_EVENT& aEvent )
|
||||
|
||||
int SCH_EDITOR_CONTROL::Redo( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
wxCHECK( m_frame, 0 );
|
||||
|
||||
if( m_frame->GetRedoCommandCount() == 0 )
|
||||
return 0;
|
||||
|
||||
@@ -1244,6 +1295,8 @@ int SCH_EDITOR_CONTROL::Redo( const TOOL_EVENT& aEvent )
|
||||
/* Get the old list */
|
||||
PICKED_ITEMS_LIST* list = m_frame->PopCommandFromRedoList();
|
||||
|
||||
wxCHECK( list, 0 );
|
||||
|
||||
/* Redo the command: */
|
||||
m_frame->PutDataInPreviousState( list );
|
||||
|
||||
@@ -1251,7 +1304,13 @@ int SCH_EDITOR_CONTROL::Redo( const TOOL_EVENT& aEvent )
|
||||
list->ReversePickersListOrder();
|
||||
m_frame->PushCommandToUndoList( list );
|
||||
|
||||
m_frame->SetSheetNumberAndCount();
|
||||
// Only rebuild the hierarchy navigator if there are sheet changes.
|
||||
if( list->ContainsItemType( SCH_SHEET_T ) )
|
||||
{
|
||||
m_frame->SetSheetNumberAndCount();
|
||||
m_frame->UpdateHierarchyNavigator();
|
||||
}
|
||||
|
||||
m_frame->TestDanglingEnds();
|
||||
|
||||
m_toolMgr->GetTool<EE_SELECTION_TOOL>()->RebuildSelection();
|
||||
@@ -1369,27 +1428,47 @@ int SCH_EDITOR_CONTROL::Copy( const TOOL_EVENT& aEvent )
|
||||
}
|
||||
|
||||
|
||||
void SCH_EDITOR_CONTROL::updatePastedSymbol( SCH_SYMBOL* aSymbol, SCH_SCREEN* aPasteScreen,
|
||||
void SCH_EDITOR_CONTROL::updatePastedSymbol( SCH_SYMBOL* aSymbol,
|
||||
const SCH_SHEET_PATH& aPastePath,
|
||||
const KIID_PATH& aClipPath,
|
||||
bool aForceKeepAnnotations )
|
||||
{
|
||||
wxCHECK( aSymbol && aPasteScreen, /* void */ );
|
||||
wxCHECK( m_frame && aSymbol, /* void */ );
|
||||
|
||||
KIID_PATH clipItemPath = aClipPath;
|
||||
SCH_SYMBOL_INSTANCE newInstance;
|
||||
bool instanceFound = false;
|
||||
KIID_PATH pasteLookupPath = aClipPath;
|
||||
|
||||
wxString reference, value, footprint;
|
||||
int unit;
|
||||
m_pastedSymbols.insert( aSymbol );
|
||||
|
||||
if( m_clipboardSymbolInstances.count( clipItemPath ) > 0 )
|
||||
for( const SCH_SYMBOL_INSTANCE& tmp : aSymbol->GetInstanceReferences() )
|
||||
{
|
||||
SCH_SYMBOL_INSTANCE instance = m_clipboardSymbolInstances.at( clipItemPath );
|
||||
if( ( tmp.m_Path.empty() && aClipPath.empty() )
|
||||
|| ( !aClipPath.empty() && tmp.m_Path.EndsWith( aClipPath ) ) )
|
||||
{
|
||||
newInstance = tmp;
|
||||
instanceFound = true;
|
||||
|
||||
unit = instance.m_Unit;
|
||||
reference = instance.m_Reference;
|
||||
wxLogTrace( traceSchPaste,
|
||||
wxS( "Pasting found symbol instance with reference %s, unit %d:"
|
||||
"\n\tClipboard path: %s\n\tSymbol UUID: %s." ),
|
||||
tmp.m_Reference, tmp.m_Unit,
|
||||
aClipPath.AsString(), aSymbol->m_Uuid.AsString() );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
// The pasted symbol look up paths include the symbol UUID.
|
||||
pasteLookupPath.push_back( aSymbol->m_Uuid );
|
||||
|
||||
if( !instanceFound )
|
||||
{
|
||||
wxLogTrace( traceSchPaste,
|
||||
wxS( "Clipboard symbol instance **not** found:\n\tClipboard path: %s\n\t"
|
||||
"Symbol UUID: %s." ),
|
||||
aClipPath.AsString(), aSymbol->m_Uuid.AsString() );
|
||||
|
||||
// Some legacy versions saved value fields escaped. While we still do in the symbol
|
||||
// editor, we don't anymore in the schematic, so be sure to unescape them.
|
||||
SCH_FIELD* valueField = aSymbol->GetField( VALUE_FIELD );
|
||||
@@ -1397,80 +1476,139 @@ void SCH_EDITOR_CONTROL::updatePastedSymbol( SCH_SYMBOL* aSymbol, SCH_SCREEN* aP
|
||||
|
||||
// Pasted from notepad or an older instance of eeschema. Use the values in the fields
|
||||
// instead.
|
||||
reference = aSymbol->GetField( REFERENCE_FIELD )->GetText();
|
||||
value = aSymbol->GetField( VALUE_FIELD )->GetText();
|
||||
footprint = aSymbol->GetField( FOOTPRINT_FIELD )->GetText();
|
||||
unit = aSymbol->GetUnit();
|
||||
newInstance.m_Reference = aSymbol->GetField( REFERENCE_FIELD )->GetText();
|
||||
newInstance.m_Unit = aSymbol->GetUnit();
|
||||
}
|
||||
|
||||
if( aForceKeepAnnotations && !reference.IsEmpty() )
|
||||
aSymbol->SetRef( &aPastePath, reference );
|
||||
else
|
||||
newInstance.m_Path = aPastePath.Path();
|
||||
newInstance.m_ProjectName = m_frame->Prj().GetProjectName();
|
||||
|
||||
aSymbol->AddHierarchicalReference( newInstance );
|
||||
|
||||
if( !aForceKeepAnnotations )
|
||||
aSymbol->ClearAnnotation( &aPastePath, false );
|
||||
|
||||
// We might clear annotations but always leave the original unit number from the paste.
|
||||
aSymbol->SetUnitSelection( &aPastePath, unit );
|
||||
aSymbol->SetUnit( unit );
|
||||
aSymbol->SetUnit( newInstance.m_Unit );
|
||||
}
|
||||
|
||||
|
||||
SCH_SHEET_PATH SCH_EDITOR_CONTROL::updatePastedSheet( const SCH_SHEET_PATH& aPastePath,
|
||||
const KIID_PATH& aClipPath, SCH_SHEET* aSheet,
|
||||
SCH_SHEET_PATH SCH_EDITOR_CONTROL::updatePastedSheet( SCH_SHEET* aSheet,
|
||||
const SCH_SHEET_PATH& aPastePath,
|
||||
const KIID_PATH& aClipPath,
|
||||
bool aForceKeepAnnotations,
|
||||
SCH_SHEET_LIST* aPastedSheetsSoFar,
|
||||
SCH_REFERENCE_LIST* aPastedSymbolsSoFar )
|
||||
SCH_SHEET_LIST* aPastedSheets,
|
||||
std::map<SCH_SHEET_PATH,
|
||||
SCH_REFERENCE_LIST>& aPastedSymbols )
|
||||
{
|
||||
wxCHECK( aSheet && aPastedSheetsSoFar && aPastedSymbolsSoFar, aPastePath );
|
||||
wxCHECK( aSheet && aPastedSheets, aPastePath );
|
||||
|
||||
SCH_SHEET_PATH sheetPath = aPastePath;
|
||||
sheetPath.push_back( aSheet );
|
||||
|
||||
aPastedSheetsSoFar->push_back( sheetPath );
|
||||
aPastedSheets->push_back( sheetPath );
|
||||
|
||||
if( aSheet->GetScreen() == nullptr )
|
||||
return sheetPath; // We can only really set the page number but not load any items
|
||||
|
||||
for( SCH_ITEM* item : aSheet->GetScreen()->Items() )
|
||||
{
|
||||
if( item->IsConnectable() )
|
||||
item->SetConnectivityDirty();
|
||||
|
||||
if( item->Type() == SCH_SYMBOL_T )
|
||||
{
|
||||
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
|
||||
|
||||
updatePastedSymbol( symbol, aSheet->GetScreen(), sheetPath, aClipPath,
|
||||
aForceKeepAnnotations );
|
||||
wxCHECK2( symbol, continue );
|
||||
|
||||
// Only do this once if the symbol is shared across multiple sheets.
|
||||
if( !m_pastedSymbols.count( symbol ) )
|
||||
{
|
||||
for( SCH_PIN* pin : symbol->GetPins() )
|
||||
{
|
||||
const_cast<KIID&>( pin->m_Uuid ) = KIID();
|
||||
pin->SetConnectivityDirty();
|
||||
}
|
||||
}
|
||||
|
||||
updatePastedSymbol( symbol, sheetPath, aClipPath, aForceKeepAnnotations );
|
||||
}
|
||||
else if( item->Type() == SCH_SHEET_T )
|
||||
{
|
||||
SCH_SHEET* subsheet = static_cast<SCH_SHEET*>( item );
|
||||
|
||||
wxCHECK2( subsheet, continue );
|
||||
|
||||
// Make sure pins get a new UUID and set the dirty connectivity flag.
|
||||
if( !aPastedSheets->ContainsSheet( subsheet ) )
|
||||
{
|
||||
for( SCH_SHEET_PIN* pin : subsheet->GetPins() )
|
||||
{
|
||||
const_cast<KIID&>( pin->m_Uuid ) = KIID();
|
||||
pin->SetConnectivityDirty();
|
||||
}
|
||||
}
|
||||
|
||||
KIID_PATH newClipPath = aClipPath;
|
||||
newClipPath.push_back( subsheet->m_Uuid );
|
||||
|
||||
updatePastedSheet( sheetPath, newClipPath, subsheet, aForceKeepAnnotations,
|
||||
aPastedSheetsSoFar, aPastedSymbolsSoFar );
|
||||
|
||||
SCH_SHEET_PATH subSheetPath = sheetPath;
|
||||
|
||||
subSheetPath.push_back( subsheet );
|
||||
subSheetPath.GetSymbols( *aPastedSymbolsSoFar );
|
||||
updatePastedSheet( subsheet, sheetPath, newClipPath, aForceKeepAnnotations,
|
||||
aPastedSheets, aPastedSymbols );
|
||||
}
|
||||
}
|
||||
|
||||
sheetPath.GetSymbols( aPastedSymbols[aPastePath] );
|
||||
|
||||
return sheetPath;
|
||||
}
|
||||
|
||||
|
||||
void SCH_EDITOR_CONTROL::setClipboardInstances( const SCH_SCREEN* aPastedScreen )
|
||||
void SCH_EDITOR_CONTROL::setPastedSymbolInstances( const SCH_SCREEN* aScreen )
|
||||
{
|
||||
m_clipboardSheetInstances.clear();
|
||||
wxCHECK( aScreen, /* void */ );
|
||||
|
||||
for( const SCH_SHEET_INSTANCE& sheet : aPastedScreen->GetSheetInstances() )
|
||||
m_clipboardSheetInstances[sheet.m_Path] = sheet;
|
||||
for( SCH_ITEM* item : aScreen->Items() )
|
||||
{
|
||||
if( item->Type() == SCH_SYMBOL_T )
|
||||
{
|
||||
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
|
||||
|
||||
m_clipboardSymbolInstances.clear();
|
||||
wxCHECK2( symbol, continue );
|
||||
|
||||
for( const SCH_SYMBOL_INSTANCE& symbol : aPastedScreen->GetSymbolInstances() )
|
||||
m_clipboardSymbolInstances[symbol.m_Path] = symbol;
|
||||
for( const SCH_SYMBOL_INSTANCE& symbolInstance : symbol->GetInstanceReferences() )
|
||||
{
|
||||
KIID_PATH pathWithSymbol = symbolInstance.m_Path;
|
||||
|
||||
pathWithSymbol.push_back( symbol->m_Uuid );
|
||||
|
||||
m_clipboardSymbolInstances[pathWithSymbol] = symbolInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SCH_EDITOR_CONTROL::prunePastedSymbolInstances()
|
||||
{
|
||||
wxCHECK( m_frame, /* void */ );
|
||||
|
||||
for( SCH_SYMBOL* symbol : m_pastedSymbols )
|
||||
{
|
||||
wxCHECK2( symbol, continue );
|
||||
|
||||
std::vector<KIID_PATH> instancePathsToRemove;
|
||||
|
||||
for( const SCH_SYMBOL_INSTANCE& instance : symbol->GetInstanceReferences() )
|
||||
{
|
||||
if( ( instance.m_ProjectName != m_frame->Prj().GetProjectName() )
|
||||
|| instance.m_Path.empty() )
|
||||
instancePathsToRemove.emplace_back( instance.m_Path );
|
||||
}
|
||||
|
||||
for( const KIID_PATH& path : instancePathsToRemove )
|
||||
symbol->RemoveInstance( path );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1523,8 +1661,11 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
|
||||
tempScreen->Append( text_item );
|
||||
}
|
||||
|
||||
// Save loaded screen instances to m_clipboardSheetInstances
|
||||
setClipboardInstances( tempScreen );
|
||||
m_pastedSymbols.clear();
|
||||
m_clipboardSymbolInstances.clear();
|
||||
|
||||
// Save pasted symbol instances.
|
||||
setPastedSymbolInstances( tempScreen );
|
||||
|
||||
tempScreen->MigrateSimModels();
|
||||
|
||||
@@ -1616,6 +1757,13 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
|
||||
EDA_ITEM* item = loadedItems[i];
|
||||
KIID_PATH clipPath( wxT( "/" ) ); // clipboard is at root
|
||||
|
||||
SCH_ITEM* schItem = static_cast<SCH_ITEM*>( item );
|
||||
|
||||
wxCHECK2( schItem, continue );
|
||||
|
||||
if( schItem->IsConnectable() )
|
||||
schItem->SetConnectivityDirty();
|
||||
|
||||
if( item->Type() == SCH_SYMBOL_T )
|
||||
{
|
||||
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
|
||||
@@ -1647,14 +1795,17 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
|
||||
}
|
||||
|
||||
for( SCH_SHEET_PATH& instance : pasteInstances )
|
||||
updatePastedSymbol( symbol, tempScreen, instance, clipPath, forceKeepAnnotations );
|
||||
updatePastedSymbol( symbol, instance, clipPath, forceKeepAnnotations );
|
||||
|
||||
// Assign a new KIID
|
||||
const_cast<KIID&>( item->m_Uuid ) = KIID();
|
||||
|
||||
// Make sure pins get a new UUID
|
||||
for( SCH_PIN* pin : symbol->GetPins() )
|
||||
{
|
||||
const_cast<KIID&>( pin->m_Uuid ) = KIID();
|
||||
pin->SetConnectivityDirty();
|
||||
}
|
||||
|
||||
for( SCH_SHEET_PATH& instance : pasteInstances )
|
||||
{
|
||||
@@ -1727,6 +1878,9 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
|
||||
m_frame->InitSheet( sheet, sheet->GetFileName() );
|
||||
}
|
||||
|
||||
// Save the symbol instances in case the user chooses to keep the existing
|
||||
// symbol annotation.
|
||||
setPastedSymbolInstances( sheet->GetScreen() );
|
||||
sheetsPasted = true;
|
||||
|
||||
// Push it to the clipboard path while it still has its old KIID
|
||||
@@ -1737,18 +1891,19 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
|
||||
|
||||
// Make sure pins get a new UUID
|
||||
for( SCH_SHEET_PIN* pin : sheet->GetPins() )
|
||||
{
|
||||
const_cast<KIID&>( pin->m_Uuid ) = KIID();
|
||||
pin->SetConnectivityDirty();
|
||||
}
|
||||
|
||||
// Once we have our new KIID we can update all pasted instances. This will either
|
||||
// reset the annotations or copy "kept" annotations from the supplementary clipboard.
|
||||
for( SCH_SHEET_PATH& instance : pasteInstances )
|
||||
{
|
||||
SCH_SHEET_PATH sheetPath = updatePastedSheet( instance, clipPath, sheet,
|
||||
( forceKeepAnnotations && annotate.automatic ),
|
||||
&pastedSheets[instance],
|
||||
&pastedSymbols[instance] );
|
||||
|
||||
sheetPath.GetSymbols( pastedSymbols[instance] );
|
||||
SCH_SHEET_PATH subPath = updatePastedSheet( sheet, instance, clipPath,
|
||||
( forceKeepAnnotations && annotate.automatic ),
|
||||
&pastedSheets[instance],
|
||||
pastedSymbols );
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1791,16 +1946,12 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
|
||||
getView()->Hide( item, true );
|
||||
}
|
||||
|
||||
pasteInstances.SortByPageNumbers();
|
||||
|
||||
if( sheetsPasted )
|
||||
{
|
||||
// Update page numbers: Find next free numeric page number
|
||||
for( SCH_SHEET_PATH& instance : pasteInstances )
|
||||
for( SCH_SHEET_PATH& sheetPath : pasteInstances )
|
||||
{
|
||||
pastedSheets[instance].SortByPageNumbers();
|
||||
|
||||
for( SCH_SHEET_PATH& pastedSheet : pastedSheets[instance] )
|
||||
for( SCH_SHEET_PATH& pastedSheet : pastedSheets[sheetPath] )
|
||||
{
|
||||
int page = 1;
|
||||
wxString pageNum = wxString::Format( "%d", page );
|
||||
@@ -1808,8 +1959,33 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
|
||||
while( hierarchy.PageNumberExists( pageNum ) )
|
||||
pageNum = wxString::Format( "%d", ++page );
|
||||
|
||||
pastedSheet.SetPageNumber( pageNum );
|
||||
SCH_SHEET_INSTANCE sheetInstance;
|
||||
|
||||
sheetInstance.m_Path = pastedSheet.Path();
|
||||
|
||||
// Don't include the actual sheet in the instance path.
|
||||
sheetInstance.m_Path.pop_back();
|
||||
sheetInstance.m_PageNumber = pageNum;
|
||||
sheetInstance.m_ProjectName = m_frame->Prj().GetProjectName();
|
||||
|
||||
SCH_SHEET* sheet = pastedSheet.Last();
|
||||
|
||||
wxCHECK2( sheet, continue );
|
||||
|
||||
sheet->AddInstance( sheetInstance );
|
||||
hierarchy.push_back( pastedSheet );
|
||||
|
||||
// Remove all pasted sheet instance data that is not part of the current project.
|
||||
std::vector<KIID_PATH> instancesToRemove;
|
||||
|
||||
for( const SCH_SHEET_INSTANCE& pastedInstance : sheet->GetInstances() )
|
||||
{
|
||||
if( !hierarchy.HasPath( pastedInstance.m_Path ) )
|
||||
instancesToRemove.push_back( pastedInstance.m_Path );
|
||||
}
|
||||
|
||||
for( const KIID_PATH& instancePath : instancesToRemove )
|
||||
sheet->RemoveInstance( instancePath );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1843,33 +2019,82 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
|
||||
annotatedSymbols[sheetPath].AddItem( pastedSymbols[sheetPath][i] );
|
||||
}
|
||||
}
|
||||
|
||||
for( const SCH_SHEET_PATH& pastedSheetPath : pastedSheets[sheetPath] )
|
||||
{
|
||||
for( size_t i = 0; i < pastedSymbols[pastedSheetPath].GetCount(); i++ )
|
||||
{
|
||||
if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS
|
||||
|| pasteMode == PASTE_MODE::RESPECT_OPTIONS
|
||||
|| pastedSymbols[pastedSheetPath][i].AlwaysAnnotate() )
|
||||
{
|
||||
annotatedSymbols[pastedSheetPath].AddItem( pastedSymbols[pastedSheetPath][i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !annotatedSymbols.empty() )
|
||||
{
|
||||
for( SCH_SHEET_PATH& instance : pasteInstances )
|
||||
for( const SCH_SHEET_PATH& path : pasteInstances )
|
||||
{
|
||||
annotatedSymbols[instance].SortByReferenceOnly();
|
||||
annotatedSymbols[path].SortByReferenceOnly();
|
||||
|
||||
if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS )
|
||||
annotatedSymbols[instance].ReannotateDuplicates( existingRefs );
|
||||
annotatedSymbols[path].ReannotateDuplicates( existingRefs );
|
||||
else
|
||||
annotatedSymbols[instance].ReannotateByOptions( (ANNOTATE_ORDER_T) annotate.sort_order,
|
||||
(ANNOTATE_ALGO_T) annotate.method,
|
||||
annotateStartNum, existingRefs,
|
||||
false,
|
||||
&hierarchy );
|
||||
annotatedSymbols[path].ReannotateByOptions( (ANNOTATE_ORDER_T) annotate.sort_order,
|
||||
(ANNOTATE_ALGO_T) annotate.method,
|
||||
annotateStartNum, existingRefs,
|
||||
false,
|
||||
&hierarchy );
|
||||
|
||||
annotatedSymbols[instance].UpdateAnnotation();
|
||||
annotatedSymbols[path].UpdateAnnotation();
|
||||
|
||||
// Update existing refs for next iteration
|
||||
for( size_t i = 0; i < annotatedSymbols[instance].GetCount(); i++ )
|
||||
existingRefs.AddItem( annotatedSymbols[instance][i] );
|
||||
for( size_t i = 0; i < annotatedSymbols[path].GetCount(); i++ )
|
||||
existingRefs.AddItem( annotatedSymbols[path][i] );
|
||||
|
||||
for( const SCH_SHEET_PATH& pastedSheetPath : pastedSheets[path] )
|
||||
{
|
||||
annotatedSymbols[pastedSheetPath].SortByReferenceOnly();
|
||||
|
||||
if( pasteMode == PASTE_MODE::UNIQUE_ANNOTATIONS )
|
||||
{
|
||||
annotatedSymbols[pastedSheetPath].ReannotateDuplicates( existingRefs );
|
||||
}
|
||||
else
|
||||
{
|
||||
annotatedSymbols[pastedSheetPath].ReannotateByOptions( (ANNOTATE_ORDER_T) annotate.sort_order,
|
||||
(ANNOTATE_ALGO_T) annotate.method,
|
||||
annotateStartNum, existingRefs,
|
||||
false,
|
||||
&hierarchy );
|
||||
}
|
||||
|
||||
annotatedSymbols[pastedSheetPath].UpdateAnnotation();
|
||||
|
||||
// Update existing refs for next iteration
|
||||
for( size_t i = 0; i < annotatedSymbols[pastedSheetPath].GetCount(); i++ )
|
||||
existingRefs.AddItem( annotatedSymbols[pastedSheetPath][i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_frame->GetCurrentSheet().UpdateAllScreenReferences();
|
||||
|
||||
// The copy operation creates instance paths that are not valid for the current project or
|
||||
// saved as part of another project. Prune them now so they do not accumulate in the saved
|
||||
// schematic file.
|
||||
prunePastedSymbolInstances();
|
||||
|
||||
SCH_SCREENS allScreens( m_frame->Schematic().Root() );
|
||||
|
||||
allScreens.PruneOrphanedSymbolInstances( m_frame->Prj().GetProjectName(),
|
||||
m_frame->Schematic().GetSheets() );
|
||||
allScreens.PruneOrphanedSheetInstances( m_frame->Prj().GetProjectName(),
|
||||
m_frame->Schematic().GetSheets() );
|
||||
|
||||
// Now clear the previous selection, select the pasted items, and fire up the "move" tool.
|
||||
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
|
||||
m_toolMgr->RunAction( EE_ACTIONS::addItemsToSel, true, &loadedItems );
|
||||
|
||||
@@ -42,7 +42,8 @@ public:
|
||||
EE_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.EditorControl" ),
|
||||
m_probingPcbToSch( false ),
|
||||
m_pickerItem( nullptr ),
|
||||
m_duplicateIsHoverSelection( false )
|
||||
m_duplicateIsHoverSelection( false ),
|
||||
m_highlightBusMembers( false )
|
||||
{ }
|
||||
|
||||
~SCH_EDITOR_CONTROL() { }
|
||||
@@ -157,6 +158,13 @@ public:
|
||||
bool aSearchHierarchy, SCH_SEARCH_T aSearchType,
|
||||
const wxString& aSearchText );
|
||||
|
||||
void SetHighlightBusMembers( bool aHighlightBusMembers )
|
||||
{
|
||||
m_highlightBusMembers = aHighlightBusMembers;
|
||||
}
|
||||
|
||||
bool GetHighlightBusMembers() const { return m_highlightBusMembers; }
|
||||
|
||||
private:
|
||||
///< copy selection to clipboard or to m_duplicateClipboard
|
||||
bool doCopy( bool aUseDuplicateClipboard = false );
|
||||
@@ -167,16 +175,25 @@ private:
|
||||
|
||||
void doCrossProbeSchToPcb( const TOOL_EVENT& aEvent, bool aForce );
|
||||
|
||||
void updatePastedSymbol( SCH_SYMBOL* aSymbol, SCH_SCREEN* aPasteScreen,
|
||||
const SCH_SHEET_PATH& aPastePath, const KIID_PATH& aClipPath,
|
||||
bool aForceKeepAnnotations );
|
||||
void updatePastedSymbol( SCH_SYMBOL* aSymbol, const SCH_SHEET_PATH& aPastePath,
|
||||
const KIID_PATH& aClipPath, bool aForceKeepAnnotations );
|
||||
|
||||
SCH_SHEET_PATH updatePastedSheet( const SCH_SHEET_PATH& aPastePath, const KIID_PATH& aClipPath,
|
||||
SCH_SHEET* aSheet, bool aForceKeepAnnotations,
|
||||
SCH_SHEET_LIST* aPastedSheetsSoFar,
|
||||
SCH_REFERENCE_LIST* aPastedSymbolsSoFar );
|
||||
SCH_SHEET_PATH updatePastedSheet( SCH_SHEET* aSheet, const SCH_SHEET_PATH& aPastePath,
|
||||
const KIID_PATH& aClipPath, bool aForceKeepAnnotations,
|
||||
SCH_SHEET_LIST* aPastedSheets,
|
||||
std::map<SCH_SHEET_PATH, SCH_REFERENCE_LIST>& aPastedSymbols );
|
||||
|
||||
void setClipboardInstances( const SCH_SCREEN* aPastedScreen );
|
||||
void setPastedSymbolInstances( const SCH_SCREEN* aScreen );
|
||||
|
||||
/**
|
||||
* Remove all pasted symbol instances that do not belong to the current project.
|
||||
*
|
||||
* @warning This should **only** be called when cleaning up after a paste. Otherwise it
|
||||
* could clobber symbol instances for schematics shared across projects. Use
|
||||
* SCH_SCREENS::PruneOrphanedSymbolInstances() to clean up invalid instance for
|
||||
* the current project.
|
||||
*/
|
||||
void prunePastedSymbolInstances();
|
||||
|
||||
/**
|
||||
* Read the footprint info from each line in the stuff file by reference designator.
|
||||
@@ -211,6 +228,8 @@ private:
|
||||
std::string m_duplicateClipboard; // Temporary storage for Duplicate action
|
||||
bool m_duplicateIsHoverSelection;
|
||||
|
||||
bool m_highlightBusMembers;
|
||||
|
||||
// A map of sheet filename --> screens for the clipboard contents. We use these to hook up
|
||||
// cut/paste operations for unsaved sheet content.
|
||||
std::map<wxString, SCH_SCREEN*> m_supplementaryClipboard;
|
||||
@@ -218,8 +237,7 @@ private:
|
||||
// A map of KIID_PATH --> symbol instances for the clipboard contents.
|
||||
std::map<KIID_PATH, SCH_SYMBOL_INSTANCE> m_clipboardSymbolInstances;
|
||||
|
||||
// A map of KIID_PATH --> sheet instances for the clipboard contents.
|
||||
std::map<KIID_PATH, SCH_SHEET_INSTANCE> m_clipboardSheetInstances;
|
||||
std::set<SCH_SYMBOL*> m_pastedSymbols;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -406,12 +406,14 @@ SCH_LINE* SCH_LINE_WIRE_BUS_TOOL::doUnfoldBus( const wxString& aNet, const VECTO
|
||||
|
||||
getViewControls()->SetCrossHairCursorPosition( m_busUnfold.entry->GetEnd(), false );
|
||||
|
||||
std::vector<DANGLING_END_ITEM> endPoints;
|
||||
std::vector<DANGLING_END_ITEM> endPointsByType;
|
||||
|
||||
for( SCH_ITEM* item : screen->Items().Overlapping( m_busUnfold.entry->GetBoundingBox() ) )
|
||||
item->GetEndPoints( endPoints );
|
||||
item->GetEndPoints( endPointsByType );
|
||||
|
||||
m_busUnfold.entry->UpdateDanglingState( endPoints );
|
||||
std::vector<DANGLING_END_ITEM> endPointsByPos = endPointsByType;
|
||||
DANGLING_END_ITEM_HELPER::sort_dangling_end_items( endPointsByType, endPointsByPos );
|
||||
m_busUnfold.entry->UpdateDanglingState( endPointsByType, endPointsByPos );
|
||||
m_busUnfold.entry->SetEndDangling( false );
|
||||
m_busUnfold.label->SetIsDangling( false );
|
||||
|
||||
@@ -937,6 +939,11 @@ int SCH_LINE_WIRE_BUS_TOOL::doDrawSegments( const TOOL_EVENT& aTool, int aType,
|
||||
m_view->AddToPreview( wire->Clone() );
|
||||
}
|
||||
}
|
||||
else if( evt->IsAction( &ACTIONS::undo ) )
|
||||
{
|
||||
// Dispatch as normal undo event
|
||||
evt->SetPassEvent();
|
||||
}
|
||||
else
|
||||
{
|
||||
wxBell();
|
||||
|
||||
@@ -569,8 +569,14 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
for( EDA_ITEM* item : selection )
|
||||
static_cast<SCH_ITEM*>( item )->GetEndPoints( internalPoints );
|
||||
|
||||
std::vector<DANGLING_END_ITEM> endPointsByType = internalPoints;
|
||||
std::vector<DANGLING_END_ITEM> endPointsByPos = endPointsByType;
|
||||
DANGLING_END_ITEM_HELPER::sort_dangling_end_items( endPointsByType,
|
||||
endPointsByPos );
|
||||
|
||||
for( EDA_ITEM* item : selection )
|
||||
static_cast<SCH_ITEM*>( item )->UpdateDanglingState( internalPoints );
|
||||
static_cast<SCH_ITEM*>( item )->UpdateDanglingState( endPointsByType,
|
||||
endPointsByPos );
|
||||
}
|
||||
|
||||
// Generic setup
|
||||
@@ -603,12 +609,14 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
}
|
||||
else
|
||||
{
|
||||
saveCopyInUndoList( (SCH_ITEM*) item, UNDO_REDO::CHANGED, appendUndo );
|
||||
saveCopyInUndoList( item, UNDO_REDO::CHANGED, appendUndo );
|
||||
appendUndo = true;
|
||||
}
|
||||
|
||||
SCH_ITEM* schItem = (SCH_ITEM*) item;
|
||||
schItem->SetStoredPos( schItem->GetPosition() );
|
||||
item->SetFlags( IS_MOVING );
|
||||
|
||||
if( SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( item ) )
|
||||
schItem->SetStoredPos( schItem->GetPosition() );
|
||||
}
|
||||
|
||||
// Set up the starting position and move/drag offset
|
||||
@@ -823,7 +831,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||
}
|
||||
else if( evt->IsAction( &ACTIONS::duplicate ) )
|
||||
{
|
||||
if( selection.Front()->IsNew() )
|
||||
if( selection.Front() && selection.Front()->IsNew() )
|
||||
{
|
||||
// This doesn't really make sense; we'll just end up dragging a stack of
|
||||
// objects so we ignore the duplicate and just carry on.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2004 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 2004-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2004-2024 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
|
||||
@@ -151,8 +151,6 @@ void HIERARCHY_PANE::UpdateHierarchySelection()
|
||||
m_events_bound = false;
|
||||
}
|
||||
|
||||
bool sheetSelected = false;
|
||||
|
||||
std::function<void( const wxTreeItemId& )> recursiveDescent =
|
||||
[&]( const wxTreeItemId& id )
|
||||
{
|
||||
@@ -162,21 +160,22 @@ void HIERARCHY_PANE::UpdateHierarchySelection()
|
||||
|
||||
if( itemData->m_SheetPath == m_frame->GetCurrentSheet() )
|
||||
{
|
||||
m_tree->EnsureVisible( id );
|
||||
wxTreeItemId parent = m_tree->GetItemParent( id );
|
||||
|
||||
if( parent.IsOk() && !m_tree->IsExpanded( parent ) )
|
||||
m_tree->Expand( parent );
|
||||
|
||||
if( !m_tree->IsVisible( id ) )
|
||||
m_tree->EnsureVisible( id );
|
||||
|
||||
m_tree->SetItemBold( id, true );
|
||||
m_tree->SetFocusedItem( id );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tree->SetItemBold( id, false );
|
||||
}
|
||||
|
||||
if( itemData->m_SheetPath.Last()->IsSelected() )
|
||||
{
|
||||
m_tree->EnsureVisible( id );
|
||||
m_tree->SelectItem( id );
|
||||
sheetSelected = true;
|
||||
}
|
||||
|
||||
wxTreeItemIdValue cookie;
|
||||
wxTreeItemId child = m_tree->GetFirstChild( id, cookie );
|
||||
|
||||
@@ -189,9 +188,6 @@ void HIERARCHY_PANE::UpdateHierarchySelection()
|
||||
|
||||
recursiveDescent( m_tree->GetRootItem() );
|
||||
|
||||
if( !sheetSelected && m_tree->GetSelection() )
|
||||
m_tree->SelectItem( m_tree->GetSelection(), false );
|
||||
|
||||
if( eventsWereBound )
|
||||
{
|
||||
// Enable selection events
|
||||
@@ -231,7 +227,8 @@ void HIERARCHY_PANE::UpdateHierarchyTree()
|
||||
buildHierarchyTree( &m_list, root );
|
||||
UpdateHierarchySelection();
|
||||
|
||||
m_tree->ExpandAll();
|
||||
if( m_tree->ItemHasChildren( root ) )
|
||||
m_tree->Expand( root );
|
||||
|
||||
if( eventsWereBound )
|
||||
{
|
||||
@@ -260,7 +257,7 @@ void HIERARCHY_PANE::onSelectSheetPath( wxTreeEvent& aEvent )
|
||||
|
||||
void HIERARCHY_PANE::onRightClick( wxTreeEvent& aEvent )
|
||||
{
|
||||
wxTreeItemId itemSel = m_tree->GetFocusedItem();
|
||||
wxTreeItemId itemSel = aEvent.GetItem();
|
||||
|
||||
if( !itemSel.IsOk() )
|
||||
return;
|
||||
|
||||
@@ -92,6 +92,7 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( APERTURE_MACRO* aApertMacro,
|
||||
SHAPE_POLY_SET& aShapeBuffer )
|
||||
{
|
||||
// Draw the primitive shape for flashed items.
|
||||
// Note: rotation of primitives inside a macro must be always done around the macro origin.
|
||||
// Create a static buffer to avoid a lot of memory reallocation.
|
||||
static std::vector<VECTOR2I> polybuffer;
|
||||
polybuffer.clear();
|
||||
@@ -218,15 +219,17 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( APERTURE_MACRO* aApertMacro,
|
||||
for( int ii = 0; ii < 4; ii++ )
|
||||
{
|
||||
polybuffer = subshape_poly;
|
||||
EDA_ANGLE sub_rotation = rotation + ANGLE_90 * ii;
|
||||
EDA_ANGLE sub_rotation = ANGLE_90 * ii;
|
||||
|
||||
for( unsigned jj = 0; jj < polybuffer.size(); jj++ )
|
||||
RotatePoint( polybuffer[jj], -sub_rotation );
|
||||
|
||||
// Move to center position given by the tool:
|
||||
// Move to center position given by the tool, and rotate the full shape around
|
||||
// the center position (origin of the macro):
|
||||
for( unsigned jj = 0; jj < polybuffer.size(); jj++ )
|
||||
{
|
||||
polybuffer[jj] += center;
|
||||
RotatePoint( polybuffer[jj], -rotation );
|
||||
}
|
||||
|
||||
aShapeBuffer.NewOutline();
|
||||
@@ -264,6 +267,8 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( APERTURE_MACRO* aApertMacro,
|
||||
VECTOR2I center( mapPt( m_Params[0].GetValueFromMacro( aApertMacro ),
|
||||
m_Params[1].GetValueFromMacro( aApertMacro ), m_GerbMetric ) );
|
||||
|
||||
EDA_ANGLE rotation( m_Params[8].GetValueFromMacro( aApertMacro ), DEGREES_T );
|
||||
|
||||
// adjust outerDiam by this on each nested circle
|
||||
int diamAdjust = ( gap + penThickness ) * 2;
|
||||
|
||||
@@ -272,17 +277,21 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( APERTURE_MACRO* aApertMacro,
|
||||
if( outerDiam <= 0 )
|
||||
break;
|
||||
|
||||
// calculate the rotated position of the center:
|
||||
VECTOR2I circle_center = center;
|
||||
RotatePoint( circle_center, -rotation );
|
||||
|
||||
// Note: outerDiam is the outer diameter of the ring.
|
||||
// the ring graphic diameter is (outerDiam - penThickness)
|
||||
if( outerDiam <= penThickness )
|
||||
{ // No room to draw a ring (no room for the hole):
|
||||
// draw a circle instead (with no hole), with the right diameter
|
||||
TransformCircleToPolygon( aShapeBuffer, center, outerDiam / 2, arc_to_seg_error,
|
||||
TransformCircleToPolygon( aShapeBuffer, circle_center, outerDiam / 2, arc_to_seg_error,
|
||||
ERROR_INSIDE );
|
||||
}
|
||||
else
|
||||
{
|
||||
TransformRingToPolygon( aShapeBuffer, center, ( outerDiam - penThickness ) / 2,
|
||||
TransformRingToPolygon( aShapeBuffer, circle_center, ( outerDiam - penThickness ) / 2,
|
||||
penThickness, arc_to_seg_error, ERROR_INSIDE );
|
||||
}
|
||||
}
|
||||
@@ -290,13 +299,11 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( APERTURE_MACRO* aApertMacro,
|
||||
// Draw the cross:
|
||||
ConvertShapeToPolygon( aApertMacro, polybuffer );
|
||||
|
||||
EDA_ANGLE rotation( m_Params[8].GetValueFromMacro( aApertMacro ), DEGREES_T );
|
||||
|
||||
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
|
||||
{
|
||||
// move crossair shape to center and rotate shape:
|
||||
RotatePoint( polybuffer[ii], -rotation );
|
||||
polybuffer[ii] += center;
|
||||
RotatePoint( polybuffer[ii], -rotation );
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -375,13 +382,13 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( APERTURE_MACRO* aApertMacro,
|
||||
// Creates the shape:
|
||||
ConvertShapeToPolygon( aApertMacro, polybuffer );
|
||||
|
||||
// rotate polygon
|
||||
// move and rotate polygonal shape
|
||||
EDA_ANGLE rotation( m_Params[5].GetValueFromMacro( aApertMacro ), DEGREES_T );
|
||||
|
||||
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
|
||||
{
|
||||
RotatePoint( polybuffer[ii], -rotation );
|
||||
polybuffer[ii] += curPos;
|
||||
RotatePoint( polybuffer[ii], -rotation );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
+1
-1
@@ -404,7 +404,7 @@ void D_CODE::ConvertShapeToPolygon( const GERBER_DRAW_ITEM* aParent )
|
||||
addHoleToPolygon( &m_Polygon, m_DrillShape, m_Drill, initialpos );
|
||||
|
||||
if( !m_Rotation.IsZero() ) // rotate polygonal shape:
|
||||
m_Polygon.Rotate( m_Rotation );
|
||||
m_Polygon.Rotate( -m_Rotation );
|
||||
|
||||
break;
|
||||
|
||||
|
||||
@@ -99,6 +99,10 @@ public:
|
||||
// and the actual coordinates calculation must handle this
|
||||
};
|
||||
|
||||
// size of a single line of text from a gerber file.
|
||||
// warning: some files can have *very long* lines, so the buffer must be large.
|
||||
#define GERBER_BUFZ 1000000
|
||||
|
||||
/**
|
||||
* Hold the image data and parameters for one gerber file and layer parameters.
|
||||
*
|
||||
@@ -455,6 +459,9 @@ public:
|
||||
GERBER_LAYER m_GBRLayerParams; // hold params for the current gerber layer
|
||||
GERBER_DRAW_ITEMS m_drawings; // linked list of Gerber Items to draw
|
||||
|
||||
// A large buffer to store one line
|
||||
static char m_LineBuffer[GERBER_BUFZ+1];
|
||||
|
||||
private:
|
||||
wxArrayString m_messagesList; // A list of messages created when reading a file
|
||||
|
||||
|
||||
@@ -106,7 +106,11 @@ GERBVIEW_FRAME::GERBVIEW_FRAME( KIWAY* aKiway, wxWindow* aParent )
|
||||
wxIcon icon;
|
||||
wxIconBundle icon_bundle;
|
||||
|
||||
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_gerbview ) );
|
||||
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_gerbview, 48 ) );
|
||||
icon_bundle.AddIcon( icon );
|
||||
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_gerbview, 128 ) );
|
||||
icon_bundle.AddIcon( icon );
|
||||
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_gerbview, 256 ) );
|
||||
icon_bundle.AddIcon( icon );
|
||||
icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_gerbview_32 ) );
|
||||
icon_bundle.AddIcon( icon );
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2007-2016 Jean-Pierre Charras jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -223,11 +223,9 @@ bool GERBER_FILE_IMAGE::TestFileIsRS274( const wxString& aFullFileName )
|
||||
return false;
|
||||
}
|
||||
|
||||
// size of a single line of text from a gerber file.
|
||||
// warning: some files can have *very long* lines, so the buffer must be large.
|
||||
#define GERBER_BUFZ 1000000
|
||||
|
||||
// A large buffer to store one line
|
||||
static char lineBuffer[GERBER_BUFZ+1];
|
||||
char GERBER_FILE_IMAGE::m_LineBuffer[GERBER_BUFZ+1];
|
||||
|
||||
bool GERBER_FILE_IMAGE::LoadGerberFile( const wxString& aFullFileName )
|
||||
{
|
||||
@@ -252,11 +250,11 @@ bool GERBER_FILE_IMAGE::LoadGerberFile( const wxString& aFullFileName )
|
||||
|
||||
while( true )
|
||||
{
|
||||
if( fgets( lineBuffer, GERBER_BUFZ, m_Current_File ) == nullptr )
|
||||
if( fgets( m_LineBuffer, GERBER_BUFZ, m_Current_File ) == nullptr )
|
||||
break;
|
||||
|
||||
m_LineNum++;
|
||||
text = StrPurge( lineBuffer );
|
||||
text = StrPurge( m_LineBuffer );
|
||||
|
||||
while( text && *text )
|
||||
{
|
||||
@@ -313,7 +311,7 @@ bool GERBER_FILE_IMAGE::LoadGerberFile( const wxString& aFullFileName )
|
||||
if( m_CommandState != ENTER_RS274X_CMD )
|
||||
{
|
||||
m_CommandState = ENTER_RS274X_CMD;
|
||||
ReadRS274XCommand( lineBuffer, GERBER_BUFZ, text );
|
||||
ReadRS274XCommand( m_LineBuffer, GERBER_BUFZ, text );
|
||||
}
|
||||
else //Error
|
||||
{
|
||||
|
||||
+6
-7
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* @file rs274d.cpp
|
||||
* @brief functions to read the rs274d commands from a rs274d/rs274x file
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
@@ -26,6 +21,11 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief functions to read the rs274d commands from a rs274d/rs274x file
|
||||
*/
|
||||
|
||||
|
||||
#include <gerbview.h>
|
||||
#include <gerbview_frame.h>
|
||||
#include <trigo.h>
|
||||
@@ -464,8 +464,7 @@ bool GERBER_FILE_IMAGE::Execute_G_Command( char*& text, int G_command )
|
||||
ExecuteRS274XCommand( code_command, nullptr, 0, cptr );
|
||||
}
|
||||
|
||||
while( *text && (*text != '*') )
|
||||
text++;
|
||||
GetEndOfBlock( m_LineBuffer, GERBER_BUFZ, text, m_Current_File );
|
||||
|
||||
break;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user