/* Copy marked items, at new position = old position + offset */ void CopyMarkedItems( MODULE* module, wxPoint offset ) { if( module == NULL ) return; for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) { if( !pad->IsSelected() ) continue; pad->ClearFlags( SELECTED ); D_PAD* NewPad = new D_PAD( *pad ); NewPad->SetParent( module ); NewPad->SetFlags( SELECTED ); module->Pads().PushFront( NewPad ); } BOARD_ITEM* newItem; for( BOARD_ITEM* item = module->GraphicalItems(); item; item = item->Next() ) { if( !item->IsSelected() ) continue; item->ClearFlags( SELECTED ); newItem = (BOARD_ITEM*)item->Clone(); newItem->SetParent( module ); newItem->SetFlags( SELECTED ); module->GraphicalItems().PushFront( newItem ); } MoveMarkedItems( module, offset ); }
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 ); }
/* Copy marked items, at new position = old position + offset */ void CopyMarkedItems( MODULE* module, wxPoint offset, bool aIncrement ) { if( module == NULL ) return; // Reference and value cannot be copied, they are unique. // Ensure they are not selected module->Reference().ClearFlags(); module->Value().ClearFlags(); for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) { if( !pad->IsSelected() ) continue; pad->ClearFlags( SELECTED ); D_PAD* NewPad = new D_PAD( *pad ); NewPad->SetParent( module ); NewPad->SetFlags( SELECTED ); module->Pads().PushFront( NewPad ); if( aIncrement ) NewPad->IncrementPadName( true, true ); } BOARD_ITEM* newItem; for( BOARD_ITEM* item = module->GraphicalItems(); item; item = item->Next() ) { if( !item->IsSelected() ) continue; item->ClearFlags( SELECTED ); newItem = (BOARD_ITEM*)item->Clone(); newItem->SetParent( module ); newItem->SetFlags( SELECTED ); module->GraphicalItems().PushFront( newItem ); } MoveMarkedItems( module, offset ); }
MODULE::MODULE( const MODULE& aModule ) : BOARD_ITEM_CONTAINER( aModule ) { m_Pos = aModule.m_Pos; m_fpid = aModule.m_fpid; m_Attributs = aModule.m_Attributs; m_ModuleStatus = aModule.m_ModuleStatus; m_Orient = aModule.m_Orient; m_BoundaryBox = aModule.m_BoundaryBox; m_CntRot90 = aModule.m_CntRot90; m_CntRot180 = aModule.m_CntRot180; m_LastEditTime = aModule.m_LastEditTime; m_Link = aModule.m_Link; m_Path = aModule.m_Path; //is this correct behavior? m_LocalClearance = aModule.m_LocalClearance; m_LocalSolderMaskMargin = aModule.m_LocalSolderMaskMargin; m_LocalSolderPasteMargin = aModule.m_LocalSolderPasteMargin; m_LocalSolderPasteMarginRatio = aModule.m_LocalSolderPasteMarginRatio; m_ZoneConnection = aModule.m_ZoneConnection; m_ThermalWidth = aModule.m_ThermalWidth; m_ThermalGap = aModule.m_ThermalGap; // Copy reference and value. m_Reference = new TEXTE_MODULE( *aModule.m_Reference ); m_Reference->SetParent( this ); m_Value = new TEXTE_MODULE( *aModule.m_Value ); m_Value->SetParent( this ); // Copy auxiliary data: Pads for( D_PAD* pad = aModule.m_Pads; pad; pad = pad->Next() ) { Add( new D_PAD( *pad ) ); } // Copy auxiliary data: Drawings for( BOARD_ITEM* item = aModule.m_Drawings; item; item = item->Next() ) { switch( item->Type() ) { case PCB_MODULE_TEXT_T: case PCB_MODULE_EDGE_T: Add( static_cast<BOARD_ITEM*>( item->Clone() ) ); break; default: wxLogMessage( wxT( "Class MODULE copy constructor internal error: unknown type" ) ); break; } } // Copy auxiliary data: 3D_Drawings info m_3D_Drawings = aModule.m_3D_Drawings; m_Doc = aModule.m_Doc; m_KeyWord = aModule.m_KeyWord; m_arflag = 0; // Ensure auxiliary data is up to date CalculateBoundingBox(); m_initial_comments = aModule.m_initial_comments ? new wxArrayString( *aModule.m_initial_comments ) : 0; }
MODULE& MODULE::operator=( const MODULE& aOther ) { BOARD_ITEM::operator=( aOther ); m_Pos = aOther.m_Pos; m_fpid = aOther.m_fpid; m_Attributs = aOther.m_Attributs; m_ModuleStatus = aOther.m_ModuleStatus; m_Orient = aOther.m_Orient; m_BoundaryBox = aOther.m_BoundaryBox; m_CntRot90 = aOther.m_CntRot90; m_CntRot180 = aOther.m_CntRot180; m_LastEditTime = aOther.m_LastEditTime; m_Link = aOther.m_Link; m_Path = aOther.m_Path; //is this correct behavior? m_LocalClearance = aOther.m_LocalClearance; m_LocalSolderMaskMargin = aOther.m_LocalSolderMaskMargin; m_LocalSolderPasteMargin = aOther.m_LocalSolderPasteMargin; m_LocalSolderPasteMarginRatio = aOther.m_LocalSolderPasteMarginRatio; m_ZoneConnection = aOther.m_ZoneConnection; m_ThermalWidth = aOther.m_ThermalWidth; m_ThermalGap = aOther.m_ThermalGap; // Copy reference and value *m_Reference = *aOther.m_Reference; m_Reference->SetParent( this ); *m_Value = *aOther.m_Value; m_Value->SetParent( this ); // Copy auxiliary data: Pads m_Pads.DeleteAll(); for( D_PAD* pad = aOther.m_Pads; pad; pad = pad->Next() ) { Add( new D_PAD( *pad ) ); } // Copy auxiliary data: Drawings m_Drawings.DeleteAll(); for( BOARD_ITEM* item = aOther.m_Drawings; item; item = item->Next() ) { switch( item->Type() ) { case PCB_MODULE_TEXT_T: case PCB_MODULE_EDGE_T: Add( static_cast<BOARD_ITEM*>( item->Clone() ) ); break; default: wxLogMessage( wxT( "MODULE::operator=() internal error: unknown type" ) ); break; } } // Copy auxiliary data: 3D_Drawings info m_3D_Drawings.clear(); m_3D_Drawings = aOther.m_3D_Drawings; m_Doc = aOther.m_Doc; m_KeyWord = aOther.m_KeyWord; // Ensure auxiliary data is up to date CalculateBoundingBox(); return *this; }
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::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::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; } }
int MODULE_TOOLS::PasteItems( const TOOL_EVENT& aEvent ) { // Parse clipboard PCB_IO io( CTL_FOR_CLIPBOARD ); MODULE* pastedModule = NULL; try { BOARD_ITEM* item = io.Parse( wxString( m_toolMgr->GetClipboard().c_str(), wxConvUTF8 ) ); assert( item->Type() == PCB_MODULE_T ); pastedModule = dyn_cast<MODULE*>( item ); } catch( ... ) { m_frame->DisplayToolMsg( _( "Invalid clipboard contents" ) ); return 0; } // Placement tool part VECTOR2I cursorPos = m_controls->GetCursorPosition(); // Add a VIEW_GROUP that serves as a preview for the new item KIGFX::VIEW_GROUP preview( m_view ); pastedModule->SetParent( m_board ); pastedModule->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); pastedModule->RunOnChildren( std::bind( &KIGFX::VIEW_GROUP::Add, std::ref( preview ), _1 ) ); preview.Add( pastedModule ); m_view->Add( &preview ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_controls->ShowCursor( true ); m_controls->SetSnapping( true ); m_controls->SetAutoPan( true ); Activate(); // Main loop: keep receiving events while( OPT_TOOL_EVENT evt = Wait() ) { cursorPos = m_controls->GetCursorPosition(); if( evt->IsMotion() ) { pastedModule->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); m_view->Update( &preview ); } else if( evt->Category() == TC_COMMAND ) { if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) { pastedModule->Rotate( pastedModule->GetPosition(), m_frame->GetRotationAngle() ); m_view->Update( &preview ); } else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) { pastedModule->Flip( pastedModule->GetPosition() ); m_view->Update( &preview ); } else if( evt->IsCancel() || evt->IsActivate() ) { preview.Clear(); break; } } else if( evt->IsClick( BUT_LEFT ) ) { BOARD_COMMIT commit( m_frame ); m_board->m_Status_Pcb = 0; // I have no clue why, but it is done in the legacy view // MODULE::RunOnChildren is infeasible here: we need to create copies of items, do not // directly modify them for( D_PAD* pad = pastedModule->Pads(); pad; pad = pad->Next() ) { D_PAD* clone = static_cast<D_PAD*>( pad->Clone() ); commit.Add( clone ); } for( BOARD_ITEM* drawing = pastedModule->GraphicalItems(); drawing; drawing = drawing->Next() ) { BOARD_ITEM* clone = static_cast<BOARD_ITEM*>( drawing->Clone() ); if( TEXTE_MODULE* text = dyn_cast<TEXTE_MODULE*>( clone ) ) { // Do not add reference/value - convert them to the common type text->SetType( TEXTE_MODULE::TEXT_is_DIVERS ); // Whyyyyyyyyyyyyyyyyyyyyyy?! All other items conform to rotation performed // on its parent module, but texts are so independent.. text->Rotate( text->GetPosition(), pastedModule->GetOrientation() ); commit.Add( text ); } commit.Add( clone ); } commit.Push( _( "Paste clipboard contents" ) ); preview.Clear(); break; } } delete pastedModule; m_controls->ShowCursor( false ); m_controls->SetSnapping( false ); m_controls->SetAutoPan( false ); m_view->Remove( &preview ); return 0; }
MODULE::MODULE( const MODULE& aModule ) : BOARD_ITEM( aModule ) { m_Pos = aModule.m_Pos; m_fpid = aModule.m_fpid; m_Layer = aModule.m_Layer; m_Attributs = aModule.m_Attributs; m_ModuleStatus = aModule.m_ModuleStatus; m_Orient = aModule.m_Orient; m_BoundaryBox = aModule.m_BoundaryBox; m_CntRot90 = aModule.m_CntRot90; m_CntRot180 = aModule.m_CntRot180; m_LastEditTime = aModule.m_LastEditTime; m_Link = aModule.m_Link; m_Path = aModule.m_Path; //is this correct behavior? m_LocalClearance = aModule.m_LocalClearance; m_LocalSolderMaskMargin = aModule.m_LocalSolderMaskMargin; m_LocalSolderPasteMargin = aModule.m_LocalSolderPasteMargin; m_LocalSolderPasteMarginRatio = aModule.m_LocalSolderPasteMarginRatio; m_ZoneConnection = aModule.m_ZoneConnection; m_ThermalWidth = aModule.m_ThermalWidth; m_ThermalGap = aModule.m_ThermalGap; // Copy reference and value. m_Reference = new TEXTE_MODULE( *aModule.m_Reference ); m_Reference->SetParent( this ); m_Value = new TEXTE_MODULE( *aModule.m_Value ); m_Value->SetParent( this ); // Copy auxiliary data: Pads for( D_PAD* pad = aModule.m_Pads; pad; pad = pad->Next() ) { D_PAD* newpad = new D_PAD( *pad ); assert( newpad->GetNet() == pad->GetNet() ); newpad->SetParent( this ); m_Pads.PushBack( newpad ); } // Copy auxiliary data: Drawings for( BOARD_ITEM* item = aModule.m_Drawings; item; item = item->Next() ) { BOARD_ITEM* newItem; switch( item->Type() ) { case PCB_MODULE_TEXT_T: case PCB_MODULE_EDGE_T: newItem = static_cast<BOARD_ITEM*>( item->Clone() ); newItem->SetParent( this ); m_Drawings.PushBack( newItem ); break; default: wxLogMessage( wxT( "MODULE::Copy() Internal Err: unknown type" ) ); break; } } // Copy auxiliary data: 3D_Drawings info for( S3D_MASTER* item = aModule.m_3D_Drawings; item; item = item->Next() ) { if( item->GetShape3DName().IsEmpty() ) // do not copy empty shapes. continue; S3D_MASTER* t3d = new S3D_MASTER( this ); t3d->Copy( item ); m_3D_Drawings.PushBack( t3d ); } // Ensure there is at least one item in m_3D_Drawings. if( m_3D_Drawings.GetCount() == 0 ) m_3D_Drawings.PushBack( new S3D_MASTER( this ) ); // push a void item m_Doc = aModule.m_Doc; m_KeyWord = aModule.m_KeyWord; m_arflag = 0; // Ensure auxiliary data is up to date CalculateBoundingBox(); m_initial_comments = aModule.m_initial_comments ? new wxArrayString( *aModule.m_initial_comments ) : 0; }