diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index ab32253a55..b74f4a6aa2 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -134,6 +134,8 @@ set( PCBNEW_DIALOGS dialogs/dialog_pad_properties_base.cpp dialogs/dialog_plot_base.cpp dialogs/dialog_plot.cpp + dialogs/dialog_position_relative.cpp + dialogs/dialog_position_relative_base.cpp dialogs/dialog_print_for_modedit.cpp dialogs/dialog_print_for_modedit_base.cpp dialogs/dialog_print_using_printer.cpp @@ -309,6 +311,7 @@ set( PCBNEW_CLASS_SRCS tools/point_editor.cpp tools/drawing_tool.cpp tools/edit_tool.cpp + tools/position_relative_tool.cpp tools/pcbnew_control.cpp tools/pcb_editor_control.cpp tools/microwave_tool.cpp diff --git a/pcbnew/dialogs/dialog_position_relative.cpp b/pcbnew/dialogs/dialog_position_relative.cpp new file mode 100644 index 0000000000..91f6adc88b --- /dev/null +++ b/pcbnew/dialogs/dialog_position_relative.cpp @@ -0,0 +1,232 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 John Beard, john.j.beard@gmail.com + * Copyright (C) 1992-2014 KiCad Developers, see AUTHORS.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 + * 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 + */ + +#include +#include +#include + +#include + +#include "dialog_position_relative.h" +#include "tools/pcb_actions.h" + +// initialise statics +DIALOG_POSITION_RELATIVE::POSITION_RELATIVE_OPTIONS DIALOG_POSITION_RELATIVE::m_options; + + +DIALOG_POSITION_RELATIVE::DIALOG_POSITION_RELATIVE( PCB_BASE_FRAME* aParent, TOOL_MANAGER* toolMgr, + wxPoint& translation, double& rotation, wxPoint& anchorPosition ) : + DIALOG_POSITION_RELATIVE_BASE( aParent ), + m_toolMgr( toolMgr ), + m_translation( translation ), + m_rotation( rotation ), + m_anchor_position( anchorPosition ) +{ + // set the unit labels + m_xUnit->SetLabelText( GetAbbreviatedUnitsLabel( g_UserUnit ) ); + m_yUnit->SetLabelText( GetAbbreviatedUnitsLabel( g_UserUnit ) ); + + // tabbing goes through the entries in sequence + m_yEntry->MoveAfterInTabOrder( m_xEntry ); + m_rotEntry->MoveAfterInTabOrder( m_yEntry ); + + // and set up the entries according to the saved options + m_polarCoords->SetValue( m_options.polarCoords ); + m_xEntry->SetValue( wxString::FromDouble( m_options.entry1 ) ); + m_yEntry->SetValue( wxString::FromDouble( m_options.entry2 ) ); + m_rotEntry->SetValue( wxString::FromDouble( m_options.entryRotation ) ); + updateDlgTexts( m_polarCoords->IsChecked() ); + + m_stdButtonsOK->SetDefault(); + + GetSizer()->SetSizeHints( this ); + Layout(); +} + + +DIALOG_POSITION_RELATIVE::~DIALOG_POSITION_RELATIVE() +{ +} + + +void DIALOG_POSITION_RELATIVE::ToPolarDeg( double x, double y, double& r, double& q ) +{ + // convert to polar coordinates + r = hypot( x, y ); + + q = ( r != 0) ? RAD2DEG( atan2( y, x ) ) : 0; +} + + +bool DIALOG_POSITION_RELATIVE::GetTranslationInIU( wxPoint& val, bool polar ) +{ + if( polar ) + { + const int r = ValueFromTextCtrl( *m_xEntry ); + const double q = DoubleValueFromString( DEGREES, m_yEntry->GetValue() ); + + val.x = r * cos( DEG2RAD( q / 10.0 ) ); + val.y = r * sin( DEG2RAD( q / 10.0 ) ); + } + else + { + // direct read + val.x = ValueFromTextCtrl( *m_xEntry ); + val.y = ValueFromTextCtrl( *m_yEntry ); + } + + // no validation to do here, but in future, you could return false here + return true; +} + + +void DIALOG_POSITION_RELATIVE::OnPolarChanged( wxCommandEvent& event ) +{ + bool newPolar = m_polarCoords->IsChecked(); + + updateDlgTexts( newPolar ); + wxPoint val; + + // get the value as previously stored + GetTranslationInIU( val, !newPolar ); + + if( newPolar ) + { + // convert to polar coordinates + double r, q; + ToPolarDeg( val.x, val.y, r, q ); + + PutValueInLocalUnits( *m_xEntry, KiROUND( r / 10.0 ) * 10 ); + m_yEntry->SetValue( wxString::FromDouble( q ) ); + } + else + { + // vector is already in Cartesian, so just render out + // note - round off the last decimal place (10nm) to prevent + // (some) rounding causing errors when round-tripping + // you can never eliminate entirely, however + PutValueInLocalUnits( *m_xEntry, KiROUND( val.x / 10.0 ) * 10 ); + PutValueInLocalUnits( *m_yEntry, KiROUND( val.y / 10.0 ) * 10 ); + } + + Layout(); +} + + +void DIALOG_POSITION_RELATIVE::updateDlgTexts( bool aPolar ) +{ + if( aPolar ) + { + m_xLabel->SetLabelText( _( "Distance:" ) ); // Polar radius + m_yLabel->SetLabelText( _( "Angle:" ) ); // Polar theta or angle + + m_yUnit->SetLabelText( GetAbbreviatedUnitsLabel( DEGREES ) ); + } + else + { + m_xLabel->SetLabelText( _( "Move vector X:" ) ); + m_yLabel->SetLabelText( _( "Move vector Y:" ) ); + + m_yUnit->SetLabelText( GetAbbreviatedUnitsLabel( g_UserUnit ) ); + } +} + + +void DIALOG_POSITION_RELATIVE::OnClear( wxCommandEvent& event ) +{ + wxObject* obj = event.GetEventObject(); + wxTextCtrl* entry = NULL; + + if( obj == m_clearX ) + { + entry = m_xEntry; + } + else if( obj == m_clearY ) + { + entry = m_yEntry; + } + else if( obj == m_clearRot ) + { + entry = m_rotEntry; + } + + if( entry ) + entry->SetValue( "0" ); +} + + +void DIALOG_POSITION_RELATIVE::OnSelectItemClick( wxCommandEvent& event ) +{ + event.Skip(); + + + POSITION_RELATIVE_TOOL* posrelTool = m_toolMgr->GetTool(); + assert( posrelTool ); + m_toolMgr->RunAction( PCB_ACTIONS::selectpositionRelativeItem, true ); +} + + +void DIALOG_POSITION_RELATIVE::UpdateAchor( BOARD_ITEM* aBoardItem ) +{ + m_anchor_position = aBoardItem->GetPosition(); + + PutValueInLocalUnits( *m_anchor_x, m_anchor_position.x ); + PutValueInLocalUnits( *m_anchor_y, m_anchor_position.y ); +} + + +void DIALOG_POSITION_RELATIVE::OnOkClick( wxCommandEvent& event ) +{ + m_rotation = DoubleValueFromString( DEGREES, m_rotEntry->GetValue() ); + + // for the output, we only deliver a Cartesian vector + bool ok = GetTranslationInIU( m_translation, m_polarCoords->IsChecked() ); + + if( ok ) + { + // save the settings + m_options.polarCoords = m_polarCoords->GetValue(); + 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() ); + POSITION_RELATIVE_TOOL* posrelTool = m_toolMgr->GetTool(); + assert( posrelTool ); + + + posrelTool->RelativeItemSelectionMove( m_anchor_position, m_translation, m_rotation ); + + event.Skip(); + } +} + + +void DIALOG_POSITION_RELATIVE::OnTextFocusLost( wxFocusEvent& event ) +{ + wxTextCtrl* obj = static_cast( event.GetEventObject() ); + + if( obj->GetValue().IsEmpty() ) + obj->SetValue( "0" ); + + event.Skip(); +} diff --git a/pcbnew/dialogs/dialog_position_relative.fbp b/pcbnew/dialogs/dialog_position_relative.fbp new file mode 100644 index 0000000000..3835fac833 --- /dev/null +++ b/pcbnew/dialogs/dialog_position_relative.fbp @@ -0,0 +1,1783 @@ + + + + + + C++ + 1 + source_name + 0 + 0 + res + UTF-8 + connect + dialog_position_relative_base + 1000 + none + 1 + DIALOG_POSITION_RELATIVE_BASE + + . + + 1 + 1 + 1 + 1 + UI + 0 + 0 + + 0 + wxAUI_MGR_DEFAULT + + + + 1 + 1 + impl_virtual + + + + 0 + wxID_ANY + + -1,-1 + DIALOG_POSITION_RELATIVE_BASE + + -1,-1 + wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER + DIALOG_SHIM; dialog_shim.h + Position Relative + + + + + + + + + + + + + + OnClose + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bMainSizer + wxVERTICAL + none + + 5 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Use polar coordinates + + 0 + + + 0 + + 1 + m_polarCoords + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + OnPolarChanged + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND|wxTOP|wxBOTTOM + 1 + + 4 + wxBOTH + 1 + + 0 + + fgSizer2 + wxFLEX_GROWMODE_SPECIFIED + none + 0 + 0 + + 5 + wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + x: + + 0 + + + 0 + + 1 + m_xLabel + 1 + + + protected + 1 + + Resizable + 1 + -1,-1 + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + + 0 + + 1 + m_xEntry + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + 0 + + + + + + + + + OnTextFocusLost + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT|wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + mm + + 0 + + + 0 + + 1 + m_xUnit + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL|wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Reset + + 0 + + + 0 + + 1 + m_clearX + 1 + + + protected + 1 + + Resizable + 1 + + wxBU_EXACTFIT + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnClear + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + y: + + 0 + + + 0 + + 1 + m_yLabel + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + + 0 + + 1 + m_yEntry + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + 0 + + + + + + + + + OnTextFocusLost + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL|wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + mm + + 0 + + + 0 + + 1 + m_yUnit + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL|wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Reset + + 0 + + + 0 + + 1 + m_clearY + 1 + + + protected + 1 + + Resizable + 1 + + wxBU_EXACTFIT + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnClear + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Item rotation: + + 0 + + + 0 + + 1 + m_rotLabel + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + + 0 + + 1 + m_rotEntry + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + 0 + + + + + + + + + OnTextFocusLost + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL|wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + deg + + 0 + + + 0 + + 1 + m_rotUnit + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL|wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Reset + + 0 + + + 0 + + 1 + m_clearRot + 1 + + + protected + 1 + + Resizable + 1 + + wxBU_EXACTFIT + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnClear + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Anchor X: + + 0 + + + 0 + + 1 + m_anchor_xLabel + 1 + + + protected + 1 + + Resizable + 1 + -1,-1 + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + + 0 + + 1 + m_anchor_x + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Y: + + 0 + + + 0 + + 1 + m_anchor_yLabel + 1 + + + protected + 1 + + Resizable + 1 + -1,-1 + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + + 0 + + 1 + m_anchor_y + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND | wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_staticline1 + 1 + + + protected + 1 + + Resizable + 1 + + wxLI_HORIZONTAL + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Select Anchor Item + + 0 + + + 0 + + 1 + m_select_anchor_button + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnSelectItemClick + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND + 0 + + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + + m_stdButtons + protected + + + + + + OnOkClick + + + + + + + + diff --git a/pcbnew/dialogs/dialog_position_relative.h b/pcbnew/dialogs/dialog_position_relative.h new file mode 100644 index 0000000000..07a854518f --- /dev/null +++ b/pcbnew/dialogs/dialog_position_relative.h @@ -0,0 +1,107 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 John Beard, john.j.beard@gmail.com + * Copyright (C) 1992-2014 KiCad Developers, see AUTHORS.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 + * 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 + */ + +#ifndef __DIALOG_POSITION_RELATIVE__ +#define __DIALOG_POSITION_RELATIVE__ + +// Include the wxFormBuider header base: +#include +#include + +#include +#include "tools/position_relative_tool.h" + +class DIALOG_POSITION_RELATIVE : public DIALOG_POSITION_RELATIVE_BASE +{ +private: + + TOOL_MANAGER* m_toolMgr; + wxPoint& m_translation; + double& m_rotation; + wxPoint& m_anchor_position; + +public: + // Constructor and destructor + DIALOG_POSITION_RELATIVE( PCB_BASE_FRAME* aParent, TOOL_MANAGER* toolMgr, wxPoint& translation, + double& rotation, wxPoint& anchorposition ); + ~DIALOG_POSITION_RELATIVE(); + + void UpdateAchor( BOARD_ITEM* aBoardItem ); + +private: + + /*! + * Reset a text field to be 0 if it was exited while blank + */ + void OnTextFocusLost( wxFocusEvent& event ) override; + + void OnPolarChanged( wxCommandEvent& event ) override; + void OnClear( wxCommandEvent& event ) override; + + void OnSelectItemClick( wxCommandEvent& event ) override; + void OnOkClick( wxCommandEvent& event ) override; + + /** + * Convert a given Cartesian point into a polar representation. + * + * Linear units are not considered, the answer is in the same units as given + * Angle is returned in degrees + */ + void ToPolarDeg( double x, double y, double& r, double& q ); + + /** + * Get the (Cartesian) translation described by the text entries + * @param val output translation vector + * @param polar interpret as polar coords + * @return false if error (though the text conversion functions don't report errors) + */ + bool GetTranslationInIU( wxPoint& val, bool polar ); + + // Update texts (comments) after changing the coordinates type (polar/cartesian) + void updateDlgTexts( bool aPolar ); + + /** + * Persistent dialog options + */ + struct POSITION_RELATIVE_OPTIONS + { + bool polarCoords; + double entry1; + double entry2; + double entryRotation; + + POSITION_RELATIVE_OPTIONS() : + polarCoords( false ), + entry1( 0 ), + entry2( 0 ), + entryRotation( 0 ) + { + } + }; + + // persistent settings + static POSITION_RELATIVE_OPTIONS m_options; +}; + +#endif // __DIALOG_POSITION_RELATIVE__ diff --git a/pcbnew/dialogs/dialog_position_relative_base.cpp b/pcbnew/dialogs/dialog_position_relative_base.cpp new file mode 100644 index 0000000000..e1d9d174bc --- /dev/null +++ b/pcbnew/dialogs/dialog_position_relative_base.cpp @@ -0,0 +1,134 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Jun 17 2015) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "dialog_position_relative_base.h" + +/////////////////////////////////////////////////////////////////////////// + +DIALOG_POSITION_RELATIVE_BASE::DIALOG_POSITION_RELATIVE_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style ) +{ + 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 ); + + 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 ); + + m_xEntry = new wxTextCtrl( this, wxID_ANY, _("0"), wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer2->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 ); + + m_clearX = new wxButton( this, wxID_ANY, _("Reset"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT ); + fgSizer2->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 ); + + m_yEntry = new wxTextCtrl( this, wxID_ANY, _("0"), wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer2->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 ); + + m_clearY = new wxButton( this, wxID_ANY, _("Reset"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT ); + fgSizer2->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 ); + + m_rotEntry = new wxTextCtrl( this, wxID_ANY, _("0"), wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer2->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 ); + + m_clearRot = new wxButton( this, wxID_ANY, _("Reset"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT ); + fgSizer2->Add( m_clearRot, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + m_anchor_xLabel = new wxStaticText( this, wxID_ANY, _("Anchor X:"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_anchor_xLabel->Wrap( -1 ); + fgSizer2->Add( m_anchor_xLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5 ); + + m_anchor_x = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer2->Add( m_anchor_x, 0, wxALL, 5 ); + + m_anchor_yLabel = new wxStaticText( this, wxID_ANY, _("Y:"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_anchor_yLabel->Wrap( -1 ); + fgSizer2->Add( m_anchor_yLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5 ); + + m_anchor_y = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer2->Add( m_anchor_y, 0, wxALL, 5 ); + + + bMainSizer->Add( fgSizer2, 1, wxEXPAND|wxTOP|wxBOTTOM, 5 ); + + m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bMainSizer->Add( m_staticline1, 0, wxEXPAND | wxALL, 5 ); + + m_select_anchor_button = new wxButton( this, wxID_ANY, _("Select Anchor Item"), wxDefaultPosition, wxDefaultSize, 0 ); + bMainSizer->Add( m_select_anchor_button, 0, wxALL, 5 ); + + m_stdButtons = new wxStdDialogButtonSizer(); + m_stdButtonsOK = new wxButton( this, wxID_OK ); + m_stdButtons->AddButton( m_stdButtonsOK ); + m_stdButtonsCancel = new wxButton( this, wxID_CANCEL ); + m_stdButtons->AddButton( m_stdButtonsCancel ); + m_stdButtons->Realize(); + + bMainSizer->Add( m_stdButtons, 0, wxALL|wxEXPAND, 5 ); + + + this->SetSizer( bMainSizer ); + this->Layout(); + bMainSizer->Fit( this ); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnClose ) ); + m_polarCoords->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnPolarChanged ), 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 ); + m_clearY->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnClear ), NULL, this ); + m_rotEntry->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnTextFocusLost ), NULL, this ); + m_clearRot->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnClear ), NULL, this ); + m_select_anchor_button->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnSelectItemClick ), NULL, this ); + m_stdButtonsOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnOkClick ), NULL, this ); +} + +DIALOG_POSITION_RELATIVE_BASE::~DIALOG_POSITION_RELATIVE_BASE() +{ + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnClose ) ); + m_polarCoords->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnPolarChanged ), 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 ); + m_clearY->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnClear ), NULL, this ); + m_rotEntry->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnTextFocusLost ), NULL, this ); + m_clearRot->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnClear ), NULL, this ); + m_select_anchor_button->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnSelectItemClick ), NULL, this ); + m_stdButtonsOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_POSITION_RELATIVE_BASE::OnOkClick ), NULL, this ); + +} diff --git a/pcbnew/dialogs/dialog_position_relative_base.h b/pcbnew/dialogs/dialog_position_relative_base.h new file mode 100644 index 0000000000..fecd8134e3 --- /dev/null +++ b/pcbnew/dialogs/dialog_position_relative_base.h @@ -0,0 +1,80 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Jun 17 2015) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#ifndef __DIALOG_POSITION_RELATIVE_BASE_H__ +#define __DIALOG_POSITION_RELATIVE_BASE_H__ + +#include +#include +#include +class DIALOG_SHIM; + +#include "dialog_shim.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +/// Class DIALOG_POSITION_RELATIVE_BASE +/////////////////////////////////////////////////////////////////////////////// +class DIALOG_POSITION_RELATIVE_BASE : public DIALOG_SHIM +{ + private: + + protected: + wxCheckBox* m_polarCoords; + wxStaticText* m_xLabel; + wxTextCtrl* m_xEntry; + wxStaticText* m_xUnit; + wxButton* m_clearX; + wxStaticText* m_yLabel; + wxTextCtrl* m_yEntry; + wxStaticText* m_yUnit; + wxButton* m_clearY; + wxStaticText* m_rotLabel; + wxTextCtrl* m_rotEntry; + wxStaticText* m_rotUnit; + wxButton* m_clearRot; + wxStaticText* m_anchor_xLabel; + wxTextCtrl* m_anchor_x; + wxStaticText* m_anchor_yLabel; + wxTextCtrl* m_anchor_y; + wxStaticLine* m_staticline1; + wxButton* m_select_anchor_button; + wxStdDialogButtonSizer* m_stdButtons; + wxButton* m_stdButtonsOK; + wxButton* m_stdButtonsCancel; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } + virtual void OnPolarChanged( wxCommandEvent& event ) { event.Skip(); } + virtual void OnTextFocusLost( wxFocusEvent& event ) { event.Skip(); } + virtual void OnClear( wxCommandEvent& event ) { event.Skip(); } + virtual void OnSelectItemClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnOkClick( wxCommandEvent& event ) { event.Skip(); } + + + public: + + DIALOG_POSITION_RELATIVE_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Position Relative"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~DIALOG_POSITION_RELATIVE_BASE(); + +}; + +#endif //__DIALOG_POSITION_RELATIVE_BASE_H__ diff --git a/pcbnew/hotkeys.cpp b/pcbnew/hotkeys.cpp index 2fa1fa5d73..e559b9f2ce 100644 --- a/pcbnew/hotkeys.cpp +++ b/pcbnew/hotkeys.cpp @@ -117,6 +117,7 @@ static EDA_HOTKEY HkFlipItem( _HKI( "Flip Item" ), HK_FLIP_ITEM, 'F' ); static EDA_HOTKEY HkRotateItem( _HKI( "Rotate Item" ), HK_ROTATE_ITEM, 'R' ); static EDA_HOTKEY HkMoveItem( _HKI( "Move Item" ), HK_MOVE_ITEM, 'M' ); static EDA_HOTKEY HkMoveItemExact( _HKI( "Move Item Exactly" ), HK_MOVE_ITEM_EXACT, 'M' + GR_KB_CTRL ); +static EDA_HOTKEY HkPositionItemRelative( _HKI( "Position Item Relative" ), HK_POSITION_RELATIVE, 'R' + GR_KB_CTRL ); static EDA_HOTKEY HkDuplicateItem( _HKI( "Duplicate Item" ), HK_DUPLICATE_ITEM, 'D' + GR_KB_CTRL ); static EDA_HOTKEY HkDuplicateItemAndIncrement( _HKI( "Duplicate Item and Increment" ), HK_DUPLICATE_ITEM_AND_INCREMENT, 'D' + GR_KB_SHIFTCTRL ); @@ -262,7 +263,7 @@ EDA_HOTKEY* board_edit_Hotkey_List[] = &HkPlaceItem, &HkCopyItem, &HkMoveItem, &HkFlipItem, - &HkRotateItem, &HkMoveItemExact, + &HkRotateItem, &HkMoveItemExact, &HkPositionItemRelative, &HkDuplicateItem, &HkDuplicateItemAndIncrement, &HkCreateArray, &HkDragFootprint, &HkGetAndMoveFootprint, &HkLock_Unlock_Footprint, &HkSavefile, &HkSavefileAs, diff --git a/pcbnew/hotkeys.h b/pcbnew/hotkeys.h index f4f3ff1903..ec5f6d36d4 100644 --- a/pcbnew/hotkeys.h +++ b/pcbnew/hotkeys.h @@ -42,6 +42,7 @@ enum hotkey_id_commnand { HK_COPY_ITEM, HK_MOVE_ITEM, HK_MOVE_ITEM_EXACT, + HK_POSITION_RELATIVE, HK_DRAG_ITEM, HK_GET_AND_MOVE_FOOTPRINT, HK_LOCK_UNLOCK_FOOTPRINT, diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index 078f7f74d8..99d5afd118 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -202,6 +202,7 @@ bool EDIT_TOOL::Init() menu.AddItem( PCB_ACTIONS::properties, SELECTION_CONDITIONS::Count( 1 ) || SELECTION_CONDITIONS::OnlyTypes( GENERAL_COLLECTOR::Tracks ) ); menu.AddItem( PCB_ACTIONS::moveExact, SELECTION_CONDITIONS::NotEmpty ); + menu.AddItem( PCB_ACTIONS::positionRelative, SELECTION_CONDITIONS::NotEmpty ); menu.AddItem( PCB_ACTIONS::duplicate, SELECTION_CONDITIONS::NotEmpty ); menu.AddItem( PCB_ACTIONS::createArray, SELECTION_CONDITIONS::NotEmpty ); diff --git a/pcbnew/tools/pcb_actions.h b/pcbnew/tools/pcb_actions.h index 03d3b3fed6..c86c97cee7 100644 --- a/pcbnew/tools/pcb_actions.h +++ b/pcbnew/tools/pcb_actions.h @@ -220,7 +220,12 @@ public: /// Distributes items evenly along the vertical axis static TOOL_ACTION distributeVertically; + // Position Relative Tool + /// Activation of the position relative tool + static TOOL_ACTION positionRelative; + /// Selection of anchor item for position relative tool + static TOOL_ACTION selectpositionRelativeItem; // Display modes static TOOL_ACTION trackDisplayMode; diff --git a/pcbnew/tools/position_relative_tool.cpp b/pcbnew/tools/position_relative_tool.cpp new file mode 100644 index 0000000000..bbe66d8ba6 --- /dev/null +++ b/pcbnew/tools/position_relative_tool.cpp @@ -0,0 +1,231 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013-2015 CERN + * @author Maciej Suminski + * @author Tomasz Wlostowski + * + * 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 + */ + +#define BOOST_BIND_NO_PLACEHOLDERS + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +using namespace std::placeholders; + +#include "pcb_actions.h" +#include "selection_tool.h" +#include "edit_tool.h" +#include "grid_helper.h" +#include "picker_tool.h" +#include "position_relative_tool.h" + +#include + +#include +#include +#include +#include + +#include + +#include + +#include + + +// Position relative tool actions + +TOOL_ACTION PCB_ACTIONS::positionRelative( "pcbnew.PositionRelative.positionRelative", + AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_POSITION_RELATIVE ), + _( "Position Relative to..." ), _( + "Positions the selected item(s) by an exact amount relative to another" ), + move_module_xpm ); + + +TOOL_ACTION PCB_ACTIONS::selectpositionRelativeItem( + "pcbnew.PositionRelative.selectpositionRelativeItem", + AS_GLOBAL, + 0, + "", + "", + nullptr ); + +POSITION_RELATIVE_TOOL::POSITION_RELATIVE_TOOL() : + PCB_TOOL( "pcbnew.PositionRelative" ), m_selectionTool( NULL ) +{ +} + + +void POSITION_RELATIVE_TOOL::Reset( RESET_REASON aReason ) +{ + if( aReason != RUN ) + m_commit.reset( new BOARD_COMMIT( this ) ); +} + + +bool POSITION_RELATIVE_TOOL::Init() +{ + // Find the selection tool, so they can cooperate + m_selectionTool = + static_cast( m_toolMgr->FindTool( "pcbnew.InteractiveSelection" ) ); + + if( !m_selectionTool ) + { + DisplayError( NULL, wxT( "pcbnew.InteractiveSelection tool is not available" ) ); + return false; + } + + + return true; +} + + +int POSITION_RELATIVE_TOOL::PositionRelative( const TOOL_EVENT& aEvent ) +{ + const auto& selection = m_selectionTool->RequestSelection(); + + if( m_selectionTool->CheckLock() == SELECTION_LOCKED ) + return 0; + + if( selection.Empty() ) + return 0; + + + m_position_relative_selection = selection; + + PCB_BASE_FRAME* editFrame = getEditFrame(); + m_position_relative_rotation = 0; + + + if( !m_position_relative_dialog ) + m_position_relative_dialog = new DIALOG_POSITION_RELATIVE( editFrame, + m_toolMgr, + m_position_relative_translation, + m_position_relative_rotation, + m_anchor_position ); + + m_position_relative_dialog->Show( true ); + + return 0; +} + + +static bool selectPRitem( TOOL_MANAGER* aToolMgr, + BOARD_ITEM* m_anchor_item, + const VECTOR2D& aPosition ) +{ + SELECTION_TOOL* selectionTool = aToolMgr->GetTool(); + POSITION_RELATIVE_TOOL* positionRelativeTool = aToolMgr->GetTool(); + + assert( selectionTool ); + assert( positionRelativeTool ); + + aToolMgr->RunAction( PCB_ACTIONS::selectionClear, true ); + aToolMgr->RunAction( PCB_ACTIONS::selectionCursor, true ); + selectionTool->SanitizeSelection(); + + const SELECTION& selection = selectionTool->GetSelection(); + + if( selection.Empty() ) + return true; + + m_anchor_item = static_cast( selection.Front() ); + positionRelativeTool->m_position_relative_dialog->UpdateAchor( m_anchor_item ); + return true; +} + + +BOARD_ITEM* POSITION_RELATIVE_TOOL::GetAnchorItem() +{ + return m_anchor_item; +} + + +int POSITION_RELATIVE_TOOL::RelativeItemSelectionMove( wxPoint anchorPosition, + wxPoint relativePosition, + double rotation ) +{ + VECTOR2I rp = m_position_relative_selection.GetCenter(); + wxPoint rotPoint( rp.x, rp.y ); + wxPoint translation = anchorPosition + relativePosition - rotPoint; + + for( auto item : m_position_relative_selection ) + { + m_commit->Modify( item ); + + static_cast( item )->Rotate( rotPoint, rotation ); + static_cast( item )->Move( translation ); + } + + m_commit->Push( _( "Positon Relative" ) ); + + if( m_position_relative_selection.IsHover() ) + m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true ); + + m_toolMgr->RunAction( PCB_ACTIONS::selectionModified, true ); + return 0; +} + + +int POSITION_RELATIVE_TOOL::SelectPositionRelativeItem( const TOOL_EVENT& aEvent ) +{ + Activate(); + + PICKER_TOOL* picker = m_toolMgr->GetTool(); + assert( picker ); + + picker->SetSnapping( false ); + picker->SetClickHandler( std::bind( selectPRitem, m_toolMgr, m_anchor_item, _1 ) ); + picker->Activate(); + Wait(); + + 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() ); +} diff --git a/pcbnew/tools/position_relative_tool.h b/pcbnew/tools/position_relative_tool.h new file mode 100644 index 0000000000..9e9c696e93 --- /dev/null +++ b/pcbnew/tools/position_relative_tool.h @@ -0,0 +1,115 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013-2015 CERN + * @author Maciej Suminski + * @author Tomasz Wlostowski + * + * 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 + */ + +#ifndef __POSITION_RELATIVE_TOOL_H +#define __POSITION_RELATIVE_TOOL_H + +#include +#include +#include "selection_tool.h" +#include "dialogs/dialog_position_relative.h" +#include "dialogs/dialog_position_relative_base.h" + +class BOARD_COMMIT; +class BOARD_ITEM; +class SELECTION_TOOL; +class DIALOG_POSITION_RELATIVE; + +/** + * Class POSITION_RELATIVE_TOOL + * + * The interactive edit tool. Allows to move, rotate, flip and change properties of items selected + * using the pcbnew.InteractiveSelection tool. + */ + +class POSITION_RELATIVE_TOOL : public PCB_TOOL +{ +public: + POSITION_RELATIVE_TOOL(); + + void Reset( RESET_REASON aReason ); + + /// @copydoc POSITION_RELATIVE_TOOL::Init() + bool Init() override; + + + /** + * Function PositionRelative() + * + * Invokes a dialog box to allow positioning of the item relative to another by an exact amount. + */ + int PositionRelative( const TOOL_EVENT& aEvent ); + + /** + * Function SelectPositionRelativeItem() + * + * Invokes the picker tool to select the item to which the previos selection will be placed relative to. + */ + int SelectPositionRelativeItem( const TOOL_EVENT& aEvent ); + + /** + * Function RelativeItemSelectionMove() + * + * Positions the m_position_relative_selection selection relative to anchorpostion using the given translation and rotation. + * Rotation is around the center of the selection. + */ + int RelativeItemSelectionMove( wxPoint anchorposition, wxPoint translation, double rotation ); + + /** + * Function GetAnchorItem() + * + * Gets the last selected anchor item. + */ + BOARD_ITEM* GetAnchorItem(); + + ///> Sets up handlers for various events. + void SetTransitions() override; + + DIALOG_POSITION_RELATIVE* m_position_relative_dialog; + +private: + ///> Selection tool used for obtaining selected items + SELECTION_TOOL* m_selectionTool; + + + std::unique_ptr m_commit; + + ///> Last anchor item selected by Position Relative To function. + BOARD_ITEM* m_anchor_item; + + ///> Translation for position relative function. + wxPoint m_position_relative_translation; + + ///> Anchor position for positive relative function. + wxPoint m_anchor_position; + + ///> Rotation for positive relative function. + double m_position_relative_rotation; + + ///> Selected that will be moved by Position relative function. + SELECTION m_position_relative_selection; +}; + +#endif diff --git a/pcbnew/tools/tools_common.cpp b/pcbnew/tools/tools_common.cpp index a653ebf24c..0843728612 100644 --- a/pcbnew/tools/tools_common.cpp +++ b/pcbnew/tools/tools_common.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -60,4 +61,5 @@ void PCB_ACTIONS::RegisterAllTools( TOOL_MANAGER* aToolManager ) aToolManager->RegisterTool( new PCB_EDITOR_CONTROL ); aToolManager->RegisterTool( new PLACEMENT_TOOL ); aToolManager->RegisterTool( new MICROWAVE_TOOL ); + aToolManager->RegisterTool( new POSITION_RELATIVE_TOOL ); }