diff --git a/bitmaps_png/png/via_sketch_24.png b/bitmaps_png/png/via_sketch_24.png index 421a11424d..9fe5549bc1 100644 Binary files a/bitmaps_png/png/via_sketch_24.png and b/bitmaps_png/png/via_sketch_24.png differ diff --git a/bitmaps_png/png/via_sketch_dark_24.png b/bitmaps_png/png/via_sketch_dark_24.png index 57d1bef8f3..872fca1d80 100644 Binary files a/bitmaps_png/png/via_sketch_dark_24.png and b/bitmaps_png/png/via_sketch_dark_24.png differ diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index ace6b4a9a7..031147fe7b 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -385,6 +385,7 @@ set( COMMON_SRCS search_stack.cpp searchhelpfilefullpath.cpp status_popup.cpp + stroke_params.cpp systemdirsappend.cpp template_fieldnames.cpp textentry_tricks.cpp @@ -613,6 +614,14 @@ generate_lemon_grammar( libeval_compiler/grammar.lemon ) +# auto-generate stroke_params_lexer.h and stroke_params_keywords.cpp +make_lexer( + common + stroke_params.keywords + stroke_params_lexer.h + stroke_params_keywords.cpp + STROKEPARAMS_T + ) # auto-generate netlist_lexer.h and netlist_keywords.cpp make_lexer( diff --git a/common/base_units.cpp b/common/base_units.cpp index 6e09de66f5..0d4553fd45 100644 --- a/common/base_units.cpp +++ b/common/base_units.cpp @@ -35,11 +35,10 @@ */ #include <base_units.h> -#include <common.h> #include <string_utils.h> #include <math/util.h> // for KiROUND #include <macros.h> -#include <title_block.h> + #if defined( PCBNEW ) || defined( CVPCB ) || defined( EESCHEMA ) || defined( GERBVIEW ) || defined( PL_EDITOR ) #define IU_TO_MM( x ) ( x / IU_PER_MM ) diff --git a/common/eda_shape.cpp b/common/eda_shape.cpp index bf9582107f..c72c783f52 100644 --- a/common/eda_shape.cpp +++ b/common/eda_shape.cpp @@ -40,8 +40,9 @@ EDA_SHAPE::EDA_SHAPE( SHAPE_T aType, int aLineWidth, FILL_T aFill, bool eeWinding ) : m_endsSwapped( false ), m_shape( aType ), - m_width( aLineWidth ), + m_stroke( aLineWidth, PLOT_DASH_TYPE::DEFAULT, COLOR4D::UNSPECIFIED ), m_fill( aFill ), + m_fillColor( COLOR4D::UNSPECIFIED ), m_editState( 0 ), m_eeWinding( eeWinding ) { @@ -352,7 +353,7 @@ void EDA_SHAPE::flip( const wxPoint& aCentre, bool aFlipLeftRight ) { std::vector<wxPoint> ctrlPoints = { m_start, m_bezierC1, m_bezierC2, m_end }; BEZIER_POLY converter( ctrlPoints ); - converter.GetPoly( m_bezierPoints, m_width ); + converter.GetPoly( m_bezierPoints, m_stroke.GetWidth() ); } break; @@ -605,7 +606,7 @@ void EDA_SHAPE::ShapeGetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PA break; } - aList.emplace_back( _( "Line width" ), MessageTextFromValue( units, m_width ) ); + aList.emplace_back( _( "Line width" ), MessageTextFromValue( units, GetWidth() ) ); } @@ -663,7 +664,7 @@ const EDA_RECT EDA_SHAPE::getBoundingBox() const break; } - bbox.Inflate( std::max( 0, m_width / 2 ) ); + bbox.Inflate( std::max( 0, GetWidth() ) / 2 ); bbox.Normalize(); return bbox; @@ -674,8 +675,8 @@ bool EDA_SHAPE::hitTest( const wxPoint& aPosition, int aAccuracy ) const { int maxdist = aAccuracy; - if( m_width > 0 ) - maxdist += m_width / 2; + if( GetWidth() > 0 ) + maxdist += GetWidth() / 2; switch( m_shape ) { @@ -727,7 +728,7 @@ bool EDA_SHAPE::hitTest( const wxPoint& aPosition, int aAccuracy ) const } case SHAPE_T::BEZIER: - const_cast<EDA_SHAPE*>( this )->RebuildBezierToSegmentsPointsList( m_width ); + const_cast<EDA_SHAPE*>( this )->RebuildBezierToSegmentsPointsList( GetWidth() ); for( unsigned int i= 1; i < m_bezierPoints.size(); i++) { @@ -1070,7 +1071,7 @@ void EDA_SHAPE::SetPolyPoints( const std::vector<wxPoint>& aPoints ) } -std::vector<SHAPE*> EDA_SHAPE::MakeEffectiveShapes() const +std::vector<SHAPE*> EDA_SHAPE::MakeEffectiveShapes( bool aEdgeOnly ) const { std::vector<SHAPE*> effectiveShapes; @@ -1078,60 +1079,50 @@ std::vector<SHAPE*> EDA_SHAPE::MakeEffectiveShapes() const { case SHAPE_T::ARC: effectiveShapes.emplace_back( new SHAPE_ARC( m_arcCenter, m_start, GetArcAngle() / 10.0, - m_width ) ); + GetWidth() ) ); break; case SHAPE_T::SEGMENT: - effectiveShapes.emplace_back( new SHAPE_SEGMENT( m_start, m_end, m_width ) ); + effectiveShapes.emplace_back( new SHAPE_SEGMENT( m_start, m_end, GetWidth() ) ); break; case SHAPE_T::RECT: { std::vector<wxPoint> pts = GetRectCorners(); - if( IsFilled() ) + if( IsFilled() && !aEdgeOnly ) effectiveShapes.emplace_back( new SHAPE_SIMPLE( pts ) ); - if( m_width > 0 || !IsFilled() ) + if( GetWidth() > 0 || !IsFilled() || aEdgeOnly ) { - effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[0], pts[1], m_width ) ); - effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[1], pts[2], m_width ) ); - effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[2], pts[3], m_width ) ); - effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[3], pts[0], m_width ) ); + effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[0], pts[1], GetWidth() ) ); + effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[1], pts[2], GetWidth() ) ); + effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[2], pts[3], GetWidth() ) ); + effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[3], pts[0], GetWidth() ) ); } } break; case SHAPE_T::CIRCLE: { - if( IsFilled() ) + if( IsFilled() && !aEdgeOnly ) effectiveShapes.emplace_back( new SHAPE_CIRCLE( getCenter(), GetRadius() ) ); - if( m_width > 0 || !IsFilled() ) - { - // SHAPE_CIRCLE has no ConvertToPolyline() method, so use a 360.0 SHAPE_ARC - SHAPE_ARC circle( getCenter(), GetEnd(), 360.0 ); - SHAPE_LINE_CHAIN l = circle.ConvertToPolyline(); - - for( int i = 0; i < l.SegmentCount(); i++ ) - { - effectiveShapes.emplace_back( new SHAPE_SEGMENT( l.Segment( i ).A, l.Segment( i ).B, - m_width ) ); - } - } + if( GetWidth() > 0 || !IsFilled() || aEdgeOnly ) + effectiveShapes.emplace_back( new SHAPE_ARC( getCenter(), GetEnd(), 360.0 ) ); break; } case SHAPE_T::BEZIER: { - auto bezierPoints = buildBezierToSegmentsPointsList( GetWidth() ); + std::vector<wxPoint> bezierPoints = buildBezierToSegmentsPointsList( GetWidth() ); wxPoint start_pt = bezierPoints[0]; for( unsigned int jj = 1; jj < bezierPoints.size(); jj++ ) { wxPoint end_pt = bezierPoints[jj]; - effectiveShapes.emplace_back( new SHAPE_SEGMENT( start_pt, end_pt, m_width ) ); + effectiveShapes.emplace_back( new SHAPE_SEGMENT( start_pt, end_pt, GetWidth() ) ); start_pt = end_pt; } @@ -1145,13 +1136,13 @@ std::vector<SHAPE*> EDA_SHAPE::MakeEffectiveShapes() const l.Rotate( -DECIDEG2RAD( getParentOrientation() ) ); l.Move( getParentPosition() ); - if( IsFilled() ) + if( IsFilled() && !aEdgeOnly ) effectiveShapes.emplace_back( new SHAPE_SIMPLE( l ) ); - if( m_width > 0 || !IsFilled() ) + if( GetWidth() > 0 || !IsFilled() || aEdgeOnly ) { for( int i = 0; i < l.SegmentCount(); i++ ) - effectiveShapes.emplace_back( new SHAPE_SEGMENT( l.Segment( i ), m_width ) ); + effectiveShapes.emplace_back( new SHAPE_SEGMENT( l.Segment( i ), GetWidth() ) ); } } break; @@ -1322,9 +1313,9 @@ void EDA_SHAPE::calcEdit( const wxPoint& aPosition ) case 4: { - double chordA = GetLineLength( m_start, aPosition ); - double chordB = GetLineLength( m_end, aPosition ); - radius = int( ( chordA + chordB ) / 2.0 ) + 1; + double radialA = GetLineLength( m_start, aPosition ); + double radialB = GetLineLength( m_end, aPosition ); + radius = int( ( radialA + radialB ) / 2.0 ) + 1; } break; @@ -1373,6 +1364,10 @@ void EDA_SHAPE::calcEdit( const wxPoint& aPosition ) case 4: // Pick the one closer to the mouse position m_arcCenter = GetLineLength( c1, aPosition ) < GetLineLength( c2, aPosition ) ? c1 : c2; + + if( GetArcAngle() > 1800 ) + std::swap( m_start, m_end ); + break; } } @@ -1425,7 +1420,7 @@ void EDA_SHAPE::SwapShape( EDA_SHAPE* aImage ) EDA_SHAPE* image = dynamic_cast<EDA_SHAPE*>( aImage ); assert( image ); - std::swap( m_width, image->m_width ); + std::swap( m_stroke, image->m_stroke ); std::swap( m_start, image->m_start ); std::swap( m_end, image->m_end ); std::swap( m_arcCenter, image->m_arcCenter ); @@ -1462,12 +1457,16 @@ int EDA_SHAPE::Compare( const EDA_SHAPE* aOther ) const else if( m_shape == SHAPE_T::POLY ) { TEST( m_poly.TotalVertices(), aOther->m_poly.TotalVertices() ); - - for( int ii = 0; ii < m_poly.TotalVertices(); ++ii ) - TEST_PT( m_poly.CVertex( ii ), aOther->m_poly.CVertex( ii ) ); } - TEST_E( m_width, aOther->m_width ); + for( size_t ii = 0; ii < m_bezierPoints.size(); ++ii ) + TEST_PT( m_bezierPoints[ii], aOther->m_bezierPoints[ii] ); + + for( int ii = 0; ii < m_poly.TotalVertices(); ++ii ) + TEST_PT( m_poly.CVertex( ii ), aOther->m_poly.CVertex( ii ) ); + + TEST_E( m_stroke.GetWidth(), aOther->m_stroke.GetWidth() ); + TEST( (int) m_stroke.GetPlotStyle(), (int) aOther->m_stroke.GetPlotStyle() ); TEST( (int) m_fill, (int) aOther->m_fill ); return 0; @@ -1479,7 +1478,7 @@ void EDA_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuf int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth ) const { - int width = ignoreLineWidth ? 0 : m_width; + int width = ignoreLineWidth ? 0 : GetWidth(); width += 2 * aClearanceValue; @@ -1580,7 +1579,7 @@ void EDA_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuf std::vector<wxPoint> ctrlPts = { GetStart(), GetBezierC1(), GetBezierC2(), GetEnd() }; BEZIER_POLY converter( ctrlPts ); std::vector< wxPoint> poly; - converter.GetPoly( poly, m_width ); + converter.GetPoly( poly, GetWidth() ); for( unsigned ii = 1; ii < poly.size(); ii++ ) { diff --git a/common/layer_id.cpp b/common/layer_id.cpp index d2d9813871..21d33edcd8 100644 --- a/common/layer_id.cpp +++ b/common/layer_id.cpp @@ -117,6 +117,7 @@ wxString LayerName( int aLayer ) case LAYER_DEVICE: return _( "Symbol body outlines" ); case LAYER_DEVICE_BACKGROUND: return _( "Symbol body fills" ); case LAYER_NOTES: return _( "Schematic text && graphics" ); + case LAYER_NOTES_BACKGROUND: return _( "Schematic text && graphics backgrounds" ); case LAYER_PIN: return _( "Pins" ); case LAYER_SHEET: return _( "Sheet borders" ); case LAYER_SHEET_BACKGROUND: return _( "Sheet backgrounds" ); diff --git a/common/plotters/plotter.cpp b/common/plotters/plotter.cpp index 4d4b7d7331..617c062373 100644 --- a/common/plotters/plotter.cpp +++ b/common/plotters/plotter.cpp @@ -41,7 +41,6 @@ #include <eda_item.h> #include <plotters/plotter.h> #include <geometry/shape_line_chain.h> -#include <geometry/geometry_utils.h> #include <bezier_curves.h> #include <math/util.h> // for KiROUND @@ -138,19 +137,19 @@ double PLOTTER::userToDeviceSize( double size ) const double PLOTTER::GetDotMarkLenIU() const { - return userToDeviceSize( dot_mark_len( GetCurrentLineWidth() ) ); + return userToDeviceSize( m_renderSettings->GetDotLength( GetCurrentLineWidth() ) ); } double PLOTTER::GetDashMarkLenIU() const { - return userToDeviceSize( dash_mark_len( GetCurrentLineWidth() ) ); + return userToDeviceSize( m_renderSettings->GetDashLength( GetCurrentLineWidth() ) ); } double PLOTTER::GetDashGapLenIU() const { - return userToDeviceSize( dash_gap_len( GetCurrentLineWidth() ) ); + return userToDeviceSize( m_renderSettings->GetGapLength( GetCurrentLineWidth() ) ); } diff --git a/common/render_settings.cpp b/common/render_settings.cpp index a6d0a3854f..764de1302f 100644 --- a/common/render_settings.cpp +++ b/common/render_settings.cpp @@ -51,6 +51,27 @@ RENDER_SETTINGS::~RENDER_SETTINGS() } +constexpr double visualCorrection = 0.8; + + +double RENDER_SETTINGS::GetDashLength( int aLineWidth ) const +{ + return std::max( m_dashLengthRatio - visualCorrection, 1.0 ) * aLineWidth; +} + + +double RENDER_SETTINGS::GetDotLength( int aLineWidth ) const +{ + return ( 1.0 - visualCorrection ) * aLineWidth; +} + + +double RENDER_SETTINGS::GetGapLength( int aLineWidth ) const +{ + return std::max( m_gapLengthRatio + visualCorrection, 1.0 ) * aLineWidth; +} + + void RENDER_SETTINGS::update() { // Calculate darkened/highlighted variants of layer colors diff --git a/common/settings/builtin_color_themes.h b/common/settings/builtin_color_themes.h index b71c9c51a3..cc83b3c812 100644 --- a/common/settings/builtin_color_themes.h +++ b/common/settings/builtin_color_themes.h @@ -48,6 +48,7 @@ static const std::map<int, COLOR4D> s_defaultTheme = { LAYER_LOCLABEL, CSS_COLOR( 15, 15, 15, 1 ) }, { LAYER_NOCONNECT, CSS_COLOR( 0, 0, 132, 1 ) }, { LAYER_NOTES, CSS_COLOR( 0, 0, 194, 1 ) }, + { LAYER_NOTES_BACKGROUND, CSS_COLOR( 0, 0, 0, 0 ) }, { LAYER_PIN, CSS_COLOR( 132, 0, 0, 1 ) }, { LAYER_PINNAM, CSS_COLOR( 0, 100, 100, 1 ) }, { LAYER_PINNUM, CSS_COLOR( 169, 0, 0, 1 ) }, @@ -193,6 +194,7 @@ static const std::map<int, COLOR4D> s_classicTheme = { LAYER_LOCLABEL, COLOR4D( BLACK ) }, { LAYER_NOCONNECT, COLOR4D( BLUE ) }, { LAYER_NOTES, COLOR4D( LIGHTBLUE ) }, + { LAYER_NOTES_BACKGROUND, COLOR4D( UNSPECIFIED_COLOR ) }, { LAYER_PIN, COLOR4D( RED ) }, { LAYER_PINNAM, COLOR4D( CYAN ) }, { LAYER_PINNUM, COLOR4D( RED ) }, diff --git a/common/settings/color_settings.cpp b/common/settings/color_settings.cpp index 50a975a111..93dbfcfb15 100644 --- a/common/settings/color_settings.cpp +++ b/common/settings/color_settings.cpp @@ -94,6 +94,7 @@ COLOR_SETTINGS::COLOR_SETTINGS( const wxString& aFilename, bool aAbsolutePath ) CLR( "schematic.label_local", LAYER_LOCLABEL ); CLR( "schematic.no_connect", LAYER_NOCONNECT ); CLR( "schematic.note", LAYER_NOTES ); + CLR( "schematic.note_background", LAYER_NOTES_BACKGROUND ); CLR( "schematic.pin", LAYER_PIN ); CLR( "schematic.pin_name", LAYER_PINNAM ); CLR( "schematic.pin_number", LAYER_PINNUM ); diff --git a/common/stroke_params.cpp b/common/stroke_params.cpp new file mode 100644 index 0000000000..c9c82c8c78 --- /dev/null +++ b/common/stroke_params.cpp @@ -0,0 +1,276 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <macros.h> +#include <base_units.h> +#include <string_utils.h> +#include <eda_rect.h> +#include <render_settings.h> +#include <geometry/shape.h> +#include <geometry/shape_segment.h> +#include <geometry/shape_simple.h> +#include <geometry/geometry_utils.h> +#include <stroke_params.h> +#include <trigo.h> + +using namespace STROKEPARAMS_T; + + +void STROKE_PARAMS::Stroke( const SHAPE* aShape, PLOT_DASH_TYPE aLineStyle, int aWidth, + const KIGFX::RENDER_SETTINGS* aRenderSettings, + std::function<void( const wxPoint& a, const wxPoint& b )> aStroker ) +{ + double strokes[6]; + int wrapAround; + + switch( aLineStyle ) + { + case PLOT_DASH_TYPE::DASH: + strokes[0] = aRenderSettings->GetDashLength( aWidth ); + strokes[1] = aRenderSettings->GetGapLength( aWidth ); + wrapAround = 2; + break; + case PLOT_DASH_TYPE::DOT: + strokes[0] = aRenderSettings->GetDotLength( aWidth ); + strokes[1] = aRenderSettings->GetGapLength( aWidth ); + wrapAround = 2; + break; + case PLOT_DASH_TYPE::DASHDOT: + strokes[0] = aRenderSettings->GetDashLength( aWidth ); + strokes[1] = aRenderSettings->GetGapLength( aWidth ); + strokes[2] = aRenderSettings->GetDotLength( aWidth ); + strokes[3] = aRenderSettings->GetGapLength( aWidth ); + wrapAround = 4; + break; + default: + UNIMPLEMENTED_FOR( lineTypeNames.at( aLineStyle ).name ); + } + + switch( aShape->Type() ) + { + case SH_SIMPLE: + { + const SHAPE_SIMPLE* poly = static_cast<const SHAPE_SIMPLE*>( aShape ); + + for( size_t ii = 0; ii < poly->GetSegmentCount(); ++ii ) + { + SEG seg = poly->GetSegment( ii ); + SHAPE_SEGMENT line( seg.A, seg.B ); + STROKE_PARAMS::Stroke( &line, aLineStyle, aWidth, aRenderSettings, aStroker ); + } + } + break; + + case SH_SEGMENT: + { + const SHAPE_SEGMENT* line = static_cast<const SHAPE_SEGMENT*>( aShape ); + + VECTOR2D start = line->GetSeg().A; + VECTOR2D end = line->GetSeg().B; + + EDA_RECT clip( (wxPoint)start, wxSize( end.x - start.x, end.y - start.y ) ); + clip.Normalize(); + + double theta = atan2( end.y - start.y, end.x - start.x ); + + for( size_t i = 0; i < 10000; ++i ) + { + // Calculations MUST be done in doubles to keep from accumulating rounding + // errors as we go. + VECTOR2D next( start.x + strokes[ i % wrapAround ] * cos( theta ), + start.y + strokes[ i % wrapAround ] * sin( theta ) ); + + // Drawing each segment can be done rounded to ints. + wxPoint a( KiROUND( start.x ), KiROUND( start.y ) ); + wxPoint b( KiROUND( next.x ), KiROUND( next.y ) ); + + if( ClipLine( &clip, a.x, a.y, b.x, b.y ) ) + break; + else if( i % 2 == 0 ) + aStroker( a, b ); + + start = next; + } + } + break; + + case SH_ARC: + { + const SHAPE_ARC* arc = static_cast<const SHAPE_ARC*>( aShape ); + + double r = arc->GetRadius(); + double C = 2.0 * M_PI * r; + VECTOR2I center = arc->GetCenter(); + VECTOR2D startRadial( arc->GetP0() - center ); + double startAngle = 180.0 / M_PI * atan2( startRadial.y, startRadial.x ); + VECTOR2D endRadial( arc->GetP1() - center ); + double arcEndAngle = 180.0 / M_PI * atan2( endRadial.y, endRadial.x ); + + if( arcEndAngle == startAngle ) + arcEndAngle = startAngle + 360.0; // ring, not null + + if( startAngle > arcEndAngle ) + { + if( arcEndAngle < 0 ) + arcEndAngle = NormalizeAngleDegrees( arcEndAngle, 0.0, 360.0 ); + else + startAngle = NormalizeAngleDegrees( startAngle, -360.0, 0.0 ); + } + + wxASSERT( startAngle < arcEndAngle ); + + for( size_t i = 0; i < 10000 && startAngle < arcEndAngle; ++i ) + { + double theta = 360.0 * strokes[ i % wrapAround ] / C; + double endAngle = std::min( startAngle + theta, arcEndAngle ); + + if( i % 2 == 0 ) + { + wxPoint a( center.x + r * cos( startAngle * M_PI / 180.0 ), + center.y + r * sin( startAngle * M_PI / 180.0 ) ); + wxPoint b( center.x + r * cos( endAngle * M_PI / 180.0 ), + center.y + r * sin( endAngle * M_PI / 180.0 ) ); + + aStroker( a, b ); + } + + startAngle = endAngle; + } + } + break; + + case SH_CIRCLE: + // A circle is always filled; a ring is represented by a 360° arc. + KI_FALLTHROUGH; + + default: + UNIMPLEMENTED_FOR( SHAPE_TYPE_asString( aShape->Type() ) ); + } +} + + +static wxString getLineStyleToken( PLOT_DASH_TYPE aStyle ) +{ + wxString token; + + switch( aStyle ) + { + case PLOT_DASH_TYPE::DASH: token = "dash"; break; + case PLOT_DASH_TYPE::DOT: token = "dot"; break; + case PLOT_DASH_TYPE::DASHDOT: token = "dash_dot"; break; + case PLOT_DASH_TYPE::SOLID: token = "solid"; break; + case PLOT_DASH_TYPE::DEFAULT: token = "default"; break; + } + + return token; +} + + +void STROKE_PARAMS::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel ) const +{ + wxASSERT( aFormatter != nullptr ); + + aFormatter->Print( aNestLevel, "(stroke (width %s) (type %s) (color %d %d %d %s))", + FormatInternalUnits(GetWidth() ).c_str(), + TO_UTF8( getLineStyleToken( GetPlotStyle() ) ), + KiROUND( GetColor().r * 255.0 ), + KiROUND( GetColor().g * 255.0 ), + KiROUND( GetColor().b * 255.0 ), + Double2Str( GetColor().a ).c_str() ); +} + + +void STROKE_PARAMS_PARSER::ParseStroke( STROKE_PARAMS& aStroke ) +{ + for( T token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_width: + aStroke.SetWidth( parseDouble( "stroke width" ) * m_iuPerMM ); + NeedRIGHT(); + break; + + case T_type: + { + token = NextTok(); + + switch( token ) + { + case T_dash: aStroke.SetPlotStyle( PLOT_DASH_TYPE::DASH ); break; + case T_dot: aStroke.SetPlotStyle( PLOT_DASH_TYPE::DOT ); break; + case T_dash_dot: aStroke.SetPlotStyle( PLOT_DASH_TYPE::DASHDOT ); break; + case T_solid: aStroke.SetPlotStyle( PLOT_DASH_TYPE::SOLID ); break; + case T_default: aStroke.SetPlotStyle( PLOT_DASH_TYPE::DEFAULT ); break; + default: + Expecting( "solid, dash, dash_dot, dot or default" ); + } + + NeedRIGHT(); + break; + } + + case T_color: + { + KIGFX::COLOR4D color; + + color.r = parseInt( "red" ) / 255.0; + color.g = parseInt( "green" ) / 255.0; + color.b = parseInt( "blue" ) / 255.0; + color.a = Clamp( parseDouble( "alpha" ), 0.0, 1.0 ); + + aStroke.SetColor( color ); + NeedRIGHT(); + break; + } + + default: + Expecting( "width, type, or color" ); + } + } +} + + +int STROKE_PARAMS_PARSER::parseInt( const char* aText ) +{ + T token = NextTok(); + + if( token != T_NUMBER ) + Expecting( aText ); + + return atoi( CurText() ); +} + + +double STROKE_PARAMS_PARSER::parseDouble( const char* aText ) +{ + T token = NextTok(); + + if( token != T_NUMBER ) + Expecting( aText ); + + double val = strtod( CurText(), NULL ); + + return val; +} diff --git a/common/stroke_params.keywords b/common/stroke_params.keywords new file mode 100644 index 0000000000..44975ea188 --- /dev/null +++ b/common/stroke_params.keywords @@ -0,0 +1,10 @@ +color +dash +dash_dot +dash_dot_dot +default +dot +solid +stroke +type +width \ No newline at end of file diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index 01120207cb..79b4fe6b2d 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -91,6 +91,8 @@ set( EESCHEMA_DLGS dialogs/dialog_rescue_each_base.cpp dialogs/dialog_sch_import_settings.cpp dialogs/dialog_sch_import_settings_base.cpp + dialogs/dialog_shape_properties.cpp + dialogs/dialog_shape_properties_base.cpp dialogs/dialog_sheet_pin_properties.cpp dialogs/dialog_sheet_pin_properties_base.cpp dialogs/dialog_sheet_properties.cpp @@ -183,7 +185,6 @@ set( EESCHEMA_SRCS lib_pin.cpp lib_symbol.cpp lib_text.cpp - symbol_viewer_frame.cpp libarch.cpp menubar.cpp pin_numbers.cpp @@ -210,6 +211,7 @@ set( EESCHEMA_SRCS sch_screen.cpp sch_plugins/kicad/sch_sexpr_parser.cpp sch_plugins/kicad/sch_sexpr_plugin.cpp + sch_shape.cpp sch_sheet.cpp sch_sheet_path.cpp sch_sheet_pin.cpp @@ -226,6 +228,7 @@ set( EESCHEMA_SRCS symbol_library.cpp symbol_tree_model_adapter.cpp symbol_tree_synchronizing_adapter.cpp + symbol_viewer_frame.cpp toolbars_symbol_viewer.cpp toolbars_sch_editor.cpp transform.cpp diff --git a/eeschema/bus-wire-junction.cpp b/eeschema/bus-wire-junction.cpp index 79a33429fd..82401ba81a 100644 --- a/eeschema/bus-wire-junction.cpp +++ b/eeschema/bus-wire-junction.cpp @@ -319,7 +319,7 @@ bool SCH_EDIT_FRAME::BreakSegment( SCH_LINE* aSegment, const wxPoint& aPoint, bool SCH_EDIT_FRAME::BreakSegments( const wxPoint& aPoint, SCH_SCREEN* aScreen ) { - static const KICAD_T wiresAndBuses[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT }; + static const KICAD_T wiresAndBuses[] = { SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T, EOT }; if( aScreen == nullptr ) aScreen = GetScreen(); @@ -380,7 +380,7 @@ void SCH_EDIT_FRAME::DeleteJunction( SCH_ITEM* aJunction, bool aAppend ) SCH_SCREEN* screen = GetScreen(); PICKED_ITEMS_LIST undoList; EE_SELECTION_TOOL* selectionTool = m_toolManager->GetTool<EE_SELECTION_TOOL>(); - KICAD_T wiresAndBuses[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT }; + KICAD_T wiresAndBuses[] = { SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T, EOT }; auto remove_item = [ & ]( SCH_ITEM* aItem ) -> void { diff --git a/eeschema/dialogs/dialog_global_edit_text_and_graphics.cpp b/eeschema/dialogs/dialog_global_edit_text_and_graphics.cpp index 78349e1a77..6c9358ac87 100644 --- a/eeschema/dialogs/dialog_global_edit_text_and_graphics.cpp +++ b/eeschema/dialogs/dialog_global_edit_text_and_graphics.cpp @@ -27,6 +27,7 @@ #include <sch_symbol.h> #include <sch_connection.h> #include <sch_edit_frame.h> +#include <sch_shape.h> #include <sch_line.h> #include <sch_junction.h> #include <sch_sheet.h> @@ -117,8 +118,8 @@ DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS( SCH_ m_colorSwatch->SetSwatchColor( COLOR4D::UNSPECIFIED, false ); m_colorSwatch->SetDefaultColor( COLOR4D::UNSPECIFIED ); - m_bgColorSwatch->SetSwatchColor( COLOR4D::UNSPECIFIED, false ); - m_bgColorSwatch->SetDefaultColor( COLOR4D::UNSPECIFIED ); + m_fillColorSwatch->SetSwatchColor( COLOR4D::UNSPECIFIED, false ); + m_fillColorSwatch->SetDefaultColor( COLOR4D::UNSPECIFIED ); m_dotColorSwatch->SetSwatchColor( COLOR4D::UNSPECIFIED, false ); m_dotColorSwatch->SetDefaultColor( COLOR4D::UNSPECIFIED ); @@ -217,7 +218,7 @@ bool DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::TransferDataToWindow() m_lineStyle->SetStringSelection( INDETERMINATE_ACTION ); m_junctionSize.SetValue( INDETERMINATE_ACTION ); m_setColor->SetValue( false ); - m_setBgColor->SetValue( false ); + m_setFillColor->SetValue( false ); m_setDotColor->SetValue( false ); return true; @@ -240,7 +241,6 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::processItem( const SCH_SHEET_PATH& aS EDA_TEXT* eda_text = dynamic_cast<EDA_TEXT*>( aItem ); SCH_TEXT* sch_text = dynamic_cast<SCH_TEXT*>( aItem ); - SCH_LINE* lineItem = dynamic_cast<SCH_LINE*>( aItem ); SCH_JUNCTION* junction = dynamic_cast<SCH_JUNCTION*>( aItem ); m_parent->SaveCopyInUndoList( aSheetPath.LastScreen(), aItem, UNDO_REDO::CHANGED, m_appendUndo ); @@ -274,21 +274,40 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::processItem( const SCH_SHEET_PATH& aS sch_text->SetLabelSpinStyle( (LABEL_SPIN_STYLE::SPIN) m_orientation->GetSelection() ); } - if( lineItem ) + if( aItem->HasLineStroke() ) { + STROKE_PARAMS stroke = aItem->GetStroke(); + if( !m_lineWidth.IsIndeterminate() ) - lineItem->SetLineWidth( m_lineWidth.GetValue() ); + stroke.SetWidth( m_lineWidth.GetValue() ); if( m_lineStyle->GetStringSelection() != INDETERMINATE_ACTION ) { if( m_lineStyle->GetStringSelection() == DEFAULT_STYLE ) - lineItem->SetLineStyle( PLOT_DASH_TYPE::DEFAULT ); + stroke.SetPlotStyle( PLOT_DASH_TYPE::DEFAULT ); else - lineItem->SetLineStyle( m_lineStyle->GetSelection() ); + stroke.SetPlotStyle( (PLOT_DASH_TYPE) m_lineStyle->GetSelection() ); } if( m_setColor->GetValue() ) - lineItem->SetLineColor( m_colorSwatch->GetSwatchColor() ); + stroke.SetColor( m_colorSwatch->GetSwatchColor() ); + + aItem->SetStroke( stroke ); + } + + if( aItem->Type() == SCH_SHAPE_T ) + { + SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem ); + + if( m_setFillColor->GetValue() ) + { + shape->SetFillColor( m_fillColorSwatch->GetSwatchColor() ); + + if( m_fillColorSwatch->GetSwatchColor() == COLOR4D::UNSPECIFIED ) + shape->SetFillMode( FILL_T::NO_FILL ); + else + shape->SetFillMode( FILL_T::FILLED_WITH_COLOR ); + } } if( junction ) @@ -348,9 +367,9 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::visitItem( const SCH_SHEET_PATH& aShe } } - static KICAD_T wireTypes[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LABEL_LOCATE_WIRE_T, EOT }; - static KICAD_T busTypes[] = { SCH_LINE_LOCATE_BUS_T, SCH_LABEL_LOCATE_BUS_T, EOT }; - static KICAD_T schTextAndGraphics[] = { SCH_TEXT_T, SCH_LINE_LOCATE_GRAPHIC_LINE_T, EOT }; + static KICAD_T wireTypes[] = { SCH_ITEM_LOCATE_WIRE_T, SCH_LABEL_LOCATE_WIRE_T, EOT }; + static KICAD_T busTypes[] = { SCH_ITEM_LOCATE_BUS_T, SCH_LABEL_LOCATE_BUS_T, EOT }; + static KICAD_T schTextAndGraphics[] = { SCH_TEXT_T, SCH_ITEM_LOCATE_GRAPHIC_LINE_T, EOT }; if( aItem->Type() == SCH_SYMBOL_T ) { @@ -409,8 +428,8 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::visitItem( const SCH_SHEET_PATH& aShe if( m_setColor->GetValue() ) sheet->SetBorderColor( m_colorSwatch->GetSwatchColor() ); - if( m_setBgColor->GetValue() ) - sheet->SetBackgroundColor( m_bgColorSwatch->GetSwatchColor() ); + if( m_setFillColor->GetValue() ) + sheet->SetBackgroundColor( m_fillColorSwatch->GetSwatchColor() ); } } else if( aItem->Type() == SCH_JUNCTION_T ) diff --git a/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.cpp b/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.cpp index 245a32cb81..dc2a096241 100644 --- a/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.cpp +++ b/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.cpp @@ -327,14 +327,14 @@ DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS_BASE::DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS_ fgSizer1->Add( 0, 0, 1, wxEXPAND, 5 ); - m_setBgColor = new wxCheckBox( m_specifiedValues, wxID_ANY, _("Sheet background color:"), wxDefaultPosition, wxDefaultSize, 0 ); - fgSizer1->Add( m_setBgColor, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + m_setFillColor = new wxCheckBox( m_specifiedValues, wxID_ANY, _("Fill color:"), wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer1->Add( m_setFillColor, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - m_bgColorSwatch = new COLOR_SWATCH( m_specifiedValues, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - m_bgColorSwatch->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - m_bgColorSwatch->SetMinSize( wxSize( 48,24 ) ); + m_fillColorSwatch = new COLOR_SWATCH( m_specifiedValues, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + m_fillColorSwatch->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_fillColorSwatch->SetMinSize( wxSize( 48,24 ) ); - fgSizer1->Add( m_bgColorSwatch, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + fgSizer1->Add( m_fillColorSwatch, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); m_dotSizeLabel = new wxStaticText( m_specifiedValues, wxID_ANY, _("Junction size:"), wxDefaultPosition, wxDefaultSize, 0 ); m_dotSizeLabel->Wrap( -1 ); diff --git a/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.fbp b/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.fbp index 2cfe9de015..cfccbec1fc 100644 --- a/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.fbp +++ b/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.fbp @@ -3570,7 +3570,7 @@ <property name="gripper">0</property> <property name="hidden">0</property> <property name="id">wxID_ANY</property> - <property name="label">Sheet background color:</property> + <property name="label">Fill color:</property> <property name="max_size"></property> <property name="maximize_button">0</property> <property name="maximum_size"></property> @@ -3578,7 +3578,7 @@ <property name="minimize_button">0</property> <property name="minimum_size"></property> <property name="moveable">1</property> - <property name="name">m_setBgColor</property> + <property name="name">m_setFillColor</property> <property name="pane_border">1</property> <property name="pane_position"></property> <property name="pane_size"></property> @@ -3644,7 +3644,7 @@ <property name="minimize_button">0</property> <property name="minimum_size">48,24</property> <property name="moveable">1</property> - <property name="name">m_bgColorSwatch</property> + <property name="name">m_fillColorSwatch</property> <property name="pane_border">1</property> <property name="pane_position"></property> <property name="pane_size"></property> diff --git a/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.h b/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.h index 066b07d0ef..cf0adacf1f 100644 --- a/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.h +++ b/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.h @@ -88,8 +88,8 @@ class DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS_BASE : public DIALOG_SHIM COLOR_SWATCH* m_colorSwatch; wxStaticText* lineStyleLabel; wxChoice* m_lineStyle; - wxCheckBox* m_setBgColor; - COLOR_SWATCH* m_bgColorSwatch; + wxCheckBox* m_setFillColor; + COLOR_SWATCH* m_fillColorSwatch; wxStaticText* m_dotSizeLabel; wxTextCtrl* m_dotSizeCtrl; wxStaticText* m_dotSizeUnits; diff --git a/eeschema/dialogs/dialog_lib_shape_properties.cpp b/eeschema/dialogs/dialog_lib_shape_properties.cpp index b7bc060aa0..4a6cc9ea9a 100644 --- a/eeschema/dialogs/dialog_lib_shape_properties.cpp +++ b/eeschema/dialogs/dialog_lib_shape_properties.cpp @@ -25,7 +25,7 @@ #include <dialog_lib_shape_properties.h> #include <symbol_edit_frame.h> #include <confirm.h> - +#include <lib_shape.h> DIALOG_LIB_SHAPE_PROPERTIES::DIALOG_LIB_SHAPE_PROPERTIES( SYMBOL_EDIT_FRAME* aParent, LIB_ITEM* aItem ) : @@ -85,7 +85,7 @@ bool DIALOG_LIB_SHAPE_PROPERTIES::TransferDataToWindow() m_checkApplyToAllConversions->Enable( enblConvOptStyle ); if( shape ) - m_fillCtrl->SetSelection( static_cast<int>( shape->GetFillType() ) - 1 ); + m_fillCtrl->SetSelection( static_cast<int>( shape->GetFillMode() ) - 1 ); m_fillCtrl->Enable( shape != nullptr ); @@ -98,13 +98,16 @@ bool DIALOG_LIB_SHAPE_PROPERTIES::TransferDataFromWindow() if( !wxDialog::TransferDataFromWindow() ) return false; - EDA_SHAPE* shape = dynamic_cast<EDA_SHAPE*>( m_item ); + LIB_SHAPE* shape = dynamic_cast<LIB_SHAPE*>( m_item ); if( shape ) + { shape->SetFillMode( static_cast<FILL_T>( std::max( m_fillCtrl->GetSelection() + 1, 1 ) ) ); - if( shape ) - shape->SetWidth( m_lineWidth.GetValue() ); + STROKE_PARAMS stroke = shape->GetStroke(); + stroke.SetWidth( m_lineWidth.GetValue() ); + shape->SetStroke( stroke ); + } if( GetApplyToAllConversions() ) m_item->SetConvert( 0 ); diff --git a/eeschema/dialogs/dialog_line_wire_bus_properties.cpp b/eeschema/dialogs/dialog_line_wire_bus_properties.cpp index f85051d7ca..4d9a4bd284 100644 --- a/eeschema/dialogs/dialog_line_wire_bus_properties.cpp +++ b/eeschema/dialogs/dialog_line_wire_bus_properties.cpp @@ -22,37 +22,15 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include <bitmaps.h> #include <sch_line.h> #include <dialog_line_wire_bus_properties.h> #include <dialogs/dialog_color_picker.h> #include <settings/settings_manager.h> #include <sch_edit_frame.h> +#include <stroke_params.h> #include <widgets/color_swatch.h> -struct lineTypeStruct -{ - wxString name; - const BITMAPS bitmap; -}; - - -/* - * Conversion map between PLOT_DASH_TYPE values and style names displayed - */ -const std::map<PLOT_DASH_TYPE, struct lineTypeStruct> lineTypeNames = { - { PLOT_DASH_TYPE::SOLID, { _( "Solid" ), BITMAPS::stroke_solid } }, - { PLOT_DASH_TYPE::DASH, { _( "Dashed" ), BITMAPS::stroke_dash } }, - { PLOT_DASH_TYPE::DOT, { _( "Dotted" ), BITMAPS::stroke_dot } }, - { PLOT_DASH_TYPE::DASHDOT, { _( "Dash-Dot" ), BITMAPS::stroke_dashdot } }, -}; - - -#define DEFAULT_STYLE _( "Default" ) -#define INDETERMINATE_STYLE _( "Leave unchanged" ) - - DIALOG_LINE_WIRE_BUS_PROPERTIES::DIALOG_LINE_WIRE_BUS_PROPERTIES( SCH_EDIT_FRAME* aParent, std::deque<SCH_ITEM*>& aItems ) : DIALOG_LINE_WIRE_BUS_PROPERTIES_BASE( aParent ), diff --git a/eeschema/dialogs/dialog_shape_properties.cpp b/eeschema/dialogs/dialog_shape_properties.cpp new file mode 100644 index 0000000000..d7e80f762c --- /dev/null +++ b/eeschema/dialogs/dialog_shape_properties.cpp @@ -0,0 +1,113 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <widgets/color_swatch.h> +#include <stroke_params.h> +#include <sch_edit_frame.h> +#include <sch_shape.h> +#include <dialog_shape_properties.h> + + +DIALOG_SHAPE_PROPERTIES::DIALOG_SHAPE_PROPERTIES( SCH_EDIT_FRAME* aParent, SCH_SHAPE* aShape ) : + DIALOG_SHAPE_PROPERTIES_BASE( aParent ), + m_shape( aShape ), + m_lineWidth( aParent, m_lineWidthLabel, m_lineWidthCtrl, m_lineWidthUnits, true ) +{ + SetTitle( wxString::Format( GetTitle(), aShape->ShowShape() ) ); + + m_helpLabel1->SetFont( KIUI::GetInfoFont( this ) ); + m_helpLabel2->SetFont( KIUI::GetInfoFont( this ) ); + + SetInitialFocus( m_lineWidthCtrl ); + + m_lineColorSwatch->SetDefaultColor( COLOR4D::UNSPECIFIED ); + + for( const std::pair<const PLOT_DASH_TYPE, lineTypeStruct>& typeEntry : lineTypeNames ) + m_lineStyleCombo->Append( typeEntry.second.name, KiBitmap( typeEntry.second.bitmap ) ); + + m_lineStyleCombo->Append( DEFAULT_STYLE ); + + m_fillColorSwatch->SetDefaultColor( COLOR4D::UNSPECIFIED ); + + // Required under wxGTK if we want to dismiss the dialog with the ESC key + SetFocus(); + m_sdbSizerOK->SetDefault(); + + // Now all widgets have the size fixed, call FinishDialogSettings + finishDialogSettings(); +} + + +bool DIALOG_SHAPE_PROPERTIES::TransferDataToWindow() +{ + if( !wxDialog::TransferDataToWindow() ) + return false; + + m_lineWidth.SetValue( m_shape->GetWidth() ); + m_lineColorSwatch->SetSwatchColor( m_shape->GetStroke().GetColor(), false ); + + int style = static_cast<int>( m_shape->GetStroke().GetPlotStyle() ); + + if( style == -1 ) + m_lineStyleCombo->SetStringSelection( DEFAULT_STYLE ); + else if( style < (int) lineTypeNames.size() ) + m_lineStyleCombo->SetSelection( style ); + else + wxFAIL_MSG( "Line type not found in the type lookup map" ); + + m_filledCtrl->SetValue( m_shape->IsFilled() ); + m_fillColorSwatch->SetSwatchColor( m_shape->GetFillColor(), false ); + + return true; +} + + +bool DIALOG_SHAPE_PROPERTIES::TransferDataFromWindow() +{ + if( !wxDialog::TransferDataFromWindow() ) + return false; + + STROKE_PARAMS stroke = m_shape->GetStroke(); + + if( !m_lineWidth.IsIndeterminate() ) + stroke.SetWidth( m_lineWidth.GetValue() ); + + auto it = lineTypeNames.begin(); + std::advance( it, m_lineStyleCombo->GetSelection() ); + + if( it == lineTypeNames.end() ) + stroke.SetPlotStyle( PLOT_DASH_TYPE::DEFAULT ); + else + stroke.SetPlotStyle( it->first ); + + stroke.SetColor( m_lineColorSwatch->GetSwatchColor() ); + + m_shape->SetStroke( stroke ); + + m_shape->SetFillMode( m_filledCtrl->GetValue() ? FILL_T::FILLED_WITH_COLOR : FILL_T::NO_FILL ); + m_shape->SetFillColor( m_fillColorSwatch->GetSwatchColor() ); + + return true; +} + + diff --git a/eeschema/dialogs/dialog_shape_properties.h b/eeschema/dialogs/dialog_shape_properties.h new file mode 100644 index 0000000000..254db7d531 --- /dev/null +++ b/eeschema/dialogs/dialog_shape_properties.h @@ -0,0 +1,49 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2021 KiCad Developers, see CHANGELOG.TXT for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef DIALOG_SHAPE_PROPERTIES_H +#define DIALOG_SHAPE_PROPERTIES_H + + +class SCH_SHAPE; +class SCH_EDIT_FRAME; + + +#include <dialog_shape_properties_base.h> +#include <widgets/unit_binder.h> + + +class DIALOG_SHAPE_PROPERTIES : public DIALOG_SHAPE_PROPERTIES_BASE +{ +public: + DIALOG_SHAPE_PROPERTIES( SCH_EDIT_FRAME* aParent, SCH_SHAPE* aShape ); + + bool TransferDataToWindow() override; + bool TransferDataFromWindow() override; + +private: + SCH_SHAPE* m_shape; + UNIT_BINDER m_lineWidth; +}; + +#endif // DIALOG_SHAPE_PROPERTIES_H diff --git a/eeschema/dialogs/dialog_shape_properties_base.cpp b/eeschema/dialogs/dialog_shape_properties_base.cpp new file mode 100644 index 0000000000..8be5815ad4 --- /dev/null +++ b/eeschema/dialogs/dialog_shape_properties_base.cpp @@ -0,0 +1,146 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Oct 26 2018) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "widgets/color_swatch.h" + +#include "dialog_shape_properties_base.h" + +/////////////////////////////////////////////////////////////////////////// + +BEGIN_EVENT_TABLE( DIALOG_SHAPE_PROPERTIES_BASE, DIALOG_SHIM ) + EVT_BUTTON( wxID_APPLY, DIALOG_SHAPE_PROPERTIES_BASE::_wxFB_resetDefaults ) +END_EVENT_TABLE() + +DIALOG_SHAPE_PROPERTIES_BASE::DIALOG_SHAPE_PROPERTIES_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* mainSizer; + mainSizer = new wxBoxSizer( wxVERTICAL ); + + wxFlexGridSizer* fgSizerGeneral; + fgSizerGeneral = new wxFlexGridSizer( 0, 3, 7, 0 ); + fgSizerGeneral->AddGrowableCol( 1 ); + fgSizerGeneral->SetFlexibleDirection( wxBOTH ); + fgSizerGeneral->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_lineWidthLabel = new wxStaticText( this, wxID_ANY, _("Line width:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_lineWidthLabel->Wrap( -1 ); + fgSizerGeneral->Add( m_lineWidthLabel, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 3 ); + + m_lineWidthCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), 0 ); + fgSizerGeneral->Add( m_lineWidthCtrl, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT, 3 ); + + m_lineWidthUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 ); + m_lineWidthUnits->Wrap( -1 ); + m_lineWidthUnits->SetMinSize( wxSize( 40,-1 ) ); + + fgSizerGeneral->Add( m_lineWidthUnits, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 3 ); + + m_lineColorLabel = new wxStaticText( this, wxID_ANY, _("Line color:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_lineColorLabel->Wrap( -1 ); + fgSizerGeneral->Add( m_lineColorLabel, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + + m_panel1 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SIMPLE|wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer2; + bSizer2 = new wxBoxSizer( wxVERTICAL ); + + m_lineColorSwatch = new COLOR_SWATCH( m_panel1, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer2->Add( m_lineColorSwatch, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + + m_panel1->SetSizer( bSizer2 ); + m_panel1->Layout(); + bSizer2->Fit( m_panel1 ); + fgSizerGeneral->Add( m_panel1, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 2 ); + + + fgSizerGeneral->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_lineStyleLabel = new wxStaticText( this, wxID_ANY, _("Line style:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_lineStyleLabel->Wrap( -1 ); + fgSizerGeneral->Add( m_lineStyleLabel, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + + m_lineStyleCombo = new wxBitmapComboBox( this, wxID_ANY, _("Combo!"), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY ); + m_lineStyleCombo->SetMinSize( wxSize( 240,-1 ) ); + + fgSizerGeneral->Add( m_lineStyleCombo, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT, 3 ); + + + fgSizerGeneral->Add( 0, 0, 1, wxEXPAND, 5 ); + + + fgSizerGeneral->Add( 0, 0, 1, wxEXPAND|wxTOP|wxBOTTOM, 5 ); + + + fgSizerGeneral->Add( 0, 0, 1, wxEXPAND, 5 ); + + + fgSizerGeneral->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_filledCtrl = new wxCheckBox( this, wxID_ANY, _("Filled shape"), wxDefaultPosition, wxDefaultSize, 0 ); + fgSizerGeneral->Add( m_filledCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + + fgSizerGeneral->Add( 0, 0, 1, wxEXPAND, 5 ); + + + fgSizerGeneral->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_fillColorLabel = new wxStaticText( this, wxID_ANY, _("Fill color:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_fillColorLabel->Wrap( -1 ); + fgSizerGeneral->Add( m_fillColorLabel, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + + m_panel11 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SIMPLE|wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer21; + bSizer21 = new wxBoxSizer( wxVERTICAL ); + + m_fillColorSwatch = new COLOR_SWATCH( m_panel11, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer21->Add( m_fillColorSwatch, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + + m_panel11->SetSizer( bSizer21 ); + m_panel11->Layout(); + bSizer21->Fit( m_panel11 ); + fgSizerGeneral->Add( m_panel11, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + + mainSizer->Add( fgSizerGeneral, 1, wxEXPAND|wxTOP|wxBOTTOM|wxLEFT, 10 ); + + m_helpLabel1 = new wxStaticText( this, wxID_ANY, _("Set line width to 0 to use Schematic Editor line widths."), wxDefaultPosition, wxDefaultSize, 0 ); + m_helpLabel1->Wrap( 333 ); + mainSizer->Add( m_helpLabel1, 0, wxTOP|wxRIGHT|wxLEFT, 10 ); + + m_helpLabel2 = new wxStaticText( this, wxID_ANY, _("Set line color to transparent to use Schematic Editor colors."), wxDefaultPosition, wxDefaultSize, 0 ); + m_helpLabel2->Wrap( -1 ); + mainSizer->Add( m_helpLabel2, 0, wxBOTTOM|wxRIGHT|wxLEFT, 10 ); + + m_staticline = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + mainSizer->Add( m_staticline, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); + + m_sdbSizer = new wxStdDialogButtonSizer(); + m_sdbSizerOK = new wxButton( this, wxID_OK ); + m_sdbSizer->AddButton( m_sdbSizerOK ); + m_sdbSizerApply = new wxButton( this, wxID_APPLY ); + m_sdbSizer->AddButton( m_sdbSizerApply ); + m_sdbSizerCancel = new wxButton( this, wxID_CANCEL ); + m_sdbSizer->AddButton( m_sdbSizerCancel ); + m_sdbSizer->Realize(); + + mainSizer->Add( m_sdbSizer, 0, wxALL|wxALIGN_RIGHT, 5 ); + + + this->SetSizer( mainSizer ); + this->Layout(); + mainSizer->Fit( this ); + + this->Centre( wxBOTH ); +} + +DIALOG_SHAPE_PROPERTIES_BASE::~DIALOG_SHAPE_PROPERTIES_BASE() +{ +} diff --git a/eeschema/dialogs/dialog_shape_properties_base.fbp b/eeschema/dialogs/dialog_shape_properties_base.fbp new file mode 100644 index 0000000000..338358ec1e --- /dev/null +++ b/eeschema/dialogs/dialog_shape_properties_base.fbp @@ -0,0 +1,1099 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<wxFormBuilder_Project> + <FileVersion major="1" minor="15" /> + <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">table</property> + <property name="file">dialog_shape_properties_base</property> + <property name="first_id">1000</property> + <property name="help_provider">none</property> + <property name="indent_with_spaces"></property> + <property name="internationalize">1</property> + <property name="name">dialog_shape_properties</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_enum">1</property> + <property name="use_microsoft_bom">0</property> + <object class="Dialog" expanded="1"> + <property name="aui_managed">0</property> + <property name="aui_manager_style">wxAUI_MGR_DEFAULT</property> + <property name="bg"></property> + <property name="center">wxBOTH</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="enabled">1</property> + <property name="event_handler">impl_virtual</property> + <property name="extra_style"></property> + <property name="fg"></property> + <property name="font"></property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="maximum_size"></property> + <property name="minimum_size"></property> + <property name="name">DIALOG_SHAPE_PROPERTIES_BASE</property> + <property name="pos"></property> + <property name="size">-1,-1</property> + <property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property> + <property name="subclass">DIALOG_SHIM; dialog_shim.h</property> + <property name="title">%s Properties</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">mainSizer</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">10</property> + <property name="flag">wxEXPAND|wxTOP|wxBOTTOM|wxLEFT</property> + <property name="proportion">1</property> + <object class="wxFlexGridSizer" expanded="1"> + <property name="cols">3</property> + <property name="flexible_direction">wxBOTH</property> + <property name="growablecols">1</property> + <property name="growablerows"></property> + <property name="hgap">0</property> + <property name="minimum_size"></property> + <property name="name">fgSizerGeneral</property> + <property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property> + <property name="permission">none</property> + <property name="rows">0</property> + <property name="vgap">7</property> + <object class="sizeritem" expanded="0"> + <property name="border">3</property> + <property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT</property> + <property name="proportion">0</property> + <object class="wxStaticText" expanded="0"> + <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="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">Line width:</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_lineWidthLabel</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="0"> + <property name="border">3</property> + <property name="flag">wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT</property> + <property name="proportion">0</property> + <object class="wxTextCtrl" expanded="0"> + <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="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">-1,-1</property> + <property name="minimize_button">0</property> + <property name="minimum_size">-1,-1</property> + <property name="moveable">1</property> + <property name="name">m_lineWidthCtrl</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">-1,-1</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 class="sizeritem" expanded="0"> + <property name="border">3</property> + <property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT</property> + <property name="proportion">0</property> + <object class="wxStaticText" expanded="0"> + <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="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">unit</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">40,-1</property> + <property name="moveable">1</property> + <property name="name">m_lineWidthUnits</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="0"> + <property name="border">5</property> + <property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT</property> + <property name="proportion">0</property> + <object class="wxStaticText" expanded="0"> + <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="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">Line color:</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_lineColorLabel</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">; ; Not forward_declare</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">2</property> + <property name="flag">wxALIGN_CENTER_VERTICAL</property> + <property name="proportion">0</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="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"></property> + <property name="moveable">1</property> + <property name="name">m_panel1</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">; ; forward_declare</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">wxBORDER_SIMPLE|wxTAB_TRAVERSAL</property> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bSizer2</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL</property> + <property name="proportion">0</property> + <object class="CustomControl" 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="class">COLOR_SWATCH</property> + <property name="close_button">1</property> + <property name="construction"></property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="declaration"></property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="include"></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_lineColorSwatch</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="settings"></property> + <property name="show">1</property> + <property name="size"></property> + <property name="subclass">COLOR_SWATCH; widgets/color_swatch.h; forward_declare</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> + </object> + </object> + </object> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND</property> + <property name="proportion">1</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">wxALIGN_CENTER_VERTICAL|wxRIGHT</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="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">Line style:</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_lineStyleLabel</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">; ; forward_declare</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">3</property> + <property name="flag">wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT</property> + <property name="proportion">0</property> + <object class="wxBitmapComboBox" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="choices"></property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="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">240,-1</property> + <property name="moveable">1</property> + <property name="name">m_lineStyleCombo</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="selection">-1</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxCB_READONLY</property> + <property name="subclass">; ; forward_declare</property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="value">Combo!</property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND</property> + <property name="proportion">1</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">wxEXPAND|wxTOP|wxBOTTOM</property> + <property name="proportion">1</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">wxEXPAND</property> + <property name="proportion">1</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">wxEXPAND</property> + <property name="proportion">1</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">wxALIGN_CENTER_VERTICAL</property> + <property name="proportion">0</property> + <object class="wxCheckBox" 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="checked">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="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">Filled shape</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_filledCtrl</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">; ; forward_declare</property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND</property> + <property name="proportion">1</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">wxEXPAND</property> + <property name="proportion">1</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">wxALIGN_CENTER_VERTICAL|wxRIGHT</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="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">Fill color:</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_fillColorLabel</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">; ; forward_declare</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">wxALIGN_CENTER_VERTICAL</property> + <property name="proportion">0</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="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"></property> + <property name="moveable">1</property> + <property name="name">m_panel11</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">; ; forward_declare</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">wxBORDER_SIMPLE|wxTAB_TRAVERSAL</property> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bSizer21</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL</property> + <property name="proportion">0</property> + <object class="CustomControl" 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="class">COLOR_SWATCH</property> + <property name="close_button">1</property> + <property name="construction"></property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="declaration"></property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="include"></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_fillColorSwatch</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="settings"></property> + <property name="show">1</property> + <property name="size"></property> + <property name="subclass">COLOR_SWATCH; widgets/color_swatch.h; forward_declare</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> + </object> + </object> + </object> + </object> + </object> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">10</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="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">Set line width to 0 to use Schematic Editor line widths.</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_helpLabel1</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">; ; forward_declare</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">333</property> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">10</property> + <property name="flag">wxBOTTOM|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="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">Set line color to transparent to use Schematic Editor colors.</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_helpLabel2</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">; ; forward_declare</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">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property> + <property name="proportion">0</property> + <object class="wxStaticLine" 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="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"></property> + <property name="moveable">1</property> + <property name="name">m_staticline</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">wxLI_HORIZONTAL</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> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxALIGN_RIGHT</property> + <property name="proportion">0</property> + <object class="wxStdDialogButtonSizer" expanded="1"> + <property name="Apply">1</property> + <property name="Cancel">1</property> + <property name="ContextHelp">0</property> + <property name="Help">0</property> + <property name="No">0</property> + <property name="OK">1</property> + <property name="Save">0</property> + <property name="Yes">0</property> + <property name="minimum_size"></property> + <property name="name">m_sdbSizer</property> + <property name="permission">protected</property> + <event name="OnApplyButtonClick">resetDefaults</event> + </object> + </object> + </object> + </object> + </object> +</wxFormBuilder_Project> diff --git a/eeschema/dialogs/dialog_shape_properties_base.h b/eeschema/dialogs/dialog_shape_properties_base.h new file mode 100644 index 0000000000..ae16b005e6 --- /dev/null +++ b/eeschema/dialogs/dialog_shape_properties_base.h @@ -0,0 +1,76 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Oct 26 2018) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include <wx/artprov.h> +#include <wx/xrc/xmlres.h> +#include <wx/intl.h> +class COLOR_SWATCH; + +#include "dialog_shim.h" +#include <wx/string.h> +#include <wx/stattext.h> +#include <wx/gdicmn.h> +#include <wx/font.h> +#include <wx/colour.h> +#include <wx/settings.h> +#include <wx/textctrl.h> +#include <wx/sizer.h> +#include <wx/panel.h> +#include <wx/bmpcbox.h> +#include <wx/checkbox.h> +#include <wx/statline.h> +#include <wx/button.h> +#include <wx/dialog.h> + +/////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +/// Class DIALOG_SHAPE_PROPERTIES_BASE +/////////////////////////////////////////////////////////////////////////////// +class DIALOG_SHAPE_PROPERTIES_BASE : public DIALOG_SHIM +{ + DECLARE_EVENT_TABLE() + private: + + // Private event handlers + void _wxFB_resetDefaults( wxCommandEvent& event ){ resetDefaults( event ); } + + + protected: + wxStaticText* m_lineWidthLabel; + wxTextCtrl* m_lineWidthCtrl; + wxStaticText* m_lineWidthUnits; + wxStaticText* m_lineColorLabel; + wxPanel* m_panel1; + COLOR_SWATCH* m_lineColorSwatch; + wxStaticText* m_lineStyleLabel; + wxBitmapComboBox* m_lineStyleCombo; + wxCheckBox* m_filledCtrl; + wxStaticText* m_fillColorLabel; + wxPanel* m_panel11; + COLOR_SWATCH* m_fillColorSwatch; + wxStaticText* m_helpLabel1; + wxStaticText* m_helpLabel2; + wxStaticLine* m_staticline; + wxStdDialogButtonSizer* m_sdbSizer; + wxButton* m_sdbSizerOK; + wxButton* m_sdbSizerApply; + wxButton* m_sdbSizerCancel; + + // Virtual event handlers, overide them in your derived class + virtual void resetDefaults( wxCommandEvent& event ) { event.Skip(); } + + + public: + + DIALOG_SHAPE_PROPERTIES_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("%s Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~DIALOG_SHAPE_PROPERTIES_BASE(); + +}; + diff --git a/eeschema/dialogs/panel_eeschema_color_settings.cpp b/eeschema/dialogs/panel_eeschema_color_settings.cpp index 00fd1bff5a..e0954d380f 100644 --- a/eeschema/dialogs/panel_eeschema_color_settings.cpp +++ b/eeschema/dialogs/panel_eeschema_color_settings.cpp @@ -49,6 +49,7 @@ std::set<int> g_excludedLayers = { + LAYER_NOTES_BACKGROUND, LAYER_DANGLING }; @@ -209,7 +210,6 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createSwatches() layers.push_back( i ); } - std::sort( layers.begin(), layers.end(), []( SCH_LAYER_ID a, SCH_LAYER_ID b ) { @@ -382,7 +382,7 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems() comp_body->SetUnit( 0 ); comp_body->SetConvert( 0 ); - comp_body->SetWidth( Mils2iu( 10 ) ); + comp_body->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) ); comp_body->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR ); comp_body->AddPoint( MILS_POINT( p.x - 200, p.y + 200 ) ); comp_body->AddPoint( MILS_POINT( p.x + 200, p.y ) ); diff --git a/eeschema/ee_collectors.cpp b/eeschema/ee_collectors.cpp index 9c3f5fc331..d532aac321 100644 --- a/eeschema/ee_collectors.cpp +++ b/eeschema/ee_collectors.cpp @@ -43,6 +43,7 @@ const KICAD_T EE_COLLECTOR::AllItems[] = { const KICAD_T EE_COLLECTOR::EditableItems[] = { + SCH_SHAPE_T, SCH_TEXT_T, SCH_LABEL_T, SCH_GLOBAL_LABEL_T, @@ -80,6 +81,7 @@ const KICAD_T EE_COLLECTOR::MovableItems[] = SCH_BUS_WIRE_ENTRY_T, SCH_LINE_T, SCH_BITMAP_T, + SCH_SHAPE_T, SCH_TEXT_T, SCH_LABEL_T, SCH_GLOBAL_LABEL_T, diff --git a/eeschema/lib_shape.cpp b/eeschema/lib_shape.cpp index 9bc42a3660..506d23ace8 100644 --- a/eeschema/lib_shape.cpp +++ b/eeschema/lib_shape.cpp @@ -33,10 +33,9 @@ #include <lib_shape.h> -LIB_SHAPE::LIB_SHAPE( LIB_SYMBOL* aParent, SHAPE_T aShape, int aDefaultLineWidth, - FILL_T aFillType ) : +LIB_SHAPE::LIB_SHAPE( LIB_SYMBOL* aParent, SHAPE_T aShape, int aLineWidth, FILL_T aFillType ) : LIB_ITEM( LIB_SHAPE_T, aParent ), - EDA_SHAPE( aShape, aDefaultLineWidth, aFillType, true ) + EDA_SHAPE( aShape, aLineWidth, aFillType, true ) { m_editState = 0; } @@ -260,7 +259,7 @@ void LIB_SHAPE::print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset, std::swap( pt1, pt2 ); } - if( forceNoFill || GetFillType() == FILL_T::NO_FILL ) + if( forceNoFill || GetFillMode() == FILL_T::NO_FILL ) { penWidth = std::max( penWidth, aSettings->GetDefaultPenWidth() ); @@ -292,7 +291,7 @@ void LIB_SHAPE::print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset, } else { - if( GetFillType() == FILL_T::FILLED_WITH_BG_BODYCOLOR ) + if( GetFillMode() == FILL_T::FILLED_WITH_BG_BODYCOLOR ) fillColor = aSettings->GetLayerColor( LAYER_DEVICE_BACKGROUND ); switch( GetShape() ) @@ -415,46 +414,20 @@ void LIB_SHAPE::AddPoint( const wxPoint& aPosition ) } else { - wxFAIL_MSG( "LIB_SHAPE::AddPoint not implemented for " + SHAPE_T_asString() ); + UNIMPLEMENTED_FOR( SHAPE_T_asString() ); } } void LIB_SHAPE::CalcArcAngles( int& aStartAngle, int& aEndAngle ) const { - wxPoint centerStartVector = GetStart() - GetCenter(); - wxPoint centerEndVector = GetEnd() - GetCenter(); + double start; + double end; - // Angles in Eeschema are still integers - aStartAngle = KiROUND( ArcTangente( centerStartVector.y, centerStartVector.x ) ); - aEndAngle = KiROUND( ArcTangente( centerEndVector.y, centerEndVector.x ) ); + EDA_SHAPE::CalcArcAngles( start, end ); - NORMALIZE_ANGLE_POS( aStartAngle ); - NORMALIZE_ANGLE_POS( aEndAngle ); // angles = 0 .. 3600 - - // Restrict angle to less than 180 to avoid PBS display mirror Trace because it is - // assumed that the arc is less than 180 deg to find orientation after rotate or mirror. - if( ( aEndAngle - aStartAngle ) > 1800 ) - aEndAngle -= 3600; - else if( ( aEndAngle - aStartAngle ) <= -1800 ) - aEndAngle += 3600; - - while( ( aEndAngle - aStartAngle ) >= 1800 ) - { - aEndAngle--; - aStartAngle++; - } - - while( ( aStartAngle - aEndAngle ) >= 1800 ) - { - aEndAngle++; - aStartAngle--; - } - - NORMALIZE_ANGLE_POS( aStartAngle ); - - if( !IsMoving() ) - NORMALIZE_ANGLE_POS( aEndAngle ); + aStartAngle = KiROUND( start * 10.0 ); + aEndAngle = KiROUND( end * 10.0 ); } diff --git a/eeschema/lib_shape.h b/eeschema/lib_shape.h index faf13940d4..7f983a9d44 100644 --- a/eeschema/lib_shape.h +++ b/eeschema/lib_shape.h @@ -49,6 +49,9 @@ public: return ShowShape(); } + STROKE_PARAMS GetStroke() const { return m_stroke; } + void SetStroke( const STROKE_PARAMS& aStroke ) { m_stroke = aStroke; } + bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override; bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override; @@ -59,7 +62,7 @@ public: // For historical reasons, a stored value of 0 means "default width" and negative // numbers meant "don't stroke". - if( GetPenWidth() < 0 && GetFillType() != FILL_T::NO_FILL ) + if( GetPenWidth() < 0 && GetFillMode() != FILL_T::NO_FILL ) return 0; else if( GetPenWidth() == 0 ) return aSettings->GetDefaultPenWidth(); diff --git a/eeschema/lib_symbol.cpp b/eeschema/lib_symbol.cpp index ec4b7e5aec..27dc6f234f 100644 --- a/eeschema/lib_symbol.cpp +++ b/eeschema/lib_symbol.cpp @@ -531,7 +531,7 @@ void LIB_SYMBOL::Print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset if( aConvert && shape.m_convert && ( shape.m_convert != aConvert ) ) continue; - if( shape.GetFillType() == FILL_T::FILLED_WITH_BG_BODYCOLOR ) + if( shape.GetFillMode() == FILL_T::FILLED_WITH_BG_BODYCOLOR ) shape.Print( aSettings, aOffset, (void*) false, aOpts.transform ); } } @@ -568,7 +568,7 @@ void LIB_SYMBOL::Print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset else if( item.Type() == LIB_SHAPE_T ) { LIB_SHAPE& shape = static_cast<LIB_SHAPE&>( item ); - bool forceNoFill = shape.GetFillType() == FILL_T::FILLED_WITH_BG_BODYCOLOR; + bool forceNoFill = shape.GetFillMode() == FILL_T::FILLED_WITH_BG_BODYCOLOR; shape.Print( aSettings, aOffset, (void*) forceNoFill, aOpts.transform ); } @@ -603,7 +603,7 @@ void LIB_SYMBOL::Plot( PLOTTER* aPlotter, int aUnit, int aConvert, const wxPoint if( aConvert && shape.m_convert && ( shape.m_convert != aConvert ) ) continue; - if( shape.GetFillType() == FILL_T::FILLED_WITH_BG_BODYCOLOR && aPlotter->GetColorMode() ) + if( shape.GetFillMode() == FILL_T::FILLED_WITH_BG_BODYCOLOR && aPlotter->GetColorMode() ) shape.Plot( aPlotter, aOffset, true, aTransform ); } @@ -627,7 +627,7 @@ void LIB_SYMBOL::Plot( PLOTTER* aPlotter, int aUnit, int aConvert, const wxPoint if( item.Type() == LIB_SHAPE_T ) { const LIB_SHAPE& shape = static_cast<const LIB_SHAPE&>( item ); - forceNoFill = shape.GetFillType() == FILL_T::FILLED_WITH_BG_BODYCOLOR; + forceNoFill = shape.GetFillMode() == FILL_T::FILLED_WITH_BG_BODYCOLOR; } item.Plot( aPlotter, aOffset, !forceNoFill, aTransform ); diff --git a/eeschema/menubar.cpp b/eeschema/menubar.cpp index 3843f615e8..53859d3194 100644 --- a/eeschema/menubar.cpp +++ b/eeschema/menubar.cpp @@ -215,6 +215,9 @@ void SCH_EDIT_FRAME::ReCreateMenuBar() placeMenu->Add( EE_ACTIONS::importSheetPin ); placeMenu->AppendSeparator(); + placeMenu->Add( EE_ACTIONS::drawRectangle ); + placeMenu->Add( EE_ACTIONS::drawCircle ); + placeMenu->Add( EE_ACTIONS::drawArc ); placeMenu->Add( EE_ACTIONS::drawLines ); placeMenu->Add( EE_ACTIONS::placeSchematicText ); placeMenu->Add( EE_ACTIONS::placeImage ); diff --git a/eeschema/sch_bus_entry.cpp b/eeschema/sch_bus_entry.cpp index 31d461cfe4..87474bd956 100644 --- a/eeschema/sch_bus_entry.cpp +++ b/eeschema/sch_bus_entry.cpp @@ -26,6 +26,7 @@ #include <bitmaps.h> #include <core/mirror.h> #include <schematic.h> +#include <geometry/shape_segment.h> #include <sch_bus_entry.h> #include <sch_edit_frame.h> #include <sch_junction.h> @@ -172,7 +173,7 @@ const EDA_RECT SCH_BUS_ENTRY_BASE::GetBoundingBox() const } -COLOR4D SCH_BUS_ENTRY_BASE::GetStrokeColor() const +COLOR4D SCH_BUS_ENTRY_BASE::GetBusEntryColor() const { if( m_stroke.GetColor() != COLOR4D::UNSPECIFIED ) { @@ -190,7 +191,7 @@ COLOR4D SCH_BUS_ENTRY_BASE::GetStrokeColor() const } -PLOT_DASH_TYPE SCH_BUS_ENTRY_BASE::GetStrokeStyle() const +PLOT_DASH_TYPE SCH_BUS_ENTRY_BASE::GetLineStyle() const { if( m_stroke.GetPlotStyle() != PLOT_DASH_TYPE::DEFAULT ) { @@ -267,57 +268,25 @@ void SCH_BUS_BUS_ENTRY::GetEndPoints( std::vector< DANGLING_END_ITEM >& aItemLis void SCH_BUS_ENTRY_BASE::Print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset ) { wxDC* DC = aSettings->GetPrintDC(); - COLOR4D color = ( GetStrokeColor() == COLOR4D::UNSPECIFIED ) ? - aSettings->GetLayerColor( m_layer ) : GetStrokeColor(); + COLOR4D color = ( GetBusEntryColor() == COLOR4D::UNSPECIFIED ) ? + aSettings->GetLayerColor( m_layer ) : GetBusEntryColor(); wxPoint start = m_pos + aOffset; wxPoint end = GetEnd() + aOffset; int penWidth = ( GetPenWidth() == 0 ) ? aSettings->GetDefaultPenWidth() : GetPenWidth(); - if( GetStrokeStyle() <= PLOT_DASH_TYPE::FIRST_TYPE ) + if( GetLineStyle() <= PLOT_DASH_TYPE::FIRST_TYPE ) { GRLine( nullptr, DC, start.x, start.y, end.x, end.y, penWidth, color ); } else { - EDA_RECT clip( (wxPoint) start, wxSize( end.x - start.x, end.y - start.y ) ); - clip.Normalize(); + SHAPE_SEGMENT segment( start, end ); - double theta = atan2( end.y - start.y, end.x - start.x ); - double strokes[] = { 1.0, dash_gap_len( penWidth ), 1.0, dash_gap_len( penWidth ) }; - - switch( GetStrokeStyle() ) - { - default: - case PLOT_DASH_TYPE::DASH: - strokes[0] = strokes[2] = dash_mark_len( penWidth ); - break; - case PLOT_DASH_TYPE::DOT: - strokes[0] = strokes[2] = dot_mark_len( penWidth ); - break; - case PLOT_DASH_TYPE::DASHDOT: - strokes[0] = dash_mark_len( penWidth ); - strokes[2] = dot_mark_len( penWidth ); - break; - } - - for( size_t i = 0; i < 10000; ++i ) - { - // Calculations MUST be done in doubles to keep from accumulating rounding - // errors as we go. - wxPoint next( start.x + strokes[ i % 4 ] * cos( theta ), - start.y + strokes[ i % 4 ] * sin( theta ) ); - - // Drawing each segment can be done rounded to ints. - wxPoint segStart( KiROUND( start.x ), KiROUND( start.y ) ); - wxPoint segEnd( KiROUND( next.x ), KiROUND( next.y ) ); - - if( ClipLine( &clip, segStart.x, segStart.y, segEnd.x, segEnd.y ) ) - break; - else if( i % 2 == 0 ) - GRLine( nullptr, DC, segStart.x, segStart.y, segEnd.x, segEnd.y, penWidth, color ); - - start = next; - } + STROKE_PARAMS::Stroke( &segment, GetLineStyle(), penWidth, aSettings, + [&]( const wxPoint& a, const wxPoint& b ) + { + GRLine( nullptr, DC, a.x, a.y, b.x, b.y, penWidth, color ); + } ); } } @@ -503,15 +472,15 @@ void SCH_BUS_ENTRY_BASE::Plot( PLOTTER* aPlotter ) const { auto* settings = static_cast<KIGFX::SCH_RENDER_SETTINGS*>( aPlotter->RenderSettings() ); - COLOR4D color = ( GetStrokeColor() == COLOR4D::UNSPECIFIED ) ? - settings->GetLayerColor( m_layer ) : GetStrokeColor(); + COLOR4D color = ( GetBusEntryColor() == COLOR4D::UNSPECIFIED ) ? + settings->GetLayerColor( m_layer ) : GetBusEntryColor(); int penWidth = ( GetPenWidth() == 0 ) ? settings->GetDefaultPenWidth() : GetPenWidth(); penWidth = std::max( penWidth, settings->GetMinPenWidth() ); aPlotter->SetCurrentLineWidth( penWidth ); aPlotter->SetColor( color ); - aPlotter->SetDash( GetStrokeStyle() ); + aPlotter->SetDash( GetLineStyle() ); aPlotter->MoveTo( m_pos ); aPlotter->FinishTo( GetEnd() ); } diff --git a/eeschema/sch_bus_entry.h b/eeschema/sch_bus_entry.h index 9f9fddf6f3..fb987daff1 100644 --- a/eeschema/sch_bus_entry.h +++ b/eeschema/sch_bus_entry.h @@ -22,11 +22,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -/** - * @file sch_bus_entry.h - * - */ - #ifndef _SCH_BUS_ENTRY_H_ #define _SCH_BUS_ENTRY_H_ @@ -81,11 +76,9 @@ public: virtual STROKE_PARAMS GetStroke() const override { return m_stroke; } virtual void SetStroke( const STROKE_PARAMS& aStroke ) override { m_stroke = aStroke; } - PLOT_DASH_TYPE GetStrokeStyle() const; - void SetStrokeStyle( PLOT_DASH_TYPE aStyle ) { m_stroke.SetPlotStyle( aStyle ); } + PLOT_DASH_TYPE GetLineStyle() const; - COLOR4D GetStrokeColor() const; - void SetStrokeColor( const COLOR4D& aColor ) { m_stroke.SetColor( aColor ); } + COLOR4D GetBusEntryColor() const; void SwapData( SCH_ITEM* aItem ) override; diff --git a/eeschema/sch_file_versions.h b/eeschema/sch_file_versions.h index e9b7e6a5ce..b6c3ca0049 100644 --- a/eeschema/sch_file_versions.h +++ b/eeschema/sch_file_versions.h @@ -66,4 +66,5 @@ //#define SEXPR_SCHEMATIC_FILE_VERSION 20210606 // Change overbar syntax from `~...~` to `~{...}`. //#define SEXPR_SCHEMATIC_FILE_VERSION 20210615 // Update overbar syntax in net names. //#define SEXPR_SCHEMATIC_FILE_VERSION 20210621 // Update overbar syntax in bus aliases. -#define SEXPR_SCHEMATIC_FILE_VERSION 20211123 // R/W uuids for junctions. +//#define SEXPR_SCHEMATIC_FILE_VERSION 20211123 // R/W uuids for junctions. +#define SEXPR_SCHEMATIC_FILE_VERSION 20220101 // Circles, arcs, rects, polys & beziers diff --git a/eeschema/sch_item.h b/eeschema/sch_item.h index e628e2d09c..22efeabe56 100644 --- a/eeschema/sch_item.h +++ b/eeschema/sch_item.h @@ -29,8 +29,7 @@ #include <unordered_set> #include <eda_item.h> -#include <plotters/plotter.h> // for PLOT_DASH_TYPE definition - +#include <plotters/plotter.h> #include <default_values.h> #include <sch_sheet_path.h> #include <netclass.h> @@ -134,44 +133,6 @@ private: typedef std::unordered_set<SCH_ITEM*> SCH_ITEM_SET; -/** - * Simple container to manage line stroke parameters. - */ -class STROKE_PARAMS -{ -public: - STROKE_PARAMS( int aWidth = Mils2iu( DEFAULT_LINE_WIDTH_MILS ), - PLOT_DASH_TYPE aPlotStyle = PLOT_DASH_TYPE::DEFAULT, - const COLOR4D& aColor = COLOR4D::UNSPECIFIED ) : - m_width( aWidth ), - m_plotstyle( aPlotStyle ), - m_color( aColor ) - { - } - - int GetWidth() const { return m_width; } - void SetWidth( int aWidth ) { m_width = aWidth; } - - PLOT_DASH_TYPE GetPlotStyle() const { return m_plotstyle; } - void SetPlotStyle( PLOT_DASH_TYPE aPlotStyle ) { m_plotstyle = aPlotStyle; } - - COLOR4D GetColor() const { return m_color; } - void SetColor( const COLOR4D& aColor ) { m_color = aColor; } - - bool operator!=( const STROKE_PARAMS& aOther ) - { - return m_width != aOther.m_width - || m_plotstyle != aOther.m_plotstyle - || m_color != aOther.m_color; - } - -private: - int m_width; - PLOT_DASH_TYPE m_plotstyle; - COLOR4D m_color; -}; - - /** * Base class for any item which can be embedded within the #SCHEMATIC container class, * and therefore instances of derived classes should only be found in EESCHEMA or other @@ -195,6 +156,24 @@ public: return wxT( "SCH_ITEM" ); } + bool IsType( const KICAD_T aScanTypes[] ) const override + { + if( EDA_ITEM::IsType( aScanTypes ) ) + return true; + + for( const KICAD_T* p = aScanTypes; *p != EOT; ++p ) + { + if( *p == SCH_ITEM_LOCATE_WIRE_T && m_layer == LAYER_WIRE ) + return true; + else if ( *p == SCH_ITEM_LOCATE_BUS_T && m_layer == LAYER_BUS ) + return true; + else if ( *p == SCH_ITEM_LOCATE_GRAPHIC_LINE_T && m_layer == LAYER_NOTES ) + return true; + } + + return false; + } + /** * Swap the internal data structures \a aItem with the schematic item. * Obviously, aItem must have the same type than me. diff --git a/eeschema/sch_line.cpp b/eeschema/sch_line.cpp index 64c77f4f4e..eff76343f6 100644 --- a/eeschema/sch_line.cpp +++ b/eeschema/sch_line.cpp @@ -26,6 +26,7 @@ #include <core/mirror.h> #include <sch_painter.h> #include <plotters/plotter.h> +#include <geometry/shape_segment.h> #include <sch_line.h> #include <sch_edit_frame.h> #include <settings/color_settings.h> @@ -37,6 +38,7 @@ #include <board_item.h> #include <advanced_config.h> + SCH_LINE::SCH_LINE( const wxPoint& pos, int layer ) : SCH_ITEM( nullptr, SCH_LINE_T ) { @@ -382,45 +384,13 @@ void SCH_LINE::Print( const RENDER_SETTINGS* aSettings, const wxPoint& offset ) } else { - EDA_RECT clip( (wxPoint) start, wxSize( end.x - start.x, end.y - start.y ) ); - clip.Normalize(); + SHAPE_SEGMENT segment( start, end ); - double theta = atan2( end.y - start.y, end.x - start.x ); - double strokes[] = { 1.0, dash_gap_len( penWidth ), 1.0, dash_gap_len( penWidth ) }; - - switch( lineStyle ) - { - default: - case PLOT_DASH_TYPE::DASH: - strokes[0] = strokes[2] = dash_mark_len( penWidth ); - break; - case PLOT_DASH_TYPE::DOT: - strokes[0] = strokes[2] = dot_mark_len( penWidth ); - break; - case PLOT_DASH_TYPE::DASHDOT: - strokes[0] = dash_mark_len( penWidth ); - strokes[2] = dot_mark_len( penWidth ); - break; - } - - for( size_t i = 0; i < 10000; ++i ) - { - // Calculations MUST be done in doubles to keep from accumulating rounding - // errors as we go. - wxPoint next( start.x + strokes[ i % 4 ] * cos( theta ), - start.y + strokes[ i % 4 ] * sin( theta ) ); - - // Drawing each segment can be done rounded to ints. - wxPoint segStart( KiROUND( start.x ), KiROUND( start.y ) ); - wxPoint segEnd( KiROUND( next.x ), KiROUND( next.y ) ); - - if( ClipLine( &clip, segStart.x, segStart.y, segEnd.x, segEnd.y ) ) - break; - else if( i % 2 == 0 ) - GRLine( nullptr, DC, segStart.x, segStart.y, segEnd.x, segEnd.y, penWidth, color ); - - start = next; - } + STROKE_PARAMS::Stroke( &segment, lineStyle, penWidth, aSettings, + [&]( const wxPoint& a, const wxPoint& b ) + { + GRLine( nullptr, DC, a.x, a.y, b.x, b.y, penWidth, color ); + } ); } } diff --git a/eeschema/sch_line.h b/eeschema/sch_line.h index c3a90e0172..ad7a27075d 100644 --- a/eeschema/sch_line.h +++ b/eeschema/sch_line.h @@ -59,24 +59,6 @@ public: return wxT( "SCH_LINE" ); } - bool IsType( const KICAD_T aScanTypes[] ) const override - { - if( SCH_ITEM::IsType( aScanTypes ) ) - return true; - - for( const KICAD_T* p = aScanTypes; *p != EOT; ++p ) - { - if( *p == SCH_LINE_LOCATE_WIRE_T && m_layer == LAYER_WIRE ) - return true; - else if ( *p == SCH_LINE_LOCATE_BUS_T && m_layer == LAYER_BUS ) - return true; - else if ( *p == SCH_LINE_LOCATE_GRAPHIC_LINE_T && m_layer == LAYER_NOTES ) - return true; - } - - return false; - } - bool IsEndPoint( const wxPoint& aPoint ) const { return aPoint == m_start || aPoint == m_end; @@ -276,11 +258,11 @@ public: private: bool doIsConnected( const wxPoint& aPosition ) const override; - bool m_startIsDangling; ///< True if start point is not connected. - bool m_endIsDangling; ///< True if end point is not connected. - wxPoint m_start; ///< Line start point - wxPoint m_end; ///< Line end point - STROKE_PARAMS m_stroke; ///< Line stroke properties. + bool m_startIsDangling; ///< True if start point is not connected. + bool m_endIsDangling; ///< True if end point is not connected. + wxPoint m_start; ///< Line start point + wxPoint m_end; ///< Line end point + STROKE_PARAMS m_stroke; ///< Line stroke properties. // If real-time connectivity gets disabled (due to being too slow on a particular // design), we can no longer rely on getting the NetClass to find netclass-specific diff --git a/eeschema/sch_painter.cpp b/eeschema/sch_painter.cpp index d1e4e53e1d..29675eb7a0 100644 --- a/eeschema/sch_painter.cpp +++ b/eeschema/sch_painter.cpp @@ -27,12 +27,12 @@ #include <sch_item.h> #include <trigo.h> -#include <bezier_curves.h> #include <symbol_library.h> #include <connection_graph.h> #include <gal/graphics_abstraction_layer.h> #include <geometry/geometry_utils.h> -#include <geometry/shape_line_chain.h> +#include <geometry/shape_segment.h> +#include <geometry/shape_simple.h> #include <gr_text.h> #include <lib_shape.h> #include <lib_field.h> @@ -60,7 +60,10 @@ #include <default_values.h> #include <advanced_config.h> #include <string_utils.h> +#include <stroke_params.h> #include "sch_painter.h" +#include "sch_shape.h" + namespace KIGFX { @@ -82,6 +85,8 @@ SCH_RENDER_SETTINGS::SCH_RENDER_SETTINGS() : m_JunctionSize( DEFAULT_JUNCTION_DIAM * IU_PER_MILS ) { SetDefaultPenWidth( DEFAULT_LINE_WIDTH_MILS * IU_PER_MILS ); + SetDashLengthRatio( 5 ); + SetGapLengthRatio( 3 ); m_minPenWidth = ADVANCED_CFG::GetCfg().m_MinPlotPenWidth * IU_PER_MM; } @@ -216,6 +221,7 @@ bool SCH_PAINTER::Draw( const VIEW_ITEM *aItem, int aLayer ) HANDLE_ITEM( SCH_SYMBOL_T, SCH_SYMBOL ); HANDLE_ITEM( SCH_JUNCTION_T, SCH_JUNCTION ); HANDLE_ITEM( SCH_LINE_T, SCH_LINE ); + HANDLE_ITEM( SCH_SHAPE_T, SCH_SHAPE ); HANDLE_ITEM( SCH_TEXT_T, SCH_TEXT ); HANDLE_ITEM( SCH_LABEL_T, SCH_TEXT ); HANDLE_ITEM( SCH_FIELD_T, SCH_FIELD ); @@ -280,7 +286,7 @@ COLOR4D SCH_PAINTER::getRenderColor( const EDA_ITEM* aItem, int aLayer, bool aDr } else if( aItem->Type() == SCH_BUS_WIRE_ENTRY_T ) { - COLOR4D busEntryColor = static_cast<const SCH_BUS_WIRE_ENTRY*>( aItem )->GetStrokeColor(); + COLOR4D busEntryColor = static_cast<const SCH_BUS_WIRE_ENTRY*>( aItem )->GetBusEntryColor(); if( busEntryColor != COLOR4D::UNSPECIFIED ) color = busEntryColor; @@ -496,11 +502,11 @@ bool SCH_PAINTER::setDeviceColors( const LIB_ITEM* aItem, int aLayer ) return false; case LAYER_DEVICE_BACKGROUND: - if( shape && shape->GetFillType() == FILL_T::FILLED_WITH_BG_BODYCOLOR ) + if( shape && shape->GetFillMode() == FILL_T::FILLED_WITH_BG_BODYCOLOR ) { COLOR4D fillColor = getRenderColor( aItem, LAYER_DEVICE_BACKGROUND, false ); - m_gal->SetIsFill( shape->GetFillType() == FILL_T::FILLED_WITH_BG_BODYCOLOR ); + m_gal->SetIsFill( shape->GetFillMode() == FILL_T::FILLED_WITH_BG_BODYCOLOR ); m_gal->SetFillColor( fillColor ); m_gal->SetIsStroke( false ); return true; @@ -509,7 +515,7 @@ bool SCH_PAINTER::setDeviceColors( const LIB_ITEM* aItem, int aLayer ) return false; case LAYER_DEVICE: - m_gal->SetIsFill( shape && shape->GetFillType() == FILL_T::FILLED_SHAPE ); + m_gal->SetIsFill( shape && shape->GetFillMode() == FILL_T::FILLED_SHAPE ); m_gal->SetFillColor( getRenderColor( aItem, LAYER_DEVICE, false ) ); if( aItem->GetPenWidth() >= 0 || !shape || !shape->IsFilled() ) @@ -597,7 +603,7 @@ void SCH_PAINTER::draw( const LIB_SHAPE *aShape, int aLayer ) break; default: - wxFAIL_MSG( "SCH_PAINTER::draw not implemented for " + aShape->SHAPE_T_asString() ); + UNIMPLEMENTED_FOR( aShape->SHAPE_T_asString() ); } } } @@ -640,21 +646,19 @@ void SCH_PAINTER::draw( const LIB_FIELD *aField, int aLayer ) return; } - m_gal->SetLineWidth( getTextThickness( aField, drawingShadows ) ); - m_gal->SetIsFill( false ); m_gal->SetIsStroke( true ); + m_gal->SetLineWidth( getTextThickness( aField, drawingShadows ) ); m_gal->SetStrokeColor( color ); + m_gal->SetIsFill( drawingShadows && eeconfig()->m_Selection.text_as_box ); + m_gal->SetFillColor( color ); EDA_RECT bbox = aField->GetBoundingBox(); wxPoint textpos = bbox.Centre(); if( drawingShadows && eeconfig()->m_Selection.text_as_box ) { - m_gal->SetIsFill( true ); - m_gal->SetFillColor( color ); - m_gal->SetLineWidth( m_gal->GetLineWidth() * 0.5 ); bbox.RevertYAxis(); - + m_gal->SetLineWidth( m_gal->GetLineWidth() / 2 ); m_gal->DrawRectangle( mapCoords( bbox.GetPosition() ), mapCoords( bbox.GetEnd() ) ); } else @@ -948,11 +952,11 @@ void SCH_PAINTER::draw( LIB_PIN *aPin, int aLayer ) LIB_SYMBOL* libEntry = aPin->GetParent(); // Draw the labels - if( drawingShadows - && ( libEntry->Type() == LIB_SYMBOL_T || libEntry->IsSelected() ) - && !eeconfig()->m_Selection.draw_selected_children ) + + if( libEntry->Type() == LIB_SYMBOL_T ) { - return; + if( drawingShadows && !eeconfig()->m_Selection.draw_selected_children ) + return; } float penWidth = (float) m_schSettings.GetDefaultPenWidth(); @@ -1278,47 +1282,120 @@ void SCH_PAINTER::draw( const SCH_LINE *aLine, int aLayer ) } else { - VECTOR2D start = aLine->GetStartPoint(); - VECTOR2D end = aLine->GetEndPoint(); + SHAPE_SEGMENT line( aLine->GetStartPoint(), aLine->GetEndPoint() ); - EDA_RECT clip( (wxPoint)start, wxSize( end.x - start.x, end.y - start.y ) ); - clip.Normalize(); + STROKE_PARAMS::Stroke( &line, lineStyle, width, &m_schSettings, + [&]( const wxPoint& a, const wxPoint& b ) + { + m_gal->DrawLine( a, b ); + } ); + } +} - double theta = atan2( end.y - start.y, end.x - start.x ); - double strokes[] = { 1.0, dash_gap_len( width ), 1.0, dash_gap_len( width ) }; - switch( lineStyle ) +void SCH_PAINTER::draw( const SCH_SHAPE* aShape, int aLayer ) +{ + bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS; + PLOT_DASH_TYPE lineStyle = aShape->GetEffectiveLineStyle(); + + if( drawingShadows && !aShape->IsSelected() ) + return; + + auto drawShape = + [&]( const SCH_SHAPE* shape ) + { + switch( shape->GetShape() ) + { + case SHAPE_T::ARC: + { + int startAngle; + int endAngle; + aShape->CalcArcAngles( startAngle, endAngle ); + + m_gal->DrawArc( aShape->GetCenter(), aShape->GetRadius(), + DECIDEG2RAD( startAngle ), DECIDEG2RAD( endAngle ) ); + } + break; + + case SHAPE_T::CIRCLE: + m_gal->DrawCircle( shape->GetPosition(), shape->GetRadius() ); + break; + + case SHAPE_T::RECT: + m_gal->DrawRectangle( shape->GetPosition(), shape->GetEnd() ); + break; + + case SHAPE_T::POLY: + { + std::deque<VECTOR2D> pts; + + for( const VECTOR2I& pt : shape->GetPolyShape().Outline( 0 ).CPoints() ) + pts.push_back( pt ); + + m_gal->DrawPolygon( pts ); + } + break; + + case SHAPE_T::BEZIER: + { + std::deque<VECTOR2D> pts; + + for( const VECTOR2I &p : shape->GetPolyShape().Outline( 0 ).CPoints() ) + pts.push_back( p ); + + m_gal->DrawPolygon( pts ); + } + break; + + default: + UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() ); + } + }; + + if( aLayer == LAYER_SELECTION_SHADOWS && eeconfig()->m_Selection.fill_shapes ) + { + m_gal->SetIsFill( true ); + m_gal->SetIsStroke( false ); + m_gal->SetFillColor( getRenderColor( aShape, aLayer, drawingShadows ) ); + + drawShape( aShape ); + } + else if( aLayer == LAYER_NOTES_BACKGROUND && aShape->IsFilled() ) + { + m_gal->SetIsFill( true ); + m_gal->SetIsStroke( false ); + m_gal->SetFillColor( aShape->GetFillColor() ); + + drawShape( aShape ); + } + else if( aLayer == LAYER_NOTES ) + { + int lineWidth = getLineWidth( aShape, drawingShadows ); + + m_gal->SetIsFill( false ); + m_gal->SetIsStroke( true ); + m_gal->SetLineWidth( lineWidth ); + m_gal->SetStrokeColor( getRenderColor( aShape, aLayer, drawingShadows ) ); + + if( lineStyle <= PLOT_DASH_TYPE::FIRST_TYPE || drawingShadows ) { - default: - case PLOT_DASH_TYPE::DASH: - strokes[0] = strokes[2] = dash_mark_len( width ); - break; - case PLOT_DASH_TYPE::DOT: - strokes[0] = strokes[2] = dot_mark_len( width ); - break; - case PLOT_DASH_TYPE::DASHDOT: - strokes[0] = dash_mark_len( width ); - strokes[2] = dot_mark_len( width ); - break; + drawShape( aShape ); } - - for( size_t i = 0; i < 10000; ++i ) + else { - // Calculations MUST be done in doubles to keep from accumulating rounding - // errors as we go. - VECTOR2D next( start.x + strokes[ i % 4 ] * cos( theta ), - start.y + strokes[ i % 4 ] * sin( theta ) ); + std::vector<SHAPE*> shapes = aShape->MakeEffectiveShapes( true ); - // Drawing each segment can be done rounded to ints. - wxPoint segStart( KiROUND( start.x ), KiROUND( start.y ) ); - wxPoint segEnd( KiROUND( next.x ), KiROUND( next.y ) ); + for( SHAPE* shape : shapes ) + { + STROKE_PARAMS::Stroke( shape, lineStyle, lineWidth, &m_schSettings, + [&]( const wxPoint& a, const wxPoint& b ) + { + m_gal->DrawLine( a, b ); + } ); + } - if( ClipLine( &clip, segStart.x, segStart.y, segEnd.x, segEnd.y ) ) - break; - else if( i % 2 == 0 ) - m_gal->DrawLine( segStart, segEnd ); - - start = next; + for( SHAPE* shape : shapes ) + delete shape; } } } @@ -1373,10 +1450,11 @@ void SCH_PAINTER::draw( const SCH_TEXT *aText, int aLayer ) return; } - m_gal->SetIsFill( false ); m_gal->SetIsStroke( true ); m_gal->SetLineWidth( getTextThickness( aText, drawingShadows ) ); m_gal->SetStrokeColor( color ); + m_gal->SetIsFill( drawingShadows && eeconfig()->m_Selection.text_as_box ); + m_gal->SetFillColor( color ); VECTOR2D text_offset = aText->GetTextPos() + aText->GetSchematicTextOffset( &m_schSettings ); wxString shownText( aText->GetShownText() ); @@ -1386,22 +1464,19 @@ void SCH_PAINTER::draw( const SCH_TEXT *aText, int aLayer ) if( eeconfig()->m_Selection.text_as_box ) { EDA_RECT bBox = aText->GetBoundingBox(); - - m_gal->SetIsFill( true ); - m_gal->SetFillColor( color ); - m_gal->SetLineWidth( m_gal->GetLineWidth() * 0.5 ); bBox.RevertYAxis(); - m_gal->DrawRectangle( mapCoords( bBox.GetPosition() ), mapCoords( bBox.GetEnd() ) ); return; } + float shadowWidth = getShadowWidth(); + switch( aText->GetLabelSpinStyle() ) { - case LABEL_SPIN_STYLE::LEFT: text_offset.x += getShadowWidth() / 2; break; - case LABEL_SPIN_STYLE::UP: text_offset.y += getShadowWidth() / 2; break; - case LABEL_SPIN_STYLE::RIGHT: text_offset.x -= getShadowWidth() / 2; break; - case LABEL_SPIN_STYLE::BOTTOM: text_offset.y -= getShadowWidth() / 2; break; + case LABEL_SPIN_STYLE::LEFT: text_offset.x += shadowWidth / 2.0; break; + case LABEL_SPIN_STYLE::UP: text_offset.y += shadowWidth / 2.0; break; + case LABEL_SPIN_STYLE::RIGHT: text_offset.x -= shadowWidth / 2.0; break; + case LABEL_SPIN_STYLE::BOTTOM: text_offset.y -= shadowWidth / 2.0; break; } } @@ -1538,11 +1613,8 @@ void SCH_PAINTER::draw( const SCH_FIELD *aField, int aLayer ) if( aField->IsVoid() ) return; - if( drawingShadows && aField->GetParent()->IsSelected() - && !eeconfig()->m_Selection.draw_selected_children ) - { + if( drawingShadows && !eeconfig()->m_Selection.draw_selected_children ) return; - } bool underline = false; @@ -1581,16 +1653,16 @@ void SCH_PAINTER::draw( const SCH_FIELD *aField, int aLayer ) EDA_RECT bbox = aField->GetBoundingBox(); wxPoint textpos = bbox.Centre(); - m_gal->SetStrokeColor( color ); m_gal->SetIsStroke( true ); + m_gal->SetLineWidth( getTextThickness( aField, drawingShadows ) ); + m_gal->SetStrokeColor( color ); + m_gal->SetIsFill( drawingShadows && eeconfig()->m_Selection.text_as_box ); + m_gal->SetFillColor( color ); if( drawingShadows && eeconfig()->m_Selection.text_as_box ) { - m_gal->SetIsFill( true ); - m_gal->SetFillColor( color ); - m_gal->SetLineWidth( m_gal->GetLineWidth() * 0.5 ); bbox.RevertYAxis(); - + m_gal->SetLineWidth( m_gal->GetLineWidth() / 2 ); m_gal->DrawRectangle( mapCoords( bbox.GetPosition() ), mapCoords( bbox.GetEnd() ) ); } else @@ -1603,7 +1675,6 @@ void SCH_PAINTER::draw( const SCH_FIELD *aField, int aLayer ) m_gal->SetFontItalic( aField->IsItalic() ); m_gal->SetFontUnderlined( underline ); m_gal->SetTextMirrored( aField->IsMirrored() ); - m_gal->SetLineWidth( getTextThickness( aField, drawingShadows ) ); strokeText( aField->GetShownText(), textpos, orient == TEXT_ANGLE_VERT ? M_PI / 2 : 0 ); } @@ -1624,38 +1695,36 @@ void SCH_PAINTER::draw( SCH_GLOBALLABEL *aLabel, int aLayer ) { bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS; - if( !drawingShadows || aLabel->IsSelected() ) - { - COLOR4D color = getRenderColor( aLabel, LAYER_GLOBLABEL, drawingShadows ); - - std::vector<wxPoint> pts; - std::deque<VECTOR2D> pts2; - - aLabel->CreateGraphicShape( &m_schSettings, pts, aLabel->GetTextPos() ); - - for( const wxPoint& p : pts ) - pts2.emplace_back( VECTOR2D( p.x, p.y ) ); - - // The text is drawn inside the graphic shape. - // On Cairo the graphic shape is filled by the background before drawing the text. - // However if the text is selected, it is draw twice: first on LAYER_SELECTION_SHADOWS - // and second on the text layer. The second must not erase the first drawing. - bool fillBg = ( ( aLayer == LAYER_SELECTION_SHADOWS ) || !aLabel->IsSelected() ) - && aLayer != LAYER_DANGLING; - m_gal->SetIsFill( fillBg ); - m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) ); - m_gal->SetIsStroke( true ); - m_gal->SetLineWidth( getTextThickness( aLabel, drawingShadows ) ); - m_gal->SetStrokeColor( color ); - m_gal->DrawPolyline( pts2 ); - - draw( static_cast<SCH_TEXT*>( aLabel ), aLayer ); - } - - if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children || !aLabel->IsSelected() ) - { + if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children ) draw( aLabel->GetIntersheetRefs(), aLayer ); - } + + if( drawingShadows && !( aLabel->IsBrightened() || aLabel->IsSelected() ) ) + return; + + COLOR4D color = getRenderColor( aLabel, LAYER_GLOBLABEL, drawingShadows ); + + std::vector<wxPoint> pts; + std::deque<VECTOR2D> pts2; + + aLabel->CreateGraphicShape( &m_schSettings, pts, aLabel->GetTextPos() ); + + for( const wxPoint& p : pts ) + pts2.emplace_back( VECTOR2D( p.x, p.y ) ); + + // The text is drawn inside the graphic shape. + // On Cairo the graphic shape is filled by the background before drawing the text. + // However if the text is selected, it is draw twice: first on LAYER_SELECTION_SHADOWS + // and second on the text layer. The second must not erase the first drawing. + bool fillBg = ( ( aLayer == LAYER_SELECTION_SHADOWS ) || !aLabel->IsSelected() ) + && aLayer != LAYER_DANGLING; + m_gal->SetIsFill( fillBg ); + m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) ); + m_gal->SetIsStroke( true ); + m_gal->SetLineWidth( getTextThickness( aLabel, drawingShadows ) ); + m_gal->SetStrokeColor( color ); + m_gal->DrawPolyline( pts2 ); + + draw( static_cast<SCH_TEXT*>( aLabel ), aLayer ); } @@ -1833,7 +1902,7 @@ void SCH_PAINTER::draw( const SCH_BUS_ENTRY_BASE *aEntry, int aLayer ) else { line.SetLineColor( color ); - line.SetLineStyle( aEntry->GetStrokeStyle() ); + line.SetLineStyle( aEntry->GetLineStyle() ); draw( &line, aLayer ); } diff --git a/eeschema/sch_painter.h b/eeschema/sch_painter.h index b6f850ea6d..630a2abe98 100644 --- a/eeschema/sch_painter.h +++ b/eeschema/sch_painter.h @@ -47,6 +47,7 @@ class SCH_HIERLABEL; class SCH_GLOBALLABEL; class SCH_SHEET; class SCH_SHEET_PIN; +class SCH_SHAPE; class SCH_MARKER; class SCH_NO_CONNECT; class SCH_LINE; @@ -156,6 +157,7 @@ private: void draw( SCH_SYMBOL* aSymbol, int aLayer ); void draw( const SCH_JUNCTION* aJct, int aLayer ); void draw( const SCH_FIELD* aField, int aLayer ); + void draw( const SCH_SHAPE* shape, int aLayer ); void draw( const SCH_TEXT* aText, int aLayer ); void draw( SCH_HIERLABEL* aLabel, int aLayer ); void draw( SCH_GLOBALLABEL* aLabel, int aLayer ); diff --git a/eeschema/sch_plugins/altium/sch_altium_plugin.cpp b/eeschema/sch_plugins/altium/sch_altium_plugin.cpp index 60af738418..6b8ea6133b 100644 --- a/eeschema/sch_plugins/altium/sch_altium_plugin.cpp +++ b/eeschema/sch_plugins/altium/sch_altium_plugin.cpp @@ -1059,7 +1059,7 @@ void SCH_ALTIUM_PLUGIN::ParseBezier( const std::map<wxString, wxString>& aProper symbol ) ); } - line->SetWidth( elem.lineWidth ); + line->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); } else if( i + 3 == elem.points.size() ) { @@ -1078,7 +1078,7 @@ void SCH_ALTIUM_PLUGIN::ParseBezier( const std::map<wxString, wxString>& aProper symbol ) ); } - line->SetWidth( elem.lineWidth ); + line->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); } else { @@ -1102,7 +1102,7 @@ void SCH_ALTIUM_PLUGIN::ParseBezier( const std::map<wxString, wxString>& aProper } } - bezier->SetWidth( elem.lineWidth ); + bezier->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); } } } @@ -1163,7 +1163,7 @@ void SCH_ALTIUM_PLUGIN::ParsePolyline( const std::map<wxString, wxString>& aProp for( wxPoint& point : elem.points ) line->AddPoint( GetRelativePosition( point + m_sheetOffset, symbol ) ); - line->SetWidth( elem.lineWidth ); + line->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); } } @@ -1224,7 +1224,7 @@ void SCH_ALTIUM_PLUGIN::ParsePolygon( const std::map<wxString, wxString>& aPrope line->AddPoint( GetRelativePosition( elem.points.front() + m_sheetOffset, symbol ) ); - line->SetWidth( elem.lineWidth ); + line->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); if( !elem.isSolid ) line->SetFillMode( FILL_T::NO_FILL ); @@ -1303,7 +1303,7 @@ void SCH_ALTIUM_PLUGIN::ParseRoundRectangle( const std::map<wxString, wxString>& rect->SetPosition( GetRelativePosition( elem.topRight + m_sheetOffset, symbol ) ); rect->SetEnd( GetRelativePosition( elem.bottomLeft + m_sheetOffset, symbol ) ); - rect->SetWidth( elem.lineWidth ); + rect->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); if( !elem.isSolid ) rect->SetFillMode( FILL_T::NO_FILL ); @@ -1351,7 +1351,7 @@ void SCH_ALTIUM_PLUGIN::ParseArc( const std::map<wxString, wxString>& aPropertie circle->SetPosition( GetRelativePosition( elem.center + m_sheetOffset, symbol ) ); circle->SetEnd( circle->GetPosition() + wxPoint( elem.radius, 0 ) ); - circle->SetWidth( elem.lineWidth ); + circle->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); } else { @@ -1371,7 +1371,7 @@ void SCH_ALTIUM_PLUGIN::ParseArc( const std::map<wxString, wxString>& aPropertie arcEnd += arc->GetCenter(); arc->SetEnd( arcEnd ); - arc->SetWidth( elem.lineWidth ); + arc->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); } } } @@ -1417,7 +1417,7 @@ void SCH_ALTIUM_PLUGIN::ParseLine( const std::map<wxString, wxString>& aProperti line->AddPoint( GetRelativePosition( elem.point1 + m_sheetOffset, symbol ) ); line->AddPoint( GetRelativePosition( elem.point2 + m_sheetOffset, symbol ) ); - line->SetWidth( elem.lineWidth ); + line->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); } } @@ -1487,7 +1487,7 @@ void SCH_ALTIUM_PLUGIN::ParseRectangle( const std::map<wxString, wxString>& aPro rect->SetPosition( GetRelativePosition( sheetTopRight, symbol ) ); rect->SetEnd( GetRelativePosition( sheetBottomLeft, symbol ) ); - rect->SetWidth( elem.lineWidth ); + rect->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); if( !elem.isSolid ) rect->SetFillMode( FILL_T::NO_FILL ); @@ -1606,7 +1606,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S { LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); aKsymbol->AddDrawItem( line1 ); - line1->SetWidth( Mils2iu( 10 ) ); + line1->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) ); line1->AddPoint( { 0, 0 } ); line1->AddPoint( { 0, Mils2iu( -50 ) } ); @@ -1614,7 +1614,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S { LIB_SHAPE* circle = new LIB_SHAPE( aKsymbol, SHAPE_T::CIRCLE ); aKsymbol->AddDrawItem( circle ); - circle->SetWidth( Mils2iu( 5 ) ); + circle->SetStroke( STROKE_PARAMS( Mils2iu( 5 ), PLOT_DASH_TYPE::SOLID ) ); circle->SetPosition( { Mils2iu( 0 ), Mils2iu( -75 ) } ); circle->SetEnd( circle->GetPosition() + wxPoint( Mils2iu( 25 ), 0 ) ); } @@ -1622,7 +1622,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S { LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); aKsymbol->AddDrawItem( line2 ); - line2->SetWidth( Mils2iu( 10 ) ); + line2->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) ); line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } ); line2->AddPoint( { Mils2iu( 25 ), Mils2iu( -50 ) } ); line2->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } ); @@ -1635,13 +1635,13 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S { LIB_SHAPE* line = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); aKsymbol->AddDrawItem( line ); - line->SetWidth( Mils2iu( 10 ) ); + line->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) ); line->AddPoint( { 0, 0 } ); line->AddPoint( { 0, Mils2iu( -72 ) } ); LIB_SHAPE* bezier = new LIB_SHAPE( aKsymbol, SHAPE_T::BEZIER ); aKsymbol->AddDrawItem( bezier ); - bezier->SetWidth( Mils2iu( 5 ) ); + bezier->SetStroke( STROKE_PARAMS( Mils2iu( 5 ), PLOT_DASH_TYPE::SOLID ) ); bezier->AddPoint( { Mils2iu( 30 ), Mils2iu( -50 ) } ); bezier->AddPoint( { Mils2iu( 30 ), Mils2iu( -87 ) } ); bezier->AddPoint( { Mils2iu( -30 ), Mils2iu( -63 ) } ); @@ -1656,7 +1656,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S { LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); aKsymbol->AddDrawItem( line1 ); - line1->SetWidth( Mils2iu( 10 ) ); + line1->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) ); line1->AddPoint( { 0, 0 } ); line1->AddPoint( { 0, Mils2iu( -100 ) } ); @@ -1664,25 +1664,25 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S { LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); aKsymbol->AddDrawItem( line2 ); - line2->SetWidth( Mils2iu( 10 ) ); + line2->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) ); line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } ); line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } ); LIB_SHAPE* line3 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); aKsymbol->AddDrawItem( line3 ); - line3->SetWidth( Mils2iu( 10 ) ); + line3->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) ); line3->AddPoint( { Mils2iu( -70 ), Mils2iu( -130 ) } ); line3->AddPoint( { Mils2iu( 70 ), Mils2iu( -130 ) } ); LIB_SHAPE* line4 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); aKsymbol->AddDrawItem( line4 ); - line4->SetWidth( Mils2iu( 10 ) ); + line4->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) ); line4->AddPoint( { Mils2iu( -40 ), Mils2iu( -160 ) } ); line4->AddPoint( { Mils2iu( 40 ), Mils2iu( -160 ) } ); LIB_SHAPE* line5 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); aKsymbol->AddDrawItem( line5 ); - line5->SetWidth( Mils2iu( 10 ) ); + line5->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) ); line5->AddPoint( { Mils2iu( -10 ), Mils2iu( -190 ) } ); line5->AddPoint( { Mils2iu( 10 ), Mils2iu( -190 ) } ); } @@ -1690,7 +1690,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S { LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); aKsymbol->AddDrawItem( line2 ); - line2->SetWidth( Mils2iu( 10 ) ); + line2->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) ); line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } ); line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } ); line2->AddPoint( { Mils2iu( 0 ), Mils2iu( -200 ) } ); @@ -1700,7 +1700,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S { LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); aKsymbol->AddDrawItem( line2 ); - line2->SetWidth( Mils2iu( 10 ) ); + line2->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) ); line2->AddPoint( { Mils2iu( -150 ), Mils2iu( -200 ) } ); line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } ); line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } ); @@ -1708,7 +1708,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S LIB_SHAPE* line3 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); aKsymbol->AddDrawItem( line3 ); - line3->SetWidth( Mils2iu( 10 ) ); + line3->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) ); line3->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } ); line3->AddPoint( { Mils2iu( -50 ), Mils2iu( -200 ) } ); } @@ -1716,7 +1716,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S { LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); aKsymbol->AddDrawItem( line2 ); - line2->SetWidth( Mils2iu( 10 ) ); + line2->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) ); line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } ); line2->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } ); line2->AddPoint( { Mils2iu( 25 ), Mils2iu( -50 ) } ); @@ -1731,25 +1731,25 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S { LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); aKsymbol->AddDrawItem( line1 ); - line1->SetWidth( Mils2iu( 10 ) ); + line1->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) ); line1->AddPoint( { 0, 0 } ); line1->AddPoint( { 0, Mils2iu( -160 ) } ); LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); aKsymbol->AddDrawItem( line2 ); - line2->SetWidth( Mils2iu( 10 ) ); + line2->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) ); line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -160 ) } ); line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -160 ) } ); LIB_SHAPE* line3 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); aKsymbol->AddDrawItem( line3 ); - line3->SetWidth( Mils2iu( 10 ) ); + line3->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) ); line3->AddPoint( { Mils2iu( -60 ), Mils2iu( -200 ) } ); line3->AddPoint( { Mils2iu( 60 ), Mils2iu( -200 ) } ); LIB_SHAPE* line4 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); aKsymbol->AddDrawItem( line4 ); - line4->SetWidth( Mils2iu( 10 ) ); + line4->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) ); line4->AddPoint( { Mils2iu( -20 ), Mils2iu( -240 ) } ); line4->AddPoint( { Mils2iu( 20 ), Mils2iu( -240 ) } ); @@ -1758,7 +1758,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S LIB_SHAPE* circle = new LIB_SHAPE( aKsymbol, SHAPE_T::CIRCLE ); aKsymbol->AddDrawItem( circle ); - circle->SetWidth( Mils2iu( 10 ) ); + circle->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) ); circle->SetPosition( { Mils2iu( 0 ), Mils2iu( -160 ) } ); circle->SetEnd( circle->GetPosition() + wxPoint( Mils2iu( 120 ), 0 ) ); @@ -1768,13 +1768,13 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S { LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); aKsymbol->AddDrawItem( line1 ); - line1->SetWidth( Mils2iu( 10 ) ); + line1->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) ); line1->AddPoint( { 0, 0 } ); line1->AddPoint( { 0, Mils2iu( -200 ) } ); LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); aKsymbol->AddDrawItem( line2 ); - line2->SetWidth( Mils2iu( 10 ) ); + line2->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) ); line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -200 ) } ); line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -200 ) } ); @@ -1790,13 +1790,13 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); aKsymbol->AddDrawItem( line1 ); - line1->SetWidth( Mils2iu( 10 ) ); + line1->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) ); line1->AddPoint( { 0, 0 } ); line1->AddPoint( { 0, Mils2iu( -100 ) } ); LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); aKsymbol->AddDrawItem( line2 ); - line2->SetWidth( Mils2iu( 10 ) ); + line2->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) ); line2->AddPoint( { Mils2iu( -50 ), Mils2iu( -100 ) } ); line2->AddPoint( { Mils2iu( 50 ), Mils2iu( -100 ) } ); diff --git a/eeschema/sch_plugins/cadstar/cadstar_sch_archive_loader.cpp b/eeschema/sch_plugins/cadstar/cadstar_sch_archive_loader.cpp index dc97f1ee1c..60b2e8601c 100644 --- a/eeschema/sch_plugins/cadstar/cadstar_sch_archive_loader.cpp +++ b/eeschema/sch_plugins/cadstar/cadstar_sch_archive_loader.cpp @@ -1682,7 +1682,7 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadLibrarySymbolShapeVertices( const std::vect } shape->SetUnit( aGateNumber ); - shape->SetWidth( aLineThickness ); + shape->SetStroke( STROKE_PARAMS( aLineThickness, PLOT_DASH_TYPE::SOLID ) ); aSymbol->AddDrawItem( shape ); prev = cur; diff --git a/eeschema/sch_plugins/eagle/sch_eagle_plugin.cpp b/eeschema/sch_plugins/eagle/sch_eagle_plugin.cpp index a964c2e22c..689ec8694e 100644 --- a/eeschema/sch_plugins/eagle/sch_eagle_plugin.cpp +++ b/eeschema/sch_plugins/eagle/sch_eagle_plugin.cpp @@ -33,11 +33,11 @@ #include <wx/tokenzr.h> #include <wx/wfstream.h> #include <wx/xml/xml.h> -#include <wx/msgdlg.h> #include <symbol_library.h> #include <plugins/eagle/eagle_parser.h> #include <string_utils.h> +#include <gr_text.h> #include <lib_shape.h> #include <lib_id.h> #include <lib_item.h> @@ -1755,7 +1755,7 @@ LIB_SHAPE* SCH_EAGLE_PLUGIN::loadSymbolCircle( std::unique_ptr<LIB_SYMBOL>& aSym circle->SetPosition( center ); circle->SetEnd( wxPoint( center.x + c.radius.ToSchUnits(), center.y ) ); - circle->SetWidth( c.width.ToSchUnits() ); + circle->SetStroke( STROKE_PARAMS( c.width.ToSchUnits(), PLOT_DASH_TYPE::SOLID ) ); circle->SetUnit( aGateNumber ); return circle; @@ -1823,12 +1823,12 @@ LIB_ITEM* SCH_EAGLE_PLUGIN::loadSymbolWire( std::unique_ptr<LIB_SYMBOL>& aSymbol + ( ( center.y - begin.y ) * ( center.y - begin.y ) ) ) ) * 2; - arc->SetWidth( 1 ); + arc->SetStroke( STROKE_PARAMS( 1, PLOT_DASH_TYPE::SOLID ) ); arc->SetFillMode( FILL_T::FILLED_SHAPE ); } else { - arc->SetWidth( ewire.width.ToSchUnits() ); + arc->SetStroke( STROKE_PARAMS( ewire.width.ToSchUnits(), PLOT_DASH_TYPE::SOLID ) ); } arc->SetArcGeometry( begin, (wxPoint) CalcArcMid( begin, end, center ), end ); @@ -1843,7 +1843,7 @@ LIB_ITEM* SCH_EAGLE_PLUGIN::loadSymbolWire( std::unique_ptr<LIB_SYMBOL>& aSymbol poly->AddPoint( begin ); poly->AddPoint( end ); poly->SetUnit( aGateNumber ); - poly->SetWidth( ewire.width.ToSchUnits() ); + poly->SetStroke( STROKE_PARAMS( ewire.width.ToSchUnits(), PLOT_DASH_TYPE::SOLID ) ); return poly; } diff --git a/eeschema/sch_plugins/kicad/sch_sexpr_parser.cpp b/eeschema/sch_plugins/kicad/sch_sexpr_parser.cpp index 9e15c57f74..52a139774e 100644 --- a/eeschema/sch_plugins/kicad/sch_sexpr_parser.cpp +++ b/eeschema/sch_plugins/kicad/sch_sexpr_parser.cpp @@ -52,7 +52,7 @@ #include <template_fieldnames.h> #include <trigo.h> #include <progress_reporter.h> - +#include <sch_shape.h> using namespace TSCHEMATIC_T; @@ -489,67 +489,11 @@ int SCH_SEXPR_PARSER::parseInternalUnits( const char* aExpected ) void SCH_SEXPR_PARSER::parseStroke( STROKE_PARAMS& aStroke ) { - wxCHECK_RET( CurTok() == T_stroke, - wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a stroke." ) ); + STROKE_PARAMS_PARSER strokeParser( reader, IU_PER_MM ); + strokeParser.SyncLineReaderWith( *this ); - aStroke.SetWidth( Mils2iu( DEFAULT_LINE_WIDTH_MILS ) ); - aStroke.SetPlotStyle( PLOT_DASH_TYPE::DEFAULT ); - aStroke.SetColor( COLOR4D::UNSPECIFIED ); - - T token; - - for( token = NextTok(); token != T_RIGHT; token = NextTok() ) - { - if( token != T_LEFT ) - Expecting( T_LEFT ); - - token = NextTok(); - - switch( token ) - { - case T_width: - aStroke.SetWidth( parseInternalUnits( "stroke width" ) ); - NeedRIGHT(); - break; - - case T_type: - { - token = NextTok(); - - switch( token ) - { - case T_dash: aStroke.SetPlotStyle( PLOT_DASH_TYPE::DASH ); break; - case T_dot: aStroke.SetPlotStyle( PLOT_DASH_TYPE::DOT ); break; - case T_dash_dot: aStroke.SetPlotStyle( PLOT_DASH_TYPE::DASHDOT ); break; - case T_solid: aStroke.SetPlotStyle( PLOT_DASH_TYPE::SOLID ); break; - case T_default: aStroke.SetPlotStyle( PLOT_DASH_TYPE::DEFAULT ); break; - default: - Expecting( "solid, dash, dash_dot, dot or default" ); - } - - NeedRIGHT(); - break; - } - - case T_color: - { - COLOR4D color; - - color.r = parseInt( "red" ) / 255.0; - color.g = parseInt( "green" ) / 255.0; - color.b = parseInt( "blue" ) / 255.0; - color.a = Clamp( parseDouble( "alpha" ), 0.0, 1.0 ); - - aStroke.SetColor( color ); - NeedRIGHT(); - break; - } - - default: - Expecting( "width, type, or color" ); - } - - } + strokeParser.ParseStroke( aStroke ); + SyncLineReaderWith( strokeParser ); } @@ -580,7 +524,8 @@ void SCH_SEXPR_PARSER::parseFill( FILL_PARAMS& aFill ) case T_none: aFill.m_FillType = FILL_T::NO_FILL; break; case T_outline: aFill.m_FillType = FILL_T::FILLED_SHAPE; break; case T_background: aFill.m_FillType = FILL_T::FILLED_WITH_BG_BODYCOLOR; break; - default: Expecting( "none, outline, or background" ); + case T_color: aFill.m_FillType = FILL_T::FILLED_WITH_COLOR; break; + default: Expecting( "none, outline, color or background" ); } NeedRIGHT(); @@ -1008,7 +953,7 @@ LIB_SHAPE* SCH_SEXPR_PARSER::parseArc() case T_stroke: parseStroke( stroke ); - arc->SetWidth( stroke.GetWidth() ); + arc->SetStroke( stroke ); break; case T_fill: @@ -1107,7 +1052,7 @@ LIB_SHAPE* SCH_SEXPR_PARSER::parseBezier() case T_stroke: parseStroke( stroke ); - bezier->SetWidth( stroke.GetWidth() ); + bezier->SetStroke( stroke ); break; case T_fill: @@ -1163,7 +1108,7 @@ LIB_SHAPE* SCH_SEXPR_PARSER::parseCircle() case T_stroke: parseStroke( stroke ); - circle->SetWidth( stroke.GetWidth() ); + circle->SetStroke( stroke ); break; case T_fill: @@ -1435,7 +1380,7 @@ LIB_SHAPE* SCH_SEXPR_PARSER::parsePolyLine() case T_stroke: parseStroke( stroke ); - poly->SetWidth( stroke.GetWidth() ); + poly->SetStroke( stroke ); break; case T_fill: @@ -1486,7 +1431,7 @@ LIB_SHAPE* SCH_SEXPR_PARSER::parseRectangle() case T_stroke: parseStroke( stroke ); - rectangle->SetWidth( stroke.GetWidth() ); + rectangle->SetStroke( stroke ); break; case T_fill: @@ -2170,6 +2115,22 @@ void SCH_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet, bool aIsCopyableOnly, screen->Append( static_cast<SCH_ITEM*>( parseLine() ) ); break; + case T_arc: + screen->Append( static_cast<SCH_ITEM*>( parseSchArc() ) ); + break; + + case T_circle: + screen->Append( static_cast<SCH_ITEM*>( parseSchCircle() ) ); + break; + + case T_rectangle: + screen->Append( static_cast<SCH_ITEM*>( parseSchRectangle() ) ); + break; + + case T_bezier: + screen->Append( static_cast<SCH_ITEM*>( parseSchBezier() ) ); + break; + case T_text: case T_label: case T_global_label: @@ -2837,6 +2798,320 @@ SCH_LINE* SCH_SEXPR_PARSER::parseLine() } +SCH_SHAPE* SCH_SEXPR_PARSER::parseSchArc() +{ + wxCHECK_MSG( CurTok() == T_arc, nullptr, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as an arc." ) ); + + T token; + wxPoint startPoint; + wxPoint midPoint; + wxPoint endPoint; + wxPoint pos; + int startAngle; + int endAngle; + STROKE_PARAMS stroke( Mils2iu( DEFAULT_LINE_WIDTH_MILS ), PLOT_DASH_TYPE::DEFAULT ); + FILL_PARAMS fill; + bool hasMidPoint = false; + bool hasAngles = false; + std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC ); + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_start: + startPoint = parseXY(); + NeedRIGHT(); + break; + + case T_mid: + midPoint = parseXY(); + NeedRIGHT(); + hasMidPoint = true; + break; + + case T_end: + endPoint = parseXY(); + NeedRIGHT(); + break; + + case T_radius: + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_at: + pos = parseXY(); + NeedRIGHT(); + break; + + case T_length: + parseInternalUnits( "radius length" ); + NeedRIGHT(); + break; + + case T_angles: + { + startAngle = KiROUND( parseDouble( "start radius angle" ) * 10.0 ); + endAngle = KiROUND( parseDouble( "end radius angle" ) * 10.0 ); + NORMALIZE_ANGLE_POS( startAngle ); + NORMALIZE_ANGLE_POS( endAngle ); + NeedRIGHT(); + hasAngles = true; + break; + } + + default: + Expecting( "at, length, or angle" ); + } + } + + break; + + case T_stroke: + parseStroke( stroke ); + arc->SetStroke( stroke ); + break; + + case T_fill: + parseFill( fill ); + arc->SetFillMode( fill.m_FillType ); + arc->SetFillColor( fill.m_Color ); + break; + + case T_uuid: + NeedSYMBOL(); + const_cast<KIID&>( arc->m_Uuid ) = KIID( FromUTF8() ); + NeedRIGHT(); + break; + + default: + Expecting( "start, mid, end, radius, stroke, fill or uuid" ); + } + } + + arc->SetStart( startPoint ); + arc->SetEnd( endPoint ); + + if( hasMidPoint ) + { + VECTOR2I center = CalcArcCenter( arc->GetStart(), midPoint, arc->GetEnd() ); + + arc->SetCenter( (wxPoint) center ); + } + else if( hasAngles ) + { + arc->SetCenter( pos ); + /** + * This accounts for an oddity in the old library format, where the symbol is overdefined. + * The previous draw (based on wxwidgets) used start point and end point and always drew + * counter-clockwise. The new GAL draw takes center, radius and start/end angles. All of + * these points were stored in the file, so we need to mimic the swapping of start/end + * points rather than using the stored angles in order to properly map edge cases. + */ + if( !TRANSFORM().MapAngles( &startAngle, &endAngle ) ) + { + wxPoint temp = arc->GetStart(); + arc->SetStart( arc->GetEnd() ); + arc->SetEnd( temp ); + } + } + else + wxFAIL_MSG( "Setting arc without either midpoint or angles not implemented." ); + + return arc.release(); +} + + +SCH_SHAPE* SCH_SEXPR_PARSER::parseSchCircle() +{ + wxCHECK_MSG( CurTok() == T_circle, nullptr, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a circle." ) ); + + T token; + wxPoint center; + int radius; + STROKE_PARAMS stroke( Mils2iu( DEFAULT_LINE_WIDTH_MILS ), PLOT_DASH_TYPE::DEFAULT ); + FILL_PARAMS fill; + std::unique_ptr<SCH_SHAPE> circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE ); + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_center: + center = parseXY(); + NeedRIGHT(); + break; + + case T_radius: + radius = parseInternalUnits( "radius length" ); + NeedRIGHT(); + break; + + case T_stroke: + parseStroke( stroke ); + circle->SetStroke( stroke ); + break; + + case T_fill: + parseFill( fill ); + circle->SetFillMode( fill.m_FillType ); + circle->SetFillColor( fill.m_Color ); + break; + + case T_uuid: + NeedSYMBOL(); + const_cast<KIID&>( circle->m_Uuid ) = KIID( FromUTF8() ); + NeedRIGHT(); + break; + + default: + Expecting( "center, radius, stroke, fill or uuid" ); + } + } + + circle->SetCenter( center ); + circle->SetEnd( wxPoint( center.x + radius, center.y ) ); + + return circle.release(); +} + + +SCH_SHAPE* SCH_SEXPR_PARSER::parseSchRectangle() +{ + wxCHECK_MSG( CurTok() == T_rectangle, nullptr, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a rectangle." ) ); + + T token; + STROKE_PARAMS stroke( Mils2iu( DEFAULT_LINE_WIDTH_MILS ), PLOT_DASH_TYPE::DEFAULT ); + FILL_PARAMS fill; + std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>( SHAPE_T::RECT ); + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_start: + rectangle->SetPosition( parseXY() ); + NeedRIGHT(); + break; + + case T_end: + rectangle->SetEnd( parseXY() ); + NeedRIGHT(); + break; + + case T_stroke: + parseStroke( stroke ); + rectangle->SetStroke( stroke ); + break; + + case T_fill: + parseFill( fill ); + rectangle->SetFillMode( fill.m_FillType ); + rectangle->SetFillColor( fill.m_Color ); + break; + + case T_uuid: + NeedSYMBOL(); + const_cast<KIID&>( rectangle->m_Uuid ) = KIID( FromUTF8() ); + NeedRIGHT(); + break; + + default: + Expecting( "start, end, stroke, fill or uuid" ); + } + } + + return rectangle.release(); +} + + +SCH_SHAPE* SCH_SEXPR_PARSER::parseSchBezier() +{ + wxCHECK_MSG( CurTok() == T_bezier, nullptr, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a bezier." ) ); + + T token; + STROKE_PARAMS stroke( Mils2iu( DEFAULT_LINE_WIDTH_MILS ), PLOT_DASH_TYPE::DEFAULT ); + FILL_PARAMS fill; + std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER ); + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_pts: + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + if( token != T_xy ) + Expecting( "xy" ); + + bezier->AddPoint( parseXY() ); + + NeedRIGHT(); + } + + break; + + case T_stroke: + parseStroke( stroke ); + bezier->SetStroke( stroke ); + break; + + case T_fill: + parseFill( fill ); + bezier->SetFillMode( fill.m_FillType ); + bezier->SetFillColor( fill.m_Color ); + break; + + case T_uuid: + NeedSYMBOL(); + const_cast<KIID&>( bezier->m_Uuid ) = KIID( FromUTF8() ); + NeedRIGHT(); + break; + + default: + Expecting( "pts, stroke, fill or uuid" ); + } + } + + return bezier.release(); +} + + SCH_TEXT* SCH_SEXPR_PARSER::parseSchText() { T token; diff --git a/eeschema/sch_plugins/kicad/sch_sexpr_parser.h b/eeschema/sch_plugins/kicad/sch_sexpr_parser.h index 0cd7239430..52f521f3c2 100644 --- a/eeschema/sch_plugins/kicad/sch_sexpr_parser.h +++ b/eeschema/sch_plugins/kicad/sch_sexpr_parser.h @@ -49,6 +49,7 @@ class SCH_BITMAP; class SCH_BUS_WIRE_ENTRY; class SCH_SYMBOL; class SCH_FIELD; +class SCH_SHAPE; class SCH_JUNCTION; class SCH_LINE; class SCH_NO_CONNECT; @@ -188,6 +189,10 @@ class SCH_SEXPR_PARSER : public SCHEMATIC_LEXER SCH_NO_CONNECT* parseNoConnect(); SCH_BUS_WIRE_ENTRY* parseBusEntry(); SCH_LINE* parseLine(); + SCH_SHAPE* parseSchArc(); + SCH_SHAPE* parseSchCircle(); + SCH_SHAPE* parseSchRectangle(); + SCH_SHAPE* parseSchBezier(); SCH_TEXT* parseSchText(); void parseBusAlias( SCH_SCREEN* aScreen ); diff --git a/eeschema/sch_plugins/kicad/sch_sexpr_plugin.cpp b/eeschema/sch_plugins/kicad/sch_sexpr_plugin.cpp index 7fecb12a93..cfa24bc9b3 100644 --- a/eeschema/sch_plugins/kicad/sch_sexpr_plugin.cpp +++ b/eeschema/sch_plugins/kicad/sch_sexpr_plugin.cpp @@ -37,6 +37,7 @@ #include <sch_edit_frame.h> // SYMBOL_ORIENTATION_T #include <sch_junction.h> #include <sch_line.h> +#include <sch_shape.h> #include <sch_no_connect.h> #include <sch_text.h> #include <sch_sheet.h> @@ -59,7 +60,6 @@ #include <wx_filename.h> // for ::ResolvePossibleSymlinks() #include <progress_reporter.h> - using namespace TSCHEMATIC_T; @@ -80,13 +80,26 @@ static void formatFill( OUTPUTFORMATTER* aFormatter, int aNestLevel, FILL_T aFil switch( aFillMode ) { - default: case FILL_T::NO_FILL: fillType = "none"; break; case FILL_T::FILLED_SHAPE: fillType = "outline"; break; case FILL_T::FILLED_WITH_BG_BODYCOLOR: fillType = "background"; break; + case FILL_T::FILLED_WITH_COLOR: fillType = "color"; break; } - aFormatter->Print( aNestLevel, "(fill (type %s))", fillType ); + if( aFillMode == FILL_T::FILLED_WITH_COLOR ) + { + aFormatter->Print( aNestLevel, "(fill (type %s) (color %d %d %d %s))", + fillType, + KiROUND( aFillColor.r * 255.0 ), + KiROUND( aFillColor.g * 255.0 ), + KiROUND( aFillColor.b * 255.0 ), + Double2Str( aFillColor.a ).c_str() ); + } + else + { + aFormatter->Print( aNestLevel, "(fill (type %s))", + fillType ); + } } @@ -222,23 +235,6 @@ static double getSheetPinAngle( SHEET_SIDE aSide ) } -static wxString getLineStyleToken( PLOT_DASH_TYPE aStyle ) -{ - wxString token; - - switch( aStyle ) - { - case PLOT_DASH_TYPE::DASH: token = "dash"; break; - case PLOT_DASH_TYPE::DOT: token = "dot"; break; - case PLOT_DASH_TYPE::DASHDOT: token = "dash_dot"; break; - case PLOT_DASH_TYPE::SOLID: token = "solid"; break; - case PLOT_DASH_TYPE::DEFAULT: token = "default"; break; - } - - return token; -} - - static const char* getTextTypeToken( KICAD_T aType ) { switch( aType ) @@ -252,28 +248,6 @@ static const char* getTextTypeToken( KICAD_T aType ) } -/** - * Write stroke definition to \a aFormatter. - * - * @param aFormatter A pointer to the #OUTPUTFORMATTER object to write to. - * @param aNestLevel The nest level to indent the stroke definition. - * @param aStroke The stroke width, line-style and color. - */ -static void formatStroke( OUTPUTFORMATTER* aFormatter, int aNestLevel, - const STROKE_PARAMS& aStroke ) -{ - wxASSERT( aFormatter != nullptr ); - - aFormatter->Print( aNestLevel, "(stroke (width %s) (type %s) (color %d %d %d %s))", - FormatInternalUnits( aStroke.GetWidth() ).c_str(), - TO_UTF8( getLineStyleToken( aStroke.GetPlotStyle() ) ), - KiROUND( aStroke.GetColor().r * 255.0 ), - KiROUND( aStroke.GetColor().g * 255.0 ), - KiROUND( aStroke.GetColor().b * 255.0 ), - Double2Str( aStroke.GetColor().a ).c_str() ); -} - - static void formatArc( OUTPUTFORMATTER* aFormatter, int aNestLevel, EDA_SHAPE* aArc, int x1, int x2, const STROKE_PARAMS& aStroke, FILL_T aFillMode, const COLOR4D& aFillColor, KIID aUuid = niluuid ) @@ -289,7 +263,7 @@ static void formatArc( OUTPUTFORMATTER* aFormatter, int aNestLevel, EDA_SHAPE* a FormatInternalUnits( aArc->GetArcMid() ).c_str(), FormatInternalUnits( aArc->GetEnd() ).c_str() ); - formatStroke( aFormatter, aNestLevel + 1, aStroke ); + aStroke.Format( aFormatter, aNestLevel + 1 ); aFormatter->Print( 0, "\n" ); formatFill( aFormatter, aNestLevel + 1, aFillMode, aFillColor ); aFormatter->Print( 0, "\n" ); @@ -310,7 +284,7 @@ static void formatCircle( OUTPUTFORMATTER* aFormatter, int aNestLevel, EDA_SHAPE FormatInternalUnits( aCircle->GetStart().y ).c_str(), FormatInternalUnits( aCircle->GetRadius() ).c_str() ); - formatStroke( aFormatter, aNestLevel + 1, aStroke ); + aStroke.Format( aFormatter, aNestLevel + 1 ); aFormatter->Print( 0, "\n" ); formatFill( aFormatter, aNestLevel + 1, aFillMode, aFillColor ); aFormatter->Print( 0, "\n" ); @@ -331,7 +305,7 @@ static void formatRect( OUTPUTFORMATTER* aFormatter, int aNestLevel, EDA_SHAPE* FormatInternalUnits( aRect->GetStart().y ).c_str(), FormatInternalUnits( aRect->GetEnd().x ).c_str(), FormatInternalUnits( aRect->GetEnd().y ).c_str() ); - formatStroke( aFormatter, aNestLevel + 1, aStroke ); + aStroke.Format( aFormatter, aNestLevel + 1 ); aFormatter->Print( 0, "\n" ); formatFill( aFormatter, aNestLevel + 1, aFillMode, aFillColor ); aFormatter->Print( 0, "\n" ); @@ -359,7 +333,7 @@ static void formatBezier( OUTPUTFORMATTER* aFormatter, int aNestLevel, EDA_SHAPE aFormatter->Print( 0, ")\n" ); // Closes pts token on same line. - formatStroke( aFormatter, aNestLevel + 1, aStroke ); + aStroke.Format( aFormatter, aNestLevel + 1 ); aFormatter->Print( 0, "\n" ); formatFill( aFormatter, aNestLevel + 1, aFillMode, aFillColor ); aFormatter->Print( 0, "\n" ); @@ -411,7 +385,7 @@ static void formatPoly( OUTPUTFORMATTER* aFormatter, int aNestLevel, EDA_SHAPE* aFormatter->Print( aNestLevel + 1, ")\n" ); // Closes pts token with multiple lines. } - formatStroke( aFormatter, aNestLevel + 1, aStroke ); + aStroke.Format( aFormatter, aNestLevel + 1 ); aFormatter->Print( 0, "\n" ); formatFill( aFormatter, aNestLevel + 1, aFillMode, aFillColor ); aFormatter->Print( 0, "\n" ); @@ -840,6 +814,10 @@ void SCH_SEXPR_PLUGIN::Format( SCH_SHEET* aSheet ) saveLine( static_cast<SCH_LINE*>( item ), 1 ); break; + case SCH_SHAPE_T: + saveShape( static_cast<SCH_SHAPE*>( item ), 1 ); + break; + case SCH_TEXT_T: case SCH_LABEL_T: case SCH_GLOBAL_LABEL_T: @@ -981,6 +959,10 @@ void SCH_SEXPR_PLUGIN::Format( EE_SELECTION* aSelection, SCH_SHEET_PATH* aSelect saveLine( static_cast< SCH_LINE* >( item ), 0 ); break; + case SCH_SHAPE_T: + saveShape( static_cast<SCH_SHAPE*>( item ), 0 ); + break; + case SCH_TEXT_T: case SCH_LABEL_T: case SCH_GLOBAL_LABEL_T: @@ -1252,7 +1234,7 @@ void SCH_SEXPR_PLUGIN::saveSheet( SCH_SHEET* aSheet, int aNestLevel ) aSheet->GetBorderColor() ); stroke.SetWidth( aSheet->GetBorderWidth() ); - formatStroke( m_out, aNestLevel + 1, stroke ); + stroke.Format( m_out, aNestLevel + 1 ); m_out->Print( 0, "\n" ); @@ -1341,7 +1323,7 @@ void SCH_SEXPR_PLUGIN::saveBusEntry( SCH_BUS_ENTRY_BASE* aBusEntry, int aNestLev FormatInternalUnits( aBusEntry->GetSize().GetWidth() ).c_str(), FormatInternalUnits( aBusEntry->GetSize().GetHeight() ).c_str() ); - formatStroke( m_out, aNestLevel + 1, aBusEntry->GetStroke() ); + aBusEntry->GetStroke().Format( m_out, aNestLevel + 1 ); m_out->Print( 0, "\n" ); @@ -1352,6 +1334,50 @@ void SCH_SEXPR_PLUGIN::saveBusEntry( SCH_BUS_ENTRY_BASE* aBusEntry, int aNestLev } +void SCH_SEXPR_PLUGIN::saveShape( SCH_SHAPE* aShape, int aNestLevel ) +{ + wxCHECK_RET( aShape != nullptr && m_out != nullptr, "" ); + + wxString lineType; + + switch( aShape->GetShape() ) + { + case SHAPE_T::ARC: + int x1; + int x2; + + aShape->CalcArcAngles( x1, x2 ); + + formatArc( m_out, aNestLevel, aShape, x1, x2, aShape->GetStroke(), aShape->GetFillMode(), + aShape->GetFillColor(), aShape->m_Uuid ); + break; + + case SHAPE_T::CIRCLE: + formatCircle( m_out, aNestLevel, aShape, aShape->GetStroke(), aShape->GetFillMode(), + aShape->GetFillColor(), aShape->m_Uuid ); + break; + + case SHAPE_T::RECT: + formatRect( m_out, aNestLevel, aShape, aShape->GetStroke(), aShape->GetFillMode(), + aShape->GetFillColor(), aShape->m_Uuid ); + break; + + case SHAPE_T::BEZIER: + formatBezier( m_out, aNestLevel, aShape, aShape->GetStroke(), aShape->GetFillMode(), + aShape->GetFillColor(), aShape->m_Uuid ); + break; + + case SHAPE_T::POLY: + formatPoly( m_out, aNestLevel, aShape, aShape->GetStroke(), aShape->GetFillMode(), + aShape->GetFillColor(), aShape->m_Uuid ); + break; + + default: + UNIMPLEMENTED_FOR( aShape->SHAPE_T_asString() ); + } +} + + void SCH_SEXPR_PLUGIN::saveLine( SCH_LINE* aLine, int aNestLevel ) { wxCHECK_RET( aLine != nullptr && m_out != nullptr, "" ); @@ -1364,8 +1390,9 @@ void SCH_SEXPR_PLUGIN::saveLine( SCH_LINE* aLine, int aNestLevel ) { case LAYER_BUS: lineType = "bus"; break; case LAYER_WIRE: lineType = "wire"; break; - case LAYER_NOTES: - default: lineType = "polyline"; break; + case LAYER_NOTES: lineType = "polyline"; break; + default: + UNIMPLEMENTED_FOR( LayerName( aLine->GetLayer() ) ); } m_out->Print( aNestLevel, "(%s (pts (xy %s %s) (xy %s %s))\n", @@ -1375,7 +1402,7 @@ void SCH_SEXPR_PLUGIN::saveLine( SCH_LINE* aLine, int aNestLevel ) FormatInternalUnits( aLine->GetEndPoint().x ).c_str(), FormatInternalUnits( aLine->GetEndPoint().y ).c_str() ); - formatStroke( m_out, aNestLevel + 1, line_stroke ); + line_stroke.Format( m_out, aNestLevel + 1 ); m_out->Print( 0, "\n" ); m_out->Print( aNestLevel + 1, "(uuid %s)\n", TO_UTF8( aLine->m_Uuid.AsString() ) ); @@ -1934,7 +1961,7 @@ void SCH_SEXPR_PLUGIN_CACHE::saveSymbolDrawItem( LIB_ITEM* aItem, OUTPUTFORMATTE { LIB_SHAPE* shape = static_cast<LIB_SHAPE*>( aItem ); STROKE_PARAMS stroke; - FILL_T fillMode = shape->GetFillType(); + FILL_T fillMode = shape->GetFillMode(); stroke.SetWidth( shape->GetWidth() ); diff --git a/eeschema/sch_plugins/kicad/sch_sexpr_plugin.h b/eeschema/sch_plugins/kicad/sch_sexpr_plugin.h index 3506d86724..8f61336012 100644 --- a/eeschema/sch_plugins/kicad/sch_sexpr_plugin.h +++ b/eeschema/sch_plugins/kicad/sch_sexpr_plugin.h @@ -39,6 +39,7 @@ class SCH_BITMAP; class SCH_JUNCTION; class SCH_NO_CONNECT; class SCH_LINE; +class SCH_SHAPE; class SCH_BUS_ENTRY_BASE; class SCH_TEXT; class SCH_SYMBOL; @@ -148,6 +149,7 @@ private: void saveNoConnect( SCH_NO_CONNECT* aNoConnect, int aNestLevel ); void saveBusEntry( SCH_BUS_ENTRY_BASE* aBusEntry, int aNestLevel ); void saveLine( SCH_LINE* aLine, int aNestLevel ); + void saveShape( SCH_SHAPE* aShape, int aNestLevel ); void saveText( SCH_TEXT* aText, int aNestLevel ); void saveBusAlias( std::shared_ptr<BUS_ALIAS> aAlias, int aNestLevel ); void saveInstances( const std::vector<SCH_SHEET_INSTANCE>& aSheets, diff --git a/eeschema/sch_plugins/legacy/sch_legacy_plugin.cpp b/eeschema/sch_plugins/legacy/sch_legacy_plugin.cpp index a7f72b6513..bd423cd306 100644 --- a/eeschema/sch_plugins/legacy/sch_legacy_plugin.cpp +++ b/eeschema/sch_plugins/legacy/sch_legacy_plugin.cpp @@ -41,6 +41,7 @@ #include <trigo.h> #include <progress_reporter.h> #include <general.h> +#include <gr_text.h> #include <sch_bitmap.h> #include <sch_bus_entry.h> #include <sch_symbol.h> @@ -3286,7 +3287,8 @@ LIB_SHAPE* SCH_LEGACY_PLUGIN_CACHE::loadArc( std::unique_ptr<LIB_SYMBOL>& aSymbo arc->SetUnit( parseInt( aReader, line, &line ) ); arc->SetConvert( parseInt( aReader, line, &line ) ); - arc->SetWidth( Mils2Iu( parseInt( aReader, line, &line ) ) ); + arc->SetStroke( STROKE_PARAMS( Mils2Iu( parseInt( aReader, line, &line ) ), + PLOT_DASH_TYPE::SOLID ) ); // Old libraries (version <= 2.2) do not have always this FILL MODE param // when fill mode is no fill (default mode). @@ -3359,7 +3361,8 @@ LIB_SHAPE* SCH_LEGACY_PLUGIN_CACHE::loadCircle( std::unique_ptr<LIB_SYMBOL>& aSy circle->SetEnd( wxPoint( center.x + radius, center.y ) ); circle->SetUnit( parseInt( aReader, line, &line ) ); circle->SetConvert( parseInt( aReader, line, &line ) ); - circle->SetWidth( Mils2Iu( parseInt( aReader, line, &line ) ) ); + circle->SetStroke( STROKE_PARAMS( Mils2Iu( parseInt( aReader, line, &line ) ), + PLOT_DASH_TYPE::SOLID ) ); if( *line != 0 ) circle->SetFillMode( parseFillMode( aReader, line, &line ) ); @@ -3488,7 +3491,8 @@ LIB_SHAPE* SCH_LEGACY_PLUGIN_CACHE::loadRect( std::unique_ptr<LIB_SYMBOL>& aSymb rectangle->SetUnit( parseInt( aReader, line, &line ) ); rectangle->SetConvert( parseInt( aReader, line, &line ) ); - rectangle->SetWidth( Mils2Iu( parseInt( aReader, line, &line ) ) ); + rectangle->SetStroke( STROKE_PARAMS( Mils2Iu( parseInt( aReader, line, &line ) ), + PLOT_DASH_TYPE::SOLID ) ); if( *line != 0 ) rectangle->SetFillMode( parseFillMode( aReader, line, &line ) ); @@ -3708,7 +3712,8 @@ LIB_SHAPE* SCH_LEGACY_PLUGIN_CACHE::loadPolyLine( std::unique_ptr<LIB_SYMBOL>& a int points = parseInt( aReader, line, &line ); polyLine->SetUnit( parseInt( aReader, line, &line ) ); polyLine->SetConvert( parseInt( aReader, line, &line ) ); - polyLine->SetWidth( Mils2Iu( parseInt( aReader, line, &line ) ) ); + polyLine->SetStroke( STROKE_PARAMS( Mils2Iu( parseInt( aReader, line, &line ) ), + PLOT_DASH_TYPE::SOLID ) ); wxPoint pt; @@ -3741,7 +3746,8 @@ LIB_SHAPE* SCH_LEGACY_PLUGIN_CACHE::loadBezier( std::unique_ptr<LIB_SYMBOL>& aSy bezier->SetUnit( parseInt( aReader, line, &line ) ); bezier->SetConvert( parseInt( aReader, line, &line ) ); - bezier->SetWidth( Mils2Iu( parseInt( aReader, line, &line ) ) ); + bezier->SetStroke( STROKE_PARAMS( Mils2Iu( parseInt( aReader, line, &line ) ), + PLOT_DASH_TYPE::SOLID ) ); bezier->SetStart( wxPoint( Mils2Iu( parseInt( aReader, line, &line ) ), Mils2Iu( parseInt( aReader, line, &line ) ) ) ); @@ -4002,7 +4008,7 @@ void SCH_LEGACY_PLUGIN_CACHE::saveArc( LIB_SHAPE* aArc, OUTPUTFORMATTER& aFormat aArc->GetUnit(), aArc->GetConvert(), Iu2Mils( aArc->GetWidth() ), - fill_tab[ static_cast<int>( aArc->GetFillType() ) - 1 ], + fill_tab[ static_cast<int>( aArc->GetFillMode() ) - 1 ], Iu2Mils( aArc->GetStart().x ), Iu2Mils( aArc->GetStart().y ), Iu2Mils( aArc->GetEnd().x ), @@ -4023,7 +4029,7 @@ void SCH_LEGACY_PLUGIN_CACHE::saveBezier( LIB_SHAPE* aBezier, OUTPUTFORMATTER& a for( const wxPoint& pt : aBezier->GetBezierPoints() ) aFormatter.Print( 0, " %d %d", Iu2Mils( pt.x ), Iu2Mils( pt.y ) ); - aFormatter.Print( 0, " %c\n", fill_tab[ static_cast<int>( aBezier->GetFillType() ) - 1 ] ); + aFormatter.Print( 0, " %c\n", fill_tab[ static_cast<int>( aBezier->GetFillMode() ) - 1 ] ); } @@ -4038,7 +4044,7 @@ void SCH_LEGACY_PLUGIN_CACHE::saveCircle( LIB_SHAPE* aCircle, OUTPUTFORMATTER& a aCircle->GetUnit(), aCircle->GetConvert(), Iu2Mils( aCircle->GetWidth() ), - fill_tab[ static_cast<int>( aCircle->GetFillType() ) - 1 ] ); + fill_tab[ static_cast<int>( aCircle->GetFillMode() ) - 1 ] ); } @@ -4168,7 +4174,7 @@ void SCH_LEGACY_PLUGIN_CACHE::savePolyLine( LIB_SHAPE* aPolyLine, OUTPUTFORMATTE for( const VECTOR2I& pt : aPolyLine->GetPolyShape().Outline( 0 ).CPoints() ) aFormatter.Print( 0, " %d %d", Iu2Mils( pt.x ), Iu2Mils( pt.y ) ); - aFormatter.Print( 0, " %c\n", fill_tab[ static_cast<int>( aPolyLine->GetFillType() ) - 1 ] ); + aFormatter.Print( 0, " %c\n", fill_tab[ static_cast<int>( aPolyLine->GetFillMode() ) - 1 ] ); } @@ -4184,7 +4190,7 @@ void SCH_LEGACY_PLUGIN_CACHE::saveRectangle( LIB_SHAPE* aRectangle, OUTPUTFORMAT aRectangle->GetUnit(), aRectangle->GetConvert(), Iu2Mils( aRectangle->GetWidth() ), - fill_tab[ static_cast<int>( aRectangle->GetFillType() ) - 1 ] ); + fill_tab[ static_cast<int>( aRectangle->GetFillMode() ) - 1 ] ); } diff --git a/eeschema/sch_shape.cpp b/eeschema/sch_shape.cpp new file mode 100644 index 0000000000..2a7cfd6c0d --- /dev/null +++ b/eeschema/sch_shape.cpp @@ -0,0 +1,422 @@ +/* + * 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) 2004-2021 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <sch_draw_panel.h> +#include <macros.h> +#include <plotters/plotter.h> +#include <base_units.h> +#include <widgets/msgpanel.h> +#include <bitmaps.h> +#include <eda_draw_frame.h> +#include <general.h> +#include <sch_shape.h> + + +SCH_SHAPE::SCH_SHAPE( SHAPE_T aShape, int aLineWidth, FILL_T aFillType ) : + SCH_ITEM( nullptr, SCH_SHAPE_T ), + EDA_SHAPE( aShape, aLineWidth, aFillType, true ) +{ + SetLayer( LAYER_NOTES ); +} + + +EDA_ITEM* SCH_SHAPE::Clone() const +{ + return new SCH_SHAPE( *this ); +} + + +void SCH_SHAPE::SetStroke( const STROKE_PARAMS& aStroke ) +{ + m_stroke = aStroke; +} + + +void SCH_SHAPE::Move( const wxPoint& aOffset ) +{ + move( aOffset ); +} + + +void SCH_SHAPE::MirrorHorizontally( int aCenter ) +{ + flip( wxPoint( aCenter, 0 ), true ); +} + + +void SCH_SHAPE::MirrorVertically( int aCenter ) +{ + flip( wxPoint( 0, aCenter ), false ); +} + + +void SCH_SHAPE::Rotate( const wxPoint& aCenter ) +{ + rotate( aCenter, 900 ); +} + + +void SCH_SHAPE::Plot( PLOTTER* aPlotter ) const +{ + int pen_size = std::max( GetPenWidth(), aPlotter->RenderSettings()->GetMinPenWidth() ); + wxPoint center; + int radius; + int startAngle; + int endAngle; + + static std::vector<wxPoint> cornerList; + + if( GetShape() == SHAPE_T::POLY ) + { + cornerList.clear(); + + for( const VECTOR2I& pt : m_poly.Outline( 0 ).CPoints() ) + cornerList.push_back( (wxPoint) pt ); + } + else if( GetShape() == SHAPE_T::ARC ) + { + center = getCenter(); + radius = GetRadius(); + CalcArcAngles( startAngle, endAngle ); + } + + if( GetStroke().GetColor() == COLOR4D::UNSPECIFIED ) + aPlotter->SetColor( aPlotter->RenderSettings()->GetLayerColor( LAYER_NOTES ) ); + else + aPlotter->SetColor( GetStroke().GetColor() ); + + aPlotter->SetCurrentLineWidth( pen_size ); + aPlotter->SetDash( GetStroke().GetPlotStyle() ); + + switch( GetShape() ) + { + case SHAPE_T::ARC: + // TODO: doesn't work for dash styles + aPlotter->Arc( center, -endAngle, -startAngle, radius, FILL_T::NO_FILL, pen_size ); + break; + + case SHAPE_T::CIRCLE: + // TODO: doesn't work for dash styles + aPlotter->Circle( GetStart(), GetRadius() * 2, FILL_T::NO_FILL, pen_size ); + break; + + case SHAPE_T::RECT: + { + std::vector<wxPoint> pts = GetRectCorners(); + + aPlotter->MoveTo( pts[0] ); + aPlotter->LineTo( pts[1] ); + aPlotter->LineTo( pts[2] ); + aPlotter->LineTo( pts[3] ); + aPlotter->FinishTo( pts[0] ); + } + break; + + case SHAPE_T::POLY: + { + aPlotter->MoveTo( cornerList[0] ); + + for( size_t ii = 1; ii < cornerList.size(); ++ii ) + aPlotter->LineTo( cornerList[ii] ); + + aPlotter->FinishTo( cornerList[0] ); + } + break; + + case SHAPE_T::BEZIER: + // TODO: doesn't work for dash styles + aPlotter->PlotPoly( m_bezierPoints, FILL_T::NO_FILL, pen_size ); + break; + + default: + UNIMPLEMENTED_FOR( SHAPE_T_asString() ); + } + + aPlotter->SetDash( PLOT_DASH_TYPE::SOLID ); + + if( m_fill == FILL_T::FILLED_WITH_COLOR && GetFillColor() != COLOR4D::UNSPECIFIED ) + { + aPlotter->SetColor( GetFillColor() ); + + switch( GetShape() ) + { + case SHAPE_T::ARC: + aPlotter->Arc( center, -endAngle, -startAngle, radius, m_fill, 0 ); + break; + + case SHAPE_T::CIRCLE: + aPlotter->Circle( GetStart(), GetRadius() * 2, m_fill, 0 ); + break; + + case SHAPE_T::RECT: + aPlotter->Rect( GetStart(), GetEnd(), m_fill, 0 ); + break; + + case SHAPE_T::POLY: + aPlotter->PlotPoly( cornerList, m_fill, 0 ); + break; + + case SHAPE_T::BEZIER: + aPlotter->PlotPoly( m_bezierPoints, m_fill, 0 ); + break; + + default: + UNIMPLEMENTED_FOR( SHAPE_T_asString() ); + } + } +} + + +int SCH_SHAPE::GetPenWidth() const +{ + // Historically 0 meant "default width" and negative numbers meant "don't stroke". + if( GetWidth() < 0 && GetFillMode() != FILL_T::NO_FILL ) + return 0; + else + return std::max( GetWidth(), 1 ); +} + + +void SCH_SHAPE::Print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset ) +{ + int penWidth = GetPenWidth(); + wxDC* DC = aSettings->GetPrintDC(); + wxPoint pt1 = GetStart(); + wxPoint pt2 = GetEnd(); + wxPoint c; + COLOR4D color; + + penWidth = std::max( penWidth, aSettings->GetDefaultPenWidth() ); + + unsigned ptCount = 0; + wxPoint* buffer = nullptr; + + if( GetShape() == SHAPE_T::POLY ) + { + SHAPE_LINE_CHAIN poly = m_poly.Outline( 0 ); + + ptCount = poly.GetPointCount(); + buffer = new wxPoint[ ptCount ]; + + for( unsigned ii = 0; ii < ptCount; ++ii ) + buffer[ii] = (wxPoint) poly.CPoint( ii ); + } + else if( GetShape() == SHAPE_T::BEZIER ) + { + ptCount = m_bezierPoints.size(); + buffer = new wxPoint[ ptCount ]; + + for( size_t ii = 0; ii < ptCount; ++ii ) + buffer[ii] = m_bezierPoints[ii]; + } + else if( GetShape() == SHAPE_T::ARC ) + { + c = getCenter(); + int t1, t2; + + CalcArcAngles( t1, t2 ); + + if( NormalizeAngle180( t1 - t2 ) > 0 ) + std::swap( pt1, pt2 ); + } + + if( GetFillMode() == FILL_T::FILLED_WITH_COLOR ) + { + color = GetFillColor(); + + switch( GetShape() ) + { + case SHAPE_T::ARC: + GRFilledArc1( nullptr, DC, pt1, pt2, c, 0, color, color ); + break; + + case SHAPE_T::CIRCLE: + GRFilledCircle( nullptr, DC, pt1.x, pt1.y, GetRadius(), 0, color, color ); + break; + + case SHAPE_T::RECT: + GRFilledRect( nullptr, DC, pt1.x, pt1.y, pt2.x, pt2.y, 0, color, color ); + break; + + case SHAPE_T::POLY: + GRPoly( nullptr, DC, ptCount, buffer, true, 0, color, color ); + break; + + case SHAPE_T::BEZIER: + GRPoly( nullptr, DC, ptCount, buffer, true, 0, color, color ); + break; + + default: + UNIMPLEMENTED_FOR( SHAPE_T_asString() ); + } + } + + if( GetStroke().GetColor() == COLOR4D::UNSPECIFIED ) + color = aSettings->GetLayerColor( LAYER_NOTES ); + else + color = GetStroke().GetColor(); + + if( GetStroke().GetPlotStyle() <= PLOT_DASH_TYPE::FIRST_TYPE ) + { + switch( GetShape() ) + { + case SHAPE_T::ARC: + GRArc1( nullptr, DC, pt1, pt2, c, penWidth, color ); + break; + + case SHAPE_T::CIRCLE: + GRCircle( nullptr, DC, pt1.x, pt1.y, GetRadius(), penWidth, color ); + break; + + case SHAPE_T::RECT: + GRRect( nullptr, DC, pt1.x, pt1.y, pt2.x, pt2.y, penWidth, color ); + break; + + case SHAPE_T::POLY: + GRPoly( nullptr, DC, ptCount, buffer, false, penWidth, color, color ); + break; + + case SHAPE_T::BEZIER: + GRPoly( nullptr, DC, ptCount, buffer, false, penWidth, color, color ); + break; + + default: + UNIMPLEMENTED_FOR( SHAPE_T_asString() ); + } + } + else + { + std::vector<SHAPE*> shapes = MakeEffectiveShapes( true ); + + for( SHAPE* shape : shapes ) + { + STROKE_PARAMS::Stroke( shape, GetStroke().GetPlotStyle(), penWidth, aSettings, + [&]( const wxPoint& a, const wxPoint& b ) + { + GRLine( nullptr, DC, a.x, a.y, b.x, b.y, penWidth, color ); + } ); + } + + for( SHAPE* shape : shapes ) + delete shape; + } + + delete[] buffer; +} + + +void SCH_SHAPE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) +{ + SCH_ITEM::GetMsgPanelInfo( aFrame, aList ); + + ShapeGetMsgPanelInfo( aFrame, aList ); +} + + +wxString SCH_SHAPE::GetSelectMenuText( EDA_UNITS aUnits ) const +{ + switch( GetShape() ) + { + case SHAPE_T::ARC: + return wxString::Format( _( "Arc, radius %s" ), + MessageTextFromValue( aUnits, GetRadius() ) ); + + case SHAPE_T::CIRCLE: + return wxString::Format( _( "Circle, radius %s" ), + MessageTextFromValue( aUnits, GetRadius() ) ); + + case SHAPE_T::RECT: + return wxString::Format( _( "Rectangle, width %s height %s" ), + MessageTextFromValue( aUnits, std::abs( m_start.x - m_end.x ) ), + MessageTextFromValue( aUnits, std::abs( m_start.y - m_end.y ) ) ); + + case SHAPE_T::POLY: + return wxString::Format( _( "Polyline, %d points" ), + int( m_poly.Outline( 0 ).GetPointCount() ) ); + + case SHAPE_T::BEZIER: + return wxString::Format( _( "Bezier Curve, %d points" ), + int( m_bezierPoints.size() ) ); + + default: + UNIMPLEMENTED_FOR( SHAPE_T_asString() ); + return wxEmptyString; + } +} + + +BITMAPS SCH_SHAPE::GetMenuImage() const +{ + switch( GetShape() ) + { + case SHAPE_T::SEGMENT: return BITMAPS::add_line; + case SHAPE_T::ARC: return BITMAPS::add_arc; + case SHAPE_T::CIRCLE: return BITMAPS::add_circle; + case SHAPE_T::RECT: return BITMAPS::add_rectangle; + case SHAPE_T::POLY: return BITMAPS::add_graphical_segments; + + default: + UNIMPLEMENTED_FOR( SHAPE_T_asString() ); + return BITMAPS::question_mark; + } +} + + +void SCH_SHAPE::ViewGetLayers( int aLayers[], int& aCount ) const +{ + aCount = 3; + aLayers[0] = LAYER_NOTES; + aLayers[1] = LAYER_NOTES_BACKGROUND; + aLayers[2] = LAYER_SELECTION_SHADOWS; +} + + +void SCH_SHAPE::AddPoint( const wxPoint& aPosition ) +{ + if( GetShape() == SHAPE_T::POLY ) + { + if( m_poly.IsEmpty() ) + m_poly.NewOutline(); + + m_poly.Outline( 0 ).Append( aPosition, true ); + } + else + { + UNIMPLEMENTED_FOR( SHAPE_T_asString() ); + } +} + + +void SCH_SHAPE::CalcArcAngles( int& aStartAngle, int& aEndAngle ) const +{ + double start; + double end; + + EDA_SHAPE::CalcArcAngles( start, end ); + + aStartAngle = KiROUND( start * 10.0 ); + aEndAngle = KiROUND( end * 10.0 ); +} + + diff --git a/eeschema/sch_shape.h b/eeschema/sch_shape.h new file mode 100644 index 0000000000..222ad2a61d --- /dev/null +++ b/eeschema/sch_shape.h @@ -0,0 +1,119 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com + * Copyright (C) 2004-2021 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef SCH_SHAPE_H +#define SCH_SHAPE_H + +#include <sch_item.h> +#include <eda_shape.h> + + +class SCH_SHAPE : public SCH_ITEM, public EDA_SHAPE +{ +public: + SCH_SHAPE( SHAPE_T aShape, int aLineWidth = 0, FILL_T aFillType = FILL_T::NO_FILL ); + + // Do not create a copy constructor. The one generated by the compiler is adequate. + + ~SCH_SHAPE() { } + + wxString GetClass() const override + { + return wxT( "SCH_SHAPE" ); + } + + bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override + { + return hitTest( aPosition, aAccuracy ); + } + + bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override + { + return hitTest( aRect, aContained, aAccuracy ); + } + + int GetPenWidth() const override; + + bool HasLineStroke() const override { return true; } + STROKE_PARAMS GetStroke() const override { return m_stroke; } + void SetStroke( const STROKE_PARAMS& aStroke ) override; + + PLOT_DASH_TYPE GetEffectiveLineStyle() const + { + if( IsFilled() ) + return PLOT_DASH_TYPE::SOLID; + else if( m_stroke.GetPlotStyle() == PLOT_DASH_TYPE::DEFAULT ) + return PLOT_DASH_TYPE::DASH; + else + return m_stroke.GetPlotStyle(); + } + + const EDA_RECT GetBoundingBox() const override { return getBoundingBox(); } + + wxPoint GetPosition() const override { return getPosition(); } + void SetPosition( const wxPoint& aPos ) override { setPosition( aPos ); } + + wxPoint GetCenter() const { return getCenter(); } + + void CalcArcAngles( int& aStartAngle, int& aEndAngle ) const; + + void BeginEdit( const wxPoint& aStartPoint ) { beginEdit( aStartPoint ); } + bool ContinueEdit( const wxPoint& aPosition ) { return continueEdit( aPosition ); } + void CalcEdit( const wxPoint& aPosition ) { calcEdit( aPosition ); } + void EndEdit() { endEdit(); } + void SetEditState( int aState ) { setEditState( aState ); } + + void Move( const wxPoint& aOffset ) override; + + void MirrorHorizontally( int aCenter ) override; + void MirrorVertically( int aCenter ) override; + void Rotate( const wxPoint& aCenter ) override; + + void AddPoint( const wxPoint& aPosition ); + + void Plot( PLOTTER* aPlotter ) const override; + + void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override; + + wxString GetSelectMenuText( EDA_UNITS aUnits ) const override; + + BITMAPS GetMenuImage() const override; + + EDA_ITEM* Clone() const override; + + void ViewGetLayers( int aLayers[], int& aCount ) const override; + +#if defined(DEBUG) + void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); } +#endif + +private: + void Print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset ) override; + + double getParentOrientation() const override { return 0.0; } + wxPoint getParentPosition() const override { return wxPoint(); } +}; + + +#endif // SCH_SHAPE_H diff --git a/eeschema/sch_symbol.cpp b/eeschema/sch_symbol.cpp index 480f1814b7..7591639ef5 100644 --- a/eeschema/sch_symbol.cpp +++ b/eeschema/sch_symbol.cpp @@ -95,10 +95,10 @@ static LIB_SYMBOL* dummy() } -SCH_SYMBOL::SCH_SYMBOL( const wxPoint& aPos, SCH_ITEM* aParent ) : - SCH_ITEM( aParent, SCH_SYMBOL_T ) +SCH_SYMBOL::SCH_SYMBOL() : + SCH_ITEM( nullptr, SCH_SYMBOL_T ) { - Init( aPos ); + Init( wxPoint( 0, 0 ) ); } diff --git a/eeschema/sch_symbol.h b/eeschema/sch_symbol.h index eb6baa8b25..4afb65aac0 100644 --- a/eeschema/sch_symbol.h +++ b/eeschema/sch_symbol.h @@ -78,7 +78,7 @@ extern std::string toUTFTildaText( const wxString& txt ); class SCH_SYMBOL : public SCH_ITEM { public: - SCH_SYMBOL( const wxPoint& pos = wxPoint( 0, 0 ), SCH_ITEM* aParent = nullptr ); + SCH_SYMBOL(); /** * Create schematic symbol from library symbol object. diff --git a/eeschema/sch_text.cpp b/eeschema/sch_text.cpp index 32980bb436..aa2f5ff1a1 100644 --- a/eeschema/sch_text.cpp +++ b/eeschema/sch_text.cpp @@ -853,8 +853,8 @@ EDA_ITEM* SCH_LABEL::Clone() const bool SCH_LABEL::IsType( const KICAD_T aScanTypes[] ) const { - static KICAD_T wireTypes[] = { SCH_LINE_LOCATE_WIRE_T, SCH_PIN_T, EOT }; - static KICAD_T busTypes[] = { SCH_LINE_LOCATE_BUS_T, EOT }; + static KICAD_T wireTypes[] = { SCH_ITEM_LOCATE_WIRE_T, SCH_PIN_T, EOT }; + static KICAD_T busTypes[] = { SCH_ITEM_LOCATE_BUS_T, EOT }; if( SCH_ITEM::IsType( aScanTypes ) ) return true; diff --git a/eeschema/sch_view.h b/eeschema/sch_view.h index e9a22f27d0..b39aea6ee7 100644 --- a/eeschema/sch_view.h +++ b/eeschema/sch_view.h @@ -56,6 +56,7 @@ static const LAYER_NUM SCH_LAYER_ORDER[] = LAYER_SELECTION_SHADOWS, LAYER_DEVICE_BACKGROUND, LAYER_SHEET_BACKGROUND, + LAYER_NOTES_BACKGROUND, LAYER_DRAWINGSHEET }; diff --git a/eeschema/schematic.keywords b/eeschema/schematic.keywords index 1f0053df5f..fceef87873 100644 --- a/eeschema/schematic.keywords +++ b/eeschema/schematic.keywords @@ -21,13 +21,10 @@ color comment company convert -dash -dash_dot data date default diameter -dot edge_clock_high effects end @@ -108,7 +105,6 @@ shape sheet sheet_instances size -solid start stroke symbol diff --git a/eeschema/symbol_editor/menubar_symbol_editor.cpp b/eeschema/symbol_editor/menubar_symbol_editor.cpp index d3ab6cdcf8..4228b39a32 100644 --- a/eeschema/symbol_editor/menubar_symbol_editor.cpp +++ b/eeschema/symbol_editor/menubar_symbol_editor.cpp @@ -139,9 +139,9 @@ void SYMBOL_EDIT_FRAME::ReCreateMenuBar() placeMenu->Add( EE_ACTIONS::placeSymbolPin ); placeMenu->Add( EE_ACTIONS::placeSymbolText ); - placeMenu->Add( EE_ACTIONS::drawSymbolRectangle ); - placeMenu->Add( EE_ACTIONS::drawSymbolCircle ); - placeMenu->Add( EE_ACTIONS::drawSymbolArc ); + placeMenu->Add( EE_ACTIONS::drawRectangle ); + placeMenu->Add( EE_ACTIONS::drawCircle ); + placeMenu->Add( EE_ACTIONS::drawArc ); placeMenu->Add( EE_ACTIONS::drawSymbolLines ); diff --git a/eeschema/symbol_editor/symbol_edit_frame.cpp b/eeschema/symbol_editor/symbol_edit_frame.cpp index e4364d7752..7a9ec65cc1 100644 --- a/eeschema/symbol_editor/symbol_edit_frame.cpp +++ b/eeschema/symbol_editor/symbol_edit_frame.cpp @@ -490,9 +490,9 @@ void SYMBOL_EDIT_FRAME::setupUIConditions() mgr->SetConditions( ACTIONS::deleteTool, EDIT_TOOL( ACTIONS::deleteTool ) ); mgr->SetConditions( EE_ACTIONS::placeSymbolPin, EDIT_TOOL( EE_ACTIONS::placeSymbolPin ) ); mgr->SetConditions( EE_ACTIONS::placeSymbolText, EDIT_TOOL( EE_ACTIONS::placeSymbolText ) ); - mgr->SetConditions( EE_ACTIONS::drawSymbolRectangle, EDIT_TOOL( EE_ACTIONS::drawSymbolRectangle ) ); - mgr->SetConditions( EE_ACTIONS::drawSymbolCircle, EDIT_TOOL( EE_ACTIONS::drawSymbolCircle ) ); - mgr->SetConditions( EE_ACTIONS::drawSymbolArc, EDIT_TOOL( EE_ACTIONS::drawSymbolArc ) ); + mgr->SetConditions( EE_ACTIONS::drawRectangle, EDIT_TOOL( EE_ACTIONS::drawRectangle ) ); + mgr->SetConditions( EE_ACTIONS::drawCircle, EDIT_TOOL( EE_ACTIONS::drawCircle ) ); + mgr->SetConditions( EE_ACTIONS::drawArc, EDIT_TOOL( EE_ACTIONS::drawArc ) ); mgr->SetConditions( EE_ACTIONS::drawSymbolLines, EDIT_TOOL( EE_ACTIONS::drawSymbolLines ) ); mgr->SetConditions( EE_ACTIONS::placeSymbolAnchor, EDIT_TOOL( EE_ACTIONS::placeSymbolAnchor ) ); diff --git a/eeschema/symbol_editor/toolbars_symbol_editor.cpp b/eeschema/symbol_editor/toolbars_symbol_editor.cpp index f734318402..bf2c8297c0 100644 --- a/eeschema/symbol_editor/toolbars_symbol_editor.cpp +++ b/eeschema/symbol_editor/toolbars_symbol_editor.cpp @@ -59,9 +59,9 @@ void SYMBOL_EDIT_FRAME::ReCreateVToolbar() m_drawToolBar->AddScaledSeparator( this ); m_drawToolBar->Add( EE_ACTIONS::placeSymbolPin, ACTION_TOOLBAR::TOGGLE ); m_drawToolBar->Add( EE_ACTIONS::placeSymbolText, ACTION_TOOLBAR::TOGGLE ); - m_drawToolBar->Add( EE_ACTIONS::drawSymbolRectangle, ACTION_TOOLBAR::TOGGLE ); - m_drawToolBar->Add( EE_ACTIONS::drawSymbolCircle, ACTION_TOOLBAR::TOGGLE ); - m_drawToolBar->Add( EE_ACTIONS::drawSymbolArc, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( EE_ACTIONS::drawRectangle, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( EE_ACTIONS::drawCircle, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( EE_ACTIONS::drawArc, ACTION_TOOLBAR::TOGGLE ); m_drawToolBar->Add( EE_ACTIONS::drawSymbolLines, ACTION_TOOLBAR::TOGGLE ); m_drawToolBar->Add( EE_ACTIONS::placeSymbolAnchor, ACTION_TOOLBAR::TOGGLE ); m_drawToolBar->Add( ACTIONS::deleteTool, ACTION_TOOLBAR::TOGGLE ); diff --git a/eeschema/tools/ee_actions.cpp b/eeschema/tools/ee_actions.cpp index 218e6b917e..33b9748d86 100644 --- a/eeschema/tools/ee_actions.cpp +++ b/eeschema/tools/ee_actions.cpp @@ -225,21 +225,6 @@ TOOL_ACTION EE_ACTIONS::placeSymbolText( "eeschema.SymbolDrawing.placeSymbolText _( "Add Text" ), _( "Add a text item" ), BITMAPS::text, AF_ACTIVATE, (void*) LIB_TEXT_T ); -TOOL_ACTION EE_ACTIONS::drawSymbolRectangle( "eeschema.SymbolDrawing.drawSymbolRectangle", - AS_GLOBAL, 0, "", - _( "Add Rectangle" ), _( "Add a rectangle" ), - BITMAPS::add_rectangle, AF_ACTIVATE, (void*) SHAPE_T::RECT ); - -TOOL_ACTION EE_ACTIONS::drawSymbolCircle( "eeschema.SymbolDrawing.drawSymbolCircle", - AS_GLOBAL, 0, "", - _( "Add Circle" ), _( "Add a circle" ), - BITMAPS::add_circle, AF_ACTIVATE, (void*) SHAPE_T::CIRCLE ); - -TOOL_ACTION EE_ACTIONS::drawSymbolArc( "eeschema.SymbolDrawing.drawSymbolArc", - AS_GLOBAL, 0, "", - _( "Add Arc" ), _( "Add an arc" ), - BITMAPS::add_arc, AF_ACTIVATE, (void*) SHAPE_T::ARC ); - TOOL_ACTION EE_ACTIONS::drawSymbolLines( "eeschema.SymbolDrawing.drawSymbolLines", AS_GLOBAL, 0, "", _( "Add Lines" ), _( "Add connected graphic lines" ), @@ -345,6 +330,21 @@ TOOL_ACTION EE_ACTIONS::placeSchematicText( "eeschema.InteractiveDrawing.placeSc _( "Add Text" ), _( "Add text" ), BITMAPS::text, AF_ACTIVATE ); +TOOL_ACTION EE_ACTIONS::drawRectangle( "eeschema.InteractiveDrawing.drawRectangle", + AS_GLOBAL, 0, "", + _( "Add Rectangle" ), _( "Add a rectangle" ), + BITMAPS::add_rectangle, AF_ACTIVATE, (void*) SHAPE_T::RECT ); + +TOOL_ACTION EE_ACTIONS::drawCircle( "eeschema.InteractiveDrawing.drawCircle", + AS_GLOBAL, 0, "", + _( "Add Circle" ), _( "Add a circle" ), + BITMAPS::add_circle, AF_ACTIVATE, (void*) SHAPE_T::CIRCLE ); + +TOOL_ACTION EE_ACTIONS::drawArc( "eeschema.InteractiveDrawing.drawArc", + AS_GLOBAL, 0, "", + _( "Add Arc" ), _( "Add an arc" ), + BITMAPS::add_arc, AF_ACTIVATE, (void*) SHAPE_T::ARC ); + TOOL_ACTION EE_ACTIONS::placeImage( "eeschema.InteractiveDrawing.placeImage", AS_GLOBAL, 0, "", _( "Add Image" ), _( "Add bitmap image" ), diff --git a/eeschema/tools/ee_actions.h b/eeschema/tools/ee_actions.h index d75067a2ab..5cb29d12fc 100644 --- a/eeschema/tools/ee_actions.h +++ b/eeschema/tools/ee_actions.h @@ -88,6 +88,9 @@ public: static TOOL_ACTION drawSheet; static TOOL_ACTION importSheetPin; static TOOL_ACTION placeSchematicText; + static TOOL_ACTION drawRectangle; + static TOOL_ACTION drawCircle; + static TOOL_ACTION drawArc; static TOOL_ACTION drawLines; static TOOL_ACTION placeImage; static TOOL_ACTION finishLineWireOrBus; @@ -99,9 +102,6 @@ public: // Symbol Tools static TOOL_ACTION placeSymbolPin; static TOOL_ACTION placeSymbolText; - static TOOL_ACTION drawSymbolRectangle; - static TOOL_ACTION drawSymbolCircle; - static TOOL_ACTION drawSymbolArc; static TOOL_ACTION drawSymbolLines; static TOOL_ACTION placeSymbolAnchor; static TOOL_ACTION finishDrawing; diff --git a/eeschema/tools/ee_point_editor.cpp b/eeschema/tools/ee_point_editor.cpp index f10defdd1e..46b0b1b76f 100644 --- a/eeschema/tools/ee_point_editor.cpp +++ b/eeschema/tools/ee_point_editor.cpp @@ -37,6 +37,7 @@ using namespace std::placeholders; #include <sch_line.h> #include <sch_bitmap.h> #include <sch_sheet.h> +#include <sch_shape.h> #include <sch_sheet_pin.h> #include <symbol_edit_frame.h> #include <lib_shape.h> @@ -123,8 +124,59 @@ public: break; default: - wxFAIL_MSG( "EDIT_POINTS_FACTORY::Make not implemented for " - + shape->SHAPE_T_asString() ); + UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() ); + } + } + break; + + case SCH_SHAPE_T: + { + SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem ); + + switch( shape->GetShape() ) + { + case SHAPE_T::ARC: + points->AddPoint( shape->GetPosition() ); + points->AddPoint( shape->GetStart() ); + points->AddPoint( shape->GetEnd() ); + break; + + case SHAPE_T::CIRCLE: + points->AddPoint( shape->GetPosition() ); + points->AddPoint( shape->GetEnd() ); + break; + + case SHAPE_T::RECT: + { + // point editor works only with rectangles having width and height > 0 + // Some symbols can have rectangles with width or height < 0 + // So normalize the size: + BOX2I dummy; + dummy.SetOrigin( shape->GetPosition() ); + dummy.SetEnd( shape->GetEnd() ); + dummy.Normalize(); + VECTOR2I topLeft = dummy.GetPosition(); + VECTOR2I botRight = dummy.GetEnd(); + + points->AddPoint( topLeft ); + points->AddPoint( VECTOR2I( botRight.x, topLeft.y ) ); + points->AddPoint( VECTOR2I( topLeft.x, botRight.y ) ); + points->AddPoint( botRight ); + } + break; + + case SHAPE_T::POLY: + for( const VECTOR2I& pt : shape->GetPolyShape().Outline( 0 ).CPoints() ) + points->AddPoint( pt ); + + break; + + case SHAPE_T::BEZIER: + // TODO + break; + + default: + UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() ); } } break; @@ -275,8 +327,9 @@ int EE_POINT_EDITOR::Main( const TOOL_EVENT& aEvent ) { static KICAD_T supportedTypes[] = { LIB_SHAPE_T, + SCH_SHAPE_T, SCH_SHEET_T, - SCH_LINE_LOCATE_GRAPHIC_LINE_T, + SCH_ITEM_LOCATE_GRAPHIC_LINE_T, SCH_BITMAP_T, EOT }; @@ -540,8 +593,71 @@ void EE_POINT_EDITOR::updateParentItem() const break; default: - wxFAIL_MSG( "EE_POINT_EDITOR::updateParentItem not implemented for " - + shape->SHAPE_T_asString() ); + UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() ); + } + } + break; + + case SCH_SHAPE_T: + { + SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( item ); + + switch( shape->GetShape() ) + { + case SHAPE_T::ARC: + if( getEditedPointIndex() == ARC_CENTER ) + { + shape->SetEditState( 4 ); + shape->CalcEdit( (wxPoint) m_editPoints->Point( ARC_CENTER ).GetPosition() ); + } + else if( getEditedPointIndex() == ARC_START ) + { + shape->SetEditState( 2 ); + shape->CalcEdit( (wxPoint) m_editPoints->Point( ARC_START ).GetPosition() ); + } + else if( getEditedPointIndex() == ARC_END ) + { + shape->SetEditState( 3 ); + shape->CalcEdit( (wxPoint) m_editPoints->Point( ARC_END ).GetPosition() ); + } + break; + + case SHAPE_T::CIRCLE: + shape->SetPosition( (wxPoint) m_editPoints->Point( CIRC_CENTER ).GetPosition() ); + shape->SetEnd( (wxPoint) m_editPoints->Point( CIRC_END ).GetPosition() ); + break; + + case SHAPE_T::POLY: + shape->GetPolyShape().RemoveAllContours(); + shape->GetPolyShape().NewOutline(); + + for( unsigned i = 0; i < m_editPoints->PointsSize(); ++i ) + shape->GetPolyShape().Append( m_editPoints->Point( i ).GetPosition() ); + + break; + + case SHAPE_T::RECT: + { + EE_GRID_HELPER gridHelper( m_toolMgr ); + VECTOR2I topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition(); + VECTOR2I topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition(); + VECTOR2I botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition(); + VECTOR2I botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition(); + + pinEditedCorner( getEditedPointIndex(), Mils2iu( 1 ), Mils2iu( 1 ), + topLeft, topRight, botLeft, botRight, &gridHelper ); + + shape->SetPosition( (wxPoint) topLeft ); + shape->SetEnd( (wxPoint) botRight ); + } + break; + + case SHAPE_T::BEZIER: + // TODO + break; + + default: + UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() ); } } break; @@ -732,8 +848,73 @@ void EE_POINT_EDITOR::updatePoints() break; default: - wxFAIL_MSG( "EE_POINT_EDITOR::updatePoints not implemented for " - + shape->SHAPE_T_asString() ); + UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() ); + } + } + break; + + case SCH_SHAPE_T: + { + SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( item ); + + switch( shape->GetShape() ) + { + case SHAPE_T::ARC: + m_editPoints->Point( ARC_CENTER ).SetPosition( shape->GetPosition() ); + m_editPoints->Point( ARC_START ).SetPosition( shape->GetStart() ); + m_editPoints->Point( ARC_END ).SetPosition( shape->GetEnd() ); + break; + + case SHAPE_T::CIRCLE: + m_editPoints->Point( CIRC_CENTER ).SetPosition( shape->GetPosition() ); + m_editPoints->Point( CIRC_END ).SetPosition( shape->GetEnd() ); + break; + + case SHAPE_T::POLY: + { + if( (int) m_editPoints->PointsSize() != shape->GetPointCount() ) + { + getView()->Remove( m_editPoints.get() ); + m_editedPoint = nullptr; + m_editPoints = EDIT_POINTS_FACTORY::Make( item, m_frame ); + getView()->Add( m_editPoints.get() ); + } + else + { + int ii = 0; + + for( const VECTOR2I& pt : shape->GetPolyShape().Outline( 0 ).CPoints() ) + m_editPoints->Point( ii++ ).SetPosition( pt ); + } + + break; + } + + case SHAPE_T::RECT: + { + // point editor works only with rectangles having width and height > 0 + // Some symbols can have rectangles with width or height < 0 + // So normalize the size: + BOX2I dummy; + dummy.SetOrigin( shape->GetPosition() ); + dummy.SetEnd( shape->GetEnd() ); + dummy.Normalize(); + VECTOR2I topLeft = dummy.GetPosition(); + VECTOR2I botRight = dummy.GetEnd(); + + m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft ); + m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( VECTOR2I( botRight.x, topLeft.y ) ); + m_editPoints->Point( RECT_BOTLEFT ).SetPosition( VECTOR2I( topLeft.x, botRight.y ) ); + m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight ); + } + break; + + case SHAPE_T::BEZIER: + // TODO + break; + + default: + UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() ); } } break; diff --git a/eeschema/tools/ee_selection_tool.cpp b/eeschema/tools/ee_selection_tool.cpp index 8138252c7d..8431457acd 100644 --- a/eeschema/tools/ee_selection_tool.cpp +++ b/eeschema/tools/ee_selection_tool.cpp @@ -150,13 +150,13 @@ bool EE_SELECTION_TOOL::Init() m_isSymbolViewer = symbolViewerFrame != nullptr; } - static KICAD_T wireOrBusTypes[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT }; - static KICAD_T connectedTypes[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, + static KICAD_T wireOrBusTypes[] = { SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T, EOT }; + static KICAD_T connectedTypes[] = { SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T, SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T, SCH_LABEL_T, SCH_SHEET_PIN_T, SCH_PIN_T, EOT }; - auto wireSelection = E_C::MoreThan( 0 ) && E_C::OnlyType( SCH_LINE_LOCATE_WIRE_T ); - auto busSelection = E_C::MoreThan( 0 ) && E_C::OnlyType( SCH_LINE_LOCATE_BUS_T ); + auto wireSelection = E_C::MoreThan( 0 ) && E_C::OnlyType( SCH_ITEM_LOCATE_WIRE_T ); + auto busSelection = E_C::MoreThan( 0 ) && E_C::OnlyType( SCH_ITEM_LOCATE_BUS_T ); auto wireOrBusSelection = E_C::MoreThan( 0 ) && E_C::OnlyTypes( wireOrBusTypes ); auto connectedSelection = E_C::MoreThan( 0 ) && E_C::OnlyTypes( connectedTypes ); auto sheetSelection = E_C::Count( 1 ) && E_C::OnlyType( SCH_SHEET_T ); @@ -293,6 +293,7 @@ const KICAD_T movableSchematicItems[] = SCH_BUS_WIRE_ENTRY_T, SCH_LINE_T, SCH_BITMAP_T, + SCH_SHAPE_T, SCH_TEXT_T, SCH_LABEL_T, SCH_GLOBAL_LABEL_T, @@ -307,7 +308,7 @@ const KICAD_T movableSchematicItems[] = const KICAD_T movableSymbolItems[] = { - LIB_SHAPE_T, + LIB_SHAPE_T, LIB_TEXT_T, LIB_PIN_T, LIB_FIELD_T, @@ -1334,18 +1335,18 @@ bool EE_SELECTION_TOOL::selectMultiple() static KICAD_T nodeTypes[] = { - SCH_SYMBOL_LOCATE_POWER_T, - SCH_PIN_T, - SCH_LINE_LOCATE_WIRE_T, - SCH_LINE_LOCATE_BUS_T, - SCH_BUS_WIRE_ENTRY_T, - SCH_BUS_BUS_ENTRY_T, - SCH_LABEL_T, - SCH_HIER_LABEL_T, - SCH_GLOBAL_LABEL_T, - SCH_SHEET_PIN_T, - SCH_JUNCTION_T, - EOT + SCH_SYMBOL_LOCATE_POWER_T, + SCH_PIN_T, + SCH_ITEM_LOCATE_WIRE_T, + SCH_ITEM_LOCATE_BUS_T, + SCH_BUS_WIRE_ENTRY_T, + SCH_BUS_BUS_ENTRY_T, + SCH_LABEL_T, + SCH_HIER_LABEL_T, + SCH_GLOBAL_LABEL_T, + SCH_SHEET_PIN_T, + SCH_JUNCTION_T, + EOT }; @@ -1383,7 +1384,7 @@ int EE_SELECTION_TOOL::SelectNode( const TOOL_EVENT& aEvent ) int EE_SELECTION_TOOL::SelectConnection( const TOOL_EVENT& aEvent ) { - static KICAD_T wiresAndBuses[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT }; + static KICAD_T wiresAndBuses[] = { SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T, EOT }; RequestSelection( wiresAndBuses ); diff --git a/eeschema/tools/sch_drawing_tools.cpp b/eeschema/tools/sch_drawing_tools.cpp index 0b8570d287..6802129a2d 100644 --- a/eeschema/tools/sch_drawing_tools.cpp +++ b/eeschema/tools/sch_drawing_tools.cpp @@ -53,7 +53,7 @@ #include <string_utils.h> #include <wildcards_and_files_ext.h> #include <wx/filedlg.h> - +#include <sch_shape.h> SCH_DRAWING_TOOLS::SCH_DRAWING_TOOLS() : EE_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.InteractiveDrawing" ), @@ -62,7 +62,9 @@ SCH_DRAWING_TOOLS::SCH_DRAWING_TOOLS() : m_lastTextOrientation( LABEL_SPIN_STYLE::RIGHT ), m_lastTextBold( false ), m_lastTextItalic( false ), + m_lastFillStyle( FILL_T::NO_FILL ), m_inPlaceSymbol( false ), + m_inDrawShape( false ), m_inPlaceImage( false ), m_inSingleClickPlace( false ), m_inTwoClickPlace( false ), @@ -1180,8 +1182,7 @@ int SCH_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent ) else // ... and second click places: { item->ClearFlags( IS_MOVING ); - m_frame->AddItemToScreenAndUndoList( m_frame->GetScreen(), (SCH_ITEM*) item, - false ); + m_frame->AddItemToScreenAndUndoList( m_frame->GetScreen(), item, false ); item = nullptr; m_view->ClearPreview(); @@ -1238,6 +1239,165 @@ int SCH_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent ) } +int SCH_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent ) +{ + if( m_inDrawShape ) + return 0; + else + m_inDrawShape = true; + + SHAPE_T type = aEvent.Parameter<SHAPE_T>(); + + // We might be running as the same shape in another co-routine. Make sure that one + // gets whacked. + m_toolMgr->DeactivateTool(); + + m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true ); + getViewControls()->ShowCursor( true ); + + std::string tool = aEvent.GetCommandStr().get(); + m_frame->PushTool( tool ); + Activate(); + + SCH_SHAPE* item = nullptr; + + auto setCursor = + [&]() + { + m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL ); + }; + + auto cleanup = + [&] () + { + m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true ); + m_view->ClearPreview(); + delete item; + item = nullptr; + }; + + // Prime the pump + if( aEvent.HasPosition() ) + m_toolMgr->RunAction( ACTIONS::cursorClick ); + + // Set initial cursor + setCursor(); + + // Main loop: keep receiving events + while( TOOL_EVENT* evt = Wait() ) + { + setCursor(); + + VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->DisableGridSnapping() ); + + if( evt->IsCancelInteractive() ) + { + if( item ) + { + cleanup(); + } + else + { + m_frame->PopTool( tool ); + break; + } + } + else if( evt->IsActivate() ) + { + if( item && evt->IsMoveTool() ) + { + // we're already drawing our own item; ignore the move tool + evt->SetPassEvent( false ); + continue; + } + + if( item ) + cleanup(); + + if( evt->IsPointEditor() ) + { + // don't exit (the point editor runs in the background) + } + else if( evt->IsMoveTool() ) + { + // leave ourselves on the stack so we come back after the move + break; + } + else + { + m_frame->PopTool( tool ); + break; + } + } + else if( evt->IsClick( BUT_LEFT ) && !item ) + { + EESCHEMA_SETTINGS* cfg = m_frame->eeconfig(); + + m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true ); + + int lineWidth = Mils2iu( cfg->m_Drawing.default_line_thickness ); + + item = new SCH_SHAPE( type, lineWidth, m_lastFillStyle ); + item->SetFlags( IS_NEW ); + item->BeginEdit( (wxPoint) cursorPos ); + + m_view->ClearPreview(); + m_view->AddToPreview( item->Clone() ); + } + else if( item && ( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) + || evt->IsAction( &EE_ACTIONS::finishDrawing ) ) ) + { + if( evt->IsDblClick( BUT_LEFT ) || evt->IsAction( &EE_ACTIONS::finishDrawing ) + || !item->ContinueEdit( (wxPoint) cursorPos ) ) + { + item->EndEdit(); + item->ClearEditFlags(); + item->SetFlags( IS_NEW ); + + m_frame->AddItemToScreenAndUndoList( m_frame->GetScreen(), item, false ); + m_selectionTool->AddItemToSel( item ); + item = nullptr; + + m_view->ClearPreview(); + m_toolMgr->RunAction( ACTIONS::activatePointEditor ); + } + } + else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) ) + { + item->CalcEdit( (wxPoint) cursorPos ); + m_view->ClearPreview(); + m_view->AddToPreview( item->Clone() ); + } + else if( evt->IsDblClick( BUT_LEFT ) && !item ) + { + m_toolMgr->RunAction( EE_ACTIONS::properties, true ); + } + else if( evt->IsClick( BUT_RIGHT ) ) + { + // Warp after context menu only if dragging... + if( !item ) + m_toolMgr->VetoContextMenuMouseWarp(); + + m_menu.ShowContextMenu( m_selectionTool->GetSelection() ); + } + else + { + evt->SetPassEvent(); + } + + // Enable autopanning and cursor capture only when there is a shape being drawn + getViewControls()->SetAutoPan( item != nullptr ); + getViewControls()->CaptureCursor( item != nullptr ); + } + + getViewControls()->SetAutoPan( false ); + getViewControls()->CaptureCursor( false ); + m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW ); + m_inDrawShape = false; + return 0; +} + + int SCH_DRAWING_TOOLS::DrawSheet( const TOOL_EVENT& aEvent ) { SCH_SHEET* sheet = nullptr; @@ -1333,8 +1493,7 @@ int SCH_DRAWING_TOOLS::DrawSheet( const TOOL_EVENT& aEvent ) m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true ); - sheet = new SCH_SHEET( m_frame->GetCurrentSheet().Last(), - static_cast<wxPoint>( cursorPos ) ); + sheet = new SCH_SHEET( m_frame->GetCurrentSheet().Last(), (wxPoint) cursorPos ); sheet->SetFlags( IS_NEW | IS_RESIZING ); sheet->SetScreen( nullptr ); sheet->SetBorderWidth( Mils2iu( cfg->m_Drawing.default_line_thickness ) ); @@ -1448,5 +1607,8 @@ void SCH_DRAWING_TOOLS::setTransitions() Go( &SCH_DRAWING_TOOLS::TwoClickPlace, EE_ACTIONS::importSheetPin.MakeEvent() ); Go( &SCH_DRAWING_TOOLS::SingleClickPlace, EE_ACTIONS::importSingleSheetPin.MakeEvent() ); Go( &SCH_DRAWING_TOOLS::TwoClickPlace, EE_ACTIONS::placeSchematicText.MakeEvent() ); + Go( &SCH_DRAWING_TOOLS::DrawShape, EE_ACTIONS::drawRectangle.MakeEvent() ); + Go( &SCH_DRAWING_TOOLS::DrawShape, EE_ACTIONS::drawCircle.MakeEvent() ); + Go( &SCH_DRAWING_TOOLS::DrawShape, EE_ACTIONS::drawArc.MakeEvent() ); Go( &SCH_DRAWING_TOOLS::PlaceImage, EE_ACTIONS::placeImage.MakeEvent() ); } diff --git a/eeschema/tools/sch_drawing_tools.h b/eeschema/tools/sch_drawing_tools.h index 92a105ef3d..4a959c6d14 100644 --- a/eeschema/tools/sch_drawing_tools.h +++ b/eeschema/tools/sch_drawing_tools.h @@ -53,6 +53,7 @@ public: int PlaceSymbol( const TOOL_EVENT& aEvent ); int SingleClickPlace( const TOOL_EVENT& aEvent ); int TwoClickPlace( const TOOL_EVENT& aEvent ); + int DrawShape( const TOOL_EVENT& aEvent ); int DrawSheet( const TOOL_EVENT& aEvent ); int PlaceImage( const TOOL_EVENT& aEvent ); @@ -88,9 +89,11 @@ private: LABEL_SPIN_STYLE m_lastTextOrientation; bool m_lastTextBold; bool m_lastTextItalic; + FILL_T m_lastFillStyle; ///< Re-entrancy guards bool m_inPlaceSymbol; + bool m_inDrawShape; bool m_inPlaceImage; bool m_inSingleClickPlace; bool m_inTwoClickPlace; diff --git a/eeschema/tools/sch_edit_tool.cpp b/eeschema/tools/sch_edit_tool.cpp index 6c65db80c8..1f3fb454ad 100644 --- a/eeschema/tools/sch_edit_tool.cpp +++ b/eeschema/tools/sch_edit_tool.cpp @@ -28,15 +28,16 @@ #include <tools/ee_selection_tool.h> #include <tools/sch_line_wire_bus_tool.h> #include <tools/sch_move_tool.h> +#include <tools/sch_drawing_tools.h> #include <widgets/infobar.h> #include <ee_actions.h> #include <bitmaps.h> #include <confirm.h> #include <eda_item.h> -#include <reporter.h> #include <string_utils.h> #include <sch_item.h> #include <sch_symbol.h> +#include <sch_shape.h> #include <sch_sheet.h> #include <sch_sheet_pin.h> #include <sch_text.h> @@ -59,17 +60,15 @@ #include <dialogs/dialog_sheet_pin_properties.h> #include <dialogs/dialog_field_properties.h> #include <dialogs/dialog_junction_props.h> -#include "sch_drawing_tools.h" +#include <dialogs/dialog_shape_properties.h> +#include <dialogs/dialog_text_and_label_properties.h> #include <math/util.h> // for KiROUND #include <pgm_base.h> #include <settings/settings_manager.h> #include <symbol_editor_settings.h> -#include <dialogs/dialog_text_and_label_properties.h> #include <core/kicad_algo.h> #include <wx/textdlg.h> - - class SYMBOL_UNIT_MENU : public ACTION_MENU { public: @@ -415,6 +414,7 @@ bool SCH_EDIT_TOOL::Init() const KICAD_T rotatableItems[] = { + SCH_SHAPE_T, SCH_TEXT_T, SCH_LABEL_T, SCH_GLOBAL_LABEL_T, @@ -533,6 +533,13 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent ) break; } + case SCH_SHAPE_T: + for( int i = 0; clockwise ? i < 1 : i < 3; ++i ) + head->Rotate( rotPoint ); + + break; + + case SCH_BITMAP_T: for( int i = 0; clockwise ? i < 3 : i < 1; ++i ) head->Rotate( rotPoint ); @@ -554,7 +561,7 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent ) } default: - break; + UNIMPLEMENTED_FOR( head->GetClass() ); } connections = head->IsConnectable(); @@ -744,6 +751,14 @@ int SCH_EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent ) break; } + case SCH_SHAPE_T: + if( vertical ) + item->MirrorVertically( item->GetPosition().y ); + else + item->MirrorHorizontally( item->GetPosition().x ); + + break; + case SCH_BITMAP_T: if( vertical ) item->MirrorVertically( item->GetPosition().y ); @@ -766,7 +781,7 @@ int SCH_EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent ) break; default: - break; + UNIMPLEMENTED_FOR( item->GetClass() ); } connections = item->IsConnectable(); @@ -915,6 +930,7 @@ static KICAD_T deletableItems[] = SCH_LINE_T, SCH_BUS_BUS_ENTRY_T, SCH_BUS_WIRE_ENTRY_T, + SCH_SHAPE_T, SCH_TEXT_T, SCH_LABEL_T, SCH_GLOBAL_LABEL_T, @@ -1458,6 +1474,18 @@ int SCH_EDIT_TOOL::Properties( const TOOL_EVENT& aEvent ) } break; + case SCH_SHAPE_T: + { + DIALOG_SHAPE_PROPERTIES dlg( m_frame, static_cast<SCH_SHAPE*>( item ) ); + + if( dlg.ShowModal() == wxID_OK ) + { + m_toolMgr->PostEvent( EVENTS::SelectedItemsModified ); + m_frame->OnModify(); + } + } + break; + case SCH_BITMAP_T: { SCH_BITMAP* bitmap = static_cast<SCH_BITMAP*>( item ); diff --git a/eeschema/tools/sch_editor_control.cpp b/eeschema/tools/sch_editor_control.cpp index 014afddca6..90d103d585 100644 --- a/eeschema/tools/sch_editor_control.cpp +++ b/eeschema/tools/sch_editor_control.cpp @@ -734,8 +734,8 @@ void SCH_EDITOR_CONTROL::doCrossProbeSchToPcb( const TOOL_EVENT& aEvent, bool aF #ifdef KICAD_SPICE -static KICAD_T wires[] = { SCH_LINE_LOCATE_WIRE_T, EOT }; -static KICAD_T wiresAndPins[] = { SCH_LINE_LOCATE_WIRE_T, SCH_PIN_T, SCH_SHEET_PIN_T, EOT }; +static KICAD_T wires[] = { SCH_ITEM_LOCATE_WIRE_T, EOT }; +static KICAD_T wiresAndPins[] = { SCH_ITEM_LOCATE_WIRE_T, SCH_PIN_T, SCH_SHEET_PIN_T, EOT }; static KICAD_T fieldsAndSymbols[] = { SCH_SYMBOL_T, SCH_FIELD_T, EOT }; #define HITTEST_THRESHOLD_PIXELS 5 diff --git a/eeschema/tools/sch_line_wire_bus_tool.cpp b/eeschema/tools/sch_line_wire_bus_tool.cpp index 2483cd5302..ae9091d2d7 100644 --- a/eeschema/tools/sch_line_wire_bus_tool.cpp +++ b/eeschema/tools/sch_line_wire_bus_tool.cpp @@ -95,7 +95,7 @@ private: { SCH_EDIT_FRAME* frame = (SCH_EDIT_FRAME*) getToolManager()->GetToolHolder(); EE_SELECTION_TOOL* selTool = getToolManager()->GetTool<EE_SELECTION_TOOL>(); - KICAD_T busType[] = { SCH_LINE_LOCATE_BUS_T, EOT }; + KICAD_T busType[] = { SCH_ITEM_LOCATE_BUS_T, EOT }; EE_SELECTION& selection = selTool->RequestSelection( busType ); SCH_LINE* bus = (SCH_LINE*) selection.Front(); @@ -200,7 +200,7 @@ bool SCH_LINE_WIRE_BUS_TOOL::Init() }; auto busSelection = EE_CONDITIONS::MoreThan( 0 ) - && EE_CONDITIONS::OnlyType( SCH_LINE_LOCATE_BUS_T ); + && EE_CONDITIONS::OnlyType( SCH_ITEM_LOCATE_BUS_T ); auto& ctxMenu = m_menu.GetMenu(); @@ -248,21 +248,21 @@ bool SCH_LINE_WIRE_BUS_TOOL::Init() bool SCH_LINE_WIRE_BUS_TOOL::IsDrawingLine( const SELECTION& aSelection ) { - static KICAD_T graphicLineType[] = { SCH_LINE_LOCATE_GRAPHIC_LINE_T, EOT }; + static KICAD_T graphicLineType[] = { SCH_ITEM_LOCATE_GRAPHIC_LINE_T, EOT }; return IsDrawingLineWireOrBus( aSelection ) && aSelection.Front()->IsType( graphicLineType ); } bool SCH_LINE_WIRE_BUS_TOOL::IsDrawingWire( const SELECTION& aSelection ) { - static KICAD_T wireType[] = { SCH_LINE_LOCATE_WIRE_T, EOT }; + static KICAD_T wireType[] = { SCH_ITEM_LOCATE_WIRE_T, EOT }; return IsDrawingLineWireOrBus( aSelection ) && aSelection.Front()->IsType( wireType ); } bool SCH_LINE_WIRE_BUS_TOOL::IsDrawingBus( const SELECTION& aSelection ) { - static KICAD_T busType[] = { SCH_LINE_LOCATE_BUS_T, EOT }; + static KICAD_T busType[] = { SCH_ITEM_LOCATE_BUS_T, EOT }; return IsDrawingLineWireOrBus( aSelection ) && aSelection.Front()->IsType( busType ); } diff --git a/eeschema/tools/symbol_editor_drawing_tools.cpp b/eeschema/tools/symbol_editor_drawing_tools.cpp index ba99507805..04cc88e3a2 100644 --- a/eeschema/tools/symbol_editor_drawing_tools.cpp +++ b/eeschema/tools/symbol_editor_drawing_tools.cpp @@ -90,6 +90,15 @@ int SYMBOL_EDITOR_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent ) m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL ); }; + auto cleanup = + [&] () + { + m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true ); + m_view->ClearPreview(); + delete item; + item = nullptr; + }; + Activate(); // Must be done after Activate() so that it gets set into the correct context getViewControls()->ShowCursor( true ); @@ -100,6 +109,9 @@ int SYMBOL_EDITOR_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent ) if( aEvent.HasPosition() || ( isText && !aEvent.IsReactivate() ) ) m_toolMgr->RunAction( ACTIONS::cursorClick ); + // Set initial cursor + setCursor(); + // Main loop: keep receiving events while( TOOL_EVENT* evt = Wait() ) { @@ -107,15 +119,6 @@ int SYMBOL_EDITOR_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent ) cursorPos = getViewControls()->GetCursorPosition( !evt->DisableGridSnapping() ); - auto cleanup = - [&] () - { - m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true ); - m_view->ClearPreview(); - delete item; - item = nullptr; - }; - if( evt->IsCancelInteractive() ) { if( item ) @@ -310,7 +313,9 @@ int SYMBOL_EDITOR_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent ) if( evt->IsCancelInteractive() ) { if( item ) + { cleanup(); + } else { m_frame->PopTool( tool ); @@ -379,7 +384,7 @@ int SYMBOL_EDITOR_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent ) } else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) ) { - item->CalcEdit( wxPoint( cursorPos.x, -cursorPos.y) ); + item->CalcEdit( wxPoint( cursorPos.x, -cursorPos.y ) ); m_view->ClearPreview(); m_view->AddToPreview( item->Clone() ); } @@ -514,9 +519,9 @@ void SYMBOL_EDITOR_DRAWING_TOOLS::setTransitions() { Go( &SYMBOL_EDITOR_DRAWING_TOOLS::TwoClickPlace, EE_ACTIONS::placeSymbolPin.MakeEvent() ); Go( &SYMBOL_EDITOR_DRAWING_TOOLS::TwoClickPlace, EE_ACTIONS::placeSymbolText.MakeEvent() ); - Go( &SYMBOL_EDITOR_DRAWING_TOOLS::DrawShape, EE_ACTIONS::drawSymbolRectangle.MakeEvent() ); - Go( &SYMBOL_EDITOR_DRAWING_TOOLS::DrawShape, EE_ACTIONS::drawSymbolCircle.MakeEvent() ); - Go( &SYMBOL_EDITOR_DRAWING_TOOLS::DrawShape, EE_ACTIONS::drawSymbolArc.MakeEvent() ); + Go( &SYMBOL_EDITOR_DRAWING_TOOLS::DrawShape, EE_ACTIONS::drawRectangle.MakeEvent() ); + Go( &SYMBOL_EDITOR_DRAWING_TOOLS::DrawShape, EE_ACTIONS::drawCircle.MakeEvent() ); + Go( &SYMBOL_EDITOR_DRAWING_TOOLS::DrawShape, EE_ACTIONS::drawArc.MakeEvent() ); Go( &SYMBOL_EDITOR_DRAWING_TOOLS::DrawShape, EE_ACTIONS::drawSymbolLines.MakeEvent() ); Go( &SYMBOL_EDITOR_DRAWING_TOOLS::PlaceAnchor, EE_ACTIONS::placeSymbolAnchor.MakeEvent() ); Go( &SYMBOL_EDITOR_DRAWING_TOOLS::RepeatDrawItem, EE_ACTIONS::repeatDrawItem.MakeEvent() ); diff --git a/include/board_item.h b/include/board_item.h index eec5547d08..707e2d0666 100644 --- a/include/board_item.h +++ b/include/board_item.h @@ -32,6 +32,7 @@ #include <gr_basic.h> #include <layer_ids.h> #include <geometry/geometry_utils.h> +#include <stroke_params.h> class BOARD; class BOARD_ITEM_CONTAINER; @@ -136,6 +137,16 @@ public: BOARD_ITEM_CONTAINER* GetParentFootprint() const; + /** + * Check if this item has line stoke properties. + * + * @see #STROKE_PARAMS + */ + virtual bool HasLineStroke() const { return false; } + + virtual STROKE_PARAMS GetStroke() const; + virtual void SetStroke( const STROKE_PARAMS& aStroke ); + /** * Return the primary layer this item is on. */ diff --git a/include/core/typeinfo.h b/include/core/typeinfo.h index 0d11b0241a..e8c572fc93 100644 --- a/include/core/typeinfo.h +++ b/include/core/typeinfo.h @@ -127,6 +127,7 @@ enum KICAD_T SCH_BUS_WIRE_ENTRY_T, SCH_BUS_BUS_ENTRY_T, SCH_LINE_T, + SCH_SHAPE_T, SCH_BITMAP_T, SCH_TEXT_T, SCH_LABEL_T, @@ -146,10 +147,10 @@ enum KICAD_T SCH_FIELD_LOCATE_FOOTPRINT_T, SCH_FIELD_LOCATE_DATASHEET_T, - // Same for picking wires and buses from SCH_LINE_T items - SCH_LINE_LOCATE_WIRE_T, - SCH_LINE_LOCATE_BUS_T, - SCH_LINE_LOCATE_GRAPHIC_LINE_T, + // Same for picking wires, buses and graphics from SCH_ITEM_T items + SCH_ITEM_LOCATE_WIRE_T, + SCH_ITEM_LOCATE_BUS_T, + SCH_ITEM_LOCATE_GRAPHIC_LINE_T, // Same for picking labels attached to wires and/or buses SCH_LABEL_LOCATE_WIRE_T, @@ -224,7 +225,7 @@ enum KICAD_T * Return the underlying type of the given type. * * This is useful for finding the element type given one of the "non-type" types such as - * SCH_LINE_LOCATE_WIRE_T. + * SCH_ITEM_LOCATE_WIRE_T. * * @param aType Given type to resolve. * @return Base type. @@ -239,9 +240,9 @@ constexpr KICAD_T BaseType( const KICAD_T aType ) case SCH_FIELD_LOCATE_DATASHEET_T: return SCH_FIELD_T; - case SCH_LINE_LOCATE_WIRE_T: - case SCH_LINE_LOCATE_BUS_T: - case SCH_LINE_LOCATE_GRAPHIC_LINE_T: + case SCH_ITEM_LOCATE_WIRE_T: + case SCH_ITEM_LOCATE_BUS_T: + case SCH_ITEM_LOCATE_GRAPHIC_LINE_T: return SCH_LINE_T; case SCH_LABEL_LOCATE_WIRE_T: @@ -287,9 +288,9 @@ constexpr bool IsInstantiableType( const KICAD_T aType ) case SCH_FIELD_LOCATE_FOOTPRINT_T: case SCH_FIELD_LOCATE_DATASHEET_T: - case SCH_LINE_LOCATE_WIRE_T: - case SCH_LINE_LOCATE_BUS_T: - case SCH_LINE_LOCATE_GRAPHIC_LINE_T: + case SCH_ITEM_LOCATE_WIRE_T: + case SCH_ITEM_LOCATE_BUS_T: + case SCH_ITEM_LOCATE_GRAPHIC_LINE_T: case SCH_LABEL_LOCATE_WIRE_T: case SCH_LABEL_LOCATE_BUS_T: @@ -346,9 +347,9 @@ constexpr bool IsEeschemaType( const KICAD_T aType ) case SCH_FIELD_LOCATE_FOOTPRINT_T: case SCH_FIELD_LOCATE_DATASHEET_T: - case SCH_LINE_LOCATE_WIRE_T: - case SCH_LINE_LOCATE_BUS_T: - case SCH_LINE_LOCATE_GRAPHIC_LINE_T: + case SCH_ITEM_LOCATE_WIRE_T: + case SCH_ITEM_LOCATE_BUS_T: + case SCH_ITEM_LOCATE_GRAPHIC_LINE_T: case SCH_LABEL_LOCATE_WIRE_T: case SCH_LABEL_LOCATE_BUS_T: diff --git a/include/eda_shape.h b/include/eda_shape.h index d0ba4ef75b..24b007fff6 100644 --- a/include/eda_shape.h +++ b/include/eda_shape.h @@ -30,12 +30,14 @@ #include <trigo.h> #include <geometry/shape_poly_set.h> #include <geometry/geometry_utils.h> +#include <stroke_params.h> class LINE_READER; class EDA_DRAW_FRAME; class FOOTPRINT; class MSG_PANEL_ITEM; +using KIGFX::COLOR4D; enum class SHAPE_T : int { @@ -75,18 +77,24 @@ public: wxString SHAPE_T_asString() const; - void SetFillMode( FILL_T aFill ) { m_fill = aFill; } - FILL_T GetFillType() const { return m_fill; } - - bool IsFilled() const { return GetFillType() != FILL_T::NO_FILL; } + bool IsFilled() const + { + return GetFillMode() != FILL_T::NO_FILL; + } void SetFilled( bool aFlag ) { m_fill = aFlag ? FILL_T::FILLED_SHAPE : FILL_T::NO_FILL; } - void SetWidth( int aWidth ) { m_width = aWidth; } - int GetWidth() const { return m_width; } + void SetFillMode( FILL_T aFill ) { m_fill = aFill; } + FILL_T GetFillMode() const { return m_fill; } + + COLOR4D GetFillColor() const { return m_fillColor; } + void SetFillColor( const COLOR4D& aColor ) { m_fillColor = aColor; } + + void SetWidth( int aWidth ) { m_stroke.SetWidth( aWidth ); } + int GetWidth() const { return m_stroke.GetWidth(); } void SetShape( SHAPE_T aShape ) { m_shape = aShape; } SHAPE_T GetShape() const { return m_shape; } @@ -232,9 +240,12 @@ public: /** * Make a set of SHAPE objects representing the EDA_SHAPE. Caller owns the objects. + * + * @param aEdgeOnly indicates only edges should be generated (even if 0 width), and no fill + * shapes. */ // fixme: move to shape_compound - std::vector<SHAPE*> MakeEffectiveShapes() const; + std::vector<SHAPE*> MakeEffectiveShapes( bool aEdgeOnly = false ) const; void ShapeGetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ); @@ -294,8 +305,10 @@ protected: protected: bool m_endsSwapped; // true if start/end were swapped e.g. SetArcAngleAndEnd SHAPE_T m_shape; // Shape: line, Circle, Arc - int m_width; // thickness of lines ... + STROKE_PARAMS m_stroke; // Line style, width, etc. FILL_T m_fill; + COLOR4D m_fillColor; + wxPoint m_start; // Line start point or Circle center wxPoint m_end; // Line end point or Circle 3 o'clock point diff --git a/include/layer_ids.h b/include/layer_ids.h index 40848f09fe..70ecf2fd71 100644 --- a/include/layer_ids.h +++ b/include/layer_ids.h @@ -338,6 +338,7 @@ enum SCH_LAYER_ID: int LAYER_FIELDS, LAYER_DEVICE, LAYER_NOTES, + LAYER_NOTES_BACKGROUND, LAYER_PIN, LAYER_SHEET, LAYER_SHEETNAME, diff --git a/include/plotters/plotter.h b/include/plotters/plotter.h index 0f214449e4..920353010e 100644 --- a/include/plotters/plotter.h +++ b/include/plotters/plotter.h @@ -38,6 +38,7 @@ #include <page_info.h> #include <outline_mode.h> #include <gal/color4d.h> +#include <stroke_params.h> #include <render_settings.h> class COLOR_SETTINGS; @@ -98,20 +99,6 @@ enum class PLOT_TEXT_MODE DEFAULT }; -/** - * Dashed line types. - */ -enum class PLOT_DASH_TYPE -{ - DEFAULT = -1, - SOLID = 0, - FIRST_TYPE = SOLID, - DASH, - DOT, - DASHDOT, - LAST_TYPE = DASHDOT -}; - /** * Base plotter engine class. General rule: all the interface with the caller * is done in IU, the IU size is specified with SetViewport. Internal and diff --git a/include/render_settings.h b/include/render_settings.h index ea0f821faa..1b8f6c0ff6 100644 --- a/include/render_settings.h +++ b/include/render_settings.h @@ -203,6 +203,15 @@ public: int GetMinPenWidth() const { return m_minPenWidth; } void SetMinPenWidth( int aWidth ) { m_minPenWidth = aWidth; } + double GetDashLengthRatio() const { return m_dashLengthRatio; } + void SetDashLengthRatio( double aRatio ) { m_dashLengthRatio = aRatio; } + double GetDashLength( int aLineWidth ) const; + double GetDotLength( int aLineWidth ) const; + + double GetGapLengthRatio() const { return m_gapLengthRatio; } + void SetGapLengthRatio( double aRatio ) { m_gapLengthRatio = aRatio; } + double GetGapLength( int aLineWidth ) const; + bool GetShowPageLimits() const { return m_showPageLimits; } void SetShowPageLimits( bool aDraw ) { m_showPageLimits = aDraw; } @@ -309,6 +318,9 @@ protected: int m_defaultPenWidth; int m_minPenWidth; // Some clients (such as PDF) don't like ultra-thin // lines. This sets an absolute minimum. + double m_dashLengthRatio; + double m_gapLengthRatio; + bool m_showPageLimits; bool m_isPrinting; diff --git a/include/stroke_params.h b/include/stroke_params.h new file mode 100644 index 0000000000..a7b4770d44 --- /dev/null +++ b/include/stroke_params.h @@ -0,0 +1,145 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef STROKE_PARAMS_H +#define STROKE_PARAMS_H + +#include <map> +#include <bitmaps.h> +#include <gal/color4d.h> +#include <wx/translation.h> +#include <geometry/shape.h> +#include <stroke_params_lexer.h> + +class STROKE_PARAMS_LEXER; + +namespace KIGFX +{ +class RENDER_SETTINGS; +} + + +/** + * Dashed line types. + */ +enum class PLOT_DASH_TYPE +{ + DEFAULT = -1, + SOLID = 0, + FIRST_TYPE = SOLID, + DASH, + DOT, + DASHDOT, + LAST_TYPE = DASHDOT +}; + + +struct lineTypeStruct +{ + wxString name; + const BITMAPS bitmap; +}; + + +/* + * Conversion map between PLOT_DASH_TYPE values and style names displayed + */ +const std::map<PLOT_DASH_TYPE, struct lineTypeStruct> lineTypeNames = +{ + { PLOT_DASH_TYPE::SOLID, { _( "Solid" ), BITMAPS::stroke_solid } }, + { PLOT_DASH_TYPE::DASH, { _( "Dashed" ), BITMAPS::stroke_dash } }, + { PLOT_DASH_TYPE::DOT, { _( "Dotted" ), BITMAPS::stroke_dot } }, + { PLOT_DASH_TYPE::DASHDOT, { _( "Dash-Dot" ), BITMAPS::stroke_dashdot } } +}; + + +#define DEFAULT_STYLE _( "Default" ) +#define INDETERMINATE_STYLE _( "Leave unchanged" ) + + +/** + * Simple container to manage line stroke parameters. + */ +class STROKE_PARAMS +{ +public: + STROKE_PARAMS( int aWidth = 0, PLOT_DASH_TYPE aPlotStyle = PLOT_DASH_TYPE::DEFAULT, + const KIGFX::COLOR4D& aColor = KIGFX::COLOR4D::UNSPECIFIED ) : + m_width( aWidth ), + m_plotstyle( aPlotStyle ), + m_color( aColor ) + { + } + + int GetWidth() const { return m_width; } + void SetWidth( int aWidth ) { m_width = aWidth; } + + PLOT_DASH_TYPE GetPlotStyle() const { return m_plotstyle; } + void SetPlotStyle( PLOT_DASH_TYPE aPlotStyle ) { m_plotstyle = aPlotStyle; } + + KIGFX::COLOR4D GetColor() const { return m_color; } + void SetColor( const KIGFX::COLOR4D& aColor ) { m_color = aColor; } + + bool operator!=( const STROKE_PARAMS& aOther ) + { + return m_width != aOther.m_width + || m_plotstyle != aOther.m_plotstyle + || m_color != aOther.m_color; + } + + void Format( OUTPUTFORMATTER* out, int nestLevel ) const; + + // Helper functions + + static void Stroke( const SHAPE* aShape, PLOT_DASH_TYPE aLineStyle, int aWidth, + const KIGFX::RENDER_SETTINGS* aRenderSettings, + std::function<void( const wxPoint& a, const wxPoint& b )> aStroker ); + +private: + int m_width; + PLOT_DASH_TYPE m_plotstyle; + KIGFX::COLOR4D m_color; +}; + + +class STROKE_PARAMS_PARSER : public STROKE_PARAMS_LEXER +{ +public: + STROKE_PARAMS_PARSER( LINE_READER* aReader, int iuPerMM ) : + STROKE_PARAMS_LEXER( aReader ), + m_iuPerMM( iuPerMM ) + { + } + + void ParseStroke( STROKE_PARAMS& aStroke ); + +private: + int parseInt( const char* aText ); + double parseDouble( const char* aText ); + +private: + int m_iuPerMM; +}; + + +#endif // STROKE_PARAMS_H diff --git a/libs/kimath/include/geometry/geometry_utils.h b/libs/kimath/include/geometry/geometry_utils.h index b36b35c942..234bf24579 100644 --- a/libs/kimath/include/geometry/geometry_utils.h +++ b/libs/kimath/include/geometry/geometry_utils.h @@ -149,24 +149,5 @@ VECTOR2<T> GetVectorSnapped45( const VECTOR2<T>& aVec, bool only45 = false ) bool ClipLine( const EDA_RECT *aClipBox, int &x1, int &y1, int &x2, int &y2 ); -/** - * Dashed and dotted line patterns. - */ - -constexpr double dot_mark_len( double aLineWidth ) -{ - return std::max( 1.0, aLineWidth ); -} - -constexpr double dash_gap_len( double aLineWidth ) -{ - return 3.0 * dot_mark_len( aLineWidth ) + ( 2.0 * aLineWidth ); -} - -constexpr double dash_mark_len( double aLineWidth ) -{ - return std::max( dash_gap_len( aLineWidth ), 5.0 * dot_mark_len( aLineWidth ) ); -} - #endif // #ifndef GEOMETRY_UTILS_H diff --git a/pcbnew/board_item.cpp b/pcbnew/board_item.cpp index b30a661443..4aca8d3d2c 100644 --- a/pcbnew/board_item.cpp +++ b/pcbnew/board_item.cpp @@ -30,6 +30,7 @@ #include <i18n_utility.h> #include <macros.h> #include <board.h> +#include <board_design_settings.h> #include <pcb_group.h> @@ -72,6 +73,18 @@ bool BOARD_ITEM::IsLocked() const } +STROKE_PARAMS BOARD_ITEM::GetStroke() const +{ + wxCHECK( false, STROKE_PARAMS( Millimeter2iu( DEFAULT_LINE_WIDTH ) ) ); +} + + +void BOARD_ITEM::SetStroke( const STROKE_PARAMS& aStroke ) +{ + wxCHECK( false, /* void */ ); +} + + wxString BOARD_ITEM::GetLayerName() const { const BOARD* board = GetBoard(); diff --git a/pcbnew/convert_shape_list_to_polygon.cpp b/pcbnew/convert_shape_list_to_polygon.cpp index 4300018cfe..5e0dfce5aa 100644 --- a/pcbnew/convert_shape_list_to_polygon.cpp +++ b/pcbnew/convert_shape_list_to_polygon.cpp @@ -745,8 +745,7 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET& break; default: - wxFAIL_MSG( "ConvertOutlineToPolygon not implemented for " - + graphic->SHAPE_T_asString() ); + UNIMPLEMENTED_FOR( graphic->SHAPE_T_asString() ); return false; } diff --git a/pcbnew/dialogs/dialog_global_edit_text_and_graphics.cpp b/pcbnew/dialogs/dialog_global_edit_text_and_graphics.cpp index 93169a33c0..d22e69cfe0 100644 --- a/pcbnew/dialogs/dialog_global_edit_text_and_graphics.cpp +++ b/pcbnew/dialogs/dialog_global_edit_text_and_graphics.cpp @@ -320,7 +320,11 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::processItem( BOARD_COMMIT& aCommit, B if( !m_lineWidth.IsIndeterminate() ) { if( drawItem ) - drawItem->SetWidth( m_lineWidth.GetValue() ); + { + STROKE_PARAMS stroke = drawItem->GetStroke(); + stroke.SetWidth( m_lineWidth.GetValue() ); + drawItem->SetStroke( stroke ); + } if( dimension ) dimension->SetLineThickness( m_lineWidth.GetValue() ); @@ -341,7 +345,11 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::processItem( BOARD_COMMIT& aCommit, B fpTextItem->SetKeepUpright( m_brdSettings->GetTextUpright( layer ) ); if( drawItem ) - drawItem->SetWidth( m_brdSettings->GetLineThickness( layer ) ); + { + STROKE_PARAMS stroke = drawItem->GetStroke(); + stroke.SetWidth( m_brdSettings->GetLineThickness( layer ) ); + drawItem->SetStroke( stroke ); + } if( dimension ) dimension->SetLineThickness( m_brdSettings->GetLineThickness( layer ) ); diff --git a/pcbnew/dialogs/dialog_graphic_item_properties.cpp b/pcbnew/dialogs/dialog_graphic_item_properties.cpp index 74c8d7a674..99cc62dac5 100644 --- a/pcbnew/dialogs/dialog_graphic_item_properties.cpp +++ b/pcbnew/dialogs/dialog_graphic_item_properties.cpp @@ -338,7 +338,11 @@ bool DIALOG_GRAPHIC_ITEM_PROPERTIES::TransferDataFromWindow() m_item->SetFilled( m_filledCtrl->GetValue() ); m_item->SetLocked( m_locked->GetValue() ); - m_item->SetWidth( m_thickness.GetValue() ); + + STROKE_PARAMS stroke = m_item->GetStroke(); + stroke.SetWidth( m_thickness.GetValue() ); + m_item->SetStroke( stroke ); + m_item->SetLayer( ToLAYER_ID( layer ) ); m_item->RebuildBezierToSegmentsPointsList( m_item->GetWidth() ); diff --git a/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp b/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp index 4c55fa74b0..0653e50574 100644 --- a/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp +++ b/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp @@ -181,7 +181,10 @@ bool DIALOG_PAD_PRIMITIVES_PROPERTIES::TransferDataFromWindow() } // Transfer data out of the GUI. - m_shape->SetWidth( m_thickness.GetValue() ); + STROKE_PARAMS stroke = m_shape->GetStroke(); + stroke.SetWidth( m_thickness.GetValue() ); + m_shape->SetStroke( stroke ); + m_shape->SetFilled( m_filledCtrl->GetValue() ); switch( m_shape->GetShape() ) @@ -311,7 +314,11 @@ bool DIALOG_PAD_PRIMITIVE_POLY_PROPS::TransferDataFromWindow() return false; m_shape->SetPolyPoints( m_currPoints ); - m_shape->SetWidth( m_thickness.GetValue() ); + + STROKE_PARAMS stroke = m_shape->GetStroke(); + stroke.SetWidth( m_thickness.GetValue() ); + m_shape->SetStroke( stroke ); + m_shape->SetFilled( m_filledCtrl->GetValue() ); return true; @@ -616,7 +623,10 @@ void DIALOG_PAD_PRIMITIVES_TRANSFORM::Transform( std::vector<std::shared_ptr<PCB } // Transform parameters common to all shape types (some can be unused) - shape->SetWidth( KiROUND( shape->GetWidth() * scale ) ); + STROKE_PARAMS stroke = shape->GetStroke(); + stroke.SetWidth( KiROUND( shape->GetWidth() * scale ) ); + shape->SetStroke( stroke ); + shape->Move( currMoveVect ); shape->Scale( scale ); shape->Rotate( wxPoint( 0, 0 ), curr_rotation ); diff --git a/pcbnew/dialogs/dialog_pad_properties.cpp b/pcbnew/dialogs/dialog_pad_properties.cpp index d17eb091db..e24590ffd1 100644 --- a/pcbnew/dialogs/dialog_pad_properties.cpp +++ b/pcbnew/dialogs/dialog_pad_properties.cpp @@ -2142,7 +2142,8 @@ void DIALOG_PAD_PROPERTIES::onAddPrimitive( wxCommandEvent& event ) PCB_SHAPE* primitive = new PCB_SHAPE(); primitive->SetShape( listtype[type] ); - primitive->SetWidth( m_board->GetDesignSettings().GetLineThickness( F_Cu ) ); + primitive->SetStroke( STROKE_PARAMS( m_board->GetDesignSettings().GetLineThickness( F_Cu ), + PLOT_DASH_TYPE::SOLID ) ); primitive->SetFilled( true ); if( listtype[type] == SHAPE_T::POLY ) diff --git a/pcbnew/drc/drc_test_provider_edge_clearance.cpp b/pcbnew/drc/drc_test_provider_edge_clearance.cpp index 6ef6b42e6d..7891d910ee 100644 --- a/pcbnew/drc/drc_test_provider_edge_clearance.cpp +++ b/pcbnew/drc/drc_test_provider_edge_clearance.cpp @@ -148,7 +148,8 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run() auto queryBoardOutlineItems = [&]( BOARD_ITEM *item ) -> bool { - PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( item ); + PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( item ); + STROKE_PARAMS stroke( 0 ); if( shape->GetShape() == SHAPE_T::RECT ) { @@ -157,19 +158,19 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run() edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) ); edges.back()->SetShape( SHAPE_T::SEGMENT ); edges.back()->SetEndX( shape->GetStartX() ); - edges.back()->SetWidth( 0 ); + edges.back()->SetStroke( stroke ); edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) ); edges.back()->SetShape( SHAPE_T::SEGMENT ); edges.back()->SetEndY( shape->GetStartY() ); - edges.back()->SetWidth( 0 ); + edges.back()->SetStroke( stroke ); edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) ); edges.back()->SetShape( SHAPE_T::SEGMENT ); edges.back()->SetStartX( shape->GetEndX() ); - edges.back()->SetWidth( 0 ); + edges.back()->SetStroke( stroke ); edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) ); edges.back()->SetShape( SHAPE_T::SEGMENT ); edges.back()->SetStartY( shape->GetEndY() ); - edges.back()->SetWidth( 0 ); + edges.back()->SetStroke( stroke ); return true; } else if( shape->GetShape() == SHAPE_T::POLY ) @@ -185,12 +186,12 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run() edges.back()->SetShape( SHAPE_T::SEGMENT ); edges.back()->SetStart((wxPoint) seg.A ); edges.back()->SetEnd((wxPoint) seg.B ); - edges.back()->SetWidth( 0 ); + edges.back()->SetStroke( stroke ); } } edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) ); - edges.back()->SetWidth( 0 ); + edges.back()->SetStroke( stroke ); return true; }; diff --git a/pcbnew/drc/drc_test_provider_library_parity.cpp b/pcbnew/drc/drc_test_provider_library_parity.cpp index 424339c3d3..b9dff417d7 100644 --- a/pcbnew/drc/drc_test_provider_library_parity.cpp +++ b/pcbnew/drc/drc_test_provider_library_parity.cpp @@ -22,6 +22,7 @@ */ #include <kiway.h> +#include <macros.h> #include <netlist_reader/pcb_netlist.h> #include <fp_lib_table.h> #include <board.h> diff --git a/pcbnew/exporters/export_gencad.cpp b/pcbnew/exporters/export_gencad.cpp index d9f588f410..e1668433a3 100644 --- a/pcbnew/exporters/export_gencad.cpp +++ b/pcbnew/exporters/export_gencad.cpp @@ -442,7 +442,7 @@ static void CreatePadsShapesSection( FILE* aFile, BOARD* aPcb ) switch( pad->GetShape() ) { default: - wxASSERT_MSG( false, "Pad type not implemented" ); + UNIMPLEMENTED_FOR( pad->ShowPadShape() ); KI_FALLTHROUGH; case PAD_SHAPE::CIRCLE: diff --git a/pcbnew/fp_shape.cpp b/pcbnew/fp_shape.cpp index 9cd1a3f7ac..ddb73b9b99 100644 --- a/pcbnew/fp_shape.cpp +++ b/pcbnew/fp_shape.cpp @@ -103,7 +103,7 @@ void FP_SHAPE::SetDrawCoord() m_bezierC2 += fp->GetPosition(); } - RebuildBezierToSegmentsPointsList( m_width ); + RebuildBezierToSegmentsPointsList( GetWidth() ); } @@ -247,7 +247,7 @@ void FP_SHAPE::Flip( const wxPoint& aCentre, bool aFlipLeftRight ) } if( GetShape() == SHAPE_T::BEZIER ) - RebuildBezierToSegmentsPointsList( m_width ); + RebuildBezierToSegmentsPointsList( GetWidth() ); if( GetShape() == SHAPE_T::ARC ) { @@ -306,7 +306,7 @@ void FP_SHAPE::Mirror( const wxPoint& aCentre, bool aMirrorAroundXAxis ) } if( GetShape() == SHAPE_T::BEZIER ) - RebuildBezierToSegmentsPointsList( m_width ); + RebuildBezierToSegmentsPointsList( GetWidth() ); break; diff --git a/pcbnew/graphics_cleaner.cpp b/pcbnew/graphics_cleaner.cpp index 53a63c947b..f38561a51d 100644 --- a/pcbnew/graphics_cleaner.cpp +++ b/pcbnew/graphics_cleaner.cpp @@ -308,7 +308,7 @@ void GRAPHICS_CLEANER::mergeRects() rect->SetStart( top->start ); rect->SetEnd( bottom->end ); rect->SetLayer( top->shape->GetLayer() ); - rect->SetWidth( top->shape->GetWidth() ); + rect->SetStroke( top->shape->GetStroke() ); m_commit.Add( rect ); m_commit.Remove( left->shape ); diff --git a/pcbnew/import_gfx/graphics_importer_pcbnew.cpp b/pcbnew/import_gfx/graphics_importer_pcbnew.cpp index 629420e01b..6dd7d4e3a0 100644 --- a/pcbnew/import_gfx/graphics_importer_pcbnew.cpp +++ b/pcbnew/import_gfx/graphics_importer_pcbnew.cpp @@ -59,12 +59,13 @@ int GRAPHICS_IMPORTER_PCBNEW::MapLineWidth( double aLineWidth ) } -void GRAPHICS_IMPORTER_PCBNEW::AddLine( const VECTOR2D& aOrigin, const VECTOR2D& aEnd, double aWidth ) +void GRAPHICS_IMPORTER_PCBNEW::AddLine( const VECTOR2D& aOrigin, const VECTOR2D& aEnd, + double aWidth ) { std::unique_ptr<PCB_SHAPE> line( createDrawing() ); line->SetShape( SHAPE_T::SEGMENT ); line->SetLayer( GetLayer() ); - line->SetWidth( MapLineWidth( aWidth ) ); + line->SetStroke( STROKE_PARAMS( MapLineWidth( aWidth ), PLOT_DASH_TYPE::SOLID ) ); line->SetStart( MapCoordinate( aOrigin ) ); line->SetEnd( MapCoordinate( aEnd ) ); @@ -75,13 +76,14 @@ void GRAPHICS_IMPORTER_PCBNEW::AddLine( const VECTOR2D& aOrigin, const VECTOR2D& } -void GRAPHICS_IMPORTER_PCBNEW::AddCircle( const VECTOR2D& aCenter, double aRadius, double aWidth, bool aFilled ) +void GRAPHICS_IMPORTER_PCBNEW::AddCircle( const VECTOR2D& aCenter, double aRadius, double aWidth, + bool aFilled ) { std::unique_ptr<PCB_SHAPE> circle( createDrawing() ); circle->SetShape( SHAPE_T::CIRCLE ); circle->SetFilled( aFilled ); circle->SetLayer( GetLayer() ); - circle->SetWidth( MapLineWidth( aWidth ) ); + circle->SetStroke( STROKE_PARAMS( MapLineWidth( aWidth ), PLOT_DASH_TYPE::SOLID ) ); circle->SetStart( MapCoordinate( aCenter )); circle->SetEnd( MapCoordinate( VECTOR2D( aCenter.x + aRadius, aCenter.y ) ) ); @@ -111,7 +113,7 @@ void GRAPHICS_IMPORTER_PCBNEW::AddArc( const VECTOR2D& aCenter, const VECTOR2D& arc->SetArcGeometry( MapCoordinate( aStart ), MapCoordinate( mid ), MapCoordinate( end ) ); - arc->SetWidth( MapLineWidth( aWidth ) ); + arc->SetStroke( STROKE_PARAMS( MapLineWidth( aWidth ), PLOT_DASH_TYPE::SOLID ) ); if( arc->Type() == PCB_FP_SHAPE_T ) static_cast<FP_SHAPE*>( arc.get() )->SetLocalCoord(); @@ -137,14 +139,15 @@ void GRAPHICS_IMPORTER_PCBNEW::AddPolygon( const std::vector< VECTOR2D >& aVerti if( polygon->Type() == PCB_FP_SHAPE_T ) static_cast<FP_SHAPE*>( polygon.get() )->SetLocalCoord(); - polygon->SetWidth( MapLineWidth( aWidth ) ); + polygon->SetStroke( STROKE_PARAMS( MapLineWidth( aWidth ), PLOT_DASH_TYPE::SOLID ) ); addItem( std::move( polygon ) ); } void GRAPHICS_IMPORTER_PCBNEW::AddText( const VECTOR2D& aOrigin, const wxString& aText, - double aHeight, double aWidth, double aThickness, double aOrientation, - EDA_TEXT_HJUSTIFY_T aHJustify, EDA_TEXT_VJUSTIFY_T aVJustify ) + double aHeight, double aWidth, double aThickness, + double aOrientation, EDA_TEXT_HJUSTIFY_T aHJustify, + EDA_TEXT_VJUSTIFY_T aVJustify ) { std::unique_ptr<BOARD_ITEM> boardItem; EDA_TEXT* textItem; @@ -167,12 +170,13 @@ void GRAPHICS_IMPORTER_PCBNEW::AddText( const VECTOR2D& aOrigin, const wxString& void GRAPHICS_IMPORTER_PCBNEW::AddSpline( const VECTOR2D& aStart, const VECTOR2D& BezierControl1, - const VECTOR2D& BezierControl2, const VECTOR2D& aEnd, double aWidth ) + const VECTOR2D& BezierControl2, const VECTOR2D& aEnd, + double aWidth ) { std::unique_ptr<PCB_SHAPE> spline( createDrawing() ); spline->SetShape( SHAPE_T::BEZIER ); spline->SetLayer( GetLayer() ); - spline->SetWidth( MapLineWidth( aWidth ) ); + spline->SetStroke( STROKE_PARAMS( MapLineWidth( aWidth ), PLOT_DASH_TYPE::SOLID ) ); spline->SetStart( MapCoordinate( aStart ) ); spline->SetBezierC1( MapCoordinate( BezierControl1 )); spline->SetBezierC2( MapCoordinate( BezierControl2 )); diff --git a/pcbnew/microwave/microwave_inductor.cpp b/pcbnew/microwave/microwave_inductor.cpp index 6e3dcf24fa..cbbe12cbdc 100644 --- a/pcbnew/microwave/microwave_inductor.cpp +++ b/pcbnew/microwave/microwave_inductor.cpp @@ -427,7 +427,7 @@ FOOTPRINT* MICROWAVE_TOOL::createMicrowaveInductor( MICROWAVE_INDUCTOR_PATTERN& FP_SHAPE* seg = new FP_SHAPE( footprint, SHAPE_T::SEGMENT ); seg->SetStart( buffer[jj - 1] ); seg->SetEnd( buffer[jj] ); - seg->SetWidth( aInductorPattern.m_Width ); + seg->SetStroke( STROKE_PARAMS( aInductorPattern.m_Width, PLOT_DASH_TYPE::SOLID ) ); seg->SetLayer( footprint->GetLayer() ); seg->SetStart0( seg->GetStart() - footprint->GetPosition() ); seg->SetEnd0( seg->GetEnd() - footprint->GetPosition() ); diff --git a/pcbnew/microwave/microwave_polygon.cpp b/pcbnew/microwave/microwave_polygon.cpp index 14f85e8fd7..c1c832145b 100644 --- a/pcbnew/microwave/microwave_polygon.cpp +++ b/pcbnew/microwave/microwave_polygon.cpp @@ -389,7 +389,7 @@ FOOTPRINT* MICROWAVE_TOOL::createPolygonShape() // Set the polygon outline thickness to 0, only the polygonal shape is filled // without extra thickness. - shape->SetWidth( 0 ); + shape->SetStroke( STROKE_PARAMS( 0, PLOT_DASH_TYPE::SOLID ) ); g_PolyEdges.clear(); editFrame.OnModify(); diff --git a/pcbnew/pad_custom_shape_functions.cpp b/pcbnew/pad_custom_shape_functions.cpp index 62778824e5..185a369429 100644 --- a/pcbnew/pad_custom_shape_functions.cpp +++ b/pcbnew/pad_custom_shape_functions.cpp @@ -48,7 +48,7 @@ void PAD::AddPrimitivePoly( const SHAPE_POLY_SET& aPoly, int aThickness, bool aF item->SetShape( SHAPE_T::POLY ); item->SetFilled( aFilled ); item->SetPolyShape( poly_no_hole ); - item->SetWidth( aThickness ); + item->SetStroke( STROKE_PARAMS( aThickness, PLOT_DASH_TYPE::SOLID ) ); item->SetParent( this ); m_editPrimitives.emplace_back( item ); SetDirty(); @@ -60,7 +60,7 @@ void PAD::AddPrimitivePoly( const std::vector<wxPoint>& aPoly, int aThickness, b PCB_SHAPE* item = new PCB_SHAPE( nullptr, SHAPE_T::POLY ); item->SetFilled( aFilled ); item->SetPolyPoints( aPoly ); - item->SetWidth( aThickness ); + item->SetStroke( STROKE_PARAMS( aThickness, PLOT_DASH_TYPE::SOLID ) ); item->SetParent( this ); m_editPrimitives.emplace_back( item ); SetDirty(); @@ -73,7 +73,7 @@ void PAD::AddPrimitiveSegment( const wxPoint& aStart, const wxPoint& aEnd, int a item->SetFilled( false ); item->SetStart( aStart ); item->SetEnd( aEnd ); - item->SetWidth( aThickness ); + item->SetStroke( STROKE_PARAMS( aThickness, PLOT_DASH_TYPE::SOLID ) ); item->SetParent( this ); m_editPrimitives.emplace_back( item ); SetDirty(); @@ -88,7 +88,7 @@ void PAD::AddPrimitiveArc( const wxPoint& aCenter, const wxPoint& aStart, int aA item->SetCenter( aCenter ); item->SetStart( aStart ); item->SetArcAngleAndEnd( aArcAngle ); - item->SetWidth( aThickness ); + item->SetStroke( STROKE_PARAMS( aThickness, PLOT_DASH_TYPE::SOLID ) ); item->SetParent( this ); m_editPrimitives.emplace_back( item ); SetDirty(); @@ -104,7 +104,7 @@ void PAD::AddPrimitiveCurve( const wxPoint& aStart, const wxPoint& aEnd, const w item->SetEnd( aEnd ); item->SetBezierC1( aCtrl1 ); item->SetBezierC2( aCtrl2 ); - item->SetWidth( aThickness ); + item->SetStroke( STROKE_PARAMS( aThickness, PLOT_DASH_TYPE::SOLID ) ); item->SetParent( this ); m_editPrimitives.emplace_back( item ); SetDirty(); @@ -117,7 +117,7 @@ void PAD::AddPrimitiveCircle( const wxPoint& aCenter, int aRadius, int aThicknes item->SetFilled( aFilled ); item->SetStart( aCenter ); item->SetEnd( wxPoint( aCenter.x + aRadius, aCenter.y ) ); - item->SetWidth( aThickness ); + item->SetStroke( STROKE_PARAMS( aThickness, PLOT_DASH_TYPE::SOLID ) ); item->SetParent( this ); m_editPrimitives.emplace_back( item ); SetDirty(); @@ -131,7 +131,7 @@ void PAD::AddPrimitiveRect( const wxPoint& aStart, const wxPoint& aEnd, int aThi item->SetFilled( aFilled ); item->SetStart( aStart ); item->SetEnd( aEnd ); - item->SetWidth( aThickness ); + item->SetStroke( STROKE_PARAMS( aThickness, PLOT_DASH_TYPE::SOLID ) ); item->SetParent( this ); m_editPrimitives.emplace_back( item ); SetDirty(); diff --git a/pcbnew/pcb_shape.cpp b/pcbnew/pcb_shape.cpp index ccb5eb9ae7..bd50532ea1 100644 --- a/pcbnew/pcb_shape.cpp +++ b/pcbnew/pcb_shape.cpp @@ -254,8 +254,9 @@ static struct PCB_SHAPE_DESC propMgr.InheritsAfter( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( BOARD_ITEM ) ); propMgr.InheritsAfter( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( EDA_SHAPE ) ); - propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "Thickness" ), - &EDA_SHAPE::SetWidth, &EDA_SHAPE::GetWidth, PROPERTY_DISPLAY::DISTANCE ) ); + // JEY TODO: + //propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "Thickness" ), + // &EDA_SHAPE::SetWidth, &EDA_SHAPE::GetWidth, PROPERTY_DISPLAY::DISTANCE ) ); // TODO show certain properties depending on the shape //propMgr.AddProperty( new PROPERTY<PCB_SHAPE, double>( _HKI( "Angle" ), // &PCB_SHAPE::SetArcAngle, &PCB_SHAPE::GetAngle, PROPERTY_DISPLAY::DECIDEGREE ) ); diff --git a/pcbnew/pcb_shape.h b/pcbnew/pcb_shape.h index da89061256..fee90d02ef 100644 --- a/pcbnew/pcb_shape.h +++ b/pcbnew/pcb_shape.h @@ -78,6 +78,11 @@ public: wxPoint GetCenter() const override { return getCenter(); } + bool HasLineStroke() const override { return true; } + + STROKE_PARAMS GetStroke() const override { return m_stroke; } + void SetStroke( const STROKE_PARAMS& aStroke ) override { m_stroke = aStroke; } + /** * Allows items to return their visual center rather than their anchor. For some shapes this * is similar to GetCenter(), but for unfilled shapes a point on the outline is better. diff --git a/pcbnew/pcbnew.cpp b/pcbnew/pcbnew.cpp index 8407508560..8a0daeb964 100644 --- a/pcbnew/pcbnew.cpp +++ b/pcbnew/pcbnew.cpp @@ -319,7 +319,7 @@ void IFACE::SaveFileAs( const wxString& aProjectBasePath, const wxString& aSrcPr } else if( ext == FootprintAssignmentFileExtension ) { - // JEY TODO + // TODO } else if( ext == "rpt" ) { diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp index 183f92b297..6ee0c5a23b 100644 --- a/pcbnew/plot_brditems_plotter.cpp +++ b/pcbnew/plot_brditems_plotter.cpp @@ -421,7 +421,7 @@ void BRDITEMS_PLOTTER::PlotDimension( const PCB_DIMENSION_BASE* aDim ) PCB_SHAPE draw; - draw.SetWidth( aDim->GetLineThickness() ); + draw.SetStroke( STROKE_PARAMS( aDim->GetLineThickness(), PLOT_DASH_TYPE::SOLID ) ); draw.SetLayer( aDim->GetLayer() ); COLOR4D color = ColorSettings()->GetColor( aDim->GetLayer() ); @@ -482,7 +482,7 @@ void BRDITEMS_PLOTTER::PlotPcbTarget( const PCB_TARGET* aMire ) draw.SetShape( SHAPE_T::CIRCLE ); draw.SetFilled( false ); - draw.SetWidth( aMire->GetWidth() ); + draw.SetStroke( STROKE_PARAMS( aMire->GetWidth(), PLOT_DASH_TYPE::SOLID ) ); draw.SetLayer( aMire->GetLayer() ); draw.SetStart( aMire->GetPosition() ); radius = aMire->GetSize() / 3; diff --git a/pcbnew/plugins/altium/altium_pcb.cpp b/pcbnew/plugins/altium/altium_pcb.cpp index 5cc5886bd3..7d4ed36d4f 100644 --- a/pcbnew/plugins/altium/altium_pcb.cpp +++ b/pcbnew/plugins/altium/altium_pcb.cpp @@ -848,6 +848,9 @@ void ALTIUM_PCB::HelperCreateBoardOutline( const std::vector<ALTIUM_VERTICE>& aV if( !aVertices.empty() ) { const ALTIUM_VERTICE* last = &aVertices.at( 0 ); + STROKE_PARAMS stroke( m_board->GetDesignSettings().GetLineThickness( Edge_Cuts ), + PLOT_DASH_TYPE::SOLID ); + for( size_t i = 0; i < aVertices.size(); i++ ) { const ALTIUM_VERTICE* cur = &aVertices.at( ( i + 1 ) % aVertices.size() ); @@ -855,7 +858,7 @@ void ALTIUM_PCB::HelperCreateBoardOutline( const std::vector<ALTIUM_VERTICE>& aV PCB_SHAPE* shape = new PCB_SHAPE( m_board ); m_board->Add( shape, ADD_MODE::APPEND ); - shape->SetWidth( m_board->GetDesignSettings().GetLineThickness( Edge_Cuts ) ); + shape->SetStroke( stroke ); shape->SetLayer( Edge_Cuts ); if( !last->isRound && !cur->isRound ) @@ -887,7 +890,7 @@ void ALTIUM_PCB::HelperCreateBoardOutline( const std::vector<ALTIUM_VERTICE>& aV PCB_SHAPE* shape2 = new PCB_SHAPE( m_board, SHAPE_T::SEGMENT ); m_board->Add( shape2, ADD_MODE::APPEND ); - shape2->SetWidth( m_board->GetDesignSettings().GetLineThickness( Edge_Cuts ) ); + shape2->SetStroke( stroke ); shape2->SetLayer( Edge_Cuts ); shape2->SetStart( last->position ); @@ -1245,7 +1248,7 @@ void ALTIUM_PCB::HelperParseDimensions6Leader( const ADIMENSION6& aElem ) PCB_SHAPE* shape = new PCB_SHAPE( m_board, SHAPE_T::SEGMENT ); m_board->Add( shape, ADD_MODE::APPEND ); shape->SetLayer( klayer ); - shape->SetWidth( aElem.linewidth ); + shape->SetStroke( STROKE_PARAMS( aElem.linewidth, PLOT_DASH_TYPE::SOLID ) ); shape->SetStart( last ); shape->SetEnd( aElem.referencePoint.at( i ) ); last = aElem.referencePoint.at( i ); @@ -1265,7 +1268,7 @@ void ALTIUM_PCB::HelperParseDimensions6Leader( const ADIMENSION6& aElem ) PCB_SHAPE* shape1 = new PCB_SHAPE( m_board, SHAPE_T::SEGMENT ); m_board->Add( shape1, ADD_MODE::APPEND ); shape1->SetLayer( klayer ); - shape1->SetWidth( aElem.linewidth ); + shape1->SetStroke( STROKE_PARAMS( aElem.linewidth, PLOT_DASH_TYPE::SOLID ) ); shape1->SetStart( referencePoint0 ); shape1->SetEnd( referencePoint0 + arrVec ); @@ -1274,7 +1277,7 @@ void ALTIUM_PCB::HelperParseDimensions6Leader( const ADIMENSION6& aElem ) PCB_SHAPE* shape2 = new PCB_SHAPE( m_board, SHAPE_T::SEGMENT ); m_board->Add( shape2, ADD_MODE::APPEND ); shape2->SetLayer( klayer ); - shape2->SetWidth( aElem.linewidth ); + shape2->SetStroke( STROKE_PARAMS( aElem.linewidth, PLOT_DASH_TYPE::SOLID ) ); shape2->SetStart( referencePoint0 ); shape2->SetEnd( referencePoint0 + arrVec ); } @@ -1316,7 +1319,7 @@ void ALTIUM_PCB::HelperParseDimensions6Datum( const ADIMENSION6& aElem ) PCB_SHAPE* shape = new PCB_SHAPE( m_board, SHAPE_T::SEGMENT ); m_board->Add( shape, ADD_MODE::APPEND ); shape->SetLayer( klayer ); - shape->SetWidth( aElem.linewidth ); + shape->SetStroke( STROKE_PARAMS( aElem.linewidth, PLOT_DASH_TYPE::SOLID ) ); shape->SetStart( aElem.referencePoint.at( i ) ); // shape->SetEnd( /* TODO: seems to be based on TEXTY */ ); } @@ -1795,7 +1798,7 @@ void ALTIUM_PCB::ParseShapeBasedRegions6Data( const CFB::CompoundFileReader& aRe m_board->Add( shape, ADD_MODE::APPEND ); shape->SetFilled( true ); shape->SetLayer( klayer ); - shape->SetWidth( 0 ); + shape->SetStroke( STROKE_PARAMS( 0 ) ); shape->SetPolyShape( linechain ); } @@ -1926,7 +1929,7 @@ void ALTIUM_PCB::ParseArcs6Data( const CFB::CompoundFileReader& aReader, if( elem.is_keepout || IsAltiumLayerAPlane( elem.layer ) ) { PCB_SHAPE shape( nullptr ); // just a helper to get the graphic - shape.SetWidth( elem.width ); + shape.SetStroke( STROKE_PARAMS( elem.width, PLOT_DASH_TYPE::SOLID ) ); if( elem.startangle == 0. && elem.endangle == 360. ) { // TODO: other variants to define circle? @@ -2031,7 +2034,7 @@ void ALTIUM_PCB::ParseArcs6Data( const CFB::CompoundFileReader& aReader, else { PCB_SHAPE* shape = HelperCreateAndAddShape( elem.component ); - shape->SetWidth( elem.width ); + shape->SetStroke( STROKE_PARAMS( elem.width, PLOT_DASH_TYPE::SOLID ) ); shape->SetLayer( klayer ); if( elem.startangle == 0. && elem.endangle == 360. ) @@ -2329,7 +2332,7 @@ void ALTIUM_PCB::HelperParsePad6NonCopper( const APAD6& aElem ) shape->SetShape( SHAPE_T::POLY ); shape->SetFilled( true ); shape->SetLayer( klayer ); - shape->SetWidth( 0 ); + shape->SetStroke( STROKE_PARAMS( 0 ) ); shape->SetPolyPoints( { aElem.position + wxPoint( aElem.topsize.x / 2, aElem.topsize.y / 2 ), aElem.position + wxPoint( aElem.topsize.x / 2, -aElem.topsize.y / 2 ), @@ -2353,7 +2356,7 @@ void ALTIUM_PCB::HelperParsePad6NonCopper( const APAD6& aElem ) PCB_SHAPE* shape = HelperCreateAndAddShape( aElem.component ); shape->SetLayer( klayer ); - shape->SetWidth( offset * 2 ); + shape->SetStroke( STROKE_PARAMS( offset * 2, PLOT_DASH_TYPE::SOLID ) ); if( cornerradius < 100 ) { @@ -2376,7 +2379,7 @@ void ALTIUM_PCB::HelperParsePad6NonCopper( const APAD6& aElem ) shape->SetFilled( true ); shape->SetStart( aElem.position ); shape->SetEnd( aElem.position - wxPoint( 0, aElem.topsize.x / 4 ) ); - shape->SetWidth( aElem.topsize.x / 2 ); + shape->SetStroke( STROKE_PARAMS( aElem.topsize.x / 2, PLOT_DASH_TYPE::SOLID ) ); } else if( aElem.topsize.x < aElem.topsize.y ) { @@ -2409,7 +2412,7 @@ void ALTIUM_PCB::HelperParsePad6NonCopper( const APAD6& aElem ) shape->SetLayer( klayer ); shape->SetStart( aElem.position ); shape->SetEnd( aElem.position - wxPoint( 0, aElem.topsize.x / 4 ) ); - shape->SetWidth( aElem.topsize.x / 2 ); + shape->SetStroke( STROKE_PARAMS( aElem.topsize.x / 2, PLOT_DASH_TYPE::SOLID ) ); HelperShapeSetLocalCoord( shape, aElem.component ); } else @@ -2418,7 +2421,8 @@ void ALTIUM_PCB::HelperParsePad6NonCopper( const APAD6& aElem ) PCB_SHAPE* shape = HelperCreateAndAddShape( aElem.component ); shape->SetShape( SHAPE_T::SEGMENT ); shape->SetLayer( klayer ); - shape->SetWidth( std::min( aElem.topsize.x, aElem.topsize.y ) ); + shape->SetStroke( STROKE_PARAMS( std::min( aElem.topsize.x, aElem.topsize.y ), + PLOT_DASH_TYPE::SOLID ) ); if( aElem.topsize.x < aElem.topsize.y ) { @@ -2447,7 +2451,7 @@ void ALTIUM_PCB::HelperParsePad6NonCopper( const APAD6& aElem ) shape->SetShape( SHAPE_T::POLY ); shape->SetFilled( true ); shape->SetLayer( klayer ); - shape->SetWidth( 0 ); + shape->SetStroke( STROKE_PARAMS( 0 ) ); wxPoint p11 = aElem.position + wxPoint( aElem.topsize.x / 2, aElem.topsize.y / 2 ); wxPoint p12 = aElem.position + wxPoint( aElem.topsize.x / 2, -aElem.topsize.y / 2 ); @@ -2564,7 +2568,7 @@ void ALTIUM_PCB::ParseTracks6Data( const CFB::CompoundFileReader& aReader, PCB_SHAPE shape( nullptr, SHAPE_T::SEGMENT ); shape.SetStart( elem.start ); shape.SetEnd( elem.end ); - shape.SetWidth( elem.width ); + shape.SetStroke( STROKE_PARAMS( elem.width, PLOT_DASH_TYPE::SOLID ) ); ZONE* zone = new ZONE( m_board ); m_board->Add( zone, ADD_MODE::APPEND ); @@ -2612,7 +2616,7 @@ void ALTIUM_PCB::ParseTracks6Data( const CFB::CompoundFileReader& aReader, klayer = Eco1_User; } - if( klayer >= F_Cu && klayer <= B_Cu ) + if( IsCopperLayer( klayer ) ) { PCB_TRACK* track = new PCB_TRACK( m_board ); m_board->Add( track, ADD_MODE::APPEND ); @@ -2629,7 +2633,7 @@ void ALTIUM_PCB::ParseTracks6Data( const CFB::CompoundFileReader& aReader, shape->SetShape( SHAPE_T::SEGMENT ); shape->SetStart( elem.start ); shape->SetEnd( elem.end ); - shape->SetWidth( elem.width ); + shape->SetStroke( STROKE_PARAMS( elem.width, PLOT_DASH_TYPE::SOLID ) ); shape->SetLayer( klayer ); HelperShapeSetLocalCoord( shape, elem.component ); } @@ -2915,7 +2919,7 @@ void ALTIUM_PCB::ParseFills6Data( const CFB::CompoundFileReader& aReader, m_board->Add( shape, ADD_MODE::APPEND ); shape->SetFilled( true ); shape->SetLayer( klayer ); - shape->SetWidth( 0 ); + shape->SetStroke( STROKE_PARAMS( 0 ) ); shape->SetPolyPoints( { p11, p12, p22, p21 } ); diff --git a/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp b/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp index d76668239f..f43bc7b0ae 100644 --- a/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp +++ b/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp @@ -1179,7 +1179,7 @@ PAD* CADSTAR_PCB_ARCHIVE_LOADER::getKiCadPad( const COMPONENT_PAD& aCadstarPad, padShape->SetShape( SHAPE_T::POLY ); padShape->SetFilled( true ); padShape->SetPolyShape( padOutline ); - padShape->SetWidth( 0 ); + padShape->SetStroke( STROKE_PARAMS( 0 ) ); padShape->Move( padOffset - drillOffset ); padShape->Rotate( wxPoint( 0, 0 ), 1800.0 - getAngleTenthDegree( csPadcode.SlotOrientation ) ); @@ -2436,7 +2436,7 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadNetTracks( const NET_ID& aCadstarNe { PCB_SHAPE* shape = getShapeFromVertex( prevEnd, v.Vertex ); shape->SetLayer( getKiCadLayer( aCadstarRoute.LayerID ) ); - shape->SetWidth( getKiCadLength( v.RouteWidth ) ); + shape->SetStroke( STROKE_PARAMS( getKiCadLength( v.RouteWidth ), PLOT_DASH_TYPE::SOLID ) ); shape->SetLocked( v.Fixed ); shapes.push_back( shape ); prevEnd = v.Vertex.End; @@ -2695,14 +2695,15 @@ void CADSTAR_PCB_ARCHIVE_LOADER::drawCadstarShape( const SHAPE& aCadstarShape, shape->SetFilled( true ); - SHAPE_POLY_SET shapePolys = getPolySetFromCadstarShape( - aCadstarShape, -1, aContainer, aMoveVector, aRotationAngle, aScalingFactor, - aTransformCentre, aMirrorInvert ); + SHAPE_POLY_SET shapePolys = getPolySetFromCadstarShape( aCadstarShape, -1, aContainer, + aMoveVector, aRotationAngle, + aScalingFactor, aTransformCentre, + aMirrorInvert ); shapePolys.Fracture( SHAPE_POLY_SET::POLYGON_MODE::PM_STRICTLY_SIMPLE ); shape->SetPolyShape( shapePolys ); - shape->SetWidth( aLineThickness ); + shape->SetStroke( STROKE_PARAMS( aLineThickness, PLOT_DASH_TYPE::SOLID ) ); shape->SetLayer( aKiCadLayer ); aContainer->Add( shape, ADD_MODE::APPEND ); @@ -2752,7 +2753,7 @@ void CADSTAR_PCB_ARCHIVE_LOADER::drawCadstarVerticesAsShapes( const std::vector< for( PCB_SHAPE* shape : shapes ) { - shape->SetWidth( aLineThickness ); + shape->SetStroke( STROKE_PARAMS( aLineThickness, PLOT_DASH_TYPE::SOLID ) ); shape->SetLayer( aKiCadLayer ); shape->SetParent( aContainer ); aContainer->Add( shape, ADD_MODE::APPEND ); diff --git a/pcbnew/plugins/eagle/eagle_plugin.cpp b/pcbnew/plugins/eagle/eagle_plugin.cpp index f41aa0041a..df37fc08b9 100644 --- a/pcbnew/plugins/eagle/eagle_plugin.cpp +++ b/pcbnew/plugins/eagle/eagle_plugin.cpp @@ -730,7 +730,7 @@ void EAGLE_PLUGIN::loadPlain( wxXmlNode* aGraphics ) } shape->SetLayer( layer ); - shape->SetWidth( width ); + shape->SetStroke( STROKE_PARAMS( width, PLOT_DASH_TYPE::SOLID ) ); } m_xpath->pop(); @@ -912,7 +912,7 @@ void EAGLE_PLUGIN::loadPlain( wxXmlNode* aGraphics ) shape->SetLayer( layer ); shape->SetStart( wxPoint( kicad_x( c.x ), kicad_y( c.y ) ) ); shape->SetEnd( wxPoint( kicad_x( c.x ) + radius, kicad_y( c.y ) ) ); - shape->SetWidth( width ); + shape->SetStroke( STROKE_PARAMS( width, PLOT_DASH_TYPE::SOLID ) ); } } @@ -1804,7 +1804,7 @@ void EAGLE_PLUGIN::packageWire( FOOTPRINT* aFootprint, wxXmlNode* aTree ) const } dwg->SetLayer( layer ); - dwg->SetWidth( width ); + dwg->SetStroke( STROKE_PARAMS( width, PLOT_DASH_TYPE::SOLID ) ); dwg->SetDrawCoord(); aFootprint->Add( dwg ); @@ -2076,7 +2076,7 @@ void EAGLE_PLUGIN::packageRectangle( FOOTPRINT* aFootprint, wxXmlNode* aTree ) c aFootprint->Add( dwg ); dwg->SetLayer( layer ); - dwg->SetWidth( 0 ); + dwg->SetStroke( STROKE_PARAMS( 0 ) ); dwg->SetFilled( true ); std::vector<wxPoint> pts; @@ -2189,7 +2189,7 @@ void EAGLE_PLUGIN::packagePolygon( FOOTPRINT* aFootprint, wxXmlNode* aTree ) con aFootprint->Add( dwg ); - dwg->SetWidth( 0 ); // it's filled, no need for boundary width + dwg->SetStroke( STROKE_PARAMS( 0 ) ); dwg->SetFilled( true ); dwg->SetLayer( layer ); @@ -2269,7 +2269,7 @@ void EAGLE_PLUGIN::packageCircle( FOOTPRINT* aFootprint, wxXmlNode* aTree ) cons } aFootprint->Add( gr ); - gr->SetWidth( width ); + gr->SetStroke( STROKE_PARAMS( width, PLOT_DASH_TYPE::SOLID ) ); switch( (int) layer ) { diff --git a/pcbnew/plugins/fabmaster/import_fabmaster.cpp b/pcbnew/plugins/fabmaster/import_fabmaster.cpp index ae00d7d699..b109d42058 100644 --- a/pcbnew/plugins/fabmaster/import_fabmaster.cpp +++ b/pcbnew/plugins/fabmaster/import_fabmaster.cpp @@ -2083,6 +2083,8 @@ bool FABMASTER::loadFootprints( BOARD* aBoard ) if( IsPcbLayer( getLayer( seg->layer ) ) ) layer = getLayer( seg->layer ); + STROKE_PARAMS defaultStroke( ds.GetLineThickness( layer ) ); + switch( seg->shape ) { @@ -2105,11 +2107,11 @@ bool FABMASTER::loadFootprints( BOARD* aBoard ) line->SetEnd( wxPoint( lsrc->end_x, lsrc->end_y ) ); } - line->SetWidth( lsrc->width ); + line->SetStroke( STROKE_PARAMS( lsrc->width, PLOT_DASH_TYPE::SOLID ) ); line->SetLocalCoord(); if( lsrc->width == 0 ) - line->SetWidth( ds.GetLineThickness( line->GetLayer() ) ); + line->SetStroke( defaultStroke ); fp->Add( line, ADD_MODE::APPEND ); break; @@ -2145,11 +2147,11 @@ bool FABMASTER::loadFootprints( BOARD* aBoard ) arc->SetArcGeometry( (wxPoint) lsrc->result.GetP0(), (wxPoint) lsrc->result.GetArcMid(), (wxPoint) lsrc->result.GetP1() ); - arc->SetWidth( lsrc->width ); + arc->SetStroke( STROKE_PARAMS( lsrc->width, PLOT_DASH_TYPE::SOLID ) ); arc->SetLocalCoord(); if( lsrc->width == 0 ) - arc->SetWidth( ds.GetLineThickness( arc->GetLayer() ) ); + arc->SetStroke( defaultStroke ); if( src->mirror ) arc->Flip( arc->GetCenter(), false ); @@ -2177,7 +2179,7 @@ bool FABMASTER::loadFootprints( BOARD* aBoard ) rect->SetEnd( wxPoint( lsrc->end_x, lsrc->end_y ) ); } - rect->SetWidth( ds.GetLineThickness( rect->GetLayer() ) ); + rect->SetStroke( defaultStroke ); rect->SetLocalCoord(); fp->Add( rect, ADD_MODE::APPEND ); @@ -2626,7 +2628,8 @@ bool FABMASTER::loadPolygon( BOARD* aBoard, const std::unique_ptr<FABMASTER::TRA if( poly_outline.OutlineCount() < 1 || poly_outline.COutline( 0 ).PointCount() < 3 ) return false; - PCB_SHAPE* new_poly = new PCB_SHAPE( aBoard ); + STROKE_PARAMS defaultStroke( aBoard->GetDesignSettings().GetLineThickness( layer ) ); + PCB_SHAPE* new_poly = new PCB_SHAPE( aBoard ); new_poly->SetShape( SHAPE_T::POLY ); new_poly->SetLayer( layer ); @@ -2635,14 +2638,15 @@ bool FABMASTER::loadPolygon( BOARD* aBoard, const std::unique_ptr<FABMASTER::TRA if( layer == F_SilkS || layer == B_SilkS ) { new_poly->SetFilled( true ); - new_poly->SetWidth( 0 ); + new_poly->SetStroke( STROKE_PARAMS( 0 ) ); } else { - new_poly->SetWidth( ( *( aLine->segment.begin() ) )->width ); + new_poly->SetStroke( STROKE_PARAMS( ( *( aLine->segment.begin() ) )->width, + PLOT_DASH_TYPE::SOLID ) ); if( new_poly->GetWidth() == 0 ) - new_poly->SetWidth( aBoard->GetDesignSettings().GetLineThickness( layer ) ); + new_poly->SetStroke( defaultStroke ); } new_poly->SetPolyShape( poly_outline ); @@ -2765,6 +2769,8 @@ bool FABMASTER::loadOutline( BOARD* aBoard, const std::unique_ptr<FABMASTER::TRA else layer = Cmts_User; + STROKE_PARAMS defaultStroke( aBoard->GetDesignSettings().GetLineThickness( layer ) ); + for( auto& seg : aLine->segment ) { switch( seg->shape ) @@ -2778,10 +2784,10 @@ bool FABMASTER::loadOutline( BOARD* aBoard, const std::unique_ptr<FABMASTER::TRA line->SetLayer( layer ); line->SetStart( wxPoint( src->start_x, src->start_y ) ); line->SetEnd( wxPoint( src->end_x, src->end_y ) ); - line->SetWidth( src->width ); + line->SetStroke( STROKE_PARAMS( src->width, PLOT_DASH_TYPE::SOLID ) ); if( line->GetWidth() == 0 ) - line->SetWidth( aBoard->GetDesignSettings().GetLineThickness( layer ) ); + line->SetStroke( defaultStroke ); aBoard->Add( line, ADD_MODE::APPEND ); break; @@ -2812,10 +2818,10 @@ bool FABMASTER::loadOutline( BOARD* aBoard, const std::unique_ptr<FABMASTER::TRA arc->SetArcGeometry( (wxPoint) src->result.GetP0(), (wxPoint) src->result.GetArcMid(), (wxPoint) src->result.GetP1() ); - arc->SetWidth( src->width ); + arc->SetStroke( STROKE_PARAMS( src->width, PLOT_DASH_TYPE::SOLID ) ); if( arc->GetWidth() == 0 ) - arc->SetWidth( aBoard->GetDesignSettings().GetLineThickness( layer ) ); + arc->SetStroke( defaultStroke ); aBoard->Add( arc, ADD_MODE::APPEND ); break; @@ -2829,7 +2835,7 @@ bool FABMASTER::loadOutline( BOARD* aBoard, const std::unique_ptr<FABMASTER::TRA rect->SetLayer( layer ); rect->SetStart( wxPoint( src->start_x, src->start_y ) ); rect->SetEnd( wxPoint( src->end_x, src->end_y ) ); - rect->SetWidth( aBoard->GetDesignSettings().GetLineThickness( layer ) ); + rect->SetStroke( defaultStroke ); aBoard->Add( rect, ADD_MODE::APPEND ); break; @@ -2891,7 +2897,7 @@ bool FABMASTER::loadGraphics( BOARD* aBoard ) PCB_SHAPE* new_poly = new PCB_SHAPE( aBoard, SHAPE_T::POLY ); new_poly->SetLayer( layer ); new_poly->SetPolyShape( poly_outline ); - new_poly->SetWidth( 0 ); + new_poly->SetStroke( STROKE_PARAMS( 0 ) ); if( layer == F_SilkS || layer == B_SilkS ) new_poly->SetFilled( true ); @@ -2913,7 +2919,7 @@ bool FABMASTER::loadGraphics( BOARD* aBoard ) line->SetLayer( layer ); line->SetStart( wxPoint( src->start_x, src->start_y ) ); line->SetEnd( wxPoint( src->end_x, src->end_y ) ); - line->SetWidth( src->width ); + line->SetStroke( STROKE_PARAMS( src->width, PLOT_DASH_TYPE::SOLID ) ); aBoard->Add( line, ADD_MODE::APPEND ); break; @@ -2941,7 +2947,7 @@ bool FABMASTER::loadGraphics( BOARD* aBoard ) arc->SetArcGeometry( (wxPoint) src->result.GetP0(), (wxPoint) src->result.GetArcMid(), (wxPoint) src->result.GetP1() ); - arc->SetWidth( src->width ); + arc->SetStroke( STROKE_PARAMS( src->width, PLOT_DASH_TYPE::SOLID ) ); aBoard->Add( arc, ADD_MODE::APPEND ); break; @@ -2955,7 +2961,7 @@ bool FABMASTER::loadGraphics( BOARD* aBoard ) rect->SetLayer( layer ); rect->SetStart( wxPoint( src->start_x, src->start_y ) ); rect->SetEnd( wxPoint( src->end_x, src->end_y ) ); - rect->SetWidth( 0 ); + rect->SetStroke( STROKE_PARAMS( 0 ) ); rect->SetFilled( true ); aBoard->Add( rect, ADD_MODE::APPEND ); break; @@ -2990,9 +2996,7 @@ bool FABMASTER::loadGraphics( BOARD* aBoard ) bool FABMASTER::orderZones( BOARD* aBoard ) { - std::vector<ZONE*> zones = aBoard->Zones(); - - std::sort( zones.begin(), zones.end(), + std::sort( aBoard->Zones().begin(), aBoard->Zones().end(), [&]( const ZONE* a, const ZONE* b ) { if( a->GetLayer() == b->GetLayer() ) @@ -3004,7 +3008,7 @@ bool FABMASTER::orderZones( BOARD* aBoard ) PCB_LAYER_ID layer = UNDEFINED_LAYER; unsigned int priority = 0; - for( ZONE* zone : zones ) + for( ZONE* zone : aBoard->Zones() ) { /// Rule areas do not have priorities if( zone->GetIsRuleArea() ) diff --git a/pcbnew/plugins/geda/gpcb_plugin.cpp b/pcbnew/plugins/geda/gpcb_plugin.cpp index 7daf4e1bc5..6e9ab161e0 100644 --- a/pcbnew/plugins/geda/gpcb_plugin.cpp +++ b/pcbnew/plugins/geda/gpcb_plugin.cpp @@ -469,7 +469,8 @@ FOOTPRINT* GPCB_FPL_CACHE::parseFOOTPRINT( LINE_READER* aLineReader ) parseInt( parameters[3], conv_unit ) ) ); shape->SetEnd0( wxPoint( parseInt( parameters[4], conv_unit ), parseInt( parameters[5], conv_unit ) ) ); - shape->SetWidth( parseInt( parameters[6], conv_unit ) ); + shape->SetStroke( STROKE_PARAMS( parseInt( parameters[6], conv_unit ), + PLOT_DASH_TYPE::SOLID ) ); shape->SetDrawCoord(); footprint->Add( shape ); continue; @@ -517,7 +518,8 @@ FOOTPRINT* GPCB_FPL_CACHE::parseFOOTPRINT( LINE_READER* aLineReader ) // Angle value is clockwise in gpcb and Pcbnew. shape->SetArcAngleAndEnd0( sweep_angle ); - shape->SetWidth( parseInt( parameters[8], conv_unit ) ); + shape->SetStroke( STROKE_PARAMS( parseInt( parameters[8], conv_unit ), + PLOT_DASH_TYPE::SOLID ) ); shape->SetDrawCoord(); continue; } diff --git a/pcbnew/plugins/kicad/pcb_parser.cpp b/pcbnew/plugins/kicad/pcb_parser.cpp index 32d1e9b992..a0deb5a473 100644 --- a/pcbnew/plugins/kicad/pcb_parser.cpp +++ b/pcbnew/plugins/kicad/pcb_parser.cpp @@ -2366,6 +2366,7 @@ PCB_SHAPE* PCB_PARSER::parsePCB_SHAPE() T token; wxPoint pt; + STROKE_PARAMS stroke( 0, PLOT_DASH_TYPE::SOLID ); std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( nullptr ); switch( CurTok() ) @@ -2572,7 +2573,6 @@ PCB_SHAPE* PCB_PARSER::parsePCB_SHAPE() case T_gr_poly: { shape->SetShape( SHAPE_T::POLY ); - shape->SetWidth( 0 ); // this is the default value. will be (perhaps) modified later shape->SetPolyPoints( {} ); SHAPE_LINE_CHAIN& outline = shape->GetPolyShape().Outline( 0 ); @@ -2640,7 +2640,7 @@ PCB_SHAPE* PCB_PARSER::parsePCB_SHAPE() break; case T_width: - shape->SetWidth( parseBoardUnits( T_width ) ); + stroke.SetWidth( parseBoardUnits( T_width ) ); NeedRIGHT(); break; @@ -2699,7 +2699,7 @@ PCB_SHAPE* PCB_PARSER::parsePCB_SHAPE() { // Legacy versions didn't have a filled flag but allowed some shapes to indicate they // should be filled by specifying a 0 stroke-width. - if( shape->GetWidth() == 0 + if( stroke.GetWidth() == 0 && ( shape->GetShape() == SHAPE_T::RECT || shape->GetShape() == SHAPE_T::CIRCLE ) ) { shape->SetFilled( true ); @@ -2713,11 +2713,13 @@ PCB_SHAPE* PCB_PARSER::parsePCB_SHAPE() // Only filled shapes may have a zero line-width. This is not permitted in KiCad but some // external tools can generate invalid files. - if( shape->GetWidth() <= 0 && !shape->IsFilled() ) + if( stroke.GetWidth() <= 0 && !shape->IsFilled() ) { - shape->SetWidth( Millimeter2iu( DEFAULT_LINE_WIDTH ) ); + stroke.SetWidth( Millimeter2iu( DEFAULT_LINE_WIDTH ) ); } + shape->SetStroke( stroke ); + return shape.release(); } @@ -3670,6 +3672,7 @@ FP_SHAPE* PCB_PARSER::parseFP_SHAPE() wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as FP_SHAPE." ) ); wxPoint pt; + STROKE_PARAMS stroke( 0, PLOT_DASH_TYPE::SOLID ); T token; std::unique_ptr<FP_SHAPE> shape = std::make_unique<FP_SHAPE>( nullptr ); @@ -3933,7 +3936,7 @@ FP_SHAPE* PCB_PARSER::parseFP_SHAPE() break; case T_width: - shape->SetWidth( parseBoardUnits( T_width ) ); + stroke.SetWidth( parseBoardUnits( T_width ) ); NeedRIGHT(); break; @@ -3992,7 +3995,7 @@ FP_SHAPE* PCB_PARSER::parseFP_SHAPE() { // Legacy versions didn't have a filled flag but allowed some shapes to indicate they // should be filled by specifying a 0 stroke-width. - if( shape->GetWidth() == 0 + if( stroke.GetWidth() == 0 && ( shape->GetShape() == SHAPE_T::RECT || shape->GetShape() == SHAPE_T::CIRCLE ) ) { shape->SetFilled( true ); @@ -4006,11 +4009,13 @@ FP_SHAPE* PCB_PARSER::parseFP_SHAPE() // Only filled shapes may have a zero line-width. This is not permitted in KiCad but some // external tools can generate invalid files. - if( shape->GetWidth() <= 0 && !shape->IsFilled() ) + if( stroke.GetWidth() <= 0 && !shape->IsFilled() ) { - shape->SetWidth( Millimeter2iu( DEFAULT_LINE_WIDTH ) ); + stroke.SetWidth( Millimeter2iu( DEFAULT_LINE_WIDTH ) ); } + shape->SetStroke( stroke ); + return shape.release(); } diff --git a/pcbnew/plugins/legacy/legacy_plugin.cpp b/pcbnew/plugins/legacy/legacy_plugin.cpp index b792a4c3e7..6dbb0afe3c 100644 --- a/pcbnew/plugins/legacy/legacy_plugin.cpp +++ b/pcbnew/plugins/legacy/legacy_plugin.cpp @@ -1667,7 +1667,7 @@ void LEGACY_PLUGIN::loadFP_SHAPE( FOOTPRINT* aFootprint ) if( layer < FIRST_LAYER || layer > LAST_NON_COPPER_LAYER ) layer = SILKSCREEN_N_FRONT; - dwg->SetWidth( width ); + dwg->SetStroke( STROKE_PARAMS( width, PLOT_DASH_TYPE::SOLID ) ); dwg->SetLayer( leg_layer2new( m_cu_count, layer ) ); FP_SHAPE* fpShape = dwg.release(); @@ -1846,18 +1846,9 @@ void LEGACY_PLUGIN::loadPCB_LINE() dseg->SetShape( static_cast<SHAPE_T>( shape ) ); dseg->SetFilled( false ); - dseg->SetWidth( width ); - - if( dseg->GetShape() == SHAPE_T::ARC ) - { - dseg->SetCenter( wxPoint( start_x, start_y ) ); - dseg->SetStart( wxPoint( end_x, end_y ) ); - } - else - { - dseg->SetStart( wxPoint( start_x, start_y ) ); - dseg->SetEnd( wxPoint( end_x, end_y ) ); - } + dseg->SetStroke( STROKE_PARAMS( width, PLOT_DASH_TYPE::SOLID ) ); + dseg->SetStart( wxPoint( start_x, start_y ) ); + dseg->SetEnd( wxPoint( end_x, end_y ) ); } else if( TESTLINE( "De" ) ) { diff --git a/pcbnew/plugins/pcad/pcb_arc.cpp b/pcbnew/plugins/pcad/pcb_arc.cpp index 18208f7f41..d55ef9a173 100644 --- a/pcbnew/plugins/pcad/pcb_arc.cpp +++ b/pcbnew/plugins/pcad/pcb_arc.cpp @@ -178,7 +178,7 @@ void PCB_ARC::AddToFootprint( FOOTPRINT* aFootprint ) arc->SetStart0( wxPoint( m_StartX, m_StartY ) ); arc->SetArcAngleAndEnd0( -m_Angle ); - arc->SetWidth( m_Width ); + arc->SetStroke( STROKE_PARAMS( m_Width, PLOT_DASH_TYPE::SOLID ) ); arc->SetLayer( m_KiCadLayer ); arc->SetDrawCoord(); @@ -197,7 +197,7 @@ void PCB_ARC::AddToBoard() arc->SetCenter( wxPoint( m_positionX, m_positionY ) ); arc->SetStart( wxPoint( m_StartX, m_StartY ) ); arc->SetArcAngleAndEnd( -m_Angle ); - arc->SetWidth( m_Width ); + arc->SetStroke( STROKE_PARAMS( m_Width, PLOT_DASH_TYPE::SOLID ) ); } diff --git a/pcbnew/plugins/pcad/pcb_line.cpp b/pcbnew/plugins/pcad/pcb_line.cpp index cf143df363..99dfc97049 100644 --- a/pcbnew/plugins/pcad/pcb_line.cpp +++ b/pcbnew/plugins/pcad/pcb_line.cpp @@ -125,7 +125,7 @@ void PCB_LINE::AddToFootprint( FOOTPRINT* aFootprint ) segment->SetStart0( wxPoint( m_positionX, m_positionY ) ); segment->SetEnd0( wxPoint( m_ToX, m_ToY ) ); - segment->SetWidth( m_Width ); + segment->SetStroke( STROKE_PARAMS( m_Width, PLOT_DASH_TYPE::SOLID ) ); segment->SetLayer( m_KiCadLayer ); segment->SetDrawCoord(); @@ -156,7 +156,7 @@ void PCB_LINE::AddToBoard() segment->SetLayer( m_KiCadLayer ); segment->SetStart( wxPoint( m_positionX, m_positionY ) ); segment->SetEnd( wxPoint( m_ToX, m_ToY ) ); - segment->SetWidth( m_Width ); + segment->SetStroke( STROKE_PARAMS( m_Width, PLOT_DASH_TYPE::SOLID ) ); } } diff --git a/pcbnew/plugins/pcad/pcb_polygon.cpp b/pcbnew/plugins/pcad/pcb_polygon.cpp index 612f9cb085..f1e34eec88 100644 --- a/pcbnew/plugins/pcad/pcb_polygon.cpp +++ b/pcbnew/plugins/pcad/pcb_polygon.cpp @@ -166,7 +166,7 @@ void PCB_POLYGON::AddToFootprint( FOOTPRINT* aFootprint ) FP_SHAPE* dwg = new FP_SHAPE( aFootprint, SHAPE_T::POLY ); aFootprint->Add( dwg ); - dwg->SetWidth( 0 ); + dwg->SetStroke( STROKE_PARAMS( 0 ) ); dwg->SetLayer( m_KiCadLayer ); auto outline = new std::vector<wxPoint>; diff --git a/pcbnew/tools/convert_tool.cpp b/pcbnew/tools/convert_tool.cpp index 395dcfbd06..1581160123 100644 --- a/pcbnew/tools/convert_tool.cpp +++ b/pcbnew/tools/convert_tool.cpp @@ -200,7 +200,7 @@ int CONVERT_TOOL::CreatePolys( const TOOL_EVENT& aEvent ) graphic->SetShape( SHAPE_T::POLY ); graphic->SetFilled( false ); - graphic->SetWidth( poly.Outline( 0 ).Width() ); + graphic->SetStroke( STROKE_PARAMS( poly.Outline( 0 ).Width() ) ); graphic->SetLayer( destLayer ); graphic->SetPolyShape( poly ); @@ -329,15 +329,14 @@ SHAPE_POLY_SET CONVERT_TOOL::makePolysFromSegs( const std::deque<EDA_ITEM*>& aIt if( aItem->Type() == PCB_ARC_T ) { - std::shared_ptr<SHAPE> es = - static_cast<PCB_ARC*>( aItem )->GetEffectiveShape(); - arc = *static_cast<SHAPE_ARC*>( es.get() ); + PCB_ARC* pcb_arc = static_cast<PCB_ARC*>( aItem ); + arc = *static_cast<SHAPE_ARC*>( pcb_arc->GetEffectiveShape().get() ); } else { - PCB_SHAPE* ps = static_cast<PCB_SHAPE*>( aItem ); - arc = SHAPE_ARC( ps->GetStart(), ps->GetArcMid(), ps->GetEnd(), - ps->GetWidth() ); + PCB_SHAPE* pcb_shape = static_cast<PCB_SHAPE*>( aItem ); + arc = SHAPE_ARC( pcb_shape->GetStart(), pcb_shape->GetArcMid(), + pcb_shape->GetEnd(), pcb_shape->GetWidth() ); } if( aDirection ) @@ -715,8 +714,6 @@ int CONVERT_TOOL::CreateLines( const TOOL_EVENT& aEvent ) } else { - - if( !IsCopperLayer( targetLayer ) ) { if( copperLayer == UNSELECTED_LAYER ) @@ -825,7 +822,7 @@ int CONVERT_TOOL::SegmentToArc( const TOOL_EVENT& aEvent ) arc->SetFilled( false ); arc->SetLayer( layer ); - arc->SetWidth( line->GetWidth() ); + arc->SetStroke( line->GetStroke() ); arc->SetCenter( wxPoint( center ) ); arc->SetStart( wxPoint( start ) ); diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp index dd7f183007..9e965fd4f7 100644 --- a/pcbnew/tools/drawing_tool.cpp +++ b/pcbnew/tools/drawing_tool.cpp @@ -164,7 +164,7 @@ DRAWING_TOOL::DRAWING_TOOL() : m_frame( nullptr ), m_mode( MODE::NONE ), m_inDrawingTool( false ), - m_lineWidth( 1 ) + m_stroke( 1, PLOT_DASH_TYPE::DEFAULT, COLOR4D::UNSPECIFIED ) { } @@ -836,17 +836,17 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent ) } else if( evt->IsAction( &PCB_ACTIONS::incWidth ) && step != SET_ORIGIN ) { - m_lineWidth += WIDTH_STEP; - dimension->SetLineThickness( m_lineWidth ); + m_stroke.SetWidth( m_stroke.GetWidth() + WIDTH_STEP ); + dimension->SetLineThickness( m_stroke.GetWidth() ); m_view->Update( &preview ); frame()->SetMsgPanel( dimension ); } else if( evt->IsAction( &PCB_ACTIONS::decWidth ) && step != SET_ORIGIN ) { - if( m_lineWidth > WIDTH_STEP ) + if( (unsigned) m_stroke.GetWidth() > WIDTH_STEP ) { - m_lineWidth -= WIDTH_STEP; - dimension->SetLineThickness( m_lineWidth ); + m_stroke.SetWidth( m_stroke.GetWidth() - WIDTH_STEP ); + dimension->SetLineThickness( m_stroke.GetWidth() ); m_view->Update( &preview ); frame()->SetMsgPanel( dimension ); } @@ -1434,7 +1434,7 @@ bool DRAWING_TOOL::drawSegment( const std::string& aTool, PCB_SHAPE** aGraphic, PCB_SHAPE*& graphic = *aGraphic; PCB_LAYER_ID drawingLayer = m_frame->GetActiveLayer(); - m_lineWidth = getSegmentWidth( drawingLayer ); + m_stroke.SetWidth( getSegmentWidth( drawingLayer ) ); // geometric construction manager KIGFX::PREVIEW::TWO_POINT_GEOMETRY_MANAGER twoPointManager; @@ -1533,7 +1533,7 @@ bool DRAWING_TOOL::drawSegment( const std::string& aTool, PCB_SHAPE** aGraphic, else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) ) { drawingLayer = m_frame->GetActiveLayer(); - m_lineWidth = getSegmentWidth( drawingLayer ); + m_stroke.SetWidth( getSegmentWidth( drawingLayer ) ); if( graphic ) { @@ -1544,7 +1544,7 @@ bool DRAWING_TOOL::drawSegment( const std::string& aTool, PCB_SHAPE** aGraphic, } graphic->SetLayer( drawingLayer ); - graphic->SetWidth( m_lineWidth ); + graphic->SetStroke( m_stroke ); m_view->Update( &preview ); frame()->SetMsgPanel( graphic ); } @@ -1583,12 +1583,12 @@ bool DRAWING_TOOL::drawSegment( const std::string& aTool, PCB_SHAPE** aGraphic, aStartingPoint = NULLOPT; } - m_lineWidth = getSegmentWidth( drawingLayer ); + m_stroke.SetWidth( getSegmentWidth( drawingLayer ) ); // Init the new item attributes graphic->SetShape( static_cast<SHAPE_T>( shape ) ); graphic->SetFilled( false ); - graphic->SetWidth( m_lineWidth ); + graphic->SetStroke( m_stroke ); graphic->SetLayer( drawingLayer ); grid.SetSkipPoint( cursorPos ); @@ -1680,17 +1680,20 @@ bool DRAWING_TOOL::drawSegment( const std::string& aTool, PCB_SHAPE** aGraphic, } else if( evt->IsAction( &PCB_ACTIONS::incWidth ) ) { - m_lineWidth += WIDTH_STEP; - graphic->SetWidth( m_lineWidth ); + m_stroke.SetWidth( m_stroke.GetWidth() + WIDTH_STEP ); + graphic->SetStroke( m_stroke ); m_view->Update( &preview ); frame()->SetMsgPanel( graphic ); } - else if( evt->IsAction( &PCB_ACTIONS::decWidth ) && ( m_lineWidth > WIDTH_STEP ) ) + else if( evt->IsAction( &PCB_ACTIONS::decWidth ) ) { - m_lineWidth -= WIDTH_STEP; - graphic->SetWidth( m_lineWidth ); - m_view->Update( &preview ); - frame()->SetMsgPanel( graphic ); + if( (unsigned) m_stroke.GetWidth() > WIDTH_STEP ) + { + m_stroke.SetWidth( m_stroke.GetWidth() - WIDTH_STEP ); + graphic->SetStroke( m_stroke ); + m_view->Update( &preview ); + frame()->SetMsgPanel( graphic ); + } } else if( evt->IsAction( &ACTIONS::resetLocalCoords ) ) { @@ -1754,7 +1757,7 @@ bool DRAWING_TOOL::drawArc( const std::string& aTool, PCB_SHAPE** aGraphic, bool PCB_LAYER_ID drawingLayer = m_frame->GetActiveLayer(); - m_lineWidth = getSegmentWidth( drawingLayer ); + m_stroke.SetWidth( getSegmentWidth( drawingLayer ) ); // Arc geometric construction manager KIGFX::PREVIEW::ARC_GEOM_MANAGER arcManager; @@ -1855,12 +1858,12 @@ bool DRAWING_TOOL::drawArc( const std::string& aTool, PCB_SHAPE** aGraphic, bool m_controls->CaptureCursor( true ); drawingLayer = m_frame->GetActiveLayer(); - m_lineWidth = getSegmentWidth( drawingLayer ); + m_stroke.SetWidth( getSegmentWidth( drawingLayer ) ); // Init the new item attributes // (non-geometric, those are handled by the manager) graphic->SetShape( SHAPE_T::ARC ); - graphic->SetWidth( m_lineWidth ); + graphic->SetStroke( m_stroke ); if( !m_view->IsLayerVisible( drawingLayer ) ) { @@ -1890,7 +1893,7 @@ bool DRAWING_TOOL::drawArc( const std::string& aTool, PCB_SHAPE** aGraphic, bool else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) ) { drawingLayer = m_frame->GetActiveLayer(); - m_lineWidth = getSegmentWidth( drawingLayer ); + m_stroke.SetWidth( getSegmentWidth( drawingLayer ) ); if( graphic ) { @@ -1901,7 +1904,7 @@ bool DRAWING_TOOL::drawArc( const std::string& aTool, PCB_SHAPE** aGraphic, bool } graphic->SetLayer( drawingLayer ); - graphic->SetWidth( m_lineWidth ); + graphic->SetStroke( m_stroke ); m_view->Update( &preview ); frame()->SetMsgPanel( graphic ); } @@ -1938,17 +1941,20 @@ bool DRAWING_TOOL::drawArc( const std::string& aTool, PCB_SHAPE** aGraphic, bool } else if( evt->IsAction( &PCB_ACTIONS::incWidth ) ) { - m_lineWidth += WIDTH_STEP; - graphic->SetWidth( m_lineWidth ); + m_stroke.SetWidth( m_stroke.GetWidth() + WIDTH_STEP ); + graphic->SetStroke( m_stroke ); m_view->Update( &preview ); frame()->SetMsgPanel( graphic ); } - else if( evt->IsAction( &PCB_ACTIONS::decWidth ) && m_lineWidth > WIDTH_STEP ) + else if( evt->IsAction( &PCB_ACTIONS::decWidth ) ) { - m_lineWidth -= WIDTH_STEP; - graphic->SetWidth( m_lineWidth ); - m_view->Update( &preview ); - frame()->SetMsgPanel( graphic ); + if( (unsigned) m_stroke.GetWidth() > WIDTH_STEP ) + { + m_stroke.SetWidth( m_stroke.GetWidth() - WIDTH_STEP ); + graphic->SetStroke( m_stroke ); + m_view->Update( &preview ); + frame()->SetMsgPanel( graphic ); + } } else if( evt->IsAction( &PCB_ACTIONS::arcPosture ) ) { diff --git a/pcbnew/tools/drawing_tool.h b/pcbnew/tools/drawing_tool.h index c520ee8b38..207105c259 100644 --- a/pcbnew/tools/drawing_tool.h +++ b/pcbnew/tools/drawing_tool.h @@ -270,7 +270,7 @@ private: MODE m_mode; bool m_inDrawingTool; // Re-entrancy guard - unsigned int m_lineWidth; // Current line width for multi-segment drawing + STROKE_PARAMS m_stroke; // Current stroke for multi-segment drawing static const unsigned int WIDTH_STEP; // Amount of width change for one -/+ key press diff --git a/pcbnew/tools/pad_tool.cpp b/pcbnew/tools/pad_tool.cpp index 3b2e56b305..0ea7fc6637 100644 --- a/pcbnew/tools/pad_tool.cpp +++ b/pcbnew/tools/pad_tool.cpp @@ -617,7 +617,7 @@ PCB_LAYER_ID PAD_TOOL::explodePad( PAD* aPad ) shape->SetShape( primitive->GetShape() ); shape->SetFilled( primitive->IsFilled() ); - shape->SetWidth( primitive->GetWidth() ); + shape->SetStroke( primitive->GetStroke() ); switch( shape->GetShape() ) { @@ -738,7 +738,7 @@ void PAD_TOOL::recombinePad( PAD* aPad ) PCB_SHAPE* shape = new PCB_SHAPE( nullptr, SHAPE_T::POLY ); shape->SetFilled( true ); - shape->SetWidth( 0 ); + shape->SetStroke( STROKE_PARAMS( 0, PLOT_DASH_TYPE::SOLID ) ); shape->SetPolyShape( existingOutline ); shape->Move( - aPad->GetPosition() ); shape->Rotate( wxPoint( 0, 0 ), - aPad->GetOrientation() ); @@ -754,7 +754,7 @@ void PAD_TOOL::recombinePad( PAD* aPad ) pcbShape->SetShape( fpShape->GetShape() ); pcbShape->SetFilled( fpShape->IsFilled() ); - pcbShape->SetWidth( fpShape->GetWidth() ); + pcbShape->SetStroke( fpShape->GetStroke() ); switch( pcbShape->GetShape() ) diff --git a/pcbnew/tools/zone_create_helper.cpp b/pcbnew/tools/zone_create_helper.cpp index 36c89f9cb5..e22f9b3a73 100644 --- a/pcbnew/tools/zone_create_helper.cpp +++ b/pcbnew/tools/zone_create_helper.cpp @@ -236,7 +236,8 @@ void ZONE_CREATE_HELPER::commitZone( std::unique_ptr<ZONE> aZone ) else poly->SetFilled( true ); - poly->SetWidth( board->GetDesignSettings().GetLineThickness( m_params.m_layer ) ); + poly->SetStroke( STROKE_PARAMS( board->GetDesignSettings().GetLineThickness( layer ), + PLOT_DASH_TYPE::SOLID ) ); poly->SetLayer( layer ); poly->SetPolyShape( *aZone->Outline() ); diff --git a/qa/pcbnew_utils/board_construction_utils.cpp b/qa/pcbnew_utils/board_construction_utils.cpp index 98d1bf5298..a601740800 100644 --- a/qa/pcbnew_utils/board_construction_utils.cpp +++ b/qa/pcbnew_utils/board_construction_utils.cpp @@ -34,12 +34,12 @@ namespace KI_TEST void DrawSegment( FOOTPRINT& aFootprint, const SEG& aSeg, int aWidth, PCB_LAYER_ID aLayer ) { - auto seg = std::make_unique<FP_SHAPE>( &aFootprint, SHAPE_T::SEGMENT ); + std::unique_ptr<FP_SHAPE> seg = std::make_unique<FP_SHAPE>( &aFootprint, SHAPE_T::SEGMENT ); seg->SetStart0( (wxPoint) aSeg.A ); seg->SetEnd0( (wxPoint) aSeg.B ); - seg->SetWidth( aWidth ); + seg->SetStroke( STROKE_PARAMS( aWidth, PLOT_DASH_TYPE::SOLID ) ); seg->SetLayer( aLayer ); aFootprint.Add( seg.release() ); @@ -59,16 +59,16 @@ void DrawPolyline( FOOTPRINT& aFootprint, const std::vector<VECTOR2I>& aPts, int void DrawArc( FOOTPRINT& aFootprint, const VECTOR2I& aCentre, const VECTOR2I& aStart, double aAngle, int aWidth, PCB_LAYER_ID aLayer ) { - auto seg = std::make_unique<FP_SHAPE>( &aFootprint, SHAPE_T::ARC ); + std::unique_ptr<FP_SHAPE> arc = std::make_unique<FP_SHAPE>( &aFootprint, SHAPE_T::ARC ); - seg->SetCenter0( (wxPoint) aCentre ); - seg->SetStart0( (wxPoint) aStart ); - seg->SetArcAngleAndEnd0( aAngle * 10 ); + arc->SetCenter0( (wxPoint) aCentre ); + arc->SetStart0( (wxPoint) aStart ); + arc->SetArcAngleAndEnd0( aAngle * 10 ); - seg->SetWidth( aWidth ); - seg->SetLayer( aLayer ); + arc->SetStroke( STROKE_PARAMS( aWidth, PLOT_DASH_TYPE::SOLID ) ); + arc->SetLayer( aLayer ); - aFootprint.Add( seg.release() ); + aFootprint.Add( arc.release() ); }