kicad/pcbnew/move-drag_pads.cpp

412 lines
10 KiB
C++

/************************/
/* Edit footprint pads. */
/************************/
#include "fctsys.h"
#include "gr_basic.h"
#include "common.h"
#include "class_drawpanel.h"
#include "confirm.h"
#include "pcbnew.h"
#include "trigo.h"
#include "block_commande.h"
#include "drag.h"
#include "protos.h"
static D_PAD* s_CurrentSelectedPad;
static wxPoint Pad_OldPos;
/* Cancel move pad command.
*/
static void Exit_Move_Pad( WinEDA_DrawPanel* Panel, wxDC* DC )
{
D_PAD* pad = s_CurrentSelectedPad;
Panel->ManageCurseur = NULL;
Panel->ForceCloseManageCurseur = NULL;
if( pad == NULL )
return;
pad->Draw( Panel, DC, GR_XOR );
pad->m_Flags = 0;
pad->m_Pos = Pad_OldPos;
pad->Draw( Panel, DC, GR_XOR );
/* Pad move in progress: the restore origin. */
if( g_Drag_Pistes_On )
{
for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ )
{
TRACK* Track = g_DragSegmentList[ii].m_Segm;
Track->Draw( Panel, DC, GR_XOR );
Track->SetState( EDIT, OFF );
g_DragSegmentList[ii].SetInitialValues();
Track->Draw( Panel, DC, GR_OR );
}
}
EraseDragList();
s_CurrentSelectedPad = NULL;
g_Drag_Pistes_On = FALSE;
}
/* Draw in drag mode when moving a pad.
*/
static void Show_Pad_Move( WinEDA_DrawPanel* panel, wxDC* DC, bool erase )
{
TRACK* Track;
BASE_SCREEN* screen = panel->GetScreen();
D_PAD* pad = s_CurrentSelectedPad;
if( erase )
pad->Draw( panel, DC, GR_XOR );
pad->m_Pos = screen->m_Curseur;
pad->Draw( panel, DC, GR_XOR );
if( !g_Drag_Pistes_On )
return;
for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ )
{
Track = g_DragSegmentList[ii].m_Segm;
if( erase )
Track->Draw( panel, DC, GR_XOR );
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->Draw( panel, DC, GR_XOR );
}
}
/* Load list of features for default pad selection.
*/
void WinEDA_BasePcbFrame::Export_Pad_Settings( D_PAD* pt_pad )
{
MODULE* Module;
if( pt_pad == NULL )
return;
Module = (MODULE*) pt_pad->GetParent();
pt_pad->DisplayInfo( this );
g_Pad_Master.m_PadShape = pt_pad->m_PadShape;
g_Pad_Master.m_Attribut = pt_pad->m_Attribut;
g_Pad_Master.m_Masque_Layer = pt_pad->m_Masque_Layer;
g_Pad_Master.m_Orient = pt_pad->m_Orient -
( (MODULE*) pt_pad->GetParent() )->m_Orient;
g_Pad_Master.m_Size = pt_pad->m_Size;
g_Pad_Master.m_DeltaSize = pt_pad->m_DeltaSize;
pt_pad->ComputeShapeMaxRadius();
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.
*/
void WinEDA_BasePcbFrame::Import_Pad_Settings( D_PAD* aPad, bool aDraw )
{
if( aDraw )
{
aPad->m_Flags |= DO_NOT_DRAW;
DrawPanel->PostDirtyRect( aPad->GetBoundingBox() );
aPad->m_Flags &= ~DO_NOT_DRAW;
}
aPad->m_PadShape = g_Pad_Master.m_PadShape;
aPad->m_Masque_Layer = g_Pad_Master.m_Masque_Layer;
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 );
aPad->m_Offset = g_Pad_Master.m_Offset;
aPad->m_Drill = g_Pad_Master.m_Drill;
aPad->m_DrillShape = g_Pad_Master.m_DrillShape;
switch( g_Pad_Master.m_PadShape )
{
case PAD_TRAPEZOID:
aPad->m_DeltaSize = g_Pad_Master.m_DeltaSize;
break;
case PAD_CIRCLE:
aPad->m_Size.y = aPad->m_Size.x;
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;
}
aPad->ComputeShapeMaxRadius();
if( aDraw )
DrawPanel->PostDirtyRect( aPad->GetBoundingBox() );
( (MODULE*) aPad->GetParent() )->m_LastEdit_Time = time( NULL );
}
/* Add a pad on the selected module.
*/
void WinEDA_BasePcbFrame::AddPad( MODULE* Module, bool draw )
{
D_PAD* Pad;
int rX, rY;
m_Pcb->m_Status_Pcb = 0;
Module->m_LastEdit_Time = time( NULL );
Pad = new D_PAD( Module );
/* Add the new pad to end of the module pad list. */
Module->m_Pads.PushBack( Pad );
/* Update the pad properties. */
Import_Pad_Settings( Pad, false );
Pad->SetNetname( wxEmptyString );
Pad->m_Pos = GetScreen()->m_Curseur;
rX = Pad->m_Pos.x - Module->m_Pos.x;
rY = Pad->m_Pos.y - Module->m_Pos.y;
RotatePoint( &rX, &rY, -Module->m_Orient );
Pad->m_Pos0.x = rX;
Pad->m_Pos0.y = rY;
/* Automatically increment the current pad number and name. */
long num = 0;
int ponder = 1;
while( g_Current_PadName.Len() && g_Current_PadName.Last() >= '0'
&& g_Current_PadName.Last() <= '9' )
{
num += ( g_Current_PadName.Last() - '0' ) * ponder;
g_Current_PadName.RemoveLast();
ponder *= 10;
}
num++;
g_Current_PadName << num;
Pad->SetPadName( g_Current_PadName );
Module->Set_Rectangle_Encadrement();
Pad->DisplayInfo( this );
if( draw )
DrawPanel->PostDirtyRect( Module->GetBoundingBox() );
}
/** 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 WinEDA_BasePcbFrame::DeletePad( D_PAD* aPad, bool aQuery )
{
MODULE* Module;
if( aPad == NULL )
return;
Module = (MODULE*) aPad->GetParent();
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;
}
m_Pcb->m_Status_Pcb = 0;
aPad->DeleteStructure();
DrawPanel->PostDirtyRect( Module->GetBoundingBox() );
Module->Set_Rectangle_Encadrement();
OnModify();
}
/* Function to initialize the "move pad" command */
void WinEDA_BasePcbFrame::StartMovePad( D_PAD* Pad, wxDC* DC )
{
MODULE* Module;
if( Pad == NULL )
return;
Module = (MODULE*) Pad->GetParent();
s_CurrentSelectedPad = Pad;
Pad_OldPos = Pad->m_Pos;
Pad->DisplayInfo( this );
DrawPanel->ManageCurseur = Show_Pad_Move;
DrawPanel->ForceCloseManageCurseur = Exit_Move_Pad;
/* Draw the pad (SKETCH mode) */
Pad->Draw( DrawPanel, DC, GR_XOR );
Pad->m_Flags |= IS_MOVED;
Pad->Draw( DrawPanel, DC, GR_XOR );
/* Build the list of track segments to drag if the command is a drag pad*/
if( g_Drag_Pistes_On )
Build_1_Pad_SegmentsToDrag( DrawPanel, DC, Pad );
else
EraseDragList();
}
/* Routine to place a moved pad. */
void WinEDA_BasePcbFrame::PlacePad( D_PAD* Pad, wxDC* DC )
{
int dX, dY;
TRACK* Track;
MODULE* Module;
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
wxPoint t_start = Track->m_Start;
wxPoint t_end = Track->m_End;
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( DrawPanel, 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( EDIT, OFF );
if( DC )
Track->Draw( DrawPanel, 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;
RotatePoint( &dX, &dY, -Module->m_Orient );
Pad->m_Pos0.x += dX;
s_CurrentSelectedPad->m_Pos0.y += dY;
Pad->m_Flags = 0;
if( DC )
Pad->Draw( DrawPanel, DC, GR_OR );
Module->Set_Rectangle_Encadrement();
Module->m_LastEdit_Time = time( NULL );
EraseDragList();
OnModify();
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
m_Pcb->m_Status_Pcb &= ~( LISTE_RATSNEST_ITEM_OK | CONNEXION_OK );
}
/* Rotate selected pad 90 degrees.
*/
void WinEDA_BasePcbFrame::RotatePad( D_PAD* Pad, wxDC* DC )
{
MODULE* Module;
if( Pad == NULL )
return;
Module = (MODULE*) Pad->GetParent();
Module->m_LastEdit_Time = time( NULL );
OnModify();
if( DC )
Module->Draw( DrawPanel, 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->Set_Rectangle_Encadrement();
Pad->DisplayInfo( this );
if( DC )
Module->Draw( DrawPanel, DC, GR_OR );
}