Convert component chooser dialog over to use symbol library table.

Change all of the component tree helper objects to use LIB_IDs instead of
LIB_ALIAS pointers.  LIB_ALIAS pointers are dangerous to use because they
can be deleted in the symbol library editor while the component chooser
dialog has copies of them.  With LIB_IDs, the LIB_ALIAS pointer is found
on demand and can be guaranteed to be valid.

Update the chooser dialog to load the symbol library table instead of the
libraries defined in the project file and return a LIB_ID instead of a
LIB_ALIAS pointer.

Modify SCH_BASE_FRAME::SelectComponentFromLibrary() to handle the LIB_IDs
returned from the component chooser dialog.
This commit is contained in:
Wayne Stambaugh 2017-09-15 10:17:44 -04:00
parent 81e8d8fd89
commit 329fc18732
14 changed files with 364 additions and 209 deletions

View File

@ -107,7 +107,6 @@ CMP_TREE_NODE::CMP_TREE_NODE()
Type( INVALID ), Type( INVALID ),
IntrinsicRank( 0 ), IntrinsicRank( 0 ),
Score( kLowestDefaultScore ), Score( kLowestDefaultScore ),
Alias( nullptr ),
Unit( 0 ) Unit( 0 )
{} {}
@ -118,7 +117,7 @@ CMP_TREE_NODE_UNIT::CMP_TREE_NODE_UNIT( CMP_TREE_NODE* aParent, int aUnit )
Type = UNIT; Type = UNIT;
Unit = aUnit; Unit = aUnit;
Alias = aParent->Alias; LibId = aParent->LibId;
Name = _( "Unit" ) + " " + LIB_PART::SubReference( aUnit, false ); Name = _( "Unit" ) + " " + LIB_PART::SubReference( aUnit, false );
Desc = wxEmptyString; Desc = wxEmptyString;
@ -128,13 +127,17 @@ CMP_TREE_NODE_UNIT::CMP_TREE_NODE_UNIT( CMP_TREE_NODE* aParent, int aUnit )
} }
CMP_TREE_NODE_ALIAS::CMP_TREE_NODE_ALIAS( CMP_TREE_NODE* aParent, LIB_ALIAS* aAlias ) CMP_TREE_NODE_LIB_ID::CMP_TREE_NODE_LIB_ID( CMP_TREE_NODE* aParent, LIB_ALIAS* aAlias )
{ {
Parent = aParent; Parent = aParent;
Type = ALIAS;
Name = aAlias->GetName(); Name = aAlias->GetName();
Desc = aAlias->GetDescription(); Desc = aAlias->GetDescription();
Alias = aAlias;
// Parent node is the library nickname so set the LIB_ID library nickname.
LibId.SetLibNickname( aParent->Name );
LibId.SetLibItemName( aAlias->GetName() );
IsRoot = aAlias->IsRoot();
// Pre-normalized strings for fast case-insensitive matching // Pre-normalized strings for fast case-insensitive matching
// Search text spaces out keywords and description to penalize description // Search text spaces out keywords and description to penalize description
@ -170,7 +173,7 @@ CMP_TREE_NODE_ALIAS::CMP_TREE_NODE_ALIAS( CMP_TREE_NODE* aParent, LIB_ALIAS* aAl
} }
CMP_TREE_NODE_UNIT& CMP_TREE_NODE_ALIAS::AddUnit( int aUnit ) CMP_TREE_NODE_UNIT& CMP_TREE_NODE_LIB_ID::AddUnit( int aUnit )
{ {
CMP_TREE_NODE_UNIT* unit = new CMP_TREE_NODE_UNIT( this, aUnit ); CMP_TREE_NODE_UNIT* unit = new CMP_TREE_NODE_UNIT( this, aUnit );
Children.push_back( std::unique_ptr<CMP_TREE_NODE>( unit ) ); Children.push_back( std::unique_ptr<CMP_TREE_NODE>( unit ) );
@ -178,7 +181,7 @@ CMP_TREE_NODE_UNIT& CMP_TREE_NODE_ALIAS::AddUnit( int aUnit )
} }
void CMP_TREE_NODE_ALIAS::UpdateScore( EDA_COMBINED_MATCHER& aMatcher ) void CMP_TREE_NODE_LIB_ID::UpdateScore( EDA_COMBINED_MATCHER& aMatcher )
{ {
if( Score <= 0 ) if( Score <= 0 )
return; // Leaf nodes without scores are out of the game. return; // Leaf nodes without scores are out of the game.
@ -235,9 +238,9 @@ CMP_TREE_NODE_LIB::CMP_TREE_NODE_LIB( CMP_TREE_NODE* aParent, wxString const& aN
} }
CMP_TREE_NODE_ALIAS& CMP_TREE_NODE_LIB::AddAlias( LIB_ALIAS* aAlias ) CMP_TREE_NODE_LIB_ID& CMP_TREE_NODE_LIB::AddAlias( LIB_ALIAS* aAlias )
{ {
CMP_TREE_NODE_ALIAS* alias = new CMP_TREE_NODE_ALIAS( this, aAlias ); CMP_TREE_NODE_LIB_ID* alias = new CMP_TREE_NODE_LIB_ID( this, aAlias );
Children.push_back( std::unique_ptr<CMP_TREE_NODE>( alias ) ); Children.push_back( std::unique_ptr<CMP_TREE_NODE>( alias ) );
return *alias; return *alias;
} }

View File

@ -25,6 +25,7 @@
#include <vector> #include <vector>
#include <memory> #include <memory>
#include <wx/string.h> #include <wx/string.h>
#include <lib_id.h>
class EDA_COMBINED_MATCHER; class EDA_COMBINED_MATCHER;
@ -70,7 +71,7 @@ class LIB_ALIAS;
* - `Desc` - description of the alias, to be displayed * - `Desc` - description of the alias, to be displayed
* - `MatchName` - Name, normalized to lowercase for matching * - `MatchName` - Name, normalized to lowercase for matching
* - `SearchText` - normalized composite of keywords and description * - `SearchText` - normalized composite of keywords and description
* - `Alias` - the LIB_ALIAS* this alias or unit is from, or nullptr * - `LibId` - the #LIB_ID this alias or unit is from, or not valid
* - `Unit` - the unit number, or zero for non-units * - `Unit` - the unit number, or zero for non-units
*/ */
class CMP_TREE_NODE { class CMP_TREE_NODE {
@ -98,16 +99,15 @@ public:
wxString MatchName; ///< Normalized name for matching wxString MatchName; ///< Normalized name for matching
wxString SearchText; ///< Descriptive text to search wxString SearchText; ///< Descriptive text to search
LIB_ALIAS* Alias; ///< Actual LIB_ALIAS*, or null LIB_ID LibId; ///< LIB_ID determined by the parent library nickname and alias name.
int Unit; ///< Actual unit, or zero int Unit; ///< Actual unit, or zero
bool IsRoot; ///< Indicates if the symbol is a root symbol instead of an alias.
/** /**
* Update the score for this part. This is accumulative - it will be * Update the score for this part. This is accumulative - it will be
* called once per search term. * called once per search term.
* *
* @param aMatcher an EDA_COMBINED_MATCHER initialized with the search * @param aMatcher an EDA_COMBINED_MATCHER initialized with the search term
* term
*/ */
virtual void UpdateScore( EDA_COMBINED_MATCHER& aMatcher ) = 0; virtual void UpdateScore( EDA_COMBINED_MATCHER& aMatcher ) = 0;
@ -173,29 +173,32 @@ public:
/** /**
* Node type: alias. * Node type: #LIB_ID.
*/ */
class CMP_TREE_NODE_ALIAS: public CMP_TREE_NODE class CMP_TREE_NODE_LIB_ID: public CMP_TREE_NODE
{ {
public: public:
/** /**
* The addresses of CMP_TREE_NODEs are used as unique IDs for the * The addresses of CMP_TREE_NODEs are used as unique IDs for the
* wxDataViewModel, so don't let them be copied around. * wxDataViewModel, so don't let them be copied around.
*/ */
CMP_TREE_NODE_ALIAS( CMP_TREE_NODE_ALIAS const& _ ) = delete; CMP_TREE_NODE_LIB_ID( CMP_TREE_NODE_LIB_ID const& _ ) = delete;
void operator=( CMP_TREE_NODE_ALIAS const& _ ) = delete; void operator=( CMP_TREE_NODE_LIB_ID const& _ ) = delete;
/** /**
* Construct an alias node. * Construct a #LIB_ID node.
* *
* All fields will be populated from the LIB_ALIAS, including children * All fields will be populated from the LIB_ALIAS, including children
* (unit nodes will be generated automatically). * (unit nodes will be generated automatically). This does not keep
* the pointer to the #LIB_ALIAS object because at any time, a #LIB_ALIAS
* can be remove from a libray which will result in an invalid pointer.
* The alias must be resolved at the time of use. Anything else is a bug.
* *
* @param aParent parent node, should be a CMP_TREE_NODE_LIB * @param aParent parent node, should be a CMP_TREE_NODE_LIB
* @param aAlias LIB_ALIAS to populate the node * @param aAlias LIB_ALIAS to populate the node.
*/ */
CMP_TREE_NODE_ALIAS( CMP_TREE_NODE* aParent, LIB_ALIAS* aAlias ); CMP_TREE_NODE_LIB_ID( CMP_TREE_NODE* aParent, LIB_ALIAS* aAlias );
/** /**
@ -240,7 +243,7 @@ public:
* *
* @param aAlias LIB_ALIAS to provide data * @param aAlias LIB_ALIAS to provide data
*/ */
CMP_TREE_NODE_ALIAS& AddAlias( LIB_ALIAS* aAlias ); CMP_TREE_NODE_LIB_ID& AddAlias( LIB_ALIAS* aAlias );
virtual void UpdateScore( EDA_COMBINED_MATCHER& aMatcher ) override; virtual void UpdateScore( EDA_COMBINED_MATCHER& aMatcher ) override;
}; };

View File

@ -21,9 +21,9 @@
#include <cmp_tree_model_adapter.h> #include <cmp_tree_model_adapter.h>
#include <class_library.h>
#include <eda_pattern_match.h> #include <eda_pattern_match.h>
#include <wx/tokenzr.h> #include <wx/tokenzr.h>
#include <symbol_lib_table.h>
CMP_TREE_MODEL_ADAPTER::WIDTH_CACHE CMP_TREE_MODEL_ADAPTER::m_width_cache; CMP_TREE_MODEL_ADAPTER::WIDTH_CACHE CMP_TREE_MODEL_ADAPTER::m_width_cache;
@ -70,7 +70,7 @@ static unsigned int IntoArray( CMP_TREE_NODE const& aNode, wxDataViewItemArray&
} }
CMP_TREE_MODEL_ADAPTER::PTR CMP_TREE_MODEL_ADAPTER::Create( PART_LIBS* aLibs ) CMP_TREE_MODEL_ADAPTER::PTR CMP_TREE_MODEL_ADAPTER::Create( SYMBOL_LIB_TABLE* aLibs )
{ {
auto adapter = new CMP_TREE_MODEL_ADAPTER( aLibs ); auto adapter = new CMP_TREE_MODEL_ADAPTER( aLibs );
auto container = CMP_TREE_MODEL_ADAPTER::PTR( adapter ); auto container = CMP_TREE_MODEL_ADAPTER::PTR( adapter );
@ -78,7 +78,7 @@ CMP_TREE_MODEL_ADAPTER::PTR CMP_TREE_MODEL_ADAPTER::Create( PART_LIBS* aLibs )
} }
CMP_TREE_MODEL_ADAPTER::CMP_TREE_MODEL_ADAPTER( PART_LIBS* aLibs ) CMP_TREE_MODEL_ADAPTER::CMP_TREE_MODEL_ADAPTER( SYMBOL_LIB_TABLE* aLibs )
:m_filter( CMP_FILTER_NONE ), :m_filter( CMP_FILTER_NONE ),
m_show_units( true ), m_show_units( true ),
m_libs( aLibs ), m_libs( aLibs ),
@ -105,60 +105,68 @@ void CMP_TREE_MODEL_ADAPTER::ShowUnits( bool aShow )
} }
void CMP_TREE_MODEL_ADAPTER::SetPreselectNode( wxString const& aName, int aUnit ) void CMP_TREE_MODEL_ADAPTER::SetPreselectNode( LIB_ID const& aLibId, int aUnit )
{ {
m_preselect_name = aName; m_preselect_lib_id = aLibId;
m_preselect_unit = aUnit; m_preselect_unit = aUnit;
} }
void CMP_TREE_MODEL_ADAPTER::AddLibrary( PART_LIB& aLib ) void CMP_TREE_MODEL_ADAPTER::AddLibrary( wxString const& aLibNickname )
{ {
if( m_filter == CMP_FILTER_POWER ) bool onlyPowerSymbols = ( m_filter == CMP_FILTER_POWER );
wxArrayString aliases;
try
{ {
wxArrayString all_aliases; m_libs->EnumerateSymbolLib( aLibNickname, aliases, onlyPowerSymbols );
aLib.GetEntryTypePowerNames( all_aliases );
AddAliasList( aLib.GetName(), all_aliases, &aLib );
} }
else catch( const IO_ERROR& ioe )
{ {
std::vector<LIB_ALIAS*> all_aliases; wxLogError( wxString::Format( _( "Error occurred loading symbol library %s."
aLib.GetAliases( all_aliases ); "\n\n%s" ), aLibNickname, ioe.What() ) );
AddAliasList( aLib.GetName(), all_aliases, &aLib ); return;
} }
AddAliasList( aLibNickname, aliases );
m_tree.AssignIntrinsicRanks(); m_tree.AssignIntrinsicRanks();
} }
void CMP_TREE_MODEL_ADAPTER::AddAliasList( void CMP_TREE_MODEL_ADAPTER::AddAliasList(
wxString const& aNodeName, wxString const& aNodeName,
wxArrayString const& aAliasNameList, wxArrayString const& aAliasNameList )
PART_LIB* aOptionalLib )
{ {
std::vector<LIB_ALIAS*> alias_list; std::vector<LIB_ALIAS*> alias_list;
for( const wxString& name: aAliasNameList ) for( const wxString& name: aAliasNameList )
{ {
LIB_ALIAS* a; LIB_ALIAS* a = nullptr;
if( aOptionalLib ) try
a = aOptionalLib->FindAlias( name ); {
else a = m_libs->LoadSymbol( aNodeName, name );
a = m_libs->FindLibraryAlias( LIB_ID( wxEmptyString, name ), wxEmptyString ); }
catch( const IO_ERROR& ioe )
{
wxLogError( wxString::Format( _( "Error occurred loading symbol %s from library %s."
"\n\n%s" ), name, aNodeName, ioe.What() ) );
continue;
}
if( a ) if( a )
alias_list.push_back( a ); alias_list.push_back( a );
} }
AddAliasList( aNodeName, alias_list, aOptionalLib ); AddAliasList( aNodeName, alias_list );
} }
void CMP_TREE_MODEL_ADAPTER::AddAliasList( void CMP_TREE_MODEL_ADAPTER::AddAliasList(
wxString const& aNodeName, wxString const& aNodeName,
std::vector<LIB_ALIAS*> const& aAliasList, std::vector<LIB_ALIAS*> const& aAliasList )
PART_LIB* aOptionalLib )
{ {
auto& lib_node = m_tree.AddLib( aNodeName ); auto& lib_node = m_tree.AddLib( aNodeName );
@ -213,10 +221,16 @@ void CMP_TREE_MODEL_ADAPTER::AttachTo( wxDataViewCtrl* aDataViewCtrl )
} }
LIB_ALIAS* CMP_TREE_MODEL_ADAPTER::GetAliasFor( wxDataViewItem aSelection ) const LIB_ID CMP_TREE_MODEL_ADAPTER::GetAliasFor( wxDataViewItem aSelection ) const
{ {
auto node = ToNode( aSelection ); auto node = ToNode( aSelection );
return node ? node->Alias : nullptr;
LIB_ID emptyId;
if( !node )
return emptyId;
return node->LibId;
} }
@ -324,7 +338,7 @@ bool CMP_TREE_MODEL_ADAPTER::GetAttr(
return false; return false;
} }
if( node->Alias && !node->Alias->IsRoot() && aCol == 0 ) if( !node->IsRoot && aCol == 0 )
{ {
// Names of non-root aliases are italicized // Names of non-root aliases are italicized
aAttr.SetItalic( true ); aAttr.SetItalic( true );
@ -432,16 +446,16 @@ bool CMP_TREE_MODEL_ADAPTER::ShowResults()
bool CMP_TREE_MODEL_ADAPTER::ShowPreselect() bool CMP_TREE_MODEL_ADAPTER::ShowPreselect()
{ {
if( m_preselect_name == wxEmptyString ) if( !m_preselect_lib_id.IsValid() )
return false; return false;
return FindAndExpand( m_tree, return FindAndExpand( m_tree,
[&]( CMP_TREE_NODE const* n ) [&]( CMP_TREE_NODE const* n )
{ {
if( n->Type == CMP_TREE_NODE::ALIAS && ( n->Children.empty() || !m_preselect_unit ) ) if( n->Type == CMP_TREE_NODE::ALIAS && ( n->Children.empty() || !m_preselect_unit ) )
return m_preselect_name == n->Name; return m_preselect_lib_id == n->LibId;
else if( n->Type == CMP_TREE_NODE::UNIT && m_preselect_unit ) else if( n->Type == CMP_TREE_NODE::UNIT && m_preselect_unit )
return m_preselect_name == n->Parent->Name && m_preselect_unit == n->Unit; return m_preselect_lib_id == n->Parent->LibId && m_preselect_unit == n->Unit;
else else
return false; return false;
} ); } );

View File

@ -22,6 +22,8 @@
#ifndef _CMP_TREE_MODEL_ADAPTER_H #ifndef _CMP_TREE_MODEL_ADAPTER_H
#define _CMP_TREE_MODEL_ADAPTER_H #define _CMP_TREE_MODEL_ADAPTER_H
#include <lib_id.h>
#include <cmp_tree_model.h> #include <cmp_tree_model.h>
#include <wx/hashmap.h> #include <wx/hashmap.h>
@ -29,9 +31,7 @@
#include <vector> #include <vector>
#include <functional> #include <functional>
class LIB_ALIAS; class SYMBOL_LIB_TABLE;
class PART_LIB;
class PART_LIBS;
/** /**
@ -112,7 +112,7 @@ public:
* *
* @param aLibs library set from which parts will be loaded * @param aLibs library set from which parts will be loaded
*/ */
static PTR Create( PART_LIBS* aLibs ); static PTR Create( SYMBOL_LIB_TABLE* aLibs );
/** /**
* This enum allows a selective filtering of components to list * This enum allows a selective filtering of components to list
@ -142,18 +142,18 @@ public:
* Set the component name to be selected if there are no search results. * Set the component name to be selected if there are no search results.
* May be set at any time; updates at the next UpdateSearchString(). * May be set at any time; updates at the next UpdateSearchString().
* *
* @param aName component name to be selected * @param aLibId symbol #LIB_ID to be selected
* @param aUnit unit to be selected, if > 0 (0 selects the alias itself) * @param aUnit unit to be selected, if > 0 (0 selects the alias itself)
*/ */
void SetPreselectNode( wxString const& aName, int aUnit ); void SetPreselectNode( LIB_ID const& aLibId, int aUnit );
/** /**
* Add all the components and their aliases in this library. To be called * Add all the components and their aliases in this library. To be called
* in the setup phase. * in the setup phase.
* *
* @param aLib reference to a library * @param aLibNickname reference to a symbol library nickname
*/ */
void AddLibrary( PART_LIB& aLib ); void AddLibrary( wxString const& aLibNickname );
/** /**
* Add the given list of components, by name. To be called in the setup * Add the given list of components, by name. To be called in the setup
@ -161,12 +161,10 @@ public:
* *
* @param aNodeName the parent node the components will appear under * @param aNodeName the parent node the components will appear under
* @param aAliasNameList list of alias names * @param aAliasNameList list of alias names
* @param aOptionalLib library to look up names in (null = global)
*/ */
void AddAliasList( void AddAliasList(
wxString const& aNodeName, wxString const& aNodeName,
wxArrayString const& aAliasNameList, wxArrayString const& aAliasNameList );
PART_LIB* aOptionalLib = nullptr );
/** /**
* Add the given list of components by alias. To be called in the setup * Add the given list of components by alias. To be called in the setup
@ -174,12 +172,10 @@ public:
* *
* @param aNodeName the parent node the components will appear under * @param aNodeName the parent node the components will appear under
* @param aAliasList list of aliases * @param aAliasList list of aliases
* @param aOptionalLib library to look up names in (null = global)
*/ */
void AddAliasList( void AddAliasList(
wxString const& aNodeName, wxString const& aNodeName,
std::vector<LIB_ALIAS*> const& aAliasList, std::vector<LIB_ALIAS*> const& aAliasList );
PART_LIB* aOptionalLib = nullptr );
/** /**
* Set the search string provided by the user. * Set the search string provided by the user.
@ -204,7 +200,7 @@ public:
* *
* @return alias, or nullptr if none is selected * @return alias, or nullptr if none is selected
*/ */
LIB_ALIAS* GetAliasFor( wxDataViewItem aSelection ) const; LIB_ID GetAliasFor( wxDataViewItem aSelection ) const;
/** /**
* Return the unit for the given item. * Return the unit for the given item.
@ -227,7 +223,7 @@ protected:
/** /**
* Constructor; takes a set of libraries to be included in the search. * Constructor; takes a set of libraries to be included in the search.
*/ */
CMP_TREE_MODEL_ADAPTER( PART_LIBS* aLibs ); CMP_TREE_MODEL_ADAPTER( SYMBOL_LIB_TABLE* aLibs );
/** /**
* Check whether a container has columns too * Check whether a container has columns too
@ -305,8 +301,8 @@ protected:
private: private:
CMP_FILTER_TYPE m_filter; CMP_FILTER_TYPE m_filter;
bool m_show_units; bool m_show_units;
PART_LIBS* m_libs; SYMBOL_LIB_TABLE* m_libs;
wxString m_preselect_name; LIB_ID m_preselect_lib_id;
int m_preselect_unit; int m_preselect_unit;
CMP_TREE_NODE_ROOT m_tree; CMP_TREE_NODE_ROOT m_tree;

View File

@ -40,6 +40,7 @@
#include <class_library.h> #include <class_library.h>
#include <sch_base_frame.h> #include <sch_base_frame.h>
#include <template_fieldnames.h> #include <template_fieldnames.h>
#include <symbol_lib_table.h>
#include <widgets/component_tree.h> #include <widgets/component_tree.h>
#include <widgets/footprint_preview_widget.h> #include <widgets/footprint_preview_widget.h>
#include <widgets/footprint_select_widget.h> #include <widgets/footprint_select_widget.h>
@ -63,7 +64,7 @@ DIALOG_CHOOSE_COMPONENT::DIALOG_CHOOSE_COMPONENT( SCH_BASE_FRAME* aParent, const
auto splitter = new wxSplitterWindow( auto splitter = new wxSplitterWindow(
this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_LIVE_UPDATE ); this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_LIVE_UPDATE );
m_tree = new COMPONENT_TREE( splitter, aAdapter ); m_tree = new COMPONENT_TREE( splitter, Prj().SchSymbolLibTable(), aAdapter );
auto right_panel = ConstructRightPanel( splitter ); auto right_panel = ConstructRightPanel( splitter );
auto buttons = new wxStdDialogButtonSizer(); auto buttons = new wxStdDialogButtonSizer();
m_dbl_click_timer = new wxTimer( this ); m_dbl_click_timer = new wxTimer( this );
@ -153,9 +154,9 @@ void DIALOG_CHOOSE_COMPONENT::OnInitDialog( wxInitDialogEvent& aEvent )
} }
LIB_ALIAS* DIALOG_CHOOSE_COMPONENT::GetSelectedAlias( int* aUnit ) const LIB_ID DIALOG_CHOOSE_COMPONENT::GetSelectedLibId( int* aUnit ) const
{ {
return m_tree->GetSelectedAlias( aUnit ); return m_tree->GetSelectedLibId( aUnit );
} }
@ -187,12 +188,32 @@ void DIALOG_CHOOSE_COMPONENT::OnSchViewDClick( wxMouseEvent& aEvent )
} }
void DIALOG_CHOOSE_COMPONENT::ShowFootprintFor( LIB_ALIAS* aAlias ) void DIALOG_CHOOSE_COMPONENT::ShowFootprintFor( LIB_ID const& aLibId )
{ {
if( !m_fp_view_ctrl->IsInitialized() ) if( !m_fp_view_ctrl->IsInitialized() )
return; return;
LIB_FIELD* fp_field = aAlias->GetPart()->GetField( FOOTPRINT ); LIB_ALIAS* alias = nullptr;
try
{
alias = Prj().SchSymbolLibTable()->LoadSymbol( aLibId );
}
catch( const IO_ERROR& ioe )
{
wxLogError( wxString::Format( _( "Error occurred loading symbol %s from library %s."
"\n\n%s" ),
aLibId.GetLibItemName().wx_str(),
aLibId.GetLibNickname().wx_str(),
ioe.What() ) );
}
if( alias == nullptr )
{
return;
}
LIB_FIELD* fp_field = alias->GetPart()->GetField( FOOTPRINT );
wxString fp_name = fp_field ? fp_field->GetFullText() : wxString( "" ); wxString fp_name = fp_field ? fp_field->GetFullText() : wxString( "" );
ShowFootprint( fp_name ); ShowFootprint( fp_name );
@ -207,32 +228,54 @@ void DIALOG_CHOOSE_COMPONENT::ShowFootprint( wxString const& aName )
} }
else else
{ {
LIB_ID lib_id( aName ); LIB_ID lib_id;
if( lib_id.Parse( aName ) == -1 && lib_id.IsValid() )
{
m_fp_view_ctrl->ClearStatus(); m_fp_view_ctrl->ClearStatus();
m_fp_view_ctrl->CacheFootprint( lib_id ); m_fp_view_ctrl->CacheFootprint( lib_id );
m_fp_view_ctrl->DisplayFootprint( lib_id ); m_fp_view_ctrl->DisplayFootprint( lib_id );
} }
else
{
m_fp_view_ctrl->SetStatusText( _( "Invalid footprint specified" ) );
}
}
} }
void DIALOG_CHOOSE_COMPONENT::PopulateFootprintSelector( LIB_ALIAS* aAlias ) void DIALOG_CHOOSE_COMPONENT::PopulateFootprintSelector( LIB_ID const& aLibId )
{ {
if( !m_fp_sel_ctrl ) if( !m_fp_sel_ctrl )
return; return;
m_fp_sel_ctrl->ClearFilters(); m_fp_sel_ctrl->ClearFilters();
if( aAlias ) LIB_ALIAS* alias = nullptr;
try
{
alias = Prj().SchSymbolLibTable()->LoadSymbol( aLibId );
}
catch( const IO_ERROR& ioe )
{
wxLogError( wxString::Format( _( "Error occurred loading symbol %s from library %s."
"\n\n%s" ),
aLibId.GetLibItemName().wx_str(),
aLibId.GetLibNickname().wx_str(),
ioe.What() ) );
}
if( alias != nullptr )
{ {
LIB_PINS temp_pins; LIB_PINS temp_pins;
LIB_FIELD* fp_field = aAlias->GetPart()->GetField( FOOTPRINT ); LIB_FIELD* fp_field = alias->GetPart()->GetField( FOOTPRINT );
wxString fp_name = fp_field ? fp_field->GetFullText() : wxString( "" ); wxString fp_name = fp_field ? fp_field->GetFullText() : wxString( "" );
aAlias->GetPart()->GetPins( temp_pins ); alias->GetPart()->GetPins( temp_pins );
m_fp_sel_ctrl->FilterByPinCount( temp_pins.size() ); m_fp_sel_ctrl->FilterByPinCount( temp_pins.size() );
m_fp_sel_ctrl->FilterByFootprintFilters( aAlias->GetPart()->GetFootPrints(), true ); m_fp_sel_ctrl->FilterByFootprintFilters( alias->GetPart()->GetFootPrints(), true );
m_fp_sel_ctrl->SetDefaultFootprint( fp_name ); m_fp_sel_ctrl->SetDefaultFootprint( fp_name );
m_fp_sel_ctrl->UpdateList(); m_fp_sel_ctrl->UpdateList();
m_fp_sel_ctrl->Enable(); m_fp_sel_ctrl->Enable();
@ -248,7 +291,29 @@ void DIALOG_CHOOSE_COMPONENT::PopulateFootprintSelector( LIB_ALIAS* aAlias )
void DIALOG_CHOOSE_COMPONENT::OnSchViewPaint( wxPaintEvent& aEvent ) void DIALOG_CHOOSE_COMPONENT::OnSchViewPaint( wxPaintEvent& aEvent )
{ {
int unit = 0; int unit = 0;
LIB_ALIAS* alias = m_tree->GetSelectedAlias( &unit ); LIB_ID id = m_tree->GetSelectedLibId( &unit );
if( !id.IsValid() )
return;
LIB_ALIAS* alias = nullptr;
try
{
alias = Prj().SchSymbolLibTable()->LoadSymbol( id );
}
catch( const IO_ERROR& ioe )
{
wxLogError( wxString::Format( _( "Error occurred loading symbol %s from library %s."
"\n\n%s" ),
id.GetLibItemName().wx_str(),
id.GetLibNickname().wx_str(),
ioe.What() ) );
}
if( alias == nullptr )
return;
LIB_PART* part = alias ? alias->GetPart() : nullptr; LIB_PART* part = alias ? alias->GetPart() : nullptr;
// Don't draw anything (not even the background) if we don't have // Don't draw anything (not even the background) if we don't have
@ -292,28 +357,29 @@ void DIALOG_CHOOSE_COMPONENT::OnFootprintSelected( wxCommandEvent& aEvent )
void DIALOG_CHOOSE_COMPONENT::OnComponentPreselected( wxCommandEvent& aEvent ) void DIALOG_CHOOSE_COMPONENT::OnComponentPreselected( wxCommandEvent& aEvent )
{ {
int unit = 0; int unit = 0;
LIB_ALIAS* alias = m_tree->GetSelectedAlias( &unit );
LIB_ID id = m_tree->GetSelectedLibId( &unit );
m_sch_view_ctrl->Refresh(); m_sch_view_ctrl->Refresh();
if( alias ) if( id.IsValid() )
{ {
ShowFootprintFor( alias ); ShowFootprintFor( id );
PopulateFootprintSelector( alias ); PopulateFootprintSelector( id );
} }
else else
{ {
if( m_fp_view_ctrl->IsInitialized() ) if( m_fp_view_ctrl->IsInitialized() )
m_fp_view_ctrl->SetStatusText( wxEmptyString ); m_fp_view_ctrl->SetStatusText( wxEmptyString );
PopulateFootprintSelector( nullptr ); PopulateFootprintSelector( id );
} }
} }
void DIALOG_CHOOSE_COMPONENT::OnComponentSelected( wxCommandEvent& aEvent ) void DIALOG_CHOOSE_COMPONENT::OnComponentSelected( wxCommandEvent& aEvent )
{ {
if( m_tree->GetSelectedAlias() ) if( m_tree->GetSelectedLibId().IsValid() )
{ {
// Got a selection. We can't just end the modal dialog here, because // Got a selection. We can't just end the modal dialog here, because
// wx leaks some events back to the parent window (in particular, the // wx leaks some events back to the parent window (in particular, the

View File

@ -60,14 +60,18 @@ class SCH_BASE_FRAME;
* for thorough documentation. A simple example usage follows: * for thorough documentation. A simple example usage follows:
* *
* // Create the adapter class * // Create the adapter class
* auto adapter( CMP_TREE_MODEL_ADAPTER::Create( Prj().SchLibs() ) ); * auto adapter( CMP_TREE_MODEL_ADAPTER::Create( Prj().SchSymbolLibTable() ) );
* *
* // Perform any configuration of adapter properties here * // Perform any configuration of adapter properties here
* adapter->SetPreselectNode( "TL072", 2 ); * adapter->SetPreselectNode( "LIB_NICKNAME", "SYMBO_NAME", 2 );
* *
* // Initialize model from PART_LIBs * // Initialize model from #SYMBOL_LIB_TABLE
* for( PART_LIB& lib: *libs ) * libNicknames = libs->GetLogicalLibs();
* adapter->AddLibrary( lib ); *
* for( auto nickname : libNicknames )
* {
* adapter->AddLibrary( nickname );
* }
* *
* // Create and display dialog * // Create and display dialog
* DIALOG_CHOOSE_COMPONENT dlg( this, title, adapter, 1 ); * DIALOG_CHOOSE_COMPONENT dlg( this, title, adapter, 1 );
@ -77,8 +81,8 @@ class SCH_BASE_FRAME;
* if( selected ) * if( selected )
* { * {
* int unit; * int unit;
* LIB_ALIAS* alias = dlg.GetSelectedAlias( &unit ); * #LIB_ID id = dlg.GetSelectedAlias( &unit );
* do_something( alias, unit ); * do_something( id, unit );
* } * }
* *
*/ */
@ -111,9 +115,9 @@ public:
* with whatever default is desired (usually 1). * with whatever default is desired (usually 1).
* *
* @param aUnit if not NULL, the selected unit is filled in here. * @param aUnit if not NULL, the selected unit is filled in here.
* @return the alias that has been selected, or NULL if there is none. * @return the #LIB_ID of the symbol that has been selected.
*/ */
LIB_ALIAS* GetSelectedAlias( int* aUnit = nullptr ) const; LIB_ID GetSelectedLibId( int* aUnit = nullptr ) const;
/** /**
* Get a list of fields edited by the user. * Get a list of fields edited by the user.
@ -159,21 +163,21 @@ protected:
void OnComponentSelected( wxCommandEvent& aEvent ); void OnComponentSelected( wxCommandEvent& aEvent );
/** /**
* Look up the footprint for a given alias and display it. * Look up the footprint for a given symbol specified in the #LIB_ID and display it.
*/ */
void ShowFootprintFor( LIB_ALIAS* aAlias ); void ShowFootprintFor( LIB_ID const& aLibId );
/** /**
* Display the given footprint by name. * Display the given footprint by name.
*/ */
void ShowFootprint( wxString const& aName ); void ShowFootprint( wxString const& aFootprint );
/** /**
* Populate the footprint selector for a given alias. * Populate the footprint selector for a given alias.
* *
* @param aAlias alias, or null to clear * @param aLibId the #LIB_ID of the selection or invalid to clear
*/ */
void PopulateFootprintSelector( LIB_ALIAS* aAlias ); void PopulateFootprintSelector( LIB_ID const& aLibId );
/** /**
* Display a given component into the schematic symbol preview. * Display a given component into the schematic symbol preview.

View File

@ -21,6 +21,9 @@
#include <generate_alias_info.h> #include <generate_alias_info.h>
#include <kicad_string.h> #include <kicad_string.h>
#include <template_fieldnames.h> #include <template_fieldnames.h>
#include <class_libentry.h>
#include <symbol_lib_table.h>
static const wxString DescriptionFormat = static const wxString DescriptionFormat =
"<b>__NAME__</b>" "<b>__NAME__</b>"
@ -45,13 +48,17 @@ static const wxString DatasheetLinkFormat = "<a href=\"__VALUE__\">__VALUE__</a>
class ALIAS_INFO_GENERATOR class ALIAS_INFO_GENERATOR
{ {
wxString m_html; wxString m_html;
LIB_ALIAS const * m_part; SYMBOL_LIB_TABLE* m_sym_lib_table;
LIB_ID const m_lib_id;
LIB_ALIAS* m_alias;
int m_unit; int m_unit;
public: public:
ALIAS_INFO_GENERATOR( LIB_ALIAS const * aAlias, int aUnit ) ALIAS_INFO_GENERATOR( SYMBOL_LIB_TABLE* aSymbolLibTable, LIB_ID const& aLibId, int aUnit )
: m_html( DescriptionFormat ), : m_html( DescriptionFormat ),
m_part( aAlias ), m_sym_lib_table( aSymbolLibTable ),
m_lib_id( aLibId ),
m_alias( nullptr ),
m_unit( aUnit ) m_unit( aUnit )
{ } { }
@ -59,6 +66,27 @@ public:
* Generate the HTML internally. * Generate the HTML internally.
*/ */
void GenerateHtml() void GenerateHtml()
{
wxCHECK_RET( m_sym_lib_table, "Symbol library table pointer is not valid" );
if( !m_lib_id.IsValid() )
return;
try
{
m_alias = const_cast< LIB_ALIAS* >( m_sym_lib_table->LoadSymbol( m_lib_id ) );
}
catch( const IO_ERROR& ioe )
{
wxLogError( wxString::Format( _( "Error occurred loading symbol %s from library %s."
"\n\n%s" ),
m_lib_id.GetLibItemName().wx_str(),
m_lib_id.GetLibNickname().wx_str(),
ioe.What() ) );
return;
}
if( m_alias )
{ {
SetHtmlName(); SetHtmlName();
SetHtmlAliasOf(); SetHtmlAliasOf();
@ -66,6 +94,7 @@ public:
SetHtmlKeywords(); SetHtmlKeywords();
SetHtmlFieldTable(); SetHtmlFieldTable();
} }
}
/** /**
* Return the generated HTML. * Return the generated HTML.
@ -78,13 +107,13 @@ public:
protected: protected:
void SetHtmlName() void SetHtmlName()
{ {
m_html.Replace( "__NAME__", EscapedHTML( m_part->GetName() ) ); m_html.Replace( "__NAME__", EscapedHTML( m_alias->GetName() ) );
} }
void SetHtmlAliasOf() void SetHtmlAliasOf()
{ {
if( m_part->IsRoot() ) if( m_alias->IsRoot() )
{ {
m_html.Replace( "__ALIASOF__", wxEmptyString ); m_html.Replace( "__ALIASOF__", wxEmptyString );
} }
@ -93,7 +122,7 @@ protected:
wxString root_name = _( "Unknown" ); wxString root_name = _( "Unknown" );
wxString root_desc = ""; wxString root_desc = "";
LIB_PART* root = m_part->GetPart(); LIB_PART* root = m_alias->GetPart();
LIB_ALIAS* root_alias = root ? root->GetAlias( 0 ) : nullptr; LIB_ALIAS* root_alias = root ? root->GetAlias( 0 ) : nullptr;
if( root ) if( root )
@ -111,7 +140,7 @@ protected:
void SetHtmlDesc() void SetHtmlDesc()
{ {
wxString raw_desc = m_part->GetDescription(); wxString raw_desc = m_alias->GetDescription();
m_html.Replace( "__DESC__", wxString::Format( DescFormat, EscapedHTML( raw_desc ) ) ); m_html.Replace( "__DESC__", wxString::Format( DescFormat, EscapedHTML( raw_desc ) ) );
} }
@ -119,7 +148,7 @@ protected:
void SetHtmlKeywords() void SetHtmlKeywords()
{ {
wxString keywords = m_part->GetKeyWords(); wxString keywords = m_alias->GetKeyWords();
if( keywords.empty() ) if( keywords.empty() )
m_html.Replace( "__KEY__", wxEmptyString ); m_html.Replace( "__KEY__", wxEmptyString );
@ -159,7 +188,7 @@ protected:
{ {
wxString fieldtable; wxString fieldtable;
LIB_FIELDS fields; LIB_FIELDS fields;
m_part->GetPart()->GetFields( fields ); m_alias->GetPart()->GetFields( fields );
for( auto const & field: fields ) for( auto const & field: fields )
{ {
@ -171,9 +200,9 @@ protected:
}; };
wxString GenerateAliasInfo( LIB_ALIAS const * aAlias, int aUnit ) wxString GenerateAliasInfo( SYMBOL_LIB_TABLE* aSymLibTable, LIB_ID const& aLibId, int aUnit )
{ {
ALIAS_INFO_GENERATOR gen( aAlias, aUnit ); ALIAS_INFO_GENERATOR gen( aSymLibTable, aLibId, aUnit );
gen.GenerateHtml(); gen.GenerateHtml();
return gen.GetHtml(); return gen.GetHtml();
} }

View File

@ -21,12 +21,15 @@
#ifndef GENERATE_ALIAS_INFO_H #ifndef GENERATE_ALIAS_INFO_H
#define GENERATE_ALIAS_INFO_H #define GENERATE_ALIAS_INFO_H
#include <class_libentry.h> #include <wx/string.h>
class LIB_ID;
class SYMBOL_LIB_TABLE;
/** /**
* Return an HTML page describing a LIB_ALIAS. This is suitable for inclusion * Return an HTML page describing a #LIB_ID in a #SYMBOL_LIB_TABLE. This is suitable for inclusion
* in a wxHtmlWindow. * in a wxHtmlWindow.
*/ */
wxString GenerateAliasInfo( LIB_ALIAS const * aAlias, int aUnit ); wxString GenerateAliasInfo( SYMBOL_LIB_TABLE* aSymLibTable, LIB_ID const& aLibId, int aUnit );
#endif // GENERATE_ALIAS_INFO_H #endif // GENERATE_ALIAS_INFO_H

View File

@ -45,6 +45,7 @@
#include <libeditframe.h> #include <libeditframe.h>
#include <viewlib_frame.h> #include <viewlib_frame.h>
#include <eeschema_id.h> #include <eeschema_id.h>
#include <symbol_lib_table.h>
#include <dialog_choose_component.h> #include <dialog_choose_component.h>
#include <cmp_tree_model_adapter.h> #include <cmp_tree_model_adapter.h>
@ -53,7 +54,7 @@
SCH_BASE_FRAME::COMPONENT_SELECTION SCH_BASE_FRAME::SelectComponentFromLibBrowser( SCH_BASE_FRAME::COMPONENT_SELECTION SCH_BASE_FRAME::SelectComponentFromLibBrowser(
const SCHLIB_FILTER* aFilter, const SCHLIB_FILTER* aFilter,
LIB_ALIAS* aPreselectedAlias, const LIB_ID& aPreselectedLibId,
int aUnit, int aConvert ) int aUnit, int aConvert )
{ {
// Close any open non-modal Lib browser, and open a new one, in "modal" mode: // Close any open non-modal Lib browser, and open a new one, in "modal" mode:
@ -67,10 +68,10 @@ SCH_BASE_FRAME::COMPONENT_SELECTION SCH_BASE_FRAME::SelectComponentFromLibBrowse
if( aFilter ) if( aFilter )
viewlibFrame->SetFilter( aFilter ); viewlibFrame->SetFilter( aFilter );
if( aPreselectedAlias ) if( aPreselectedLibId.IsValid() )
{ {
viewlibFrame->SetSelectedLibrary( aPreselectedAlias->GetLibraryName() ); viewlibFrame->SetSelectedLibrary( aPreselectedLibId.GetLibNickname() );
viewlibFrame->SetSelectedComponent( aPreselectedAlias->GetName() ); viewlibFrame->SetSelectedComponent( aPreselectedLibId.GetLibItemName() );
} }
viewlibFrame->SetUnitAndConvert( aUnit, aConvert ); viewlibFrame->SetUnitAndConvert( aUnit, aConvert );
@ -101,7 +102,7 @@ SCH_BASE_FRAME::COMPONENT_SELECTION SCH_BASE_FRAME::SelectComponentFromLibrary(
bool aAllowFields ) bool aAllowFields )
{ {
wxString dialogTitle; wxString dialogTitle;
PART_LIBS* libs = Prj().SchLibs(); SYMBOL_LIB_TABLE* libs = Prj().SchSymbolLibTable();
auto adapter( CMP_TREE_MODEL_ADAPTER::Create( libs ) ); auto adapter( CMP_TREE_MODEL_ADAPTER::Create( libs ) );
bool loaded = false; bool loaded = false;
@ -112,12 +113,10 @@ SCH_BASE_FRAME::COMPONENT_SELECTION SCH_BASE_FRAME::SelectComponentFromLibrary(
for( unsigned ii = 0; ii < liblist.GetCount(); ii++ ) for( unsigned ii = 0; ii < liblist.GetCount(); ii++ )
{ {
PART_LIB* currLibrary = libs->FindLibrary( liblist[ii] ); if( libs->HasLibrary( liblist[ii] ) )
if( currLibrary )
{ {
loaded = true; loaded = true;
adapter->AddLibrary( *currLibrary ); adapter->AddLibrary( liblist[ii] );
} }
} }
@ -126,23 +125,41 @@ SCH_BASE_FRAME::COMPONENT_SELECTION SCH_BASE_FRAME::SelectComponentFromLibrary(
} }
if( !aHistoryList.empty() ) if( !aHistoryList.empty() )
{ {
wxArrayString history_list; std::vector< LIB_ALIAS* > history_list;
for( auto const& i : aHistoryList ) for( auto const& i : aHistoryList )
history_list.push_back( i.Name ); {
LIB_ALIAS* alias = nullptr;
adapter->AddAliasList( "-- " + _( "History" ) + " --", history_list, NULL ); try
adapter->SetPreselectNode( aHistoryList[0].Name, aHistoryList[0].Unit ); {
alias = libs->LoadSymbol( i.LibNickname, i.Name );
} }
catch( const IO_ERROR& ioe )
{
wxLogError( wxString::Format( _( "Error occurred loading symbol %s from library %s."
"\n\n%s" ), i.Name, i.LibNickname, ioe.What() ) );
continue;
}
if( alias )
history_list.push_back( alias );
}
adapter->AddAliasList( "-- " + _( "History" ) + " --", history_list );
adapter->SetPreselectNode( LIB_ID( aHistoryList[0].LibNickname, aHistoryList[0].Name ),
aHistoryList[0].Unit );
}
std::vector< wxString > libNicknames = libs->GetLogicalLibs();
if( !loaded ) if( !loaded )
{ {
for( PART_LIB& lib : *libs ) for( auto nickname : libNicknames )
{ {
adapter->AddLibrary( lib ); adapter->AddLibrary( nickname );
} }
} }
@ -157,21 +174,19 @@ SCH_BASE_FRAME::COMPONENT_SELECTION SCH_BASE_FRAME::SelectComponentFromLibrary(
return COMPONENT_SELECTION(); return COMPONENT_SELECTION();
COMPONENT_SELECTION sel; COMPONENT_SELECTION sel;
LIB_ALIAS* const alias = dlg.GetSelectedAlias( &sel.Unit ); LIB_ID id = dlg.GetSelectedLibId( &sel.Unit );
if( alias == nullptr ) // Dialog closed by OK button, but no symbol selected if( !id.IsValid() ) // Dialog closed by OK button, but no symbol selected
return COMPONENT_SELECTION(); return COMPONENT_SELECTION();
if( sel.Unit == 0 ) if( sel.Unit == 0 )
sel.Unit = 1; sel.Unit = 1;
sel.Fields = dlg.GetFields(); sel.Fields = dlg.GetFields();
sel.Name = id.GetLibItemName();
if ( alias )
sel.Name = alias->GetName();
if( dlg.IsExternalBrowserSelected() ) // User requested component browser. if( dlg.IsExternalBrowserSelected() ) // User requested component browser.
sel = SelectComponentFromLibBrowser( aFilter, alias, sel.Unit, sel.Convert ); sel = SelectComponentFromLibBrowser( aFilter, id, sel.Unit, sel.Convert );
if( !sel.Name.empty() ) if( !sel.Name.empty() )
{ {

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2008-2017 Wayne Stambaugh <stambaughw@verizon.net> * Copyright (C) 2008 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 2004-2017 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2004-2017 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -45,6 +45,7 @@
#include <template_fieldnames.h> #include <template_fieldnames.h>
#include <wildcards_and_files_ext.h> #include <wildcards_and_files_ext.h>
#include <schframe.h> #include <schframe.h>
#include <symbol_lib_table.h>
#include <dialog_choose_component.h> #include <dialog_choose_component.h>
#include <cmp_tree_model_adapter.h> #include <cmp_tree_model_adapter.h>
@ -514,7 +515,6 @@ void LIB_EDIT_FRAME::DisplayCmpDoc()
void LIB_EDIT_FRAME::DeleteOnePart( wxCommandEvent& event ) void LIB_EDIT_FRAME::DeleteOnePart( wxCommandEvent& event )
{ {
wxString cmp_name; wxString cmp_name;
LIB_ALIAS* libEntry;
wxArrayString nameList; wxArrayString nameList;
wxString msg; wxString msg;
@ -538,12 +538,12 @@ void LIB_EDIT_FRAME::DeleteOnePart( wxCommandEvent& event )
} }
} }
auto adapter( CMP_TREE_MODEL_ADAPTER::Create( Prj().SchLibs() ) ); auto adapter( CMP_TREE_MODEL_ADAPTER::Create( Prj().SchSymbolLibTable() ) );
wxString name = part ? part->GetName() : wxString( wxEmptyString ); wxString name = part ? part->GetName() : wxString( wxEmptyString );
adapter->SetPreselectNode( name, /* aUnit */ 0 ); adapter->SetPreselectNode( name, /* aUnit */ 0 );
adapter->ShowUnits( false ); adapter->ShowUnits( false );
adapter->AddLibrary( *lib ); adapter->AddLibrary( lib->GetName() );
wxString dialogTitle; wxString dialogTitle;
dialogTitle.Printf( _( "Delete Component (%u items loaded)" ), adapter->GetComponentsCount() ); dialogTitle.Printf( _( "Delete Component (%u items loaded)" ), adapter->GetComponentsCount() );
@ -555,25 +555,29 @@ void LIB_EDIT_FRAME::DeleteOnePart( wxCommandEvent& event )
return; return;
} }
libEntry = dlg.GetSelectedAlias( NULL ); LIB_ID id;
if( !libEntry ) id = dlg.GetSelectedLibId();
{
if( !id.IsValid() )
return;
LIB_ALIAS* alias = Prj().SchSymbolLibTable()->LoadSymbol( id );
if( !alias )
return; return;
}
msg.Printf( _( "Delete component '%s' from library '%s' ?" ), msg.Printf( _( "Delete component '%s' from library '%s' ?" ),
GetChars( libEntry->GetName() ), id.GetLibItemName().wx_str(), id.GetLibNickname().wx_str() );
GetChars( lib->GetName() ) );
if( !IsOK( this, msg ) ) if( !IsOK( this, msg ) )
return; return;
part = GetCurPart(); part = GetCurPart();
if( !part || !part->HasAlias( libEntry->GetName() ) ) if( !part || !part->HasAlias( id.GetLibItemName() ) )
{ {
lib->RemoveAlias( libEntry ); Prj().SchSymbolLibTable()->DeleteAlias( id.GetLibNickname(), id.GetLibItemName() );
m_canvas->Refresh(); m_canvas->Refresh();
return; return;
} }
@ -588,19 +592,10 @@ void LIB_EDIT_FRAME::DeleteOnePart( wxCommandEvent& event )
return; return;
} }
LIB_ALIAS* nextEntry = lib->RemoveAlias( libEntry ); Prj().SchSymbolLibTable()->DeleteAlias( id.GetLibNickname(), id.GetLibItemName() );
if( nextEntry != NULL )
{
if( LoadOneLibraryPartAux( nextEntry, lib ) )
Zoom_Automatique( false );
}
else
{
SetCurPart( NULL ); // delete CurPart SetCurPart( NULL ); // delete CurPart
m_aliasName.Empty(); m_aliasName.Empty();
}
m_canvas->Refresh(); m_canvas->Refresh();
} }

View File

@ -34,6 +34,7 @@ class LIB_EDIT_FRAME;
class LIB_ALIAS; class LIB_ALIAS;
class PART_LIB; class PART_LIB;
class SCHLIB_FILTER; class SCHLIB_FILTER;
class LIB_ID;
/** /**
* Class SCH_BASE_FRAME * Class SCH_BASE_FRAME
@ -127,6 +128,7 @@ public:
struct COMPONENT_SELECTION struct COMPONENT_SELECTION
{ {
wxString LibNickname;
wxString Name; wxString Name;
int Unit; int Unit;
int Convert; int Convert;
@ -134,6 +136,7 @@ public:
std::vector<std::pair<int, wxString>> Fields; std::vector<std::pair<int, wxString>> Fields;
COMPONENT_SELECTION(): COMPONENT_SELECTION():
LibNickname( "" ),
Name( "" ), Name( "" ),
Unit( 1 ), Unit( 1 ),
Convert( 1 ) Convert( 1 )
@ -185,14 +188,14 @@ protected:
* in modal mode. * in modal mode.
* @param aFilter is a filter to pass the allowed library names * @param aFilter is a filter to pass the allowed library names
* and/or some other filter * and/or some other filter
* @param aPreselectedAlias Preselected component alias. NULL if none. * @param aPreselectedLibId Preselected component LIB_ID. Not valid if none selected.
* @param aUnit preselected unit * @param aUnit preselected unit
* @param aConvert preselected deMorgan conversion * @param aConvert preselected deMorgan conversion
* @return the selected component * @return the selected component
*/ */
COMPONENT_SELECTION SelectComponentFromLibBrowser( COMPONENT_SELECTION SelectComponentFromLibBrowser(
const SCHLIB_FILTER* aFilter, const SCHLIB_FILTER* aFilter,
LIB_ALIAS* aPreselectedAlias, const LIB_ID& aPreselectedLibid,
int aUnit, int aConvert ); int aUnit, int aConvert );
/** /**

View File

@ -48,14 +48,18 @@
void LIB_VIEW_FRAME::OnSelectSymbol( wxCommandEvent& aEvent ) void LIB_VIEW_FRAME::OnSelectSymbol( wxCommandEvent& aEvent )
{ {
wxString dialogTitle; wxString dialogTitle;
PART_LIBS* libs = Prj().SchLibs(); SYMBOL_LIB_TABLE* libs = Prj().SchSymbolLibTable();
// Container doing search-as-you-type. // Container doing search-as-you-type.
auto adapter( CMP_TREE_MODEL_ADAPTER::Create( libs ) ); auto adapter( CMP_TREE_MODEL_ADAPTER::Create( libs ) );
for( PART_LIB& lib : *libs ) std::vector< wxString > libNicknames;
libNicknames = libs->GetLogicalLibs();
for( auto nickname : libNicknames )
{ {
adapter->AddLibrary( lib ); adapter->AddLibrary( nickname );
} }
dialogTitle.Printf( _( "Choose Component (%d items loaded)" ), dialogTitle.Printf( _( "Choose Component (%d items loaded)" ),
@ -67,21 +71,24 @@ void LIB_VIEW_FRAME::OnSelectSymbol( wxCommandEvent& aEvent )
/// @todo: The unit selection gets reset to 1 by SetSelectedComponent() so the unit /// @todo: The unit selection gets reset to 1 by SetSelectedComponent() so the unit
/// selection feature of the choose symbol dialog doesn't work. /// selection feature of the choose symbol dialog doesn't work.
LIB_ALIAS* const alias = dlg.GetSelectedAlias( &m_unit ); LIB_ID id = dlg.GetSelectedLibId( &m_unit );
if( !alias || !alias->GetLib() ) if( !id.IsValid() || id.GetLibNickname().empty() )
return; return;
if( m_libraryName == alias->GetLib()->GetName() ) if( m_libraryName == id.GetLibNickname() )
{ {
if( m_entryName != alias->GetName() ) if( m_entryName != id.GetLibItemName() )
SetSelectedComponent( alias->GetName() ); SetSelectedComponent( id.GetLibItemName() );
} }
else else
{ {
m_entryName = alias->GetName(); m_entryName = id.GetLibItemName();
SetSelectedLibrary( alias->GetLib()->GetName() ); SetSelectedLibrary( id.GetLibNickname() );
SetSelectedComponent( id.GetLibItemName() );
} }
Zoom_Automatique( false );
} }

View File

@ -32,9 +32,16 @@
#include <wx/statbmp.h> #include <wx/statbmp.h>
#include <wx/html/htmlwin.h> #include <wx/html/htmlwin.h>
COMPONENT_TREE::COMPONENT_TREE( wxWindow* aParent, #include <symbol_lib_table.h>
COMPONENT_TREE::COMPONENT_TREE( wxWindow* aParent, SYMBOL_LIB_TABLE* aSymLibTable,
CMP_TREE_MODEL_ADAPTER::PTR& aAdapter, WIDGETS aWidgets ) CMP_TREE_MODEL_ADAPTER::PTR& aAdapter, WIDGETS aWidgets )
: wxPanel( aParent ), m_adapter( aAdapter ), m_query_ctrl( nullptr ), m_details_ctrl( nullptr ) : wxPanel( aParent ),
m_sym_lib_table( aSymLibTable ),
m_adapter( aAdapter ),
m_query_ctrl( nullptr ),
m_details_ctrl( nullptr )
{ {
auto sizer = new wxBoxSizer( wxVERTICAL ); auto sizer = new wxBoxSizer( wxVERTICAL );
@ -43,8 +50,8 @@ COMPONENT_TREE::COMPONENT_TREE( wxWindow* aParent,
{ {
auto search_sizer = new wxBoxSizer( wxHORIZONTAL ); auto search_sizer = new wxBoxSizer( wxHORIZONTAL );
m_query_ctrl = new wxTextCtrl( m_query_ctrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition,
this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER ); wxDefaultSize, wxTE_PROCESS_ENTER );
// Additional visual cue for GTK, which hides the placeholder text on focus // Additional visual cue for GTK, which hides the placeholder text on focus
#ifdef __WXGTK__ #ifdef __WXGTK__
@ -102,10 +109,17 @@ COMPONENT_TREE::COMPONENT_TREE( wxWindow* aParent,
} }
LIB_ALIAS* COMPONENT_TREE::GetSelectedAlias( int* aUnit ) const LIB_ID COMPONENT_TREE::GetSelectedLibId( int* aUnit ) const
{ {
auto sel = m_tree_ctrl->GetSelection(); auto sel = m_tree_ctrl->GetSelection();
if( !sel )
{
LIB_ID emptyId;
return emptyId;
}
if( aUnit ) if( aUnit )
*aUnit = m_adapter->GetUnitFor( sel ); *aUnit = m_adapter->GetUnitFor( sel );
@ -151,7 +165,7 @@ void COMPONENT_TREE::onQueryText( wxCommandEvent& aEvent )
void COMPONENT_TREE::onQueryEnter( wxCommandEvent& aEvent ) void COMPONENT_TREE::onQueryEnter( wxCommandEvent& aEvent )
{ {
if( GetSelectedAlias() ) if( GetSelectedLibId().IsValid() )
postSelectEvent(); postSelectEvent();
} }
@ -181,7 +195,7 @@ void COMPONENT_TREE::onTreeSelect( wxDataViewEvent& aEvent )
void COMPONENT_TREE::onTreeActivate( wxDataViewEvent& aEvent ) void COMPONENT_TREE::onTreeActivate( wxDataViewEvent& aEvent )
{ {
if( !GetSelectedAlias() ) if( !GetSelectedLibId().IsValid() )
{ {
// Expand library/part units subtree // Expand library/part units subtree
auto const sel = m_tree_ctrl->GetSelection(); auto const sel = m_tree_ctrl->GetSelection();
@ -210,10 +224,10 @@ void COMPONENT_TREE::onPreselect( wxCommandEvent& aEvent )
if( m_details_ctrl ) if( m_details_ctrl )
{ {
int unit = 0; int unit = 0;
LIB_ALIAS* alias = GetSelectedAlias( &unit ); LIB_ID id = GetSelectedLibId( &unit );
if( alias ) if( id.IsValid() )
m_details_ctrl->SetPage( GenerateAliasInfo( alias, unit ) ); m_details_ctrl->SetPage( GenerateAliasInfo( m_sym_lib_table, id, unit ) );
else else
m_details_ctrl->SetPage( wxEmptyString ); m_details_ctrl->SetPage( wxEmptyString );
} }

View File

@ -33,6 +33,9 @@ class wxDataViewCtrl;
class wxTextCtrl; class wxTextCtrl;
class wxHtmlWindow; class wxHtmlWindow;
class wxHtmlLinkEvent; class wxHtmlLinkEvent;
class LIB_ID;
class SYMBOL_LIB_TABLE;
/** /**
* Widget displaying a tree of components with optional search text control and description panel. * Widget displaying a tree of components with optional search text control and description panel.
@ -43,7 +46,7 @@ public:
///> Flags to select extra widgets ///> Flags to select extra widgets
enum WIDGETS { NONE = 0x00, SEARCH = 0x01, DETAILS = 0x02, ALL = 0xFF }; enum WIDGETS { NONE = 0x00, SEARCH = 0x01, DETAILS = 0x02, ALL = 0xFF };
COMPONENT_TREE( wxWindow* aParent, COMPONENT_TREE( wxWindow* aParent, SYMBOL_LIB_TABLE* aSymLibTable,
CMP_TREE_MODEL_ADAPTER::PTR& aAdapter, WIDGETS aWidgets = ALL ); CMP_TREE_MODEL_ADAPTER::PTR& aAdapter, WIDGETS aWidgets = ALL );
/** /**
@ -53,9 +56,9 @@ public:
* with whatever default is desired (usually 1). * with whatever default is desired (usually 1).
* *
* @param aUnit if not NULL, the selected unit is filled in here. * @param aUnit if not NULL, the selected unit is filled in here.
* @return the alias that has been selected, or NULL if there is none. * @return the library id of the symbol that has been selected.
*/ */
LIB_ALIAS* GetSelectedAlias( int* aUnit = nullptr ) const; LIB_ID GetSelectedLibId( int* aUnit = nullptr ) const;
protected: protected:
/** /**
@ -84,8 +87,8 @@ protected:
void onDetailsLink( wxHtmlLinkEvent& aEvent ); void onDetailsLink( wxHtmlLinkEvent& aEvent );
void onPreselect( wxCommandEvent& aEvent ); void onPreselect( wxCommandEvent& aEvent );
SYMBOL_LIB_TABLE* m_sym_lib_table;
CMP_TREE_MODEL_ADAPTER::PTR m_adapter; CMP_TREE_MODEL_ADAPTER::PTR m_adapter;
wxTextCtrl* m_query_ctrl; wxTextCtrl* m_query_ctrl;
wxDataViewCtrl* m_tree_ctrl; wxDataViewCtrl* m_tree_ctrl;
wxHtmlWindow* m_details_ctrl; wxHtmlWindow* m_details_ctrl;