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) 2014 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||||
* Copyright (C) 2004-2014 KiCad Developers, see change_log.txt for contributors.
|
* 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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* 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& GetOrigin() const { return m_Pos; }
|
||||||
const wxPoint& GetPosition() 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 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 GetWidth() const { return m_Size.x; }
|
||||||
int GetHeight() const { return m_Size.y; }
|
int GetHeight() const { return m_Size.y; }
|
||||||
|
|
|
@ -124,6 +124,13 @@ public:
|
||||||
|
|
||||||
const BOX2I ViewBBox() const override;
|
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
|
EDA_ITEM* operator[]( const int index ) const
|
||||||
{
|
{
|
||||||
if( index < 0 || (unsigned int) index >= m_items.size() )
|
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 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||||
* Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net>
|
* Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net>
|
||||||
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
|
* 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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -188,17 +189,49 @@ bool FOOTPRINT_EDIT_FRAME::HandleBlockEnd( wxDC* DC )
|
||||||
|
|
||||||
if( itemsCount )
|
if( itemsCount )
|
||||||
{
|
{
|
||||||
wxPoint translation;
|
MOVE_PARAMETERS params;
|
||||||
double rotation = 0;
|
params.allowOverride = false;
|
||||||
|
|
||||||
|
DIALOG_MOVE_EXACT dialog( this, params );
|
||||||
|
|
||||||
DIALOG_MOVE_EXACT dialog( this, translation, rotation );
|
|
||||||
int ret = dialog.ShowModal();
|
int ret = dialog.ShowModal();
|
||||||
|
|
||||||
if( ret == wxID_OK )
|
if( ret == wxID_OK )
|
||||||
{
|
{
|
||||||
SaveCopyInUndoList( currentModule, UR_CHANGED );
|
SaveCopyInUndoList( currentModule, UR_CHANGED );
|
||||||
const wxPoint blockCentre = GetScreen()->m_BlockLocate.Centre();
|
wxPoint blockCentre = GetScreen()->m_BlockLocate.Centre();
|
||||||
MoveMarkedItemsExactly( currentModule, blockCentre, translation, rotation );
|
|
||||||
|
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;
|
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
|
unsigned MODULE::GetPadCount( INCLUDE_NPTH_T aIncludeNPTH ) const
|
||||||
{
|
{
|
||||||
if( aIncludeNPTH )
|
if( aIncludeNPTH )
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
* 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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* 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* GetPad( const wxPoint& aPosition, LSET aLayerMask = LSET::AllLayersMask() );
|
||||||
|
|
||||||
|
D_PAD* GetTopLeftPad();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GetPadCount
|
* GetPadCount
|
||||||
* returns the number of pads.
|
* returns the number of pads.
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2014 John Beard, john.j.beard@gmail.com
|
* Copyright (C) 2014 John Beard, john.j.beard@gmail.com
|
||||||
* Copyright (C) 1992-2014 KiCad Developers, see AUTHORS.txt for contributors.
|
* 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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* 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::MOVE_EXACT_OPTIONS DIALOG_MOVE_EXACT::m_options;
|
||||||
|
|
||||||
|
|
||||||
DIALOG_MOVE_EXACT::DIALOG_MOVE_EXACT( PCB_BASE_FRAME* aParent,
|
DIALOG_MOVE_EXACT::DIALOG_MOVE_EXACT(PCB_BASE_FRAME *aParent, MOVE_PARAMETERS &aParams ) :
|
||||||
wxPoint& translation, double& rotation ):
|
|
||||||
DIALOG_MOVE_EXACT_BASE( aParent ),
|
DIALOG_MOVE_EXACT_BASE( aParent ),
|
||||||
m_translation( translation ),
|
m_translation( aParams.translation ),
|
||||||
m_rotation( rotation )
|
m_rotation( aParams.rotation ),
|
||||||
|
m_origin( aParams.origin ),
|
||||||
|
m_anchor( aParams.anchor ),
|
||||||
|
m_allowOverride( aParams.allowOverride ),
|
||||||
|
m_editingFootprint( aParams.editingFootprint )
|
||||||
{
|
{
|
||||||
// set the unit labels
|
// set the unit labels
|
||||||
m_xUnit->SetLabelText( GetAbbreviatedUnitsLabel( g_UserUnit ) );
|
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_xEntry->SetValue( wxString::FromDouble( m_options.entry1 ) );
|
||||||
m_yEntry->SetValue( wxString::FromDouble( m_options.entry2 ) );
|
m_yEntry->SetValue( wxString::FromDouble( m_options.entry2 ) );
|
||||||
m_rotEntry->SetValue( wxString::FromDouble( m_options.entryRotation ) );
|
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() );
|
updateDlgTexts( m_polarCoords->IsChecked() );
|
||||||
|
|
||||||
m_stdButtonsOK->SetDefault();
|
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 )
|
void DIALOG_MOVE_EXACT::updateDlgTexts( bool aPolar )
|
||||||
{
|
{
|
||||||
if( aPolar )
|
if( aPolar )
|
||||||
|
@ -174,6 +272,16 @@ void DIALOG_MOVE_EXACT::OnClear( wxCommandEvent& event )
|
||||||
void DIALOG_MOVE_EXACT::OnOkClick( wxCommandEvent& event )
|
void DIALOG_MOVE_EXACT::OnOkClick( wxCommandEvent& event )
|
||||||
{
|
{
|
||||||
m_rotation = DoubleValueFromString( DEGREES, m_rotEntry->GetValue() );
|
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
|
// for the output, we only deliver a Cartesian vector
|
||||||
bool ok = GetTranslationInIU( m_translation, m_polarCoords->IsChecked() );
|
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.entry1 = DoubleValueFromString( UNSCALED_UNITS, m_xEntry->GetValue() );
|
||||||
m_options.entry2 = DoubleValueFromString( UNSCALED_UNITS, m_yEntry->GetValue() );
|
m_options.entry2 = DoubleValueFromString( UNSCALED_UNITS, m_yEntry->GetValue() );
|
||||||
m_options.entryRotation = DoubleValueFromString( UNSCALED_UNITS, m_rotEntry->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();
|
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) 2014 John Beard, john.j.beard@gmail.com
|
||||||
* Copyright (C) 1992-2014 KiCad Developers, see AUTHORS.txt for contributors.
|
* 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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -29,17 +30,49 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <dialog_move_exact_base.h>
|
#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
|
class DIALOG_MOVE_EXACT : public DIALOG_MOVE_EXACT_BASE
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
wxPoint& m_translation;
|
wxPoint& m_translation;
|
||||||
double& m_rotation;
|
double& m_rotation;
|
||||||
|
MOVE_EXACT_ORIGIN& m_origin;
|
||||||
|
MOVE_EXACT_ANCHOR& m_anchor;
|
||||||
|
bool& m_allowOverride;
|
||||||
|
bool& m_editingFootprint;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructor and destructor
|
// Constructor and destructor
|
||||||
DIALOG_MOVE_EXACT( PCB_BASE_FRAME* aParent, wxPoint& translation,
|
DIALOG_MOVE_EXACT(PCB_BASE_FRAME *aParent, MOVE_PARAMETERS &aParams );
|
||||||
double& rotation );
|
|
||||||
~DIALOG_MOVE_EXACT();
|
~DIALOG_MOVE_EXACT();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -52,6 +85,9 @@ private:
|
||||||
void OnPolarChanged( wxCommandEvent& event ) override;
|
void OnPolarChanged( wxCommandEvent& event ) override;
|
||||||
void OnClear( wxCommandEvent& event ) override;
|
void OnClear( wxCommandEvent& event ) override;
|
||||||
|
|
||||||
|
void OnOriginChanged( wxCommandEvent& event ) override;
|
||||||
|
void OnOverrideChanged( wxCommandEvent& event ) override;
|
||||||
|
|
||||||
void OnOkClick( wxCommandEvent& event ) override;
|
void OnOkClick( wxCommandEvent& event ) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -78,16 +114,22 @@ private:
|
||||||
*/
|
*/
|
||||||
struct MOVE_EXACT_OPTIONS
|
struct MOVE_EXACT_OPTIONS
|
||||||
{
|
{
|
||||||
bool polarCoords;
|
bool polarCoords;
|
||||||
double entry1;
|
double entry1;
|
||||||
double entry2;
|
double entry2;
|
||||||
double entryRotation;
|
double entryRotation;
|
||||||
|
MOVE_EXACT_ORIGIN origin;
|
||||||
|
MOVE_EXACT_ANCHOR anchor;
|
||||||
|
bool overrideAnchor;
|
||||||
|
|
||||||
MOVE_EXACT_OPTIONS():
|
MOVE_EXACT_OPTIONS():
|
||||||
polarCoords(false),
|
polarCoords( false ),
|
||||||
entry1(0),
|
entry1( 0 ),
|
||||||
entry2(0),
|
entry2( 0 ),
|
||||||
entryRotation(0)
|
entryRotation( 0 ),
|
||||||
|
origin( RELATIVE_TO_CURRENT_POSITION ),
|
||||||
|
anchor( ANCHOR_FROM_LIBRARY ),
|
||||||
|
overrideAnchor( false )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -97,3 +139,4 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __DIALOG_MOVE_EXACT__
|
#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/
|
// http://www.wxformbuilder.org/
|
||||||
//
|
//
|
||||||
// PLEASE DO "NOT" EDIT THIS FILE!
|
// 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 );
|
this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize );
|
||||||
|
|
||||||
wxBoxSizer* bMainSizer;
|
|
||||||
bMainSizer = new wxBoxSizer( wxVERTICAL );
|
bMainSizer = new wxBoxSizer( wxVERTICAL );
|
||||||
|
|
||||||
m_polarCoords = new wxCheckBox( this, wxID_ANY, _("Use polar coordinates"), wxDefaultPosition, wxDefaultSize, 0 );
|
m_polarCoords = new wxCheckBox( this, wxID_ANY, _("Use polar coordinates"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
bMainSizer->Add( m_polarCoords, 0, wxALL|wxEXPAND, 5 );
|
bMainSizer->Add( m_polarCoords, 0, wxALL|wxEXPAND, 5 );
|
||||||
|
|
||||||
wxFlexGridSizer* fgSizer2;
|
wxBoxSizer* bMiddleSizer;
|
||||||
fgSizer2 = new wxFlexGridSizer( 0, 4, 0, 0 );
|
bMiddleSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||||
fgSizer2->AddGrowableCol( 1 );
|
|
||||||
fgSizer2->SetFlexibleDirection( wxBOTH );
|
wxFlexGridSizer* fgInputSizer;
|
||||||
fgSizer2->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
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 = new wxStaticText( this, wxID_ANY, _("x:"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
|
||||||
m_xLabel->Wrap( -1 );
|
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 );
|
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 = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
m_xUnit->Wrap( -1 );
|
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 );
|
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 = new wxStaticText( this, wxID_ANY, _("y:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
m_yLabel->Wrap( -1 );
|
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 );
|
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 = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
m_yUnit->Wrap( -1 );
|
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 );
|
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 = new wxStaticText( this, wxID_ANY, _("Item rotation:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
m_rotLabel->Wrap( -1 );
|
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 );
|
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 = new wxStaticText( this, wxID_ANY, _("deg"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
m_rotUnit->Wrap( -1 );
|
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 );
|
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 );
|
m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||||
bMainSizer->Add( m_staticline1, 0, wxEXPAND | wxALL, 5 );
|
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->SetSizer( bMainSizer );
|
||||||
this->Layout();
|
this->Layout();
|
||||||
bMainSizer->Fit( this );
|
|
||||||
|
|
||||||
// Connect Events
|
// Connect Events
|
||||||
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_MOVE_EXACT_BASE::OnClose ) );
|
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_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_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_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 );
|
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_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_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_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 );
|
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/
|
// http://www.wxformbuilder.org/
|
||||||
//
|
//
|
||||||
// PLEASE DO "NOT" EDIT THIS FILE!
|
// PLEASE DO "NOT" EDIT THIS FILE!
|
||||||
|
@ -24,6 +24,8 @@ class DIALOG_SHIM;
|
||||||
#include <wx/textctrl.h>
|
#include <wx/textctrl.h>
|
||||||
#include <wx/button.h>
|
#include <wx/button.h>
|
||||||
#include <wx/sizer.h>
|
#include <wx/sizer.h>
|
||||||
|
#include <wx/radiobox.h>
|
||||||
|
#include <wx/choice.h>
|
||||||
#include <wx/statline.h>
|
#include <wx/statline.h>
|
||||||
#include <wx/dialog.h>
|
#include <wx/dialog.h>
|
||||||
|
|
||||||
|
@ -38,6 +40,7 @@ class DIALOG_MOVE_EXACT_BASE : public DIALOG_SHIM
|
||||||
private:
|
private:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
wxBoxSizer* bMainSizer;
|
||||||
wxCheckBox* m_polarCoords;
|
wxCheckBox* m_polarCoords;
|
||||||
wxStaticText* m_xLabel;
|
wxStaticText* m_xLabel;
|
||||||
wxTextCtrl* m_xEntry;
|
wxTextCtrl* m_xEntry;
|
||||||
|
@ -51,6 +54,10 @@ class DIALOG_MOVE_EXACT_BASE : public DIALOG_SHIM
|
||||||
wxTextCtrl* m_rotEntry;
|
wxTextCtrl* m_rotEntry;
|
||||||
wxStaticText* m_rotUnit;
|
wxStaticText* m_rotUnit;
|
||||||
wxButton* m_clearRot;
|
wxButton* m_clearRot;
|
||||||
|
wxRadioBox* m_originChooser;
|
||||||
|
wxBoxSizer* bAnchorSizer;
|
||||||
|
wxCheckBox* m_cbOverride;
|
||||||
|
wxChoice* m_anchorChoice;
|
||||||
wxStaticLine* m_staticline1;
|
wxStaticLine* m_staticline1;
|
||||||
wxStdDialogButtonSizer* m_stdButtons;
|
wxStdDialogButtonSizer* m_stdButtons;
|
||||||
wxButton* m_stdButtonsOK;
|
wxButton* m_stdButtonsOK;
|
||||||
|
@ -61,12 +68,14 @@ class DIALOG_MOVE_EXACT_BASE : public DIALOG_SHIM
|
||||||
virtual void OnPolarChanged( wxCommandEvent& event ) { event.Skip(); }
|
virtual void OnPolarChanged( wxCommandEvent& event ) { event.Skip(); }
|
||||||
virtual void OnTextFocusLost( wxFocusEvent& event ) { event.Skip(); }
|
virtual void OnTextFocusLost( wxFocusEvent& event ) { event.Skip(); }
|
||||||
virtual void OnClear( wxCommandEvent& 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(); }
|
virtual void OnOkClick( wxCommandEvent& event ) { event.Skip(); }
|
||||||
|
|
||||||
|
|
||||||
public:
|
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();
|
~DIALOG_MOVE_EXACT_BASE();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
* Copyright (C) 2015 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
* Copyright (C) 2015 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||||
* Copyright (C) 2015 Wayne Stambaugh <stambaughw@verizon.net>
|
* Copyright (C) 2015 Wayne Stambaugh <stambaughw@verizon.net>
|
||||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
* 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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* 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()
|
void PCB_EDIT_FRAME::moveExact()
|
||||||
{
|
{
|
||||||
wxPoint translation;
|
MOVE_PARAMETERS params;
|
||||||
double rotation = 0;
|
|
||||||
|
|
||||||
DIALOG_MOVE_EXACT dialog( this, translation, rotation );
|
DIALOG_MOVE_EXACT dialog( this, params );
|
||||||
int ret = dialog.ShowModal();
|
int ret = dialog.ShowModal();
|
||||||
|
|
||||||
if( ret == wxID_OK )
|
if( ret == wxID_OK )
|
||||||
|
@ -1555,8 +1555,66 @@ void PCB_EDIT_FRAME::moveExact()
|
||||||
// Could be moved or rotated
|
// Could be moved or rotated
|
||||||
SaveCopyInUndoList( itemToSave, UR_CHANGED );
|
SaveCopyInUndoList( itemToSave, UR_CHANGED );
|
||||||
|
|
||||||
item->Move( translation );
|
// begin with the default anchor
|
||||||
item->Rotate( item->GetPosition(), rotation );
|
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();
|
m_canvas->Refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
* 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) 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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* 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()
|
void FOOTPRINT_EDIT_FRAME::moveExact()
|
||||||
{
|
{
|
||||||
wxPoint translation;
|
MOVE_PARAMETERS params;
|
||||||
double rotation = 0;
|
params.allowOverride = false;
|
||||||
|
params.editingFootprint = true;
|
||||||
|
|
||||||
DIALOG_MOVE_EXACT dialog( this, translation, rotation );
|
DIALOG_MOVE_EXACT dialog( this, params );
|
||||||
int ret = dialog.ShowModal();
|
int ret = dialog.ShowModal();
|
||||||
|
|
||||||
if( ret == wxID_OK )
|
if( ret == wxID_OK )
|
||||||
|
@ -849,8 +851,39 @@ void FOOTPRINT_EDIT_FRAME::moveExact()
|
||||||
|
|
||||||
BOARD_ITEM* item = GetScreen()->GetCurItem();
|
BOARD_ITEM* item = GetScreen()->GetCurItem();
|
||||||
|
|
||||||
item->Move( translation );
|
wxPoint anchorPoint = item->GetPosition();
|
||||||
item->Rotate( item->GetPosition(), rotation );
|
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();
|
m_canvas->Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -880,16 +913,15 @@ void FOOTPRINT_EDIT_FRAME::Transform( MODULE* module, int transform )
|
||||||
|
|
||||||
case ID_MODEDIT_MODULE_MOVE_EXACT:
|
case ID_MODEDIT_MODULE_MOVE_EXACT:
|
||||||
{
|
{
|
||||||
wxPoint translation;
|
MOVE_PARAMETERS params;
|
||||||
double rotation = 0;
|
|
||||||
|
|
||||||
DIALOG_MOVE_EXACT dialog( this, translation, rotation );
|
DIALOG_MOVE_EXACT dialog( this, params );
|
||||||
int ret = dialog.ShowModal();
|
int ret = dialog.ShowModal();
|
||||||
|
|
||||||
if( ret == wxID_OK )
|
if( ret == wxID_OK )
|
||||||
{
|
{
|
||||||
MoveMarkedItemsExactly( module, wxPoint(0, 0),
|
MoveMarkedItemsExactly( module, wxPoint( 0, 0 ),
|
||||||
translation, rotation, true );
|
params.translation, params.rotation, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* Copyright (C) 2013-2015 CERN
|
* Copyright (C) 2013-2015 CERN
|
||||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||||
* @author Tomasz Wlostowski <tomasz.wlostowski@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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -221,6 +222,8 @@ bool EDIT_TOOL::Init()
|
||||||
|
|
||||||
|
|
||||||
bool EDIT_TOOL::invokeInlineRouter()
|
bool EDIT_TOOL::invokeInlineRouter()
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
TRACK* track = uniqueSelected<TRACK>();
|
TRACK* track = uniqueSelected<TRACK>();
|
||||||
VIA* via = uniqueSelected<VIA>();
|
VIA* via = uniqueSelected<VIA>();
|
||||||
|
@ -707,13 +710,12 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent )
|
||||||
if( selection.Empty() )
|
if( selection.Empty() )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
wxPoint translation;
|
|
||||||
double rotation = 0;
|
|
||||||
|
|
||||||
PCB_BASE_FRAME* editFrame = getEditFrame<PCB_BASE_FRAME>();
|
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();
|
int ret = dialog.ShowModal();
|
||||||
|
|
||||||
if( ret == wxID_OK )
|
if( ret == wxID_OK )
|
||||||
|
@ -721,11 +723,97 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent )
|
||||||
VECTOR2I rp = selection.GetCenter();
|
VECTOR2I rp = selection.GetCenter();
|
||||||
wxPoint rotPoint( rp.x, rp.y );
|
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 )
|
for( auto item : selection )
|
||||||
{
|
{
|
||||||
m_commit->Modify( item );
|
m_commit->Modify( item );
|
||||||
static_cast<BOARD_ITEM*>( item )->Move( translation );
|
static_cast<BOARD_ITEM*>( item )->Move( finalMoveVector );
|
||||||
static_cast<BOARD_ITEM*>( item )->Rotate( rotPoint, rotation );
|
static_cast<BOARD_ITEM*>( item )->Rotate( rotPoint, params.rotation );
|
||||||
|
|
||||||
|
if( !m_dragging )
|
||||||
|
getView()->Update( item );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_commit->Push( _( "Move exact" ) );
|
m_commit->Push( _( "Move exact" ) );
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* Copyright (C) 2013-2017 CERN
|
* Copyright (C) 2013-2017 CERN
|
||||||
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||||
* @author Maciej Suminski <maciej.suminski@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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* 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
|
// TODO(JE) Only works for BOARD_ITEM
|
||||||
|
VECTOR2I SELECTION::GetPosition() const
|
||||||
|
{
|
||||||
|
return static_cast<VECTOR2I>( GetBoundingBox().GetPosition() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
VECTOR2I SELECTION::GetCenter() const
|
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
|
* Copyright (C) 2013-2017 CERN
|
||||||
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||||
* @author Maciej Suminski <maciej.suminski@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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
|
Loading…
Reference in New Issue