kicad/pcbnew/move-drag_pads.cpp

416 lines
10 KiB
C++
Raw Normal View History

/**
* @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();
2008-02-23 01:27:21 +00:00
pad->m_Pos = Pad_OldPos;
2008-04-01 05:21:50 +00:00
pad->Draw( Panel, DC, GR_XOR );
/* 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
pad->m_Pos = 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
{
Track->m_Start = pad->m_Pos;
2008-02-23 01:27:21 +00:00
}
if( g_DragSegmentList[ii].m_Pad_End )
2008-02-23 01:27:21 +00:00
{
Track->m_End = pad->m_Pos;
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
*/
void PCB_BASE_FRAME::Export_Pad_Settings( D_PAD* pt_pad )
{
2008-02-23 01:27:21 +00:00
if( pt_pad == NULL )
return;
pt_pad->DisplayInfo( this );
2008-02-23 01:27:21 +00:00
g_Pad_Master.m_PadShape = pt_pad->m_PadShape;
g_Pad_Master.m_Attribut = pt_pad->m_Attribut;
g_Pad_Master.m_layerMask = pt_pad->m_layerMask;
2008-02-23 01:27:21 +00:00
g_Pad_Master.m_Orient = pt_pad->m_Orient -
( (MODULE*) pt_pad->GetParent() )->m_Orient;
g_Pad_Master.m_Size = pt_pad->m_Size;
2008-02-23 01:27:21 +00:00
g_Pad_Master.m_DeltaSize = pt_pad->m_DeltaSize;
pt_pad->ComputeShapeMaxRadius();
2008-02-23 01:27:21 +00:00
g_Pad_Master.m_Offset = pt_pad->m_Offset;
g_Pad_Master.m_Drill = pt_pad->m_Drill;
g_Pad_Master.m_DrillShape = pt_pad->m_DrillShape;
}
/* Imports the new values of dimensions of the pad edge by pt_pad
* - 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
aPad->m_PadShape = g_Pad_Master.m_PadShape;
aPad->m_layerMask = g_Pad_Master.m_layerMask;
aPad->m_Attribut = g_Pad_Master.m_Attribut;
aPad->m_Orient = g_Pad_Master.m_Orient + ( (MODULE*) aPad->GetParent() )->m_Orient;
aPad->m_Size = g_Pad_Master.m_Size;
aPad->m_DeltaSize = wxSize( 0, 0 );
2008-04-18 13:28:56 +00:00
aPad->m_Offset = g_Pad_Master.m_Offset;
aPad->m_Drill = g_Pad_Master.m_Drill;
aPad->m_DrillShape = g_Pad_Master.m_DrillShape;
2008-02-23 01:27:21 +00:00
switch( g_Pad_Master.m_PadShape )
{
case PAD_TRAPEZOID:
2008-04-18 13:28:56 +00:00
aPad->m_DeltaSize = g_Pad_Master.m_DeltaSize;
2008-02-23 01:27:21 +00:00
break;
case PAD_CIRCLE:
aPad->m_Size.y = aPad->m_Size.x;
2008-02-23 01:27:21 +00:00
break;
}
switch( g_Pad_Master.m_Attribut & 0x7F )
{
case PAD_SMD:
case PAD_CONN:
aPad->m_Drill = wxSize( 0, 0 );
aPad->m_Offset.x = 0;
aPad->m_Offset.y = 0;
2008-02-23 01:27:21 +00:00
}
aPad->ComputeShapeMaxRadius();
2008-02-23 01:27:21 +00:00
2008-04-18 13:28:56 +00:00
if( aDraw )
m_canvas->RefreshDrawingRect( aPad->GetBoundingBox() );
( (MODULE*) aPad->GetParent() )->m_LastEdit_Time = time( NULL );
}
/* Add a pad on the selected module.
*/
void PCB_BASE_FRAME::AddPad( MODULE* Module, bool draw )
{
wxString lastPadName; // Last used pad name (pad num)
2011-12-12 08:37:05 +00:00
lastPadName = g_Pad_Master.GetPadName();
2008-02-23 01:27:21 +00:00
m_Pcb->m_Status_Pcb = 0;
Module->m_LastEdit_Time = time( NULL );
D_PAD* Pad = new D_PAD( Module );
2008-02-23 01:27:21 +00:00
/* Add the new pad to end of the module pad list. */
Module->m_Pads.PushBack( Pad );
2008-02-23 01:27:21 +00:00
/* Update the pad properties. */
2008-04-18 13:28:56 +00:00
Import_Pad_Settings( Pad, false );
Pad->SetNetname( wxEmptyString );
2008-02-23 01:27:21 +00:00
Pad->m_Pos = 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)
Pad->m_Pos0 = Pad->m_Pos - Module->m_Pos;
RotatePoint( &Pad->m_Pos0, -Module->m_Orient );
2008-02-23 01:27:21 +00:00
/* 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;
Pad->SetPadName( lastPadName );
g_Pad_Master.SetPadName(lastPadName);
2008-02-23 01:27:21 +00:00
Module->CalculateBoundingBox();
Pad->DisplayInfo( this );
if( draw )
m_canvas->RefreshDrawingRect( Module->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 )
{
2008-02-23 01:27:21 +00:00
MODULE* Module;
if( aPad == NULL )
2008-02-23 01:27:21 +00:00
return;
Module = (MODULE*) aPad->GetParent();
2008-02-23 01:27:21 +00:00
Module->m_LastEdit_Time = time( NULL );
if( aQuery )
{
wxString msg;
msg.Printf( _( "Delete Pad (module %s %s) " ),
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();
m_canvas->RefreshDrawingRect( Module->GetBoundingBox() );
Module->CalculateBoundingBox();
2008-03-18 02:52:49 +00:00
OnModify();
}
2008-02-23 01:27:21 +00:00
/* Function to initialize the "move pad" command */
void PCB_BASE_FRAME::StartMovePad( D_PAD* Pad, wxDC* DC )
{
2008-02-23 01:27:21 +00:00
if( Pad == NULL )
return;
2008-02-23 01:27:21 +00:00
s_CurrentSelectedPad = Pad;
Pad_OldPos = Pad->m_Pos;
Pad->DisplayInfo( this );
m_canvas->SetMouseCapture( Show_Pad_Move, Abort_Move_Pad );
2008-02-23 01:27:21 +00:00
/* Draw the pad (SKETCH mode) */
Pad->Draw( m_canvas, DC, GR_XOR );
Pad->SetFlags( IS_MOVED );
Pad->Draw( m_canvas, DC, GR_XOR );
2008-02-23 01:27:21 +00:00
/* Build the list of track segments to drag if the command is a drag pad*/
if( g_Drag_Pistes_On )
Build_1_Pad_SegmentsToDrag( m_canvas, DC, Pad );
2008-02-23 01:27:21 +00:00
else
EraseDragList();
}
/* Routine to place a moved pad. */
void PCB_BASE_FRAME::PlacePad( D_PAD* Pad, wxDC* DC )
{
int dX, dY;
TRACK* Track;
MODULE* Module;
2008-02-23 01:27:21 +00:00
if( Pad == NULL )
return;
Module = (MODULE*) Pad->GetParent();
ITEM_PICKER picker( NULL, UR_CHANGED );
PICKED_ITEMS_LIST pickList;
/* 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;
picker.m_PickedItem = Track;
pickList.PushItem( picker );
}
/* Save old module and old items values */
wxPoint pad_curr_position = Pad->m_Pos;
Pad->m_Pos = Pad_OldPos;
if( g_DragSegmentList.size() == 0 )
SaveCopyInUndoList( Module, UR_CHANGED );
else
{
picker.m_PickedItem = Module;
pickList.PushItem( picker );
SaveCopyInUndoList( pickList, UR_CHANGED );
}
Pad->m_Pos = pad_curr_position;
Pad->Draw( m_canvas, DC, GR_XOR );
/* 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 )
Track->m_Start = Pad->m_Pos;
if( g_DragSegmentList[ii].m_Pad_End )
Track->m_End = Pad->m_Pos;
Track->SetState( IN_EDIT, OFF );
if( DC )
Track->Draw( m_canvas, DC, GR_OR );
}
/* Compute local coordinates (i.e refer to Module position and for Module orient = 0) */
dX = Pad->m_Pos.x - Pad_OldPos.x;
dY = Pad->m_Pos.y - Pad_OldPos.y;
2008-02-23 01:27:21 +00:00
RotatePoint( &dX, &dY, -Module->m_Orient );
Pad->m_Pos0.x += dX;
s_CurrentSelectedPad->m_Pos0.y += dY;
Pad->ClearFlags();
if( DC )
Pad->Draw( m_canvas, DC, GR_OR );
Module->CalculateBoundingBox();
2008-02-23 01:27:21 +00:00
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
/* Rotate selected pad 90 degrees.
*/
void PCB_BASE_FRAME::RotatePad( D_PAD* Pad, wxDC* DC )
{
2008-02-23 01:27:21 +00:00
MODULE* Module;
2008-02-23 01:27:21 +00:00
if( Pad == NULL )
return;
Module = (MODULE*) Pad->GetParent();
2008-02-23 01:27:21 +00:00
Module->m_LastEdit_Time = time( NULL );
OnModify();
if( DC )
Module->Draw( m_canvas, DC, GR_XOR );
EXCHG( Pad->m_Size.x, Pad->m_Size.y );
EXCHG( Pad->m_Drill.x, Pad->m_Drill.y );
EXCHG( Pad->m_Offset.x, Pad->m_Offset.y );
Pad->m_Offset.y = -Pad->m_Offset.y;
EXCHG( Pad->m_DeltaSize.x, Pad->m_DeltaSize.y );
Pad->m_DeltaSize.x = -Pad->m_DeltaSize.x;
Module->CalculateBoundingBox();
Pad->DisplayInfo( this );
if( DC )
Module->Draw( m_canvas, DC, GR_OR );
2008-02-23 01:27:21 +00:00
}