void FOOTPRINT_VIEWER_FRAME::SelectCurrentFootprint( wxCommandEvent& event ) { PCB_EDIT_FRAME* parent = (PCB_EDIT_FRAME*) GetParent(); wxString libname = m_libraryName + wxT( "." ) + LegacyFootprintLibPathExtension; MODULE* oldmodule = GetBoard()->m_Modules; MODULE* module = LoadModuleFromLibrary( libname, parent->FootprintLibs(), false ); if( module ) { module->SetPosition( wxPoint( 0, 0 ) ); // Only one footprint allowed: remove the previous footprint (if exists) if( oldmodule ) { GetBoard()->Remove( oldmodule ); delete oldmodule; } m_footprintName = FROM_UTF8( module->GetFPID().GetFootprintName().c_str() ); module->ClearFlags(); SetCurItem( NULL ); Zoom_Automatique( false ); m_canvas->Refresh(); Update3D_Frame(); m_footprintList->SetStringSelection( m_footprintName ); } }
/** * Abort text move in progress. * * If a text is selected, its initial coordinates are regenerated. */ static void AbortMoveTextModule( EDA_DRAW_PANEL* Panel, wxDC* DC ) { BASE_SCREEN* screen = Panel->GetScreen(); TEXTE_MODULE* Text = static_cast<TEXTE_MODULE*>( screen->GetCurItem() ); MODULE* Module; Panel->SetMouseCapture( NULL, NULL ); if( Text == NULL ) return; Module = static_cast<MODULE*>( Text->GetParent() ); Text->DrawUmbilical( Panel, DC, GR_XOR, -MoveVector ); Text->Draw( Panel, DC, GR_XOR, MoveVector ); // If the text was moved (the move does not change internal data) // it could be rotated while moving. So set old value for orientation if( Text->IsMoving() ) Text->SetTextAngle( TextInitialOrientation ); // Redraw the text Panel->RefreshDrawingRect( Text->GetBoundingBox() ); // leave it at (0,0) so we can use it Rotate when not moving. MoveVector.x = MoveVector.y = 0; Text->ClearFlags(); Module->ClearFlags(); screen->SetCurItem( NULL ); }
void PCB_EDIT_FRAME::Block_Delete() { OnModify(); SetCurItem( NULL ); PICKED_ITEMS_LIST* itemsList = &GetScreen()->m_BlockLocate.GetItems(); itemsList->m_Status = UR_DELETED; // unlink items and clear flags for( unsigned ii = 0; ii < itemsList->GetCount(); ii++ ) { BOARD_ITEM* item = (BOARD_ITEM*) itemsList->GetPickedItem( ii ); itemsList->SetPickedItemStatus( UR_DELETED, ii ); GetBoard()->GetConnectivity()->Remove( item ); switch( item->Type() ) { case PCB_MODULE_T: { MODULE* module = (MODULE*) item; module->ClearFlags(); module->UnLink(); m_Pcb->m_Status_Pcb = 0; } break; case PCB_ZONE_AREA_T: // a zone area m_Pcb->Remove( item ); break; case PCB_LINE_T: // a segment not on copper layers case PCB_TEXT_T: // a text on a layer case PCB_TRACE_T: // a track segment (segment on a copper layer) case PCB_VIA_T: // a via (like track segment on a copper layer) case PCB_DIMENSION_T: // a dimension (graphic item) case PCB_TARGET_T: // a target (graphic item) item->UnLink(); break; // These items are deleted, but not put in undo list case PCB_MARKER_T: // a marker used to show something case PCB_ZONE_T: // SEG_ZONE items are now deprecated item->UnLink(); itemsList->RemovePicker( ii ); ii--; item->DeleteStructure(); break; default: wxMessageBox( wxT( "PCB_EDIT_FRAME::Block_Delete( ) error: unexpected type" ) ); break; } } SaveCopyInUndoList( *itemsList, UR_DELETED ); Compile_Ratsnest( NULL, true ); m_canvas->Refresh( true ); }
bool FOOTPRINT_EDIT_FRAME::Load_Module_From_BOARD( MODULE* aModule ) { MODULE* newModule; PCB_EDIT_FRAME* frame = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB, false ); if( frame == NULL ) // happens if no board editor opened return false; if( aModule == NULL ) { if( ! frame->GetBoard() || ! frame->GetBoard()->m_Modules ) return false; aModule = SelectFootprint( frame->GetBoard() ); } if( aModule == NULL ) return false; SetCurItem( NULL ); Clear_Pcb( false ); GetBoard()->m_Status_Pcb = 0; newModule = new MODULE( *aModule ); newModule->SetParent( GetBoard() ); newModule->SetLink( aModule->GetTimeStamp() ); aModule = newModule; GetBoard()->Add( newModule ); newModule->ClearFlags(); // Clear references to net info, because the footprint editor // does know any thing about nets handled by the current edited board. // Morever the main board can change or the net info relative to this main board // can change while editing this footprint in the footprint editor for( D_PAD* pad = newModule->Pads(); pad; pad = pad->Next() ) pad->SetNetCode( NETINFO_LIST::UNCONNECTED ); SetCrossHairPosition( wxPoint( 0, 0 ) ); PlaceModule( newModule, NULL ); // Put it on FRONT layer, // because this is the default in ModEdit, and in libs if( newModule->GetLayer() != LAYER_N_FRONT ) newModule->Flip( newModule->GetPosition() ); // Put it in orientation 0, // because this is the default orientation in ModEdit, and in libs Rotate_Module( NULL, newModule, 0, false ); GetScreen()->ClrModify(); Zoom_Automatique( false ); return true; }
void PCB_BASE_FRAME::PlaceTexteModule( TEXTE_MODULE* Text, wxDC* DC ) { if( Text != NULL ) { m_canvas->RefreshDrawingRect( Text->GetBoundingBox() ); Text->DrawUmbilical( m_canvas, DC, GR_XOR, -MoveVector ); // Update the coordinates for anchor. MODULE* Module = static_cast<MODULE*>( Text->GetParent() ); if( Module ) { // Prepare undo command (a rotation can be made while moving) double tmp = Text->GetTextAngle(); Text->SetTextAngle( TextInitialOrientation ); if( IsType( FRAME_PCB ) ) SaveCopyInUndoList( Module, UR_CHANGED ); else SaveCopyInUndoList( Module, UR_CHANGED ); Text->SetTextAngle( tmp ); // Set the new position for text. Text->SetTextPos( GetCrossHairPosition() ); wxPoint textRelPos = Text->GetTextPos() - Module->GetPosition(); RotatePoint( &textRelPos, -Module->GetOrientation() ); Text->SetPos0( textRelPos ); Text->ClearFlags(); Module->ClearFlags(); Module->SetLastEditTime(); OnModify(); // Redraw text. m_canvas->RefreshDrawingRect( Text->GetBoundingBox() ); } else { Text->SetTextPos( GetCrossHairPosition() ); } } // leave it at (0,0) so we can use it Rotate when not moving. MoveVector.x = MoveVector.y = 0; m_canvas->SetMouseCapture( NULL, NULL ); }
void EDIT_TOOL::remove( BOARD_ITEM* aItem ) { BOARD* board = getModel<BOARD>(); switch( aItem->Type() ) { case PCB_MODULE_T: { MODULE* module = static_cast<MODULE*>( aItem ); module->ClearFlags(); module->RunOnChildren( boost::bind( &KIGFX::VIEW::Remove, getView(), _1 ) ); // Module itself is deleted after the switch scope is finished // list of pads is rebuild by BOARD::BuildListOfNets() // Clear flags to indicate, that the ratsnest, list of nets & pads are not valid anymore board->m_Status_Pcb = 0; } break; // Default removal procedure case PCB_MODULE_TEXT_T: { TEXTE_MODULE* text = static_cast<TEXTE_MODULE*>( aItem ); switch( text->GetType() ) { case TEXTE_MODULE::TEXT_is_REFERENCE: DisplayError( getEditFrame<PCB_BASE_FRAME>(), _( "Cannot delete component reference." ) ); return; case TEXTE_MODULE::TEXT_is_VALUE: DisplayError( getEditFrame<PCB_BASE_FRAME>(), _( "Cannot delete component value." ) ); return; case TEXTE_MODULE::TEXT_is_DIVERS: // suppress warnings break; } if( m_editModules ) { MODULE* module = static_cast<MODULE*>( aItem->GetParent() ); module->SetLastEditTime(); board->m_Status_Pcb = 0; // it is done in the legacy view aItem->DeleteStructure(); } return; } case PCB_PAD_T: case PCB_MODULE_EDGE_T: { MODULE* module = static_cast<MODULE*>( aItem->GetParent() ); module->SetLastEditTime(); board->m_Status_Pcb = 0; // it is done in the legacy view if( !m_editModules ) { getView()->Remove( aItem ); board->Remove( aItem ); } aItem->DeleteStructure(); return; } case PCB_LINE_T: // a segment not on copper layers case PCB_TEXT_T: // a text on a layer case PCB_TRACE_T: // a track segment (segment on a copper layer) case PCB_VIA_T: // a via (like track segment on a copper layer) case PCB_DIMENSION_T: // a dimension (graphic item) case PCB_TARGET_T: // a target (graphic item) case PCB_MARKER_T: // a marker used to show something case PCB_ZONE_T: // SEG_ZONE items are now deprecated case PCB_ZONE_AREA_T: break; default: // other types do not need to (or should not) be handled assert( false ); return; } getView()->Remove( aItem ); board->Remove( aItem ); }
/* * Function GlobalChange_PadSettings * Function to change pad caracteristics for the given footprint * or alls footprints which look like the given footprint * aPad is the pattern. The given footprint is the parent of this pad * aSameFootprints: if true, make changes on all identical footprints * aPadShapeFilter: if true, make changes only on pads having the same shape as aPad * aPadOrientFilter: if true, make changes only on pads having the same orientation as aPad * aPadLayerFilter: if true, make changes only on pads having the same layers as aPad * aRedraw: if true: redraws the footprint * aSaveForUndo: if true: create an entry in the Undo/Redo list * (usually: true in Schematic editor, false in Module editor) */ void PCB_BASE_FRAME::GlobalChange_PadSettings( D_PAD* aPad, bool aSameFootprints, bool aPadShapeFilter, bool aPadOrientFilter, bool aPadLayerFilter, bool aRedraw, bool aSaveForUndo ) { if( aPad == NULL ) aPad = &GetDesignSettings().m_Pad_Master; MODULE* module = aPad->GetParent(); if( module == NULL ) { DisplayError( this, wxT( "Global_Import_Pad_Settings() Error: NULL module" ) ); return; } // Search and copy the name of library reference. MODULE* Module_Ref = module; double pad_orient = aPad->GetOrientation() - Module_Ref->GetOrientation(); // Prepare an undo list: if( aSaveForUndo ) { PICKED_ITEMS_LIST itemsList; for( module = m_Pcb->m_Modules; module; module = module->Next() ) { if( !aSameFootprints && (module != Module_Ref) ) continue; if( module->GetFPID() != Module_Ref->GetFPID() ) continue; bool saveMe = false; for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) { // Filters changes prohibited. if( aPadShapeFilter && ( pad->GetShape() != aPad->GetShape() ) ) continue; double currpad_orient = pad->GetOrientation() - module->GetOrientation(); if( aPadOrientFilter && ( currpad_orient != pad_orient ) ) continue; if( aPadLayerFilter && pad->GetLayerSet() != aPad->GetLayerSet() ) continue; saveMe = true; } if( saveMe ) { ITEM_PICKER itemWrapper( module, UR_CHANGED ); itemsList.PushItem( itemWrapper ); } } SaveCopyInUndoList( itemsList, UR_CHANGED ); } // Update the current module and same others modules if requested. for( module = m_Pcb->m_Modules; module; module = module->Next() ) { if( !aSameFootprints && (module != Module_Ref) ) continue; if( module->GetFPID() != Module_Ref->GetFPID() ) continue; // Erase module on screen if( aRedraw ) { module->SetFlags( DO_NOT_DRAW ); m_canvas->RefreshDrawingRect( module->GetBoundingBox() ); module->ClearFlags( DO_NOT_DRAW ); } for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) { // Filters changes prohibited. if( aPadShapeFilter && ( pad->GetShape() != aPad->GetShape() ) ) continue; if( aPadOrientFilter && (pad->GetOrientation() - module->GetOrientation()) != pad_orient ) continue; if( aPadLayerFilter ) { if( pad->GetLayerSet() != aPad->GetLayerSet() ) continue; else m_Pcb->m_Status_Pcb &= ~( LISTE_RATSNEST_ITEM_OK | CONNEXION_OK); } // Change characteristics: pad->SetAttribute( aPad->GetAttribute() ); pad->SetShape( aPad->GetShape() ); pad->SetLayerSet( aPad->GetLayerSet() ); pad->SetSize( aPad->GetSize() ); pad->SetDelta( aPad->GetDelta() ); pad->SetOffset( aPad->GetOffset() ); pad->SetDrillSize( aPad->GetDrillSize() ); pad->SetDrillShape( aPad->GetDrillShape() ); pad->SetOrientation( pad_orient + module->GetOrientation() ); // copy also local mask margins, because these parameters usually depend on // pad sizes and layers pad->SetLocalSolderMaskMargin( aPad->GetLocalSolderMaskMargin() ); pad->SetLocalSolderPasteMargin( aPad->GetLocalSolderPasteMargin() ); pad->SetLocalSolderPasteMarginRatio( aPad->GetLocalSolderPasteMarginRatio() ); if( pad->GetShape() != PAD_TRAPEZOID ) { pad->SetDelta( wxSize( 0, 0 ) ); } if( pad->GetShape() == PAD_CIRCLE ) { // Ensure pad size.y = pad size.x int size = pad->GetSize().x; pad->SetSize( wxSize( size, size ) ); } switch( pad->GetAttribute() ) { case PAD_SMD: case PAD_CONN: pad->SetDrillSize( wxSize( 0, 0 ) ); pad->SetOffset( wxPoint( 0, 0 ) ); break; default: break; } } module->CalculateBoundingBox(); if( aRedraw ) m_canvas->RefreshDrawingRect( module->GetBoundingBox() ); } OnModify(); }
bool FOOTPRINT_EDIT_FRAME::Load_Module_From_BOARD( MODULE* aModule ) { MODULE* newModule; PCB_EDIT_FRAME* frame = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB, false ); if( frame == NULL ) // happens if no board editor opened return false; if( aModule == NULL ) { if( ! frame->GetBoard() || ! frame->GetBoard()->m_Modules ) return false; aModule = SelectFootprint( frame->GetBoard() ); } if( aModule == NULL ) return false; SetCurItem( NULL ); Clear_Pcb( false ); GetBoard()->m_Status_Pcb = 0; newModule = new MODULE( *aModule ); newModule->SetParent( GetBoard() ); newModule->SetLink( aModule->GetTimeStamp() ); aModule = newModule; newModule->ClearFlags(); newModule->RunOnChildren( boost::bind( &clearModuleItemFlags, _1 ) ); GetBoard()->Add( newModule ); // Clear references to any net info, because the footprint editor // does know any thing about nets handled by the current edited board. // Morever we do not want to save any reference to an unknown net when // saving the footprint in lib cache // so we force the ORPHANED dummy net info for all pads newModule->ClearAllNets(); SetCrossHairPosition( wxPoint( 0, 0 ) ); PlaceModule( newModule, NULL ); newModule->SetPosition( wxPoint( 0, 0 ) ); // cursor in GAL may not be initialized at the moment // Put it on FRONT layer, // because this is the default in ModEdit, and in libs if( newModule->GetLayer() != F_Cu ) newModule->Flip( newModule->GetPosition() ); // Put it in orientation 0, // because this is the default orientation in ModEdit, and in libs Rotate_Module( NULL, newModule, 0, false ); GetScreen()->ClrModify(); Zoom_Automatique( false ); if( IsGalCanvasActive() ) updateView(); return true; }
void FOOTPRINT_EDIT_FRAME::OnLeftClick( wxDC* DC, const wxPoint& MousePos ) { BOARD_ITEM* item = GetCurItem(); m_canvas->CrossHairOff( DC ); if( GetToolId() == ID_NO_TOOL_SELECTED ) { if( item && item->GetFlags() ) // Move item command in progress { switch( item->Type() ) { case PCB_MODULE_TEXT_T: PlaceTexteModule( (TEXTE_MODULE*) item, DC ); break; case PCB_MODULE_EDGE_T: SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); Place_EdgeMod( (EDGE_MODULE*) item ); break; case PCB_PAD_T: PlacePad( (D_PAD*) item, DC ); break; default: { wxString msg; msg.Printf( wxT( "WinEDA_ModEditFrame::OnLeftClick err:Struct %d, m_Flag %X" ), item->Type(), item->GetFlags() ); DisplayError( this, msg ); item->ClearFlags(); break; } } } else { if( !wxGetKeyState( WXK_SHIFT ) && !wxGetKeyState( WXK_ALT ) && !wxGetKeyState( WXK_CONTROL ) ) item = ModeditLocateAndDisplay(); SetCurItem( item ); } } item = GetCurItem(); bool no_item_edited = item == NULL || item->GetFlags() == 0; switch( GetToolId() ) { case ID_NO_TOOL_SELECTED: break; case ID_MODEDIT_CIRCLE_TOOL: case ID_MODEDIT_ARC_TOOL: case ID_MODEDIT_LINE_TOOL: if( no_item_edited ) { STROKE_T shape = S_SEGMENT; if( GetToolId() == ID_MODEDIT_CIRCLE_TOOL ) shape = S_CIRCLE; if( GetToolId() == ID_MODEDIT_ARC_TOOL ) shape = S_ARC; SetCurItem( Begin_Edge_Module( (EDGE_MODULE*) NULL, DC, shape ) ); } else if( item->IsNew() ) { if( ( (EDGE_MODULE*) item )->GetShape() == S_CIRCLE ) { End_Edge_Module( (EDGE_MODULE*) item ); SetCurItem( NULL ); m_canvas->Refresh(); } else if( ( (EDGE_MODULE*) item )->GetShape() == S_ARC ) { End_Edge_Module( (EDGE_MODULE*) item ); SetCurItem( NULL ); m_canvas->Refresh(); } else if( ( (EDGE_MODULE*) item )->GetShape() == S_SEGMENT ) { SetCurItem( Begin_Edge_Module( (EDGE_MODULE*) item, DC, S_SEGMENT ) ); } else { DisplayError( this, wxT( "ProcessCommand error: item flags error" ) ); } } break; case ID_MODEDIT_DELETE_TOOL: if( ! no_item_edited ) // Item in edit, cannot delete it break; item = ModeditLocateAndDisplay(); if( item->Type() != PCB_MODULE_T ) // Cannot delete the module itself { SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); RemoveStruct( item ); SetCurItem( NULL ); } break; case ID_MODEDIT_ANCHOR_TOOL: { MODULE* module = GetBoard()->m_Modules; if( module == NULL // No module loaded || (module->GetFlags() != 0) ) break; module->ClearFlags(); SaveCopyInUndoList( module, UR_MODEDIT ); Place_Ancre( module ); // set the new relatives internal coordinates of items RedrawScreen( wxPoint( 0, 0 ), true ); // Replace the module in position 0, to recalculate absolutes coordinates of items module->SetPosition( wxPoint( 0, 0 ) ); SetToolID( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor(), wxEmptyString ); SetCurItem( NULL ); m_canvas->Refresh(); } break; case ID_MODEDIT_PLACE_GRID_COORD: m_canvas->DrawGridAxis( DC, GR_XOR ); GetScreen()->m_GridOrigin = GetScreen()->GetCrossHairPosition(); m_canvas->DrawGridAxis( DC, GR_COPY ); GetScreen()->SetModify(); break; case ID_MODEDIT_TEXT_TOOL: if( GetBoard()->m_Modules == NULL ) break; SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); CreateTextModule( GetBoard()->m_Modules, DC ); break; case ID_MODEDIT_PAD_TOOL: if( GetBoard()->m_Modules ) { SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); AddPad( GetBoard()->m_Modules, true ); } break; default: DisplayError( this, wxT( "FOOTPRINT_EDIT_FRAME::ProcessCommand error" ) ); SetToolID( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor(), wxEmptyString ); } m_canvas->CrossHairOn( DC ); }
MODULE* PCB_EDIT_FRAME::Genere_Self( wxDC* DC ) { D_PAD* pad; int ll; wxString msg; m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); m_canvas->SetMouseCapture( NULL, NULL ); if( Self_On == 0 ) { DisplayError( this, wxT( "Starting point not init.." ) ); return NULL; } Self_On = 0; Mself.m_End = GetCrossHairPosition(); wxPoint pt = Mself.m_End - Mself.m_Start; int min_len = KiROUND( EuclideanNorm( pt ) ); Mself.lng = min_len; // Enter the desired length. msg = StringFromValue( g_UserUnit, Mself.lng ); wxTextEntryDialog dlg( this, _( "Length:" ), _( "Length" ), msg ); if( dlg.ShowModal() != wxID_OK ) return NULL; // canceled by user msg = dlg.GetValue(); Mself.lng = ValueFromString( g_UserUnit, msg ); // Control values (ii = minimum length) if( Mself.lng < min_len ) { DisplayError( this, _( "Requested length < minimum length" ) ); return NULL; } // Calculate the elements. Mself.m_Width = GetBoard()->GetCurrentTrackWidth(); std::vector <wxPoint> buffer; ll = BuildCornersList_S_Shape( buffer, Mself.m_Start, Mself.m_End, Mself.lng, Mself.m_Width ); if( !ll ) { DisplayError( this, _( "Requested length too large" ) ); return NULL; } // Generate module. MODULE* module; module = Create_1_Module( wxEmptyString ); if( module == NULL ) return NULL; // here the module is already in the BOARD, Create_1_Module() does that. module->SetFPID( FPID( std::string( "MuSelf" ) ) ); module->SetAttributes( MOD_VIRTUAL | MOD_CMS ); module->ClearFlags(); module->SetPosition( Mself.m_End ); // Generate segments for( unsigned jj = 1; jj < buffer.size(); jj++ ) { EDGE_MODULE* PtSegm; PtSegm = new EDGE_MODULE( module ); PtSegm->SetStart( buffer[jj - 1] ); PtSegm->SetEnd( buffer[jj] ); PtSegm->SetWidth( Mself.m_Width ); PtSegm->SetLayer( module->GetLayer() ); PtSegm->SetShape( S_SEGMENT ); PtSegm->SetStart0( PtSegm->GetStart() - module->GetPosition() ); PtSegm->SetEnd0( PtSegm->GetEnd() - module->GetPosition() ); module->GraphicalItems().PushBack( PtSegm ); } // Place a pad on each end of coil. pad = new D_PAD( module ); module->Pads().PushFront( pad ); pad->SetPadName( wxT( "1" ) ); pad->SetPosition( Mself.m_End ); pad->SetPos0( pad->GetPosition() - module->GetPosition() ); pad->SetSize( wxSize( Mself.m_Width, Mself.m_Width ) ); pad->SetLayerMask( GetLayerMask( module->GetLayer() ) ); pad->SetAttribute( PAD_SMD ); pad->SetShape( PAD_CIRCLE ); D_PAD* newpad = new D_PAD( *pad ); module->Pads().Insert( newpad, pad->Next() ); pad = newpad; pad->SetPadName( wxT( "2" ) ); pad->SetPosition( Mself.m_Start ); pad->SetPos0( pad->GetPosition() - module->GetPosition() ); // Modify text positions. SetMsgPanel( module ); wxPoint refPos( ( Mself.m_Start.x + Mself.m_End.x ) / 2, ( Mself.m_Start.y + Mself.m_End.y ) / 2 ); wxPoint valPos = refPos; refPos.y -= module->Reference().GetSize().y; module->Reference().SetTextPosition( refPos ); valPos.y += module->Value().GetSize().y; module->Value().SetTextPosition( valPos ); module->Reference().SetPos0( module->Reference().GetTextPosition() - module->GetPosition() ); module->Value().SetPos0( module->Value().GetTextPosition() - module->GetPosition() ); module->CalculateBoundingBox(); module->Draw( m_canvas, DC, GR_OR ); return module; }
void BOARD_COMMIT::Push( const wxString& aMessage ) { // Objects potentially interested in changes: PICKED_ITEMS_LIST undoList; KIGFX::VIEW* view = m_toolMgr->GetView(); BOARD* board = (BOARD*) m_toolMgr->GetModel(); PCB_BASE_FRAME* frame = (PCB_BASE_FRAME*) m_toolMgr->GetEditFrame(); RN_DATA* ratsnest = board->GetRatsnest(); std::set<EDA_ITEM*> savedModules; if( Empty() ) return; for( COMMIT_LINE& ent : m_changes ) { int changeType = ent.m_type & CHT_TYPE; int changeFlags = ent.m_type & CHT_FLAGS; BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( ent.m_item ); // Module items need to be saved in the undo buffer before modification if( m_editModules ) { // Be sure that we are storing a module if( ent.m_item->Type() != PCB_MODULE_T ) ent.m_item = ent.m_item->GetParent(); // We have not saved the module yet, so let's create an entry if( savedModules.count( ent.m_item ) == 0 ) { if( !ent.m_copy ) { assert( changeType != CHT_MODIFY ); // too late to make a copy.. ent.m_copy = ent.m_item->Clone(); } assert( ent.m_item->Type() == PCB_MODULE_T ); assert( ent.m_copy->Type() == PCB_MODULE_T ); ITEM_PICKER itemWrapper( ent.m_item, UR_CHANGED ); itemWrapper.SetLink( ent.m_copy ); undoList.PushItem( itemWrapper ); frame->SaveCopyInUndoList( undoList, UR_CHANGED ); savedModules.insert( ent.m_item ); static_cast<MODULE*>( ent.m_item )->SetLastEditTime(); } } switch( changeType ) { case CHT_ADD: { if( !m_editModules ) { undoList.PushItem( ITEM_PICKER( boardItem, UR_NEW ) ); if( !( changeFlags & CHT_DONE ) ) board->Add( boardItem ); //ratsnest->Add( boardItem ); // TODO currently done by BOARD::Add() if( boardItem->Type() == PCB_MODULE_T ) { MODULE* mod = static_cast<MODULE*>( boardItem ); mod->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, view, _1 ) ); } } else { // modules inside modules are not supported yet assert( boardItem->Type() != PCB_MODULE_T ); if( !( changeFlags & CHT_DONE ) ) board->m_Modules->Add( boardItem ); } view->Add( boardItem ); break; } case CHT_REMOVE: { if( !m_editModules ) { undoList.PushItem( ITEM_PICKER( boardItem, UR_DELETED ) ); } switch( boardItem->Type() ) { // Module items case PCB_PAD_T: case PCB_MODULE_EDGE_T: case PCB_MODULE_TEXT_T: { // Do not allow footprint text removal when not editing a module if( !m_editModules ) break; bool remove = true; if( boardItem->Type() == PCB_MODULE_TEXT_T ) { TEXTE_MODULE* text = static_cast<TEXTE_MODULE*>( boardItem ); switch( text->GetType() ) { case TEXTE_MODULE::TEXT_is_REFERENCE: //DisplayError( frame, _( "Cannot delete component reference." ) ); remove = false; break; case TEXTE_MODULE::TEXT_is_VALUE: //DisplayError( frame, _( "Cannot delete component value." ) ); remove = false; break; case TEXTE_MODULE::TEXT_is_DIVERS: // suppress warnings break; default: assert( false ); break; } } if( remove ) { view->Remove( boardItem ); if( !( changeFlags & CHT_DONE ) ) { MODULE* module = static_cast<MODULE*>( boardItem->GetParent() ); assert( module && module->Type() == PCB_MODULE_T ); module->Delete( boardItem ); } board->m_Status_Pcb = 0; // it is done in the legacy view (ratsnest perhaps?) } break; } // Board items case PCB_LINE_T: // a segment not on copper layers case PCB_TEXT_T: // a text on a layer case PCB_TRACE_T: // a track segment (segment on a copper layer) case PCB_VIA_T: // a via (like track segment on a copper layer) case PCB_DIMENSION_T: // a dimension (graphic item) case PCB_TARGET_T: // a target (graphic item) case PCB_MARKER_T: // a marker used to show something case PCB_ZONE_T: // SEG_ZONE items are now deprecated case PCB_ZONE_AREA_T: view->Remove( boardItem ); if( !( changeFlags & CHT_DONE ) ) board->Remove( boardItem ); //ratsnest->Remove( boardItem ); // currently done by BOARD::Remove() break; case PCB_MODULE_T: { // There are no modules inside a module yet assert( !m_editModules ); MODULE* module = static_cast<MODULE*>( boardItem ); module->ClearFlags(); module->RunOnChildren( boost::bind( &KIGFX::VIEW::Remove, view, _1 ) ); view->Remove( module ); if( !( changeFlags & CHT_DONE ) ) board->Remove( module ); // Clear flags to indicate, that the ratsnest, list of nets & pads are not valid anymore board->m_Status_Pcb = 0; } break; default: // other types do not need to (or should not) be handled assert( false ); break; } break; } case CHT_MODIFY: { if( !m_editModules ) { ITEM_PICKER itemWrapper( boardItem, UR_CHANGED ); assert( ent.m_copy ); itemWrapper.SetLink( ent.m_copy ); undoList.PushItem( itemWrapper ); } boardItem->ViewUpdate( KIGFX::VIEW_ITEM::ALL ); ratsnest->Update( boardItem ); break; } default: assert( false ); break; } } if( !m_editModules ) frame->SaveCopyInUndoList( undoList, UR_UNSPECIFIED ); frame->OnModify(); ratsnest->Recalculate(); clear(); }
/* * Function DoPushPadProperties * Function to change pad properties for the given footprint or all identical footprints * aPad is the pattern. The given footprint is the parent of this pad * aSameFootprints: if true, make changes on all identical footprints * aPadShapeFilter: if true, make changes only on pads having the same shape as aPad * aPadOrientFilter: if true, make changes only on pads having the same orientation as aPad * aPadLayerFilter: if true, make changes only on pads having the same layers as aPad * aSaveForUndo: if true: create an entry in the Undo/Redo list * (usually: true in Schematic editor, false in Module editor) */ void PCB_BASE_FRAME::DoPushPadProperties( D_PAD* aPad, bool aSameFootprints, bool aPadShapeFilter, bool aPadOrientFilter, bool aPadLayerFilter, bool aSaveForUndo ) { MODULE* Module_Ref = aPad->GetParent(); double pad_orient = aPad->GetOrientation() - Module_Ref->GetOrientation(); // Prepare an undo list: if( aSaveForUndo ) { PICKED_ITEMS_LIST itemsList; if( aSameFootprints ) { for( MODULE* module = m_Pcb->m_Modules; module; module = module->Next() ) { if( module->GetFPID() == Module_Ref->GetFPID() ) { ITEM_PICKER itemWrapper( module, UR_CHANGED ); itemsList.PushItem( itemWrapper ); } } } else { ITEM_PICKER itemWrapper( Module_Ref, UR_CHANGED ); itemsList.PushItem( itemWrapper ); } SaveCopyInUndoList( itemsList, UR_CHANGED ); } // Update the current module and same others modules if requested. for( MODULE* module = m_Pcb->m_Modules; module; module = module->Next() ) { if( !aSameFootprints && (module != Module_Ref) ) continue; if( module->GetFPID() != Module_Ref->GetFPID() ) continue; // Erase module on screen module->SetFlags( DO_NOT_DRAW ); m_canvas->RefreshDrawingRect( module->GetBoundingBox() ); module->ClearFlags( DO_NOT_DRAW ); for( D_PAD* pad = module->PadsList(); pad; pad = pad->Next() ) { if( aPadShapeFilter && ( pad->GetShape() != aPad->GetShape() ) ) continue; double currpad_orient = pad->GetOrientation() - module->GetOrientation(); if( aPadOrientFilter && ( currpad_orient != pad_orient ) ) continue; if( aPadLayerFilter && ( pad->GetLayerSet() != aPad->GetLayerSet() ) ) continue; // Do not copy pad to itself, it can create issues with custom pad primitives. if( pad == aPad ) continue; pad->ImportSettingsFromMaster( *aPad ); } module->CalculateBoundingBox(); m_canvas->RefreshDrawingRect( module->GetBoundingBox() ); } OnModify(); }
void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) { int id = event.GetId(); wxPoint pos; bool redraw = false; INSTALL_UNBUFFERED_DC( dc, m_canvas ); wxGetMousePosition( &pos.x, &pos.y ); pos.y += 20; switch( id ) { case wxID_CUT: case wxID_COPY: case ID_TOOLBARH_PCB_SELECT_LAYER: case ID_MODEDIT_PAD_SETTINGS: case ID_PCB_USER_GRID_SETUP: case ID_POPUP_PCB_ROTATE_TEXTEPCB: case ID_POPUP_PCB_EDIT_TEXTEPCB: case ID_POPUP_PCB_ROTATE_TEXTMODULE: case ID_POPUP_PCB_ROTATE_MODULE_CLOCKWISE: case ID_POPUP_PCB_ROTATE_MODULE_COUNTERCLOCKWISE: case ID_POPUP_PCB_EDIT_TEXTMODULE: case ID_POPUP_PCB_IMPORT_PAD_SETTINGS: case ID_POPUP_PCB_EXPORT_PAD_SETTINGS: case ID_POPUP_PCB_GLOBAL_IMPORT_PAD_SETTINGS: case ID_POPUP_PCB_STOP_CURRENT_DRAWING: case ID_POPUP_MODEDIT_EDIT_BODY_ITEM: case ID_POPUP_MODEDIT_EDIT_WIDTH_CURRENT_EDGE: case ID_POPUP_MODEDIT_EDIT_WIDTH_ALL_EDGE: case ID_POPUP_MODEDIT_EDIT_LAYER_CURRENT_EDGE: case ID_POPUP_MODEDIT_EDIT_LAYER_ALL_EDGE: case ID_POPUP_MODEDIT_ENTER_EDGE_WIDTH: case ID_POPUP_PCB_DELETE_EDGE: case ID_POPUP_PCB_DELETE_TEXTMODULE: case ID_POPUP_PCB_DELETE_PAD: case ID_POPUP_DELETE_BLOCK: case ID_POPUP_PLACE_BLOCK: case ID_POPUP_ZOOM_BLOCK: case ID_POPUP_MIRROR_X_BLOCK: case ID_POPUP_ROTATE_BLOCK: case ID_POPUP_COPY_BLOCK: break; case ID_POPUP_CANCEL_CURRENT_COMMAND: default: if( m_canvas->IsMouseCaptured() ) { // for all other commands: stop the move in progress m_canvas->CallEndMouseCapture( &dc ); } if( id != ID_POPUP_CANCEL_CURRENT_COMMAND ) SetToolID( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor(), wxEmptyString ); break; } switch( id ) { case ID_EXIT: Close( true ); break; case ID_MODEDIT_SELECT_CURRENT_LIB: Select_Active_Library(); break; case ID_OPEN_MODULE_VIEWER: { FOOTPRINT_VIEWER_FRAME * viewer = FOOTPRINT_VIEWER_FRAME::GetActiveFootprintViewer(); if( viewer == NULL ) { viewer = new FOOTPRINT_VIEWER_FRAME( this, NULL ); viewer->Show( true ); viewer->Zoom_Automatique( false ); } else { if( viewer->IsIconized() ) viewer->Iconize( false ); viewer->Raise(); // Raising the window does not set the focus on Linux. This should work on // any platform. if( wxWindow::FindFocus() != viewer ) viewer->SetFocus(); } } break; case ID_MODEDIT_DELETE_PART: DeleteModuleFromCurrentLibrary(); break; case ID_MODEDIT_NEW_MODULE: { Clear_Pcb( true ); GetScreen()->ClearUndoRedoList(); SetCurItem( NULL ); GetScreen()->SetCrossHairPosition( wxPoint( 0, 0 ) ); MODULE* module = Create_1_Module( wxEmptyString ); if( module ) // i.e. if create module command not aborted { // Initialize data relative to nets and netclasses (for a new // module the defaults are used) // This is mandatory to handle and draw pads GetBoard()->BuildListOfNets(); redraw = true; module->SetPosition( wxPoint( 0, 0 ) ); if( GetBoard()->m_Modules ) GetBoard()->m_Modules->ClearFlags(); Zoom_Automatique( false ); } } break; case ID_MODEDIT_NEW_MODULE_FROM_WIZARD: { Clear_Pcb( true ); GetScreen()->ClearUndoRedoList(); SetCurItem( NULL ); GetScreen()->SetCrossHairPosition( wxPoint( 0, 0 ) ); wxSemaphore semaphore( 0, 1 ); FOOTPRINT_WIZARD_FRAME *wizard = new FOOTPRINT_WIZARD_FRAME( this, &semaphore, KICAD_DEFAULT_DRAWFRAME_STYLE | wxFRAME_FLOAT_ON_PARENT ); wizard->Show( true ); wizard->Zoom_Automatique( false ); while( semaphore.TryWait() == wxSEMA_BUSY ) // Wait for viewer closing event { wxYield(); wxMilliSleep( 50 ); } MODULE* module = wizard->GetBuiltFootprint(); if( module ) // i.e. if create module command not aborted { /* Here we should make a copy of the object before adding to board*/ module->SetParent( (EDA_ITEM*)GetBoard() ); GetBoard()->m_Modules.Append( module ); // Initialize data relative to nets and netclasses (for a new // module the defaults are used) // This is mandatory to handle and draw pads GetBoard()->BuildListOfNets(); redraw = true; module->SetPosition( wxPoint( 0, 0 ) ); if( GetBoard()->m_Modules ) GetBoard()->m_Modules->ClearFlags(); } wizard->Destroy(); } break; case ID_MODEDIT_SAVE_LIBMODULE: if( GetBoard()->m_Modules && getLibPath() != wxEmptyString ) { Save_Module_In_Library( getLibPath(), GetBoard()->m_Modules, true, true ); GetScreen()->ClrModify(); } break; case ID_MODEDIT_INSERT_MODULE_IN_BOARD: case ID_MODEDIT_UPDATE_MODULE_IN_BOARD: { // update module in the current board, // not just add it to the board with total disregard for the netlist... PCB_EDIT_FRAME* pcbframe = (PCB_EDIT_FRAME*) GetParent(); BOARD* mainpcb = pcbframe->GetBoard(); MODULE* source_module = NULL; MODULE* module_in_edit = GetBoard()->m_Modules; // Search the old module (source) if exists // Because this source could be deleted when editing the main board... if( module_in_edit->m_Link ) // this is not a new module ... { source_module = mainpcb->m_Modules; for( ; source_module != NULL; source_module = (MODULE*) source_module->Next() ) { if( module_in_edit->m_Link == source_module->GetTimeStamp() ) break; } } if( ( source_module == NULL ) && ( id == ID_MODEDIT_UPDATE_MODULE_IN_BOARD ) ) // source not found { wxString msg; msg.Printf( _( "Unable to find the footprint source on the main board" ) ); msg << _( "\nCannot update the footprint" ); DisplayError( this, msg ); break; } if( ( source_module != NULL ) && ( id == ID_MODEDIT_INSERT_MODULE_IN_BOARD ) ) // source not found { wxString msg; msg.Printf( _( "A footprint source was found on the main board" ) ); msg << _( "\nCannot insert this footprint" ); DisplayError( this, msg ); break; } // Create the "new" module MODULE* newmodule = new MODULE( *module_in_edit ); newmodule->SetParent( mainpcb ); newmodule->m_Link = 0; // Put the footprint in the main pcb linked list. mainpcb->Add( newmodule ); if( source_module ) // this is an update command { // In the main board, // the new module replace the old module (pos, orient, ref, value // and connexions are kept) // and the source_module (old module) is deleted PICKED_ITEMS_LIST pickList; pcbframe->Exchange_Module( source_module, newmodule, &pickList ); newmodule->SetTimeStamp( module_in_edit->m_Link ); if( pickList.GetCount() ) pcbframe->SaveCopyInUndoList( pickList, UR_UNSPECIFIED ); } else // This is an insert command { wxPoint cursor_pos = pcbframe->GetScreen()->GetCrossHairPosition(); pcbframe->GetScreen()->SetCrossHairPosition( wxPoint( 0, 0 ) ); pcbframe->PlaceModule( newmodule, NULL ); pcbframe->GetScreen()->SetCrossHairPosition( cursor_pos ); newmodule->SetTimeStamp( GetNewTimeStamp() ); pcbframe->SaveCopyInUndoList( newmodule, UR_NEW ); } newmodule->ClearFlags(); GetScreen()->ClrModify(); pcbframe->SetCurItem( NULL ); mainpcb->m_Status_Pcb = 0; } break; case ID_MODEDIT_IMPORT_PART: if( ! Clear_Pcb( true ) ) break; // //this command is aborted GetScreen()->ClearUndoRedoList(); SetCurItem( NULL ); GetScreen()->SetCrossHairPosition( wxPoint( 0, 0 ) ); Import_Module(); redraw = true; if( GetBoard()->m_Modules ) GetBoard()->m_Modules->ClearFlags(); GetScreen()->ClrModify(); Zoom_Automatique( false ); if( m_Draw3DFrame ) m_Draw3DFrame->NewDisplay(); break; case ID_MODEDIT_EXPORT_PART: if( GetBoard()->m_Modules ) Export_Module( GetBoard()->m_Modules ); break; case ID_MODEDIT_CREATE_NEW_LIB_AND_SAVE_CURRENT_PART: if( GetBoard()->m_Modules ) { // CreateModuleLibrary() only creates a new library, does not save footprint wxString libPath = CreateNewLibrary(); if( libPath.size() ) SaveCurrentModule( &libPath ); } break; case ID_MODEDIT_SHEET_SET: break; case ID_MODEDIT_LOAD_MODULE: { wxString libPath = getLibPath(); // might be empty wxLogDebug( wxT( "Loading module from library " ) + libPath ); GetScreen()->ClearUndoRedoList(); SetCurItem( NULL ); Clear_Pcb( true ); GetScreen()->SetCrossHairPosition( wxPoint( 0, 0 ) ); Load_Module_From_Library( libPath, true ); redraw = true; } if( GetBoard()->m_Modules ) GetBoard()->m_Modules->ClearFlags(); // if either m_Reference or m_Value are gone, reinstall them - // otherwise you cannot see what you are doing on board if( GetBoard() && GetBoard()->m_Modules ) { TEXTE_MODULE* ref = GetBoard()->m_Modules->m_Reference; TEXTE_MODULE* val = GetBoard()->m_Modules->m_Value; if( val && ref ) { ref->SetType( TEXT_is_REFERENCE ); // just in case ... if( ref->m_Text.Length() == 0 ) ref->m_Text = L"Ref**"; val->SetType( TEXT_is_VALUE ); // just in case ... if( val->m_Text.Length() == 0 ) val->m_Text = L"Val**"; } } GetScreen()->ClrModify(); Zoom_Automatique( false ); if( m_Draw3DFrame ) m_Draw3DFrame->NewDisplay(); break; case ID_MODEDIT_PAD_SETTINGS: InstallPadOptionsFrame( NULL ); break; case ID_MODEDIT_CHECK: break; case ID_MODEDIT_EDIT_MODULE_PROPERTIES: if( GetBoard()->m_Modules ) { SetCurItem( GetBoard()->m_Modules ); DIALOG_MODULE_MODULE_EDITOR dialog( this, (MODULE*) GetScreen()-> GetCurItem() ); int ret = dialog.ShowModal(); GetScreen()->GetCurItem()->ClearFlags(); if( ret > 0 ) m_canvas->Refresh(); } break; case ID_POPUP_CLOSE_CURRENT_TOOL: break; case ID_POPUP_CANCEL_CURRENT_COMMAND: break; case ID_POPUP_PCB_ROTATE_MODULE_COUNTERCLOCKWISE: m_canvas->MoveCursorToCrossHair(); Rotate_Module( NULL, (MODULE*) GetScreen()->GetCurItem(), 900, true ); redraw = true; break; case ID_POPUP_PCB_ROTATE_MODULE_CLOCKWISE: m_canvas->MoveCursorToCrossHair(); Rotate_Module( NULL, (MODULE*) GetScreen()->GetCurItem(), -900, true ); redraw = true; break; case ID_POPUP_PCB_EDIT_MODULE: { DIALOG_MODULE_MODULE_EDITOR dialog( this, (MODULE*) GetScreen()->GetCurItem() ); int ret = dialog.ShowModal(); GetScreen()->GetCurItem()->ClearFlags(); GetScreen()->GetCurItem()->ClearFlags(); m_canvas->MoveCursorToCrossHair(); if( ret > 0 ) m_canvas->Refresh(); } break; case ID_POPUP_PCB_MOVE_PAD_REQUEST: m_canvas->MoveCursorToCrossHair(); StartMovePad( (D_PAD*) GetScreen()->GetCurItem(), &dc, false ); break; case ID_POPUP_PCB_EDIT_PAD: InstallPadOptionsFrame( (D_PAD*) GetScreen()->GetCurItem() ); m_canvas->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_DELETE_PAD: SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); DeletePad( (D_PAD*) GetScreen()->GetCurItem(), false ); SetCurItem( NULL ); m_canvas->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_IMPORT_PAD_SETTINGS: SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); m_canvas->MoveCursorToCrossHair(); Import_Pad_Settings( (D_PAD*) GetScreen()->GetCurItem(), true ); break; case ID_POPUP_PCB_GLOBAL_IMPORT_PAD_SETTINGS: SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); // Calls the global change dialog: DlgGlobalChange_PadSettings( (D_PAD*) GetScreen()->GetCurItem() ); m_canvas->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_EXPORT_PAD_SETTINGS: m_canvas->MoveCursorToCrossHair(); Export_Pad_Settings( (D_PAD*) GetScreen()->GetCurItem() ); break; case ID_POPUP_PCB_EDIT_TEXTMODULE: InstallTextModOptionsFrame( (TEXTE_MODULE*) GetScreen()->GetCurItem(), &dc ); m_canvas->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_MOVE_TEXTMODULE_REQUEST: m_canvas->MoveCursorToCrossHair(); StartMoveTexteModule( (TEXTE_MODULE*) GetScreen()->GetCurItem(), &dc ); break; case ID_POPUP_PCB_ROTATE_TEXTMODULE: RotateTextModule( (TEXTE_MODULE*) GetScreen()->GetCurItem(), &dc ); m_canvas->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_DELETE_TEXTMODULE: SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); DeleteTextModule( (TEXTE_MODULE*) GetScreen()->GetCurItem() ); SetCurItem( NULL ); m_canvas->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_MOVE_EDGE: Start_Move_EdgeMod( (EDGE_MODULE*) GetScreen()->GetCurItem(), &dc ); m_canvas->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_STOP_CURRENT_DRAWING: m_canvas->MoveCursorToCrossHair(); if( GetScreen()->GetCurItem()->IsNew() ) { End_Edge_Module( (EDGE_MODULE*) GetScreen()->GetCurItem() ); SetCurItem( NULL ); } break; case ID_POPUP_MODEDIT_ENTER_EDGE_WIDTH: { EDGE_MODULE* edge = NULL; if( GetScreen()->GetCurItem() && ( GetScreen()->GetCurItem()->Type() == PCB_MODULE_EDGE_T ) ) { edge = (EDGE_MODULE*) GetScreen()->GetCurItem(); } Enter_Edge_Width( edge ); m_canvas->MoveCursorToCrossHair(); if( edge ) m_canvas->Refresh(); } break; case ID_POPUP_MODEDIT_EDIT_BODY_ITEM : m_canvas->MoveCursorToCrossHair(); InstallFootprintBodyItemPropertiesDlg( (EDGE_MODULE*) GetScreen()->GetCurItem() ); m_canvas->Refresh(); break; case ID_POPUP_MODEDIT_EDIT_WIDTH_CURRENT_EDGE: m_canvas->MoveCursorToCrossHair(); Edit_Edge_Width( (EDGE_MODULE*) GetScreen()->GetCurItem() ); m_canvas->Refresh(); break; case ID_POPUP_MODEDIT_EDIT_WIDTH_ALL_EDGE: m_canvas->MoveCursorToCrossHair(); Edit_Edge_Width( NULL ); m_canvas->Refresh(); break; case ID_POPUP_MODEDIT_EDIT_LAYER_CURRENT_EDGE: m_canvas->MoveCursorToCrossHair(); Edit_Edge_Layer( (EDGE_MODULE*) GetScreen()->GetCurItem() ); m_canvas->Refresh(); break; case ID_POPUP_MODEDIT_EDIT_LAYER_ALL_EDGE: m_canvas->MoveCursorToCrossHair(); Edit_Edge_Layer( NULL ); m_canvas->Refresh(); break; case ID_POPUP_PCB_DELETE_EDGE: SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); m_canvas->MoveCursorToCrossHair(); RemoveStruct( GetScreen()->GetCurItem() ); SetCurItem( NULL ); break; case ID_MODEDIT_MODULE_ROTATE: case ID_MODEDIT_MODULE_MIRROR: SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); Transform( (MODULE*) GetScreen()->GetCurItem(), id ); redraw = true; break; case ID_PCB_DRAWINGS_WIDTHS_SETUP: InstallOptionsFrame( pos ); break; case ID_PCB_PAD_SETUP: { BOARD_ITEM* item = GetCurItem(); if( item ) { if( item->Type() != PCB_PAD_T ) item = NULL; } InstallPadOptionsFrame( (D_PAD*) item ); } break; case ID_PCB_USER_GRID_SETUP: InstallGridFrame( pos ); break; case ID_POPUP_PLACE_BLOCK: GetScreen()->m_BlockLocate.SetCommand( BLOCK_MOVE ); m_canvas->SetAutoPanRequest( false ); HandleBlockPlace( &dc ); break; case ID_POPUP_COPY_BLOCK: GetScreen()->m_BlockLocate.SetCommand( BLOCK_COPY ); GetScreen()->m_BlockLocate.SetMessageBlock( this ); m_canvas->SetAutoPanRequest( false ); HandleBlockPlace( &dc ); break; case ID_POPUP_ZOOM_BLOCK: GetScreen()->m_BlockLocate.SetCommand( BLOCK_ZOOM ); GetScreen()->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); break; case ID_POPUP_DELETE_BLOCK: GetScreen()->m_BlockLocate.SetCommand( BLOCK_DELETE ); GetScreen()->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); break; case ID_POPUP_ROTATE_BLOCK: GetScreen()->m_BlockLocate.SetCommand( BLOCK_ROTATE ); GetScreen()->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); break; case ID_POPUP_MIRROR_X_BLOCK: GetScreen()->m_BlockLocate.SetCommand( BLOCK_MIRROR_X ); GetScreen()->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); break; default: DisplayError( this, wxT( "FOOTPRINT_EDIT_FRAME::Process_Special_Functions error" ) ); break; } if( redraw ) m_canvas->Refresh(); }
MODULE* PCB_EDIT_FRAME::Genere_Self( wxDC* DC ) { D_PAD* pad; int ll; wxString msg; m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); m_canvas->SetMouseCapture( NULL, NULL ); if( s_inductor_pattern.m_Flag == false ) { DisplayError( this, wxT( "Starting point not init.." ) ); return NULL; } s_inductor_pattern.m_Flag = false; s_inductor_pattern.m_End = GetCrossHairPosition(); wxPoint pt = s_inductor_pattern.m_End - s_inductor_pattern.m_Start; int min_len = KiROUND( EuclideanNorm( pt ) ); s_inductor_pattern.m_lenght = min_len; // Enter the desired length. msg = StringFromValue( g_UserUnit, s_inductor_pattern.m_lenght ); wxTextEntryDialog dlg( this, wxEmptyString, _( "Length of Trace:" ), msg ); if( dlg.ShowModal() != wxID_OK ) return NULL; // canceled by user msg = dlg.GetValue(); s_inductor_pattern.m_lenght = ValueFromString( g_UserUnit, msg ); // Control values (ii = minimum length) if( s_inductor_pattern.m_lenght < min_len ) { DisplayError( this, _( "Requested length < minimum length" ) ); return NULL; } // Calculate the elements. s_inductor_pattern.m_Width = GetDesignSettings().GetCurrentTrackWidth(); std::vector <wxPoint> buffer; ll = BuildCornersList_S_Shape( buffer, s_inductor_pattern.m_Start, s_inductor_pattern.m_End, s_inductor_pattern.m_lenght, s_inductor_pattern.m_Width ); if( !ll ) { DisplayError( this, _( "Requested length too large" ) ); return NULL; } // Generate footprint. the value is also used as footprint name. msg.Empty(); wxTextEntryDialog cmpdlg( this, wxEmptyString, _( "Component Value:" ), msg ); cmpdlg.SetTextValidator( FILE_NAME_CHAR_VALIDATOR( &msg ) ); if( ( cmpdlg.ShowModal() != wxID_OK ) || msg.IsEmpty() ) return NULL; // Aborted by user MODULE* module = CreateNewModule( msg ); // here the module is already in the BOARD, CreateNewModule() does that. module->SetFPID( FPID( std::string( "mw_inductor" ) ) ); module->SetAttributes( MOD_VIRTUAL | MOD_CMS ); module->ClearFlags(); module->SetPosition( s_inductor_pattern.m_End ); // Generate segments for( unsigned jj = 1; jj < buffer.size(); jj++ ) { EDGE_MODULE* PtSegm; PtSegm = new EDGE_MODULE( module ); PtSegm->SetStart( buffer[jj - 1] ); PtSegm->SetEnd( buffer[jj] ); PtSegm->SetWidth( s_inductor_pattern.m_Width ); PtSegm->SetLayer( module->GetLayer() ); PtSegm->SetShape( S_SEGMENT ); PtSegm->SetStart0( PtSegm->GetStart() - module->GetPosition() ); PtSegm->SetEnd0( PtSegm->GetEnd() - module->GetPosition() ); module->GraphicalItems().PushBack( PtSegm ); } // Place a pad on each end of coil. pad = new D_PAD( module ); module->Pads().PushFront( pad ); pad->SetPadName( wxT( "1" ) ); pad->SetPosition( s_inductor_pattern.m_End ); pad->SetPos0( pad->GetPosition() - module->GetPosition() ); pad->SetSize( wxSize( s_inductor_pattern.m_Width, s_inductor_pattern.m_Width ) ); pad->SetLayerSet( LSET( module->GetLayer() ) ); pad->SetAttribute( PAD_ATTRIB_SMD ); pad->SetShape( PAD_SHAPE_CIRCLE ); D_PAD* newpad = new D_PAD( *pad ); module->Pads().Insert( newpad, pad->Next() ); pad = newpad; pad->SetPadName( wxT( "2" ) ); pad->SetPosition( s_inductor_pattern.m_Start ); pad->SetPos0( pad->GetPosition() - module->GetPosition() ); // Modify text positions. SetMsgPanel( module ); wxPoint refPos( ( s_inductor_pattern.m_Start.x + s_inductor_pattern.m_End.x ) / 2, ( s_inductor_pattern.m_Start.y + s_inductor_pattern.m_End.y ) / 2 ); wxPoint valPos = refPos; refPos.y -= module->Reference().GetSize().y; module->Reference().SetPosition( refPos ); valPos.y += module->Value().GetSize().y; module->Value().SetPosition( valPos ); module->CalculateBoundingBox(); module->Draw( m_canvas, DC, GR_OR ); return module; }
MODULE* MWAVE::CreateMicrowaveInductor( INDUCTOR_PATTERN& inductorPattern, PCB_EDIT_FRAME* aPcbFrame, wxString& aErrorMessage ) { /* Build a microwave inductor footprint. * - Length Mself.lng * - Extremities Mself.m_Start and Mself.m_End * We must determine: * Mself.nbrin = number of segments perpendicular to the direction * (The coil nbrin will demicercles + 1 + 2 1 / 4 circle) * Mself.lbrin = length of a strand * Mself.radius = radius of rounded parts of the coil * Mself.delta = segments extremities connection between him and the coil even * * The equations are * Mself.m_Size.x = 2 * Mself.radius + Mself.lbrin * Mself.m_Size.y * Mself.delta = 2 + 2 * Mself.nbrin * Mself.radius * Mself.lng = 2 * Mself.delta / / connections to the coil + (Mself.nbrin-2) * Mself.lbrin / / length of the strands except 1st and last + (Mself.nbrin 1) * (PI * Mself.radius) / / length of rounded * Mself.lbrin + / 2 - Melf.radius * 2) / / length of 1st and last bit * * The constraints are: * Nbrin >= 2 * Mself.radius < Mself.m_Size.x * Mself.m_Size.y = Mself.radius * 4 + 2 * Mself.raccord * Mself.lbrin> Mself.radius * 2 * * The calculation is conducted in the following way: * Initially: * Nbrin = 2 * Radius = 4 * m_Size.x (arbitrarily fixed value) * Then: * Increasing the number of segments to the desired length * (Radius decreases if necessary) */ D_PAD* pad; int ll; wxString msg; auto pt = inductorPattern.m_End - inductorPattern.m_Start; int min_len = KiROUND( EuclideanNorm( pt ) ); inductorPattern.m_length = min_len; // Enter the desired length. msg = StringFromValue( g_UserUnit, inductorPattern.m_length ); wxTextEntryDialog dlg( nullptr, wxEmptyString, _( "Length of Trace:" ), msg ); if( dlg.ShowModal() != wxID_OK ) return nullptr; // canceled by user msg = dlg.GetValue(); inductorPattern.m_length = ValueFromString( g_UserUnit, msg ); // Control values (ii = minimum length) if( inductorPattern.m_length < min_len ) { aErrorMessage = _( "Requested length < minimum length" ); return nullptr; } // Calculate the elements. std::vector <wxPoint> buffer; ll = BuildCornersList_S_Shape( buffer, inductorPattern.m_Start, inductorPattern.m_End, inductorPattern.m_length, inductorPattern.m_Width ); if( !ll ) { aErrorMessage = _( "Requested length too large" ); return nullptr; } // Generate footprint. the value is also used as footprint name. msg = "L"; wxTextEntryDialog cmpdlg( nullptr, wxEmptyString, _( "Component Value:" ), msg ); cmpdlg.SetTextValidator( FILE_NAME_CHAR_VALIDATOR( &msg ) ); if( ( cmpdlg.ShowModal() != wxID_OK ) || msg.IsEmpty() ) return nullptr; // Aborted by user MODULE* module = aPcbFrame->CreateNewModule( msg ); // here the module is already in the BOARD, CreateNewModule() does that. module->SetFPID( LIB_ID( wxString( "mw_inductor" ) ) ); module->SetAttributes( MOD_VIRTUAL | MOD_CMS ); module->ClearFlags(); module->SetPosition( inductorPattern.m_End ); // Generate segments for( unsigned jj = 1; jj < buffer.size(); jj++ ) { EDGE_MODULE* PtSegm; PtSegm = new EDGE_MODULE( module ); PtSegm->SetStart( buffer[jj - 1] ); PtSegm->SetEnd( buffer[jj] ); PtSegm->SetWidth( inductorPattern.m_Width ); PtSegm->SetLayer( module->GetLayer() ); PtSegm->SetShape( S_SEGMENT ); PtSegm->SetStart0( PtSegm->GetStart() - module->GetPosition() ); PtSegm->SetEnd0( PtSegm->GetEnd() - module->GetPosition() ); module->GraphicalItemsList().PushBack( PtSegm ); } // Place a pad on each end of coil. pad = new D_PAD( module ); module->PadsList().PushFront( pad ); pad->SetName( "1" ); pad->SetPosition( inductorPattern.m_End ); pad->SetPos0( pad->GetPosition() - module->GetPosition() ); pad->SetSize( wxSize( inductorPattern.m_Width, inductorPattern.m_Width ) ); pad->SetLayerSet( LSET( module->GetLayer() ) ); pad->SetAttribute( PAD_ATTRIB_SMD ); pad->SetShape( PAD_SHAPE_CIRCLE ); D_PAD* newpad = new D_PAD( *pad ); module->PadsList().Insert( newpad, pad->Next() ); pad = newpad; pad->SetName( "2" ); pad->SetPosition( inductorPattern.m_Start ); pad->SetPos0( pad->GetPosition() - module->GetPosition() ); // Modify text positions. wxPoint refPos( ( inductorPattern.m_Start.x + inductorPattern.m_End.x ) / 2, ( inductorPattern.m_Start.y + inductorPattern.m_End.y ) / 2 ); wxPoint valPos = refPos; refPos.y -= module->Reference().GetTextSize().y; module->Reference().SetPosition( refPos ); valPos.y += module->Value().GetTextSize().y; module->Value().SetPosition( valPos ); module->CalculateBoundingBox(); return module; }
void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool aSetDirtyBit ) { // Objects potentially interested in changes: PICKED_ITEMS_LIST undoList; KIGFX::VIEW* view = m_toolMgr->GetView(); BOARD* board = (BOARD*) m_toolMgr->GetModel(); PCB_BASE_FRAME* frame = (PCB_BASE_FRAME*) m_toolMgr->GetEditFrame(); auto connectivity = board->GetConnectivity(); std::set<EDA_ITEM*> savedModules; std::vector<BOARD_ITEM*> itemsToDeselect; if( Empty() ) return; for( COMMIT_LINE& ent : m_changes ) { int changeType = ent.m_type & CHT_TYPE; int changeFlags = ent.m_type & CHT_FLAGS; BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( ent.m_item ); // Module items need to be saved in the undo buffer before modification if( m_editModules ) { // Be sure that we are storing a module if( ent.m_item->Type() != PCB_MODULE_T ) ent.m_item = ent.m_item->GetParent(); // We have not saved the module yet, so let's create an entry if( savedModules.count( ent.m_item ) == 0 ) { if( !ent.m_copy ) { wxASSERT( changeType != CHT_MODIFY ); // too late to make a copy.. ent.m_copy = ent.m_item->Clone(); } wxASSERT( ent.m_item->Type() == PCB_MODULE_T ); wxASSERT( ent.m_copy->Type() == PCB_MODULE_T ); if( aCreateUndoEntry ) { ITEM_PICKER itemWrapper( ent.m_item, UR_CHANGED ); itemWrapper.SetLink( ent.m_copy ); undoList.PushItem( itemWrapper ); frame->SaveCopyInUndoList( undoList, UR_CHANGED ); } savedModules.insert( ent.m_item ); static_cast<MODULE*>( ent.m_item )->SetLastEditTime(); } } switch( changeType ) { case CHT_ADD: { if( !m_editModules ) { if( aCreateUndoEntry ) { undoList.PushItem( ITEM_PICKER( boardItem, UR_NEW ) ); } if( !( changeFlags & CHT_DONE ) ) board->Add( boardItem ); // handles connectivity } else { // modules inside modules are not supported yet wxASSERT( boardItem->Type() != PCB_MODULE_T ); boardItem->SetParent( board->m_Modules.GetFirst() ); if( !( changeFlags & CHT_DONE ) ) board->m_Modules->Add( boardItem ); } view->Add( boardItem ); break; } case CHT_REMOVE: { if( !m_editModules && aCreateUndoEntry ) undoList.PushItem( ITEM_PICKER( boardItem, UR_DELETED ) ); switch( boardItem->Type() ) { // Module items case PCB_PAD_T: case PCB_MODULE_EDGE_T: case PCB_MODULE_TEXT_T: // This level can only handle module items when editing modules if( !m_editModules ) break; if( boardItem->Type() == PCB_MODULE_TEXT_T ) { TEXTE_MODULE* text = static_cast<TEXTE_MODULE*>( boardItem ); // don't allow deletion of Reference or Value if( text->GetType() != TEXTE_MODULE::TEXT_is_DIVERS ) break; } view->Remove( boardItem ); if( !( changeFlags & CHT_DONE ) ) { MODULE* module = static_cast<MODULE*>( boardItem->GetParent() ); wxASSERT( module && module->Type() == PCB_MODULE_T ); module->Delete( boardItem ); } board->m_Status_Pcb = 0; // it is done in the legacy view (ratsnest perhaps?) break; // Board items case PCB_LINE_T: // a segment not on copper layers case PCB_TEXT_T: // a text on a layer case PCB_TRACE_T: // a track segment (segment on a copper layer) case PCB_VIA_T: // a via (like track segment on a copper layer) case PCB_DIMENSION_T: // a dimension (graphic item) case PCB_TARGET_T: // a target (graphic item) case PCB_MARKER_T: // a marker used to show something case PCB_ZONE_AREA_T: itemsToDeselect.push_back( boardItem ); view->Remove( boardItem ); if( !( changeFlags & CHT_DONE ) ) board->Remove( boardItem ); break; case PCB_MODULE_T: { itemsToDeselect.push_back( boardItem ); // There are no modules inside a module yet wxASSERT( !m_editModules ); MODULE* module = static_cast<MODULE*>( boardItem ); view->Remove( module ); module->ClearFlags(); if( !( changeFlags & CHT_DONE ) ) board->Remove( module ); // handles connectivity // Clear flags to indicate, that the ratsnest, list of nets & pads are not valid anymore board->m_Status_Pcb = 0; } break; default: // other types do not need to (or should not) be handled wxASSERT( false ); break; } break; } case CHT_MODIFY: { if( !m_editModules && aCreateUndoEntry ) { ITEM_PICKER itemWrapper( boardItem, UR_CHANGED ); wxASSERT( ent.m_copy ); itemWrapper.SetLink( ent.m_copy ); undoList.PushItem( itemWrapper ); } if( ent.m_copy ) connectivity->MarkItemNetAsDirty( static_cast<BOARD_ITEM*>( ent.m_copy ) ); connectivity->Update( boardItem ); view->Update( boardItem ); // if no undo entry is needed, the copy would create a memory leak if( !aCreateUndoEntry ) delete ent.m_copy; break; } default: wxASSERT( false ); break; } } // Removing an item should trigger the unselect action // but only after all items are removed otherwise we can get // flickering depending on the system if( itemsToDeselect.size() > 0 ) m_toolMgr->RunAction( PCB_ACTIONS::unselectItems, true, &itemsToDeselect ); if( !m_editModules && aCreateUndoEntry ) frame->SaveCopyInUndoList( undoList, UR_UNSPECIFIED ); if( TOOL_MANAGER* toolMgr = frame->GetToolManager() ) toolMgr->PostEvent( { TC_MESSAGE, TA_MODEL_CHANGE, AS_GLOBAL } ); if ( !m_editModules ) { auto panel = static_cast<PCB_DRAW_PANEL_GAL*>( frame->GetGalCanvas() ); connectivity->RecalculateRatsnest(); connectivity->ClearDynamicRatsnest(); panel->RedrawRatsnest(); } if( aSetDirtyBit ) frame->OnModify(); frame->UpdateMsgPanel(); clear(); }
void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) { int id = event.GetId(); wxPoint pos; INSTALL_UNBUFFERED_DC( dc, m_canvas ); wxGetMousePosition( &pos.x, &pos.y ); pos.y += 20; switch( id ) { case wxID_CUT: case wxID_COPY: case ID_TOOLBARH_PCB_SELECT_LAYER: case ID_MODEDIT_PAD_SETTINGS: case ID_PCB_USER_GRID_SETUP: case ID_POPUP_PCB_ROTATE_TEXTEPCB: case ID_POPUP_PCB_EDIT_TEXTEPCB: case ID_POPUP_PCB_ROTATE_TEXTMODULE: case ID_POPUP_PCB_ROTATE_MODULE_CLOCKWISE: case ID_POPUP_PCB_ROTATE_MODULE_COUNTERCLOCKWISE: case ID_POPUP_PCB_EDIT_TEXTMODULE: case ID_POPUP_PCB_APPLY_PAD_SETTINGS: case ID_POPUP_PCB_COPY_PAD_SETTINGS: case ID_POPUP_PCB_GLOBAL_IMPORT_PAD_SETTINGS: case ID_POPUP_PCB_STOP_CURRENT_DRAWING: case ID_POPUP_MODEDIT_EDIT_BODY_ITEM: case ID_POPUP_MODEDIT_EDIT_WIDTH_ALL_EDGE: case ID_POPUP_MODEDIT_EDIT_LAYER_ALL_EDGE: case ID_POPUP_MODEDIT_ENTER_EDGE_WIDTH: case ID_POPUP_PCB_DELETE_EDGE: case ID_POPUP_PCB_DELETE_TEXTMODULE: case ID_POPUP_PCB_DELETE_PAD: case ID_POPUP_DELETE_BLOCK: case ID_POPUP_PLACE_BLOCK: case ID_POPUP_ZOOM_BLOCK: case ID_POPUP_MIRROR_X_BLOCK: case ID_POPUP_ROTATE_BLOCK: case ID_POPUP_COPY_BLOCK: break; case ID_POPUP_CANCEL_CURRENT_COMMAND: default: if( m_canvas->IsMouseCaptured() ) { // for all other commands: stop the move in progress m_canvas->CallEndMouseCapture( &dc ); } if( id != ID_POPUP_CANCEL_CURRENT_COMMAND ) SetToolID( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor(), wxEmptyString ); break; } switch( id ) { case ID_EXIT: Close( true ); break; case ID_MODEDIT_SELECT_CURRENT_LIB: { wxString library = SelectLibrary( GetCurrentLib() ); if( library.size() ) { Prj().SetRString( PROJECT::PCB_LIB_NICKNAME, library ); updateTitle(); } } break; case ID_OPEN_MODULE_VIEWER: { FOOTPRINT_VIEWER_FRAME* viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_PCB_MODULE_VIEWER, false ); if( !viewer ) { viewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_PCB_MODULE_VIEWER, true ); viewer->Show( true ); viewer->Zoom_Automatique( false ); } else { // On Windows, Raise() does not bring the window on screen, when iconized if( viewer->IsIconized() ) viewer->Iconize( false ); viewer->Raise(); // Raising the window does not set the focus on Linux. This should work on // any platform. if( wxWindow::FindFocus() != viewer ) viewer->SetFocus(); } } break; case ID_MODEDIT_DELETE_PART: DeleteModuleFromCurrentLibrary(); break; case ID_MODEDIT_NEW_MODULE: { if( !Clear_Pcb( true ) ) break; SetCrossHairPosition( wxPoint( 0, 0 ) ); MODULE* module = CreateNewModule( wxEmptyString ); if( module ) // i.e. if create module command not aborted { // Initialize data relative to nets and netclasses (for a new // module the defaults are used) // This is mandatory to handle and draw pads GetBoard()->BuildListOfNets(); module->SetPosition( wxPoint( 0, 0 ) ); if( GetBoard()->m_Modules ) GetBoard()->m_Modules->ClearFlags(); Zoom_Automatique( false ); } updateView(); m_canvas->Refresh(); GetScreen()->ClrModify(); } break; case ID_MODEDIT_NEW_MODULE_FROM_WIZARD: { if( GetScreen()->IsModify() && !GetBoard()->IsEmpty() ) { if( !IsOK( this, _( "Current Footprint will be lost and this operation cannot be undone. Continue ?" ) ) ) break; } FOOTPRINT_WIZARD_FRAME* wizard = (FOOTPRINT_WIZARD_FRAME*) Kiway().Player( FRAME_PCB_FOOTPRINT_WIZARD_MODAL, true, this ); if( wizard->ShowModal( NULL, this ) ) { // Creates the new footprint from python script wizard MODULE* module = wizard->GetBuiltFootprint(); if( module == NULL ) // i.e. if create module command aborted break; Clear_Pcb( false ); SetCrossHairPosition( wxPoint( 0, 0 ) ); // Add the new object to board GetBoard()->Add( module, ADD_APPEND ); // Initialize data relative to nets and netclasses (for a new // module the defaults are used) // This is mandatory to handle and draw pads GetBoard()->BuildListOfNets(); module->SetPosition( wxPoint( 0, 0 ) ); module->ClearFlags(); Zoom_Automatique( false ); updateView(); m_canvas->Refresh(); EDA_3D_VIEWER* draw3DFrame = Get3DViewerFrame(); if( draw3DFrame ) draw3DFrame->NewDisplay(); GetScreen()->ClrModify(); } wizard->Destroy(); } break; case ID_MODEDIT_SAVE_LIBMODULE: if( GetBoard()->m_Modules && GetCurrentLib().size() ) { SaveFootprintInLibrary( GetCurrentLib(), GetBoard()->m_Modules, true, true ); GetScreen()->ClrModify(); } break; case ID_MODEDIT_INSERT_MODULE_IN_BOARD: case ID_MODEDIT_UPDATE_MODULE_IN_BOARD: { // update module in the current board, // not just add it to the board with total disregard for the netlist... PCB_EDIT_FRAME* pcbframe = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB, false ); if( pcbframe == NULL ) // happens when the board editor is not active (or closed) { wxMessageBox( _("No board currently edited" ) ); break; } BOARD* mainpcb = pcbframe->GetBoard(); MODULE* source_module = NULL; MODULE* module_in_edit = GetBoard()->m_Modules; // Search the old module (source) if exists // Because this source could be deleted when editing the main board... if( module_in_edit->GetLink() ) // this is not a new module ... { source_module = mainpcb->m_Modules; for( ; source_module != NULL; source_module = source_module->Next() ) { if( module_in_edit->GetLink() == source_module->GetTimeStamp() ) break; } } if( ( source_module == NULL ) && ( id == ID_MODEDIT_UPDATE_MODULE_IN_BOARD ) ) // source not found { wxString msg; msg.Printf( _( "Unable to find the footprint source on the main board" ) ); msg << _( "\nCannot update the footprint" ); DisplayError( this, msg ); break; } if( ( source_module != NULL ) && ( id == ID_MODEDIT_INSERT_MODULE_IN_BOARD ) ) // source not found { wxString msg; msg.Printf( _( "A footprint source was found on the main board" ) ); msg << _( "\nCannot insert this footprint" ); DisplayError( this, msg ); break; } m_toolManager->RunAction( PCB_ACTIONS::selectionClear, true ); pcbframe->GetToolManager()->RunAction( PCB_ACTIONS::selectionClear, true ); BOARD_COMMIT commit( pcbframe ); // Create the "new" module MODULE* newmodule = new MODULE( *module_in_edit ); newmodule->SetParent( mainpcb ); newmodule->SetLink( 0 ); if( source_module ) // this is an update command { // In the main board, // the new module replace the old module (pos, orient, ref, value // and connexions are kept) // and the source_module (old module) is deleted pcbframe->Exchange_Module( source_module, newmodule, commit ); newmodule->SetTimeStamp( module_in_edit->GetLink() ); commit.Push( wxT( "Update module" ) ); } else // This is an insert command { wxPoint cursor_pos = pcbframe->GetCrossHairPosition(); commit.Add( newmodule ); pcbframe->SetCrossHairPosition( wxPoint( 0, 0 ) ); pcbframe->PlaceModule( newmodule, NULL ); newmodule->SetPosition( wxPoint( 0, 0 ) ); pcbframe->SetCrossHairPosition( cursor_pos ); newmodule->SetTimeStamp( GetNewTimeStamp() ); commit.Push( wxT( "Insert module" ) ); } newmodule->ClearFlags(); GetScreen()->ClrModify(); pcbframe->SetCurItem( NULL ); // @todo LEGACY should be unnecessary mainpcb->m_Status_Pcb = 0; } break; case ID_MODEDIT_IMPORT_PART: if( ! Clear_Pcb( true ) ) break; // //this command is aborted SetCrossHairPosition( wxPoint( 0, 0 ) ); Import_Module(); if( GetBoard()->m_Modules ) GetBoard()->m_Modules->ClearFlags(); GetScreen()->ClrModify(); Zoom_Automatique( false ); m_canvas->Refresh(); { EDA_3D_VIEWER* draw3DFrame = Get3DViewerFrame(); if( draw3DFrame ) draw3DFrame->NewDisplay(); } break; case ID_MODEDIT_EXPORT_PART: if( GetBoard()->m_Modules ) Export_Module( GetBoard()->m_Modules ); break; case ID_MODEDIT_CREATE_NEW_LIB_AND_SAVE_CURRENT_PART: if( GetBoard()->m_Modules ) { // CreateModuleLibrary() only creates a new library, does not save footprint wxString libPath = CreateNewLibrary(); if( libPath.size() ) SaveCurrentModule( &libPath ); } break; case ID_MODEDIT_SHEET_SET: break; case ID_MODEDIT_LOAD_MODULE: wxLogDebug( wxT( "Loading module from library " ) + getLibPath() ); if( ! Clear_Pcb( true ) ) break; SetCrossHairPosition( wxPoint( 0, 0 ) ); LoadModuleFromLibrary( GetCurrentLib(), Prj().PcbFootprintLibs(), true ); if( GetBoard() && GetBoard()->m_Modules ) { GetBoard()->m_Modules->ClearFlags(); // if either m_Reference or m_Value are gone, reinstall them - // otherwise you cannot see what you are doing on board TEXTE_MODULE* ref = &GetBoard()->m_Modules->Reference(); TEXTE_MODULE* val = &GetBoard()->m_Modules->Value(); if( val && ref ) { ref->SetType( TEXTE_MODULE::TEXT_is_REFERENCE ); // just in case ... if( ref->GetLength() == 0 ) ref->SetText( wxT( "Ref**" ) ); val->SetType( TEXTE_MODULE::TEXT_is_VALUE ); // just in case ... if( val->GetLength() == 0 ) val->SetText( wxT( "Val**" ) ); } } Zoom_Automatique( false ); { EDA_3D_VIEWER* draw3DFrame = Get3DViewerFrame(); if( draw3DFrame ) draw3DFrame->NewDisplay(); } GetScreen()->ClrModify(); updateView(); m_canvas->Refresh(); break; case ID_MODEDIT_PAD_SETTINGS: InstallPadOptionsFrame( NULL ); break; case ID_MODEDIT_CHECK: // Currently: not implemented break; case ID_MODEDIT_EDIT_MODULE_PROPERTIES: if( GetBoard()->m_Modules ) { SetCurItem( GetBoard()->m_Modules ); DIALOG_MODULE_MODULE_EDITOR dialog( this, (MODULE*) GetScreen()->GetCurItem() ); dialog.ShowModal(); GetScreen()->GetCurItem()->ClearFlags(); m_canvas->Refresh(); } break; case ID_POPUP_CLOSE_CURRENT_TOOL: break; case ID_POPUP_CANCEL_CURRENT_COMMAND: break; case ID_POPUP_PCB_ROTATE_MODULE_COUNTERCLOCKWISE: m_canvas->MoveCursorToCrossHair(); Rotate_Module( NULL, (MODULE*) GetScreen()->GetCurItem(), 900, true ); m_canvas->Refresh(); break; case ID_POPUP_PCB_ROTATE_MODULE_CLOCKWISE: m_canvas->MoveCursorToCrossHair(); Rotate_Module( NULL, (MODULE*) GetScreen()->GetCurItem(), -900, true ); m_canvas->Refresh(); break; case ID_POPUP_PCB_EDIT_MODULE_PRMS: { DIALOG_MODULE_MODULE_EDITOR dialog( this, (MODULE*) GetScreen()->GetCurItem() ); dialog.ShowModal(); GetScreen()->GetCurItem()->ClearFlags(); m_canvas->MoveCursorToCrossHair(); m_canvas->Refresh(); } break; case ID_POPUP_PCB_MOVE_PAD_REQUEST: m_canvas->MoveCursorToCrossHair(); StartMovePad( (D_PAD*) GetScreen()->GetCurItem(), &dc, false ); break; case ID_POPUP_PCB_EDIT_PAD: InstallPadOptionsFrame( (D_PAD*) GetScreen()->GetCurItem() ); m_canvas->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_DELETE_PAD: SaveCopyInUndoList( GetBoard()->m_Modules, UR_CHANGED ); DeletePad( (D_PAD*) GetScreen()->GetCurItem(), false ); SetCurItem( NULL ); m_canvas->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_DUPLICATE_ITEM: duplicateItems( false ); break; case ID_POPUP_PCB_DUPLICATE_ITEM_AND_INCREMENT: duplicateItems( true ); break; case ID_POPUP_PCB_MOVE_EXACT: moveExact(); break; case ID_POPUP_PCB_CREATE_ARRAY: createArray(); break; case ID_POPUP_PCB_APPLY_PAD_SETTINGS: SaveCopyInUndoList( GetBoard()->m_Modules, UR_CHANGED ); m_canvas->MoveCursorToCrossHair(); Import_Pad_Settings( (D_PAD*) GetScreen()->GetCurItem(), true ); break; case ID_POPUP_PCB_GLOBAL_IMPORT_PAD_SETTINGS: SaveCopyInUndoList( GetBoard()->m_Modules, UR_CHANGED ); // Calls the global change dialog: DlgGlobalChange_PadSettings( (D_PAD*) GetScreen()->GetCurItem() ); m_canvas->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_COPY_PAD_SETTINGS: m_canvas->MoveCursorToCrossHair(); Export_Pad_Settings( (D_PAD*) GetScreen()->GetCurItem() ); break; case ID_POPUP_PCB_EDIT_TEXTMODULE: InstallTextModOptionsFrame( static_cast<TEXTE_MODULE*>( GetScreen()->GetCurItem() ), &dc ); m_canvas->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_MOVE_TEXTMODULE_REQUEST: m_canvas->MoveCursorToCrossHair(); StartMoveTexteModule( static_cast<TEXTE_MODULE*>( GetScreen()->GetCurItem() ), &dc ); break; case ID_POPUP_PCB_ROTATE_TEXTMODULE: RotateTextModule( static_cast<TEXTE_MODULE*>( GetScreen()->GetCurItem() ), &dc ); m_canvas->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_DELETE_TEXTMODULE: SaveCopyInUndoList( GetBoard()->m_Modules, UR_CHANGED ); DeleteTextModule( static_cast<TEXTE_MODULE*>( GetScreen()->GetCurItem() ) ); SetCurItem( NULL ); m_canvas->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_MOVE_EDGE: Start_Move_EdgeMod( static_cast<EDGE_MODULE*>( GetScreen()->GetCurItem() ), &dc ); m_canvas->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_STOP_CURRENT_DRAWING: m_canvas->MoveCursorToCrossHair(); if( GetScreen()->GetCurItem()->IsNew() ) { End_Edge_Module( (EDGE_MODULE*) GetScreen()->GetCurItem() ); SetCurItem( NULL ); } break; case ID_POPUP_MODEDIT_ENTER_EDGE_WIDTH: { EDGE_MODULE* edge = NULL; if( GetScreen()->GetCurItem() && ( GetScreen()->GetCurItem()->Type() == PCB_MODULE_EDGE_T ) ) { edge = (EDGE_MODULE*) GetScreen()->GetCurItem(); } Enter_Edge_Width( edge ); m_canvas->MoveCursorToCrossHair(); if( edge ) m_canvas->Refresh(); } break; case ID_POPUP_MODEDIT_EDIT_BODY_ITEM : m_canvas->MoveCursorToCrossHair(); InstallFootprintBodyItemPropertiesDlg( (EDGE_MODULE*) GetScreen()->GetCurItem() ); m_canvas->Refresh(); break; case ID_POPUP_MODEDIT_EDIT_WIDTH_ALL_EDGE: m_canvas->MoveCursorToCrossHair(); Edit_Edge_Width( NULL ); m_canvas->Refresh(); break; case ID_POPUP_MODEDIT_EDIT_LAYER_ALL_EDGE: m_canvas->MoveCursorToCrossHair(); Edit_Edge_Layer( NULL ); m_canvas->Refresh(); break; case ID_POPUP_PCB_DELETE_EDGE: SaveCopyInUndoList( GetBoard()->m_Modules, UR_CHANGED ); m_canvas->MoveCursorToCrossHair(); RemoveStruct( GetScreen()->GetCurItem() ); SetCurItem( NULL ); break; case ID_MODEDIT_MODULE_ROTATE: case ID_MODEDIT_MODULE_MIRROR: case ID_MODEDIT_MODULE_MOVE_EXACT: SaveCopyInUndoList( GetBoard()->m_Modules, UR_CHANGED ); Transform( (MODULE*) GetScreen()->GetCurItem(), id ); m_canvas->Refresh(); break; case ID_PCB_DRAWINGS_WIDTHS_SETUP: InstallOptionsFrame( pos ); break; case ID_PCB_PAD_SETUP: { BOARD_ITEM* item = GetCurItem(); if( item ) { if( item->Type() != PCB_PAD_T ) item = NULL; } InstallPadOptionsFrame( (D_PAD*) item ); } break; case ID_PCB_USER_GRID_SETUP: InvokeDialogGrid(); break; case ID_POPUP_PLACE_BLOCK: GetScreen()->m_BlockLocate.SetCommand( BLOCK_MOVE ); m_canvas->SetAutoPanRequest( false ); HandleBlockPlace( &dc ); break; case ID_POPUP_COPY_BLOCK: GetScreen()->m_BlockLocate.SetCommand( BLOCK_COPY ); GetScreen()->m_BlockLocate.SetMessageBlock( this ); m_canvas->SetAutoPanRequest( false ); HandleBlockPlace( &dc ); break; case ID_POPUP_ZOOM_BLOCK: GetScreen()->m_BlockLocate.SetCommand( BLOCK_ZOOM ); GetScreen()->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); break; case ID_POPUP_DELETE_BLOCK: GetScreen()->m_BlockLocate.SetCommand( BLOCK_DELETE ); GetScreen()->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); break; case ID_POPUP_ROTATE_BLOCK: GetScreen()->m_BlockLocate.SetCommand( BLOCK_ROTATE ); GetScreen()->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); break; case ID_POPUP_MIRROR_X_BLOCK: GetScreen()->m_BlockLocate.SetCommand( BLOCK_MIRROR_X ); GetScreen()->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); break; case ID_POPUP_MOVE_BLOCK_EXACT: GetScreen()->m_BlockLocate.SetCommand( BLOCK_MOVE_EXACT ); GetScreen()->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); break; case ID_GEN_IMPORT_DXF_FILE: if( GetBoard()->m_Modules ) { InvokeDXFDialogModuleImport( this, GetBoard()->m_Modules ); m_canvas->Refresh(); } break; default: DisplayError( this, wxT( "FOOTPRINT_EDIT_FRAME::Process_Special_Functions error" ) ); break; } }
bool FOOTPRINT_EDIT_FRAME::SaveFootprintToBoard( bool aAddNew ) { // update module in the current board, // not just add it to the board with total disregard for the netlist... PCB_EDIT_FRAME* pcbframe = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB, false ); if( pcbframe == NULL ) // happens when the board editor is not active (or closed) { DisplayErrorMessage( this, _("No board currently open." ) ); return false; } BOARD* mainpcb = pcbframe->GetBoard(); MODULE* source_module = NULL; MODULE* module_in_edit = GetBoard()->m_Modules; // Search the old module (source) if exists // Because this source could be deleted when editing the main board... if( module_in_edit->GetLink() ) // this is not a new module ... { source_module = mainpcb->m_Modules; for( ; source_module != NULL; source_module = source_module->Next() ) { if( module_in_edit->GetLink() == source_module->GetTimeStamp() ) break; } } if( !aAddNew && source_module == NULL ) // source not found { DisplayError( this, _( "Unable to find the footprint on the main board.\nCannot save." ) ); return false; } if( aAddNew && source_module != NULL ) { DisplayError( this, _( "Footprint already exists on board." ) ); return false; } m_toolManager->RunAction( PCB_ACTIONS::selectionClear, true ); pcbframe->GetToolManager()->RunAction( PCB_ACTIONS::selectionClear, true ); BOARD_COMMIT commit( pcbframe ); // Create the "new" module MODULE* newmodule = new MODULE( *module_in_edit ); newmodule->SetParent( mainpcb ); newmodule->SetLink( 0 ); if( source_module ) // this is an update command { // In the main board, // the new module replace the old module (pos, orient, ref, value // and connexions are kept) // and the source_module (old module) is deleted pcbframe->Exchange_Module( source_module, newmodule, commit ); newmodule->SetTimeStamp( module_in_edit->GetLink() ); commit.Push( wxT( "Update module" ) ); } else // This is an insert command { wxPoint cursor_pos = pcbframe->GetCrossHairPosition(); commit.Add( newmodule ); pcbframe->SetCrossHairPosition( wxPoint( 0, 0 ) ); pcbframe->PlaceModule( newmodule, NULL ); newmodule->SetPosition( wxPoint( 0, 0 ) ); pcbframe->SetCrossHairPosition( cursor_pos ); newmodule->SetTimeStamp( GetNewTimeStamp() ); commit.Push( wxT( "Insert module" ) ); } newmodule->ClearFlags(); pcbframe->SetCurItem( NULL ); // @todo LEGACY should be unnecessary mainpcb->m_Status_Pcb = 0; return true; }