From c479deaf02e9f9cd7129ed79f1600aa80c71661f Mon Sep 17 00:00:00 2001 From: Ian McInerney Date: Thu, 20 Aug 2020 01:22:48 +0100 Subject: [PATCH] Use groups when doing graphics import ADDED: Allow DXF/SVG graphics to be imported as a group Also, cleanup the placement routine to allow the edit tool's flip and rotate routines to be used when placing the items. --- include/class_pcb_group.h | 15 +++++ pcbnew/import_gfx/dialog_import_gfx.cpp | 2 + pcbnew/import_gfx/dialog_import_gfx.h | 14 ++++ pcbnew/import_gfx/dialog_import_gfx_base.cpp | 25 +++++-- pcbnew/import_gfx/dialog_import_gfx_base.h | 9 ++- pcbnew/tools/drawing_tool.cpp | 69 ++++++++++++-------- 6 files changed, 101 insertions(+), 33 deletions(-) diff --git a/include/class_pcb_group.h b/include/class_pcb_group.h index d8e26765ca..ef28b03aeb 100644 --- a/include/class_pcb_group.h +++ b/include/class_pcb_group.h @@ -35,6 +35,7 @@ #ifndef CLASS_PCB_GROUP_H_ #define CLASS_PCB_GROUP_H_ +#include #include #include #include @@ -172,6 +173,20 @@ public: ///> @copydoc EDA_ITEM::GetMsgPanelInfo void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector& aList ) override; + /** + * Add all the immediate children of this group to the board commit. This function does not + * enter any subgroups of this group, or add the group itself. + * + * @param aCommit is the commit to add the children to. + */ + void AddChildrenToCommit( BOARD_COMMIT& aCommit ) + { + RunOnChildren( [&]( BOARD_ITEM* bItem ) + { + aCommit.Add( bItem ); + } ); + } + /** * Invokes a function on all members of the group. * Note that this function should not add or remove items to the group diff --git a/pcbnew/import_gfx/dialog_import_gfx.cpp b/pcbnew/import_gfx/dialog_import_gfx.cpp index 827e8c1da7..cf140c48bc 100644 --- a/pcbnew/import_gfx/dialog_import_gfx.cpp +++ b/pcbnew/import_gfx/dialog_import_gfx.cpp @@ -37,6 +37,7 @@ // Static members of DIALOG_IMPORT_GFX, to remember the user's choices during the session wxString DIALOG_IMPORT_GFX::m_filename; bool DIALOG_IMPORT_GFX::m_placementInteractive = true; +bool DIALOG_IMPORT_GFX::m_shouldGroupItems = true; LAYER_NUM DIALOG_IMPORT_GFX::m_layer = Dwgs_User; double DIALOG_IMPORT_GFX::m_scaleImport = 1.0; // Do not change the imported items size int DIALOG_IMPORT_GFX::m_originUnits = 0; // millimeter @@ -95,6 +96,7 @@ DIALOG_IMPORT_GFX::DIALOG_IMPORT_GFX( PCB_BASE_FRAME* aParent, bool aImportAsFoo m_textCtrlFileName->SetValue( m_filename ); m_rbInteractivePlacement->SetValue( m_placementInteractive ); m_rbAbsolutePlacement->SetValue( not m_placementInteractive ); + m_groupItems->SetValue( m_shouldGroupItems ); m_textCtrlImportScale->SetValue( wxString::Format( "%f", m_scaleImport ) ); diff --git a/pcbnew/import_gfx/dialog_import_gfx.h b/pcbnew/import_gfx/dialog_import_gfx.h index 5f5397493f..008984fc04 100644 --- a/pcbnew/import_gfx/dialog_import_gfx.h +++ b/pcbnew/import_gfx/dialog_import_gfx.h @@ -56,6 +56,14 @@ public: return m_placementInteractive; } + /** + * @return true if the items should be added into a group when being placed. + */ + bool ShouldGroupItems() + { + return m_shouldGroupItems; + } + bool TransferDataFromWindow() override; private: @@ -67,6 +75,7 @@ private: // Always in mm static wxString m_filename; + static bool m_shouldGroupItems; static bool m_placementInteractive; static LAYER_NUM m_layer; double m_lineWidth; // always in mm: line width when a line width @@ -91,6 +100,11 @@ private: m_placementInteractive = false; } + void onGroupItems( wxCommandEvent& event ) override + { + m_shouldGroupItems = m_groupItems->GetValue(); + } + void updatePcbImportOffsets_mm(); double getPCBdefaultLineWidthMM(); void showPCBdefaultLineWidth(); diff --git a/pcbnew/import_gfx/dialog_import_gfx_base.cpp b/pcbnew/import_gfx/dialog_import_gfx_base.cpp index 8c9bbef1da..337b504a16 100644 --- a/pcbnew/import_gfx/dialog_import_gfx_base.cpp +++ b/pcbnew/import_gfx/dialog_import_gfx_base.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Jul 10 2019) +// C++ code generated with wxFormBuilder (version Oct 26 2018) // http://www.wxformbuilder.org/ // // PLEASE DO *NOT* EDIT THIS FILE! @@ -107,13 +107,13 @@ DIALOG_IMPORT_GFX_BASE::DIALOG_IMPORT_GFX_BASE( wxWindow* parent, wxWindowID id, bSizerPosSettings->Add( m_DxfPcbPositionUnits, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - bSizerUserPos->Add( bSizerPosSettings, 1, wxBOTTOM|wxEXPAND|wxTOP, 5 ); + bSizerUserPos->Add( bSizerPosSettings, 1, wxBOTTOM|wxEXPAND|wxRIGHT|wxTOP, 5 ); bSizerOptions->Add( bSizerUserPos, 0, wxEXPAND, 5 ); - sbSizer2->Add( bSizerOptions, 1, wxEXPAND|wxLEFT, 20 ); + sbSizer2->Add( bSizerOptions, 0, wxEXPAND|wxLEFT, 20 ); bSizerMain->Add( sbSizer2, 1, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 5 ); @@ -144,7 +144,7 @@ DIALOG_IMPORT_GFX_BASE::DIALOG_IMPORT_GFX_BASE( wxWindow* parent, wxWindowID id, int m_choiceUnitLineWidthNChoices = sizeof( m_choiceUnitLineWidthChoices ) / sizeof( wxString ); m_choiceUnitLineWidth = new wxChoice( sbSizer1->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceUnitLineWidthNChoices, m_choiceUnitLineWidthChoices, 0 ); m_choiceUnitLineWidth->SetSelection( 0 ); - fgSizerImportSettings->Add( m_choiceUnitLineWidth, 0, wxALIGN_CENTER_VERTICAL, 5 ); + fgSizerImportSettings->Add( m_choiceUnitLineWidth, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); m_staticTextBrdlayer = new wxStaticText( sbSizer1->GetStaticBox(), wxID_ANY, _("Graphic layer:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticTextBrdlayer->Wrap( -1 ); @@ -172,6 +172,20 @@ DIALOG_IMPORT_GFX_BASE::DIALOG_IMPORT_GFX_BASE( wxWindow* parent, wxWindowID id, sbSizer1->Add( bSizer7, 1, wxEXPAND, 5 ); + m_staticline1 = new wxStaticLine( sbSizer1->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + sbSizer1->Add( m_staticline1, 0, wxALL|wxEXPAND, 5 ); + + wxBoxSizer* bSizer8; + bSizer8 = new wxBoxSizer( wxVERTICAL ); + + m_groupItems = new wxCheckBox( sbSizer1->GetStaticBox(), wxID_ANY, _("Group items"), wxDefaultPosition, wxDefaultSize, 0 ); + m_groupItems->SetToolTip( _("Add all imported items into a new group") ); + + bSizer8->Add( m_groupItems, 0, wxBOTTOM|wxEXPAND|wxLEFT, 10 ); + + + sbSizer1->Add( bSizer8, 0, wxALL|wxEXPAND, 5 ); + bSizerMain->Add( sbSizer1, 1, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 5 ); @@ -190,7 +204,6 @@ DIALOG_IMPORT_GFX_BASE::DIALOG_IMPORT_GFX_BASE( wxWindow* parent, wxWindowID id, this->SetSizer( bSizerMain ); this->Layout(); - bSizerMain->Fit( this ); this->Centre( wxBOTH ); @@ -202,6 +215,7 @@ DIALOG_IMPORT_GFX_BASE::DIALOG_IMPORT_GFX_BASE( wxWindow* parent, wxWindowID id, m_rbAbsolutePlacement->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_IMPORT_GFX_BASE::originOptionOnUpdateUI ), NULL, this ); m_DxfPcbPositionUnits->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_IMPORT_GFX_BASE::onUnitPositionSelection ), NULL, this ); m_choiceUnitLineWidth->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_IMPORT_GFX_BASE::onUnitWidthSelection ), NULL, this ); + m_groupItems->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_GFX_BASE::onGroupItems ), NULL, this ); } DIALOG_IMPORT_GFX_BASE::~DIALOG_IMPORT_GFX_BASE() @@ -214,5 +228,6 @@ DIALOG_IMPORT_GFX_BASE::~DIALOG_IMPORT_GFX_BASE() m_rbAbsolutePlacement->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_IMPORT_GFX_BASE::originOptionOnUpdateUI ), NULL, this ); m_DxfPcbPositionUnits->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_IMPORT_GFX_BASE::onUnitPositionSelection ), NULL, this ); m_choiceUnitLineWidth->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_IMPORT_GFX_BASE::onUnitWidthSelection ), NULL, this ); + m_groupItems->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_GFX_BASE::onGroupItems ), NULL, this ); } diff --git a/pcbnew/import_gfx/dialog_import_gfx_base.h b/pcbnew/import_gfx/dialog_import_gfx_base.h index 92ed242071..d313a2a04c 100644 --- a/pcbnew/import_gfx/dialog_import_gfx_base.h +++ b/pcbnew/import_gfx/dialog_import_gfx_base.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Jul 10 2019) +// C++ code generated with wxFormBuilder (version Oct 26 2018) // http://www.wxformbuilder.org/ // // PLEASE DO *NOT* EDIT THIS FILE! @@ -30,6 +30,8 @@ class PCB_LAYER_BOX_SELECTOR; #include #include #include +#include +#include #include /////////////////////////////////////////////////////////////////////////// @@ -61,6 +63,8 @@ class DIALOG_IMPORT_GFX_BASE : public DIALOG_SHIM PCB_LAYER_BOX_SELECTOR* m_SelLayerBox; wxStaticText* m_staticTextscale; wxTextCtrl* m_textCtrlImportScale; + wxStaticLine* m_staticline1; + wxCheckBox* m_groupItems; wxStdDialogButtonSizer* m_sdbSizer; wxButton* m_sdbSizerOK; wxButton* m_sdbSizerCancel; @@ -72,11 +76,12 @@ class DIALOG_IMPORT_GFX_BASE : public DIALOG_SHIM virtual void onAbsolutePlacement( wxCommandEvent& event ) { event.Skip(); } virtual void onUnitPositionSelection( wxCommandEvent& event ) { event.Skip(); } virtual void onUnitWidthSelection( wxCommandEvent& event ) { event.Skip(); } + virtual void onGroupItems( wxCommandEvent& event ) { event.Skip(); } public: - DIALOG_IMPORT_GFX_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Import Vector Graphics File"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + DIALOG_IMPORT_GFX_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Import Vector Graphics File"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 446,432 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); ~DIALOG_IMPORT_GFX_BASE(); }; diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp index c3dac1acd3..0d9bdc16a0 100644 --- a/pcbnew/tools/drawing_tool.cpp +++ b/pcbnew/tools/drawing_tool.cpp @@ -751,7 +751,7 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent ) DIALOG_IMPORT_GFX dlg( m_frame, m_editModules ); int dlgResult = dlg.ShowModal(); - auto& list = dlg.GetImportedItems(); + std::list>& list = dlg.GetImportedItems(); if( dlgResult != wxID_OK ) return 0; @@ -767,7 +767,11 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent ) // Add a VIEW_GROUP that serves as a preview for the new item PCBNEW_SELECTION preview; - BOARD_COMMIT commit( m_frame ); + BOARD_COMMIT commit( m_frame ); + PCB_GROUP* grp = nullptr; + + if( dlg.ShouldGroupItems() ) + grp = new PCB_GROUP( m_frame->GetBoard() ); // Build the undo list & add items to the current view for( auto& ptr : list) @@ -779,7 +783,9 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent ) else wxASSERT( item->Type() == PCB_LINE_T || item->Type() == PCB_TEXT_T ); - if( dlg.IsPlacementInteractive() ) + if( grp ) + grp->AddItem( static_cast( item ) ); + else if( dlg.IsPlacementInteractive() ) preview.Add( item ); else commit.Add( item ); @@ -789,14 +795,31 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent ) if( !dlg.IsPlacementInteractive() ) { + if( grp ) + { + grp->AddChildrenToCommit( commit ); + commit.Add( grp ); + } + commit.Push( _( "Place a DXF_SVG drawing" ) ); return 0; } + if( grp ) + preview.Add( grp ); + + std::vector newItems; + + for( EDA_ITEM* item : preview ) + newItems.push_back( static_cast( item ) ); + BOARD_ITEM* firstItem = static_cast( preview.Front() ); m_view->Add( &preview ); + // Clear the current selection then select the drawings so that edit tools work on them m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true ); + m_toolMgr->RunAction( PCB_ACTIONS::selectItems, true, &newItems ); + m_controls->ShowCursor( true ); m_controls->SetSnapping( true ); m_controls->ForceCursorPosition( false ); @@ -824,6 +847,18 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent ) if( evt->IsCancelInteractive() || evt->IsActivate() ) { + m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true ); + + // If a group is being used, we must delete the items themselves, + // since they are only in the group and not in the preview + if( grp ) + { + grp->RunOnChildren( [&]( BOARD_ITEM* bItem ) + { + delete bItem ; + } ); + } + preview.FreeItems(); break; } @@ -836,29 +871,6 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent ) m_view->Update( &preview ); } - else if( evt->Category() == TC_COMMAND ) - { - // TODO it should be handled by EDIT_TOOL, so add items and select? - if( TOOL_EVT_UTILS::IsRotateToolEvt( *evt ) ) - { - const auto rotationPoint = (wxPoint) cursorPos; - const auto rotationAngle = TOOL_EVT_UTILS::GetEventRotationAngle( *m_frame, *evt ); - - for( auto item : preview ) - static_cast( item )->Rotate( rotationPoint, rotationAngle ); - - m_view->Update( &preview ); - } - else if( evt->IsAction( &PCB_ACTIONS::flip ) ) - { - bool leftRight = m_frame->Settings().m_FlipLeftRight; - - for( EDA_ITEM* item : preview ) - static_cast( item )->Flip( (wxPoint) cursorPos, leftRight ); - - m_view->Update( &preview ); - } - } else if( evt->IsClick( BUT_RIGHT ) ) { m_menu.ShowContextMenu( selection() ); @@ -867,7 +879,12 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent ) { // Place the imported drawings for( EDA_ITEM* item : preview ) + { + if( item->Type() == PCB_GROUP_T ) + static_cast( item )->AddChildrenToCommit( commit ); + commit.Add( item ); + } commit.Push( _( "Place a DXF_SVG drawing" ) ); break; // This is a one-shot command, not a tool