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 ); }
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; }
/** * 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::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::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 ); } }
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 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 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 ); }
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(); }
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 ); }
/** * 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 ); }
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_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. for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { ITEM_PICKER picker = aItemsList.GetItemWrapper(ii); BOARD_ITEM* item = (BOARD_ITEM*) aItemsList.GetPickedItem( ii ); // For texts belonging to modules, we need to save state of the parent module if( item->Type() == PCB_MODULE_TEXT_T || item->Type() == PCB_PAD_T ) { item = item->GetParent(); wxASSERT( item->Type() == PCB_MODULE_T ); if( item == NULL ) continue; 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 ) commandToUndo->PushItem( ITEM_PICKER(item, UR_CHANGED ) ); else continue; } else { commandToUndo->PushItem( 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: /* 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: { 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; } }
bool FOOTPRINT_EDIT_FRAME::HandleBlockEnd( wxDC* DC ) { int itemsCount = 0; bool nextcmd = false; MODULE* currentModule = GetBoard()->m_Modules; if( GetScreen()->m_BlockLocate.GetCount() ) { // Set the SELECTED flag of all preselected items, and clear preselect list ClearMarkItems( currentModule ); PICKED_ITEMS_LIST* list = &GetScreen()->m_BlockLocate.GetItems(); for( unsigned ii = 0, e = list->GetCount(); ii < e; ++ii ) { BOARD_ITEM* item = (BOARD_ITEM*) list->GetPickedItem( ii ); item->SetFlags( SELECTED ); ++itemsCount; } GetScreen()->m_BlockLocate.ClearItemsList(); } switch( GetScreen()->m_BlockLocate.GetCommand() ) { case BLOCK_IDLE: DisplayError( this, wxT( "Error in HandleBlockPLace" ) ); break; case BLOCK_DRAG: // Drag case BLOCK_DRAG_ITEM: // Drag a given item (not used here) case BLOCK_MOVE: // Move case BLOCK_COPY: // Copy case BLOCK_COPY_AND_INCREMENT: // Specific to duplicate with increment command // Find selected items if we didn't already set them manually if( itemsCount == 0 ) itemsCount = MarkItemsInBloc( currentModule, GetScreen()->m_BlockLocate ); if( itemsCount ) { nextcmd = true; if( m_canvas->IsMouseCaptured() ) { m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); m_canvas->SetMouseCaptureCallback( DrawMovingBlockOutlines ); m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); } GetScreen()->m_BlockLocate.SetState( STATE_BLOCK_MOVE ); m_canvas->Refresh( true ); } break; case BLOCK_MOVE_EXACT: itemsCount = MarkItemsInBloc( currentModule, GetScreen()->m_BlockLocate ); if( itemsCount ) { wxPoint translation; double rotation = 0; DIALOG_MOVE_EXACT dialog( this, translation, rotation ); int ret = dialog.ShowModal(); if( ret == wxID_OK ) { SaveCopyInUndoList( currentModule, UR_MODEDIT ); const wxPoint blockCentre = GetScreen()->m_BlockLocate.Centre(); MoveMarkedItemsExactly( currentModule, blockCentre, translation, rotation ); } } break; case BLOCK_PRESELECT_MOVE: // Move with preselection list nextcmd = true; m_canvas->SetMouseCaptureCallback( DrawMovingBlockOutlines ); GetScreen()->m_BlockLocate.SetState( STATE_BLOCK_MOVE ); break; case BLOCK_DELETE: // Delete itemsCount = MarkItemsInBloc( currentModule, GetScreen()->m_BlockLocate ); if( itemsCount ) SaveCopyInUndoList( currentModule, UR_MODEDIT ); DeleteMarkedItems( currentModule ); break; case BLOCK_SAVE: // Save case BLOCK_PASTE: break; case BLOCK_ROTATE: itemsCount = MarkItemsInBloc( currentModule, GetScreen()->m_BlockLocate ); if( itemsCount ) SaveCopyInUndoList( currentModule, UR_MODEDIT ); RotateMarkedItems( currentModule, GetScreen()->m_BlockLocate.Centre() ); break; case BLOCK_MIRROR_X: case BLOCK_MIRROR_Y: case BLOCK_FLIP: // mirror itemsCount = MarkItemsInBloc( currentModule, GetScreen()->m_BlockLocate ); if( itemsCount ) SaveCopyInUndoList( currentModule, UR_MODEDIT ); MirrorMarkedItems( currentModule, GetScreen()->m_BlockLocate.Centre() ); break; case BLOCK_ZOOM: // Window Zoom Window_Zoom( GetScreen()->m_BlockLocate ); break; case BLOCK_ABORT: break; case BLOCK_SELECT_ITEMS_ONLY: break; } if( !nextcmd ) { if( GetScreen()->m_BlockLocate.GetCommand() != BLOCK_SELECT_ITEMS_ONLY ) { ClearMarkItems( currentModule ); } GetScreen()->ClearBlockCommand(); SetCurItem( NULL ); m_canvas->EndMouseCapture( GetToolId(), m_canvas->GetCurrentCursor(), wxEmptyString, false ); m_canvas->Refresh( true ); } return nextcmd; }
/** * 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." ) ); }
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 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 ); }
void PCB_EDIT_FRAME::RunActionPlugin( ACTION_PLUGIN* aActionPlugin ) { PICKED_ITEMS_LIST itemsList; BOARD* currentPcb = GetBoard(); bool fromEmpty = false; itemsList.m_Status = UR_CHANGED; OnModify(); // Append tracks: for( BOARD_ITEM* item = currentPcb->m_Track; item != NULL; item = item->Next() ) { ITEM_PICKER picker( item, UR_CHANGED ); itemsList.PushItem( picker ); } // Append modules: for( BOARD_ITEM* item = currentPcb->m_Modules; item != NULL; item = item->Next() ) { ITEM_PICKER picker( item, UR_CHANGED ); itemsList.PushItem( picker ); } // Append drawings for( BOARD_ITEM* item = currentPcb->m_Drawings; item != NULL; item = item->Next() ) { ITEM_PICKER picker( item, UR_CHANGED ); itemsList.PushItem( picker ); } // Append zones outlines for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ ) { ITEM_PICKER picker( (EDA_ITEM*) currentPcb->GetArea( ii ), UR_CHANGED ); itemsList.PushItem( picker ); } // Append zones segm: for( BOARD_ITEM* item = currentPcb->m_SegZoneDeprecated; item != NULL; item = item->Next() ) { ITEM_PICKER picker( item, UR_CHANGED ); itemsList.PushItem( picker ); } if( itemsList.GetCount() > 0 ) SaveCopyInUndoList( itemsList, UR_CHANGED, wxPoint( 0.0, 0.0 ) ); else fromEmpty = true; itemsList.ClearItemsList(); // Execute plugin itself... ACTION_PLUGINS::SetActionRunning( true ); aActionPlugin->Run(); ACTION_PLUGINS::SetActionRunning( false ); currentPcb->m_Status_Pcb = 0; // Get back the undo buffer to fix some modifications PICKED_ITEMS_LIST* oldBuffer = NULL; if( fromEmpty ) { oldBuffer = new PICKED_ITEMS_LIST(); oldBuffer->m_Status = UR_NEW; } else { oldBuffer = GetScreen()->PopCommandFromUndoList(); wxASSERT( oldBuffer ); } // Try do discover what was modified PICKED_ITEMS_LIST deletedItemsList; // Found deleted modules for( unsigned int i = 0; i < oldBuffer->GetCount(); i++ ) { BOARD_ITEM* item = (BOARD_ITEM*) oldBuffer->GetPickedItem( i ); ITEM_PICKER picker( item, UR_DELETED ); wxASSERT( item ); switch( item->Type() ) { case PCB_NETINFO_T: case PCB_MARKER_T: case PCB_MODULE_T: case PCB_TRACE_T: case PCB_VIA_T: case PCB_LINE_T: case PCB_TEXT_T: case PCB_DIMENSION_T: case PCB_TARGET_T: case PCB_SEGZONE_T: // If item has a list it's mean that the element is on the board if( item->GetList() == NULL ) { deletedItemsList.PushItem( picker ); } break; case PCB_ZONE_AREA_T: { bool zoneFound = false; for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ ) zoneFound |= currentPcb->GetArea( ii ) == item; if( !zoneFound ) { deletedItemsList.PushItem( picker ); } break; } default: wxString msg; msg.Printf( _( "(PCB_EDIT_FRAME::OnActionPlugin) needs work: " "BOARD_ITEM type (%d) not handled" ), item->Type() ); wxFAIL_MSG( msg ); break; } } // Mark deleted elements in undolist for( unsigned int i = 0; i < deletedItemsList.GetCount(); i++ ) { oldBuffer->PushItem( deletedItemsList.GetItemWrapper( i ) ); } // Find new modules for( BOARD_ITEM* item = currentPcb->m_Modules; item != NULL; item = item->Next() ) { if( !oldBuffer->ContainsItem( item ) ) { ITEM_PICKER picker( item, UR_NEW ); oldBuffer->PushItem( picker ); } } for( BOARD_ITEM* item = currentPcb->m_Track; item != NULL; item = item->Next() ) { if( !oldBuffer->ContainsItem( item ) ) { ITEM_PICKER picker( item, UR_NEW ); oldBuffer->PushItem( picker ); } } for( BOARD_ITEM* item = currentPcb->m_Drawings; item != NULL; item = item->Next() ) { if( !oldBuffer->ContainsItem( item ) ) { ITEM_PICKER picker( item, UR_NEW ); oldBuffer->PushItem( picker ); } } for( BOARD_ITEM* item = currentPcb->m_SegZoneDeprecated; item != NULL; item = item->Next() ) { if( !oldBuffer->ContainsItem( item ) ) { ITEM_PICKER picker( item, UR_NEW ); oldBuffer->PushItem( picker ); } } for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ ) { if( !oldBuffer->ContainsItem( (EDA_ITEM*) currentPcb->GetArea( ii ) ) ) { ITEM_PICKER picker( (EDA_ITEM*) currentPcb->GetArea( ii ), UR_NEW ); oldBuffer->PushItem( picker ); } } GetScreen()->PushCommandToUndoList( oldBuffer ); if( IsGalCanvasActive() ) { UseGalCanvas( GetGalCanvas() ); } else { UpdateUserInterface(); GetScreen()->SetModify(); Refresh(); } }
void SCH_SCREEN::SelectBlockItems() { auto addConnections = [ this ]( SCH_ITEM* item ) -> void { std::vector< wxPoint > connections; item->GetConnectionPoints( connections ); for( auto conn : connections ) addConnectedItemsToBlock( item, conn ); }; 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 ); addConnections( item ); } pickedlist->SetPickerFlags( item->GetFlags(), ii ); } else if( item->IsConnectable() ) { addConnections( item ); } } // Select the items that are connected to a block object that was added // to our selection list in the last step. for( unsigned ii = last_select_id; ii < pickedlist->GetCount(); ii++ ) { SCH_ITEM* item = (SCH_ITEM*)pickedlist->GetPickedItem( ii ); if( item->Type() == SCH_COMPONENT_T || item->Type() == SCH_BUS_BUS_ENTRY_T || item->Type() == SCH_BUS_WIRE_ENTRY_T || item->Type() == SCH_SHEET_T || ( item->Type() == SCH_LINE_T && !( item->GetFlags() & ( ENDPOINT | STARTPOINT ) ) ) ) { item->SetFlags( IS_DRAGGED ); addConnections( item ); } } m_BlockLocate.Inflate( -1 ); }
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; }
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; } }
void PCB_EDIT_FRAME::Block_Rotate() { wxPoint centre; // rotation cent-re for the rotation transform int rotAngle = m_rotationAngle; // rotation angle in 0.1 deg. centre = GetScreen()->m_BlockLocate.Centre(); OnModify(); PICKED_ITEMS_LIST* itemsList = &GetScreen()->m_BlockLocate.GetItems(); itemsList->m_Status = UR_CHANGED; for( unsigned ii = 0; ii < itemsList->GetCount(); ii++ ) { BOARD_ITEM* item = (BOARD_ITEM*) itemsList->GetPickedItem( ii ); wxASSERT( item ); itemsList->SetPickedItemStatus( UR_CHANGED, ii ); 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; } } // Save all the block items in there current state before applying the rotation. SaveCopyInUndoList( *itemsList, UR_CHANGED, centre ); // Now perform the rotation. for( unsigned ii = 0; ii < itemsList->GetCount(); ii++ ) { BOARD_ITEM* item = (BOARD_ITEM*) itemsList->GetPickedItem( ii ); wxASSERT( item ); item->Rotate( centre, rotAngle ); GetBoard()->GetConnectivity()->Update( item ); } Compile_Ratsnest( NULL, true ); m_canvas->Refresh( true ); }
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_BASE_FRAME::ResetModuleTextSizes( const wxString & aFilter, bool aRef, bool aValue, bool aOthers ) { MODULE* module; BOARD_ITEM* boardItem; 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 ) { TEXTE_MODULE *item = &module->Reference(); if( item->GetSize() != GetDesignSettings().m_ModuleTextSize || item->GetThickness() != GetDesignSettings().m_ModuleTextWidth ) { undoItemList.PushItem( itemWrapper ); } } if( aValue ) { TEXTE_MODULE *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 ) { TEXTE_MODULE *item = static_cast<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 ) { TEXTE_MODULE *item = static_cast<TEXTE_MODULE*>( boardItem ); item->SetThickness( GetDesignSettings().m_ModuleTextWidth ); item->SetSize( GetDesignSettings().m_ModuleTextSize ); } } } } OnModify(); }