int EDIT_TOOL::Remove( const TOOL_EVENT& aEvent ) { const SELECTION& selection = m_selectionTool->GetSelection(); if( !hoverSelection( selection ) ) return 0; // Get a copy of the selected items set PICKED_ITEMS_LIST selectedItems = selection.items; PCB_BASE_FRAME* editFrame = getEditFrame<PCB_BASE_FRAME>(); // As we are about to remove items, they have to be removed from the selection first m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); // Save them for( unsigned int i = 0; i < selectedItems.GetCount(); ++i ) selectedItems.SetPickedItemStatus( UR_DELETED, i ); editFrame->OnModify(); editFrame->SaveCopyInUndoList( selectedItems, UR_DELETED ); // And now remove for( unsigned int i = 0; i < selectedItems.GetCount(); ++i ) remove( static_cast<BOARD_ITEM*>( selectedItems.GetPickedItem( i ) ) ); getModel<BOARD>()->GetRatsnest()->Recalculate(); return 0; }
void DuplicateItemsInList( SCH_SCREEN* screen, PICKED_ITEMS_LIST& aItemsList, const wxPoint& aMoveVector ) { SCH_ITEM* newitem; if( aItemsList.GetCount() == 0 ) return; for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { newitem = DuplicateStruct( (SCH_ITEM*) aItemsList.GetPickedItem( ii ) ); aItemsList.SetPickedItem( newitem, ii ); aItemsList.SetPickedItemStatus( UR_NEW, ii ); { switch( newitem->Type() ) { case SCH_JUNCTION_T: case SCH_LINE_T: case SCH_BUS_BUS_ENTRY_T: case SCH_BUS_WIRE_ENTRY_T: case SCH_TEXT_T: case SCH_LABEL_T: case SCH_GLOBAL_LABEL_T: case SCH_HIERARCHICAL_LABEL_T: case SCH_SHEET_PIN_T: case SCH_MARKER_T: case SCH_NO_CONNECT_T: default: break; case SCH_SHEET_T: { SCH_SHEET* sheet = (SCH_SHEET*) newitem; sheet->SetTimeStamp( GetNewTimeStamp() ); break; } case SCH_COMPONENT_T: ( (SCH_COMPONENT*) newitem )->SetTimeStamp( GetNewTimeStamp() ); ( (SCH_COMPONENT*) newitem )->ClearAnnotation( NULL ); break; } SetSchItemParent( newitem, screen ); screen->Append( newitem ); } } MoveItemsInList( aItemsList, aMoveVector ); }
/** * Function DeleteItemsInList * delete schematic items in aItemsList * deleted items are put in undo list */ void DeleteItemsInList( EDA_DRAW_PANEL* panel, PICKED_ITEMS_LIST& aItemsList ) { SCH_SCREEN* screen = (SCH_SCREEN*) panel->GetScreen(); SCH_EDIT_FRAME* frame = (SCH_EDIT_FRAME*) panel->GetParent(); PICKED_ITEMS_LIST itemsList; for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii ); ITEM_PICKER itemWrapper( item, UR_DELETED ); if( item->Type() == SCH_SHEET_PIN_T ) { /* this item is depending on a sheet, and is not in global list */ wxMessageBox( wxT( "DeleteItemsInList() err: unexpected SCH_SHEET_PIN_T" ) ); } else { screen->Remove( item ); /* Unlink the structure */ itemsList.PushItem( itemWrapper ); } } frame->SaveCopyInUndoList( itemsList, UR_DELETED ); }
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 ); }
void PCB_EDIT_FRAME::Block_Flip() { #define INVERT( pos ) (pos) = center.y - ( (pos) - center.y ) wxPoint memo; wxPoint center; // Position of the axis for inversion of all elements OnModify(); PICKED_ITEMS_LIST* itemsList = &GetScreen()->m_BlockLocate.GetItems(); itemsList->m_Status = UR_FLIPPED; memo = GetCrossHairPosition(); center = GetScreen()->m_BlockLocate.Centre(); for( unsigned ii = 0; ii < itemsList->GetCount(); ii++ ) { BOARD_ITEM* item = (BOARD_ITEM*) itemsList->GetPickedItem( ii ); wxASSERT( item ); itemsList->SetPickedItemStatus( UR_FLIPPED, ii ); item->Flip( center ); switch( item->Type() ) { case PCB_MODULE_T: item->ClearFlags(); m_Pcb->m_Status_Pcb = 0; break; // Move and rotate the track segments 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) m_Pcb->m_Status_Pcb = 0; break; case PCB_ZONE_AREA_T: case PCB_LINE_T: case PCB_TEXT_T: case PCB_TARGET_T: case PCB_DIMENSION_T: break; // This item is not put in undo list case PCB_ZONE_T: // SEG_ZONE items are now deprecated itemsList->RemovePicker( ii ); ii--; break; default: wxMessageBox( wxT( "PCB_EDIT_FRAME::Block_Flip( ) error: unexpected type" ) ); break; } } SaveCopyInUndoList( *itemsList, UR_FLIPPED, center ); Compile_Ratsnest( NULL, true ); m_canvas->Refresh( true ); }
void MoveItemsInList( PICKED_ITEMS_LIST& aItemsList, const wxPoint& aMoveVector ) { for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii ); item->Move( aMoveVector ); } }
void PCB_EDIT_FRAME::Block_Rotate() { wxPoint oldpos; wxPoint centre; // rotation cent-re for the rotation transform int rotAngle = 900; // rotation angle in 0.1 deg. oldpos = GetScreen()->GetCrossHairPosition(); centre = GetScreen()->m_BlockLocate.Centre(); OnModify(); PICKED_ITEMS_LIST* itemsList = &GetScreen()->m_BlockLocate.m_ItemsSelection; itemsList->m_Status = UR_ROTATED; for( unsigned ii = 0; ii < itemsList->GetCount(); ii++ ) { BOARD_ITEM* item = (BOARD_ITEM*) itemsList->GetPickedItem( ii ); wxASSERT( item ); itemsList->SetPickedItemStatus( UR_ROTATED, ii ); item->Rotate( centre, rotAngle ); switch( item->Type() ) { case PCB_MODULE_T: ( (MODULE*) item )->ClearFlags(); m_Pcb->m_Status_Pcb = 0; break; /* Move and rotate the track segments */ 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) m_Pcb->m_Status_Pcb = 0; break; case PCB_ZONE_AREA_T: case PCB_LINE_T: case PCB_TEXT_T: case PCB_TARGET_T: case PCB_DIMENSION_T: break; // This item is not put in undo list case PCB_ZONE_T: // SEG_ZONE items are now deprecated itemsList->RemovePicker( ii ); ii--; break; default: wxMessageBox( wxT( "PCB_EDIT_FRAME::Block_Rotate( ) error: unexpected type" ) ); break; } } SaveCopyInUndoList( *itemsList, UR_ROTATED, centre ); Compile_Ratsnest( NULL, true ); m_canvas->Refresh( true ); }
void MirrorX( PICKED_ITEMS_LIST& aItemsList, const wxPoint& aMirrorPoint ) { for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii ); item->MirrorX( aMirrorPoint.y ); // Place it in its new position. item->ClearFlags(); } }
void RotateListOfItems( PICKED_ITEMS_LIST& aItemsList, const wxPoint& rotationPoint ) { for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii ); item->Rotate( rotationPoint ); // Place it in its new position. item->ClearFlags(); } }
void PCB_EDIT_FRAME::Delete_Drawings_All_Layer( LAYER_ID aLayer ) { if( IsCopperLayer( aLayer ) ) { DisplayError( this, _( "Copper layer global delete not allowed!" ) ); return; } wxString msg = wxString::Format( _( "Delete everything on layer %s?" ), GetChars( GetBoard()->GetLayerName( aLayer ) ) ); if( !IsOK( this, msg ) ) return; PICKED_ITEMS_LIST pickList; ITEM_PICKER picker( NULL, UR_DELETED ); BOARD_ITEM* PtNext; for( BOARD_ITEM* item = GetBoard()->m_Drawings; item; item = PtNext ) { PtNext = item->Next(); switch( item->Type() ) { case PCB_LINE_T: case PCB_TEXT_T: case PCB_DIMENSION_T: case PCB_TARGET_T: if( item->GetLayer() == aLayer ) { item->UnLink(); picker.SetItem( item ); pickList.PushItem( picker ); } break; default: { wxString msg; msg.Printf( wxT("Delete_Drawings_All_Layer() error: unknown type %d"), item->Type() ); wxMessageBox( msg ); break; } } } if( pickList.GetCount() ) { OnModify(); SaveCopyInUndoList(pickList, UR_DELETED); } }
/* * Function SaveCopyInUndoList * Create a copy of the current board item, and put it in the undo list. * * aCommandType = * UR_CHANGED * UR_NEW * UR_DELETED * UR_MOVED * UR_FLIPPED * UR_ROTATED */ void PCB_EDIT_FRAME::SaveCopyInUndoList( BOARD_ITEM* aItem, UNDO_REDO_T aCommandType, const wxPoint& aTransformPoint ) { if( aItem == NULL ) // Nothing to save 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 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_EDIT_FRAME::Block_Duplicate( bool aIncrement ) { wxPoint MoveVector = GetScreen()->m_BlockLocate.GetMoveVector(); OnModify(); PICKED_ITEMS_LIST* itemsList = &GetScreen()->m_BlockLocate.GetItems(); PICKED_ITEMS_LIST newList; newList.m_Status = UR_NEW; ITEM_PICKER picker( NULL, UR_NEW ); BOARD_ITEM* newitem; for( unsigned ii = 0; ii < itemsList->GetCount(); ii++ ) { BOARD_ITEM* item = (BOARD_ITEM*) itemsList->GetPickedItem( ii ); newitem = (BOARD_ITEM*)item->Clone(); if( aIncrement ) newitem->IncrementItemReference(); if( item->Type() == PCB_MODULE_T ) m_Pcb->m_Status_Pcb = 0; m_Pcb->Add( newitem ); if( newitem ) { newitem->Move( MoveVector ); picker.SetItem ( newitem ); newList.PushItem( picker ); } } if( newList.GetCount() ) SaveCopyInUndoList( newList, UR_NEW ); Compile_Ratsnest( NULL, true ); m_canvas->Refresh( true ); }
void PCB_EDIT_FRAME::Block_Move() { OnModify(); wxPoint MoveVector = GetScreen()->m_BlockLocate.GetMoveVector(); PICKED_ITEMS_LIST* itemsList = &GetScreen()->m_BlockLocate.GetItems(); itemsList->m_Status = UR_MOVED; for( unsigned ii = 0; ii < itemsList->GetCount(); ii++ ) { BOARD_ITEM* item = (BOARD_ITEM*) itemsList->GetPickedItem( ii ); itemsList->SetPickedItemStatus( UR_MOVED, ii ); item->Move( MoveVector ); GetBoard()->GetConnectivity()->Update( item ); item->ClearFlags( IS_MOVED ); switch( item->Type() ) { case PCB_MODULE_T: m_Pcb->m_Status_Pcb = 0; item->ClearFlags(); break; // Move track segments case PCB_TRACE_T: // a track segment (segment on a copper layer) case PCB_VIA_T: // a via (like a track segment on a copper layer) m_Pcb->m_Status_Pcb = 0; break; case PCB_ZONE_AREA_T: case PCB_LINE_T: case PCB_TEXT_T: case PCB_TARGET_T: case PCB_DIMENSION_T: break; // This item is not put in undo list case PCB_ZONE_T: // SEG_ZONE items are now deprecated itemsList->RemovePicker( ii ); ii--; break; default: wxMessageBox( wxT( "PCB_EDIT_FRAME::Block_Move( ) error: unexpected type" ) ); break; } } SaveCopyInUndoList( *itemsList, UR_MOVED, MoveVector ); Compile_Ratsnest( NULL, true ); m_canvas->Refresh( true ); }
void SCH_EDIT_FRAME::CheckListConnections( PICKED_ITEMS_LIST& aItemsList, bool aAppend ) { std::vector< wxPoint > pts; std::vector< wxPoint > connections; GetSchematicConnections( connections ); for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii ); std::vector< wxPoint > new_pts; if( !item->IsConnectable() ) continue; item->GetConnectionPoints( new_pts ); pts.insert( pts.end(), new_pts.begin(), new_pts.end() ); // If the item is a line, we also add any connection points from the rest of the schematic // that terminate on the line after it is moved. if( item->Type() == SCH_LINE_T ) { SCH_LINE* line = (SCH_LINE*) item; for( auto i : connections ) if( IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), i ) ) pts.push_back( i ); } else { // Clean up any wires that short non-wire connections in the list for( auto point = new_pts.begin(); point != new_pts.end(); point++ ) { for( auto second_point = point + 1; second_point != new_pts.end(); second_point++ ) { aAppend |= TrimWire( *point, *second_point, aAppend ); } } } } // We always have some overlapping connection points. Drop duplicates here std::sort( pts.begin(), pts.end(), []( const wxPoint& a, const wxPoint& b ) -> bool { return a.x < b.x || (a.x == b.x && a.y < b.y); } ); pts.erase( unique( pts.begin(), pts.end() ), pts.end() ); for( auto point : pts ) { if( GetScreen()->IsJunctionNeeded( point, true ) ) { AddJunction( point, aAppend ); aAppend = true; } } }
void SCH_EDIT_FRAME::SaveCopyInUndoList( SCH_ITEM* aItem, UNDO_REDO_T aCommandType, const wxPoint& aTransformPoint ) { /* Does not save a null item or a UR_WIRE_IMAGE command type. UR_WIRE_IMAGE commands * are handled by the overloaded version of SaveCopyInUndoList that takes a reference * to a PICKED_ITEMS_LIST. */ if( aItem == NULL || aCommandType == UR_WIRE_IMAGE ) return; PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST(); commandToUndo->m_TransformPoint = aTransformPoint; ITEM_PICKER itemWrapper( aItem, aCommandType ); if( aItem ) itemWrapper.SetFlags( aItem->GetFlags() ); switch( aCommandType ) { case UR_CHANGED: /* Create a copy of item */ itemWrapper.SetLink( DuplicateStruct( aItem, true ) ); commandToUndo->PushItem( itemWrapper ); break; case UR_NEW: case UR_DELETED: case UR_ROTATED: case UR_MOVED: commandToUndo->PushItem( itemWrapper ); break; default: wxFAIL_MSG( wxString::Format( wxT( "SaveCopyInUndoList() error (unknown code %X)" ), aCommandType ) ); 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_EDIT_FRAME::Edit_Track_Width( wxDC* aDC, TRACK* aTrackSegment ) { /* Modify a full track (a trace) width (using DRC control). * a full track is the set of track segments between 2 nodes: pads or a node that has * more than 2 segments connected * aDC = the curred device context (can be NULL) * aTrackSegment = a via or a track belonging to the trace to change */ TRACK* pt_track; int nb_segm; if( aTrackSegment == NULL ) return; pt_track = GetBoard()->MarkTrace( GetBoard()->m_Track, aTrackSegment, &nb_segm, NULL, NULL, true ); PICKED_ITEMS_LIST itemsListPicker; bool change = false; for( int ii = 0; ii < nb_segm; ii++, pt_track = pt_track->Next() ) { pt_track->SetState( BUSY, false ); if( !SetTrackSegmentWidth( pt_track, &itemsListPicker, false ) ) change = true; } if( !change ) return; // Some segment have changed: redraw them and save in undo list if( aDC ) { m_canvas->CrossHairOff( aDC ); // Erase cursor shape for( unsigned ii = 0; ii < itemsListPicker.GetCount(); ii++ ) { TRACK* segm = (TRACK*) itemsListPicker.GetPickedItemLink( ii ); segm->Draw( m_canvas, aDC, GR_XOR ); // Erase old track shape segm = (TRACK*) itemsListPicker.GetPickedItem( ii ); segm->Draw( m_canvas, aDC, GR_OR ); // Display new track shape // fixme: commit! // segm->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); } m_canvas->CrossHairOn( aDC ); // Display cursor shape } SaveCopyInUndoList( itemsListPicker, UR_CHANGED ); }
void FOOTPRINT_EDIT_FRAME::SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList, UNDO_REDO_T aTypeCommand, const wxPoint& aTransformPoint ) { assert( aItemsList.GetPickedItem( 0 )->GetParent()->Type() == PCB_MODULE_T ); MODULE* owner = static_cast<MODULE*>( aItemsList.GetPickedItem( 0 )->GetParent() ); #ifndef NDEBUG // All items should have the same parent (MODULE) to make undo/redo entry valid for( unsigned int i = 0; i < aItemsList.GetCount(); ++i ) assert( aItemsList.GetPickedItem( i )->GetParent() == owner ); #endif /* not NDEBUG */ SaveCopyInUndoList( owner, aTypeCommand, aTransformPoint ); }
void SCH_EDIT_FRAME::DeleteItemsInList( PICKED_ITEMS_LIST& aItemsList, bool aAppend ) { PICKED_ITEMS_LIST itemsList; for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii ); ITEM_PICKER itemWrapper( item, UR_DELETED ); if( item->GetFlags() & STRUCT_DELETED ) continue; DeleteItem( item, aAppend ); aAppend = true; } GetScreen()->ClearDrawingState(); }
/** * Function Edit_Track_Width * Modify a full track width (using DRC control). * a full track is the set of track segments between 2 ends: pads or a point that has * more than 2 segments ends connected * @param aDC = the curred device context (can be NULL) * @param aTrackSegment = a segment or via on the track to change */ void PCB_EDIT_FRAME::Edit_Track_Width( wxDC* aDC, TRACK* aTrackSegment ) { TRACK* pt_track; int nb_segm; if( aTrackSegment == NULL ) return; pt_track = GetBoard()->MarkTrace( aTrackSegment, &nb_segm, NULL, NULL, true ); PICKED_ITEMS_LIST itemsListPicker; bool change = false; for( int ii = 0; ii < nb_segm; ii++, pt_track = pt_track->Next() ) { pt_track->SetState( BUSY, false ); if( SetTrackSegmentWidth( pt_track, &itemsListPicker, false ) ) change = true; } if( !change ) return; // Some segment have changed: redraw them and save in undo list if( aDC ) { m_canvas->CrossHairOff( aDC ); // Erase cursor shape for( unsigned ii = 0; ii < itemsListPicker.GetCount(); ii++ ) { TRACK* segm = (TRACK*) itemsListPicker.GetPickedItemLink( ii ); segm->Draw( m_canvas, aDC, GR_XOR ); // Erase old track shape segm = (TRACK*) itemsListPicker.GetPickedItem( ii ); segm->Draw( m_canvas, aDC, GR_OR ); // Display new track shape } m_canvas->CrossHairOn( aDC ); // Display cursor shape } SaveCopyInUndoList( itemsListPicker, UR_CHANGED ); }
void SCH_EDIT_FRAME::copyBlockItems( PICKED_ITEMS_LIST& aItemsList ) { m_blockItems.ClearListAndDeleteItems(); // delete previous saved list, if exists for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { // Clear m_Flag member of selected items: aItemsList.GetPickedItem( ii )->ClearFlags(); /* Make a copy of the original picked item. */ SCH_ITEM* copy = DuplicateStruct( (SCH_ITEM*) aItemsList.GetPickedItem( ii ) ); copy->SetParent( NULL ); // In list the wrapper is owner of the schematic item, we can use the UR_DELETED // status for the picker because pickers with this status are owner of the picked item // (or TODO ?: create a new status like UR_DUPLICATE) ITEM_PICKER item( copy, UR_DELETED ); m_blockItems.PushItem( item ); } }
static void drawPickedItems( EDA_DRAW_PANEL* aPanel, wxDC* aDC, wxPoint aOffset ) { PICKED_ITEMS_LIST* itemsList = &aPanel->GetScreen()->m_BlockLocate.GetItems(); PCB_BASE_FRAME* frame = (PCB_BASE_FRAME*) aPanel->GetParent(); g_Offset_Module = -aOffset; for( unsigned ii = 0; ii < itemsList->GetCount(); ii++ ) { BOARD_ITEM* item = (BOARD_ITEM*) itemsList->GetPickedItem( ii ); switch( item->Type() ) { case PCB_MODULE_T: frame->GetBoard()->m_Status_Pcb &= ~RATSNEST_ITEM_LOCAL_OK; ((MODULE*) item)->DrawOutlinesWhenMoving( aPanel, aDC, g_Offset_Module ); break; case PCB_LINE_T: case PCB_TEXT_T: case PCB_TRACE_T: case PCB_VIA_T: case PCB_TARGET_T: case PCB_DIMENSION_T: // Currently markers are not affected by block commands case PCB_MARKER_T: item->Draw( aPanel, aDC, GR_XOR, aOffset ); break; case PCB_ZONE_AREA_T: item->Draw( aPanel, aDC, GR_XOR, aOffset ); ((ZONE_CONTAINER*) item)->DrawFilledArea( aPanel, aDC, GR_XOR, aOffset ); break; default: break; } } g_Offset_Module = wxPoint( 0, 0 ); }
void PCB_BASE_EDIT_FRAME::SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList, UNDO_REDO_T aTypeCommand, const wxPoint& aTransformPoint ) { PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST(); commandToUndo->m_TransformPoint = aTransformPoint; // First, filter unnecessary stuff from the list (i.e. for multiple pads / labels modified), // take the first occurence of the module (we save copies of modules when one of its subitems // is changed). for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { ITEM_PICKER curr_picker = aItemsList.GetItemWrapper(ii); BOARD_ITEM* item = (BOARD_ITEM*) aItemsList.GetPickedItem( ii ); // For items belonging to modules, we need to save state of the parent module if( item->Type() == PCB_MODULE_TEXT_T || item->Type() == PCB_MODULE_EDGE_T || item->Type() == PCB_PAD_T ) { // Item to be stored in the undo buffer is the parent module item = item->GetParent(); wxASSERT( item && item->Type() == PCB_MODULE_T ); if( item == NULL ) continue; // Check if the parent module has already been saved in another entry bool found = false; for( unsigned j = 0; j < commandToUndo->GetCount(); j++ ) { if( commandToUndo->GetPickedItem( j ) == item && commandToUndo->GetPickedItemStatus( j ) == UR_CHANGED ) { found = true; break; } } if( !found ) { // Create a clean copy of the parent module MODULE* orig = static_cast<MODULE*>( item ); MODULE* clone = new MODULE( *orig ); clone->SetParent( GetBoard() ); // Clear current flags (which can be temporary set by a current edit command) for( EDA_ITEM* loc_item = clone->GraphicalItemsList(); loc_item; loc_item = loc_item->Next() ) loc_item->ClearFlags(); for( D_PAD* pad = clone->PadsList(); pad; pad = pad->Next() ) pad->ClearFlags(); clone->Reference().ClearFlags(); clone->Value().ClearFlags(); ITEM_PICKER picker( item, UR_CHANGED ); picker.SetLink( clone ); commandToUndo->PushItem( picker ); orig->SetLastEditTime(); } else { continue; } } else { // Normal case: all other BOARD_ITEMs, are simply copied to the new list commandToUndo->PushItem( curr_picker ); } } for( unsigned ii = 0; ii < commandToUndo->GetCount(); ii++ ) { BOARD_ITEM* item = (BOARD_ITEM*) commandToUndo->GetPickedItem( ii ); UNDO_REDO_T command = commandToUndo->GetPickedItemStatus( ii ); if( command == UR_UNSPECIFIED ) { command = aTypeCommand; commandToUndo->SetPickedItemStatus( command, ii ); } wxASSERT( item ); switch( command ) { case UR_CHANGED: case UR_DRILLORIGIN: case UR_GRIDORIGIN: /* If needed, create a copy of item, and put in undo list * in the picker, as link * If this link is not null, the copy is already done */ if( commandToUndo->GetPickedItemLink( ii ) == NULL ) { EDA_ITEM* cloned = item->Clone(); commandToUndo->SetPickedItemLink( cloned, ii ); } break; case UR_MOVED: case UR_ROTATED: case UR_ROTATED_CLOCKWISE: case UR_FLIPPED: case UR_NEW: case UR_DELETED: break; default: { wxLogDebug( wxT( "SaveCopyInUndoList() error (unknown code %X)" ), command ); } break; } } if( commandToUndo->GetCount() ) { /* Save the copy in undo list */ GetScreen()->PushCommandToUndoList( commandToUndo ); /* Clear redo list, because after a new command one cannot redo a command */ GetScreen()->ClearUndoORRedoList( GetScreen()->m_RedoList ); } else { // Should not occur wxASSERT( false ); delete commandToUndo; } }
/** * Function UpdateCopyOfZonesList * check a pick list to remove zones identical to their copies * and set the type of operation in picker (UR_DELETED, UR_CHANGED) * if an item is deleted, the initial values are retrievered, * because they can have changed in edition * @param aPickList = the main pick list * @param aAuxiliaryList = the list of deleted or added (new created) items after calculations * @param aPcb = the Board * * aAuxiliaryList is a list of pickers updated by zone algorithms: * This list contains zones which were added or deleted during the zones combine process * aPickList :is a list of zones that can be modified (changed or deleted, or not modified) * Typically, this is the list of existing zones on the layer of the edited zone, * before any change. * >> if the picked zone is not changed, it is removed from list * >> if the picked zone was deleted (i.e. not found in board list), the picker is modified: * its status becomes UR_DELETED * the aAuxiliaryList corresponding picker is removed (if not found : set an error) * >> if the picked zone was flagged as UR_NEW, and was after deleted , * perhaps combined with an other zone (i.e. not found in board list): * the picker is removed * the zone itself if really deleted * the aAuxiliaryList corresponding picker is removed (if not found : set an error) * After aPickList is cleaned, the aAuxiliaryList is read * All pickers flagged UR_NEW are moved to aPickList * (the corresponding zones are zone that were created by the zone normalize and combine process, * mainly when adding cutout areas, or creating self intersecting contours) * All pickers flagged UR_DELETED are removed, and the coresponding zones actually deleted * (the corresponding zones are new zone that were created by the zone normalize process, * when creating self intersecting contours, and after combined with an existing zone. * At the end of the update process the aAuxiliaryList must be void, * because all pickers created by the combine process * must have been removed (removed for new and deleted zones, or moved in aPickList.) * If not an error is set. */ void UpdateCopyOfZonesList( PICKED_ITEMS_LIST& aPickList, PICKED_ITEMS_LIST& aAuxiliaryList, BOARD* aPcb ) { for( unsigned kk = 0; kk < aPickList.GetCount(); kk++ ) { UNDO_REDO_T status = aPickList.GetPickedItemStatus( kk ); ZONE_CONTAINER* ref = (ZONE_CONTAINER*) aPickList.GetPickedItem( kk ); for( unsigned ii = 0; ; ii++ ) // analyse the main picked list { ZONE_CONTAINER* zone = aPcb->GetArea( ii ); if( zone == NULL ) { /* End of list: the stored item is not found: * it must be in aDeletedList: * search it and restore initial values * or * if flagged UR_NEW: remove it definitively */ if( status == UR_NEW ) { delete ref; ref = NULL; aPickList.RemovePicker( kk ); kk--; } else { ZONE_CONTAINER* zcopy = (ZONE_CONTAINER*) aPickList.GetPickedItemLink( kk ); aPickList.SetPickedItemStatus( UR_DELETED, kk ); wxASSERT_MSG( zcopy != NULL, wxT( "UpdateCopyOfZonesList() error: link = NULL" ) ); ref->Copy( zcopy ); // the copy was deleted; the link does not exists now. aPickList.SetPickedItemLink( NULL, kk ); delete zcopy; } // Remove this item from aAuxiliaryList, mainly for tests purpose bool notfound = true; for( unsigned nn = 0; nn < aAuxiliaryList.GetCount(); nn++ ) { if( ref != NULL && aAuxiliaryList.GetPickedItem( nn ) == ref ) { aAuxiliaryList.RemovePicker( nn ); notfound = false; break; } } wxASSERT_MSG( notfound != true, wxT( "UpdateCopyOfZonesList() error: item not found in " "aAuxiliaryList" ) ); break; } if( zone == ref ) // picked zone found { if( aPickList.GetPickedItemStatus( kk ) != UR_NEW ) { ZONE_CONTAINER* zcopy = (ZONE_CONTAINER*) aPickList.GetPickedItemLink( kk ); if( zone->IsSame( *zcopy ) ) // Remove picked, because no changes { delete zcopy; // Delete copy aPickList.RemovePicker( kk ); kk--; } } break; } } } // Add new zones in main pick list, and remove pickers from Auxiliary List for( unsigned ii = 0; ii < aAuxiliaryList.GetCount(); ) { if( aAuxiliaryList.GetPickedItemStatus( ii ) == UR_NEW ) { ITEM_PICKER picker = aAuxiliaryList.GetItemWrapper( ii ); aPickList.PushItem( picker ); aAuxiliaryList.RemovePicker( ii ); } else if( aAuxiliaryList.GetPickedItemStatus( ii ) == UR_DELETED ) { delete aAuxiliaryList.GetPickedItemLink( ii ); aAuxiliaryList.RemovePicker( ii ); } else ii++; } // Should not occur: wxASSERT_MSG( aAuxiliaryList.GetCount() == 0, wxT( "UpdateCopyOfZonesList() error: aAuxiliaryList not empty." ) ); }
int PCB_EDITOR_CONTROL::ZoneMerge( const TOOL_EVENT& aEvent ) { SELECTION selection = m_toolMgr->GetTool<SELECTION_TOOL>()->GetSelection(); BOARD* board = getModel<BOARD>(); RN_DATA* ratsnest = board->GetRatsnest(); KIGFX::VIEW* view = getView(); if( selection.Size() < 2 ) return 0; PICKED_ITEMS_LIST changes; int netcode = -1; // Loop through all combinations for( int ia1 = 0; ia1 < selection.Size() - 1; ++ia1 ) { ZONE_CONTAINER* curr_area = dynamic_cast<ZONE_CONTAINER*>( selection.Item<EDA_ITEM>( ia1 ) ); if( !curr_area ) continue; netcode = curr_area->GetNetCode(); EDA_RECT b1 = curr_area->Outline()->GetBoundingBox(); bool mod_ia1 = false; for( int ia2 = selection.Size() - 1; ia2 > ia1; --ia2 ) { ZONE_CONTAINER* area2 = dynamic_cast<ZONE_CONTAINER*>( selection.Item<EDA_ITEM>( ia2 ) ); if( !area2 ) continue; if( area2->GetNetCode() != netcode ) continue; if( curr_area->GetPriority() != area2->GetPriority() ) continue; if( curr_area->GetIsKeepout() != area2->GetIsKeepout() ) continue; if( curr_area->GetLayer() != area2->GetLayer() ) continue; EDA_RECT b2 = area2->Outline()->GetBoundingBox(); if( b1.Intersects( b2 ) ) { EDA_ITEM* backup = curr_area->Clone(); bool ret = board->TestAreaIntersection( curr_area, area2 ); if( ret && board->CombineAreas( &changes, curr_area, area2 ) ) { mod_ia1 = true; selection.items.RemovePicker( ia2 ); ITEM_PICKER picker( curr_area, UR_CHANGED ); picker.SetLink( backup ); changes.PushItem( picker ); } else { delete backup; } } } if( mod_ia1 ) --ia1; // if modified, we need to check it again } m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_frame->SaveCopyInUndoList( changes, UR_UNSPECIFIED ); for( unsigned i = 0; i < changes.GetCount(); ++i ) { ITEM_PICKER picker = changes.GetItemWrapper( i ); BOARD_ITEM* item = static_cast<BOARD_ITEM*>( picker.GetItem() ); if( picker.GetStatus() == UR_DELETED ) { view->Remove( item ); ratsnest->Remove( item ); } else if( picker.GetStatus() == UR_CHANGED ) { item->ViewUpdate( KIGFX::VIEW_ITEM::ALL ); m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, item ); } } return 0; }
void SCH_SCREEN::SelectBlockItems() { PICKED_ITEMS_LIST* pickedlist = &m_BlockLocate.GetItems(); if( pickedlist->GetCount() == 0 ) return; ClearDrawingState(); for( unsigned ii = 0; ii < pickedlist->GetCount(); ii++ ) { SCH_ITEM* item = (SCH_ITEM*) pickedlist->GetPickedItem( ii ); item->SetFlags( SELECTED ); } if( !m_BlockLocate.IsDragging() ) return; // Select all the items in the screen connected to the items in the block. // be sure end lines that are on the block limits are seen inside this block m_BlockLocate.Inflate( 1 ); unsigned last_select_id = pickedlist->GetCount(); for( unsigned ii = 0; ii < last_select_id; ii++ ) { SCH_ITEM* item = (SCH_ITEM*)pickedlist->GetPickedItem( ii ); item->SetFlags( IS_DRAGGED ); if( item->Type() == SCH_LINE_T ) { item->IsSelectStateChanged( m_BlockLocate ); if( !item->IsSelected() ) { // This is a special case: // this selected wire has no ends in block. // But it was selected (because it intersects the selecting area), // so we must keep it selected and select items connected to it // Note: an other option could be: remove it from drag list item->SetFlags( SELECTED | SKIP_STRUCT ); std::vector< wxPoint > connections; item->GetConnectionPoints( connections ); for( size_t i = 0; i < connections.size(); i++ ) addConnectedItemsToBlock( connections[i] ); } pickedlist->SetPickerFlags( item->GetFlags(), ii ); } else if( item->IsConnectable() ) { std::vector< wxPoint > connections; item->GetConnectionPoints( connections ); for( size_t jj = 0; jj < connections.size(); jj++ ) addConnectedItemsToBlock( connections[jj] ); } } m_BlockLocate.Inflate( -1 ); }
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 SCH_EDIT_FRAME::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, UNDO_REDO_T aTypeCommand, const wxPoint& aTransformPoint ) { PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST(); commandToUndo->m_TransformPoint = aTransformPoint; commandToUndo->m_Status = aTypeCommand; // Copy picker list: commandToUndo->CopyList( aItemsList ); // Verify list, and creates data if needed for( unsigned ii = 0; ii < commandToUndo->GetCount(); ii++ ) { SCH_ITEM* item = (SCH_ITEM*) commandToUndo->GetPickedItem( ii ); wxASSERT( item ); UNDO_REDO_T command = commandToUndo->GetPickedItemStatus( ii ); if( command == UR_UNSPECIFIED ) { command = aTypeCommand; commandToUndo->SetPickedItemStatus( command, ii ); } switch( command ) { case UR_CHANGED: /* Create a copy of item */ /* If needed, create a copy of item, and put in undo list * in the picker, as link * If this link is not null, the copy is already done */ if( commandToUndo->GetPickedItemLink( ii ) == NULL ) commandToUndo->SetPickedItemLink( DuplicateStruct( item, true ), ii ); wxASSERT( commandToUndo->GetPickedItemLink( ii ) ); break; case UR_MOVED: case UR_MIRRORED_Y: case UR_MIRRORED_X: case UR_ROTATED: case UR_NEW: case UR_DELETED: case UR_EXCHANGE_T: case UR_WIRE_IMAGE: break; default: wxFAIL_MSG( wxString::Format( wxT( "Unknown undo/redo command %d" ), command ) ); break; } } if( commandToUndo->GetCount() || aTypeCommand == UR_WIRE_IMAGE ) { /* 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 // Should not occur { delete commandToUndo; } }
void PCB_EDIT_FRAME::SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList, UNDO_REDO_T aTypeCommand, const wxPoint& aTransformPoint ) { PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST(); commandToUndo->m_TransformPoint = aTransformPoint; // Copy picker list: commandToUndo->CopyList( aItemsList ); // Verify list, and creates data if needed for( unsigned ii = 0; ii < commandToUndo->GetCount(); ii++ ) { BOARD_ITEM* item = (BOARD_ITEM*) commandToUndo->GetPickedItem( ii ); // For texts belonging to modules, we need to save state of the parent module if( item->Type() == PCB_MODULE_TEXT_T ) { item = item->GetParent(); wxASSERT( item->Type() == PCB_MODULE_T ); if( item == NULL ) continue; commandToUndo->SetPickedItem( item, ii ); commandToUndo->SetPickedItemStatus( UR_CHANGED, ii ); } UNDO_REDO_T command = commandToUndo->GetPickedItemStatus( ii ); if( command == UR_UNSPECIFIED ) { command = aTypeCommand; commandToUndo->SetPickedItemStatus( command, ii ); } wxASSERT( item ); switch( command ) { case UR_CHANGED: /* If needed, create a copy of item, and put in undo list * in the picker, as link * If this link is not null, the copy is already done */ if( commandToUndo->GetPickedItemLink( ii ) == NULL ) commandToUndo->SetPickedItemLink( item->Clone(), ii ); break; case UR_MOVED: case UR_ROTATED: case UR_ROTATED_CLOCKWISE: case UR_FLIPPED: case UR_NEW: case UR_DELETED: break; default: { wxString msg; msg.Printf( wxT( "SaveCopyInUndoList() error (unknown code %X)" ), command ); wxMessageBox( msg ); } break; } } if( commandToUndo->GetCount() ) { /* Save the copy in undo list */ GetScreen()->PushCommandToUndoList( commandToUndo ); /* Clear redo list, because after a new command one cannot redo a command */ GetScreen()->ClearUndoORRedoList( GetScreen()->m_RedoList ); } else // Should not occur { delete commandToUndo; } }
void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC ) { MODULE* currModule = NULL; wxPoint PosOK; wxPoint memopos; int error; LAYER_ID lay_tmp_TOP, lay_tmp_BOTTOM; // Undo: init list PICKED_ITEMS_LIST newList; newList.m_Status = UR_CHANGED; ITEM_PICKER picker( NULL, UR_CHANGED ); if( GetBoard()->m_Modules == NULL ) return; m_canvas->SetAbortRequest( false ); switch( place_mode ) { case PLACE_1_MODULE: currModule = Module; if( currModule == NULL ) return; currModule->SetIsPlaced( false ); currModule->SetNeedsPlaced( false ); break; case PLACE_OUT_OF_BOARD: break; case PLACE_ALL: if( !IsOK( this, _( "Footprints NOT LOCKED will be moved" ) ) ) return; break; case PLACE_INCREMENTAL: if( !IsOK( this, _( "Footprints NOT PLACED will be moved" ) ) ) return; break; } memopos = CurrPosition; lay_tmp_BOTTOM = g_Route_Layer_BOTTOM; lay_tmp_TOP = g_Route_Layer_TOP; RoutingMatrix.m_GridRouting = (int) GetScreen()->GetGridSize().x; // Ensure Board.m_GridRouting has a reasonable value: if( RoutingMatrix.m_GridRouting < Millimeter2iu( 0.25 ) ) RoutingMatrix.m_GridRouting = Millimeter2iu( 0.25 ); // Compute module parameters used in auto place if( genPlacementRoutingMatrix( GetBoard(), m_messagePanel ) == 0 ) return; int moduleCount = 0; Module = GetBoard()->m_Modules; for( ; Module != NULL; Module = Module->Next() ) { Module->SetNeedsPlaced( false ); switch( place_mode ) { case PLACE_1_MODULE: if( currModule == Module ) { // Module will be placed, add to undo. picker.SetItem( currModule ); newList.PushItem( picker ); Module->SetNeedsPlaced( true ); } break; case PLACE_OUT_OF_BOARD: Module->SetIsPlaced( false ); if( Module->IsLocked() ) break; if( !RoutingMatrix.m_BrdBox.Contains( Module->GetPosition() ) ) { // Module will be placed, add to undo. picker.SetItem( Module ); newList.PushItem( picker ); Module->SetNeedsPlaced( true ); } break; case PLACE_ALL: Module->SetIsPlaced( false ); if( Module->IsLocked() ) break; // Module will be placed, add to undo. picker.SetItem( Module ); newList.PushItem( picker ); Module->SetNeedsPlaced( true ); break; case PLACE_INCREMENTAL: if( Module->IsLocked() ) { Module->SetIsPlaced( false ); break; } if( !Module->NeedsPlaced() ) { // Module will be placed, add to undo. picker.SetItem( Module ); newList.PushItem( picker ); Module->SetNeedsPlaced( true ); } break; } if( Module->NeedsPlaced() ) // Erase from screen { moduleCount++; Module->Draw( m_canvas, DC, GR_XOR ); } else { genModuleOnRoutingMatrix( Module ); } } // Undo command: prepare list if( newList.GetCount() ) SaveCopyInUndoList( newList, UR_CHANGED ); int cnt = 0; wxString msg; while( ( Module = PickModule( this, DC ) ) != NULL ) { // Display some info about activity, module placement can take a while: msg.Printf( _( "Place footprint %d of %d" ), cnt, moduleCount ); SetStatusText( msg ); double initialOrient = Module->GetOrientation(); // Display fill area of interest, barriers, penalties. drawPlacementRoutingMatrix( GetBoard(), DC ); error = getOptimalModulePlacement( this, Module, DC ); double bestScore = MinCout; double bestRotation = 0.0; int rotAllowed; PosOK = CurrPosition; if( error == ESC ) goto end_of_tst; // Try orientations 90, 180, 270 degrees from initial orientation rotAllowed = Module->GetPlacementCost180(); if( rotAllowed != 0 ) { Rotate_Module( DC, Module, 1800.0, true ); error = getOptimalModulePlacement( this, Module, DC ); MinCout *= OrientPenality[rotAllowed]; if( bestScore > MinCout ) // This orientation is better. { PosOK = CurrPosition; bestScore = MinCout; bestRotation = 1800.0; } else { Rotate_Module( DC, Module, initialOrient, false ); } if( error == ESC ) goto end_of_tst; } // Determine if the best orientation of a module is 90. rotAllowed = Module->GetPlacementCost90(); if( rotAllowed != 0 ) { Rotate_Module( DC, Module, 900.0, true ); error = getOptimalModulePlacement( this, Module, DC ); MinCout *= OrientPenality[rotAllowed]; if( bestScore > MinCout ) // This orientation is better. { PosOK = CurrPosition; bestScore = MinCout; bestRotation = 900.0; } else { Rotate_Module( DC, Module, initialOrient, false ); } if( error == ESC ) goto end_of_tst; } // Determine if the best orientation of a module is -90. if( rotAllowed != 0 ) { Rotate_Module( DC, Module, 2700.0, true ); error = getOptimalModulePlacement( this, Module, DC ); MinCout *= OrientPenality[rotAllowed]; if( bestScore > MinCout ) // This orientation is better. { PosOK = CurrPosition; bestScore = MinCout; bestRotation = 2700.0; } else { Rotate_Module( DC, Module, initialOrient, false ); } if( error == ESC ) goto end_of_tst; } end_of_tst: if( error == ESC ) break; // Place module. CurrPosition = GetCrossHairPosition(); SetCrossHairPosition( PosOK ); PlaceModule( Module, DC ); bestRotation += initialOrient; if( bestRotation != Module->GetOrientation() ) Rotate_Module( DC, Module, bestRotation, false ); SetCrossHairPosition( CurrPosition ); Module->CalculateBoundingBox(); genModuleOnRoutingMatrix( Module ); Module->SetIsPlaced( true ); Module->SetNeedsPlaced( false ); } CurrPosition = memopos; RoutingMatrix.UnInitRoutingMatrix(); g_Route_Layer_TOP = lay_tmp_TOP; g_Route_Layer_BOTTOM = lay_tmp_BOTTOM; Module = GetBoard()->m_Modules; for( ; Module != NULL; Module = Module->Next() ) { Module->CalculateBoundingBox(); } GetBoard()->m_Status_Pcb = 0; Compile_Ratsnest( DC, true ); m_canvas->ReDraw( DC, true ); }
int PCBNEW_CONTROL::AppendBoard( const TOOL_EVENT& aEvent ) { int open_ctl; wxString fileName; PICKED_ITEMS_LIST undoListPicker; ITEM_PICKER picker( NULL, UR_NEW ); PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame ); BOARD* board = getModel<BOARD>(); KIGFX::VIEW* view = getView(); if( !editFrame ) return 0; // Pick a file to append if( !AskLoadBoardFileName( editFrame, &open_ctl, &fileName, true ) ) return 0; IO_MGR::PCB_FILE_T pluginType = plugin_type( fileName, open_ctl ); PLUGIN::RELEASER pi( IO_MGR::PluginFind( pluginType ) ); // keep track of existing items, in order to know what are the new items // (for undo command for instance) // Tracks are inserted, not appended, so mark the existing tracks to know what are the new tracks for( TRACK* track = board->m_Track; track; track = track->Next() ) track->SetFlags( FLAG0 ); // Other items are appended to the item list, so keep trace to the last existing item is enough MODULE* module = board->m_Modules.GetLast(); BOARD_ITEM* drawing = board->m_Drawings.GetLast(); int zonescount = board->GetAreaCount(); // Keep also the count of copper layers, to adjust if necessary int initialCopperLayerCount = board->GetCopperLayerCount(); LSET initialEnabledLayers = board->GetEnabledLayers(); // Load the data try { PROPERTIES props; char xbuf[30]; char ybuf[30]; // EAGLE_PLUGIN can use this info to center the BOARD, but it does not yet. sprintf( xbuf, "%d", editFrame->GetPageSizeIU().x ); sprintf( ybuf, "%d", editFrame->GetPageSizeIU().y ); props["page_width"] = xbuf; props["page_height"] = ybuf; editFrame->GetDesignSettings().m_NetClasses.Clear(); pi->Load( fileName, board, &props ); } catch( const IO_ERROR& ioe ) { wxString msg = wxString::Format( _( "Error loading board.\n%s" ), GetChars( ioe.errorText )); DisplayError( editFrame, msg ); return 0; } m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); // Process the new items for( TRACK* track = board->m_Track; track; track = track->Next() ) { if( track->GetFlags() & FLAG0 ) { track->ClearFlags( FLAG0 ); continue; } picker.SetItem( track ); undoListPicker.PushItem( picker ); view->Add( track ); m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, track ); } module = module ? module->Next() : board->m_Modules; for( ; module; module = module->Next() ) { picker.SetItem( module ); undoListPicker.PushItem( picker ); module->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, view, _1 ) ); view->Add( module ); m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, module ); } drawing = drawing ? drawing->Next() : board->m_Drawings; for( ; drawing; drawing = drawing->Next() ) { picker.SetItem( drawing ); undoListPicker.PushItem( picker ); view->Add( drawing ); m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, drawing ); } for( ZONE_CONTAINER* zone = board->GetArea( zonescount ); zone; zone = board->GetArea( zonescount ) ) { picker.SetItem( zone ); undoListPicker.PushItem( picker ); zonescount++; view->Add( zone ); m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, zone ); } if( undoListPicker.GetCount() == 0 ) return 0; editFrame->SaveCopyInUndoList( undoListPicker, UR_NEW ); // Synchronize layers // we should not ask PLUGINs to do these items: int copperLayerCount = board->GetCopperLayerCount(); if( copperLayerCount > initialCopperLayerCount ) board->SetCopperLayerCount( copperLayerCount ); // Enable all used layers, and make them visible: LSET enabledLayers = board->GetEnabledLayers(); enabledLayers |= initialEnabledLayers; board->SetEnabledLayers( enabledLayers ); board->SetVisibleLayers( enabledLayers ); editFrame->ReCreateLayerBox(); editFrame->ReFillLayerWidget(); static_cast<PCB_DRAW_PANEL_GAL*>( editFrame->GetGalCanvas() )->SyncLayersVisibility( board ); // Ratsnest board->BuildListOfNets(); board->SynchronizeNetsAndNetClasses(); board->GetRatsnest()->Recalculate(); // Start dragging the appended board VECTOR2D v( static_cast<BOARD_ITEM*>( undoListPicker.GetPickedItem( 0 ) )->GetPosition() ); getViewControls()->WarpCursor( v, true, true ); m_toolMgr->InvokeTool( "pcbnew.InteractiveEdit" ); return 0; }