Compare commits
392 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 582732918d | |||
| f1f69c607e | |||
| 8e82fee494 | |||
| a51475a094 | |||
| f25e2d48bd | |||
| 2bbff64a12 | |||
| 70b4503187 | |||
| 912bd4458f | |||
| d3f4494925 | |||
| 464467ae8b | |||
| 8e579ec8e0 | |||
| 4ef6cbf4fb | |||
| 68dfcddbe9 | |||
| 907761f14e | |||
| be7917c8d8 | |||
| 2e25f09ae4 | |||
| ea95d8604a | |||
| 35def3ab2e | |||
| 5527c12a8d | |||
| fb1cc72013 | |||
| 1f34883a27 | |||
| 724262651f | |||
| d7b2247878 | |||
| 372e7b6312 | |||
| 323a2d83fa | |||
| 03c3393616 | |||
| cbff011e3c | |||
| 2ba6fad633 | |||
| bc4878d71e | |||
| e991ae504b | |||
| c18181042f | |||
| 3de80d3b20 | |||
| 39dcd0a352 | |||
| 199e31ea3f | |||
| dce2247925 | |||
| 89e78c0276 | |||
| 9a57c11348 | |||
| 1dbe8b2a79 | |||
| 29fd0caf58 | |||
| d30701ed59 | |||
| e39550e77f | |||
| a21e7a5eee | |||
| 927b5ae707 | |||
| f59626004c | |||
| 2ece2719d0 | |||
| 78ee542d8d | |||
| cea9b38815 | |||
| cb8f6db68d | |||
| 85038c2b46 | |||
| 1e8055f504 | |||
| a7a5f20d1c | |||
| 0d744a4e74 | |||
| 216ec60dc1 | |||
| 3d9047bec4 | |||
| 08d65beb26 | |||
| 5cab66fb18 | |||
| 9466624f9d | |||
| 80b842a704 | |||
| d513a9fe5c | |||
| c98081cb04 | |||
| 17a1dc18be | |||
| b22ff229db | |||
| 23b03fd6ab | |||
| 97b273905a | |||
| e759c4d27a | |||
| 76685ae2d9 | |||
| 3fad3ceb35 | |||
| dede9e8549 | |||
| 97c018118d | |||
| 8b1ce36402 | |||
| 7931f315b1 | |||
| abb6404ab2 | |||
| c434542c65 | |||
| 42b7aa6450 | |||
| f2ce9cf857 | |||
| 56134d0202 | |||
| f33bbe2d5d | |||
| 59a478bdc5 | |||
| 141b332d4f | |||
| d4a312d6cb | |||
| 31d688b34c | |||
| fbef9ea600 | |||
| 0688491e1b | |||
| 434161687e | |||
| 4b3709b96b | |||
| 1fa993303d | |||
| 01897e7755 | |||
| 7040b2178d | |||
| edf23c4c18 | |||
| b0b9e66fad | |||
| 89488a43b9 | |||
| 798e13f70d | |||
| e758391a23 | |||
| 00d1e01e12 | |||
| 4f265a52a2 | |||
| 560717de76 | |||
| 0f40894317 | |||
| 3915e882a8 | |||
| c5caa23a63 | |||
| 36978d2ddc | |||
| 3f90c895b9 | |||
| 2ada171806 | |||
| 5dc683c968 | |||
| 7026cfe140 | |||
| b7cd1dd764 | |||
| 09bb8fc4f4 | |||
| 746ab49d36 | |||
| 1614dc975a | |||
| ba7598d90d | |||
| 92fc4872e8 | |||
| 30dbfc33a4 | |||
| b3de5aa08e | |||
| ba4773e448 | |||
| a713ee852c | |||
| a65accd412 | |||
| 1dc9583e06 | |||
| 3afe02ac1f | |||
| 57aa61f1ba | |||
| 121ea14fe4 | |||
| 9d457dc0ab | |||
| befd836ab4 | |||
| 044c301d64 | |||
| 94fd0df2e2 | |||
| e5087ca3db | |||
| 819a9da599 | |||
| fb02e55424 | |||
| 70e86434ef | |||
| c41b1e2f06 | |||
| 64641c28ef | |||
| 69e9f4ada2 | |||
| d28cf632e4 | |||
| b466bfa6c8 | |||
| 1c06f4cf06 | |||
| 25f40566ed | |||
| e8fa2cbc4d | |||
| 779c441e0a | |||
| e33031ee7d | |||
| ae63313b55 | |||
| ae50b8d839 | |||
| 10a27156c2 | |||
| 94057886a3 | |||
| 2d9bcb6e4f | |||
| 249bcd9e1a | |||
| b2679b7648 | |||
| 9995b8714b | |||
| 7b4dd2f7f5 | |||
| cc6b01cf88 | |||
| 3568ff72bf | |||
| e20614660b | |||
| c5a69f073c | |||
| 3025671b1a | |||
| 74da0043b4 | |||
| c0ddca12df | |||
| bf55e610b9 | |||
| 4e775a4090 | |||
| 9f7b31b5c5 | |||
| 279641df73 | |||
| 9e1fd16329 | |||
| d6ff5f0239 | |||
| 3f5d3fa0c6 | |||
| 51dc2b109e | |||
| 2358ff6f07 | |||
| 11788d2f39 | |||
| 541f7467c6 | |||
| 411c9707ee | |||
| ee0ba17c03 | |||
| 64bc850d8f | |||
| 154f64dae3 | |||
| 7fa758358f | |||
| f135881bd6 | |||
| 839301f81e | |||
| 04f4ca9772 | |||
| 525328fba1 | |||
| 471c125c1a | |||
| 8ef99137c6 | |||
| 404cad062a | |||
| d4be813f2e | |||
| ab3c0b2f03 | |||
| defcfc2962 | |||
| 267cfdf54b | |||
| a7b0231b3c | |||
| 7c19958840 | |||
| 34c3bb7d2c | |||
| b37545ee6c | |||
| c1e924c894 | |||
| 200e9e28ea | |||
| b95f958890 | |||
| fe9666bdaf | |||
| 948de5dc79 | |||
| 8800fd8250 | |||
| b1e5d8c915 | |||
| 02aec8b091 | |||
| 50517f6aa6 | |||
| a752473280 | |||
| 7e1972d483 | |||
| de48bf04bc | |||
| 228bf66cac | |||
| c986c1d26a | |||
| b0f7ea5b16 | |||
| 8b2e2ff1f8 | |||
| d00166223f | |||
| 4701b4bfc2 | |||
| e4c74c727f | |||
| f626ce29c4 | |||
| 768d8e5811 | |||
| 2ac3a4a103 | |||
| bb512f3fc0 | |||
| d6e7a89c97 | |||
| a5455da909 | |||
| 8dadc698cc | |||
| 2127712115 | |||
| d5b635027e | |||
| 9b2aeda51e | |||
| 5aba9b539f | |||
| b82020722b | |||
| b62a8fe65a | |||
| a5d85e3281 | |||
| e699bcf5a3 | |||
| 7ef5e079fd | |||
| 4076461347 | |||
| d610486c1e | |||
| 1891e2ad68 | |||
| f1e060902b | |||
| 7dbd920912 | |||
| 05ab9e3836 | |||
| a4e0f1f7aa | |||
| a8f27d13e6 | |||
| 05d425ea88 | |||
| 3cb12b5a60 | |||
| 8f1237e629 | |||
| 2c7f44f78d | |||
| a9447aa8c7 | |||
| 9b61b350fe | |||
| e3cf65fbdf | |||
| e51d43568e | |||
| 1bb6b7acdd | |||
| adc7a3ba4a | |||
| 94ec6cc362 | |||
| bbdb5eb6e3 | |||
| e487ca8bd8 | |||
| f5b0e20f78 | |||
| 6116eebbad | |||
| 8619705e44 | |||
| c216ed2d1f | |||
| e17dc25bba | |||
| d311915f9d | |||
| 3a95826b42 | |||
| dcc1009162 | |||
| d61e01ff4f | |||
| 51b9d8e7ad | |||
| 90eb5e9c31 | |||
| 17c34c88dc | |||
| ff6f658f9d | |||
| fb798a4150 | |||
| 4213bb3a62 | |||
| 8a34f91172 | |||
| 764ddd4773 | |||
| ea0dcc8ebd | |||
| 3f5db9f7f9 | |||
| a6a0bba1b7 | |||
| 5ec785e2f7 | |||
| f7d9f1f69d | |||
| 42efd2d005 | |||
| d32e13daee | |||
| e82c21e944 | |||
| 33f835a437 | |||
| 59d8110801 | |||
| d028b381fa | |||
| a1a3f810f0 | |||
| c96f0f2396 | |||
| 46c8985661 | |||
| c588639503 | |||
| b3c6f559b2 | |||
| 85544d109c | |||
| 4aba595b2b | |||
| b2241dca72 | |||
| 4ffe742b69 | |||
| 5979b8e385 | |||
| 955bd5a6d1 | |||
| 1eb8191519 | |||
| 396bda5611 | |||
| cb334be8c4 | |||
| 8845cc0556 | |||
| e34800ad49 | |||
| 5b574901b3 | |||
| 59b68154e1 | |||
| 5a501c8e48 | |||
| f927c15adf | |||
| d08157f7db | |||
| 8a9ac4f01f | |||
| 39df5f3b15 | |||
| 981bf328ae | |||
| 1f8e9727b0 | |||
| f604bcb557 | |||
| eccf9eb4a4 | |||
| 39403fa885 | |||
| 5e7cc30564 | |||
| f942b4c657 | |||
| f5aeb5b068 | |||
| 7f6cb9b07b | |||
| db3657d411 | |||
| 38e5da724d | |||
| 24a63eb304 | |||
| c1f5ae1c5a | |||
| 009211c740 | |||
| 1a208a1612 | |||
| b867e51c6c | |||
| 7693b93c50 | |||
| c3d7158669 | |||
| 9f5e50f25e | |||
| a091ab76d7 | |||
| d5eb242295 | |||
| b21e65fc5f | |||
| 1b07e81936 | |||
| 962b2d45ef | |||
| 7894b41277 | |||
| 51d0b8d2b5 | |||
| 7b992a1dc4 | |||
| 2f8615c6c4 | |||
| aee6d9d01c | |||
| fd4a0dbedf | |||
| 14381ac68a | |||
| c00a98fed4 | |||
| aab7581909 | |||
| 74dcc1b9d5 | |||
| 17241b3543 | |||
| a4a859f47b | |||
| b66ed8bc41 | |||
| 754feff5e7 | |||
| cd1b425a80 | |||
| 187947e8d8 | |||
| 6b38927123 | |||
| f46e4049b6 | |||
| 0ea8299fa7 | |||
| 5d793193e0 | |||
| 62337f75b8 | |||
| 4d4fdfff70 | |||
| b63d0a3138 | |||
| 7949c09183 | |||
| 3f535aca8c | |||
| 9f44809164 | |||
| f7ccb18af5 | |||
| cca9945867 | |||
| f23c6b0c2f | |||
| 6d22b8c6ed | |||
| 245ce7259c | |||
| f36cd60fdb | |||
| 8467e2d376 | |||
| 2529918d5f | |||
| e2711a6121 | |||
| 89d22e5f94 | |||
| f13fda9be5 | |||
| 49f6a63a06 | |||
| e078fea846 | |||
| 048c8b1670 | |||
| 3b5c38d861 | |||
| 90fb075e34 | |||
| 08c6d9ce96 | |||
| 76ccb8c31f | |||
| 3dfc502814 | |||
| df0f626283 | |||
| 1909ce9220 | |||
| 15bef82e1e | |||
| 60a45241e6 | |||
| d403e92315 | |||
| eed7ede376 | |||
| d20f49b58b | |||
| 37091df142 | |||
| 21081cf80f | |||
| c213b37e96 | |||
| d1ca84aa43 | |||
| 0f7fbc411a | |||
| f4b2b1b03f | |||
| 0ecc36c4a5 | |||
| a48eace90a | |||
| 7a2a51ad44 | |||
| f56fcb0a14 | |||
| 7816652078 | |||
| 20aacc7026 | |||
| 49938cfd09 | |||
| 53a4ed6b24 | |||
| 534000b49d | |||
| 7e2ccbf909 | |||
| b0b6968185 | |||
| 94963b5b3a | |||
| 77fa61e6fc | |||
| 94c450ad16 | |||
| a292bf7c83 | |||
| b24ee1c44f | |||
| 981b22ba49 | |||
| e1eedd3bba | |||
| b949fd4d43 |
@@ -0,0 +1,20 @@
|
||||
<!-- --------Before Creating a New Issue-----------
|
||||
* Limit report to a single issue.
|
||||
* Search the issue tracker to verify the issue has not already been reported.
|
||||
* Complete all instructions between `template comment markers <>.
|
||||
* Keep report contents limited to the necessary information required to fix the issue.
|
||||
* When creating an issue against the stable version of KiCad, make sure the latest available stable version is installed as issues may have already been resolved in later stable versions. -->
|
||||
# Description
|
||||
<!-- What is the current behavior and what is the expected behavior? -->
|
||||
<!-- If the issue is visual/graphical, please attach screenshots of the problem. -->
|
||||
<!-- Add the issue details below this line and before the "Steps to reproduce" heading. -->
|
||||
|
||||
# Steps to reproduce
|
||||
<!-- If there are multiple steps to reproduce it or it is a visual issue, then providing a screen recording as an attachment to this report is recommended. -->
|
||||
<!-- If this issue is specific to a project, please attach the necessary files to this issue. -->
|
||||
<!-- Add the steps to reproduce using the numbers below -->
|
||||
<!-- Add new step numbers before the "KiCad Version" heading. -->
|
||||
1.
|
||||
|
||||
# KiCad Version
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2022 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* 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
|
||||
@@ -671,7 +671,8 @@ bool BOARD_ADAPTER::createBoardPolygon( wxString* aErrorMsg )
|
||||
return false;
|
||||
}
|
||||
|
||||
int chainingEpsilon = pcbIUScale.mmToIU( 0.02 ); // max dist from one endPt to next startPt
|
||||
// max dist from one endPt to next startPt
|
||||
int chainingEpsilon = m_board->GetOutlinesChainingEpsilon();
|
||||
|
||||
success = BuildFootprintPolygonOutlines( m_board, m_board_poly,
|
||||
m_board->GetDesignSettings().m_MaxError,
|
||||
|
||||
@@ -342,8 +342,7 @@ private:
|
||||
OBJECT_2D* createPadWithDrill( const PAD* aPad, int aInflateValue );
|
||||
|
||||
void addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
|
||||
PCB_LAYER_ID aLayerId, bool aSkipNPTHPadsWihNoCopper, bool aSkipPlatedPads,
|
||||
bool aSkipNonPlatedPads );
|
||||
PCB_LAYER_ID aLayerId, bool aSkipPlatedPads, bool aSkipNonPlatedPads );
|
||||
|
||||
void addFootprintShapes( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
|
||||
PCB_LAYER_ID aLayerId );
|
||||
|
||||
@@ -145,7 +145,7 @@ void BOARD_ADAPTER::addText( const EDA_TEXT* aText, CONTAINER_2D_BASE* aContaine
|
||||
void BOARD_ADAPTER::addShape( const PCB_DIMENSION_BASE* aDimension, CONTAINER_2D_BASE* aContainer,
|
||||
const BOARD_ITEM* aOwner )
|
||||
{
|
||||
addText( &aDimension->Text(), aContainer, aDimension );
|
||||
addText( aDimension, aContainer, aDimension );
|
||||
|
||||
const int linewidth = aDimension->GetLineThickness();
|
||||
|
||||
@@ -275,6 +275,10 @@ void BOARD_ADAPTER::createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDs
|
||||
int arcsegcount = GetArcToSegmentCount( radius, ARC_HIGH_DEF, arc_angle );
|
||||
int circlesegcount;
|
||||
|
||||
// Avoid arcs that cannot be drawn
|
||||
if( radius < std::numeric_limits<double>::min() || arc_angle.IsZero() )
|
||||
break;
|
||||
|
||||
// We need a circle to segment count. However, the arc angle can be small, and the
|
||||
// radius very big. so we calculate a reasonable value for circlesegcount.
|
||||
if( arcsegcount <= 1 ) // The arc will be approximated by a segment
|
||||
@@ -488,41 +492,24 @@ OBJECT_2D* BOARD_ADAPTER::createPadWithDrill( const PAD* aPad, int aInflateValue
|
||||
|
||||
|
||||
void BOARD_ADAPTER::addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aContainer,
|
||||
PCB_LAYER_ID aLayerId, bool aSkipNPTHPadsWihNoCopper,
|
||||
bool aSkipPlatedPads, bool aSkipNonPlatedPads )
|
||||
PCB_LAYER_ID aLayerId, bool aSkipPlatedPads, bool aSkipNonPlatedPads )
|
||||
{
|
||||
for( PAD* pad : aFootprint->Pads() )
|
||||
{
|
||||
if( !pad->IsOnLayer( aLayerId ) )
|
||||
continue;
|
||||
|
||||
// Skip pad annulus when not connected on this layer (if removing is enabled)
|
||||
if( !pad->FlashLayer( aLayerId ) && IsCopperLayer( aLayerId ) )
|
||||
continue;
|
||||
|
||||
// NPTH pads are not drawn on layers if the shape size and pos is the same as their hole:
|
||||
if( aSkipNPTHPadsWihNoCopper && ( pad->GetAttribute() == PAD_ATTRIB::NPTH ) )
|
||||
if( IsCopperLayer( aLayerId ) )
|
||||
{
|
||||
if( pad->GetDrillSize() == pad->GetSize() && pad->GetOffset() == wxPoint( 0, 0 ) )
|
||||
{
|
||||
switch( pad->GetShape() )
|
||||
{
|
||||
case PAD_SHAPE::CIRCLE:
|
||||
if( pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
|
||||
continue;
|
||||
// Skip pad annulus when there isn't one (note: this is more discerning than
|
||||
// pad->IsOnLayer(), which doesn't check for NPTH pads with holes that consume
|
||||
// the entire pad).
|
||||
if( !pad->IsOnCopperLayer() )
|
||||
continue;
|
||||
|
||||
break;
|
||||
|
||||
case PAD_SHAPE::OVAL:
|
||||
if( pad->GetDrillShape() != PAD_DRILL_SHAPE_CIRCLE )
|
||||
continue;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Skip pad annulus when not connected on this layer (if removing is enabled)
|
||||
if( !pad->FlashLayer( aLayerId ) )
|
||||
continue;
|
||||
}
|
||||
|
||||
VECTOR2I margin( 0, 0 );
|
||||
|
||||
@@ -525,9 +525,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||
// ADD PADS
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
{
|
||||
// Note: NPTH pads are not drawn on copper layers when the pad has the same shape
|
||||
// as its hole
|
||||
addPads( footprint, layerContainer, layer, true, renderPlatedPadsAsPlated, false );
|
||||
addPads( footprint, layerContainer, layer, renderPlatedPadsAsPlated, false );
|
||||
|
||||
// Micro-wave footprints may have items on copper layers
|
||||
addFootprintShapes( footprint, layerContainer, layer );
|
||||
@@ -539,8 +537,8 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||
// ADD PLATED PADS
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
{
|
||||
addPads( footprint, m_platedPadsFront, F_Cu, true, false, true );
|
||||
addPads( footprint, m_platedPadsBack, B_Cu, true, false, true );
|
||||
addPads( footprint, m_platedPadsFront, F_Cu, false, true );
|
||||
addPads( footprint, m_platedPadsBack, B_Cu, false, true );
|
||||
}
|
||||
|
||||
m_platedPadsFront->BuildBVH();
|
||||
@@ -995,7 +993,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
||||
}
|
||||
else
|
||||
{
|
||||
addPads( footprint, layerContainer, layer, false, false, false );
|
||||
addPads( footprint, layerContainer, layer, false, false );
|
||||
}
|
||||
|
||||
addFootprintShapes( footprint, layerContainer, layer );
|
||||
|
||||
@@ -383,6 +383,15 @@ void EDA_3D_CANVAS::DoRePaint()
|
||||
if( m_glRC == nullptr )
|
||||
m_glRC = GL_CONTEXT_MANAGER::Get().CreateCtx( this );
|
||||
|
||||
// CreateCtx could and does fail per sentry crash events, lets be graceful
|
||||
if( m_glRC == nullptr )
|
||||
{
|
||||
warningReporter.Report( _( "OpenGL context creation error" ), RPT_SEVERITY_ERROR );
|
||||
warningReporter.Finalize();
|
||||
m_is_currently_painting.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC, this );
|
||||
|
||||
// Set the OpenGL viewport according to the client size of this canvas.
|
||||
|
||||
@@ -257,6 +257,13 @@ void EDA_3D_MODEL_VIEWER::OnPaint( wxPaintEvent& event )
|
||||
if( m_glRC == nullptr )
|
||||
m_glRC = GL_CONTEXT_MANAGER::Get().CreateCtx( this );
|
||||
|
||||
// CreateCtx could and does fail per sentry crash events, lets be graceful
|
||||
if( m_glRC == nullptr )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::OnPaint creating gl context failed" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC, this );
|
||||
|
||||
// Set the OpenGL viewport according to the client size of this canvas.
|
||||
@@ -323,8 +330,16 @@ void EDA_3D_MODEL_VIEWER::OnPaint( wxPaintEvent& event )
|
||||
m_ogl_3dmodel->BeginDrawMulti( true );
|
||||
|
||||
m_ogl_3dmodel->DrawOpaque( false );
|
||||
|
||||
glDepthMask( GL_FALSE );
|
||||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
m_ogl_3dmodel->DrawTransparent( 1.0f, false );
|
||||
|
||||
glDisable( GL_BLEND );
|
||||
glDepthMask( GL_TRUE );
|
||||
|
||||
m_ogl_3dmodel->EndDrawMulti();
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
@@ -27,13 +27,14 @@
|
||||
* @file c_ogl_3dmodel.cpp
|
||||
* @brief
|
||||
*/
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <gal/opengl/kiglew.h> // Must be included first
|
||||
|
||||
#include "3d_model.h"
|
||||
#include "opengl_utils.h"
|
||||
#include "../common_ogl/ogl_utils.h"
|
||||
#include "../3d_math.h"
|
||||
#include <utility>
|
||||
#include <wx/debug.h>
|
||||
#include <wx/log.h>
|
||||
#include <chrono>
|
||||
@@ -177,9 +178,11 @@ MODEL_3D::MODEL_3D( const S3DMODEL& a3DModel, MATERIAL_MODE aMaterialMode )
|
||||
// use material color for mesh bounding box or some sort of average vertex color.
|
||||
glm::vec3 avg_color = material.m_Diffuse;
|
||||
|
||||
BBOX_3D &mesh_bbox = m_meshes_bbox[mesh_i];
|
||||
|
||||
for( unsigned int vtx_i = 0; vtx_i < mesh.m_VertexSize; ++vtx_i )
|
||||
{
|
||||
m_meshes_bbox[mesh_i].Union( mesh.m_Positions[vtx_i] );
|
||||
mesh_bbox.Union( mesh.m_Positions[vtx_i] );
|
||||
|
||||
VERTEX& vtx_out = mesh_group.m_vertices[vtx_offset + vtx_i];
|
||||
|
||||
@@ -222,16 +225,19 @@ MODEL_3D::MODEL_3D( const S3DMODEL& a3DModel, MATERIAL_MODE aMaterialMode )
|
||||
}
|
||||
}
|
||||
|
||||
if( m_meshes_bbox[mesh_i].IsInitialized() )
|
||||
if( mesh_bbox.IsInitialized() )
|
||||
{
|
||||
// generate geometry for the bounding box
|
||||
MakeBbox( m_meshes_bbox[mesh_i], ( mesh_i + 1 ) * bbox_vtx_count,
|
||||
MakeBbox( mesh_bbox, ( mesh_i + 1 ) * bbox_vtx_count,
|
||||
&bbox_tmp_vertices[( mesh_i + 1 ) * bbox_vtx_count],
|
||||
&bbox_tmp_indices[( mesh_i + 1 ) * bbox_idx_count],
|
||||
{ avg_color, 1.0f } );
|
||||
|
||||
// bump the outer bounding box
|
||||
m_model_bbox.Union( m_meshes_bbox[mesh_i] );
|
||||
m_model_bbox.Union( mesh_bbox );
|
||||
|
||||
// add to the material group
|
||||
material.m_bbox.Union( mesh_bbox );
|
||||
}
|
||||
|
||||
|
||||
@@ -410,7 +416,9 @@ void MODEL_3D::EndDrawMulti()
|
||||
|
||||
|
||||
void MODEL_3D::Draw( bool aTransparent, float aOpacity, bool aUseSelectedMaterial,
|
||||
SFVEC3F& aSelectionColor ) const
|
||||
const SFVEC3F& aSelectionColor,
|
||||
const glm::mat4 *aModelWorldMatrix,
|
||||
const SFVEC3F *aCameraWorldPos ) const
|
||||
{
|
||||
if( aOpacity <= FLT_EPSILON )
|
||||
return;
|
||||
@@ -439,27 +447,102 @@ void MODEL_3D::Draw( bool aTransparent, float aOpacity, bool aUseSelectedMateria
|
||||
|
||||
glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (const float*)¶m.x );
|
||||
|
||||
for( const MODEL_3D::MATERIAL& mat : m_materials )
|
||||
std::vector<const MODEL_3D::MATERIAL *> materialsToRender;
|
||||
|
||||
materialsToRender.reserve( m_materials.size() );
|
||||
|
||||
if( aModelWorldMatrix && aCameraWorldPos )
|
||||
{
|
||||
if( ( mat.IsTransparent() != aTransparent )
|
||||
// Sort Material groups
|
||||
|
||||
std::vector<std::pair<const MODEL_3D::MATERIAL*, float>> materialsSorted;
|
||||
|
||||
// Calculate the distance to the camera for each material group
|
||||
for( const MODEL_3D::MATERIAL& mat : m_materials )
|
||||
{
|
||||
if( mat.m_render_idx_count == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( ( mat.IsTransparent() != aTransparent )
|
||||
&& ( aOpacity >= 1.0f )
|
||||
&& m_materialMode != MATERIAL_MODE::DIFFUSE_ONLY )
|
||||
{
|
||||
continue;
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const BBOX_3D& bBox = mat.m_bbox;
|
||||
const SFVEC3F& bBoxCenter = bBox.GetCenter();
|
||||
const SFVEC3F bBoxWorld = *aModelWorldMatrix * glm::vec4( bBoxCenter, 1.0f );
|
||||
|
||||
const float distanceToCamera = glm::length( *aCameraWorldPos - bBoxWorld );
|
||||
|
||||
materialsSorted.emplace_back( &mat, distanceToCamera );
|
||||
}
|
||||
|
||||
// Sort from back to front
|
||||
std::sort( materialsSorted.begin(), materialsSorted.end(),
|
||||
[&]( std::pair<const MODEL_3D::MATERIAL*, float>& a,
|
||||
std::pair<const MODEL_3D::MATERIAL*, float>& b ) {
|
||||
// If A is inside B, then A is rendered first
|
||||
if( b.first->m_bbox.Inside( a.first->m_bbox ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( a.first->m_bbox.Inside( b.first->m_bbox ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return a.second > b.second;
|
||||
} );
|
||||
|
||||
for( const std::pair<const MODEL_3D::MATERIAL*, float>& mat : materialsSorted )
|
||||
{
|
||||
materialsToRender.push_back( mat.first );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( const MODEL_3D::MATERIAL& mat : m_materials )
|
||||
{
|
||||
// There is at least one default material created in case a mesh has no declared materials.
|
||||
// Most meshes have a material, so usually the first material will have nothing to render and is skip.
|
||||
// See S3D::GetModel for more details.
|
||||
if( mat.m_render_idx_count == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( ( mat.IsTransparent() != aTransparent )
|
||||
&& ( aOpacity >= 1.0f )
|
||||
&& m_materialMode != MATERIAL_MODE::DIFFUSE_ONLY )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
materialsToRender.push_back( &mat );
|
||||
}
|
||||
}
|
||||
|
||||
for( const MODEL_3D::MATERIAL* mat : materialsToRender )
|
||||
{
|
||||
switch( m_materialMode )
|
||||
{
|
||||
case MATERIAL_MODE::NORMAL:
|
||||
OglSetMaterial( mat, aOpacity, aUseSelectedMaterial, aSelectionColor );
|
||||
OglSetMaterial( *mat, aOpacity, aUseSelectedMaterial, aSelectionColor );
|
||||
break;
|
||||
|
||||
case MATERIAL_MODE::DIFFUSE_ONLY:
|
||||
OglSetDiffuseMaterial( mat.m_Diffuse, aOpacity, aUseSelectedMaterial, aSelectionColor );
|
||||
OglSetDiffuseMaterial( mat->m_Diffuse, aOpacity, aUseSelectedMaterial, aSelectionColor );
|
||||
break;
|
||||
|
||||
case MATERIAL_MODE::CAD_MODE:
|
||||
OglSetDiffuseMaterial( MaterialDiffuseToColorCAD( mat.m_Diffuse ), aOpacity,
|
||||
OglSetDiffuseMaterial( MaterialDiffuseToColorCAD( mat->m_Diffuse ), aOpacity,
|
||||
aUseSelectedMaterial, aSelectionColor );
|
||||
break;
|
||||
|
||||
@@ -467,9 +550,9 @@ void MODEL_3D::Draw( bool aTransparent, float aOpacity, bool aUseSelectedMateria
|
||||
break;
|
||||
}
|
||||
|
||||
glDrawElements( GL_TRIANGLES, mat.m_render_idx_count, m_index_buffer_type,
|
||||
glDrawElements( GL_TRIANGLES, mat->m_render_idx_count, m_index_buffer_type,
|
||||
reinterpret_cast<const void*>(
|
||||
static_cast<uintptr_t>( mat.m_render_idx_buffer_offset ) ) );
|
||||
static_cast<uintptr_t>( mat->m_render_idx_buffer_offset ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
*/
|
||||
void DrawOpaque( bool aUseSelectedMaterial, SFVEC3F aSelectionColor = SFVEC3F( 0.0f ) ) const
|
||||
{
|
||||
Draw( false, 1.0f, aUseSelectedMaterial, aSelectionColor );
|
||||
Draw( false, 1.0f, aUseSelectedMaterial, aSelectionColor, nullptr, nullptr );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,9 +63,19 @@ public:
|
||||
void DrawTransparent( float aOpacity, bool aUseSelectedMaterial,
|
||||
SFVEC3F aSelectionColor = SFVEC3F( 0.0f ) ) const
|
||||
{
|
||||
Draw( true, aOpacity, aUseSelectedMaterial, aSelectionColor );
|
||||
Draw( true, aOpacity, aUseSelectedMaterial, aSelectionColor, nullptr, nullptr );
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the model into the current context.
|
||||
* if aModelWorldMatrix and aCameraWorldPos is provided,
|
||||
* it renders the material groups sorted.
|
||||
*/
|
||||
void Draw( bool aTransparent, float aOpacity, bool aUseSelectedMaterial,
|
||||
const SFVEC3F& aSelectionColor,
|
||||
const glm::mat4 *aModelWorldMatrix,
|
||||
const SFVEC3F *aCameraWorldPos ) const;
|
||||
|
||||
/**
|
||||
* Return true if have opaque meshes to render.
|
||||
*/
|
||||
@@ -136,6 +146,8 @@ private:
|
||||
unsigned int m_render_idx_buffer_offset = 0;
|
||||
unsigned int m_render_idx_count = 0;
|
||||
|
||||
BBOX_3D m_bbox; ///< bounding box for this material group, used for transparent material ordering
|
||||
|
||||
MATERIAL( const SMATERIAL& aOther ) : SMATERIAL( aOther ) { }
|
||||
bool IsTransparent() const { return m_Transparency > FLT_EPSILON; }
|
||||
};
|
||||
@@ -159,9 +171,6 @@ private:
|
||||
|
||||
static void MakeBbox( const BBOX_3D& aBox, unsigned int aIdxOffset, VERTEX* aVtxOut,
|
||||
GLuint* aIdxOut, const glm::vec4& aColor );
|
||||
|
||||
void Draw( bool aTransparent, float aOpacity, bool aUseSelectedMaterial,
|
||||
SFVEC3F& aSelectionColor ) const;
|
||||
};
|
||||
|
||||
#endif // _MODEL_3D_H_
|
||||
|
||||
@@ -912,7 +912,8 @@ void RENDER_3D_OPENGL::load3dModels( REPORTER* aStatusReporter )
|
||||
if( !m_boardAdapter.GetBoard() )
|
||||
return;
|
||||
|
||||
if( !m_boardAdapter.m_Cfg->m_Render.show_footprints_normal
|
||||
if( !m_boardAdapter.m_IsPreviewer
|
||||
&& !m_boardAdapter.m_Cfg->m_Render.show_footprints_normal
|
||||
&& !m_boardAdapter.m_Cfg->m_Render.show_footprints_insert
|
||||
&& !m_boardAdapter.m_Cfg->m_Render.show_footprints_virtual )
|
||||
{
|
||||
|
||||
@@ -22,14 +22,19 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <gal/opengl/kiglew.h> // Must be included first
|
||||
|
||||
#include "plugins/3dapi/xv3d_types.h"
|
||||
#include "render_3d_opengl.h"
|
||||
#include "opengl_utils.h"
|
||||
#include "common_ogl/ogl_utils.h"
|
||||
#include <footprint.h>
|
||||
#include <3d_math.h>
|
||||
#include <glm/geometric.hpp>
|
||||
#include <math/util.h> // for KiROUND
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include <base_units.h>
|
||||
@@ -858,9 +863,12 @@ bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter,
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
glm::mat4 cameraViewMatrix;
|
||||
|
||||
glGetFloatv( GL_MODELVIEW_MATRIX, glm::value_ptr( cameraViewMatrix ) );
|
||||
|
||||
// Render 3D Models (Non-transparent)
|
||||
render3dModels( false, false );
|
||||
render3dModels( true, false );
|
||||
renderOpaqueModels( cameraViewMatrix );
|
||||
|
||||
// Display board body
|
||||
if( m_boardAdapter.m_Cfg->m_Render.show_board_body )
|
||||
@@ -922,8 +930,7 @@ bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter,
|
||||
glTexEnvi( GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_CONSTANT );
|
||||
glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA );
|
||||
|
||||
render3dModels( false, true );
|
||||
render3dModels( true, true );
|
||||
renderTransparentModels( cameraViewMatrix );
|
||||
|
||||
glDisable( GL_BLEND );
|
||||
OglResetTextureState();
|
||||
@@ -1143,14 +1150,15 @@ void RENDER_3D_OPENGL::renderSolderMaskLayer( PCB_LAYER_ID aLayerID, float aZPos
|
||||
}
|
||||
|
||||
|
||||
void RENDER_3D_OPENGL::render3dModelsSelected( bool aRenderTopOrBot, bool aRenderTransparentOnly,
|
||||
bool aRenderSelectedOnly )
|
||||
void RENDER_3D_OPENGL::get3dModelsSelected( std::list<MODELTORENDER> &aDstRenderList,
|
||||
bool aGetTop, bool aGetBot, bool aRenderTransparentOnly,
|
||||
bool aRenderSelectedOnly )
|
||||
{
|
||||
wxASSERT( ( aGetTop == true ) || ( aGetBot == true ) );
|
||||
|
||||
if( !m_boardAdapter.GetBoard() )
|
||||
return;
|
||||
|
||||
MODEL_3D::BeginDrawMulti( !aRenderSelectedOnly );
|
||||
|
||||
// Go for all footprints
|
||||
for( FOOTPRINT* fp : m_boardAdapter.GetBoard()->Footprints() )
|
||||
{
|
||||
@@ -1175,54 +1183,52 @@ void RENDER_3D_OPENGL::render3dModelsSelected( bool aRenderTopOrBot, bool aRende
|
||||
{
|
||||
if( m_boardAdapter.IsFootprintShown( (FOOTPRINT_ATTR_T) fp->GetAttributes() ) )
|
||||
{
|
||||
if( aRenderTopOrBot == !fp->IsFlipped() )
|
||||
renderFootprint( fp, aRenderTransparentOnly, highlight );
|
||||
const bool isFlipped = fp->IsFlipped();
|
||||
|
||||
if( ( aGetTop == !isFlipped ) ||
|
||||
( aGetBot == isFlipped ) )
|
||||
get3dModelsFromFootprint( aDstRenderList, fp, aRenderTransparentOnly, highlight );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MODEL_3D::EndDrawMulti();
|
||||
}
|
||||
|
||||
|
||||
void RENDER_3D_OPENGL::render3dModels( bool aRenderTopOrBot, bool aRenderTransparentOnly )
|
||||
{
|
||||
if( m_boardAdapter.m_IsBoardView )
|
||||
render3dModelsSelected( aRenderTopOrBot, aRenderTransparentOnly, true );
|
||||
|
||||
render3dModelsSelected( aRenderTopOrBot, aRenderTransparentOnly, false );
|
||||
}
|
||||
|
||||
|
||||
void RENDER_3D_OPENGL::renderFootprint( const FOOTPRINT* aFootprint, bool aRenderTransparentOnly,
|
||||
bool aIsSelected )
|
||||
void RENDER_3D_OPENGL::get3dModelsFromFootprint( std::list<MODELTORENDER> &aDstRenderList,
|
||||
const FOOTPRINT* aFootprint, bool aRenderTransparentOnly,
|
||||
bool aIsSelected )
|
||||
{
|
||||
if( !aFootprint->Models().empty() )
|
||||
{
|
||||
const double zpos = m_boardAdapter.GetFootprintZPos( aFootprint->IsFlipped() );
|
||||
SFVEC3F selColor = m_boardAdapter.GetColor( m_boardAdapter.m_Cfg->m_Render.opengl_selection_color );
|
||||
|
||||
|
||||
glPushMatrix();
|
||||
|
||||
VECTOR2I pos = aFootprint->GetPosition();
|
||||
|
||||
glTranslatef( pos.x * m_boardAdapter.BiuTo3dUnits(), -pos.y * m_boardAdapter.BiuTo3dUnits(),
|
||||
zpos );
|
||||
glm::mat4 fpMatrix( 1.0f );
|
||||
|
||||
fpMatrix = glm::translate( fpMatrix,
|
||||
SFVEC3F( pos.x * m_boardAdapter.BiuTo3dUnits(),
|
||||
-pos.y * m_boardAdapter.BiuTo3dUnits(),
|
||||
zpos ) );
|
||||
|
||||
if( !aFootprint->GetOrientation().IsZero() )
|
||||
glRotated( aFootprint->GetOrientation().AsDegrees(), 0.0, 0.0, 1.0 );
|
||||
{
|
||||
fpMatrix = glm::rotate( fpMatrix,
|
||||
(float) aFootprint->GetOrientation().AsRadians(),
|
||||
SFVEC3F( 0.0f, 0.0f, 1.0f ) );
|
||||
}
|
||||
|
||||
if( aFootprint->IsFlipped() )
|
||||
{
|
||||
glRotatef( 180.0f, 0.0f, 1.0f, 0.0f );
|
||||
glRotatef( 180.0f, 0.0f, 0.0f, 1.0f );
|
||||
fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(), SFVEC3F( 0.0f, 1.0f, 0.0f ) );
|
||||
fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(), SFVEC3F( 0.0f, 0.0f, 1.0f ) );
|
||||
}
|
||||
|
||||
double modelunit_to_3d_units_factor = m_boardAdapter.BiuTo3dUnits() * UNITS3D_TO_UNITSPCB;
|
||||
const double modelunit_to_3d_units_factor = m_boardAdapter.BiuTo3dUnits() *
|
||||
UNITS3D_TO_UNITSPCB;
|
||||
|
||||
glScaled( modelunit_to_3d_units_factor, modelunit_to_3d_units_factor,
|
||||
modelunit_to_3d_units_factor );
|
||||
fpMatrix = glm::scale( fpMatrix,
|
||||
SFVEC3F( modelunit_to_3d_units_factor ) );
|
||||
|
||||
// Get the list of model files for this model
|
||||
for( const FP_3DMODEL& sM : aFootprint->Models() )
|
||||
@@ -1243,66 +1249,232 @@ void RENDER_3D_OPENGL::renderFootprint( const FOOTPRINT* aFootprint, bool aRende
|
||||
if( ( !aRenderTransparentOnly && modelPtr->HasOpaqueMeshes() && opaque ) ||
|
||||
( aRenderTransparentOnly && ( modelPtr->HasTransparentMeshes() || !opaque ) ) )
|
||||
{
|
||||
glPushMatrix();
|
||||
glm::mat4 modelworldMatrix = fpMatrix;
|
||||
|
||||
std::vector<double> key = { sM.m_Offset.x, sM.m_Offset.y, sM.m_Offset.z,
|
||||
sM.m_Rotation.x, sM.m_Rotation.y, sM.m_Rotation.z,
|
||||
sM.m_Scale.x, sM.m_Scale.y, sM.m_Scale.z };
|
||||
const SFVEC3F offset = SFVEC3F( sM.m_Offset.x, sM.m_Offset.y, sM.m_Offset.z );
|
||||
const SFVEC3F rotation = SFVEC3F( sM.m_Rotation.x, sM.m_Rotation.y, sM.m_Rotation.z );
|
||||
const SFVEC3F scale = SFVEC3F( sM.m_Scale.x, sM.m_Scale.y, sM.m_Scale.z );
|
||||
|
||||
std::vector<float> key = { offset.x, offset.y, offset.z,
|
||||
rotation.x, rotation.y, rotation.z,
|
||||
scale.x, scale.y, scale.z };
|
||||
|
||||
auto it = m_3dModelMatrixMap.find( key );
|
||||
|
||||
if( it != m_3dModelMatrixMap.end() )
|
||||
{
|
||||
glMultMatrixf( glm::value_ptr( it->second ) );
|
||||
modelworldMatrix *= it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
glm::mat4 mtx( 1 );
|
||||
mtx = glm::translate( mtx, { sM.m_Offset.x, sM.m_Offset.y, sM.m_Offset.z } );
|
||||
mtx = glm::rotate( mtx, glm::radians( (float) -sM.m_Rotation.z ), { 0.0f, 0.0f, 1.0f } );
|
||||
mtx = glm::rotate( mtx, glm::radians( (float) -sM.m_Rotation.y ), { 0.0f, 1.0f, 0.0f } );
|
||||
mtx = glm::rotate( mtx, glm::radians( (float) -sM.m_Rotation.x ), { 1.0f, 0.0f, 0.0f } );
|
||||
mtx = glm::scale( mtx, { sM.m_Scale.x, sM.m_Scale.y, sM.m_Scale.z } );
|
||||
glm::mat4 mtx( 1.0f );
|
||||
mtx = glm::translate( mtx, offset );
|
||||
mtx = glm::rotate( mtx, glm::radians( -rotation.z ), { 0.0f, 0.0f, 1.0f } );
|
||||
mtx = glm::rotate( mtx, glm::radians( -rotation.y ), { 0.0f, 1.0f, 0.0f } );
|
||||
mtx = glm::rotate( mtx, glm::radians( -rotation.x ), { 1.0f, 0.0f, 0.0f } );
|
||||
mtx = glm::scale( mtx, scale );
|
||||
m_3dModelMatrixMap[ key ] = mtx;
|
||||
|
||||
glMultMatrixf( glm::value_ptr( mtx ) );
|
||||
modelworldMatrix *= mtx;
|
||||
}
|
||||
|
||||
|
||||
if( aRenderTransparentOnly )
|
||||
{
|
||||
modelPtr->DrawTransparent( sM.m_Opacity,
|
||||
aFootprint->IsSelected() || aIsSelected,
|
||||
selColor );
|
||||
aDstRenderList.emplace_back( modelworldMatrix,
|
||||
modelPtr,
|
||||
sM.m_Opacity,
|
||||
true,
|
||||
aFootprint->IsSelected() || aIsSelected );
|
||||
}
|
||||
else
|
||||
{
|
||||
modelPtr->DrawOpaque( aFootprint->IsSelected() || aIsSelected, selColor );
|
||||
aDstRenderList.emplace_back( modelworldMatrix,
|
||||
modelPtr,
|
||||
1.0f,
|
||||
false,
|
||||
aFootprint->IsSelected() || aIsSelected );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( m_boardAdapter.m_Cfg->m_Render.opengl_show_model_bbox )
|
||||
{
|
||||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
glDisable( GL_LIGHTING );
|
||||
void RENDER_3D_OPENGL::renderOpaqueModels( const glm::mat4 &aCameraViewMatrix )
|
||||
{
|
||||
const SFVEC3F selColor = m_boardAdapter.GetColor( m_boardAdapter.m_Cfg->m_Render.opengl_selection_color );
|
||||
|
||||
glLineWidth( 1 );
|
||||
modelPtr->DrawBboxes();
|
||||
glPushMatrix();
|
||||
|
||||
glLineWidth( 4 );
|
||||
modelPtr->DrawBbox();
|
||||
std::list<MODELTORENDER> renderList;
|
||||
|
||||
glEnable( GL_LIGHTING );
|
||||
glDisable( GL_BLEND );
|
||||
}
|
||||
if( m_boardAdapter.m_IsBoardView )
|
||||
{
|
||||
renderList.clear();
|
||||
|
||||
glPopMatrix();
|
||||
get3dModelsSelected( renderList, true, true, false, true );
|
||||
|
||||
if( !renderList.empty() )
|
||||
{
|
||||
MODEL_3D::BeginDrawMulti( false );
|
||||
|
||||
for( const MODELTORENDER& mtr : renderList )
|
||||
{
|
||||
renderModel( aCameraViewMatrix, mtr, selColor, nullptr );
|
||||
}
|
||||
|
||||
MODEL_3D::EndDrawMulti();
|
||||
}
|
||||
}
|
||||
|
||||
renderList.clear();
|
||||
get3dModelsSelected( renderList, true, true, false, false );
|
||||
|
||||
if( !renderList.empty() )
|
||||
{
|
||||
MODEL_3D::BeginDrawMulti( true );
|
||||
|
||||
for( const MODELTORENDER& mtr : renderList )
|
||||
{
|
||||
renderModel( aCameraViewMatrix, mtr, selColor, nullptr );
|
||||
}
|
||||
|
||||
MODEL_3D::EndDrawMulti();
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
void RENDER_3D_OPENGL::renderTransparentModels( const glm::mat4 &aCameraViewMatrix )
|
||||
{
|
||||
const SFVEC3F selColor = m_boardAdapter.GetColor( m_boardAdapter.m_Cfg->m_Render.opengl_selection_color );
|
||||
|
||||
std::list<MODELTORENDER> renderListModels; // do not clear it until this function returns
|
||||
|
||||
if( m_boardAdapter.m_IsBoardView )
|
||||
{
|
||||
// Get Transparent Selected
|
||||
get3dModelsSelected( renderListModels, true, true, true, true );
|
||||
}
|
||||
|
||||
// Get Transparent Not Selected
|
||||
get3dModelsSelected( renderListModels, true, true, true, false );
|
||||
|
||||
if( renderListModels.empty() )
|
||||
return;
|
||||
|
||||
std::vector<std::pair<const MODELTORENDER *, float>> transparentModelList;
|
||||
|
||||
transparentModelList.reserve( renderListModels.size() );
|
||||
|
||||
// Calculate the distance to the camera for each model
|
||||
const SFVEC3F &cameraPos = m_camera.GetPos();
|
||||
|
||||
for( const MODELTORENDER& mtr : renderListModels )
|
||||
{
|
||||
const BBOX_3D& bBox = mtr.m_model->GetBBox();
|
||||
const SFVEC3F& bBoxCenter = bBox.GetCenter();
|
||||
const SFVEC3F bBoxWorld = mtr.m_modelWorldMat * glm::vec4( bBoxCenter, 1.0f );
|
||||
|
||||
const float distanceToCamera = glm::length( cameraPos - bBoxWorld );
|
||||
|
||||
transparentModelList.emplace_back( &mtr, distanceToCamera );
|
||||
}
|
||||
|
||||
// Sort from back to front
|
||||
std::sort( transparentModelList.begin(), transparentModelList.end(),
|
||||
[&]( std::pair<const MODELTORENDER *, float>& a,
|
||||
std::pair<const MODELTORENDER *, float>& b ) {
|
||||
return a.second > b.second;
|
||||
} );
|
||||
|
||||
// Start rendering calls
|
||||
glPushMatrix();
|
||||
|
||||
bool isUsingColorInformation = !( transparentModelList.begin()->first->m_isSelected &&
|
||||
m_boardAdapter.m_IsBoardView );
|
||||
|
||||
MODEL_3D::BeginDrawMulti( isUsingColorInformation );
|
||||
|
||||
for( const std::pair<const MODELTORENDER *, float>& mtr : transparentModelList )
|
||||
{
|
||||
if( m_boardAdapter.m_IsBoardView )
|
||||
{
|
||||
// Toggle between using model color or the select color
|
||||
if( !isUsingColorInformation && !mtr.first->m_isSelected )
|
||||
{
|
||||
isUsingColorInformation = true;
|
||||
|
||||
glEnableClientState( GL_COLOR_ARRAY );
|
||||
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( isUsingColorInformation && mtr.first->m_isSelected )
|
||||
{
|
||||
isUsingColorInformation = false;
|
||||
|
||||
glDisableClientState( GL_COLOR_ARRAY );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glDisable( GL_COLOR_MATERIAL );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
// Render model, sort each individuall material group
|
||||
// by passing cameraPos
|
||||
renderModel( aCameraViewMatrix, *mtr.first, selColor, &cameraPos );
|
||||
}
|
||||
|
||||
MODEL_3D::EndDrawMulti();
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
void RENDER_3D_OPENGL::renderModel( const glm::mat4 &aCameraViewMatrix,
|
||||
const MODELTORENDER &aModelToRender,
|
||||
const SFVEC3F &aSelColor,
|
||||
const SFVEC3F *aCameraWorldPos )
|
||||
{
|
||||
const glm::mat4 modelviewMatrix = aCameraViewMatrix * aModelToRender.m_modelWorldMat;
|
||||
|
||||
glLoadMatrixf( glm::value_ptr( modelviewMatrix ) );
|
||||
|
||||
aModelToRender.m_model->Draw( aModelToRender.m_isTransparent,
|
||||
aModelToRender.m_opacity,
|
||||
aModelToRender.m_isSelected,
|
||||
aSelColor,
|
||||
&aModelToRender.m_modelWorldMat,
|
||||
aCameraWorldPos );
|
||||
|
||||
if( m_boardAdapter.m_Cfg->m_Render.opengl_show_model_bbox )
|
||||
{
|
||||
const bool wasBlendEnabled = glIsEnabled( GL_BLEND );
|
||||
|
||||
if( !wasBlendEnabled )
|
||||
{
|
||||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
}
|
||||
|
||||
glDisable( GL_LIGHTING );
|
||||
|
||||
glLineWidth( 1 );
|
||||
aModelToRender.m_model->DrawBboxes();
|
||||
|
||||
glLineWidth( 4 );
|
||||
aModelToRender.m_model->DrawBbox();
|
||||
|
||||
glEnable( GL_LIGHTING );
|
||||
|
||||
if( !wasBlendEnabled )
|
||||
{
|
||||
glDisable( GL_BLEND );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -129,18 +129,44 @@ private:
|
||||
*/
|
||||
void load3dModels( REPORTER* aStatusReporter );
|
||||
|
||||
/**
|
||||
* @param aRenderTopOrBot true will render Top, false will render bottom
|
||||
* @param aRenderTransparentOnly true will render only the transparent objects, false will
|
||||
* render opaque
|
||||
*/
|
||||
void render3dModels( bool aRenderTopOrBot, bool aRenderTransparentOnly );
|
||||
struct MODELTORENDER
|
||||
{
|
||||
glm::mat4 m_modelWorldMat;
|
||||
const MODEL_3D* m_model;
|
||||
float m_opacity;
|
||||
bool m_isTransparent;
|
||||
bool m_isSelected;
|
||||
|
||||
void render3dModelsSelected( bool aRenderTopOrBot, bool aRenderTransparentOnly,
|
||||
bool aRenderSelectedOnly );
|
||||
MODELTORENDER( glm::mat4 aModelWorldMat,
|
||||
const MODEL_3D* aNodel,
|
||||
float aOpacity,
|
||||
bool aIsTransparent,
|
||||
bool aIsSelected ) :
|
||||
m_modelWorldMat( std::move( aModelWorldMat ) ),
|
||||
m_model( aNodel ),
|
||||
m_opacity( aOpacity ),
|
||||
m_isTransparent( aIsTransparent ),
|
||||
m_isSelected( aIsSelected )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
void renderFootprint( const FOOTPRINT* aFootprint, bool aRenderTransparentOnly,
|
||||
bool aIsSelected );
|
||||
void renderOpaqueModels( const glm::mat4 &aCameraViewMatrix );
|
||||
void renderTransparentModels( const glm::mat4 &aCameraViewMatrix );
|
||||
|
||||
void renderModel( const glm::mat4 &aCameraViewMatrix,
|
||||
const MODELTORENDER &aModelToRender,
|
||||
const SFVEC3F &aSelColor,
|
||||
const SFVEC3F *aCameraWorldPos );
|
||||
|
||||
|
||||
void get3dModelsSelected( std::list<MODELTORENDER> &aDstRenderList,
|
||||
bool aGetTop, bool aGetBot, bool aRenderTransparentOnly,
|
||||
bool aRenderSelectedOnly );
|
||||
|
||||
void get3dModelsFromFootprint( std::list<MODELTORENDER> &aDstRenderList,
|
||||
const FOOTPRINT* aFootprint, bool aRenderTransparentOnly,
|
||||
bool aIsSelected );
|
||||
|
||||
void setLightFront( bool enabled );
|
||||
void setLightTop( bool enabled );
|
||||
@@ -210,7 +236,7 @@ private:
|
||||
|
||||
// Caches
|
||||
std::map< wxString, MODEL_3D* > m_3dModelMap;
|
||||
std::map< std::vector<double>, glm::mat4 > m_3dModelMatrixMap;
|
||||
std::map< std::vector<float>, glm::mat4 > m_3dModelMatrixMap;
|
||||
|
||||
BOARD_ITEM* m_currentRollOverItem;
|
||||
|
||||
|
||||
@@ -1202,7 +1202,8 @@ void RENDER_3D_RAYTRACE::load3DModels( CONTAINER_3D& aDstContainer, bool aSkipMa
|
||||
if( !m_boardAdapter.GetBoard() )
|
||||
return;
|
||||
|
||||
if( !m_boardAdapter.m_Cfg->m_Render.show_footprints_normal
|
||||
if( !m_boardAdapter.m_IsPreviewer
|
||||
&& !m_boardAdapter.m_Cfg->m_Render.show_footprints_normal
|
||||
&& !m_boardAdapter.m_Cfg->m_Render.show_footprints_insert
|
||||
&& !m_boardAdapter.m_Cfg->m_Render.show_footprints_virtual )
|
||||
{
|
||||
|
||||
@@ -229,6 +229,16 @@ bool BBOX_2D::Inside( const SFVEC2F& aPoint ) const
|
||||
}
|
||||
|
||||
|
||||
bool BBOX_2D::Inside( const BBOX_2D& aBBox ) const
|
||||
{
|
||||
wxASSERT( IsInitialized() );
|
||||
wxASSERT( aBBox.IsInitialized() );
|
||||
|
||||
return Inside( aBBox.Min() ) &&
|
||||
Inside( aBBox.Max() );
|
||||
}
|
||||
|
||||
|
||||
float BBOX_2D::Area() const
|
||||
{
|
||||
SFVEC2F extent = GetExtent();
|
||||
|
||||
@@ -132,6 +132,14 @@ public:
|
||||
*/
|
||||
bool Inside( const SFVEC2F& aPoint ) const;
|
||||
|
||||
/**
|
||||
* Check if a bounding box is inside this bounding box.
|
||||
*
|
||||
* @param aBBox the bounding box to test if it is inside
|
||||
* @return true if aBBox is smaller and all points are inside
|
||||
*/
|
||||
bool Inside( const BBOX_2D& aBBox ) const;
|
||||
|
||||
/**
|
||||
* Calculate the area of a bounding box.
|
||||
*
|
||||
|
||||
@@ -238,6 +238,16 @@ bool BBOX_3D::Inside( const SFVEC3F& aPoint ) const
|
||||
}
|
||||
|
||||
|
||||
bool BBOX_3D::Inside( const BBOX_3D& aBBox ) const
|
||||
{
|
||||
wxASSERT( IsInitialized() );
|
||||
wxASSERT( aBBox.IsInitialized() );
|
||||
|
||||
return Inside( aBBox.Min() ) &&
|
||||
Inside( aBBox.Max() );
|
||||
}
|
||||
|
||||
|
||||
float BBOX_3D::Volume() const
|
||||
{
|
||||
wxASSERT( IsInitialized() );
|
||||
|
||||
@@ -125,6 +125,14 @@ public:
|
||||
*/
|
||||
bool Inside( const SFVEC3F& aPoint ) const;
|
||||
|
||||
/**
|
||||
* Check if a bounding box is inside this bounding box.
|
||||
*
|
||||
* @param aBBox the bounding box to test if it is inside
|
||||
* @return true if aBBox is smaller and all points are inside
|
||||
*/
|
||||
bool Inside( const BBOX_3D& aBBox ) const;
|
||||
|
||||
/**
|
||||
* Apply a transformation matrix to the box points.
|
||||
*
|
||||
|
||||
@@ -70,6 +70,8 @@ PANEL_PREVIEW_3D_MODEL::PANEL_PREVIEW_3D_MODEL( wxWindow* aParent, PCB_BASE_FRAM
|
||||
|
||||
m_selected = -1;
|
||||
|
||||
m_previewLabel->SetFont( KIUI::GetStatusFont( this ) );
|
||||
|
||||
// Set the bitmap of 3D view buttons:
|
||||
m_bpvTop->SetBitmap( KiBitmap( BITMAPS::axis3d_top ) );
|
||||
m_bpvFront->SetBitmap( KiBitmap( BITMAPS::axis3d_front ) );
|
||||
@@ -140,6 +142,9 @@ PANEL_PREVIEW_3D_MODEL::PANEL_PREVIEW_3D_MODEL( wxWindow* aParent, PCB_BASE_FRAM
|
||||
this );
|
||||
}
|
||||
|
||||
aFrame->Connect( UNITS_CHANGED, wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL::onUnitsChanged ),
|
||||
nullptr, this );
|
||||
|
||||
#ifdef __WXOSX__
|
||||
// Call layout once to get the proper button sizes after the bitmaps have been set
|
||||
Layout();
|
||||
@@ -538,6 +543,29 @@ void PANEL_PREVIEW_3D_MODEL::onMouseWheelOffset( wxMouseEvent& event )
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREVIEW_3D_MODEL::onUnitsChanged( wxCommandEvent& aEvent )
|
||||
{
|
||||
double xoff_mm = EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, m_userUnits,
|
||||
xoff->GetValue() )
|
||||
/ pcbIUScale.IU_PER_MM;
|
||||
double yoff_mm = EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, m_userUnits,
|
||||
yoff->GetValue() )
|
||||
/ pcbIUScale.IU_PER_MM;
|
||||
double zoff_mm = EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, m_userUnits,
|
||||
zoff->GetValue() )
|
||||
/ pcbIUScale.IU_PER_MM;
|
||||
|
||||
PCB_BASE_FRAME* frame = static_cast<PCB_BASE_FRAME*>( aEvent.GetClientData() );
|
||||
m_userUnits = frame->GetUserUnits();
|
||||
|
||||
xoff->SetValue( formatOffsetValue( xoff_mm ) );
|
||||
yoff->SetValue( formatOffsetValue( yoff_mm ) );
|
||||
zoff->SetValue( formatOffsetValue( zoff_mm ) );
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREVIEW_3D_MODEL::UpdateDummyFootprint( bool aReloadRequired )
|
||||
{
|
||||
m_dummyFootprint->Models().clear();
|
||||
|
||||
@@ -141,6 +141,8 @@ private:
|
||||
void doIncrementRotation( wxSpinEvent& aEvent, double aSign );
|
||||
void doIncrementOffset( wxSpinEvent& aEvent, double aSign );
|
||||
|
||||
void onUnitsChanged( wxCommandEvent& aEvent );
|
||||
|
||||
wxString formatScaleValue( double aValue );
|
||||
wxString formatRotationValue( double aValue );
|
||||
wxString formatOffsetValue( double aValue );
|
||||
|
||||
@@ -183,12 +183,11 @@ PANEL_PREVIEW_3D_MODEL_BASE::PANEL_PREVIEW_3D_MODEL_BASE( wxWindow* parent, wxWi
|
||||
wxBoxSizer* bSizer6;
|
||||
bSizer6 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
wxStaticText* staticPreviewLabel;
|
||||
staticPreviewLabel = new wxStaticText( this, wxID_ANY, _("Preview"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
staticPreviewLabel->Wrap( -1 );
|
||||
staticPreviewLabel->SetFont( wxFont( 11, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
|
||||
m_previewLabel = new wxStaticText( this, wxID_ANY, _("Preview"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_previewLabel->Wrap( -1 );
|
||||
m_previewLabel->SetFont( wxFont( 11, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
|
||||
|
||||
bSizer6->Add( staticPreviewLabel, 0, wxEXPAND|wxLEFT|wxRIGHT, 10 );
|
||||
bSizer6->Add( m_previewLabel, 1, wxEXPAND|wxLEFT|wxRIGHT, 10 );
|
||||
|
||||
|
||||
bSizerRight->Add( bSizer6, 0, wxEXPAND, 5 );
|
||||
@@ -207,7 +206,7 @@ PANEL_PREVIEW_3D_MODEL_BASE::PANEL_PREVIEW_3D_MODEL_BASE( wxWindow* parent, wxWi
|
||||
m_bpvISO = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
|
||||
m_bpvISO->SetToolTip( _("Enable/disable orthographic projection") );
|
||||
|
||||
bSizer3DButtons->Add( m_bpvISO, 0, wxTOP|wxBOTTOM, 5 );
|
||||
bSizer3DButtons->Add( m_bpvISO, 0, wxTOP, 14 );
|
||||
|
||||
|
||||
bSizer3DButtons->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
@@ -2089,7 +2089,7 @@
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">10</property>
|
||||
<property name="flag">wxEXPAND|wxLEFT|wxRIGHT</property>
|
||||
<property name="proportion">0</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxStaticText" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
@@ -2127,11 +2127,11 @@
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">staticPreviewLabel</property>
|
||||
<property name="name">m_previewLabel</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">none</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
@@ -2172,8 +2172,8 @@
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxTOP|wxBOTTOM</property>
|
||||
<property name="border">14</property>
|
||||
<property name="flag">wxTOP</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBitmapButton" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
|
||||
@@ -68,6 +68,7 @@ class PANEL_PREVIEW_3D_MODEL_BASE : public wxPanel
|
||||
wxSlider* m_opacity;
|
||||
wxTextCtrl* m_boardThicknessCtrl;
|
||||
wxStaticText* m_boardThicknessUnits;
|
||||
wxStaticText* m_previewLabel;
|
||||
wxBoxSizer* m_SizerPanelView;
|
||||
wxBitmapButton* m_bpvISO;
|
||||
wxBitmapButton* m_bpvLeft;
|
||||
|
||||
+6
-2
@@ -350,12 +350,16 @@ endif(USE_DISTCC)
|
||||
# Set flags for GCC, or treat llvm as GCC
|
||||
#================================================
|
||||
|
||||
if( CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
|
||||
|
||||
if( CMAKE_COMPILER_IS_GNUCXX )
|
||||
# Set 32-bit flag for GCC to prevent excess precision
|
||||
# clang des not know this flag, so keep this separate
|
||||
if( CMAKE_SIZEOF_VOID_P EQUAL 4 )
|
||||
set( CMAKE_CXX_FLAGS "-ffloat-store ${CMAKE_CXX_FLAGS}" )
|
||||
endif()
|
||||
endif( CMAKE_COMPILER_IS_GNUCXX )
|
||||
|
||||
|
||||
if( CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
|
||||
|
||||
# Link flags in Debug: -g1 and -ggdb1 or -g1 and -ggdb3 can be used.
|
||||
# Level 1 produces minimal information, enough for making basic backtraces.
|
||||
|
||||
@@ -66,7 +66,7 @@ macro( create_git_version_header _git_src_path )
|
||||
# Check to make sure 'git' command did not fail. Otherwise fallback
|
||||
# to KiCadVersion.cmake as the revision level.
|
||||
if( _git_describe_result EQUAL 0 )
|
||||
set( KICAD_VERSION "(${_git_DESCRIBE})" )
|
||||
set( KICAD_VERSION "${_git_DESCRIBE}" )
|
||||
endif()
|
||||
|
||||
if( _git_rev_parse_head_result EQUAL 0 )
|
||||
|
||||
@@ -926,8 +926,17 @@ if(wxWidgets_FOUND)
|
||||
"\\2" wxWidgets_VERSION_MINOR "${_wx_version_h}" )
|
||||
string(REGEX REPLACE "^(.*\n)?#define +wxRELEASE_NUMBER +([0-9]+).*"
|
||||
"\\2" wxWidgets_VERSION_PATCH "${_wx_version_h}" )
|
||||
set(wxWidgets_VERSION_STRING
|
||||
"${wxWidgets_VERSION_MAJOR}.${wxWidgets_VERSION_MINOR}.${wxWidgets_VERSION_PATCH}" )
|
||||
string(REGEX REPLACE "^(.*\n)?#define +wxSUBRELEASE_NUMBER +([0-9]+).*"
|
||||
"\\2" wxWidgets_VERSION_SUBRELEASE "${_wx_version_h}" )
|
||||
|
||||
if( ${wxWidgets_VERSION_SUBRELEASE} GREATER 0 )
|
||||
set(wxWidgets_VERSION_STRING
|
||||
"${wxWidgets_VERSION_MAJOR}.${wxWidgets_VERSION_MINOR}.${wxWidgets_VERSION_PATCH}.${wxWidgets_VERSION_SUBRELEASE}" )
|
||||
else()
|
||||
set(wxWidgets_VERSION_STRING
|
||||
"${wxWidgets_VERSION_MAJOR}.${wxWidgets_VERSION_MINOR}.${wxWidgets_VERSION_PATCH}" )
|
||||
endif()
|
||||
|
||||
DBG_MSG("wxWidgets_VERSION_STRING: ${wxWidgets_VERSION_STRING}")
|
||||
endif()
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
# KiCad.
|
||||
#
|
||||
# Note: This version string should follow the semantic versioning system
|
||||
set( KICAD_SEMANTIC_VERSION "7.0.0" )
|
||||
set( KICAD_SEMANTIC_VERSION "7.0.2" )
|
||||
|
||||
# Default the version to the semantic version.
|
||||
# This is overridden by the git repository tag though (if using git)
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <eda_base_frame.h>
|
||||
#include <eda_draw_frame.h>
|
||||
#include <paths.h>
|
||||
#include <kiplatform/ui.h>
|
||||
|
||||
|
||||
static std::unique_ptr<BITMAP_STORE> s_BitmapStore;
|
||||
|
||||
+18
-11
@@ -75,6 +75,7 @@ void BITMAP_BASE::SetImage( wxImage* aImage )
|
||||
delete m_originalImage;
|
||||
m_originalImage = new wxImage( *aImage );
|
||||
rebuildBitmap();
|
||||
updatePPI();
|
||||
}
|
||||
|
||||
|
||||
@@ -90,6 +91,21 @@ void BITMAP_BASE::rebuildBitmap( bool aResetID )
|
||||
}
|
||||
|
||||
|
||||
void BITMAP_BASE::updatePPI()
|
||||
{
|
||||
// Todo: eventually we need to support dpi / scaling in both dimensions
|
||||
int dpiX = m_originalImage->GetOptionInt( wxIMAGE_OPTION_RESOLUTIONX );
|
||||
|
||||
if( dpiX > 1 )
|
||||
{
|
||||
if( m_originalImage->GetOptionInt( wxIMAGE_OPTION_RESOLUTIONUNIT ) == wxIMAGE_RESOLUTION_CM )
|
||||
m_ppi = KiROUND( dpiX * 2.54 );
|
||||
else
|
||||
m_ppi = dpiX;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BITMAP_BASE::ImportData( BITMAP_BASE* aItem )
|
||||
{
|
||||
*m_image = *aItem->m_image;
|
||||
@@ -116,6 +132,7 @@ bool BITMAP_BASE::ReadImageFile( wxInputStream& aInStream )
|
||||
delete m_originalImage;
|
||||
m_originalImage = new wxImage( *m_image );
|
||||
rebuildBitmap();
|
||||
updatePPI();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -136,17 +153,7 @@ bool BITMAP_BASE::ReadImageFile( const wxString& aFullFilename )
|
||||
delete m_originalImage;
|
||||
m_originalImage = new wxImage( *m_image );
|
||||
rebuildBitmap();
|
||||
|
||||
// Todo: eventually we need to support dpi / scaling in both dimensions
|
||||
int dpiX = m_originalImage->GetOptionInt( wxIMAGE_OPTION_RESOLUTIONX );
|
||||
|
||||
if( dpiX > 1 )
|
||||
{
|
||||
if( m_originalImage->GetOptionInt( wxIMAGE_OPTION_RESOLUTIONUNIT ) == wxIMAGE_RESOLUTION_CM )
|
||||
m_ppi = KiROUND( dpiX * 2.54 );
|
||||
else
|
||||
m_ppi = dpiX;
|
||||
}
|
||||
updatePPI();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -177,12 +177,20 @@ wxString GetVersionInfoData( const wxString& aTitle, bool aHtml, bool aBrief )
|
||||
|
||||
aMsg << eol;
|
||||
|
||||
aMsg << "Platform: "
|
||||
wxString osDescription;
|
||||
|
||||
#if __LINUX__
|
||||
<< wxGetLinuxDistributionInfo().Description << ", "
|
||||
#else
|
||||
<< wxGetOsDescription() << ", "
|
||||
osDescription = wxGetLinuxDistributionInfo().Description;
|
||||
#endif
|
||||
|
||||
// Linux uses the lsb-release program to get the description of the OS, if lsb-release
|
||||
// isn't installed, then the string will be empty and we fallback to the method used on
|
||||
// the other platforms (to at least get the kernel/uname info).
|
||||
if( osDescription.empty() )
|
||||
osDescription = wxGetOsDescription();
|
||||
|
||||
aMsg << "Platform: "
|
||||
<< osDescription << ", "
|
||||
<< GetPlatformGetBitnessName() << ", "
|
||||
<< platform.GetEndiannessName() << ", "
|
||||
<< platform.GetPortIdName();
|
||||
|
||||
+4
-21
@@ -31,30 +31,13 @@
|
||||
#include <dialogs/html_message_box.h>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
#include <pgm_base.h>
|
||||
#include "cli/cli_names.h"
|
||||
|
||||
// Set of dialogs that have been chosen not to be shown again
|
||||
static std::unordered_map<unsigned long, int> doNotShowAgainDlgs;
|
||||
|
||||
|
||||
bool IsGUI()
|
||||
{
|
||||
if( !wxTheApp )
|
||||
return false;
|
||||
|
||||
#if wxCHECK_VERSION( 3, 1, 6 )
|
||||
return wxTheApp->IsGUI();
|
||||
#else
|
||||
// wxWidgets older than version 3.1.6 do not have a way to know if the app
|
||||
// has a GUI or is a console application.
|
||||
// So the trick is to set the App class name when starting kicad-cli, and when
|
||||
// the app class name is the kicad-cli class name the app is a console app
|
||||
bool run_gui = wxTheApp->GetClassName() != KICAD_CLI_APP_NAME;
|
||||
return run_gui;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
KIDIALOG::KIDIALOG( wxWindow* aParent, const wxString& aMessage, const wxString& aCaption,
|
||||
long aStyle )
|
||||
: wxRichMessageDialog( aParent, aMessage, aCaption, aStyle | wxCENTRE | wxSTAY_ON_TOP ),
|
||||
@@ -305,7 +288,7 @@ void DisplayError( wxWindow* aParent, const wxString& aText, int aDisplayTime )
|
||||
return;
|
||||
}
|
||||
|
||||
if( !IsGUI() )
|
||||
if( !Pgm().IsGUI() )
|
||||
{
|
||||
wxFprintf( stderr, aText );
|
||||
return;
|
||||
@@ -330,7 +313,7 @@ void DisplayErrorMessage( wxWindow* aParent, const wxString& aText, const wxStri
|
||||
return;
|
||||
}
|
||||
|
||||
if( !IsGUI() )
|
||||
if( !Pgm().IsGUI() )
|
||||
{
|
||||
wxFprintf( stderr, aText );
|
||||
return;
|
||||
@@ -357,7 +340,7 @@ void DisplayInfoMessage( wxWindow* aParent, const wxString& aMessage, const wxSt
|
||||
return;
|
||||
}
|
||||
|
||||
if( !IsGUI() )
|
||||
if( !Pgm().IsGUI() )
|
||||
{
|
||||
wxFprintf( stdout, "%s %s", aMessage, aExtraInfo );
|
||||
return;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2022 Jon Evans <jon@craftyjon.com>
|
||||
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2022-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 as published by the
|
||||
@@ -178,7 +178,15 @@ bool DATABASE_CONNECTION::Disconnect()
|
||||
return false;
|
||||
}
|
||||
|
||||
m_conn->disconnect();
|
||||
try
|
||||
{
|
||||
m_conn->disconnect();
|
||||
}
|
||||
catch( boost::locale::conv::conversion_error& exc )
|
||||
{
|
||||
wxLogTrace( traceDatabase, wxT( "Disconnect() error \"%s\" occured." ), exc.what() );
|
||||
return false;
|
||||
}
|
||||
|
||||
return !m_conn->connected();
|
||||
}
|
||||
|
||||
@@ -659,6 +659,10 @@ static void buildKicadAboutBanner( EDA_BASE_FRAME* aParent, ABOUT_APP_INFO& aInf
|
||||
wxEmptyString,
|
||||
wxEmptyString,
|
||||
wxS( "Greek (el_GR)" ) ) );
|
||||
aInfo.AddTranslator( new CONTRIBUTOR( wxS( "aris-kimi" ),
|
||||
wxEmptyString,
|
||||
wxEmptyString,
|
||||
wxS( "Greek (el_GR)" ) ) );
|
||||
|
||||
aInfo.AddTranslator( new CONTRIBUTOR( wxT( "Adolfo Jayme Barrientos" ),
|
||||
wxEmptyString,
|
||||
@@ -688,6 +692,10 @@ static void buildKicadAboutBanner( EDA_BASE_FRAME* aParent, ABOUT_APP_INFO& aInf
|
||||
wxEmptyString,
|
||||
wxEmptyString,
|
||||
wxS( "Spanish (ES)" ) ) );
|
||||
aInfo.AddTranslator( new CONTRIBUTOR( wxT( "VicSanRoPe" ),
|
||||
wxEmptyString,
|
||||
wxEmptyString,
|
||||
wxS( "Spanish - Latin American (ES)" ) ) );
|
||||
|
||||
aInfo.AddTranslator( new CONTRIBUTOR( wxT( "Ulices Avila Hernandez" ),
|
||||
wxEmptyString,
|
||||
@@ -822,14 +830,46 @@ static void buildKicadAboutBanner( EDA_BASE_FRAME* aParent, ABOUT_APP_INFO& aInf
|
||||
wxEmptyString,
|
||||
wxEmptyString,
|
||||
wxS( "Korean (KO)" ) ) );
|
||||
aInfo.AddTranslator( new CONTRIBUTOR( wxT( "김낙환" ),
|
||||
wxEmptyString,
|
||||
wxEmptyString,
|
||||
wxS( "Korean (KO)" ) ) );
|
||||
aInfo.AddTranslator( new CONTRIBUTOR( wxT( "이기형" ),
|
||||
wxEmptyString,
|
||||
wxEmptyString,
|
||||
wxS( "Korean (KO)" ) ) );
|
||||
aInfo.AddTranslator( new CONTRIBUTOR( wxT( "남우근" ),
|
||||
wxEmptyString,
|
||||
wxEmptyString,
|
||||
wxS( "Korean (KO)" ) ) );
|
||||
aInfo.AddTranslator( new CONTRIBUTOR( wxT( "강명구" ),
|
||||
wxEmptyString,
|
||||
wxEmptyString,
|
||||
wxS( "Korean (KO)" ) ) );
|
||||
aInfo.AddTranslator( new CONTRIBUTOR( wxT( "김용재" ),
|
||||
wxEmptyString,
|
||||
wxEmptyString,
|
||||
wxS( "Korean (KO)" ) ) );
|
||||
aInfo.AddTranslator( new CONTRIBUTOR( wxT( "서범기" ),
|
||||
wxEmptyString,
|
||||
wxEmptyString,
|
||||
wxS( "Korean (KO)" ) ) );
|
||||
aInfo.AddTranslator( new CONTRIBUTOR( wxT( "김세영" ),
|
||||
wxEmptyString,
|
||||
wxEmptyString,
|
||||
wxS( "Korean (KO)" ) ) );
|
||||
aInfo.AddTranslator( new CONTRIBUTOR( wxT( "이윤성" ),
|
||||
wxEmptyString,
|
||||
wxEmptyString,
|
||||
wxS( "Korean (KO)" ) ) );
|
||||
aInfo.AddTranslator( new CONTRIBUTOR( wxT( "KwonHyeokbeom" ),
|
||||
wxEmptyString,
|
||||
wxEmptyString,
|
||||
wxS( "Korean (KO)" ) ) );
|
||||
aInfo.AddTranslator( new CONTRIBUTOR( wxT( "Minsu Kim (0xGabriel)" ),
|
||||
wxEmptyString,
|
||||
wxEmptyString,
|
||||
wxS( "Korean (KO)" ) ) );
|
||||
|
||||
aInfo.AddTranslator( new CONTRIBUTOR( wxT( "Henrik Kauhanen" ),
|
||||
wxEmptyString,
|
||||
@@ -860,6 +900,14 @@ static void buildKicadAboutBanner( EDA_BASE_FRAME* aParent, ABOUT_APP_INFO& aInf
|
||||
wxEmptyString,
|
||||
wxEmptyString,
|
||||
wxS( "Dutch (NL)" ) ) );
|
||||
aInfo.AddTranslator( new CONTRIBUTOR( wxT( "Tom Niesse" ),
|
||||
wxEmptyString,
|
||||
wxEmptyString,
|
||||
wxS( "Dutch (NL)" ) ) );
|
||||
aInfo.AddTranslator( new CONTRIBUTOR( wxT( "Christiaan Nieuwlaat" ),
|
||||
wxEmptyString,
|
||||
wxEmptyString,
|
||||
wxS( "Dutch (NL)" ) ) );
|
||||
|
||||
aInfo.AddTranslator( new CONTRIBUTOR( wxT( "Jarl Gjessing" ),
|
||||
wxEmptyString,
|
||||
@@ -932,6 +980,10 @@ static void buildKicadAboutBanner( EDA_BASE_FRAME* aParent, ABOUT_APP_INFO& aInf
|
||||
wxEmptyString,
|
||||
wxEmptyString,
|
||||
wxS( "Portuguese (PT)" ) ) );
|
||||
aInfo.AddTranslator( new CONTRIBUTOR( wxT( "ssantos" ),
|
||||
wxEmptyString,
|
||||
wxEmptyString,
|
||||
wxS( "Portuguese (PT)" ) ) );
|
||||
|
||||
aInfo.AddTranslator( new CONTRIBUTOR( wxT( "Igor Plyatov" ),
|
||||
wxEmptyString,
|
||||
@@ -1129,7 +1181,7 @@ static void buildKicadAboutBanner( EDA_BASE_FRAME* aParent, ABOUT_APP_INFO& aInf
|
||||
#define SYMBOL_LIB_CONTRIBUTION _( "Symbols by" )
|
||||
aInfo.AddLibrarian( new CONTRIBUTOR( wxS( "GitLab contributors" ),
|
||||
wxEmptyString,
|
||||
wxS( "https://gitlab.com/kicad/libraries/kicad-symbols/-/graphs/v7" ),
|
||||
wxS( "https://gitlab.com/kicad/libraries/kicad-symbols/-/graphs/master" ),
|
||||
SYMBOL_LIB_CONTRIBUTION,
|
||||
aInfo.CreateKiBitmap( BITMAPS::add_component ) ) );
|
||||
|
||||
|
||||
@@ -223,7 +223,7 @@ bool DIALOG_PAGES_SETTINGS::TransferDataFromWindow()
|
||||
m_screen->SetContentModified();
|
||||
|
||||
if( LocalPrjConfigChanged() )
|
||||
m_parent->SaveProjectSettings();
|
||||
m_parent->OnModify();
|
||||
|
||||
// Call the post processing (if any) after changes
|
||||
m_parent->OnPageSettingsChange();
|
||||
@@ -674,9 +674,9 @@ void DIALOG_PAGES_SETTINGS::UpdateDrawingSheetExample()
|
||||
|
||||
GRFilledRect( &memDC, VECTOR2I( 0, 0 ), m_layout_size, 0, bgColor, bgColor );
|
||||
|
||||
PrintDrawingSheet( &renderSettings, pageDUMMY, emptyString, emptyString, m_tb,
|
||||
nullptr, m_screen->GetPageCount(), m_screen->GetPageNumber(), 1,
|
||||
&Prj(), wxEmptyString, m_screen->GetVirtualPageNumber() == 1 );
|
||||
PrintDrawingSheet( &renderSettings, pageDUMMY, emptyString, emptyString, emptyString,
|
||||
m_tb, nullptr, m_screen->GetPageCount(), m_screen->GetPageNumber(),
|
||||
1, &Prj(), wxEmptyString, m_screen->GetVirtualPageNumber() == 1 );
|
||||
|
||||
memDC.SelectObject( wxNullBitmap );
|
||||
m_PageLayoutExampleBitmap->SetBitmap( *m_pageBitmap );
|
||||
|
||||
@@ -117,8 +117,7 @@ void PANEL_COLOR_SETTINGS::OnThemeChanged( wxCommandEvent& event )
|
||||
|
||||
if( idx == static_cast<int>( m_cbTheme->GetCount() ) - 2 )
|
||||
{
|
||||
// separator; re-select active theme
|
||||
m_cbTheme->SetStringSelection( m_currentSettings->GetName() );
|
||||
m_cbTheme->SetStringSelection( GetSettingsDropdownName( m_currentSettings ) );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -217,10 +216,7 @@ void PANEL_COLOR_SETTINGS::createThemeList( const wxString& aCurrent )
|
||||
|
||||
for( COLOR_SETTINGS* settings : Pgm().GetSettingsManager().GetColorSettingsList() )
|
||||
{
|
||||
wxString name = settings->GetName();
|
||||
|
||||
if( settings->IsReadOnly() )
|
||||
name += wxS( " " ) + _( "(read-only)" );
|
||||
wxString name = GetSettingsDropdownName( settings );
|
||||
|
||||
int pos = m_cbTheme->Append( name, static_cast<void*>( settings ) );
|
||||
|
||||
@@ -262,8 +258,11 @@ void PANEL_COLOR_SETTINGS::createSwatch( int aLayer, const wxString& aName )
|
||||
defaultColor, SWATCH_MEDIUM );
|
||||
swatch->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
|
||||
|
||||
m_colorsGridSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxLEFT, 5 );
|
||||
// Display the swatches in the left column and the layer name in the right column
|
||||
// The right column is sometimes (depending on the translation) truncated for long texts.
|
||||
// We cannot allow swatches to be truncated or not shown
|
||||
m_colorsGridSizer->Add( swatch, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3 );
|
||||
m_colorsGridSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxLEFT, 5 );
|
||||
|
||||
m_labels[aLayer] = label;
|
||||
m_swatches[aLayer] = swatch;
|
||||
@@ -283,6 +282,8 @@ void PANEL_COLOR_SETTINGS::ShowColorContextMenu( wxMouseEvent& aEvent, int aLaye
|
||||
auto selected =
|
||||
static_cast<COLOR_SETTINGS*>( m_cbTheme->GetClientData( m_cbTheme->GetSelection() ) );
|
||||
|
||||
wxCHECK_RET( selected, wxT( "Invalid color theme selected" ) );
|
||||
|
||||
COLOR4D current = m_currentSettings->GetColor( aLayer );
|
||||
COLOR4D saved = selected->GetColor( aLayer );
|
||||
bool readOnly = m_currentSettings->IsReadOnly();
|
||||
@@ -376,3 +377,14 @@ bool PANEL_COLOR_SETTINGS::saveCurrentTheme( bool aValidate )
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
wxString PANEL_COLOR_SETTINGS::GetSettingsDropdownName(COLOR_SETTINGS* aSettings)
|
||||
{
|
||||
wxString name = aSettings->GetName();
|
||||
|
||||
if( aSettings->IsReadOnly() )
|
||||
name += wxS( " " ) + _( "(read-only)" );
|
||||
|
||||
return name;
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2018 jean-pierre.charras
|
||||
* Copyright (C) 2011-2020 Kicad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2011-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
|
||||
@@ -110,12 +110,19 @@ bool PANEL_IMAGE_EDITOR::TransferDataFromWindow()
|
||||
void PANEL_IMAGE_EDITOR::OnRedrawPanel( wxPaintEvent& event )
|
||||
{
|
||||
wxPaintDC dc( m_panelDraw );
|
||||
wxSize size = m_panelDraw->GetClientSize();
|
||||
dc.SetDeviceOrigin( size.x / 2, size.y / 2 );
|
||||
wxSize display_size = m_panelDraw->GetClientSize();
|
||||
|
||||
double scale = 1.0 / m_workingImage->GetScalingFactor();
|
||||
dc.SetUserScale( scale, scale );
|
||||
m_workingImage->DrawBitmap( &dc, wxPoint( 0, 0 ) );
|
||||
double img_scale = 1.0 / m_workingImage->GetScalingFactor();
|
||||
VECTOR2I img_size_pixels = m_workingImage->GetSizePixels();
|
||||
|
||||
// Adjust the display scale to use the full available display area
|
||||
double scale_X = (double)display_size.x/img_size_pixels.x;
|
||||
double scale_Y = (double)display_size.y/img_size_pixels.y;
|
||||
|
||||
double display_scale = img_scale * std::min( scale_X, scale_Y );
|
||||
|
||||
dc.SetUserScale( display_scale, display_scale );
|
||||
m_workingImage->DrawBitmap( &dc, VECTOR2I( m_workingImage->GetSize()/2 ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-133-g388db8e4)
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-282-g1fa54006)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
|
||||
@@ -0,0 +1,368 @@
|
||||
<?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">panel_image_editor_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">panel_image_editor_base</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="Panel" expanded="1">
|
||||
<property name="aui_managed">0</property>
|
||||
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
|
||||
<property name="bg"></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="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"></property>
|
||||
<property name="name">PANEL_IMAGE_EDITOR_BASE</property>
|
||||
<property name="pos"></property>
|
||||
<property name="size">500,300</property>
|
||||
<property name="subclass">; ; forward_declare</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">wxTAB_TRAVERSAL</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizerMain</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bUpperSizer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizerLeft</property>
|
||||
<property name="orient">wxHORIZONTAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND | wxALL</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxPanel" 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="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size">256,256</property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_panelDraw</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="subclass"></property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style">wxFULL_REPAINT_ON_RESIZE|wxTAB_TRAVERSAL|wxBORDER_SIMPLE</property>
|
||||
<event name="OnPaint">OnRedrawPanel</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND|wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizerRight</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxButton" 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="auth_needed">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="bitmap"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="current"></property>
|
||||
<property name="default">0</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="disabled"></property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="focus"></property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Grey</property>
|
||||
<property name="margins"></property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_buttonGrey</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="position"></property>
|
||||
<property name="pressed"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass"></property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnButtonClick">OnGreyScaleConvert</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">10</property>
|
||||
<property name="flag">wxEXPAND|wxTOP|wxBOTTOM</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="spacer" expanded="1">
|
||||
<property name="height">0</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="width">0</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxTOP|wxRIGHT|wxLEFT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticText" 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="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">Image Scale:</property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_staticTextScale</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass"></property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<property name="wrap">-1</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxTextCtrl" 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="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="maxlength">0</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_textCtrlScale</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass"></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="value"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</wxFormBuilder_Project>
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-133-g388db8e4)
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-282-g1fa54006)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
|
||||
+10
-11
@@ -58,7 +58,13 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin
|
||||
const wxPoint& aPosition, const wxSize& aSize,
|
||||
KIGFX::GAL_DISPLAY_OPTIONS& aOptions, GAL_TYPE aGalType ) :
|
||||
wxScrolledCanvas( aParentWindow, aWindowId, aPosition, aSize ),
|
||||
m_MouseCapturedLost( false ),
|
||||
m_parent( aParentWindow ),
|
||||
m_edaFrame( nullptr ),
|
||||
m_lastRefresh( 0 ),
|
||||
m_pendingRefresh( false ),
|
||||
m_drawing( false ),
|
||||
m_drawingEnabled( false ),
|
||||
m_gal( nullptr ),
|
||||
m_view( nullptr ),
|
||||
m_painter( nullptr ),
|
||||
@@ -70,11 +76,10 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin
|
||||
m_stealsFocus( true ),
|
||||
m_statusPopup( nullptr )
|
||||
{
|
||||
m_parent = aParentWindow;
|
||||
m_MouseCapturedLost = false;
|
||||
|
||||
m_PaintEventCounter = std::make_unique<PROF_COUNTER>( "Draw panel paint events" );
|
||||
|
||||
m_minRefreshPeriod = 13; // 77 FPS (minus render time) by default
|
||||
|
||||
SetLayoutDirection( wxLayout_LeftToRight );
|
||||
|
||||
m_edaFrame = dynamic_cast<EDA_DRAW_FRAME*>( m_parent );
|
||||
@@ -146,12 +151,6 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin
|
||||
Connect( eventType, wxEventHandler( EDA_DRAW_PANEL_GAL::OnEvent ), nullptr,
|
||||
m_eventDispatcher );
|
||||
|
||||
m_pendingRefresh = false;
|
||||
m_drawing = false;
|
||||
m_drawingEnabled = false;
|
||||
|
||||
m_minRefreshPeriod = 13; // 77 FPS (minus render time) by default
|
||||
|
||||
// Set up timer that prevents too frequent redraw commands
|
||||
m_refreshTimer.SetOwner( this );
|
||||
Connect( m_refreshTimer.GetId(), wxEVT_TIMER,
|
||||
@@ -212,7 +211,7 @@ void EDA_DRAW_PANEL_GAL::DoRePaint()
|
||||
if( !m_drawingEnabled )
|
||||
return;
|
||||
|
||||
if( !m_gal->IsVisible() )
|
||||
if( !m_gal->IsInitialized() || !m_gal->IsVisible() )
|
||||
return;
|
||||
|
||||
m_pendingRefresh = false;
|
||||
@@ -627,7 +626,7 @@ void EDA_DRAW_PANEL_GAL::onRefreshTimer( wxTimerEvent& aEvent )
|
||||
|
||||
void EDA_DRAW_PANEL_GAL::onShowTimer( wxTimerEvent& aEvent )
|
||||
{
|
||||
if( m_gal && m_gal->IsVisible() )
|
||||
if( m_gal && m_gal->IsInitialized() && m_gal->IsVisible() )
|
||||
{
|
||||
m_onShowTimer.Stop();
|
||||
OnShow();
|
||||
|
||||
@@ -219,6 +219,10 @@ void EDA_BASE_FRAME::windowClosing( wxCloseEvent& event )
|
||||
if( canCloseWindow( event ) )
|
||||
{
|
||||
m_isClosing = true;
|
||||
|
||||
if( m_infoBar )
|
||||
m_infoBar->Dismiss();
|
||||
|
||||
APP_SETTINGS_BASE* cfg = config();
|
||||
|
||||
if( cfg )
|
||||
@@ -1230,7 +1234,7 @@ bool EDA_BASE_FRAME::IsWritable( const wxFileName& aFileName, bool aVerbose )
|
||||
|
||||
void EDA_BASE_FRAME::CheckForAutoSaveFile( const wxFileName& aFileName )
|
||||
{
|
||||
if( !IsGUI() )
|
||||
if( !Pgm().IsGUI() )
|
||||
return;
|
||||
|
||||
wxCHECK_RET( aFileName.IsOk(), wxT( "Invalid file name!" ) );
|
||||
|
||||
+27
-13
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2004-2017 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-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
|
||||
@@ -78,12 +78,16 @@ BEGIN_EVENT_TABLE( EDA_DRAW_FRAME, KIWAY_PLAYER )
|
||||
EVT_ACTIVATE( EDA_DRAW_FRAME::onActivate )
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
bool EDA_DRAW_FRAME::m_openGLFailureOccured = false;
|
||||
|
||||
|
||||
EDA_DRAW_FRAME::EDA_DRAW_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType,
|
||||
const wxString& aTitle, const wxPoint& aPos, const wxSize& aSize,
|
||||
long aStyle, const wxString& aFrameName, const EDA_IU_SCALE& aIuScale ) :
|
||||
KIWAY_PLAYER( aKiway, aParent, aFrameType, aTitle, aPos, aSize, aStyle, aFrameName, aIuScale )
|
||||
long aStyle, const wxString& aFrameName,
|
||||
const EDA_IU_SCALE& aIuScale ) :
|
||||
KIWAY_PLAYER( aKiway, aParent, aFrameType, aTitle, aPos, aSize, aStyle, aFrameName, aIuScale ),
|
||||
m_socketServer( nullptr )
|
||||
{
|
||||
m_socketServer = nullptr;
|
||||
m_mainToolBar = nullptr;
|
||||
@@ -171,8 +175,8 @@ EDA_DRAW_FRAME::EDA_DRAW_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrame
|
||||
OnMove( dummy );
|
||||
|
||||
// we need to kludge the msg panel to the correct size again
|
||||
// especially important even for first launches as the constructor of the window here usually doesn't
|
||||
// have the correct dpi awareness yet
|
||||
// especially important even for first launches as the constructor of the window
|
||||
// here usually doesn't have the correct dpi awareness yet
|
||||
m_frameSize.y += m_msgFrameHeight;
|
||||
m_msgFrameHeight = EDA_MSG_PANEL::GetRequiredHeight( this );
|
||||
m_frameSize.y -= m_msgFrameHeight;
|
||||
@@ -285,7 +289,7 @@ void EDA_DRAW_FRAME::ToggleUserUnits()
|
||||
else
|
||||
{
|
||||
SetUserUnits( GetUserUnits() == EDA_UNITS::INCHES ? EDA_UNITS::MILLIMETRES
|
||||
: EDA_UNITS::INCHES );
|
||||
: EDA_UNITS::INCHES );
|
||||
unitsChangeRefresh();
|
||||
|
||||
wxCommandEvent e( UNITS_CHANGED );
|
||||
@@ -609,7 +613,8 @@ void EDA_DRAW_FRAME::DisplayGridMsg()
|
||||
{
|
||||
wxString msg;
|
||||
|
||||
msg.Printf( wxS( "grid %s" ), MessageTextFromValue( GetCanvas()->GetGAL()->GetGridSize().x, false ) );
|
||||
msg.Printf( _( "grid %s" ), MessageTextFromValue( GetCanvas()->GetGAL()->GetGridSize().x,
|
||||
false ) );
|
||||
|
||||
SetStatusText( msg, 4 );
|
||||
}
|
||||
@@ -985,8 +990,8 @@ static const wxString productName = wxT( "KiCad E.D.A. " );
|
||||
|
||||
|
||||
void PrintDrawingSheet( const RENDER_SETTINGS* aSettings, const PAGE_INFO& aPageInfo,
|
||||
const wxString& aFullSheetName, const wxString& aFileName,
|
||||
const TITLE_BLOCK& aTitleBlock,
|
||||
const wxString& aSheetName, const wxString& aSheetPath,
|
||||
const wxString& aFileName, const TITLE_BLOCK& aTitleBlock,
|
||||
const std::map<wxString, wxString>* aProperties, int aSheetCount,
|
||||
const wxString& aPageNumber, double aMils2Iu, const PROJECT* aProject,
|
||||
const wxString& aSheetLayer, bool aIsFirstPage )
|
||||
@@ -998,7 +1003,8 @@ void PrintDrawingSheet( const RENDER_SETTINGS* aSettings, const PAGE_INFO& aPage
|
||||
drawList.SetPageNumber( aPageNumber );
|
||||
drawList.SetSheetCount( aSheetCount );
|
||||
drawList.SetFileName( aFileName );
|
||||
drawList.SetSheetName( aFullSheetName );
|
||||
drawList.SetSheetName( aSheetName );
|
||||
drawList.SetSheetPath( aSheetPath );
|
||||
drawList.SetSheetLayer( aSheetLayer );
|
||||
drawList.SetProject( aProject );
|
||||
drawList.SetIsFirstPage( aIsFirstPage );
|
||||
@@ -1028,9 +1034,10 @@ void EDA_DRAW_FRAME::PrintDrawingSheet( const RENDER_SETTINGS* aSettings, BASE_S
|
||||
DC->SetAxisOrientation( true, false );
|
||||
}
|
||||
|
||||
::PrintDrawingSheet( aSettings, GetPageSettings(), GetScreenDesc(), aFilename, GetTitleBlock(),
|
||||
aProperties, aScreen->GetPageCount(), aScreen->GetPageNumber(), aMils2Iu,
|
||||
&Prj(), aSheetLayer, aScreen->GetVirtualPageNumber() == 1 );
|
||||
::PrintDrawingSheet( aSettings, GetPageSettings(), GetScreenDesc(), GetFullScreenDesc(),
|
||||
aFilename, GetTitleBlock(), aProperties, aScreen->GetPageCount(),
|
||||
aScreen->GetPageNumber(), aMils2Iu, &Prj(), aSheetLayer,
|
||||
aScreen->GetVirtualPageNumber() == 1 );
|
||||
|
||||
if( origin.y > 0 )
|
||||
{
|
||||
@@ -1047,6 +1054,13 @@ wxString EDA_DRAW_FRAME::GetScreenDesc() const
|
||||
}
|
||||
|
||||
|
||||
wxString EDA_DRAW_FRAME::GetFullScreenDesc() const
|
||||
{
|
||||
// Virtual function. Base class implementation returns an empty string.
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
|
||||
bool EDA_DRAW_FRAME::LibraryFileBrowser( bool doOpen, wxFileName& aFilename,
|
||||
const wxString& wildcard, const wxString& ext,
|
||||
bool isDirectory, bool aIsGlobal,
|
||||
|
||||
+3
-4
@@ -392,10 +392,9 @@ static struct EDA_ITEM_DESC
|
||||
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
|
||||
REGISTER_TYPE( EDA_ITEM );
|
||||
|
||||
auto typeProp = new PROPERTY_ENUM<EDA_ITEM, KICAD_T>( wxS( "Type" ),
|
||||
NO_SETTER( EDA_ITEM, KICAD_T ), &EDA_ITEM::Type );
|
||||
typeProp->SetIsInternal( true );
|
||||
propMgr.AddProperty( typeProp );
|
||||
propMgr.AddProperty( new PROPERTY_ENUM<EDA_ITEM, KICAD_T>( wxS( "Type" ),
|
||||
NO_SETTER( EDA_ITEM, KICAD_T ), &EDA_ITEM::Type ) )
|
||||
.SetIsHiddenFromPropertiesManager();
|
||||
}
|
||||
} _EDA_ITEM_DESC;
|
||||
|
||||
|
||||
+30
-5
@@ -1687,21 +1687,36 @@ static struct EDA_SHAPE_DESC
|
||||
|
||||
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
|
||||
REGISTER_TYPE( EDA_SHAPE );
|
||||
|
||||
auto isNotPolygon =
|
||||
[]( INSPECTABLE* aItem ) -> bool
|
||||
{
|
||||
// Polygons, unlike other shapes, have no meaningful start or end coordinates
|
||||
if( EDA_SHAPE* shape = dynamic_cast<EDA_SHAPE*>( aItem ) )
|
||||
return shape->GetShape() != SHAPE_T::POLY;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
auto shape = new PROPERTY_ENUM<EDA_SHAPE, SHAPE_T>( _HKI( "Shape" ),
|
||||
NO_SETTER( EDA_SHAPE, SHAPE_T ), &EDA_SHAPE::GetShape );
|
||||
propMgr.AddProperty( shape );
|
||||
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "Start X" ),
|
||||
&EDA_SHAPE::SetStartX, &EDA_SHAPE::GetStartX, PROPERTY_DISPLAY::PT_COORD,
|
||||
ORIGIN_TRANSFORMS::ABS_X_COORD ) );
|
||||
ORIGIN_TRANSFORMS::ABS_X_COORD ) )
|
||||
.SetAvailableFunc( isNotPolygon );
|
||||
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "Start Y" ),
|
||||
&EDA_SHAPE::SetStartY, &EDA_SHAPE::GetStartY, PROPERTY_DISPLAY::PT_COORD,
|
||||
ORIGIN_TRANSFORMS::ABS_Y_COORD ) );
|
||||
ORIGIN_TRANSFORMS::ABS_Y_COORD ) )
|
||||
.SetAvailableFunc( isNotPolygon );
|
||||
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "End X" ),
|
||||
&EDA_SHAPE::SetEndX, &EDA_SHAPE::GetEndX, PROPERTY_DISPLAY::PT_COORD,
|
||||
ORIGIN_TRANSFORMS::ABS_X_COORD ) );
|
||||
ORIGIN_TRANSFORMS::ABS_X_COORD ) )
|
||||
.SetAvailableFunc( isNotPolygon );
|
||||
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "End Y" ),
|
||||
&EDA_SHAPE::SetEndY, &EDA_SHAPE::GetEndY, PROPERTY_DISPLAY::PT_COORD,
|
||||
ORIGIN_TRANSFORMS::ABS_Y_COORD ) );
|
||||
ORIGIN_TRANSFORMS::ABS_Y_COORD ) )
|
||||
.SetAvailableFunc( isNotPolygon );
|
||||
// TODO: m_arcCenter, m_bezierC1, m_bezierC2, m_poly
|
||||
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "Line Width" ),
|
||||
&EDA_SHAPE::SetWidth, &EDA_SHAPE::GetWidth, PROPERTY_DISPLAY::PT_SIZE ) );
|
||||
@@ -1721,7 +1736,17 @@ static struct EDA_SHAPE_DESC
|
||||
filled->SetAvailableFunc(
|
||||
[=]( INSPECTABLE* aItem ) -> bool
|
||||
{
|
||||
SHAPE_T itemShape = aItem->Get<SHAPE_T>( shape );
|
||||
SHAPE_T itemShape;
|
||||
|
||||
try
|
||||
{
|
||||
itemShape = aItem->Get<SHAPE_T>( shape );
|
||||
}
|
||||
catch( std::runtime_error& err )
|
||||
{
|
||||
wxFAIL_MSG( err.what() );
|
||||
return false;
|
||||
}
|
||||
|
||||
switch( itemShape )
|
||||
{
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2004-2022 KiCad Developers, see change_log.txt for contributors.
|
||||
* Copyright (C) 2004-2023 KiCad Developers, see change_log.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
||||
@@ -65,7 +65,7 @@ int EDA_UNIT_UTILS::Mils2mm( double aVal )
|
||||
}
|
||||
|
||||
|
||||
void EDA_UNIT_UTILS::FetchUnitsFromString( const wxString& aTextValue, EDA_UNITS& aUnits )
|
||||
bool EDA_UNIT_UTILS::FetchUnitsFromString( const wxString& aTextValue, EDA_UNITS& aUnits )
|
||||
{
|
||||
wxString buf( aTextValue.Strip( wxString::both ) );
|
||||
unsigned brk_point = 0;
|
||||
@@ -92,6 +92,9 @@ void EDA_UNIT_UTILS::FetchUnitsFromString( const wxString& aTextValue, EDA_UNITS
|
||||
aUnits = EDA_UNITS::INCHES;
|
||||
else if( unit == wxT( "de" ) || unit == wxT( "ra" ) ) // "deg" or "rad"
|
||||
aUnits = EDA_UNITS::DEGREES;
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+148
-33
@@ -18,23 +18,25 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <fontconfig/fontconfig.h>
|
||||
|
||||
#include <font/fontconfig.h>
|
||||
#include <pgm_base.h>
|
||||
#include <wx/log.h>
|
||||
#include <trace_helpers.h>
|
||||
#include <string_utils.h>
|
||||
#include <macros.h>
|
||||
#include <font/fontconfig.h>
|
||||
|
||||
using namespace fontconfig;
|
||||
|
||||
static FONTCONFIG* g_config = nullptr;
|
||||
|
||||
|
||||
inline static FcChar8* wxStringToFcChar8( const wxString& str )
|
||||
/**
|
||||
* A simple wrapper to avoid exporing fontconfig in the header
|
||||
*/
|
||||
struct fontconfig::FONTCONFIG_PAT
|
||||
{
|
||||
wxScopedCharBuffer const fcBuffer = str.ToUTF8();
|
||||
return (FcChar8*) fcBuffer.data();
|
||||
}
|
||||
FcPattern* pat;
|
||||
};
|
||||
|
||||
|
||||
wxString FONTCONFIG::Version()
|
||||
@@ -61,19 +63,112 @@ FONTCONFIG* Fontconfig()
|
||||
}
|
||||
|
||||
|
||||
bool FONTCONFIG::isLanguageMatch( const wxString& aSearchLang, const wxString& aSupportedLang )
|
||||
{
|
||||
if( aSearchLang.Lower() == aSupportedLang.Lower() )
|
||||
return true;
|
||||
|
||||
if( aSupportedLang.empty() )
|
||||
return false;
|
||||
|
||||
if( aSearchLang.empty() )
|
||||
return false;
|
||||
|
||||
wxArrayString supportedLangBits;
|
||||
wxStringSplit( aSupportedLang.Lower(), supportedLangBits, wxS( '-' ) );
|
||||
|
||||
wxArrayString searhcLangBits;
|
||||
wxStringSplit( aSearchLang.Lower(), searhcLangBits, wxS( '-' ) );
|
||||
|
||||
// if either side of the comparison have only one section, then its a broad match but fine
|
||||
// i.e. the haystack is declaring broad support or the search language is broad
|
||||
if( searhcLangBits.size() == 1 || supportedLangBits.size() == 1 )
|
||||
{
|
||||
return searhcLangBits[0] == supportedLangBits[0];
|
||||
}
|
||||
|
||||
// the full two part comparison should have passed the initial shortcut
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
std::string FONTCONFIG::getFcString( FONTCONFIG_PAT& aPat, const char* aObj, int aIdx )
|
||||
{
|
||||
FcChar8* str;
|
||||
std::string res;
|
||||
|
||||
if( FcPatternGetString( aPat.pat, aObj, aIdx, &str ) == FcResultMatch )
|
||||
res = std::string( reinterpret_cast<char*>( str ) );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void FONTCONFIG::getAllFamilyStrings( FONTCONFIG_PAT& aPat,
|
||||
std::unordered_map<std::string, std::string>& aFamStringMap )
|
||||
{
|
||||
std::string famLang;
|
||||
std::string fam;
|
||||
|
||||
int langIdx = 0;
|
||||
do
|
||||
{
|
||||
famLang = getFcString( aPat, FC_FAMILYLANG, langIdx );
|
||||
|
||||
if( famLang.empty() && langIdx != 0 )
|
||||
break;
|
||||
else
|
||||
{
|
||||
fam = getFcString( aPat, FC_FAMILY, langIdx );
|
||||
aFamStringMap.insert_or_assign( famLang, fam );
|
||||
}
|
||||
} while( langIdx++ < std::numeric_limits<
|
||||
int8_t>::max() ); //arbitrary to avoid getting stuck for any reason
|
||||
}
|
||||
|
||||
|
||||
std::string FONTCONFIG::getFamilyStringByLang( FONTCONFIG_PAT& aPat, const wxString& aDesiredLang )
|
||||
{
|
||||
std::unordered_map<std::string, std::string> famStrings;
|
||||
getAllFamilyStrings( aPat, famStrings );
|
||||
|
||||
if( famStrings.empty() )
|
||||
return "";
|
||||
|
||||
for( auto const& [key, val] : famStrings )
|
||||
{
|
||||
if( isLanguageMatch( aDesiredLang, FROM_UTF8( key.c_str() ) ) )
|
||||
{
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
// fall back to the first and maybe only available name
|
||||
// most fonts by review don't even bother declaring more than one font family name
|
||||
// and they don't even bother declare the language tag either, they just leave it blank
|
||||
return famStrings.begin()->second;
|
||||
}
|
||||
|
||||
|
||||
FONTCONFIG::FF_RESULT FONTCONFIG::FindFont( const wxString &aFontName, wxString &aFontFile,
|
||||
bool aBold, bool aItalic )
|
||||
int& aFaceIndex, bool aBold, bool aItalic )
|
||||
{
|
||||
FF_RESULT retval = FF_RESULT::FF_ERROR;
|
||||
wxString qualifiedFontName = aFontName;
|
||||
|
||||
wxScopedCharBuffer const fcBuffer = qualifiedFontName.ToUTF8();
|
||||
|
||||
FcPattern* pat = FcPatternCreate();
|
||||
|
||||
if( aBold )
|
||||
qualifiedFontName << wxS( ":Bold" );
|
||||
FcPatternAddString( pat, FC_STYLE, (const FcChar8*) "Bold" );
|
||||
|
||||
if( aItalic )
|
||||
qualifiedFontName << wxS( ":Italic" );
|
||||
FcPatternAddString( pat, FC_STYLE, (const FcChar8*) "Italic" );
|
||||
|
||||
FcPatternAddString( pat, FC_FAMILY, (FcChar8*) fcBuffer.data() );
|
||||
|
||||
FcPattern* pat = FcNameParse( wxStringToFcChar8( qualifiedFontName ) );
|
||||
FcConfigSubstitute( nullptr, pat, FcMatchPattern );
|
||||
FcDefaultSubstitute( pat );
|
||||
|
||||
@@ -89,14 +184,23 @@ FONTCONFIG::FF_RESULT FONTCONFIG::FindFont( const wxString &aFontName, wxString
|
||||
if( FcPatternGetString( font, FC_FILE, 0, &file ) == FcResultMatch )
|
||||
{
|
||||
aFontFile = wxString::FromUTF8( (char*) file );
|
||||
aFaceIndex = 0;
|
||||
|
||||
wxString styleStr;
|
||||
FcChar8* family = nullptr;
|
||||
FcChar8* style = nullptr;
|
||||
|
||||
retval = FF_RESULT::FF_SUBSTITUTE;
|
||||
|
||||
std::unordered_map<std::string, std::string> famStrings;
|
||||
FONTCONFIG_PAT patHolder{ font };
|
||||
|
||||
getAllFamilyStrings( patHolder, famStrings );
|
||||
|
||||
if( FcPatternGetString( font, FC_FAMILY, 0, &family ) == FcResultMatch )
|
||||
{
|
||||
FcPatternGetInteger( font, FC_INDEX, 0, &aFaceIndex );
|
||||
|
||||
fontName = wxString::FromUTF8( (char*) family );
|
||||
|
||||
if( FcPatternGetString( font, FC_STYLE, 0, &style ) == FcResultMatch )
|
||||
@@ -129,18 +233,26 @@ FONTCONFIG::FF_RESULT FONTCONFIG::FindFont( const wxString &aFontName, wxString
|
||||
has_ital = true;
|
||||
}
|
||||
|
||||
if( fontName.Lower().StartsWith( aFontName.Lower() ) )
|
||||
for( auto const& [key, val] : famStrings )
|
||||
{
|
||||
if( ( aBold && !has_bold ) && ( aItalic && !has_ital ) )
|
||||
retval = FF_RESULT::FF_MISSING_BOLD_ITAL;
|
||||
else if( aBold && !has_bold )
|
||||
retval = FF_RESULT::FF_MISSING_BOLD;
|
||||
else if( aItalic && !has_ital )
|
||||
retval = FF_RESULT::FF_MISSING_ITAL;
|
||||
else if( ( aBold != has_bold ) || ( aItalic != has_ital ) )
|
||||
retval = FF_RESULT::FF_SUBSTITUTE;
|
||||
else
|
||||
retval = FF_RESULT::FF_OK;
|
||||
wxString searchFont;
|
||||
searchFont = wxString::FromUTF8( (char*) val.data() );
|
||||
|
||||
if( searchFont.Lower().StartsWith( aFontName.Lower() ) )
|
||||
{
|
||||
if( ( aBold && !has_bold ) && ( aItalic && !has_ital ) )
|
||||
retval = FF_RESULT::FF_MISSING_BOLD_ITAL;
|
||||
else if( aBold && !has_bold )
|
||||
retval = FF_RESULT::FF_MISSING_BOLD;
|
||||
else if( aItalic && !has_ital )
|
||||
retval = FF_RESULT::FF_MISSING_ITAL;
|
||||
else if( ( aBold != has_bold ) || ( aItalic != has_ital ) )
|
||||
retval = FF_RESULT::FF_SUBSTITUTE;
|
||||
else
|
||||
retval = FF_RESULT::FF_OK;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -158,13 +270,14 @@ FONTCONFIG::FF_RESULT FONTCONFIG::FindFont( const wxString &aFontName, wxString
|
||||
}
|
||||
|
||||
|
||||
void FONTCONFIG::ListFonts( std::vector<std::string>& aFonts )
|
||||
void FONTCONFIG::ListFonts( std::vector<std::string>& aFonts, const std::string& aDesiredLang )
|
||||
{
|
||||
if( m_fonts.empty() )
|
||||
// be sure to cache bust if the language changed
|
||||
if( m_fontInfoCache.empty() || m_fontCacheLastLang != aDesiredLang )
|
||||
{
|
||||
FcPattern* pat = FcPatternCreate();
|
||||
FcObjectSet* os = FcObjectSetBuild( FC_FAMILY, FC_STYLE, FC_LANG, FC_FILE, FC_OUTLINE,
|
||||
nullptr );
|
||||
FcObjectSet* os = FcObjectSetBuild( FC_FAMILY, FC_FAMILYLANG, FC_STYLE, FC_LANG, FC_FILE,
|
||||
FC_OUTLINE, nullptr );
|
||||
FcFontSet* fs = FcFontList( nullptr, pat, os );
|
||||
|
||||
for( int i = 0; fs && i < fs->nfont; ++i )
|
||||
@@ -172,12 +285,10 @@ void FONTCONFIG::ListFonts( std::vector<std::string>& aFonts )
|
||||
FcPattern* font = fs->fonts[i];
|
||||
FcChar8* file;
|
||||
FcChar8* style;
|
||||
FcChar8* family;
|
||||
FcLangSet* langSet;
|
||||
FcBool outline;
|
||||
|
||||
if( FcPatternGetString( font, FC_FILE, 0, &file ) == FcResultMatch
|
||||
&& FcPatternGetString( font, FC_FAMILY, 0, &family ) == FcResultMatch
|
||||
&& FcPatternGetString( font, FC_STYLE, 0, &style ) == FcResultMatch
|
||||
&& FcPatternGetLangSet( font, FC_LANG, 0, &langSet ) == FcResultMatch
|
||||
&& FcPatternGetBool( font, FC_OUTLINE, 0, &outline ) == FcResultMatch )
|
||||
@@ -185,7 +296,9 @@ void FONTCONFIG::ListFonts( std::vector<std::string>& aFonts )
|
||||
if( !outline )
|
||||
continue;
|
||||
|
||||
std::string theFamily( reinterpret_cast<char *>( family ) );
|
||||
FONTCONFIG_PAT patHolder{ font };
|
||||
std::string theFamily =
|
||||
getFamilyStringByLang( patHolder, FROM_UTF8( aDesiredLang.c_str() ) );
|
||||
|
||||
#ifdef __WXMAC__
|
||||
// On Mac (at least) some of the font names are in their own language. If
|
||||
@@ -238,10 +351,10 @@ void FONTCONFIG::ListFonts( std::vector<std::string>& aFonts )
|
||||
if( theFamily.length() > 0 && theFamily.front() == '.' )
|
||||
continue;
|
||||
|
||||
std::map<std::string, FONTINFO>::iterator it = m_fonts.find( theFamily );
|
||||
std::map<std::string, FONTINFO>::iterator it = m_fontInfoCache.find( theFamily );
|
||||
|
||||
if( it == m_fonts.end() )
|
||||
m_fonts.emplace( theFamily, fontInfo );
|
||||
if( it == m_fontInfoCache.end() )
|
||||
m_fontInfoCache.emplace( theFamily, fontInfo );
|
||||
else
|
||||
it->second.Children().push_back( fontInfo );
|
||||
}
|
||||
@@ -249,8 +362,10 @@ void FONTCONFIG::ListFonts( std::vector<std::string>& aFonts )
|
||||
|
||||
if( fs )
|
||||
FcFontSetDestroy( fs );
|
||||
|
||||
m_fontCacheLastLang = aDesiredLang;
|
||||
}
|
||||
|
||||
for( const std::pair<const std::string, FONTINFO>& entry : m_fonts )
|
||||
for( const std::pair<const std::string, FONTINFO>& entry : m_fontInfoCache )
|
||||
aFonts.push_back( entry.second.Family() );
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ using namespace KIFONT;
|
||||
|
||||
|
||||
FT_Library OUTLINE_FONT::m_freeType = nullptr;
|
||||
std::mutex OUTLINE_FONT::m_freeTypeMutex;
|
||||
|
||||
OUTLINE_FONT::OUTLINE_FONT() :
|
||||
m_face(NULL),
|
||||
@@ -51,6 +52,8 @@ OUTLINE_FONT::OUTLINE_FONT() :
|
||||
m_fakeBold( false ),
|
||||
m_fakeItal( false )
|
||||
{
|
||||
std::lock_guard<std::mutex> guard( m_freeTypeMutex );
|
||||
|
||||
if( !m_freeType )
|
||||
FT_Init_FreeType( &m_freeType );
|
||||
}
|
||||
@@ -58,6 +61,8 @@ OUTLINE_FONT::OUTLINE_FONT() :
|
||||
|
||||
wxString OUTLINE_FONT::FreeTypeVersion()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard( m_freeTypeMutex );
|
||||
|
||||
if( !m_freeType )
|
||||
FT_Init_FreeType( &m_freeType );
|
||||
|
||||
@@ -90,12 +95,16 @@ wxString OUTLINE_FONT::FontLibraryVersion()
|
||||
|
||||
OUTLINE_FONT* OUTLINE_FONT::LoadFont( const wxString& aFontName, bool aBold, bool aItalic )
|
||||
{
|
||||
OUTLINE_FONT* font = new OUTLINE_FONT();
|
||||
std::unique_ptr<OUTLINE_FONT> font = std::make_unique<OUTLINE_FONT>();
|
||||
|
||||
wxString fontFile;
|
||||
int faceIndex;
|
||||
using fc = fontconfig::FONTCONFIG;
|
||||
|
||||
fc::FF_RESULT retval = Fontconfig()->FindFont( aFontName, fontFile, aBold, aItalic );
|
||||
fc::FF_RESULT retval = Fontconfig()->FindFont( aFontName, fontFile, faceIndex, aBold, aItalic );
|
||||
|
||||
if( retval == fc::FF_RESULT::FF_ERROR )
|
||||
return nullptr;
|
||||
|
||||
if( retval == fc::FF_RESULT::FF_MISSING_BOLD || retval == fc::FF_RESULT::FF_MISSING_BOLD_ITAL )
|
||||
font->SetFakeBold();
|
||||
@@ -103,21 +112,23 @@ OUTLINE_FONT* OUTLINE_FONT::LoadFont( const wxString& aFontName, bool aBold, boo
|
||||
if( retval == fc::FF_RESULT::FF_MISSING_ITAL || retval == fc::FF_RESULT::FF_MISSING_BOLD_ITAL )
|
||||
font->SetFakeItal();
|
||||
|
||||
if( retval != fc::FF_RESULT::FF_ERROR )
|
||||
(void) font->loadFace( fontFile );
|
||||
if( font->loadFace( fontFile, faceIndex ) != 0 )
|
||||
return nullptr;
|
||||
|
||||
font->m_fontName = aFontName; // Keep asked-for name, even if we substituted.
|
||||
font->m_fontFileName = fontFile;
|
||||
|
||||
return font;
|
||||
return font.release();
|
||||
}
|
||||
|
||||
|
||||
FT_Error OUTLINE_FONT::loadFace( const wxString& aFontFileName )
|
||||
FT_Error OUTLINE_FONT::loadFace( const wxString& aFontFileName, int aFaceIndex )
|
||||
{
|
||||
std::lock_guard<std::mutex> guard( m_freeTypeMutex );
|
||||
|
||||
// TODO: check that going from wxString to char* with UTF-8
|
||||
// conversion for filename makes sense on any/all platforms
|
||||
FT_Error e = FT_New_Face( m_freeType, aFontFileName.mb_str( wxConvUTF8 ), 0, &m_face );
|
||||
FT_Error e = FT_New_Face( m_freeType, aFontFileName.mb_str( wxConvUTF8 ), aFaceIndex, &m_face );
|
||||
|
||||
if( !e )
|
||||
{
|
||||
@@ -323,6 +334,18 @@ VECTOR2I OUTLINE_FONT::getTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_pt
|
||||
const VECTOR2I& aPosition, const EDA_ANGLE& aAngle,
|
||||
bool aMirror, const VECTOR2I& aOrigin,
|
||||
TEXT_STYLE_FLAGS aTextStyle ) const
|
||||
{
|
||||
std::lock_guard<std::mutex> guard( m_freeTypeMutex );
|
||||
|
||||
return getTextAsGlyphsUnlocked( aBBox, aGlyphs, aText, aSize, aPosition, aAngle, aMirror,
|
||||
aOrigin, aTextStyle );
|
||||
}
|
||||
|
||||
VECTOR2I OUTLINE_FONT::getTextAsGlyphsUnlocked( BOX2I* aBBox, std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
|
||||
const wxString& aText, const VECTOR2I& aSize,
|
||||
const VECTOR2I& aPosition, const EDA_ANGLE& aAngle,
|
||||
bool aMirror, const VECTOR2I& aOrigin,
|
||||
TEXT_STYLE_FLAGS aTextStyle ) const
|
||||
{
|
||||
VECTOR2D glyphSize = aSize;
|
||||
FT_Face face = m_face;
|
||||
@@ -366,7 +389,7 @@ VECTOR2I OUTLINE_FONT::getTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_pt
|
||||
{
|
||||
FT_Matrix matrix;
|
||||
// Create a 12 degree slant
|
||||
const float angle = ( -M_PI * 12 ) / 180.0f;
|
||||
const float angle = (float)( -M_PI * 12.0f ) / 180.0f;
|
||||
matrix.xx = (FT_Fixed) ( cos( angle ) * 0x10000L );
|
||||
matrix.xy = (FT_Fixed) ( -sin( angle ) * 0x10000L );
|
||||
matrix.yx = (FT_Fixed) ( 0 * 0x10000L ); // Don't rotate in the y direction
|
||||
@@ -466,7 +489,7 @@ VECTOR2I OUTLINE_FONT::getTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_pt
|
||||
{
|
||||
std::vector<std::unique_ptr<GLYPH>> underscoreGlyphs;
|
||||
|
||||
getTextAsGlyphs( nullptr, &underscoreGlyphs, wxT( "_" ), aSize, { 0, 0 }, ANGLE_0, false,
|
||||
getTextAsGlyphsUnlocked( nullptr, &underscoreGlyphs, wxT( "_" ), aSize, { 0, 0 }, ANGLE_0, false,
|
||||
{ 0, 0 }, aTextStyle & ~TEXT_STYLE::OVERBAR );
|
||||
|
||||
OUTLINE_GLYPH* underscoreGlyph = static_cast<OUTLINE_GLYPH*>( underscoreGlyphs[0].get() );
|
||||
@@ -552,6 +575,9 @@ void OUTLINE_FONT::RenderToOpenGLCanvas( KIGFX::OPENGL_GAL& aGal, const wxString
|
||||
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 );
|
||||
|
||||
std::lock_guard<std::mutex> guard( m_freeTypeMutex );
|
||||
|
||||
hb_font_t* referencedFont = hb_ft_font_create_referenced( m_face );
|
||||
|
||||
hb_ft_font_set_funcs( referencedFont );
|
||||
|
||||
+20
-10
@@ -52,7 +52,8 @@ static constexpr double UNDERLINE_POSITION_FACTOR = -0.16;
|
||||
///< Scale factor for a glyph
|
||||
static constexpr double STROKE_FONT_SCALE = 1.0 / 21.0;
|
||||
|
||||
static constexpr int FONT_OFFSET = -10;
|
||||
///< Offset (in stroke font units) to move the origin to the baseline.
|
||||
static constexpr int FONT_OFFSET = -8;
|
||||
|
||||
|
||||
bool g_defaultFontInitialized = false;
|
||||
@@ -225,11 +226,8 @@ VECTOR2I STROKE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr
|
||||
bool aMirror, const VECTOR2I& aOrigin,
|
||||
TEXT_STYLE_FLAGS aTextStyle ) const
|
||||
{
|
||||
constexpr double SPACE_WIDTH = 0.6;
|
||||
constexpr int TAB_WIDTH = 4;
|
||||
constexpr double INTER_CHAR = 0.2;
|
||||
constexpr double TAB_WIDTH = 4 * 0.82; // Not quite as wide as 5.1/6.0 tab formatting, but
|
||||
// a better match for Scintilla, and closer to the
|
||||
// nominal SPACE_WIDTH + INTER_CHAR
|
||||
constexpr double SUPER_SUB_SIZE_MULTIPLIER = 0.7;
|
||||
constexpr double SUPER_HEIGHT_OFFSET = 0.5;
|
||||
constexpr double SUB_HEIGHT_OFFSET = 0.3;
|
||||
@@ -237,6 +235,8 @@ VECTOR2I STROKE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr
|
||||
VECTOR2I cursor( aPosition );
|
||||
VECTOR2D glyphSize( aSize );
|
||||
double tilt = ( aTextStyle & TEXT_STYLE::ITALIC ) ? ITALIC_TILT : 0.0;
|
||||
double space_width = m_glyphBoundingBoxes->front().GetWidth(); // First char is space
|
||||
int char_count = 0;
|
||||
|
||||
if( aTextStyle & TEXT_STYLE::SUBSCRIPT || aTextStyle & TEXT_STYLE::SUPERSCRIPT )
|
||||
{
|
||||
@@ -250,18 +250,26 @@ VECTOR2I STROKE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr
|
||||
|
||||
for( wxUniChar c : aText )
|
||||
{
|
||||
// Handle tabs as locked to the nearest 4th column (in space-widths).
|
||||
// Handle tabs as locked to the next 4th column (in base-widths).
|
||||
if( c == '\t' )
|
||||
{
|
||||
int tabWidth = KiROUND( glyphSize.x * TAB_WIDTH );
|
||||
int currentIntrusion = ( cursor.x - aOrigin.x ) % tabWidth;
|
||||
char_count = ( char_count / TAB_WIDTH + 1 ) * TAB_WIDTH - 1;
|
||||
|
||||
cursor.x += tabWidth - currentIntrusion;
|
||||
int new_cursor = aPosition.x + aSize.x * char_count
|
||||
+ aSize.x * space_width;
|
||||
|
||||
while( new_cursor <= cursor.x )
|
||||
{
|
||||
char_count += TAB_WIDTH;
|
||||
new_cursor += aSize.x * TAB_WIDTH;
|
||||
}
|
||||
|
||||
cursor.x = new_cursor;
|
||||
}
|
||||
else if( c == ' ' )
|
||||
{
|
||||
// 'space' character - draw nothing, advance cursor position
|
||||
cursor.x += KiROUND( glyphSize.x * SPACE_WIDTH );
|
||||
cursor.x += KiROUND( glyphSize.x * space_width );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -292,6 +300,8 @@ VECTOR2I STROKE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr
|
||||
|
||||
cursor.x += KiROUND( glyphExtents.x );
|
||||
}
|
||||
|
||||
++char_count;
|
||||
}
|
||||
|
||||
VECTOR2D barOffset( 0.0, 0.0 );
|
||||
|
||||
@@ -596,6 +596,7 @@ bool FP_LIB_TABLE::LoadGlobalTable( FP_LIB_TABLE& aTable )
|
||||
}
|
||||
}
|
||||
|
||||
aTable.Clear();
|
||||
aTable.Load( fn.GetFullPath() );
|
||||
|
||||
SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
|
||||
|
||||
+47
-13
@@ -57,11 +57,6 @@ static std::optional<double> getKiCadConfiguredScale( const COMMON_SETTINGS& aCo
|
||||
scale = canvas_scale;
|
||||
}
|
||||
|
||||
if( scale )
|
||||
{
|
||||
wxLogTrace( traceHiDpi, wxS( "Scale factor (configured): %f" ), *scale );
|
||||
}
|
||||
|
||||
return scale;
|
||||
}
|
||||
|
||||
@@ -83,11 +78,6 @@ static std::optional<double> getEnvironmentScale()
|
||||
scale = ENV_VAR::GetEnvVar<double>( wxS( "GDK_SCALE" ) );
|
||||
}
|
||||
|
||||
if( scale )
|
||||
{
|
||||
wxLogTrace( traceHiDpi, wxS( "Scale factor (environment): %f" ), *scale );
|
||||
}
|
||||
|
||||
return scale;
|
||||
}
|
||||
|
||||
@@ -101,15 +91,18 @@ DPI_SCALING::DPI_SCALING( COMMON_SETTINGS* aConfig, const wxWindow* aWindow )
|
||||
double DPI_SCALING::GetScaleFactor() const
|
||||
{
|
||||
std::optional<double> val;
|
||||
wxString src;
|
||||
|
||||
if( m_config )
|
||||
{
|
||||
val = getKiCadConfiguredScale( *m_config );
|
||||
src = wxS( "config" );
|
||||
}
|
||||
|
||||
if( !val )
|
||||
{
|
||||
val = getEnvironmentScale();
|
||||
src = wxS( "env" );
|
||||
}
|
||||
|
||||
if( !val && m_window )
|
||||
@@ -117,17 +110,58 @@ double DPI_SCALING::GetScaleFactor() const
|
||||
// Use the native WX reporting.
|
||||
// On Linux, this will not work until WX 3.2 and GTK >= 3.10
|
||||
// Otherwise it returns 1.0
|
||||
val = KIPLATFORM::UI::GetSystemScaleFactor( m_window );
|
||||
wxLogTrace( traceHiDpi, wxS( "Scale factor (WX): %f" ), *val );
|
||||
val = KIPLATFORM::UI::GetPixelScaleFactor( m_window );
|
||||
src = wxS( "platform" );
|
||||
}
|
||||
|
||||
if( !val )
|
||||
{
|
||||
// Nothing else we can do, give it a default value
|
||||
val = GetDefaultScaleFactor();
|
||||
wxLogTrace( traceHiDpi, wxS( "Scale factor (default): %f" ), *val );
|
||||
src = wxS( "default" );
|
||||
}
|
||||
|
||||
wxLogTrace( traceHiDpi, wxS( "Scale factor (%s): %f" ), src, *val );
|
||||
|
||||
return *val;
|
||||
}
|
||||
|
||||
|
||||
double DPI_SCALING::GetContentScaleFactor() const
|
||||
{
|
||||
std::optional<double> val;
|
||||
wxString src;
|
||||
|
||||
if( m_config )
|
||||
{
|
||||
val = getKiCadConfiguredScale( *m_config );
|
||||
src = wxS( "config" );
|
||||
}
|
||||
|
||||
if( !val )
|
||||
{
|
||||
val = getEnvironmentScale();
|
||||
src = wxS( "env" );
|
||||
}
|
||||
|
||||
if( !val && m_window )
|
||||
{
|
||||
// Use the native WX reporting.
|
||||
// On Linux, this will not work until WX 3.2 and GTK >= 3.10
|
||||
// Otherwise it returns 1.0
|
||||
val = KIPLATFORM::UI::GetContentScaleFactor( m_window );
|
||||
src = wxS( "platform" );
|
||||
}
|
||||
|
||||
if( !val )
|
||||
{
|
||||
// Nothing else we can do, give it a default value
|
||||
val = GetDefaultScaleFactor();
|
||||
src = wxS( "default" );
|
||||
}
|
||||
|
||||
wxLogTrace( traceHiDpi, wxS( "Content scale factor (%s): %f" ), src, *val );
|
||||
|
||||
return *val;
|
||||
}
|
||||
|
||||
|
||||
@@ -169,14 +169,6 @@ GLuint GL_BITMAP_CACHE::cacheBitmap( const BITMAP_BASE* aBitmap )
|
||||
bmp.w = imgData.GetSize().x;
|
||||
bmp.h = imgData.GetSize().y;
|
||||
|
||||
// The bitmap size needs to be a multiple of 4.
|
||||
// This is easiest to achieve by ensuring that each row
|
||||
// has a multiple of 4 pixels
|
||||
int extra_w = bmp.w % 4;
|
||||
|
||||
if( extra_w )
|
||||
extra_w = 4 - extra_w;
|
||||
|
||||
GLuint textureID;
|
||||
|
||||
if( m_freedTextureIds.empty() )
|
||||
@@ -189,15 +181,14 @@ GLuint GL_BITMAP_CACHE::cacheBitmap( const BITMAP_BASE* aBitmap )
|
||||
m_freedTextureIds.pop_front();
|
||||
}
|
||||
|
||||
// make_unique initializes this to 0, so extra pixels are transparent
|
||||
bmp.size = ( bmp.w + extra_w ) * bmp.h * 4;
|
||||
bmp.size = bmp.w * bmp.h * 4;
|
||||
auto buf = std::make_unique<uint8_t[]>( bmp.size );
|
||||
|
||||
for( int y = 0; y < bmp.h; y++ )
|
||||
{
|
||||
for( int x = 0; x < bmp.w; x++ )
|
||||
{
|
||||
uint8_t* p = buf.get() + ( ( bmp.w + extra_w ) * y + x ) * 4;
|
||||
uint8_t* p = buf.get() + ( bmp.w * y + x ) * 4;
|
||||
|
||||
p[0] = imgData.GetRed( x, y );
|
||||
p[1] = imgData.GetGreen( x, y );
|
||||
@@ -214,7 +205,7 @@ GLuint GL_BITMAP_CACHE::cacheBitmap( const BITMAP_BASE* aBitmap )
|
||||
}
|
||||
|
||||
glBindTexture( GL_TEXTURE_2D, textureID );
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, bmp.w + extra_w, bmp.h, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, bmp.w, bmp.h, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
buf.get() );
|
||||
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
|
||||
|
||||
@@ -91,6 +91,11 @@ void GRSetColorPen( wxDC* DC, const COLOR4D& Color, int width, wxPenStyle style
|
||||
if( s_ForceBlackPen )
|
||||
color = COLOR4D::BLACK;
|
||||
|
||||
// wxWidgets will enforce a minimum pen width when printing, so we have to make the pen
|
||||
// transparent when we don't want the object stroked.
|
||||
if( width == 0 )
|
||||
color = COLOR4D::UNSPECIFIED;
|
||||
|
||||
const wxPen& curr_pen = DC->GetPen();
|
||||
|
||||
if( !curr_pen.IsOk() || curr_pen.GetColour() != color.ToColour()
|
||||
|
||||
@@ -424,6 +424,7 @@ void GRID_TRICKS::onCharHook( wxKeyEvent& ev )
|
||||
{
|
||||
wxCommandEvent dummy;
|
||||
m_addHandler( dummy );
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
else if( ev.GetModifiers() == wxMOD_CONTROL && ev.GetKeyCode() == 'V' )
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Mark Roszko <mark.roszko@gmail.com>
|
||||
* Copyright (C) 2015-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2015-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
|
||||
@@ -100,12 +100,13 @@ static int xferinfo( void* aProgress, curl_off_t aDLtotal, curl_off_t aDLnow, cu
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
||||
#if LIBCURL_VERSION_NUM < 0x072000 // 7.32.0
|
||||
static int progressinfo( void* aProgress, double aDLtotal, double aDLnow, double aULtotal, double aULnow )
|
||||
{
|
||||
return xferinfo( aProgress, static_cast<curl_off_t>( aDLtotal ), static_cast<curl_off_t>( aDLnow ),
|
||||
static_cast<curl_off_t>( aULtotal ), static_cast<curl_off_t>( aULnow ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
KICAD_CURL_EASY::KICAD_CURL_EASY() :
|
||||
@@ -126,7 +127,11 @@ KICAD_CURL_EASY::KICAD_CURL_EASY() :
|
||||
curl_easy_setopt( m_CURL, CURLOPT_WRITEDATA, static_cast<void*>( &m_buffer ) );
|
||||
|
||||
// Only allow HTTP and HTTPS protocols
|
||||
#if LIBCURL_VERSION_NUM >= 0x075500 // version 7.85.0
|
||||
curl_easy_setopt(m_CURL, CURLOPT_PROTOCOLS_STR, "http,https");
|
||||
#else
|
||||
curl_easy_setopt( m_CURL, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS );
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
// We need this to use the Windows Certificate store
|
||||
@@ -264,7 +269,7 @@ bool KICAD_CURL_EASY::SetTransferCallback( const TRANSFER_CALLBACK& aCallback, s
|
||||
{
|
||||
progress = std::make_unique<CURL_PROGRESS>( this, aCallback,
|
||||
static_cast<curl_off_t>( aInterval ) );
|
||||
#ifdef CURLOPT_XFERINFOFUNCTION
|
||||
#if LIBCURL_VERSION_NUM >= 0x072000 // 7.32.0
|
||||
setOption( CURLOPT_XFERINFOFUNCTION, xferinfo );
|
||||
setOption( CURLOPT_XFERINFODATA, progress.get() );
|
||||
#else
|
||||
@@ -286,7 +291,7 @@ bool KICAD_CURL_EASY::SetOutputStream( const std::ostream* aOutput )
|
||||
|
||||
int KICAD_CURL_EASY::GetTransferTotal( uint64_t& aDownloadedBytes ) const
|
||||
{
|
||||
#ifdef CURLINFO_SIZE_DOWNLOAD_T
|
||||
#if LIBCURL_VERSION_NUM >= 0x073700 // 7.55.0
|
||||
curl_off_t dl;
|
||||
int result = curl_easy_getinfo( m_CURL, CURLINFO_SIZE_DOWNLOAD_T, &dl );
|
||||
aDownloadedBytes = static_cast<uint64_t>( dl );
|
||||
|
||||
+6
-4
@@ -431,15 +431,17 @@ KIWAY_PLAYER* KIWAY::Player( FRAME_T aFrameType, bool doCreate, wxTopLevelWindow
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
DisplayErrorMessage( nullptr, _( "Error loading editor." ), ioe.What() );
|
||||
wxLogError( ioe.What() );
|
||||
wxLogError( _( "Error loading editor." ) );
|
||||
}
|
||||
catch( const std::exception& e)
|
||||
catch( const std::exception& e )
|
||||
{
|
||||
DisplayErrorMessage( nullptr, _( "Error loading editor." ), e.what() );
|
||||
wxLogError( e.what() );
|
||||
wxLogError( _( "Error loading editor." ) );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
DisplayErrorMessage( nullptr, _( "Error loading editor." ) );
|
||||
wxLogError( _( "Error loading editor." ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -193,6 +193,8 @@ LIB_TABLE_ROW* LIB_TABLE::findRow( const wxString& aNickName, bool aCheckIfEnabl
|
||||
{
|
||||
cur->ensureIndex();
|
||||
|
||||
std::shared_lock<std::shared_mutex> lock( cur->m_nickIndexMutex );
|
||||
|
||||
for( const std::pair<const wxString, int>& entry : cur->m_nickIndex )
|
||||
{
|
||||
if( entry.first == aNickName )
|
||||
@@ -303,7 +305,7 @@ bool LIB_TABLE::InsertRow( LIB_TABLE_ROW* aRow, bool doReplace )
|
||||
{
|
||||
ensureIndex();
|
||||
|
||||
std::lock_guard<std::mutex> lock( m_nickIndexMutex );
|
||||
std::lock_guard<std::shared_mutex> lock( m_nickIndexMutex );
|
||||
|
||||
INDEX_CITER it = m_nickIndex.find( aRow->GetNickName() );
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2017-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 as published by the
|
||||
@@ -24,12 +24,16 @@ LIB_TABLE_GRID_TRICKS::LIB_TABLE_GRID_TRICKS( WX_GRID* aGrid ) : GRID_TRICKS( aG
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void LIB_TABLE_GRID_TRICKS::showPopupMenu( wxMenu& menu )
|
||||
{
|
||||
bool showActivate = false;
|
||||
bool showDeactivate = false;
|
||||
LIB_TABLE_GRID* tbl = static_cast<LIB_TABLE_GRID*>( m_grid->GetTable() );
|
||||
|
||||
// Ensure selection parameters are up to date
|
||||
getSelectedArea();
|
||||
|
||||
for( int row = m_sel_row_start; row < m_sel_row_start + m_sel_row_count; ++row )
|
||||
{
|
||||
if( tbl->GetValueAsBool( row, 0 ) )
|
||||
@@ -49,10 +53,14 @@ void LIB_TABLE_GRID_TRICKS::showPopupMenu( wxMenu& menu )
|
||||
menu.Append( LIB_TABLE_GRID_TRICKS_ACTIVATE_SELECTED, _( "Activate selected" ) );
|
||||
if( showDeactivate )
|
||||
menu.Append( LIB_TABLE_GRID_TRICKS_DEACTIVATE_SELECTED, _( "Deactivate selected" ) );
|
||||
menu.AppendSeparator();
|
||||
|
||||
if( showActivate || showDeactivate )
|
||||
menu.AppendSeparator();
|
||||
|
||||
GRID_TRICKS::showPopupMenu( menu );
|
||||
}
|
||||
|
||||
|
||||
void LIB_TABLE_GRID_TRICKS::doPopupSelection( wxCommandEvent& event )
|
||||
{
|
||||
int menu_id = event.GetId();
|
||||
@@ -61,10 +69,13 @@ void LIB_TABLE_GRID_TRICKS::doPopupSelection( wxCommandEvent& event )
|
||||
{
|
||||
LIB_TABLE_GRID* tbl = (LIB_TABLE_GRID*) m_grid->GetTable();
|
||||
|
||||
bool selected_state = menu_id == LIB_TABLE_GRID_TRICKS_ACTIVATE_SELECTED;
|
||||
|
||||
for( int row = m_sel_row_start; row < m_sel_row_start + m_sel_row_count; ++row )
|
||||
{
|
||||
tbl->SetValueAsBool( row, 0, menu_id == LIB_TABLE_GRID_TRICKS_ACTIVATE_SELECTED );
|
||||
}
|
||||
tbl->SetValueAsBool( row, 0, selected_state );
|
||||
|
||||
// Ensure the new state (on/off) of the widgets is immediately shown:
|
||||
m_grid->Refresh();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -269,7 +269,7 @@ void LIB_TREE_MODEL_ADAPTER::recreateColumns()
|
||||
for( const wxString& colName : m_shownColumns )
|
||||
{
|
||||
if( !m_colNameMap.count( colName ) )
|
||||
doAddColumn( colName, false );
|
||||
doAddColumn( colName, colName == wxT( "Description" ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is part of libeval, a simple math expression evaluator
|
||||
*
|
||||
* Copyright (C) 2017 Michael Geselbracht, mgeselbracht3@gmail.com
|
||||
* Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2019-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 as published by
|
||||
@@ -356,10 +356,11 @@ void COMPILER::newString( const wxString& aString )
|
||||
m_parseFinished = false;
|
||||
}
|
||||
|
||||
|
||||
T_TOKEN COMPILER::getToken()
|
||||
{
|
||||
T_TOKEN rv;
|
||||
rv.value.str = nullptr;
|
||||
rv.value = defaultTokenValue;
|
||||
|
||||
bool done = false;
|
||||
|
||||
|
||||
+39
-1
@@ -110,7 +110,7 @@ LANGUAGE_DESCR LanguagesList[] =
|
||||
{ wxLANGUAGE_SWEDISH, ID_LANGUAGE_SWEDISH, wxT( "Svenska" ), true },
|
||||
// { wxLANGUAGE_VIETNAMESE, ID_LANGUAGE_VIETNAMESE, wxT( "Tiếng Việt" ), true },
|
||||
// { wxLANGUAGE_TURKISH, ID_LANGUAGE_TURKISH, wxT( "Türkçe" ), true },
|
||||
{ wxLANGUAGE_UKRAINIAN, ID_LANGUAGE_UKRANIAN, wxT( "Українець" ), true },
|
||||
{ wxLANGUAGE_UKRAINIAN, ID_LANGUAGE_UKRANIAN, wxT( "Українська" ), true },
|
||||
{ wxLANGUAGE_CHINESE_SIMPLIFIED, ID_LANGUAGE_CHINESE_SIMPLIFIED,
|
||||
wxT( "简体中文" ), true },
|
||||
{ wxLANGUAGE_CHINESE_TRADITIONAL, ID_LANGUAGE_CHINESE_TRADITIONAL,
|
||||
@@ -775,6 +775,26 @@ void PGM_BASE::SetLanguageIdentifier( int menu_id )
|
||||
}
|
||||
|
||||
|
||||
wxString PGM_BASE::GetLanguageTag()
|
||||
{
|
||||
const wxLanguageInfo* langInfo = wxLocale::GetLanguageInfo( m_language_id );
|
||||
|
||||
if( !langInfo )
|
||||
return "";
|
||||
else
|
||||
{
|
||||
#if wxCHECK_VERSION( 3, 1, 6 )
|
||||
wxString str = langInfo->GetCanonicalWithRegion();
|
||||
#else
|
||||
wxString str = langInfo->CanonicalName;
|
||||
#endif
|
||||
str.Replace( "_", "-" );
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PGM_BASE::SetLanguagePath()
|
||||
{
|
||||
wxLocale::AddCatalogLookupPathPrefix( PATHS::GetLocaleDataPath() );
|
||||
@@ -837,3 +857,21 @@ ENV_VAR_MAP& PGM_BASE::GetLocalEnvVariables() const
|
||||
{
|
||||
return GetCommonSettings()->m_Env.vars;
|
||||
}
|
||||
|
||||
|
||||
bool PGM_BASE::IsGUI()
|
||||
{
|
||||
if( !wxTheApp )
|
||||
return false;
|
||||
|
||||
#if wxCHECK_VERSION( 3, 1, 6 )
|
||||
return wxTheApp->IsGUI();
|
||||
#else
|
||||
// wxWidgets older than version 3.1.6 do not have a way to know if the app
|
||||
// has a GUI or is a console application.
|
||||
// So the trick is to set the App class name when starting kicad-cli, and when
|
||||
// the app class name is the kicad-cli class name the app is a console app
|
||||
bool run_gui = wxTheApp->GetClassName() != KICAD_CLI_APP_NAME;
|
||||
return run_gui;
|
||||
#endif
|
||||
}
|
||||
+180
-139
@@ -861,145 +861,186 @@ void DXF_PLOTTER::Text( const VECTOR2I& aPos,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Emit text as a text entity. This loses formatting and shape but it's
|
||||
more useful as a CAD object */
|
||||
VECTOR2D origin_dev = userToDeviceCoordinates( aPos );
|
||||
SetColor( aColor );
|
||||
wxString cname = getDXFColorName( m_currentColor );
|
||||
VECTOR2D size_dev = userToDeviceSize( aSize );
|
||||
int h_code = 0, v_code = 0;
|
||||
|
||||
switch( aH_justify )
|
||||
{
|
||||
case GR_TEXT_H_ALIGN_LEFT: h_code = 0; break;
|
||||
case GR_TEXT_H_ALIGN_CENTER: h_code = 1; break;
|
||||
case GR_TEXT_H_ALIGN_RIGHT: h_code = 2; break;
|
||||
}
|
||||
|
||||
switch( aV_justify )
|
||||
{
|
||||
case GR_TEXT_V_ALIGN_TOP: v_code = 3; break;
|
||||
case GR_TEXT_V_ALIGN_CENTER: v_code = 2; break;
|
||||
case GR_TEXT_V_ALIGN_BOTTOM: v_code = 1; break;
|
||||
}
|
||||
|
||||
// Position, size, rotation and alignment
|
||||
// The two alignment point usages is somewhat idiot (see the DXF ref)
|
||||
// Anyway since we don't use the fit/aligned options, they're the same
|
||||
fprintf( m_outputFile,
|
||||
" 0\n"
|
||||
"TEXT\n"
|
||||
" 7\n"
|
||||
"%s\n" // Text style
|
||||
" 8\n"
|
||||
"%s\n" // Layer name
|
||||
" 10\n"
|
||||
"%g\n" // First point X
|
||||
" 11\n"
|
||||
"%g\n" // Second point X
|
||||
" 20\n"
|
||||
"%g\n" // First point Y
|
||||
" 21\n"
|
||||
"%g\n" // Second point Y
|
||||
" 40\n"
|
||||
"%g\n" // Text height
|
||||
" 41\n"
|
||||
"%g\n" // Width factor
|
||||
" 50\n"
|
||||
"%g\n" // Rotation
|
||||
" 51\n"
|
||||
"%g\n" // Oblique angle
|
||||
" 71\n"
|
||||
"%d\n" // Mirror flags
|
||||
" 72\n"
|
||||
"%d\n" // H alignment
|
||||
" 73\n"
|
||||
"%d\n", // V alignment
|
||||
aBold ? (aItalic ? "KICADBI" : "KICADB") : (aItalic ? "KICADI" : "KICAD"),
|
||||
TO_UTF8( cname ),
|
||||
origin_dev.x, origin_dev.x,
|
||||
origin_dev.y, origin_dev.y,
|
||||
size_dev.y, fabs( size_dev.x / size_dev.y ),
|
||||
aOrient.AsDegrees(),
|
||||
aItalic ? DXF_OBLIQUE_ANGLE : 0,
|
||||
size_dev.x < 0 ? 2 : 0, // X mirror flag
|
||||
h_code, v_code );
|
||||
|
||||
/* There are two issue in emitting the text:
|
||||
- Our overline character (~) must be converted to the appropriate
|
||||
control sequence %%O or %%o
|
||||
- Text encoding in DXF is more or less unspecified since depends on
|
||||
the DXF declared version, the acad version reading it *and* some
|
||||
system variables to be put in the header handled only by newer acads
|
||||
Also before R15 unicode simply is not supported (you need to use
|
||||
bigfonts which are a massive PITA). Common denominator solution:
|
||||
use Latin1 (and however someone could choke on it, anyway). Sorry
|
||||
for the extended latin people. If somewant want to try fixing this
|
||||
recent version seems to use UTF-8 (and not UCS2 like the rest of
|
||||
Windows)
|
||||
|
||||
XXX Actually there is a *third* issue: older DXF formats are limited
|
||||
to 255 bytes records (it was later raised to 2048); since I'm lazy
|
||||
and text so long is not probable I just don't implement this rule.
|
||||
If someone is interested in fixing this, you have to emit the first
|
||||
partial lines with group code 3 (max 250 bytes each) and then finish
|
||||
with a group code 1 (less than 250 bytes). The DXF refs explains it
|
||||
in no more details...
|
||||
*/
|
||||
|
||||
int braceNesting = 0;
|
||||
int overbarDepth = -1;
|
||||
|
||||
fputs( " 1\n", m_outputFile );
|
||||
|
||||
for( unsigned int i = 0; i < aText.length(); i++ )
|
||||
{
|
||||
/* Here I do a bad thing: writing the output one byte at a time!
|
||||
but today I'm lazy and I have no idea on how to coerce a Unicode
|
||||
wxString to spit out latin1 encoded text ...
|
||||
|
||||
At least stdio is *supposed* to do output buffering, so there is
|
||||
hope is not too slow */
|
||||
wchar_t ch = aText[i];
|
||||
|
||||
if( ch > 255 )
|
||||
{
|
||||
// I can't encode this...
|
||||
putc( '?', m_outputFile );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( aText[i] == '~' && i+1 < aText.length() && aText[i+1] == '{' )
|
||||
{
|
||||
fputs( "%%o", m_outputFile );
|
||||
overbarDepth = braceNesting;
|
||||
|
||||
// Skip the '{'
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else if( aText[i] == '{' )
|
||||
{
|
||||
braceNesting++;
|
||||
}
|
||||
else if( aText[i] == '}' )
|
||||
{
|
||||
if( braceNesting > 0 )
|
||||
braceNesting--;
|
||||
|
||||
if( braceNesting == overbarDepth )
|
||||
{
|
||||
fputs( "%%O", m_outputFile );
|
||||
overbarDepth = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
putc( ch, m_outputFile );
|
||||
}
|
||||
}
|
||||
|
||||
putc( '\n', m_outputFile );
|
||||
TEXT_ATTRIBUTES attrs;
|
||||
attrs.m_Halign = aH_justify;
|
||||
attrs.m_Valign =aV_justify;
|
||||
attrs.m_StrokeWidth = aWidth;
|
||||
attrs.m_Angle = aOrient;
|
||||
attrs.m_Italic = aItalic;
|
||||
attrs.m_Bold = aBold;
|
||||
attrs.m_Mirrored = aSize.x < 0;
|
||||
attrs.m_Multiline = false;
|
||||
plotOneLineOfText( aPos, aColor, aText, attrs );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DXF_PLOTTER::PlotText( const VECTOR2I& aPos, const COLOR4D& aColor,
|
||||
const wxString& aText,
|
||||
const TEXT_ATTRIBUTES& aAttributes,
|
||||
KIFONT::FONT* aFont,
|
||||
void* aData )
|
||||
{
|
||||
TEXT_ATTRIBUTES attrs = aAttributes;
|
||||
// Fix me: see how to use DXF text mode for multiline texts
|
||||
if( attrs.m_Multiline && !aText.Contains( wxT( "\n" ) ) )
|
||||
attrs.m_Multiline = false; // the text has only one line.
|
||||
|
||||
bool processSuperSub = aText.Contains( wxT( "^{" ) ) || aText.Contains( wxT( "_{" ) );
|
||||
|
||||
if( m_textAsLines || containsNonAsciiChars( aText ) || attrs.m_Multiline || processSuperSub )
|
||||
{
|
||||
// output text as graphics.
|
||||
// Perhaps multiline texts could be handled as DXF text entity
|
||||
// but I do not want spend time about that (JPC)
|
||||
PLOTTER::PlotText( aPos, aColor, aText, aAttributes, aFont, aData );
|
||||
}
|
||||
else
|
||||
plotOneLineOfText( aPos, aColor, aText, attrs );
|
||||
}
|
||||
|
||||
void DXF_PLOTTER::plotOneLineOfText( const VECTOR2I& aPos, const COLOR4D& aColor,
|
||||
const wxString& aText,
|
||||
const TEXT_ATTRIBUTES& aAttributes )
|
||||
{
|
||||
/* Emit text as a text entity. This loses formatting and shape but it's
|
||||
more useful as a CAD object */
|
||||
VECTOR2D origin_dev = userToDeviceCoordinates( aPos );
|
||||
SetColor( aColor );
|
||||
wxString cname = getDXFColorName( m_currentColor );
|
||||
VECTOR2D size_dev = userToDeviceSize( aAttributes.m_Size );
|
||||
int h_code = 0, v_code = 0;
|
||||
|
||||
switch( aAttributes.m_Halign )
|
||||
{
|
||||
case GR_TEXT_H_ALIGN_LEFT: h_code = 0; break;
|
||||
case GR_TEXT_H_ALIGN_CENTER: h_code = 1; break;
|
||||
case GR_TEXT_H_ALIGN_RIGHT: h_code = 2; break;
|
||||
}
|
||||
|
||||
switch( aAttributes.m_Valign )
|
||||
{
|
||||
case GR_TEXT_V_ALIGN_TOP: v_code = 3; break;
|
||||
case GR_TEXT_V_ALIGN_CENTER: v_code = 2; break;
|
||||
case GR_TEXT_V_ALIGN_BOTTOM: v_code = 1; break;
|
||||
}
|
||||
|
||||
// Position, size, rotation and alignment
|
||||
// The two alignment point usages is somewhat idiot (see the DXF ref)
|
||||
// Anyway since we don't use the fit/aligned options, they're the same
|
||||
fprintf( m_outputFile,
|
||||
" 0\n"
|
||||
"TEXT\n"
|
||||
" 7\n"
|
||||
"%s\n" // Text style
|
||||
" 8\n"
|
||||
"%s\n" // Layer name
|
||||
" 10\n"
|
||||
"%g\n" // First point X
|
||||
" 11\n"
|
||||
"%g\n" // Second point X
|
||||
" 20\n"
|
||||
"%g\n" // First point Y
|
||||
" 21\n"
|
||||
"%g\n" // Second point Y
|
||||
" 40\n"
|
||||
"%g\n" // Text height
|
||||
" 41\n"
|
||||
"%g\n" // Width factor
|
||||
" 50\n"
|
||||
"%g\n" // Rotation
|
||||
" 51\n"
|
||||
"%g\n" // Oblique angle
|
||||
" 71\n"
|
||||
"%d\n" // Mirror flags
|
||||
" 72\n"
|
||||
"%d\n" // H alignment
|
||||
" 73\n"
|
||||
"%d\n", // V alignment
|
||||
aAttributes.m_Bold ?
|
||||
(aAttributes.m_Italic ? "KICADBI" : "KICADB")
|
||||
: (aAttributes.m_Italic ? "KICADI" : "KICAD"), TO_UTF8( cname ),
|
||||
origin_dev.x, origin_dev.x,
|
||||
origin_dev.y, origin_dev.y,
|
||||
size_dev.y, fabs( size_dev.x / size_dev.y ),
|
||||
aAttributes.m_Angle.AsDegrees(),
|
||||
aAttributes.m_Italic ? DXF_OBLIQUE_ANGLE : 0,
|
||||
aAttributes.m_Mirrored ? 2 : 0, // X mirror flag
|
||||
h_code, v_code );
|
||||
|
||||
/* There are two issue in emitting the text:
|
||||
- Our overline character (~) must be converted to the appropriate
|
||||
control sequence %%O or %%o
|
||||
- Text encoding in DXF is more or less unspecified since depends on
|
||||
the DXF declared version, the acad version reading it *and* some
|
||||
system variables to be put in the header handled only by newer acads
|
||||
Also before R15 unicode simply is not supported (you need to use
|
||||
bigfonts which are a massive PITA). Common denominator solution:
|
||||
use Latin1 (and however someone could choke on it, anyway). Sorry
|
||||
for the extended latin people. If somewant want to try fixing this
|
||||
recent version seems to use UTF-8 (and not UCS2 like the rest of
|
||||
Windows)
|
||||
|
||||
XXX Actually there is a *third* issue: older DXF formats are limited
|
||||
to 255 bytes records (it was later raised to 2048); since I'm lazy
|
||||
and text so long is not probable I just don't implement this rule.
|
||||
If someone is interested in fixing this, you have to emit the first
|
||||
partial lines with group code 3 (max 250 bytes each) and then finish
|
||||
with a group code 1 (less than 250 bytes). The DXF refs explains it
|
||||
in no more details...
|
||||
*/
|
||||
|
||||
int braceNesting = 0;
|
||||
int overbarDepth = -1;
|
||||
|
||||
fputs( " 1\n", m_outputFile );
|
||||
|
||||
for( unsigned int i = 0; i < aText.length(); i++ )
|
||||
{
|
||||
/* Here I do a bad thing: writing the output one byte at a time!
|
||||
but today I'm lazy and I have no idea on how to coerce a Unicode
|
||||
wxString to spit out latin1 encoded text ...
|
||||
|
||||
At least stdio is *supposed* to do output buffering, so there is
|
||||
hope is not too slow */
|
||||
wchar_t ch = aText[i];
|
||||
|
||||
if( ch > 255 )
|
||||
{
|
||||
// I can't encode this...
|
||||
putc( '?', m_outputFile );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( aText[i] == '~' && i+1 < aText.length() && aText[i+1] == '{' )
|
||||
{
|
||||
fputs( "%%o", m_outputFile );
|
||||
overbarDepth = braceNesting;
|
||||
|
||||
// Skip the '{'
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else if( aText[i] == '{' )
|
||||
{
|
||||
braceNesting++;
|
||||
}
|
||||
else if( aText[i] == '}' )
|
||||
{
|
||||
if( braceNesting > 0 )
|
||||
braceNesting--;
|
||||
|
||||
if( braceNesting == overbarDepth )
|
||||
{
|
||||
fputs( "%%O", m_outputFile );
|
||||
overbarDepth = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
putc( ch, m_outputFile );
|
||||
}
|
||||
}
|
||||
|
||||
putc( '\n', m_outputFile );
|
||||
}
|
||||
|
||||
@@ -154,7 +154,6 @@ void GERBER_PLOTTER::SetGerberCoordinatesFormat( int aResolution, bool aUseInche
|
||||
|
||||
void GERBER_PLOTTER::emitDcode( const VECTOR2D& pt, int dcode )
|
||||
{
|
||||
|
||||
fprintf( m_outputFile, "X%dY%dD%02d*\n", KiROUND( pt.x ), KiROUND( pt.y ), dcode );
|
||||
}
|
||||
|
||||
@@ -849,11 +848,16 @@ void GERBER_PLOTTER::plotArc( const SHAPE_ARC& aArc, bool aPlotInRegion )
|
||||
LineTo( start );
|
||||
|
||||
VECTOR2D devEnd = userToDeviceCoordinates( end );
|
||||
VECTOR2D devCenter = userToDeviceCoordinates( center - start );
|
||||
|
||||
// devRelCenter is the position on arc center relative to the arc start, in Gerber coord.
|
||||
// Warning: it is **not** userToDeviceCoordinates( center - start ) when the plotter
|
||||
// has an offset.
|
||||
VECTOR2D devRelCenter = userToDeviceCoordinates( center ) - userToDeviceCoordinates( start );
|
||||
|
||||
// We need to know if the arc is CW or CCW in device coordinates, so build this arc.
|
||||
SHAPE_ARC deviceArc( userToDeviceCoordinates( start ),
|
||||
userToDeviceCoordinates( aArc.GetArcMid() ), devEnd, 0 );
|
||||
userToDeviceCoordinates( aArc.GetArcMid() ),
|
||||
devEnd, 0 );
|
||||
|
||||
fprintf( m_outputFile, "G75*\n" ); // Multiquadrant (360 degrees) mode
|
||||
|
||||
@@ -864,7 +868,7 @@ void GERBER_PLOTTER::plotArc( const SHAPE_ARC& aArc, bool aPlotInRegion )
|
||||
|
||||
fprintf( m_outputFile, "X%dY%dI%dJ%dD01*\n",
|
||||
KiROUND( devEnd.x ), KiROUND( devEnd.y ),
|
||||
KiROUND( devCenter.x ), KiROUND( devCenter.y ) );
|
||||
KiROUND( devRelCenter.x ), KiROUND( devRelCenter.y ) );
|
||||
|
||||
fprintf( m_outputFile, "G01*\n" ); // Back to linear interpolate (perhaps useless here).
|
||||
}
|
||||
@@ -885,7 +889,8 @@ void GERBER_PLOTTER::plotArc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAn
|
||||
end.x = aCenter.x + KiROUND( aRadius * aEndAngle.Cos() );
|
||||
end.y = aCenter.y - KiROUND( aRadius * aEndAngle.Sin() );
|
||||
VECTOR2D devEnd = userToDeviceCoordinates( end );
|
||||
VECTOR2D devCenter = userToDeviceCoordinates( aCenter ) - userToDeviceCoordinates( start );
|
||||
// devRelCenter is the position on arc center relative to the arc start, in Gerber coord.
|
||||
VECTOR2D devRelCenter = userToDeviceCoordinates( aCenter ) - userToDeviceCoordinates( start );
|
||||
|
||||
fprintf( m_outputFile, "G75*\n" ); // Multiquadrant (360 degrees) mode
|
||||
|
||||
@@ -896,24 +901,22 @@ void GERBER_PLOTTER::plotArc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAn
|
||||
|
||||
fprintf( m_outputFile, "X%dY%dI%dJ%dD01*\n",
|
||||
KiROUND( devEnd.x ), KiROUND( devEnd.y ),
|
||||
KiROUND( devCenter.x ), KiROUND( devCenter.y ) );
|
||||
KiROUND( devRelCenter.x ), KiROUND( devRelCenter.y ) );
|
||||
|
||||
fprintf( m_outputFile, "G01*\n" ); // Back to linear interpolate (perhaps useless here).
|
||||
}
|
||||
|
||||
|
||||
void GERBER_PLOTTER::PlotGerberRegion( const SHAPE_LINE_CHAIN& aPoly, void* aData )
|
||||
void GERBER_PLOTTER::PlotGerberRegion( const SHAPE_LINE_CHAIN& aPoly, GBR_METADATA* aGbrMetadata )
|
||||
{
|
||||
if( aPoly.PointCount() <= 2 )
|
||||
return;
|
||||
|
||||
GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
|
||||
|
||||
bool clearTA_AperFunction = false; // true if a TA.AperFunction is used
|
||||
|
||||
if( gbr_metadata )
|
||||
if( aGbrMetadata )
|
||||
{
|
||||
std::string attrib = gbr_metadata->m_ApertureMetadata.FormatAttribute( !m_useX2format );
|
||||
std::string attrib = aGbrMetadata->m_ApertureMetadata.FormatAttribute( !m_useX2format );
|
||||
|
||||
if( !attrib.empty() )
|
||||
{
|
||||
@@ -922,7 +925,7 @@ void GERBER_PLOTTER::PlotGerberRegion( const SHAPE_LINE_CHAIN& aPoly, void* aDat
|
||||
}
|
||||
}
|
||||
|
||||
PlotPoly( aPoly, FILL_T::FILLED_SHAPE, 0 , gbr_metadata );
|
||||
PlotPoly( aPoly, FILL_T::FILLED_SHAPE, 0 , aGbrMetadata );
|
||||
|
||||
// Clear the TA attribute, to avoid the next item to inherit it:
|
||||
if( clearTA_AperFunction )
|
||||
@@ -939,18 +942,17 @@ void GERBER_PLOTTER::PlotGerberRegion( const SHAPE_LINE_CHAIN& aPoly, void* aDat
|
||||
}
|
||||
|
||||
|
||||
void GERBER_PLOTTER::PlotGerberRegion( const std::vector<VECTOR2I>& aCornerList, void* aData )
|
||||
void GERBER_PLOTTER::PlotGerberRegion( const std::vector<VECTOR2I>& aCornerList,
|
||||
GBR_METADATA* aGbrMetadata )
|
||||
{
|
||||
if( aCornerList.size() <= 2 )
|
||||
return;
|
||||
|
||||
GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
|
||||
|
||||
bool clearTA_AperFunction = false; // true if a TA.AperFunction is used
|
||||
|
||||
if( gbr_metadata )
|
||||
if( aGbrMetadata )
|
||||
{
|
||||
std::string attrib = gbr_metadata->m_ApertureMetadata.FormatAttribute( !m_useX2format );
|
||||
std::string attrib = aGbrMetadata->m_ApertureMetadata.FormatAttribute( !m_useX2format );
|
||||
|
||||
if( !attrib.empty() )
|
||||
{
|
||||
@@ -959,7 +961,7 @@ void GERBER_PLOTTER::PlotGerberRegion( const std::vector<VECTOR2I>& aCornerList,
|
||||
}
|
||||
}
|
||||
|
||||
PlotPoly( aCornerList, FILL_T::FILLED_SHAPE, 0, gbr_metadata );
|
||||
PlotPoly( aCornerList, FILL_T::FILLED_SHAPE, 0, aGbrMetadata );
|
||||
|
||||
// Clear the TA attribute, to avoid the next item to inherit it:
|
||||
if( clearTA_AperFunction )
|
||||
@@ -976,6 +978,19 @@ void GERBER_PLOTTER::PlotGerberRegion( const std::vector<VECTOR2I>& aCornerList,
|
||||
}
|
||||
|
||||
|
||||
void GERBER_PLOTTER::PlotPolyAsRegion( const SHAPE_LINE_CHAIN& aPoly, FILL_T aFill,
|
||||
int aWidth, GBR_METADATA* aGbrMetadata )
|
||||
{
|
||||
// plot a filled polygon using Gerber region, therefore adding X2 attributes
|
||||
// to the solid polygon
|
||||
if( aWidth )
|
||||
PlotPoly( aPoly, FILL_T::NO_FILL, aWidth, aGbrMetadata );
|
||||
|
||||
if( aFill != FILL_T::NO_FILL )
|
||||
PlotGerberRegion( aPoly, aGbrMetadata );
|
||||
}
|
||||
|
||||
|
||||
void GERBER_PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aPoly, FILL_T aFill, int aWidth,
|
||||
void* aData )
|
||||
{
|
||||
@@ -1011,7 +1026,7 @@ void GERBER_PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aPoly, FILL_T aFill, int
|
||||
{
|
||||
const SHAPE_ARC& arc = aPoly.Arc( arcindex );
|
||||
|
||||
plotArc( arc, ii > 0 );
|
||||
plotArc( arc, true );
|
||||
|
||||
// skip points on arcs, since we plot the arc itself
|
||||
while( ii+1 < aPoly.PointCount() && arcindex == aPoly.ArcIndex( ii+1 ) )
|
||||
@@ -1045,7 +1060,7 @@ void GERBER_PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aPoly, FILL_T aFill, int
|
||||
{
|
||||
const SHAPE_ARC& arc = aPoly.Arc( arcindex );
|
||||
|
||||
plotArc( arc, ii > 0 );
|
||||
plotArc( arc, true );
|
||||
|
||||
// skip points on arcs, since we plot the arc itself
|
||||
while( ii+1 < aPoly.PointCount() && arcindex == aPoly.ArcIndex( ii+1 ) )
|
||||
@@ -1322,7 +1337,7 @@ void GERBER_PLOTTER::FlashPadOval( const VECTOR2I& aPos, const VECTOR2I& aSize,
|
||||
if( orient.IsCardinal90() )
|
||||
std::swap( size.x, size.y );
|
||||
|
||||
VECTOR2I pos_device = userToDeviceCoordinates( aPos );
|
||||
VECTOR2D pos_device = userToDeviceCoordinates( aPos );
|
||||
int aperture_attrib = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0;
|
||||
selectAperture( size, 0, ANGLE_0, APERTURE::AT_OVAL, aperture_attrib );
|
||||
|
||||
@@ -1353,7 +1368,7 @@ void GERBER_PLOTTER::FlashPadOval( const VECTOR2I& aPos, const VECTOR2I& aSize,
|
||||
orient -= ANGLE_180;
|
||||
}
|
||||
|
||||
VECTOR2I pos_device = userToDeviceCoordinates( aPos );
|
||||
VECTOR2D pos_device = userToDeviceCoordinates( aPos );
|
||||
int aperture_attrib = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0;
|
||||
selectAperture( size, 0, orient, APERTURE::AM_ROTATED_OVAL, aperture_attrib );
|
||||
|
||||
@@ -1416,7 +1431,7 @@ void GERBER_PLOTTER::FlashPadRect( const VECTOR2I& pos, const VECTOR2I& aSize,
|
||||
}
|
||||
else
|
||||
{
|
||||
VECTOR2I pos_device = userToDeviceCoordinates( pos );
|
||||
VECTOR2D pos_device = userToDeviceCoordinates( pos );
|
||||
int aperture_attrib = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0;
|
||||
selectAperture( size, 0, ANGLE_0, APERTURE::AT_RECT, aperture_attrib );
|
||||
|
||||
@@ -1433,7 +1448,7 @@ void GERBER_PLOTTER::FlashPadRect( const VECTOR2I& pos, const VECTOR2I& aSize,
|
||||
{
|
||||
m_hasApertureRotRect = true;
|
||||
|
||||
VECTOR2I pos_device = userToDeviceCoordinates( pos );
|
||||
VECTOR2D pos_device = userToDeviceCoordinates( pos );
|
||||
int aperture_attrib = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0;
|
||||
selectAperture( size, 0, aOrient, APERTURE::AM_ROT_RECT, aperture_attrib );
|
||||
|
||||
@@ -1755,7 +1770,7 @@ void GERBER_PLOTTER::FlashPadChamferRoundRect( const VECTOR2I& aShapePos, const
|
||||
if( aData )
|
||||
gbr_metadata = *static_cast<GBR_METADATA*>( aData );
|
||||
|
||||
VECTOR2I pos_device = userToDeviceCoordinates( aShapePos );
|
||||
VECTOR2D pos_device = userToDeviceCoordinates( aShapePos );
|
||||
SHAPE_POLY_SET outline;
|
||||
std::vector<VECTOR2I> cornerList;
|
||||
|
||||
@@ -1994,6 +2009,20 @@ void GERBER_PLOTTER::Text( const VECTOR2I& aPos,
|
||||
}
|
||||
|
||||
|
||||
void GERBER_PLOTTER::PlotText( const VECTOR2I& aPos, const COLOR4D& aColor,
|
||||
const wxString& aText,
|
||||
const TEXT_ATTRIBUTES& aAttributes,
|
||||
KIFONT::FONT* aFont,
|
||||
void* aData )
|
||||
{
|
||||
GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
|
||||
|
||||
if( gbr_metadata )
|
||||
formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
|
||||
|
||||
PLOTTER::PlotText( aPos, aColor, aText, aAttributes, aFont, aData );
|
||||
}
|
||||
|
||||
void GERBER_PLOTTER::SetLayerPolarity( bool aPositive )
|
||||
{
|
||||
if( aPositive )
|
||||
|
||||
@@ -1376,7 +1376,9 @@ void PDF_PLOTTER::Text( const VECTOR2I& aPos,
|
||||
double ctm_a, ctm_b, ctm_c, ctm_d, ctm_e, ctm_f;
|
||||
double wideningFactor, heightFactor;
|
||||
|
||||
computeTextParameters( aPos, aText, aOrient, aSize, m_plotMirror, aH_justify,
|
||||
VECTOR2I t_size( std::abs( aSize.x ), std::abs( aSize.y ) );
|
||||
|
||||
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 );
|
||||
|
||||
@@ -1389,7 +1391,7 @@ void PDF_PLOTTER::Text( const VECTOR2I& aPos,
|
||||
if( !aFont )
|
||||
aFont = KIFONT::FONT::GetFont();
|
||||
|
||||
VECTOR2I full_box( aFont->StringBoundaryLimits( aText, aSize, aWidth, aBold, aItalic ) );
|
||||
VECTOR2I full_box( aFont->StringBoundaryLimits( aText, t_size, aWidth, aBold, aItalic ) );
|
||||
VECTOR2I box_x( full_box.x, 0 );
|
||||
VECTOR2I box_y( 0, full_box.y );
|
||||
|
||||
@@ -1410,13 +1412,13 @@ void PDF_PLOTTER::Text( const VECTOR2I& aPos,
|
||||
{
|
||||
wxString word = str_tok.GetNextToken();
|
||||
|
||||
computeTextParameters( pos, word, aOrient, aSize, m_plotMirror, GR_TEXT_H_ALIGN_LEFT,
|
||||
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 );
|
||||
|
||||
// Extract the changed width and rotate by the orientation to get the offset for the
|
||||
// next word
|
||||
VECTOR2I bbox( aFont->StringBoundaryLimits( word, aSize, aWidth, aBold, aItalic ).x, 0 );
|
||||
VECTOR2I bbox( aFont->StringBoundaryLimits( word, t_size, aWidth, aBold, aItalic ).x, 0 );
|
||||
RotatePoint( bbox, aOrient );
|
||||
pos += bbox;
|
||||
|
||||
@@ -1444,6 +1446,30 @@ void PDF_PLOTTER::Text( const VECTOR2I& aPos,
|
||||
}
|
||||
|
||||
|
||||
void PDF_PLOTTER::PlotText( const VECTOR2I& aPos, const COLOR4D& aColor,
|
||||
const wxString& aText,
|
||||
const TEXT_ATTRIBUTES& aAttributes,
|
||||
KIFONT::FONT* aFont,
|
||||
void* aData )
|
||||
{
|
||||
VECTOR2I size = aAttributes.m_Size;
|
||||
|
||||
// PDF files do not like 0 sized texts which create broken files.
|
||||
if( size.x == 0 || size.y == 0 )
|
||||
return;
|
||||
|
||||
if( aAttributes.m_Mirrored )
|
||||
size.x = -size.x;
|
||||
|
||||
PDF_PLOTTER::Text( aPos, aColor, aText, aAttributes.m_Angle, size,
|
||||
aAttributes.m_Halign, aAttributes.m_Valign,
|
||||
aAttributes.m_StrokeWidth,
|
||||
aAttributes.m_Italic, aAttributes.m_Bold,
|
||||
aAttributes.m_Multiline,
|
||||
aFont, aData );
|
||||
}
|
||||
|
||||
|
||||
void PDF_PLOTTER::HyperlinkBox( const BOX2I& aBox, const wxString& aDestinationURL )
|
||||
{
|
||||
m_hyperlinksInPage.push_back( std::make_pair( aBox, aDestinationURL ) );
|
||||
|
||||
@@ -967,6 +967,28 @@ void PS_PLOTTER::Text( const VECTOR2I& aPos,
|
||||
}
|
||||
|
||||
|
||||
void PS_PLOTTER::PlotText( const VECTOR2I& aPos,
|
||||
const COLOR4D& aColor,
|
||||
const wxString& aText,
|
||||
const TEXT_ATTRIBUTES& aAttributes,
|
||||
KIFONT::FONT* aFont,
|
||||
void* aData )
|
||||
{
|
||||
SetCurrentLineWidth( aAttributes.m_StrokeWidth );
|
||||
SetColor( aColor );
|
||||
|
||||
// Draw the hidden postscript text (if requested)
|
||||
if( m_textMode == PLOT_TEXT_MODE::PHANTOM )
|
||||
{
|
||||
std::string ps_test = encodeStringForPlotter( aText );
|
||||
VECTOR2D pos_dev = userToDeviceCoordinates( aPos );
|
||||
fprintf( m_outputFile, "%s %g %g phantomshow\n", ps_test.c_str(), pos_dev.x, pos_dev.y );
|
||||
}
|
||||
|
||||
PLOTTER::PlotText( aPos, aColor, aText, aAttributes, aFont, aData );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Character widths for Helvetica
|
||||
*/
|
||||
|
||||
@@ -633,7 +633,13 @@ void SVG_PLOTTER::PlotImage( const wxImage& aImage, const VECTOR2I& aPos, double
|
||||
{
|
||||
wxMemoryOutputStream img_stream;
|
||||
|
||||
aImage.SaveFile( img_stream, wxBITMAP_TYPE_PNG );
|
||||
if( m_colorMode )
|
||||
aImage.SaveFile( img_stream, wxBITMAP_TYPE_PNG );
|
||||
else // Plot in B&W
|
||||
{
|
||||
wxImage image = aImage.ConvertToGreyscale();
|
||||
image.SaveFile( img_stream, wxBITMAP_TYPE_PNG );
|
||||
}
|
||||
size_t input_len = img_stream.GetOutputStreamBuffer()->GetBufferSize();
|
||||
std::vector<uint8_t> buffer( input_len );
|
||||
std::vector<uint8_t> encoded;
|
||||
@@ -847,3 +853,23 @@ void SVG_PLOTTER::Text( const VECTOR2I& aPos,
|
||||
|
||||
fputs( "</g>", m_outputFile );
|
||||
}
|
||||
|
||||
|
||||
void SVG_PLOTTER::PlotText( const VECTOR2I& aPos, const COLOR4D& aColor,
|
||||
const wxString& aText,
|
||||
const TEXT_ATTRIBUTES& aAttributes,
|
||||
KIFONT::FONT* aFont,
|
||||
void* aData )
|
||||
{
|
||||
VECTOR2I size = aAttributes.m_Size;
|
||||
|
||||
if( aAttributes.m_Mirrored )
|
||||
size.x = -size.x;
|
||||
|
||||
SVG_PLOTTER::Text( aPos, aColor, aText, aAttributes.m_Angle, size,
|
||||
aAttributes.m_Halign, aAttributes.m_Valign,
|
||||
aAttributes.m_StrokeWidth,
|
||||
aAttributes.m_Italic, aAttributes.m_Bold,
|
||||
aAttributes.m_Multiline,
|
||||
aFont, aData );
|
||||
}
|
||||
|
||||
+50
-18
@@ -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) 2017-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2017-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
|
||||
@@ -694,23 +694,6 @@ void PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aCornerList, FILL_T aFill, int a
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Same as GRText, but plot graphic text instead of draw it.
|
||||
*
|
||||
* @param aPos is the text position (according to aH_justify, aV_justify).
|
||||
* @param aColor is the text color.
|
||||
* @param aText is the text to draw.
|
||||
* @param aOrient is the angle.
|
||||
* @param aSize is the text size (size.x or size.y can be < 0 for mirrored texts).
|
||||
* @param aH_justify is the horizontal justification (Left, center, right).
|
||||
* @param aV_justify is the vertical justification (bottom, center, top).
|
||||
* @param aPenWidth is the line width (if = 0, use plot default line width).
|
||||
* @param aItalic is the true to simulate an italic font.
|
||||
* @param aBold use true to use a bold font Useful only with default width value (aPenWidth = 0).
|
||||
* @param aMultilineAllowed use true to plot text as multiline, otherwise single line.
|
||||
* @param aData is a parameter used by some plotters in SetCurrentLineWidth(),
|
||||
* not directly used here.
|
||||
*/
|
||||
void PLOTTER::Text( const VECTOR2I& aPos,
|
||||
const COLOR4D& aColor,
|
||||
const wxString& aText,
|
||||
@@ -759,6 +742,55 @@ void PLOTTER::Text( const VECTOR2I& aPos,
|
||||
attributes.m_Valign = aV_justify;
|
||||
attributes.m_Size = aSize;
|
||||
|
||||
// if Size.x is < 0, the text is mirrored (we have no other param to know a text is mirrored)
|
||||
if( attributes.m_Size.x < 0 )
|
||||
{
|
||||
attributes.m_Size.x = -attributes.m_Size.x;
|
||||
attributes.m_Mirrored = true;
|
||||
}
|
||||
|
||||
if( !aFont )
|
||||
aFont = KIFONT::FONT::GetFont();
|
||||
|
||||
aFont->Draw( &callback_gal, aText, aPos, attributes );
|
||||
}
|
||||
|
||||
void PLOTTER::PlotText( const VECTOR2I& aPos, const COLOR4D& aColor,
|
||||
const wxString& aText,
|
||||
const TEXT_ATTRIBUTES& aAttributes,
|
||||
KIFONT::FONT* aFont,
|
||||
void* aData )
|
||||
{
|
||||
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
|
||||
|
||||
TEXT_ATTRIBUTES attributes = aAttributes;
|
||||
int penWidth = attributes.m_StrokeWidth;
|
||||
|
||||
SetColor( aColor );
|
||||
SetCurrentLineWidth( penWidth, aData );
|
||||
|
||||
if( penWidth == 0 && attributes.m_Bold ) // Use default values if aPenWidth == 0
|
||||
penWidth = GetPenSizeForBold( std::min( attributes.m_Size.x, attributes.m_Size.y ) );
|
||||
|
||||
if( penWidth < 0 )
|
||||
penWidth = -penWidth;
|
||||
|
||||
attributes.m_StrokeWidth = penWidth;
|
||||
|
||||
CALLBACK_GAL callback_gal( empty_opts,
|
||||
// Stroke callback
|
||||
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
|
||||
{
|
||||
MoveTo( aPt1 );
|
||||
LineTo( aPt2 );
|
||||
PenFinish();
|
||||
},
|
||||
// Polygon callback
|
||||
[&]( const SHAPE_LINE_CHAIN& aPoly )
|
||||
{
|
||||
PlotPoly( aPoly, FILL_T::FILLED_SHAPE, 0, aData );
|
||||
} );
|
||||
|
||||
if( !aFont )
|
||||
aFont = KIFONT::FONT::GetFont();
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ void CADSTAR_ARCHIVE_PARSER::LINECODE::Parse( XNODE* aNode, PARSER_CONTEXT* aCon
|
||||
|
||||
XNODE* cNode = aNode->GetChildren();
|
||||
|
||||
if( cNode->GetName() != wxT( "STYLE" ) )
|
||||
if( !cNode || cNode->GetName() != wxT( "STYLE" ) )
|
||||
THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxString::Format( "LINECODE -> %s", Name ) );
|
||||
|
||||
wxString styleStr = GetXmlAttributeIDString( cNode, 0 );
|
||||
@@ -486,18 +486,28 @@ void CADSTAR_ARCHIVE_PARSER::VERTEX::AppendToChain( SHAPE_LINE_CHAIN* aChainToAp
|
||||
const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback,
|
||||
double aAccuracy ) const
|
||||
{
|
||||
VECTOR2I endPoint = aCadstarToKicadPointCallback( End );
|
||||
|
||||
if( Type == VERTEX_TYPE::POINT )
|
||||
{
|
||||
aChainToAppendTo->Append( endPoint );
|
||||
aChainToAppendTo->Append( aCadstarToKicadPointCallback( End ) );
|
||||
return;
|
||||
}
|
||||
|
||||
wxCHECK_MSG( aChainToAppendTo->PointCount() > 0, /*void*/,
|
||||
"Can't append an arc to vertex to an empty chain" );
|
||||
|
||||
VECTOR2I startPoint = aChainToAppendTo->GetPoint( -1 );
|
||||
aChainToAppendTo->Append( BuildArc( aChainToAppendTo->GetPoint( -1 ), aCadstarToKicadPointCallback),
|
||||
aAccuracy );
|
||||
}
|
||||
|
||||
|
||||
SHAPE_ARC CADSTAR_ARCHIVE_PARSER::VERTEX::BuildArc( const VECTOR2I& aPrevPoint,
|
||||
const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback ) const
|
||||
{
|
||||
wxCHECK_MSG( Type != VERTEX_TYPE::POINT, SHAPE_ARC(),
|
||||
"Can't build an arc for a straight segment!" );
|
||||
|
||||
VECTOR2I startPoint = aPrevPoint;
|
||||
VECTOR2I endPoint = aCadstarToKicadPointCallback( End );
|
||||
VECTOR2I centerPoint;
|
||||
|
||||
if( Type == VERTEX_TYPE::ANTICLOCKWISE_SEMICIRCLE || Type == VERTEX_TYPE::CLOCKWISE_SEMICIRCLE )
|
||||
@@ -516,9 +526,8 @@ void CADSTAR_ARCHIVE_PARSER::VERTEX::AppendToChain( SHAPE_LINE_CHAIN* aChainToAp
|
||||
clockwise = !clockwise;
|
||||
|
||||
SHAPE_ARC arc;
|
||||
arc.ConstructFromStartEndCenter( startPoint, endPoint, centerPoint, clockwise );
|
||||
|
||||
aChainToAppendTo->Append( arc, aAccuracy );
|
||||
return arc.ConstructFromStartEndCenter( startPoint, endPoint, centerPoint, clockwise );
|
||||
}
|
||||
|
||||
|
||||
@@ -2419,7 +2428,9 @@ XNODE* CADSTAR_ARCHIVE_PARSER::LoadArchiveFile( const wxString& aFileName,
|
||||
const wxString& aFileTypeIdentifier, PROGRESS_REPORTER* aProgressReporter )
|
||||
{
|
||||
KEYWORD emptyKeywords[1] = {};
|
||||
XNODE * iNode = nullptr, *cNode = nullptr;
|
||||
XNODE* rootNode = nullptr;
|
||||
XNODE* cNode = nullptr;
|
||||
XNODE* iNode = nullptr;
|
||||
int tok;
|
||||
bool cadstarFileCheckDone = false;
|
||||
wxString str;
|
||||
@@ -2451,7 +2462,10 @@ XNODE* CADSTAR_ARCHIVE_PARSER::LoadArchiveFile( const wxString& aFileName,
|
||||
if( aProgressReporter && ( currentProgress() - previousReportedProgress ) > 0.01 )
|
||||
{
|
||||
if( !aProgressReporter->KeepRefreshing() )
|
||||
{
|
||||
delete rootNode;
|
||||
THROW_IO_ERROR( _( "File import cancelled by user." ) );
|
||||
}
|
||||
|
||||
aProgressReporter->SetCurrentProgress( currentProgress() );
|
||||
previousReportedProgress = currentProgress();
|
||||
@@ -2467,6 +2481,7 @@ XNODE* CADSTAR_ARCHIVE_PARSER::LoadArchiveFile( const wxString& aFileName,
|
||||
else
|
||||
{
|
||||
//too many closing brackets
|
||||
delete rootNode;
|
||||
THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
|
||||
}
|
||||
}
|
||||
@@ -2476,6 +2491,9 @@ XNODE* CADSTAR_ARCHIVE_PARSER::LoadArchiveFile( const wxString& aFileName,
|
||||
str = wxString( lexer.CurText(), *conv );
|
||||
cNode = new XNODE( wxXML_ELEMENT_NODE, str );
|
||||
|
||||
if( !rootNode )
|
||||
rootNode = cNode;
|
||||
|
||||
if( iNode )
|
||||
{
|
||||
//we will add it as attribute as well as child node
|
||||
@@ -2485,7 +2503,10 @@ XNODE* CADSTAR_ARCHIVE_PARSER::LoadArchiveFile( const wxString& aFileName,
|
||||
else if( !cadstarFileCheckDone )
|
||||
{
|
||||
if( cNode->GetName() != aFileTypeIdentifier )
|
||||
{
|
||||
delete rootNode;
|
||||
THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
|
||||
}
|
||||
|
||||
cadstarFileCheckDone = true;
|
||||
}
|
||||
@@ -2501,19 +2522,28 @@ XNODE* CADSTAR_ARCHIVE_PARSER::LoadArchiveFile( const wxString& aFileName,
|
||||
else
|
||||
{
|
||||
//not enough closing brackets
|
||||
delete rootNode;
|
||||
THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Not enough closing brackets
|
||||
if( iNode != nullptr )
|
||||
{
|
||||
delete rootNode;
|
||||
THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
|
||||
}
|
||||
|
||||
// Throw if no data was parsed
|
||||
if( cNode )
|
||||
return cNode;
|
||||
if( rootNode )
|
||||
{
|
||||
return rootNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete rootNode;
|
||||
THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -83,6 +83,7 @@ class wxXmlAttribute;
|
||||
class PROGRESS_REPORTER;
|
||||
class SHAPE_LINE_CHAIN;
|
||||
class SHAPE_POLY_SET;
|
||||
class SHAPE_ARC;
|
||||
|
||||
/**
|
||||
* @brief Helper functions and common structures for CADSTAR PCB and Schematic archive files.
|
||||
@@ -92,6 +93,8 @@ class CADSTAR_ARCHIVE_PARSER
|
||||
public:
|
||||
CADSTAR_ARCHIVE_PARSER() { m_progressReporter = nullptr; }
|
||||
|
||||
virtual ~CADSTAR_ARCHIVE_PARSER() {}
|
||||
|
||||
|
||||
typedef wxString LINECODE_ID;
|
||||
typedef wxString HATCHCODE_ID;
|
||||
@@ -451,6 +454,10 @@ public:
|
||||
void AppendToChain( SHAPE_LINE_CHAIN* aChainToAppendTo,
|
||||
const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback,
|
||||
double aAccuracy ) const;
|
||||
|
||||
SHAPE_ARC BuildArc( const VECTOR2I& aPrevPoint,
|
||||
const std::function<VECTOR2I( const VECTOR2I& )>
|
||||
aCadstarToKicadPointCallback ) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -47,7 +47,6 @@ struct EPART;
|
||||
struct ETEXT;
|
||||
|
||||
typedef std::unordered_map<wxString, wxXmlNode*> NODE_MAP;
|
||||
typedef std::map<wxString, FOOTPRINT*> FOOTPRINT_MAP;
|
||||
typedef std::map<wxString, EINSTANCE*> EINSTANCE_MAP;
|
||||
typedef std::map<wxString, std::unique_ptr<EPART>> EPART_MAP;
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ const void* PROPERTY_MANAGER::TypeCast( const void* aSource, TYPE_ID aBase, TYPE
|
||||
}
|
||||
|
||||
|
||||
void PROPERTY_MANAGER::AddProperty( PROPERTY_BASE* aProperty, const wxString& aGroup )
|
||||
PROPERTY_BASE& PROPERTY_MANAGER::AddProperty( PROPERTY_BASE* aProperty, const wxString& aGroup )
|
||||
{
|
||||
const wxString& name = aProperty->Name();
|
||||
TYPE_ID hash = aProperty->OwnerHash();
|
||||
@@ -147,15 +147,16 @@ void PROPERTY_MANAGER::AddProperty( PROPERTY_BASE* aProperty, const wxString& aG
|
||||
}
|
||||
|
||||
m_dirty = true;
|
||||
return *aProperty;
|
||||
}
|
||||
|
||||
|
||||
void PROPERTY_MANAGER::ReplaceProperty( size_t aBase, const wxString& aName, PROPERTY_BASE* aNew,
|
||||
const wxString& aGroup )
|
||||
PROPERTY_BASE& PROPERTY_MANAGER::ReplaceProperty( size_t aBase, const wxString& aName,
|
||||
PROPERTY_BASE* aNew, const wxString& aGroup )
|
||||
{
|
||||
CLASS_DESC& classDesc = getClass( aNew->OwnerHash() );
|
||||
classDesc.m_replaced.insert( std::make_pair( aBase, aName ) );
|
||||
AddProperty( aNew, aGroup );
|
||||
return AddProperty( aNew, aGroup );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <pgm_base.h>
|
||||
#include <settings/app_settings.h>
|
||||
#include <settings/json_settings_internals.h>
|
||||
#include <settings/color_settings.h>
|
||||
#include <settings/common_settings.h>
|
||||
#include <settings/parameters.h>
|
||||
|
||||
@@ -147,7 +148,7 @@ APP_SETTINGS_BASE::APP_SETTINGS_BASE( const std::string& aFilename, int aSchemaV
|
||||
&m_System.last_imperial_units, static_cast<int>( EDA_UNITS::INCHES ) ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<wxString>( "appearance.color_theme",
|
||||
&m_ColorTheme, wxS( "_builtin_default" ) ) );
|
||||
&m_ColorTheme, COLOR_SETTINGS::COLOR_BUILTIN_DEFAULT ) );
|
||||
|
||||
addParamsForWindow( &m_Window, "window" );
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
|
||||
///! Update the schema version whenever a migration is required
|
||||
const int colorsSchemaVersion = 5;
|
||||
const wxString COLOR_SETTINGS::COLOR_BUILTIN_DEFAULT = "_builtin_default";
|
||||
const wxString COLOR_SETTINGS::COLOR_BUILTIN_CLASSIC = "_builtin_classic";
|
||||
|
||||
|
||||
COLOR_SETTINGS::COLOR_SETTINGS( const wxString& aFilename, bool aAbsolutePath ) :
|
||||
@@ -378,12 +380,12 @@ void COLOR_SETTINGS::SetColor( int aLayer, const COLOR4D& aColor )
|
||||
|
||||
std::vector<COLOR_SETTINGS*> COLOR_SETTINGS::CreateBuiltinColorSettings()
|
||||
{
|
||||
COLOR_SETTINGS* defaultTheme = new COLOR_SETTINGS( wxT( "_builtin_default" ) );
|
||||
COLOR_SETTINGS* defaultTheme = new COLOR_SETTINGS( COLOR_BUILTIN_DEFAULT );
|
||||
defaultTheme->SetName( _( "KiCad Default" ) );
|
||||
defaultTheme->m_writeFile = false;
|
||||
defaultTheme->Load(); // We can just get the colors out of the param defaults for this one
|
||||
|
||||
COLOR_SETTINGS* classicTheme = new COLOR_SETTINGS( wxT( "_builtin_classic" ) );
|
||||
COLOR_SETTINGS* classicTheme = new COLOR_SETTINGS( COLOR_BUILTIN_CLASSIC );
|
||||
classicTheme->SetName( _( "KiCad Classic" ) );
|
||||
classicTheme->m_writeFile = false;
|
||||
|
||||
|
||||
@@ -66,6 +66,10 @@ SETTINGS_MANAGER::SETTINGS_MANAGER( bool aHeadless ) :
|
||||
|
||||
// create the common settings shared by all applications. Not loaded immediately
|
||||
m_common_settings = RegisterSettings( new COMMON_SETTINGS, false );
|
||||
|
||||
// Create the built-in color settings
|
||||
// Here to allow the Python API to access the built-in colors
|
||||
registerBuiltinColorSettings();
|
||||
}
|
||||
|
||||
SETTINGS_MANAGER::~SETTINGS_MANAGER()
|
||||
@@ -203,7 +207,7 @@ COLOR_SETTINGS* SETTINGS_MANAGER::GetColorSettings( const wxString& aName )
|
||||
if( !ret )
|
||||
{
|
||||
ret = registerColorSettings( aName );
|
||||
*ret = *m_color_settings.at( "_builtin_default" );
|
||||
*ret = *m_color_settings.at( COLOR_SETTINGS::COLOR_BUILTIN_DEFAULT );
|
||||
ret->SetFilename( wxT( "user" ) );
|
||||
ret->SetReadOnly( false );
|
||||
}
|
||||
@@ -212,7 +216,7 @@ COLOR_SETTINGS* SETTINGS_MANAGER::GetColorSettings( const wxString& aName )
|
||||
}
|
||||
|
||||
// This had better work
|
||||
return m_color_settings.at( "_builtin_default" );
|
||||
return m_color_settings.at( COLOR_SETTINGS::COLOR_BUILTIN_DEFAULT );
|
||||
}
|
||||
|
||||
|
||||
@@ -305,11 +309,17 @@ COLOR_SETTINGS* SETTINGS_MANAGER::GetMigratedColorSettings()
|
||||
}
|
||||
|
||||
|
||||
void SETTINGS_MANAGER::registerBuiltinColorSettings()
|
||||
{
|
||||
for( COLOR_SETTINGS* settings : COLOR_SETTINGS::CreateBuiltinColorSettings() )
|
||||
m_color_settings[settings->GetFilename()] = RegisterSettings( settings, false );
|
||||
}
|
||||
|
||||
|
||||
void SETTINGS_MANAGER::loadAllColorSettings()
|
||||
{
|
||||
// Create the built-in color settings
|
||||
for( COLOR_SETTINGS* settings : COLOR_SETTINGS::CreateBuiltinColorSettings() )
|
||||
m_color_settings[settings->GetFilename()] = RegisterSettings( settings, false );
|
||||
registerBuiltinColorSettings();
|
||||
|
||||
wxFileName third_party_path;
|
||||
const ENV_VAR_MAP& env = Pgm().GetLocalEnvVariables();
|
||||
@@ -623,12 +633,12 @@ bool SETTINGS_MANAGER::GetPreviousVersionPaths( std::vector<wxString>* aPaths )
|
||||
wxFileName wxGtkPath;
|
||||
wxGtkPath.AssignDir( wxS( "~/.config/kicad" ) );
|
||||
wxGtkPath.MakeAbsolute();
|
||||
base_paths.emplace_back( wxGtkPath.GetPath() );
|
||||
base_paths.emplace_back( wxGtkPath );
|
||||
|
||||
// We also want to pick up regular flatpak if we are nightly
|
||||
wxGtkPath.AssignDir( wxS( "~/.var/app/org.kicad.KiCad/config/kicad" ) );
|
||||
wxGtkPath.MakeAbsolute();
|
||||
base_paths.emplace_back( wxGtkPath.GetPath() );
|
||||
base_paths.emplace_back( wxGtkPath );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ wxString EscapeString( const wxString& aSource, ESCAPE_CONTEXT aContext )
|
||||
}
|
||||
else if( aContext == CTX_JS_STR )
|
||||
{
|
||||
if( c >= 0x7F || c == '\'' || c == '\\' )
|
||||
if( c >= 0x7F || c == '\'' || c == '\\' || c == '(' || c == ')' )
|
||||
{
|
||||
unsigned int code = c;
|
||||
char buffer[16];
|
||||
|
||||
+41
-1
@@ -34,13 +34,18 @@
|
||||
|
||||
%rename(getWxPoint) operator wxPoint;
|
||||
%rename(getWxSize) operator wxSize;
|
||||
%{
|
||||
#include <math/vector2d.h>
|
||||
%include <math/vector2d.h>
|
||||
#include <math/vector3.h>
|
||||
#include <math/box2.h>
|
||||
%}
|
||||
%include <math/vector2d.h>
|
||||
%include <math/vector3.h>
|
||||
%include <math/box2.h>
|
||||
|
||||
%template(VECTOR2I) VECTOR2<int>;
|
||||
%template(VECTOR2I_EXTENDED_TYPE) VECTOR2_TRAITS<int>;
|
||||
%template(VECTOR3D) VECTOR3<double>;
|
||||
%template(BOX2I) BOX2<VECTOR2I>;
|
||||
|
||||
%extend VECTOR2<int>
|
||||
@@ -74,3 +79,38 @@
|
||||
|
||||
%}
|
||||
}
|
||||
|
||||
%extend VECTOR3<double>
|
||||
{
|
||||
void Set(double x, double y, double z) { self->x = x; self->y = y; self->z = z; }
|
||||
|
||||
PyObject* Get()
|
||||
{
|
||||
PyObject* tup = PyTuple_New(3);
|
||||
PyTuple_SET_ITEM(tup, 0, PyFloat_FromDouble(self->x));
|
||||
PyTuple_SET_ITEM(tup, 1, PyFloat_FromDouble(self->y));
|
||||
PyTuple_SET_ITEM(tup, 2, PyFloat_FromDouble(self->z));
|
||||
return tup;
|
||||
}
|
||||
|
||||
%pythoncode
|
||||
%{
|
||||
def __eq__(self,other): return (self.x==other.x and self.y==other.y and self.z==other.z)
|
||||
def __ne__(self,other): return not (self==other)
|
||||
def __str__(self): return str(self.Get())
|
||||
def __repr__(self): return 'VECTOR3D'+str(self.Get())
|
||||
def __len__(self): return len(self.Get())
|
||||
def __getitem__(self, index): return self.Get()[index]
|
||||
def __setitem__(self, index, val):
|
||||
if index == 0:
|
||||
self.x = val
|
||||
elif index == 1:
|
||||
self.y = val
|
||||
elif index == 2:
|
||||
self.z = val
|
||||
else:
|
||||
raise IndexError
|
||||
def __nonzero__(self): return self.Get() != (0, 0, 0)
|
||||
|
||||
%}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
/// URL to launch a new issue with pre-populated description
|
||||
wxString COMMON_CONTROL::m_bugReportUrl =
|
||||
wxS( "https://gitlab.com/kicad/code/kicad/issues/new?issue[description]=%s" );
|
||||
wxS( "https://gitlab.com/kicad/code/kicad/issues/new?issuable_template=bare&issue[description]=%s" );
|
||||
|
||||
|
||||
/// Issue template to use for reporting bugs (this should not be translated)
|
||||
@@ -113,7 +113,9 @@ int COMMON_CONTROL::ShowLibraryTable( const TOOL_EVENT& aEvent )
|
||||
try // Sch frame was not available, try to start it
|
||||
{
|
||||
KIFACE* kiface = m_frame->Kiway().KiFACE( KIWAY::FACE_SCH );
|
||||
kiface->CreateKiWindow( m_frame, DIALOG_SCH_LIBRARY_TABLE, &m_frame->Kiway() );
|
||||
|
||||
if( kiface )
|
||||
kiface->CreateKiWindow( m_frame, DIALOG_SCH_LIBRARY_TABLE, &m_frame->Kiway() );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
|
||||
@@ -1400,7 +1400,7 @@ void VIEW::RecacheAllItems()
|
||||
|
||||
void VIEW::UpdateItems()
|
||||
{
|
||||
if( !m_gal->IsVisible() )
|
||||
if( !m_gal->IsVisible() || !m_gal->IsInitialized() )
|
||||
return;
|
||||
|
||||
unsigned int cntGeomUpdate = 0;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <widgets/color_swatch.h>
|
||||
#include <wx/dcmemory.h>
|
||||
|
||||
#include <gal/dpi_scaling.h>
|
||||
#include <dialogs/dialog_color_picker.h>
|
||||
#include <memory>
|
||||
|
||||
@@ -133,6 +134,16 @@ COLOR_SWATCH::COLOR_SWATCH( wxWindow* aParent, const COLOR4D& aColor, int aID,
|
||||
m_checkerboardSize = ConvertDialogToPixels( CHECKERBOARD_SIZE_DU );
|
||||
m_checkerboardBg = aParent->GetBackgroundColour();
|
||||
|
||||
#ifdef __WXMSW__
|
||||
// These need additional scaling on Windows because of some discrepancy between pixel and
|
||||
// content scaling that only affects certain widgets on Windows HiDPI. On other platforms, the
|
||||
// value returned by ConvertDialogToPixels appears to be correct.
|
||||
DPI_SCALING dpi( nullptr, aParent );
|
||||
|
||||
m_size /= dpi.GetContentScaleFactor();
|
||||
m_checkerboardSize /= dpi.GetContentScaleFactor();
|
||||
#endif
|
||||
|
||||
auto sizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
SetSizer( sizer );
|
||||
|
||||
@@ -300,4 +311,4 @@ void COLOR_SWATCH::OnDarkModeToggle()
|
||||
m_checkerboardBg = m_parent->GetBackgroundColour();
|
||||
wxBitmap bm = MakeBitmap( m_color, m_background, m_size, m_checkerboardSize, m_checkerboardBg );
|
||||
m_swatch->SetBitmap( bm );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,10 @@
|
||||
*/
|
||||
|
||||
#include <widgets/font_choice.h>
|
||||
#include <kiplatform/ui.h>
|
||||
#include <wx/fontenum.h>
|
||||
#include <font/fontconfig.h>
|
||||
#include <pgm_base.h>
|
||||
|
||||
// The "official" name of the building Kicad stroke font (always existing)
|
||||
#include <font/kicad_font_name.h>
|
||||
@@ -32,7 +34,7 @@ FONT_CHOICE::FONT_CHOICE( wxWindow* aParent, int aId, wxPoint aPosition, wxSize
|
||||
m_systemFontCount = wxChoice::GetCount();
|
||||
|
||||
std::vector<std::string> fontNames;
|
||||
Fontconfig()->ListFonts( fontNames );
|
||||
Fontconfig()->ListFonts( fontNames, std::string( Pgm().GetLanguageTag().utf8_str() ) );
|
||||
|
||||
wxArrayString menuList;
|
||||
|
||||
@@ -53,7 +55,11 @@ FONT_CHOICE::FONT_CHOICE( wxWindow* aParent, int aId, wxPoint aPosition, wxSize
|
||||
menuList.Add( wxString( name ) );
|
||||
|
||||
menuList.Sort();
|
||||
|
||||
Freeze();
|
||||
Append( menuList );
|
||||
KIPLATFORM::UI::LargeChoiceBoxHack( this );
|
||||
Thaw();
|
||||
|
||||
m_notFound = wxS( " " ) + _( "<not found>" );
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <wx/odcombo.h>
|
||||
#include <wx/menuitem.h>
|
||||
|
||||
#include <gal/dpi_scaling.h>
|
||||
#include <layer_ids.h>
|
||||
#include <widgets/layer_box_selector.h>
|
||||
|
||||
@@ -140,9 +141,12 @@ int LAYER_BOX_SELECTOR::SetLayerSelection( int layer )
|
||||
|
||||
void LAYER_BOX_SELECTOR::ResyncBitmapOnly()
|
||||
{
|
||||
DPI_SCALING dpi( nullptr, this );
|
||||
int size = static_cast<int>( dpi.GetScaleFactor() * 14 );
|
||||
|
||||
for( int i = 0; i < (int) GetCount(); ++i )
|
||||
{
|
||||
wxBitmap layerbmp( 14, 14 );
|
||||
wxBitmap layerbmp( size, size );
|
||||
DrawColorSwatch( layerbmp, getLayerColor( LAYER_PCB_BACKGROUND ), getLayerColor( i ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,6 +185,16 @@ LIB_TREE::~LIB_TREE()
|
||||
}
|
||||
|
||||
|
||||
void LIB_TREE::ShowChangedLanguage()
|
||||
{
|
||||
if( m_query_ctrl )
|
||||
m_query_ctrl->SetDescriptiveText( _( "Filter" ) );
|
||||
|
||||
if( m_adapter )
|
||||
m_adapter->ShowChangedLanguage();
|
||||
}
|
||||
|
||||
|
||||
LIB_ID LIB_TREE::GetSelectedLibId( int* aUnit ) const
|
||||
{
|
||||
wxDataViewItem sel = m_tree_ctrl->GetSelection();
|
||||
|
||||
+238
-218
@@ -61,7 +61,8 @@ double mpWindow::zoomIncrementalFactor = 1.1;
|
||||
|
||||
IMPLEMENT_ABSTRACT_CLASS( mpLayer, wxObject )
|
||||
|
||||
mpLayer::mpLayer() : m_type( mpLAYER_UNDEF )
|
||||
mpLayer::mpLayer() :
|
||||
m_type( mpLAYER_UNDEF )
|
||||
{
|
||||
SetPen( (wxPen&) *wxBLACK_PEN );
|
||||
SetFont( (wxFont&) *wxNORMAL_FONT );
|
||||
@@ -197,12 +198,14 @@ wxSize mpInfoLayer::GetSize() const
|
||||
}
|
||||
|
||||
|
||||
mpInfoCoords::mpInfoCoords() : mpInfoLayer()
|
||||
mpInfoCoords::mpInfoCoords() :
|
||||
mpInfoLayer()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
mpInfoCoords::mpInfoCoords( wxRect rect, const wxBrush* brush ) : mpInfoLayer( rect, brush )
|
||||
mpInfoCoords::mpInfoCoords( wxRect rect, const wxBrush* brush ) :
|
||||
mpInfoLayer( rect, brush )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -273,12 +276,14 @@ void mpInfoCoords::Plot( wxDC& dc, mpWindow& w )
|
||||
}
|
||||
|
||||
|
||||
mpInfoLegend::mpInfoLegend() : mpInfoLayer()
|
||||
mpInfoLegend::mpInfoLegend() :
|
||||
mpInfoLayer()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
mpInfoLegend::mpInfoLegend( wxRect rect, const wxBrush* brush ) : mpInfoLayer( rect, brush )
|
||||
mpInfoLegend::mpInfoLegend( wxRect rect, const wxBrush* brush ) :
|
||||
mpInfoLayer( rect, brush )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -301,7 +306,7 @@ void mpInfoLegend::Plot( wxDC& dc, mpWindow& w )
|
||||
int scrx = w.GetScrX();
|
||||
int scry = w.GetScrY();
|
||||
|
||||
if( (m_winX != scrx) || (m_winY != scry) )
|
||||
if( m_winX != scrx || m_winY != scry )
|
||||
{
|
||||
if( m_winX > 1 )
|
||||
m_dim.x = (int) floor( (double) (m_dim.x * scrx / m_winX) );
|
||||
@@ -322,26 +327,27 @@ void mpInfoLegend::Plot( wxDC& dc, mpWindow& w )
|
||||
// wxBrush semiWhite(image1);
|
||||
dc.SetBrush( m_brush );
|
||||
dc.SetFont( m_font );
|
||||
const int baseWidth = (mpLEGEND_MARGIN * 2 + mpLEGEND_LINEWIDTH);
|
||||
int textX = baseWidth, textY = mpLEGEND_MARGIN;
|
||||
int plotCount = 0;
|
||||
int posY = 0;
|
||||
int tmpX = 0, tmpY = 0;
|
||||
mpLayer* ly = NULL;
|
||||
wxPen lpen;
|
||||
wxString label;
|
||||
|
||||
const int baseWidth = mpLEGEND_MARGIN * 2 + mpLEGEND_LINEWIDTH;
|
||||
int textX = baseWidth, textY = mpLEGEND_MARGIN;
|
||||
int plotCount = 0;
|
||||
int posY = 0;
|
||||
int tmpX = 0;
|
||||
int tmpY = 0;
|
||||
mpLayer* layer = nullptr;
|
||||
wxPen lpen;
|
||||
wxString label;
|
||||
|
||||
for( unsigned int p = 0; p < w.CountAllLayers(); p++ )
|
||||
{
|
||||
ly = w.GetLayer( p );
|
||||
layer = w.GetLayer( p );
|
||||
|
||||
if( (ly->GetLayerType() == mpLAYER_PLOT) && ( ly->IsVisible() ) )
|
||||
if( layer->GetLayerType() == mpLAYER_PLOT && layer->IsVisible() )
|
||||
{
|
||||
label = ly->GetName();
|
||||
label = layer->GetDisplayName();
|
||||
dc.GetTextExtent( label, &tmpX, &tmpY );
|
||||
textX =
|
||||
( textX > (tmpX + baseWidth) ) ? textX : (tmpX + baseWidth + mpLEGEND_MARGIN);
|
||||
textY += (tmpY);
|
||||
textX = ( textX > tmpX + baseWidth ) ? textX : tmpX + baseWidth + mpLEGEND_MARGIN;
|
||||
textY += tmpY;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,25 +363,25 @@ void mpInfoLegend::Plot( wxDC& dc, mpWindow& w )
|
||||
|
||||
for( unsigned int p2 = 0; p2 < w.CountAllLayers(); p2++ )
|
||||
{
|
||||
ly = w.GetLayer( p2 );
|
||||
layer = w.GetLayer( p2 );
|
||||
|
||||
if( (ly->GetLayerType() == mpLAYER_PLOT) && ( ly->IsVisible() ) )
|
||||
if( layer->GetLayerType() == mpLAYER_PLOT && layer->IsVisible() )
|
||||
{
|
||||
label = ly->GetName();
|
||||
lpen = ly->GetPen();
|
||||
label = layer->GetDisplayName();
|
||||
lpen = layer->GetPen();
|
||||
dc.GetTextExtent( label, &tmpX, &tmpY );
|
||||
dc.SetPen( lpen );
|
||||
// textX = (textX > (tmpX + baseWidth)) ? textX : (tmpX + baseWidth);
|
||||
// textY += (tmpY + mpLEGEND_MARGIN);
|
||||
posY = m_dim.y + mpLEGEND_MARGIN + plotCount * tmpY + (tmpY >> 1);
|
||||
dc.DrawLine( m_dim.x + mpLEGEND_MARGIN, // X start coord
|
||||
posY, // Y start coord
|
||||
m_dim.x + mpLEGEND_LINEWIDTH + mpLEGEND_MARGIN, // X end coord
|
||||
posY );
|
||||
dc.DrawLine( m_dim.x + mpLEGEND_MARGIN, // X start coord
|
||||
posY, // Y start coord
|
||||
m_dim.x + mpLEGEND_LINEWIDTH + mpLEGEND_MARGIN, // X end coord
|
||||
posY );
|
||||
// dc.DrawRectangle(m_dim.x + 5, m_dim.y + 5 + plotCount*tmpY, 5, 5);
|
||||
dc.DrawText( label,
|
||||
m_dim.x + baseWidth,
|
||||
m_dim.y + mpLEGEND_MARGIN + plotCount * tmpY );
|
||||
m_dim.x + baseWidth,
|
||||
m_dim.y + mpLEGEND_MARGIN + plotCount * tmpY );
|
||||
plotCount++;
|
||||
}
|
||||
}
|
||||
@@ -541,8 +547,8 @@ mpFXY::mpFXY( const wxString& name, int flags )
|
||||
SetName( name );
|
||||
m_flags = flags;
|
||||
m_type = mpLAYER_PLOT;
|
||||
m_scaleX = NULL;
|
||||
m_scaleY = NULL;
|
||||
m_scaleX = nullptr;
|
||||
m_scaleY = nullptr;
|
||||
|
||||
// Avoid not initialized members:
|
||||
maxDrawX = minDrawX = maxDrawY = minDrawY = 0;
|
||||
@@ -562,207 +568,218 @@ void mpFXY::UpdateViewBoundary( wxCoord xnew, wxCoord ynew )
|
||||
|
||||
void mpFXY::Plot( wxDC& dc, mpWindow& w )
|
||||
{
|
||||
if( m_visible )
|
||||
wxCHECK_RET( m_scaleX, wxS( "X scale was not set" ) );
|
||||
|
||||
wxCHECK_RET( m_scaleY, wxS( "Y scale was not set" ) );
|
||||
|
||||
if( !m_visible )
|
||||
return;
|
||||
|
||||
wxCoord startPx = m_drawOutsideMargins ? 0 : w.GetMarginLeft();
|
||||
wxCoord endPx = m_drawOutsideMargins ? w.GetScrX() : w.GetScrX() - w.GetMarginRight();
|
||||
wxCoord minYpx = m_drawOutsideMargins ? 0 : w.GetMarginTop();
|
||||
wxCoord maxYpx = m_drawOutsideMargins ? w.GetScrY() : w.GetScrY() - w.GetMarginBottom();
|
||||
|
||||
// Check for a collapsed window before we try to allocate a negative number of points
|
||||
if( endPx <= startPx || minYpx >= maxYpx )
|
||||
return;
|
||||
|
||||
dc.SetPen( m_pen );
|
||||
|
||||
double x, y;
|
||||
// Do this to reset the counters to evaluate bounding box for label positioning
|
||||
Rewind();
|
||||
GetNextXY( x, y );
|
||||
maxDrawX = x;
|
||||
minDrawX = x;
|
||||
maxDrawY = y;
|
||||
minDrawY = y;
|
||||
// drawnPoints = 0;
|
||||
Rewind();
|
||||
|
||||
dc.SetClippingRegion( startPx, minYpx, endPx - startPx + 1, maxYpx - minYpx + 1 );
|
||||
|
||||
if( !m_continuous )
|
||||
{
|
||||
dc.SetPen( m_pen );
|
||||
bool first = true;
|
||||
wxCoord ix = 0;
|
||||
std::set<wxCoord> ys;
|
||||
|
||||
double x, y;
|
||||
// Do this to reset the counters to evaluate bounding box for label positioning
|
||||
Rewind(); GetNextXY( x, y );
|
||||
maxDrawX = x; minDrawX = x; maxDrawY = y; minDrawY = y;
|
||||
// drawnPoints = 0;
|
||||
Rewind();
|
||||
|
||||
wxCoord startPx = m_drawOutsideMargins ? 0 : w.GetMarginLeft();
|
||||
wxCoord endPx = m_drawOutsideMargins ? w.GetScrX() : w.GetScrX() - w.GetMarginRight();
|
||||
wxCoord minYpx = m_drawOutsideMargins ? 0 : w.GetMarginTop();
|
||||
wxCoord maxYpx = m_drawOutsideMargins ? w.GetScrY() : w.GetScrY() - w.GetMarginBottom();
|
||||
|
||||
dc.SetClippingRegion( startPx, minYpx, endPx - startPx + 1, maxYpx - minYpx + 1 );
|
||||
|
||||
if( !m_continuous )
|
||||
while( GetNextXY( x, y ) )
|
||||
{
|
||||
bool first = true;
|
||||
wxCoord ix = 0;
|
||||
std::set<wxCoord> ys;
|
||||
double px = m_scaleX->TransformToPlot( x );
|
||||
double py = m_scaleY->TransformToPlot( y );
|
||||
wxCoord newX = w.x2p( px );
|
||||
|
||||
while( GetNextXY( x, y ) )
|
||||
if( first )
|
||||
{
|
||||
double px = m_scaleX->TransformToPlot( x );
|
||||
double py = m_scaleY->TransformToPlot( y );
|
||||
wxCoord newX = w.x2p( px );
|
||||
|
||||
if( first )
|
||||
{
|
||||
ix = newX;
|
||||
first = false;
|
||||
}
|
||||
|
||||
if( newX == ix ) // continue until a new X coordinate is reached
|
||||
{
|
||||
// collect all unique points
|
||||
ys.insert( w.y2p( py ) );
|
||||
continue;
|
||||
}
|
||||
|
||||
for( auto& iy: ys )
|
||||
{
|
||||
if( m_drawOutsideMargins
|
||||
|| ( (ix >= startPx) && (ix <= endPx) && (iy >= minYpx)
|
||||
&& (iy <= maxYpx) ) )
|
||||
{
|
||||
// for some reason DrawPoint does not use the current pen,
|
||||
// so we use DrawLine for fat pens
|
||||
if( m_pen.GetWidth() <= 1 )
|
||||
{
|
||||
dc.DrawPoint( ix, iy );
|
||||
}
|
||||
else
|
||||
{
|
||||
dc.DrawLine( ix, iy, ix, iy );
|
||||
}
|
||||
|
||||
UpdateViewBoundary( ix, iy );
|
||||
}
|
||||
}
|
||||
|
||||
ys.clear();
|
||||
ix = newX;
|
||||
first = false;
|
||||
}
|
||||
|
||||
if( newX == ix ) // continue until a new X coordinate is reached
|
||||
{
|
||||
// collect all unique points
|
||||
ys.insert( w.y2p( py ) );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int count = 0;
|
||||
int x0=0; // X position of merged current vertical line
|
||||
int ymin0=0; // y min coord of merged current vertical line
|
||||
int ymax0=0; // y max coord of merged current vertical line
|
||||
int dupx0 = 0; // count of currently merged vertical lines
|
||||
wxPoint line_start; // starting point of the current line to draw
|
||||
|
||||
// A buffer to store coordinates of lines to draw
|
||||
std::vector<wxPoint>pointList;
|
||||
pointList.reserve( endPx - startPx + 1 );
|
||||
|
||||
// Note: we can use dc.DrawLines() only for a reasonable number or points (<10000),
|
||||
// because at least on Windows dc.DrawLines() can hang for a lot of points.
|
||||
// (> 10000 points) (can happens when a lot of points is calculated)
|
||||
// To avoid long draw time (and perhaps hanging) one plot only not redundant lines.
|
||||
// To avoid artifacts when skipping points to the same x coordinate, for each
|
||||
// group of points at a give, x coordinate we also draw a vertical line at this coord,
|
||||
// from the ymin to the ymax vertical coordinates of skipped points
|
||||
while( GetNextXY( x, y ) )
|
||||
for( auto& iy: ys )
|
||||
{
|
||||
double px = m_scaleX->TransformToPlot( x );
|
||||
double py = m_scaleY->TransformToPlot( y );
|
||||
|
||||
wxCoord x1 = w.x2p( px );
|
||||
wxCoord y1 = w.y2p( py );
|
||||
|
||||
// Store only points on the drawing area, to speed up the drawing time
|
||||
// Note: x1 is a value truncated from px by w.x2p(). So to be sure the
|
||||
// first point is drawn, the x1 low limit is startPx-1 in plot coordinates
|
||||
if( x1 >= startPx-1 && x1 <= endPx )
|
||||
if( m_drawOutsideMargins
|
||||
|| ( (ix >= startPx) && (ix <= endPx) && (iy >= minYpx) && (iy <= maxYpx) ) )
|
||||
{
|
||||
if( !count || line_start.x != x1 )
|
||||
{
|
||||
if( count && dupx0 > 1 && ymin0 != ymax0 )
|
||||
{
|
||||
// Vertical points are merged, draw the pending vertical line
|
||||
// However, if the line is one pixel length, it is not drawn,
|
||||
// because the main trace show this point
|
||||
dc.DrawLine( x0, ymin0, x0, ymax0 );
|
||||
}
|
||||
|
||||
x0 = x1;
|
||||
ymin0 = ymax0 = y1;
|
||||
dupx0 = 0;
|
||||
|
||||
pointList.emplace_back( wxPoint( x1, y1 ) );
|
||||
|
||||
line_start.x = x1;
|
||||
line_start.y = y1;
|
||||
count++;
|
||||
}
|
||||
// for some reason DrawPoint does not use the current pen, so we use
|
||||
// DrawLine for fat pens
|
||||
if( m_pen.GetWidth() <= 1 )
|
||||
dc.DrawPoint( ix, iy );
|
||||
else
|
||||
{
|
||||
ymin0 = std::min( ymin0, y1 );
|
||||
ymax0 = std::max( ymax0, y1 );
|
||||
x0 = x1;
|
||||
dupx0++;
|
||||
}
|
||||
dc.DrawLine( ix, iy, ix, iy );
|
||||
|
||||
UpdateViewBoundary( ix, iy );
|
||||
}
|
||||
}
|
||||
|
||||
if( pointList.size() > 1 )
|
||||
{
|
||||
// For a better look (when using dashed lines) and more optimization,
|
||||
// try to merge horizontal segments, in order to plot longer lines
|
||||
// we are merging horizontal segments because this is easy,
|
||||
// and horizontal segments are a frequent cases
|
||||
std::vector<wxPoint> drawPoints;
|
||||
drawPoints.reserve( endPx - startPx + 1 );
|
||||
|
||||
drawPoints.push_back( pointList[0] ); // push the first point in list
|
||||
|
||||
for( size_t ii = 1; ii < pointList.size()-1; ii++ )
|
||||
{
|
||||
// Skip intermediate points between the first point and the last
|
||||
// point of the segment candidate
|
||||
if( drawPoints.back().y == pointList[ii].y &&
|
||||
drawPoints.back().y == pointList[ii+1].y )
|
||||
continue;
|
||||
else
|
||||
drawPoints.push_back( pointList[ii] );
|
||||
}
|
||||
|
||||
// push the last point to draw in list
|
||||
if( drawPoints.back() != pointList.back() )
|
||||
drawPoints.push_back( pointList.back() );
|
||||
|
||||
dc.DrawLines( drawPoints.size(), &drawPoints[0] );
|
||||
}
|
||||
ys.clear();
|
||||
ix = newX;
|
||||
ys.insert( w.y2p( py ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int count = 0;
|
||||
int x0=0; // X position of merged current vertical line
|
||||
int ymin0=0; // y min coord of merged current vertical line
|
||||
int ymax0=0; // y max coord of merged current vertical line
|
||||
int dupx0 = 0; // count of currently merged vertical lines
|
||||
wxPoint line_start; // starting point of the current line to draw
|
||||
|
||||
if( !m_name.IsEmpty() && m_showName )
|
||||
// A buffer to store coordinates of lines to draw
|
||||
std::vector<wxPoint>pointList;
|
||||
pointList.reserve( endPx - startPx + 1 );
|
||||
|
||||
// Note: we can use dc.DrawLines() only for a reasonable number or points (<10000),
|
||||
// because at least on Windows dc.DrawLines() can hang for a lot of points.
|
||||
// (> 10000 points) (can happens when a lot of points is calculated)
|
||||
// To avoid long draw time (and perhaps hanging) one plot only not redundant lines.
|
||||
// To avoid artifacts when skipping points to the same x coordinate, for each group of
|
||||
// points at a give, x coordinate we also draw a vertical line at this coord, from the
|
||||
// ymin to the ymax vertical coordinates of skipped points
|
||||
while( GetNextXY( x, y ) )
|
||||
{
|
||||
dc.SetFont( m_font );
|
||||
double px = m_scaleX->TransformToPlot( x );
|
||||
double py = m_scaleY->TransformToPlot( y );
|
||||
|
||||
wxCoord tx, ty;
|
||||
dc.GetTextExtent( m_name, &tx, &ty );
|
||||
wxCoord x1 = w.x2p( px );
|
||||
wxCoord y1 = w.y2p( py );
|
||||
|
||||
// xxx implement else ... if (!HasBBox())
|
||||
// Store only points on the drawing area, to speed up the drawing time
|
||||
// Note: x1 is a value truncated from px by w.x2p(). So to be sure the first point
|
||||
// is drawn, the x1 low limit is startPx-1 in plot coordinates
|
||||
if( x1 >= startPx-1 && x1 <= endPx )
|
||||
{
|
||||
// const int sx = w.GetScrX();
|
||||
// const int sy = w.GetScrY();
|
||||
if( !count || line_start.x != x1 )
|
||||
{
|
||||
if( count && dupx0 > 1 && ymin0 != ymax0 )
|
||||
{
|
||||
// Vertical points are merged, draw the pending vertical line
|
||||
// However, if the line is one pixel length, it is not drawn, because
|
||||
// the main trace show this point
|
||||
dc.DrawLine( x0, ymin0, x0, ymax0 );
|
||||
}
|
||||
|
||||
if( (m_flags & mpALIGNMASK) == mpALIGN_NW )
|
||||
{
|
||||
tx = minDrawX + 8;
|
||||
ty = maxDrawY + 8;
|
||||
}
|
||||
else if( (m_flags & mpALIGNMASK) == mpALIGN_NE )
|
||||
{
|
||||
tx = maxDrawX - tx - 8;
|
||||
ty = maxDrawY + 8;
|
||||
}
|
||||
else if( (m_flags & mpALIGNMASK) == mpALIGN_SE )
|
||||
{
|
||||
tx = maxDrawX - tx - 8;
|
||||
ty = minDrawY - ty - 8;
|
||||
x0 = x1;
|
||||
ymin0 = ymax0 = y1;
|
||||
dupx0 = 0;
|
||||
|
||||
pointList.emplace_back( wxPoint( x1, y1 ) );
|
||||
|
||||
line_start.x = x1;
|
||||
line_start.y = y1;
|
||||
count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// mpALIGN_SW
|
||||
tx = minDrawX + 8;
|
||||
ty = minDrawY - ty - 8;
|
||||
ymin0 = std::min( ymin0, y1 );
|
||||
ymax0 = std::max( ymax0, y1 );
|
||||
x0 = x1;
|
||||
dupx0++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( pointList.size() > 1 )
|
||||
{
|
||||
// For a better look (when using dashed lines) and more optimization, try to merge
|
||||
// horizontal segments, in order to plot longer lines
|
||||
// We are merging horizontal segments because this is easy, and horizontal segments
|
||||
// are a frequent cases
|
||||
std::vector<wxPoint> drawPoints;
|
||||
drawPoints.reserve( endPx - startPx + 1 );
|
||||
|
||||
drawPoints.push_back( pointList[0] ); // push the first point in list
|
||||
|
||||
for( size_t ii = 1; ii < pointList.size()-1; ii++ )
|
||||
{
|
||||
// Skip intermediate points between the first point and the last point of the
|
||||
// segment candidate
|
||||
if( drawPoints.back().y == pointList[ii].y &&
|
||||
drawPoints.back().y == pointList[ii+1].y )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
drawPoints.push_back( pointList[ii] );
|
||||
}
|
||||
}
|
||||
|
||||
dc.DrawText( m_name, tx, ty );
|
||||
// push the last point to draw in list
|
||||
if( drawPoints.back() != pointList.back() )
|
||||
drawPoints.push_back( pointList.back() );
|
||||
|
||||
dc.DrawLines( drawPoints.size(), &drawPoints[0] );
|
||||
}
|
||||
}
|
||||
|
||||
if( !m_name.IsEmpty() && m_showName )
|
||||
{
|
||||
dc.SetFont( m_font );
|
||||
|
||||
wxCoord tx, ty;
|
||||
dc.GetTextExtent( m_name, &tx, &ty );
|
||||
|
||||
// xxx implement else ... if (!HasBBox())
|
||||
{
|
||||
// const int sx = w.GetScrX();
|
||||
// const int sy = w.GetScrY();
|
||||
|
||||
if( (m_flags & mpALIGNMASK) == mpALIGN_NW )
|
||||
{
|
||||
tx = minDrawX + 8;
|
||||
ty = maxDrawY + 8;
|
||||
}
|
||||
else if( (m_flags & mpALIGNMASK) == mpALIGN_NE )
|
||||
{
|
||||
tx = maxDrawX - tx - 8;
|
||||
ty = maxDrawY + 8;
|
||||
}
|
||||
else if( (m_flags & mpALIGNMASK) == mpALIGN_SE )
|
||||
{
|
||||
tx = maxDrawX - tx - 8;
|
||||
ty = minDrawY - ty - 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
// mpALIGN_SW
|
||||
tx = minDrawX + 8;
|
||||
ty = minDrawY - ty - 8;
|
||||
}
|
||||
}
|
||||
|
||||
dc.DrawText( m_name, tx, ty );
|
||||
}
|
||||
|
||||
dc.DestroyClippingRegion();
|
||||
}
|
||||
|
||||
@@ -1395,7 +1412,7 @@ mpScaleY::mpScaleY( const wxString& name, int flags, bool ticks )
|
||||
m_flags = flags;
|
||||
m_ticks = ticks;
|
||||
m_type = mpLAYER_AXIS;
|
||||
m_masterScale = NULL;
|
||||
m_masterScale = nullptr;
|
||||
m_nameFlags = mpALIGN_BORDER_LEFT;
|
||||
}
|
||||
|
||||
@@ -1601,7 +1618,8 @@ EVT_MENU( mpID_ZOOM_OUT, mpWindow::OnZoomOut )
|
||||
EVT_MENU( mpID_LOCKASPECT, mpWindow::OnLockAspect )
|
||||
END_EVENT_TABLE()
|
||||
|
||||
mpWindow::mpWindow() : wxWindow(),
|
||||
mpWindow::mpWindow() :
|
||||
wxWindow(),
|
||||
m_lockaspect( false ),
|
||||
m_minX( 0.0 ),
|
||||
m_maxX( 0.0 ),
|
||||
@@ -1662,11 +1680,11 @@ mpWindow::mpWindow( wxWindow* parent,
|
||||
m_minX = m_minY = 0;
|
||||
m_maxX = m_maxY = 0;
|
||||
m_last_lx = m_last_ly = 0;
|
||||
m_buff_bmp = NULL;
|
||||
m_buff_bmp = nullptr;
|
||||
m_enableDoubleBuffer = false;
|
||||
m_enableMouseNavigation = true;
|
||||
m_enableLimitedView = false;
|
||||
m_movingInfoLayer = NULL;
|
||||
m_movingInfoLayer = nullptr;
|
||||
// Set margins to 0
|
||||
m_marginTop = 0; m_marginRight = 0; m_marginBottom = 0; m_marginLeft = 0;
|
||||
|
||||
@@ -1914,10 +1932,10 @@ void mpWindow::OnMouseLeftRelease( wxMouseEvent& event )
|
||||
|
||||
m_zooming = false;
|
||||
|
||||
if( m_movingInfoLayer != NULL )
|
||||
if( m_movingInfoLayer != nullptr )
|
||||
{
|
||||
m_movingInfoLayer->UpdateReference();
|
||||
m_movingInfoLayer = NULL;
|
||||
m_movingInfoLayer = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1953,7 +1971,7 @@ void mpWindow::Fit( double xMin, double xMax, double yMin, double yMax,
|
||||
yMin -= yExtra;
|
||||
yMax += yExtra;
|
||||
|
||||
if( printSizeX != NULL && printSizeY != NULL )
|
||||
if( printSizeX != nullptr && printSizeY != nullptr )
|
||||
{
|
||||
// Printer:
|
||||
m_scrX = *printSizeX;
|
||||
@@ -1994,7 +2012,7 @@ void mpWindow::Fit( double xMin, double xMax, double yMin, double yMax,
|
||||
|
||||
// It is VERY IMPORTANT to DO NOT call Refresh if we are drawing to the printer!!
|
||||
// Otherwise, the DC dimensions will be those of the window instead of the printer device
|
||||
if( printSizeX == NULL || printSizeY == NULL )
|
||||
if( printSizeX == nullptr || printSizeY == nullptr )
|
||||
UpdateAll();
|
||||
}
|
||||
|
||||
@@ -2634,7 +2652,7 @@ unsigned int mpWindow::CountLayers() const
|
||||
mpLayer* mpWindow::GetLayer( int position ) const
|
||||
{
|
||||
if( ( position >= (int) m_layers.size() ) || position < 0 )
|
||||
return NULL;
|
||||
return nullptr;
|
||||
|
||||
return m_layers[position];
|
||||
}
|
||||
@@ -2648,7 +2666,7 @@ const mpLayer* mpWindow::GetLayerByName( const wxString& name ) const
|
||||
return layer;
|
||||
}
|
||||
|
||||
return NULL; // Not found
|
||||
return nullptr; // Not found
|
||||
}
|
||||
|
||||
|
||||
@@ -2735,7 +2753,7 @@ mpInfoLayer* mpWindow::IsInsideInfoLayer( wxPoint& point )
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -2815,7 +2833,8 @@ void mpWindow::SetColourTheme( const wxColour& bgColour, const wxColour& drawCol
|
||||
IMPLEMENT_DYNAMIC_CLASS( mpFXYVector, mpFXY )
|
||||
|
||||
// Constructor
|
||||
mpFXYVector::mpFXYVector( const wxString& name, int flags ) : mpFXY( name, flags )
|
||||
mpFXYVector::mpFXYVector( const wxString& name, int flags ) :
|
||||
mpFXY( name, flags )
|
||||
{
|
||||
m_index = 0;
|
||||
m_minX = -1;
|
||||
@@ -3019,7 +3038,8 @@ void mpText::Plot( wxDC& dc, mpWindow& w )
|
||||
// mpPrintout - provided by Davide Rondini
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
mpPrintout::mpPrintout( mpWindow* drawWindow, const wxChar* title ) : wxPrintout( title )
|
||||
mpPrintout::mpPrintout( mpWindow* drawWindow, const wxChar* title ) :
|
||||
wxPrintout( title )
|
||||
{
|
||||
drawn = false;
|
||||
plotWindow = drawWindow;
|
||||
@@ -3078,9 +3098,9 @@ bool mpPrintout::OnPrintPage( int page )
|
||||
// Restore colours
|
||||
plotWindow->SetColourTheme( oldBgColour, oldFgColour, oldAxColour );
|
||||
// Restore drawing
|
||||
plotWindow->Fit( plotWindow->GetDesiredXmin(),
|
||||
plotWindow->GetDesiredXmax(), plotWindow->GetDesiredYmin(),
|
||||
plotWindow->GetDesiredYmax(), NULL, NULL );
|
||||
plotWindow->Fit( plotWindow->GetDesiredXmin(), plotWindow->GetDesiredXmax(),
|
||||
plotWindow->GetDesiredYmin(), plotWindow->GetDesiredYmax(), nullptr,
|
||||
nullptr );
|
||||
plotWindow->UpdateAll();
|
||||
}
|
||||
|
||||
|
||||
@@ -65,8 +65,6 @@ PROPERTIES_PANEL::PROPERTIES_PANEL( wxWindow* aParent, EDA_BASE_FRAME* aFrame )
|
||||
delete wxPGGlobalVars->m_defaultRenderer;
|
||||
wxPGGlobalVars->m_defaultRenderer = new PG_CELL_RENDERER();
|
||||
|
||||
m_cachedSelection = std::make_unique<SELECTION>();
|
||||
|
||||
m_caption = new wxStaticText( this, wxID_ANY, _( "No objects selected" ) );
|
||||
mainSizer->Add( m_caption, 0, wxALL | wxEXPAND, 5 );
|
||||
|
||||
@@ -74,6 +72,7 @@ PROPERTIES_PANEL::PROPERTIES_PANEL( wxWindow* aParent, EDA_BASE_FRAME* aFrame )
|
||||
wxPG_DEFAULT_STYLE );
|
||||
m_grid->SetUnspecifiedValueAppearance( wxPGCell( wxT( "<...>" ) ) );
|
||||
m_grid->SetExtraStyle( wxPG_EX_HELP_AS_TOOLTIPS );
|
||||
m_grid->SetValidationFailureBehavior( wxPG_VFB_MARK_CELL );
|
||||
m_grid->AddActionTrigger( wxPG_ACTION_NEXT_PROPERTY, WXK_RETURN );
|
||||
m_grid->AddActionTrigger( wxPG_ACTION_NEXT_PROPERTY, WXK_NUMPAD_ENTER );
|
||||
m_grid->AddActionTrigger( wxPG_ACTION_NEXT_PROPERTY, WXK_DOWN );
|
||||
@@ -131,23 +130,20 @@ void PROPERTIES_PANEL::OnLanguageChanged()
|
||||
|
||||
void PROPERTIES_PANEL::rebuildProperties( const SELECTION& aSelection )
|
||||
{
|
||||
if( *m_cachedSelection == aSelection )
|
||||
{
|
||||
updatePropertyValues( aSelection );
|
||||
return;
|
||||
}
|
||||
auto reset =
|
||||
[&]()
|
||||
{
|
||||
if( m_grid->IsEditorFocused() )
|
||||
m_grid->CommitChangesFromEditor();
|
||||
|
||||
*m_cachedSelection = aSelection;
|
||||
|
||||
if( m_grid->IsEditorFocused() )
|
||||
m_grid->CommitChangesFromEditor();
|
||||
|
||||
m_grid->Clear();
|
||||
m_displayed.clear();
|
||||
m_grid->Clear();
|
||||
m_displayed.clear();
|
||||
};
|
||||
|
||||
if( aSelection.Empty() )
|
||||
{
|
||||
m_caption->SetLabel( _( "No objects selected" ) );
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -159,15 +155,6 @@ void PROPERTIES_PANEL::rebuildProperties( const SELECTION& aSelection )
|
||||
|
||||
wxCHECK( !types.empty(), /* void */ );
|
||||
|
||||
if( aSelection.Size() > 1 )
|
||||
{
|
||||
m_caption->SetLabel( wxString::Format( _( "%d objects selected" ), aSelection.Size() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_caption->SetLabel( aSelection.Front()->GetFriendlyName() );
|
||||
}
|
||||
|
||||
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
|
||||
propMgr.SetUnits( m_frame->GetUserUnits() );
|
||||
propMgr.SetTransforms( &m_frame->GetOriginTransforms() );
|
||||
@@ -181,8 +168,7 @@ void PROPERTIES_PANEL::rebuildProperties( const SELECTION& aSelection )
|
||||
std::vector<wxString> groupDisplayOrder = propMgr.GetGroupDisplayOrder( *types.begin() );
|
||||
std::set<wxString> groups( groupDisplayOrder.begin(), groupDisplayOrder.end() );
|
||||
|
||||
std::map<wxPGProperty*, int> pgPropOrders;
|
||||
std::map<wxString, std::vector<wxPGProperty*>> pgPropGroups;
|
||||
std::set<PROPERTY_BASE*> availableProps;
|
||||
|
||||
// Get all possible properties
|
||||
for( const TYPE_ID& type : types )
|
||||
@@ -214,40 +200,77 @@ void PROPERTIES_PANEL::rebuildProperties( const SELECTION& aSelection )
|
||||
}
|
||||
}
|
||||
|
||||
EDA_ITEM* firstItem = aSelection.Front();
|
||||
|
||||
// Find a set of properties that is common to all selected items
|
||||
for( PROPERTY_BASE* property : commonProps )
|
||||
{
|
||||
if( property->IsInternal() )
|
||||
if( property->IsHiddenFromPropertiesManager() )
|
||||
continue;
|
||||
|
||||
if( !propMgr.IsAvailableFor( TYPE_HASH( *aSelection.Front() ), property,
|
||||
aSelection.Front() ) )
|
||||
if( propMgr.IsAvailableFor( TYPE_HASH( *firstItem ), property, firstItem ) )
|
||||
availableProps.insert( property );
|
||||
}
|
||||
|
||||
bool writeable = true;
|
||||
std::set<PROPERTY_BASE*> existingProps;
|
||||
|
||||
for( wxPropertyGridIterator it = m_grid->GetIterator(); !it.AtEnd(); it.Next() )
|
||||
{
|
||||
wxPGProperty* pgProp = it.GetProperty();
|
||||
PROPERTY_BASE* property = propMgr.GetProperty( TYPE_HASH( *firstItem ), pgProp->GetName() );
|
||||
|
||||
// Switching item types? Property may no longer be valid
|
||||
if( !property )
|
||||
continue;
|
||||
|
||||
// Either determine the common value for a property or "<...>" to indicate multiple values
|
||||
bool available;
|
||||
bool writeable;
|
||||
wxVariant commonVal;
|
||||
|
||||
available = extractValueAndWritability( aSelection, property, commonVal, writeable );
|
||||
extractValueAndWritability( aSelection, property, commonVal, writeable );
|
||||
pgProp->SetValue( commonVal );
|
||||
pgProp->Enable( writeable );
|
||||
|
||||
if( available )
|
||||
existingProps.insert( property );
|
||||
}
|
||||
|
||||
if( existingProps == availableProps )
|
||||
return;
|
||||
|
||||
// Some difference exists: start from scratch
|
||||
reset();
|
||||
|
||||
std::map<wxPGProperty*, int> pgPropOrders;
|
||||
std::map<wxString, std::vector<wxPGProperty*>> pgPropGroups;
|
||||
|
||||
for( PROPERTY_BASE* property : availableProps )
|
||||
{
|
||||
wxPGProperty* pgProp = createPGProperty( property );
|
||||
wxVariant commonVal;
|
||||
|
||||
if( !extractValueAndWritability( aSelection, property, commonVal, writeable ) )
|
||||
continue;
|
||||
|
||||
if( pgProp )
|
||||
{
|
||||
wxPGProperty* pgProp = createPGProperty( property );
|
||||
pgProp->SetValue( commonVal );
|
||||
pgProp->Enable( writeable );
|
||||
m_displayed.push_back( property );
|
||||
|
||||
if( pgProp )
|
||||
{
|
||||
pgProp->SetValue( commonVal );
|
||||
pgProp->Enable( writeable );
|
||||
m_displayed.push_back( property );
|
||||
|
||||
wxASSERT( displayOrder.count( property ) );
|
||||
pgPropOrders[pgProp] = displayOrder[property];
|
||||
pgPropGroups[property->Group()].emplace_back( pgProp );
|
||||
}
|
||||
wxASSERT( displayOrder.count( property ) );
|
||||
pgPropOrders[pgProp] = displayOrder[property];
|
||||
pgPropGroups[property->Group()].emplace_back( pgProp );
|
||||
}
|
||||
}
|
||||
|
||||
if( aSelection.Size() > 1 )
|
||||
{
|
||||
m_caption->SetLabel( wxString::Format( _( "%d objects selected" ), aSelection.Size() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_caption->SetLabel( aSelection.Front()->GetFriendlyName() );
|
||||
}
|
||||
|
||||
const wxString unspecifiedGroupCaption = _( "Basic Properties" );
|
||||
|
||||
for( const wxString& groupName : groupDisplayOrder )
|
||||
|
||||
@@ -75,24 +75,10 @@ protected:
|
||||
/**
|
||||
* Generates the property grid for a given selection of items.
|
||||
*
|
||||
* Calling this will remove any existing properties shown, causing visible flicker on some
|
||||
* platforms and canceling any pending edits. Make sure to only call this when the group of
|
||||
* selected items has actually changed.
|
||||
*
|
||||
* @param aSelection is a set of items to show properties for.
|
||||
*/
|
||||
virtual void rebuildProperties( const SELECTION& aSelection );
|
||||
|
||||
/**
|
||||
* Updates the values shown in the property grid for the current selection.
|
||||
*
|
||||
* Does not add or remove properties from the display (@see rebuildProperties)
|
||||
* This implies that aSelection must have the same contents as m_cachedSelection.
|
||||
*
|
||||
* @param aSelection is the set of selected items.
|
||||
*/
|
||||
virtual void updatePropertyValues( const SELECTION& aSelection ) {}
|
||||
|
||||
virtual wxPGProperty* createPGProperty( const PROPERTY_BASE* aProperty ) const = 0;
|
||||
|
||||
// Event handlers
|
||||
@@ -128,9 +114,6 @@ protected:
|
||||
|
||||
/// Proportion of the grid column splitter that is used for the key column (0.0 - 1.0)
|
||||
float m_splitter_key_proportion;
|
||||
|
||||
/// A copy of the most recent selection passed to rebuildProperties
|
||||
std::unique_ptr<SELECTION> m_cachedSelection;
|
||||
};
|
||||
|
||||
#endif /* PROPERTIES_PANEL_H */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2022-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 as published by the
|
||||
@@ -42,6 +42,8 @@ void SEARCH_PANE::OnLanguageChange()
|
||||
wxWindow* page = m_notebook->GetPage( i );
|
||||
SEARCH_PANE_TAB* tab = dynamic_cast<SEARCH_PANE_TAB*>( page );
|
||||
|
||||
wxCHECK( tab, /* void */ );
|
||||
|
||||
tab->RefreshColumnNames();
|
||||
m_notebook->SetPageText( i, wxGetTranslation( tab->GetSearchHandler()->GetName() ) );
|
||||
}
|
||||
@@ -103,4 +105,4 @@ void SEARCH_PANE::OnNotebookPageChanged( wxBookCtrlEvent& aEvent )
|
||||
SEARCH_PANE_TAB* SEARCH_PANE::GetCurrentTab() const
|
||||
{
|
||||
return dynamic_cast<SEARCH_PANE_TAB*>( m_notebook->GetCurrentPage() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,6 @@ UNIT_BINDER::UNIT_BINDER( EDA_DRAW_FRAME* aParent, wxStaticText* aLabel, wxWindo
|
||||
UNIT_BINDER::UNIT_BINDER( UNITS_PROVIDER* aUnitsProvider, wxWindow* aEventSource,
|
||||
wxStaticText* aLabel, wxWindow* aValueCtrl, wxStaticText* aUnitLabel,
|
||||
bool aAllowEval, bool aBindFocusEvent ) :
|
||||
m_eventSource( aEventSource ),
|
||||
m_bindFocusEvent( aBindFocusEvent ),
|
||||
m_label( aLabel ),
|
||||
m_valueCtrl( aValueCtrl ),
|
||||
@@ -99,10 +98,10 @@ UNIT_BINDER::UNIT_BINDER( UNITS_PROVIDER* aUnitsProvider, wxWindow* aEventSource
|
||||
this );
|
||||
}
|
||||
|
||||
if( m_eventSource )
|
||||
if( aEventSource )
|
||||
{
|
||||
m_eventSource->Connect( UNITS_CHANGED, wxCommandEventHandler( UNIT_BINDER::onUnitsChanged ),
|
||||
nullptr, this );
|
||||
aEventSource->Connect( UNITS_CHANGED, wxCommandEventHandler( UNIT_BINDER::onUnitsChanged ),
|
||||
nullptr, this );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,12 +114,6 @@ UNIT_BINDER::~UNIT_BINDER()
|
||||
this );
|
||||
}
|
||||
|
||||
if( m_eventSource )
|
||||
{
|
||||
m_eventSource->Disconnect( UNITS_CHANGED, wxCommandEventHandler( UNIT_BINDER::onUnitsChanged ),
|
||||
nullptr, this );
|
||||
}
|
||||
|
||||
if( m_valueCtrl )
|
||||
{
|
||||
m_valueCtrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( UNIT_BINDER::onSetFocus ),
|
||||
@@ -395,7 +388,7 @@ void UNIT_BINDER::SetValue( const wxString& aValue )
|
||||
|
||||
value += EDA_UNIT_UTILS::GetLabel( m_units, m_dataType );
|
||||
}
|
||||
|
||||
|
||||
if( textEntry )
|
||||
textEntry->SetValue( value );
|
||||
else if( staticText )
|
||||
|
||||
@@ -273,7 +273,7 @@ void WX_GRID::DestroyTable( wxGridTableBase* aTable )
|
||||
}
|
||||
|
||||
|
||||
wxString WX_GRID::GetShownColumns()
|
||||
wxString WX_GRID::GetShownColumnsAsString()
|
||||
{
|
||||
wxString shownColumns;
|
||||
|
||||
@@ -292,6 +292,17 @@ wxString WX_GRID::GetShownColumns()
|
||||
}
|
||||
|
||||
|
||||
std::bitset<64> WX_GRID::GetShownColumns()
|
||||
{
|
||||
std::bitset<64> shownColumns;
|
||||
|
||||
for( int ii = 0; ii < GetNumberCols(); ++ii )
|
||||
shownColumns[ii] = IsColShown( ii );
|
||||
|
||||
return shownColumns;
|
||||
}
|
||||
|
||||
|
||||
void WX_GRID::ShowHideColumns( const wxString& shownColumns )
|
||||
{
|
||||
for( int i = 0; i < GetNumberCols(); ++i )
|
||||
@@ -310,6 +321,18 @@ void WX_GRID::ShowHideColumns( const wxString& shownColumns )
|
||||
}
|
||||
|
||||
|
||||
void WX_GRID::ShowHideColumns( const std::bitset<64>& aShownColumns )
|
||||
{
|
||||
for( int ii = 0; ii < GetNumberCols(); ++ ii )
|
||||
{
|
||||
if( aShownColumns[ii] )
|
||||
ShowCol( ii );
|
||||
else
|
||||
HideCol( ii );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void WX_GRID::DrawCornerLabel( wxDC& dc )
|
||||
{
|
||||
if( m_nativeColumnLabels )
|
||||
|
||||
@@ -63,7 +63,7 @@ WX_INFOBAR::WX_INFOBAR( wxWindow* aParent, wxAuiManager* aMgr, wxWindowID aWinid
|
||||
|
||||
// Infobar is broken on Mac without the effects
|
||||
SetShowHideEffects( wxSHOW_EFFECT_ROLL_TO_BOTTOM, wxSHOW_EFFECT_ROLL_TO_TOP );
|
||||
SetEffectDuration( 300 );
|
||||
SetEffectDuration( 200 );
|
||||
#else
|
||||
// Infobar freezes canvas on Windows with the effect, and GTK looks bad with it
|
||||
SetShowHideEffects( wxSHOW_EFFECT_NONE, wxSHOW_EFFECT_NONE );
|
||||
|
||||
@@ -38,9 +38,8 @@ SYMBOLS_LISTBOX::SYMBOLS_LISTBOX( CVPCB_MAINFRAME* parent, wxWindowID id ) :
|
||||
ITEMS_LISTBOX_BASE( parent, id ),
|
||||
m_warningAttr( std::make_unique<wxListItemAttr>() )
|
||||
{
|
||||
m_warningAttr->SetBackgroundColour( KIPLATFORM::UI::IsDarkTheme()
|
||||
? wxColour( 112, 96, 32 )
|
||||
: *wxYELLOW );
|
||||
m_warningAttr->SetBackgroundColour( KIPLATFORM::UI::IsDarkTheme() ? wxColour( 112, 96, 32 )
|
||||
: wxColour( 255, 248, 212 ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -84,6 +84,9 @@ void CVPCB_MAINFRAME::ReCreateHToolbar()
|
||||
m_tcFilterString = new wxTextCtrl( m_mainToolBar, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||
wxDefaultSize, wxTE_PROCESS_ENTER );
|
||||
|
||||
// Min size on Mac is (a not very useful) single character
|
||||
m_tcFilterString->SetMinSize( wxSize( 150, -1 ) );
|
||||
|
||||
m_tcFilterString->Bind( wxEVT_TEXT_ENTER, &CVPCB_MAINFRAME::onTextFilterChanged, this );
|
||||
|
||||
m_mainToolBar->AddControl( m_tcFilterString );
|
||||
|
||||
+108
-11
@@ -195,7 +195,7 @@ bool CONNECTION_SUBGRAPH::ResolveDrivers( bool aCheckMultipleDrivers )
|
||||
m_driver_connection->SetDriver( m_driver );
|
||||
m_driver_connection->ClearDirty();
|
||||
}
|
||||
else
|
||||
else if( !m_is_bus_member )
|
||||
{
|
||||
m_driver_connection = nullptr;
|
||||
}
|
||||
@@ -246,7 +246,36 @@ wxString CONNECTION_SUBGRAPH::GetNetName() const
|
||||
}
|
||||
|
||||
|
||||
std::vector<SCH_ITEM*> CONNECTION_SUBGRAPH::GetBusLabels() const
|
||||
std::vector<SCH_ITEM*> CONNECTION_SUBGRAPH::GetAllBusLabels() const
|
||||
{
|
||||
std::vector<SCH_ITEM*> labels;
|
||||
|
||||
for( SCH_ITEM* item : m_drivers )
|
||||
{
|
||||
switch( item->Type() )
|
||||
{
|
||||
case SCH_LABEL_T:
|
||||
case SCH_GLOBAL_LABEL_T:
|
||||
{
|
||||
CONNECTION_TYPE type = item->Connection( &m_sheet )->Type();
|
||||
|
||||
// Only consider bus vectors
|
||||
if( type == CONNECTION_TYPE::BUS || type == CONNECTION_TYPE::BUS_GROUP )
|
||||
labels.push_back( item );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return labels;
|
||||
}
|
||||
|
||||
|
||||
std::vector<SCH_ITEM*> CONNECTION_SUBGRAPH::GetVectorBusLabels() const
|
||||
{
|
||||
std::vector<SCH_ITEM*> labels;
|
||||
|
||||
@@ -971,6 +1000,58 @@ void CONNECTION_GRAPH::collectAllDriverValues()
|
||||
}
|
||||
|
||||
|
||||
void CONNECTION_GRAPH::generateBusAliasMembers()
|
||||
{
|
||||
std::vector<CONNECTION_SUBGRAPH*> new_subgraphs;
|
||||
|
||||
SCH_CONNECTION dummy( this );
|
||||
|
||||
for( auto&& subgraph : m_driver_subgraphs )
|
||||
{
|
||||
auto vec = subgraph->GetAllBusLabels();
|
||||
|
||||
for( auto& item : vec )
|
||||
{
|
||||
SCH_LABEL_BASE* label = static_cast<SCH_LABEL_BASE*>( item );
|
||||
|
||||
dummy.ConfigureFromLabel( label->GetText() );
|
||||
|
||||
wxLogTrace( ConnTrace, wxS( "new bus label (%s)" ), label->GetText() );
|
||||
|
||||
for( auto& conn : dummy.Members() )
|
||||
{
|
||||
wxString name = conn->FullLocalName();
|
||||
|
||||
CONNECTION_SUBGRAPH* new_sg = new CONNECTION_SUBGRAPH( this );
|
||||
SCH_CONNECTION* new_conn = new SCH_CONNECTION( this );
|
||||
|
||||
new_conn->SetName( name );
|
||||
new_conn->SetType( CONNECTION_TYPE::NET );
|
||||
int code = assignNewNetCode( *new_conn );
|
||||
|
||||
wxLogTrace( ConnTrace, wxS( "SG(%ld), Adding full local name (%s) with sg (%d)" ), subgraph->m_code,
|
||||
name, code );
|
||||
|
||||
new_sg->m_driver_connection = new_conn;
|
||||
new_sg->m_code = m_last_subgraph_code++;
|
||||
new_sg->m_sheet = subgraph->m_sheet;
|
||||
new_sg->m_is_bus_member = true;
|
||||
new_sg->m_strong_driver = true;
|
||||
/// Need to figure out why these sgs are not getting connected to their bus parents
|
||||
|
||||
NET_NAME_CODE_CACHE_KEY key = { new_sg->GetNetName(), code };
|
||||
m_net_code_to_subgraphs_map[ key ].push_back( new_sg );
|
||||
m_net_name_to_subgraphs_map[ name ].push_back( new_sg );
|
||||
m_subgraphs.push_back( new_sg );
|
||||
new_subgraphs.push_back( new_sg );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::copy( new_subgraphs.begin(), new_subgraphs.end(), std::back_inserter( m_driver_subgraphs ) );
|
||||
}
|
||||
|
||||
|
||||
void CONNECTION_GRAPH::generateInvisiblePinSubGraphs()
|
||||
{
|
||||
// Generate subgraphs for invisible power pins. These will be merged with other subgraphs
|
||||
@@ -1115,7 +1196,7 @@ void CONNECTION_GRAPH::processSubGraphs()
|
||||
|
||||
name = new_name;
|
||||
}
|
||||
else
|
||||
else if( subgraph->m_driver )
|
||||
{
|
||||
// If there is no conflict, promote sheet pins to be strong drivers so that they
|
||||
// will be considered below for propagation/merging.
|
||||
@@ -1355,7 +1436,8 @@ void CONNECTION_GRAPH::processSubGraphs()
|
||||
if( subgraph->m_absorbed )
|
||||
continue;
|
||||
|
||||
subgraph->ResolveDrivers();
|
||||
if( !subgraph->ResolveDrivers() )
|
||||
continue;
|
||||
|
||||
if( subgraph->m_driver_connection->IsBus() )
|
||||
assignNetCodesToBus( subgraph->m_driver_connection );
|
||||
@@ -1412,6 +1494,8 @@ void CONNECTION_GRAPH::buildConnectionGraph( std::function<void( SCH_ITEM* )>* a
|
||||
|
||||
generateInvisiblePinSubGraphs();
|
||||
|
||||
generateBusAliasMembers();
|
||||
|
||||
PROF_TIMER proc_sub_graph( "ProcessSubGraphs" );
|
||||
processSubGraphs();
|
||||
|
||||
@@ -1610,7 +1694,7 @@ void CONNECTION_GRAPH::buildConnectionGraph( std::function<void( SCH_ITEM* )>* a
|
||||
// As a visual aid, we can check sheet pins that are driven by themselves to see
|
||||
// if they should be promoted to buses
|
||||
|
||||
if( subgraph->m_driver->Type() == SCH_SHEET_PIN_T )
|
||||
if( subgraph->m_driver && subgraph->m_driver->Type() == SCH_SHEET_PIN_T )
|
||||
{
|
||||
SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( subgraph->m_driver );
|
||||
|
||||
@@ -1689,6 +1773,8 @@ void CONNECTION_GRAPH::buildConnectionGraph( std::function<void( SCH_ITEM* )>* a
|
||||
const CONNECTION_SUBGRAPH* driverSubgraph = nullptr;
|
||||
wxString netclass;
|
||||
|
||||
wxCHECK_RET( !subgraphs.empty(), wxT("Invalid empty subgraph" ) );
|
||||
|
||||
for( const CONNECTION_SUBGRAPH* subgraph : subgraphs )
|
||||
{
|
||||
for( SCH_ITEM* item : subgraph->m_items )
|
||||
@@ -1699,7 +1785,7 @@ void CONNECTION_GRAPH::buildConnectionGraph( std::function<void( SCH_ITEM* )>* a
|
||||
break;
|
||||
}
|
||||
|
||||
if( !netclass.IsEmpty() || !driverSubgraph )
|
||||
if( !netclass.IsEmpty() )
|
||||
{
|
||||
driverSubgraph = subgraph;
|
||||
break;
|
||||
@@ -1709,6 +1795,9 @@ void CONNECTION_GRAPH::buildConnectionGraph( std::function<void( SCH_ITEM* )>* a
|
||||
if( netclass.IsEmpty() )
|
||||
return;
|
||||
|
||||
if( !driverSubgraph )
|
||||
driverSubgraph = subgraphs.front();
|
||||
|
||||
const wxString netname = driverSubgraph->GetNetName();
|
||||
|
||||
if( driverSubgraph->m_driver_connection->IsBus() )
|
||||
@@ -1735,22 +1824,30 @@ void CONNECTION_GRAPH::buildConnectionGraph( std::function<void( SCH_ITEM* )>* a
|
||||
}
|
||||
|
||||
|
||||
int CONNECTION_GRAPH::assignNewNetCode( SCH_CONNECTION& aConnection )
|
||||
int CONNECTION_GRAPH::getOrCreateNetCode( const wxString& aNetName )
|
||||
{
|
||||
int code;
|
||||
|
||||
auto it = m_net_name_to_code_map.find( aConnection.Name() );
|
||||
auto it = m_net_name_to_code_map.find( aNetName );
|
||||
|
||||
if( it == m_net_name_to_code_map.end() )
|
||||
{
|
||||
code = m_last_net_code++;
|
||||
m_net_name_to_code_map[ aConnection.Name() ] = code;
|
||||
m_net_name_to_code_map[ aNetName ] = code;
|
||||
}
|
||||
else
|
||||
{
|
||||
code = it->second;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
int CONNECTION_GRAPH::assignNewNetCode( SCH_CONNECTION& aConnection )
|
||||
{
|
||||
int code = getOrCreateNetCode( aConnection.Name() );
|
||||
|
||||
aConnection.SetNetCode( code );
|
||||
|
||||
return code;
|
||||
@@ -1759,7 +1856,7 @@ int CONNECTION_GRAPH::assignNewNetCode( SCH_CONNECTION& aConnection )
|
||||
|
||||
void CONNECTION_GRAPH::assignNetCodesToBus( SCH_CONNECTION* aConnection )
|
||||
{
|
||||
std::vector< std::shared_ptr<SCH_CONNECTION>>& connections_to_check( aConnection->Members() );
|
||||
std::vector<std::shared_ptr<SCH_CONNECTION>> connections_to_check( aConnection->Members() );
|
||||
|
||||
for( unsigned i = 0; i < connections_to_check.size(); i++ )
|
||||
{
|
||||
@@ -2230,7 +2327,7 @@ std::vector<const CONNECTION_SUBGRAPH*> CONNECTION_GRAPH::GetBusesNeedingMigrati
|
||||
if( !connection->IsBus() )
|
||||
continue;
|
||||
|
||||
auto labels = subgraph->GetBusLabels();
|
||||
auto labels = subgraph->GetVectorBusLabels();
|
||||
|
||||
if( labels.size() > 1 )
|
||||
{
|
||||
|
||||
@@ -76,6 +76,7 @@ public:
|
||||
m_graph( aGraph ),
|
||||
m_dirty( false ),
|
||||
m_absorbed( false ),
|
||||
m_is_bus_member( false ),
|
||||
m_absorbed_by( nullptr ),
|
||||
m_code( -1 ),
|
||||
m_multiple_drivers( false ),
|
||||
@@ -108,8 +109,11 @@ public:
|
||||
*/
|
||||
wxString GetNetName() const;
|
||||
|
||||
/// Returns all the bus labels attached to this subgraph (if any)
|
||||
std::vector<SCH_ITEM*> GetBusLabels() const;
|
||||
/// Returns all the vector-based bus labels attached to this subgraph (if any)
|
||||
std::vector<SCH_ITEM*> GetVectorBusLabels() const;
|
||||
|
||||
/// Returns all the all bus labels attached to this subgraph (if any)
|
||||
std::vector<SCH_ITEM*> GetAllBusLabels() const;
|
||||
|
||||
/// Returns the candidate net name for a driver
|
||||
const wxString& GetNameForDriver( SCH_ITEM* aItem ) const;
|
||||
@@ -160,6 +164,12 @@ public:
|
||||
/// True if this subgraph has been absorbed into another. No pointers here are safe if so!
|
||||
bool m_absorbed;
|
||||
|
||||
/**
|
||||
* True if the subgraph is not actually part of a net. These are created for bus members
|
||||
* to ensure that bus-to-bus connection happens but they don't have any valid data
|
||||
*/
|
||||
bool m_is_bus_member;
|
||||
|
||||
/// If this subgraph is absorbed, points to the absorbing (and valid) subgraph
|
||||
CONNECTION_SUBGRAPH* m_absorbed_by;
|
||||
|
||||
@@ -421,6 +431,11 @@ private:
|
||||
*/
|
||||
void generateInvisiblePinSubGraphs();
|
||||
|
||||
/**
|
||||
* Iterate through labels to create placeholders for bus elements
|
||||
*/
|
||||
void generateBusAliasMembers();
|
||||
|
||||
/**
|
||||
* Process all subgraphs to assign netcodes and merge subgraphs based on labels
|
||||
*/
|
||||
@@ -433,6 +448,13 @@ private:
|
||||
*/
|
||||
int assignNewNetCode( SCH_CONNECTION& aConnection );
|
||||
|
||||
/**
|
||||
*
|
||||
* @param aNetName string with the netname for coding
|
||||
* @return existing netcode (if it exists) or newly created one
|
||||
*/
|
||||
int getOrCreateNetCode( const wxString& aNetName );
|
||||
|
||||
/**
|
||||
* Ensures all members of the bus connection have a valid net code assigned
|
||||
* @param aConnection is a bus connection
|
||||
|
||||
@@ -947,6 +947,10 @@ void SCH_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
|
||||
m_toolManager->RunAction( ACTIONS::updateSchematicFromPcb, true );
|
||||
break;
|
||||
|
||||
case MAIL_RELOAD_LIB:
|
||||
SyncView();
|
||||
break;
|
||||
|
||||
default:;
|
||||
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ DIALOG_ANNOTATE::~DIALOG_ANNOTATE()
|
||||
if( projSettings.m_AnnotateStartNum != startNum )
|
||||
{
|
||||
projSettings.m_AnnotateStartNum = startNum;
|
||||
schFrame->SaveProjectSettings();
|
||||
schFrame->OnModify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -512,21 +512,18 @@ int DIALOG_CHANGE_SYMBOLS::processMatchingSymbols()
|
||||
|
||||
|
||||
int DIALOG_CHANGE_SYMBOLS::processSymbols( const std::map<SCH_SYMBOL*,
|
||||
SYMBOL_CHANGE_INFO>& aSymbols )
|
||||
SYMBOL_CHANGE_INFO>& aSymbols )
|
||||
{
|
||||
wxCHECK( !aSymbols.empty(), 0 );
|
||||
|
||||
int matchesProcessed = 0;
|
||||
SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
|
||||
SCH_SCREEN* screen = nullptr;
|
||||
LIB_SYMBOL* libSymbol = nullptr;
|
||||
std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO> symbols = aSymbols;
|
||||
wxString msg;
|
||||
|
||||
wxCHECK( frame, 0 );
|
||||
|
||||
wxString msg;
|
||||
|
||||
auto it = symbols.begin();
|
||||
std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO> symbols = aSymbols;
|
||||
std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO>::iterator it = symbols.begin();
|
||||
|
||||
// Remove all symbols that don't have a valid library symbol link or enough units to
|
||||
// satify the library symbol update.
|
||||
@@ -536,7 +533,7 @@ int DIALOG_CHANGE_SYMBOLS::processSymbols( const std::map<SCH_SYMBOL*,
|
||||
|
||||
wxCHECK2( symbol && it->second.m_LibId.IsValid(), continue );
|
||||
|
||||
libSymbol = frame->GetLibSymbol( it->second.m_LibId );
|
||||
LIB_SYMBOL* libSymbol = frame->GetLibSymbol( it->second.m_LibId );
|
||||
|
||||
if( !libSymbol )
|
||||
{
|
||||
@@ -562,18 +559,21 @@ int DIALOG_CHANGE_SYMBOLS::processSymbols( const std::map<SCH_SYMBOL*,
|
||||
}
|
||||
}
|
||||
|
||||
bool appendUndo = false;
|
||||
|
||||
// Removing the symbol needs to be done before the LIB_SYMBOL is changed to prevent stale
|
||||
// library symbols in the schematic file.
|
||||
for( const auto& [ symbol, symbol_change_info ] : symbols )
|
||||
{
|
||||
wxCHECK( symbol && !symbol_change_info.m_Instances.empty(), 0 );
|
||||
|
||||
screen = symbol_change_info.m_Instances[0].LastScreen();
|
||||
SCH_SCREEN* screen = symbol_change_info.m_Instances[0].LastScreen();
|
||||
|
||||
wxCHECK( screen, 0 );
|
||||
|
||||
screen->Remove( symbol );
|
||||
frame->SaveCopyInUndoList( screen, symbol, UNDO_REDO::CHANGED, true );
|
||||
frame->SaveCopyInUndoList( screen, symbol, UNDO_REDO::CHANGED, appendUndo );
|
||||
appendUndo = true;
|
||||
}
|
||||
|
||||
for( const auto& [ symbol, symbol_change_info ] : symbols )
|
||||
@@ -581,8 +581,9 @@ int DIALOG_CHANGE_SYMBOLS::processSymbols( const std::map<SCH_SYMBOL*,
|
||||
if( symbol_change_info.m_LibId != symbol->GetLibId() )
|
||||
symbol->SetLibId( symbol_change_info.m_LibId );
|
||||
|
||||
libSymbol = frame->GetLibSymbol( symbol_change_info.m_LibId );
|
||||
LIB_SYMBOL* libSymbol = frame->GetLibSymbol( symbol_change_info.m_LibId );
|
||||
std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
|
||||
SCH_SCREEN* screen = symbol_change_info.m_Instances[0].LastScreen();
|
||||
|
||||
symbol->SetLibSymbol( flattenedSymbol.release() );
|
||||
|
||||
@@ -696,7 +697,6 @@ int DIALOG_CHANGE_SYMBOLS::processSymbols( const std::map<SCH_SYMBOL*,
|
||||
}
|
||||
|
||||
symbol->SetSchSymbolLibraryName( wxEmptyString );
|
||||
screen = symbol_change_info.m_Instances[0].LastScreen();
|
||||
screen->Append( symbol );
|
||||
frame->GetCanvas()->GetView()->Update( symbol );
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ private:
|
||||
void InstallPageSpiceModel();
|
||||
|
||||
bool TransferDataFromWindow() override;
|
||||
void NetlistUpdateOpt();
|
||||
bool NetlistUpdateOpt();
|
||||
|
||||
void updateGeneratorButtons();
|
||||
|
||||
@@ -254,7 +254,7 @@ DIALOG_EXPORT_NETLIST::DIALOG_EXPORT_NETLIST( SCH_EDIT_FRAME* parent ) :
|
||||
|
||||
SCHEMATIC_SETTINGS& settings = m_Parent->Schematic().Settings();
|
||||
|
||||
for( EXPORT_NETLIST_PAGE*& page : m_PanelNetType)
|
||||
for( EXPORT_NETLIST_PAGE*& page : m_PanelNetType )
|
||||
page = nullptr;
|
||||
|
||||
// Add notebook pages:
|
||||
@@ -463,22 +463,35 @@ void DIALOG_EXPORT_NETLIST::OnNetlistTypeSelection( wxNotebookEvent& event )
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_EXPORT_NETLIST::NetlistUpdateOpt()
|
||||
bool DIALOG_EXPORT_NETLIST::NetlistUpdateOpt()
|
||||
{
|
||||
bool saveAllVoltages = m_PanelNetType[ PANELSPICE ]->m_SaveAllVoltages->IsChecked();
|
||||
bool saveAllCurrents = m_PanelNetType[ PANELSPICE ]->m_SaveAllCurrents->IsChecked();
|
||||
bool changed = false;
|
||||
|
||||
bool saveAllVoltages = m_PanelNetType[ PANELSPICE ]->m_SaveAllVoltages->IsChecked();
|
||||
bool saveAllCurrents = m_PanelNetType[ PANELSPICE ]->m_SaveAllCurrents->IsChecked();
|
||||
|
||||
wxString spiceCmdString = m_PanelNetType[ PANELSPICE ]->m_CommandStringCtrl->GetValue();
|
||||
bool curSheetAsRoot = m_PanelNetType[ PANELSPICE ]->m_CurSheetAsRoot->GetValue();
|
||||
bool spiceModelCurSheetAsRoot = m_PanelNetType[ PANELSPICEMODEL ]->m_CurSheetAsRoot->GetValue();
|
||||
|
||||
SCHEMATIC_SETTINGS& settings = m_Parent->Schematic().Settings();
|
||||
wxString netFormatName = m_PanelNetType[m_NoteBook->GetSelection()]->GetPageNetFmtName();
|
||||
|
||||
settings.m_SpiceSaveAllVoltages = saveAllVoltages;
|
||||
settings.m_SpiceSaveAllCurrents = saveAllCurrents;
|
||||
settings.m_SpiceCommandString = spiceCmdString;
|
||||
settings.m_SpiceCurSheetAsRoot = curSheetAsRoot;
|
||||
changed |= ( settings.m_SpiceSaveAllVoltages != saveAllVoltages );
|
||||
changed |= ( settings.m_SpiceSaveAllCurrents != saveAllCurrents );
|
||||
changed |= ( settings.m_SpiceCommandString != spiceCmdString );
|
||||
changed |= ( settings.m_SpiceCurSheetAsRoot != curSheetAsRoot );
|
||||
changed |= ( settings.m_SpiceModelCurSheetAsRoot != spiceModelCurSheetAsRoot );
|
||||
changed |= ( settings.m_NetFormatName != netFormatName );
|
||||
|
||||
settings.m_SpiceSaveAllVoltages = saveAllVoltages;
|
||||
settings.m_SpiceSaveAllCurrents = saveAllCurrents;
|
||||
settings.m_SpiceCommandString = spiceCmdString;
|
||||
settings.m_SpiceCurSheetAsRoot = curSheetAsRoot;
|
||||
settings.m_SpiceModelCurSheetAsRoot = spiceModelCurSheetAsRoot;
|
||||
settings.m_NetFormatName = m_PanelNetType[m_NoteBook->GetSelection()]->GetPageNetFmtName();
|
||||
settings.m_NetFormatName = netFormatName;
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
@@ -489,7 +502,8 @@ bool DIALOG_EXPORT_NETLIST::TransferDataFromWindow()
|
||||
wxString fileExt;
|
||||
wxString title = _( "Save Netlist File" );
|
||||
|
||||
NetlistUpdateOpt();
|
||||
if( NetlistUpdateOpt() )
|
||||
m_Parent->OnModify();
|
||||
|
||||
EXPORT_NETLIST_PAGE* currPage;
|
||||
currPage = (EXPORT_NETLIST_PAGE*) m_NoteBook->GetCurrentPage();
|
||||
@@ -621,7 +635,8 @@ bool DIALOG_EXPORT_NETLIST::FilenamePrms( NETLIST_TYPE_ID aType, wxString * aExt
|
||||
|
||||
void DIALOG_EXPORT_NETLIST::WriteCurrentNetlistSetup()
|
||||
{
|
||||
NetlistUpdateOpt();
|
||||
if( NetlistUpdateOpt() )
|
||||
m_Parent->OnModify();
|
||||
|
||||
EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
|
||||
wxASSERT( cfg );
|
||||
@@ -798,7 +813,7 @@ int InvokeDialogNetList( SCH_EDIT_FRAME* aCaller )
|
||||
DIALOG_EXPORT_NETLIST dlg( aCaller );
|
||||
|
||||
int ret = dlg.ShowModal();
|
||||
aCaller->SaveProjectSettings();
|
||||
aCaller->SaveProjectLocalSettings();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -157,6 +157,8 @@ void DIALOG_FIELD_PROPERTIES::init()
|
||||
|
||||
// Predefined fields cannot contain some chars, or cannot be empty,
|
||||
// and need a SCH_FIELD_VALIDATOR (m_StyledTextCtrl cannot use a SCH_FIELD_VALIDATOR).
|
||||
// VALUE_FIELD does not use the validator so that it uses the Scintilla text control, since we
|
||||
// allow text replacement for this field (but not the other predefined fields)
|
||||
bool use_validator = m_fieldId == REFERENCE_FIELD
|
||||
|| m_fieldId == FOOTPRINT_FIELD
|
||||
|| m_fieldId == DATASHEET_FIELD
|
||||
@@ -189,10 +191,12 @@ void DIALOG_FIELD_PROPERTIES::init()
|
||||
"cannot be changed." ) ) );
|
||||
m_note->Show( true );
|
||||
m_TextCtrl->Enable( false );
|
||||
m_StyledTextCtrl->Enable( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_TextCtrl->Enable( true );
|
||||
m_StyledTextCtrl->Enable( true );
|
||||
}
|
||||
|
||||
GetSizer()->SetSizeHints( this );
|
||||
|
||||
@@ -489,6 +489,16 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::visitItem( const SCH_SHEET_PATH& aShe
|
||||
processItem( aSheetPath, pin );
|
||||
}
|
||||
}
|
||||
else if( m_wires->GetValue() && aItem->IsType( { SCH_ITEM_LOCATE_WIRE_T,
|
||||
SCH_LABEL_LOCATE_WIRE_T } ) )
|
||||
{
|
||||
processItem( aSheetPath, aItem );
|
||||
}
|
||||
else if( m_buses->GetValue() && aItem->IsType( { SCH_ITEM_LOCATE_BUS_T,
|
||||
SCH_LABEL_LOCATE_BUS_T } ) )
|
||||
{
|
||||
processItem( aSheetPath, aItem );
|
||||
}
|
||||
else if( aItem->IsType( { SCH_LABEL_LOCATE_ANY_T } ) )
|
||||
{
|
||||
if( m_globalLabels->GetValue() && aItem->Type() == SCH_GLOBAL_LABEL_T )
|
||||
@@ -529,16 +539,6 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::visitItem( const SCH_SHEET_PATH& aShe
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( m_wires->GetValue() && aItem->IsType( { SCH_ITEM_LOCATE_WIRE_T,
|
||||
SCH_LABEL_LOCATE_WIRE_T } ) )
|
||||
{
|
||||
processItem( aSheetPath, aItem );
|
||||
}
|
||||
else if( m_buses->GetValue() && aItem->IsType( { SCH_ITEM_LOCATE_BUS_T,
|
||||
SCH_LABEL_LOCATE_BUS_T } ) )
|
||||
{
|
||||
processItem( aSheetPath, aItem );
|
||||
}
|
||||
else if( m_schTextAndGraphics->GetValue() && aItem->IsType( { SCH_TEXT_T, SCH_TEXTBOX_T,
|
||||
SCH_ITEM_LOCATE_GRAPHIC_LINE_T,
|
||||
SCH_SHAPE_T } ) )
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-282-g1fa54006)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -79,7 +79,6 @@ DIALOG_IMAGE_PROPERTIES_BASE::DIALOG_IMAGE_PROPERTIES_BASE( wxWindow* parent, wx
|
||||
|
||||
this->SetSizer( m_GeneralBoxSizer );
|
||||
this->Layout();
|
||||
m_GeneralBoxSizer->Fit( this );
|
||||
|
||||
this->Centre( wxBOTH );
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
<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>
|
||||
@@ -47,8 +48,8 @@
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">DIALOG_IMAGE_PROPERTIES_BASE</property>
|
||||
<property name="pos"></property>
|
||||
<property name="size"></property>
|
||||
<property name="style">wxDEFAULT_DIALOG_STYLE</property>
|
||||
<property name="size">363,281</property>
|
||||
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
|
||||
<property name="subclass">DIALOG_SHIM; dialog_shim.h; forward_declare</property>
|
||||
<property name="title"></property>
|
||||
<property name="tooltip"></property>
|
||||
@@ -87,6 +88,7 @@
|
||||
<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>
|
||||
@@ -143,6 +145,7 @@
|
||||
<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>
|
||||
@@ -231,6 +234,7 @@
|
||||
<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>
|
||||
@@ -292,6 +296,7 @@
|
||||
<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>
|
||||
@@ -356,6 +361,7 @@
|
||||
<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>
|
||||
@@ -417,6 +423,7 @@
|
||||
<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>
|
||||
@@ -478,6 +485,7 @@
|
||||
<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>
|
||||
@@ -542,6 +550,7 @@
|
||||
<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>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user