You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

196 lines
6.9 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2013-2017 CERN
  5. * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
  6. *
  7. * @author Maciej Suminski <maciej.suminski@cern.ch>
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License
  11. * as published by the Free Software Foundation; either version 2
  12. * of the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, you may find one here:
  21. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  22. * or you may search the http://www.gnu.org website for the version 2 license,
  23. * or you may write to the Free Software Foundation, Inc.,
  24. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  25. */
  26. #ifndef PCB_POINT_EDITOR_H
  27. #define PCB_POINT_EDITOR_H
  28. #include <tool/tool_interactive.h>
  29. #include "tool/edit_points.h"
  30. #include <pcbnew_settings.h>
  31. #include <status_popup.h>
  32. #include <memory>
  33. class PCB_SELECTION_TOOL;
  34. class SHAPE_POLY_SET;
  35. /**
  36. * Tool that displays edit points allowing to modify items by dragging the points.
  37. */
  38. class PCB_POINT_EDITOR : public PCB_TOOL_BASE
  39. {
  40. public:
  41. PCB_POINT_EDITOR();
  42. /// @copydoc TOOL_INTERACTIVE::Reset()
  43. void Reset( RESET_REASON aReason ) override;
  44. /// @copydoc TOOL_INTERACTIVE::Init()
  45. bool Init() override;
  46. /**
  47. * Change selection event handler.
  48. */
  49. int OnSelectionChange( const TOOL_EVENT& aEvent );
  50. /**
  51. * Indicate the cursor is over an edit point.
  52. *
  53. * Used to coordinate cursor shapes with other tools.
  54. */
  55. bool HasPoint() { return m_editedPoint != nullptr; }
  56. bool HasMidpoint() { return HasPoint() && dynamic_cast<EDIT_LINE*>( m_editedPoint ); }
  57. bool HasCorner() { return HasPoint() && !HasMidpoint(); }
  58. private:
  59. ///< Set up handlers for various events.
  60. void setTransitions() override;
  61. void buildForPolyOutline( std::shared_ptr<EDIT_POINTS> points, const SHAPE_POLY_SET* aOutline );
  62. std::shared_ptr<EDIT_POINTS> makePoints( EDA_ITEM* aItem );
  63. ///< Update item's points with edit points.
  64. void updateItem() const;
  65. /**
  66. * Validate a polygon and displays a popup warning if invalid.
  67. *
  68. * @param aModified is the polygon to be checked.
  69. * @return True if polygon is valid.
  70. */
  71. bool validatePolygon( SHAPE_POLY_SET& aModified ) const;
  72. ///< Update edit points with item's points.
  73. void updatePoints();
  74. ///< Update which point is being edited.
  75. void updateEditedPoint( const TOOL_EVENT& aEvent );
  76. ///< Set the current point being edited. NULL means none.
  77. void setEditedPoint( EDIT_POINT* aPoint );
  78. inline int getEditedPointIndex() const
  79. {
  80. for( unsigned i = 0; i < m_editPoints->PointsSize(); ++i )
  81. {
  82. if( m_editedPoint == &m_editPoints->Point( i ) )
  83. return i;
  84. }
  85. return wxNOT_FOUND;
  86. }
  87. ///< Return true if aPoint is the currently modified point.
  88. inline bool isModified( const EDIT_POINT& aPoint ) const
  89. {
  90. return m_editedPoint == &aPoint;
  91. }
  92. void pinEditedCorner( VECTOR2I& aTopLeft, VECTOR2I& aTopRight, VECTOR2I& aBotLeft,
  93. VECTOR2I& aBotRight, const VECTOR2I& aHole = { 0, 0 },
  94. const VECTOR2I& aHoleSize = { 0, 0 } ) const;
  95. ///< Set up an alternative constraint (typically enabled upon a modifier key being pressed).
  96. void setAltConstraint( bool aEnabled );
  97. ///< Return a point that should be used as a constrainer for 45 degrees mode.
  98. EDIT_POINT get45DegConstrainer() const;
  99. ///< Condition to display "Create corner" context menu entry.
  100. static bool addCornerCondition( const SELECTION& aSelection );
  101. ///< Determine if the tool can currently add a corner to the given item
  102. static bool canAddCorner( const EDA_ITEM& aItem );
  103. ///< Condition to display "Remove corner" context menu entry.
  104. bool removeCornerCondition( const SELECTION& aSelection );
  105. /// TOOL_ACTION handlers
  106. int movePoint( const TOOL_EVENT& aEvent );
  107. int addCorner( const TOOL_EVENT& aEvent );
  108. int removeCorner( const TOOL_EVENT& aEvent );
  109. int modifiedSelection( const TOOL_EVENT& aEvent );
  110. /**
  111. * Move an end point of the arc, while keeping the tangent at the other endpoint.
  112. */
  113. void editArcEndpointKeepTangent( PCB_SHAPE* aArc, const VECTOR2I& aCenter,
  114. const VECTOR2I& aStart, const VECTOR2I& aMid,
  115. const VECTOR2I& aEnd, const VECTOR2I& aCursor ) const;
  116. /**
  117. * Move an end point of the arc around the circumference.
  118. */
  119. void editArcEndpointKeepCenter( PCB_SHAPE* aArc, const VECTOR2I& aCenter,
  120. const VECTOR2I& aStart, const VECTOR2I& aMid,
  121. const VECTOR2I& aEnd, const VECTOR2I& aCursor ) const;
  122. /**
  123. * Move the arc center but keep endpoint locations.
  124. */
  125. void editArcCenterKeepEndpoints( PCB_SHAPE* aArc, const VECTOR2I& aCenter,
  126. const VECTOR2I& aStart, const VECTOR2I& aMid,
  127. const VECTOR2I& aEnd ) const;
  128. /**
  129. * Move the mid point of the arc, while keeping the two endpoints.
  130. */
  131. void editArcMidKeepEndpoints( PCB_SHAPE* aArc, const VECTOR2I& aStart, const VECTOR2I& aEnd,
  132. const VECTOR2I& aCursor ) const;
  133. /**
  134. * Move the mid point of the arc, while keeping the angle.
  135. */
  136. void editArcMidKeepCenter( PCB_SHAPE* aArc, const VECTOR2I& aCenter, const VECTOR2I& aStart,
  137. const VECTOR2I& aMid, const VECTOR2I& aEnd,
  138. const VECTOR2I& aCursor ) const;
  139. ///< Change the edit method for arcs.
  140. int changeArcEditMode( const TOOL_EVENT& aEvent );
  141. PCB_SELECTION_TOOL* m_selectionTool;
  142. mutable std::unique_ptr<STATUS_TEXT_POPUP> m_statusPopup;
  143. std::shared_ptr<EDIT_POINTS> m_editPoints;
  144. EDIT_POINT* m_editedPoint;
  145. EDIT_POINT* m_hoveredPoint;
  146. EDIT_POINT m_original; ///< Original position for the current drag point.
  147. bool m_refill;
  148. ARC_EDIT_MODE m_arcEditMode;
  149. // Alternative constraint, enabled while a modifier key is held
  150. std::shared_ptr<EDIT_CONSTRAINT<EDIT_POINT>> m_altConstraint;
  151. EDIT_POINT m_altConstrainer;
  152. static const unsigned int COORDS_PADDING; // Padding from coordinates limits for this tool
  153. };
  154. #endif