pcbnew: Enforce maximum movement in Move Exact
This checks the movement against a maximum value that would place the selection outside of the valid area for the footprint or board. Fixes: lp:1833478 * https://bugs.launchpad.net/kicad/+bug/1833478
This commit is contained in:
parent
f0ac61a8fd
commit
845833e8fd
|
@ -191,7 +191,7 @@ bool FOOTPRINT_EDIT_FRAME::HandleBlockEnd( wxDC* DC )
|
|||
double rotation;
|
||||
ROTATION_ANCHOR rotationAnchor = ROTATE_AROUND_SEL_CENTER;
|
||||
|
||||
DIALOG_MOVE_EXACT dialog( this, translation, rotation, rotationAnchor );
|
||||
DIALOG_MOVE_EXACT dialog( this, translation, rotation, rotationAnchor, GetScreen()->m_BlockLocate );
|
||||
|
||||
if( dialog.ShowModal() == wxID_OK )
|
||||
{
|
||||
|
|
|
@ -33,11 +33,13 @@ DIALOG_MOVE_EXACT::MOVE_EXACT_OPTIONS DIALOG_MOVE_EXACT::m_options;
|
|||
|
||||
|
||||
DIALOG_MOVE_EXACT::DIALOG_MOVE_EXACT( PCB_BASE_FRAME *aParent, wxPoint& aTranslate,
|
||||
double& aRotate, ROTATION_ANCHOR& aAnchor ) :
|
||||
double& aRotate, ROTATION_ANCHOR& aAnchor,
|
||||
const EDA_RECT& aBbox ) :
|
||||
DIALOG_MOVE_EXACT_BASE( aParent ),
|
||||
m_translation( aTranslate ),
|
||||
m_rotation( aRotate ),
|
||||
m_rotationAnchor( aAnchor ),
|
||||
m_bbox( aBbox ),
|
||||
m_moveX( aParent, m_xLabel, m_xEntry, m_xUnit ),
|
||||
m_moveY( aParent, m_yLabel, m_yEntry, m_yUnit ),
|
||||
m_rotate( aParent, m_rotLabel, m_rotEntry, m_rotUnit )
|
||||
|
@ -238,3 +240,37 @@ void DIALOG_MOVE_EXACT::OnTextFocusLost( wxFocusEvent& event )
|
|||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_MOVE_EXACT::OnTextChanged( wxCommandEvent& event )
|
||||
{
|
||||
|
||||
int delta_x = m_moveX.GetValue();
|
||||
int delta_y = m_moveY.GetValue();
|
||||
int max_border = std::numeric_limits<int>::max() * 0.7071;
|
||||
|
||||
if( m_bbox.GetLeft() + delta_x < -max_border ||
|
||||
m_bbox.GetRight() + delta_x > max_border ||
|
||||
m_bbox.GetTop() + delta_y < -max_border ||
|
||||
m_bbox.GetBottom() + delta_y > max_border )
|
||||
{
|
||||
const wxString invalid_length = _( "Invalid movement values. Movement would place selection "
|
||||
"outside of the maximum board area." );
|
||||
|
||||
m_xEntry->SetToolTip( invalid_length );
|
||||
m_xEntry->SetForegroundColour( *wxRED );
|
||||
m_yEntry->SetToolTip( invalid_length );
|
||||
m_yEntry->SetForegroundColour( *wxRED );
|
||||
m_stdButtons->GetAffirmativeButton()->Disable();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_xEntry->SetToolTip( "" );
|
||||
m_xEntry->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) );
|
||||
m_yEntry->SetToolTip( "" );
|
||||
m_yEntry->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) );
|
||||
m_stdButtons->GetAffirmativeButton()->Enable();
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ private:
|
|||
wxPoint& m_translation;
|
||||
double& m_rotation;
|
||||
ROTATION_ANCHOR& m_rotationAnchor;
|
||||
const EDA_RECT& m_bbox;
|
||||
|
||||
UNIT_BINDER m_moveX;
|
||||
UNIT_BINDER m_moveY;
|
||||
|
@ -59,7 +60,8 @@ private:
|
|||
public:
|
||||
// Constructor and destructor
|
||||
DIALOG_MOVE_EXACT(PCB_BASE_FRAME *aParent, wxPoint& aTranslate,
|
||||
double& aRotate, ROTATION_ANCHOR& aAnchor );
|
||||
double& aRotate, ROTATION_ANCHOR& aAnchor,
|
||||
const EDA_RECT& aBbox);
|
||||
~DIALOG_MOVE_EXACT() { };
|
||||
|
||||
private:
|
||||
|
@ -71,6 +73,7 @@ private:
|
|||
|
||||
void OnPolarChanged( wxCommandEvent& event ) override;
|
||||
void OnClear( wxCommandEvent& event ) override;
|
||||
void OnTextChanged( wxCommandEvent& event ) override;
|
||||
|
||||
// Automatically called when clicking on the OK button
|
||||
bool TransferDataFromWindow() override;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Nov 10 2018)
|
||||
// C++ code generated with wxFormBuilder (version Apr 23 2019)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
|
@ -103,8 +103,10 @@ DIALOG_MOVE_EXACT_BASE::DIALOG_MOVE_EXACT_BASE( wxWindow* parent, wxWindowID id,
|
|||
|
||||
// Connect Events
|
||||
m_xEntry->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_MOVE_EXACT_BASE::OnTextFocusLost ), NULL, this );
|
||||
m_xEntry->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_MOVE_EXACT_BASE::OnTextChanged ), NULL, this );
|
||||
m_clearX->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MOVE_EXACT_BASE::OnClear ), NULL, this );
|
||||
m_yEntry->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_MOVE_EXACT_BASE::OnTextFocusLost ), NULL, this );
|
||||
m_yEntry->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_MOVE_EXACT_BASE::OnTextChanged ), NULL, this );
|
||||
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 );
|
||||
|
@ -115,8 +117,10 @@ DIALOG_MOVE_EXACT_BASE::~DIALOG_MOVE_EXACT_BASE()
|
|||
{
|
||||
// Disconnect Events
|
||||
m_xEntry->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_MOVE_EXACT_BASE::OnTextFocusLost ), NULL, this );
|
||||
m_xEntry->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_MOVE_EXACT_BASE::OnTextChanged ), NULL, this );
|
||||
m_clearX->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MOVE_EXACT_BASE::OnClear ), NULL, this );
|
||||
m_yEntry->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_MOVE_EXACT_BASE::OnTextFocusLost ), NULL, this );
|
||||
m_yEntry->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_MOVE_EXACT_BASE::OnTextChanged ), NULL, this );
|
||||
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 );
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<property name="file">dialog_move_exact_base</property>
|
||||
<property name="first_id">1000</property>
|
||||
<property name="help_provider">none</property>
|
||||
<property name="image_path_wrapper_function_name"></property>
|
||||
<property name="indent_with_spaces"></property>
|
||||
<property name="internationalize">1</property>
|
||||
<property name="name">DIALOG_MOVE_EXACT_BASE</property>
|
||||
|
@ -25,6 +26,7 @@
|
|||
<property name="skip_php_events">1</property>
|
||||
<property name="skip_python_events">1</property>
|
||||
<property name="ui_table">UI</property>
|
||||
<property name="use_array_enum">0</property>
|
||||
<property name="use_enum">0</property>
|
||||
<property name="use_microsoft_bom">0</property>
|
||||
<object class="Dialog" expanded="1">
|
||||
|
@ -198,6 +200,7 @@
|
|||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnKillFocus">OnTextFocusLost</event>
|
||||
<event name="OnText">OnTextChanged</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="0">
|
||||
|
@ -458,6 +461,7 @@
|
|||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnKillFocus">OnTextFocusLost</event>
|
||||
<event name="OnText">OnTextChanged</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="0">
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Nov 10 2018)
|
||||
// C++ code generated with wxFormBuilder (version Apr 23 2019)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
|
@ -61,6 +61,7 @@ class DIALOG_MOVE_EXACT_BASE : public DIALOG_SHIM
|
|||
|
||||
// Virtual event handlers, overide them in your derived class
|
||||
virtual void OnTextFocusLost( wxFocusEvent& event ) { event.Skip(); }
|
||||
virtual void OnTextChanged( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnClear( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnPolarChanged( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
|
|
@ -1521,13 +1521,14 @@ void PCB_EDIT_FRAME::moveExact()
|
|||
wxPoint translation;
|
||||
double rotation;
|
||||
ROTATION_ANCHOR rotationAnchor = ROTATE_AROUND_ITEM_ANCHOR;
|
||||
BOARD_ITEM* item = GetScreen()->GetCurItem();
|
||||
|
||||
DIALOG_MOVE_EXACT dialog( this, translation, rotation, rotationAnchor );
|
||||
DIALOG_MOVE_EXACT dialog( this, translation, rotation, rotationAnchor, item->GetBoundingBox() );
|
||||
int ret = dialog.ShowModal();
|
||||
|
||||
if( ret == wxID_OK )
|
||||
{
|
||||
if( BOARD_ITEM* item = GetScreen()->GetCurItem() )
|
||||
if( item )
|
||||
{
|
||||
// When a pad is modified, the full footprint is saved
|
||||
BOARD_ITEM* itemToSave = item;
|
||||
|
|
|
@ -844,16 +844,16 @@ void FOOTPRINT_EDIT_FRAME::moveExact()
|
|||
wxPoint translation;
|
||||
double rotation;
|
||||
ROTATION_ANCHOR rotationAnchor = ROTATE_AROUND_ITEM_ANCHOR;
|
||||
BOARD_ITEM* item = GetScreen()->GetCurItem();
|
||||
|
||||
DIALOG_MOVE_EXACT dialog( this, translation, rotation, rotationAnchor );
|
||||
DIALOG_MOVE_EXACT dialog( this, translation, rotation, rotationAnchor,
|
||||
item->GetBoundingBox() );
|
||||
int ret = dialog.ShowModal();
|
||||
|
||||
if( ret == wxID_OK )
|
||||
{
|
||||
SaveCopyInUndoList( GetBoard()->m_Modules, UR_CHANGED );
|
||||
|
||||
BOARD_ITEM* item = GetScreen()->GetCurItem();
|
||||
|
||||
item->Move( translation );
|
||||
|
||||
switch( rotationAnchor )
|
||||
|
@ -903,7 +903,7 @@ void FOOTPRINT_EDIT_FRAME::Transform( MODULE* module, int transform )
|
|||
double rotation;
|
||||
ROTATION_ANCHOR rotationAnchor = ROTATE_AROUND_ITEM_ANCHOR;
|
||||
|
||||
DIALOG_MOVE_EXACT dialog( this, translation, rotation, rotationAnchor );
|
||||
DIALOG_MOVE_EXACT dialog( this, translation, rotation, rotationAnchor, module->GetBoundingBox() );
|
||||
|
||||
if( dialog.ShowModal() == wxID_OK )
|
||||
{
|
||||
|
|
|
@ -1022,7 +1022,10 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent )
|
|||
ROTATION_ANCHOR rotationAnchor = selection.Size() > 1 ? ROTATE_AROUND_SEL_CENTER
|
||||
: ROTATE_AROUND_ITEM_ANCHOR;
|
||||
|
||||
DIALOG_MOVE_EXACT dialog( editFrame, translation, rotation, rotationAnchor );
|
||||
// TODO: Implement a visible bounding border at the edge
|
||||
auto sel_box = selection.GetBoundingBox();
|
||||
|
||||
DIALOG_MOVE_EXACT dialog( editFrame, translation, rotation, rotationAnchor, sel_box );
|
||||
int ret = dialog.ShowModal();
|
||||
|
||||
if( ret == wxID_OK )
|
||||
|
|
Loading…
Reference in New Issue