1 /* 2 * This program source code file is part of KiCad, a free EDA CAD application. 3 * 4 * Copyright (C) 2014 CERN 5 * Copyright (C) 2020 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 27 #ifndef ALIGN_DISTRIBUTE_TOOL_H_ 28 #define ALIGN_DISTRIBUTE_TOOL_H_ 29 30 #include <tool/tool_interactive.h> 31 #include <tools/pcb_selection.h> 32 #include <board_item.h> 33 #include <pcb_base_frame.h> 34 35 using ALIGNMENT_RECT = std::pair<BOARD_ITEM*, EDA_RECT>; 36 using ALIGNMENT_RECTS = std::vector<ALIGNMENT_RECT>; 37 38 class PCB_SELECTION_TOOL; 39 40 class ALIGN_DISTRIBUTE_TOOL : public TOOL_INTERACTIVE 41 { 42 public: 43 ALIGN_DISTRIBUTE_TOOL(); 44 virtual ~ALIGN_DISTRIBUTE_TOOL(); 45 46 /// @copydoc TOOL_INTERACTIVE::Reset() Reset(RESET_REASON aReason)47 void Reset( RESET_REASON aReason ) override {} 48 49 /// @copydoc TOOL_INTERACTIVE::Init() 50 bool Init() override; 51 52 /** 53 * Set Y coordinate of the selected items to the value of the top-most selected item Y 54 * coordinate. 55 */ 56 int AlignTop( const TOOL_EVENT& aEvent ); 57 58 /** 59 * Sets Y coordinate of the selected items to the value of the bottom-most selected item Y 60 * coordinate. 61 */ 62 int AlignBottom( const TOOL_EVENT& aEvent ); 63 64 /** 65 * Sets X coordinate of the selected items to the value of the left-most selected item X 66 * coordinate. 67 */ 68 int AlignLeft( const TOOL_EVENT& aEvent ); 69 70 /** 71 * Sets X coordinate of the selected items to the value of the right-most selected item X 72 * coordinate. 73 */ 74 int AlignRight( const TOOL_EVENT& aEvent ); 75 76 /** 77 * Set the x coordinate of the midpoint of each of the selected items to the value of the 78 * x coordinate of the center of the middle selected item. 79 */ 80 int AlignCenterX( const TOOL_EVENT& aEvent ); 81 82 /** 83 * Set the y coordinate of the midpoint of each of the selected items to the value of the 84 * y coordinate of the center of the middle selected item. 85 */ 86 int AlignCenterY( const TOOL_EVENT& aEvent ); 87 88 /** 89 * Distribute the selected items along the X axis. 90 */ 91 int DistributeHorizontally( const TOOL_EVENT& aEvent ); 92 93 /** 94 * Distribute the selected items along the Y axis. 95 */ 96 int DistributeVertically( const TOOL_EVENT& aEvent ); 97 98 ///< Set up handlers for various events. 99 void setTransitions() override; 100 101 private: 102 /** 103 * Populate two vectors with the sorted selection and sorted locked items. 104 * 105 * Returns the size of aItemsToAlign() 106 */ 107 template< typename T > 108 size_t GetSelections( ALIGNMENT_RECTS& aItemsToAlign, ALIGNMENT_RECTS& aLockedItems, 109 T aCompare ); 110 111 template< typename T > 112 int selectTarget( ALIGNMENT_RECTS& aItems, ALIGNMENT_RECTS& aLocked, T aGetValue ); 113 114 /** 115 * Sets X coordinate of the selected items to the value of the left-most selected item 116 * X coordinate. 117 * 118 * @note Uses the bounding box of items, which do not get mirrored even when 119 * the view is mirrored! 120 */ 121 int doAlignLeft(); 122 123 /** 124 * Align selected items using the right edge of their bounding boxes to the right-most item. 125 * 126 * @note Uses the bounding box of items, which do not get mirrored even when 127 * the view is mirrored! 128 */ 129 int doAlignRight(); 130 131 /** 132 * Distribute selected items using an even spacing between the centers of their bounding 133 * boxes. 134 * 135 * @note Using the centers of bounding box of items can give unsatisfactory visual results 136 * since items of differing widths will be placed with different gaps. Is only used if 137 * items overlap. 138 */ 139 void doDistributeCentersHorizontally( ALIGNMENT_RECTS& itemsToDistribute, 140 BOARD_COMMIT& aCommit ) const; 141 142 /** 143 * Distribute selected items using an even spacing between the centers of their bounding 144 * boxes. 145 * 146 * @note Using the centers of bounding box of items can give unsatisfactory visual results 147 * since items of differing widths will be placed with different gaps. Is only used 148 * if items overlap 149 */ 150 void doDistributeCentersVertically( ALIGNMENT_RECTS& itemsToDistribute, 151 BOARD_COMMIT& aCommit ) const; 152 153 /** 154 * Distributes selected items using an even spacing between their bounding boxes 155 * 156 * @note Using the edges of bounding box of items is only possible if there is enough space 157 * between them. If this is not the case, use the center spacing method 158 */ 159 void doDistributeGapsHorizontally( ALIGNMENT_RECTS& itemsToDistribute, BOARD_COMMIT& aCommit, 160 const BOARD_ITEM* lastItem, int totalGap ) const; 161 162 /** 163 * Distributes selected items using an even spacing between their bounding boxes 164 * 165 * @note Using the edges of bounding box of items is only possible if there is enough space 166 * between them. If this is not the case, use the center spacing method 167 */ 168 void doDistributeGapsVertically( ALIGNMENT_RECTS& itemsToDistribute, BOARD_COMMIT& aCommit, 169 const BOARD_ITEM* lastItem, int totalGap ) const; 170 171 private: 172 PCB_SELECTION_TOOL* m_selectionTool; 173 ACTION_MENU* m_placementMenu; 174 PCB_BASE_FRAME* m_frame; 175 }; 176 177 #endif /* ALIGN_DISTRIBUTE_TOOL_H_ */ 178