diff --git a/common/import_gfx/graphics_importer.h b/common/import_gfx/graphics_importer.h index a4236dbbff..65afab2152 100644 --- a/common/import_gfx/graphics_importer.h +++ b/common/import_gfx/graphics_importer.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -208,22 +209,20 @@ public: * * @param aOrigin is the segment origin point expressed in mm. * @param aEnd is the segment end point expressed in mm. - * @param aWidth is the segment thickness in mm. Use -1 for default line thickness - * @param aColor is the shape color + * @param aStroke is the shape stroke parameters. */ - virtual void AddLine( const VECTOR2D& aOrigin, const VECTOR2D& aEnd, double aWidth, - const COLOR4D& aColor ) = 0; + virtual void AddLine( const VECTOR2D& aOrigin, const VECTOR2D& aEnd, + const STROKE_PARAMS& aStroke ) = 0; /** * Create an object representing a circle. * * @param aCenter is the circle center point expressed in mm. * @param aRadius is the circle radius expressed in mm. - * @param aWidth is the segment thickness in mm. Use -1 for default line thickness - * @param aColor is the shape color + * @param aStroke is the shape stroke parameters. */ - virtual void AddCircle( const VECTOR2D& aCenter, double aRadius, double aWidth, bool aFilled, - const COLOR4D& aColor ) = 0; + virtual void AddCircle( const VECTOR2D& aCenter, double aRadius, const STROKE_PARAMS& aStroke, + bool aFilled, const COLOR4D& aFillColor ) = 0; /** * Create an object representing an arc. @@ -232,14 +231,21 @@ public: * @param aStart is the arc arm end point expressed in mm. * Its length is the arc radius. * @param aAngle is the arc angle. - * @param aWidth is the segment thickness in mm. Use -1 for default line thickness - * @param aColor is the shape color + * @param aStroke is the shape stroke parameters. */ virtual void AddArc( const VECTOR2D& aCenter, const VECTOR2D& aStart, const EDA_ANGLE& aAngle, - double aWidth, const COLOR4D& aColor ) = 0; + const STROKE_PARAMS& aStroke ) = 0; - virtual void AddPolygon( const std::vector& aVertices, double aWidth, - const COLOR4D& aColor ) = 0; + /** + * Create an object representing a polygon. + * + * @param aVertices is the array of vertices. + * @param aWidth is the stroke width. + * @param aStroke is the shape stroke parameters. + * @param aFillColor is the fill color. + */ + virtual void AddPolygon( const std::vector& aVertices, const STROKE_PARAMS& aStroke, + bool aFilled, const COLOR4D& aFillColor ) = 0; /** * Create an object representing a text. @@ -266,12 +272,11 @@ public: * @param aBezierControl1 is the first Bezier control point expressed in mm. * @param aBezierControl2 is the second Bezier control point expressed in mm. * @param aEnd is the curve end point expressed in mm. - * @param aWidth is the segment thickness in mm. Use -1 for default line thickness - * @param aColor is the shape color + * @param aStroke is the shape stroke parameters. */ virtual void AddSpline( const VECTOR2D& aStart, const VECTOR2D& aBezierControl1, - const VECTOR2D& aBezierControl2, const VECTOR2D& aEnd, double aWidth, - const COLOR4D& aColor ) = 0; + const VECTOR2D& aBezierControl2, const VECTOR2D& aEnd, + const STROKE_PARAMS& aStroke ) = 0; protected: ///< Add an item to the imported shapes list. diff --git a/common/import_gfx/graphics_importer_buffer.cpp b/common/import_gfx/graphics_importer_buffer.cpp index 36d9ab47d6..f37e833c7c 100644 --- a/common/import_gfx/graphics_importer_buffer.cpp +++ b/common/import_gfx/graphics_importer_buffer.cpp @@ -38,32 +38,35 @@ static std::unique_ptr make_shape( const Args&... aArguments ) return std::make_unique( aArguments... ); } -void GRAPHICS_IMPORTER_BUFFER::AddLine( const VECTOR2D& aStart, const VECTOR2D& aEnd, double aWidth, - const COLOR4D& aColor ) +void GRAPHICS_IMPORTER_BUFFER::AddLine( const VECTOR2D& aStart, const VECTOR2D& aEnd, + const STROKE_PARAMS& aStroke ) { - m_shapes.push_back( make_shape< IMPORTED_LINE >( aStart, aEnd, aWidth, aColor ) ); + m_shapes.push_back( make_shape( aStart, aEnd, aStroke ) ); } -void GRAPHICS_IMPORTER_BUFFER::AddCircle( const VECTOR2D& aCenter, double aRadius, double aWidth, - bool aFilled, const COLOR4D& aColor ) +void GRAPHICS_IMPORTER_BUFFER::AddCircle( const VECTOR2D& aCenter, double aRadius, + const STROKE_PARAMS& aStroke, bool aFilled, + const COLOR4D& aFillColor ) { - m_shapes.push_back( make_shape( aCenter, aRadius, aWidth, aFilled, aColor ) ); + m_shapes.push_back( + make_shape( aCenter, aRadius, aStroke, aFilled, aFillColor ) ); } void GRAPHICS_IMPORTER_BUFFER::AddArc( const VECTOR2D& aCenter, const VECTOR2D& aStart, - const EDA_ANGLE& aAngle, double aWidth, - const COLOR4D& aColor ) + const EDA_ANGLE& aAngle, const STROKE_PARAMS& aStroke ) { - m_shapes.push_back( make_shape( aCenter, aStart, aAngle, aWidth, aColor ) ); + m_shapes.push_back( make_shape( aCenter, aStart, aAngle, aStroke ) ); } -void GRAPHICS_IMPORTER_BUFFER::AddPolygon( const std::vector& aVertices, double aWidth, - const COLOR4D& aColor ) +void GRAPHICS_IMPORTER_BUFFER::AddPolygon( const std::vector& aVertices, + const STROKE_PARAMS& aStroke, bool aFilled, + const COLOR4D& aFillColor ) { - m_shapes.push_back( make_shape( aVertices, aWidth, aColor ) ); + m_shapes.push_back( make_shape( aVertices, aStroke, aFilled, aFillColor ) ); + m_shapes.back()->SetParentShapeIndex( m_shapeFillRules.size() - 1 ); } @@ -73,16 +76,17 @@ void GRAPHICS_IMPORTER_BUFFER::AddText( const VECTOR2D& aOrigin, const wxString& double aOrientation, GR_TEXT_H_ALIGN_T aHJustify, GR_TEXT_V_ALIGN_T aVJustify, const COLOR4D& aColor ) { - m_shapes.push_back( make_shape< IMPORTED_TEXT >( aOrigin, aText, aHeight, aWidth, - aThickness, aOrientation, aHJustify, aVJustify, aColor ) ); + m_shapes.push_back( make_shape( aOrigin, aText, aHeight, aWidth, aThickness, + aOrientation, aHJustify, aVJustify, aColor ) ); } void GRAPHICS_IMPORTER_BUFFER::AddSpline( const VECTOR2D& aStart, const VECTOR2D& aBezierControl1, const VECTOR2D& aBezierControl2, const VECTOR2D& aEnd, - double aWidth, const COLOR4D& aColor ) + const STROKE_PARAMS& aStroke ) { - m_shapes.push_back( make_shape( aStart, aBezierControl1, aBezierControl2, aEnd, aWidth, aColor ) ); + m_shapes.push_back( make_shape( aStart, aBezierControl1, aBezierControl2, aEnd, + aStroke ) ); } @@ -101,8 +105,8 @@ void GRAPHICS_IMPORTER_BUFFER::ImportTo( GRAPHICS_IMPORTER& aImporter ) // converts a single SVG-style polygon (multiple outlines, hole detection based on orientation, custom fill rule) to a format that can be digested by KiCad (single outline, fractured) static void convertPolygon( std::list>& aShapes, std::vector& aPaths, - GRAPHICS_IMPORTER::POLY_FILL_RULE aFillRule, double aWidth, - const COLOR4D& aColor ) + GRAPHICS_IMPORTER::POLY_FILL_RULE aFillRule, + const STROKE_PARAMS& aStroke, bool aFilled, const COLOR4D& aFillColor ) { double minX = std::numeric_limits::max(); double minY = minX; @@ -170,16 +174,18 @@ static void convertPolygon( std::list>& aShapes, pts.emplace_back( VECTOR2D( xp, yp ) ); } - aShapes.push_back( std::make_unique( pts, aWidth, aColor ) ); + aShapes.push_back( + std::make_unique( pts, aStroke, aFilled, aFillColor ) ); } } void GRAPHICS_IMPORTER_BUFFER::PostprocessNestedPolygons() { - int curShapeIdx = -1; - double lastWidth = 0; - COLOR4D lastColor = COLOR4D::UNSPECIFIED; + int curShapeIdx = -1; + STROKE_PARAMS lastStroke; + bool lastFilled = false; + COLOR4D lastFillColor = COLOR4D::UNSPECIFIED; std::list> newShapes; std::vector polypaths; @@ -198,19 +204,24 @@ void GRAPHICS_IMPORTER_BUFFER::PostprocessNestedPolygons() if( index != curShapeIdx && curShapeIdx >= 0 ) { - convertPolygon( newShapes, polypaths, m_shapeFillRules[curShapeIdx], lastWidth, - lastColor ); + convertPolygon( newShapes, polypaths, m_shapeFillRules[curShapeIdx], lastStroke, + lastFilled, lastFillColor ); + polypaths.clear(); } curShapeIdx = index; - lastWidth = poly->GetWidth(); - lastColor = poly->GetColor(); + lastStroke = poly->GetStroke(); + lastFilled = poly->isFilled(); + lastFillColor = poly->GetFillColor(); polypaths.push_back( poly ); } if( curShapeIdx >= 0 ) - convertPolygon( newShapes, polypaths, m_shapeFillRules[curShapeIdx], lastWidth, lastColor ); + { + convertPolygon( newShapes, polypaths, m_shapeFillRules[curShapeIdx], lastStroke, lastFilled, + lastFillColor ); + } m_shapes.swap( newShapes ); } diff --git a/common/import_gfx/graphics_importer_buffer.h b/common/import_gfx/graphics_importer_buffer.h index 26889e7acf..09cf7920f8 100644 --- a/common/import_gfx/graphics_importer_buffer.h +++ b/common/import_gfx/graphics_importer_buffer.h @@ -53,16 +53,14 @@ protected: class IMPORTED_LINE : public IMPORTED_SHAPE { public: - IMPORTED_LINE( const VECTOR2D& aStart, const VECTOR2D& aEnd, double aWidth, - const COLOR4D& aColor ) : - m_start( aStart ), - m_end( aEnd ), m_width( aWidth ), m_color( aColor ) + IMPORTED_LINE( const VECTOR2D& aStart, const VECTOR2D& aEnd, const STROKE_PARAMS& aStroke ) : + m_start( aStart ), m_end( aEnd ), m_stroke( aStroke ) { } void ImportTo( GRAPHICS_IMPORTER& aImporter ) const override { - aImporter.AddLine( m_start, m_end, m_width, m_color ); + aImporter.AddLine( m_start, m_end, m_stroke ); } virtual std::unique_ptr clone() const override @@ -70,33 +68,32 @@ public: return std::make_unique( *this ); } - void Transform(const MATRIX3x3D& aTransform, const VECTOR2D& aTranslation) override + void Transform( const MATRIX3x3D& aTransform, const VECTOR2D& aTranslation ) override { m_start = aTransform * m_start + aTranslation; m_end = aTransform * m_end + aTranslation; } private: - VECTOR2D m_start; - VECTOR2D m_end; - double m_width; - COLOR4D m_color; + VECTOR2D m_start; + VECTOR2D m_end; + STROKE_PARAMS m_stroke; }; class IMPORTED_CIRCLE : public IMPORTED_SHAPE { public: - IMPORTED_CIRCLE( const VECTOR2D& aCenter, double aRadius, double aWidth, bool aFilled, - const COLOR4D& aColor ) : + IMPORTED_CIRCLE( const VECTOR2D& aCenter, double aRadius, const STROKE_PARAMS& aStroke, + bool aFilled, const COLOR4D& aFillColor ) : m_center( aCenter ), - m_radius( aRadius ), m_width( aWidth ), m_filled( aFilled ), m_color( aColor ) + m_radius( aRadius ), m_stroke( aStroke ), m_filled( aFilled ), m_fillColor( aFillColor ) { } void ImportTo( GRAPHICS_IMPORTER& aImporter ) const override { - aImporter.AddCircle( m_center, m_radius, m_width, m_filled, m_color ); + aImporter.AddCircle( m_center, m_radius, m_stroke, m_filled, m_fillColor ); } virtual std::unique_ptr clone() const override @@ -116,11 +113,11 @@ public: } private: - VECTOR2D m_center; - double m_radius; - double m_width; - bool m_filled; - COLOR4D m_color; + VECTOR2D m_center; + double m_radius; + STROKE_PARAMS m_stroke; + bool m_filled; + COLOR4D m_fillColor; }; @@ -128,15 +125,15 @@ class IMPORTED_ARC : public IMPORTED_SHAPE { public: IMPORTED_ARC( const VECTOR2D& aCenter, const VECTOR2D& aStart, const EDA_ANGLE& aAngle, - double aWidth, const COLOR4D& aColor ) : + const STROKE_PARAMS& aStroke ) : m_center( aCenter ), - m_start( aStart ), m_angle( aAngle ), m_width( aWidth ), m_color( aColor ) + m_start( aStart ), m_angle( aAngle ), m_stroke( aStroke ) { } void ImportTo( GRAPHICS_IMPORTER& aImporter ) const override { - aImporter.AddArc( m_center, m_start, m_angle, m_width, m_color ); + aImporter.AddArc( m_center, m_start, m_angle, m_stroke ); } virtual std::unique_ptr clone() const override @@ -151,27 +148,26 @@ public: } private: - VECTOR2D m_center; - VECTOR2D m_start; - EDA_ANGLE m_angle; - double m_width; - COLOR4D m_color; + VECTOR2D m_center; + VECTOR2D m_start; + EDA_ANGLE m_angle; + STROKE_PARAMS m_stroke; }; class IMPORTED_POLYGON : public IMPORTED_SHAPE { public: - IMPORTED_POLYGON( const std::vector& aVertices, double aWidth, - const COLOR4D& aColor ) : + IMPORTED_POLYGON( const std::vector& aVertices, const STROKE_PARAMS& aStroke, + bool aFilled, const COLOR4D& aFillColor ) : m_vertices( aVertices ), - m_width( aWidth ), m_color( aColor ) + m_stroke( aStroke ), m_filled( aFilled ), m_fillColor( aFillColor ) { } void ImportTo( GRAPHICS_IMPORTER& aImporter ) const override { - aImporter.AddPolygon( m_vertices, m_width, m_color ); + aImporter.AddPolygon( m_vertices, m_stroke, m_filled, m_fillColor ); } virtual std::unique_ptr clone() const override @@ -181,7 +177,7 @@ public: void Transform( const MATRIX3x3D& aTransform, const VECTOR2D& aTranslation ) override { - for(VECTOR2D& vert : m_vertices ) + for( VECTOR2D& vert : m_vertices ) { vert = aTransform * vert + aTranslation; } @@ -189,14 +185,17 @@ public: std::vector& Vertices() { return m_vertices; } - double GetWidth() const { return m_width; } + bool isFilled() const { return m_filled; } - const COLOR4D& GetColor() const { return m_color; } + const COLOR4D& GetFillColor() const { return m_fillColor; } + + const STROKE_PARAMS& GetStroke() const { return m_stroke; } private: std::vector m_vertices; - double m_width; - COLOR4D m_color; + STROKE_PARAMS m_stroke; + bool m_filled; + COLOR4D m_fillColor; }; @@ -246,17 +245,17 @@ class IMPORTED_SPLINE : public IMPORTED_SHAPE { public: IMPORTED_SPLINE( const VECTOR2D& aStart, const VECTOR2D& aBezierControl1, - const VECTOR2D& aBezierControl2, const VECTOR2D& aEnd, double aWidth, - const COLOR4D& aColor ) : + const VECTOR2D& aBezierControl2, const VECTOR2D& aEnd, + const STROKE_PARAMS& aStroke ) : m_start( aStart ), m_bezierControl1( aBezierControl1 ), m_bezierControl2( aBezierControl2 ), m_end( aEnd ), - m_width( aWidth ), m_color( aColor ) + m_stroke( aStroke ) { } void ImportTo( GRAPHICS_IMPORTER& aImporter ) const override { - aImporter.AddSpline( m_start, m_bezierControl1, m_bezierControl2, m_end, m_width, m_color ); + aImporter.AddSpline( m_start, m_bezierControl1, m_bezierControl2, m_end, m_stroke ); } virtual std::unique_ptr clone() const override @@ -273,38 +272,37 @@ public: } private: - VECTOR2D m_start; - VECTOR2D m_bezierControl1; - VECTOR2D m_bezierControl2; - VECTOR2D m_end; - double m_width; - COLOR4D m_color; + VECTOR2D m_start; + VECTOR2D m_bezierControl1; + VECTOR2D m_bezierControl2; + VECTOR2D m_end; + STROKE_PARAMS m_stroke; }; class GRAPHICS_IMPORTER_BUFFER : public GRAPHICS_IMPORTER { public: - void AddLine( const VECTOR2D& aStart, const VECTOR2D& aEnd, double aWidth, - const COLOR4D& aColor = COLOR4D::UNSPECIFIED ) override; + void AddLine( const VECTOR2D& aStart, const VECTOR2D& aEnd, + const STROKE_PARAMS& aStroke ) override; - void AddCircle( const VECTOR2D& aCenter, double aRadius, double aWidth, bool aFilled, - const COLOR4D& aColor = COLOR4D::UNSPECIFIED ) override; + void AddCircle( const VECTOR2D& aCenter, double aRadius, const STROKE_PARAMS& aStroke, + bool aFilled, const COLOR4D& aFillColor = COLOR4D::UNSPECIFIED ) override; void AddArc( const VECTOR2D& aCenter, const VECTOR2D& aStart, const EDA_ANGLE& aAngle, - double aWidth, const COLOR4D& aColor = COLOR4D::UNSPECIFIED ) override; + const STROKE_PARAMS& aStroke ) override; - void AddPolygon( const std::vector& aVertices, double aWidth, - const COLOR4D& aColor = COLOR4D::UNSPECIFIED ) override; + void AddPolygon( const std::vector& aVertices, const STROKE_PARAMS& aStroke, + bool aFilled, const COLOR4D& aFillColor = COLOR4D::UNSPECIFIED ) override; void AddText( const VECTOR2D& aOrigin, const wxString& aText, double aHeight, double aWidth, double aThickness, double aOrientation, GR_TEXT_H_ALIGN_T aHJustify, GR_TEXT_V_ALIGN_T aVJustify, const COLOR4D& aColor = COLOR4D::UNSPECIFIED ) override; - void AddSpline( const VECTOR2D& aStart, const VECTOR2D& BezierControl1, - const VECTOR2D& BezierControl2, const VECTOR2D& aEnd, double aWidth, - const COLOR4D& aColor = COLOR4D::UNSPECIFIED ) override; + void AddSpline( const VECTOR2D& aStart, const VECTOR2D& aBezierControl1, + const VECTOR2D& aBezierControl2, const VECTOR2D& aEnd, + const STROKE_PARAMS& aStroke ) override; void ImportTo( GRAPHICS_IMPORTER& aImporter ); void AddShape( std::unique_ptr& aShape ); diff --git a/common/import_gfx/svg_import_plugin.cpp b/common/import_gfx/svg_import_plugin.cpp index cc4c76905b..d83020bf9f 100644 --- a/common/import_gfx/svg_import_plugin.cpp +++ b/common/import_gfx/svg_import_plugin.cpp @@ -113,21 +113,69 @@ bool SVG_IMPORT_PLUGIN::Import() double lineWidth = shape->stroke.type != NSVG_PAINT_NONE ? shape->strokeWidth : -1; bool filled = shape->fill.type != NSVG_PAINT_NONE && alpha( shape->fill.color ) > 0; - COLOR4D color = COLOR4D::UNSPECIFIED; + COLOR4D fillColor = COLOR4D::UNSPECIFIED; if( shape->fill.type == NSVG_PAINT_COLOR ) { unsigned int icolor = shape->fill.color; - color.r = std::clamp( ( icolor >> 0 ) & 0xFF, 0u, 255u ) / 255.0; - color.g = std::clamp( ( icolor >> 8 ) & 0xFF, 0u, 255u ) / 255.0; - color.b = std::clamp( ( icolor >> 16 ) & 0xFF, 0u, 255u ) / 255.0; - color.a = std::clamp( ( icolor >> 24 ) & 0xFF, 0u, 255u ) / 255.0; + fillColor.r = std::clamp( ( icolor >> 0 ) & 0xFF, 0u, 255u ) / 255.0; + fillColor.g = std::clamp( ( icolor >> 8 ) & 0xFF, 0u, 255u ) / 255.0; + fillColor.b = std::clamp( ( icolor >> 16 ) & 0xFF, 0u, 255u ) / 255.0; + fillColor.a = std::clamp( ( icolor >> 24 ) & 0xFF, 0u, 255u ) / 255.0; - if( color == COLOR4D::BLACK ) // nanosvg probably didn't read it properly, use default - color = COLOR4D::UNSPECIFIED; + // nanosvg probably didn't read it properly, use default + if( fillColor == COLOR4D::BLACK ) + fillColor = COLOR4D::UNSPECIFIED; } + COLOR4D strokeColor = COLOR4D::UNSPECIFIED; + + if( shape->stroke.type == NSVG_PAINT_COLOR ) + { + unsigned int icolor = shape->stroke.color; + + strokeColor.r = std::clamp( ( icolor >> 0 ) & 0xFF, 0u, 255u ) / 255.0; + strokeColor.g = std::clamp( ( icolor >> 8 ) & 0xFF, 0u, 255u ) / 255.0; + strokeColor.b = std::clamp( ( icolor >> 16 ) & 0xFF, 0u, 255u ) / 255.0; + strokeColor.a = std::clamp( ( icolor >> 24 ) & 0xFF, 0u, 255u ) / 255.0; + + // nanosvg probably didn't read it properly, use default + if( strokeColor == COLOR4D::BLACK ) + strokeColor = COLOR4D::UNSPECIFIED; + } + + PLOT_DASH_TYPE dashType = PLOT_DASH_TYPE::SOLID; + + if( shape->strokeDashCount > 0 ) + { + float* dashArray = shape->strokeDashArray; + + int dotCount = 0; + int dashCount = 0; + + const float dashThreshold = shape->strokeWidth * 1.9f; + + for( int i = 0; i < shape->strokeDashCount; i += 2 ) + { + if( dashArray[i] < dashThreshold ) + dotCount++; + else + dashCount++; + } + + if( dotCount > 0 && dashCount == 0 ) + dashType = PLOT_DASH_TYPE::DOT; + else if( dotCount == 0 && dashCount > 0 ) + dashType = PLOT_DASH_TYPE::DASH; + else if( dotCount == 1 && dashCount == 1 ) + dashType = PLOT_DASH_TYPE::DASHDOT; + else if( dotCount == 2 && dashCount == 1 ) + dashType = PLOT_DASH_TYPE::DASHDOTDOT; + } + + STROKE_PARAMS stroke( lineWidth, dashType, strokeColor ); + GRAPHICS_IMPORTER::POLY_FILL_RULE rule = GRAPHICS_IMPORTER::PF_NONZERO; switch( shape->fillRule ) @@ -143,7 +191,7 @@ bool SVG_IMPORT_PLUGIN::Import() { bool closed = path->closed || filled || rule == GRAPHICS_IMPORTER::PF_EVEN_ODD; - DrawPath( path->pts, path->npts, closed, filled, lineWidth, color ); + DrawPath( path->pts, path->npts, closed, stroke, filled, fillColor ); } } @@ -204,18 +252,19 @@ BOX2D SVG_IMPORT_PLUGIN::GetImageBBox() const } -void SVG_IMPORT_PLUGIN::DrawPath( const float* aPoints, int aNumPoints, bool aPoly, bool aFilled, - double aLineWidth, const COLOR4D& aColor ) +void SVG_IMPORT_PLUGIN::DrawPath( const float* aPoints, int aNumPoints, bool aClosedPath, + const STROKE_PARAMS& aStroke, bool aFilled, + const COLOR4D& aFillColor ) { - std::vector< VECTOR2D > collectedPathPoints; + std::vector collectedPathPoints; if( aNumPoints > 0 ) DrawCubicBezierPath( aPoints, aNumPoints, collectedPathPoints ); - if( aPoly && aFilled ) - DrawPolygon( collectedPathPoints, aLineWidth, aColor ); + if( aClosedPath ) + DrawPolygon( collectedPathPoints, aStroke, aFilled, aFillColor ); else - DrawLineSegments( collectedPathPoints, aLineWidth, aColor ); + DrawLineSegments( collectedPathPoints, aStroke ); } @@ -250,20 +299,21 @@ void SVG_IMPORT_PLUGIN::DrawCubicBezierCurve( const float* aPoints, } -void SVG_IMPORT_PLUGIN::DrawPolygon( const std::vector& aPoints, double aWidth, - const COLOR4D& aColor ) +void SVG_IMPORT_PLUGIN::DrawPolygon( const std::vector& aPoints, + const STROKE_PARAMS& aStroke, bool aFilled, + const COLOR4D& aFillColor ) { - m_internalImporter.AddPolygon( aPoints, aWidth, aColor ); + m_internalImporter.AddPolygon( aPoints, aStroke, aFilled, aFillColor ); } -void SVG_IMPORT_PLUGIN::DrawLineSegments( const std::vector& aPoints, double aWidth, - const COLOR4D& aColor ) +void SVG_IMPORT_PLUGIN::DrawLineSegments( const std::vector& aPoints, + const STROKE_PARAMS& aStroke ) { unsigned int numLineStartPoints = aPoints.size() - 1; for( unsigned int pointIndex = 0; pointIndex < numLineStartPoints; ++pointIndex ) - m_internalImporter.AddLine( aPoints[ pointIndex ], aPoints[ pointIndex + 1 ], aWidth, aColor ); + m_internalImporter.AddLine( aPoints[pointIndex], aPoints[pointIndex + 1], aStroke ); } diff --git a/common/import_gfx/svg_import_plugin.h b/common/import_gfx/svg_import_plugin.h index 698e5d18f5..b711a2e568 100644 --- a/common/import_gfx/svg_import_plugin.h +++ b/common/import_gfx/svg_import_plugin.h @@ -31,6 +31,7 @@ #include #include +#include class SVG_IMPORT_PLUGIN : public GRAPHICS_IMPORT_PLUGIN @@ -70,18 +71,18 @@ public: virtual BOX2D GetImageBBox() const override; private: - void DrawPath( const float* aPoints, int aNumPoints, bool aClosedPath, bool aFilled, - double aLineWidth, const COLOR4D& aColor ); + void DrawPath( const float* aPoints, int aNumPoints, bool aClosedPath, + const STROKE_PARAMS& aStroke, bool aFilled, const COLOR4D& aFillColor ); void DrawCubicBezierPath( const float* aPoints, int aNumPoints, std::vector& aGeneratedPoints ); void DrawCubicBezierCurve( const float* aPoints, std::vector& aGeneratedPoints ); - void DrawPolygon( const std::vector& aPoints, double aWidth, const COLOR4D& aColor ); + void DrawPolygon( const std::vector& aPoints, const STROKE_PARAMS& aStroke, + bool aFilled, const COLOR4D& aFillColor ); - void DrawLineSegments( const std::vector& aPoints, double aWidth, - const COLOR4D& aColor ); + void DrawLineSegments( const std::vector& aPoints, const STROKE_PARAMS& aStroke ); struct NSVGimage* m_parsedImage; diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index ee65396a5e..788f5212a3 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -282,6 +282,8 @@ set ( EESCHEMA_LIBEDIT_SRCS ) set( EESCHEMA_IMPORT_GFX + import_gfx/dialog_import_gfx_sch_base.cpp + import_gfx/dialog_import_gfx_sch.cpp import_gfx/graphics_importer_lib_symbol.cpp ) diff --git a/eeschema/eeschema_settings.cpp b/eeschema/eeschema_settings.cpp index 5266bee155..e273e35b9f 100644 --- a/eeschema/eeschema_settings.cpp +++ b/eeschema/eeschema_settings.cpp @@ -121,6 +121,7 @@ EESCHEMA_SETTINGS::EESCHEMA_SETTINGS() : m_NetlistPanel(), m_PlotPanel(), m_SymChooserPanel(), + m_ImportGraphics(), m_Selection(), m_Simulator(), m_RescueNeverShow( false ) @@ -551,6 +552,27 @@ EESCHEMA_SETTINGS::EESCHEMA_SETTINGS() : m_params.emplace_back( new PARAM( "symbol_chooser.place_all_units", &m_SymChooserPanel.place_all_units, true ) ); + m_params.emplace_back( new PARAM( "import_graphics.interactive_placement", + &m_ImportGraphics.interactive_placement, true ) ); + + m_params.emplace_back( new PARAM( "import_graphics.line_width_units", + &m_ImportGraphics.dxf_line_width_units, 0 ) ); + + m_params.emplace_back( new PARAM( "import_graphics.line_width", + &m_ImportGraphics.dxf_line_width, 0.2 ) ); + + m_params.emplace_back( new PARAM( "import_graphics.origin_units", + &m_ImportGraphics.origin_units, 0 ) ); + + m_params.emplace_back( new PARAM( "import_graphics.origin_x", + &m_ImportGraphics.origin_x, 0 ) ); + + m_params.emplace_back( new PARAM( "import_graphics.origin_y", + &m_ImportGraphics.origin_y, 0 ) ); + + m_params.emplace_back( new PARAM( "import_graphics.dxf_units", + &m_ImportGraphics.dxf_units, 0 ) ); + m_params.emplace_back( new PARAM( "system.never_show_rescue_dialog", &m_RescueNeverShow, false ) ); diff --git a/eeschema/eeschema_settings.h b/eeschema/eeschema_settings.h index 1282b017b5..ae4879eb98 100644 --- a/eeschema/eeschema_settings.h +++ b/eeschema/eeschema_settings.h @@ -262,6 +262,18 @@ public: bool place_all_units; }; + struct DIALOG_IMPORT_GRAPHICS + { + bool interactive_placement; + wxString last_file; + double dxf_line_width; + int dxf_line_width_units; + int origin_units; + double origin_x; + double origin_y; + int dxf_units; + }; + struct SIMULATOR { int plot_panel_width; @@ -334,6 +346,8 @@ public: PANEL_SYM_CHOOSER m_SymChooserPanel; + DIALOG_IMPORT_GRAPHICS m_ImportGraphics; + SELECTION m_Selection; SIMULATOR m_Simulator; diff --git a/eeschema/import_gfx/dialog_import_gfx_sch.cpp b/eeschema/import_gfx/dialog_import_gfx_sch.cpp new file mode 100644 index 0000000000..b1358473cc --- /dev/null +++ b/eeschema/import_gfx/dialog_import_gfx_sch.cpp @@ -0,0 +1,311 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the 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 "dialog_import_gfx_sch.h" + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + +// Static members of DIALOG_IMPORT_GFX_SCH, to remember the user's choices during the session +bool DIALOG_IMPORT_GFX_SCH::m_placementInteractive = true; +double DIALOG_IMPORT_GFX_SCH::m_importScale = 1.0; // Do not change the imported items size + + +const std::map dxfUnitsMap = { + { DXF_IMPORT_UNITS::INCHES, _( "Inches" ) }, + { DXF_IMPORT_UNITS::MILLIMETERS, _( "Millimeters" ) }, + { DXF_IMPORT_UNITS::MILS, _( "Mils" ) }, + { DXF_IMPORT_UNITS::CENTIMETERS, _( "Centimeter" ) }, + { DXF_IMPORT_UNITS::FEET, _( "Feet" ) }, +}; + + +DIALOG_IMPORT_GFX_SCH::DIALOG_IMPORT_GFX_SCH( SCH_BASE_FRAME* aParent ) : + DIALOG_IMPORT_GFX_SCH_BASE( aParent ), + m_parent( aParent ), + m_xOrigin( aParent, m_xLabel, m_xCtrl, m_xUnits ), + m_yOrigin( aParent, m_yLabel, m_yCtrl, m_yUnits ), + m_defaultLineWidth( aParent, m_lineWidthLabel, m_lineWidthCtrl, m_lineWidthUnits ) +{ + auto initWidgetsFromSettings = [&]( const auto& aCfg ) + { + m_placementInteractive = aCfg->m_ImportGraphics.interactive_placement; + + m_xOrigin.SetValue( aCfg->m_ImportGraphics.origin_x * schIUScale.IU_PER_MM ); + m_yOrigin.SetValue( aCfg->m_ImportGraphics.origin_y * schIUScale.IU_PER_MM ); + m_defaultLineWidth.SetValue( aCfg->m_ImportGraphics.dxf_line_width * schIUScale.IU_PER_MM ); + + m_textCtrlFileName->SetValue( aCfg->m_ImportGraphics.last_file ); + m_rbInteractivePlacement->SetValue( m_placementInteractive ); + m_rbAbsolutePlacement->SetValue( !m_placementInteractive ); + + m_importScaleCtrl->SetValue( wxString::Format( wxT( "%f" ), m_importScale ) ); + + for( const std::pair& unitEntry : dxfUnitsMap ) + m_choiceDxfUnits->Append( unitEntry.second ); + + m_choiceDxfUnits->SetSelection( aCfg->m_ImportGraphics.dxf_units ); + + m_browseButton->SetBitmap( KiBitmap( BITMAPS::small_folder ) ); + }; + + if( SYMBOL_EDIT_FRAME* symFrame = dynamic_cast( aParent ) ) + { + m_importer = std::make_unique( symFrame->GetCurSymbol(), + symFrame->GetUnit() ); + + SYMBOL_EDITOR_SETTINGS* cfg = m_parent->libeditconfig(); + initWidgetsFromSettings( cfg ); + } + else if( SCH_EDIT_FRAME* schFrame = dynamic_cast( aParent ) ) + { + /*m_importer = std::make_unique( symFrame ); + + EESCHEMA_SETTINGS* cfg = m_parent->eeconfig(); + initWidgetsFromSettings( cfg );*/ + } + + // construct an import manager with options from config + { + GRAPHICS_IMPORT_MGR::TYPE_LIST blacklist; + // Currently: all types are allowed, so the blacklist is empty + // (no GFX_FILE_T in the blacklist) + // To disable SVG import, enable these 2 lines + // if( !ADVANCED_CFG::GetCfg().m_enableSvgImport ) + // blacklist.push_back( GRAPHICS_IMPORT_MGR::SVG ); + // The SVG import has currently a flaw: all SVG shapes are imported as curves and + // converted to a lot of segments. A better approach is to convert to polylines + // (not yet existing in Pcbnew) and keep arcs and circles as primitives (not yet + // possible with tinysvg library). + + m_gfxImportMgr = std::make_unique( blacklist ); + } + + wxCommandEvent dummy; + onFilename( dummy ); + + SetInitialFocus( m_textCtrlFileName ); + SetupStandardButtons(); + + GetSizer()->Fit( this ); + GetSizer()->SetSizeHints( this ); + Centre(); + + m_textCtrlFileName->Connect( wxEVT_COMMAND_TEXT_UPDATED, + wxCommandEventHandler( DIALOG_IMPORT_GFX_SCH::onFilename ), + nullptr, this ); +} + + +DIALOG_IMPORT_GFX_SCH::~DIALOG_IMPORT_GFX_SCH() +{ + auto saveToSettings = [&]( const auto& aCfg ) + { + aCfg->m_ImportGraphics.interactive_placement = m_placementInteractive; + aCfg->m_ImportGraphics.last_file = m_textCtrlFileName->GetValue(); + aCfg->m_ImportGraphics.dxf_line_width = schIUScale.IUTomm( m_defaultLineWidth.GetValue() ); + aCfg->m_ImportGraphics.origin_x = schIUScale.IUTomm( m_xOrigin.GetValue() ); + aCfg->m_ImportGraphics.origin_y = schIUScale.IUTomm( m_yOrigin.GetValue() ); + aCfg->m_ImportGraphics.dxf_units = m_choiceDxfUnits->GetSelection(); + + m_importScale = EDA_UNIT_UTILS::UI::DoubleValueFromString( m_importScaleCtrl->GetValue() ); + }; + + if( SYMBOL_EDIT_FRAME* symFrame = dynamic_cast( m_parent ) ) + { + m_importer = std::make_unique( symFrame->GetCurSymbol(), + symFrame->GetUnit() ); + + SYMBOL_EDITOR_SETTINGS* cfg = m_parent->libeditconfig(); + saveToSettings( cfg ); + } + else if( SCH_EDIT_FRAME* schFrame = dynamic_cast( m_parent ) ) + { + /*m_importer = std::make_unique( symFrame ); + + EESCHEMA_SETTINGS* cfg = m_parent->eeconfig(); + saveToSettings( cfg );*/ + } + + m_textCtrlFileName->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, + wxCommandEventHandler( DIALOG_IMPORT_GFX_SCH::onFilename ), + nullptr, this ); +} + + +void DIALOG_IMPORT_GFX_SCH::onFilename( wxCommandEvent& event ) +{ + bool enableDXFControls = true; + wxString ext = wxFileName( m_textCtrlFileName->GetValue() ).GetExt(); + + if( std::unique_ptr plugin = m_gfxImportMgr->GetPluginByExt( ext ) ) + enableDXFControls = dynamic_cast( plugin.get() ) != nullptr; + + m_defaultLineWidth.Enable( enableDXFControls ); + + m_staticTextLineWidth1->Enable( enableDXFControls ); + m_choiceDxfUnits->Enable( enableDXFControls ); +} + + +void DIALOG_IMPORT_GFX_SCH::onBrowseFiles( wxCommandEvent& event ) +{ + wxString path; + wxString filename = m_textCtrlFileName->GetValue(); + + if( !filename.IsEmpty() ) + { + wxFileName fn( filename ); + path = fn.GetPath(); + filename = fn.GetFullName(); + } + + // Generate the list of handled file formats + wxString wildcardsDesc; + wxString allWildcards; + + for( GRAPHICS_IMPORT_MGR::GFX_FILE_T pluginType : m_gfxImportMgr->GetImportableFileTypes() ) + { + std::unique_ptr plugin = m_gfxImportMgr->GetPlugin( pluginType ); + const std::vector extensions = plugin->GetFileExtensions(); + + wildcardsDesc += wxT( "|" ) + plugin->GetName() + AddFileExtListToFilter( extensions ); + allWildcards += plugin->GetWildcards() + wxT( ";" ); + } + + wildcardsDesc = _( "All supported formats" ) + wxT( "|" ) + allWildcards + wildcardsDesc; + + wxFileDialog dlg( m_parent, _( "Open File" ), path, filename, wildcardsDesc, + wxFD_OPEN | wxFD_FILE_MUST_EXIST ); + + if( dlg.ShowModal() == wxID_OK && !dlg.GetPath().IsEmpty() ) + m_textCtrlFileName->SetValue( dlg.GetPath() ); +} + + +bool DIALOG_IMPORT_GFX_SCH::TransferDataFromWindow() +{ + if( !wxDialog::TransferDataFromWindow() ) + return false; + + if( m_textCtrlFileName->GetValue().IsEmpty() ) + { + wxMessageBox( _( "No file selected!" ) ); + return false; + } + + wxString ext = wxFileName( m_textCtrlFileName->GetValue() ).GetExt(); + double scale = EDA_UNIT_UTILS::UI::DoubleValueFromString( m_importScaleCtrl->GetValue() ); + double xscale = scale; + double yscale = scale; + + if( dynamic_cast( m_parent ) ) + yscale *= -1; + + VECTOR2D origin( m_xOrigin.GetValue() / xscale, m_yOrigin.GetValue() / yscale ); + + if( std::unique_ptr plugin = m_gfxImportMgr->GetPluginByExt( ext ) ) + { + if( DXF_IMPORT_PLUGIN* dxfPlugin = dynamic_cast( plugin.get() ) ) + { + auto it = dxfUnitsMap.begin(); + std::advance( it, m_choiceDxfUnits->GetSelection() ); + + if( it == dxfUnitsMap.end() ) + dxfPlugin->SetUnit( DXF_IMPORT_UNITS::DEFAULT ); + else + dxfPlugin->SetUnit( it->first ); + + m_importer->SetLineWidthMM( schIUScale.IUTomm( m_defaultLineWidth.GetValue() ) ); + } + else + { + m_importer->SetLineWidthMM( 0.0 ); + } + + m_importer->SetPlugin( std::move( plugin ) ); + m_importer->SetImportOffsetMM( { schIUScale.IUTomm( origin.x ), schIUScale.IUTomm( origin.y ) } ); + + LOCALE_IO dummy; // Ensure floats can be read. + + if( m_importer->Load( m_textCtrlFileName->GetValue() ) ) + m_importer->Import( VECTOR2D( xscale, yscale ) ); + + // Get warning messages: + wxString warnings = m_importer->GetMessages(); + + // This isn't a fatal error so allow the dialog to close with wxID_OK. + if( !warnings.empty() ) + { + HTML_MESSAGE_BOX dlg( this, _( "Warning" ) ); + dlg.MessageSet( _( "Items in the imported file could not be handled properly." ) ); + warnings.Replace( wxT( "\n" ), wxT( "
" ) ); + dlg.AddHTML_Text( warnings ); + dlg.ShowModal(); + } + + return true; + } + else + { + wxMessageBox( _( "There is no plugin to handle this file type." ) ); + return false; + } +} + + +void DIALOG_IMPORT_GFX_SCH::originOptionOnUpdateUI( wxUpdateUIEvent& event ) +{ + if( m_rbInteractivePlacement->GetValue() != m_placementInteractive ) + m_rbInteractivePlacement->SetValue( m_placementInteractive ); + + if( m_rbAbsolutePlacement->GetValue() == m_placementInteractive ) + m_rbAbsolutePlacement->SetValue( !m_placementInteractive ); + + m_xOrigin.Enable( !m_placementInteractive ); + m_yOrigin.Enable( !m_placementInteractive ); +} + + diff --git a/eeschema/import_gfx/dialog_import_gfx_sch.h b/eeschema/import_gfx/dialog_import_gfx_sch.h new file mode 100644 index 0000000000..760da402a6 --- /dev/null +++ b/eeschema/import_gfx/dialog_import_gfx_sch.h @@ -0,0 +1,90 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * 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_IMPORT_GFX_SCH_H__ +#define __DIALOG_IMPORT_GFX_SCH_H__ + +#include "dialog_import_gfx_sch_base.h" + +#include +#include + +class SCH_BASE_FRAME; +class GRAPHICS_IMPORT_MGR; + + +class DIALOG_IMPORT_GFX_SCH : public DIALOG_IMPORT_GFX_SCH_BASE +{ +public: + DIALOG_IMPORT_GFX_SCH( SCH_BASE_FRAME* aParent ); + ~DIALOG_IMPORT_GFX_SCH(); + + /** + * @return a list of items imported from a vector graphics file. + */ + std::list>& GetImportedItems() + { + return m_importer->GetItems(); + } + + /** + * @return true if the placement is interactive, i.e. all imported + * items must be moved by the mouse cursor to the final position + * false means the imported items are placed to the final position after import. + */ + bool IsPlacementInteractive() { return m_placementInteractive; } + + bool TransferDataFromWindow() override; + +private: + // Virtual event handlers + void onBrowseFiles( wxCommandEvent& event ) override; + void onFilename( wxCommandEvent& event ); + void originOptionOnUpdateUI( wxUpdateUIEvent& event ) override; + + void onInteractivePlacement( wxCommandEvent& event ) override + { + m_placementInteractive = true; + } + + void onAbsolutePlacement( wxCommandEvent& event ) override + { + m_placementInteractive = false; + } + +private: + SCH_BASE_FRAME* m_parent; + std::unique_ptr m_importer; + std::unique_ptr m_gfxImportMgr; + + UNIT_BINDER m_xOrigin; + UNIT_BINDER m_yOrigin; + UNIT_BINDER m_defaultLineWidth; + + static bool m_placementInteractive; + static double m_importScale; // a scale factor to change the size of imported + // items m_importScale =1.0 means keep original size +}; + +#endif // __DIALOG_IMPORT_GFX_SCH_H__ diff --git a/eeschema/import_gfx/dialog_import_gfx_sch_base.cpp b/eeschema/import_gfx/dialog_import_gfx_sch_base.cpp new file mode 100644 index 0000000000..fb8b10a516 --- /dev/null +++ b/eeschema/import_gfx/dialog_import_gfx_sch_base.cpp @@ -0,0 +1,223 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "widgets/std_bitmap_button.h" + +#include "dialog_import_gfx_sch_base.h" + +/////////////////////////////////////////////////////////////////////////// + +DIALOG_IMPORT_GFX_SCH_BASE::DIALOG_IMPORT_GFX_SCH_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* bSizerMain; + bSizerMain = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizerFile; + bSizerFile = new wxBoxSizer( wxHORIZONTAL ); + + m_staticTextFile = new wxStaticText( this, wxID_ANY, _("File:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextFile->Wrap( -1 ); + m_staticTextFile->SetToolTip( _("Only vectors will be imported. Bitmaps and fonts will be ignored.") ); + + bSizerFile->Add( m_staticTextFile, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + + m_textCtrlFileName = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_textCtrlFileName->SetToolTip( _("Only vectors will be imported. Bitmaps and fonts will be ignored.") ); + m_textCtrlFileName->SetMinSize( wxSize( 300,-1 ) ); + + bSizerFile->Add( m_textCtrlFileName, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + m_browseButton = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 ); + bSizerFile->Add( m_browseButton, 0, wxTOP|wxBOTTOM, 5 ); + + + bSizerMain->Add( bSizerFile, 0, wxALL|wxEXPAND, 10 ); + + wxStaticBoxSizer* sbSizer2; + sbSizer2 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Placement") ), wxVERTICAL ); + + wxBoxSizer* bSizerOptions; + bSizerOptions = new wxBoxSizer( wxVERTICAL ); + + m_rbInteractivePlacement = new wxRadioButton( sbSizer2->GetStaticBox(), wxID_ANY, _("Interactive placement"), wxDefaultPosition, wxDefaultSize, 0 ); + m_rbInteractivePlacement->SetValue( true ); + bSizerOptions->Add( m_rbInteractivePlacement, 0, wxEXPAND|wxBOTTOM, 5 ); + + wxBoxSizer* bSizerUserPos; + bSizerUserPos = new wxBoxSizer( wxHORIZONTAL ); + + m_rbAbsolutePlacement = new wxRadioButton( sbSizer2->GetStaticBox(), wxID_ANY, _("At"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizerUserPos->Add( m_rbAbsolutePlacement, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + wxBoxSizer* bSizerPosSettings; + bSizerPosSettings = new wxBoxSizer( wxHORIZONTAL ); + + m_xLabel = new wxStaticText( sbSizer2->GetStaticBox(), wxID_ANY, _("X:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_xLabel->Wrap( -1 ); + bSizerPosSettings->Add( m_xLabel, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 ); + + m_xCtrl = new wxTextCtrl( sbSizer2->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + #ifdef __WXGTK__ + if ( !m_xCtrl->HasFlag( wxTE_MULTILINE ) ) + { + m_xCtrl->SetMaxLength( 10 ); + } + #else + m_xCtrl->SetMaxLength( 10 ); + #endif + m_xCtrl->SetToolTip( _("DXF origin on PCB Grid, X Coordinate") ); + + bSizerPosSettings->Add( m_xCtrl, 1, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + + m_xUnits = new wxStaticText( sbSizer2->GetStaticBox(), wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, 0 ); + m_xUnits->Wrap( -1 ); + bSizerPosSettings->Add( m_xUnits, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxTOP, 5 ); + + m_yLabel = new wxStaticText( sbSizer2->GetStaticBox(), wxID_ANY, _("Y:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_yLabel->Wrap( -1 ); + bSizerPosSettings->Add( m_yLabel, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 ); + + m_yCtrl = new wxTextCtrl( sbSizer2->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + #ifdef __WXGTK__ + if ( !m_yCtrl->HasFlag( wxTE_MULTILINE ) ) + { + m_yCtrl->SetMaxLength( 10 ); + } + #else + m_yCtrl->SetMaxLength( 10 ); + #endif + m_yCtrl->SetToolTip( _("DXF origin on PCB Grid, Y Coordinate") ); + + bSizerPosSettings->Add( m_yCtrl, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + + m_yUnits = new wxStaticText( sbSizer2->GetStaticBox(), wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, 0 ); + m_yUnits->Wrap( -1 ); + bSizerPosSettings->Add( m_yUnits, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + + + bSizerUserPos->Add( bSizerPosSettings, 1, wxBOTTOM|wxEXPAND|wxRIGHT|wxTOP, 5 ); + + + bSizerOptions->Add( bSizerUserPos, 0, wxEXPAND, 5 ); + + + sbSizer2->Add( bSizerOptions, 0, wxEXPAND|wxTOP|wxLEFT, 5 ); + + + bSizerMain->Add( sbSizer2, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 10 ); + + wxStaticBoxSizer* sbSizer1; + sbSizer1 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Import Parameters") ), wxVERTICAL ); + + wxBoxSizer* bSizer7; + bSizer7 = new wxBoxSizer( wxHORIZONTAL ); + + wxFlexGridSizer* fgSizerImportSettings; + fgSizerImportSettings = new wxFlexGridSizer( 0, 3, 5, 5 ); + fgSizerImportSettings->AddGrowableCol( 1 ); + fgSizerImportSettings->SetFlexibleDirection( wxBOTH ); + fgSizerImportSettings->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_importScaleLabel = new wxStaticText( sbSizer1->GetStaticBox(), wxID_ANY, _("Import scale:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_importScaleLabel->Wrap( -1 ); + fgSizerImportSettings->Add( m_importScaleLabel, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_importScaleCtrl = new wxTextCtrl( sbSizer1->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + fgSizerImportSettings->Add( m_importScaleCtrl, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + + fgSizerImportSettings->Add( 0, 0, 0, 0, 5 ); + + + bSizer7->Add( fgSizerImportSettings, 1, wxEXPAND|wxALL, 5 ); + + + sbSizer1->Add( bSizer7, 1, wxEXPAND, 5 ); + + + bSizerMain->Add( sbSizer1, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 10 ); + + wxStaticBoxSizer* sbSizer3; + sbSizer3 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("DXF Parameters") ), wxVERTICAL ); + + wxBoxSizer* bSizer81; + bSizer81 = new wxBoxSizer( wxHORIZONTAL ); + + wxFlexGridSizer* fgDxfImportSettings; + fgDxfImportSettings = new wxFlexGridSizer( 0, 3, 5, 5 ); + fgDxfImportSettings->AddGrowableCol( 1 ); + fgDxfImportSettings->SetFlexibleDirection( wxBOTH ); + fgDxfImportSettings->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_lineWidthLabel = new wxStaticText( sbSizer3->GetStaticBox(), wxID_ANY, _("Default line width:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_lineWidthLabel->Wrap( -1 ); + fgDxfImportSettings->Add( m_lineWidthLabel, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_lineWidthCtrl = new wxTextCtrl( sbSizer3->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + fgDxfImportSettings->Add( m_lineWidthCtrl, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + m_lineWidthUnits = new wxStaticText( sbSizer3->GetStaticBox(), wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, 0 ); + m_lineWidthUnits->Wrap( -1 ); + fgDxfImportSettings->Add( m_lineWidthUnits, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxTOP, 5 ); + + m_staticTextLineWidth1 = new wxStaticText( sbSizer3->GetStaticBox(), wxID_ANY, _("Default units:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextLineWidth1->Wrap( -1 ); + fgDxfImportSettings->Add( m_staticTextLineWidth1, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + wxArrayString m_choiceDxfUnitsChoices; + m_choiceDxfUnits = new wxChoice( sbSizer3->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceDxfUnitsChoices, 0 ); + m_choiceDxfUnits->SetSelection( 0 ); + fgDxfImportSettings->Add( m_choiceDxfUnits, 0, wxEXPAND, 5 ); + + + fgDxfImportSettings->Add( 0, 0, 1, wxEXPAND, 5 ); + + + bSizer81->Add( fgDxfImportSettings, 1, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 ); + + + sbSizer3->Add( bSizer81, 1, wxEXPAND, 5 ); + + + bSizerMain->Add( sbSizer3, 1, wxEXPAND|wxRIGHT|wxLEFT, 10 ); + + m_sdbSizer = new wxStdDialogButtonSizer(); + m_sdbSizerOK = new wxButton( this, wxID_OK ); + m_sdbSizer->AddButton( m_sdbSizerOK ); + m_sdbSizerCancel = new wxButton( this, wxID_CANCEL ); + m_sdbSizer->AddButton( m_sdbSizerCancel ); + m_sdbSizer->Realize(); + + bSizerMain->Add( m_sdbSizer, 0, wxEXPAND|wxALL, 5 ); + + + this->SetSizer( bSizerMain ); + this->Layout(); + bSizerMain->Fit( this ); + + this->Centre( wxBOTH ); + + // Connect Events + m_browseButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_GFX_SCH_BASE::onBrowseFiles ), NULL, this ); + m_rbInteractivePlacement->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_IMPORT_GFX_SCH_BASE::onInteractivePlacement ), NULL, this ); + m_rbInteractivePlacement->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_IMPORT_GFX_SCH_BASE::originOptionOnUpdateUI ), NULL, this ); + m_rbAbsolutePlacement->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_IMPORT_GFX_SCH_BASE::onAbsolutePlacement ), NULL, this ); + m_rbAbsolutePlacement->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_IMPORT_GFX_SCH_BASE::originOptionOnUpdateUI ), NULL, this ); +} + +DIALOG_IMPORT_GFX_SCH_BASE::~DIALOG_IMPORT_GFX_SCH_BASE() +{ + // Disconnect Events + m_browseButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_GFX_SCH_BASE::onBrowseFiles ), NULL, this ); + m_rbInteractivePlacement->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_IMPORT_GFX_SCH_BASE::onInteractivePlacement ), NULL, this ); + m_rbInteractivePlacement->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_IMPORT_GFX_SCH_BASE::originOptionOnUpdateUI ), NULL, this ); + m_rbAbsolutePlacement->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_IMPORT_GFX_SCH_BASE::onAbsolutePlacement ), NULL, this ); + m_rbAbsolutePlacement->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_IMPORT_GFX_SCH_BASE::originOptionOnUpdateUI ), NULL, this ); + +} diff --git a/eeschema/import_gfx/dialog_import_gfx_sch_base.fbp b/eeschema/import_gfx/dialog_import_gfx_sch_base.fbp new file mode 100644 index 0000000000..163b8ff2c7 --- /dev/null +++ b/eeschema/import_gfx/dialog_import_gfx_sch_base.fbp @@ -0,0 +1,1388 @@ + + + + + + C++ + 1 + source_name + 0 + 0 + res + UTF-8 + connect + dialog_import_gfx_sch_base + 1000 + none + + + 1 + dialog_import_gfx_sch_base + + . + + 1 + 1 + 1 + 1 + UI + 0 + 0 + 0 + + 0 + wxAUI_MGR_DEFAULT + + wxBOTH + + 1 + 1 + impl_virtual + + + + 0 + wxID_ANY + + + DIALOG_IMPORT_GFX_SCH_BASE + + -1,-1 + wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER + DIALOG_SHIM; dialog_shim.h + Import Vector Graphics File + + 0 + + + + + + bSizerMain + wxVERTICAL + none + + 10 + wxALL|wxEXPAND + 0 + + + bSizerFile + wxHORIZONTAL + none + + 5 + wxALIGN_CENTER_VERTICAL|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + File: + 0 + + 0 + + + 0 + + 1 + m_staticTextFile + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Only vectors will be imported. Bitmaps and fonts will be ignored. + + + + -1 + + + + 5 + wxALIGN_CENTER_VERTICAL + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + + 0 + 300,-1 + 1 + m_textCtrlFileName + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Only vectors will be imported. Bitmaps and fonts will be ignored. + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + 5 + wxTOP|wxBOTTOM + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 1 + + 1 + + + 0 + 0 + wxID_ANY + Browse... + + 0 + + 0 + + + 0 + + 1 + m_browseButton + 1 + + + protected + 1 + + + + Resizable + 1 + -1,-1 + + STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + onBrowseFiles + + + + + + 10 + wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT + 0 + + wxID_ANY + Placement + + sbSizer2 + wxVERTICAL + 1 + none + + 5 + wxEXPAND|wxTOP|wxLEFT + 0 + + + bSizerOptions + wxVERTICAL + none + + 5 + wxEXPAND|wxBOTTOM + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Interactive placement + + 0 + + + 0 + + 1 + m_rbInteractivePlacement + 1 + + + protected + 1 + + Resizable + 1 + + + ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + 1 + + + + onInteractivePlacement + originOptionOnUpdateUI + + + + 5 + wxEXPAND + 0 + + + bSizerUserPos + wxHORIZONTAL + none + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + At + + 0 + + + 0 + + 1 + m_rbAbsolutePlacement + 1 + + + protected + 1 + + Resizable + 1 + + + ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + 0 + + + + onAbsolutePlacement + originOptionOnUpdateUI + + + + 5 + wxBOTTOM|wxEXPAND|wxRIGHT|wxTOP + 1 + + + bSizerPosSettings + wxHORIZONTAL + none + + 5 + wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + X: + 0 + + 0 + + + 0 + + 1 + m_xLabel + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + 5 + wxALIGN_CENTER_VERTICAL|wxRIGHT + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 10 + + 0 + + 1 + m_xCtrl + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + DXF origin on PCB Grid, X Coordinate + + wxFILTER_NUMERIC + wxTextValidator + + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxTOP + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + mm + 0 + + 0 + + + 0 + + 1 + m_xUnits + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Y: + 0 + + 0 + + + 0 + + 1 + m_yLabel + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + 5 + wxALIGN_CENTER_VERTICAL|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 10 + + 0 + + 1 + m_yCtrl + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + DXF origin on PCB Grid, Y Coordinate + + wxFILTER_NUMERIC + wxTextValidator + + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + mm + 0 + + 0 + + + 0 + + 1 + m_yUnits + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + 10 + wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT + 0 + + wxID_ANY + Import Parameters + + sbSizer1 + wxVERTICAL + 1 + none + + 5 + wxEXPAND + 1 + + + bSizer7 + wxHORIZONTAL + none + + 5 + wxEXPAND|wxALL + 1 + + 3 + wxBOTH + 1 + + 5 + + fgSizerImportSettings + wxFLEX_GROWMODE_SPECIFIED + none + 0 + 5 + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Import scale: + 0 + + 0 + + + 0 + + 1 + m_importScaleLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALIGN_CENTER_VERTICAL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + + 0 + + 1 + m_importScaleCtrl + 1 + + + protected + 1 + + Resizable + 1 + + + ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + 5 + + 0 + + 0 + protected + 0 + + + + + + + + + + 10 + wxEXPAND|wxRIGHT|wxLEFT + 1 + + wxID_ANY + DXF Parameters + + sbSizer3 + wxVERTICAL + 1 + none + + 5 + wxEXPAND + 1 + + + bSizer81 + wxHORIZONTAL + none + + 5 + wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT + 1 + + 3 + wxBOTH + 1 + + 5 + + fgDxfImportSettings + wxFLEX_GROWMODE_SPECIFIED + none + 0 + 5 + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Default line width: + 0 + + 0 + + + 0 + + 1 + m_lineWidthLabel + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + 5 + wxALIGN_CENTER_VERTICAL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + + 0 + + 1 + m_lineWidthCtrl + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxTOP + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + mm + 0 + + 0 + + + 0 + + 1 + m_lineWidthUnits + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Default units: + 0 + + 0 + + + 0 + + 1 + m_staticTextLineWidth1 + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + 5 + wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_choiceDxfUnits + 1 + + + protected + 1 + + Resizable + 0 + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxEXPAND + 1 + + 0 + protected + 0 + + + + + + + + + + 5 + wxEXPAND|wxALL + 0 + + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + + m_sdbSizer + protected + + + + + + diff --git a/eeschema/import_gfx/dialog_import_gfx_sch_base.h b/eeschema/import_gfx/dialog_import_gfx_sch_base.h new file mode 100644 index 0000000000..052539e806 --- /dev/null +++ b/eeschema/import_gfx/dialog_import_gfx_sch_base.h @@ -0,0 +1,82 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include +#include +class STD_BITMAP_BUTTON; + +#include "dialog_shim.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +/// Class DIALOG_IMPORT_GFX_SCH_BASE +/////////////////////////////////////////////////////////////////////////////// +class DIALOG_IMPORT_GFX_SCH_BASE : public DIALOG_SHIM +{ + private: + + protected: + wxStaticText* m_staticTextFile; + wxTextCtrl* m_textCtrlFileName; + STD_BITMAP_BUTTON* m_browseButton; + wxRadioButton* m_rbInteractivePlacement; + wxRadioButton* m_rbAbsolutePlacement; + wxStaticText* m_xLabel; + wxTextCtrl* m_xCtrl; + wxStaticText* m_xUnits; + wxStaticText* m_yLabel; + wxTextCtrl* m_yCtrl; + wxStaticText* m_yUnits; + wxStaticText* m_importScaleLabel; + wxTextCtrl* m_importScaleCtrl; + wxStaticText* m_lineWidthLabel; + wxTextCtrl* m_lineWidthCtrl; + wxStaticText* m_lineWidthUnits; + wxStaticText* m_staticTextLineWidth1; + wxChoice* m_choiceDxfUnits; + wxStdDialogButtonSizer* m_sdbSizer; + wxButton* m_sdbSizerOK; + wxButton* m_sdbSizerCancel; + + // Virtual event handlers, override them in your derived class + virtual void onBrowseFiles( wxCommandEvent& event ) { event.Skip(); } + virtual void onInteractivePlacement( wxCommandEvent& event ) { event.Skip(); } + virtual void originOptionOnUpdateUI( wxUpdateUIEvent& event ) { event.Skip(); } + virtual void onAbsolutePlacement( wxCommandEvent& event ) { event.Skip(); } + + + public: + + DIALOG_IMPORT_GFX_SCH_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Import Vector Graphics File"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + + ~DIALOG_IMPORT_GFX_SCH_BASE(); + +}; + diff --git a/eeschema/import_gfx/graphics_importer_lib_symbol.cpp b/eeschema/import_gfx/graphics_importer_lib_symbol.cpp index 41d93dcb27..3dfc07532e 100644 --- a/eeschema/import_gfx/graphics_importer_lib_symbol.cpp +++ b/eeschema/import_gfx/graphics_importer_lib_symbol.cpp @@ -53,7 +53,7 @@ VECTOR2I GRAPHICS_IMPORTER_LIB_SYMBOL::MapCoordinate( const VECTOR2D& aCoordinat int GRAPHICS_IMPORTER_LIB_SYMBOL::MapLineWidth( double aLineWidth ) { VECTOR2D factor = ImportScalingFactor(); - double scale = ( factor.x + factor.y ) * 0.5; + double scale = ( std::abs( factor.x ) + std::abs( factor.y ) ) * 0.5; if( aLineWidth <= 0.0 ) return int( GetLineWidthMM() * scale ); @@ -63,33 +63,46 @@ int GRAPHICS_IMPORTER_LIB_SYMBOL::MapLineWidth( double aLineWidth ) } -void GRAPHICS_IMPORTER_LIB_SYMBOL::AddLine( const VECTOR2D& aOrigin, const VECTOR2D& aEnd, - double aWidth, const COLOR4D& aColor ) +STROKE_PARAMS GRAPHICS_IMPORTER_LIB_SYMBOL::MapStrokeParams( const STROKE_PARAMS& aStroke ) { - std::unique_ptr line = std::make_unique( m_symbol, SHAPE_T::POLY ); - line->SetUnit( m_unit ); - line->SetFillColor( aColor ); - line->SetStroke( STROKE_PARAMS( MapLineWidth( aWidth ), PLOT_DASH_TYPE::SOLID ) ); - line->AddPoint( MapCoordinate( aOrigin ) ); - line->AddPoint( MapCoordinate( aEnd ) ); + int width = aStroke.GetWidth(); + + return STROKE_PARAMS( width != -1 ? MapLineWidth( width ) : -1, aStroke.GetPlotStyle(), + aStroke.GetColor() ); +} + + +void GRAPHICS_IMPORTER_LIB_SYMBOL::AddLine( const VECTOR2D& aStart, const VECTOR2D& aEnd, + const STROKE_PARAMS& aStroke ) +{ + VECTOR2I pt0 = MapCoordinate( aStart ); + VECTOR2I pt1 = MapCoordinate( aEnd ); // Skip 0 len lines: - if( line->GetStart() == line->GetEnd() ) + if( pt0 == pt1 ) return; + std::unique_ptr line = std::make_unique( m_symbol, SHAPE_T::POLY ); + line->SetUnit( m_unit ); + line->SetStroke( MapStrokeParams( aStroke ) ); + + line->AddPoint( pt0 ); + line->AddPoint( pt1 ); + addItem( std::move( line ) ); } -void GRAPHICS_IMPORTER_LIB_SYMBOL::AddCircle( const VECTOR2D& aCenter, double aRadius, double aWidth, - bool aFilled, const COLOR4D& aColor ) +void GRAPHICS_IMPORTER_LIB_SYMBOL::AddCircle( const VECTOR2D& aCenter, double aRadius, + const STROKE_PARAMS& aStroke, bool aFilled, + const COLOR4D& aFillColor ) { std::unique_ptr circle = std::make_unique( m_symbol, SHAPE_T::CIRCLE ); circle->SetUnit( m_unit ); - circle->SetFillColor( aColor ); + circle->SetFillColor( aFillColor ); circle->SetFilled( aFilled ); - circle->SetStroke( STROKE_PARAMS( MapLineWidth( aWidth ), PLOT_DASH_TYPE::SOLID ) ); - circle->SetStart( MapCoordinate( aCenter )); + circle->SetStroke( MapStrokeParams( aStroke ) ); + circle->SetStart( MapCoordinate( aCenter ) ); circle->SetEnd( MapCoordinate( VECTOR2D( aCenter.x + aRadius, aCenter.y ) ) ); addItem( std::move( circle ) ); @@ -97,12 +110,10 @@ void GRAPHICS_IMPORTER_LIB_SYMBOL::AddCircle( const VECTOR2D& aCenter, double aR void GRAPHICS_IMPORTER_LIB_SYMBOL::AddArc( const VECTOR2D& aCenter, const VECTOR2D& aStart, - const EDA_ANGLE& aAngle, double aWidth, - const COLOR4D& aColor ) + const EDA_ANGLE& aAngle, const STROKE_PARAMS& aStroke ) { std::unique_ptr arc = std::make_unique( m_symbol, SHAPE_T::ARC ); arc->SetUnit( m_unit ); - arc->SetFillColor( aColor ); /** * We need to perform the rotation/conversion here while still using floating point values @@ -120,25 +131,26 @@ void GRAPHICS_IMPORTER_LIB_SYMBOL::AddArc( const VECTOR2D& aCenter, const VECTOR // The criteria used here is radius < MAX_INT / 2. // this is not perfect, but we do not know the exact final position of the arc, so // we cannot test the coordinate values, because the arc can be moved before being placed. - VECTOR2D center = CalcArcCenter( arc->GetStart(), arc->GetEnd(), aAngle ); - double radius = ( center - arc->GetStart() ).EuclideanNorm(); + VECTOR2D center = CalcArcCenter( arc->GetStart(), arc->GetEnd(), aAngle ); + double radius = ( center - arc->GetStart() ).EuclideanNorm(); constexpr double rd_max_value = std::numeric_limits::max() / 2.0; if( radius >= rd_max_value ) { // Arc cannot be handled: convert it to a segment - AddLine( aStart, end, aWidth, aColor ); + AddLine( aStart, end, aStroke ); return; } - arc->SetStroke( STROKE_PARAMS( MapLineWidth( aWidth ), PLOT_DASH_TYPE::SOLID ) ); + arc->SetStroke( MapStrokeParams( aStroke ) ); addItem( std::move( arc ) ); } -void GRAPHICS_IMPORTER_LIB_SYMBOL::AddPolygon( const std::vector& aVertices, double aWidth, - const COLOR4D& aColor ) +void GRAPHICS_IMPORTER_LIB_SYMBOL::AddPolygon( const std::vector& aVertices, + const STROKE_PARAMS& aStroke, bool aFilled, + const COLOR4D& aFillColor ) { std::vector convertedPoints; convertedPoints.reserve( aVertices.size() ); @@ -151,24 +163,27 @@ void GRAPHICS_IMPORTER_LIB_SYMBOL::AddPolygon( const std::vector& aVer std::unique_ptr polygon = std::make_unique( m_symbol, SHAPE_T::POLY ); polygon->SetUnit( m_unit ); - polygon->SetFilled( true ); - polygon->SetFillMode( aColor != COLOR4D::UNSPECIFIED ? FILL_T::FILLED_WITH_COLOR - : FILL_T::FILLED_SHAPE ); - polygon->SetFillColor( aColor ); + + if( aFilled ) + { + polygon->SetFillMode( aFillColor != COLOR4D::UNSPECIFIED ? FILL_T::FILLED_WITH_COLOR + : FILL_T::FILLED_SHAPE ); + } + + polygon->SetFillColor( aFillColor ); polygon->SetPolyPoints( convertedPoints ); polygon->AddPoint( convertedPoints[0] ); // Need to close last point for libedit - polygon->SetStroke( - STROKE_PARAMS( aWidth != -1 ? MapLineWidth( aWidth ) : -1, PLOT_DASH_TYPE::SOLID ) ); + polygon->SetStroke( MapStrokeParams( aStroke ) ); addItem( std::move( polygon ) ); } void GRAPHICS_IMPORTER_LIB_SYMBOL::AddText( const VECTOR2D& aOrigin, const wxString& aText, - double aHeight, double aWidth, double aThickness, - double aOrientation, GR_TEXT_H_ALIGN_T aHJustify, - GR_TEXT_V_ALIGN_T aVJustify, const COLOR4D& aColor ) + double aHeight, double aWidth, double aThickness, + double aOrientation, GR_TEXT_H_ALIGN_T aHJustify, + GR_TEXT_V_ALIGN_T aVJustify, const COLOR4D& aColor ) { std::unique_ptr textItem = std::make_unique( m_symbol ); textItem->SetUnit( m_unit ); @@ -186,29 +201,29 @@ void GRAPHICS_IMPORTER_LIB_SYMBOL::AddText( const VECTOR2D& aOrigin, const wxStr } -void GRAPHICS_IMPORTER_LIB_SYMBOL::AddSpline( const VECTOR2D& aStart, const VECTOR2D& BezierControl1, - const VECTOR2D& BezierControl2, const VECTOR2D& aEnd, - double aWidth, const COLOR4D& aColor ) +void GRAPHICS_IMPORTER_LIB_SYMBOL::AddSpline( const VECTOR2D& aStart, + const VECTOR2D& aBezierControl1, + const VECTOR2D& aBezierControl2, const VECTOR2D& aEnd, + const STROKE_PARAMS& aStroke ) { std::unique_ptr spline = std::make_unique( m_symbol, SHAPE_T::BEZIER ); spline->SetUnit( m_unit ); - spline->SetFillColor( aColor ); - spline->SetStroke( STROKE_PARAMS( MapLineWidth( aWidth ), PLOT_DASH_TYPE::SOLID ) ); + spline->SetStroke( MapStrokeParams( aStroke ) ); spline->SetStart( MapCoordinate( aStart ) ); - spline->SetBezierC1( MapCoordinate( BezierControl1 )); - spline->SetBezierC2( MapCoordinate( BezierControl2 )); + spline->SetBezierC1( MapCoordinate( aBezierControl1 ) ); + spline->SetBezierC2( MapCoordinate( aBezierControl2 ) ); spline->SetEnd( MapCoordinate( aEnd ) ); - spline->RebuildBezierToSegmentsPointsList( aWidth ); + spline->RebuildBezierToSegmentsPointsList( aStroke.GetWidth() ); // If the spline is degenerated (i.e. a segment) add it as segment or discard it if // null (i.e. very small) length if( spline->GetBezierPoints().size() <= 2 ) { spline->SetShape( SHAPE_T::SEGMENT ); - int dist = VECTOR2I(spline->GetStart()- spline->GetEnd()).EuclideanNorm(); + int dist = VECTOR2I( spline->GetStart() - spline->GetEnd() ).EuclideanNorm(); - // segment smaller than MIN_SEG_LEN_ACCEPTABLE_NM nanometers are skipped. - #define MIN_SEG_LEN_ACCEPTABLE_NM 20 +// segment smaller than MIN_SEG_LEN_ACCEPTABLE_NM nanometers are skipped. +#define MIN_SEG_LEN_ACCEPTABLE_NM 20 if( dist < MIN_SEG_LEN_ACCEPTABLE_NM ) return; } diff --git a/eeschema/import_gfx/graphics_importer_lib_symbol.h b/eeschema/import_gfx/graphics_importer_lib_symbol.h index fa24f830a5..5e1cd70a73 100644 --- a/eeschema/import_gfx/graphics_importer_lib_symbol.h +++ b/eeschema/import_gfx/graphics_importer_lib_symbol.h @@ -40,25 +40,26 @@ class GRAPHICS_IMPORTER_LIB_SYMBOL : public GRAPHICS_IMPORTER public: GRAPHICS_IMPORTER_LIB_SYMBOL( LIB_SYMBOL* aSymbol, int aUnit ); - void AddLine( const VECTOR2D& aOrigin, const VECTOR2D& aEnd, double aWidth, - const COLOR4D& aColor ) override; + void AddLine( const VECTOR2D& aStart, const VECTOR2D& aEnd, + const STROKE_PARAMS& aStroke ) override; - void AddCircle( const VECTOR2D& aOrigin, double aRadius, double aWidth, bool aFilled, - const COLOR4D& aColor ) override; + void AddCircle( const VECTOR2D& aCenter, double aRadius, const STROKE_PARAMS& aStroke, + bool aFilled, const COLOR4D& aFillColor = COLOR4D::UNSPECIFIED ) override; void AddArc( const VECTOR2D& aCenter, const VECTOR2D& aStart, const EDA_ANGLE& aAngle, - double aWidth, const COLOR4D& aColor ) override; + const STROKE_PARAMS& aStroke ) override; - void AddPolygon( const std::vector& aVertices, double aWidth, - const COLOR4D& aColor ) override; + void AddPolygon( const std::vector& aVertices, const STROKE_PARAMS& aStroke, + bool aFilled, const COLOR4D& aFillColor = COLOR4D::UNSPECIFIED ) override; void AddText( const VECTOR2D& aOrigin, const wxString& aText, double aHeight, double aWidth, double aThickness, double aOrientation, GR_TEXT_H_ALIGN_T aHJustify, - GR_TEXT_V_ALIGN_T aVJustify, const COLOR4D& aColor ) override; + GR_TEXT_V_ALIGN_T aVJustify, + const COLOR4D& aColor = COLOR4D::UNSPECIFIED ) override; void AddSpline( const VECTOR2D& aStart, const VECTOR2D& aBezierControl1, - const VECTOR2D& aBezierControl2, const VECTOR2D& aEnd, double aWidth, - const COLOR4D& aColor ) override; + const VECTOR2D& aBezierControl2, const VECTOR2D& aEnd, + const STROKE_PARAMS& aStroke ) override; /** * Convert an imported coordinate to a board coordinate, according to the internal units, @@ -76,6 +77,8 @@ public: */ int MapLineWidth( double aLineWidth ); + STROKE_PARAMS MapStrokeParams( const STROKE_PARAMS& aStroke ); + LIB_SYMBOL* m_symbol; int m_unit; }; diff --git a/eeschema/symbol_editor/menubar_symbol_editor.cpp b/eeschema/symbol_editor/menubar_symbol_editor.cpp index dba85bc7ff..e1a96eb035 100644 --- a/eeschema/symbol_editor/menubar_symbol_editor.cpp +++ b/eeschema/symbol_editor/menubar_symbol_editor.cpp @@ -61,7 +61,15 @@ void SYMBOL_EDIT_FRAME::doReCreateMenuBar() fileMenu->Add( ACTIONS::revert ); fileMenu->AppendSeparator(); - fileMenu->Add( EE_ACTIONS::importSymbol ); + + ACTION_MENU* submenuImport = new ACTION_MENU( false, selTool ); + submenuImport->SetTitle( _( "Import" ) ); + submenuImport->SetIcon( BITMAPS::import ); + + submenuImport->Add( EE_ACTIONS::importSymbol, ACTION_MENU::NORMAL, _( "Symbol..." ) ); + submenuImport->Add( EE_ACTIONS::symbolImportGraphics, ACTION_MENU::NORMAL, _( "Graphics..." ) ); + + fileMenu->Add( submenuImport ); // Export submenu ACTION_MENU* submenuExport = new ACTION_MENU( false, selTool ); diff --git a/eeschema/symbol_editor/symbol_edit_frame.cpp b/eeschema/symbol_editor/symbol_edit_frame.cpp index 5b2289b2ae..d7b243f2fa 100644 --- a/eeschema/symbol_editor/symbol_edit_frame.cpp +++ b/eeschema/symbol_editor/symbol_edit_frame.cpp @@ -540,6 +540,7 @@ void SYMBOL_EDIT_FRAME::setupUIConditions() mgr->SetConditions( EE_ACTIONS::drawSymbolLines, EDIT_TOOL( EE_ACTIONS::drawSymbolLines ) ); mgr->SetConditions( EE_ACTIONS::drawSymbolPolygon, EDIT_TOOL( EE_ACTIONS::drawSymbolPolygon ) ); mgr->SetConditions( EE_ACTIONS::placeSymbolAnchor, EDIT_TOOL( EE_ACTIONS::placeSymbolAnchor ) ); + mgr->SetConditions( EE_ACTIONS::symbolImportGraphics, EDIT_TOOL( EE_ACTIONS::symbolImportGraphics ) ); #undef CHECK #undef ENABLE diff --git a/eeschema/symbol_editor/symbol_editor_settings.cpp b/eeschema/symbol_editor/symbol_editor_settings.cpp index 86869cc13c..469204376c 100644 --- a/eeschema/symbol_editor/symbol_editor_settings.cpp +++ b/eeschema/symbol_editor/symbol_editor_settings.cpp @@ -36,6 +36,7 @@ SYMBOL_EDITOR_SETTINGS::SYMBOL_EDITOR_SETTINGS() : APP_SETTINGS_BASE( "symbol_editor", libeditSchemaVersion ), m_Defaults(), m_Repeat(), + m_ImportGraphics(), m_ShowPinElectricalType( true ), m_LibWidth(), m_EditSymbolVisibleColumns() @@ -76,6 +77,27 @@ SYMBOL_EDITOR_SETTINGS::SYMBOL_EDITOR_SETTINGS() : m_params.emplace_back( new PARAM( "repeat.pin_step", &m_Repeat.pin_step, 100 ) ); + m_params.emplace_back( new PARAM( "import_graphics.interactive_placement", + &m_ImportGraphics.interactive_placement, true ) ); + + m_params.emplace_back( new PARAM( "import_graphics.line_width_units", + &m_ImportGraphics.dxf_line_width_units, 0 ) ); + + m_params.emplace_back( new PARAM( "import_graphics.line_width", + &m_ImportGraphics.dxf_line_width, 0.2 ) ); + + m_params.emplace_back( new PARAM( "import_graphics.origin_units", + &m_ImportGraphics.origin_units, 0 ) ); + + m_params.emplace_back( new PARAM( "import_graphics.origin_x", + &m_ImportGraphics.origin_x, 0 ) ); + + m_params.emplace_back( new PARAM( "import_graphics.origin_y", + &m_ImportGraphics.origin_y, 0 ) ); + + m_params.emplace_back( new PARAM( "import_graphics.dxf_units", + &m_ImportGraphics.dxf_units, 0 ) ); + m_params.emplace_back( new PARAM( "show_pin_electrical_type", &m_ShowPinElectricalType, true ) ); diff --git a/eeschema/symbol_editor/symbol_editor_settings.h b/eeschema/symbol_editor/symbol_editor_settings.h index b3df541f99..b83a794d7c 100644 --- a/eeschema/symbol_editor/symbol_editor_settings.h +++ b/eeschema/symbol_editor/symbol_editor_settings.h @@ -53,6 +53,18 @@ public: int pin_step; }; + struct DIALOG_IMPORT_GRAPHICS + { + bool interactive_placement; + wxString last_file; + double dxf_line_width; + int dxf_line_width_units; + int origin_units; + double origin_x; + double origin_y; + int dxf_units; + }; + SYMBOL_EDITOR_SETTINGS(); virtual ~SYMBOL_EDITOR_SETTINGS() {} @@ -65,6 +77,8 @@ public: REPEAT m_Repeat; + DIALOG_IMPORT_GRAPHICS m_ImportGraphics; + bool m_ShowPinElectricalType; int m_LibWidth; diff --git a/eeschema/tools/ee_actions.cpp b/eeschema/tools/ee_actions.cpp index 07bd5b3436..a3ffe45fb8 100644 --- a/eeschema/tools/ee_actions.cpp +++ b/eeschema/tools/ee_actions.cpp @@ -369,6 +369,16 @@ TOOL_ACTION EE_ACTIONS::placeSymbolAnchor( TOOL_ACTION_ARGS() .Icon( BITMAPS::anchor ) .Flags( AF_ACTIVATE ) ); +TOOL_ACTION EE_ACTIONS::symbolImportGraphics( TOOL_ACTION_ARGS() + .Name( "eeschema.SymbolDrawing.symbolImportGraphics" ) + .Scope( AS_GLOBAL ) + .DefaultHotkey( MD_SHIFT + MD_CTRL + 'F' ) + .LegacyHotkeyName( "Place DXF" ) + .MenuText( _( "Import Graphics..." ) ) + .Tooltip( _( "Import 2D drawing file" ) ) + .Icon( BITMAPS::import_vector ) + .Flags( AF_ACTIVATE ) ); + TOOL_ACTION EE_ACTIONS::finishDrawing( TOOL_ACTION_ARGS() .Name( "eeschema.SymbolDrawing.finishDrawing" ) .Scope( AS_GLOBAL ) diff --git a/eeschema/tools/ee_actions.h b/eeschema/tools/ee_actions.h index 87616ef051..e22d6be5c4 100644 --- a/eeschema/tools/ee_actions.h +++ b/eeschema/tools/ee_actions.h @@ -112,6 +112,7 @@ public: static TOOL_ACTION drawSymbolLines; static TOOL_ACTION drawSymbolPolygon; static TOOL_ACTION placeSymbolAnchor; + static TOOL_ACTION symbolImportGraphics; static TOOL_ACTION finishDrawing; // Interactive Editing diff --git a/eeschema/tools/symbol_editor_drawing_tools.cpp b/eeschema/tools/symbol_editor_drawing_tools.cpp index da6ab3a36a..a1b483396c 100644 --- a/eeschema/tools/symbol_editor_drawing_tools.cpp +++ b/eeschema/tools/symbol_editor_drawing_tools.cpp @@ -38,6 +38,9 @@ #include #include #include +#include +#include +#include #include "dialog_lib_textbox_properties.h" static void* g_lastPinWeakPtr; @@ -651,6 +654,173 @@ int SYMBOL_EDITOR_DRAWING_TOOLS::PlaceAnchor( const TOOL_EVENT& aEvent ) } +int SYMBOL_EDITOR_DRAWING_TOOLS::SymbolImportGraphics( const TOOL_EVENT& aEvent ) +{ + LIB_SYMBOL* symbol = m_frame->GetCurSymbol(); + + if( !symbol ) + return 0; + + // Note: PlaceImportedGraphics() will convert PCB_SHAPE_T and PCB_TEXT_T to footprint + // items if needed + DIALOG_IMPORT_GFX_SCH dlg( m_frame ); + int dlgResult = dlg.ShowModal(); + + std::list>& list = dlg.GetImportedItems(); + + if( dlgResult != wxID_OK ) + return 0; + + // Ensure the list is not empty: + if( list.empty() ) + { + wxMessageBox( _( "No graphic items found in file." ) ); + return 0; + } + + m_toolMgr->RunAction( ACTIONS::cancelInteractive ); + + KIGFX::VIEW_CONTROLS* controls = getViewControls(); + std::vector newItems; // all new items, including group + std::vector selectedItems; // the group, or newItems if no group + EE_SELECTION preview; + SCH_COMMIT commit( m_toolMgr ); + + for( std::unique_ptr& ptr : list ) + { + LIB_ITEM* item = dynamic_cast( ptr.get() ); + wxCHECK2( item, continue ); + + newItems.push_back( item ); + selectedItems.push_back( item ); + preview.Add( item ); + + ptr.release(); + } + + if( !dlg.IsPlacementInteractive() ) + { + commit.Modify( symbol, m_frame->GetScreen() ); + + // Place the imported drawings + for( LIB_ITEM* item : newItems ) + { + symbol->AddDrawItem( item ); + item->ClearEditFlags(); + } + + commit.Push( _( "Import Graphic" ) ); + m_frame->RebuildView(); + + return 0; + } + + m_view->Add( &preview ); + + // Clear the current selection then select the drawings so that edit tools work on them + m_toolMgr->RunAction( EE_ACTIONS::clearSelection ); + + EDA_ITEMS selItems( selectedItems.begin(), selectedItems.end() ); + m_toolMgr->RunAction( EE_ACTIONS::addItemsToSel, &selItems ); + + m_frame->PushTool( aEvent ); + + auto setCursor = [&]() + { + m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::MOVING ); + }; + + Activate(); + // Must be done after Activate() so that it gets set into the correct context + controls->ShowCursor( true ); + controls->ForceCursorPosition( false ); + // Set initial cursor + setCursor(); + + //SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::DXF ); + EE_GRID_HELPER grid( m_toolMgr ); + + // Now move the new items to the current cursor position: + VECTOR2I cursorPos = controls->GetCursorPosition( !aEvent.DisableGridSnapping() ); + VECTOR2I delta = cursorPos; + VECTOR2I currentOffset; + + for( LIB_ITEM* item : selectedItems ) + item->Offset( delta ); + + currentOffset += delta; + + m_view->Update( &preview ); + + // Main loop: keep receiving events + while( TOOL_EVENT* evt = Wait() ) + { + setCursor(); + + grid.SetSnap( !evt->Modifier( MD_SHIFT ) ); + grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() ); + + cursorPos = grid.Align( controls->GetMousePosition(), GRID_GRAPHICS ); + controls->ForceCursorPosition( true, cursorPos ); + + if( evt->IsCancelInteractive() || evt->IsActivate() ) + { + m_toolMgr->RunAction( EE_ACTIONS::clearSelection ); + + for( LIB_ITEM* item : newItems ) + delete item; + + break; + } + else if( evt->IsMotion() ) + { + delta = VECTOR2I( cursorPos.x, -cursorPos.y ) - currentOffset; + + for( LIB_ITEM* item : selectedItems ) + item->Offset( delta ); + + currentOffset += delta; + + m_view->Update( &preview ); + } + else if( evt->IsClick( BUT_RIGHT ) ) + { + m_menu.ShowContextMenu( m_selectionTool->GetSelection() ); + } + else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) ) + { + commit.Modify( symbol, m_frame->GetScreen() ); + + // Place the imported drawings + for( LIB_ITEM* item : newItems ) + { + symbol->AddDrawItem( item ); + item->ClearEditFlags(); + } + + commit.Push( _( "Import Graphic" ) ); + break; // This is a one-shot command, not a tool + } + else + { + evt->SetPassEvent(); + } + } + + preview.Clear(); + m_view->Remove( &preview ); + + m_frame->RebuildView(); + + m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW ); + controls->ForceCursorPosition( false ); + + m_frame->PopTool( aEvent ); + + return 0; +} + + int SYMBOL_EDITOR_DRAWING_TOOLS::RepeatDrawItem( const TOOL_EVENT& aEvent ) { SYMBOL_EDITOR_PIN_TOOL* pinTool = m_toolMgr->GetTool(); @@ -698,5 +868,6 @@ void SYMBOL_EDITOR_DRAWING_TOOLS::setTransitions() Go( &SYMBOL_EDITOR_DRAWING_TOOLS::DrawShape, EE_ACTIONS::drawSymbolPolygon.MakeEvent() ); Go( &SYMBOL_EDITOR_DRAWING_TOOLS::DrawSymbolTextBox, EE_ACTIONS::drawSymbolTextBox.MakeEvent() ); Go( &SYMBOL_EDITOR_DRAWING_TOOLS::PlaceAnchor, EE_ACTIONS::placeSymbolAnchor.MakeEvent() ); + Go( &SYMBOL_EDITOR_DRAWING_TOOLS::SymbolImportGraphics, EE_ACTIONS::symbolImportGraphics.MakeEvent() ); Go( &SYMBOL_EDITOR_DRAWING_TOOLS::RepeatDrawItem, EE_ACTIONS::repeatDrawItem.MakeEvent() ); } diff --git a/eeschema/tools/symbol_editor_drawing_tools.h b/eeschema/tools/symbol_editor_drawing_tools.h index 0abc7f61ac..21a791cf43 100644 --- a/eeschema/tools/symbol_editor_drawing_tools.h +++ b/eeschema/tools/symbol_editor_drawing_tools.h @@ -52,6 +52,7 @@ public: int DrawShape( const TOOL_EVENT& aEvent ); int DrawSymbolTextBox( const TOOL_EVENT& aEvent ); int PlaceAnchor( const TOOL_EVENT& aEvent ); + int SymbolImportGraphics( const TOOL_EVENT& aEvent ); int RepeatDrawItem( const TOOL_EVENT& aEvent ); diff --git a/pcbnew/import_gfx/graphics_importer_pcbnew.cpp b/pcbnew/import_gfx/graphics_importer_pcbnew.cpp index 6862219839..781c99a111 100644 --- a/pcbnew/import_gfx/graphics_importer_pcbnew.cpp +++ b/pcbnew/import_gfx/graphics_importer_pcbnew.cpp @@ -64,14 +64,23 @@ int GRAPHICS_IMPORTER_PCBNEW::MapLineWidth( double aLineWidth ) } -void GRAPHICS_IMPORTER_PCBNEW::AddLine( const VECTOR2D& aOrigin, const VECTOR2D& aEnd, - double aWidth, const COLOR4D& aColor ) +STROKE_PARAMS GRAPHICS_IMPORTER_PCBNEW::MapStrokeParams( const STROKE_PARAMS& aStroke ) +{ + int width = aStroke.GetWidth(); + + return STROKE_PARAMS( width != -1 ? MapLineWidth( width ) : -1, aStroke.GetPlotStyle(), + aStroke.GetColor() ); +} + + +void GRAPHICS_IMPORTER_PCBNEW::AddLine( const VECTOR2D& aStart, const VECTOR2D& aEnd, + const STROKE_PARAMS& aStroke ) { std::unique_ptr line( createDrawing() ); line->SetShape( SHAPE_T::SEGMENT ); line->SetLayer( GetLayer() ); - line->SetStroke( STROKE_PARAMS( MapLineWidth( aWidth ), PLOT_DASH_TYPE::SOLID ) ); - line->SetStart( MapCoordinate( aOrigin ) ); + line->SetStroke( MapStrokeParams( aStroke ) ); + line->SetStart( MapCoordinate( aStart ) ); line->SetEnd( MapCoordinate( aEnd ) ); // Skip 0 len lines: @@ -82,15 +91,16 @@ void GRAPHICS_IMPORTER_PCBNEW::AddLine( const VECTOR2D& aOrigin, const VECTOR2D& } -void GRAPHICS_IMPORTER_PCBNEW::AddCircle( const VECTOR2D& aCenter, double aRadius, double aWidth, - bool aFilled, const COLOR4D& aColor ) +void GRAPHICS_IMPORTER_PCBNEW::AddCircle( const VECTOR2D& aCenter, double aRadius, + const STROKE_PARAMS& aStroke, bool aFilled, + const COLOR4D& aFillColor ) { std::unique_ptr circle( createDrawing() ); circle->SetShape( SHAPE_T::CIRCLE ); circle->SetFilled( aFilled ); circle->SetLayer( GetLayer() ); - circle->SetStroke( STROKE_PARAMS( MapLineWidth( aWidth ), PLOT_DASH_TYPE::SOLID ) ); - circle->SetStart( MapCoordinate( aCenter )); + circle->SetStroke( MapStrokeParams( aStroke ) ); + circle->SetStart( MapCoordinate( aCenter ) ); circle->SetEnd( MapCoordinate( VECTOR2D( aCenter.x + aRadius, aCenter.y ) ) ); addItem( std::move( circle ) ); @@ -98,8 +108,7 @@ void GRAPHICS_IMPORTER_PCBNEW::AddCircle( const VECTOR2D& aCenter, double aRadiu void GRAPHICS_IMPORTER_PCBNEW::AddArc( const VECTOR2D& aCenter, const VECTOR2D& aStart, - const EDA_ANGLE& aAngle, double aWidth, - const COLOR4D& aColor ) + const EDA_ANGLE& aAngle, const STROKE_PARAMS& aStroke ) { std::unique_ptr arc( createDrawing() ); arc->SetShape( SHAPE_T::ARC ); @@ -128,18 +137,19 @@ void GRAPHICS_IMPORTER_PCBNEW::AddArc( const VECTOR2D& aCenter, const VECTOR2D& if( radius >= rd_max_value ) { // Arc cannot be handled: convert it to a segment - AddLine( aStart, end, aWidth, aColor ); + AddLine( aStart, end, aStroke ); return; } - arc->SetStroke( STROKE_PARAMS( MapLineWidth( aWidth ), PLOT_DASH_TYPE::SOLID ) ); + arc->SetStroke( MapStrokeParams( aStroke ) ); addItem( std::move( arc ) ); } -void GRAPHICS_IMPORTER_PCBNEW::AddPolygon( const std::vector& aVertices, double aWidth, - const COLOR4D& aColor ) +void GRAPHICS_IMPORTER_PCBNEW::AddPolygon( const std::vector& aVertices, + const STROKE_PARAMS& aStroke, bool aFilled, + const COLOR4D& aFillColor ) { std::vector convertedPoints; convertedPoints.reserve( aVertices.size() ); @@ -159,7 +169,7 @@ void GRAPHICS_IMPORTER_PCBNEW::AddPolygon( const std::vector& aVertice polygon->Move( parentFP->GetPosition() ); } - polygon->SetStroke( STROKE_PARAMS( MapLineWidth( aWidth ), PLOT_DASH_TYPE::SOLID ) ); + polygon->SetStroke( MapStrokeParams( aStroke ) ); addItem( std::move( polygon ) ); } @@ -184,19 +194,19 @@ 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 COLOR4D& aColor ) +void GRAPHICS_IMPORTER_PCBNEW::AddSpline( const VECTOR2D& aStart, const VECTOR2D& aBezierControl1, + const VECTOR2D& aBezierControl2, const VECTOR2D& aEnd, + const STROKE_PARAMS& aStroke ) { std::unique_ptr spline( createDrawing() ); spline->SetShape( SHAPE_T::BEZIER ); spline->SetLayer( GetLayer() ); - spline->SetStroke( STROKE_PARAMS( MapLineWidth( aWidth ), PLOT_DASH_TYPE::SOLID ) ); + spline->SetStroke( MapStrokeParams( aStroke ) ); spline->SetStart( MapCoordinate( aStart ) ); - spline->SetBezierC1( MapCoordinate( BezierControl1 )); - spline->SetBezierC2( MapCoordinate( BezierControl2 )); + spline->SetBezierC1( MapCoordinate( aBezierControl1 )); + spline->SetBezierC2( MapCoordinate( aBezierControl2 )); spline->SetEnd( MapCoordinate( aEnd ) ); - spline->RebuildBezierToSegmentsPointsList( aWidth ); + spline->RebuildBezierToSegmentsPointsList( aStroke.GetWidth() ); // If the spline is degenerated (i.e. a segment) add it as segment or discard it if // null (i.e. very small) length diff --git a/pcbnew/import_gfx/graphics_importer_pcbnew.h b/pcbnew/import_gfx/graphics_importer_pcbnew.h index 258b7f4dd3..7ee1b3ddf2 100644 --- a/pcbnew/import_gfx/graphics_importer_pcbnew.h +++ b/pcbnew/import_gfx/graphics_importer_pcbnew.h @@ -59,25 +59,26 @@ public: return m_layer; } - void AddLine( const VECTOR2D& aOrigin, const VECTOR2D& aEnd, double aWidth, - const COLOR4D& aColor ) override; + void AddLine( const VECTOR2D& aStart, const VECTOR2D& aEnd, + const STROKE_PARAMS& aStroke ) override; - void AddCircle( const VECTOR2D& aOrigin, double aRadius, double aWidth, bool aFilled, - const COLOR4D& aColor ) override; + void AddCircle( const VECTOR2D& aCenter, double aRadius, const STROKE_PARAMS& aStroke, + bool aFilled, const COLOR4D& aFillColor = COLOR4D::UNSPECIFIED ) override; void AddArc( const VECTOR2D& aCenter, const VECTOR2D& aStart, const EDA_ANGLE& aAngle, - double aWidth, const COLOR4D& aColor ) override; + const STROKE_PARAMS& aStroke ) override; - void AddPolygon( const std::vector& aVertices, double aWidth, - const COLOR4D& aColor ) override; + void AddPolygon( const std::vector& aVertices, const STROKE_PARAMS& aStroke, + bool aFilled, const COLOR4D& aFillColor = COLOR4D::UNSPECIFIED ) override; void AddText( const VECTOR2D& aOrigin, const wxString& aText, double aHeight, double aWidth, double aThickness, double aOrientation, GR_TEXT_H_ALIGN_T aHJustify, - GR_TEXT_V_ALIGN_T aVJustify, const COLOR4D& aColor ) override; + GR_TEXT_V_ALIGN_T aVJustify, + const COLOR4D& aColor = COLOR4D::UNSPECIFIED ) override; void AddSpline( const VECTOR2D& aStart, const VECTOR2D& aBezierControl1, - const VECTOR2D& aBezierControl2, const VECTOR2D& aEnd, double aWidth, - const COLOR4D& aColor ) override; + const VECTOR2D& aBezierControl2, const VECTOR2D& aEnd, + const STROKE_PARAMS& aStroke ) override; /** * Convert an imported coordinate to a board coordinate, according to the internal units, @@ -95,6 +96,8 @@ public: */ int MapLineWidth( double aLineWidth ); + STROKE_PARAMS MapStrokeParams( const STROKE_PARAMS& aStroke ); + protected: ///< Create an object representing a graphical shape. virtual std::unique_ptr createDrawing() = 0;