7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-20 20:11:41 +00:00

ADDED: Position items relative to arbitrary reference point

Fixes https://gitlab.com/kicad/code/kicad/-/issues/4756
This commit is contained in:
Jon Evans 2024-08-11 18:59:26 -04:00
parent c9af2f318f
commit bd946313dc
13 changed files with 1350 additions and 1119 deletions

View File

@ -162,4 +162,13 @@ VECTOR2I GRID_HELPER::Align( const VECTOR2I& aPoint, const VECTOR2D& aGrid,
bool GRID_HELPER::canUseGrid() const
{
return m_enableGrid && m_toolMgr->GetView()->GetGAL()->GetGridSnapping();
}
}
std::optional<VECTOR2I> GRID_HELPER::GetSnappedPoint() const
{
if( m_snapItem )
return m_snapItem->pos;
return std::nullopt;
}

View File

@ -101,6 +101,7 @@ int PICKER_TOOL::Main( const TOOL_EVENT& aEvent )
{
setCursor();
VECTOR2D cursorPos = controls->GetCursorPosition( m_snap && m_frame->IsGridVisible() );
m_modifiers = aEvent.Modifier();
if( evt->IsCancelInteractive() || evt->IsActivate() )
{

View File

@ -115,6 +115,8 @@ public:
void SetMaskFlag( int aFlag ) { m_maskTypes |= aFlag; }
void ClearMaskFlag( int aFlag ) { m_maskTypes = m_maskTypes & ~aFlag; }
std::optional<VECTOR2I> GetSnappedPoint() const;
enum ANCHOR_FLAGS {
CORNER = 1,
OUTLINE = 2,

View File

@ -106,6 +106,8 @@ public:
m_finalizeHandler = aHandler;
}
int CurrentModifiers() const { return m_modifiers; }
protected:
///< Reinitializes tool to its initial state.
virtual void reset();
@ -113,6 +115,7 @@ protected:
EDA_DRAW_FRAME* m_frame;
KICURSOR m_cursor;
bool m_snap;
int m_modifiers;
std::optional<CLICK_HANDLER> m_clickHandler;
std::optional<MOTION_HANDLER> m_motionHandler;

View File

@ -215,7 +215,19 @@ void DIALOG_POSITION_RELATIVE::OnSelectItemClick( wxCommandEvent& event )
POSITION_RELATIVE_TOOL* posrelTool = m_toolMgr->GetTool<POSITION_RELATIVE_TOOL>();
wxASSERT( posrelTool );
m_toolMgr->RunAction( PCB_ACTIONS::selectpositionRelativeItem );
m_toolMgr->RunAction( PCB_ACTIONS::selectPositionRelativeItem );
Hide();
}
void DIALOG_POSITION_RELATIVE::OnSelectPointClick( wxCommandEvent& event )
{
event.Skip();
POSITION_RELATIVE_TOOL* posrelTool = m_toolMgr->GetTool<POSITION_RELATIVE_TOOL>();
wxASSERT( posrelTool );
m_toolMgr->RunAction( PCB_ACTIONS::selectPositionRelativePoint );
Hide();
}
@ -244,6 +256,13 @@ void DIALOG_POSITION_RELATIVE::updateAnchorInfo( BOARD_ITEM* aItem )
m_referenceInfo->SetLabel( wxString::Format( _( "Reference item: %s" ), msg ) );
break;
}
case ANCHOR_POINT:
m_referenceInfo->SetLabel( wxString::Format(
_( "Reference location: selected point (%s, %s)" ),
m_parentFrame->MessageTextFromValue( m_anchorItemPosition.x ),
m_parentFrame->MessageTextFromValue( m_anchorItemPosition.y ) ) );
break;
}
}
@ -259,6 +278,7 @@ VECTOR2I DIALOG_POSITION_RELATIVE::getAnchorPos()
return static_cast<PCB_BASE_FRAME*>( m_toolMgr->GetToolHolder() )->GetScreen()->m_LocalOrigin;
case ANCHOR_ITEM:
case ANCHOR_POINT:
return m_anchorItemPosition;
}
@ -295,6 +315,19 @@ void DIALOG_POSITION_RELATIVE::UpdateAnchor( EDA_ITEM* aItem )
}
void DIALOG_POSITION_RELATIVE::UpdateAnchor( std::optional<VECTOR2I> aPoint )
{
m_options.anchorType = ANCHOR_POINT;
if( aPoint )
m_anchorItemPosition = *aPoint;
updateAnchorInfo( nullptr );
Show( true );
}
void DIALOG_POSITION_RELATIVE::OnOkClick( wxCommandEvent& event )
{
// for the output, we only deliver a Cartesian vector

View File

@ -40,6 +40,7 @@ public:
~DIALOG_POSITION_RELATIVE() { };
void UpdateAnchor( EDA_ITEM* aItem );
void UpdateAnchor( std::optional<VECTOR2I> aPoint );
private:
/**
@ -51,6 +52,7 @@ private:
void OnClear( wxCommandEvent& event ) override;
void OnSelectItemClick( wxCommandEvent& event ) override;
void OnSelectPointClick( wxCommandEvent& event ) override;
void OnUseGridOriginClick( wxCommandEvent& event ) override;
void OnUseUserOriginClick( wxCommandEvent& event ) override;
void OnOkClick( wxCommandEvent& event ) override;
@ -87,7 +89,8 @@ private:
{
ANCHOR_GRID_ORIGIN,
ANCHOR_USER_ORIGIN,
ANCHOR_ITEM
ANCHOR_ITEM,
ANCHOR_POINT
};
struct POSITION_RELATIVE_OPTIONS

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -23,7 +23,7 @@ DIALOG_POSITION_RELATIVE_BASE::DIALOG_POSITION_RELATIVE_BASE( wxWindow* parent,
m_referenceInfo->Wrap( -1 );
m_referenceInfo->SetMinSize( wxSize( 340,-1 ) );
bUpperSizer->Add( m_referenceInfo, 0, wxALL, 5 );
bUpperSizer->Add( m_referenceInfo, 0, wxALL|wxEXPAND, 5 );
bUpperSizer->Add( 0, 0, 0, wxEXPAND, 5 );
@ -42,6 +42,9 @@ DIALOG_POSITION_RELATIVE_BASE::DIALOG_POSITION_RELATIVE_BASE( wxWindow* parent,
bSizerButtOpts->Add( m_select_anchor_button, 1, wxALL|wxEXPAND, 5 );
m_select_point_button = new wxButton( this, wxID_ANY, _("Select Point..."), wxDefaultPosition, wxDefaultSize, 0 );
bSizerButtOpts->Add( m_select_point_button, 1, wxALL, 5 );
bUpperSizer->Add( bSizerButtOpts, 1, wxEXPAND|wxTOP|wxBOTTOM, 5 );
@ -132,6 +135,7 @@ DIALOG_POSITION_RELATIVE_BASE::DIALOG_POSITION_RELATIVE_BASE( wxWindow* parent,
m_user_origin_button->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnUseUserOriginClick ), NULL, this );
m_grid_origin_button->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnUseGridOriginClick ), NULL, this );
m_select_anchor_button->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnSelectItemClick ), NULL, this );
m_select_point_button->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnSelectPointClick ), NULL, this );
m_xEntry->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnTextFocusLost ), NULL, this );
m_clearX->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnClear ), NULL, this );
m_yEntry->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnTextFocusLost ), NULL, this );
@ -147,6 +151,7 @@ DIALOG_POSITION_RELATIVE_BASE::~DIALOG_POSITION_RELATIVE_BASE()
m_user_origin_button->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnUseUserOriginClick ), NULL, this );
m_grid_origin_button->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnUseGridOriginClick ), NULL, this );
m_select_anchor_button->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnSelectItemClick ), NULL, this );
m_select_point_button->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnSelectPointClick ), NULL, this );
m_xEntry->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnTextFocusLost ), NULL, this );
m_clearX->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnClear ), NULL, this );
m_yEntry->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnTextFocusLost ), NULL, this );

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -29,7 +29,6 @@
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class DIALOG_POSITION_RELATIVE_BASE
///////////////////////////////////////////////////////////////////////////////
@ -42,6 +41,7 @@ class DIALOG_POSITION_RELATIVE_BASE : public DIALOG_SHIM
wxButton* m_user_origin_button;
wxButton* m_grid_origin_button;
wxButton* m_select_anchor_button;
wxButton* m_select_point_button;
wxStaticLine* m_staticline2;
wxStaticText* m_xLabel;
wxTextCtrl* m_xEntry;
@ -61,6 +61,7 @@ class DIALOG_POSITION_RELATIVE_BASE : public DIALOG_SHIM
virtual void OnUseUserOriginClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnUseGridOriginClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnSelectItemClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnSelectPointClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnTextFocusLost( wxFocusEvent& event ) { event.Skip(); }
virtual void OnClear( wxCommandEvent& event ) { event.Skip(); }
virtual void OnPolarChanged( wxCommandEvent& event ) { event.Skip(); }

View File

@ -2021,10 +2021,14 @@ TOOL_ACTION PCB_ACTIONS::positionRelative( TOOL_ACTION_ARGS()
.Tooltip( _( "Positions the selected item(s) by an exact amount relative to another" ) )
.Icon( BITMAPS::move_relative ) );
TOOL_ACTION PCB_ACTIONS::selectpositionRelativeItem( TOOL_ACTION_ARGS()
TOOL_ACTION PCB_ACTIONS::selectPositionRelativeItem( TOOL_ACTION_ARGS()
.Name( "pcbnew.PositionRelative.selectpositionRelativeItem" )
.Scope( AS_GLOBAL ) );
TOOL_ACTION PCB_ACTIONS::selectPositionRelativePoint( TOOL_ACTION_ARGS()
.Name( "pcbnew.PositionRelative.selectPositionRelativePoint" )
.Scope( AS_GLOBAL ) );
// PCB_SELECTION_TOOL
//
@ -2480,4 +2484,4 @@ const TOOL_EVENT PCB_EVENTS::SnappingModeChangedByKeyEvent( TC_MESSAGE, TA_ACTIO
"common.Interactive.snappingModeChangedByKey" );
const TOOL_EVENT PCB_EVENTS::LayerPairPresetChangedByKeyEvent( TC_MESSAGE, TA_ACTION,
"pcbnew.Control.layerPairPresetChangedByKey" );
"pcbnew.Control.layerPairPresetChangedByKey" );

View File

@ -321,7 +321,8 @@ public:
static TOOL_ACTION positionRelative;
/// Selection of anchor item for position relative tool
static TOOL_ACTION selectpositionRelativeItem;
static TOOL_ACTION selectPositionRelativeItem;
static TOOL_ACTION selectPositionRelativePoint;
// Display modes
static TOOL_ACTION showRatsnest;

View File

@ -28,6 +28,7 @@ using namespace std::placeholders;
#include <kiplatform/ui.h>
#include <tools/position_relative_tool.h>
#include <tools/pcb_actions.h>
#include <tools/pcb_grid_helper.h>
#include <tools/pcb_selection_tool.h>
#include <tools/pcb_picker_tool.h>
#include <dialogs/dialog_position_relative.h>
@ -229,9 +230,79 @@ int POSITION_RELATIVE_TOOL::SelectPositionRelativeItem( const TOOL_EVENT& aEvent
}
int POSITION_RELATIVE_TOOL::SelectPositionRelativePoint( const TOOL_EVENT& aEvent )
{
PCB_PICKER_TOOL* picker = m_toolMgr->GetTool<PCB_PICKER_TOOL>();
STATUS_TEXT_POPUP statusPopup( frame() );
bool done = false;
PCB_GRID_HELPER grid_helper( m_toolMgr, frame()->GetMagneticItemsSettings() );
Activate();
statusPopup.SetText( _( "Click on reference point..." ) );
picker->SetClickHandler(
[&]( const VECTOR2D& aPoint ) -> bool
{
std::optional<VECTOR2I> snapped = grid_helper.GetSnappedPoint();
statusPopup.Hide();
if( m_dialog )
m_dialog->UpdateAnchor( snapped ? *snapped : VECTOR2I( aPoint ) );
return false; // got our item; don't need any more
} );
picker->SetMotionHandler(
[&] ( const VECTOR2D& aPos )
{
grid_helper.SetSnap( !( picker->CurrentModifiers() & MD_SHIFT ) );
statusPopup.Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, -50 ) );
} );
picker->SetCancelHandler(
[&]()
{
statusPopup.Hide();
if( m_dialog )
m_dialog->UpdateAnchor( std::nullopt );
} );
picker->SetFinalizeHandler(
[&]( const int& aFinalState )
{
done = true;
} );
statusPopup.Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, -50 ) );
statusPopup.Popup();
canvas()->SetStatusPopup( statusPopup.GetPanel() );
m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
while( !done )
{
// Pass events unless we receive a null event, then we must shut down
if( TOOL_EVENT* evt = Wait() )
evt->SetPassEvent();
else
break;
}
canvas()->SetStatusPopup( nullptr );
return 0;
}
void POSITION_RELATIVE_TOOL::setTransitions()
{
Go( &POSITION_RELATIVE_TOOL::PositionRelative, PCB_ACTIONS::positionRelative.MakeEvent() );
Go( &POSITION_RELATIVE_TOOL::SelectPositionRelativeItem,
PCB_ACTIONS::selectpositionRelativeItem.MakeEvent() );
PCB_ACTIONS::selectPositionRelativeItem.MakeEvent() );
Go( &POSITION_RELATIVE_TOOL::SelectPositionRelativePoint,
PCB_ACTIONS::selectPositionRelativePoint.MakeEvent() );
}

View File

@ -63,6 +63,12 @@ public:
*/
int SelectPositionRelativeItem( const TOOL_EVENT& aEvent );
/**
* Invoke the picker tool to select the point to which the previous selection will be placed
* relative to.
*/
int SelectPositionRelativePoint( const TOOL_EVENT& aEvent );
/**
* Return the position of the selected item(s)
*/