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.
This commit is contained in:
Ian McInerney 2020-08-20 01:22:48 +01:00
parent 68f1c678dd
commit c479deaf02
6 changed files with 101 additions and 33 deletions

View File

@ -35,6 +35,7 @@
#ifndef CLASS_PCB_GROUP_H_ #ifndef CLASS_PCB_GROUP_H_
#define CLASS_PCB_GROUP_H_ #define CLASS_PCB_GROUP_H_
#include <board_commit.h>
#include <class_board_item.h> #include <class_board_item.h>
#include <common.h> #include <common.h>
#include <unordered_set> #include <unordered_set>
@ -172,6 +173,20 @@ public:
///> @copydoc EDA_ITEM::GetMsgPanelInfo ///> @copydoc EDA_ITEM::GetMsgPanelInfo
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override; void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& 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. * Invokes a function on all members of the group.
* Note that this function should not add or remove items to the group * Note that this function should not add or remove items to the group

View File

@ -37,6 +37,7 @@
// Static members of DIALOG_IMPORT_GFX, to remember the user's choices during the session // Static members of DIALOG_IMPORT_GFX, to remember the user's choices during the session
wxString DIALOG_IMPORT_GFX::m_filename; wxString DIALOG_IMPORT_GFX::m_filename;
bool DIALOG_IMPORT_GFX::m_placementInteractive = true; bool DIALOG_IMPORT_GFX::m_placementInteractive = true;
bool DIALOG_IMPORT_GFX::m_shouldGroupItems = true;
LAYER_NUM DIALOG_IMPORT_GFX::m_layer = Dwgs_User; LAYER_NUM DIALOG_IMPORT_GFX::m_layer = Dwgs_User;
double DIALOG_IMPORT_GFX::m_scaleImport = 1.0; // Do not change the imported items size double DIALOG_IMPORT_GFX::m_scaleImport = 1.0; // Do not change the imported items size
int DIALOG_IMPORT_GFX::m_originUnits = 0; // millimeter 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_textCtrlFileName->SetValue( m_filename );
m_rbInteractivePlacement->SetValue( m_placementInteractive ); m_rbInteractivePlacement->SetValue( m_placementInteractive );
m_rbAbsolutePlacement->SetValue( not m_placementInteractive ); m_rbAbsolutePlacement->SetValue( not m_placementInteractive );
m_groupItems->SetValue( m_shouldGroupItems );
m_textCtrlImportScale->SetValue( wxString::Format( "%f", m_scaleImport ) ); m_textCtrlImportScale->SetValue( wxString::Format( "%f", m_scaleImport ) );

View File

@ -56,6 +56,14 @@ public:
return m_placementInteractive; 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; bool TransferDataFromWindow() override;
private: private:
@ -67,6 +75,7 @@ private:
// Always in mm // Always in mm
static wxString m_filename; static wxString m_filename;
static bool m_shouldGroupItems;
static bool m_placementInteractive; static bool m_placementInteractive;
static LAYER_NUM m_layer; static LAYER_NUM m_layer;
double m_lineWidth; // always in mm: line width when a line width double m_lineWidth; // always in mm: line width when a line width
@ -91,6 +100,11 @@ private:
m_placementInteractive = false; m_placementInteractive = false;
} }
void onGroupItems( wxCommandEvent& event ) override
{
m_shouldGroupItems = m_groupItems->GetValue();
}
void updatePcbImportOffsets_mm(); void updatePcbImportOffsets_mm();
double getPCBdefaultLineWidthMM(); double getPCBdefaultLineWidthMM();
void showPCBdefaultLineWidth(); void showPCBdefaultLineWidth();

View File

@ -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/ // http://www.wxformbuilder.org/
// //
// PLEASE DO *NOT* EDIT THIS FILE! // 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 ); 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 ); 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 ); 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 ); 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 = new wxChoice( sbSizer1->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceUnitLineWidthNChoices, m_choiceUnitLineWidthChoices, 0 );
m_choiceUnitLineWidth->SetSelection( 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 = new wxStaticText( sbSizer1->GetStaticBox(), wxID_ANY, _("Graphic layer:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextBrdlayer->Wrap( -1 ); 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 ); 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 ); 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->SetSizer( bSizerMain );
this->Layout(); this->Layout();
bSizerMain->Fit( this );
this->Centre( wxBOTH ); 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_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_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_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() 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_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_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_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 );
} }

View File

@ -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/ // http://www.wxformbuilder.org/
// //
// PLEASE DO *NOT* EDIT THIS FILE! // PLEASE DO *NOT* EDIT THIS FILE!
@ -30,6 +30,8 @@ class PCB_LAYER_BOX_SELECTOR;
#include <wx/choice.h> #include <wx/choice.h>
#include <wx/statbox.h> #include <wx/statbox.h>
#include <wx/bmpcbox.h> #include <wx/bmpcbox.h>
#include <wx/statline.h>
#include <wx/checkbox.h>
#include <wx/dialog.h> #include <wx/dialog.h>
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@ -61,6 +63,8 @@ class DIALOG_IMPORT_GFX_BASE : public DIALOG_SHIM
PCB_LAYER_BOX_SELECTOR* m_SelLayerBox; PCB_LAYER_BOX_SELECTOR* m_SelLayerBox;
wxStaticText* m_staticTextscale; wxStaticText* m_staticTextscale;
wxTextCtrl* m_textCtrlImportScale; wxTextCtrl* m_textCtrlImportScale;
wxStaticLine* m_staticline1;
wxCheckBox* m_groupItems;
wxStdDialogButtonSizer* m_sdbSizer; wxStdDialogButtonSizer* m_sdbSizer;
wxButton* m_sdbSizerOK; wxButton* m_sdbSizerOK;
wxButton* m_sdbSizerCancel; wxButton* m_sdbSizerCancel;
@ -72,11 +76,12 @@ class DIALOG_IMPORT_GFX_BASE : public DIALOG_SHIM
virtual void onAbsolutePlacement( wxCommandEvent& event ) { event.Skip(); } virtual void onAbsolutePlacement( wxCommandEvent& event ) { event.Skip(); }
virtual void onUnitPositionSelection( wxCommandEvent& event ) { event.Skip(); } virtual void onUnitPositionSelection( wxCommandEvent& event ) { event.Skip(); }
virtual void onUnitWidthSelection( wxCommandEvent& event ) { event.Skip(); } virtual void onUnitWidthSelection( wxCommandEvent& event ) { event.Skip(); }
virtual void onGroupItems( wxCommandEvent& event ) { event.Skip(); }
public: 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(); ~DIALOG_IMPORT_GFX_BASE();
}; };

View File

@ -751,7 +751,7 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent )
DIALOG_IMPORT_GFX dlg( m_frame, m_editModules ); DIALOG_IMPORT_GFX dlg( m_frame, m_editModules );
int dlgResult = dlg.ShowModal(); int dlgResult = dlg.ShowModal();
auto& list = dlg.GetImportedItems(); std::list<std::unique_ptr<EDA_ITEM>>& list = dlg.GetImportedItems();
if( dlgResult != wxID_OK ) if( dlgResult != wxID_OK )
return 0; 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 // Add a VIEW_GROUP that serves as a preview for the new item
PCBNEW_SELECTION preview; 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 // Build the undo list & add items to the current view
for( auto& ptr : list) for( auto& ptr : list)
@ -779,7 +783,9 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent )
else else
wxASSERT( item->Type() == PCB_LINE_T || item->Type() == PCB_TEXT_T ); wxASSERT( item->Type() == PCB_LINE_T || item->Type() == PCB_TEXT_T );
if( dlg.IsPlacementInteractive() ) if( grp )
grp->AddItem( static_cast<BOARD_ITEM*>( item ) );
else if( dlg.IsPlacementInteractive() )
preview.Add( item ); preview.Add( item );
else else
commit.Add( item ); commit.Add( item );
@ -789,14 +795,31 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent )
if( !dlg.IsPlacementInteractive() ) if( !dlg.IsPlacementInteractive() )
{ {
if( grp )
{
grp->AddChildrenToCommit( commit );
commit.Add( grp );
}
commit.Push( _( "Place a DXF_SVG drawing" ) ); commit.Push( _( "Place a DXF_SVG drawing" ) );
return 0; return 0;
} }
if( grp )
preview.Add( grp );
std::vector<BOARD_ITEM*> newItems;
for( EDA_ITEM* item : preview )
newItems.push_back( static_cast<BOARD_ITEM*>( item ) );
BOARD_ITEM* firstItem = static_cast<BOARD_ITEM*>( preview.Front() ); BOARD_ITEM* firstItem = static_cast<BOARD_ITEM*>( preview.Front() );
m_view->Add( &preview ); 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::selectionClear, true );
m_toolMgr->RunAction( PCB_ACTIONS::selectItems, true, &newItems );
m_controls->ShowCursor( true ); m_controls->ShowCursor( true );
m_controls->SetSnapping( true ); m_controls->SetSnapping( true );
m_controls->ForceCursorPosition( false ); m_controls->ForceCursorPosition( false );
@ -824,6 +847,18 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent )
if( evt->IsCancelInteractive() || evt->IsActivate() ) 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(); preview.FreeItems();
break; break;
} }
@ -836,29 +871,6 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent )
m_view->Update( &preview ); 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<BOARD_ITEM*>( 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<BOARD_ITEM*>( item )->Flip( (wxPoint) cursorPos, leftRight );
m_view->Update( &preview );
}
}
else if( evt->IsClick( BUT_RIGHT ) ) else if( evt->IsClick( BUT_RIGHT ) )
{ {
m_menu.ShowContextMenu( selection() ); m_menu.ShowContextMenu( selection() );
@ -867,7 +879,12 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent )
{ {
// Place the imported drawings // Place the imported drawings
for( EDA_ITEM* item : preview ) for( EDA_ITEM* item : preview )
{
if( item->Type() == PCB_GROUP_T )
static_cast<PCB_GROUP*>( item )->AddChildrenToCommit( commit );
commit.Add( item ); commit.Add( item );
}
commit.Push( _( "Place a DXF_SVG drawing" ) ); commit.Push( _( "Place a DXF_SVG drawing" ) );
break; // This is a one-shot command, not a tool break; // This is a one-shot command, not a tool