Add footprint select dropdown to component chooser, serious refactoring
- DIALOG_CHOOSE_COMPONENT has footprint select widget - FOOTPRINT_SELECT_WIDGET - FOOTPRINT_CHOICE widget (customized wxComboCtrl) - FOOTPRINT_FILTER class - FOOTPRINT_INFO rework: - FOOTPRINT_ASYNC_LOADER to load without freezing UI - Rewrite loader threads as queue-driven thread pool - Make FOOTPRINT_INFO available via kiway - FP_LIB_TABLE::PrefetchLib - Access to global fp-lib-table via kiway - SYNC_QUEUE threadsafe queue template - Remove KICAD_FOOTPRINT_SELECTOR build option
This commit is contained in:
parent
cc7825d00b
commit
849b3c2a4b
|
@ -101,8 +101,6 @@ option( BUILD_GITHUB_PLUGIN "Build the GITHUB_PLUGIN for pcbnew." ON )
|
||||||
|
|
||||||
option( KICAD_SPICE "Build Kicad with internal Spice simulator." OFF )
|
option( KICAD_SPICE "Build Kicad with internal Spice simulator." OFF )
|
||||||
|
|
||||||
option( KICAD_FOOTPRINT_SELECTOR "Build experimental eeschema footprint selector." OFF )
|
|
||||||
|
|
||||||
# Global setting: exports are explicit
|
# Global setting: exports are explicit
|
||||||
set( CMAKE_CXX_VISIBILITY_PRESET "hidden" )
|
set( CMAKE_CXX_VISIBILITY_PRESET "hidden" )
|
||||||
set( CMAKE_VISIBILITY_INLINES_HIDDEN ON )
|
set( CMAKE_VISIBILITY_INLINES_HIDDEN ON )
|
||||||
|
@ -321,10 +319,6 @@ if( KICAD_SPICE )
|
||||||
add_definitions( -DKICAD_SPICE )
|
add_definitions( -DKICAD_SPICE )
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if( KICAD_FOOTPRINT_SELECTOR )
|
|
||||||
add_definitions( -DKICAD_FOOTPRINT_SELECTOR )
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if( KICAD_USE_SCH_IO_MANAGER )
|
if( KICAD_USE_SCH_IO_MANAGER )
|
||||||
add_definitions( -DKICAD_USE_SCH_IO_MANAGER )
|
add_definitions( -DKICAD_USE_SCH_IO_MANAGER )
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -171,6 +171,8 @@ set( COMMON_WIDGET_SRCS
|
||||||
widgets/widget_hotkey_list.cpp
|
widgets/widget_hotkey_list.cpp
|
||||||
widgets/two_column_tree_list.cpp
|
widgets/two_column_tree_list.cpp
|
||||||
widgets/footprint_preview_widget.cpp
|
widgets/footprint_preview_widget.cpp
|
||||||
|
widgets/footprint_select_widget.cpp
|
||||||
|
widgets/footprint_choice.cpp
|
||||||
widgets/indicator_icon.cpp
|
widgets/indicator_icon.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -243,6 +245,8 @@ set( COMMON_SRCS
|
||||||
exceptions.cpp
|
exceptions.cpp
|
||||||
executable_names.cpp
|
executable_names.cpp
|
||||||
filter_reader.cpp
|
filter_reader.cpp
|
||||||
|
footprint_info.cpp
|
||||||
|
footprint_filter.cpp
|
||||||
lib_id.cpp
|
lib_id.cpp
|
||||||
lib_table_keywords.cpp
|
lib_table_keywords.cpp
|
||||||
# findkicadhelppath.cpp.notused deprecated, use searchhelpfilefullpath.cpp
|
# findkicadhelppath.cpp.notused deprecated, use searchhelpfilefullpath.cpp
|
||||||
|
@ -351,7 +355,6 @@ set( PCB_COMMON_SRCS
|
||||||
eda_text.cpp
|
eda_text.cpp
|
||||||
class_page_info.cpp
|
class_page_info.cpp
|
||||||
lset.cpp
|
lset.cpp
|
||||||
footprint_info.cpp
|
|
||||||
../pcbnew/basepcbframe.cpp
|
../pcbnew/basepcbframe.cpp
|
||||||
../pcbnew/class_board.cpp
|
../pcbnew/class_board.cpp
|
||||||
../pcbnew/class_board_connected_item.cpp
|
../pcbnew/class_board_connected_item.cpp
|
||||||
|
|
|
@ -34,6 +34,12 @@ bool EDA_PATTERN_MATCH_SUBSTR::SetPattern( const wxString& aPattern )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString const& EDA_PATTERN_MATCH_SUBSTR::GetPattern() const
|
||||||
|
{
|
||||||
|
return m_pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int EDA_PATTERN_MATCH_SUBSTR::Find( const wxString& aCandidate ) const
|
int EDA_PATTERN_MATCH_SUBSTR::Find( const wxString& aCandidate ) const
|
||||||
{
|
{
|
||||||
int loc = aCandidate.Find( m_pattern );
|
int loc = aCandidate.Find( m_pattern );
|
||||||
|
@ -75,6 +81,12 @@ bool EDA_PATTERN_MATCH_REGEX::SetPattern( const wxString& aPattern )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString const& EDA_PATTERN_MATCH_REGEX::GetPattern() const
|
||||||
|
{
|
||||||
|
return m_pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int EDA_PATTERN_MATCH_REGEX::Find( const wxString& aCandidate ) const
|
int EDA_PATTERN_MATCH_REGEX::Find( const wxString& aCandidate ) const
|
||||||
{
|
{
|
||||||
if( m_regex.IsValid() )
|
if( m_regex.IsValid() )
|
||||||
|
@ -100,6 +112,8 @@ int EDA_PATTERN_MATCH_REGEX::Find( const wxString& aCandidate ) const
|
||||||
|
|
||||||
bool EDA_PATTERN_MATCH_WILDCARD::SetPattern( const wxString& aPattern )
|
bool EDA_PATTERN_MATCH_WILDCARD::SetPattern( const wxString& aPattern )
|
||||||
{
|
{
|
||||||
|
m_wildcard_pattern = aPattern;
|
||||||
|
|
||||||
// Compile the wildcard string to a regular expression
|
// Compile the wildcard string to a regular expression
|
||||||
wxString regex;
|
wxString regex;
|
||||||
regex.Alloc( 2 * aPattern.Length() ); // no need to keep resizing, we know the size roughly
|
regex.Alloc( 2 * aPattern.Length() ); // no need to keep resizing, we know the size roughly
|
||||||
|
@ -132,6 +146,12 @@ bool EDA_PATTERN_MATCH_WILDCARD::SetPattern( const wxString& aPattern )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString const& EDA_PATTERN_MATCH_WILDCARD::GetPattern() const
|
||||||
|
{
|
||||||
|
return m_wildcard_pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int EDA_PATTERN_MATCH_WILDCARD::Find( const wxString& aCandidate ) const
|
int EDA_PATTERN_MATCH_WILDCARD::Find( const wxString& aCandidate ) const
|
||||||
{
|
{
|
||||||
return EDA_PATTERN_MATCH_REGEX::Find( aCandidate );
|
return EDA_PATTERN_MATCH_REGEX::Find( aCandidate );
|
||||||
|
|
|
@ -0,0 +1,230 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||||
|
* Copyright (C) 1992-2017 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <footprint_filter.h>
|
||||||
|
#include <make_unique.h>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
using FOOTPRINT_FILTER_IT = FOOTPRINT_FILTER::ITERATOR;
|
||||||
|
|
||||||
|
|
||||||
|
FOOTPRINT_FILTER::ITERATOR::ITERATOR() : m_pos( 0 ), m_filter( nullptr )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FOOTPRINT_FILTER::ITERATOR::ITERATOR( FOOTPRINT_FILTER_IT const& aOther )
|
||||||
|
: m_pos( aOther.m_pos ), m_filter( aOther.m_filter )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FOOTPRINT_FILTER::ITERATOR::ITERATOR( FOOTPRINT_FILTER& aFilter )
|
||||||
|
: m_pos( (size_t) -1 ), m_filter( &aFilter )
|
||||||
|
{
|
||||||
|
increment();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_FILTER_IT::increment()
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
if( !m_filter || !m_filter->m_list || m_filter->m_list->GetCount() == 0 )
|
||||||
|
{
|
||||||
|
m_pos = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto filter_type = m_filter->m_filter_type;
|
||||||
|
auto list = m_filter->m_list;
|
||||||
|
auto& lib_name = m_filter->m_lib_name;
|
||||||
|
auto& filter_pattern = m_filter->m_filter_pattern;
|
||||||
|
auto& filter = m_filter->m_filter;
|
||||||
|
|
||||||
|
for( ++m_pos; m_pos < list->GetCount() && !found; ++m_pos )
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
|
||||||
|
if( ( filter_type & FOOTPRINT_FILTER::FILTERING_BY_LIBRARY ) && !lib_name.IsEmpty()
|
||||||
|
&& !list->GetItem( m_pos ).InLibrary( lib_name ) )
|
||||||
|
found = false;
|
||||||
|
|
||||||
|
if( ( filter_type & FOOTPRINT_FILTER::FILTERING_BY_COMPONENT_KEYWORD )
|
||||||
|
&& !FootprintFilterMatch( list->GetItem( m_pos ) ) )
|
||||||
|
found = false;
|
||||||
|
|
||||||
|
if( ( filter_type & FOOTPRINT_FILTER::FILTERING_BY_PIN_COUNT )
|
||||||
|
&& !PinCountMatch( list->GetItem( m_pos ) ) )
|
||||||
|
found = false;
|
||||||
|
|
||||||
|
if( ( filter_type & FOOTPRINT_FILTER::FILTERING_BY_NAME ) && !filter_pattern.IsEmpty() )
|
||||||
|
{
|
||||||
|
wxString currname;
|
||||||
|
|
||||||
|
// If the search string contains a ':' character,
|
||||||
|
// include the library name in the search string
|
||||||
|
// e.g. LibName:FootprintName
|
||||||
|
if( filter_pattern.Contains( ":" ) )
|
||||||
|
currname = list->GetItem( m_pos ).GetNickname().Lower() + ":";
|
||||||
|
|
||||||
|
currname += list->GetItem( m_pos ).GetFootprintName().Lower();
|
||||||
|
|
||||||
|
if( filter.Find( currname ) == EDA_PATTERN_NOT_FOUND )
|
||||||
|
found = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( filter_type == FOOTPRINT_FILTER::UNFILTERED_FP_LIST )
|
||||||
|
{
|
||||||
|
// override
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// for loop will stop one past the correct item
|
||||||
|
if( found )
|
||||||
|
--m_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool FOOTPRINT_FILTER_IT::equal( FOOTPRINT_FILTER_IT const& aOther ) const
|
||||||
|
{
|
||||||
|
// Invalid iterators are always equal
|
||||||
|
return ( m_pos == aOther.m_pos ) && ( m_filter == aOther.m_filter || m_pos == (size_t) -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FOOTPRINT_INFO& FOOTPRINT_FILTER_IT::dereference() const
|
||||||
|
{
|
||||||
|
if( m_filter && m_filter->m_list && m_pos < m_filter->m_list->GetCount() )
|
||||||
|
return m_filter->m_list->GetItem( m_pos );
|
||||||
|
else
|
||||||
|
throw std::out_of_range( "Attempt to dereference past FOOTPRINT_FILTER::end()" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool FOOTPRINT_FILTER_IT::FootprintFilterMatch( FOOTPRINT_INFO& aItem )
|
||||||
|
{
|
||||||
|
if( m_filter->m_footprint_filters.empty() )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// The matching is case insensitive
|
||||||
|
wxString name = "";
|
||||||
|
|
||||||
|
EDA_PATTERN_MATCH_WILDCARD patternFilter;
|
||||||
|
|
||||||
|
for( auto const& each_filter : m_filter->m_footprint_filters )
|
||||||
|
{
|
||||||
|
// If the filter contains a ':' character, include the library name in the pattern
|
||||||
|
if( each_filter->GetPattern().Contains( ":" ) )
|
||||||
|
{
|
||||||
|
name = aItem.GetNickname().Lower() + ":";
|
||||||
|
}
|
||||||
|
|
||||||
|
name += aItem.GetFootprintName().Lower();
|
||||||
|
|
||||||
|
if( each_filter->Find( name ) != EDA_PATTERN_NOT_FOUND )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool FOOTPRINT_FILTER_IT::PinCountMatch( FOOTPRINT_INFO& aItem )
|
||||||
|
{
|
||||||
|
return (unsigned) m_filter->m_pin_count == aItem.GetUniquePadCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FOOTPRINT_FILTER::FOOTPRINT_FILTER( FOOTPRINT_LIST& aList ) : FOOTPRINT_FILTER()
|
||||||
|
{
|
||||||
|
SetList( aList );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FOOTPRINT_FILTER::FOOTPRINT_FILTER()
|
||||||
|
: m_list( nullptr ), m_pin_count( -1 ), m_filter_type( UNFILTERED_FP_LIST )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_FILTER::SetList( FOOTPRINT_LIST& aList )
|
||||||
|
{
|
||||||
|
m_list = &aList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_FILTER::ClearFilters()
|
||||||
|
{
|
||||||
|
m_filter_type = UNFILTERED_FP_LIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_FILTER::FilterByLibrary( wxString const& aLibName )
|
||||||
|
{
|
||||||
|
m_lib_name = aLibName;
|
||||||
|
m_filter_type |= FILTERING_BY_LIBRARY;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_FILTER::FilterByPinCount( int aPinCount )
|
||||||
|
{
|
||||||
|
m_pin_count = aPinCount;
|
||||||
|
m_filter_type |= FILTERING_BY_PIN_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_FILTER::FilterByFootprintFilters( wxArrayString const& aFilters )
|
||||||
|
{
|
||||||
|
m_footprint_filters.clear();
|
||||||
|
|
||||||
|
for( auto const& each_pattern : aFilters )
|
||||||
|
{
|
||||||
|
m_footprint_filters.push_back( std::make_unique<EDA_PATTERN_MATCH_WILDCARD>() );
|
||||||
|
wxASSERT( m_footprint_filters.back()->SetPattern( each_pattern.Lower() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_filter_type |= FILTERING_BY_COMPONENT_KEYWORD;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_FILTER::FilterByPattern( wxString const& aPattern )
|
||||||
|
{
|
||||||
|
m_filter_pattern = aPattern;
|
||||||
|
m_filter.SetPattern( aPattern.Lower() );
|
||||||
|
m_filter_type |= FILTERING_BY_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FOOTPRINT_FILTER_IT FOOTPRINT_FILTER::begin()
|
||||||
|
{
|
||||||
|
return FOOTPRINT_FILTER_IT( *this );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FOOTPRINT_FILTER_IT FOOTPRINT_FILTER::end()
|
||||||
|
{
|
||||||
|
FOOTPRINT_FILTER_IT end_it( *this );
|
||||||
|
end_it.m_pos = m_list->GetCount();
|
||||||
|
return end_it;
|
||||||
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 Jean-Pierre Charras, <jp.charras@wanadoo.fr>
|
* Copyright (C) 2011 Jean-Pierre Charras, <jp.charras@wanadoo.fr>
|
||||||
* Copyright (C) 2013-2016 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
* Copyright (C) 2013-2016 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 1992-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
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -23,242 +23,31 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file footprint_info.cpp
|
* @file footprint_info.cpp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
No. concurrent threads doing "http(s) GET". More than 6 is not significantly
|
|
||||||
faster, less than 6 is likely slower. Main thread is in this count, so if
|
|
||||||
set to 1 then no temp threads are created.
|
|
||||||
*/
|
|
||||||
#define READER_THREADS 6
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Functions to read footprint libraries and fill m_footprints by available footprints names
|
* Functions to read footprint libraries and fill m_footprints by available footprints names
|
||||||
* and their documentation (comments and keywords)
|
* and their documentation (comments and keywords)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <fctsys.h>
|
#include <class_module.h>
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
#include <fctsys.h>
|
||||||
|
#include <footprint_info.h>
|
||||||
|
#include <fp_lib_table.h>
|
||||||
|
#include <html_messagebox.h>
|
||||||
|
#include <io_mgr.h>
|
||||||
|
#include <kiface_ids.h>
|
||||||
|
#include <kiway.h>
|
||||||
|
#include <lib_id.h>
|
||||||
#include <macros.h>
|
#include <macros.h>
|
||||||
#include <pgm_base.h>
|
#include <pgm_base.h>
|
||||||
#include <wildcards_and_files_ext.h>
|
|
||||||
#include <footprint_info.h>
|
|
||||||
#include <io_mgr.h>
|
|
||||||
#include <fp_lib_table.h>
|
|
||||||
#include <lib_id.h>
|
|
||||||
#include <class_module.h>
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <html_messagebox.h>
|
#include <wildcards_and_files_ext.h>
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
static wxString ToHTMLFragment( const IO_ERROR* aDerivative )
|
|
||||||
{
|
|
||||||
@todo
|
|
||||||
|
|
||||||
1) change up IO_ERROR so it keeps linenumbers, source file name and
|
|
||||||
error message in separate strings.
|
|
||||||
|
|
||||||
2) Add a summarizing virtual member like
|
|
||||||
virtual wxString What()
|
|
||||||
to combine all portions of an IO_ERROR's text into a single wxString.
|
|
||||||
|
|
||||||
3) Do same for PARSE_ERROR.
|
|
||||||
|
|
||||||
4) Add a "reason or error category" to IO_ERROR and thereby also PARSE_ERROR?
|
|
||||||
|
|
||||||
msg += "
|
|
||||||
|
|
||||||
for( int i=0; i<aCount; ++i )
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
wxArrayString* sl = wxStringSplit( aList, wxChar( '\n' ) );
|
|
||||||
|
|
||||||
|
|
||||||
delete sl;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString msg = wxT( "<ul>" );
|
|
||||||
|
|
||||||
for ( unsigned ii = 0; ii < strings_list->GetCount(); ii++ )
|
|
||||||
{
|
|
||||||
msg += wxT( "<li>" );
|
|
||||||
msg += strings_list->Item( ii ) + wxT( "</li>" );
|
|
||||||
}
|
|
||||||
|
|
||||||
msg += wxT( "</ul>" );
|
|
||||||
|
|
||||||
m_htmlWindow->AppendToPage( msg );
|
|
||||||
|
|
||||||
delete strings_list;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
void FOOTPRINT_INFO::load()
|
|
||||||
{
|
|
||||||
FP_LIB_TABLE* fptable = m_owner->GetTable();
|
|
||||||
|
|
||||||
wxASSERT( fptable );
|
|
||||||
|
|
||||||
std::unique_ptr<MODULE> footprint( fptable->FootprintLoad( m_nickname, m_fpname ) );
|
|
||||||
|
|
||||||
if( footprint.get() == NULL ) // Should happen only with malformed/broken libraries
|
|
||||||
{
|
|
||||||
m_pad_count = 0;
|
|
||||||
m_unique_pad_count = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_pad_count = footprint->GetPadCount( DO_NOT_INCLUDE_NPTH );
|
|
||||||
m_unique_pad_count = footprint->GetUniquePadCount( DO_NOT_INCLUDE_NPTH );
|
|
||||||
m_keywords = footprint->GetKeywords();
|
|
||||||
m_doc = footprint->GetDescription();
|
|
||||||
|
|
||||||
// tell ensure_loaded() I'm loaded.
|
|
||||||
m_loaded = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FOOTPRINT_LIST::loader_job( const wxString* aNicknameList, int aJobZ )
|
|
||||||
{
|
|
||||||
for( int i=0; i<aJobZ; ++i )
|
|
||||||
{
|
|
||||||
const wxString& nickname = aNicknameList[i];
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
wxArrayString fpnames = m_lib_table->FootprintEnumerate( nickname );
|
|
||||||
|
|
||||||
for( unsigned ni=0; ni<fpnames.GetCount(); ++ni )
|
|
||||||
{
|
|
||||||
FOOTPRINT_INFO* fpinfo = new FOOTPRINT_INFO( this, nickname, fpnames[ni] );
|
|
||||||
|
|
||||||
addItem( fpinfo );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch( const PARSE_ERROR& pe )
|
|
||||||
{
|
|
||||||
// m_errors.push_back is not thread safe, lock its MUTEX.
|
|
||||||
MUTLOCK lock( m_errors_lock );
|
|
||||||
|
|
||||||
++m_error_count; // modify only under lock
|
|
||||||
m_errors.push_back( new IO_ERROR( pe ) );
|
|
||||||
}
|
|
||||||
catch( const IO_ERROR& ioe )
|
|
||||||
{
|
|
||||||
MUTLOCK lock( m_errors_lock );
|
|
||||||
|
|
||||||
++m_error_count;
|
|
||||||
m_errors.push_back( new IO_ERROR( ioe ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Catch anything unexpected and map it into the expected.
|
|
||||||
// Likely even more important since this function runs on GUI-less
|
|
||||||
// worker threads.
|
|
||||||
catch( const std::exception& se )
|
|
||||||
{
|
|
||||||
// This is a round about way to do this, but who knows what THROW_IO_ERROR()
|
|
||||||
// may be tricked out to do someday, keep it in the game.
|
|
||||||
try
|
|
||||||
{
|
|
||||||
THROW_IO_ERROR( se.what() );
|
|
||||||
}
|
|
||||||
catch( const IO_ERROR& ioe )
|
|
||||||
{
|
|
||||||
MUTLOCK lock( m_errors_lock );
|
|
||||||
|
|
||||||
++m_error_count;
|
|
||||||
m_errors.push_back( new IO_ERROR( ioe ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool FOOTPRINT_LIST::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* aNickname )
|
|
||||||
{
|
|
||||||
bool retv = true;
|
|
||||||
|
|
||||||
m_lib_table = aTable;
|
|
||||||
|
|
||||||
// Clear data before reading files
|
|
||||||
m_error_count = 0;
|
|
||||||
m_errors.clear();
|
|
||||||
m_list.clear();
|
|
||||||
|
|
||||||
if( aNickname )
|
|
||||||
// single footprint
|
|
||||||
loader_job( aNickname, 1 );
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::vector< wxString > nicknames;
|
|
||||||
|
|
||||||
// do all of them
|
|
||||||
nicknames = aTable->GetLogicalLibs();
|
|
||||||
|
|
||||||
// Even though the PLUGIN API implementation is the place for the
|
|
||||||
// locale toggling, in order to keep LOCAL_IO::C_count at 1 or greater
|
|
||||||
// for the duration of all helper threads, we increment by one here via instantiation.
|
|
||||||
// Only done here because of the multi-threaded nature of this code.
|
|
||||||
// Without this C_count skips in and out of "equal to zero" and causes
|
|
||||||
// needless locale toggling among the threads, based on which of them
|
|
||||||
// are in a PLUGIN::FootprintLoad() function. And that is occasionally
|
|
||||||
// none of them.
|
|
||||||
LOCALE_IO top_most_nesting;
|
|
||||||
|
|
||||||
// Something which will not invoke a thread copy constructor, one of many ways obviously:
|
|
||||||
typedef std::vector< std::thread > MYTHREADS;
|
|
||||||
|
|
||||||
MYTHREADS threads;
|
|
||||||
|
|
||||||
unsigned jobz = (nicknames.size() + READER_THREADS - 1) / READER_THREADS;
|
|
||||||
|
|
||||||
// Give each thread JOBZ nicknames to process. The last portion of, or if the entire
|
|
||||||
// size() is small, I'll do myself.
|
|
||||||
for( unsigned i=0; i<nicknames.size(); )
|
|
||||||
{
|
|
||||||
if( i + jobz >= nicknames.size() ) // on the last iteration of this for(;;)
|
|
||||||
{
|
|
||||||
jobz = nicknames.size() - i;
|
|
||||||
|
|
||||||
// Only a little bit to do, I'll do it myself on current thread.
|
|
||||||
// I am part of the READER_THREADS count.
|
|
||||||
loader_job( &nicknames[i], jobz );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Delegate the job to a temporary thread created here.
|
|
||||||
threads.push_back( std::thread( &FOOTPRINT_LIST::loader_job,
|
|
||||||
this, &nicknames[i], jobz ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
i += jobz;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for all the worker threads to complete, it does not matter in what order
|
|
||||||
// we wait for them as long as a full sweep is made. Think of the great race,
|
|
||||||
// everyone must finish.
|
|
||||||
for( unsigned i=0; i<threads.size(); ++i )
|
|
||||||
{
|
|
||||||
threads[i].join();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_list.sort();
|
|
||||||
}
|
|
||||||
|
|
||||||
// The result of this function can be a blend of successes and failures, whose
|
|
||||||
// mix is given by the Count()s of the two lists. The return value indicates whether
|
|
||||||
// an abort occurred, even true does not necessarily mean full success, although
|
|
||||||
// false definitely means failure.
|
|
||||||
|
|
||||||
return retv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FOOTPRINT_INFO* FOOTPRINT_LIST::GetModuleInfo( const wxString& aFootprintName )
|
FOOTPRINT_INFO* FOOTPRINT_LIST::GetModuleInfo( const wxString& aFootprintName )
|
||||||
|
@ -266,19 +55,19 @@ FOOTPRINT_INFO* FOOTPRINT_LIST::GetModuleInfo( const wxString& aFootprintName )
|
||||||
if( aFootprintName.IsEmpty() )
|
if( aFootprintName.IsEmpty() )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
for( FOOTPRINT_INFO& fp : m_list )
|
for( auto& fp : m_list )
|
||||||
{
|
{
|
||||||
LIB_ID fpid;
|
LIB_ID fpid;
|
||||||
|
|
||||||
wxCHECK_MSG( fpid.Parse( aFootprintName ) < 0, NULL,
|
wxCHECK_MSG( fpid.Parse( aFootprintName ) < 0, NULL,
|
||||||
wxString::Format( wxT( "'%s' is not a valid LIB_ID." ),
|
wxString::Format(
|
||||||
GetChars( aFootprintName ) ) );
|
wxT( "'%s' is not a valid LIB_ID." ), GetChars( aFootprintName ) ) );
|
||||||
|
|
||||||
wxString libNickname = fpid.GetLibNickname();
|
wxString libNickname = fpid.GetLibNickname();
|
||||||
wxString footprintName = fpid.GetLibItemName();
|
wxString footprintName = fpid.GetLibItemName();
|
||||||
|
|
||||||
if( libNickname == fp.GetNickname() && footprintName == fp.GetFootprintName() )
|
if( libNickname == fp->GetNickname() && footprintName == fp->GetFootprintName() )
|
||||||
return &fp;
|
return &*fp;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -304,12 +93,119 @@ void FOOTPRINT_LIST::DisplayErrors( wxTopLevelWindow* aWindow )
|
||||||
|
|
||||||
wxString msg;
|
wxString msg;
|
||||||
|
|
||||||
for( unsigned i = 0; i<m_errors.size(); ++i )
|
while( auto error = PopError() )
|
||||||
{
|
{
|
||||||
msg += wxT( "<p>" ) + m_errors[i].Problem() + wxT( "</p>" );
|
msg += wxT( "<p>" ) + error->Problem() + wxT( "</p>" );
|
||||||
}
|
}
|
||||||
|
|
||||||
dlg.AddHTML_Text( msg );
|
dlg.AddHTML_Text( msg );
|
||||||
|
|
||||||
dlg.ShowModal();
|
dlg.ShowModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static std::unique_ptr<FOOTPRINT_LIST> get_instance_from_id( KIWAY& aKiway, int aId )
|
||||||
|
{
|
||||||
|
void* ptr = nullptr;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
KIFACE* kiface = aKiway.KiFACE( KIWAY::FACE_PCB );
|
||||||
|
|
||||||
|
if( !kiface )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
ptr = kiface->IfaceOrAddress( aId );
|
||||||
|
|
||||||
|
if( !ptr )
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
catch( ... )
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::unique_ptr<FOOTPRINT_LIST>( (FOOTPRINT_LIST*) ( ptr ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::unique_ptr<FOOTPRINT_LIST> FOOTPRINT_LIST::GetInstance( KIWAY& aKiway )
|
||||||
|
{
|
||||||
|
return get_instance_from_id( aKiway, KIFACE_NEW_FOOTPRINT_LIST );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FOOTPRINT_ASYNC_LOADER::FOOTPRINT_ASYNC_LOADER() : m_list( nullptr )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_ASYNC_LOADER::SetList( FOOTPRINT_LIST* aList )
|
||||||
|
{
|
||||||
|
m_list = aList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_ASYNC_LOADER::Start(
|
||||||
|
FP_LIB_TABLE* aTable, wxString const* aNickname, unsigned aNThreads )
|
||||||
|
{
|
||||||
|
m_started = true;
|
||||||
|
|
||||||
|
// Capture the FP_LIB_TABLE into m_last_table. Formatting it as a string instead of storing the
|
||||||
|
// raw data avoids having to pull in the FP-specific parts.
|
||||||
|
STRING_FORMATTER sof;
|
||||||
|
aTable->Format( &sof, 0 );
|
||||||
|
m_last_table = sof.GetString();
|
||||||
|
|
||||||
|
m_list->StartWorkers( aTable, aNickname, this, aNThreads );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool FOOTPRINT_ASYNC_LOADER::Join()
|
||||||
|
{
|
||||||
|
if( m_list )
|
||||||
|
{
|
||||||
|
bool rv = m_list->JoinWorkers();
|
||||||
|
m_list = nullptr;
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int FOOTPRINT_ASYNC_LOADER::GetProgress() const
|
||||||
|
{
|
||||||
|
if( !m_started )
|
||||||
|
return 0;
|
||||||
|
else if( m_total_libs == 0 || !m_list )
|
||||||
|
return 100;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int loaded = m_list->CountFinished();
|
||||||
|
int prog = ( 100 * loaded ) / m_total_libs;
|
||||||
|
|
||||||
|
if( loaded == m_total_libs )
|
||||||
|
return 100;
|
||||||
|
else if( loaded < m_total_libs && prog >= 100 )
|
||||||
|
return 99;
|
||||||
|
else if( prog <= 0 )
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return prog;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_ASYNC_LOADER::SetCompletionCallback( std::function<void()> aCallback )
|
||||||
|
{
|
||||||
|
m_completion_cb = aCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool FOOTPRINT_ASYNC_LOADER::IsSameTable( FP_LIB_TABLE* aOther )
|
||||||
|
{
|
||||||
|
STRING_FORMATTER sof;
|
||||||
|
aOther->Format( &sof, 0 );
|
||||||
|
return m_last_table == sof.GetString();
|
||||||
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
* Copyright (C) 2010-2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||||
* Copyright (C) 2012-2016 Wayne Stambaugh <stambaughw@gmail.com>
|
* Copyright (C) 2012-2016 Wayne Stambaugh <stambaughw@gmail.com>
|
||||||
* Copyright (C) 2012-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 2012-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
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -204,6 +204,14 @@ wxArrayString FP_LIB_TABLE::FootprintEnumerate( const wxString& aNickname )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FP_LIB_TABLE::PrefetchLib( const wxString& aNickname )
|
||||||
|
{
|
||||||
|
const FP_LIB_TABLE_ROW* row = FindRow( aNickname );
|
||||||
|
wxASSERT( (PLUGIN*) row->plugin );
|
||||||
|
row->plugin->PrefetchLib( row->GetFullURI( true ), row->GetProperties() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const FP_LIB_TABLE_ROW* FP_LIB_TABLE::FindRow( const wxString& aNickname )
|
const FP_LIB_TABLE_ROW* FP_LIB_TABLE::FindRow( const wxString& aNickname )
|
||||||
throw( IO_ERROR )
|
throw( IO_ERROR )
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,8 +1,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) 2014 KiCad Developers, see CHANGELOG.TXT for contributors.
|
* Copyright (C) 2014-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
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -22,7 +21,6 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <wx/stdpaths.h>
|
#include <wx/stdpaths.h>
|
||||||
|
|
||||||
#include <fctsys.h>
|
#include <fctsys.h>
|
||||||
|
@ -34,6 +32,9 @@
|
||||||
#include <kicad_string.h>
|
#include <kicad_string.h>
|
||||||
#include <config_params.h>
|
#include <config_params.h>
|
||||||
#include <wildcards_and_files_ext.h>
|
#include <wildcards_and_files_ext.h>
|
||||||
|
#include <fp_lib_table.h>
|
||||||
|
#include <kiway.h>
|
||||||
|
#include <kiface_ids.h>
|
||||||
|
|
||||||
|
|
||||||
PROJECT::PROJECT()
|
PROJECT::PROJECT()
|
||||||
|
@ -379,3 +380,41 @@ const wxString PROJECT::AbsolutePath( const wxString& aFileName ) const
|
||||||
|
|
||||||
return fn.GetFullPath();
|
return fn.GetFullPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FP_LIB_TABLE* PROJECT::PcbFootprintLibs( KIWAY& aKiway )
|
||||||
|
{
|
||||||
|
// This is a lazy loading function, it loads the project specific table when
|
||||||
|
// that table is asked for, not before.
|
||||||
|
|
||||||
|
FP_LIB_TABLE* tbl = (FP_LIB_TABLE*) GetElem( ELEM_FPTBL );
|
||||||
|
|
||||||
|
// its gotta be NULL or a FP_LIB_TABLE, or a bug.
|
||||||
|
wxASSERT( !tbl || dynamic_cast<FP_LIB_TABLE*>( tbl ) );
|
||||||
|
|
||||||
|
if( !tbl )
|
||||||
|
{
|
||||||
|
// Stack the project specific FP_LIB_TABLE overlay on top of the global table.
|
||||||
|
// ~FP_LIB_TABLE() will not touch the fallback table, so multiple projects may
|
||||||
|
// stack this way, all using the same global fallback table.
|
||||||
|
KIFACE* kiface = aKiway.KiFACE( KIWAY::FACE_PCB );
|
||||||
|
if( kiface )
|
||||||
|
tbl = (FP_LIB_TABLE*) kiface->IfaceOrAddress( KIFACE_G_FOOTPRINT_TABLE );
|
||||||
|
|
||||||
|
wxASSERT( tbl );
|
||||||
|
SetElem( ELEM_FPTBL, tbl );
|
||||||
|
|
||||||
|
wxString projectFpLibTableFileName = FootprintLibTblName();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
tbl->Load( projectFpLibTableFileName );
|
||||||
|
}
|
||||||
|
catch( const IO_ERROR& ioe )
|
||||||
|
{
|
||||||
|
DisplayError( NULL, ioe.What() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tbl;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,262 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <widgets/footprint_choice.h>
|
||||||
|
#include <wx/dc.h>
|
||||||
|
#include <wx/pen.h>
|
||||||
|
|
||||||
|
wxDEFINE_EVENT( EVT_INTERACTIVE_CHOICE, wxCommandEvent );
|
||||||
|
|
||||||
|
|
||||||
|
wxColour FOOTPRINT_CHOICE::m_grey( 0x808080 );
|
||||||
|
|
||||||
|
|
||||||
|
FOOTPRINT_CHOICE::FOOTPRINT_CHOICE( wxWindow* aParent, int aId )
|
||||||
|
: wxOwnerDrawnComboBox( aParent, aId, wxEmptyString, wxDefaultPosition, wxDefaultSize,
|
||||||
|
/* n */ 0, /* choices */ nullptr, wxCB_READONLY ),
|
||||||
|
m_last_selection( 0 )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FOOTPRINT_CHOICE::~FOOTPRINT_CHOICE()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_CHOICE::DoSetPopupControl( wxComboPopup* aPopup )
|
||||||
|
{
|
||||||
|
using namespace std::placeholders;
|
||||||
|
wxOwnerDrawnComboBox::DoSetPopupControl( aPopup );
|
||||||
|
|
||||||
|
// Bind events to intercept selections, so the separator can be made nonselectable.
|
||||||
|
|
||||||
|
GetVListBoxComboPopup()->Bind( wxEVT_MOTION, &FOOTPRINT_CHOICE::TryVetoMouse, this );
|
||||||
|
GetVListBoxComboPopup()->Bind( wxEVT_LEFT_DOWN, &FOOTPRINT_CHOICE::TryVetoMouse, this );
|
||||||
|
GetVListBoxComboPopup()->Bind( wxEVT_LEFT_UP, &FOOTPRINT_CHOICE::TryVetoMouse, this );
|
||||||
|
GetVListBoxComboPopup()->Bind( wxEVT_LEFT_UP, &FOOTPRINT_CHOICE::OnMouseUp, this );
|
||||||
|
GetVListBoxComboPopup()->Bind( wxEVT_LEFT_DCLICK, &FOOTPRINT_CHOICE::TryVetoMouse, this );
|
||||||
|
GetVListBoxComboPopup()->Bind(
|
||||||
|
wxEVT_LISTBOX, std::bind( &FOOTPRINT_CHOICE::TryVetoSelect, this, _1, true ) );
|
||||||
|
Bind( wxEVT_COMBOBOX, std::bind( &FOOTPRINT_CHOICE::TryVetoSelect, this, _1, false ) );
|
||||||
|
GetVListBoxComboPopup()->Bind(
|
||||||
|
wxEVT_CHAR_HOOK, std::bind( &FOOTPRINT_CHOICE::TrySkipSeparator, this, _1, true ) );
|
||||||
|
GetVListBoxComboPopup()->Bind( wxEVT_CHAR_HOOK, &FOOTPRINT_CHOICE::OnKeyUp, this );
|
||||||
|
Bind( wxEVT_KEY_DOWN, std::bind( &FOOTPRINT_CHOICE::TrySkipSeparator, this, _1, false ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_CHOICE::OnDrawItem( wxDC& aDC, wxRect const& aRect, int aItem, int aFlags ) const
|
||||||
|
{
|
||||||
|
wxString text = SafeGetString( aItem );
|
||||||
|
|
||||||
|
if( text == wxEmptyString )
|
||||||
|
{
|
||||||
|
wxPen pen( m_grey, 1, wxPENSTYLE_SOLID );
|
||||||
|
|
||||||
|
aDC.SetPen( pen );
|
||||||
|
aDC.DrawLine( aRect.x, aRect.y + aRect.height / 2, aRect.x + aRect.width,
|
||||||
|
aRect.y + aRect.height / 2 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxCoord x, y;
|
||||||
|
|
||||||
|
if( aFlags & wxODCB_PAINTING_CONTROL )
|
||||||
|
{
|
||||||
|
x = aRect.x + GetMargins().x;
|
||||||
|
y = ( aRect.height - aDC.GetCharHeight() ) / 2 + aRect.y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = aRect.x + 2;
|
||||||
|
y = aRect.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this item has a footprint and that footprint has a ":" delimiter, find the
|
||||||
|
// library component, then find that in the display string and grey it out.
|
||||||
|
|
||||||
|
size_t start_grey = 0;
|
||||||
|
size_t end_grey = 0;
|
||||||
|
|
||||||
|
wxString lib = static_cast<wxStringClientData*>( GetClientObject( aItem ) )->GetData();
|
||||||
|
size_t colon_index = lib.rfind( ':' );
|
||||||
|
|
||||||
|
if( colon_index != wxString::npos )
|
||||||
|
{
|
||||||
|
wxString library_part = lib.SubString( 0, colon_index );
|
||||||
|
size_t library_index = text.rfind( library_part );
|
||||||
|
|
||||||
|
if( library_index != wxString::npos )
|
||||||
|
{
|
||||||
|
start_grey = library_index;
|
||||||
|
end_grey = start_grey + library_part.Length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( start_grey != end_grey && !( aFlags & wxODCB_PAINTING_SELECTED ) )
|
||||||
|
{
|
||||||
|
x = DrawTextFragment( aDC, x, y, text.SubString( 0, start_grey - 1 ) );
|
||||||
|
|
||||||
|
wxColour standard_color = aDC.GetTextForeground();
|
||||||
|
|
||||||
|
aDC.SetTextForeground( m_grey );
|
||||||
|
x = DrawTextFragment( aDC, x, y, text.SubString( start_grey, end_grey - 1 ) );
|
||||||
|
|
||||||
|
aDC.SetTextForeground( standard_color );
|
||||||
|
x = DrawTextFragment( aDC, x, y, text.SubString( end_grey, text.Length() - 1 ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aDC.DrawText( text, x, y );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wxCoord FOOTPRINT_CHOICE::OnMeasureItem( size_t aItem ) const
|
||||||
|
{
|
||||||
|
if( SafeGetString( aItem ) == "" )
|
||||||
|
return 11;
|
||||||
|
else
|
||||||
|
return wxOwnerDrawnComboBox::OnMeasureItem( aItem );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxCoord FOOTPRINT_CHOICE::OnMeasureItemWidth( size_t aItem ) const
|
||||||
|
{
|
||||||
|
if( SafeGetString( aItem ) == "" )
|
||||||
|
return GetTextRect().GetWidth() - 2;
|
||||||
|
else
|
||||||
|
return wxOwnerDrawnComboBox::OnMeasureItemWidth( aItem );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxCoord FOOTPRINT_CHOICE::DrawTextFragment( wxDC& aDC, wxCoord x, wxCoord y, wxString const& aText )
|
||||||
|
{
|
||||||
|
aDC.DrawText( aText, x, y );
|
||||||
|
return x + aDC.GetTextExtent( aText ).GetWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_CHOICE::TryVetoMouse( wxMouseEvent& aEvent )
|
||||||
|
{
|
||||||
|
int item = GetVListBoxComboPopup()->VirtualHitTest( aEvent.GetPosition().y );
|
||||||
|
|
||||||
|
if( SafeGetString( item ) != "" )
|
||||||
|
aEvent.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_CHOICE::OnMouseUp( wxMouseEvent& aEvent )
|
||||||
|
{
|
||||||
|
int item = GetVListBoxComboPopup()->VirtualHitTest( aEvent.GetPosition().y );
|
||||||
|
|
||||||
|
wxCommandEvent evt( EVT_INTERACTIVE_CHOICE );
|
||||||
|
evt.SetInt( item );
|
||||||
|
wxPostEvent( this, evt );
|
||||||
|
|
||||||
|
aEvent.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_CHOICE::OnKeyUp( wxKeyEvent& aEvent )
|
||||||
|
{
|
||||||
|
int item = GetSelectionEither( true );
|
||||||
|
|
||||||
|
if( aEvent.GetKeyCode() == WXK_RETURN )
|
||||||
|
{
|
||||||
|
wxCommandEvent evt( EVT_INTERACTIVE_CHOICE );
|
||||||
|
evt.SetInt( item );
|
||||||
|
wxPostEvent( this, evt );
|
||||||
|
}
|
||||||
|
|
||||||
|
aEvent.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_CHOICE::TryVetoSelect( wxCommandEvent& aEvent, bool aInner )
|
||||||
|
{
|
||||||
|
int sel = GetSelectionEither( aInner );
|
||||||
|
|
||||||
|
if( sel >= 0 && sel < (int) GetCount() )
|
||||||
|
{
|
||||||
|
wxString text = SafeGetString( sel );
|
||||||
|
|
||||||
|
if( text == "" )
|
||||||
|
SetSelectionEither( aInner, m_last_selection );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_last_selection = sel;
|
||||||
|
aEvent.Skip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_CHOICE::TrySkipSeparator( wxKeyEvent& aEvent, bool aInner )
|
||||||
|
{
|
||||||
|
int key = aEvent.GetKeyCode();
|
||||||
|
int sel = GetSelectionEither( aInner );
|
||||||
|
int new_sel = sel;
|
||||||
|
|
||||||
|
if( key == WXK_UP && SafeGetString( sel - 1 ) == wxEmptyString )
|
||||||
|
{
|
||||||
|
new_sel = sel - 2;
|
||||||
|
}
|
||||||
|
else if( key == WXK_DOWN && SafeGetString( sel + 1 ) == wxEmptyString )
|
||||||
|
{
|
||||||
|
new_sel = sel + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( new_sel != sel )
|
||||||
|
SetSelectionEither( aInner, new_sel );
|
||||||
|
else
|
||||||
|
aEvent.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString FOOTPRINT_CHOICE::SafeGetString( int aItem ) const
|
||||||
|
{
|
||||||
|
if( aItem >= 0 && aItem < (int) GetCount() )
|
||||||
|
return GetVListBoxComboPopup()->GetString( aItem );
|
||||||
|
else
|
||||||
|
return wxEmptyString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int FOOTPRINT_CHOICE::GetSelectionEither( bool aInner ) const
|
||||||
|
{
|
||||||
|
if( aInner )
|
||||||
|
return GetVListBoxComboPopup()->wxVListBox::GetSelection();
|
||||||
|
else
|
||||||
|
return GetSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_CHOICE::SetSelectionEither( bool aInner, int aSel )
|
||||||
|
{
|
||||||
|
if( aSel >= 0 && aSel < (int) GetCount() )
|
||||||
|
{
|
||||||
|
if( aInner )
|
||||||
|
return GetVListBoxComboPopup()->wxVListBox::SetSelection( aSel );
|
||||||
|
else
|
||||||
|
return SetSelection( aSel );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,304 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dialog_shim.h>
|
||||||
|
#include <kiway.h>
|
||||||
|
#include <kiway_player.h>
|
||||||
|
#include <make_unique.h>
|
||||||
|
#include <project.h>
|
||||||
|
#include <widgets/footprint_choice.h>
|
||||||
|
#include <widgets/footprint_select_widget.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <wx/combo.h>
|
||||||
|
#include <wx/gauge.h>
|
||||||
|
#include <wx/odcombo.h>
|
||||||
|
#include <wx/simplebook.h>
|
||||||
|
#include <wx/sizer.h>
|
||||||
|
#include <wx/timer.h>
|
||||||
|
#include <wx/utils.h>
|
||||||
|
#include <wx/wupdlock.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fixed positions for standard items in the list
|
||||||
|
*/
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
POS_DEFAULT,
|
||||||
|
POS_OTHER,
|
||||||
|
POS_SEPARATOR
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page numbers in the wxSimplebook
|
||||||
|
*/
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PAGE_PROGRESS,
|
||||||
|
PAGE_SELECT
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
wxDEFINE_EVENT( EVT_FOOTPRINT_SELECTED, wxCommandEvent );
|
||||||
|
|
||||||
|
|
||||||
|
FOOTPRINT_SELECT_WIDGET::FOOTPRINT_SELECT_WIDGET( wxWindow* aParent,
|
||||||
|
FOOTPRINT_ASYNC_LOADER& aLoader, std::unique_ptr<FOOTPRINT_LIST>& aFpList, bool aUpdate,
|
||||||
|
int aMaxItems )
|
||||||
|
: wxPanel( aParent ),
|
||||||
|
m_kiway( nullptr ),
|
||||||
|
m_update( aUpdate ),
|
||||||
|
m_finished_loading( false ),
|
||||||
|
m_max_items( aMaxItems ),
|
||||||
|
m_last_item( 0 ),
|
||||||
|
m_fp_loader( aLoader ),
|
||||||
|
m_fp_list( aFpList )
|
||||||
|
{
|
||||||
|
m_sizer = new wxBoxSizer( wxVERTICAL );
|
||||||
|
m_progress_timer = std::make_unique<wxTimer>( this );
|
||||||
|
m_book = new wxSimplebook( this, wxID_ANY );
|
||||||
|
m_progress_ctrl = new wxGauge( m_book, wxID_ANY, 100 );
|
||||||
|
m_fp_sel_ctrl = new FOOTPRINT_CHOICE( m_book, wxID_ANY );
|
||||||
|
|
||||||
|
m_book->SetEffect( wxSHOW_EFFECT_BLEND );
|
||||||
|
m_book->AddPage( m_progress_ctrl, "", true );
|
||||||
|
m_book->AddPage( m_fp_sel_ctrl, "", false );
|
||||||
|
m_sizer->Add( m_book, 1, wxEXPAND | wxALL, 5 );
|
||||||
|
|
||||||
|
SetSizer( m_sizer );
|
||||||
|
Layout();
|
||||||
|
m_sizer->Fit( this );
|
||||||
|
|
||||||
|
Bind( wxEVT_TIMER, &FOOTPRINT_SELECT_WIDGET::OnProgressTimer, this, m_progress_timer->GetId() );
|
||||||
|
m_fp_sel_ctrl->Bind( wxEVT_COMBOBOX, &FOOTPRINT_SELECT_WIDGET::OnComboBox, this );
|
||||||
|
m_fp_sel_ctrl->Bind(
|
||||||
|
EVT_INTERACTIVE_CHOICE, &FOOTPRINT_SELECT_WIDGET::OnComboInteractive, this );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_SELECT_WIDGET::Load( KIWAY& aKiway, PROJECT& aProject )
|
||||||
|
{
|
||||||
|
m_kiway = &aKiway;
|
||||||
|
auto fp_lib_table = aProject.PcbFootprintLibs( aKiway );
|
||||||
|
|
||||||
|
if( m_fp_loader.GetProgress() == 0 || !m_fp_loader.IsSameTable( fp_lib_table ) )
|
||||||
|
{
|
||||||
|
m_fp_list = FOOTPRINT_LIST::GetInstance( aKiway );
|
||||||
|
m_fp_loader.SetList( &*m_fp_list );
|
||||||
|
m_fp_loader.Start( fp_lib_table );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_progress_timer->Start( 200 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_SELECT_WIDGET::OnProgressTimer( wxTimerEvent& aEvent )
|
||||||
|
{
|
||||||
|
int prog = m_fp_loader.GetProgress();
|
||||||
|
m_progress_ctrl->SetValue( prog );
|
||||||
|
|
||||||
|
if( prog == 100 )
|
||||||
|
{
|
||||||
|
wxBusyCursor busy;
|
||||||
|
|
||||||
|
m_fp_loader.Join();
|
||||||
|
m_fp_filter.SetList( *m_fp_list );
|
||||||
|
m_progress_timer->Stop();
|
||||||
|
|
||||||
|
m_book->SetSelection( PAGE_SELECT );
|
||||||
|
m_finished_loading = true;
|
||||||
|
|
||||||
|
if( m_update )
|
||||||
|
UpdateList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_SELECT_WIDGET::OnComboBox( wxCommandEvent& aEvent )
|
||||||
|
{
|
||||||
|
wxCommandEvent evt( EVT_FOOTPRINT_SELECTED );
|
||||||
|
int sel = m_fp_sel_ctrl->GetSelection();
|
||||||
|
|
||||||
|
switch( sel )
|
||||||
|
{
|
||||||
|
case wxNOT_FOUND: return;
|
||||||
|
|
||||||
|
case POS_SEPARATOR:
|
||||||
|
// User somehow managed to select the separator. This should not be
|
||||||
|
// possible, but just in case... deselect it
|
||||||
|
m_fp_sel_ctrl->SetSelection( m_last_item );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case POS_OTHER:
|
||||||
|
// When POS_OTHER is selected, a dialog should be shown. However, we don't want to
|
||||||
|
// do this ALL the time, as some times (e.g. when moving around with the arrow keys)
|
||||||
|
// it could be very annoying. Therefore showing the picker is done from the custom
|
||||||
|
// "interactive select" event on FOOTPRINT_CHOICE, which only fires for more direct
|
||||||
|
// choice actions.
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
wxStringClientData* clientdata =
|
||||||
|
static_cast<wxStringClientData*>( m_fp_sel_ctrl->GetClientObject( sel ) );
|
||||||
|
wxASSERT( clientdata );
|
||||||
|
|
||||||
|
evt.SetString( clientdata->GetData() );
|
||||||
|
wxPostEvent( this, evt );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_SELECT_WIDGET::OnComboInteractive( wxCommandEvent& aEvent )
|
||||||
|
{
|
||||||
|
if( aEvent.GetInt() == POS_OTHER && !m_fp_sel_ctrl->IsPopupShown() )
|
||||||
|
{
|
||||||
|
DoOther();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_SELECT_WIDGET::DoOther()
|
||||||
|
{
|
||||||
|
wxCommandEvent evt( EVT_FOOTPRINT_SELECTED );
|
||||||
|
|
||||||
|
wxString fpname = ShowPicker();
|
||||||
|
m_other_footprint = fpname;
|
||||||
|
UpdateList();
|
||||||
|
m_fp_sel_ctrl->SetSelection( POS_OTHER );
|
||||||
|
m_last_item = POS_OTHER;
|
||||||
|
|
||||||
|
evt.SetString( m_other_footprint );
|
||||||
|
wxPostEvent( this, evt );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString FOOTPRINT_SELECT_WIDGET::ShowPicker()
|
||||||
|
{
|
||||||
|
wxString fpname;
|
||||||
|
wxWindow* parent = ::wxGetTopLevelParent( this );
|
||||||
|
DIALOG_SHIM* dsparent = dynamic_cast<DIALOG_SHIM*>( parent );
|
||||||
|
|
||||||
|
// Only quasimodal dialogs can launch modal kiface dialogs. Otherwise the
|
||||||
|
// event loop goes all silly.
|
||||||
|
wxASSERT( !dsparent || dsparent->IsQuasiModal() );
|
||||||
|
|
||||||
|
auto frame = m_kiway->Player( FRAME_PCB_MODULE_VIEWER_MODAL, true );
|
||||||
|
|
||||||
|
if( !frame->ShowModal( &fpname, parent ) )
|
||||||
|
{
|
||||||
|
fpname = wxEmptyString;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame->Destroy();
|
||||||
|
|
||||||
|
return fpname;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_SELECT_WIDGET::ClearFilters()
|
||||||
|
{
|
||||||
|
m_fp_filter.ClearFilters();
|
||||||
|
m_default_footprint.Clear();
|
||||||
|
m_other_footprint.Clear();
|
||||||
|
m_zero_filter = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_SELECT_WIDGET::FilterByPinCount( int aPinCount )
|
||||||
|
{
|
||||||
|
m_fp_filter.FilterByPinCount( aPinCount );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_SELECT_WIDGET::FilterByFootprintFilters(
|
||||||
|
wxArrayString const& aFilters, bool aZeroFilters )
|
||||||
|
{
|
||||||
|
if( aZeroFilters && aFilters.size() == 0 )
|
||||||
|
m_zero_filter = true;
|
||||||
|
else
|
||||||
|
m_zero_filter = false;
|
||||||
|
|
||||||
|
m_fp_filter.FilterByFootprintFilters( aFilters );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_SELECT_WIDGET::SetDefaultFootprint( wxString const& aFp )
|
||||||
|
{
|
||||||
|
m_default_footprint = aFp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool FOOTPRINT_SELECT_WIDGET::UpdateList()
|
||||||
|
{
|
||||||
|
int n_items = 0;
|
||||||
|
|
||||||
|
if( !m_fp_list || !m_finished_loading )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wxWindowUpdateLocker lock( m_fp_sel_ctrl );
|
||||||
|
m_fp_sel_ctrl->Clear();
|
||||||
|
|
||||||
|
// Be careful adding items! "Default" must occupy POS_DEFAULT,
|
||||||
|
// "Other" must occupy POS_OTHER, and the separator must occupy POS_SEPARATOR.
|
||||||
|
|
||||||
|
m_fp_sel_ctrl->Append( m_default_footprint.IsEmpty() ?
|
||||||
|
_( "No default footprint" ) :
|
||||||
|
"[" + _( "Default" ) + "] " + m_default_footprint,
|
||||||
|
new wxStringClientData( m_default_footprint ) );
|
||||||
|
|
||||||
|
m_fp_sel_ctrl->Append( m_other_footprint.IsEmpty() ?
|
||||||
|
_( "Other..." ) :
|
||||||
|
"[" + _( "Other..." ) + "] " + m_other_footprint,
|
||||||
|
new wxStringClientData( m_other_footprint ) );
|
||||||
|
|
||||||
|
m_fp_sel_ctrl->Append( "", new wxStringClientData( "" ) );
|
||||||
|
|
||||||
|
if( !m_zero_filter )
|
||||||
|
{
|
||||||
|
for( auto& fpinfo : m_fp_filter )
|
||||||
|
{
|
||||||
|
wxString display_name( fpinfo.GetNickname() + ":" + fpinfo.GetFootprintName() );
|
||||||
|
|
||||||
|
m_fp_sel_ctrl->Append( display_name, new wxStringClientData( display_name ) );
|
||||||
|
++n_items;
|
||||||
|
|
||||||
|
if( n_items >= m_max_items )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectDefault();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_SELECT_WIDGET::SelectDefault()
|
||||||
|
{
|
||||||
|
m_fp_sel_ctrl->SetSelection( POS_DEFAULT );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool FOOTPRINT_SELECT_WIDGET::Enable( bool aEnable )
|
||||||
|
{
|
||||||
|
return m_fp_sel_ctrl->Enable( aEnable );
|
||||||
|
}
|
|
@ -1,7 +1,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) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 1992-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
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -215,7 +215,7 @@ void CVPCB_MAINFRAME::AutomaticFootprintMatching( wxCommandEvent& event )
|
||||||
if( equivItem.m_ComponentValue.CmpNoCase( component->GetValue() ) != 0 )
|
if( equivItem.m_ComponentValue.CmpNoCase( component->GetValue() ) != 0 )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const FOOTPRINT_INFO *module = m_FootprintsList.GetModuleInfo( equivItem.m_FootprintFPID );
|
const FOOTPRINT_INFO *module = m_FootprintsList->GetModuleInfo( equivItem.m_FootprintFPID );
|
||||||
|
|
||||||
bool equ_is_unique = true;
|
bool equ_is_unique = true;
|
||||||
unsigned next = idx+1;
|
unsigned next = idx+1;
|
||||||
|
@ -277,7 +277,7 @@ void CVPCB_MAINFRAME::AutomaticFootprintMatching( wxCommandEvent& event )
|
||||||
{
|
{
|
||||||
// we do not need to analyze wildcards: single footprint do not
|
// we do not need to analyze wildcards: single footprint do not
|
||||||
// contain them and if there are wildcards it just will not match any
|
// contain them and if there are wildcards it just will not match any
|
||||||
const FOOTPRINT_INFO* module = m_FootprintsList.GetModuleInfo( component->GetFootprintFilters()[0] );
|
const FOOTPRINT_INFO* module = m_FootprintsList->GetModuleInfo( component->GetFootprintFilters()[0] );
|
||||||
|
|
||||||
if( module )
|
if( module )
|
||||||
SetNewPkg( component->GetFootprintFilters()[0] );
|
SetNewPkg( component->GetFootprintFilters()[0] );
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||||
* Copyright (C) 2015-2016 Wayne Stambaugh <stambaughw@verizon.net>
|
* Copyright (C) 2015-2016 Wayne Stambaugh <stambaughw@verizon.net>
|
||||||
* Copyright (C) 2007-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 2007-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
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -459,7 +459,7 @@ MODULE* DISPLAY_FOOTPRINTS_FRAME::Get_Module( const wxString& aFootprintName )
|
||||||
wxLogDebug( wxT( "Load footprint <%s> from library <%s>." ),
|
wxLogDebug( wxT( "Load footprint <%s> from library <%s>." ),
|
||||||
fpname.c_str(), nickname.c_str() );
|
fpname.c_str(), nickname.c_str() );
|
||||||
|
|
||||||
footprint = Prj().PcbFootprintLibs()->FootprintLoad(
|
footprint = Prj().PcbFootprintLibs( Kiway() )->FootprintLoad(
|
||||||
FROM_UTF8( nickname.c_str() ), FROM_UTF8( fpname.c_str() ) );
|
FROM_UTF8( nickname.c_str() ), FROM_UTF8( fpname.c_str() ) );
|
||||||
}
|
}
|
||||||
catch( const IO_ERROR& ioe )
|
catch( const IO_ERROR& ioe )
|
||||||
|
@ -495,7 +495,7 @@ void DISPLAY_FOOTPRINTS_FRAME::InitDisplay()
|
||||||
|
|
||||||
SetTitle( msg );
|
SetTitle( msg );
|
||||||
const FOOTPRINT_INFO* module_info =
|
const FOOTPRINT_INFO* module_info =
|
||||||
parentframe->m_FootprintsList.GetModuleInfo( footprintName );
|
parentframe->m_FootprintsList->GetModuleInfo( footprintName );
|
||||||
|
|
||||||
const wxChar* libname;
|
const wxChar* libname;
|
||||||
|
|
||||||
|
|
|
@ -29,12 +29,14 @@
|
||||||
|
|
||||||
#include <fctsys.h>
|
#include <fctsys.h>
|
||||||
#include <wxstruct.h>
|
#include <wxstruct.h>
|
||||||
|
#include <wx/wupdlock.h>
|
||||||
|
|
||||||
#include <cvpcb.h>
|
#include <cvpcb.h>
|
||||||
#include <cvpcb_mainframe.h>
|
#include <cvpcb_mainframe.h>
|
||||||
#include <listview_classes.h>
|
#include <listview_classes.h>
|
||||||
#include <cvpcb_id.h>
|
#include <cvpcb_id.h>
|
||||||
#include <eda_pattern_match.h>
|
#include <eda_pattern_match.h>
|
||||||
|
#include <footprint_filter.h>
|
||||||
|
|
||||||
|
|
||||||
FOOTPRINTS_LISTBOX::FOOTPRINTS_LISTBOX( CVPCB_MAINFRAME* parent,
|
FOOTPRINTS_LISTBOX::FOOTPRINTS_LISTBOX( CVPCB_MAINFRAME* parent,
|
||||||
|
@ -133,62 +135,28 @@ void FOOTPRINTS_LISTBOX::SetFootprints( FOOTPRINT_LIST& aList, const wxString& a
|
||||||
wxString msg;
|
wxString msg;
|
||||||
wxString oldSelection;
|
wxString oldSelection;
|
||||||
|
|
||||||
EDA_PATTERN_MATCH_WILDCARD patternFilter;
|
FOOTPRINT_FILTER filter( aList );
|
||||||
patternFilter.SetPattern( aFootPrintFilterPattern.Lower() ); // Use case insensitive search
|
|
||||||
|
if( aFilterType & FILTERING_BY_COMPONENT_KEYWORD )
|
||||||
|
filter.FilterByFootprintFilters( aComponent->GetFootprintFilters() );
|
||||||
|
|
||||||
|
if( aFilterType & FILTERING_BY_PIN_COUNT )
|
||||||
|
filter.FilterByPinCount( aComponent->GetNetCount() );
|
||||||
|
|
||||||
|
if( aFilterType & FILTERING_BY_LIBRARY )
|
||||||
|
filter.FilterByLibrary( aLibName );
|
||||||
|
|
||||||
|
if( aFilterType & FILTERING_BY_NAME )
|
||||||
|
filter.FilterByPattern( aFootPrintFilterPattern );
|
||||||
|
|
||||||
if( GetSelection() >= 0 && GetSelection() < (int)m_footprintList.GetCount() )
|
if( GetSelection() >= 0 && GetSelection() < (int)m_footprintList.GetCount() )
|
||||||
oldSelection = m_footprintList[ GetSelection() ];
|
oldSelection = m_footprintList[ GetSelection() ];
|
||||||
|
|
||||||
for( unsigned ii = 0; ii < aList.GetCount(); ii++ )
|
for( auto& i: filter )
|
||||||
{
|
{
|
||||||
if( aFilterType == UNFILTERED_FP_LIST )
|
msg.Printf( "%3d %s:%s", int( newList.GetCount() + 1 ),
|
||||||
{
|
GetChars( i.GetNickname() ),
|
||||||
msg.Printf( wxT( "%3d %s:%s" ), int( newList.GetCount() + 1 ),
|
GetChars( i.GetFootprintName() ) );
|
||||||
GetChars( aList.GetItem( ii ).GetNickname() ),
|
|
||||||
GetChars( aList.GetItem( ii ).GetFootprintName() ) );
|
|
||||||
newList.Add( msg );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter footprints by selected library
|
|
||||||
if( (aFilterType & FILTERING_BY_LIBRARY) && !aLibName.IsEmpty()
|
|
||||||
&& !aList.GetItem( ii ).InLibrary( aLibName ) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Filter footprints by symbol fp-filters
|
|
||||||
if( (aFilterType & FILTERING_BY_COMPONENT_KEYWORD) && aComponent
|
|
||||||
&& !aComponent->MatchesFootprintFilters( aList.GetItem( ii ).GetNickname(), aList.GetItem( ii ).GetFootprintName() ) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Filter footprints by symbol pin-count
|
|
||||||
if( (aFilterType & FILTERING_BY_PIN_COUNT) && aComponent
|
|
||||||
&& aComponent->GetNetCount() != aList.GetItem( ii ).GetUniquePadCount() )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Filter footprints by text-input
|
|
||||||
if( (aFilterType & FILTERING_BY_NAME ) && !aFootPrintFilterPattern.IsEmpty() )
|
|
||||||
{
|
|
||||||
wxString currname = "";
|
|
||||||
|
|
||||||
// If the search string contains a ':' character,
|
|
||||||
// include the library name in the search string
|
|
||||||
// e.g. LibName:FootprintName
|
|
||||||
if( aFootPrintFilterPattern.Contains( ":" ) )
|
|
||||||
{
|
|
||||||
currname = aList.GetItem( ii ).GetNickname().Lower() + ":";
|
|
||||||
}
|
|
||||||
|
|
||||||
currname += aList.GetItem( ii ).GetFootprintName().Lower();
|
|
||||||
|
|
||||||
if( patternFilter.Find( currname ) == EDA_PATTERN_NOT_FOUND )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
msg.Printf( wxT( "%3d %s:%s" ), int( newList.GetCount() + 1 ),
|
|
||||||
GetChars( aList.GetItem( ii ).GetNickname() ),
|
|
||||||
GetChars( aList.GetItem( ii ).GetFootprintName() ) );
|
|
||||||
newList.Add( msg );
|
newList.Add( msg );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,6 +170,7 @@ void FOOTPRINTS_LISTBOX::SetFootprints( FOOTPRINT_LIST& aList, const wxString& a
|
||||||
if( selection == wxNOT_FOUND )
|
if( selection == wxNOT_FOUND )
|
||||||
selection = 0;
|
selection = 0;
|
||||||
|
|
||||||
|
wxWindowUpdateLocker freeze( this );
|
||||||
DeleteAllItems();
|
DeleteAllItems();
|
||||||
|
|
||||||
if( m_footprintList.GetCount() )
|
if( m_footprintList.GetCount() )
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||||
* Copyright (C) 2011-2016 Wayne Stambaugh <stambaughw@verizon.net>
|
* Copyright (C) 2011-2016 Wayne Stambaugh <stambaughw@verizon.net>
|
||||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 1992-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
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -127,6 +127,7 @@ CVPCB_MAINFRAME::CVPCB_MAINFRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||||
m_skipComponentSelect = false;
|
m_skipComponentSelect = false;
|
||||||
m_filteringOptions = 0;
|
m_filteringOptions = 0;
|
||||||
m_tcFilterString = NULL;
|
m_tcFilterString = NULL;
|
||||||
|
m_FootprintsList = FOOTPRINT_LIST::GetInstance( Kiway() );
|
||||||
|
|
||||||
/* Name of the document footprint list
|
/* Name of the document footprint list
|
||||||
* usually located in share/modules/footprints_doc
|
* usually located in share/modules/footprints_doc
|
||||||
|
@ -409,7 +410,7 @@ bool CVPCB_MAINFRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, i
|
||||||
void CVPCB_MAINFRAME::OnEditFootprintLibraryTable( wxCommandEvent& aEvent )
|
void CVPCB_MAINFRAME::OnEditFootprintLibraryTable( wxCommandEvent& aEvent )
|
||||||
{
|
{
|
||||||
bool tableChanged = false;
|
bool tableChanged = false;
|
||||||
int r = InvokePcbLibTableEditor( this, &GFootprintTable, Prj().PcbFootprintLibs() );
|
int r = InvokePcbLibTableEditor( this, &GFootprintTable, Prj().PcbFootprintLibs( Kiway() ) );
|
||||||
|
|
||||||
if( r & 1 )
|
if( r & 1 )
|
||||||
{
|
{
|
||||||
|
@ -437,7 +438,7 @@ void CVPCB_MAINFRAME::OnEditFootprintLibraryTable( wxCommandEvent& aEvent )
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Prj().PcbFootprintLibs()->Save( fileName );
|
Prj().PcbFootprintLibs( Kiway() )->Save( fileName );
|
||||||
tableChanged = true;
|
tableChanged = true;
|
||||||
}
|
}
|
||||||
catch( const IO_ERROR& ioe )
|
catch( const IO_ERROR& ioe )
|
||||||
|
@ -455,7 +456,7 @@ void CVPCB_MAINFRAME::OnEditFootprintLibraryTable( wxCommandEvent& aEvent )
|
||||||
{
|
{
|
||||||
wxBusyCursor dummy;
|
wxBusyCursor dummy;
|
||||||
BuildLIBRARY_LISTBOX();
|
BuildLIBRARY_LISTBOX();
|
||||||
m_FootprintsList.ReadFootprintFiles( Prj().PcbFootprintLibs() );
|
m_FootprintsList->ReadFootprintFiles( Prj().PcbFootprintLibs( Kiway() ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,7 +483,7 @@ void CVPCB_MAINFRAME::OnSelectComponent( wxListEvent& event )
|
||||||
COMPONENT* component = GetSelectedComponent();
|
COMPONENT* component = GetSelectedComponent();
|
||||||
libraryName = m_libListBox->GetSelectedLibrary();
|
libraryName = m_libListBox->GetSelectedLibrary();
|
||||||
|
|
||||||
m_footprintListBox->SetFootprints( m_FootprintsList, libraryName, component,
|
m_footprintListBox->SetFootprints( *m_FootprintsList, libraryName, component,
|
||||||
m_currentSearchPattern, m_filteringOptions);
|
m_currentSearchPattern, m_filteringOptions);
|
||||||
|
|
||||||
refreshAfterComponentSearch (component);
|
refreshAfterComponentSearch (component);
|
||||||
|
@ -657,7 +658,7 @@ void CVPCB_MAINFRAME::DisplayStatus()
|
||||||
{
|
{
|
||||||
wxString footprintName = GetSelectedFootprint();
|
wxString footprintName = GetSelectedFootprint();
|
||||||
|
|
||||||
FOOTPRINT_INFO* module = m_FootprintsList.GetModuleInfo( footprintName );
|
FOOTPRINT_INFO* module = m_FootprintsList->GetModuleInfo( footprintName );
|
||||||
|
|
||||||
if( module ) // can be NULL if no netlist loaded
|
if( module ) // can be NULL if no netlist loaded
|
||||||
{
|
{
|
||||||
|
@ -715,7 +716,7 @@ void CVPCB_MAINFRAME::DisplayStatus()
|
||||||
|
|
||||||
bool CVPCB_MAINFRAME::LoadFootprintFiles()
|
bool CVPCB_MAINFRAME::LoadFootprintFiles()
|
||||||
{
|
{
|
||||||
FP_LIB_TABLE* fptbl = Prj().PcbFootprintLibs();
|
FP_LIB_TABLE* fptbl = Prj().PcbFootprintLibs( Kiway() );
|
||||||
|
|
||||||
// Check if there are footprint libraries in the footprint library table.
|
// Check if there are footprint libraries in the footprint library table.
|
||||||
if( !fptbl || !fptbl->GetLogicalLibs().size() )
|
if( !fptbl || !fptbl->GetLogicalLibs().size() )
|
||||||
|
@ -728,12 +729,12 @@ bool CVPCB_MAINFRAME::LoadFootprintFiles()
|
||||||
{
|
{
|
||||||
wxBusyCursor dummy; // Let the user know something is happening.
|
wxBusyCursor dummy; // Let the user know something is happening.
|
||||||
|
|
||||||
m_FootprintsList.ReadFootprintFiles( fptbl );
|
m_FootprintsList->ReadFootprintFiles( fptbl );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( m_FootprintsList.GetErrorCount() )
|
if( m_FootprintsList->GetErrorCount() )
|
||||||
{
|
{
|
||||||
m_FootprintsList.DisplayErrors( this );
|
m_FootprintsList->DisplayErrors( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -862,7 +863,7 @@ void CVPCB_MAINFRAME::BuildFOOTPRINTS_LISTBOX()
|
||||||
wxFONTWEIGHT_NORMAL ) );
|
wxFONTWEIGHT_NORMAL ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_footprintListBox->SetFootprints( m_FootprintsList, wxEmptyString, NULL,
|
m_footprintListBox->SetFootprints( *m_FootprintsList, wxEmptyString, NULL,
|
||||||
wxEmptyString, FOOTPRINTS_LISTBOX::UNFILTERED_FP_LIST );
|
wxEmptyString, FOOTPRINTS_LISTBOX::UNFILTERED_FP_LIST );
|
||||||
DisplayStatus();
|
DisplayStatus();
|
||||||
}
|
}
|
||||||
|
@ -921,7 +922,7 @@ void CVPCB_MAINFRAME::BuildLIBRARY_LISTBOX()
|
||||||
wxFONTWEIGHT_NORMAL ) );
|
wxFONTWEIGHT_NORMAL ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
FP_LIB_TABLE* tbl = Prj().PcbFootprintLibs();
|
FP_LIB_TABLE* tbl = Prj().PcbFootprintLibs( Kiway() );
|
||||||
|
|
||||||
if( tbl )
|
if( tbl )
|
||||||
{
|
{
|
||||||
|
|
|
@ -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) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 1992-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
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -37,6 +37,7 @@
|
||||||
#include <wxBasePcbFrame.h>
|
#include <wxBasePcbFrame.h>
|
||||||
#include <config_params.h>
|
#include <config_params.h>
|
||||||
#include <autosel.h>
|
#include <autosel.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
|
||||||
/* Forward declarations of all top-level window classes. */
|
/* Forward declarations of all top-level window classes. */
|
||||||
|
@ -72,7 +73,7 @@ public:
|
||||||
wxArrayString m_ModuleLibNames;
|
wxArrayString m_ModuleLibNames;
|
||||||
wxArrayString m_EquFilesNames;
|
wxArrayString m_EquFilesNames;
|
||||||
wxString m_DocModulesFileName;
|
wxString m_DocModulesFileName;
|
||||||
FOOTPRINT_LIST m_FootprintsList;
|
std::unique_ptr<FOOTPRINT_LIST> m_FootprintsList;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int m_undefinedComponentCnt;
|
int m_undefinedComponentCnt;
|
||||||
|
|
|
@ -1,7 +1,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) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 1992-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
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
#define CVSTRUCT_H
|
#define CVSTRUCT_H
|
||||||
|
|
||||||
#include <wx/listctrl.h>
|
#include <wx/listctrl.h>
|
||||||
|
#include <footprint_filter.h>
|
||||||
|
|
||||||
/* Forward declarations of all top-level window classes. */
|
/* Forward declarations of all top-level window classes. */
|
||||||
class CVPCB_MAINFRAME;
|
class CVPCB_MAINFRAME;
|
||||||
|
@ -90,8 +90,12 @@ private:
|
||||||
wxArrayString m_footprintList;
|
wxArrayString m_footprintList;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// OR'ed mask to manage footprint filtering options
|
|
||||||
enum FP_FILTER_T
|
/**
|
||||||
|
* Filter setting constants. The filter type is a bitwise OR of these flags,
|
||||||
|
* and only footprints matching all selected filter types are shown.
|
||||||
|
*/
|
||||||
|
enum FP_FILTER_T: int
|
||||||
{
|
{
|
||||||
UNFILTERED_FP_LIST = 0,
|
UNFILTERED_FP_LIST = 0,
|
||||||
FILTERING_BY_COMPONENT_KEYWORD = 0x0001,
|
FILTERING_BY_COMPONENT_KEYWORD = 0x0001,
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2015 Jean-Pierre Charras, jean-pierre.charras
|
* Copyright (C) 2015 Jean-Pierre Charras, jean-pierre.charras
|
||||||
* Copyright (C) 2011-2016 Wayne Stambaugh <stambaughw@verizon.net>
|
* Copyright (C) 2011-2016 Wayne Stambaugh <stambaughw@verizon.net>
|
||||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 1992-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
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -26,7 +26,6 @@
|
||||||
* or you may write to the Free Software Foundation, Inc.,
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <fctsys.h>
|
#include <fctsys.h>
|
||||||
#include <kiway.h>
|
#include <kiway.h>
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
@ -212,7 +211,7 @@ bool CVPCB_MAINFRAME::ReadNetListAndLinkFiles( const std::string& aNetlist )
|
||||||
if( component->GetFPID().IsLegacy() )
|
if( component->GetFPID().IsLegacy() )
|
||||||
{
|
{
|
||||||
// get this first here, it's possibly obsoleted if we get it too soon.
|
// get this first here, it's possibly obsoleted if we get it too soon.
|
||||||
FP_LIB_TABLE* tbl = Prj().PcbFootprintLibs();
|
FP_LIB_TABLE* tbl = Prj().PcbFootprintLibs( Kiway() );
|
||||||
|
|
||||||
int guess = guessNickname( tbl, (LIB_ID*) &component->GetFPID() );
|
int guess = guessNickname( tbl, (LIB_ID*) &component->GetFPID() );
|
||||||
|
|
||||||
|
|
|
@ -25,30 +25,31 @@
|
||||||
|
|
||||||
#include <dialog_choose_component.h>
|
#include <dialog_choose_component.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <wx/tokenzr.h>
|
#include <wx/tokenzr.h>
|
||||||
#include <wx/utils.h>
|
#include <wx/utils.h>
|
||||||
|
|
||||||
#include <wx/artprov.h>
|
#include <wx/artprov.h>
|
||||||
#include <wx/bitmap.h>
|
#include <wx/bitmap.h>
|
||||||
#include <wx/statbmp.h>
|
#include <wx/button.h>
|
||||||
#include <wx/textctrl.h>
|
#include <wx/choice.h>
|
||||||
#include <wx/sizer.h>
|
|
||||||
#include <wx/dataview.h>
|
#include <wx/dataview.h>
|
||||||
#include <wx/html/htmlwin.h>
|
#include <wx/html/htmlwin.h>
|
||||||
#include <wx/panel.h>
|
#include <wx/panel.h>
|
||||||
#include <wx/choice.h>
|
#include <wx/sizer.h>
|
||||||
#include <wx/splitter.h>
|
#include <wx/splitter.h>
|
||||||
#include <wx/button.h>
|
#include <wx/statbmp.h>
|
||||||
|
#include <wx/textctrl.h>
|
||||||
#include <wx/timer.h>
|
#include <wx/timer.h>
|
||||||
#include <wx/utils.h>
|
#include <wx/utils.h>
|
||||||
|
|
||||||
#include <class_library.h>
|
#include <class_library.h>
|
||||||
#include <sch_base_frame.h>
|
|
||||||
#include <widgets/footprint_preview_widget.h>
|
|
||||||
#include <widgets/two_column_tree_list.h>
|
|
||||||
#include <template_fieldnames.h>
|
|
||||||
#include <generate_alias_info.h>
|
#include <generate_alias_info.h>
|
||||||
|
#include <sch_base_frame.h>
|
||||||
|
#include <template_fieldnames.h>
|
||||||
|
#include <widgets/footprint_preview_widget.h>
|
||||||
|
#include <widgets/footprint_select_widget.h>
|
||||||
|
|
||||||
// Tree navigation helpers.
|
// Tree navigation helpers.
|
||||||
static wxDataViewItem GetPrevItem( const wxDataViewCtrl& ctrl, const wxDataViewItem& item );
|
static wxDataViewItem GetPrevItem( const wxDataViewCtrl& ctrl, const wxDataViewItem& item );
|
||||||
|
@ -56,21 +57,25 @@ static wxDataViewItem GetNextItem( const wxDataViewCtrl& ctrl, const wxDataViewI
|
||||||
static wxDataViewItem GetPrevSibling( const wxDataViewCtrl& ctrl, const wxDataViewItem& item );
|
static wxDataViewItem GetPrevSibling( const wxDataViewCtrl& ctrl, const wxDataViewItem& item );
|
||||||
static wxDataViewItem GetNextSibling( const wxDataViewCtrl& ctrl, const wxDataViewItem& item );
|
static wxDataViewItem GetNextSibling( const wxDataViewCtrl& ctrl, const wxDataViewItem& item );
|
||||||
|
|
||||||
DIALOG_CHOOSE_COMPONENT::DIALOG_CHOOSE_COMPONENT(
|
FOOTPRINT_ASYNC_LOADER DIALOG_CHOOSE_COMPONENT::m_fp_loader;
|
||||||
SCH_BASE_FRAME* aParent, const wxString& aTitle,
|
std::unique_ptr<FOOTPRINT_LIST> DIALOG_CHOOSE_COMPONENT::m_fp_list;
|
||||||
CMP_TREE_MODEL_ADAPTER::PTR& aAdapter, int aDeMorganConvert ):
|
|
||||||
DIALOG_SHIM( aParent, wxID_ANY, aTitle, wxDefaultPosition,
|
DIALOG_CHOOSE_COMPONENT::DIALOG_CHOOSE_COMPONENT( SCH_BASE_FRAME* aParent, const wxString& aTitle,
|
||||||
wxSize( 800, 650 ), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ),
|
CMP_TREE_MODEL_ADAPTER::PTR& aAdapter, int aDeMorganConvert, bool aAllowFieldEdits )
|
||||||
|
: DIALOG_SHIM( aParent, wxID_ANY, aTitle, wxDefaultPosition, wxSize( 800, 650 ),
|
||||||
|
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ),
|
||||||
m_parent( aParent ),
|
m_parent( aParent ),
|
||||||
m_adapter( aAdapter ),
|
m_adapter( aAdapter ),
|
||||||
m_deMorganConvert( aDeMorganConvert >= 0 ? aDeMorganConvert : 0 ),
|
m_deMorganConvert( aDeMorganConvert >= 0 ? aDeMorganConvert : 0 ),
|
||||||
|
m_allow_field_edits( aAllowFieldEdits ),
|
||||||
m_external_browser_requested( false )
|
m_external_browser_requested( false )
|
||||||
{
|
{
|
||||||
wxBusyCursor busy_while_loading;
|
wxBusyCursor busy_while_loading;
|
||||||
|
|
||||||
auto sizer = new wxBoxSizer( wxVERTICAL );
|
auto sizer = new wxBoxSizer( wxVERTICAL );
|
||||||
|
|
||||||
auto splitter = new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_LIVE_UPDATE );
|
auto splitter = new wxSplitterWindow(
|
||||||
|
this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_LIVE_UPDATE );
|
||||||
auto left_panel = ConstructLeftPanel( splitter );
|
auto left_panel = ConstructLeftPanel( splitter );
|
||||||
auto right_panel = ConstructRightPanel( splitter );
|
auto right_panel = ConstructRightPanel( splitter );
|
||||||
auto buttons = new wxStdDialogButtonSizer();
|
auto buttons = new wxStdDialogButtonSizer();
|
||||||
|
@ -89,17 +94,23 @@ DIALOG_CHOOSE_COMPONENT::DIALOG_CHOOSE_COMPONENT(
|
||||||
SetSizer( sizer );
|
SetSizer( sizer );
|
||||||
|
|
||||||
Bind( wxEVT_INIT_DIALOG, &DIALOG_CHOOSE_COMPONENT::OnInitDialog, this );
|
Bind( wxEVT_INIT_DIALOG, &DIALOG_CHOOSE_COMPONENT::OnInitDialog, this );
|
||||||
Bind( wxEVT_TIMER, &DIALOG_CHOOSE_COMPONENT::OnCloseTimer, this );
|
Bind( wxEVT_TIMER, &DIALOG_CHOOSE_COMPONENT::OnCloseTimer, this, m_dbl_click_timer->GetId() );
|
||||||
|
|
||||||
m_query_ctrl->Bind( wxEVT_TEXT, &DIALOG_CHOOSE_COMPONENT::OnQueryText, this );
|
m_query_ctrl->Bind( wxEVT_TEXT, &DIALOG_CHOOSE_COMPONENT::OnQueryText, this );
|
||||||
m_query_ctrl->Bind( wxEVT_TEXT_ENTER, &DIALOG_CHOOSE_COMPONENT::OnQueryEnter, this );
|
m_query_ctrl->Bind( wxEVT_TEXT_ENTER, &DIALOG_CHOOSE_COMPONENT::OnQueryEnter, this );
|
||||||
m_query_ctrl->Bind( wxEVT_CHAR_HOOK, &DIALOG_CHOOSE_COMPONENT::OnQueryCharHook, this );
|
m_query_ctrl->Bind( wxEVT_CHAR_HOOK, &DIALOG_CHOOSE_COMPONENT::OnQueryCharHook, this );
|
||||||
m_tree_ctrl->Bind( wxEVT_DATAVIEW_ITEM_ACTIVATED, &DIALOG_CHOOSE_COMPONENT::OnTreeActivate, this );
|
m_tree_ctrl->Bind(
|
||||||
m_tree_ctrl->Bind( wxEVT_DATAVIEW_SELECTION_CHANGED, &DIALOG_CHOOSE_COMPONENT::OnTreeSelect, this );
|
wxEVT_DATAVIEW_ITEM_ACTIVATED, &DIALOG_CHOOSE_COMPONENT::OnTreeActivate, this );
|
||||||
|
m_tree_ctrl->Bind(
|
||||||
|
wxEVT_DATAVIEW_SELECTION_CHANGED, &DIALOG_CHOOSE_COMPONENT::OnTreeSelect, this );
|
||||||
m_details_ctrl->Bind( wxEVT_HTML_LINK_CLICKED, &DIALOG_CHOOSE_COMPONENT::OnDetailsLink, this );
|
m_details_ctrl->Bind( wxEVT_HTML_LINK_CLICKED, &DIALOG_CHOOSE_COMPONENT::OnDetailsLink, this );
|
||||||
m_sch_view_ctrl->Bind( wxEVT_LEFT_DCLICK, &DIALOG_CHOOSE_COMPONENT::OnSchViewDClick, this );
|
m_sch_view_ctrl->Bind( wxEVT_LEFT_DCLICK, &DIALOG_CHOOSE_COMPONENT::OnSchViewDClick, this );
|
||||||
m_sch_view_ctrl->Bind( wxEVT_PAINT, &DIALOG_CHOOSE_COMPONENT::OnSchViewPaint, this );
|
m_sch_view_ctrl->Bind( wxEVT_PAINT, &DIALOG_CHOOSE_COMPONENT::OnSchViewPaint, this );
|
||||||
|
|
||||||
|
if( m_fp_sel_ctrl )
|
||||||
|
m_fp_sel_ctrl->Bind(
|
||||||
|
EVT_FOOTPRINT_SELECTED, &DIALOG_CHOOSE_COMPONENT::OnFootprintSelected, this );
|
||||||
|
|
||||||
Layout();
|
Layout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,24 +132,20 @@ wxPanel* DIALOG_CHOOSE_COMPONENT::ConstructLeftPanel( wxWindow* aParent )
|
||||||
auto sizer = new wxBoxSizer( wxVERTICAL );
|
auto sizer = new wxBoxSizer( wxVERTICAL );
|
||||||
auto search_sizer = new wxBoxSizer( wxHORIZONTAL );
|
auto search_sizer = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
|
||||||
m_query_ctrl = new wxTextCtrl( panel, wxID_ANY,
|
m_query_ctrl = new wxTextCtrl(
|
||||||
wxEmptyString, wxDefaultPosition, wxDefaultSize,
|
panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER );
|
||||||
wxTE_PROCESS_ENTER );
|
|
||||||
|
|
||||||
m_tree_ctrl = new wxDataViewCtrl( panel, wxID_ANY,
|
m_tree_ctrl =
|
||||||
wxDefaultPosition, wxDefaultSize,
|
new wxDataViewCtrl( panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_SINGLE );
|
||||||
wxDV_SINGLE );
|
|
||||||
m_adapter->AttachTo( m_tree_ctrl );
|
m_adapter->AttachTo( m_tree_ctrl );
|
||||||
|
|
||||||
m_details_ctrl = new wxHtmlWindow( panel, wxID_ANY,
|
m_details_ctrl = new wxHtmlWindow( panel, wxID_ANY, wxDefaultPosition, wxSize( 320, 240 ),
|
||||||
wxDefaultPosition, wxSize( 320,240 ),
|
|
||||||
wxHW_SCROLLBAR_AUTO | wxSUNKEN_BORDER );
|
wxHW_SCROLLBAR_AUTO | wxSUNKEN_BORDER );
|
||||||
|
|
||||||
// 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__
|
||||||
search_sizer->Add(
|
search_sizer->Add( new wxStaticBitmap( panel, wxID_ANY,
|
||||||
new wxStaticBitmap(
|
wxArtProvider::GetBitmap( wxART_FIND, wxART_FRAME_ICON ) ),
|
||||||
panel, wxID_ANY, wxArtProvider::GetBitmap( wxART_FIND, wxART_FRAME_ICON ) ),
|
|
||||||
0, wxALIGN_CENTER | wxALL, 5 );
|
0, wxALIGN_CENTER | wxALL, 5 );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -160,23 +167,25 @@ wxPanel* DIALOG_CHOOSE_COMPONENT::ConstructRightPanel( wxWindow* aParent )
|
||||||
auto panel = new wxPanel( aParent );
|
auto panel = new wxPanel( aParent );
|
||||||
auto sizer = new wxBoxSizer( wxVERTICAL );
|
auto sizer = new wxBoxSizer( wxVERTICAL );
|
||||||
|
|
||||||
m_sch_view_ctrl = new wxPanel( panel, wxID_ANY,
|
m_sch_view_ctrl = new wxPanel( panel, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ),
|
||||||
wxDefaultPosition, wxSize( -1, -1 ),
|
|
||||||
wxFULL_REPAINT_ON_RESIZE | wxSUNKEN_BORDER | wxTAB_TRAVERSAL );
|
wxFULL_REPAINT_ON_RESIZE | wxSUNKEN_BORDER | wxTAB_TRAVERSAL );
|
||||||
m_sch_view_ctrl->SetLayoutDirection( wxLayout_LeftToRight );
|
m_sch_view_ctrl->SetLayoutDirection( wxLayout_LeftToRight );
|
||||||
|
|
||||||
m_fp_sel_ctrl = new wxChoice( panel, wxID_ANY );
|
if( m_allow_field_edits )
|
||||||
m_fp_sel_ctrl->SetSelection( 0 );
|
m_fp_sel_ctrl = new FOOTPRINT_SELECT_WIDGET( panel, m_fp_loader, m_fp_list, true );
|
||||||
|
else
|
||||||
|
m_fp_sel_ctrl = nullptr;
|
||||||
|
|
||||||
m_fp_view_ctrl = new FOOTPRINT_PREVIEW_WIDGET( panel, Kiway() );
|
m_fp_view_ctrl = new FOOTPRINT_PREVIEW_WIDGET( panel, Kiway() );
|
||||||
|
|
||||||
|
|
||||||
sizer->Add( m_sch_view_ctrl, 1, wxEXPAND | wxALL, 5 );
|
sizer->Add( m_sch_view_ctrl, 1, wxEXPAND | wxALL, 5 );
|
||||||
|
|
||||||
|
if( m_fp_sel_ctrl )
|
||||||
sizer->Add( m_fp_sel_ctrl, 0, wxEXPAND | wxALL, 5 );
|
sizer->Add( m_fp_sel_ctrl, 0, wxEXPAND | wxALL, 5 );
|
||||||
|
|
||||||
sizer->Add( m_fp_view_ctrl, 1, wxEXPAND | wxALL, 5 );
|
sizer->Add( m_fp_view_ctrl, 1, wxEXPAND | wxALL, 5 );
|
||||||
|
|
||||||
#ifndef KICAD_FOOTPRINT_SELECTOR
|
|
||||||
m_fp_sel_ctrl->Hide();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
panel->SetSizer( sizer );
|
panel->SetSizer( sizer );
|
||||||
panel->Layout();
|
panel->Layout();
|
||||||
|
@ -199,6 +208,12 @@ void DIALOG_CHOOSE_COMPONENT::OnInitDialog( wxInitDialogEvent& aEvent )
|
||||||
// This hides the GAL panel and shows the status label
|
// This hides the GAL panel and shows the status label
|
||||||
m_fp_view_ctrl->SetStatusText( wxEmptyString );
|
m_fp_view_ctrl->SetStatusText( wxEmptyString );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( m_fp_sel_ctrl )
|
||||||
|
m_fp_sel_ctrl->Load( Kiway(), Prj() );
|
||||||
|
|
||||||
|
// There may be a part preselected in the model. Make sure it is displayed.
|
||||||
|
PostSelectEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -206,13 +221,19 @@ LIB_ALIAS* DIALOG_CHOOSE_COMPONENT::GetSelectedAlias( int* aUnit ) const
|
||||||
{
|
{
|
||||||
auto sel = m_tree_ctrl->GetSelection();
|
auto sel = m_tree_ctrl->GetSelection();
|
||||||
|
|
||||||
if( aUnit && m_adapter->GetUnitFor( sel ) )
|
if( aUnit )
|
||||||
*aUnit = m_adapter->GetUnitFor( sel );
|
*aUnit = m_adapter->GetUnitFor( sel );
|
||||||
|
|
||||||
return m_adapter->GetAliasFor( sel );
|
return m_adapter->GetAliasFor( sel );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<std::pair<int, wxString>> DIALOG_CHOOSE_COMPONENT::GetFields() const
|
||||||
|
{
|
||||||
|
return m_field_edits;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DIALOG_CHOOSE_COMPONENT::OnQueryText( wxCommandEvent& aEvent )
|
void DIALOG_CHOOSE_COMPONENT::OnQueryText( wxCommandEvent& aEvent )
|
||||||
{
|
{
|
||||||
m_adapter->UpdateSearchString( m_query_ctrl->GetLineText( 0 ) );
|
m_adapter->UpdateSearchString( m_query_ctrl->GetLineText( 0 ) );
|
||||||
|
@ -254,13 +275,9 @@ void DIALOG_CHOOSE_COMPONENT::OnQueryCharHook( wxKeyEvent& aKeyStroke )
|
||||||
|
|
||||||
switch( aKeyStroke.GetKeyCode() )
|
switch( aKeyStroke.GetKeyCode() )
|
||||||
{
|
{
|
||||||
case WXK_UP:
|
case WXK_UP: SelectIfValid( GetPrevItem( *m_tree_ctrl, sel ) ); break;
|
||||||
SelectIfValid( GetPrevItem( *m_tree_ctrl, sel ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WXK_DOWN:
|
case WXK_DOWN: SelectIfValid( GetNextItem( *m_tree_ctrl, sel ) ); break;
|
||||||
SelectIfValid( GetNextItem( *m_tree_ctrl, sel ) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
aKeyStroke.Skip(); // Any other key: pass on to search box directly.
|
aKeyStroke.Skip(); // Any other key: pass on to search box directly.
|
||||||
|
@ -281,6 +298,7 @@ void DIALOG_CHOOSE_COMPONENT::OnTreeSelect( wxDataViewEvent& aEvent )
|
||||||
{
|
{
|
||||||
m_details_ctrl->SetPage( GenerateAliasInfo( alias, unit ) );
|
m_details_ctrl->SetPage( GenerateAliasInfo( alias, unit ) );
|
||||||
ShowFootprintFor( alias );
|
ShowFootprintFor( alias );
|
||||||
|
PopulateFootprintSelector( alias );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -288,6 +306,8 @@ void DIALOG_CHOOSE_COMPONENT::OnTreeSelect( wxDataViewEvent& aEvent )
|
||||||
|
|
||||||
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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,7 +334,7 @@ void DIALOG_CHOOSE_COMPONENT::OnCloseTimer( wxTimerEvent& aEvent )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EndModal( wxID_OK );
|
EndQuasiModal( wxID_OK );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,7 +342,7 @@ void DIALOG_CHOOSE_COMPONENT::OnCloseTimer( wxTimerEvent& aEvent )
|
||||||
void DIALOG_CHOOSE_COMPONENT::OnSchViewDClick( wxMouseEvent& aEvent )
|
void DIALOG_CHOOSE_COMPONENT::OnSchViewDClick( wxMouseEvent& aEvent )
|
||||||
{
|
{
|
||||||
m_external_browser_requested = true;
|
m_external_browser_requested = true;
|
||||||
EndModal( wxID_OK );
|
EndQuasiModal( wxID_OK );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -331,32 +351,62 @@ void DIALOG_CHOOSE_COMPONENT::ShowFootprintFor( LIB_ALIAS* aAlias )
|
||||||
if( !m_fp_view_ctrl->IsInitialized() )
|
if( !m_fp_view_ctrl->IsInitialized() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LIB_FIELDS fields;
|
LIB_FIELD* fp_field = aAlias->GetPart()->GetField( FOOTPRINT );
|
||||||
aAlias->GetPart()->GetFields( fields );
|
wxString fp_name = fp_field ? fp_field->GetFullText() : wxString( "" );
|
||||||
|
|
||||||
for( auto const & field: fields )
|
ShowFootprint( fp_name );
|
||||||
{
|
}
|
||||||
if( field.GetId() != FOOTPRINT )
|
|
||||||
continue;
|
|
||||||
wxString fpname = field.GetFullText();
|
void DIALOG_CHOOSE_COMPONENT::ShowFootprint( wxString const& aName )
|
||||||
if( fpname == wxEmptyString )
|
{
|
||||||
|
if( aName == wxEmptyString )
|
||||||
{
|
{
|
||||||
m_fp_view_ctrl->SetStatusText( _( "No footprint specified" ) );
|
m_fp_view_ctrl->SetStatusText( _( "No footprint specified" ) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
LIB_ID lib_id( aName );
|
||||||
|
|
||||||
m_fp_view_ctrl->ClearStatus();
|
m_fp_view_ctrl->ClearStatus();
|
||||||
m_fp_view_ctrl->CacheFootprint( LIB_ID( fpname ) );
|
m_fp_view_ctrl->CacheFootprint( lib_id );
|
||||||
m_fp_view_ctrl->DisplayFootprint( LIB_ID( fpname ) );
|
m_fp_view_ctrl->DisplayFootprint( lib_id );
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DIALOG_CHOOSE_COMPONENT::PopulateFootprintSelector( LIB_ALIAS* aAlias )
|
||||||
|
{
|
||||||
|
if( !m_fp_sel_ctrl )
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_fp_sel_ctrl->ClearFilters();
|
||||||
|
|
||||||
|
if( aAlias )
|
||||||
|
{
|
||||||
|
LIB_PINS temp_pins;
|
||||||
|
LIB_FIELD* fp_field = aAlias->GetPart()->GetField( FOOTPRINT );
|
||||||
|
wxString fp_name = fp_field ? fp_field->GetFullText() : wxString( "" );
|
||||||
|
|
||||||
|
aAlias->GetPart()->GetPins( temp_pins );
|
||||||
|
|
||||||
|
m_fp_sel_ctrl->FilterByPinCount( temp_pins.size() );
|
||||||
|
m_fp_sel_ctrl->FilterByFootprintFilters( aAlias->GetPart()->GetFootPrints(), true );
|
||||||
|
m_fp_sel_ctrl->SetDefaultFootprint( fp_name );
|
||||||
|
m_fp_sel_ctrl->UpdateList();
|
||||||
|
m_fp_sel_ctrl->Enable();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_fp_sel_ctrl->UpdateList();
|
||||||
|
m_fp_sel_ctrl->Disable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DIALOG_CHOOSE_COMPONENT::OnDetailsLink( wxHtmlLinkEvent& aEvent )
|
void DIALOG_CHOOSE_COMPONENT::OnDetailsLink( wxHtmlLinkEvent& aEvent )
|
||||||
{
|
{
|
||||||
const wxHtmlLinkInfo & info = aEvent.GetLinkInfo();
|
const wxHtmlLinkInfo& info = aEvent.GetLinkInfo();
|
||||||
::wxLaunchDefaultBrowser( info.GetHref() );
|
::wxLaunchDefaultBrowser( info.GetHref() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,6 +442,21 @@ void DIALOG_CHOOSE_COMPONENT::OnSchViewPaint( wxPaintEvent& aEvent )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DIALOG_CHOOSE_COMPONENT::OnFootprintSelected( wxCommandEvent& aEvent )
|
||||||
|
{
|
||||||
|
m_fp_override = aEvent.GetString();
|
||||||
|
|
||||||
|
m_field_edits.erase(
|
||||||
|
std::remove_if( m_field_edits.begin(), m_field_edits.end(),
|
||||||
|
[]( std::pair<int, wxString> const& i ) { return i.first == FOOTPRINT; } ),
|
||||||
|
m_field_edits.end() );
|
||||||
|
|
||||||
|
m_field_edits.push_back( std::make_pair( FOOTPRINT, m_fp_override ) );
|
||||||
|
|
||||||
|
ShowFootprint( m_fp_override );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DIALOG_CHOOSE_COMPONENT::RenderPreview( LIB_PART* aComponent, int aUnit )
|
void DIALOG_CHOOSE_COMPONENT::RenderPreview( LIB_PART* aComponent, int aUnit )
|
||||||
{
|
{
|
||||||
wxPaintDC dc( m_sch_view_ctrl );
|
wxPaintDC dc( m_sch_view_ctrl );
|
||||||
|
@ -503,7 +568,7 @@ static wxDataViewItem GetNextItem( const wxDataViewCtrl& tree, const wxDataViewI
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Walk up levels until we find one that has a next sibling.
|
// Walk up levels until we find one that has a next sibling.
|
||||||
for ( wxDataViewItem walk = item; walk.IsOk(); walk = tree.GetModel()->GetParent( walk ) )
|
for( wxDataViewItem walk = item; walk.IsOk(); walk = tree.GetModel()->GetParent( walk ) )
|
||||||
{
|
{
|
||||||
nextItem = GetNextSibling( tree, walk );
|
nextItem = GetNextSibling( tree, walk );
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include "dialog_shim.h"
|
#include "dialog_shim.h"
|
||||||
#include <cmp_tree_model_adapter.h>
|
#include <cmp_tree_model_adapter.h>
|
||||||
|
#include <footprint_info.h>
|
||||||
|
|
||||||
class wxStaticBitmap;
|
class wxStaticBitmap;
|
||||||
class wxTextCtrl;
|
class wxTextCtrl;
|
||||||
|
@ -40,6 +41,7 @@ class wxButton;
|
||||||
class wxTimer;
|
class wxTimer;
|
||||||
|
|
||||||
class FOOTPRINT_PREVIEW_WIDGET;
|
class FOOTPRINT_PREVIEW_WIDGET;
|
||||||
|
class FOOTPRINT_SELECT_WIDGET;
|
||||||
class LIB_ALIAS;
|
class LIB_ALIAS;
|
||||||
class LIB_PART;
|
class LIB_PART;
|
||||||
class SCH_BASE_FRAME;
|
class SCH_BASE_FRAME;
|
||||||
|
@ -82,7 +84,6 @@ class SCH_BASE_FRAME;
|
||||||
class DIALOG_CHOOSE_COMPONENT : public DIALOG_SHIM
|
class DIALOG_CHOOSE_COMPONENT : public DIALOG_SHIM
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create dialog to choose component.
|
* Create dialog to choose component.
|
||||||
*
|
*
|
||||||
|
@ -92,30 +93,44 @@ public:
|
||||||
* for documentation.
|
* for documentation.
|
||||||
* @param aDeMorganConvert preferred deMorgan conversion
|
* @param aDeMorganConvert preferred deMorgan conversion
|
||||||
* (TODO: should happen in dialog)
|
* (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.
|
||||||
*/
|
*/
|
||||||
DIALOG_CHOOSE_COMPONENT( SCH_BASE_FRAME* aParent, const wxString& aTitle,
|
DIALOG_CHOOSE_COMPONENT( SCH_BASE_FRAME* aParent, const wxString& aTitle,
|
||||||
CMP_TREE_MODEL_ADAPTER::PTR& aAdapter,
|
CMP_TREE_MODEL_ADAPTER::PTR& aAdapter, int aDeMorganConvert, bool aAllowFieldEdits );
|
||||||
int aDeMorganConvert );
|
|
||||||
|
|
||||||
~DIALOG_CHOOSE_COMPONENT();
|
~DIALOG_CHOOSE_COMPONENT();
|
||||||
|
|
||||||
/** Function GetSelectedAlias
|
/** Function GetSelectedAlias
|
||||||
* To be called after this dialog returns from ShowModal().
|
* To be called after this dialog returns from ShowModal().
|
||||||
*
|
*
|
||||||
|
* For multi-unit components, if the user selects the component 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.
|
* @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 alias that has been selected, or NULL if there is none.
|
||||||
*/
|
*/
|
||||||
LIB_ALIAS* GetSelectedAlias( int* aUnit ) const;
|
LIB_ALIAS* GetSelectedAlias( int* aUnit ) 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;
|
||||||
|
|
||||||
/** Function IsExternalBrowserSelected
|
/** Function IsExternalBrowserSelected
|
||||||
*
|
*
|
||||||
* @return true, iff the user pressed the thumbnail view of the component to
|
* @return true, iff the user pressed the thumbnail view of the component to
|
||||||
* launch the component browser.
|
* launch the component browser.
|
||||||
*/
|
*/
|
||||||
bool IsExternalBrowserSelected() const { return m_external_browser_requested; }
|
bool IsExternalBrowserSelected() const
|
||||||
|
{
|
||||||
|
return m_external_browser_requested;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
static constexpr int DblClickDelay = 100; // milliseconds
|
static constexpr int DblClickDelay = 100; // milliseconds
|
||||||
|
|
||||||
wxPanel* ConstructLeftPanel( wxWindow* aParent );
|
wxPanel* ConstructLeftPanel( wxWindow* aParent );
|
||||||
|
@ -123,6 +138,7 @@ protected:
|
||||||
|
|
||||||
void OnInitDialog( wxInitDialogEvent& aEvent );
|
void OnInitDialog( wxInitDialogEvent& aEvent );
|
||||||
void OnCloseTimer( wxTimerEvent& aEvent );
|
void OnCloseTimer( wxTimerEvent& aEvent );
|
||||||
|
void OnProgressTimer( wxTimerEvent& aEvent );
|
||||||
|
|
||||||
void OnQueryText( wxCommandEvent& aEvent );
|
void OnQueryText( wxCommandEvent& aEvent );
|
||||||
void OnQueryEnter( wxCommandEvent& aEvent );
|
void OnQueryEnter( wxCommandEvent& aEvent );
|
||||||
|
@ -136,11 +152,25 @@ protected:
|
||||||
void OnSchViewDClick( wxMouseEvent& aEvent );
|
void OnSchViewDClick( wxMouseEvent& aEvent );
|
||||||
void OnSchViewPaint( wxPaintEvent& aEvent );
|
void OnSchViewPaint( wxPaintEvent& aEvent );
|
||||||
|
|
||||||
|
void OnFootprintSelected( wxCommandEvent& aEvent );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Look up the footprint for a given alias and display it.
|
* Look up the footprint for a given alias and display it.
|
||||||
*/
|
*/
|
||||||
void ShowFootprintFor( LIB_ALIAS* aAlias );
|
void ShowFootprintFor( LIB_ALIAS* aAlias );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the given footprint by name.
|
||||||
|
*/
|
||||||
|
void ShowFootprint( wxString const& aName );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate the footprint selector for a given alias.
|
||||||
|
*
|
||||||
|
* @param aAlias alias, or null to clear
|
||||||
|
*/
|
||||||
|
void PopulateFootprintSelector( LIB_ALIAS* aAlias );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If a wxDataViewitem is valid, select it and post a selection event.
|
* If a wxDataViewitem is valid, select it and post a selection event.
|
||||||
*/
|
*/
|
||||||
|
@ -170,15 +200,20 @@ protected:
|
||||||
wxDataViewCtrl* m_tree_ctrl;
|
wxDataViewCtrl* m_tree_ctrl;
|
||||||
wxHtmlWindow* m_details_ctrl;
|
wxHtmlWindow* m_details_ctrl;
|
||||||
wxPanel* m_sch_view_ctrl;
|
wxPanel* m_sch_view_ctrl;
|
||||||
wxChoice* m_fp_sel_ctrl;
|
|
||||||
|
|
||||||
|
FOOTPRINT_SELECT_WIDGET* m_fp_sel_ctrl;
|
||||||
FOOTPRINT_PREVIEW_WIDGET* m_fp_view_ctrl;
|
FOOTPRINT_PREVIEW_WIDGET* m_fp_view_ctrl;
|
||||||
|
|
||||||
SCH_BASE_FRAME* m_parent;
|
SCH_BASE_FRAME* m_parent;
|
||||||
CMP_TREE_MODEL_ADAPTER::PTR m_adapter;
|
CMP_TREE_MODEL_ADAPTER::PTR m_adapter;
|
||||||
int m_deMorganConvert;
|
int m_deMorganConvert;
|
||||||
|
bool m_allow_field_edits;
|
||||||
bool m_external_browser_requested;
|
bool m_external_browser_requested;
|
||||||
|
wxString m_fp_override;
|
||||||
|
|
||||||
|
static FOOTPRINT_ASYNC_LOADER m_fp_loader;
|
||||||
|
static std::unique_ptr<FOOTPRINT_LIST> m_fp_list;
|
||||||
|
std::vector<std::pair<int, wxString>> m_field_edits;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DIALOG_CHOOSE_COMPONENT_H */
|
#endif /* DIALOG_CHOOSE_COMPONENT_H */
|
||||||
|
|
|
@ -281,14 +281,14 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnTestChipName( wxCommandEvent& event )
|
||||||
|
|
||||||
void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnSelectChipName( wxCommandEvent& event )
|
void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::OnSelectChipName( wxCommandEvent& event )
|
||||||
{
|
{
|
||||||
wxArrayString dummy;
|
SCH_BASE_FRAME::HISTORY_LIST dummy;
|
||||||
int dummyunit = 1;
|
|
||||||
wxString chipname = m_parent->SelectComponentFromLibrary( NULL, dummy, dummyunit,
|
auto sel = m_parent->SelectComponentFromLibrary( NULL, dummy, true, 0, 0 );
|
||||||
true, NULL, NULL );
|
|
||||||
if( chipname.IsEmpty() )
|
if( sel.Name.IsEmpty() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
chipnameTextCtrl->SetValue( chipname );
|
chipnameTextCtrl->SetValue( sel.Name );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
* @brief functions to get and place library components.
|
* @brief functions to get and place library components.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <fctsys.h>
|
#include <fctsys.h>
|
||||||
#include <pgm_base.h>
|
#include <pgm_base.h>
|
||||||
#include <kiway.h>
|
#include <kiway.h>
|
||||||
|
@ -50,9 +51,10 @@
|
||||||
#include <dialog_get_component.h>
|
#include <dialog_get_component.h>
|
||||||
|
|
||||||
|
|
||||||
wxString SCH_BASE_FRAME::SelectComponentFromLibBrowser( const SCHLIB_FILTER* aFilter,
|
SCH_BASE_FRAME::COMPONENT_SELECTION SCH_BASE_FRAME::SelectComponentFromLibBrowser(
|
||||||
|
const SCHLIB_FILTER* aFilter,
|
||||||
LIB_ALIAS* aPreselectedAlias,
|
LIB_ALIAS* aPreselectedAlias,
|
||||||
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:
|
||||||
LIB_VIEW_FRAME* viewlibFrame = (LIB_VIEW_FRAME*) Kiway().Player( FRAME_SCH_VIEWER, false );
|
LIB_VIEW_FRAME* viewlibFrame = (LIB_VIEW_FRAME*) Kiway().Player( FRAME_SCH_VIEWER, false );
|
||||||
|
@ -71,38 +73,36 @@ wxString SCH_BASE_FRAME::SelectComponentFromLibBrowser( const SCHLIB_FILTER* aFi
|
||||||
viewlibFrame->SetSelectedComponent( aPreselectedAlias->GetName() );
|
viewlibFrame->SetSelectedComponent( aPreselectedAlias->GetName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( aUnit && *aUnit > 0 )
|
if( aUnit > 0 )
|
||||||
viewlibFrame->SetUnit( *aUnit );
|
viewlibFrame->SetUnit( aUnit );
|
||||||
|
|
||||||
if( aConvert && *aConvert > 0 )
|
if( aConvert > 0 )
|
||||||
viewlibFrame->SetConvert( *aConvert );
|
viewlibFrame->SetConvert( aConvert );
|
||||||
|
|
||||||
viewlibFrame->Refresh();
|
viewlibFrame->Refresh();
|
||||||
|
|
||||||
wxString cmpname;
|
COMPONENT_SELECTION sel;
|
||||||
|
|
||||||
if( viewlibFrame->ShowModal( &cmpname, this ) )
|
if( viewlibFrame->ShowModal( &sel.Name, this ) )
|
||||||
{
|
{
|
||||||
if( aUnit )
|
sel.Unit = viewlibFrame->GetUnit();
|
||||||
*aUnit = viewlibFrame->GetUnit();
|
sel.Convert = viewlibFrame->GetConvert();
|
||||||
|
|
||||||
if( aConvert )
|
|
||||||
*aConvert = viewlibFrame->GetConvert();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
viewlibFrame->Destroy();
|
viewlibFrame->Destroy();
|
||||||
|
|
||||||
return cmpname;
|
return sel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
wxString SCH_BASE_FRAME::SelectComponentFromLibrary( const SCHLIB_FILTER* aFilter,
|
SCH_BASE_FRAME::COMPONENT_SELECTION SCH_BASE_FRAME::SelectComponentFromLibrary(
|
||||||
wxArrayString& aHistoryList,
|
const SCHLIB_FILTER* aFilter,
|
||||||
int& aHistoryLastUnit,
|
std::vector<COMPONENT_SELECTION>& aHistoryList,
|
||||||
bool aUseLibBrowser,
|
bool aUseLibBrowser,
|
||||||
int* aUnit,
|
int aUnit,
|
||||||
int* aConvert,
|
int aConvert,
|
||||||
const wxString& aHighlight )
|
const wxString& aHighlight,
|
||||||
|
bool aAllowFields )
|
||||||
{
|
{
|
||||||
wxString dialogTitle;
|
wxString dialogTitle;
|
||||||
PART_LIBS* libs = Prj().SchLibs();
|
PART_LIBS* libs = Prj().SchLibs();
|
||||||
|
@ -141,56 +141,68 @@ wxString SCH_BASE_FRAME::SelectComponentFromLibrary( const SCHLIB_FILTER* aFilte
|
||||||
|
|
||||||
if( !aHistoryList.empty() )
|
if( !aHistoryList.empty() )
|
||||||
{
|
{
|
||||||
adapter->AddAliasList( "-- " + _( "History" ) + " --", aHistoryList, NULL );
|
wxArrayString history_list;
|
||||||
adapter->SetPreselectNode( aHistoryList[0], aHistoryLastUnit );
|
|
||||||
|
for( auto const& i : aHistoryList )
|
||||||
|
history_list.push_back( i.Name );
|
||||||
|
|
||||||
|
adapter->AddAliasList( "-- " + _( "History" ) + " --", history_list, NULL );
|
||||||
|
adapter->SetPreselectNode( aHistoryList[0].Name, aHistoryList[0].Unit );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !aHighlight.IsEmpty() )
|
if( !aHighlight.IsEmpty() )
|
||||||
adapter->SetPreselectNode( aHighlight, /* aUnit */ 0 );
|
adapter->SetPreselectNode( aHighlight, /* aUnit */ 0 );
|
||||||
|
|
||||||
const int deMorgan = aConvert ? *aConvert : 1;
|
|
||||||
dialogTitle.Printf( _( "Choose Component (%d items loaded)" ),
|
dialogTitle.Printf( _( "Choose Component (%d items loaded)" ),
|
||||||
adapter->GetComponentsCount() );
|
adapter->GetComponentsCount() );
|
||||||
DIALOG_CHOOSE_COMPONENT dlg( this, dialogTitle, adapter, deMorgan );
|
DIALOG_CHOOSE_COMPONENT dlg( this, dialogTitle, adapter, aConvert, aAllowFields );
|
||||||
|
|
||||||
if( dlg.ShowModal() == wxID_CANCEL )
|
if( dlg.ShowQuasiModal() == wxID_CANCEL )
|
||||||
return wxEmptyString;
|
return COMPONENT_SELECTION();
|
||||||
|
|
||||||
|
COMPONENT_SELECTION sel;
|
||||||
|
LIB_ALIAS* const alias = dlg.GetSelectedAlias( &sel.Unit );
|
||||||
|
|
||||||
|
if( alias->GetPart()->IsMulti() && sel.Unit == 0 )
|
||||||
|
sel.Unit = 1;
|
||||||
|
|
||||||
|
sel.Fields = dlg.GetFields();
|
||||||
|
|
||||||
wxString cmpName;
|
|
||||||
LIB_ALIAS* const alias = dlg.GetSelectedAlias( aUnit );
|
|
||||||
if ( alias )
|
if ( alias )
|
||||||
cmpName = alias->GetName();
|
sel.Name = alias->GetName();
|
||||||
|
|
||||||
if( dlg.IsExternalBrowserSelected() ) // User requested component browser.
|
if( dlg.IsExternalBrowserSelected() ) // User requested component browser.
|
||||||
cmpName = SelectComponentFromLibBrowser( aFilter, alias, aUnit, aConvert);
|
sel = SelectComponentFromLibBrowser( aFilter, alias, sel.Unit, sel.Convert );
|
||||||
|
|
||||||
if( !cmpName.empty() )
|
if( !sel.Name.empty() )
|
||||||
{
|
{
|
||||||
AddHistoryComponentName( aHistoryList, cmpName );
|
aHistoryList.erase(
|
||||||
|
std::remove_if(
|
||||||
|
aHistoryList.begin(),
|
||||||
|
aHistoryList.end(),
|
||||||
|
[ &sel ]( COMPONENT_SELECTION const& i ) { return i.Name == sel.Name; } ),
|
||||||
|
aHistoryList.end() );
|
||||||
|
|
||||||
if ( aUnit )
|
aHistoryList.insert( aHistoryList.begin(), sel );
|
||||||
aHistoryLastUnit = *aUnit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmpName;
|
return sel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SCH_COMPONENT* SCH_EDIT_FRAME::Load_Component( wxDC* aDC,
|
SCH_COMPONENT* SCH_EDIT_FRAME::Load_Component(
|
||||||
|
wxDC* aDC,
|
||||||
const SCHLIB_FILTER* aFilter,
|
const SCHLIB_FILTER* aFilter,
|
||||||
wxArrayString& aHistoryList,
|
SCH_BASE_FRAME::HISTORY_LIST& aHistoryList,
|
||||||
int& aHistoryLastUnit,
|
|
||||||
bool aUseLibBrowser )
|
bool aUseLibBrowser )
|
||||||
{
|
{
|
||||||
int unit = 1;
|
|
||||||
int convert = 1;
|
|
||||||
SetRepeatItem( NULL );
|
SetRepeatItem( NULL );
|
||||||
m_canvas->SetIgnoreMouseEvents( true );
|
m_canvas->SetIgnoreMouseEvents( true );
|
||||||
|
|
||||||
wxString name = SelectComponentFromLibrary( aFilter, aHistoryList, aHistoryLastUnit,
|
auto sel = SelectComponentFromLibrary( aFilter, aHistoryList,
|
||||||
aUseLibBrowser, &unit, &convert );
|
aUseLibBrowser, 1, 1 );
|
||||||
|
|
||||||
if( name.IsEmpty() )
|
if( sel.Name.IsEmpty() )
|
||||||
{
|
{
|
||||||
m_canvas->SetIgnoreMouseEvents( false );
|
m_canvas->SetIgnoreMouseEvents( false );
|
||||||
m_canvas->MoveCursorToCrossHair();
|
m_canvas->MoveCursorToCrossHair();
|
||||||
|
@ -205,19 +217,19 @@ SCH_COMPONENT* SCH_EDIT_FRAME::Load_Component( wxDC* aDC,
|
||||||
if( aFilter )
|
if( aFilter )
|
||||||
libsource = aFilter->GetLibSource();
|
libsource = aFilter->GetLibSource();
|
||||||
|
|
||||||
LIB_PART* part = Prj().SchLibs()->FindLibPart( LIB_ID( wxEmptyString, name ), libsource );
|
LIB_PART* part = Prj().SchLibs()->FindLibPart( LIB_ID( wxEmptyString, sel.Name ), libsource );
|
||||||
|
|
||||||
if( !part )
|
if( !part )
|
||||||
{
|
{
|
||||||
wxString msg = wxString::Format( _(
|
wxString msg = wxString::Format( _(
|
||||||
"Failed to find part '%s' in library" ),
|
"Failed to find part '%s' in library" ),
|
||||||
GetChars( name )
|
GetChars( sel.Name )
|
||||||
);
|
);
|
||||||
wxMessageBox( msg );
|
wxMessageBox( msg );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SCH_COMPONENT* component = new SCH_COMPONENT( *part, m_CurrentSheet, unit, convert,
|
SCH_COMPONENT* component = new SCH_COMPONENT( *part, m_CurrentSheet, sel.Unit, sel.Convert,
|
||||||
GetCrossHairPosition(), true );
|
GetCrossHairPosition(), true );
|
||||||
|
|
||||||
// Set the m_ChipName value, from component name in lib, for aliases
|
// Set the m_ChipName value, from component name in lib, for aliases
|
||||||
|
@ -225,14 +237,23 @@ SCH_COMPONENT* SCH_EDIT_FRAME::Load_Component( wxDC* aDC,
|
||||||
// alias exists because its root component was found
|
// alias exists because its root component was found
|
||||||
LIB_ID libId;
|
LIB_ID libId;
|
||||||
|
|
||||||
libId.SetLibItemName( name, false );
|
libId.SetLibItemName( sel.Name, false );
|
||||||
component->SetLibId( libId );
|
component->SetLibId( libId );
|
||||||
|
|
||||||
// Be sure the link to the corresponding LIB_PART is OK:
|
// Be sure the link to the corresponding LIB_PART is OK:
|
||||||
component->Resolve( Prj().SchLibs() );
|
component->Resolve( Prj().SchLibs() );
|
||||||
|
|
||||||
|
// Set any fields that have been modified
|
||||||
|
for( auto const& i : sel.Fields )
|
||||||
|
{
|
||||||
|
auto field = component->GetField( i.first );
|
||||||
|
|
||||||
|
if( field )
|
||||||
|
field->SetText( i.second );
|
||||||
|
}
|
||||||
|
|
||||||
// Set the component value that can differ from component name in lib, for aliases
|
// Set the component value that can differ from component name in lib, for aliases
|
||||||
component->GetField( VALUE )->SetText( name );
|
component->GetField( VALUE )->SetText( sel.Name );
|
||||||
|
|
||||||
MSG_PANEL_ITEMS items;
|
MSG_PANEL_ITEMS items;
|
||||||
|
|
||||||
|
|
|
@ -105,7 +105,6 @@ bool LIB_EDIT_FRAME::LoadComponentFromCurrentLib( LIB_ALIAS* aLibEntry )
|
||||||
|
|
||||||
void LIB_EDIT_FRAME::LoadOneLibraryPart( wxCommandEvent& event )
|
void LIB_EDIT_FRAME::LoadOneLibraryPart( wxCommandEvent& event )
|
||||||
{
|
{
|
||||||
wxString cmp_name;
|
|
||||||
LIB_ALIAS* libEntry = NULL;
|
LIB_ALIAS* libEntry = NULL;
|
||||||
|
|
||||||
m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor() );
|
m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor() );
|
||||||
|
@ -130,14 +129,13 @@ void LIB_EDIT_FRAME::LoadOneLibraryPart( wxCommandEvent& event )
|
||||||
LIB_PART* current_part = GetCurPart();
|
LIB_PART* current_part = GetCurPart();
|
||||||
wxString part_name = current_part ? current_part->GetName() : wxString( wxEmptyString );
|
wxString part_name = current_part ? current_part->GetName() : wxString( wxEmptyString );
|
||||||
|
|
||||||
wxArrayString dummyHistoryList;
|
SCH_BASE_FRAME::HISTORY_LIST dummyHistoryList;
|
||||||
int dummyLastUnit;
|
|
||||||
SCHLIB_FILTER filter;
|
SCHLIB_FILTER filter;
|
||||||
filter.LoadFrom( lib->GetName() );
|
filter.LoadFrom( lib->GetName() );
|
||||||
cmp_name = SelectComponentFromLibrary( &filter, dummyHistoryList, dummyLastUnit,
|
auto sel = SelectComponentFromLibrary( &filter, dummyHistoryList,
|
||||||
true, NULL, NULL, part_name );
|
true, 0, 0, part_name, false );
|
||||||
|
|
||||||
if( cmp_name.IsEmpty() )
|
if( sel.Name.IsEmpty() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
GetScreen()->ClrModify();
|
GetScreen()->ClrModify();
|
||||||
|
@ -148,14 +146,14 @@ void LIB_EDIT_FRAME::LoadOneLibraryPart( wxCommandEvent& event )
|
||||||
m_aliasName.Empty();
|
m_aliasName.Empty();
|
||||||
|
|
||||||
// Load the new library component
|
// Load the new library component
|
||||||
libEntry = lib->FindAlias( cmp_name );
|
libEntry = lib->FindAlias( sel.Name );
|
||||||
PART_LIB* searchLib = lib;
|
PART_LIB* searchLib = lib;
|
||||||
|
|
||||||
if( !libEntry )
|
if( !libEntry )
|
||||||
{
|
{
|
||||||
// Not found in the active library: search inside the full list
|
// Not found in the active library: search inside the full list
|
||||||
// (can happen when using Viewlib to load a component)
|
// (can happen when using Viewlib to load a component)
|
||||||
libEntry = Prj().SchLibs()->FindLibraryAlias( LIB_ID( wxEmptyString, cmp_name ) );
|
libEntry = Prj().SchLibs()->FindLibraryAlias( LIB_ID( wxEmptyString, sel.Name ) );
|
||||||
|
|
||||||
if( libEntry )
|
if( libEntry )
|
||||||
{
|
{
|
||||||
|
@ -175,7 +173,7 @@ void LIB_EDIT_FRAME::LoadOneLibraryPart( wxCommandEvent& event )
|
||||||
if( !libEntry )
|
if( !libEntry )
|
||||||
{
|
{
|
||||||
wxString msg = wxString::Format( _( "Part name '%s' not found in library '%s'" ),
|
wxString msg = wxString::Format( _( "Part name '%s' not found in library '%s'" ),
|
||||||
GetChars( cmp_name ),
|
GetChars( sel.Name ),
|
||||||
GetChars( searchLib->GetName() ) );
|
GetChars( searchLib->GetName() ) );
|
||||||
DisplayError( this, msg );
|
DisplayError( this, msg );
|
||||||
return;
|
return;
|
||||||
|
@ -540,9 +538,9 @@ void LIB_EDIT_FRAME::DeleteOnePart( wxCommandEvent& event )
|
||||||
wxString dialogTitle;
|
wxString dialogTitle;
|
||||||
dialogTitle.Printf( _( "Delete Component (%u items loaded)" ), adapter->GetComponentsCount() );
|
dialogTitle.Printf( _( "Delete Component (%u items loaded)" ), adapter->GetComponentsCount() );
|
||||||
|
|
||||||
DIALOG_CHOOSE_COMPONENT dlg( this, dialogTitle, adapter, m_convert );
|
DIALOG_CHOOSE_COMPONENT dlg( this, dialogTitle, adapter, m_convert, false );
|
||||||
|
|
||||||
if( dlg.ShowModal() == wxID_CANCEL )
|
if( dlg.ShowQuasiModal() == wxID_CANCEL )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||||
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
|
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
|
||||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 1992-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
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -53,11 +53,8 @@
|
||||||
|
|
||||||
// TODO(hzeller): These pairs of elmenets should be represented by an object, but don't want
|
// TODO(hzeller): These pairs of elmenets should be represented by an object, but don't want
|
||||||
// to refactor too much right now to not get in the way with other code changes.
|
// to refactor too much right now to not get in the way with other code changes.
|
||||||
static wxArrayString s_CmpNameList;
|
static SCH_BASE_FRAME::HISTORY_LIST s_CmpNameList;
|
||||||
static int s_CmpLastUnit;
|
static SCH_BASE_FRAME::HISTORY_LIST s_PowerNameList;
|
||||||
|
|
||||||
static wxArrayString s_PowerNameList;
|
|
||||||
static int s_LastPowerUnit;
|
|
||||||
|
|
||||||
|
|
||||||
void SCH_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition )
|
void SCH_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition )
|
||||||
|
@ -306,7 +303,7 @@ void SCH_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition )
|
||||||
if( (item == NULL) || (item->GetFlags() == 0) )
|
if( (item == NULL) || (item->GetFlags() == 0) )
|
||||||
{
|
{
|
||||||
GetScreen()->SetCurItem( Load_Component( aDC, NULL,
|
GetScreen()->SetCurItem( Load_Component( aDC, NULL,
|
||||||
s_CmpNameList, s_CmpLastUnit, true ) );
|
s_CmpNameList, true ) );
|
||||||
m_canvas->SetAutoPanRequest( true );
|
m_canvas->SetAutoPanRequest( true );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -321,7 +318,7 @@ void SCH_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition )
|
||||||
SCHLIB_FILTER filter;
|
SCHLIB_FILTER filter;
|
||||||
filter.FilterPowerParts( true );
|
filter.FilterPowerParts( true );
|
||||||
GetScreen()->SetCurItem( Load_Component( aDC, &filter,
|
GetScreen()->SetCurItem( Load_Component( aDC, &filter,
|
||||||
s_PowerNameList, s_LastPowerUnit, false ) );
|
s_PowerNameList, false ) );
|
||||||
m_canvas->SetAutoPanRequest( true );
|
m_canvas->SetAutoPanRequest( true );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -122,31 +122,55 @@ public:
|
||||||
|
|
||||||
void UpdateStatusBar() override;
|
void UpdateStatusBar() override;
|
||||||
|
|
||||||
|
|
||||||
|
struct COMPONENT_SELECTION
|
||||||
|
{
|
||||||
|
wxString Name;
|
||||||
|
int Unit;
|
||||||
|
int Convert;
|
||||||
|
|
||||||
|
std::vector<std::pair<int, wxString>> Fields;
|
||||||
|
|
||||||
|
COMPONENT_SELECTION():
|
||||||
|
Name(""),
|
||||||
|
Unit(1),
|
||||||
|
Convert(1)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<COMPONENT_SELECTION> HISTORY_LIST;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function SelectComponentFromLib
|
* Function SelectComponentFromLib
|
||||||
* Calls the library viewer to select component to import into schematic.
|
* Calls the library viewer to select component to import into schematic.
|
||||||
* if the library viewer is currently running, it is closed and reopened
|
* if the library viewer is currently running, it is closed and reopened
|
||||||
* in modal mode.
|
* in modal mode.
|
||||||
|
*
|
||||||
|
* aAllowFields chooses whether or not features that permit the user to edit
|
||||||
|
* fields (e.g. footprint selection) should be enabled. This should be false
|
||||||
|
* when they would have no effect, for example loading a part into libedit.
|
||||||
|
*
|
||||||
* @param aFilter is a SCHLIB_FILTER filter to pass the allowed library names
|
* @param aFilter is a SCHLIB_FILTER filter to pass the allowed library names
|
||||||
* and/or the library name to load the component from and/or some other filter
|
* and/or the library name to load the component from and/or some other filter
|
||||||
* if NULL, no filtering.
|
* if NULL, no filtering.
|
||||||
* @param aHistoryList list of previously loaded components
|
* @param aHistoryList list of previously loaded components - will be edited
|
||||||
* @param aHistoryLastUnit remembering last unit in last component.
|
|
||||||
* @param aUseLibBrowser bool to call the library viewer to select the component
|
* @param aUseLibBrowser bool to call the library viewer to select the component
|
||||||
* @param aUnit a pointer to int to return the selected unit (if any)
|
* @param aUnit preselected unit
|
||||||
* @param aConvert a pointer to int to return the selected De Morgan shape (if any)
|
* @param aConvert preselected De Morgan shape
|
||||||
* @param aHighlight name of component to highlight in the list.
|
* @param aHighlight name of component 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 aAllowFields whether to allow field editing in the dialog
|
||||||
*
|
*
|
||||||
* @return the component name
|
* @return the selected component
|
||||||
*/
|
*/
|
||||||
wxString SelectComponentFromLibrary( const SCHLIB_FILTER* aFilter,
|
COMPONENT_SELECTION SelectComponentFromLibrary(
|
||||||
wxArrayString& aHistoryList,
|
const SCHLIB_FILTER* aFilter,
|
||||||
int& aHistoryLastUnit,
|
std::vector<COMPONENT_SELECTION>& aHistoryList,
|
||||||
bool aUseLibBrowser,
|
bool aUseLibBrowser,
|
||||||
int* aUnit,
|
int aUnit,
|
||||||
int* aConvert,
|
int aConvert,
|
||||||
const wxString& aHighlight = wxEmptyString );
|
const wxString& aHighlight = wxEmptyString,
|
||||||
|
bool aAllowFields = true );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -158,15 +182,14 @@ protected:
|
||||||
* @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 aPreselectedAlias Preselected component alias. NULL if none.
|
||||||
* @param aUnit Pointer to Unit-number. Input is the pre-selected unit, output
|
* @param aUnit preselected unit
|
||||||
* is the finally selected unit by the user. Can be NULL.
|
* @param aConvert preselected deMorgan conversion
|
||||||
* @param aConvert Pointer to deMorgan conversion. Input is what is pre-selected,
|
* @return the selected component
|
||||||
* output is the finally selected deMorgan type by the user.
|
|
||||||
* @return the component name
|
|
||||||
*/
|
*/
|
||||||
wxString SelectComponentFromLibBrowser( const SCHLIB_FILTER* aFilter,
|
COMPONENT_SELECTION SelectComponentFromLibBrowser(
|
||||||
|
const SCHLIB_FILTER* aFilter,
|
||||||
LIB_ALIAS* aPreselectedAlias,
|
LIB_ALIAS* aPreselectedAlias,
|
||||||
int* aUnit, int* aConvert );
|
int aUnit, int aConvert );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function OnOpenLibraryViewer
|
* Function OnOpenLibraryViewer
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras wanadoo.fr
|
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras wanadoo.fr
|
||||||
* Copyright (C) 2008-2015 Wayne Stambaugh <stambaughw@verizon.net>
|
* Copyright (C) 2008-2015 Wayne Stambaugh <stambaughw@verizon.net>
|
||||||
* Copyright (C) 2004-2015 KiCad Developers, see change_log.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
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -1093,7 +1093,6 @@ private:
|
||||||
* to load the component from and/or some other filters
|
* to load the component from and/or some other filters
|
||||||
* if NULL, no filtering.
|
* if NULL, no filtering.
|
||||||
* @param aHistoryList list remembering recently used component names.
|
* @param aHistoryList list remembering recently used component names.
|
||||||
* @param aHistoryLastUnit remembering last unit in last component.
|
|
||||||
* @param aUseLibBrowser is the flag to determine if the library browser should be launched.
|
* @param aUseLibBrowser is the flag to determine if the library browser should be launched.
|
||||||
* @return a pointer the SCH_COMPONENT object selected or NULL if no component was selected.
|
* @return a pointer the SCH_COMPONENT object selected or NULL if no component was selected.
|
||||||
* (TODO(hzeller): This really should be a class doing history, but didn't
|
* (TODO(hzeller): This really should be a class doing history, but didn't
|
||||||
|
@ -1101,8 +1100,7 @@ private:
|
||||||
*/
|
*/
|
||||||
SCH_COMPONENT* Load_Component( wxDC* aDC,
|
SCH_COMPONENT* Load_Component( wxDC* aDC,
|
||||||
const SCHLIB_FILTER* aFilter,
|
const SCHLIB_FILTER* aFilter,
|
||||||
wxArrayString& aHistoryList,
|
SCH_BASE_FRAME::HISTORY_LIST& aHistoryList,
|
||||||
int& aHistoryLastUnit,
|
|
||||||
bool aUseLibBrowser );
|
bool aUseLibBrowser );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -59,9 +59,9 @@ void LIB_VIEW_FRAME::OnSelectSymbol( wxCommandEvent& aEvent )
|
||||||
|
|
||||||
dialogTitle.Printf( _( "Choose Component (%d items loaded)" ),
|
dialogTitle.Printf( _( "Choose Component (%d items loaded)" ),
|
||||||
adapter->GetComponentsCount() );
|
adapter->GetComponentsCount() );
|
||||||
DIALOG_CHOOSE_COMPONENT dlg( this, dialogTitle, adapter, m_convert );
|
DIALOG_CHOOSE_COMPONENT dlg( this, dialogTitle, adapter, m_convert, false );
|
||||||
|
|
||||||
if( dlg.ShowModal() == wxID_CANCEL )
|
if( dlg.ShowQuasiModal() == wxID_CANCEL )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/// @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
|
||||||
|
|
|
@ -1,8 +1,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 Chris Pavlina <pavlina.chris@gmail.com>
|
* Copyright (C) 2015-2017 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
* Copyright (C) 2015 KiCad Developers, see change_log.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
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -52,6 +51,11 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual bool SetPattern( const wxString& aPattern ) = 0;
|
virtual bool SetPattern( const wxString& aPattern ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the pattern passed to SetPattern().
|
||||||
|
*/
|
||||||
|
virtual wxString const& GetPattern() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the location of a match iff a given candidate string matches the set pattern.
|
* Return the location of a match iff a given candidate string matches the set pattern.
|
||||||
* Otherwise, return EDA_PATTERN_NOT_FOUND.
|
* Otherwise, return EDA_PATTERN_NOT_FOUND.
|
||||||
|
@ -67,6 +71,7 @@ class EDA_PATTERN_MATCH_SUBSTR : public EDA_PATTERN_MATCH
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual bool SetPattern( const wxString& aPattern ) override;
|
virtual bool SetPattern( const wxString& aPattern ) override;
|
||||||
|
virtual wxString const& GetPattern() const override;
|
||||||
virtual int Find( const wxString& aCandidate ) const override;
|
virtual int Find( const wxString& aCandidate ) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -81,6 +86,7 @@ class EDA_PATTERN_MATCH_REGEX : public EDA_PATTERN_MATCH
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual bool SetPattern( const wxString& aPattern ) override;
|
virtual bool SetPattern( const wxString& aPattern ) override;
|
||||||
|
virtual wxString const& GetPattern() const override;
|
||||||
virtual int Find( const wxString& aCandidate ) const override;
|
virtual int Find( const wxString& aCandidate ) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -93,7 +99,11 @@ class EDA_PATTERN_MATCH_WILDCARD : public EDA_PATTERN_MATCH_REGEX
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual bool SetPattern( const wxString& aPattern ) override;
|
virtual bool SetPattern( const wxString& aPattern ) override;
|
||||||
|
virtual wxString const& GetPattern() const override;
|
||||||
virtual int Find( const wxString& aCandidate ) const override;
|
virtual int Find( const wxString& aCandidate ) const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
wxString m_wildcard_pattern;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,148 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FOOTPRINT_FILTER_H
|
||||||
|
#define FOOTPRINT_FILTER_H
|
||||||
|
|
||||||
|
#include <boost/iterator/iterator_facade.hpp>
|
||||||
|
#include <eda_pattern_match.h>
|
||||||
|
#include <footprint_info.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Footprint display filter. Takes a list of footprints and filtering settings,
|
||||||
|
* and provides an iterable view of the filtered data.
|
||||||
|
*/
|
||||||
|
class FOOTPRINT_FILTER
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Construct a filter.
|
||||||
|
*
|
||||||
|
* @param aList - unfiltered list of footprints
|
||||||
|
*/
|
||||||
|
FOOTPRINT_FILTER( FOOTPRINT_LIST& aList );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a filter without assigning a footprint list. The filter MUST NOT
|
||||||
|
* be iterated over until SetList() is called.
|
||||||
|
*/
|
||||||
|
FOOTPRINT_FILTER();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the list to filter.
|
||||||
|
*/
|
||||||
|
void SetList( FOOTPRINT_LIST& aList );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all filter criteria.
|
||||||
|
*/
|
||||||
|
void ClearFilters();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add library name to filter criteria.
|
||||||
|
*/
|
||||||
|
void FilterByLibrary( wxString const& aLibName );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a pin count to filter by.
|
||||||
|
*/
|
||||||
|
void FilterByPinCount( int aPinCount );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a list of footprint filters to filter by.
|
||||||
|
*/
|
||||||
|
void FilterByFootprintFilters( wxArrayString const& aFilters );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a pattern to filter by name, including wildcards and optionally a colon-delimited
|
||||||
|
* library name.
|
||||||
|
*/
|
||||||
|
void FilterByPattern( wxString const& aPattern );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inner iterator class returned by begin() and end().
|
||||||
|
*/
|
||||||
|
class ITERATOR
|
||||||
|
: public boost::iterator_facade<ITERATOR, FOOTPRINT_INFO, boost::forward_traversal_tag>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ITERATOR();
|
||||||
|
ITERATOR( ITERATOR const& aOther );
|
||||||
|
ITERATOR( FOOTPRINT_FILTER& aFilter );
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class boost::iterator_core_access;
|
||||||
|
friend class FOOTPRINT_FILTER;
|
||||||
|
|
||||||
|
void increment();
|
||||||
|
bool equal( ITERATOR const& aOther ) const;
|
||||||
|
FOOTPRINT_INFO& dereference() const;
|
||||||
|
|
||||||
|
size_t m_pos;
|
||||||
|
FOOTPRINT_FILTER* m_filter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the stored component matches an item by footprint filter.
|
||||||
|
*/
|
||||||
|
bool FootprintFilterMatch( FOOTPRINT_INFO& aItem );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the stored component matches an item by pin count.
|
||||||
|
*/
|
||||||
|
bool PinCountMatch( FOOTPRINT_INFO& aItem );
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an iterator to the beginning of the filtered view.
|
||||||
|
*/
|
||||||
|
ITERATOR begin();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an iterator to the end of the filtered view. The end iterator is
|
||||||
|
* invalid and may not be dereferenced, only compared against.
|
||||||
|
*/
|
||||||
|
ITERATOR end();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Filter setting constants. The filter type is a bitwise OR of these flags,
|
||||||
|
* and only footprints matching all selected filter types are shown.
|
||||||
|
*/
|
||||||
|
enum FP_FILTER_T : int
|
||||||
|
{
|
||||||
|
UNFILTERED_FP_LIST = 0,
|
||||||
|
FILTERING_BY_COMPONENT_KEYWORD = 0x0001,
|
||||||
|
FILTERING_BY_PIN_COUNT = 0x0002,
|
||||||
|
FILTERING_BY_LIBRARY = 0x0004,
|
||||||
|
FILTERING_BY_NAME = 0x0008
|
||||||
|
};
|
||||||
|
|
||||||
|
FOOTPRINT_LIST* m_list;
|
||||||
|
|
||||||
|
wxString m_lib_name;
|
||||||
|
wxString m_filter_pattern;
|
||||||
|
int m_pin_count;
|
||||||
|
int m_filter_type;
|
||||||
|
EDA_PATTERN_MATCH_WILDCARD m_filter;
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<EDA_PATTERN_MATCH>> m_footprint_filters;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FOOTPRINT_FILTER_H
|
|
@ -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) 2011 Jean-Pierre Charras, <jp.charras@wanadoo.fr>
|
* Copyright (C) 2011 Jean-Pierre Charras, <jp.charras@wanadoo.fr>
|
||||||
* Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 1992-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
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -32,8 +32,15 @@
|
||||||
|
|
||||||
#include <boost/ptr_container/ptr_vector.hpp>
|
#include <boost/ptr_container/ptr_vector.hpp>
|
||||||
|
|
||||||
|
#include <import_export.h>
|
||||||
|
#include <ki_exception.h>
|
||||||
#include <ki_mutex.h>
|
#include <ki_mutex.h>
|
||||||
#include <kicad_string.h>
|
#include <kicad_string.h>
|
||||||
|
#include <sync_queue.h>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
|
||||||
#define USE_FPI_LAZY 0 // 1:yes lazy, 0:no early
|
#define USE_FPI_LAZY 0 // 1:yes lazy, 0:no early
|
||||||
|
@ -41,38 +48,39 @@
|
||||||
|
|
||||||
class FP_LIB_TABLE;
|
class FP_LIB_TABLE;
|
||||||
class FOOTPRINT_LIST;
|
class FOOTPRINT_LIST;
|
||||||
|
class FOOTPRINT_LIST_IMPL;
|
||||||
|
class FOOTPRINT_ASYNC_LOADER;
|
||||||
class wxTopLevelWindow;
|
class wxTopLevelWindow;
|
||||||
|
class KIWAY;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class FOOTPRINT_INFO
|
* Helper class to handle the list of footprints available in libraries. It stores
|
||||||
* is a helper class to handle the list of footprints available in libraries. It stores
|
* footprint names, doc and keywords.
|
||||||
* footprint names, doc and keywords
|
*
|
||||||
|
* This is a virtual class; its implementation lives in pcbnew/footprint_info_impl.cpp.
|
||||||
|
* To get instances of these classes, see FOOTPRINT_LIST::GetInstance().
|
||||||
*/
|
*/
|
||||||
class FOOTPRINT_INFO
|
class APIEXPORT FOOTPRINT_INFO
|
||||||
{
|
{
|
||||||
friend bool operator<( const FOOTPRINT_INFO& item1, const FOOTPRINT_INFO& item2 );
|
friend bool operator<( const FOOTPRINT_INFO& item1, const FOOTPRINT_INFO& item2 );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual ~FOOTPRINT_INFO()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// These two accessors do not have to call ensure_loaded(), because constructor
|
// These two accessors do not have to call ensure_loaded(), because constructor
|
||||||
// fills in these fields:
|
// fills in these fields:
|
||||||
|
|
||||||
const wxString& GetFootprintName() const { return m_fpname; }
|
const wxString& GetFootprintName() const
|
||||||
const wxString& GetNickname() const { return m_nickname; }
|
|
||||||
|
|
||||||
FOOTPRINT_INFO( FOOTPRINT_LIST* aOwner, const wxString& aNickname, const wxString& aFootprintName ) :
|
|
||||||
m_owner( aOwner ),
|
|
||||||
m_loaded( false ),
|
|
||||||
m_nickname( aNickname ),
|
|
||||||
m_fpname( aFootprintName ),
|
|
||||||
m_num( 0 ),
|
|
||||||
m_pad_count( 0 ),
|
|
||||||
m_unique_pad_count( 0 )
|
|
||||||
{
|
{
|
||||||
#if !USE_FPI_LAZY
|
return m_fpname;
|
||||||
load();
|
}
|
||||||
#endif
|
|
||||||
|
const wxString& GetNickname() const
|
||||||
|
{
|
||||||
|
return m_nickname;
|
||||||
}
|
}
|
||||||
|
|
||||||
const wxString& GetDoc()
|
const wxString& GetDoc()
|
||||||
|
@ -106,8 +114,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function InLibrary
|
* Test if the #FOOTPRINT_INFO object was loaded from \a aLibrary.
|
||||||
* tests if the #FOOTPRINT_INFO object was loaded from \a aLibrary.
|
|
||||||
*
|
*
|
||||||
* @param aLibrary is the nickname of the library to test.
|
* @param aLibrary is the nickname of the library to test.
|
||||||
*
|
*
|
||||||
|
@ -116,8 +123,7 @@ public:
|
||||||
*/
|
*/
|
||||||
bool InLibrary( const wxString& aLibrary ) const;
|
bool InLibrary( const wxString& aLibrary ) const;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
|
|
||||||
void ensure_loaded()
|
void ensure_loaded()
|
||||||
{
|
{
|
||||||
if( !m_loaded )
|
if( !m_loaded )
|
||||||
|
@ -125,7 +131,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// lazily load stuff not filled in by constructor. This may throw IO_ERRORS.
|
/// lazily load stuff not filled in by constructor. This may throw IO_ERRORS.
|
||||||
void load();
|
virtual void load() = 0;
|
||||||
|
|
||||||
FOOTPRINT_LIST* m_owner; ///< provides access to FP_LIB_TABLE
|
FOOTPRINT_LIST* m_owner; ///< provides access to FP_LIB_TABLE
|
||||||
|
|
||||||
|
@ -154,89 +160,91 @@ inline bool operator<( const FOOTPRINT_INFO& item1, const FOOTPRINT_INFO& item2
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class FOOTPRINT_LIST
|
* Holds a list of FOOTPRINT_INFO objects, along with a list of IO_ERRORs or
|
||||||
* holds a list of FOOTPRINT_INFO objects, along with a list of IO_ERRORs or
|
|
||||||
* PARSE_ERRORs that were thrown acquiring the FOOTPRINT_INFOs.
|
* PARSE_ERRORs that were thrown acquiring the FOOTPRINT_INFOs.
|
||||||
|
*
|
||||||
|
* This is a virtual class; its implementation lives in pcbnew/footprint_info_impl.cpp.
|
||||||
|
* To get instances of these classes, see FOOTPRINT_LIST::GetInstance().
|
||||||
*/
|
*/
|
||||||
class FOOTPRINT_LIST
|
class APIEXPORT FOOTPRINT_LIST
|
||||||
{
|
{
|
||||||
FP_LIB_TABLE* m_lib_table; ///< no ownership
|
friend class FOOTPRINT_ASYNC_LOADER;
|
||||||
volatile int m_error_count; ///< thread safe to read.
|
|
||||||
|
|
||||||
typedef boost::ptr_vector< FOOTPRINT_INFO > FPILIST;
|
protected:
|
||||||
typedef boost::ptr_vector< IO_ERROR > ERRLIST;
|
FP_LIB_TABLE* m_lib_table; ///< no ownership
|
||||||
|
|
||||||
|
typedef std::vector<std::unique_ptr<FOOTPRINT_INFO>> FPILIST;
|
||||||
|
typedef SYNC_QUEUE<std::unique_ptr<IO_ERROR>> ERRLIST;
|
||||||
|
|
||||||
FPILIST m_list;
|
FPILIST m_list;
|
||||||
ERRLIST m_errors; ///< some can be PARSE_ERRORs also
|
ERRLIST m_errors; ///< some can be PARSE_ERRORs also
|
||||||
|
|
||||||
MUTEX m_errors_lock;
|
|
||||||
MUTEX m_list_lock;
|
MUTEX m_list_lock;
|
||||||
|
|
||||||
/**
|
|
||||||
* Function loader_job
|
|
||||||
* loads footprints from @a aNicknameList and calls AddItem() on to help fill
|
|
||||||
* m_list.
|
|
||||||
*
|
|
||||||
* @param aNicknameList is a wxString[] holding libraries to load all footprints from.
|
|
||||||
* @param aJobZ is the size of the job, i.e. the count of nicknames.
|
|
||||||
*/
|
|
||||||
void loader_job( const wxString* aNicknameList, int aJobZ );
|
|
||||||
|
|
||||||
void addItem( FOOTPRINT_INFO* aItem )
|
|
||||||
{
|
|
||||||
// m_list is not thread safe, and this function is called from
|
|
||||||
// worker threads, lock m_list.
|
|
||||||
MUTLOCK lock( m_list_lock );
|
|
||||||
|
|
||||||
m_list.push_back( aItem );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
FOOTPRINT_LIST() : m_lib_table( 0 )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
FOOTPRINT_LIST() :
|
virtual ~FOOTPRINT_LIST()
|
||||||
m_lib_table( 0 ),
|
|
||||||
m_error_count( 0 )
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function GetCount
|
|
||||||
* @return the number of items stored in list
|
* @return the number of items stored in list
|
||||||
*/
|
*/
|
||||||
unsigned GetCount() const { return m_list.size(); }
|
unsigned GetCount() const
|
||||||
|
{
|
||||||
|
return m_list.size();
|
||||||
|
}
|
||||||
|
|
||||||
/// Was forced to add this by modview_frame.cpp
|
/// Was forced to add this by modview_frame.cpp
|
||||||
const FPILIST& GetList() const { return m_list; }
|
const FPILIST& GetList() const
|
||||||
|
{
|
||||||
|
return m_list;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function GetModuleInfo
|
* Get info for a module by name.
|
||||||
* @param aFootprintName = the footprint name inside the FOOTPRINT_INFO of interest.
|
* @param aFootprintName = the footprint name inside the FOOTPRINT_INFO of interest.
|
||||||
* @return FOOTPRINT_INF* - the item stored in list if found
|
* @return FOOTPRINT_INF* - the item stored in list if found
|
||||||
*/
|
*/
|
||||||
FOOTPRINT_INFO* GetModuleInfo( const wxString& aFootprintName );
|
FOOTPRINT_INFO* GetModuleInfo( const wxString& aFootprintName );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function GetItem
|
* Get info for a module by index.
|
||||||
* @param aIdx = index of the given item
|
* @param aIdx = index of the given item
|
||||||
* @return the aIdx item in list
|
* @return the aIdx item in list
|
||||||
*/
|
*/
|
||||||
FOOTPRINT_INFO& GetItem( unsigned aIdx ) { return m_list[aIdx]; }
|
FOOTPRINT_INFO& GetItem( unsigned aIdx )
|
||||||
|
{
|
||||||
|
return *m_list[aIdx];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function AddItem
|
* Add aItem to list
|
||||||
* add aItem in list
|
|
||||||
* @param aItem = item to add
|
* @param aItem = item to add
|
||||||
*/
|
*/
|
||||||
void AddItem( FOOTPRINT_INFO* aItem );
|
void AddItem( FOOTPRINT_INFO* aItem );
|
||||||
|
|
||||||
unsigned GetErrorCount() const { return m_errors.size(); }
|
unsigned GetErrorCount() const
|
||||||
|
{
|
||||||
|
return m_errors.size();
|
||||||
|
}
|
||||||
|
|
||||||
const IO_ERROR* GetError( unsigned aIdx ) const { return &m_errors[aIdx]; }
|
std::unique_ptr<IO_ERROR> PopError()
|
||||||
|
{
|
||||||
|
auto item = m_errors.pop();
|
||||||
|
|
||||||
|
if( item )
|
||||||
|
return std::move( *item );
|
||||||
|
else
|
||||||
|
return std::unique_ptr<IO_ERROR>();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function ReadFootprintFiles
|
* Read all the footprints provided by the combination of aTable and aNickname.
|
||||||
* reads all the footprints provided by the combination of aTable and aNickname.
|
|
||||||
*
|
*
|
||||||
* @param aTable defines all the libraries.
|
* @param aTable defines all the libraries.
|
||||||
* @param aNickname is the library to read from, or if NULL means read all
|
* @param aNickname is the library to read from, or if NULL means read all
|
||||||
|
@ -245,11 +253,133 @@ public:
|
||||||
* some number of errors. If true, it does not mean there were no errors, check
|
* some number of errors. If true, it does not mean there were no errors, check
|
||||||
* GetErrorCount() for that, should be zero to indicate success.
|
* GetErrorCount() for that, should be zero to indicate success.
|
||||||
*/
|
*/
|
||||||
bool ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* aNickname = NULL );
|
virtual bool ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* aNickname = NULL ) = 0;
|
||||||
|
|
||||||
void DisplayErrors( wxTopLevelWindow* aCaller = NULL );
|
void DisplayErrors( wxTopLevelWindow* aCaller = NULL );
|
||||||
|
|
||||||
FP_LIB_TABLE* GetTable() const { return m_lib_table; }
|
FP_LIB_TABLE* GetTable() const
|
||||||
|
{
|
||||||
|
return m_lib_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory function to return a new FOOTPRINT_LIST via Kiway. NOT guaranteed
|
||||||
|
* to succeed; will return null if the kiface is not available.
|
||||||
|
*
|
||||||
|
* @param aKiway - active kiway instance
|
||||||
|
*/
|
||||||
|
static std::unique_ptr<FOOTPRINT_LIST> GetInstance( KIWAY& aKiway );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* Launch worker threads to load footprints. Part of the
|
||||||
|
* FOOTPRINT_ASYNC_LOADER implementation.
|
||||||
|
*/
|
||||||
|
virtual void StartWorkers( FP_LIB_TABLE* aTable, wxString const* aNickname,
|
||||||
|
FOOTPRINT_ASYNC_LOADER* aLoader, unsigned aNThreads ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Join worker threads. Part of the FOOTPRINT_ASYNC_LOADER implementation.
|
||||||
|
*/
|
||||||
|
virtual bool JoinWorkers() = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the number of libraries finished (successfully or otherwise).
|
||||||
|
*/
|
||||||
|
virtual size_t CountFinished() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class can be used to populate a FOOTPRINT_LIST asynchronously.
|
||||||
|
* Constructing one, calling .Start(), then waiting until it reports completion
|
||||||
|
* is equivalent to calling FOOTPRINT_LIST::ReadFootprintFiles().
|
||||||
|
*/
|
||||||
|
class APIEXPORT FOOTPRINT_ASYNC_LOADER
|
||||||
|
{
|
||||||
|
friend class FOOTPRINT_LIST;
|
||||||
|
friend class FOOTPRINT_LIST_IMPL;
|
||||||
|
|
||||||
|
FOOTPRINT_LIST* m_list;
|
||||||
|
std::function<void()> m_completion_cb;
|
||||||
|
std::string m_last_table;
|
||||||
|
|
||||||
|
bool m_started; ///< True if Start() has been called - does not reset
|
||||||
|
int m_total_libs;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Construct an asynchronous loader.
|
||||||
|
*/
|
||||||
|
FOOTPRINT_ASYNC_LOADER();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assign a FOOTPRINT_LIST to the loader. This does not take ownership of
|
||||||
|
* the list.
|
||||||
|
*/
|
||||||
|
void SetList( FOOTPRINT_LIST* aList );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Launch the worker threads.
|
||||||
|
* @param aTable defines all the libraries.
|
||||||
|
* @param aNickname is the library to read from, or if NULL means read all
|
||||||
|
* footprints from all known libraries in aTable.
|
||||||
|
* @param aNThreads is the number of worker threads.
|
||||||
|
*/
|
||||||
|
void Start( FP_LIB_TABLE* aTable, wxString const* aNickname = nullptr,
|
||||||
|
unsigned aNThreads = DEFAULT_THREADS );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait until the worker threads are finished, and then perform any required
|
||||||
|
* single-threaded finishing on the list. This must be called before using
|
||||||
|
* the list, even if the completion callback was used!
|
||||||
|
*
|
||||||
|
* It is safe to call this method from a thread, but it is not safe to use
|
||||||
|
* the list from ANY thread until it completes. It is recommended to call
|
||||||
|
* this from the main thread because of this.
|
||||||
|
*
|
||||||
|
* It is safe to call this multiple times, but after the first it will
|
||||||
|
* always return true.
|
||||||
|
*
|
||||||
|
* @return true if no errors occurred
|
||||||
|
*/
|
||||||
|
bool Join();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current completion percentage. 0 and 100 are reserved values:
|
||||||
|
* 0 will only be returned if Start() has not yet been called, and 100
|
||||||
|
* will only be returned if totally complete (i.e. rounding errors will
|
||||||
|
* never cause a 100% progress despite not being complete).
|
||||||
|
*
|
||||||
|
* If there are no libraries at all, returns 100 (as loading zero libraries
|
||||||
|
* is always complete).
|
||||||
|
*
|
||||||
|
* Threadsafe.
|
||||||
|
*/
|
||||||
|
int GetProgress() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a callback to receive notice when loading is complete.
|
||||||
|
*
|
||||||
|
* Callback MUST be threadsafe, and must be set before calling Start
|
||||||
|
* if you want to use it (it is safe not to set it at all).
|
||||||
|
*/
|
||||||
|
void SetCompletionCallback( std::function<void()> aCallback );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the given table is the same as the last table loaded.
|
||||||
|
* Useful for checking if the table has been modified and needs to be
|
||||||
|
* reloaded.
|
||||||
|
*/
|
||||||
|
bool IsSameTable( FP_LIB_TABLE* aOther );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default number of worker threads. Determined empirically (by dickelbeck):
|
||||||
|
* More than 6 is not significantly faster, less than 6 is likely slower.
|
||||||
|
*/
|
||||||
|
static constexpr unsigned DEFAULT_THREADS = 6;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // FOOTPRINT_INFO_H_
|
#endif // FOOTPRINT_INFO_H_
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
* Copyright (C) 2010-2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||||
* Copyright (C) 2012-2016 Wayne Stambaugh <stambaughw@verizon.net>
|
* Copyright (C) 2012-2016 Wayne Stambaugh <stambaughw@verizon.net>
|
||||||
* Copyright (C) 2012-2016 KiCad Developers, see change_log.txt for contributors.
|
* Copyright (C) 2012-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
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -145,6 +145,19 @@ public:
|
||||||
*/
|
*/
|
||||||
wxArrayString FootprintEnumerate( const wxString& aNickname );
|
wxArrayString FootprintEnumerate( const wxString& aNickname );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function PrefetchLib
|
||||||
|
* If possible, prefetches the specified library (e.g. performing downloads). Does not parse.
|
||||||
|
* Threadsafe.
|
||||||
|
*
|
||||||
|
* This is a no-op for libraries that cannot be prefetched.
|
||||||
|
*
|
||||||
|
* @param aNickname is a locator for the library; it is a name in LIB_TABLE_ROW.
|
||||||
|
*
|
||||||
|
* @throw IO_ERROR if there is an error prefetching the library.
|
||||||
|
*/
|
||||||
|
void PrefetchLib( const wxString& aNickname );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function FootprintLoad
|
* Function FootprintLoad
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 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 KIFACE_IDS_H
|
||||||
|
#define KIFACE_IDS_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IDs of objects that may be returned by KIFACE::IfaceOrAddress.
|
||||||
|
*/
|
||||||
|
enum KIFACE_ADDR_ID : int
|
||||||
|
{
|
||||||
|
INVALID,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new instance of FOOTPRINT_LIST from pcbnew.
|
||||||
|
* Type is FOOTPRINT_LIST*
|
||||||
|
* Caller takes ownership
|
||||||
|
*/
|
||||||
|
KIFACE_NEW_FOOTPRINT_LIST,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new FP_LIB_TABLE copying the global table.
|
||||||
|
* Type is FP_LIB_TABLE*
|
||||||
|
* Caller takes ownership
|
||||||
|
*/
|
||||||
|
KIFACE_G_FOOTPRINT_TABLE, ///<
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KIFACE_IDS
|
|
@ -1,7 +1,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) 2014 KiCad Developers, see CHANGELOG.TXT for contributors.
|
* Copyright (C) 2014-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
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -20,7 +20,6 @@
|
||||||
* or you may write to the Free Software Foundation, Inc.,
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef PROJECT_H_
|
#ifndef PROJECT_H_
|
||||||
#define PROJECT_H_
|
#define PROJECT_H_
|
||||||
|
|
||||||
|
@ -39,6 +38,7 @@ class FP_LIB_TABLE;
|
||||||
class PART_LIBS;
|
class PART_LIBS;
|
||||||
class SEARCH_STACK;
|
class SEARCH_STACK;
|
||||||
class S3D_CACHE;
|
class S3D_CACHE;
|
||||||
|
class KIWAY;
|
||||||
|
|
||||||
#define VTBL_ENTRY virtual
|
#define VTBL_ENTRY virtual
|
||||||
|
|
||||||
|
@ -235,6 +235,11 @@ public:
|
||||||
*/
|
*/
|
||||||
VTBL_ENTRY const wxString AbsolutePath( const wxString& aFileName ) const;
|
VTBL_ENTRY const wxString AbsolutePath( const wxString& aFileName ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the table of footprint libraries. Requires an active Kiway as
|
||||||
|
* this is fetched from pcbnew.
|
||||||
|
*/
|
||||||
|
VTBL_ENTRY FP_LIB_TABLE* PcbFootprintLibs( KIWAY& aKiway );
|
||||||
|
|
||||||
//-----</Cross Module API>---------------------------------------------------
|
//-----</Cross Module API>---------------------------------------------------
|
||||||
|
|
||||||
|
@ -250,7 +255,10 @@ public:
|
||||||
// functions can get linked into the KIFACE that needs them, and only there.
|
// functions can get linked into the KIFACE that needs them, and only there.
|
||||||
// In fact, the other KIFACEs don't even know they exist.
|
// In fact, the other KIFACEs don't even know they exist.
|
||||||
#if defined(PCBNEW) || defined(CVPCB)
|
#if defined(PCBNEW) || defined(CVPCB)
|
||||||
// These are all prefaced with "Pcb"
|
/**
|
||||||
|
* Return the table of footprint libraries without Kiway, only from within
|
||||||
|
* pcbnew.
|
||||||
|
*/
|
||||||
FP_LIB_TABLE* PcbFootprintLibs();
|
FP_LIB_TABLE* PcbFootprintLibs();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SYNC_QUEUE_H
|
||||||
|
#define SYNC_QUEUE_H
|
||||||
|
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
#include <mutex>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronized, locking queue. Safe for multiple producer/multiple consumer environments with
|
||||||
|
* nontrivial data (though bear in mind data needs to be copied in and out).
|
||||||
|
*/
|
||||||
|
template <typename T> class SYNC_QUEUE
|
||||||
|
{
|
||||||
|
typedef std::lock_guard<std::mutex> GUARD;
|
||||||
|
|
||||||
|
std::queue<T> m_queue;
|
||||||
|
mutable std::mutex m_mutex;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SYNC_QUEUE()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Push a value onto the queue.
|
||||||
|
*/
|
||||||
|
void push( T const& aValue )
|
||||||
|
{
|
||||||
|
GUARD guard( m_mutex );
|
||||||
|
m_queue.push( aValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move a value onto the queue. Useful for e.g. unique_ptr.
|
||||||
|
*/
|
||||||
|
void move_push( T&& aValue )
|
||||||
|
{
|
||||||
|
GUARD guard( m_mutex );
|
||||||
|
m_queue.push( std::move( aValue ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pop a value off the queue if there is one, returning it. If the queue is empty,
|
||||||
|
* return boost::none instead.
|
||||||
|
*/
|
||||||
|
boost::optional<T> pop()
|
||||||
|
{
|
||||||
|
GUARD guard( m_mutex );
|
||||||
|
|
||||||
|
if( m_queue.empty() )
|
||||||
|
{
|
||||||
|
return boost::none;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
T val = std::move( m_queue.front() );
|
||||||
|
m_queue.pop();
|
||||||
|
return std::move( val );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true iff the queue is empty.
|
||||||
|
*/
|
||||||
|
bool empty() const
|
||||||
|
{
|
||||||
|
GUARD guard( m_mutex );
|
||||||
|
return m_queue.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the size of the queue.
|
||||||
|
*/
|
||||||
|
size_t size() const
|
||||||
|
{
|
||||||
|
GUARD guard( m_mutex );
|
||||||
|
return m_queue.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the queue.
|
||||||
|
*/
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
GUARD guard( m_mutex );
|
||||||
|
|
||||||
|
while( !m_queue.empty() )
|
||||||
|
{
|
||||||
|
m_queue.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SYNC_QUEUE_H
|
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FOOTPRINT_CHOICE_H
|
||||||
|
#define FOOTPRINT_CHOICE_H
|
||||||
|
|
||||||
|
#include <wx/odcombo.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event thrown when an item is selected "interactively". This includes direct clicks
|
||||||
|
* and presses of the Enter key, but not arrow key motion. Integer data will be the
|
||||||
|
* item selected.
|
||||||
|
*/
|
||||||
|
wxDECLARE_EVENT( EVT_INTERACTIVE_CHOICE, wxCommandEvent );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Customized combo box for footprint selection. This provides the following features:
|
||||||
|
*
|
||||||
|
* - library name is greyed out for readability when lib:footprint format is found in
|
||||||
|
* the item text
|
||||||
|
* - empty items are displayed as nonselectable separators
|
||||||
|
*
|
||||||
|
* Multiple separators in a row is undefined behavior; it is likely to result in errors
|
||||||
|
* such as the ability to select separators. Separators ARE valid at the top and bottom.
|
||||||
|
*
|
||||||
|
* For any items containing footprints, the "lib:footprint" name should be attached to
|
||||||
|
* the item as a wxStringClientData.
|
||||||
|
*/
|
||||||
|
class FOOTPRINT_CHOICE : public wxOwnerDrawnComboBox
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FOOTPRINT_CHOICE( wxWindow* aParent, int aId );
|
||||||
|
|
||||||
|
virtual ~FOOTPRINT_CHOICE();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void DoSetPopupControl( wxComboPopup* aPopup ) override;
|
||||||
|
virtual void OnDrawItem( wxDC& aDC, wxRect const& aRect, int aItem, int aFlags ) const override;
|
||||||
|
virtual wxCoord OnMeasureItem( size_t aItem ) const override;
|
||||||
|
virtual wxCoord OnMeasureItemWidth( size_t aItem ) const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw a fragment of text, then return the next x coordinate to continue drawing.
|
||||||
|
*/
|
||||||
|
static wxCoord DrawTextFragment( wxDC& aDC, wxCoord x, wxCoord y, wxString const& aText );
|
||||||
|
|
||||||
|
/// Veto a mouseover event if in the separator
|
||||||
|
void TryVetoMouse( wxMouseEvent& aEvent );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Veto a select event for the separator
|
||||||
|
*
|
||||||
|
* @param aInner - true if event was called for the inner list (ie the popup)
|
||||||
|
*/
|
||||||
|
void TryVetoSelect( wxCommandEvent& aEvent, bool aInner );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mouse up on an item in the list.
|
||||||
|
*/
|
||||||
|
void OnMouseUp( wxMouseEvent& aEvent );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key up on an item in the list.
|
||||||
|
*/
|
||||||
|
void OnKeyUp( wxKeyEvent& aEvent );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For arrow key events, skip over separators.
|
||||||
|
*
|
||||||
|
* @param aInner - true if event was called for the inner list (ie the popup)
|
||||||
|
*/
|
||||||
|
void TrySkipSeparator( wxKeyEvent& aEvent, bool aInner );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Safely get a string for an item, returning wxEmptyString if the item doesn't exist.
|
||||||
|
*/
|
||||||
|
wxString SafeGetString( int aItem ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get selection from either the outer (combo box) or inner (popup) list.
|
||||||
|
*/
|
||||||
|
int GetSelectionEither( bool aInner ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Safely set selection for either the outer (combo box) or inner (popup) list, doing nothing
|
||||||
|
* for invalid selections.
|
||||||
|
*/
|
||||||
|
void SetSelectionEither( bool aInner, int aSel );
|
||||||
|
|
||||||
|
static wxColour m_grey;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_last_selection;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FOOTPRINT_CHOICE_H
|
|
@ -0,0 +1,161 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FOOTPRINT_SELECT_WIDGET_H
|
||||||
|
#define FOOTPRINT_SELECT_WIDGET_H
|
||||||
|
|
||||||
|
#include <footprint_filter.h>
|
||||||
|
#include <footprint_info.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <wx/panel.h>
|
||||||
|
#include <wx/wx.h>
|
||||||
|
|
||||||
|
class KIWAY;
|
||||||
|
class PROJECT;
|
||||||
|
class FOOTPRINT_CHOICE;
|
||||||
|
class wxGauge;
|
||||||
|
class wxMenu;
|
||||||
|
class wxTimer;
|
||||||
|
class wxTimerEvent;
|
||||||
|
class wxWindow;
|
||||||
|
class wxSimplebook;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This event is fired when a footprint is selected. The string data of the
|
||||||
|
* event will contain the footprint name.
|
||||||
|
*/
|
||||||
|
wxDECLARE_EVENT( EVT_FOOTPRINT_SELECTED, wxCommandEvent );
|
||||||
|
|
||||||
|
class FOOTPRINT_SELECT_WIDGET : public wxPanel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Construct a footprint selector widget.
|
||||||
|
*
|
||||||
|
* This requires references to an external footprint loader, and an external
|
||||||
|
* unique_ptr-to-FOOTPRINT_LIST. The latter will be populated with a
|
||||||
|
* FOOTPRINT_LIST instance the first time Load() is called.
|
||||||
|
*
|
||||||
|
* The reason for this is that footprint loading tends to be very expensive,
|
||||||
|
* especially when using online libraries. The caller is expected to keep
|
||||||
|
* these objects around (e.g. they may be statics on the dialog this
|
||||||
|
* FOOTPRINT_SELECT_WIDGET is created in) so footprints do not have to be
|
||||||
|
* loaded more than once.
|
||||||
|
*
|
||||||
|
* @param aParent - parent window
|
||||||
|
* @param aLoader - FOOTPRINT_ASYNC_LOADER instance
|
||||||
|
* @param aFpList - FOOTPRINT_LIST container
|
||||||
|
* @param aUpdate - whether to call UpdateList() automatically when finished loading
|
||||||
|
* @param aMaxItems - maximum number of filter items to display, in addition to
|
||||||
|
* Default and Other
|
||||||
|
*/
|
||||||
|
FOOTPRINT_SELECT_WIDGET( wxWindow* aParent, FOOTPRINT_ASYNC_LOADER& aLoader,
|
||||||
|
std::unique_ptr<FOOTPRINT_LIST>& aFpList, bool aUpdate = true, int aMaxItems = 10 );
|
||||||
|
|
||||||
|
virtual ~FOOTPRINT_SELECT_WIDGET()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start loading. This function returns immediately; footprints will
|
||||||
|
* continue to load in the background.
|
||||||
|
*
|
||||||
|
* @param aKiway - active kiway instance. This is cached for use when "Other"
|
||||||
|
* is selected.
|
||||||
|
* @param aProject - current project
|
||||||
|
*/
|
||||||
|
void Load( KIWAY& aKiway, PROJECT& aProject );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all filters. Does not update the list.
|
||||||
|
*/
|
||||||
|
void ClearFilters();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter by pin count. Does not update the list.
|
||||||
|
*/
|
||||||
|
void FilterByPinCount( int aPinCount );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter by footprint filter list. Does not update the list.
|
||||||
|
*
|
||||||
|
* @param aZeroFilters - if true, zero filters = zero footprints. If false, zero filters =
|
||||||
|
* not filtering.
|
||||||
|
*/
|
||||||
|
void FilterByFootprintFilters( wxArrayString const& aFilters, bool aZeroFilters );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the default footprint for a part. This will be listed at the
|
||||||
|
* top. May be an empty string.
|
||||||
|
*/
|
||||||
|
void SetDefaultFootprint( wxString const& aFp );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the contents of the list to match the filters. Has no effect if
|
||||||
|
* the footprint list has not been loaded yet. The "default" footprint will be
|
||||||
|
* selected.
|
||||||
|
*
|
||||||
|
* @return true if the footprint list has been loaded (and the list was updated)
|
||||||
|
*/
|
||||||
|
bool UpdateList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set current selection to the default footprint
|
||||||
|
*/
|
||||||
|
void SelectDefault();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable or disable the control for input
|
||||||
|
*/
|
||||||
|
virtual bool Enable( bool aEnable = true ) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
KIWAY* m_kiway;
|
||||||
|
wxGauge* m_progress_ctrl;
|
||||||
|
FOOTPRINT_CHOICE* m_fp_sel_ctrl;
|
||||||
|
wxSizer* m_sizer;
|
||||||
|
wxSimplebook* m_book;
|
||||||
|
|
||||||
|
std::unique_ptr<wxTimer> m_progress_timer;
|
||||||
|
|
||||||
|
bool m_update;
|
||||||
|
bool m_finished_loading;
|
||||||
|
int m_max_items;
|
||||||
|
wxString m_default_footprint;
|
||||||
|
wxString m_other_footprint;
|
||||||
|
int m_last_item;
|
||||||
|
|
||||||
|
FOOTPRINT_ASYNC_LOADER& m_fp_loader;
|
||||||
|
std::unique_ptr<FOOTPRINT_LIST>& m_fp_list;
|
||||||
|
FOOTPRINT_FILTER m_fp_filter;
|
||||||
|
bool m_zero_filter;
|
||||||
|
|
||||||
|
void OnProgressTimer( wxTimerEvent& aEvent );
|
||||||
|
void OnComboBox( wxCommandEvent& aEvent );
|
||||||
|
void OnComboInteractive( wxCommandEvent& aEvent );
|
||||||
|
|
||||||
|
/// Show the component picker and return the selected component. Used by DoOther()
|
||||||
|
wxString ShowPicker();
|
||||||
|
|
||||||
|
/// Handle activation of the "Other..." item
|
||||||
|
void DoOther();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // FOOTPRINT_SELECT_WIDGET
|
|
@ -238,6 +238,7 @@ set( PCBNEW_CLASS_SRCS
|
||||||
edtxtmod.cpp
|
edtxtmod.cpp
|
||||||
event_handlers_tracks_vias_sizes.cpp
|
event_handlers_tracks_vias_sizes.cpp
|
||||||
files.cpp
|
files.cpp
|
||||||
|
footprint_info_impl.cpp
|
||||||
globaleditpad.cpp
|
globaleditpad.cpp
|
||||||
highlight.cpp
|
highlight.cpp
|
||||||
hotkeys.cpp
|
hotkeys.cpp
|
||||||
|
|
|
@ -0,0 +1,230 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Jean-Pierre Charras, <jp.charras@wanadoo.fr>
|
||||||
|
* Copyright (C) 2013-2016 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||||
|
* Copyright (C) 1992-2017 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <footprint_info_impl.h>
|
||||||
|
|
||||||
|
#include <class_module.h>
|
||||||
|
#include <common.h>
|
||||||
|
#include <fctsys.h>
|
||||||
|
#include <footprint_info.h>
|
||||||
|
#include <fp_lib_table.h>
|
||||||
|
#include <html_messagebox.h>
|
||||||
|
#include <io_mgr.h>
|
||||||
|
#include <kiface_ids.h>
|
||||||
|
#include <kiway.h>
|
||||||
|
#include <lib_id.h>
|
||||||
|
#include <macros.h>
|
||||||
|
#include <make_unique.h>
|
||||||
|
#include <pgm_base.h>
|
||||||
|
#include <wildcards_and_files_ext.h>
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_INFO_IMPL::load()
|
||||||
|
{
|
||||||
|
FP_LIB_TABLE* fptable = m_owner->GetTable();
|
||||||
|
|
||||||
|
wxASSERT( fptable );
|
||||||
|
|
||||||
|
std::unique_ptr<MODULE> footprint( fptable->FootprintLoad( m_nickname, m_fpname ) );
|
||||||
|
|
||||||
|
if( footprint.get() == NULL ) // Should happen only with malformed/broken libraries
|
||||||
|
{
|
||||||
|
m_pad_count = 0;
|
||||||
|
m_unique_pad_count = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_pad_count = footprint->GetPadCount( DO_NOT_INCLUDE_NPTH );
|
||||||
|
m_unique_pad_count = footprint->GetUniquePadCount( DO_NOT_INCLUDE_NPTH );
|
||||||
|
m_keywords = footprint->GetKeywords();
|
||||||
|
m_doc = footprint->GetDescription();
|
||||||
|
|
||||||
|
// tell ensure_loaded() I'm loaded.
|
||||||
|
m_loaded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool FOOTPRINT_LIST_IMPL::CatchErrors( std::function<void()> aFunc )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
aFunc();
|
||||||
|
}
|
||||||
|
catch( const IO_ERROR& ioe )
|
||||||
|
{
|
||||||
|
m_errors.move_push( std::make_unique<IO_ERROR>( ioe ) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch( const std::exception& se )
|
||||||
|
{
|
||||||
|
// This is a round about way to do this, but who knows what THROW_IO_ERROR()
|
||||||
|
// may be tricked out to do someday, keep it in the game.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
THROW_IO_ERROR( se.what() );
|
||||||
|
}
|
||||||
|
catch( const IO_ERROR& ioe )
|
||||||
|
{
|
||||||
|
m_errors.move_push( std::make_unique<IO_ERROR>( ioe ) );
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_LIST_IMPL::loader_job()
|
||||||
|
{
|
||||||
|
while( auto const nickname = m_queue_in.pop() )
|
||||||
|
{
|
||||||
|
CatchErrors( [this, &nickname]() {
|
||||||
|
m_lib_table->PrefetchLib( *nickname );
|
||||||
|
m_queue_out.push( *nickname );
|
||||||
|
} );
|
||||||
|
|
||||||
|
m_count_finished.fetch_add( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !m_first_to_finish.exchange( true ) )
|
||||||
|
{
|
||||||
|
// yay, we're first to finish!
|
||||||
|
if( m_loader->m_completion_cb )
|
||||||
|
{
|
||||||
|
m_loader->m_completion_cb();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool FOOTPRINT_LIST_IMPL::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* aNickname )
|
||||||
|
{
|
||||||
|
FOOTPRINT_ASYNC_LOADER loader;
|
||||||
|
|
||||||
|
loader.SetList( this );
|
||||||
|
loader.Start( aTable, aNickname );
|
||||||
|
return loader.Join();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FOOTPRINT_LIST_IMPL::StartWorkers( FP_LIB_TABLE* aTable, wxString const* aNickname,
|
||||||
|
FOOTPRINT_ASYNC_LOADER* aLoader, unsigned aNThreads )
|
||||||
|
{
|
||||||
|
m_loader = aLoader;
|
||||||
|
m_lib_table = aTable;
|
||||||
|
|
||||||
|
// Clear data before reading files
|
||||||
|
m_first_to_finish.store( false );
|
||||||
|
m_count_finished.store( 0 );
|
||||||
|
m_errors.clear();
|
||||||
|
m_list.clear();
|
||||||
|
m_threads.clear();
|
||||||
|
m_queue_in.clear();
|
||||||
|
m_queue_out.clear();
|
||||||
|
|
||||||
|
if( aNickname )
|
||||||
|
m_queue_in.push( *aNickname );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( auto const& nickname : aTable->GetLogicalLibs() )
|
||||||
|
m_queue_in.push( nickname );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_loader->m_total_libs = m_queue_in.size();
|
||||||
|
|
||||||
|
for( unsigned i = 0; i < aNThreads; ++i )
|
||||||
|
{
|
||||||
|
m_threads.push_back( std::thread( &FOOTPRINT_LIST_IMPL::loader_job, this ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FOOTPRINT_LIST_IMPL::JoinWorkers()
|
||||||
|
{
|
||||||
|
for( auto& i : m_threads )
|
||||||
|
i.join();
|
||||||
|
|
||||||
|
m_threads.clear();
|
||||||
|
m_queue_in.clear();
|
||||||
|
|
||||||
|
LOCALE_IO toggle_locale;
|
||||||
|
|
||||||
|
// Parse the footprints in parallel. WARNING! This requires changing the locale, which is
|
||||||
|
// GLOBAL. It is only threadsafe to construct the LOCALE_IO before the threads are created,
|
||||||
|
// destroy it after they finish, and block the main (GUI) thread while they work. Any deviation
|
||||||
|
// from this will cause nasal demons.
|
||||||
|
//
|
||||||
|
// TODO: blast LOCALE_IO into the sun
|
||||||
|
|
||||||
|
SYNC_QUEUE<std::unique_ptr<FOOTPRINT_INFO>> queue_parsed;
|
||||||
|
std::vector<std::thread> threads;
|
||||||
|
|
||||||
|
for( size_t i = 0; i < std::thread::hardware_concurrency() + 1; ++i )
|
||||||
|
{
|
||||||
|
threads.push_back( std::thread( [this, &queue_parsed]() {
|
||||||
|
while( auto nickname = this->m_queue_out.pop() )
|
||||||
|
{
|
||||||
|
CatchErrors( [this, &queue_parsed, &nickname]() {
|
||||||
|
wxArrayString fpnames = this->m_lib_table->FootprintEnumerate( *nickname );
|
||||||
|
|
||||||
|
for( auto const& fpname : fpnames )
|
||||||
|
{
|
||||||
|
FOOTPRINT_INFO* fpinfo = new FOOTPRINT_INFO_IMPL( this, *nickname, fpname );
|
||||||
|
queue_parsed.move_push( std::unique_ptr<FOOTPRINT_INFO>( fpinfo ) );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
} ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( auto& thr : threads )
|
||||||
|
thr.join();
|
||||||
|
|
||||||
|
while( auto fpi = queue_parsed.pop() )
|
||||||
|
m_list.push_back( std::move( *fpi ) );
|
||||||
|
|
||||||
|
std::sort( m_list.begin(), m_list.end(),
|
||||||
|
[]( std::unique_ptr<FOOTPRINT_INFO> const& lhs,
|
||||||
|
std::unique_ptr<FOOTPRINT_INFO> const& rhs ) -> bool { return *lhs < *rhs; } );
|
||||||
|
|
||||||
|
return m_errors.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t FOOTPRINT_LIST_IMPL::CountFinished()
|
||||||
|
{
|
||||||
|
return m_count_finished.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FOOTPRINT_LIST_IMPL::FOOTPRINT_LIST_IMPL() : m_loader( nullptr )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FOOTPRINT_LIST_IMPL::~FOOTPRINT_LIST_IMPL()
|
||||||
|
{
|
||||||
|
for( auto& i : m_threads )
|
||||||
|
i.join();
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Jean-Pierre Charras, <jp.charras@wanadoo.fr>
|
||||||
|
* Copyright (C) 1992-2017 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FOOTPRINT_INFO_IMPL_H
|
||||||
|
#define FOOTPRINT_INFO_IMPL_H
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <footprint_info.h>
|
||||||
|
#include <sync_queue.h>
|
||||||
|
|
||||||
|
class LOCALE_IO;
|
||||||
|
|
||||||
|
class FOOTPRINT_INFO_IMPL : public FOOTPRINT_INFO
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FOOTPRINT_INFO_IMPL(
|
||||||
|
FOOTPRINT_LIST* aOwner, const wxString& aNickname, const wxString& aFootprintName )
|
||||||
|
{
|
||||||
|
m_owner = aOwner;
|
||||||
|
m_loaded = false;
|
||||||
|
m_nickname = aNickname;
|
||||||
|
m_fpname = aFootprintName;
|
||||||
|
m_num = 0;
|
||||||
|
m_pad_count = 0;
|
||||||
|
m_unique_pad_count = 0;
|
||||||
|
#if !USE_FPI_LAZY
|
||||||
|
load();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void load() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class FOOTPRINT_LIST_IMPL : public FOOTPRINT_LIST
|
||||||
|
{
|
||||||
|
FOOTPRINT_ASYNC_LOADER* m_loader;
|
||||||
|
std::vector<std::thread> m_threads;
|
||||||
|
SYNC_QUEUE<wxString> m_queue_in;
|
||||||
|
SYNC_QUEUE<wxString> m_queue_out;
|
||||||
|
std::atomic_size_t m_count_finished;
|
||||||
|
std::atomic_bool m_first_to_finish;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call aFunc, pushing any IO_ERRORs and std::exceptions it throws onto m_errors.
|
||||||
|
*
|
||||||
|
* @return true if no error occurred.
|
||||||
|
*/
|
||||||
|
bool CatchErrors( std::function<void()> aFunc );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void StartWorkers( FP_LIB_TABLE* aTable, wxString const* aNickname,
|
||||||
|
FOOTPRINT_ASYNC_LOADER* aLoader, unsigned aNThreads ) override;
|
||||||
|
virtual bool JoinWorkers() override;
|
||||||
|
virtual size_t CountFinished() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function loader_job
|
||||||
|
* loads footprints from m_queue_in.
|
||||||
|
*/
|
||||||
|
void loader_job();
|
||||||
|
|
||||||
|
public:
|
||||||
|
FOOTPRINT_LIST_IMPL();
|
||||||
|
virtual ~FOOTPRINT_LIST_IMPL();
|
||||||
|
|
||||||
|
virtual bool ReadFootprintFiles(
|
||||||
|
FP_LIB_TABLE* aTable, const wxString* aNickname = NULL ) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FOOTPRINT_INFO_IMPL_H
|
|
@ -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 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
* Copyright (C) 2015 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||||
* Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 2016-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
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -165,6 +165,18 @@ wxArrayString GITHUB_PLUGIN::FootprintEnumerate(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GITHUB_PLUGIN::PrefetchLib(
|
||||||
|
const wxString& aLibraryPath, const PROPERTIES* aProperties )
|
||||||
|
{
|
||||||
|
if( m_lib_path != aLibraryPath )
|
||||||
|
{
|
||||||
|
m_zip_image.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
remoteGetZip( aLibraryPath );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
MODULE* GITHUB_PLUGIN::FootprintLoad( const wxString& aLibraryPath,
|
MODULE* GITHUB_PLUGIN::FootprintLoad( const wxString& aLibraryPath,
|
||||||
const wxString& aFootprintName, const PROPERTIES* aProperties )
|
const wxString& aFootprintName, const PROPERTIES* aProperties )
|
||||||
{
|
{
|
||||||
|
@ -370,9 +382,14 @@ void GITHUB_PLUGIN::cacheLib( const wxString& aLibraryPath, const PROPERTIES* aP
|
||||||
{
|
{
|
||||||
delete m_gh_cache;
|
delete m_gh_cache;
|
||||||
m_gh_cache = 0;
|
m_gh_cache = 0;
|
||||||
|
|
||||||
m_pretty_dir.clear();
|
m_pretty_dir.clear();
|
||||||
|
|
||||||
|
if( !m_lib_path.empty() )
|
||||||
|
{
|
||||||
|
// Library path wasn't empty before - it's been changed. Flush out the prefetch cache.
|
||||||
|
m_zip_image.clear();
|
||||||
|
}
|
||||||
|
|
||||||
if( aProperties )
|
if( aProperties )
|
||||||
{
|
{
|
||||||
UTF8 pretty_dir;
|
UTF8 pretty_dir;
|
||||||
|
@ -516,6 +533,9 @@ void GITHUB_PLUGIN::remoteGetZip( const wxString& aRepoURL ) throw( IO_ERROR )
|
||||||
{
|
{
|
||||||
std::string zip_url;
|
std::string zip_url;
|
||||||
|
|
||||||
|
if( !m_zip_image.empty() )
|
||||||
|
return;
|
||||||
|
|
||||||
if( !repoURL_zipURL( aRepoURL, &zip_url ) )
|
if( !repoURL_zipURL( aRepoURL, &zip_url ) )
|
||||||
{
|
{
|
||||||
wxString msg = wxString::Format( _( "Unable to parse URL:\n'%s'" ), GetChars( aRepoURL ) );
|
wxString msg = wxString::Format( _( "Unable to parse URL:\n'%s'" ), GetChars( aRepoURL ) );
|
||||||
|
|
|
@ -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) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
* Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||||
* Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 2016-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
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -170,6 +170,9 @@ public:
|
||||||
wxArrayString FootprintEnumerate( const wxString& aLibraryPath,
|
wxArrayString FootprintEnumerate( const wxString& aLibraryPath,
|
||||||
const PROPERTIES* aProperties = NULL ) override;
|
const PROPERTIES* aProperties = NULL ) override;
|
||||||
|
|
||||||
|
void PrefetchLib( const wxString& aLibraryPath,
|
||||||
|
const PROPERTIES* aProperties = NULL ) override;
|
||||||
|
|
||||||
MODULE* FootprintLoad( const wxString& aLibraryPath,
|
MODULE* FootprintLoad( const wxString& aLibraryPath,
|
||||||
const wxString& aFootprintName, const PROPERTIES* aProperties ) override;
|
const wxString& aFootprintName, const PROPERTIES* aProperties ) override;
|
||||||
|
|
||||||
|
@ -215,7 +218,8 @@ protected:
|
||||||
/**
|
/**
|
||||||
* Function remoteGetZip
|
* Function remoteGetZip
|
||||||
* fetches a zip file image from a github repo synchronously. The byte image
|
* fetches a zip file image from a github repo synchronously. The byte image
|
||||||
* is received into the m_input_stream.
|
* is received into the m_input_stream. If the image has already been stored,
|
||||||
|
* do nothing.
|
||||||
*/
|
*/
|
||||||
void remoteGetZip( const wxString& aRepoURL ) throw( IO_ERROR );
|
void remoteGetZip( const wxString& aRepoURL ) throw( IO_ERROR );
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,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) 2011-2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
* Copyright (C) 2011-2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||||
* Copyright (C) 2016 Kicad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 2016-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
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -282,6 +282,28 @@ public:
|
||||||
virtual wxArrayString FootprintEnumerate( const wxString& aLibraryPath,
|
virtual wxArrayString FootprintEnumerate( const wxString& aLibraryPath,
|
||||||
const PROPERTIES* aProperties = NULL );
|
const PROPERTIES* aProperties = NULL );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function PrefetchLib
|
||||||
|
* If possible, prefetches the specified library (e.g. performing downloads). Does not parse.
|
||||||
|
* Threadsafe.
|
||||||
|
*
|
||||||
|
* This is a no-op for libraries that cannot be prefetched.
|
||||||
|
*
|
||||||
|
* Plugins that cannot prefetch need not override this; a default no-op is provided.
|
||||||
|
*
|
||||||
|
* @param aLibraryPath is a locator for the "library", usually a directory, file,
|
||||||
|
* or URL containing several footprints.
|
||||||
|
*
|
||||||
|
* @param aProperties is an associative array that can be used to tell the
|
||||||
|
* plugin anything needed about how to perform with respect to @a aLibraryPath.
|
||||||
|
* The caller continues to own this object (plugin may not delete it), and
|
||||||
|
* plugins should expect it to be optionally NULL.
|
||||||
|
*
|
||||||
|
* @throw IO_ERROR if there is an error prefetching the library.
|
||||||
|
*/
|
||||||
|
virtual void PrefetchLib( const wxString& aLibraryPath,
|
||||||
|
const PROPERTIES* aProperties = NULL );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function FootprintLoad
|
* Function FootprintLoad
|
||||||
* loads a footprint having @a aFootprintName from the @a aLibraryPath containing
|
* loads a footprint having @a aFootprintName from the @a aLibraryPath containing
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
|
* Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
|
||||||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 1992-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
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -54,6 +54,7 @@ using namespace std::placeholders;
|
||||||
#include <pcbnew.h>
|
#include <pcbnew.h>
|
||||||
#include <module_editor_frame.h>
|
#include <module_editor_frame.h>
|
||||||
#include <footprint_info.h>
|
#include <footprint_info.h>
|
||||||
|
#include <footprint_info_impl.h>
|
||||||
#include <dialog_get_component.h>
|
#include <dialog_get_component.h>
|
||||||
#include <modview_frame.h>
|
#include <modview_frame.h>
|
||||||
#include <wildcards_and_files_ext.h>
|
#include <wildcards_and_files_ext.h>
|
||||||
|
@ -62,7 +63,9 @@ using namespace std::placeholders;
|
||||||
|
|
||||||
static void DisplayCmpDoc( wxString& aName, void* aData );
|
static void DisplayCmpDoc( wxString& aName, void* aData );
|
||||||
|
|
||||||
static FOOTPRINT_LIST MList;
|
// Use the _IMPL class directly here because this is static - don't want to yank
|
||||||
|
// a static through kiface.
|
||||||
|
static FOOTPRINT_LIST_IMPL MList;
|
||||||
|
|
||||||
static void clearModuleItemFlags( BOARD_ITEM* aItem )
|
static void clearModuleItemFlags( BOARD_ITEM* aItem )
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
* Copyright (C) 2012-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||||
* Copyright (C) 2008-2016 Wayne Stambaugh <stambaughw@verizon.net>
|
* Copyright (C) 2008-2016 Wayne Stambaugh <stambaughw@verizon.net>
|
||||||
* Copyright (C) 2004-2016 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
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -60,6 +60,7 @@
|
||||||
#include "tools/pcb_actions.h"
|
#include "tools/pcb_actions.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
|
||||||
|
@ -387,21 +388,21 @@ void FOOTPRINT_VIEWER_FRAME::ReCreateFootprintList()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FOOTPRINT_LIST fp_info_list;
|
auto fp_info_list( FOOTPRINT_LIST::GetInstance( Kiway() ) );
|
||||||
|
|
||||||
wxString nickname = getCurNickname();
|
wxString nickname = getCurNickname();
|
||||||
|
|
||||||
fp_info_list.ReadFootprintFiles( Prj().PcbFootprintLibs(), !nickname ? NULL : &nickname );
|
fp_info_list->ReadFootprintFiles( Prj().PcbFootprintLibs(), !nickname ? NULL : &nickname );
|
||||||
|
|
||||||
if( fp_info_list.GetErrorCount() )
|
if( fp_info_list->GetErrorCount() )
|
||||||
{
|
{
|
||||||
fp_info_list.DisplayErrors( this );
|
fp_info_list->DisplayErrors( this );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( const FOOTPRINT_INFO& footprint : fp_info_list.GetList() )
|
for( auto& footprint : fp_info_list->GetList() )
|
||||||
{
|
{
|
||||||
m_footprintList->Append( footprint.GetFootprintName() );
|
m_footprintList->Append( footprint->GetFootprintName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
int index = m_footprintList->FindString( getCurFootprintName() );
|
int index = m_footprintList->FindString( getCurFootprintName() );
|
||||||
|
|
|
@ -73,38 +73,6 @@ const COMPONENT_NET& COMPONENT::GetNet( const wxString& aPinName )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool COMPONENT::MatchesFootprintFilters( const wxString& aLibraryName, const wxString& aFootprintName ) const
|
|
||||||
{
|
|
||||||
if( m_footprintFilters.GetCount() == 0 )
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// The matching is case insensitive
|
|
||||||
wxString name = "";
|
|
||||||
|
|
||||||
EDA_PATTERN_MATCH_WILDCARD patternFilter;
|
|
||||||
|
|
||||||
for( unsigned ii = 0; ii < m_footprintFilters.GetCount(); ii++ )
|
|
||||||
{
|
|
||||||
// If the filter contains a ':' character, include the library name in the pattern
|
|
||||||
if( m_footprintFilters[ii].Contains( ":" ) )
|
|
||||||
{
|
|
||||||
name = aLibraryName.Lower() + ":";
|
|
||||||
}
|
|
||||||
|
|
||||||
name += aFootprintName.Lower();
|
|
||||||
|
|
||||||
patternFilter.SetPattern( m_footprintFilters[ii].Lower() );
|
|
||||||
|
|
||||||
if( patternFilter.Find( name ) != EDA_PATTERN_NOT_FOUND )
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void COMPONENT::Format( OUTPUTFORMATTER* aOut, int aNestLevel, int aCtl )
|
void COMPONENT::Format( OUTPUTFORMATTER* aOut, int aNestLevel, int aCtl )
|
||||||
{
|
{
|
||||||
int nl = aNestLevel;
|
int nl = aNestLevel;
|
||||||
|
|
|
@ -174,14 +174,6 @@ public:
|
||||||
|
|
||||||
const wxArrayString& GetFootprintFilters() const { return m_footprintFilters; }
|
const wxArrayString& GetFootprintFilters() const { return m_footprintFilters; }
|
||||||
|
|
||||||
/**
|
|
||||||
* Function MatchesFootprintFilters
|
|
||||||
*
|
|
||||||
* @return true if \a aFootprintName matches any of the footprint filters or no footprint
|
|
||||||
* filters are defined.
|
|
||||||
*/
|
|
||||||
bool MatchesFootprintFilters( const wxString& aLibraryName, const wxString& aFootprintName ) const;
|
|
||||||
|
|
||||||
MODULE* GetModule( bool aRelease = false )
|
MODULE* GetModule( bool aRelease = false )
|
||||||
{
|
{
|
||||||
return ( aRelease ) ? m_footprint.release() : m_footprint.get();
|
return ( aRelease ) ? m_footprint.release() : m_footprint.get();
|
||||||
|
|
|
@ -35,8 +35,10 @@
|
||||||
#include <fctsys.h>
|
#include <fctsys.h>
|
||||||
#include <pgm_base.h>
|
#include <pgm_base.h>
|
||||||
#include <kiface_i.h>
|
#include <kiface_i.h>
|
||||||
|
#include <kiface_ids.h>
|
||||||
#include <confirm.h>
|
#include <confirm.h>
|
||||||
#include <macros.h>
|
#include <macros.h>
|
||||||
|
#include <make_unique.h>
|
||||||
#include <class_drawpanel.h>
|
#include <class_drawpanel.h>
|
||||||
#include <wxPcbStruct.h>
|
#include <wxPcbStruct.h>
|
||||||
#include <eda_dde.h>
|
#include <eda_dde.h>
|
||||||
|
@ -58,6 +60,7 @@
|
||||||
#include <modview_frame.h>
|
#include <modview_frame.h>
|
||||||
#include <footprint_wizard_frame.h>
|
#include <footprint_wizard_frame.h>
|
||||||
#include <footprint_preview_panel.h>
|
#include <footprint_preview_panel.h>
|
||||||
|
#include <footprint_info_impl.h>
|
||||||
#include <gl_context_mgr.h>
|
#include <gl_context_mgr.h>
|
||||||
extern bool IsWxPythonLoaded();
|
extern bool IsWxPythonLoaded();
|
||||||
|
|
||||||
|
@ -170,7 +173,17 @@ static struct IFACE : public KIFACE_I
|
||||||
*/
|
*/
|
||||||
void* IfaceOrAddress( int aDataId ) override
|
void* IfaceOrAddress( int aDataId ) override
|
||||||
{
|
{
|
||||||
return NULL;
|
switch( aDataId )
|
||||||
|
{
|
||||||
|
case KIFACE_NEW_FOOTPRINT_LIST:
|
||||||
|
return (void*) static_cast<FOOTPRINT_LIST*>( new FOOTPRINT_LIST_IMPL() );
|
||||||
|
|
||||||
|
case KIFACE_G_FOOTPRINT_TABLE:
|
||||||
|
return (void*) new FP_LIB_TABLE( &GFootprintTable );
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} kiface( "pcbnew", KIWAY::FACE_PCB );
|
} kiface( "pcbnew", KIWAY::FACE_PCB );
|
||||||
|
|
|
@ -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) 2011-2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
* Copyright (C) 2011-2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||||
* Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 2016-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
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -66,6 +66,13 @@ wxArrayString PLUGIN::FootprintEnumerate( const wxString& aLibraryPath, const PR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PLUGIN::PrefetchLib( const wxString& aLibraryPath, const PROPERTIES* aProperties )
|
||||||
|
{
|
||||||
|
(void) aLibraryPath;
|
||||||
|
(void) aProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
MODULE* PLUGIN::FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName,
|
MODULE* PLUGIN::FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName,
|
||||||
const PROPERTIES* aProperties )
|
const PROPERTIES* aProperties )
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue