Push most of DIALOG_CHOOSE_SYMBOL down into PANEL_SYMBOL_CHOOSER.

Includes a dialog wrapper (DIALOG_SYMBOL_CHOOSER) and a frame
wrapper (SYMBOL_CHOOSER_FRAME).
This commit is contained in:
Jeff Young 2023-09-28 14:09:45 +01:00
parent 23033451b1
commit 974da4ea7c
36 changed files with 929 additions and 756 deletions

View File

@ -666,8 +666,7 @@ void DIALOG_PAGES_SETTINGS::UpdateDrawingSheetExample()
if( m_parent->IsType( FRAME_SCH ) if( m_parent->IsType( FRAME_SCH )
|| m_parent->IsType( FRAME_SCH_SYMBOL_EDITOR ) || m_parent->IsType( FRAME_SCH_SYMBOL_EDITOR )
|| m_parent->IsType( FRAME_SCH_VIEWER ) || m_parent->IsType( FRAME_SCH_VIEWER ) )
|| m_parent->IsType( FRAME_SCH_VIEWER_MODAL ) )
{ {
COLOR4D color = renderSettings.GetLayerColor( LAYER_SCHEMATIC_DRAWINGSHEET ); COLOR4D color = renderSettings.GetLayerColor( LAYER_SCHEMATIC_DRAWINGSHEET );
renderSettings.SetLayerColor( LAYER_DRAWINGSHEET, color ); renderSettings.SetLayerColor( LAYER_DRAWINGSHEET, color );

View File

@ -60,7 +60,6 @@ PANEL_GRID_SETTINGS::PANEL_GRID_SETTINGS( wxWindow* aParent, UNITS_PROVIDER* aUn
if( m_frameType != FRAME_SCH if( m_frameType != FRAME_SCH
&& m_frameType != FRAME_SCH_SYMBOL_EDITOR && m_frameType != FRAME_SCH_SYMBOL_EDITOR
&& m_frameType != FRAME_SCH_VIEWER && m_frameType != FRAME_SCH_VIEWER
&& m_frameType != FRAME_SCH_VIEWER_MODAL
&& m_frameType != FRAME_SIMULATOR ) && m_frameType != FRAME_SIMULATOR )
{ {
m_checkGridOverrideConnected->Show( false ); m_checkGridOverrideConnected->Show( false );

View File

@ -374,7 +374,7 @@ KIWAY::FACE_T KIWAY::KifaceType( FRAME_T aFrameType )
case FRAME_SCH: case FRAME_SCH:
case FRAME_SCH_SYMBOL_EDITOR: case FRAME_SCH_SYMBOL_EDITOR:
case FRAME_SCH_VIEWER: case FRAME_SCH_VIEWER:
case FRAME_SCH_VIEWER_MODAL: case FRAME_SYMBOL_CHOOSER:
case FRAME_SIMULATOR: case FRAME_SIMULATOR:
return FACE_SCH; return FACE_SCH;

View File

@ -355,8 +355,7 @@ int COMMON_TOOLS::doZoomFit( ZOOM_FIT_TYPE_T aFitType )
// Leave a bigger margin for library editors & viewers // Leave a bigger margin for library editors & viewers
if( frame->IsType( FRAME_FOOTPRINT_VIEWER ) if( frame->IsType( FRAME_FOOTPRINT_VIEWER )
|| frame->IsType( FRAME_SCH_VIEWER ) || frame->IsType( FRAME_SCH_VIEWER ) )
|| frame->IsType( FRAME_SCH_VIEWER_MODAL ) )
{ {
margin_scale_factor = 1.30; margin_scale_factor = 1.30;
} }

View File

@ -214,7 +214,7 @@ protected:
rawValue = m_preselect; rawValue = m_preselect;
wxString symbolId = escapeLibId( rawValue ); wxString symbolId = escapeLibId( rawValue );
KIWAY_PLAYER* frame = m_dlg->Kiway().Player( FRAME_SCH_VIEWER_MODAL, true, m_dlg ); KIWAY_PLAYER* frame = m_dlg->Kiway().Player( FRAME_SYMBOL_CHOOSER, true, m_dlg );
if( frame->ShowModal( &symbolId, m_dlg ) ) if( frame->ShowModal( &symbolId, m_dlg ) )
SetValue( UnescapeString( symbolId ) ); SetValue( UnescapeString( symbolId ) );

View File

@ -149,9 +149,6 @@ LIB_TREE::LIB_TREE( wxWindow* aParent, const wxString& aRecentSearchesKey, LIB_T
m_tree_ctrl = new WX_DATAVIEWCTRL( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, dvFlags ); m_tree_ctrl = new WX_DATAVIEWCTRL( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, dvFlags );
m_adapter->AttachTo( m_tree_ctrl ); m_adapter->AttachTo( m_tree_ctrl );
if( aFlags & DETAILS )
sizer->AddSpacer( 5 );
sizer->Add( m_tree_ctrl, 5, wxRIGHT | wxBOTTOM | wxEXPAND, 1 ); sizer->Add( m_tree_ctrl, 5, wxRIGHT | wxBOTTOM | wxEXPAND, 1 );
// Description panel // Description panel
@ -162,8 +159,7 @@ LIB_TREE::LIB_TREE( wxWindow* aParent, const wxString& aRecentSearchesKey, LIB_T
wxPoint html_size = ConvertDialogToPixels( wxPoint( 80, 80 ) ); wxPoint html_size = ConvertDialogToPixels( wxPoint( 80, 80 ) );
m_details_ctrl = new HTML_WINDOW( this, wxID_ANY, wxDefaultPosition, m_details_ctrl = new HTML_WINDOW( this, wxID_ANY, wxDefaultPosition,
wxSize( html_size.x, html_size.y ), wxSize( html_size.x, html_size.y ) );
wxHW_SCROLLBAR_AUTO );
sizer->Add( m_details_ctrl, 2, wxTOP | wxEXPAND, 5 ); sizer->Add( m_details_ctrl, 2, wxTOP | wxEXPAND, 5 );
} }

View File

@ -77,7 +77,6 @@ set( EESCHEMA_DLGS
dialogs/dialog_bom_base.cpp dialogs/dialog_bom_base.cpp
dialogs/dialog_change_symbols.cpp dialogs/dialog_change_symbols.cpp
dialogs/dialog_change_symbols_base.cpp dialogs/dialog_change_symbols_base.cpp
dialogs/dialog_choose_symbol.cpp
dialogs/dialog_database_lib_settings_base.cpp dialogs/dialog_database_lib_settings_base.cpp
dialogs/dialog_database_lib_settings.cpp dialogs/dialog_database_lib_settings.cpp
dialogs/dialog_edit_symbols_libid.cpp dialogs/dialog_edit_symbols_libid.cpp
@ -135,6 +134,7 @@ set( EESCHEMA_DLGS
dialogs/dialog_sheet_pin_properties_base.cpp dialogs/dialog_sheet_pin_properties_base.cpp
dialogs/dialog_sheet_properties.cpp dialogs/dialog_sheet_properties.cpp
dialogs/dialog_sheet_properties_base.cpp dialogs/dialog_sheet_properties_base.cpp
dialogs/dialog_symbol_chooser.cpp
dialogs/dialog_symbol_fields_table.cpp dialogs/dialog_symbol_fields_table.cpp
dialogs/dialog_symbol_fields_table_base.cpp dialogs/dialog_symbol_fields_table_base.cpp
dialogs/dialog_symbol_properties.cpp dialogs/dialog_symbol_properties.cpp
@ -256,6 +256,7 @@ set( EESCHEMA_SIM_SRCS
set( EESCHEMA_WIDGETS set( EESCHEMA_WIDGETS
widgets/hierarchy_pane.cpp widgets/hierarchy_pane.cpp
widgets/panel_symbol_chooser.cpp
widgets/pin_shape_combobox.cpp widgets/pin_shape_combobox.cpp
widgets/pin_type_combobox.cpp widgets/pin_type_combobox.cpp
widgets/symbol_diff_widget.cpp widgets/symbol_diff_widget.cpp
@ -368,6 +369,7 @@ set( EESCHEMA_SRCS
sheet.cpp sheet.cpp
symbol_async_loader.cpp symbol_async_loader.cpp
symbol_checker.cpp symbol_checker.cpp
symbol_chooser_frame.cpp
symbol_lib_table.cpp symbol_lib_table.cpp
symbol_library.cpp symbol_library.cpp
symbol_library_manager.cpp symbol_library_manager.cpp

View File

@ -244,7 +244,7 @@ void DIALOG_CHANGE_SYMBOLS::launchMatchIdSymbolBrowser( wxCommandEvent& aEvent )
{ {
wxString newName = getLibIdValue( m_specifiedId ); wxString newName = getLibIdValue( m_specifiedId );
KIWAY_PLAYER* frame = Kiway().Player( FRAME_SCH_VIEWER_MODAL, true, this ); KIWAY_PLAYER* frame = Kiway().Player( FRAME_SYMBOL_CHOOSER, true, this );
if( frame->ShowModal( &newName, this ) ) if( frame->ShowModal( &newName, this ) )
{ {
@ -260,7 +260,7 @@ void DIALOG_CHANGE_SYMBOLS::launchNewIdSymbolBrowser( wxCommandEvent& aEvent )
{ {
wxString newName = getLibIdValue( m_newId ); wxString newName = getLibIdValue( m_newId );
KIWAY_PLAYER* frame = Kiway().Player( FRAME_SCH_VIEWER_MODAL, true, this ); KIWAY_PLAYER* frame = Kiway().Player( FRAME_SYMBOL_CHOOSER, true, this );
if( frame->ShowModal( &newName, this ) ) if( frame->ShowModal( &newName, this ) )
{ {

View File

@ -1,233 +0,0 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2014 Henner Zeller <h.zeller@acm.org>
* Copyright (C) 2014-2022 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
*/
#ifndef DIALOG_CHOOSE_SYMBOL_H
#define DIALOG_CHOOSE_SYMBOL_H
#include "dialog_shim.h"
#include <symbol_tree_model_adapter.h>
#include <footprint_info.h>
#include <widgets/html_window.h>
class wxCheckBox;
class wxStaticBitmap;
class wxTextCtrl;
class wxStdDialogButtonSizer;
class wxDataViewCtrl;
class wxHtmlLinkEvent;
class wxPanel;
class wxChoice;
class wxButton;
class wxTimer;
class wxSplitterWindow;
class LIB_TREE;
class SYMBOL_PREVIEW_WIDGET;
class FOOTPRINT_PREVIEW_WIDGET;
class FOOTPRINT_SELECT_WIDGET;
class LIB_ALIAS;
class SCH_BASE_FRAME;
class SCH_DRAW_PANEL;
/**
* Dialog class to select a symbol from the libraries. This is the master View class in a
* Model-View-Adapter (mediated MVC) architecture. The other pieces are in:
*
* - Adapter: SYM_TREE_MODEL_ADAPTER in common/cmp_tree_model_adapter.h
* - Model: SYM_TREE_NODE and descendants in common/cmp_tree_model.h
*
* Because everything is tied together in the adapter class, see that file
* for thorough documentation. A simple example usage follows:
*
* // Create the adapter class
* auto adapter( SYMBOL_TREE_MODEL_ADAPTER::Create( PROJECT_SCH::SchSymbolLibTable( &Prj() ) );
*
* // Perform any configuration of adapter properties here
* adapter->SetPreselectNode( "LIB_NICKNAME", "SYMBO_NAME", 2 );
*
* // Initialize model from #SYMBOL_LIB_TABLE
* libNicknames = libs->GetLogicalLibs();
*
* for( auto nickname : libNicknames )
* adapter->AddLibrary( nickname );
*
* // Create and display dialog
* DIALOG_CHOOSE_SYMBOL dlg( this, title, adapter, 1 );
* bool selected = ( dlg.ShowModal() != wxID_CANCEL );
*
* // Receive part
* if( selected )
* {
* int unit;
* #LIB_ID id = dlg.GetSelectedAlias( &unit );
* do_something( id, unit );
* }
*
*/
class DIALOG_CHOOSE_SYMBOL : public DIALOG_SHIM
{
public:
/**
* Create dialog to choose symbol.
*
* @param aParent a SCH_BASE_FRAME parent window.
* @param aTitle Dialog title.
* @param aAdapter SYMBOL_TREE_MODEL_ADAPTER::PTR. See SYM_TREE_MODEL_ADAPTER
* for documentation.
* @param aDeMorganConvert preferred deMorgan conversion.
* (TODO: should happen in dialog)
* @param aAllowFieldEdits if false, all functions that allow the user to edit fields
* (currently just footprint selection) will not be available.
* @param aShowFootprints if false, all footprint preview and selection features are
* disabled. This forces aAllowFieldEdits false too.
* @param aAllowBrowser show a Select with Browser button.
*/
DIALOG_CHOOSE_SYMBOL( SCH_BASE_FRAME* aParent, const wxString& aTitle,
wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER>& aAdapter,
int aDeMorganConvert, bool aAllowFieldEdits, bool aShowFootprints,
bool aAllowBrowser );
~DIALOG_CHOOSE_SYMBOL();
/**
* To be called after this dialog returns from ShowModal().
*
* For multi-unit symbols, if the user selects the symbol itself rather than picking
* an individual unit, 0 will be returned in aUnit.
* Beware that this is an invalid unit number - this should be replaced with whatever
* default is desired (usually 1).
*
* @param aUnit if not NULL, the selected unit is filled in here.
* @return the #LIB_ID of the symbol that has been selected.
*/
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;
/**
* 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;
/**
* Get a list of fields edited by the user.
*
* @return vector of pairs; each.first = field ID, each.second = new value.
*/
std::vector<std::pair<int, wxString>> GetFields() const
{
return m_field_edits;
}
/**
* @return true if the user requested the symbol browser.
*/
bool IsExternalBrowserSelected() const
{
return m_external_browser_requested;
}
protected:
static constexpr int DblClickDelay = 100; // milliseconds
wxPanel* ConstructRightPanel( wxWindow* aParent );
void OnInitDialog( wxInitDialogEvent& aEvent );
void OnCharHook( wxKeyEvent& aEvt ) override;
void OnCloseTimer( wxTimerEvent& aEvent );
void OnUseBrowser( wxCommandEvent& aEvent );
void OnFootprintSelected( wxCommandEvent& aEvent );
void OnComponentPreselected( wxCommandEvent& aEvent );
/**
* Handle the selection of an item. This is called when either the search box or the tree
* receive an Enter, or the tree receives a double click.
* If the item selected is a category, it is expanded or collapsed; if it is a symbol, the
* symbol is picked.
*/
void OnComponentSelected( wxCommandEvent& aEvent );
/**
* Look up the footprint for a given symbol specified in the #LIB_ID and display it.
*/
void ShowFootprintFor( const LIB_ID& aLibId );
/**
* Display the given footprint by name.
*/
void ShowFootprint( const wxString& aFootprint );
/**
* Populate the footprint selector for a given alias.
*
* @param aLibId the #LIB_ID of the selection or invalid to clear.
*/
void PopulateFootprintSelector( const LIB_ID& aLibId );
public:
static std::mutex g_Mutex;
protected:
static wxString g_symbolSearchString;
static wxString g_powerSearchString;
wxTimer* m_dbl_click_timer;
SYMBOL_PREVIEW_WIDGET* m_symbol_preview;
wxButton* m_browser_button;
wxSplitterWindow* m_hsplitter;
wxSplitterWindow* m_vsplitter;
FOOTPRINT_SELECT_WIDGET* m_fp_sel_ctrl;
FOOTPRINT_PREVIEW_WIDGET* m_fp_preview;
wxCheckBox* m_keepSymbol;
wxCheckBox* m_useUnits;
LIB_TREE* m_tree;
HTML_WINDOW* m_details;
SCH_BASE_FRAME* m_parent;
bool m_showPower;
int m_deMorganConvert;
bool m_allow_field_edits;
bool m_show_footprints;
bool m_external_browser_requested;
wxString m_fp_override;
std::vector<std::pair<int, wxString>> m_field_edits;
};
#endif /* DIALOG_CHOOSE_SYMBOL_H */

View File

@ -347,8 +347,8 @@ private:
}; };
DIALOG_EDIT_SYMBOLS_LIBID::DIALOG_EDIT_SYMBOLS_LIBID( SCH_EDIT_FRAME* aParent ) DIALOG_EDIT_SYMBOLS_LIBID::DIALOG_EDIT_SYMBOLS_LIBID( SCH_EDIT_FRAME* aParent ) :
:DIALOG_EDIT_SYMBOLS_LIBID_BASE( aParent ) DIALOG_EDIT_SYMBOLS_LIBID_BASE( aParent )
{ {
m_autoWrapRenderer = new GRIDCELL_AUTOWRAP_STRINGRENDERER; m_autoWrapRenderer = new GRIDCELL_AUTOWRAP_STRINGRENDERER;
@ -668,13 +668,8 @@ void DIALOG_EDIT_SYMBOLS_LIBID::onClickOrphansButton( wxCommandEvent& event )
bool DIALOG_EDIT_SYMBOLS_LIBID::setLibIdByBrowser( int aRow ) bool DIALOG_EDIT_SYMBOLS_LIBID::setLibIdByBrowser( int aRow )
{ {
#if 0
// Use dialog symbol selector to choose a symbol
SCH_BASE_FRAME::HISTORY_LIST dummy;
SCH_BASE_FRAME::PICKED_SYMBOL sel = m_frame->SelectComponentFromLibrary( nullptr, dummy, true,
0, 0, false );
#else
// Use library viewer to choose a symbol // Use library viewer to choose a symbol
std::vector<PICKED_SYMBOL> dummyHistory;
LIB_ID preselected; LIB_ID preselected;
wxString current = getLibIdValue( m_grid, aRow, COL_NEW_LIBID ); wxString current = getLibIdValue( m_grid, aRow, COL_NEW_LIBID );
@ -684,8 +679,8 @@ bool DIALOG_EDIT_SYMBOLS_LIBID::setLibIdByBrowser( int aRow )
if( !current.IsEmpty() ) if( !current.IsEmpty() )
preselected.Parse( current, true ); preselected.Parse( current, true );
PICKED_SYMBOL sel = GetParent()->PickSymbolFromLibBrowser( this, nullptr, preselected, 0, 0 ); PICKED_SYMBOL sel = GetParent()->PickSymbolFromLibrary( nullptr, dummyHistory, false,
#endif &preselected, false );
if( sel.LibId.empty() ) // command aborted if( sel.LibId.empty() ) // command aborted
return false; return false;

View File

@ -0,0 +1,126 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 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 <symbol_library.h>
#include <dialog_symbol_chooser.h>
#include <widgets/panel_symbol_chooser.h>
#include <eeschema_settings.h>
#include <kiface_base.h>
#include <sch_base_frame.h>
#include <core/kicad_algo.h>
#include <template_fieldnames.h>
#include <widgets/footprint_preview_widget.h>
#include <widgets/footprint_select_widget.h>
#include <widgets/symbol_preview_widget.h>
#include <wx/button.h>
#include <wx/checkbox.h>
#include <wx/sizer.h>
std::mutex DIALOG_SYMBOL_CHOOSER::g_Mutex;
DIALOG_SYMBOL_CHOOSER::DIALOG_SYMBOL_CHOOSER( SCH_BASE_FRAME* aParent, const LIB_ID* aPreselect,
const SYMBOL_LIBRARY_FILTER* aFilter,
std::vector<PICKED_SYMBOL>& aHistoryList,
bool aAllowFieldEdits, bool aShowFootprints ) :
DIALOG_SHIM( aParent, wxID_ANY, _( "Choose Symbol" ), wxDefaultPosition, wxDefaultSize,
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER )
{
wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
m_chooserPanel = new PANEL_SYMBOL_CHOOSER( aParent, this, aFilter, aHistoryList,
aAllowFieldEdits, aShowFootprints,
[this]()
{
EndModal( wxID_OK );
} );
sizer->Add( m_chooserPanel, 1, wxEXPAND, 5 );
if( aPreselect && aPreselect->IsValid() )
m_chooserPanel->SetPreselect( *aPreselect );
if( aFilter->GetFilterPowerSymbols() )
SetTitle( _( "Choose Power Symbol" ) );
SetTitle( GetTitle() + wxString::Format( _( " (%d items loaded)" ),
m_chooserPanel->GetItemCount() ) );
wxBoxSizer* buttonsSizer = new wxBoxSizer( wxHORIZONTAL );
m_keepSymbol = new wxCheckBox( this, wxID_ANY, _( "Place repeated copies" ) );
m_keepSymbol->SetToolTip( _( "Keep the symbol selected for subsequent clicks." ) );
m_useUnits = new wxCheckBox( this, wxID_ANY, _( "Place all units" ) );
m_useUnits->SetToolTip( _( "Sequentially place all units of the symbol." ) );
if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
{
m_keepSymbol->SetValue( cfg->m_SymChooserPanel.keep_symbol );
m_useUnits->SetValue( cfg->m_SymChooserPanel.place_all_units );
}
buttonsSizer->Add( m_keepSymbol, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 5 );
buttonsSizer->Add( m_useUnits, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 30 );
wxStdDialogButtonSizer* sdbSizer = new wxStdDialogButtonSizer();
wxButton* okButton = new wxButton( this, wxID_OK );
wxButton* cancelButton = new wxButton( this, wxID_CANCEL );
sdbSizer->AddButton( okButton );
sdbSizer->AddButton( cancelButton );
sdbSizer->Realize();
buttonsSizer->Add( sdbSizer, 1, wxALL, 5 );
sizer->Add( buttonsSizer, 0, wxEXPAND | wxLEFT, 5 );
SetSizer( sizer );
SetInitialFocus( m_chooserPanel->GetFocusTarget() );
SetupStandardButtons();
m_chooserPanel->FinishSetup();
Layout();
}
DIALOG_SYMBOL_CHOOSER::~DIALOG_SYMBOL_CHOOSER()
{
if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
{
cfg->m_SymChooserPanel.keep_symbol = m_keepSymbol->GetValue();
cfg->m_SymChooserPanel.place_all_units = m_useUnits->GetValue();
}
}
LIB_ID DIALOG_SYMBOL_CHOOSER::GetSelectedLibId( int* aUnit ) const
{
return m_chooserPanel->GetSelectedLibId( aUnit );
}
std::vector<std::pair<int, wxString>> DIALOG_SYMBOL_CHOOSER::GetFields() const
{
return m_chooserPanel->GetFields();
}

View File

@ -0,0 +1,86 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 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
*/
#ifndef DIALOG_SYMBOL_CHOOSER_H
#define DIALOG_SYMBOL_CHOOSER_H
#include "dialog_shim.h"
#include <symbol_tree_model_adapter.h>
#include <footprint_info.h>
#include <widgets/html_window.h>
#include <wx/checkbox.h>
class SCH_BASE_FRAME;
class PANEL_SYMBOL_CHOOSER;
struct PICKED_SYMBOL;
class DIALOG_SYMBOL_CHOOSER : public DIALOG_SHIM
{
public:
/**
* Create dialog to choose symbol.
*
* @param aParent a SCH_BASE_FRAME parent window.
* @param aAllowFieldEdits if false, all functions that allow the user to edit fields
* (currently just footprint selection) will not be available.
* @param aShowFootprints if false, all footprint preview and selection features are
* disabled. This forces aAllowFieldEdits false too.
*/
DIALOG_SYMBOL_CHOOSER( SCH_BASE_FRAME* aParent, const LIB_ID* aPreselect,
const SYMBOL_LIBRARY_FILTER* aFilter,
std::vector<PICKED_SYMBOL>& aHistoryList,
bool aAllowFieldEdits, bool aShowFootprints );
~DIALOG_SYMBOL_CHOOSER();
/**
* To be called after this dialog returns from ShowModal().
*
* For multi-unit symbols, if the user selects the symbol itself rather than picking
* an individual unit, 0 will be returned in aUnit.
* Beware that this is an invalid unit number - this should be replaced with whatever
* default is desired (usually 1).
*
* @param aUnit if not NULL, the selected unit is filled in here.
* @return the #LIB_ID of the symbol that has been selected.
*/
LIB_ID GetSelectedLibId( int* aUnit = nullptr ) const;
/**
* Get a list of fields edited by the user.
*
* @return vector of pairs; each.first = field ID, each.second = new value.
*/
std::vector<std::pair<int, wxString>> GetFields() const;
public:
static std::mutex g_Mutex;
protected:
PANEL_SYMBOL_CHOOSER* m_chooserPanel;
wxCheckBox* m_keepSymbol;
wxCheckBox* m_useUnits;
};
#endif /* DIALOG_SYMBOL_CHOOSER_H */

View File

@ -35,7 +35,7 @@
#include <sch_edit_frame.h> #include <sch_edit_frame.h>
#include <symbol_edit_frame.h> #include <symbol_edit_frame.h>
#include <symbol_viewer_frame.h> #include <symbol_viewer_frame.h>
#include <transform.h> #include <symbol_chooser_frame.h>
#include <symbol_lib_table.h> #include <symbol_lib_table.h>
#include <dialogs/dialog_global_sym_lib_table_config.h> #include <dialogs/dialog_global_sym_lib_table_config.h>
#include <dialogs/panel_grid_settings.h> #include <dialogs/panel_grid_settings.h>
@ -178,10 +178,14 @@ static struct IFACE : public KIFACE_BASE, public UNITS_PROVIDER
} }
case FRAME_SCH_VIEWER: case FRAME_SCH_VIEWER:
case FRAME_SCH_VIEWER_MODAL:
{ {
SYMBOL_VIEWER_FRAME* frame = new SYMBOL_VIEWER_FRAME( aKiway, aParent, SYMBOL_VIEWER_FRAME* frame = new SYMBOL_VIEWER_FRAME( aKiway, aParent );
FRAME_T( aClassId ) ); return frame;
}
case FRAME_SYMBOL_CHOOSER:
{
SYMBOL_CHOOSER_FRAME* frame = new SYMBOL_CHOOSER_FRAME( aKiway, aParent );
return frame; return frame;
} }

View File

@ -60,7 +60,6 @@ enum id_eeschema_frm
ID_LIBEDIT_SELECT_UNIT_NUMBER, ID_LIBEDIT_SELECT_UNIT_NUMBER,
/* Library viewer horizontal toolbar IDs */ /* Library viewer horizontal toolbar IDs */
ID_LIBVIEW_SELECT_PART,
ID_LIBVIEW_NEXT, ID_LIBVIEW_NEXT,
ID_LIBVIEW_PREVIOUS, ID_LIBVIEW_PREVIOUS,
ID_LIBVIEW_SELECT_UNIT_NUMBER, ID_LIBVIEW_SELECT_UNIT_NUMBER,

View File

@ -43,180 +43,29 @@
#include <tools/ee_actions.h> #include <tools/ee_actions.h>
#include <project_sch.h> #include <project_sch.h>
#include <dialog_choose_symbol.h> #include <dialog_symbol_chooser.h>
PICKED_SYMBOL SCH_BASE_FRAME::PickSymbolFromLibBrowser( wxTopLevelWindow* aParent, PICKED_SYMBOL SCH_BASE_FRAME::PickSymbolFromLibrary( const SYMBOL_LIBRARY_FILTER* aFilter,
const SYMBOL_LIBRARY_FILTER* aFilter,
const LIB_ID& aPreselectedLibId,
int aUnit, int aConvert )
{
// Close any open non-modal Lib browser, and open a new one, in "modal" mode:
SYMBOL_VIEWER_FRAME* viewer = (SYMBOL_VIEWER_FRAME*) Kiway().Player( FRAME_SCH_VIEWER, false );
if( viewer )
viewer->Destroy();
viewer = (SYMBOL_VIEWER_FRAME*) Kiway().Player( FRAME_SCH_VIEWER_MODAL, true, aParent );
if( aFilter )
viewer->SetFilter( aFilter );
if( aPreselectedLibId.IsValid() )
{
viewer->SetSelectedLibrary( aPreselectedLibId.GetLibNickname() );
viewer->SetSelectedSymbol( aPreselectedLibId.GetLibItemName());
}
viewer->SetUnitAndConvert( aUnit, aConvert );
viewer->Refresh();
PICKED_SYMBOL sel;
wxString symbol;
if( viewer->ShowModal( &symbol, aParent ) )
{
LIB_ID id;
if( id.Parse( symbol ) == -1 )
sel.LibId = id;
sel.Unit = viewer->GetUnit();
sel.Convert = viewer->GetConvert();
}
viewer->Destroy();
return sel;
}
PICKED_SYMBOL SCH_BASE_FRAME::PickSymbolFromLibTree( const SYMBOL_LIBRARY_FILTER* aFilter,
std::vector<PICKED_SYMBOL>& aHistoryList, std::vector<PICKED_SYMBOL>& aHistoryList,
bool aUseLibBrowser, int aUnit, int aConvert,
bool aShowFootprints, const LIB_ID* aHighlight, bool aShowFootprints, const LIB_ID* aHighlight,
bool aAllowFields ) bool aAllowFields )
{ {
std::unique_lock<std::mutex> dialogLock( DIALOG_CHOOSE_SYMBOL::g_Mutex, std::defer_lock ); std::unique_lock<std::mutex> dialogLock( DIALOG_SYMBOL_CHOOSER::g_Mutex, std::defer_lock );
SYMBOL_LIB_TABLE* libs = PROJECT_SCH::SchSymbolLibTable( &Prj() );
COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
PROJECT_FILE& project = Prj().GetProjectFile();
// One DIALOG_CHOOSE_SYMBOL dialog at a time. User probably can't handle more anyway. // One DIALOG_SYMBOL_CHOOSER dialog at a time. User probably can't handle more anyway.
if( !dialogLock.try_lock() ) if( !dialogLock.try_lock() )
return PICKED_SYMBOL(); return PICKED_SYMBOL();
// Make sure settings are loaded before we start running multi-threaded symbol loaders DIALOG_SYMBOL_CHOOSER dlg( this, aHighlight, aFilter, aHistoryList, aAllowFields,
Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>(); aShowFootprints );
Pgm().GetSettingsManager().GetAppSettings<SYMBOL_EDITOR_SETTINGS>();
if( dlg.ShowModal() == wxID_CANCEL )
wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER> dataPtr
= SYMBOL_TREE_MODEL_ADAPTER::Create( this, libs );
SYMBOL_TREE_MODEL_ADAPTER* modelAdapter
= static_cast<SYMBOL_TREE_MODEL_ADAPTER*>( dataPtr.get() );
bool loaded = false;
if( aFilter )
{
const wxArrayString& liblist = aFilter->GetAllowedLibList();
for( const wxString& nickname : liblist )
{
if( libs->HasLibrary( nickname, true ) )
{
loaded = true;
bool pinned = alg::contains( cfg->m_Session.pinned_symbol_libs, nickname )
|| alg::contains( project.m_PinnedSymbolLibs, nickname );
if( libs->FindRow( nickname )->GetIsVisible() )
modelAdapter->AddLibrary( nickname, pinned );
}
}
modelAdapter->AssignIntrinsicRanks();
if( aFilter->GetFilterPowerSymbols() )
modelAdapter->SetFilter( SYMBOL_TREE_MODEL_ADAPTER::SYM_FILTER_POWER );
}
std::vector<LIB_SYMBOL> history_list_storage;
std::vector<LIB_TREE_ITEM*> history_list;
history_list_storage.reserve( aHistoryList.size() );
for( const PICKED_SYMBOL& i : aHistoryList )
{
LIB_SYMBOL* symbol = GetLibSymbol( i.LibId );
// This can be null, for example when a symbol has been deleted from a library
if( symbol )
{
history_list_storage.emplace_back( *symbol );
for( const std::pair<int, wxString>& fieldDef : i.Fields )
{
LIB_FIELD* field = history_list_storage.back().GetFieldById( fieldDef.first );
if( field )
field->SetText( fieldDef.second );
}
history_list.push_back( &history_list_storage.back() );
}
}
modelAdapter->DoAddLibrary( wxT( "-- " ) + _( "Recently Used" ) + wxT( " --" ), wxEmptyString,
history_list, false, true );
if( !aHistoryList.empty() )
modelAdapter->SetPreselectNode( aHistoryList[0].LibId, aHistoryList[0].Unit );
const std::vector< wxString > libNicknames = libs->GetLogicalLibs();
if( !loaded )
{
if( !modelAdapter->AddLibraries( libNicknames, this ) )
{
// loading cancelled by user
return PICKED_SYMBOL();
}
}
if( aHighlight && aHighlight->IsValid() )
modelAdapter->SetPreselectNode( *aHighlight, /* aUnit */ 0 );
wxString dialogTitle;
if( modelAdapter->GetFilter() == SYMBOL_TREE_MODEL_ADAPTER::SYM_FILTER_POWER )
dialogTitle.Printf( _( "Choose Power Symbol (%d items loaded)" ), dataPtr->GetItemCount() );
else
dialogTitle.Printf( _( "Choose Symbol (%d items loaded)" ), dataPtr->GetItemCount() );
DIALOG_CHOOSE_SYMBOL dlg( this, dialogTitle, dataPtr, aConvert, aAllowFields, aShowFootprints,
aUseLibBrowser );
int ret = dlg.ShowModal();
// Save any changes to column widths, etc.
modelAdapter->SaveSettings();
if( ret == wxID_CANCEL )
return PICKED_SYMBOL(); return PICKED_SYMBOL();
PICKED_SYMBOL sel; PICKED_SYMBOL sel;
LIB_ID id = dlg.GetSelectedLibId( &sel.Unit ); LIB_ID id = dlg.GetSelectedLibId( &sel.Unit );
if( dlg.IsExternalBrowserSelected() ) // User requested symbol browser. if( !id.IsValid() )
{
sel = PickSymbolFromLibBrowser( this, aFilter, id, sel.Unit, sel.Convert );
id = sel.LibId;
}
if( !id.IsValid() ) // Dialog closed by OK button,
// or the selection by lib browser was requested,
// but no symbol selected
return PICKED_SYMBOL(); return PICKED_SYMBOL();
if( sel.Unit == 0 ) if( sel.Unit == 0 )

View File

@ -94,6 +94,7 @@ SCH_BASE_FRAME::SCH_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aWindo
aFrameName, schIUScale ), aFrameName, schIUScale ),
m_base_frame_defaults( nullptr, "base_Frame_defaults" ), m_spaceMouse( nullptr ) m_base_frame_defaults( nullptr, "base_Frame_defaults" ), m_spaceMouse( nullptr )
{ {
if( ( aStyle & wxFRAME_NO_TASKBAR ) == 0 )
createCanvas(); createCanvas();
Bind( wxEVT_IDLE, Bind( wxEVT_IDLE,

View File

@ -146,9 +146,6 @@ public:
* @param aFilter is an optional #SYMBOL_LIBRARY_FILTER filter to pass the allowed library names * @param aFilter is an optional #SYMBOL_LIBRARY_FILTER filter to pass the allowed library names
* and/or the library name to load the symbol from and/or some other filter * and/or the library name to load the symbol from and/or some other filter
* @param aHistoryList is the list of previously loaded symbols - will be edited * @param aHistoryList is the list of previously loaded symbols - will be edited
* @param aUseLibBrowser is the flag to call the library viewer to select the symbol
* @param aUnit is the preselected unit.
* @param aConvert is the preselected De Morgan shape.
* @param aHighlight is the name of symbol to highlight in the list. * @param aHighlight is the name of symbol to highlight in the list.
* highlights none if there isn't one by that name. * highlights none if there isn't one by that name.
* @param aShowFootprints is the whether to show footprints in the dialog. * @param aShowFootprints is the whether to show footprints in the dialog.
@ -156,13 +153,9 @@ public:
* *
* @return the selected symbol * @return the selected symbol
*/ */
PICKED_SYMBOL PickSymbolFromLibTree( const SYMBOL_LIBRARY_FILTER* aFilter, PICKED_SYMBOL PickSymbolFromLibrary( const SYMBOL_LIBRARY_FILTER* aFilter,
std::vector<PICKED_SYMBOL>& aHistoryList, std::vector<PICKED_SYMBOL>& aHistoryList,
bool aUseLibBrowser, bool aShowFootprints, const LIB_ID* aHighlight = nullptr,
int aUnit,
int aConvert,
bool aShowFootprints,
const LIB_ID* aHighlight = nullptr,
bool aAllowFields = true ); bool aAllowFields = true );
/** /**
@ -177,23 +170,6 @@ public:
LIB_SYMBOL* GetLibSymbol( const LIB_ID& aLibId, bool aUseCacheLib = false, LIB_SYMBOL* GetLibSymbol( const LIB_ID& aLibId, bool aUseCacheLib = false,
bool aShowErrorMsg = false ); bool aShowErrorMsg = false );
/**
* Call the library viewer to select symbol to import into schematic.
* If the library viewer is currently running, it is closed and reopened in modal mode.
*
* @param aParent is the caller.
* @param aFilter is a filter to pass the allowed library names
* and/or some other filter.
* @param aPreselectedLibId is the preselected symbol's #LIB_ID. Not valid if none selected.
* @param aUnit is the preselected unit.
* @param aConvert is the preselected deMorgan conversion.
* @return the selected symbol.
*/
PICKED_SYMBOL PickSymbolFromLibBrowser( wxTopLevelWindow* aParent,
const SYMBOL_LIBRARY_FILTER* aFilter,
const LIB_ID& aPreselectedLibId,
int aUnit, int aConvert );
/** /**
* Display a list of loaded libraries and allows the user to select a library. * Display a list of loaded libraries and allows the user to select a library.
* *

View File

@ -50,6 +50,7 @@
#include <project/net_settings.h> #include <project/net_settings.h>
#include <python_scripting.h> #include <python_scripting.h>
#include <sch_edit_frame.h> #include <sch_edit_frame.h>
#include <symbol_chooser_frame.h>
#include <sch_painter.h> #include <sch_painter.h>
#include <sch_sheet.h> #include <sch_sheet.h>
#include <sch_marker.h> #include <sch_marker.h>
@ -903,9 +904,11 @@ bool SCH_EDIT_FRAME::canCloseWindow( wxCloseEvent& aEvent )
if( symbolViewer && !symbolViewer->Close() ) // Can close symbol viewer? if( symbolViewer && !symbolViewer->Close() ) // Can close symbol viewer?
return false; return false;
symbolViewer = (SYMBOL_VIEWER_FRAME*) Kiway().Player( FRAME_SCH_VIEWER_MODAL, false ); // SYMBOL_CHOOSER_FRAME is always modal so this shouldn't come up, but better safe than
// sorry.
auto* chooser = (SYMBOL_CHOOSER_FRAME*) Kiway().Player( FRAME_SYMBOL_CHOOSER, false );
if( symbolViewer && !symbolViewer->Close() ) // Can close modal symbol viewer? if( chooser && !chooser->Close() ) // Can close symbol chooser?
return false; return false;
} }
else else

View File

@ -0,0 +1,174 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 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 <pgm_base.h>
#include <kiplatform/ui.h>
#include <wx/button.h>
#include <sch_base_frame.h>
#include <eeschema_settings.h>
#include <widgets/panel_symbol_chooser.h>
#include <symbol_chooser_frame.h>
static std::vector<PICKED_SYMBOL> s_SymbolHistoryList;
static unsigned s_SymbolHistoryMaxCount = 8;
static void AddSymbolToHistory( const PICKED_SYMBOL& aSymbol )
{
// Remove duplicates
alg::delete_if( s_SymbolHistoryList,
[&]( const PICKED_SYMBOL& candidate ) -> bool
{
return candidate.LibId == aSymbol.LibId
&& candidate.Unit == aSymbol.Unit
&& candidate.Convert == aSymbol.Convert;
} );
// Add the new name at the beginning of the history list
s_SymbolHistoryList.insert( s_SymbolHistoryList.begin(), aSymbol );
// Remove extra names
while( s_SymbolHistoryList.size() > s_SymbolHistoryMaxCount )
s_SymbolHistoryList.resize( s_SymbolHistoryMaxCount );
}
BEGIN_EVENT_TABLE( SYMBOL_CHOOSER_FRAME, SCH_BASE_FRAME )
// Menu (and/or hotkey) events
EVT_MENU( wxID_CLOSE, SYMBOL_CHOOSER_FRAME::CloseSymbolChooser )
EVT_BUTTON( wxID_OK, SYMBOL_CHOOSER_FRAME::OnOK )
EVT_BUTTON( wxID_CANCEL, SYMBOL_CHOOSER_FRAME::CloseSymbolChooser )
EVT_PAINT( SYMBOL_CHOOSER_FRAME::OnPaint )
END_EVENT_TABLE()
#define PARENT_STYLE ( wxRESIZE_BORDER | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN \
| wxWANTS_CHARS | wxFRAME_NO_TASKBAR | wxFRAME_FLOAT_ON_PARENT )
SYMBOL_CHOOSER_FRAME::SYMBOL_CHOOSER_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
SCH_BASE_FRAME( aKiway, aParent, FRAME_SYMBOL_CHOOSER, _( "Symbol Chooser" ),
wxDefaultPosition, wxDefaultSize, PARENT_STYLE, SYMBOL_CHOOSER_FRAME_NAME )
{
SetModal( true );
wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
m_chooserPanel = new PANEL_SYMBOL_CHOOSER( this, this, nullptr /* no filter */,
s_SymbolHistoryList, false, false,
[this]()
{
wxCommandEvent dummy;
OnOK( dummy );
} );
sizer->Add( m_chooserPanel, 1, wxEXPAND, 5 );
wxStdDialogButtonSizer* sdbSizer = new wxStdDialogButtonSizer();
wxButton* okButton = new wxButton( this, wxID_OK );
wxButton* cancelButton = new wxButton( this, wxID_CANCEL );
sdbSizer->AddButton( okButton );
sdbSizer->AddButton( cancelButton );
sdbSizer->Realize();
sizer->Add( sdbSizer, 0, wxEXPAND | wxALL, 5 );
SetSizer( sizer );
SetTitle( GetTitle() + wxString::Format( _( " (%d items loaded)" ),
m_chooserPanel->GetItemCount() ) );
Layout();
m_chooserPanel->FinishSetup();
}
bool SYMBOL_CHOOSER_FRAME::ShowModal( wxString* aSymbol, wxWindow* aParent )
{
if( aSymbol && !aSymbol->IsEmpty() )
{
LIB_ID libid;
libid.Parse( *aSymbol, true );
if( libid.IsValid() )
m_chooserPanel->SetPreselect( libid );
}
return KIWAY_PLAYER::ShowModal( aSymbol, aParent );
}
void SYMBOL_CHOOSER_FRAME::doCloseWindow()
{
// Only dismiss a modal frame once, so that the return values set by
// the prior DismissModal() are not bashed for ShowModal().
if( !IsDismissed() )
DismissModal( false );
// window to be destroyed by the caller of KIWAY_PLAYER::ShowModal()
}
void SYMBOL_CHOOSER_FRAME::OnPaint( wxPaintEvent& aEvent )
{
if( m_firstPaintEvent )
{
KIPLATFORM::UI::FixupCancelButtonCmdKeyCollision( this );
KIPLATFORM::UI::ForceFocus( m_chooserPanel->GetFocusTarget() );
m_firstPaintEvent = false;
}
aEvent.Skip();
}
void SYMBOL_CHOOSER_FRAME::OnOK( wxCommandEvent& aEvent )
{
LIB_ID libId = m_chooserPanel->GetSelectedLibId();
if( libId.IsValid() )
{
PICKED_SYMBOL symbol;
symbol.LibId = libId;
AddSymbolToHistory( symbol );
DismissModal( true, libId.Format() );
}
else
{
DismissModal( false );
}
}
WINDOW_SETTINGS* SYMBOL_CHOOSER_FRAME::GetWindowSettings( APP_SETTINGS_BASE* aCfg )
{
auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( aCfg );
wxASSERT( cfg );
return &cfg->m_LibViewPanel.window;
}
void SYMBOL_CHOOSER_FRAME::CloseSymbolChooser( wxCommandEvent& event )
{
Close( false );
}

View File

@ -0,0 +1,87 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 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
*/
#ifndef SYMBOL_CHOOSER_FRAME_H
#define SYMBOL_CHOOSER_FRAME_H
#include <sch_base_frame.h>
class PANEL_SYMBOL_CHOOSER;
/**
* Symbol library viewer main window.
*/
class SYMBOL_CHOOSER_FRAME : public SCH_BASE_FRAME
{
public:
/**
* @param aKiway
* @param aParent is the parent frame of the viewer.
* @param aFrameType must be either #FRAME_SCH_LIB_VIEWER or #FRAME_SCH_LIB_VIEWER_MODAL.
* @param aLibrary is the library to open when starting (default = NULL).
*/
SYMBOL_CHOOSER_FRAME( KIWAY* aKiway, wxWindow* aParent );
~SYMBOL_CHOOSER_FRAME() {};
/**
* Runs the symbol viewer as a modal dialog.
*
* @param aSymbol an optional FPID string to initialize the viewer with and to
* return a selected footprint through.
*/
bool ShowModal( wxString* aSymbol, wxWindow* aParent ) override;
/**
* Set a filter to display only libraries and/or symbols which match the filter.
*
* @param aFilter is a filter to pass the allowed library name list and/or some other filter
* see SCH_BASE_FRAME::SelectSymbolFromLibrary() for details.
* if aFilter == NULL, remove all filtering.
*/
void SetFilter( const SYMBOL_LIBRARY_FILTER* aFilter );
private:
void OnPaint( wxPaintEvent& aEvent );
void OnOK( wxCommandEvent& aEvent );
void doCloseWindow() override;
void CloseSymbolChooser( wxCommandEvent& aEvent );
WINDOW_SETTINGS* GetWindowSettings( APP_SETTINGS_BASE* aCfg ) override;
DECLARE_EVENT_TABLE()
private:
PANEL_SYMBOL_CHOOSER* m_chooserPanel;
// On MacOS (at least) SetFocus() calls made in the constructor will fail because a
// window that isn't yet visible will return false to AcceptsFocus(). So we must delay
// the initial-focus SetFocus() call to the first paint event.
bool m_firstPaintEvent;
};
#endif // SYMBOL_CHOOSER_FRAME_H

View File

@ -26,7 +26,6 @@
#include <bitmaps.h> #include <bitmaps.h>
#include <symbol_library_common.h> #include <symbol_library_common.h>
#include <confirm.h> #include <confirm.h>
#include <dialog_choose_symbol.h>
#include <dialogs/html_message_box.h> #include <dialogs/html_message_box.h>
#include <eeschema_id.h> #include <eeschema_id.h>
#include <eeschema_settings.h> #include <eeschema_settings.h>
@ -81,7 +80,6 @@ BEGIN_EVENT_TABLE( SYMBOL_VIEWER_FRAME, SCH_BASE_FRAME )
EVT_ACTIVATE( SYMBOL_VIEWER_FRAME::OnActivate ) EVT_ACTIVATE( SYMBOL_VIEWER_FRAME::OnActivate )
// Toolbar events // Toolbar events
EVT_TOOL( ID_LIBVIEW_SELECT_PART, SYMBOL_VIEWER_FRAME::OnSelectSymbol )
EVT_TOOL( ID_LIBVIEW_NEXT, SYMBOL_VIEWER_FRAME::onSelectNextSymbol ) EVT_TOOL( ID_LIBVIEW_NEXT, SYMBOL_VIEWER_FRAME::onSelectNextSymbol )
EVT_TOOL( ID_LIBVIEW_PREVIOUS, SYMBOL_VIEWER_FRAME::onSelectPreviousSymbol ) EVT_TOOL( ID_LIBVIEW_PREVIOUS, SYMBOL_VIEWER_FRAME::onSelectPreviousSymbol )
EVT_CHOICE( ID_LIBVIEW_SELECT_UNIT_NUMBER, SYMBOL_VIEWER_FRAME::onSelectSymbolUnit ) EVT_CHOICE( ID_LIBVIEW_SELECT_UNIT_NUMBER, SYMBOL_VIEWER_FRAME::onSelectSymbolUnit )
@ -101,34 +99,20 @@ BEGIN_EVENT_TABLE( SYMBOL_VIEWER_FRAME, SCH_BASE_FRAME )
END_EVENT_TABLE() END_EVENT_TABLE()
#define LIB_VIEW_NAME "ViewlibFrame" SYMBOL_VIEWER_FRAME::SYMBOL_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
#define LIB_VIEW_NAME_MODAL "ViewlibFrameModal" SCH_BASE_FRAME( aKiway, aParent, FRAME_SCH_VIEWER, _( "Symbol Library Browser" ),
wxDefaultPosition, wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE,
#define LIB_VIEW_STYLE ( KICAD_DEFAULT_DRAWFRAME_STYLE ) LIB_VIEW_FRAME_NAME ),
#define LIB_VIEW_STYLE_MODAL ( KICAD_DEFAULT_DRAWFRAME_STYLE | wxFRAME_FLOAT_ON_PARENT )
SYMBOL_VIEWER_FRAME::SYMBOL_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType,
const wxString& aLibraryName ) :
SCH_BASE_FRAME( aKiway, aParent, aFrameType, _( "Symbol Library Browser" ),
wxDefaultPosition, wxDefaultSize,
aFrameType == FRAME_SCH_VIEWER_MODAL ? LIB_VIEW_STYLE_MODAL : LIB_VIEW_STYLE,
aFrameType == FRAME_SCH_VIEWER_MODAL ? LIB_VIEW_NAME_MODAL : LIB_VIEW_NAME ),
m_unitChoice( nullptr ), m_unitChoice( nullptr ),
m_libList( nullptr ), m_libList( nullptr ),
m_symbolList( nullptr ) m_symbolList( nullptr )
{ {
wxASSERT( aFrameType == FRAME_SCH_VIEWER || aFrameType == FRAME_SCH_VIEWER_MODAL ); m_aboutTitle = _HKI( "KiCad Symbol Library Browser" );
if( aFrameType == FRAME_SCH_VIEWER_MODAL )
SetModal( true );
m_aboutTitle = _HKI( "KiCad Symbol Library Viewer" );
// Force the frame name used in config. the lib viewer frame has a name // Force the frame name used in config. the lib viewer frame has a name
// depending on aFrameType (needed to identify the frame by wxWidgets), // depending on aFrameType (needed to identify the frame by wxWidgets),
// but only one configuration is preferable. // but only one configuration is preferable.
m_configName = LIB_VIEW_NAME; m_configName = LIB_VIEW_FRAME_NAME;
// Give an icon // Give an icon
wxIcon icon; wxIcon icon;
@ -204,18 +188,7 @@ SYMBOL_VIEWER_FRAME::SYMBOL_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAM
// Preload libraries // Preload libraries
loadAllLibraries(); loadAllLibraries();
if( aLibraryName.empty() )
{
ReCreateLibList(); ReCreateLibList();
}
else
{
m_currentSymbol.SetLibNickname( aLibraryName );
m_currentSymbol.SetLibItemName( "" );
m_unit = 1;
m_convert = 1;
}
m_selection_changed = false; m_selection_changed = false;
@ -236,8 +209,6 @@ SYMBOL_VIEWER_FRAME::SYMBOL_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAM
m_auimgr.AddPane( GetCanvas(), EDA_PANE().Canvas().Name( "DrawFrame" ).Center() ); m_auimgr.AddPane( GetCanvas(), EDA_PANE().Canvas().Name( "DrawFrame" ).Center() );
m_auimgr.GetPane( libPanel ).Show( aLibraryName.empty() );
m_auimgr.Update(); m_auimgr.Update();
if( m_libListWidth > 0 ) if( m_libListWidth > 0 )
@ -1072,59 +1043,6 @@ void SYMBOL_VIEWER_FRAME::FinishModal()
} }
void SYMBOL_VIEWER_FRAME::OnSelectSymbol( wxCommandEvent& aEvent )
{
std::unique_lock<std::mutex> dialogLock( DIALOG_CHOOSE_SYMBOL::g_Mutex, std::defer_lock );
// One CHOOSE_SYMBOL dialog at a time. User probably can't handle more anyway.
if( !dialogLock.try_lock() )
return;
// Container doing search-as-you-type.
SYMBOL_LIB_TABLE* libs = PROJECT_SCH::SchSymbolLibTable( &Prj() );
wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER> dataPtr
= SYMBOL_TREE_MODEL_ADAPTER::Create( this, libs );
SYMBOL_TREE_MODEL_ADAPTER* modelAdapter
= static_cast<SYMBOL_TREE_MODEL_ADAPTER*>( dataPtr.get() );
if( !modelAdapter->AddLibraries( libs->GetLogicalLibs(), this ) )
{
// loading cancelled by user
return;
}
LIB_SYMBOL* current = GetSelectedSymbol();
LIB_ID id;
int unit = 0;
if( current )
{
id = current->GetLibId();
modelAdapter->SetPreselectNode( id, unit );
}
wxString dialogTitle;
dialogTitle.Printf( _( "Choose Symbol (%d items loaded)" ), modelAdapter->GetItemCount() );
DIALOG_CHOOSE_SYMBOL dlg( this, dialogTitle, dataPtr, m_convert, false, false, false );
if( dlg.ShowQuasiModal() == wxID_CANCEL )
return;
// Save any changes to column widths, etc.
modelAdapter->SaveSettings();
id = dlg.GetSelectedLibId( &unit );
if( !id.IsValid() )
return;
SetSelectedLibrary( id.GetLibNickname(), id.GetSubLibraryName() );
SetSelectedSymbol( id.GetLibItemName() );
SetUnitAndConvert( unit, 1 );
}
void SYMBOL_VIEWER_FRAME::OnLibFilter( wxCommandEvent& aEvent ) void SYMBOL_VIEWER_FRAME::OnLibFilter( wxCommandEvent& aEvent )
{ {
ReCreateLibList(); ReCreateLibList();

View File

@ -51,8 +51,7 @@ public:
* @param aFrameType must be either #FRAME_SCH_LIB_VIEWER or #FRAME_SCH_LIB_VIEWER_MODAL. * @param aFrameType must be either #FRAME_SCH_LIB_VIEWER or #FRAME_SCH_LIB_VIEWER_MODAL.
* @param aLibrary is the library to open when starting (default = NULL). * @param aLibrary is the library to open when starting (default = NULL).
*/ */
SYMBOL_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType, SYMBOL_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent );
const wxString& aLibraryName = wxEmptyString );
~SYMBOL_VIEWER_FRAME(); ~SYMBOL_VIEWER_FRAME();
@ -95,7 +94,6 @@ public:
void ClickOnLibList( wxCommandEvent& event ); void ClickOnLibList( wxCommandEvent& event );
void ClickOnSymbolList( wxCommandEvent& event ); void ClickOnSymbolList( wxCommandEvent& event );
void OnSelectSymbol( wxCommandEvent& aEvent );
void LoadSettings( APP_SETTINGS_BASE* aCfg ) override; void LoadSettings( APP_SETTINGS_BASE* aCfg ) override;
void SaveSettings( APP_SETTINGS_BASE* aCfg ) override; void SaveSettings( APP_SETTINGS_BASE* aCfg ) override;

View File

@ -46,10 +46,6 @@ void SYMBOL_VIEWER_FRAME::ReCreateHToolbar()
m_mainToolBar->SetAuiManager( &m_auimgr ); m_mainToolBar->SetAuiManager( &m_auimgr );
} }
m_mainToolBar->AddTool( ID_LIBVIEW_SELECT_PART, wxEmptyString,
KiScaledBitmap( BITMAPS::library_browser, this ),
_( "Choose symbol" ) );
m_mainToolBar->AddTool( ID_LIBVIEW_PREVIOUS, wxEmptyString, m_mainToolBar->AddTool( ID_LIBVIEW_PREVIOUS, wxEmptyString,
KiScaledBitmap( BITMAPS::lib_previous, this ), KiScaledBitmap( BITMAPS::lib_previous, this ),
_( "Display previous symbol" ) ); _( "Display previous symbol" ) );

View File

@ -404,7 +404,7 @@ int EE_INSPECTION_TOOL::ShowDatasheet( const TOOL_EVENT& aEvent )
datasheet = symbol->GetDatasheetField().GetText(); datasheet = symbol->GetDatasheetField().GetText();
} }
else if( m_frame->IsType( FRAME_SCH_VIEWER ) || m_frame->IsType( FRAME_SCH_VIEWER_MODAL ) ) else if( m_frame->IsType( FRAME_SCH_VIEWER ) )
{ {
LIB_SYMBOL* entry = static_cast<SYMBOL_VIEWER_FRAME*>( m_frame )->GetSelectedSymbol(); LIB_SYMBOL* entry = static_cast<SYMBOL_VIEWER_FRAME*>( m_frame )->GetSelectedSymbol();

View File

@ -305,8 +305,8 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
// Pick the symbol to be placed // Pick the symbol to be placed
bool footprintPreviews = m_frame->eeconfig()->m_Appearance.footprint_preview; bool footprintPreviews = m_frame->eeconfig()->m_Appearance.footprint_preview;
PICKED_SYMBOL sel = m_frame->PickSymbolFromLibTree( &filter, *historyList, true, PICKED_SYMBOL sel = m_frame->PickSymbolFromLibrary( &filter, *historyList,
1, 1, footprintPreviews ); footprintPreviews );
LIB_SYMBOL* libSymbol = sel.LibId.IsValid() ? m_frame->GetLibSymbol( sel.LibId ) LIB_SYMBOL* libSymbol = sel.LibId.IsValid() ? m_frame->GetLibSymbol( sel.LibId )
: nullptr; : nullptr;

View File

@ -447,7 +447,7 @@ int SYMBOL_EDITOR_CONTROL::OnDeMorgan( const TOOL_EVENT& aEvent )
m_toolMgr->ResetTools( TOOL_BASE::MODEL_RELOAD ); m_toolMgr->ResetTools( TOOL_BASE::MODEL_RELOAD );
symbolEditor->RebuildView(); symbolEditor->RebuildView();
} }
else if( m_frame->IsType( FRAME_SCH_VIEWER ) || m_frame->IsType( FRAME_SCH_VIEWER_MODAL ) ) else if( m_frame->IsType( FRAME_SCH_VIEWER ) )
{ {
SYMBOL_VIEWER_FRAME* symbolViewer = static_cast<SYMBOL_VIEWER_FRAME*>( m_frame ); SYMBOL_VIEWER_FRAME* symbolViewer = static_cast<SYMBOL_VIEWER_FRAME*>( m_frame );
symbolViewer->SetUnitAndConvert( symbolViewer->GetUnit(), convert ); symbolViewer->SetUnitAndConvert( symbolViewer->GetUnit(), convert );

View File

@ -23,7 +23,7 @@
*/ */
#include <symbol_library.h> #include <symbol_library.h>
#include <dialog_choose_symbol.h> #include <panel_symbol_chooser.h>
#include <eeschema_settings.h> #include <eeschema_settings.h>
#include <kiface_base.h> #include <kiface_base.h>
#include <sch_base_frame.h> #include <sch_base_frame.h>
@ -34,10 +34,11 @@
#include <widgets/footprint_select_widget.h> #include <widgets/footprint_select_widget.h>
#include <widgets/lib_tree.h> #include <widgets/lib_tree.h>
#include <widgets/symbol_preview_widget.h> #include <widgets/symbol_preview_widget.h>
#include <settings/settings_manager.h>
#include <project/project_file.h>
#include <symbol_editor_settings.h>
#include <wx/button.h> #include <wx/button.h>
#include <wx/checkbox.h>
#include <wx/clipbrd.h> #include <wx/clipbrd.h>
#include <wx/dataview.h>
#include <wx/log.h> #include <wx/log.h>
#include <wx/panel.h> #include <wx/panel.h>
#include <wx/sizer.h> #include <wx/sizer.h>
@ -45,40 +46,118 @@
#include <wx/timer.h> #include <wx/timer.h>
#include <wx/utils.h> #include <wx/utils.h>
#include <wx/wxhtml.h> #include <wx/wxhtml.h>
#include "pgm_base.h"
std::mutex DIALOG_CHOOSE_SYMBOL::g_Mutex;
wxString DIALOG_CHOOSE_SYMBOL::g_symbolSearchString;
wxString DIALOG_CHOOSE_SYMBOL::g_powerSearchString;
DIALOG_CHOOSE_SYMBOL::DIALOG_CHOOSE_SYMBOL( SCH_BASE_FRAME* aParent, const wxString& aTitle, wxString PANEL_SYMBOL_CHOOSER::g_symbolSearchString;
wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER>& aAdapter, wxString PANEL_SYMBOL_CHOOSER::g_powerSearchString;
int aDeMorganConvert, bool aAllowFieldEdits,
bool aShowFootprints, bool aAllowBrowser )
: DIALOG_SHIM( aParent, wxID_ANY, aTitle, wxDefaultPosition, wxDefaultSize, PANEL_SYMBOL_CHOOSER::PANEL_SYMBOL_CHOOSER( SCH_BASE_FRAME* aFrame, wxWindow* aParent,
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ), const SYMBOL_LIBRARY_FILTER* aFilter,
std::vector<PICKED_SYMBOL>& aHistoryList,
bool aAllowFieldEdits, bool aShowFootprints,
std::function<void()> aCloseHandler ) :
wxPanel( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize ),
m_symbol_preview( nullptr ), m_symbol_preview( nullptr ),
m_browser_button( nullptr ),
m_hsplitter( nullptr ), m_hsplitter( nullptr ),
m_vsplitter( nullptr ), m_vsplitter( nullptr ),
m_fp_sel_ctrl( nullptr ), m_fp_sel_ctrl( nullptr ),
m_fp_preview( nullptr ), m_fp_preview( nullptr ),
m_keepSymbol( nullptr ),
m_useUnits( nullptr ),
m_tree( nullptr ), m_tree( nullptr ),
m_details( nullptr ), m_details( nullptr ),
m_parent( aParent ), m_frame( aFrame ),
m_deMorganConvert( aDeMorganConvert >= 0 ? aDeMorganConvert : 0 ), m_closeHandler( std::move( aCloseHandler ) ),
m_showPower( false ),
m_allow_field_edits( aAllowFieldEdits ), m_allow_field_edits( aAllowFieldEdits ),
m_show_footprints( aShowFootprints ), m_show_footprints( aShowFootprints )
m_external_browser_requested( false )
{ {
m_showPower = aAdapter->GetFilter() == SYMBOL_TREE_MODEL_ADAPTER::SYM_FILTER_POWER; SYMBOL_LIB_TABLE* libs = PROJECT_SCH::SchSymbolLibTable( &m_frame->Prj() );
COMMON_SETTINGS::SESSION& session = Pgm().GetCommonSettings()->m_Session;
PROJECT_FILE& project = m_frame->Prj().GetProjectFile();
// Never show footprints in power symbol mode // Make sure settings are loaded before we start running multi-threaded symbol loaders
if( m_showPower ) Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>();
Pgm().GetSettingsManager().GetAppSettings<SYMBOL_EDITOR_SETTINGS>();
m_adapter = SYMBOL_TREE_MODEL_ADAPTER::Create( m_frame, libs );
SYMBOL_TREE_MODEL_ADAPTER* adapter = static_cast<SYMBOL_TREE_MODEL_ADAPTER*>( m_adapter.get() );
bool loaded = false;
if( aFilter )
{
const wxArrayString& liblist = aFilter->GetAllowedLibList();
for( const wxString& nickname : liblist )
{
if( libs->HasLibrary( nickname, true ) )
{
loaded = true;
bool pinned = alg::contains( session.pinned_symbol_libs, nickname )
|| alg::contains( project.m_PinnedSymbolLibs, nickname );
if( libs->FindRow( nickname )->GetIsVisible() )
adapter->AddLibrary( nickname, pinned );
}
}
adapter->AssignIntrinsicRanks();
if( aFilter->GetFilterPowerSymbols() )
{
adapter->SetFilter( SYMBOL_TREE_MODEL_ADAPTER::SYM_FILTER_POWER );
m_showPower = true;
m_show_footprints = false; m_show_footprints = false;
}
}
std::vector<LIB_SYMBOL> history_list_storage;
std::vector<LIB_TREE_ITEM*> history_list;
history_list_storage.reserve( aHistoryList.size() );
for( const PICKED_SYMBOL& i : aHistoryList )
{
LIB_SYMBOL* symbol = m_frame->GetLibSymbol( i.LibId );
// This can be null, for example when a symbol has been deleted from a library
if( symbol )
{
history_list_storage.emplace_back( *symbol );
for( const std::pair<int, wxString>& fieldDef : i.Fields )
{
LIB_FIELD* field = history_list_storage.back().GetFieldById( fieldDef.first );
if( field )
field->SetText( fieldDef.second );
}
history_list.push_back( &history_list_storage.back() );
}
}
adapter->DoAddLibrary( wxT( "-- " ) + _( "Recently Used" ) + wxT( " --" ), wxEmptyString,
history_list, false, true );
if( !aHistoryList.empty() )
adapter->SetPreselectNode( aHistoryList[0].LibId, aHistoryList[0].Unit );
const std::vector< wxString > libNicknames = libs->GetLogicalLibs();
if( !loaded )
{
if( !adapter->AddLibraries( libNicknames, m_frame ) )
{
// loading cancelled by user
m_closeHandler();
}
}
// -------------------------------------------------------------------------------------
// Construct the actual dialog
//
wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL ); wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
@ -92,7 +171,7 @@ DIALOG_CHOOSE_SYMBOL::DIALOG_CHOOSE_SYMBOL( SCH_BASE_FRAME* aParent, const wxStr
//Avoid the splitter window being assigned as the Parent to additional windows //Avoid the splitter window being assigned as the Parent to additional windows
m_hsplitter->SetExtraStyle( wxWS_EX_TRANSIENT ); m_hsplitter->SetExtraStyle( wxWS_EX_TRANSIENT );
sizer->Add( m_hsplitter, 1, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 ); sizer->Add( m_hsplitter, 1, wxEXPAND, 5 );
} }
else else
{ {
@ -110,9 +189,8 @@ DIALOG_CHOOSE_SYMBOL::DIALOG_CHOOSE_SYMBOL( SCH_BASE_FRAME* aParent, const wxStr
wxBoxSizer* detailsSizer = new wxBoxSizer( wxVERTICAL ); wxBoxSizer* detailsSizer = new wxBoxSizer( wxVERTICAL );
detailsPanel->SetSizer( detailsSizer ); detailsPanel->SetSizer( detailsSizer );
m_details = new HTML_WINDOW( detailsPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_details = new HTML_WINDOW( detailsPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize );
wxHW_SCROLLBAR_AUTO ); detailsSizer->Add( m_details, 1, wxEXPAND, 5 );
detailsSizer->Add( m_details, 1, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 );
detailsPanel->Layout(); detailsPanel->Layout();
detailsSizer->Fit( detailsPanel ); detailsSizer->Fit( detailsPanel );
@ -120,7 +198,7 @@ DIALOG_CHOOSE_SYMBOL::DIALOG_CHOOSE_SYMBOL( SCH_BASE_FRAME* aParent, const wxStr
m_vsplitter->SetMinimumPaneSize( 20 ); m_vsplitter->SetMinimumPaneSize( 20 );
m_vsplitter->SplitHorizontally( m_hsplitter, detailsPanel ); m_vsplitter->SplitHorizontally( m_hsplitter, detailsPanel );
sizer->Add( m_vsplitter, 1, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 ); sizer->Add( m_vsplitter, 1, wxEXPAND, 5 );
} }
wxPanel* treePanel = new wxPanel( m_hsplitter ); wxPanel* treePanel = new wxPanel( m_hsplitter );
@ -128,15 +206,13 @@ DIALOG_CHOOSE_SYMBOL::DIALOG_CHOOSE_SYMBOL( SCH_BASE_FRAME* aParent, const wxStr
treePanel->SetSizer( treeSizer ); treePanel->SetSizer( treeSizer );
m_tree = new LIB_TREE( treePanel, m_showPower ? wxT( "power" ) : wxT( "symbols" ), m_tree = new LIB_TREE( treePanel, m_showPower ? wxT( "power" ) : wxT( "symbols" ),
PROJECT_SCH::SchSymbolLibTable( &Prj() ), aAdapter, libs, m_adapter, LIB_TREE::FLAGS::ALL_WIDGETS, m_details );
LIB_TREE::FLAGS::ALL_WIDGETS,
m_details );
treeSizer->Add( m_tree, 1, wxEXPAND | wxALL, 5 ); treeSizer->Add( m_tree, 1, wxEXPAND, 5 );
treePanel->Layout(); treePanel->Layout();
treeSizer->Fit( treePanel ); treeSizer->Fit( treePanel );
aAdapter->FinishTreeInitialization(); m_adapter->FinishTreeInitialization();
if( m_showPower ) if( m_showPower )
m_tree->SetSearchString( g_powerSearchString ); m_tree->SetSearchString( g_powerSearchString );
@ -149,100 +225,33 @@ DIALOG_CHOOSE_SYMBOL::DIALOG_CHOOSE_SYMBOL( SCH_BASE_FRAME* aParent, const wxStr
m_dbl_click_timer = new wxTimer( this ); m_dbl_click_timer = new wxTimer( this );
wxBoxSizer* buttonsSizer = new wxBoxSizer( wxHORIZONTAL );
if( aAllowBrowser )
{
m_browser_button = new wxButton( this, wxID_ANY, _( "Select with Browser" ) );
buttonsSizer->Add( m_browser_button, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
}
m_keepSymbol = new wxCheckBox( this, wxID_ANY, _( "Place repeated copies" ) );
m_keepSymbol->SetToolTip( _( "Keep the symbol selected for subsequent clicks." ) );
m_useUnits = new wxCheckBox( this, wxID_ANY, _( "Place all units" ) );
m_useUnits->SetToolTip( _( "Sequentially place all units of the symbol." ) );
if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
{
m_keepSymbol->SetValue( cfg->m_SymChooserPanel.keep_symbol );
m_useUnits->SetValue( cfg->m_SymChooserPanel.place_all_units );
}
buttonsSizer->Add( m_keepSymbol, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 30 );
buttonsSizer->Add( m_useUnits, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 30 );
wxStdDialogButtonSizer* sdbSizer = new wxStdDialogButtonSizer();
wxButton* okButton = new wxButton( this, wxID_OK );
wxButton* cancelButton = new wxButton( this, wxID_CANCEL );
sdbSizer->AddButton( okButton );
sdbSizer->AddButton( cancelButton );
sdbSizer->Realize();
buttonsSizer->Add( sdbSizer, 1, wxALL, 5 );
sizer->Add( buttonsSizer, 0, wxEXPAND | wxLEFT, 5 );
SetSizer( sizer ); SetSizer( sizer );
Layout(); Layout();
if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) ) Bind( wxEVT_TIMER, &PANEL_SYMBOL_CHOOSER::OnCloseTimer, this, m_dbl_click_timer->GetId() );
{ Bind( SYMBOL_PRESELECTED, &PANEL_SYMBOL_CHOOSER::OnComponentPreselected, this );
EESCHEMA_SETTINGS::PANEL_SYM_CHOOSER& panelCfg = cfg->m_SymChooserPanel; Bind( SYMBOL_SELECTED, &PANEL_SYMBOL_CHOOSER::OnComponentSelected, this );
// We specify the width of the right window (m_symbol_view_panel), because specify
// the width of the left window does not work as expected when SetSashGravity() is called
m_hsplitter->SetSashPosition( panelCfg.sash_pos_h > 0 ? panelCfg.sash_pos_h
: horizPixelsFromDU( 220 ) );
if( m_vsplitter )
{
m_vsplitter->SetSashPosition( panelCfg.sash_pos_v > 0 ? panelCfg.sash_pos_v
: vertPixelsFromDU( 230 ) );
}
wxSize dlgSize( panelCfg.width > 0 ? panelCfg.width : horizPixelsFromDU( 390 ),
panelCfg.height > 0 ? panelCfg.height : vertPixelsFromDU( 300 ) );
SetSize( dlgSize );
aAdapter->SetSortMode( (LIB_TREE_MODEL_ADAPTER::SORT_MODE) cfg->m_SymChooserPanel.sort_mode );
}
SetInitialFocus( m_tree->GetFocusTarget() );
SetupStandardButtons();
Bind( wxEVT_INIT_DIALOG, &DIALOG_CHOOSE_SYMBOL::OnInitDialog, this );
Bind( wxEVT_TIMER, &DIALOG_CHOOSE_SYMBOL::OnCloseTimer, this, m_dbl_click_timer->GetId() );
Bind( SYMBOL_PRESELECTED, &DIALOG_CHOOSE_SYMBOL::OnComponentPreselected, this );
Bind( SYMBOL_SELECTED, &DIALOG_CHOOSE_SYMBOL::OnComponentSelected, this );
if( m_browser_button )
{
m_browser_button->Bind( wxEVT_COMMAND_BUTTON_CLICKED, &DIALOG_CHOOSE_SYMBOL::OnUseBrowser,
this );
}
if( m_fp_sel_ctrl ) if( m_fp_sel_ctrl )
{ {
m_fp_sel_ctrl->Bind( EVT_FOOTPRINT_SELECTED, &DIALOG_CHOOSE_SYMBOL::OnFootprintSelected, m_fp_sel_ctrl->Bind( EVT_FOOTPRINT_SELECTED, &PANEL_SYMBOL_CHOOSER::OnFootprintSelected,
this ); this );
} }
if( m_details ) if( m_details )
{ {
m_details->Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_CHOOSE_SYMBOL::OnCharHook ), m_details->Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( PANEL_SYMBOL_CHOOSER::OnCharHook ),
nullptr, this ); nullptr, this );
} }
} }
DIALOG_CHOOSE_SYMBOL::~DIALOG_CHOOSE_SYMBOL() PANEL_SYMBOL_CHOOSER::~PANEL_SYMBOL_CHOOSER()
{ {
Unbind( wxEVT_INIT_DIALOG, &DIALOG_CHOOSE_SYMBOL::OnInitDialog, this ); Unbind( wxEVT_TIMER, &PANEL_SYMBOL_CHOOSER::OnCloseTimer, this );
Unbind( wxEVT_TIMER, &DIALOG_CHOOSE_SYMBOL::OnCloseTimer, this ); Unbind( SYMBOL_PRESELECTED, &PANEL_SYMBOL_CHOOSER::OnComponentPreselected, this );
Unbind( SYMBOL_PRESELECTED, &DIALOG_CHOOSE_SYMBOL::OnComponentPreselected, this ); Unbind( SYMBOL_SELECTED, &PANEL_SYMBOL_CHOOSER::OnComponentSelected, this );
Unbind( SYMBOL_SELECTED, &DIALOG_CHOOSE_SYMBOL::OnComponentSelected, this );
// Stop the timer during destruction early to avoid potential race conditions (that do happen) // Stop the timer during destruction early to avoid potential race conditions (that do happen)
m_dbl_click_timer->Stop(); m_dbl_click_timer->Stop();
@ -253,22 +262,16 @@ DIALOG_CHOOSE_SYMBOL::~DIALOG_CHOOSE_SYMBOL()
else else
g_symbolSearchString = m_tree->GetSearchString(); g_symbolSearchString = m_tree->GetSearchString();
if( m_browser_button )
{
m_browser_button->Unbind( wxEVT_COMMAND_BUTTON_CLICKED,
&DIALOG_CHOOSE_SYMBOL::OnUseBrowser, this );
}
if( m_fp_sel_ctrl ) if( m_fp_sel_ctrl )
{ {
m_fp_sel_ctrl->Unbind( EVT_FOOTPRINT_SELECTED, &DIALOG_CHOOSE_SYMBOL::OnFootprintSelected, m_fp_sel_ctrl->Unbind( EVT_FOOTPRINT_SELECTED, &PANEL_SYMBOL_CHOOSER::OnFootprintSelected,
this ); this );
} }
if( m_details ) if( m_details )
{ {
m_details->Disconnect( wxEVT_CHAR_HOOK, m_details->Disconnect( wxEVT_CHAR_HOOK,
wxKeyEventHandler( DIALOG_CHOOSE_SYMBOL::OnCharHook ), nullptr, wxKeyEventHandler( PANEL_SYMBOL_CHOOSER::OnCharHook ), nullptr,
this ); this );
} }
@ -277,9 +280,6 @@ DIALOG_CHOOSE_SYMBOL::~DIALOG_CHOOSE_SYMBOL()
cfg->m_SymChooserPanel.width = GetSize().x; cfg->m_SymChooserPanel.width = GetSize().x;
cfg->m_SymChooserPanel.height = GetSize().y; cfg->m_SymChooserPanel.height = GetSize().y;
cfg->m_SymChooserPanel.keep_symbol = m_keepSymbol->GetValue();
cfg->m_SymChooserPanel.place_all_units = m_useUnits->GetValue();
cfg->m_SymChooserPanel.sash_pos_h = m_hsplitter->GetSashPosition(); cfg->m_SymChooserPanel.sash_pos_h = m_hsplitter->GetSashPosition();
if( m_vsplitter ) if( m_vsplitter )
@ -290,39 +290,50 @@ DIALOG_CHOOSE_SYMBOL::~DIALOG_CHOOSE_SYMBOL()
} }
wxPanel* DIALOG_CHOOSE_SYMBOL::ConstructRightPanel( wxWindow* aParent ) wxPanel* PANEL_SYMBOL_CHOOSER::ConstructRightPanel( wxWindow* aParent )
{ {
EDA_DRAW_PANEL_GAL::GAL_TYPE backend;
if( m_frame->GetCanvas() )
{
backend = m_frame->GetCanvas()->GetBackend();
}
else
{
EESCHEMA_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>();
backend = (EDA_DRAW_PANEL_GAL::GAL_TYPE) cfg->m_Graphics.canvas_type;
}
wxPanel* panel = new wxPanel( aParent ); wxPanel* panel = new wxPanel( aParent );
wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL ); wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
EDA_DRAW_PANEL_GAL::GAL_TYPE backend = m_parent->GetCanvas()->GetBackend();
m_symbol_preview = new SYMBOL_PREVIEW_WIDGET( panel, &Kiway(), true, backend ); m_symbol_preview = new SYMBOL_PREVIEW_WIDGET( panel, &m_frame->Kiway(), true, backend );
m_symbol_preview->SetLayoutDirection( wxLayout_LeftToRight ); m_symbol_preview->SetLayoutDirection( wxLayout_LeftToRight );
if( m_show_footprints ) if( m_show_footprints )
{ {
FOOTPRINT_LIST* fp_list = FOOTPRINT_LIST::GetInstance( Kiway() ); FOOTPRINT_LIST* fp_list = FOOTPRINT_LIST::GetInstance( m_frame->Kiway() );
sizer->Add( m_symbol_preview, 11, wxEXPAND | wxALL, 5 ); sizer->Add( m_symbol_preview, 11, wxEXPAND | wxBOTTOM, 5 );
if ( fp_list ) if ( fp_list )
{ {
if( m_allow_field_edits ) if( m_allow_field_edits )
m_fp_sel_ctrl = new FOOTPRINT_SELECT_WIDGET( m_parent, panel, fp_list, true ); m_fp_sel_ctrl = new FOOTPRINT_SELECT_WIDGET( m_frame, panel, fp_list, true );
m_fp_preview = new FOOTPRINT_PREVIEW_WIDGET( panel, Kiway() ); m_fp_preview = new FOOTPRINT_PREVIEW_WIDGET( panel, m_frame->Kiway() );
m_fp_preview->SetUserUnits( GetUserUnits() ); m_fp_preview->SetUserUnits( m_frame->GetUserUnits() );
} }
if( m_fp_sel_ctrl ) if( m_fp_sel_ctrl )
sizer->Add( m_fp_sel_ctrl, 0, wxEXPAND | wxALL, 4 ); sizer->Add( m_fp_sel_ctrl, 0, wxEXPAND | wxTOP | wxBOTTOM, 4 );
if( m_fp_preview ) if( m_fp_preview )
sizer->Add( m_fp_preview, 10, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5 ); sizer->Add( m_fp_preview, 10, wxEXPAND, 5 );
} }
else else
{ {
sizer->Add( m_symbol_preview, 1, wxEXPAND | wxALL, 5 ); sizer->Add( m_symbol_preview, 1, wxEXPAND, 5 );
} }
panel->SetSizer( sizer ); panel->SetSizer( sizer );
@ -333,8 +344,42 @@ wxPanel* DIALOG_CHOOSE_SYMBOL::ConstructRightPanel( wxWindow* aParent )
} }
void DIALOG_CHOOSE_SYMBOL::OnInitDialog( wxInitDialogEvent& aEvent ) void PANEL_SYMBOL_CHOOSER::FinishSetup()
{ {
if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
{
auto horizPixelsFromDU =
[&]( int x ) -> int
{
wxSize sz( x, 0 );
return GetParent()->ConvertDialogToPixels( sz ).x;
};
EESCHEMA_SETTINGS::PANEL_SYM_CHOOSER& panelCfg = cfg->m_SymChooserPanel;
int w = panelCfg.width > 40 ? panelCfg.width : horizPixelsFromDU( 440 );
int h = panelCfg.height > 40 ? panelCfg.height : horizPixelsFromDU( 340 );
GetParent()->SetSize( wxSize( w, h ) );
GetParent()->Layout();
// We specify the width of the right window (m_symbol_view_panel), because specify
// the width of the left window does not work as expected when SetSashGravity() is called
if( panelCfg.sash_pos_h < 0 )
panelCfg.sash_pos_h = horizPixelsFromDU( 220 );
if( panelCfg.sash_pos_v < 0 )
panelCfg.sash_pos_v = horizPixelsFromDU( 230 );
m_hsplitter->SetSashPosition( panelCfg.sash_pos_h );
if( m_vsplitter )
m_vsplitter->SetSashPosition( panelCfg.sash_pos_v );
m_adapter->SetSortMode( (LIB_TREE_MODEL_ADAPTER::SORT_MODE) panelCfg.sort_mode );
}
if( m_fp_preview && m_fp_preview->IsInitialized() ) if( m_fp_preview && m_fp_preview->IsInitialized() )
{ {
// This hides the GAL panel and shows the status label // This hides the GAL panel and shows the status label
@ -342,11 +387,11 @@ void DIALOG_CHOOSE_SYMBOL::OnInitDialog( wxInitDialogEvent& aEvent )
} }
if( m_fp_sel_ctrl ) if( m_fp_sel_ctrl )
m_fp_sel_ctrl->Load( Kiway(), Prj() ); m_fp_sel_ctrl->Load( m_frame->Kiway(), m_frame->Prj() );
} }
void DIALOG_CHOOSE_SYMBOL::OnCharHook( wxKeyEvent& e ) void PANEL_SYMBOL_CHOOSER::OnCharHook( wxKeyEvent& e )
{ {
if( m_details && e.GetKeyCode() == 'C' && e.ControlDown() && if( m_details && e.GetKeyCode() == 'C' && e.ControlDown() &&
!e.AltDown() && !e.ShiftDown() && !e.MetaDown() ) !e.AltDown() && !e.ShiftDown() && !e.MetaDown() )
@ -368,42 +413,39 @@ void DIALOG_CHOOSE_SYMBOL::OnCharHook( wxKeyEvent& e )
} }
LIB_ID DIALOG_CHOOSE_SYMBOL::GetSelectedLibId( int* aUnit ) const void PANEL_SYMBOL_CHOOSER::SetPreselect( const LIB_ID& aPreselect )
{
m_adapter->SetPreselectNode( aPreselect, 0 );
}
LIB_ID PANEL_SYMBOL_CHOOSER::GetSelectedLibId( int* aUnit ) const
{ {
return m_tree->GetSelectedLibId( aUnit ); return m_tree->GetSelectedLibId( aUnit );
} }
void DIALOG_CHOOSE_SYMBOL::OnUseBrowser( wxCommandEvent& aEvent ) void PANEL_SYMBOL_CHOOSER::OnCloseTimer( wxTimerEvent& aEvent )
{ {
m_external_browser_requested = true; // Hack because of eaten MouseUp event. See PANEL_SYMBOL_CHOOSER::OnComponentSelected
// for the beginning of this spaghetti noodle.
wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) ); wxMouseState state = wxGetMouseState();
}
void DIALOG_CHOOSE_SYMBOL::OnCloseTimer( wxTimerEvent& aEvent )
{
// Hack handler because of eaten MouseUp event. See
// DIALOG_CHOOSE_SYMBOL::OnComponentSelected for the beginning
// of this spaghetti noodle.
auto state = wxGetMouseState();
if( state.LeftIsDown() ) if( state.LeftIsDown() )
{ {
// Mouse hasn't been raised yet, so fire the timer again. Otherwise the // Mouse hasn't been raised yet, so fire the timer again. Otherwise the
// purpose of this timer is defeated. // purpose of this timer is defeated.
m_dbl_click_timer->StartOnce( DIALOG_CHOOSE_SYMBOL::DblClickDelay ); m_dbl_click_timer->StartOnce( PANEL_SYMBOL_CHOOSER::DblClickDelay );
} }
else else
{ {
wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) ); m_closeHandler();
} }
} }
void DIALOG_CHOOSE_SYMBOL::ShowFootprintFor( LIB_ID const& aLibId ) void PANEL_SYMBOL_CHOOSER::ShowFootprintFor( LIB_ID const& aLibId )
{ {
if( !m_fp_preview || !m_fp_preview->IsInitialized() ) if( !m_fp_preview || !m_fp_preview->IsInitialized() )
return; return;
@ -412,7 +454,7 @@ void DIALOG_CHOOSE_SYMBOL::ShowFootprintFor( LIB_ID const& aLibId )
try try
{ {
symbol = PROJECT_SCH::SchSymbolLibTable( &Prj() )->LoadSymbol( aLibId ); symbol = PROJECT_SCH::SchSymbolLibTable( &m_frame->Prj() )->LoadSymbol( aLibId );
} }
catch( const IO_ERROR& ioe ) catch( const IO_ERROR& ioe )
{ {
@ -432,7 +474,7 @@ void DIALOG_CHOOSE_SYMBOL::ShowFootprintFor( LIB_ID const& aLibId )
} }
void DIALOG_CHOOSE_SYMBOL::ShowFootprint( wxString const& aName ) void PANEL_SYMBOL_CHOOSER::ShowFootprint( wxString const& aName )
{ {
if( !m_fp_preview || !m_fp_preview->IsInitialized() ) if( !m_fp_preview || !m_fp_preview->IsInitialized() )
return; return;
@ -458,7 +500,7 @@ void DIALOG_CHOOSE_SYMBOL::ShowFootprint( wxString const& aName )
} }
void DIALOG_CHOOSE_SYMBOL::PopulateFootprintSelector( LIB_ID const& aLibId ) void PANEL_SYMBOL_CHOOSER::PopulateFootprintSelector( LIB_ID const& aLibId )
{ {
if( !m_fp_sel_ctrl ) if( !m_fp_sel_ctrl )
return; return;
@ -471,7 +513,7 @@ void DIALOG_CHOOSE_SYMBOL::PopulateFootprintSelector( LIB_ID const& aLibId )
{ {
try try
{ {
symbol = PROJECT_SCH::SchSymbolLibTable( &Prj() )->LoadSymbol( aLibId ); symbol = PROJECT_SCH::SchSymbolLibTable( &m_frame->Prj() )->LoadSymbol( aLibId );
} }
catch( const IO_ERROR& ioe ) catch( const IO_ERROR& ioe )
{ {
@ -508,7 +550,7 @@ void DIALOG_CHOOSE_SYMBOL::PopulateFootprintSelector( LIB_ID const& aLibId )
} }
void DIALOG_CHOOSE_SYMBOL::OnFootprintSelected( wxCommandEvent& aEvent ) void PANEL_SYMBOL_CHOOSER::OnFootprintSelected( wxCommandEvent& aEvent )
{ {
m_fp_override = aEvent.GetString(); m_fp_override = aEvent.GetString();
@ -523,7 +565,7 @@ void DIALOG_CHOOSE_SYMBOL::OnFootprintSelected( wxCommandEvent& aEvent )
} }
void DIALOG_CHOOSE_SYMBOL::OnComponentPreselected( wxCommandEvent& aEvent ) void PANEL_SYMBOL_CHOOSER::OnComponentPreselected( wxCommandEvent& aEvent )
{ {
LIB_TREE_NODE* node = m_tree->GetCurrentTreeNode(); LIB_TREE_NODE* node = m_tree->GetCurrentTreeNode();
@ -550,7 +592,7 @@ void DIALOG_CHOOSE_SYMBOL::OnComponentPreselected( wxCommandEvent& aEvent )
} }
void DIALOG_CHOOSE_SYMBOL::OnComponentSelected( wxCommandEvent& aEvent ) void PANEL_SYMBOL_CHOOSER::OnComponentSelected( wxCommandEvent& aEvent )
{ {
if( m_tree->GetSelectedLibId().IsValid() ) if( m_tree->GetSelectedLibId().IsValid() )
{ {
@ -564,20 +606,8 @@ void DIALOG_CHOOSE_SYMBOL::OnComponentSelected( wxCommandEvent& aEvent )
// possible (docs are vague). To get around this, we use a one-shot // possible (docs are vague). To get around this, we use a one-shot
// timer to schedule the dialog close. // timer to schedule the dialog close.
// //
// See DIALOG_CHOOSE_SYMBOL::OnCloseTimer for the other end of this // See PANEL_SYMBOL_CHOOSER::OnCloseTimer for the other end of this
// spaghetti noodle. // spaghetti noodle.
m_dbl_click_timer->StartOnce( DIALOG_CHOOSE_SYMBOL::DblClickDelay ); m_dbl_click_timer->StartOnce( PANEL_SYMBOL_CHOOSER::DblClickDelay );
} }
} }
bool DIALOG_CHOOSE_SYMBOL::GetUseAllUnits() const
{
return m_useUnits->GetValue();
}
bool DIALOG_CHOOSE_SYMBOL::GetKeepSymbol() const
{
return m_keepSymbol->GetValue();
}

View File

@ -0,0 +1,162 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2014 Henner Zeller <h.zeller@acm.org>
* Copyright (C) 2014-2023 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
*/
#ifndef PANEL_SYMBOL_CHOOSER_H
#define PANEL_SYMBOL_CHOOSER_H
#include <widgets/lib_tree.h>
#include <symbol_tree_model_adapter.h>
#include <footprint_info.h>
#include <widgets/html_window.h>
class wxPanel;
class wxTimer;
class wxSplitterWindow;
class SYMBOL_PREVIEW_WIDGET;
class FOOTPRINT_PREVIEW_WIDGET;
class FOOTPRINT_SELECT_WIDGET;
class SCH_BASE_FRAME;
struct PICKED_SYMBOL;
class PANEL_SYMBOL_CHOOSER : public wxPanel
{
public:
/**
* Create dialog to choose symbol.
*
* @param aFrame the parent frame (usually a SCH_EDIT_FRAME or SYMBOL_CHOOSER_FRAME)
* @param aParent the parent window (usually a DIALOG_SHIM or SYMBOL_CHOOSER_FRAME)
* @param aAllowFieldEdits if false, all functions that allow the user to edit fields
* (currently just footprint selection) will not be available.
* @param aShowFootprints if false, all footprint preview and selection features are
* disabled. This forces aAllowFieldEdits false too.
* @param aCloseHandler a handler to be called on double-click of a footprint
*/
PANEL_SYMBOL_CHOOSER( SCH_BASE_FRAME* aFrame, wxWindow* aParent,
const SYMBOL_LIBRARY_FILTER* aFilter,
std::vector<PICKED_SYMBOL>& aHistoryList,
bool aAllowFieldEdits, bool aShowFootprints,
std::function<void()> aCloseHandler );
~PANEL_SYMBOL_CHOOSER();
void FinishSetup();
void SetPreselect( const LIB_ID& aPreselect );
/**
* To be called after this dialog returns from ShowModal().
*
* For multi-unit symbols, if the user selects the symbol itself rather than picking
* an individual unit, 0 will be returned in aUnit.
* Beware that this is an invalid unit number - this should be replaced with whatever
* default is desired (usually 1).
*
* @param aUnit if not NULL, the selected unit is filled in here.
* @return the #LIB_ID of the symbol that has been selected.
*/
LIB_ID GetSelectedLibId( int* aUnit = nullptr ) const;
int GetItemCount() const { return m_adapter->GetItemCount(); }
wxWindow* GetFocusTarget() const { return m_tree->GetFocusTarget(); }
/**
* Get a list of fields edited by the user.
*
* @return vector of pairs; each.first = field ID, each.second = new value.
*/
std::vector<std::pair<int, wxString>> GetFields() const
{
return m_field_edits;
}
protected:
static constexpr int DblClickDelay = 100; // milliseconds
wxPanel* ConstructRightPanel( wxWindow* aParent );
void OnCharHook( wxKeyEvent& aEvt );
void OnCloseTimer( wxTimerEvent& aEvent );
void OnFootprintSelected( wxCommandEvent& aEvent );
void OnComponentPreselected( wxCommandEvent& aEvent );
/**
* Handle the selection of an item. This is called when either the search box or the tree
* receive an Enter, or the tree receives a double click.
* If the item selected is a category, it is expanded or collapsed; if it is a symbol, the
* symbol is picked.
*/
void OnComponentSelected( wxCommandEvent& aEvent );
/**
* Look up the footprint for a given symbol specified in the #LIB_ID and display it.
*/
void ShowFootprintFor( const LIB_ID& aLibId );
/**
* Display the given footprint by name.
*/
void ShowFootprint( const wxString& aFootprint );
/**
* Populate the footprint selector for a given alias.
*
* @param aLibId the #LIB_ID of the selection or invalid to clear.
*/
void PopulateFootprintSelector( const LIB_ID& aLibId );
public:
static std::mutex g_Mutex;
protected:
static wxString g_symbolSearchString;
static wxString g_powerSearchString;
wxTimer* m_dbl_click_timer;
SYMBOL_PREVIEW_WIDGET* m_symbol_preview;
wxSplitterWindow* m_hsplitter;
wxSplitterWindow* m_vsplitter;
wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER> m_adapter;
FOOTPRINT_SELECT_WIDGET* m_fp_sel_ctrl;
FOOTPRINT_PREVIEW_WIDGET* m_fp_preview;
LIB_TREE* m_tree;
HTML_WINDOW* m_details;
SCH_BASE_FRAME* m_frame;
std::function<void()> m_closeHandler;
bool m_showPower;
bool m_allow_field_edits;
bool m_show_footprints;
wxString m_fp_override;
std::vector<std::pair<int, wxString>> m_field_edits;
};
#endif /* PANEL_SYMBOL_CHOOSER_H */

View File

@ -57,7 +57,9 @@ using KIGFX::COLOR4D;
using KIGFX::RENDER_SETTINGS; using KIGFX::RENDER_SETTINGS;
#define LIB_EDIT_FRAME_NAME wxT( "LibeditFrame" ) #define LIB_EDIT_FRAME_NAME wxT( "LibeditFrame" )
#define LIB_VIEW_FRAME_NAME wxT( "ViewlibFrame" )
#define SCH_EDIT_FRAME_NAME wxT( "SchematicFrame" ) #define SCH_EDIT_FRAME_NAME wxT( "SchematicFrame" )
#define SYMBOL_CHOOSER_FRAME_NAME wxT( "SymbolChooserFrame" )
#define PL_EDITOR_FRAME_NAME wxT( "PlEditorFrame" ) #define PL_EDITOR_FRAME_NAME wxT( "PlEditorFrame" )
#define FOOTPRINT_WIZARD_FRAME_NAME wxT( "FootprintWizard" ) #define FOOTPRINT_WIZARD_FRAME_NAME wxT( "FootprintWizard" )
#define FOOTPRINT_CHOOSER_FRAME_NAME wxT( "FootprintChooserFrame" ) #define FOOTPRINT_CHOOSER_FRAME_NAME wxT( "FootprintChooserFrame" )

View File

@ -34,7 +34,7 @@ enum FRAME_T
FRAME_SCH = 0, FRAME_SCH = 0,
FRAME_SCH_SYMBOL_EDITOR, FRAME_SCH_SYMBOL_EDITOR,
FRAME_SCH_VIEWER, FRAME_SCH_VIEWER,
FRAME_SCH_VIEWER_MODAL, FRAME_SYMBOL_CHOOSER,
FRAME_SIMULATOR, FRAME_SIMULATOR,
FRAME_PCB_EDITOR, FRAME_PCB_EDITOR,

View File

@ -38,7 +38,7 @@ DIALOG_FOOTPRINT_CHOOSER::DIALOG_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aParent,
m_chooserPanel = new PANEL_FOOTPRINT_CHOOSER( aParent, this, aFootprintHistoryList, m_chooserPanel = new PANEL_FOOTPRINT_CHOOSER( aParent, this, aFootprintHistoryList,
[this]() [this]()
{ {
EndQuasiModal( wxID_OK ); EndModal( wxID_OK );
} ); } );
sizer->Add( m_chooserPanel, 1, wxEXPAND, 5 ); sizer->Add( m_chooserPanel, 1, wxEXPAND, 5 );

View File

@ -41,7 +41,7 @@ static void AddFootprintToHistory( const wxString& aName )
for( int ii = s_FootprintHistoryList.GetCount() - 1; ii >= 0; --ii ) for( int ii = s_FootprintHistoryList.GetCount() - 1; ii >= 0; --ii )
{ {
if( s_FootprintHistoryList[ ii ] == aName ) if( s_FootprintHistoryList[ ii ] == aName )
s_FootprintHistoryList.RemoveAt((size_t) ii ); s_FootprintHistoryList.RemoveAt( (size_t) ii );
} }
// Add the new name at the beginning of the history list // Add the new name at the beginning of the history list

View File

@ -188,7 +188,7 @@ FOOTPRINT* PCB_BASE_FRAME::SelectFootprintFromLibrary( LIB_ID aPreselect )
DIALOG_FOOTPRINT_CHOOSER dialog( this, aPreselect, s_FootprintHistoryList ); DIALOG_FOOTPRINT_CHOOSER dialog( this, aPreselect, s_FootprintHistoryList );
if( dialog.ShowQuasiModal() == wxID_CANCEL ) if( dialog.ShowModal() == wxID_CANCEL )
return nullptr; return nullptr;
fpid = dialog.GetSelectedLibId(); fpid = dialog.GetSelectedLibId();

View File

@ -107,6 +107,7 @@
#include <core/profile.h> #include <core/profile.h>
#include <view/wx_view_controls.h> #include <view/wx_view_controls.h>
#include <footprint_viewer_frame.h> #include <footprint_viewer_frame.h>
#include <footprint_chooser_frame.h>
#include <action_plugin.h> #include <action_plugin.h>
#include <pcbnew_scripting_helpers.h> #include <pcbnew_scripting_helpers.h>
@ -1054,9 +1055,11 @@ bool PCB_EDIT_FRAME::canCloseWindow( wxCloseEvent& aEvent )
if( fpViewer && !fpViewer->Close() ) // Can close footprint viewer? if( fpViewer && !fpViewer->Close() ) // Can close footprint viewer?
return false; return false;
fpViewer = (FOOTPRINT_VIEWER_FRAME*) Kiway().Player( FRAME_FOOTPRINT_CHOOSER, false ); // FOOTPRINT_CHOOSER_FRAME is always modal so this shouldn't come up, but better safe than
// sorry.
auto* chooser = (FOOTPRINT_CHOOSER_FRAME*) Kiway().Player( FRAME_FOOTPRINT_CHOOSER, false );
if( fpViewer && !fpViewer->Close() ) // Can close modal footprint viewer? if( chooser && !chooser->Close() ) // Can close footprint chooser?
return false; return false;
} }
else else

View File

@ -89,25 +89,29 @@ PANEL_FOOTPRINT_CHOOSER::PANEL_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aFrame, wxTopL
adapter->AddLibraries( aFrame ); adapter->AddLibraries( aFrame );
// -------------------------------------------------------------------------------------
// Construct the actual dialog
//
wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL ); wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
HTML_WINDOW* details = nullptr; HTML_WINDOW* details = nullptr;
m_vsplitter = new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_vsplitter = new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxSP_LIVE_UPDATE | wxSP_3DSASH ); wxSP_LIVE_UPDATE | wxSP_NOBORDER | wxSP_3DSASH );
m_hsplitter = new wxSplitterWindow( m_vsplitter, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_hsplitter = new wxSplitterWindow( m_vsplitter, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxSP_LIVE_UPDATE | wxSP_3DSASH ); wxSP_LIVE_UPDATE | wxSP_NOBORDER | wxSP_3DSASH );
//Avoid the splitter window being assigned as the Parent to additional windows //Avoid the splitter window being assigned as the Parent to additional windows
m_vsplitter->SetExtraStyle( wxWS_EX_TRANSIENT );
m_hsplitter->SetExtraStyle( wxWS_EX_TRANSIENT ); m_hsplitter->SetExtraStyle( wxWS_EX_TRANSIENT );
auto detailsPanel = new wxPanel( m_vsplitter ); auto detailsPanel = new wxPanel( m_vsplitter );
auto detailsSizer = new wxBoxSizer( wxVERTICAL ); auto detailsSizer = new wxBoxSizer( wxVERTICAL );
detailsPanel->SetSizer( detailsSizer ); detailsPanel->SetSizer( detailsSizer );
details = new HTML_WINDOW( detailsPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, details = new HTML_WINDOW( detailsPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize );
wxHW_SCROLLBAR_AUTO ); detailsSizer->Add( details, 1, wxEXPAND, 5 );
detailsSizer->Add( details, 1, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 );
detailsPanel->Layout(); detailsPanel->Layout();
detailsSizer->Fit( detailsPanel ); detailsSizer->Fit( detailsPanel );
@ -115,7 +119,7 @@ PANEL_FOOTPRINT_CHOOSER::PANEL_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aFrame, wxTopL
m_vsplitter->SetMinimumPaneSize( 20 ); m_vsplitter->SetMinimumPaneSize( 20 );
m_vsplitter->SplitHorizontally( m_hsplitter, detailsPanel ); m_vsplitter->SplitHorizontally( m_hsplitter, detailsPanel );
sizer->Add( m_vsplitter, 1, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 ); sizer->Add( m_vsplitter, 1, wxEXPAND, 5 );
m_tree = new LIB_TREE( m_hsplitter, wxT( "footprints" ), fpTable, m_adapter, m_tree = new LIB_TREE( m_hsplitter, wxT( "footprints" ), fpTable, m_adapter,
LIB_TREE::FLAGS::ALL_WIDGETS, details ); LIB_TREE::FLAGS::ALL_WIDGETS, details );
@ -128,7 +132,7 @@ PANEL_FOOTPRINT_CHOOSER::PANEL_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aFrame, wxTopL
m_preview_ctrl = new FOOTPRINT_PREVIEW_WIDGET( rightPanel, m_frame->Kiway() ); m_preview_ctrl = new FOOTPRINT_PREVIEW_WIDGET( rightPanel, m_frame->Kiway() );
m_preview_ctrl->SetUserUnits( m_frame->GetUserUnits() ); m_preview_ctrl->SetUserUnits( m_frame->GetUserUnits() );
rightPanelSizer->Add( m_preview_ctrl, 1, wxEXPAND | wxTOP | wxRIGHT, 5 ); rightPanelSizer->Add( m_preview_ctrl, 1, wxEXPAND, 5 );
rightPanel->SetSizer( rightPanelSizer ); rightPanel->SetSizer( rightPanelSizer );
rightPanel->Layout(); rightPanel->Layout();
@ -190,8 +194,8 @@ void PANEL_FOOTPRINT_CHOOSER::FinishSetup()
PCBNEW_SETTINGS::FOOTPRINT_CHOOSER& cfg = settings->m_FootprintChooser; PCBNEW_SETTINGS::FOOTPRINT_CHOOSER& cfg = settings->m_FootprintChooser;
int w = cfg.width < 0 ? horizPixelsFromDU( 440 ) : cfg.width; int w = cfg.width < 40 ? horizPixelsFromDU( 440 ) : cfg.width;
int h = cfg.height < 0 ? horizPixelsFromDU( 340 ) : cfg.height; int h = cfg.height < 40 ? horizPixelsFromDU( 340 ) : cfg.height;
GetParent()->SetSize( wxSize( w, h ) ); GetParent()->SetSize( wxSize( w, h ) );
GetParent()->Layout(); GetParent()->Layout();

View File

@ -23,7 +23,6 @@
#ifndef PANEL_FOOTPRINT_CHOOSER_H #ifndef PANEL_FOOTPRINT_CHOOSER_H
#define PANEL_FOOTPRINT_CHOOSER_H #define PANEL_FOOTPRINT_CHOOSER_H
#include "dialog_shim.h"
#include <widgets/lib_tree.h> #include <widgets/lib_tree.h>
#include <fp_tree_model_adapter.h> #include <fp_tree_model_adapter.h>
#include <footprint_info.h> #include <footprint_info.h>
@ -41,8 +40,8 @@ public:
/** /**
* Create dialog to choose component. * Create dialog to choose component.
* *
* @param aFrame the parent frame (FRAME_PCB_EDIT_FRAME or FOOTPRINT_CHOOSER_FRAME) * @param aFrame the parent frame (usually a PCB_EDIT_FRAME or FOOTPRINT_CHOOSER_FRAME)
* @param aParent the parent window (DIALOG_SHIM or FOOTPRINT_CHOOSER_FRAME) * @param aParent the parent window (usually a DIALOG_SHIM or FOOTPRINT_CHOOSER_FRAME)
* @param aCloseHandler a handler to be called on double-click of a footprint * @param aCloseHandler a handler to be called on double-click of a footprint
*/ */
PANEL_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aFrame, wxTopLevelWindow* aParent, PANEL_FOOTPRINT_CHOOSER( PCB_BASE_FRAME* aFrame, wxTopLevelWindow* aParent,
@ -66,7 +65,6 @@ public:
wxWindow* GetFocusTarget() const { return m_tree->GetFocusTarget(); } wxWindow* GetFocusTarget() const { return m_tree->GetFocusTarget(); }
protected: protected:
static constexpr int DblClickDelay = 100; // milliseconds static constexpr int DblClickDelay = 100; // milliseconds