From 0f5bfdb15662bff53125b9bcee9e6b732f2a11f5 Mon Sep 17 00:00:00 2001 From: John Beard Date: Mon, 23 Jan 2017 14:47:39 +0800 Subject: [PATCH] Add mirror tool action for GAL module editor This is basically a simple clone of the legacy tool with a few minor tidy-ups for GAL mode. Fixes: lp:1619301 * https://bugs.launchpad.net/kicad/+bug/1619301 --- pcbnew/tools/common_actions.cpp | 4 ++ pcbnew/tools/common_actions.h | 3 + pcbnew/tools/edit_tool.cpp | 117 ++++++++++++++++++++++++++++++++ pcbnew/tools/edit_tool.h | 7 ++ 4 files changed, 131 insertions(+) diff --git a/pcbnew/tools/common_actions.cpp b/pcbnew/tools/common_actions.cpp index dc65bf6e35..da2694db59 100644 --- a/pcbnew/tools/common_actions.cpp +++ b/pcbnew/tools/common_actions.cpp @@ -125,6 +125,10 @@ TOOL_ACTION COMMON_ACTIONS::flip( "pcbnew.InteractiveEdit.flip", AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_FLIP_ITEM ), _( "Flip" ), _( "Flips selected item(s)" ), swap_layer_xpm ); +TOOL_ACTION COMMON_ACTIONS::mirror( "pcbnew.InteractiveEdit.mirror", + AS_GLOBAL, 0, + _( "Mirror" ), _( "Mirrors selected item" ), mirror_h_xpm ); + TOOL_ACTION COMMON_ACTIONS::remove( "pcbnew.InteractiveEdit.remove", AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_DELETE ), _( "Remove" ), _( "Deletes selected item(s)" ), delete_xpm ); diff --git a/pcbnew/tools/common_actions.h b/pcbnew/tools/common_actions.h index 2cf312ad36..a878520da3 100644 --- a/pcbnew/tools/common_actions.h +++ b/pcbnew/tools/common_actions.h @@ -76,6 +76,9 @@ public: /// Flipping of selected objects static TOOL_ACTION flip; + /// Mirroring of selected items + static TOOL_ACTION mirror; + /// Activation of the edit tool static TOOL_ACTION properties; diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index 7c831774ba..36dd9e648e 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -86,6 +86,10 @@ bool EDIT_TOOL::Init() return false; } + auto editingModuleCondition = [ this ] ( const SELECTION& aSelection ) { + return m_editModules; + }; + // Add context menu entries that are displayed when selection tool is active CONDITIONAL_MENU& menu = m_selectionTool->GetToolMenu().GetMenu(); menu.AddItem( COMMON_ACTIONS::editActivate, SELECTION_CONDITIONS::NotEmpty ); @@ -98,6 +102,9 @@ bool EDIT_TOOL::Init() menu.AddItem( COMMON_ACTIONS::duplicate, SELECTION_CONDITIONS::NotEmpty ); menu.AddItem( COMMON_ACTIONS::createArray, SELECTION_CONDITIONS::NotEmpty ); + // Mirror only available in modedit + menu.AddItem( COMMON_ACTIONS::mirror, editingModuleCondition && SELECTION_CONDITIONS::NotEmpty ); + // Footprint actions menu.AddItem( COMMON_ACTIONS::editFootprintInFpEditor, SELECTION_CONDITIONS::OnlyType( PCB_MODULE_T ) && @@ -404,6 +411,115 @@ int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent ) return 0; } +/*! + * Mirror a point about the vertical axis passing through another point + */ +static wxPoint mirrorPointX( const wxPoint& aPoint, const wxPoint& aMirrorPoint ) +{ + wxPoint mirrored = aPoint; + + mirrored.x -= aMirrorPoint.x; + mirrored.x = -mirrored.x; + mirrored.x += aMirrorPoint.x; + + return mirrored; +} + + +/** + * Mirror a pad in the vertical axis passing through a point + */ +static void mirrorPadX( D_PAD& aPad, const wxPoint& aMirrorPoint ) +{ + wxPoint tmpPt = mirrorPointX( aPad.GetPosition(), aMirrorPoint ); + + aPad.SetPosition( tmpPt ); + + aPad.SetX0( aPad.GetPosition().x ); + + tmpPt = aPad.GetOffset(); + tmpPt.x = -tmpPt.x; + aPad.SetOffset( tmpPt ); + + auto tmpz = aPad.GetDelta(); + tmpz.x = -tmpz.x; + aPad.SetDelta( tmpz ); + + aPad.SetOrientation( -aPad.GetOrientation() ); +} + + +int EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent ) +{ + const SELECTION& selection = m_selectionTool->GetSelection(); + PCB_BASE_EDIT_FRAME* editFrame = getEditFrame(); + + // Shall the selection be cleared at the end? + bool unselect = selection.Empty(); + + if( !hoverSelection() || m_selectionTool->CheckLock() == SELECTION_LOCKED ) + return 0; + + wxPoint mirrorPoint = getModificationPoint( selection ); + + for( auto item : selection ) + { + // only modify items we can mirror + switch( item->Type() ) + { + case PCB_MODULE_EDGE_T: + case PCB_MODULE_TEXT_T: + case PCB_PAD_T: + m_commit->Modify( item ); + break; + default: + continue; + } + + // modify each object as necessary + switch( item->Type() ) + { + case PCB_MODULE_EDGE_T: + { + auto& edge = static_cast( *item ); + edge.Mirror( mirrorPoint, false ); + break; + } + + case PCB_MODULE_TEXT_T: + { + auto& modText = static_cast( *item ); + modText.Mirror( mirrorPoint, false ); + break; + } + + case PCB_PAD_T: + { + auto& pad = static_cast( *item ); + mirrorPadX( pad, mirrorPoint ); + break; + } + + default: + // it's likely the commit object is wrong if you get here + assert( false ); + break; + } + } + + if( !m_dragging ) + m_commit->Push( _( "Mirror" ) ); + + if( unselect ) + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); + + // TODO selectionModified + m_toolMgr->RunAction( COMMON_ACTIONS::editModifiedSelection, true ); + editFrame->Refresh(); + + return 0; +} + int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent ) { @@ -671,6 +787,7 @@ void EDIT_TOOL::SetTransitions() Go( &EDIT_TOOL::Duplicate, COMMON_ACTIONS::duplicate.MakeEvent() ); Go( &EDIT_TOOL::Duplicate, COMMON_ACTIONS::duplicateIncrement.MakeEvent() ); Go( &EDIT_TOOL::CreateArray,COMMON_ACTIONS::createArray.MakeEvent() ); + Go( &EDIT_TOOL::Mirror, COMMON_ACTIONS::mirror.MakeEvent() ); Go( &EDIT_TOOL::editFootprintInFpEditor, COMMON_ACTIONS::editFootprintInFpEditor.MakeEvent() ); } diff --git a/pcbnew/tools/edit_tool.h b/pcbnew/tools/edit_tool.h index 0f9b509db8..260cdeab9b 100644 --- a/pcbnew/tools/edit_tool.h +++ b/pcbnew/tools/edit_tool.h @@ -80,6 +80,13 @@ public: */ int Flip( const TOOL_EVENT& aEvent ); + /** + * Function Mirror + * + * Mirrors the current selection. The mirror axis passes through the current point. + */ + int Mirror( const TOOL_EVENT& aEvent ); + /** * Function Remove() *