/************************/ /* 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 Abort_Move_Pad( EDA_DRAW_PANEL* Panel, wxDC* DC ) { D_PAD* pad = s_CurrentSelectedPad; Panel->SetMouseCapture( NULL, 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( IN_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( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, bool aErase ) { TRACK* Track; BASE_SCREEN* screen = aPanel->GetScreen(); D_PAD* pad = s_CurrentSelectedPad; if( pad == NULL ) // Should not occur return; if( aErase ) pad->Draw( aPanel, aDC, GR_XOR ); pad->m_Pos = screen->GetCrossHairPosition(); pad->Draw( aPanel, aDC, GR_XOR ); if( !g_Drag_Pistes_On ) return; for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) { Track = g_DragSegmentList[ii].m_Segm; if( aErase ) Track->Draw( aPanel, aDC, 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( aPanel, aDC, GR_XOR ); } } /* Load list of features for default pad selection. */ void PCB_BASE_FRAME::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 PCB_BASE_FRAME::Import_Pad_Settings( D_PAD* aPad, bool aDraw ) { if( aDraw ) { aPad->m_Flags |= DO_NOT_DRAW; DrawPanel->RefreshDrawingRect( 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->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) lastPadName = g_Pad_Master.ReturnStringPadName(); m_Pcb->m_Status_Pcb = 0; Module->m_LastEdit_Time = time( NULL ); D_PAD* 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()->GetCrossHairPosition(); // 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 ); /* Automatically increment the current pad number. */ long num = 0; int ponder = 1; while( lastPadName.Len() && lastPadName.Last() >= '0' && lastPadName.Last() <= '9' ) { num += ( lastPadName.Last() - '0' ) * ponder; lastPadName.RemoveLast(); ponder *= 10; } num++; // Use next number for the new pad lastPadName << num; Pad->SetPadName( lastPadName ); g_Pad_Master.SetPadName(lastPadName); Module->Set_Rectangle_Encadrement(); Pad->DisplayInfo( this ); if( draw ) DrawPanel->RefreshDrawingRect( 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 PCB_BASE_FRAME::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->RefreshDrawingRect( Module->GetBoundingBox() ); Module->Set_Rectangle_Encadrement(); OnModify(); } /* Function to initialize the "move pad" command */ void PCB_BASE_FRAME::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->SetMouseCapture( Show_Pad_Move, Abort_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 PCB_BASE_FRAME::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( IN_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->SetMouseCapture( NULL, NULL ); m_Pcb->m_Status_Pcb &= ~( LISTE_RATSNEST_ITEM_OK | CONNEXION_OK ); } /* Rotate selected pad 90 degrees. */ void PCB_BASE_FRAME::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 ); }