Pcbnew: add option to select origin & anchor in move exactly tool
This patch adds a radiobox to allow the user to select a reference point for the move. The additional options are: User Origin (set with <space>), Grid Origin and Sheet Origin (effectively making it an absolute coordinate). A checkbox is added (where it makes sense) to allow overriding which point within the component is put on top of the designated coordinate. Fixes: lp:1460460 * https://bugs.launchpad.net/kicad/+bug/1460460
This commit is contained in:
parent
0af5695e51
commit
e57c962336
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2014 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2004-2014 KiCad Developers, see change_log.txt for contributors.
|
||||
* Copyright (C) 2017 KiCad Developers, see CHANGELOG.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
|
||||
|
@ -109,6 +110,7 @@ public:
|
|||
const wxPoint& GetOrigin() const { return m_Pos; }
|
||||
const wxPoint& GetPosition() const { return m_Pos; }
|
||||
const wxPoint GetEnd() const { return wxPoint( m_Pos.x + m_Size.x, m_Pos.y + m_Size.y ); }
|
||||
const wxPoint GetCenter() const { return wxPoint( m_Pos.x + ( m_Size.x / 2 ), m_Pos.y + ( m_Size.y / 2 ) ); }
|
||||
|
||||
int GetWidth() const { return m_Size.x; }
|
||||
int GetHeight() const { return m_Size.y; }
|
||||
|
|
|
@ -124,6 +124,13 @@ public:
|
|||
|
||||
const BOX2I ViewBBox() const override;
|
||||
|
||||
/// Returns the top left point of the selection area bounding box.
|
||||
VECTOR2I GetPosition() const;
|
||||
|
||||
EDA_RECT GetBoundingBox() const;
|
||||
EDA_ITEM* GetTopLeftItem( bool onlyModules = false ) const;
|
||||
EDA_ITEM* GetTopLeftModule() const;
|
||||
|
||||
EDA_ITEM* operator[]( const int index ) const
|
||||
{
|
||||
if( index < 0 || (unsigned int) index >= m_items.size() )
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net>
|
||||
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2017 KiCad Developers, see CHANGELOG.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
|
||||
|
@ -188,17 +189,49 @@ bool FOOTPRINT_EDIT_FRAME::HandleBlockEnd( wxDC* DC )
|
|||
|
||||
if( itemsCount )
|
||||
{
|
||||
wxPoint translation;
|
||||
double rotation = 0;
|
||||
MOVE_PARAMETERS params;
|
||||
params.allowOverride = false;
|
||||
|
||||
DIALOG_MOVE_EXACT dialog( this, params );
|
||||
|
||||
DIALOG_MOVE_EXACT dialog( this, translation, rotation );
|
||||
int ret = dialog.ShowModal();
|
||||
|
||||
if( ret == wxID_OK )
|
||||
{
|
||||
SaveCopyInUndoList( currentModule, UR_CHANGED );
|
||||
const wxPoint blockCentre = GetScreen()->m_BlockLocate.Centre();
|
||||
MoveMarkedItemsExactly( currentModule, blockCentre, translation, rotation );
|
||||
wxPoint blockCentre = GetScreen()->m_BlockLocate.Centre();
|
||||
|
||||
wxPoint origin;
|
||||
|
||||
switch( params.origin )
|
||||
{
|
||||
case RELATIVE_TO_USER_ORIGIN:
|
||||
origin = GetScreen()->m_O_Curseur;
|
||||
break;
|
||||
|
||||
case RELATIVE_TO_GRID_ORIGIN:
|
||||
origin = GetGridOrigin();
|
||||
break;
|
||||
|
||||
case RELATIVE_TO_DRILL_PLACE_ORIGIN:
|
||||
origin = GetAuxOrigin();
|
||||
break;
|
||||
|
||||
case RELATIVE_TO_SHEET_ORIGIN:
|
||||
origin = wxPoint( 0, 0 );
|
||||
break;
|
||||
|
||||
case RELATIVE_TO_CURRENT_POSITION:
|
||||
// relative movement means that only the translation values should be used:
|
||||
// -> set origin and blockCentre to zero
|
||||
origin = wxPoint( 0, 0 );
|
||||
blockCentre = wxPoint( 0, 0 );
|
||||
break;
|
||||
}
|
||||
|
||||
wxPoint finalMoveVector = params.translation + origin - blockCentre;
|
||||
|
||||
MoveMarkedItemsExactly( currentModule, blockCentre, finalMoveVector, params.rotation );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -653,6 +653,26 @@ D_PAD* MODULE::GetPad( const wxPoint& aPosition, LSET aLayerMask )
|
|||
}
|
||||
|
||||
|
||||
D_PAD* MODULE::GetTopLeftPad()
|
||||
{
|
||||
D_PAD* topLeftPad = m_Pads;
|
||||
|
||||
for( D_PAD* p = m_Pads->Next(); p; p = p->Next() )
|
||||
{
|
||||
wxPoint pnt = p->GetPosition(); // GetPosition() returns the center of the pad
|
||||
|
||||
if( ( pnt.x < topLeftPad->GetPosition().x ) ||
|
||||
( ( topLeftPad->GetPosition().x == pnt.x ) &&
|
||||
( pnt.y < topLeftPad->GetPosition().y ) ) )
|
||||
{
|
||||
topLeftPad = p;
|
||||
}
|
||||
}
|
||||
|
||||
return topLeftPad;
|
||||
}
|
||||
|
||||
|
||||
unsigned MODULE::GetPadCount( INCLUDE_NPTH_T aIncludeNPTH ) const
|
||||
{
|
||||
if( aIncludeNPTH )
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2017 KiCad Developers, see CHANGELOG.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
|
||||
|
@ -478,6 +479,8 @@ public:
|
|||
*/
|
||||
D_PAD* GetPad( const wxPoint& aPosition, LSET aLayerMask = LSET::AllLayersMask() );
|
||||
|
||||
D_PAD* GetTopLeftPad();
|
||||
|
||||
/**
|
||||
* GetPadCount
|
||||
* returns the number of pads.
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2014 John Beard, john.j.beard@gmail.com
|
||||
* Copyright (C) 1992-2014 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2017 KiCad Developers, see CHANGELOG.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
|
||||
|
@ -34,11 +35,14 @@
|
|||
DIALOG_MOVE_EXACT::MOVE_EXACT_OPTIONS DIALOG_MOVE_EXACT::m_options;
|
||||
|
||||
|
||||
DIALOG_MOVE_EXACT::DIALOG_MOVE_EXACT( PCB_BASE_FRAME* aParent,
|
||||
wxPoint& translation, double& rotation ):
|
||||
DIALOG_MOVE_EXACT::DIALOG_MOVE_EXACT(PCB_BASE_FRAME *aParent, MOVE_PARAMETERS &aParams ) :
|
||||
DIALOG_MOVE_EXACT_BASE( aParent ),
|
||||
m_translation( translation ),
|
||||
m_rotation( rotation )
|
||||
m_translation( aParams.translation ),
|
||||
m_rotation( aParams.rotation ),
|
||||
m_origin( aParams.origin ),
|
||||
m_anchor( aParams.anchor ),
|
||||
m_allowOverride( aParams.allowOverride ),
|
||||
m_editingFootprint( aParams.editingFootprint )
|
||||
{
|
||||
// set the unit labels
|
||||
m_xUnit->SetLabelText( GetAbbreviatedUnitsLabel( g_UserUnit ) );
|
||||
|
@ -53,6 +57,69 @@ DIALOG_MOVE_EXACT::DIALOG_MOVE_EXACT( PCB_BASE_FRAME* aParent,
|
|||
m_xEntry->SetValue( wxString::FromDouble( m_options.entry1 ) );
|
||||
m_yEntry->SetValue( wxString::FromDouble( m_options.entry2 ) );
|
||||
m_rotEntry->SetValue( wxString::FromDouble( m_options.entryRotation ) );
|
||||
m_originChooser->SetSelection( m_options.origin );
|
||||
|
||||
if( m_allowOverride )
|
||||
{
|
||||
m_cbOverride->SetValue( m_options.overrideAnchor );
|
||||
m_anchorChoice->Enable( m_options.overrideAnchor );
|
||||
|
||||
// ME_ANCHOR_FROM_LIBRARY is not in the wxChoice options so show the first choice instead
|
||||
if( m_options.anchor == ANCHOR_FROM_LIBRARY )
|
||||
{
|
||||
m_anchorChoice->SetSelection( ANCHOR_TOP_LEFT_PAD );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_anchorChoice->SetSelection( m_options.anchor );
|
||||
}
|
||||
|
||||
if( m_options.origin == RELATIVE_TO_CURRENT_POSITION )
|
||||
{
|
||||
// no footprint override necessary in this mode
|
||||
m_cbOverride->Disable();
|
||||
m_anchorChoice->Disable();
|
||||
}
|
||||
|
||||
if( m_editingFootprint )
|
||||
{
|
||||
// there is no point in showing the center footprint option when editing footprints
|
||||
m_anchorChoice->Delete( ANCHOR_CENTER_FOOTPRINT );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// hide the checkbox and choice control if overides are not allowed
|
||||
bMainSizer->Hide( bAnchorSizer, true );
|
||||
}
|
||||
|
||||
if( wxPoint( 0, 0 ) == aParent->GetScreen()->m_O_Curseur )
|
||||
{
|
||||
// disble the user origin option when the user oigin is not set
|
||||
m_originChooser->Enable( RELATIVE_TO_USER_ORIGIN, false );
|
||||
m_originChooser->SetItemToolTip( RELATIVE_TO_USER_ORIGIN,
|
||||
wxString( "The user origin is currently not set\n"
|
||||
"Set it by using the <space> hotkey" ) );
|
||||
}
|
||||
|
||||
if( wxPoint( 0, 0 ) == aParent->GetGridOrigin() )
|
||||
{
|
||||
// disble the grid origin option when the user oigin is not set
|
||||
m_originChooser->Enable( RELATIVE_TO_GRID_ORIGIN, false );
|
||||
m_originChooser->SetItemToolTip( RELATIVE_TO_GRID_ORIGIN,
|
||||
wxString( "The grid origin is currently not set\n"
|
||||
"Set it by using the tool in the <place> menu" ) );
|
||||
}
|
||||
|
||||
if( wxPoint( 0, 0 ) == aParent->GetAuxOrigin() )
|
||||
{
|
||||
// disble the grid origin option when the drill/place oigin is not set
|
||||
m_originChooser->Enable( RELATIVE_TO_DRILL_PLACE_ORIGIN, false );
|
||||
m_originChooser->SetItemToolTip( RELATIVE_TO_DRILL_PLACE_ORIGIN,
|
||||
wxString( "The drill/place origin is currently not set\n"
|
||||
"Set it by using the tool in the <place> menu" ) );
|
||||
}
|
||||
|
||||
updateDlgTexts( m_polarCoords->IsChecked() );
|
||||
|
||||
m_stdButtonsOK->SetDefault();
|
||||
|
@ -129,6 +196,37 @@ void DIALOG_MOVE_EXACT::OnPolarChanged( wxCommandEvent& event )
|
|||
}
|
||||
|
||||
|
||||
void DIALOG_MOVE_EXACT::OnOriginChanged( wxCommandEvent& event )
|
||||
{
|
||||
if( m_originChooser->GetSelection() == RELATIVE_TO_CURRENT_POSITION )
|
||||
{
|
||||
//no need to override the achor in this mode since the reference in the current position
|
||||
m_cbOverride->Disable();
|
||||
m_anchorChoice->Disable();
|
||||
}
|
||||
else if( m_allowOverride )
|
||||
{
|
||||
m_cbOverride->Enable();
|
||||
|
||||
if( m_cbOverride->IsChecked() )
|
||||
m_anchorChoice->Enable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_MOVE_EXACT::OnOverrideChanged( wxCommandEvent& event )
|
||||
{
|
||||
if( m_cbOverride->IsChecked() )
|
||||
{
|
||||
m_anchorChoice->Enable();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_anchorChoice->Disable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_MOVE_EXACT::updateDlgTexts( bool aPolar )
|
||||
{
|
||||
if( aPolar )
|
||||
|
@ -174,6 +272,16 @@ void DIALOG_MOVE_EXACT::OnClear( wxCommandEvent& event )
|
|||
void DIALOG_MOVE_EXACT::OnOkClick( wxCommandEvent& event )
|
||||
{
|
||||
m_rotation = DoubleValueFromString( DEGREES, m_rotEntry->GetValue() );
|
||||
m_origin = static_cast<MOVE_EXACT_ORIGIN>( m_originChooser->GetSelection() );
|
||||
|
||||
if( m_cbOverride->IsChecked() && m_allowOverride )
|
||||
{
|
||||
m_anchor = static_cast<MOVE_EXACT_ANCHOR>( m_anchorChoice->GetSelection() );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_anchor = ANCHOR_FROM_LIBRARY;
|
||||
}
|
||||
|
||||
// for the output, we only deliver a Cartesian vector
|
||||
bool ok = GetTranslationInIU( m_translation, m_polarCoords->IsChecked() );
|
||||
|
@ -185,7 +293,9 @@ void DIALOG_MOVE_EXACT::OnOkClick( wxCommandEvent& event )
|
|||
m_options.entry1 = DoubleValueFromString( UNSCALED_UNITS, m_xEntry->GetValue() );
|
||||
m_options.entry2 = DoubleValueFromString( UNSCALED_UNITS, m_yEntry->GetValue() );
|
||||
m_options.entryRotation = DoubleValueFromString( UNSCALED_UNITS, m_rotEntry->GetValue() );
|
||||
|
||||
m_options.origin = m_origin;
|
||||
m_options.anchor = static_cast<MOVE_EXACT_ANCHOR>( m_anchorChoice->GetSelection() );
|
||||
m_options.overrideAnchor = m_cbOverride->IsChecked();
|
||||
event.Skip();
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2014 John Beard, john.j.beard@gmail.com
|
||||
* Copyright (C) 1992-2014 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2017 KiCad Developers, see CHANGELOG.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
|
||||
|
@ -29,17 +30,49 @@
|
|||
#include <vector>
|
||||
#include <dialog_move_exact_base.h>
|
||||
|
||||
enum MOVE_EXACT_ORIGIN
|
||||
{
|
||||
RELATIVE_TO_CURRENT_POSITION,
|
||||
RELATIVE_TO_USER_ORIGIN,
|
||||
RELATIVE_TO_GRID_ORIGIN,
|
||||
RELATIVE_TO_DRILL_PLACE_ORIGIN,
|
||||
RELATIVE_TO_SHEET_ORIGIN
|
||||
};
|
||||
|
||||
|
||||
enum MOVE_EXACT_ANCHOR
|
||||
{
|
||||
ANCHOR_TOP_LEFT_PAD,
|
||||
ANCHOR_CENTER_FOOTPRINT,
|
||||
ANCHOR_FROM_LIBRARY
|
||||
};
|
||||
|
||||
|
||||
struct MOVE_PARAMETERS
|
||||
{
|
||||
wxPoint translation = wxPoint( 0,0 );
|
||||
double rotation = 0;
|
||||
MOVE_EXACT_ORIGIN origin = RELATIVE_TO_CURRENT_POSITION;
|
||||
MOVE_EXACT_ANCHOR anchor = ANCHOR_FROM_LIBRARY;
|
||||
bool allowOverride = true;
|
||||
bool editingFootprint = false;
|
||||
};
|
||||
|
||||
|
||||
class DIALOG_MOVE_EXACT : public DIALOG_MOVE_EXACT_BASE
|
||||
{
|
||||
private:
|
||||
|
||||
wxPoint& m_translation;
|
||||
double& m_rotation;
|
||||
wxPoint& m_translation;
|
||||
double& m_rotation;
|
||||
MOVE_EXACT_ORIGIN& m_origin;
|
||||
MOVE_EXACT_ANCHOR& m_anchor;
|
||||
bool& m_allowOverride;
|
||||
bool& m_editingFootprint;
|
||||
|
||||
public:
|
||||
// Constructor and destructor
|
||||
DIALOG_MOVE_EXACT( PCB_BASE_FRAME* aParent, wxPoint& translation,
|
||||
double& rotation );
|
||||
DIALOG_MOVE_EXACT(PCB_BASE_FRAME *aParent, MOVE_PARAMETERS &aParams );
|
||||
~DIALOG_MOVE_EXACT();
|
||||
|
||||
private:
|
||||
|
@ -52,6 +85,9 @@ private:
|
|||
void OnPolarChanged( wxCommandEvent& event ) override;
|
||||
void OnClear( wxCommandEvent& event ) override;
|
||||
|
||||
void OnOriginChanged( wxCommandEvent& event ) override;
|
||||
void OnOverrideChanged( wxCommandEvent& event ) override;
|
||||
|
||||
void OnOkClick( wxCommandEvent& event ) override;
|
||||
|
||||
/**
|
||||
|
@ -78,16 +114,22 @@ private:
|
|||
*/
|
||||
struct MOVE_EXACT_OPTIONS
|
||||
{
|
||||
bool polarCoords;
|
||||
double entry1;
|
||||
double entry2;
|
||||
double entryRotation;
|
||||
bool polarCoords;
|
||||
double entry1;
|
||||
double entry2;
|
||||
double entryRotation;
|
||||
MOVE_EXACT_ORIGIN origin;
|
||||
MOVE_EXACT_ANCHOR anchor;
|
||||
bool overrideAnchor;
|
||||
|
||||
MOVE_EXACT_OPTIONS():
|
||||
polarCoords(false),
|
||||
entry1(0),
|
||||
entry2(0),
|
||||
entryRotation(0)
|
||||
polarCoords( false ),
|
||||
entry1( 0 ),
|
||||
entry2( 0 ),
|
||||
entryRotation( 0 ),
|
||||
origin( RELATIVE_TO_CURRENT_POSITION ),
|
||||
anchor( ANCHOR_FROM_LIBRARY ),
|
||||
overrideAnchor( false )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -97,3 +139,4 @@ private:
|
|||
};
|
||||
|
||||
#endif // __DIALOG_MOVE_EXACT__
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Jun 17 2015)
|
||||
// C++ code generated with wxFormBuilder (version Jan 13 2017)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO "NOT" EDIT THIS FILE!
|
||||
|
@ -13,62 +13,87 @@ DIALOG_MOVE_EXACT_BASE::DIALOG_MOVE_EXACT_BASE( wxWindow* parent, wxWindowID id,
|
|||
{
|
||||
this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize );
|
||||
|
||||
wxBoxSizer* bMainSizer;
|
||||
bMainSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_polarCoords = new wxCheckBox( this, wxID_ANY, _("Use polar coordinates"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bMainSizer->Add( m_polarCoords, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
wxFlexGridSizer* fgSizer2;
|
||||
fgSizer2 = new wxFlexGridSizer( 0, 4, 0, 0 );
|
||||
fgSizer2->AddGrowableCol( 1 );
|
||||
fgSizer2->SetFlexibleDirection( wxBOTH );
|
||||
fgSizer2->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
wxBoxSizer* bMiddleSizer;
|
||||
bMiddleSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
wxFlexGridSizer* fgInputSizer;
|
||||
fgInputSizer = new wxFlexGridSizer( 0, 4, 0, 0 );
|
||||
fgInputSizer->AddGrowableCol( 1 );
|
||||
fgInputSizer->SetFlexibleDirection( wxBOTH );
|
||||
fgInputSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_xLabel = new wxStaticText( this, wxID_ANY, _("x:"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
|
||||
m_xLabel->Wrap( -1 );
|
||||
fgSizer2->Add( m_xLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5 );
|
||||
fgInputSizer->Add( m_xLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5 );
|
||||
|
||||
m_xEntry = new wxTextCtrl( this, wxID_ANY, _("0"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer2->Add( m_xEntry, 0, wxALL|wxEXPAND, 5 );
|
||||
fgInputSizer->Add( m_xEntry, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_xUnit = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_xUnit->Wrap( -1 );
|
||||
fgSizer2->Add( m_xUnit, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT|wxALL, 5 );
|
||||
fgInputSizer->Add( m_xUnit, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT|wxALL, 5 );
|
||||
|
||||
m_clearX = new wxButton( this, wxID_ANY, _("Reset"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT );
|
||||
fgSizer2->Add( m_clearX, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
fgInputSizer->Add( m_clearX, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_yLabel = new wxStaticText( this, wxID_ANY, _("y:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_yLabel->Wrap( -1 );
|
||||
fgSizer2->Add( m_yLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5 );
|
||||
fgInputSizer->Add( m_yLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5 );
|
||||
|
||||
m_yEntry = new wxTextCtrl( this, wxID_ANY, _("0"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer2->Add( m_yEntry, 0, wxALL|wxEXPAND, 5 );
|
||||
fgInputSizer->Add( m_yEntry, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_yUnit = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_yUnit->Wrap( -1 );
|
||||
fgSizer2->Add( m_yUnit, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
fgInputSizer->Add( m_yUnit, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_clearY = new wxButton( this, wxID_ANY, _("Reset"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT );
|
||||
fgSizer2->Add( m_clearY, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
fgInputSizer->Add( m_clearY, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_rotLabel = new wxStaticText( this, wxID_ANY, _("Item rotation:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_rotLabel->Wrap( -1 );
|
||||
fgSizer2->Add( m_rotLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5 );
|
||||
fgInputSizer->Add( m_rotLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5 );
|
||||
|
||||
m_rotEntry = new wxTextCtrl( this, wxID_ANY, _("0"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer2->Add( m_rotEntry, 0, wxALL|wxEXPAND, 5 );
|
||||
fgInputSizer->Add( m_rotEntry, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_rotUnit = new wxStaticText( this, wxID_ANY, _("deg"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_rotUnit->Wrap( -1 );
|
||||
fgSizer2->Add( m_rotUnit, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
fgInputSizer->Add( m_rotUnit, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_clearRot = new wxButton( this, wxID_ANY, _("Reset"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT );
|
||||
fgSizer2->Add( m_clearRot, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
fgInputSizer->Add( m_clearRot, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
bMainSizer->Add( fgSizer2, 1, wxEXPAND|wxTOP|wxBOTTOM, 5 );
|
||||
bMiddleSizer->Add( fgInputSizer, 1, wxALL|wxBOTTOM|wxEXPAND|wxTOP, 5 );
|
||||
|
||||
wxString m_originChooserChoices[] = { _("Current Position"), _("User Origin"), _("Grid Origin"), _("Drill/Place Origin"), _("Sheet Origin") };
|
||||
int m_originChooserNChoices = sizeof( m_originChooserChoices ) / sizeof( wxString );
|
||||
m_originChooser = new wxRadioBox( this, wxID_ANY, _("Move relative to:"), wxDefaultPosition, wxDefaultSize, m_originChooserNChoices, m_originChooserChoices, 1, wxRA_SPECIFY_COLS );
|
||||
m_originChooser->SetSelection( 0 );
|
||||
bMiddleSizer->Add( m_originChooser, 0, wxALL, 5 );
|
||||
|
||||
|
||||
bMainSizer->Add( bMiddleSizer, 1, wxEXPAND, 5 );
|
||||
|
||||
bAnchorSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_cbOverride = new wxCheckBox( this, wxID_ANY, _("Override default component anchor with:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bAnchorSizer->Add( m_cbOverride, 1, wxALL, 5 );
|
||||
|
||||
wxString m_anchorChoiceChoices[] = { _("top left pad"), _("footprint center") };
|
||||
int m_anchorChoiceNChoices = sizeof( m_anchorChoiceChoices ) / sizeof( wxString );
|
||||
m_anchorChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_anchorChoiceNChoices, m_anchorChoiceChoices, 0 );
|
||||
m_anchorChoice->SetSelection( 0 );
|
||||
bAnchorSizer->Add( m_anchorChoice, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
|
||||
|
||||
|
||||
bMainSizer->Add( bAnchorSizer, 0, wxEXPAND, 5 );
|
||||
|
||||
m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
bMainSizer->Add( m_staticline1, 0, wxEXPAND | wxALL, 5 );
|
||||
|
@ -85,7 +110,6 @@ DIALOG_MOVE_EXACT_BASE::DIALOG_MOVE_EXACT_BASE( wxWindow* parent, wxWindowID id,
|
|||
|
||||
this->SetSizer( bMainSizer );
|
||||
this->Layout();
|
||||
bMainSizer->Fit( this );
|
||||
|
||||
// Connect Events
|
||||
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_MOVE_EXACT_BASE::OnClose ) );
|
||||
|
@ -96,6 +120,8 @@ DIALOG_MOVE_EXACT_BASE::DIALOG_MOVE_EXACT_BASE( wxWindow* parent, wxWindowID id,
|
|||
m_clearY->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MOVE_EXACT_BASE::OnClear ), NULL, this );
|
||||
m_rotEntry->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_MOVE_EXACT_BASE::OnTextFocusLost ), NULL, this );
|
||||
m_clearRot->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MOVE_EXACT_BASE::OnClear ), NULL, this );
|
||||
m_originChooser->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_MOVE_EXACT_BASE::OnOriginChanged ), NULL, this );
|
||||
m_cbOverride->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_MOVE_EXACT_BASE::OnOverrideChanged ), NULL, this );
|
||||
m_stdButtonsOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MOVE_EXACT_BASE::OnOkClick ), NULL, this );
|
||||
}
|
||||
|
||||
|
@ -110,6 +136,8 @@ DIALOG_MOVE_EXACT_BASE::~DIALOG_MOVE_EXACT_BASE()
|
|||
m_clearY->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MOVE_EXACT_BASE::OnClear ), NULL, this );
|
||||
m_rotEntry->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_MOVE_EXACT_BASE::OnTextFocusLost ), NULL, this );
|
||||
m_clearRot->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MOVE_EXACT_BASE::OnClear ), NULL, this );
|
||||
m_originChooser->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_MOVE_EXACT_BASE::OnOriginChanged ), NULL, this );
|
||||
m_cbOverride->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_MOVE_EXACT_BASE::OnOverrideChanged ), NULL, this );
|
||||
m_stdButtonsOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MOVE_EXACT_BASE::OnOkClick ), NULL, this );
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Jun 17 2015)
|
||||
// C++ code generated with wxFormBuilder (version Jan 13 2017)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO "NOT" EDIT THIS FILE!
|
||||
|
@ -24,6 +24,8 @@ class DIALOG_SHIM;
|
|||
#include <wx/textctrl.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/radiobox.h>
|
||||
#include <wx/choice.h>
|
||||
#include <wx/statline.h>
|
||||
#include <wx/dialog.h>
|
||||
|
||||
|
@ -38,6 +40,7 @@ class DIALOG_MOVE_EXACT_BASE : public DIALOG_SHIM
|
|||
private:
|
||||
|
||||
protected:
|
||||
wxBoxSizer* bMainSizer;
|
||||
wxCheckBox* m_polarCoords;
|
||||
wxStaticText* m_xLabel;
|
||||
wxTextCtrl* m_xEntry;
|
||||
|
@ -51,6 +54,10 @@ class DIALOG_MOVE_EXACT_BASE : public DIALOG_SHIM
|
|||
wxTextCtrl* m_rotEntry;
|
||||
wxStaticText* m_rotUnit;
|
||||
wxButton* m_clearRot;
|
||||
wxRadioBox* m_originChooser;
|
||||
wxBoxSizer* bAnchorSizer;
|
||||
wxCheckBox* m_cbOverride;
|
||||
wxChoice* m_anchorChoice;
|
||||
wxStaticLine* m_staticline1;
|
||||
wxStdDialogButtonSizer* m_stdButtons;
|
||||
wxButton* m_stdButtonsOK;
|
||||
|
@ -61,12 +68,14 @@ class DIALOG_MOVE_EXACT_BASE : public DIALOG_SHIM
|
|||
virtual void OnPolarChanged( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnTextFocusLost( wxFocusEvent& event ) { event.Skip(); }
|
||||
virtual void OnClear( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnOriginChanged( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnOverrideChanged( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnOkClick( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
DIALOG_MOVE_EXACT_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Move Item"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
|
||||
DIALOG_MOVE_EXACT_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Move Item"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 509,277 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
|
||||
~DIALOG_MOVE_EXACT_BASE();
|
||||
|
||||
};
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* Copyright (C) 2015 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2015 Wayne Stambaugh <stambaughw@verizon.net>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2017 KiCad Developers, see CHANGELOG.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
|
||||
|
@ -1536,10 +1537,9 @@ void PCB_EDIT_FRAME::OnSelectTool( wxCommandEvent& aEvent )
|
|||
|
||||
void PCB_EDIT_FRAME::moveExact()
|
||||
{
|
||||
wxPoint translation;
|
||||
double rotation = 0;
|
||||
MOVE_PARAMETERS params;
|
||||
|
||||
DIALOG_MOVE_EXACT dialog( this, translation, rotation );
|
||||
DIALOG_MOVE_EXACT dialog( this, params );
|
||||
int ret = dialog.ShowModal();
|
||||
|
||||
if( ret == wxID_OK )
|
||||
|
@ -1555,8 +1555,66 @@ void PCB_EDIT_FRAME::moveExact()
|
|||
// Could be moved or rotated
|
||||
SaveCopyInUndoList( itemToSave, UR_CHANGED );
|
||||
|
||||
item->Move( translation );
|
||||
item->Rotate( item->GetPosition(), rotation );
|
||||
// begin with the default anchor
|
||||
wxPoint anchorPoint = item->GetPosition();
|
||||
|
||||
if( item->Type() == PCB_MODULE_T )
|
||||
{
|
||||
// cast to module to allow access to the pads
|
||||
MODULE* mod = static_cast<MODULE*>( item );
|
||||
|
||||
switch( params.anchor )
|
||||
{
|
||||
case ANCHOR_TOP_LEFT_PAD:
|
||||
if( mod->GetTopLeftPad()->GetAttribute() == PAD_ATTRIB_SMD )
|
||||
{
|
||||
anchorPoint = mod->GetTopLeftPad()->GetBoundingBox().GetPosition();
|
||||
}
|
||||
else
|
||||
{
|
||||
anchorPoint = mod->GetTopLeftPad()->GetPosition();
|
||||
}
|
||||
break;
|
||||
case ANCHOR_CENTER_FOOTPRINT:
|
||||
anchorPoint = mod->GetFootprintRect().GetCenter();
|
||||
break;
|
||||
case ANCHOR_FROM_LIBRARY:
|
||||
; // nothing to do
|
||||
}
|
||||
}
|
||||
|
||||
wxPoint origin;
|
||||
|
||||
switch( params.origin )
|
||||
{
|
||||
case RELATIVE_TO_USER_ORIGIN:
|
||||
origin = GetScreen()->m_O_Curseur;
|
||||
break;
|
||||
|
||||
case RELATIVE_TO_GRID_ORIGIN:
|
||||
origin = GetGridOrigin();
|
||||
break;
|
||||
|
||||
case RELATIVE_TO_DRILL_PLACE_ORIGIN:
|
||||
origin = GetAuxOrigin();
|
||||
break;
|
||||
|
||||
case RELATIVE_TO_SHEET_ORIGIN:
|
||||
origin = wxPoint( 0, 0 );
|
||||
break;
|
||||
|
||||
case RELATIVE_TO_CURRENT_POSITION:
|
||||
// relative movement means that only the translation values should be used:
|
||||
// -> set origin and anchor to zero
|
||||
origin = wxPoint( 0, 0 );
|
||||
anchorPoint = wxPoint( 0, 0 );
|
||||
break;
|
||||
}
|
||||
|
||||
wxPoint finalMoveVector = params.translation + origin - anchorPoint;
|
||||
|
||||
item->Move( finalMoveVector );
|
||||
item->Rotate( item->GetPosition(), params.rotation );
|
||||
m_canvas->Refresh();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2017 KiCad Developers, see CHANGELOG.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
|
||||
|
@ -837,10 +838,11 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
|
|||
|
||||
void FOOTPRINT_EDIT_FRAME::moveExact()
|
||||
{
|
||||
wxPoint translation;
|
||||
double rotation = 0;
|
||||
MOVE_PARAMETERS params;
|
||||
params.allowOverride = false;
|
||||
params.editingFootprint = true;
|
||||
|
||||
DIALOG_MOVE_EXACT dialog( this, translation, rotation );
|
||||
DIALOG_MOVE_EXACT dialog( this, params );
|
||||
int ret = dialog.ShowModal();
|
||||
|
||||
if( ret == wxID_OK )
|
||||
|
@ -849,8 +851,39 @@ void FOOTPRINT_EDIT_FRAME::moveExact()
|
|||
|
||||
BOARD_ITEM* item = GetScreen()->GetCurItem();
|
||||
|
||||
item->Move( translation );
|
||||
item->Rotate( item->GetPosition(), rotation );
|
||||
wxPoint anchorPoint = item->GetPosition();
|
||||
wxPoint origin;
|
||||
|
||||
switch( params.origin )
|
||||
{
|
||||
case RELATIVE_TO_USER_ORIGIN:
|
||||
origin = GetScreen()->m_O_Curseur;
|
||||
break;
|
||||
|
||||
case RELATIVE_TO_GRID_ORIGIN:
|
||||
origin = GetGridOrigin();
|
||||
break;
|
||||
|
||||
case RELATIVE_TO_DRILL_PLACE_ORIGIN:
|
||||
origin = GetAuxOrigin();
|
||||
break;
|
||||
|
||||
case RELATIVE_TO_SHEET_ORIGIN:
|
||||
origin = wxPoint( 0, 0 );
|
||||
break;
|
||||
|
||||
case RELATIVE_TO_CURRENT_POSITION:
|
||||
// relative movement means that only the translation values should be used:
|
||||
// -> set origin and anchor to zero
|
||||
origin = wxPoint( 0, 0 );
|
||||
anchorPoint = wxPoint( 0, 0 );
|
||||
break;
|
||||
}
|
||||
|
||||
wxPoint finalMoveVector = params.translation + origin - anchorPoint;
|
||||
|
||||
item->Move( finalMoveVector );
|
||||
item->Rotate( item->GetPosition(), params.rotation );
|
||||
m_canvas->Refresh();
|
||||
}
|
||||
|
||||
|
@ -880,16 +913,15 @@ void FOOTPRINT_EDIT_FRAME::Transform( MODULE* module, int transform )
|
|||
|
||||
case ID_MODEDIT_MODULE_MOVE_EXACT:
|
||||
{
|
||||
wxPoint translation;
|
||||
double rotation = 0;
|
||||
MOVE_PARAMETERS params;
|
||||
|
||||
DIALOG_MOVE_EXACT dialog( this, translation, rotation );
|
||||
DIALOG_MOVE_EXACT dialog( this, params );
|
||||
int ret = dialog.ShowModal();
|
||||
|
||||
if( ret == wxID_OK )
|
||||
{
|
||||
MoveMarkedItemsExactly( module, wxPoint(0, 0),
|
||||
translation, rotation, true );
|
||||
MoveMarkedItemsExactly( module, wxPoint( 0, 0 ),
|
||||
params.translation, params.rotation, true );
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* Copyright (C) 2013-2015 CERN
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
* Copyright (C) 2017 KiCad Developers, see CHANGELOG.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
|
||||
|
@ -221,6 +222,8 @@ bool EDIT_TOOL::Init()
|
|||
|
||||
|
||||
bool EDIT_TOOL::invokeInlineRouter()
|
||||
|
||||
|
||||
{
|
||||
TRACK* track = uniqueSelected<TRACK>();
|
||||
VIA* via = uniqueSelected<VIA>();
|
||||
|
@ -707,13 +710,12 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent )
|
|||
if( selection.Empty() )
|
||||
return 0;
|
||||
|
||||
|
||||
wxPoint translation;
|
||||
double rotation = 0;
|
||||
|
||||
PCB_BASE_FRAME* editFrame = getEditFrame<PCB_BASE_FRAME>();
|
||||
|
||||
DIALOG_MOVE_EXACT dialog( editFrame, translation, rotation );
|
||||
MOVE_PARAMETERS params;
|
||||
params.editingFootprint = m_editModules;
|
||||
|
||||
DIALOG_MOVE_EXACT dialog( editFrame, params );
|
||||
int ret = dialog.ShowModal();
|
||||
|
||||
if( ret == wxID_OK )
|
||||
|
@ -721,11 +723,97 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent )
|
|||
VECTOR2I rp = selection.GetCenter();
|
||||
wxPoint rotPoint( rp.x, rp.y );
|
||||
|
||||
// Begin at the center of the selection determined above
|
||||
wxPoint anchorPoint = rotPoint;
|
||||
|
||||
// If the anchor is not ANCHOR_FROM_LIBRARY then the user applied an override.
|
||||
// Also run through this block if only one item is slected because it may be a module,
|
||||
// in which case we want something different than the center of the selection
|
||||
if( ( params.anchor != ANCHOR_FROM_LIBRARY ) || ( selection.GetSize() == 1 ) )
|
||||
{
|
||||
BOARD_ITEM* topLeftItem = static_cast<BOARD_ITEM*>( selection.GetTopLeftModule() );
|
||||
|
||||
// no module found if the GetTopLeftModule() returns null, retry for
|
||||
if( topLeftItem == nullptr )
|
||||
{
|
||||
topLeftItem = static_cast<BOARD_ITEM*>( selection.GetTopLeftItem() );
|
||||
anchorPoint = topLeftItem->GetPosition();
|
||||
}
|
||||
|
||||
if( topLeftItem->Type() == PCB_MODULE_T )
|
||||
{
|
||||
// Cast to module to allow access to the pads
|
||||
MODULE* mod = static_cast<MODULE*>( topLeftItem );
|
||||
|
||||
switch( params.anchor )
|
||||
{
|
||||
case ANCHOR_FROM_LIBRARY:
|
||||
anchorPoint = mod->GetPosition();
|
||||
break;
|
||||
case ANCHOR_TOP_LEFT_PAD:
|
||||
topLeftItem = mod->GetTopLeftPad();
|
||||
break;
|
||||
case ANCHOR_CENTER_FOOTPRINT:
|
||||
anchorPoint = mod->GetFootprintRect().GetCenter();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( topLeftItem->Type() == PCB_PAD_T )
|
||||
{
|
||||
if( static_cast<D_PAD*>( topLeftItem )->GetAttribute() == PAD_ATTRIB_SMD )
|
||||
{
|
||||
// Use the top left corner of SMD pads as an anchor instead of the center
|
||||
anchorPoint = topLeftItem->GetBoundingBox().GetPosition();
|
||||
}
|
||||
else
|
||||
{
|
||||
anchorPoint = topLeftItem->GetPosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wxPoint origin;
|
||||
|
||||
switch( params.origin )
|
||||
{
|
||||
case RELATIVE_TO_USER_ORIGIN:
|
||||
origin = editFrame->GetScreen()->m_O_Curseur;
|
||||
break;
|
||||
|
||||
case RELATIVE_TO_GRID_ORIGIN:
|
||||
origin = editFrame->GetGridOrigin();
|
||||
break;
|
||||
|
||||
case RELATIVE_TO_DRILL_PLACE_ORIGIN:
|
||||
origin = editFrame->GetAuxOrigin();
|
||||
break;
|
||||
|
||||
case RELATIVE_TO_SHEET_ORIGIN:
|
||||
origin = wxPoint( 0, 0 );
|
||||
break;
|
||||
|
||||
case RELATIVE_TO_CURRENT_POSITION:
|
||||
// relative movement means that only the translation values should be used:
|
||||
// -> set origin and anchor to zero
|
||||
origin = wxPoint( 0, 0 );
|
||||
anchorPoint = wxPoint( 0, 0 );
|
||||
break;
|
||||
}
|
||||
|
||||
wxPoint finalMoveVector = params.translation + origin - anchorPoint;
|
||||
|
||||
// Make sure the rotation is from the right reference point
|
||||
rotPoint += finalMoveVector;
|
||||
|
||||
for( auto item : selection )
|
||||
{
|
||||
m_commit->Modify( item );
|
||||
static_cast<BOARD_ITEM*>( item )->Move( translation );
|
||||
static_cast<BOARD_ITEM*>( item )->Rotate( rotPoint, rotation );
|
||||
static_cast<BOARD_ITEM*>( item )->Move( finalMoveVector );
|
||||
static_cast<BOARD_ITEM*>( item )->Rotate( rotPoint, params.rotation );
|
||||
|
||||
if( !m_dragging )
|
||||
getView()->Update( item );
|
||||
}
|
||||
|
||||
m_commit->Push( _( "Move exact" ) );
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* Copyright (C) 2013-2017 CERN
|
||||
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
* Copyright (C) 2017 KiCad Developers, see CHANGELOG.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
|
||||
|
@ -1820,29 +1821,74 @@ bool SELECTION_TOOL::SanitizeSelection()
|
|||
|
||||
|
||||
// TODO(JE) Only works for BOARD_ITEM
|
||||
VECTOR2I SELECTION::GetPosition() const
|
||||
{
|
||||
return static_cast<VECTOR2I>( GetBoundingBox().GetPosition() );
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I SELECTION::GetCenter() const
|
||||
{
|
||||
VECTOR2I centre;
|
||||
return static_cast<VECTOR2I>( GetBoundingBox().Centre() );
|
||||
}
|
||||
|
||||
if( Size() == 1 )
|
||||
|
||||
EDA_RECT SELECTION::GetBoundingBox() const
|
||||
{
|
||||
EDA_RECT bbox;
|
||||
|
||||
bbox = Front()->GetBoundingBox();
|
||||
auto i = m_items.begin();
|
||||
++i;
|
||||
|
||||
for( ; i != m_items.end(); ++i )
|
||||
{
|
||||
centre = static_cast<BOARD_ITEM*>( Front() )->GetCenter();
|
||||
bbox.Merge( (*i)->GetBoundingBox() );
|
||||
}
|
||||
else
|
||||
{
|
||||
EDA_RECT bbox = Front()->GetBoundingBox();
|
||||
auto i = m_items.begin();
|
||||
++i;
|
||||
|
||||
for( ; i != m_items.end(); ++i )
|
||||
return bbox;
|
||||
}
|
||||
|
||||
|
||||
EDA_ITEM* SELECTION::GetTopLeftItem( bool onlyModules ) const
|
||||
{
|
||||
BOARD_ITEM* topLeftItem = nullptr;
|
||||
BOARD_ITEM* currentItem;
|
||||
|
||||
wxPoint pnt;
|
||||
|
||||
// find the leftmost (smallest x coord) and highest (smallest y with the smallest x) item in the selection
|
||||
for( auto item : m_items )
|
||||
{
|
||||
currentItem = static_cast<BOARD_ITEM*>( item );
|
||||
pnt = currentItem->GetPosition();
|
||||
|
||||
if( ( currentItem->Type() != PCB_MODULE_T ) && onlyModules )
|
||||
{
|
||||
bbox.Merge( (*i)->GetBoundingBox() );
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( topLeftItem == nullptr )
|
||||
{
|
||||
topLeftItem = currentItem;
|
||||
}
|
||||
else if( ( pnt.x < topLeftItem->GetPosition().x ) ||
|
||||
( ( topLeftItem->GetPosition().x == pnt.x ) &&
|
||||
( pnt.y < topLeftItem->GetPosition().y ) ) )
|
||||
{
|
||||
topLeftItem = currentItem;
|
||||
}
|
||||
}
|
||||
|
||||
centre = bbox.Centre();
|
||||
}
|
||||
|
||||
return centre;
|
||||
return static_cast<EDA_ITEM*>( topLeftItem );
|
||||
}
|
||||
|
||||
|
||||
EDA_ITEM* SELECTION::GetTopLeftModule() const
|
||||
{
|
||||
return GetTopLeftItem( true );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* Copyright (C) 2013-2017 CERN
|
||||
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
* Copyright (C) 2017 KiCad Developers, see CHANGELOG.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
|
||||
|
|
Loading…
Reference in New Issue