kicad-source/pcbnew/dialogs/panel_assign_component_classes.cpp
Seth Hillbrand 8b62eac886 Make sure that we are disconnected before dtor
The child class removes itself from the parent panel, which calls the
DTOR.  This automatically disconnects the events, so if we want to
explicitly do this, we need to do it before freeing the memory

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21307
2025-07-12 12:09:02 -07:00

788 lines
27 KiB
C++

/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <dialogs/panel_assign_component_classes.h>
#include <bitmaps.h>
#include <board.h>
#include <component_classes/component_class_assignment_rule.h>
#include <component_classes/component_class_manager.h>
#include <footprint.h>
#include <kiway.h>
#include <pcb_edit_frame.h>
#include <project/project_file.h>
#include <tool/selection_tool.h>
#include <tool/tool_manager.h>
#include <tools/pcb_selection_tool.h>
#include <widgets/paged_dialog.h>
#include <widgets/std_bitmap_button.h>
/**************************************************************************************************
*
* PANEL_ASSIGN_COMPONENT_CLASSES implementation
* This is the top-level panel for component class configuration
*
*************************************************************************************************/
PANEL_ASSIGN_COMPONENT_CLASSES::PANEL_ASSIGN_COMPONENT_CLASSES(
wxWindow* aParentWindow, PCB_EDIT_FRAME* aFrame,
std::shared_ptr<COMPONENT_CLASS_SETTINGS> aSettings, DIALOG_SHIM* aDlg ) :
PANEL_ASSIGN_COMPONENT_CLASSES_BASE( aParentWindow ), m_dlg( aDlg ), m_frame( aFrame ),
m_componentClassSettings( std::move( aSettings ) ),
m_assignmentsList( static_cast<wxBoxSizer*>( m_assignmentsScrollWindow->GetSizer() ) )
{
// Load footprint fields and sheet names
const BOARD* board = dynamic_cast<BOARD*>( m_frame->GetModel() );
std::set<wxString> fieldsSet;
std::set<wxString> sheetsSet;
for( const FOOTPRINT* fp : board->Footprints() )
{
wxString sheetName = fp->GetSheetname();
if( !sheetName.empty() )
{
sheetName.Replace( wxT( "\"" ), wxT( "" ) );
sheetName.Replace( wxT( "'" ), wxT( "" ) );
sheetsSet.insert( fp->GetSheetname() );
}
for( const PCB_FIELD* field : fp->GetFields() )
fieldsSet.insert( field->GetName() );
}
// Sort field names
std::vector<wxString> fieldNames( fieldsSet.begin(), fieldsSet.end() );
std::ranges::sort( fieldNames,
[]( const wxString& a, const wxString& b )
{
return a.Cmp( b ) < 0;
} );
m_fieldNames = std::move( fieldNames );
// Sort sheet names
std::vector<wxString> sheetNames( sheetsSet.begin(), sheetsSet.end() );
std::ranges::sort( sheetNames,
[]( const wxString& a, const wxString& b )
{
return a.Cmp( b ) < 0;
} );
m_sheetNames = std::move( sheetNames );
// Get references of currently selected items
std::set<wxString> refsSet;
for( const EDA_ITEM* item : m_frame->GetCurrentSelection() )
{
if( item->Type() != PCB_FOOTPRINT_T )
continue;
const FOOTPRINT* fp = static_cast<const FOOTPRINT*>( item );
wxString ref = fp->GetReferenceAsString();
refsSet.insert( ref );
}
std::vector<wxString> refs( refsSet.begin(), refsSet.end() );
std::ranges::sort( refs,
[]( const wxString& a, const wxString& b )
{
return a.Cmp( b ) < 0;
} );
m_selectionRefs = std::move( refs );
}
PANEL_ASSIGN_COMPONENT_CLASSES::~PANEL_ASSIGN_COMPONENT_CLASSES()
{
BOARD* board = dynamic_cast<BOARD*>( m_frame->GetModel() );
PCB_SELECTION_TOOL* selTool = m_frame->GetToolManager()->GetTool<PCB_SELECTION_TOOL>();
for( FOOTPRINT* fp : board->Footprints() )
selTool->UnbrightenItem( fp );
m_frame->GetCanvas()->Refresh();
}
bool PANEL_ASSIGN_COMPONENT_CLASSES::TransferDataToWindow()
{
// Load sheet-level settings
m_assignSheetClasses->SetValue( m_componentClassSettings->GetEnableSheetComponentClasses() );
// Load dynamic component class assignments
for( const COMPONENT_CLASS_ASSIGNMENT_DATA& assignmentData :
m_componentClassSettings->GetComponentClassAssignments() )
{
PANEL_COMPONENT_CLASS_ASSIGNMENT* assignment = addAssignment();
assignment->SetComponentClass( assignmentData.GetComponentClass() );
assignment->SetConditionsOperator( assignmentData.GetConditionsOperator() );
for( const auto& [conditionType, conditionData] : assignmentData.GetConditions() )
{
CONDITION_DATA* match = assignment->AddCondition( conditionType );
match->SetPrimaryField( conditionData.first );
match->SetSecondaryField( conditionData.second );
}
}
return true;
}
bool PANEL_ASSIGN_COMPONENT_CLASSES::TransferDataFromWindow()
{
if( !Validate() )
return false;
// Save sheet-level settings
m_componentClassSettings->SetEnableSheetComponentClasses( m_assignSheetClasses->GetValue() );
// Save dynamic component class assignments
m_componentClassSettings->ClearComponentClassAssignments();
for( const auto assignment : m_assignments )
{
COMPONENT_CLASS_ASSIGNMENT_DATA assignmentData = assignment->GenerateAssignmentData();
m_componentClassSettings->AddComponentClassAssignment( assignmentData );
}
return true;
}
bool PANEL_ASSIGN_COMPONENT_CLASSES::Validate()
{
PCB_EDIT_FRAME* frame = GetFrame();
BOARD* board = dynamic_cast<BOARD*>( frame->GetModel() );
frame->GetCanvas()->Refresh();
for( PANEL_COMPONENT_CLASS_ASSIGNMENT* assignment : m_assignments )
{
const COMPONENT_CLASS_ASSIGNMENT_DATA assignmentData = assignment->GenerateAssignmentData();
const std::shared_ptr<COMPONENT_CLASS_ASSIGNMENT_RULE> rule =
board->GetComponentClassManager().CompileAssignmentRule( assignmentData );
if( !rule )
{
const wxString msg = wxString::Format(
_( "Error with conditions for component class assignment %s" ),
assignment->GetComponentClass() );
PAGED_DIALOG::GetDialog( this )->SetError( msg, this, assignment );
scrollToAssignment( assignment );
assignment->SetFocus();
return false;
}
}
return true;
}
void PANEL_ASSIGN_COMPONENT_CLASSES::OnAddAssignmentClick( wxCommandEvent& event )
{
PANEL_COMPONENT_CLASS_ASSIGNMENT* assignment = addAssignment();
scrollToAssignment( assignment );
}
PANEL_COMPONENT_CLASS_ASSIGNMENT* PANEL_ASSIGN_COMPONENT_CLASSES::addAssignment()
{
PANEL_COMPONENT_CLASS_ASSIGNMENT* assignmentPanel =
new PANEL_COMPONENT_CLASS_ASSIGNMENT( m_assignmentsScrollWindow, this, m_dlg );
#if __OSX__
m_assignmentsList->Add( assignmentPanel, 0, wxEXPAND, 5 );
#else
m_assignmentsList->Add( assignmentPanel, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5 );
#endif
Layout();
m_assignments.push_back( assignmentPanel );
return assignmentPanel;
}
void PANEL_ASSIGN_COMPONENT_CLASSES::scrollToAssignment(
const PANEL_COMPONENT_CLASS_ASSIGNMENT* aAssignment ) const
{
const wxPoint viewStart = m_assignmentsScrollWindow->GetViewStart();
const wxPoint panelPosition = aAssignment->GetPosition();
const wxSize panelSize = aAssignment->GetClientSize();
m_assignmentsScrollWindow->Scroll( viewStart.x, panelPosition.y + panelSize.y );
}
void PANEL_ASSIGN_COMPONENT_CLASSES::RemoveAssignment( PANEL_COMPONENT_CLASS_ASSIGNMENT* aPanel )
{
m_assignments.erase( std::ranges::find( m_assignments, aPanel ) );
m_assignmentsList->Detach( aPanel );
aPanel->Destroy();
Layout();
}
void PANEL_ASSIGN_COMPONENT_CLASSES::ImportSettingsFrom(
const std::shared_ptr<COMPONENT_CLASS_SETTINGS>& aOtherSettings )
{
std::shared_ptr<COMPONENT_CLASS_SETTINGS> savedSettings = m_componentClassSettings;
m_componentClassSettings = aOtherSettings;
TransferDataToWindow();
m_componentClassSettings = std::move( savedSettings );
}
/**************************************************************************************************
*
* CONDITION_DATA implementation
* Provides a common interface for all condition panel types
*
*************************************************************************************************/
wxString CONDITION_DATA::GetPrimaryField() const
{
wxString data = m_primaryCtrl->GetValue();
data.Trim( true );
data.Trim( false );
if( m_conditionType != COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::CUSTOM )
{
data.Replace( wxT( "\"" ), wxT( "" ) );
data.Replace( wxT( "'" ), wxT( "" ) );
}
return data;
}
void CONDITION_DATA::SetPrimaryField( const wxString& aVal )
{
m_primaryCtrl->SetValue( aVal );
}
wxString CONDITION_DATA::GetSecondaryField() const
{
if( !m_secondaryCtrl )
return wxEmptyString;
wxString data = m_secondaryCtrl->GetValue();
data.Trim( true );
data.Trim( false );
if( m_conditionType != COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::CUSTOM )
{
data.Replace( wxT( "\"" ), wxT( "" ) );
data.Replace( wxT( "'" ), wxT( "" ) );
}
return data;
}
void CONDITION_DATA::SetSecondaryField( const wxString& aVal )
{
if( m_secondaryCtrl )
m_secondaryCtrl->SetValue( aVal );
};
/**************************************************************************************************
*
* PANEL_COMPONENT_CLASS_ASSIGNMENT implementation
* This is the dynamically-added panel for each component class assignment rule set
*
*************************************************************************************************/
PANEL_COMPONENT_CLASS_ASSIGNMENT::PANEL_COMPONENT_CLASS_ASSIGNMENT(
wxWindow* aParent, PANEL_ASSIGN_COMPONENT_CLASSES* aPanelParent, DIALOG_SHIM* aDlg ) :
PANEL_COMPONENT_CLASS_ASSIGNMENT_BASE( aParent ), m_parentPanel( aPanelParent ),
m_matchesList( static_cast<wxStaticBoxSizer*>( GetSizer() ) ), m_dlg( aDlg )
{
m_buttonAddCondition->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
m_buttonDeleteAssignment->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
m_buttonHighlightItems->SetBitmap( KiBitmapBundle( BITMAPS::net_highlight ) );
Connect( wxEVT_MENU, wxCommandEventHandler( PANEL_COMPONENT_CLASS_ASSIGNMENT::onMenu ), nullptr,
this );
}
PANEL_COMPONENT_CLASS_ASSIGNMENT::~PANEL_COMPONENT_CLASS_ASSIGNMENT()
{
Disconnect( wxEVT_MENU, wxCommandEventHandler( PANEL_COMPONENT_CLASS_ASSIGNMENT::onMenu ),
nullptr, this );
}
COMPONENT_CLASS_ASSIGNMENT_DATA PANEL_COMPONENT_CLASS_ASSIGNMENT::GenerateAssignmentData() const
{
COMPONENT_CLASS_ASSIGNMENT_DATA assignmentData;
assignmentData.SetComponentClass( GetComponentClass() );
assignmentData.SetConditionsOperation( GetConditionsOperator() );
for( const auto& condition : GetConditions() )
{
assignmentData.SetCondition( condition->GetConditionType(), condition->GetPrimaryField(),
condition->GetSecondaryField() );
}
return assignmentData;
}
void PANEL_COMPONENT_CLASS_ASSIGNMENT::OnAddConditionClick( wxCommandEvent& event )
{
auto hasCondition = [this]( const COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE aCondition )
{
return m_conditionTypes.contains( aCondition );
};
wxMenu menu;
menu.Append( ID_REFERENCE, _( "Reference..." ) );
menu.Append( ID_FOOTPRINT, _( "Footprint..." ) );
menu.Append( ID_SIDE, _( "Side..." ) );
menu.Append( ID_ROTATION, _( "Rotation..." ) );
menu.Append( ID_FOOTPRINT_FIELD, _( "Footprint Field..." ) );
menu.Append( ID_SHEET_NAME, _( "Sheet Name..." ) );
menu.Append( ID_CUSTOM, _( "Custom..." ) );
menu.Enable( ID_REFERENCE,
!hasCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::REFERENCE ) );
menu.Enable( ID_FOOTPRINT,
!hasCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::FOOTPRINT ) );
menu.Enable( ID_SIDE, !hasCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::SIDE ) );
menu.Enable( ID_ROTATION,
!hasCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::ROTATION ) );
menu.Enable(
ID_FOOTPRINT_FIELD,
!hasCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::FOOTPRINT_FIELD ) );
menu.Enable( ID_CUSTOM,
!hasCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::CUSTOM ) );
menu.Enable( ID_SHEET_NAME,
!hasCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::SHEET_NAME ) );
PopupMenu( &menu );
}
void PANEL_COMPONENT_CLASS_ASSIGNMENT::OnDeleteAssignmentClick( wxCommandEvent& event )
{
m_parentPanel->RemoveAssignment( this );
}
void PANEL_COMPONENT_CLASS_ASSIGNMENT::SetComponentClass( const wxString& aComponentClass ) const
{
m_componentClass->SetValue( aComponentClass );
}
const wxString PANEL_COMPONENT_CLASS_ASSIGNMENT::GetComponentClass() const
{
return m_componentClass->GetValue();
}
void PANEL_COMPONENT_CLASS_ASSIGNMENT::onMenu( wxCommandEvent& aEvent )
{
switch( aEvent.GetId() )
{
case ID_REFERENCE:
AddCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::REFERENCE );
break;
case ID_FOOTPRINT:
AddCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::FOOTPRINT );
break;
case ID_SIDE: AddCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::SIDE ); break;
case ID_ROTATION:
AddCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::ROTATION );
break;
case ID_FOOTPRINT_FIELD:
AddCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::FOOTPRINT_FIELD );
break;
case ID_CUSTOM: AddCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::CUSTOM ); break;
case ID_SHEET_NAME:
AddCondition( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::SHEET_NAME );
break;
default: wxFAIL_MSG( wxT( "Unknown ID in context menu event" ) );
}
}
CONDITION_DATA* PANEL_COMPONENT_CLASS_ASSIGNMENT::AddCondition(
const COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE aCondition )
{
wxASSERT_MSG( !m_conditionTypes.contains( aCondition ), "Condition type already exists" );
wxPanel* panelToAdd = nullptr;
switch( aCondition )
{
case COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::REFERENCE:
{
PANEL_COMPONENT_CLASS_CONDITION_REFERENCE* refsPanel =
new PANEL_COMPONENT_CLASS_CONDITION_REFERENCE( this );
refsPanel->SetSelectionRefs( m_parentPanel->GetSelectionRefs() );
panelToAdd = refsPanel;
m_conditionTypes.insert( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::REFERENCE );
break;
}
case COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::FOOTPRINT:
{
panelToAdd = new PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT( this, m_dlg );
m_conditionTypes.insert( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::FOOTPRINT );
break;
}
case COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::SIDE:
{
panelToAdd = new PANEL_COMPONENT_CLASS_CONDITION_SIDE( this );
m_conditionTypes.insert( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::SIDE );
break;
}
case COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::ROTATION:
{
panelToAdd = new PANEL_COMPONENT_CLASS_CONDITION_ROTATION( this );
m_conditionTypes.insert( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::ROTATION );
break;
}
case COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::FOOTPRINT_FIELD:
{
PANEL_COMPONENT_CLASS_CONDITION_FIELD* fieldPanel =
new PANEL_COMPONENT_CLASS_CONDITION_FIELD( this );
fieldPanel->SetFieldsList( m_parentPanel->GetFieldNames() );
panelToAdd = fieldPanel;
m_conditionTypes.insert( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::FOOTPRINT_FIELD );
break;
}
case COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::CUSTOM:
{
panelToAdd = new PANEL_COMPONENT_CLASS_CONDITION_CUSTOM( this );
m_conditionTypes.insert( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::CUSTOM );
break;
}
case COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::SHEET_NAME:
{
PANEL_COMPONENT_CLASS_CONDITION_SHEET* sheetPanel =
new PANEL_COMPONENT_CLASS_CONDITION_SHEET( this );
sheetPanel->SetSheetsList( m_parentPanel->GetSheetNames() );
panelToAdd = sheetPanel;
m_conditionTypes.insert( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::SHEET_NAME );
break;
}
}
const size_t numItems = m_matchesList->GetItemCount();
m_matchesList->Insert( numItems - 1, panelToAdd, 0, wxEXPAND | wxTOP, 5 );
Layout();
GetParent()->Layout();
m_parentPanel->Layout();
CONDITION_DATA* conditionIface = dynamic_cast<CONDITION_DATA*>( panelToAdd );
m_matches.push_back( conditionIface );
return conditionIface;
}
void PANEL_COMPONENT_CLASS_ASSIGNMENT::RemoveCondition( wxPanel* aMatch )
{
if( CONDITION_DATA* matchData = dynamic_cast<CONDITION_DATA*>( aMatch ) )
{
m_conditionTypes.erase( matchData->GetConditionType() );
m_matches.erase( std::ranges::find( m_matches, matchData ) );
}
m_matchesList->Detach( aMatch );
aMatch->Destroy();
Layout();
m_parentPanel->Layout();
}
void PANEL_COMPONENT_CLASS_ASSIGNMENT::SetConditionsOperator(
const COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITIONS_OPERATOR aCondition ) const
{
if( aCondition == COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITIONS_OPERATOR::ALL )
{
m_radioAll->SetValue( true );
m_radioAny->SetValue( false );
}
else
{
m_radioAll->SetValue( false );
m_radioAny->SetValue( true );
}
}
COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITIONS_OPERATOR
PANEL_COMPONENT_CLASS_ASSIGNMENT::GetConditionsOperator() const
{
if( m_radioAll->GetValue() == true )
return COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITIONS_OPERATOR::ALL;
return COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITIONS_OPERATOR::ANY;
}
void PANEL_COMPONENT_CLASS_ASSIGNMENT::OnHighlightItemsClick( wxCommandEvent& event )
{
PCB_EDIT_FRAME* frame = m_parentPanel->GetFrame();
BOARD* board = dynamic_cast<BOARD*>( frame->GetModel() );
PCB_SELECTION_TOOL* selTool = frame->GetToolManager()->GetTool<PCB_SELECTION_TOOL>();
const COMPONENT_CLASS_ASSIGNMENT_DATA assignment = GenerateAssignmentData();
const std::shared_ptr<COMPONENT_CLASS_ASSIGNMENT_RULE> rule =
board->GetComponentClassManager().CompileAssignmentRule( assignment );
if( !rule )
return;
for( FOOTPRINT* fp : board->Footprints() )
{
if( rule->Matches( fp ) )
selTool->BrightenItem( fp );
else
selTool->UnbrightenItem( fp );
}
frame->GetCanvas()->Refresh();
}
/**************************************************************************************************
*
* PANEL_COMPONENT_CLASS_CONDITION_* implementations
* These are the dynamically-added panels for each condition / match type
*
*************************************************************************************************/
PANEL_COMPONENT_CLASS_CONDITION_REFERENCE::PANEL_COMPONENT_CLASS_CONDITION_REFERENCE(
wxWindow* aParent ) :
PANEL_COMPONENT_CLASS_CONDITION_REFERENCE_BASE( aParent ),
CONDITION_DATA( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::REFERENCE, m_refs ),
m_panelParent( static_cast<PANEL_COMPONENT_CLASS_ASSIGNMENT*>( aParent ) )
{
m_title->SetMinSize( { GetTextExtent( _( "Footprint Field:" ) ).x, -1 } );
m_buttonImportRefs->SetBitmap( KiBitmapBundle( BITMAPS::config ) );
m_buttonDeleteMatch->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
Connect( wxEVT_MENU, wxCommandEventHandler( PANEL_COMPONENT_CLASS_CONDITION_REFERENCE::onMenu ),
nullptr, this );
}
void PANEL_COMPONENT_CLASS_CONDITION_REFERENCE::OnDeleteConditionClick( wxCommandEvent& event )
{
Disconnect( wxEVT_MENU,
wxCommandEventHandler( PANEL_COMPONENT_CLASS_CONDITION_REFERENCE::onMenu ), nullptr,
this );
m_panelParent->RemoveCondition( this );
}
void PANEL_COMPONENT_CLASS_CONDITION_REFERENCE::OnImportRefsClick( wxCommandEvent& event )
{
wxMenu menu;
menu.Append( ID_IMPORT_REFS, _( "Import references from selection" ) );
menu.Enable( ID_IMPORT_REFS, !m_selectionRefs.empty() );
PopupMenu( &menu );
}
void PANEL_COMPONENT_CLASS_CONDITION_REFERENCE::onMenu( wxCommandEvent& aEvent )
{
if( aEvent.GetId() != ID_IMPORT_REFS )
wxFAIL_MSG( wxT( "Unknown ID in context menu event" ) );
if( m_selectionRefs.empty() )
return;
wxString refs = m_selectionRefs[0];
for( size_t i = 1; i < m_selectionRefs.size(); i++ )
{
refs += wxT( "," );
refs += m_selectionRefs[i];
}
m_refs->SetValue( refs );
}
PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT::PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT(
wxWindow* aParent, DIALOG_SHIM* aDlg ) :
PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT_BASE( aParent ),
CONDITION_DATA( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::FOOTPRINT, m_footprint ),
m_panelParent( static_cast<PANEL_COMPONENT_CLASS_ASSIGNMENT*>( aParent ) ), m_dlg( aDlg )
{
m_title->SetMinSize( { GetTextExtent( _( "Footprint Field:" ) ).x, -1 } );
m_buttonDeleteMatch->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
m_buttonShowLibrary->SetBitmap( KiBitmapBundle( BITMAPS::small_library ) );
}
void PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT::OnDeleteConditionClick( wxCommandEvent& event )
{
m_panelParent->RemoveCondition( this );
}
void PANEL_COMPONENT_CLASS_CONDITION_FOOTPRINT::OnShowLibraryClick( wxCommandEvent& event )
{
wxString fpId = m_footprint->GetValue();
if( KIWAY_PLAYER* frame = m_dlg->Kiway().Player( FRAME_FOOTPRINT_CHOOSER, true, m_dlg ) )
{
if( frame->ShowModal( &fpId, this ) )
{
m_footprint->SetValue( fpId );
}
frame->Destroy();
}
}
PANEL_COMPONENT_CLASS_CONDITION_SIDE::PANEL_COMPONENT_CLASS_CONDITION_SIDE( wxWindow* aParent ) :
PANEL_COMPONENT_CLASS_CONDITION_SIDE_BASE( aParent ),
CONDITION_DATA( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::SIDE, m_side ),
m_panelParent( static_cast<PANEL_COMPONENT_CLASS_ASSIGNMENT*>( aParent ) )
{
m_title->SetMinSize( { GetTextExtent( _( "Footprint Field:" ) ).x, -1 } );
m_buttonDeleteMatch->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
m_side->Append( wxT( "Any" ) );
m_side->Append( wxT( "Front" ) );
m_side->Append( wxT( "Back" ) );
m_side->SetValue( wxT( "Any" ) );
}
void PANEL_COMPONENT_CLASS_CONDITION_SIDE::OnDeleteConditionClick( wxCommandEvent& event )
{
m_panelParent->RemoveCondition( this );
}
PANEL_COMPONENT_CLASS_CONDITION_ROTATION::PANEL_COMPONENT_CLASS_CONDITION_ROTATION(
wxWindow* aParent ) :
PANEL_COMPONENT_CLASS_CONDITION_ROTATION_BASE( aParent ),
CONDITION_DATA( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::ROTATION, m_rotation ),
m_panelParent( static_cast<PANEL_COMPONENT_CLASS_ASSIGNMENT*>( aParent ) )
{
m_title->SetMinSize( { GetTextExtent( _( "Footprint Field:" ) ).x, -1 } );
m_rotUnit->SetLabel( wxT( "°" ) );
m_buttonDeleteMatch->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
m_rotation->Append( wxT( "Any" ) );
m_rotation->Append( wxT( "0" ) );
m_rotation->Append( wxT( "90" ) );
m_rotation->Append( wxT( "180" ) );
m_rotation->Append( wxT( "-90" ) );
m_rotation->SetValue( wxT( "Any" ) );
}
void PANEL_COMPONENT_CLASS_CONDITION_ROTATION::OnDeleteConditionClick( wxCommandEvent& event )
{
m_panelParent->RemoveCondition( this );
}
PANEL_COMPONENT_CLASS_CONDITION_FIELD::PANEL_COMPONENT_CLASS_CONDITION_FIELD( wxWindow* aParent ) :
PANEL_COMPONENT_CLASS_CONDITION_FIELD_BASE( aParent ),
CONDITION_DATA( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::FOOTPRINT_FIELD,
m_fieldName, m_fieldValue ),
m_panelParent( static_cast<PANEL_COMPONENT_CLASS_ASSIGNMENT*>( aParent ) )
{
m_title->SetMinSize( { GetTextExtent( _( "Footprint Field:" ) ).x, -1 } );
m_buttonDeleteMatch->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
}
void PANEL_COMPONENT_CLASS_CONDITION_FIELD::OnDeleteConditionClick( wxCommandEvent& event )
{
m_panelParent->RemoveCondition( this );
}
void PANEL_COMPONENT_CLASS_CONDITION_FIELD::SetFieldsList( const std::vector<wxString>& aFields )
{
m_fieldName->Append( aFields );
}
PANEL_COMPONENT_CLASS_CONDITION_CUSTOM::PANEL_COMPONENT_CLASS_CONDITION_CUSTOM(
wxWindow* aParent ) :
PANEL_COMPONENT_CLASS_CONDITION_CUSTOM_BASE( aParent ),
CONDITION_DATA( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::CUSTOM,
m_customCondition ),
m_panelParent( static_cast<PANEL_COMPONENT_CLASS_ASSIGNMENT*>( aParent ) )
{
m_title->SetMinSize( { GetTextExtent( _( "Footprint Field:" ) ).x, -1 } );
m_buttonDeleteMatch->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
}
void PANEL_COMPONENT_CLASS_CONDITION_CUSTOM::OnDeleteConditionClick( wxCommandEvent& event )
{
m_panelParent->RemoveCondition( this );
}
PANEL_COMPONENT_CLASS_CONDITION_SHEET::PANEL_COMPONENT_CLASS_CONDITION_SHEET( wxWindow* aParent ) :
PANEL_COMPONENT_CLASS_CONDITION_SHEET_BASE( aParent ),
CONDITION_DATA( COMPONENT_CLASS_ASSIGNMENT_DATA::CONDITION_TYPE::SHEET_NAME, m_sheetName ),
m_panelParent( static_cast<PANEL_COMPONENT_CLASS_ASSIGNMENT*>( aParent ) )
{
m_title->SetMinSize( { GetTextExtent( _( "Footprint Field:" ) ).x, -1 } );
m_buttonDeleteMatch->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
}
void PANEL_COMPONENT_CLASS_CONDITION_SHEET::OnDeleteConditionClick( wxCommandEvent& event )
{
m_panelParent->RemoveCondition( this );
}
void PANEL_COMPONENT_CLASS_CONDITION_SHEET::SetSheetsList( const std::vector<wxString>& aSheets )
{
m_sheetName->Append( aSheets );
}