diff --git a/eeschema/sch_design_block_utils.cpp b/eeschema/sch_design_block_utils.cpp index 647c53264a..7b2ce75a7f 100644 --- a/eeschema/sch_design_block_utils.cpp +++ b/eeschema/sch_design_block_utils.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -380,6 +381,24 @@ bool SCH_EDIT_FRAME::SaveSelectionToDesignBlock( const LIB_ID& aLibId ) return false; } + // If we have a single group, we want to strip the group and select the children + SCH_GROUP* group = nullptr; + + if( selection.Size() == 1 ) + { + EDA_ITEM* item = selection.Front(); + + if( item->Type() == SCH_GROUP_T ) + { + group = static_cast( item ); + + selection.Remove( item ); + + // Don't recurse; if we have a group of groups the user probably intends the inner groups to be saved + group->RunOnChildren( [&]( EDA_ITEM* aItem ) { selection.Add( aItem ); }, RECURSE_MODE::NO_RECURSE ); + } + } + DESIGN_BLOCK* blk = nullptr; try @@ -400,11 +419,31 @@ bool SCH_EDIT_FRAME::SaveSelectionToDesignBlock( const LIB_ID& aLibId ) // Create a temporary screen SCH_SCREEN* tempScreen = new SCH_SCREEN( m_schematic ); - // Copy the selected items to the temporary screen + auto cloneAndAdd = + [&] ( EDA_ITEM* aItem ) + { + if( !aItem->IsSCH_ITEM() ) + return static_cast( nullptr ); + + SCH_ITEM* copy = static_cast( aItem->Clone() ); + tempScreen->Append( static_cast( copy ) ); + return copy; + }; + + // Copy the selected items to the temporary board for( EDA_ITEM* item : selection ) { - EDA_ITEM* copy = item->Clone(); - tempScreen->Append( static_cast( copy ) ); + // Remove parent group membership since we strip the first group layer + if( SCH_ITEM* copy = cloneAndAdd( item ) ) + copy->SetParentGroup( nullptr ); + + if( item->Type() == SCH_GROUP_T ) + { + SCH_GROUP* innerGroup = static_cast( item ); + + // Groups also need their children copied + innerGroup->RunOnChildren( cloneAndAdd, RECURSE_MODE::RECURSE ); + } } // Create a sheet for the temporary screen @@ -428,6 +467,24 @@ bool SCH_EDIT_FRAME::SaveSelectionToDesignBlock( const LIB_ID& aLibId ) { success = Prj().DesignBlockLibs()->DesignBlockSave( aLibId.GetLibNickname(), blk ) == DESIGN_BLOCK_LIB_TABLE::SAVE_OK; + + // If we had a group, we need to reselect it + if( group ) + { + selection.Clear(); + selection.Add( group ); + + // If we didn't have a design block link before, add one for convenience + if( !group->HasDesignBlockLink() ) + { + SCH_COMMIT commit( m_toolManager ); + + commit.Modify( group ); + group->SetDesignBlockLibId( aLibId ); + + commit.Push( "Set Group Design Block Link" ); + } + } } catch( const IO_ERROR& ioe ) { diff --git a/eeschema/sch_edit_frame.cpp b/eeschema/sch_edit_frame.cpp index b390cfd3a7..3c41068182 100644 --- a/eeschema/sch_edit_frame.cpp +++ b/eeschema/sch_edit_frame.cpp @@ -616,6 +616,20 @@ void SCH_EDIT_FRAME::setupUIConditions() return GetUndoCommandCount() > 0; }; + auto groupWithDesignBlockLink = + [] ( const SELECTION& aSel ) + { + if( aSel.Size() != 1 ) + return false; + + if( aSel[0]->Type() != SCH_GROUP_T ) + return false; + + SCH_GROUP* group = static_cast( aSel.GetItem( 0 ) ); + + return group->HasDesignBlockLink(); + }; + #define ENABLE( x ) ACTION_CONDITIONS().Enable( x ) #define CHECK( x ) ACTION_CONDITIONS().Check( x ) @@ -656,6 +670,9 @@ void SCH_EDIT_FRAME::setupUIConditions() mgr->SetConditions( ACTIONS::group, ENABLE( SELECTION_CONDITIONS::NotEmpty ) ); mgr->SetConditions( ACTIONS::ungroup, ENABLE( SELECTION_CONDITIONS::HasType( SCH_GROUP_T ) ) ); + mgr->SetConditions( SCH_ACTIONS::placeLinkedDesignBlock, ENABLE( groupWithDesignBlockLink ) ); + mgr->SetConditions( SCH_ACTIONS::saveToLinkedDesignBlock, ENABLE( groupWithDesignBlockLink ) ); + mgr->SetConditions( ACTIONS::zoomTool, CHECK( cond.CurrentTool( ACTIONS::zoomTool ) ) ); mgr->SetConditions( ACTIONS::selectionTool, CHECK( cond.CurrentTool( ACTIONS::selectionTool ) ) ); diff --git a/eeschema/tools/sch_actions.cpp b/eeschema/tools/sch_actions.cpp index 4f4d61eadf..ab9fcdc171 100644 --- a/eeschema/tools/sch_actions.cpp +++ b/eeschema/tools/sch_actions.cpp @@ -461,6 +461,22 @@ TOOL_ACTION SCH_ACTIONS::placeDesignBlock( TOOL_ACTION_ARGS() .Flags( AF_ACTIVATE ) .Parameter( nullptr ) ); +TOOL_ACTION SCH_ACTIONS::placeLinkedDesignBlock( TOOL_ACTION_ARGS() + .Name( "eeschema.InteractiveDrawing.placeLinkedDesignBlock" ) + .Scope( AS_GLOBAL ) + .FriendlyName( _( "Place Linked Design Block" ) ) + .Tooltip( _( "Place design block linked to selected group" ) ) + .Icon( BITMAPS::add_component ) + .Flags( AF_ACTIVATE ) ); + +TOOL_ACTION SCH_ACTIONS::saveToLinkedDesignBlock( TOOL_ACTION_ARGS() + .Name( "eeschema.InteractiveDrawing.saveToLinkedDesignBlock" ) + .Scope( AS_GLOBAL ) + .FriendlyName( _( "Save to Linked Design Block" ) ) + .Tooltip( _( "Save selected group to linked design block" ) ) + .Icon( BITMAPS::add_component ) + .Flags( AF_ACTIVATE ) ); + TOOL_ACTION SCH_ACTIONS::placeNoConnect( TOOL_ACTION_ARGS() .Name( "eeschema.InteractiveDrawing.placeNoConnect" ) diff --git a/eeschema/tools/sch_actions.h b/eeschema/tools/sch_actions.h index 325d9eecdb..bd953184cb 100644 --- a/eeschema/tools/sch_actions.h +++ b/eeschema/tools/sch_actions.h @@ -67,6 +67,8 @@ public: static TOOL_ACTION placeNextSymbolUnit; static TOOL_ACTION placePower; static TOOL_ACTION placeDesignBlock; + static TOOL_ACTION placeLinkedDesignBlock; + static TOOL_ACTION saveToLinkedDesignBlock; static TOOL_ACTION drawWire; static TOOL_ACTION drawBus; static TOOL_ACTION unfoldBus; diff --git a/eeschema/tools/sch_design_block_control.cpp b/eeschema/tools/sch_design_block_control.cpp index 1dc85e0119..cbf6269826 100644 --- a/eeschema/tools/sch_design_block_control.cpp +++ b/eeschema/tools/sch_design_block_control.cpp @@ -84,7 +84,10 @@ int SCH_DESIGN_BLOCK_CONTROL::SaveSheetAsDesignBlock( const TOOL_EVENT& aEvent ) if( !current ) return -1; - if( !m_editFrame->SaveSheetAsDesignBlock( current->m_LibId.GetLibNickname(), m_editFrame->GetCurrentSheet() ) ) + // This can be modified as a result of the save operation so copy it + LIB_ID libId = current->m_LibId; + + if( !m_editFrame->SaveSheetAsDesignBlock( libId.GetLibNickname(), m_editFrame->GetCurrentSheet() ) ) return -1; notifyOtherFrames(); @@ -100,7 +103,10 @@ int SCH_DESIGN_BLOCK_CONTROL::SaveSelectionAsDesignBlock( const TOOL_EVENT& aEve if( !current ) return -1; - if( !m_editFrame->SaveSelectionAsDesignBlock( current->m_LibId.GetLibNickname() ) ) + // This can be modified as a result of the save operation so copy it + LIB_ID libId = current->m_LibId; + + if( !m_editFrame->SaveSelectionAsDesignBlock( libId.GetLibNickname() ) ) return -1; notifyOtherFrames(); @@ -116,7 +122,10 @@ int SCH_DESIGN_BLOCK_CONTROL::SaveSheetToDesignBlock( const TOOL_EVENT& aEvent ) if( !current ) return -1; - if( !m_editFrame->SaveSheetToDesignBlock( current->m_LibId, m_editFrame->GetCurrentSheet() ) ) + // This can be modified as a result of the save operation so copy it + LIB_ID libId = current->m_LibId; + + if( !m_editFrame->SaveSheetToDesignBlock( libId, m_editFrame->GetCurrentSheet() ) ) return -1; notifyOtherFrames(); @@ -132,7 +141,10 @@ int SCH_DESIGN_BLOCK_CONTROL::SaveSelectionToDesignBlock( const TOOL_EVENT& aEve if( !current ) return -1; - if( !m_editFrame->SaveSelectionToDesignBlock( current->m_LibId ) ) + // This can be modified as a result of the save operation so copy it + LIB_ID libId = current->m_LibId; + + if( !m_editFrame->SaveSelectionToDesignBlock( libId ) ) return -1; notifyOtherFrames(); diff --git a/eeschema/tools/sch_editor_control.cpp b/eeschema/tools/sch_editor_control.cpp index cdcd94bd5f..395870ffb3 100644 --- a/eeschema/tools/sch_editor_control.cpp +++ b/eeschema/tools/sch_editor_control.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -2967,6 +2969,89 @@ int SCH_EDITOR_CONTROL::GridFeedback( const TOOL_EVENT& aEvent ) } +int SCH_EDITOR_CONTROL::PlaceLinkedDesignBlock( const TOOL_EVENT& aEvent ) +{ + SCH_EDIT_FRAME* editFrame = dynamic_cast( m_frame ); + + if( !editFrame ) + return 1; + + // Need to have a group selected and it needs to have a linked design block + SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool(); + SCH_SELECTION selection = selTool->GetSelection(); + + if( selection.Size() != 1 || selection[0]->Type() != SCH_GROUP_T ) + return 1; + + SCH_GROUP* group = static_cast( selection[0] ); + + if( !group->HasDesignBlockLink() ) + return 1; + + // Get the associated design block + DESIGN_BLOCK* designBlock = + editFrame->GetDesignBlockPane()->GetDesignBlock( group->GetDesignBlockLibId(), true, true ); + + if( !designBlock ) + { + wxString msg; + msg.Printf( _( "Could not find design block %s." ), group->GetDesignBlockLibId().GetUniStringLibId() ); + m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING ); + return 1; + } + + if( designBlock->GetSchematicFile().IsEmpty() ) + { + wxString msg; + msg.Printf( _( "Design block %s does not have a schematic file." ), + group->GetDesignBlockLibId().GetUniStringLibId() ); + m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING ); + return 1; + } + + editFrame->GetDesignBlockPane()->SelectLibId( group->GetDesignBlockLibId() ); + + return m_toolMgr->RunAction( SCH_ACTIONS::placeDesignBlock, designBlock ); +} + + +int SCH_EDITOR_CONTROL::SaveToLinkedDesignBlock( const TOOL_EVENT& aEvent ) +{ + SCH_EDIT_FRAME* editFrame = dynamic_cast( m_frame ); + + if( !editFrame ) + return 1; + + // Need to have a group selected and it needs to have a linked design block + SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool(); + SCH_SELECTION selection = selTool->GetSelection(); + + if( selection.Size() != 1 || selection[0]->Type() != SCH_GROUP_T ) + return 1; + + SCH_GROUP* group = static_cast( selection[0] ); + + if( !group->HasDesignBlockLink() ) + return 1; + + // Get the associated design block + DESIGN_BLOCK* designBlock = + editFrame->GetDesignBlockPane()->GetDesignBlock( group->GetDesignBlockLibId(), true, true ); + + if( !designBlock ) + { + wxString msg; + msg.Printf( _( "Could not find design block %s." ), group->GetDesignBlockLibId().GetUniStringLibId() ); + m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING ); + return 1; + } + + editFrame->GetDesignBlockPane()->SelectLibId( group->GetDesignBlockLibId() ); + + return m_toolMgr->RunAction( SCH_ACTIONS::saveSelectionToDesignBlock ) ? 1 : 0; +} + + void SCH_EDITOR_CONTROL::setTransitions() { Go( &SCH_EDITOR_CONTROL::New, ACTIONS::doNew.MakeEvent() ); @@ -3057,4 +3142,7 @@ void SCH_EDITOR_CONTROL::setTransitions() Go( &SCH_EDITOR_CONTROL::ExportSymbolsToLibrary, SCH_ACTIONS::exportSymbolsToLibrary.MakeEvent() ); Go( &SCH_EDITOR_CONTROL::ExportSymbolsToLibrary, SCH_ACTIONS::exportSymbolsToNewLibrary.MakeEvent() ); + + Go( &SCH_EDITOR_CONTROL::PlaceLinkedDesignBlock, SCH_ACTIONS::placeLinkedDesignBlock.MakeEvent() ); + Go( &SCH_EDITOR_CONTROL::SaveToLinkedDesignBlock, SCH_ACTIONS::saveToLinkedDesignBlock.MakeEvent() ); } diff --git a/eeschema/tools/sch_editor_control.h b/eeschema/tools/sch_editor_control.h index 6e3b3558be..ea4b38c741 100644 --- a/eeschema/tools/sch_editor_control.h +++ b/eeschema/tools/sch_editor_control.h @@ -178,6 +178,9 @@ public: bool GetHighlightBusMembers() const { return m_highlightBusMembers; } + int PlaceLinkedDesignBlock( const TOOL_EVENT& aEvent ); + int SaveToLinkedDesignBlock( const TOOL_EVENT& aEvent ); + private: ///< copy selection to clipboard or to m_duplicateClipboard bool doCopy( bool aUseDuplicateClipboard = false ); diff --git a/eeschema/tools/sch_selection_tool.cpp b/eeschema/tools/sch_selection_tool.cpp index ab49e6ddbc..53c14f331d 100644 --- a/eeschema/tools/sch_selection_tool.cpp +++ b/eeschema/tools/sch_selection_tool.cpp @@ -304,6 +304,8 @@ bool SCH_SELECTION_TOOL::Init() // clang-format off menu.AddItem( ACTIONS::groupEnter, groupEnterCondition, 1 ); menu.AddItem( ACTIONS::groupLeave, inGroupCondition, 1 ); + menu.AddItem( SCH_ACTIONS::placeLinkedDesignBlock, groupEnterCondition, 1 ); + menu.AddItem( SCH_ACTIONS::saveToLinkedDesignBlock, groupEnterCondition, 1 ); menu.AddItem( SCH_ACTIONS::clearHighlight, haveHighlight && SCH_CONDITIONS::Idle, 1 ); menu.AddSeparator( haveHighlight && SCH_CONDITIONS::Idle, 1 ); diff --git a/pcbnew/pcb_design_block_utils.cpp b/pcbnew/pcb_design_block_utils.cpp index cde8562b01..b23fab29ee 100644 --- a/pcbnew/pcb_design_block_utils.cpp +++ b/pcbnew/pcb_design_block_utils.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -262,16 +263,35 @@ bool PCB_EDIT_FRAME::saveSelectionToDesignBlock( const wxString& aNickname, PCB_ } }; + auto cloneAndAdd = + [&] ( EDA_ITEM* aItem ) + { + if( !aItem->IsBOARD_ITEM() ) + return static_cast( nullptr ); + + BOARD_ITEM* copy = static_cast( aItem->Clone() ); + tempBoard->Add( copy, ADD_MODE::APPEND, false ); + return copy; + }; + // Copy the selected items to the temporary board for( EDA_ITEM* item : aSelection ) { - EDA_ITEM* copy = item->Clone(); - tempBoard->Add( static_cast( copy ), ADD_MODE::APPEND, false ); + if( BOARD_ITEM* copy = cloneAndAdd( item ) ) + copy->SetParentGroup( nullptr ); - if( FOOTPRINT* fp = dynamic_cast( item ) ) - fp->RunOnChildren( addNetIfNeeded, RECURSE_MODE::NO_RECURSE ); + if( item->Type() == PCB_FOOTPRINT_T ) + static_cast( item )->RunOnChildren( addNetIfNeeded, RECURSE_MODE::NO_RECURSE ); + else if( item->Type() == PCB_GROUP_T || item->Type() == PCB_GENERATOR_T ) + { + PCB_GROUP* group = static_cast( item ); + + // Groups also need their children copied + group->RunOnChildren( cloneAndAdd, RECURSE_MODE::RECURSE ); + group->RunOnChildren( addNetIfNeeded, RECURSE_MODE::RECURSE ); + } else - addNetIfNeeded( copy ); + addNetIfNeeded( item ); } // Rebuild connectivity, remove any unused nets @@ -368,6 +388,24 @@ bool PCB_EDIT_FRAME::SaveSelectionToDesignBlock( const LIB_ID& aLibId ) return false; } + // If we have a single group, we want to strip the group and select the children + PCB_GROUP* group = nullptr; + + if( selection.Size() == 1 ) + { + EDA_ITEM* item = selection.Front(); + + if( item->Type() == PCB_GROUP_T || item->Type() == PCB_GENERATOR_T ) + { + group = static_cast( item ); + + selection.Remove( item ); + + // Don't recurse; if we have a group of groups the user probably intends the inner groups to be saved + group->RunOnChildren( [&]( EDA_ITEM* aItem ) { selection.Add( aItem ); }, RECURSE_MODE::NO_RECURSE ); + } + } + DESIGN_BLOCK* blk = nullptr; try @@ -381,9 +419,28 @@ bool PCB_EDIT_FRAME::SaveSelectionToDesignBlock( const LIB_ID& aLibId ) } if( !blk->GetBoardFile().IsEmpty() && !checkOverwriteDbLayout( this, aLibId ) ) - { return false; + + if( !saveSelectionToDesignBlock( aLibId.GetLibNickname(), selection, *blk ) ) + return false; + + // If we had a group, we need to reselect it + if( group ) + { + selection.Clear(); + selection.Add( group ); + + // If we didn't have a design block link before, add one for convenience + if( !group->HasDesignBlockLink() ) + { + BOARD_COMMIT commit( m_toolManager ); + + commit.Modify( group ); + group->SetDesignBlockLibId( aLibId ); + + commit.Push( "Set Group Design Block Link" ); + } } - return saveSelectionToDesignBlock( aLibId.GetLibNickname(), selection, *blk ); + return true; } diff --git a/pcbnew/pcb_edit_frame.cpp b/pcbnew/pcb_edit_frame.cpp index d7fa12d133..b720dc057c 100644 --- a/pcbnew/pcb_edit_frame.cpp +++ b/pcbnew/pcb_edit_frame.cpp @@ -858,8 +858,6 @@ void PCB_EDIT_FRAME::setupUIConditions() mgr->SetConditions( ACTIONS::doDelete, ENABLE( cond.HasItems() ) ); mgr->SetConditions( ACTIONS::duplicate, ENABLE( cond.HasItems() ) ); - mgr->SetConditions( PCB_ACTIONS::placeLinkedDesignBlock, ENABLE( groupWithDesignBlockLink) ); - static const std::vector groupTypes = { PCB_GROUP_T, PCB_GENERATOR_T }; mgr->SetConditions( ACTIONS::group, ENABLE( SELECTION_CONDITIONS::NotEmpty ) ); @@ -867,6 +865,9 @@ void PCB_EDIT_FRAME::setupUIConditions() mgr->SetConditions( PCB_ACTIONS::lock, ENABLE( PCB_SELECTION_CONDITIONS::HasUnlockedItems ) ); mgr->SetConditions( PCB_ACTIONS::unlock, ENABLE( PCB_SELECTION_CONDITIONS::HasLockedItems ) ); + mgr->SetConditions( PCB_ACTIONS::placeLinkedDesignBlock, ENABLE( groupWithDesignBlockLink) ); + mgr->SetConditions( PCB_ACTIONS::saveToLinkedDesignBlock, ENABLE( groupWithDesignBlockLink) ); + mgr->SetConditions( PCB_ACTIONS::padDisplayMode, CHECK( !cond.PadFillDisplay() ) ); mgr->SetConditions( PCB_ACTIONS::viaDisplayMode, CHECK( !cond.ViaFillDisplay() ) ); mgr->SetConditions( PCB_ACTIONS::trackDisplayMode, CHECK( !cond.TrackFillDisplay() ) ); diff --git a/pcbnew/tools/pcb_actions.cpp b/pcbnew/tools/pcb_actions.cpp index 274f40e1d2..ef1a62742e 100644 --- a/pcbnew/tools/pcb_actions.cpp +++ b/pcbnew/tools/pcb_actions.cpp @@ -463,6 +463,13 @@ TOOL_ACTION PCB_ACTIONS::placeLinkedDesignBlock( TOOL_ACTION_ARGS() .Icon( BITMAPS::add_component ) .Flags( AF_ACTIVATE ) ); +TOOL_ACTION PCB_ACTIONS::saveToLinkedDesignBlock( TOOL_ACTION_ARGS() + .Name( "pcbnew.InteractiveDrawing.saveToLinkedDesignBlock" ) + .Scope( AS_GLOBAL ) + .FriendlyName( _( "Save to Linked Design Block" ) ) + .Tooltip( _( "Save selected group to linked design block" ) ) + .Icon( BITMAPS::add_component ) + .Flags( AF_ACTIVATE ) ); TOOL_ACTION PCB_ACTIONS::showDesignBlockPanel( TOOL_ACTION_ARGS() .Name( "pcbnew.PcbDesignBlockControl.showDesignBlockPanel" ) diff --git a/pcbnew/tools/pcb_actions.h b/pcbnew/tools/pcb_actions.h index a3915c097e..e4736cdefd 100644 --- a/pcbnew/tools/pcb_actions.h +++ b/pcbnew/tools/pcb_actions.h @@ -438,6 +438,7 @@ public: // Design Block management static TOOL_ACTION placeDesignBlock; static TOOL_ACTION placeLinkedDesignBlock; + static TOOL_ACTION saveToLinkedDesignBlock; static TOOL_ACTION showDesignBlockPanel; static TOOL_ACTION saveBoardAsDesignBlock; static TOOL_ACTION saveSelectionAsDesignBlock; diff --git a/pcbnew/tools/pcb_control.cpp b/pcbnew/tools/pcb_control.cpp index 8ae3c90cb9..06d1de323a 100644 --- a/pcbnew/tools/pcb_control.cpp +++ b/pcbnew/tools/pcb_control.cpp @@ -1406,6 +1406,43 @@ int PCB_CONTROL::PlaceLinkedDesignBlock( const TOOL_EVENT& aEvent ) } +int PCB_CONTROL::SaveToLinkedDesignBlock( const TOOL_EVENT& aEvent ) +{ + PCB_EDIT_FRAME* editFrame = dynamic_cast( m_frame ); + + if( !editFrame ) + return 1; + + // Need to have a group selected and it needs to have a linked design block + PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool(); + PCB_SELECTION selection = selTool->GetSelection(); + + if( selection.Size() != 1 || selection[0]->Type() != PCB_GROUP_T ) + return 1; + + PCB_GROUP* group = static_cast( selection[0] ); + + if( !group->HasDesignBlockLink() ) + return 1; + + // Get the associated design block + DESIGN_BLOCK* designBlock = + editFrame->GetDesignBlockPane()->GetDesignBlock( group->GetDesignBlockLibId(), true, true ); + + if( !designBlock ) + { + wxString msg; + msg.Printf( _( "Could not find design block %s." ), group->GetDesignBlockLibId().GetUniStringLibId() ); + m_frame->GetInfoBar()->ShowMessageFor( msg, 5000, wxICON_WARNING ); + return 1; + } + + editFrame->GetDesignBlockPane()->SelectLibId( group->GetDesignBlockLibId() ); + + return m_toolMgr->RunAction( PCB_ACTIONS::saveSelectionToDesignBlock ) ? 1 : 0; +} + + template static void moveUnflaggedItems( const std::deque& aList, std::vector& aTarget, bool aIsNew ) @@ -2576,6 +2613,7 @@ void PCB_CONTROL::setTransitions() // Append control Go( &PCB_CONTROL::AppendDesignBlock, PCB_ACTIONS::placeDesignBlock.MakeEvent() ); Go( &PCB_CONTROL::PlaceLinkedDesignBlock, PCB_ACTIONS::placeLinkedDesignBlock.MakeEvent() ); + Go( &PCB_CONTROL::SaveToLinkedDesignBlock, PCB_ACTIONS::saveToLinkedDesignBlock.MakeEvent() ); Go( &PCB_CONTROL::AppendBoardFromFile, PCB_ACTIONS::appendBoard.MakeEvent() ); Go( &PCB_CONTROL::DdAppendBoard, PCB_ACTIONS::ddAppendBoard.MakeEvent() ); Go( &PCB_CONTROL::PlaceCharacteristics, PCB_ACTIONS::placeCharacteristics.MakeEvent() ); diff --git a/pcbnew/tools/pcb_control.h b/pcbnew/tools/pcb_control.h index 8ee700fa09..99f9b42afb 100644 --- a/pcbnew/tools/pcb_control.h +++ b/pcbnew/tools/pcb_control.h @@ -108,6 +108,7 @@ public: int AppendBoardFromFile( const TOOL_EVENT& aEvent ); int AppendDesignBlock( const TOOL_EVENT& aEvent ); int PlaceLinkedDesignBlock( const TOOL_EVENT& aEvent ); + int SaveToLinkedDesignBlock( const TOOL_EVENT& aEvent ); int AppendBoard( PCB_IO& pi, const wxString& fileName, DESIGN_BLOCK* aDesignBlock = nullptr ); int UpdateMessagePanel( const TOOL_EVENT& aEvent ); int PlaceCharacteristics( const TOOL_EVENT& aEvent ); diff --git a/pcbnew/tools/pcb_design_block_control.cpp b/pcbnew/tools/pcb_design_block_control.cpp index aa34640cfd..a59d73cc72 100644 --- a/pcbnew/tools/pcb_design_block_control.cpp +++ b/pcbnew/tools/pcb_design_block_control.cpp @@ -84,7 +84,10 @@ int PCB_DESIGN_BLOCK_CONTROL::SaveBoardAsDesignBlock( const TOOL_EVENT& aEvent ) if( !current ) return -1; - if( !m_editFrame->SaveBoardAsDesignBlock( current->m_LibId.GetLibNickname() ) ) + // This can be modified as a result of the save operation so copy it + LIB_ID libId = current->m_LibId; + + if( !m_editFrame->SaveBoardAsDesignBlock( libId.GetLibNickname() ) ) return -1; notifyOtherFrames(); @@ -100,7 +103,10 @@ int PCB_DESIGN_BLOCK_CONTROL::SaveSelectionAsDesignBlock( const TOOL_EVENT& aEve if( !current ) return -1; - if( !m_editFrame->SaveSelectionAsDesignBlock( current->m_LibId.GetLibNickname() ) ) + // This can be modified as a result of the save operation so copy it + LIB_ID libId = current->m_LibId; + + if( !m_editFrame->SaveSelectionAsDesignBlock( libId.GetLibNickname() ) ) return -1; notifyOtherFrames(); @@ -116,7 +122,10 @@ int PCB_DESIGN_BLOCK_CONTROL::SaveBoardToDesignBlock( const TOOL_EVENT& aEvent ) if( !current ) return -1; - if( !m_editFrame->SaveBoardToDesignBlock( current->m_LibId ) ) + // This can be modified as a result of the save operation so copy it + LIB_ID libId = current->m_LibId; + + if( !m_editFrame->SaveBoardToDesignBlock( libId ) ) return -1; notifyOtherFrames(); @@ -132,7 +141,10 @@ int PCB_DESIGN_BLOCK_CONTROL::SaveSelectionToDesignBlock( const TOOL_EVENT& aEve if( !current ) return -1; - if( !m_editFrame->SaveSelectionToDesignBlock( current->m_LibId ) ) + // This can be modified as a result of the save operation so copy it + LIB_ID libId = current->m_LibId; + + if( !m_editFrame->SaveSelectionToDesignBlock( libId ) ) return -1; notifyOtherFrames(); diff --git a/pcbnew/tools/pcb_selection_tool.cpp b/pcbnew/tools/pcb_selection_tool.cpp index 1cc880f277..8e42fb38a6 100644 --- a/pcbnew/tools/pcb_selection_tool.cpp +++ b/pcbnew/tools/pcb_selection_tool.cpp @@ -213,6 +213,7 @@ bool PCB_SELECTION_TOOL::Init() menu.AddItem( ACTIONS::groupEnter, groupEnterCondition, 1 ); menu.AddItem( ACTIONS::groupLeave, inGroupCondition, 1 ); menu.AddItem( PCB_ACTIONS::placeLinkedDesignBlock, groupEnterCondition, 1 ); + menu.AddItem( PCB_ACTIONS::saveToLinkedDesignBlock, groupEnterCondition, 1 ); menu.AddItem( PCB_ACTIONS::clearHighlight, haveHighlight, 1 ); menu.AddSeparator( haveHighlight, 1 );