/* * 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_SHAPE_TRAPEZOID ) { pad->SetDelta( wxSize( 0, 0 ) ); } if( pad->GetShape() == PAD_SHAPE_CIRCLE ) { // Ensure pad size.y = pad size.x int size = pad->GetSize().x; pad->SetSize( wxSize( size, size ) ); } switch( pad->GetAttribute() ) { case PAD_ATTRIB_SMD: case PAD_ATTRIB_CONN: pad->SetDrillSize( wxSize( 0, 0 ) ); break; default: break; } } module->CalculateBoundingBox(); if( aRedraw ) m_canvas->RefreshDrawingRect( module->GetBoundingBox() ); } OnModify(); }
int EDIT_TOOL::CreateArray( const TOOL_EVENT& aEvent ) { // first, check if we have a selection, or try to get one SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); const SELECTION& selection = selTool->GetSelection(); // Be sure that there is at least one item that we can modify if( !hoverSelection( selection ) ) return 0; bool originalItemsModified = false; // we have a selection to work on now, so start the tool process PCB_BASE_FRAME* editFrame = getEditFrame<PCB_BASE_FRAME>(); editFrame->OnModify(); if( m_editModules ) { // Module editors do their undo point upfront for the whole module editFrame->SaveCopyInUndoList( editFrame->GetBoard()->m_Modules, UR_MODEDIT ); } else { // We may also change the original item editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED ); } DIALOG_CREATE_ARRAY::ARRAY_OPTIONS* array_opts = NULL; VECTOR2I rp = selection.GetCenter(); const wxPoint rotPoint( rp.x, rp.y ); DIALOG_CREATE_ARRAY dialog( editFrame, rotPoint, &array_opts ); int ret = dialog.ShowModal(); if( ret == wxID_OK && array_opts != NULL ) { PICKED_ITEMS_LIST newItemList; for( int i = 0; i < selection.Size(); ++i ) { BOARD_ITEM* item = selection.Item<BOARD_ITEM>( i ); if( !item ) continue; wxString cachedString; if( item->Type() == PCB_MODULE_T ) { cachedString = static_cast<MODULE*>( item )->GetReferencePrefix(); } else if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item ) ) { // Copy the text (not just take a reference cachedString = text->GetText(); } // iterate across the array, laying out the item at the // correct position const unsigned nPoints = array_opts->GetArraySize(); for( unsigned ptN = 0; ptN < nPoints; ++ptN ) { BOARD_ITEM* newItem = NULL; if( ptN == 0 ) newItem = item; else { // if renumbering, no need to increment const bool increment = !array_opts->ShouldRenumberItems(); // Some items cannot be duplicated // i.e. the ref and value fields of a footprint or zones // therefore newItem can be null if( m_editModules ) newItem = editFrame->GetBoard()->m_Modules->DuplicateAndAddItem( item, increment ); else { #if 0 // @TODO: see if we allow zone duplication here // Duplicate zones is especially tricky (overlaping zones must be merged) // so zones are not duplicated if( item->Type() == PCB_ZONE_AREA_T ) newItem = NULL; else #endif newItem = editFrame->GetBoard()->DuplicateAndAddItem( item, increment ); } if( newItem ) { array_opts->TransformItem( ptN, newItem, rotPoint ); m_toolMgr->RunAction( COMMON_ACTIONS::unselectItem, true, newItem ); newItemList.PushItem( newItem ); if( newItem->Type() == PCB_MODULE_T) { static_cast<MODULE*>( newItem )->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, getView(), _1 ) ); } editFrame->GetGalCanvas()->GetView()->Add( newItem ); getModel<BOARD>()->GetRatsnest()->Update( newItem ); } } // set the number if needed: if( newItem && array_opts->ShouldRenumberItems() ) { switch( newItem->Type() ) { case PCB_PAD_T: { const wxString padName = array_opts->GetItemNumber( ptN ); static_cast<D_PAD*>( newItem )->SetPadName( padName ); originalItemsModified = true; break; } case PCB_MODULE_T: { const wxString moduleName = array_opts->GetItemNumber( ptN ); MODULE* module = static_cast<MODULE*>( newItem ); module->SetReference( cachedString + moduleName ); originalItemsModified = true; break; } case PCB_MODULE_TEXT_T: case PCB_TEXT_T: { EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( newItem ); if( text ) text->SetText( array_opts->InterpolateNumberIntoString( ptN, cachedString ) ); originalItemsModified = true; break; } default: // no renumbering of other items break; } } } } if( !m_editModules ) { if( originalItemsModified ) { // Update the appearance of the original items selection.group->ItemsViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); } // Add all items as a single undo point for PCB editors // TODO: Can this be merged into the previous undo point (where // we saved the original items) editFrame->SaveCopyInUndoList( newItemList, UR_NEW ); } } getModel<BOARD>()->GetRatsnest()->Recalculate(); return 0; }
int SCH_SCREEN::GetConnection( const wxPoint& aPosition, PICKED_ITEMS_LIST& aList, bool aFullConnection ) { SCH_ITEM* item; EDA_ITEM* tmp; EDA_ITEMS list; // Clear flags member for all items. ClearDrawingState(); BreakSegmentsOnJunctions(); if( GetNode( aPosition, list ) == 0 ) return 0; for( size_t i = 0; i < list.size(); i++ ) { item = (SCH_ITEM*) list[ i ]; item->SetFlags( SELECTEDNODE | STRUCT_DELETED ); /* Put this structure in the picked list: */ ITEM_PICKER picker( item, UR_DELETED ); aList.PushItem( picker ); } // Mark all wires, junctions, .. connected to the item(s) found. if( aFullConnection ) { SCH_LINE* segment; for( item = m_drawList.begin(); item; item = item->Next() ) { if( !(item->GetFlags() & SELECTEDNODE) ) continue; if( item->Type() != SCH_LINE_T ) continue; MarkConnections( (SCH_LINE*) item ); } // Search all attached wires (i.e wire with one new dangling end ) for( item = m_drawList.begin(); item; item = item->Next() ) { bool noconnect = false; if( item->GetFlags() & STRUCT_DELETED ) continue; // Already seen if( !(item->GetFlags() & CANDIDATE) ) continue; // not a candidate if( item->Type() != SCH_LINE_T ) continue; item->SetFlags( SKIP_STRUCT ); segment = (SCH_LINE*) item; /* If the wire start point is connected to a wire that was already found * and now is not connected, add the wire to the list. */ for( tmp = m_drawList.begin(); tmp; tmp = tmp->Next() ) { // Ensure tmp is a previously deleted segment: if( ( tmp->GetFlags() & STRUCT_DELETED ) == 0 ) continue; if( tmp->Type() != SCH_LINE_T ) continue; SCH_LINE* testSegment = (SCH_LINE*) tmp; // Test for segment connected to the previously deleted segment: if( testSegment->IsEndPoint( segment->GetStartPoint() ) ) break; } // when tmp != NULL, segment is a new candidate: // put it in deleted list if // the start point is not connected to an other item (like pin) if( tmp && !CountConnectedItems( segment->GetStartPoint(), true ) ) noconnect = true; /* If the wire end point is connected to a wire that has already been found * and now is not connected, add the wire to the list. */ for( tmp = m_drawList.begin(); tmp; tmp = tmp->Next() ) { // Ensure tmp is a previously deleted segment: if( ( tmp->GetFlags() & STRUCT_DELETED ) == 0 ) continue; if( tmp->Type() != SCH_LINE_T ) continue; SCH_LINE* testSegment = (SCH_LINE*) tmp; // Test for segment connected to the previously deleted segment: if( testSegment->IsEndPoint( segment->GetEndPoint() ) ) break; } // when tmp != NULL, segment is a new candidate: // put it in deleted list if // the end point is not connected to an other item (like pin) if( tmp && !CountConnectedItems( segment->GetEndPoint(), true ) ) noconnect = true; item->ClearFlags( SKIP_STRUCT ); if( noconnect ) { item->SetFlags( STRUCT_DELETED ); ITEM_PICKER picker( item, UR_DELETED ); aList.PushItem( picker ); item = m_drawList.begin(); } } // Get redundant junctions (junctions which connect < 3 end wires // and no pin) for( item = m_drawList.begin(); item; item = item->Next() ) { if( item->GetFlags() & STRUCT_DELETED ) continue; if( !(item->GetFlags() & CANDIDATE) ) continue; if( item->Type() != SCH_JUNCTION_T ) continue; SCH_JUNCTION* junction = (SCH_JUNCTION*) item; if( CountConnectedItems( junction->GetPosition(), false ) <= 2 ) { item->SetFlags( STRUCT_DELETED ); ITEM_PICKER picker( item, UR_DELETED ); aList.PushItem( picker ); } } for( item = m_drawList.begin(); item; item = item->Next() ) { if( item->GetFlags() & STRUCT_DELETED ) continue; if( item->Type() != SCH_LABEL_T ) continue; tmp = GetWireOrBus( ( (SCH_TEXT*) item )->GetPosition() ); if( tmp && tmp->GetFlags() & STRUCT_DELETED ) { item->SetFlags( STRUCT_DELETED ); ITEM_PICKER picker( item, UR_DELETED ); aList.PushItem( picker ); } } } ClearDrawingState(); return aList.GetCount(); }
void PCB_EDIT_FRAME::Block_SelectItems() { LSET layerMask; bool selectOnlyComplete = GetScreen()->m_BlockLocate.GetWidth() > 0 ; GetScreen()->m_BlockLocate.Normalize(); PICKED_ITEMS_LIST* itemsList = &GetScreen()->m_BlockLocate.GetItems(); ITEM_PICKER picker( NULL, UR_UNSPECIFIED ); // Add modules if( blockIncludeModules ) { for( MODULE* module = m_Pcb->m_Modules; module; module = module->Next() ) { LAYER_ID layer = module->GetLayer(); if( module->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) && ( !module->IsLocked() || blockIncludeLockedModules ) ) { if( blockIncludeItemsOnInvisibleLayers || m_Pcb->IsModuleLayerVisible( layer ) ) { picker.SetItem ( module ); itemsList->PushItem( picker ); } } } } // Add tracks and vias if( blockIncludeTracks ) { for( TRACK* track = m_Pcb->m_Track; track != NULL; track = track->Next() ) { if( track->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) ) { if( blockIncludeItemsOnInvisibleLayers || m_Pcb->IsLayerVisible( track->GetLayer() ) ) { picker.SetItem( track ); itemsList->PushItem( picker ); } } } } // Add graphic items layerMask = LSET( Edge_Cuts ); if( blockIncludeItemsOnTechLayers ) layerMask.set(); if( !blockIncludeBoardOutlineLayer ) layerMask.set( Edge_Cuts, false ); for( BOARD_ITEM* PtStruct = m_Pcb->m_Drawings; PtStruct != NULL; PtStruct = PtStruct->Next() ) { if( !m_Pcb->IsLayerVisible( PtStruct->GetLayer() ) && ! blockIncludeItemsOnInvisibleLayers) continue; bool select_me = false; switch( PtStruct->Type() ) { case PCB_LINE_T: if( !layerMask[PtStruct->GetLayer()] ) break; if( !PtStruct->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) ) break; select_me = true; // This item is in bloc: select it break; case PCB_TEXT_T: if( !blockIncludePcbTexts ) break; if( !PtStruct->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) ) break; select_me = true; // This item is in bloc: select it break; case PCB_TARGET_T: if( !layerMask[PtStruct->GetLayer()] ) break; if( !PtStruct->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) ) break; select_me = true; // This item is in bloc: select it break; case PCB_DIMENSION_T: if( !layerMask[PtStruct->GetLayer()] ) break; if( !PtStruct->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) ) break; select_me = true; // This item is in bloc: select it break; default: break; } if( select_me ) { picker.SetItem ( PtStruct ); itemsList->PushItem( picker ); } } // Add zones if( blockIncludeZones ) { for( int ii = 0; ii < m_Pcb->GetAreaCount(); ii++ ) { ZONE_CONTAINER* area = m_Pcb->GetArea( ii ); if( area->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) ) { if( blockIncludeItemsOnInvisibleLayers || m_Pcb->IsLayerVisible( area->GetLayer() ) ) { BOARD_ITEM* zone_c = (BOARD_ITEM*) area; picker.SetItem ( zone_c ); itemsList->PushItem( picker ); } } } } }
void PCB_EDIT_FRAME::SaveCopyInUndoList( BOARD_ITEM* aItem, UNDO_REDO_T aCommandType, const wxPoint& aTransformPoint ) { if( aItem == NULL ) // Nothing to save return; // For texts belonging to modules, we need to save state of the parent module if( aItem->Type() == PCB_MODULE_TEXT_T ) { aItem = aItem->GetParent(); wxASSERT( aItem->Type() == PCB_MODULE_T ); aCommandType = UR_CHANGED; if( aItem == NULL ) return; } PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST(); commandToUndo->m_TransformPoint = aTransformPoint; ITEM_PICKER itemWrapper( aItem, aCommandType ); switch( aCommandType ) { case UR_CHANGED: // Create a copy of item if( itemWrapper.GetLink() == NULL ) // When not null, the copy is already done itemWrapper.SetLink( aItem->Clone() ); commandToUndo->PushItem( itemWrapper ); break; case UR_NEW: case UR_DELETED: #ifdef USE_WX_OVERLAY // Avoid to redraw when autoplacing if( aItem->Type() == PCB_MODULE_T ) if( ((MODULE*)aItem)->GetFlags() & MODULE_to_PLACE ) break; m_canvas->Refresh(); #endif case UR_MOVED: case UR_FLIPPED: case UR_ROTATED: case UR_ROTATED_CLOCKWISE: commandToUndo->PushItem( itemWrapper ); break; default: { wxString msg; msg.Printf( wxT( "SaveCopyInUndoList() error (unknown code %X)" ), aCommandType ); wxMessageBox( msg ); } break; } if( commandToUndo->GetCount() ) { /* Save the copy in undo list */ GetScreen()->PushCommandToUndoList( commandToUndo ); /* Clear redo list, because after new save there is no redo to do */ GetScreen()->ClearUndoORRedoList( GetScreen()->m_RedoList ); } else { delete commandToUndo; } }
void PCB_BASE_FRAME::ResetModuleTextSizes( const wxString & aFilter, bool aRef, bool aValue, bool aOthers ) { MODULE* module; BOARD_ITEM* boardItem; TEXTE_MODULE* item; ITEM_PICKER itemWrapper( NULL, UR_CHANGED ); PICKED_ITEMS_LIST undoItemList; unsigned int ii; // Prepare undo list for( module = GetBoard()->m_Modules; module; module = module->Next() ) { itemWrapper.SetItem( module ); if( ! aFilter.IsEmpty() ) { if( ! WildCompareString( aFilter, FROM_UTF8( module->GetFPID().Format().c_str() ), false ) ) continue; } if( aRef ) { item = &module->Reference(); if( item->GetSize() != GetDesignSettings().m_ModuleTextSize || item->GetThickness() != GetDesignSettings().m_ModuleTextWidth ) { undoItemList.PushItem( itemWrapper ); } } if( aValue ) { item = &module->Value(); if( item->GetSize() != GetDesignSettings().m_ModuleTextSize || item->GetThickness() != GetDesignSettings().m_ModuleTextWidth ) { undoItemList.PushItem( itemWrapper ); } } if( aOthers ) { // Go through all other module text fields for( boardItem = module->GraphicalItems(); boardItem; boardItem = boardItem->Next() ) { if( boardItem->Type() == PCB_MODULE_TEXT_T ) { item = (TEXTE_MODULE*) boardItem; if( item->GetSize() != GetDesignSettings().m_ModuleTextSize || item->GetThickness() != GetDesignSettings().m_ModuleTextWidth ) { undoItemList.PushItem( itemWrapper ); } } } } } // Exit if there's nothing to do if( !undoItemList.GetCount() ) return; SaveCopyInUndoList( undoItemList, UR_CHANGED ); // Apply changes to modules in the undo list for( ii = 0; ii < undoItemList.GetCount(); ii++ ) { module = (MODULE*) undoItemList.GetPickedItem( ii ); if( aRef ) { module->Reference().SetThickness( GetDesignSettings().m_ModuleTextWidth ); module->Reference().SetSize( GetDesignSettings().m_ModuleTextSize ); } if( aValue ) { module->Value().SetThickness( GetDesignSettings().m_ModuleTextWidth ); module->Value().SetSize( GetDesignSettings().m_ModuleTextSize ); } if( aOthers ) { for( boardItem = module->GraphicalItems(); boardItem; boardItem = boardItem->Next() ) { if( boardItem->Type() == PCB_MODULE_TEXT_T ) { item = (TEXTE_MODULE*) boardItem; item->SetThickness( GetDesignSettings().m_ModuleTextWidth ); item->SetSize( GetDesignSettings().m_ModuleTextSize ); } } } } OnModify(); }