kicad/pcbnew/move-drag_pads.cpp

439 lines
11 KiB
C++
Raw Normal View History

2012-02-19 04:02:19 +00:00
/**
* @file move-drag_pads.cpp
* @brief Edit footprint pads.
*/
#include <fctsys.h>
#include <gr_basic.h>
#include <common.h>
#include <class_drawpanel.h>
#include <confirm.h>
#include <trigo.h>
#include <block_commande.h>
#include <wxBasePcbFrame.h>
#include <macros.h>
#include <pcbcommon.h>
#include <class_board.h>
#include <class_module.h>
#include <pcbnew.h>
#include <drag.h>
#include <protos.h>
static D_PAD* s_CurrentSelectedPad;
static wxPoint Pad_OldPos;
/* Cancel move pad command.
2008-02-23 01:27:21 +00:00
*/
static void Abort_Move_Pad( EDA_DRAW_PANEL* Panel, wxDC* DC )
{
2008-02-23 01:27:21 +00:00
D_PAD* pad = s_CurrentSelectedPad;
Panel->SetMouseCapture( NULL, NULL );
2008-02-23 01:27:21 +00:00
if( pad == NULL )
return;
2008-04-01 05:21:50 +00:00
pad->Draw( Panel, DC, GR_XOR );
pad->ClearFlags();
2012-02-19 04:02:19 +00:00
pad->SetPosition( Pad_OldPos );
2008-04-01 05:21:50 +00:00
pad->Draw( Panel, DC, GR_XOR );
2012-02-19 04:02:19 +00:00
// Pad move in progress: the restore origin.
2008-02-23 01:27:21 +00:00
if( g_Drag_Pistes_On )
{
for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ )
2008-02-23 01:27:21 +00:00
{
TRACK* Track = g_DragSegmentList[ii].m_Segm;
2008-02-23 01:27:21 +00:00
Track->Draw( Panel, DC, GR_XOR );
Track->SetState( IN_EDIT, OFF );
g_DragSegmentList[ii].SetInitialValues();
2008-02-23 01:27:21 +00:00
Track->Draw( Panel, DC, GR_OR );
}
}
EraseDragList();
2008-02-23 01:27:21 +00:00
s_CurrentSelectedPad = NULL;
g_Drag_Pistes_On = false;
}
/* Draw in drag mode when moving a pad.
*/
static void Show_Pad_Move( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition,
bool aErase )
{
2008-02-23 01:27:21 +00:00
TRACK* Track;
BASE_SCREEN* screen = aPanel->GetScreen();
2008-02-23 01:27:21 +00:00
D_PAD* pad = s_CurrentSelectedPad;
if( pad == NULL ) // Should not occur
return;
if( aErase )
pad->Draw( aPanel, aDC, GR_XOR );
2008-04-01 05:21:50 +00:00
2012-02-19 04:02:19 +00:00
pad->SetPosition( screen->GetCrossHairPosition() );
pad->Draw( aPanel, aDC, GR_XOR );
2008-02-23 01:27:21 +00:00
if( !g_Drag_Pistes_On )
return;
for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ )
2008-02-23 01:27:21 +00:00
{
Track = g_DragSegmentList[ii].m_Segm;
if( aErase )
Track->Draw( aPanel, aDC, GR_XOR );
if( g_DragSegmentList[ii].m_Pad_Start )
2008-02-23 01:27:21 +00:00
{
2012-02-19 04:02:19 +00:00
Track->m_Start = pad->GetPosition();
2008-02-23 01:27:21 +00:00
}
if( g_DragSegmentList[ii].m_Pad_End )
2008-02-23 01:27:21 +00:00
{
2012-02-19 04:02:19 +00:00
Track->m_End = pad->GetPosition();
2008-02-23 01:27:21 +00:00
}
Track->Draw( aPanel, aDC, GR_XOR );
2008-02-23 01:27:21 +00:00
}
}
/* Load list of features for default pad selection.
2008-02-23 01:27:21 +00:00
*/
2012-02-19 04:02:19 +00:00
void PCB_BASE_FRAME::Export_Pad_Settings( D_PAD* aPad )
{
2012-02-19 04:02:19 +00:00
if( aPad == NULL )
2008-02-23 01:27:21 +00:00
return;
2012-02-19 04:02:19 +00:00
aPad->DisplayInfo( this );
D_PAD& mp = GetDesignSettings().m_Pad_Master;
2012-02-19 04:02:19 +00:00
mp.SetShape( aPad->GetShape() );
mp.SetAttribute( aPad->GetAttribute() );
mp.SetLayerMask( aPad->GetLayerMask() );
2012-02-19 04:02:19 +00:00
mp.SetOrientation( aPad->GetOrientation() - aPad->GetParent()->GetOrientation() );
mp.SetSize( aPad->GetSize() );
mp.SetDelta( aPad->GetDelta() );
mp.SetOffset( aPad->GetOffset() );
mp.SetDrillSize( aPad->GetDrillSize() );
mp.SetDrillShape( aPad->GetDrillShape() );
}
2012-02-19 04:02:19 +00:00
/* Imports the new values of dimensions of the pad edge by aPad
* - Source: selected values of general characteristics
* - Measurements are modified
* - The position, names, and keys are not.
2008-02-23 01:27:21 +00:00
*/
void PCB_BASE_FRAME::Import_Pad_Settings( D_PAD* aPad, bool aDraw )
{
2008-04-18 13:28:56 +00:00
if( aDraw )
{
aPad->SetFlags( DO_NOT_DRAW );
m_canvas->RefreshDrawingRect( aPad->GetBoundingBox() );
aPad->ClearFlags( DO_NOT_DRAW );
}
2008-04-18 13:28:56 +00:00
2012-02-19 04:02:19 +00:00
D_PAD& mp = GetDesignSettings().m_Pad_Master;
aPad->SetShape( mp.GetShape() );
aPad->SetLayerMask( mp.GetLayerMask() );
aPad->SetAttribute( mp.GetAttribute() );
aPad->SetOrientation( mp.GetOrientation() + aPad->GetParent()->GetOrientation() );
aPad->SetSize( mp.GetSize() );
aPad->SetDelta( wxSize( 0, 0 ) );
aPad->SetOffset( mp.GetOffset() );
aPad->SetDrillSize( mp.GetDrillSize() );
aPad->SetDrillShape( mp.GetDrillShape() );
switch( mp.GetShape() )
2008-02-23 01:27:21 +00:00
{
case PAD_TRAPEZOID:
2012-02-19 04:02:19 +00:00
aPad->SetDelta( mp.GetDelta() );
2008-02-23 01:27:21 +00:00
break;
case PAD_CIRCLE:
2012-02-19 04:02:19 +00:00
// set size.y to size.x
aPad->SetSize( wxSize( aPad->GetSize().x, aPad->GetSize().x ) );
2008-02-23 01:27:21 +00:00
break;
2012-02-19 04:02:19 +00:00
default:
;
2008-02-23 01:27:21 +00:00
}
2012-02-19 04:02:19 +00:00
switch( mp.GetAttribute() )
2008-02-23 01:27:21 +00:00
{
case PAD_SMD:
case PAD_CONN:
2012-02-19 04:02:19 +00:00
aPad->SetDrillSize( wxSize( 0, 0 ) );
aPad->SetOffset( wxPoint( 0, 0 ) );
2008-02-23 01:27:21 +00:00
}
2008-04-18 13:28:56 +00:00
if( aDraw )
m_canvas->RefreshDrawingRect( aPad->GetBoundingBox() );
2012-02-19 04:02:19 +00:00
aPad->GetParent()->m_LastEdit_Time = time( NULL );
}
/* Add a pad on the selected module.
*/
2012-02-19 04:02:19 +00:00
void PCB_BASE_FRAME::AddPad( MODULE* aModule, bool draw )
{
2012-02-19 04:02:19 +00:00
// Last used pad name (pad num)
wxString lastPadName = GetDesignSettings().m_Pad_Master.GetPadName();
2008-02-23 01:27:21 +00:00
m_Pcb->m_Status_Pcb = 0;
2012-02-19 04:02:19 +00:00
aModule->m_LastEdit_Time = time( NULL );
2008-02-23 01:27:21 +00:00
2012-02-19 04:02:19 +00:00
D_PAD* pad = new D_PAD( aModule );
2008-02-23 01:27:21 +00:00
2012-02-19 04:02:19 +00:00
// Add the new pad to end of the module pad list.
aModule->m_Pads.PushBack( pad );
2008-02-23 01:27:21 +00:00
2012-02-19 04:02:19 +00:00
// Update the pad properties.
Import_Pad_Settings( pad, false );
pad->SetNetname( wxEmptyString );
2008-02-23 01:27:21 +00:00
2012-02-19 04:02:19 +00:00
pad->SetPosition( GetScreen()->GetCrossHairPosition() );
2008-02-23 01:27:21 +00:00
// Set the relative pad position
// ( pad position for module orient, 0, and relative to the module position)
2008-02-23 01:27:21 +00:00
2012-02-19 04:02:19 +00:00
wxPoint pos0 = pad->GetPosition() - aModule->GetPosition();
RotatePoint( &pos0, -aModule->GetOrientation() );
pad->SetPos0( pos0 );
// Automatically increment the current pad number.
long num = 0;
int ponder = 1;
while( lastPadName.Len() && lastPadName.Last() >= '0' && lastPadName.Last() <= '9' )
2008-02-23 01:27:21 +00:00
{
num += ( lastPadName.Last() - '0' ) * ponder;
lastPadName.RemoveLast();
2008-02-23 01:27:21 +00:00
ponder *= 10;
}
num++; // Use next number for the new pad
lastPadName << num;
2012-02-19 04:02:19 +00:00
pad->SetPadName( lastPadName );
GetDesignSettings().m_Pad_Master.SetPadName(lastPadName);
2008-02-23 01:27:21 +00:00
2012-02-19 04:02:19 +00:00
aModule->CalculateBoundingBox();
pad->DisplayInfo( this );
if( draw )
2012-02-19 04:02:19 +00:00
m_canvas->RefreshDrawingRect( aModule->GetBoundingBox() );
}
2008-02-23 01:27:21 +00:00
/**
* Function DeletePad
* Delete the pad aPad.
* Refresh the modified screen area
* Refresh modified parameters of the parent module (bounding box, last date)
* @param aPad = the pad to delete
* @param aQuery = true to promt for confirmation, false to delete silently
*/
void PCB_BASE_FRAME::DeletePad( D_PAD* aPad, bool aQuery )
{
2012-02-19 04:02:19 +00:00
MODULE* module;
if( aPad == NULL )
2008-02-23 01:27:21 +00:00
return;
2012-02-19 04:02:19 +00:00
module = (MODULE*) aPad->GetParent();
module->m_LastEdit_Time = time( NULL );
if( aQuery )
{
wxString msg;
msg.Printf( _( "Delete Pad (module %s %s) " ),
2012-02-19 04:02:19 +00:00
GetChars( module->m_Reference->m_Text ),
GetChars( module->m_Value->m_Text ) );
if( !IsOK( this, msg ) )
return;
}
2008-02-23 01:27:21 +00:00
m_Pcb->m_Status_Pcb = 0;
aPad->DeleteStructure();
2012-02-19 04:02:19 +00:00
m_canvas->RefreshDrawingRect( module->GetBoundingBox() );
module->CalculateBoundingBox();
2008-03-18 02:52:49 +00:00
OnModify();
}
2008-02-23 01:27:21 +00:00
2012-02-19 04:02:19 +00:00
// Function to initialize the "move pad" command
void PCB_BASE_FRAME::StartMovePad( D_PAD* aPad, wxDC* DC )
{
2012-02-19 04:02:19 +00:00
if( aPad == NULL )
2008-02-23 01:27:21 +00:00
return;
2012-02-19 04:02:19 +00:00
s_CurrentSelectedPad = aPad;
Pad_OldPos = aPad->GetPosition();
aPad->DisplayInfo( this );
m_canvas->SetMouseCapture( Show_Pad_Move, Abort_Move_Pad );
2012-02-19 04:02:19 +00:00
// Draw the pad (SKETCH mode)
aPad->Draw( m_canvas, DC, GR_XOR );
aPad->SetFlags( IS_MOVED );
aPad->Draw( m_canvas, DC, GR_XOR );
2012-02-19 04:02:19 +00:00
// Build the list of track segments to drag if the command is a drag pad
2008-02-23 01:27:21 +00:00
if( g_Drag_Pistes_On )
2012-02-19 04:02:19 +00:00
Build_1_Pad_SegmentsToDrag( m_canvas, DC, aPad );
2008-02-23 01:27:21 +00:00
else
EraseDragList();
}
2012-02-19 04:02:19 +00:00
// Routine to place a moved pad.
void PCB_BASE_FRAME::PlacePad( D_PAD* aPad, wxDC* DC )
{
int dX, dY;
TRACK* Track;
2008-02-23 01:27:21 +00:00
2012-02-19 04:02:19 +00:00
if( aPad == NULL )
2008-02-23 01:27:21 +00:00
return;
2012-02-19 04:02:19 +00:00
MODULE* module = aPad->GetParent();
ITEM_PICKER picker( NULL, UR_CHANGED );
PICKED_ITEMS_LIST pickList;
2012-02-19 04:02:19 +00:00
// Save dragged track segments in undo list
for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ )
{
Track = g_DragSegmentList[ii].m_Segm;
// Set the old state
if( g_DragSegmentList[ii].m_Pad_Start )
Track->m_Start = Pad_OldPos;
if( g_DragSegmentList[ii].m_Pad_End )
Track->m_End = Pad_OldPos;
2012-02-05 13:02:46 +00:00
picker.SetItem( Track );
pickList.PushItem( picker );
}
2012-02-19 04:02:19 +00:00
// Save old module and old items values
wxPoint pad_curr_position = aPad->GetPosition();
2012-02-19 04:02:19 +00:00
aPad->SetPosition( Pad_OldPos );
if( g_DragSegmentList.size() == 0 )
2012-02-19 04:02:19 +00:00
SaveCopyInUndoList( module, UR_CHANGED );
else
{
2012-02-19 04:02:19 +00:00
picker.SetItem( module );
pickList.PushItem( picker );
SaveCopyInUndoList( pickList, UR_CHANGED );
}
2012-02-19 04:02:19 +00:00
aPad->SetPosition( pad_curr_position );
aPad->Draw( m_canvas, DC, GR_XOR );
2012-02-19 04:02:19 +00:00
// Redraw dragged track segments
for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ )
{
Track = g_DragSegmentList[ii].m_Segm;
// Set the new state
if( g_DragSegmentList[ii].m_Pad_Start )
2012-02-19 04:02:19 +00:00
Track->m_Start = aPad->GetPosition();
if( g_DragSegmentList[ii].m_Pad_End )
2012-02-19 04:02:19 +00:00
Track->m_End = aPad->GetPosition();
Track->SetState( IN_EDIT, OFF );
if( DC )
Track->Draw( m_canvas, DC, GR_OR );
}
2012-02-19 04:02:19 +00:00
// Compute local coordinates (i.e refer to module position and for module orient = 0)
dX = aPad->GetPosition().x - Pad_OldPos.x;
dY = aPad->GetPosition().y - Pad_OldPos.y;
RotatePoint( &dX, &dY, -module->GetOrientation() );
2012-02-19 04:02:19 +00:00
aPad->SetX0( dX + aPad->GetPos0().x );
2012-02-19 04:02:19 +00:00
s_CurrentSelectedPad->SetY0( dY + s_CurrentSelectedPad->GetPos0().y );
aPad->ClearFlags();
if( DC )
2012-02-19 04:02:19 +00:00
aPad->Draw( m_canvas, DC, GR_OR );
2012-02-19 04:02:19 +00:00
module->CalculateBoundingBox();
module->m_LastEdit_Time = time( NULL );
EraseDragList();
2008-02-23 01:27:21 +00:00
OnModify();
m_canvas->SetMouseCapture( NULL, NULL );
m_Pcb->m_Status_Pcb &= ~( LISTE_RATSNEST_ITEM_OK | CONNEXION_OK );
}
2008-02-23 01:27:21 +00:00
2012-02-19 04:02:19 +00:00
// Rotate selected pad 90 degrees.
void PCB_BASE_FRAME::RotatePad( D_PAD* aPad, wxDC* DC )
{
2012-02-19 04:02:19 +00:00
if( aPad == NULL )
2008-02-23 01:27:21 +00:00
return;
2012-02-19 04:02:19 +00:00
MODULE* module = aPad->GetParent();
module->m_LastEdit_Time = time( NULL );
OnModify();
if( DC )
2012-02-19 04:02:19 +00:00
module->Draw( m_canvas, DC, GR_XOR );
wxSize sz = aPad->GetSize();
EXCHG( sz.x, sz.y );
aPad->SetSize( sz );
sz = aPad->GetDrillSize();
EXCHG( sz.x, sz.y );
aPad->SetDrillSize( sz );
wxPoint pt = aPad->GetOffset();
EXCHG( pt.x, pt.y );
aPad->SetOffset( pt );
aPad->SetOffset( wxPoint( aPad->GetOffset().x, -aPad->GetOffset().y ) );
2012-02-19 04:02:19 +00:00
sz = aPad->GetDelta();
EXCHG( sz.x, sz.y );
sz.x = -sz.x;
aPad->SetDelta( sz );
2012-02-19 04:02:19 +00:00
module->CalculateBoundingBox();
aPad->DisplayInfo( this );
if( DC )
2012-02-19 04:02:19 +00:00
module->Draw( m_canvas, DC, GR_OR );
2008-02-23 01:27:21 +00:00
}