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_
#define CLASS_PCB_GROUP_H_
#include <board_commit.h>
#include <class_board_item.h>
#include <common.h>
#include <unordered_set>
@ -172,6 +173,20 @@ public:
///> @copydoc EDA_ITEM::GetMsgPanelInfo
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.
* 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
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 ) );

View File

@ -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();

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/
//
// 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 );
}

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/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -30,6 +30,8 @@ class PCB_LAYER_BOX_SELECTOR;
#include <wx/choice.h>
#include <wx/statbox.h>
#include <wx/bmpcbox.h>
#include <wx/statline.h>
#include <wx/checkbox.h>
#include <wx/dialog.h>
///////////////////////////////////////////////////////////////////////////
@ -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();
};

View File

@ -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<std::unique_ptr<EDA_ITEM>>& list = dlg.GetImportedItems();
if( dlgResult != wxID_OK )
return 0;
@ -768,6 +768,10 @@ 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 );
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<BOARD_ITEM*>( 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<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() );
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<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 ) )
{
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<PCB_GROUP*>( item )->AddChildrenToCommit( commit );
commit.Add( item );
}
commit.Push( _( "Place a DXF_SVG drawing" ) );
break; // This is a one-shot command, not a tool