2014-07-09 13:02:56 +00:00
/*
* This program source code file is part of KiCad , a free EDA CAD application .
*
2015-02-21 20:16:28 +00:00
* Copyright ( C ) 2014 - 2015 CERN
2014-07-09 13:02:56 +00:00
* @ author Maciej Suminski < maciej . suminski @ cern . ch >
*
* 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
*/
2017-01-27 11:07:29 +00:00
# include "module_editor_tools.h"
2017-05-18 17:21:30 +00:00
# include "kicad_clipboard.h"
2014-07-09 13:02:56 +00:00
# include "selection_tool.h"
2017-02-21 12:42:08 +00:00
# include "pcb_actions.h"
2015-05-05 18:39:41 +00:00
# include <tool/tool_manager.h>
2014-07-09 13:02:56 +00:00
# include <class_draw_panel_gal.h>
# include <view/view_controls.h>
# include <view/view_group.h>
2014-07-09 13:10:32 +00:00
# include <pcb_painter.h>
2015-09-05 19:47:35 +00:00
# include <origin_viewitem.h>
2014-07-09 13:02:56 +00:00
# include <kicad_plugin.h>
# include <pcbnew_id.h>
2014-07-09 13:02:56 +00:00
# include <collectors.h>
# include <confirm.h>
2014-07-09 13:10:32 +00:00
# include <dialogs/dialog_enum_pads.h>
2017-02-20 18:10:20 +00:00
# include <hotkeys.h>
# include <bitmaps.h>
2014-07-09 13:02:56 +00:00
# include <wxPcbStruct.h>
# include <class_board.h>
# include <class_module.h>
# include <class_edge_mod.h>
2016-06-21 15:06:28 +00:00
# include <board_commit.h>
2014-07-09 13:02:56 +00:00
2017-02-04 05:09:50 +00:00
# include <tools/tool_event_utils.h>
2016-06-29 10:23:11 +00:00
# include <functional>
using namespace std : : placeholders ;
2014-07-09 13:10:32 +00:00
# include <wx/defs.h>
2014-07-09 13:02:56 +00:00
2017-02-20 18:10:20 +00:00
// Module editor tools
TOOL_ACTION PCB_ACTIONS : : placePad ( " pcbnew.ModuleEditor.placePad " ,
AS_GLOBAL , 0 ,
_ ( " Add Pad " ) , _ ( " Add a pad " ) , NULL , AF_ACTIVATE ) ;
2017-10-19 21:16:06 +00:00
TOOL_ACTION PCB_ACTIONS : : createPadFromShapes ( " pcbnew.ModuleEditor.createPadFromShapes " ,
AS_CONTEXT , 0 ,
_ ( " Create Pad from Selected Shapes " ) , _ ( " Creates a custom-shaped pads from a set of selected shapes " ) ) ;
TOOL_ACTION PCB_ACTIONS : : explodePadToShapes ( " pcbnew.ModuleEditor.explodePadToShapes " ,
AS_CONTEXT , 0 ,
_ ( " Explode Selected Pad to Graphical Shapes " ) , _ ( " Converts a custom-shaped pads to a set of graphical shapes " ) ) ;
2017-02-20 18:10:20 +00:00
TOOL_ACTION PCB_ACTIONS : : enumeratePads ( " pcbnew.ModuleEditor.enumeratePads " ,
AS_GLOBAL , 0 ,
_ ( " Enumerate Pads " ) , _ ( " Enumerate pads " ) , pad_enumerate_xpm , AF_ACTIVATE ) ;
TOOL_ACTION PCB_ACTIONS : : moduleEdgeOutlines ( " pcbnew.ModuleEditor.graphicOutlines " ,
AS_GLOBAL , 0 ,
" " , " " ) ;
TOOL_ACTION PCB_ACTIONS : : moduleTextOutlines ( " pcbnew.ModuleEditor.textOutlines " ,
AS_GLOBAL , 0 ,
" " , " " ) ;
2017-01-27 11:07:29 +00:00
MODULE_EDITOR_TOOLS : : MODULE_EDITOR_TOOLS ( ) :
2017-04-18 15:32:05 +00:00
PCB_TOOL ( " pcbnew.ModuleEditor " )
2014-07-09 13:02:56 +00:00
{
2015-09-05 19:47:35 +00:00
}
2017-01-27 11:07:29 +00:00
MODULE_EDITOR_TOOLS : : ~ MODULE_EDITOR_TOOLS ( )
2015-09-05 19:47:35 +00:00
{
2014-07-09 13:02:56 +00:00
}
2017-01-27 11:07:29 +00:00
void MODULE_EDITOR_TOOLS : : Reset ( RESET_REASON aReason )
2014-07-09 13:02:56 +00:00
{
}
2017-04-22 15:46:31 +00:00
2017-01-27 11:07:29 +00:00
int MODULE_EDITOR_TOOLS : : PlacePad ( const TOOL_EVENT & aEvent )
2014-07-09 13:02:56 +00:00
{
2017-04-22 15:46:31 +00:00
struct PAD_PLACER : public INTERACTIVE_PLACER_BASE
2014-07-09 13:02:56 +00:00
{
2017-04-22 15:46:31 +00:00
std : : unique_ptr < BOARD_ITEM > CreateItem ( ) override
2014-07-09 13:02:56 +00:00
{
2017-04-22 15:46:31 +00:00
D_PAD * pad = new D_PAD ( m_board - > m_Modules ) ;
m_frame - > Import_Pad_Settings ( pad , false ) ; // use the global settings for pad
2017-06-23 13:19:04 +00:00
pad - > IncrementPadName ( true , true ) ;
2017-04-22 15:46:31 +00:00
return std : : unique_ptr < BOARD_ITEM > ( pad ) ;
2014-07-09 13:02:56 +00:00
}
2017-04-22 15:46:31 +00:00
} ;
2014-07-09 13:02:56 +00:00
2017-04-22 15:46:31 +00:00
PAD_PLACER placer ;
2014-07-09 13:02:56 +00:00
2017-04-22 15:46:31 +00:00
frame ( ) - > SetToolID ( ID_MODEDIT_PAD_TOOL , wxCURSOR_PENCIL , _ ( " Add pads " ) ) ;
2014-07-09 13:02:56 +00:00
2017-04-22 15:46:31 +00:00
assert ( board ( ) - > m_Modules ) ;
2014-07-09 13:02:56 +00:00
2017-04-22 15:46:31 +00:00
doInteractiveItemPlacement ( & placer , _ ( " Place pad " ) , IPO_REPEAT | IPO_SINGLE_CLICK | IPO_ROTATE | IPO_FLIP | IPO_PROPERTIES ) ;
2014-07-09 13:02:56 +00:00
2017-04-18 15:32:05 +00:00
frame ( ) - > SetNoToolSelected ( ) ;
2014-07-09 13:02:56 +00:00
return 0 ;
}
2017-01-27 11:07:29 +00:00
int MODULE_EDITOR_TOOLS : : EnumeratePads ( const TOOL_EVENT & aEvent )
2014-07-09 13:02:56 +00:00
{
2017-04-25 09:06:24 +00:00
if ( ! board ( ) - > m_Modules | | ! board ( ) - > m_Modules - > PadsList ( ) )
2015-08-25 08:22:52 +00:00
return 0 ;
2017-07-19 13:58:53 +00:00
DIALOG_ENUM_PADS settingsDlg ( frame ( ) ) ;
if ( settingsDlg . ShowModal ( ) ! = wxID_OK )
return 0 ;
2017-03-02 11:34:19 +00:00
Activate ( ) ;
2014-07-09 13:02:56 +00:00
GENERAL_COLLECTOR collector ;
const KICAD_T types [ ] = { PCB_PAD_T , EOT } ;
2017-04-18 15:32:05 +00:00
GENERAL_COLLECTORS_GUIDE guide = frame ( ) - > GetCollectorsGuide ( ) ;
2014-07-09 13:02:56 +00:00
guide . SetIgnoreMTextsMarkedNoShow ( true ) ;
2014-09-11 16:35:19 +00:00
guide . SetIgnoreMTextsOnBack ( true ) ;
guide . SetIgnoreMTextsOnFront ( true ) ;
2014-07-09 13:02:56 +00:00
guide . SetIgnoreModulesVals ( true ) ;
guide . SetIgnoreModulesRefs ( true ) ;
2014-07-09 13:10:32 +00:00
int padNumber = settingsDlg . GetStartNumber ( ) ;
wxString padPrefix = settingsDlg . GetPrefix ( ) ;
2014-07-09 13:02:56 +00:00
2017-04-18 15:32:05 +00:00
frame ( ) - > DisplayToolMsg ( _ (
" Hold left mouse button and move cursor over pads to enumerate them " ) ) ;
2014-07-09 13:02:56 +00:00
2017-02-21 12:42:08 +00:00
m_toolMgr - > RunAction ( PCB_ACTIONS : : selectionClear , true ) ;
2017-04-18 15:32:05 +00:00
getViewControls ( ) - > ShowCursor ( true ) ;
2017-07-19 13:58:53 +00:00
frame ( ) - > GetGalCanvas ( ) - > SetCursor ( wxCURSOR_HAND ) ;
2017-03-02 11:34:19 +00:00
KIGFX : : VIEW * view = m_toolMgr - > GetView ( ) ;
2017-07-19 13:58:53 +00:00
VECTOR2I oldCursorPos ; // store the previous mouse cursor position, during mouse drag
2015-02-21 20:16:28 +00:00
std : : list < D_PAD * > selectedPads ;
2017-04-18 15:32:05 +00:00
BOARD_COMMIT commit ( frame ( ) ) ;
2017-03-02 11:34:19 +00:00
std : : map < wxString , wxString > oldNames ;
2017-07-19 13:58:53 +00:00
bool isFirstPoint = true ; // used to be sure oldCursorPos will be initialized at least once.
2014-07-09 13:02:56 +00:00
while ( OPT_TOOL_EVENT evt = Wait ( ) )
{
2017-08-08 14:46:20 +00:00
if ( evt - > IsDrag ( BUT_LEFT ) | | evt - > IsClick ( BUT_LEFT ) )
2014-07-09 13:02:56 +00:00
{
2015-02-21 20:16:28 +00:00
selectedPads . clear ( ) ;
2017-04-18 15:32:05 +00:00
VECTOR2I cursorPos = getViewControls ( ) - > GetCursorPosition ( ) ;
2014-07-09 13:02:56 +00:00
2017-07-19 13:58:53 +00:00
// Be sure the old cursor mouse position was initialized:
if ( isFirstPoint )
{
oldCursorPos = cursorPos ;
isFirstPoint = false ;
}
// wxWidgets deliver mouse move events not frequently enough, resulting in skipping
// pads if the user moves cursor too fast. To solve it, create a line that approximates
// the mouse move and search pads that are on the line.
int distance = ( cursorPos - oldCursorPos ) . EuclideanNorm ( ) ;
// Search will be made every 0.1 mm:
int segments = distance / int ( 0.1 * IU_PER_MM ) + 1 ;
const wxPoint line_step ( ( cursorPos - oldCursorPos ) / segments ) ;
collector . Empty ( ) ;
for ( int j = 0 ; j < segments ; + + j )
2014-07-09 13:02:56 +00:00
{
2017-07-19 13:58:53 +00:00
wxPoint testpoint ( cursorPos . x - j * line_step . x ,
cursorPos . y - j * line_step . y ) ;
collector . Collect ( board ( ) , types , testpoint , guide ) ;
2014-07-09 13:02:56 +00:00
2015-02-21 20:16:28 +00:00
for ( int i = 0 ; i < collector . GetCount ( ) ; + + i )
{
2017-07-19 13:58:53 +00:00
selectedPads . push_back ( static_cast < D_PAD * > ( collector [ i ] ) ) ;
2015-02-21 20:16:28 +00:00
}
}
2014-07-09 13:02:56 +00:00
2017-07-19 13:58:53 +00:00
selectedPads . unique ( ) ;
2015-02-21 20:16:28 +00:00
2016-06-29 20:07:55 +00:00
for ( D_PAD * pad : selectedPads )
2015-02-21 20:16:28 +00:00
{
2017-03-02 11:34:19 +00:00
// If pad was not selected, then enumerate it
if ( ! pad - > IsSelected ( ) )
2015-02-21 20:16:28 +00:00
{
2017-03-02 11:34:19 +00:00
commit . Modify ( pad ) ;
// Rename pad and store the old name
wxString newName = wxString : : Format ( wxT ( " %s%d " ) , padPrefix . c_str ( ) , padNumber + + ) ;
2017-08-11 09:22:13 +00:00
oldNames [ newName ] = pad - > GetName ( ) ;
pad - > SetName ( newName ) ;
2015-02-21 20:16:28 +00:00
pad - > SetSelected ( ) ;
2017-03-02 11:34:19 +00:00
getView ( ) - > Update ( pad ) ;
2015-02-21 20:16:28 +00:00
}
2017-03-02 11:34:19 +00:00
// ..or restore the old name if it was enumerated and clicked again
else if ( pad - > IsSelected ( ) & & evt - > IsClick ( BUT_LEFT ) )
2015-02-21 20:16:28 +00:00
{
2017-08-11 09:22:13 +00:00
auto it = oldNames . find ( pad - > GetName ( ) ) ;
2017-03-02 11:34:19 +00:00
wxASSERT ( it ! = oldNames . end ( ) ) ;
if ( it ! = oldNames . end ( ) )
{
2017-08-11 09:22:13 +00:00
pad - > SetName ( it - > second ) ;
2017-03-02 11:34:19 +00:00
oldNames . erase ( it ) ;
}
2015-02-21 20:16:28 +00:00
pad - > ClearSelected ( ) ;
2017-03-02 11:34:19 +00:00
getView ( ) - > Update ( pad ) ;
2014-07-09 13:02:56 +00:00
}
}
}
else if ( ( evt - > IsKeyPressed ( ) & & evt - > KeyCode ( ) = = WXK_RETURN ) | |
evt - > IsDblClick ( BUT_LEFT ) )
{
2016-06-21 15:06:28 +00:00
commit . Push ( _ ( " Enumerate pads " ) ) ;
2014-07-09 13:02:56 +00:00
break ;
}
else if ( evt - > IsCancel ( ) | | evt - > IsActivate ( ) )
{
2017-03-02 11:34:19 +00:00
commit . Revert ( ) ;
2014-07-09 13:02:56 +00:00
break ;
}
2017-07-19 13:58:53 +00:00
// Prepare the next loop by updating the old cursor mouse position
// to this last mouse cursor position
oldCursorPos = getViewControls ( ) - > GetCursorPosition ( ) ;
2014-07-09 13:02:56 +00:00
}
2017-04-25 09:06:24 +00:00
for ( auto p : board ( ) - > m_Modules - > Pads ( ) )
2017-03-02 11:34:19 +00:00
{
p - > ClearSelected ( ) ;
view - > Update ( p ) ;
}
2014-07-09 13:02:56 +00:00
2017-04-18 15:32:05 +00:00
frame ( ) - > DisplayToolMsg ( wxEmptyString ) ;
2017-07-19 13:58:53 +00:00
frame ( ) - > GetGalCanvas ( ) - > SetCursor ( wxCURSOR_ARROW ) ;
2014-07-09 13:02:56 +00:00
return 0 ;
}
2017-01-27 11:07:29 +00:00
int MODULE_EDITOR_TOOLS : : ModuleTextOutlines ( const TOOL_EVENT & aEvent )
2014-07-09 13:10:32 +00:00
{
2017-01-17 12:34:56 +00:00
KIGFX : : VIEW * view = getView ( ) ;
2014-07-09 13:10:32 +00:00
KIGFX : : PCB_RENDER_SETTINGS * settings =
2017-01-17 12:34:56 +00:00
static_cast < KIGFX : : PCB_RENDER_SETTINGS * > ( view - > GetPainter ( ) - > GetSettings ( ) ) ;
2014-07-09 13:10:32 +00:00
2017-03-13 03:19:33 +00:00
const LAYER_NUM layers [ ] = { LAYER_MOD_TEXT_BK ,
LAYER_MOD_TEXT_FR ,
LAYER_MOD_TEXT_INVISIBLE ,
LAYER_MOD_REFERENCES ,
LAYER_MOD_VALUES } ;
2014-07-09 13:10:32 +00:00
bool enable = ! settings - > GetSketchMode ( layers [ 0 ] ) ;
2016-06-29 20:07:55 +00:00
for ( LAYER_NUM layer : layers )
2014-07-09 13:10:32 +00:00
settings - > SetSketchMode ( layer , enable ) ;
2017-04-18 15:32:05 +00:00
for ( auto module : board ( ) - > Modules ( ) )
2014-07-09 13:10:32 +00:00
{
2017-04-25 09:06:24 +00:00
for ( auto item : module - > GraphicalItems ( ) )
2014-07-09 13:10:32 +00:00
{
if ( item - > Type ( ) = = PCB_MODULE_TEXT_T )
2017-01-17 12:34:56 +00:00
view - > Update ( item , KIGFX : : GEOMETRY ) ;
2014-07-09 13:10:32 +00:00
}
2017-01-17 12:34:56 +00:00
view - > Update ( & module - > Reference ( ) , KIGFX : : GEOMETRY ) ;
view - > Update ( & module - > Value ( ) , KIGFX : : GEOMETRY ) ;
2014-07-09 13:10:32 +00:00
}
2017-04-18 15:32:05 +00:00
frame ( ) - > GetGalCanvas ( ) - > Refresh ( ) ;
2014-07-09 13:10:32 +00:00
return 0 ;
}
2017-01-27 11:07:29 +00:00
int MODULE_EDITOR_TOOLS : : ModuleEdgeOutlines ( const TOOL_EVENT & aEvent )
2014-07-09 13:10:32 +00:00
{
2017-01-17 12:34:56 +00:00
KIGFX : : VIEW * view = getView ( ) ;
2014-07-09 13:10:32 +00:00
KIGFX : : PCB_RENDER_SETTINGS * settings =
2017-01-17 12:34:56 +00:00
static_cast < KIGFX : : PCB_RENDER_SETTINGS * > ( view - > GetPainter ( ) - > GetSettings ( ) ) ;
2014-07-09 13:10:32 +00:00
2017-03-13 03:19:33 +00:00
const PCB_LAYER_ID layers [ ] = { F_Adhes , B_Adhes , F_Paste , B_Paste ,
2014-07-09 14:25:50 +00:00
F_SilkS , B_SilkS , F_Mask , B_Mask ,
Dwgs_User , Cmts_User , Eco1_User , Eco2_User , Edge_Cuts } ;
2014-07-09 13:10:32 +00:00
bool enable = ! settings - > GetSketchMode ( layers [ 0 ] ) ;
2016-06-29 20:07:55 +00:00
for ( LAYER_NUM layer : layers )
2014-07-09 13:10:32 +00:00
settings - > SetSketchMode ( layer , enable ) ;
2017-04-18 15:32:05 +00:00
for ( auto module : board ( ) - > Modules ( ) )
2014-07-09 13:10:32 +00:00
{
2017-04-25 09:06:24 +00:00
for ( auto item : module - > GraphicalItems ( ) )
2014-07-09 13:10:32 +00:00
{
if ( item - > Type ( ) = = PCB_MODULE_EDGE_T )
2017-01-17 12:34:56 +00:00
view - > Update ( item , KIGFX : : GEOMETRY ) ;
2014-07-09 13:10:32 +00:00
}
}
2017-04-18 15:32:05 +00:00
frame ( ) - > GetGalCanvas ( ) - > Refresh ( ) ;
2014-07-09 13:10:32 +00:00
return 0 ;
}
2017-10-19 21:16:06 +00:00
int MODULE_EDITOR_TOOLS : : ExplodePadToShapes ( const TOOL_EVENT & aEvent )
{
SELECTION & selection = m_toolMgr - > GetTool < SELECTION_TOOL > ( ) - > GetSelection ( ) ;
BOARD_COMMIT commit ( frame ( ) ) ;
if ( selection . Size ( ) ! = 1 )
return 0 ;
if ( selection [ 0 ] - > Type ( ) ! = PCB_PAD_T )
return 0 ;
auto pad = static_cast < D_PAD * > ( selection [ 0 ] ) ;
if ( pad - > GetShape ( ) ! = PAD_SHAPE_CUSTOM )
return 0 ;
commit . Modify ( pad ) ;
wxPoint anchor = pad - > GetPosition ( ) ;
for ( auto prim : pad - > GetPrimitives ( ) )
{
auto ds = new EDGE_MODULE ( board ( ) - > m_Modules ) ;
ds - > SetLayer ( pad - > GetLayer ( ) ) ;
ds - > SetShape ( prim . m_Shape ) ;
ds - > SetStart ( prim . m_Start + anchor ) ;
ds - > SetEnd ( prim . m_End + anchor ) ;
ds - > SetWidth ( prim . m_Thickness ) ;
for ( auto & p : prim . m_Poly )
p + = anchor ;
ds - > SetPolyPoints ( prim . m_Poly ) ;
ds - > SetAngle ( prim . m_ArcAngle ) ;
commit . Add ( ds ) ;
}
pad - > SetShape ( pad - > GetAnchorPadShape ( ) ) ;
commit . Push ( _ ( " Explode pad to shapes " ) ) ;
m_toolMgr - > RunAction ( PCB_ACTIONS : : selectionClear , true ) ;
return 0 ;
}
int MODULE_EDITOR_TOOLS : : CreatePadFromShapes ( const TOOL_EVENT & aEvent )
{
SELECTION & selection = m_toolMgr - > GetTool < SELECTION_TOOL > ( ) - > GetSelection ( ) ;
std : : unique_ptr < D_PAD > pad ( new D_PAD ( board ( ) - > m_Modules ) ) ;
D_PAD * refPad = nullptr ;
bool multipleRefPadsFound = false ;
bool illegalItemsFound = false ;
std : : vector < PAD_CS_PRIMITIVE > shapes ;
BOARD_COMMIT commit ( frame ( ) ) ;
for ( auto item : selection )
{
switch ( item - > Type ( ) )
{
case PCB_PAD_T :
{
if ( refPad )
multipleRefPadsFound = true ;
refPad = static_cast < D_PAD * > ( item ) ;
break ;
}
case PCB_MODULE_EDGE_T :
{
auto em = static_cast < EDGE_MODULE * > ( item ) ;
PAD_CS_PRIMITIVE shape ( em - > GetShape ( ) ) ;
shape . m_Start = em - > GetStart ( ) ;
shape . m_End = em - > GetEnd ( ) ;
shape . m_Radius = em - > GetRadius ( ) ;
shape . m_Thickness = em - > GetWidth ( ) ;
shape . m_ArcAngle = em - > GetAngle ( ) ;
for ( auto p : em - > GetPolyPoints ( ) )
shape . m_Poly . push_back ( p ) ;
shapes . push_back ( shape ) ;
break ;
}
default :
{
illegalItemsFound = true ;
break ;
}
}
}
if ( refPad & & selection . Size ( ) = = 1 )
{
// don't convert a pad into itself...
return 0 ;
}
if ( multipleRefPadsFound )
{
DisplayErrorMessage ( frame ( ) , _ ( " Cannot convert items to a custom-shaped pad: selection contains more than one reference pad. " ) ) ;
return 0 ;
}
if ( illegalItemsFound )
{
DisplayErrorMessage ( frame ( ) , _ ( " Cannot convert items to a custom-shaped pad: selection contains unsupported items. Only graphical lines, circles, arcs and polygons are allowed. " ) ) ;
return 0 ;
}
if ( refPad )
{
pad . reset ( static_cast < D_PAD * > ( refPad - > Clone ( ) ) ) ;
}
else
{
pad - > SetAnchorPadShape ( PAD_SHAPE_CIRCLE ) ;
pad - > SetAttribute ( PAD_ATTRIB_SMD ) ;
pad - > SetLayerSet ( D_PAD : : SMDMask ( ) ) ;
pad - > SetSize ( wxSize ( 10000 , 10000 ) ) ;
pad - > IncrementPadName ( true , true ) ;
}
pad - > SetPrimitives ( shapes ) ;
pad - > SetShape ( PAD_SHAPE_CUSTOM ) ;
boost : : optional < VECTOR2I > anchor ;
VECTOR2I tmp ;
if ( refPad )
{
anchor = pad - > GetPosition ( ) ;
}
else if ( pad - > GetBestAnchorPosition ( tmp ) )
{
anchor = tmp ;
}
if ( ! anchor )
{
DisplayErrorMessage ( frame ( ) , _ ( " Cannot convert items to a custom-shaped pad: unable to determine the anchor point position. Consider adding a small anchor pad to the selection and try again. " ) ) ;
return 0 ;
}
// relocate the shapes, they are relative to the anchor pad position
for ( auto & shape : shapes )
{
shape . m_Start . x - = anchor - > x ;
shape . m_Start . y - = anchor - > y ;
shape . m_End . x - = anchor - > x ;
shape . m_End . y - = anchor - > y ;
for ( auto & p : shape . m_Poly )
{
p . x - = anchor - > x ;
p . y - = anchor - > y ;
}
}
pad - > SetPosition ( wxPoint ( anchor - > x , anchor - > y ) ) ;
pad - > SetPrimitives ( shapes ) ;
bool result = pad - > MergePrimitivesAsPolygon ( ) ;
if ( ! result )
{
DisplayErrorMessage ( frame ( ) , _ ( " Cannot convert items to a custom-shaped pad: selected items do not form a single solid shape. " ) ) ;
return 0 ;
}
auto padPtr = pad . release ( ) ;
commit . Add ( padPtr ) ;
for ( auto item : selection )
{
commit . Remove ( item ) ;
}
m_toolMgr - > RunAction ( PCB_ACTIONS : : selectionClear , true ) ;
m_toolMgr - > RunAction ( PCB_ACTIONS : : selectItem , true , padPtr ) ;
commit . Push ( _ ( " Create Pad From Selected Shapes " ) ) ;
return 0 ;
}
2014-07-09 13:10:32 +00:00
2017-07-31 12:30:51 +00:00
void MODULE_EDITOR_TOOLS : : setTransitions ( )
2014-07-09 13:02:56 +00:00
{
2017-02-21 12:42:08 +00:00
Go ( & MODULE_EDITOR_TOOLS : : PlacePad , PCB_ACTIONS : : placePad . MakeEvent ( ) ) ;
2017-10-19 21:16:06 +00:00
Go ( & MODULE_EDITOR_TOOLS : : CreatePadFromShapes , PCB_ACTIONS : : createPadFromShapes . MakeEvent ( ) ) ;
Go ( & MODULE_EDITOR_TOOLS : : ExplodePadToShapes , PCB_ACTIONS : : explodePadToShapes . MakeEvent ( ) ) ;
2017-02-21 12:42:08 +00:00
Go ( & MODULE_EDITOR_TOOLS : : EnumeratePads , PCB_ACTIONS : : enumeratePads . MakeEvent ( ) ) ;
Go ( & MODULE_EDITOR_TOOLS : : ModuleTextOutlines , PCB_ACTIONS : : moduleTextOutlines . MakeEvent ( ) ) ;
Go ( & MODULE_EDITOR_TOOLS : : ModuleEdgeOutlines , PCB_ACTIONS : : moduleEdgeOutlines . MakeEvent ( ) ) ;
2014-07-09 13:02:56 +00:00
}