eeschema: Allow mult-part placement option

When placing a new component in the schematic, this allows the user to
iterate through all units in the selected component without re-opening
the choose part dialog.  It also allows the optional addition of
multiple copies of the same component to be placed in the schematic.

Fixes: lp:1806217
* https://bugs.launchpad.net/kicad/+bug/1806217
This commit is contained in:
Seth Hillbrand 2019-10-28 22:06:39 -07:00
parent 04bae776a7
commit 7b2d6ab40e
6 changed files with 111 additions and 6 deletions

View File

@ -42,10 +42,12 @@
#include <wx/clipbrd.h>
#include <kiface_i.h>
#define SYM_CHOOSER_HSASH wxT( "SymbolChooserHSashPosition" )
#define SYM_CHOOSER_VSASH wxT( "SymbolChooserVSashPosition" )
#define SYM_CHOOSER_WIDTH_KEY wxT( "SymbolChooserWidth" )
#define SYM_CHOOSER_HEIGHT_KEY wxT( "SymbolChooserHeight" )
#define SYM_CHOOSER_HSASH wxT( "SymbolChooserHSashPosition" )
#define SYM_CHOOSER_VSASH wxT( "SymbolChooserVSashPosition" )
#define SYM_CHOOSER_WIDTH_KEY wxT( "SymbolChooserWidth" )
#define SYM_CHOOSER_HEIGHT_KEY wxT( "SymbolChooserHeight" )
#define SYM_CHOOSER_KEEP_SYM_KEY wxT( "SymbolChooserKeepSymbol" )
#define SYM_CHOOSER_USE_UNITS_KEY wxT( "SymbolChooserUseUnits" )
std::mutex DIALOG_CHOOSE_COMPONENT::g_Mutex;
@ -206,6 +208,9 @@ DIALOG_CHOOSE_COMPONENT::~DIALOG_CHOOSE_COMPONENT()
m_config->Write( SYM_CHOOSER_WIDTH_KEY, GetSize().x );
m_config->Write( SYM_CHOOSER_HEIGHT_KEY, GetSize().y );
m_config->Write( SYM_CHOOSER_KEEP_SYM_KEY, m_keepSymbol->GetValue() );
m_config->Write( SYM_CHOOSER_USE_UNITS_KEY, m_useUnits->GetValue() );
m_config->Write( SYM_CHOOSER_HSASH, m_hsplitter->GetSashPosition() );
if( m_vsplitter )
@ -247,6 +252,27 @@ wxPanel* DIALOG_CHOOSE_COMPONENT::ConstructRightPanel( wxWindow* aParent )
sizer->Add( m_symbol_preview, 1, wxEXPAND | wxTOP | wxRIGHT, 5 );
}
m_keepSymbol = new wxCheckBox( panel, 1000, _("Multi-Symbol Placement"), wxDefaultPosition,
wxDefaultSize, wxALIGN_RIGHT );
m_keepSymbol->SetValue( m_config->ReadBool( SYM_CHOOSER_KEEP_SYM_KEY, false ) );
m_keepSymbol->SetToolTip( _( "Place multiple copies of the symbol." ) );
m_useUnits = new wxCheckBox( panel, 1000, _("Place all units"), wxDefaultPosition,
wxDefaultSize, wxALIGN_RIGHT );
m_useUnits->SetValue( m_config->ReadBool( SYM_CHOOSER_USE_UNITS_KEY, true ) );
m_useUnits->SetToolTip( _( "Sequentially place all units of the symbol." ) );
auto fgSizer = new wxFlexGridSizer( 0, 2, 0, 1 );
fgSizer->AddGrowableCol( 0 );
fgSizer->SetFlexibleDirection( wxBOTH );
fgSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
fgSizer->Add( 0, 0, 1, wxEXPAND );
fgSizer->Add( m_keepSymbol, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
fgSizer->Add( 0, 0, 1, wxEXPAND );
fgSizer->Add( m_useUnits, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
sizer->Add( fgSizer, 0, wxALL | wxEXPAND, 5 );
panel->SetSizer( sizer );
panel->Layout();
sizer->Fit( panel );

View File

@ -122,6 +122,25 @@ public:
*/
LIB_ID GetSelectedLibId( int* aUnit = nullptr ) const;
/**
* To be called after this dialog returns from ShowModal()
*
* In the case of multi-unit symbols, this preferences asks to iterate through
* all units of the symbol, one per click
* @return The value of the dialog preference checkbox
*/
bool GetUseAllUnits() const { return m_useUnits->GetValue(); }
/**
* To be called after this dialog returns from ShowModal()
*
* Keeps a new copy of the symbol on the mouse cursor, allowing the user to rapidly
* place multiple copies of the same symbol on their schematic
*
* @return The value of the keep symbol preference checkbox
*/
bool GetKeepSymbol() const { return m_keepSymbol->GetValue(); }
/**
* Get a list of fields edited by the user.
* @return vector of pairs; each.first = field ID, each.second = new value
@ -191,6 +210,8 @@ protected:
FOOTPRINT_SELECT_WIDGET* m_fp_sel_ctrl;
FOOTPRINT_PREVIEW_WIDGET* m_fp_preview;
wxCheckBox* m_keepSymbol;
wxCheckBox* m_useUnits;
LIB_TREE* m_tree;
wxHtmlWindow* m_details;

View File

@ -181,6 +181,9 @@ SCH_BASE_FRAME::COMPONENT_SELECTION SCH_BASE_FRAME::SelectCompFromLibTree(
// but no symbol selected
return COMPONENT_SELECTION();
SetUseAllUnits( dlg.GetUseAllUnits() );
SetRepeatComponent( dlg.GetKeepSymbol() );
if( sel.Unit == 0 )
sel.Unit = 1;

View File

@ -97,6 +97,8 @@ SCH_BASE_FRAME::SCH_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aWindo
m_repeatStep = wxPoint( DEFAULT_REPEAT_OFFSET_X, DEFAULT_REPEAT_OFFSET_Y );
m_repeatDeltaLabel = DEFAULT_REPEAT_LABEL_INC;
m_showPinElectricalTypeName = false;
m_repeatComponent = false;
m_useAllUnits = false;
}

View File

@ -93,6 +93,9 @@ protected:
bool m_showPinElectricalTypeName;
bool m_dragActionIsMove; // drag action defaults to move, otherwise it's drag
bool m_repeatComponent; // After placing one component, reload a sequential
bool m_useAllUnits; // After placing unit A, place unit B of the same
public:
SCH_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent,
FRAME_T aWindowType,
@ -147,6 +150,28 @@ public:
*/
void SetRepeatDeltaLabel( int aDelta ) { m_repeatDeltaLabel = aDelta; }
/**
* @return the current setting of placing copies of the same symbol for each click
*/
const bool GetRepeatComponent() { return m_repeatComponent; }
/**
* If true, keep placing new copies of the same symbol on each click
* @param aRepeat True to repeat the same symbol, False to only set one
*/
void SetRepeatComponent( bool aRepeat ) { m_repeatComponent = aRepeat; }
/**
* @return the current setting to use all units when placing a component
*/
const bool GetUseAllUnits() { return m_useAllUnits; }
/**
* Sets whether to utilize all units of a component when placing
* @param aUseAll True to iterate through Units A, B, ...
*/
void SetUseAllUnits( bool aUseAll ) { m_useAllUnits = aUseAll; }
/**
* Function GetZoomLevelIndicator

View File

@ -188,10 +188,38 @@ int SCH_DRAWING_TOOLS::PlaceComponent( const TOOL_EVENT& aEvent )
}
else
{
m_frame->AddItemToScreenAndUndoList( component );
component = nullptr;
SCH_COMPONENT* next_comp = nullptr;
m_view->ClearPreview();
m_frame->AddItemToScreenAndUndoList( component );
if( m_frame->GetUseAllUnits() || m_frame->GetRepeatComponent() )
{
int new_unit = component->GetUnit();
if( m_frame->GetUseAllUnits()
&& component->GetUnit() < component->GetUnitCount() )
new_unit++;
else
new_unit = 1;
// We are either stepping to the next unit or next component
if( m_frame->GetRepeatComponent() || new_unit > 1 )
{
next_comp = static_cast<SCH_COMPONENT*>( component->Duplicate() );
next_comp->SetFlags( IS_NEW | IS_MOVED );
next_comp->SetUnit( new_unit );
if( m_frame->GetAutoplaceFields() )
component->AutoplaceFields( /* aScreen */ NULL, /* aManual */ false );
m_frame->SaveCopyForRepeatItem( next_comp );
m_view->AddToPreview( next_comp->Clone() );
m_selectionTool->AddItemToSel( next_comp );
}
}
component = next_comp;
}
}
else if( evt->IsClick( BUT_RIGHT ) )