2014-02-14 08:05:04 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2014 Henner Zeller <h.zeller@acm.org>
|
2018-01-03 02:52:35 +00:00
|
|
|
* Copyright (C) 2016-2018 KiCad Developers, see AUTHORS.txt for contributors.
|
2014-02-14 08:05:04 +00:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
2017-02-19 02:39:55 +00:00
|
|
|
|
2014-02-14 08:05:04 +00:00
|
|
|
#include <dialog_choose_component.h>
|
|
|
|
|
2017-03-23 00:59:25 +00:00
|
|
|
#include <algorithm>
|
2014-02-14 08:05:04 +00:00
|
|
|
#include <set>
|
2017-02-19 02:39:55 +00:00
|
|
|
#include <wx/utils.h>
|
2014-02-14 08:05:04 +00:00
|
|
|
|
2017-03-23 00:59:25 +00:00
|
|
|
#include <wx/button.h>
|
2017-03-08 17:00:07 +00:00
|
|
|
#include <wx/dataview.h>
|
|
|
|
#include <wx/panel.h>
|
2017-03-23 00:59:25 +00:00
|
|
|
#include <wx/sizer.h>
|
2017-03-08 17:00:07 +00:00
|
|
|
#include <wx/splitter.h>
|
|
|
|
#include <wx/timer.h>
|
2017-03-08 20:10:50 +00:00
|
|
|
#include <wx/utils.h>
|
2017-03-08 17:00:07 +00:00
|
|
|
|
2014-02-14 08:05:04 +00:00
|
|
|
#include <class_library.h>
|
|
|
|
#include <sch_base_frame.h>
|
2017-02-19 14:00:02 +00:00
|
|
|
#include <template_fieldnames.h>
|
2017-09-15 14:17:44 +00:00
|
|
|
#include <symbol_lib_table.h>
|
2018-07-27 20:47:51 +00:00
|
|
|
#include <widgets/lib_tree.h>
|
2017-03-23 00:59:25 +00:00
|
|
|
#include <widgets/footprint_preview_widget.h>
|
|
|
|
#include <widgets/footprint_select_widget.h>
|
2014-02-14 08:05:04 +00:00
|
|
|
|
|
|
|
|
2018-02-08 18:40:55 +00:00
|
|
|
wxSize DIALOG_CHOOSE_COMPONENT::m_last_dlg_size( -1, -1 );
|
2018-07-25 23:16:34 +00:00
|
|
|
int DIALOG_CHOOSE_COMPONENT::m_h_sash_pos = 0;
|
|
|
|
int DIALOG_CHOOSE_COMPONENT::m_v_sash_pos = 0;
|
2018-01-06 02:33:41 +00:00
|
|
|
|
2018-04-16 22:18:02 +00:00
|
|
|
std::mutex DIALOG_CHOOSE_COMPONENT::g_Mutex;
|
|
|
|
|
|
|
|
|
2017-03-23 00:59:25 +00:00
|
|
|
DIALOG_CHOOSE_COMPONENT::DIALOG_CHOOSE_COMPONENT( SCH_BASE_FRAME* aParent, const wxString& aTitle,
|
2018-07-27 20:47:51 +00:00
|
|
|
SYMBOL_TREE_MODEL_ADAPTER::PTR& aAdapter,
|
|
|
|
int aDeMorganConvert, bool aAllowFieldEdits,
|
|
|
|
bool aShowFootprints, bool aAllowBrowser )
|
2018-01-06 02:33:41 +00:00
|
|
|
: DIALOG_SHIM( aParent, wxID_ANY, aTitle, wxDefaultPosition, wxDefaultSize,
|
2018-07-27 20:47:51 +00:00
|
|
|
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ),
|
|
|
|
m_browser_button( nullptr ),
|
2018-07-26 14:38:30 +00:00
|
|
|
m_hsplitter( nullptr ),
|
|
|
|
m_vsplitter( nullptr ),
|
2018-01-03 02:52:35 +00:00
|
|
|
m_fp_sel_ctrl( nullptr ),
|
2018-07-27 20:47:51 +00:00
|
|
|
m_fp_preview( nullptr ),
|
2017-03-23 00:59:25 +00:00
|
|
|
m_parent( aParent ),
|
|
|
|
m_deMorganConvert( aDeMorganConvert >= 0 ? aDeMorganConvert : 0 ),
|
|
|
|
m_allow_field_edits( aAllowFieldEdits ),
|
2018-01-03 02:52:35 +00:00
|
|
|
m_show_footprints( aShowFootprints ),
|
2018-07-26 14:38:30 +00:00
|
|
|
m_external_browser_requested( false )
|
2014-02-14 08:05:04 +00:00
|
|
|
{
|
2018-07-25 23:16:34 +00:00
|
|
|
auto sizer = new wxBoxSizer( wxVERTICAL );
|
|
|
|
wxHtmlWindow* details = nullptr;
|
2017-02-24 19:27:49 +00:00
|
|
|
|
2018-01-03 02:52:35 +00:00
|
|
|
// Use a slightly different layout, with a details pane spanning the entire window,
|
|
|
|
// if we're not showing footprints.
|
2018-07-25 23:16:34 +00:00
|
|
|
if( aShowFootprints )
|
|
|
|
{
|
|
|
|
m_hsplitter = new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
2018-08-02 17:00:41 +00:00
|
|
|
wxSP_LIVE_UPDATE );
|
2018-01-03 02:52:35 +00:00
|
|
|
|
2018-07-25 23:16:34 +00:00
|
|
|
//Avoid the splitter window being assigned as the Parent to additional windows
|
|
|
|
m_hsplitter->SetExtraStyle( wxWS_EX_TRANSIENT );
|
2018-01-03 02:52:35 +00:00
|
|
|
|
2018-07-25 23:16:34 +00:00
|
|
|
sizer->Add( m_hsplitter, 1, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_vsplitter = new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
2018-08-02 17:00:41 +00:00
|
|
|
wxSP_LIVE_UPDATE );
|
2018-06-06 04:22:13 +00:00
|
|
|
|
2018-07-25 23:16:34 +00:00
|
|
|
m_hsplitter = new wxSplitterWindow( m_vsplitter, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
2018-08-02 17:00:41 +00:00
|
|
|
wxSP_LIVE_UPDATE );
|
2018-01-03 02:52:35 +00:00
|
|
|
|
2018-07-25 23:16:34 +00:00
|
|
|
//Avoid the splitter window being assigned as the Parent to additional windows
|
|
|
|
m_hsplitter->SetExtraStyle( wxWS_EX_TRANSIENT );
|
2014-02-22 12:39:59 +00:00
|
|
|
|
2018-07-25 23:16:34 +00:00
|
|
|
auto detailsPanel = new wxPanel( m_vsplitter );
|
|
|
|
auto detailsSizer = new wxBoxSizer( wxVERTICAL );
|
|
|
|
detailsPanel->SetSizer( detailsSizer );
|
|
|
|
|
|
|
|
details = new wxHtmlWindow( detailsPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
2018-08-02 17:00:41 +00:00
|
|
|
wxHW_SCROLLBAR_AUTO );
|
2018-08-05 13:22:29 +00:00
|
|
|
detailsSizer->Add( details, 1, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 );
|
2018-07-25 23:16:34 +00:00
|
|
|
detailsPanel->Layout();
|
|
|
|
detailsSizer->Fit( detailsPanel );
|
|
|
|
|
|
|
|
m_vsplitter->SetSashGravity( 0.5 );
|
|
|
|
m_vsplitter->SetMinimumPaneSize( 20 );
|
|
|
|
m_vsplitter->SplitHorizontally( m_hsplitter, detailsPanel );
|
|
|
|
|
|
|
|
sizer->Add( m_vsplitter, 1, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5 );
|
|
|
|
}
|
|
|
|
|
2018-07-27 20:47:51 +00:00
|
|
|
m_tree = new LIB_TREE( m_hsplitter, Prj().SchSymbolLibTable(), aAdapter,
|
2018-08-02 17:00:41 +00:00
|
|
|
LIB_TREE::WIDGETS::ALL, details );
|
2018-07-25 23:16:34 +00:00
|
|
|
|
|
|
|
m_hsplitter->SetSashGravity( 0.8 );
|
|
|
|
m_hsplitter->SetMinimumPaneSize( 20 );
|
2018-07-27 20:47:51 +00:00
|
|
|
m_hsplitter->SplitVertically( m_tree, ConstructRightPanel( m_hsplitter ) );
|
2018-01-03 02:52:35 +00:00
|
|
|
|
2018-07-25 23:16:34 +00:00
|
|
|
m_dbl_click_timer = new wxTimer( this );
|
|
|
|
|
2018-07-27 20:47:51 +00:00
|
|
|
auto buttonsSizer = new wxBoxSizer( wxHORIZONTAL );
|
|
|
|
|
|
|
|
if( aAllowBrowser )
|
|
|
|
{
|
|
|
|
m_browser_button = new wxButton( this, wxID_ANY, _( "Select with Browser" ) );
|
2018-08-05 13:22:29 +00:00
|
|
|
buttonsSizer->Add( m_browser_button, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
|
2018-07-27 20:47:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
auto sdbSizer = new wxStdDialogButtonSizer();
|
|
|
|
auto okButton = new wxButton( this, wxID_OK );
|
|
|
|
auto cancelButton = new wxButton( this, wxID_CANCEL );
|
|
|
|
sdbSizer->AddButton( okButton );
|
|
|
|
sdbSizer->AddButton( cancelButton );
|
|
|
|
sdbSizer->Realize();
|
|
|
|
|
|
|
|
buttonsSizer->Add( sdbSizer, 1, wxALL, 5 );
|
2015-03-30 19:34:41 +00:00
|
|
|
|
2018-07-27 20:47:51 +00:00
|
|
|
sizer->Add( buttonsSizer, 0, wxEXPAND | wxLEFT, 5 );
|
2017-03-08 17:00:07 +00:00
|
|
|
SetSizer( sizer );
|
|
|
|
|
|
|
|
Bind( wxEVT_INIT_DIALOG, &DIALOG_CHOOSE_COMPONENT::OnInitDialog, this );
|
2017-03-23 00:59:25 +00:00
|
|
|
Bind( wxEVT_TIMER, &DIALOG_CHOOSE_COMPONENT::OnCloseTimer, this, m_dbl_click_timer->GetId() );
|
2017-06-25 21:13:39 +00:00
|
|
|
Bind( COMPONENT_PRESELECTED, &DIALOG_CHOOSE_COMPONENT::OnComponentPreselected, this );
|
|
|
|
Bind( COMPONENT_SELECTED, &DIALOG_CHOOSE_COMPONENT::OnComponentSelected, this );
|
2018-07-27 20:47:51 +00:00
|
|
|
m_symbol_preview->Bind( wxEVT_PAINT, &DIALOG_CHOOSE_COMPONENT::OnSymbolPreviewPaint, this );
|
2017-03-23 00:59:25 +00:00
|
|
|
|
2018-07-27 20:47:51 +00:00
|
|
|
if( m_browser_button )
|
2018-08-02 17:00:41 +00:00
|
|
|
m_browser_button->Bind( wxEVT_COMMAND_BUTTON_CLICKED,
|
|
|
|
&DIALOG_CHOOSE_COMPONENT::OnUseBrowser, this );
|
2017-03-08 17:00:07 +00:00
|
|
|
|
2017-03-23 00:59:25 +00:00
|
|
|
if( m_fp_sel_ctrl )
|
2018-08-02 17:00:41 +00:00
|
|
|
m_fp_sel_ctrl->Bind( EVT_FOOTPRINT_SELECTED,
|
|
|
|
&DIALOG_CHOOSE_COMPONENT::OnFootprintSelected, this );
|
2017-03-23 00:59:25 +00:00
|
|
|
|
2017-02-19 02:39:55 +00:00
|
|
|
Layout();
|
2018-01-06 02:33:41 +00:00
|
|
|
|
2018-02-08 18:40:55 +00:00
|
|
|
// We specify the width of the right window (m_symbol_view_panel), because specify
|
|
|
|
// the width of the left window does not work as expected when SetSashGravity() is called
|
2018-07-25 23:16:34 +00:00
|
|
|
m_hsplitter->SetSashPosition( m_h_sash_pos ? m_h_sash_pos : HorizPixelsFromDU( 240 ) );
|
2018-01-06 18:18:28 +00:00
|
|
|
|
2018-07-25 23:16:34 +00:00
|
|
|
if( m_vsplitter )
|
|
|
|
m_vsplitter->SetSashPosition( m_v_sash_pos ? m_v_sash_pos : VertPixelsFromDU( 170 ) );
|
|
|
|
|
|
|
|
if( m_last_dlg_size == wxSize( -1, -1 ) )
|
|
|
|
SetSizeInDU( 360, 280 );
|
|
|
|
else
|
|
|
|
SetSize( m_last_dlg_size );
|
2018-07-27 20:47:51 +00:00
|
|
|
|
|
|
|
SetInitialFocus( m_tree );
|
|
|
|
okButton->SetDefault();
|
2017-03-08 17:00:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-23 15:52:05 +00:00
|
|
|
DIALOG_CHOOSE_COMPONENT::~DIALOG_CHOOSE_COMPONENT()
|
|
|
|
{
|
2018-06-08 23:50:06 +00:00
|
|
|
Unbind( wxEVT_INIT_DIALOG, &DIALOG_CHOOSE_COMPONENT::OnInitDialog, this );
|
|
|
|
Unbind( wxEVT_TIMER, &DIALOG_CHOOSE_COMPONENT::OnCloseTimer, this );
|
|
|
|
Unbind( COMPONENT_PRESELECTED, &DIALOG_CHOOSE_COMPONENT::OnComponentPreselected, this );
|
|
|
|
Unbind( COMPONENT_SELECTED, &DIALOG_CHOOSE_COMPONENT::OnComponentSelected, this );
|
2018-07-27 20:47:51 +00:00
|
|
|
m_symbol_preview->Unbind( wxEVT_PAINT, &DIALOG_CHOOSE_COMPONENT::OnSymbolPreviewPaint, this );
|
2018-06-08 23:50:06 +00:00
|
|
|
|
2018-07-27 20:47:51 +00:00
|
|
|
if( m_browser_button )
|
2018-08-02 17:00:41 +00:00
|
|
|
m_browser_button->Unbind( wxEVT_COMMAND_BUTTON_CLICKED,
|
|
|
|
&DIALOG_CHOOSE_COMPONENT::OnUseBrowser, this );
|
2018-06-08 23:50:06 +00:00
|
|
|
|
|
|
|
if( m_fp_sel_ctrl )
|
2018-08-02 17:00:41 +00:00
|
|
|
m_fp_sel_ctrl->Unbind( EVT_FOOTPRINT_SELECTED,
|
|
|
|
&DIALOG_CHOOSE_COMPONENT::OnFootprintSelected, this );
|
2018-06-08 23:50:06 +00:00
|
|
|
|
2017-03-23 15:52:05 +00:00
|
|
|
// I am not sure the following two lines are necessary,
|
|
|
|
// but they will not hurt anyone
|
|
|
|
m_dbl_click_timer->Stop();
|
|
|
|
delete m_dbl_click_timer;
|
2018-01-06 02:33:41 +00:00
|
|
|
|
2018-02-08 18:40:55 +00:00
|
|
|
m_last_dlg_size = GetSize();
|
2018-07-25 23:16:34 +00:00
|
|
|
m_h_sash_pos = m_hsplitter->GetSashPosition();
|
|
|
|
|
|
|
|
if( m_vsplitter )
|
|
|
|
m_v_sash_pos = m_vsplitter->GetSashPosition();
|
2017-03-23 15:52:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-08 17:00:07 +00:00
|
|
|
wxPanel* DIALOG_CHOOSE_COMPONENT::ConstructRightPanel( wxWindow* aParent )
|
2014-02-14 08:05:04 +00:00
|
|
|
{
|
2017-03-08 17:00:07 +00:00
|
|
|
auto panel = new wxPanel( aParent );
|
|
|
|
auto sizer = new wxBoxSizer( wxVERTICAL );
|
|
|
|
|
2018-07-27 20:47:51 +00:00
|
|
|
m_symbol_preview = new wxPanel( panel, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ),
|
2018-08-02 17:00:41 +00:00
|
|
|
wxFULL_REPAINT_ON_RESIZE | wxTAB_TRAVERSAL );
|
2018-07-27 20:47:51 +00:00
|
|
|
m_symbol_preview->SetLayoutDirection( wxLayout_LeftToRight );
|
2017-03-08 17:00:07 +00:00
|
|
|
|
2018-01-03 02:52:35 +00:00
|
|
|
if( m_show_footprints )
|
|
|
|
{
|
2018-05-30 07:51:47 +00:00
|
|
|
FOOTPRINT_LIST* fp_list = FOOTPRINT_LIST::GetInstance( Kiway() );
|
|
|
|
|
2018-01-03 02:52:35 +00:00
|
|
|
if( m_allow_field_edits )
|
2018-05-30 07:51:47 +00:00
|
|
|
m_fp_sel_ctrl = new FOOTPRINT_SELECT_WIDGET( panel, fp_list, true );
|
2017-03-08 17:00:07 +00:00
|
|
|
|
2018-07-27 20:47:51 +00:00
|
|
|
m_fp_preview = new FOOTPRINT_PREVIEW_WIDGET( panel, Kiway() );
|
2017-03-08 17:00:07 +00:00
|
|
|
|
2017-03-23 00:59:25 +00:00
|
|
|
|
2018-07-27 20:47:51 +00:00
|
|
|
sizer->Add( m_symbol_preview, 1, wxEXPAND | wxTOP | wxBOTTOM | wxRIGHT, 5 );
|
2017-03-23 00:59:25 +00:00
|
|
|
|
2018-01-03 02:52:35 +00:00
|
|
|
if( m_fp_sel_ctrl )
|
2018-08-02 17:00:41 +00:00
|
|
|
sizer->Add( m_fp_sel_ctrl, 0, wxEXPAND | wxBOTTOM | wxTOP | wxRIGHT, 5 );
|
2017-03-23 00:59:25 +00:00
|
|
|
|
2018-07-27 20:47:51 +00:00
|
|
|
sizer->Add( m_fp_preview, 1, wxEXPAND | wxBOTTOM | wxRIGHT, 5 );
|
2018-01-03 02:52:35 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-07-27 20:47:51 +00:00
|
|
|
sizer->Add( m_symbol_preview, 1, wxEXPAND | wxTOP | wxRIGHT, 5 );
|
2018-01-03 02:52:35 +00:00
|
|
|
}
|
2017-03-08 17:00:07 +00:00
|
|
|
|
|
|
|
panel->SetSizer( sizer );
|
|
|
|
panel->Layout();
|
|
|
|
sizer->Fit( panel );
|
|
|
|
|
|
|
|
return panel;
|
2014-02-24 10:52:08 +00:00
|
|
|
}
|
2014-02-14 08:05:04 +00:00
|
|
|
|
2017-03-08 17:00:07 +00:00
|
|
|
|
|
|
|
void DIALOG_CHOOSE_COMPONENT::OnInitDialog( wxInitDialogEvent& aEvent )
|
2017-01-22 22:29:16 +00:00
|
|
|
{
|
2018-07-27 20:47:51 +00:00
|
|
|
if( m_fp_preview && m_fp_preview->IsInitialized() )
|
2017-03-08 17:00:07 +00:00
|
|
|
{
|
|
|
|
// This hides the GAL panel and shows the status label
|
2018-07-27 20:47:51 +00:00
|
|
|
m_fp_preview->SetStatusText( wxEmptyString );
|
2017-03-08 17:00:07 +00:00
|
|
|
}
|
2018-06-08 23:50:06 +00:00
|
|
|
|
|
|
|
if( m_fp_sel_ctrl )
|
|
|
|
m_fp_sel_ctrl->Load( Kiway(), Prj() );
|
2018-04-16 22:18:02 +00:00
|
|
|
}
|
2017-03-23 00:59:25 +00:00
|
|
|
|
2018-04-16 22:18:02 +00:00
|
|
|
|
2018-07-27 20:47:51 +00:00
|
|
|
LIB_ID DIALOG_CHOOSE_COMPONENT::GetSelectedLibId( int* aUnit ) const
|
2018-04-16 22:18:02 +00:00
|
|
|
{
|
2018-07-27 20:47:51 +00:00
|
|
|
return m_tree->GetSelectedLibId( aUnit );
|
2017-01-22 22:29:16 +00:00
|
|
|
}
|
|
|
|
|
2014-02-18 21:41:27 +00:00
|
|
|
|
2018-07-27 20:47:51 +00:00
|
|
|
void DIALOG_CHOOSE_COMPONENT::OnUseBrowser( wxCommandEvent& aEvent )
|
2014-02-24 10:52:08 +00:00
|
|
|
{
|
2018-07-27 20:47:51 +00:00
|
|
|
m_external_browser_requested = true;
|
|
|
|
EndQuasiModal( wxID_OK );
|
2014-02-14 08:05:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-24 01:29:03 +00:00
|
|
|
void DIALOG_CHOOSE_COMPONENT::OnCloseTimer( wxTimerEvent& aEvent )
|
2014-02-14 08:05:04 +00:00
|
|
|
{
|
2017-02-24 01:29:03 +00:00
|
|
|
// Hack handler because of eaten MouseUp event. See
|
2018-06-08 23:50:06 +00:00
|
|
|
// DIALOG_CHOOSE_COMPONENT::OnComponentSelected for the beginning
|
2017-02-24 01:29:03 +00:00
|
|
|
// of this spaghetti noodle.
|
|
|
|
|
|
|
|
auto state = wxGetMouseState();
|
|
|
|
|
|
|
|
if( state.LeftIsDown() )
|
|
|
|
{
|
|
|
|
// Mouse hasn't been raised yet, so fire the timer again. Otherwise the
|
|
|
|
// purpose of this timer is defeated.
|
|
|
|
m_dbl_click_timer->StartOnce( DIALOG_CHOOSE_COMPONENT::DblClickDelay );
|
|
|
|
}
|
2017-02-24 01:59:15 +00:00
|
|
|
else
|
2017-02-24 01:29:03 +00:00
|
|
|
{
|
2017-03-23 00:59:25 +00:00
|
|
|
EndQuasiModal( wxID_OK );
|
2017-02-24 01:29:03 +00:00
|
|
|
}
|
2014-02-14 08:05:04 +00:00
|
|
|
}
|
|
|
|
|
2017-02-24 01:59:15 +00:00
|
|
|
|
2017-09-15 14:17:44 +00:00
|
|
|
void DIALOG_CHOOSE_COMPONENT::ShowFootprintFor( LIB_ID const& aLibId )
|
2017-02-19 02:39:55 +00:00
|
|
|
{
|
2018-07-27 20:47:51 +00:00
|
|
|
if( !m_fp_preview || !m_fp_preview->IsInitialized() )
|
2017-02-19 02:39:55 +00:00
|
|
|
return;
|
|
|
|
|
2017-09-15 14:17:44 +00:00
|
|
|
LIB_ALIAS* alias = nullptr;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
alias = Prj().SchSymbolLibTable()->LoadSymbol( aLibId );
|
|
|
|
}
|
|
|
|
catch( const IO_ERROR& ioe )
|
|
|
|
{
|
|
|
|
wxLogError( wxString::Format( _( "Error occurred loading symbol %s from library %s."
|
|
|
|
"\n\n%s" ),
|
|
|
|
aLibId.GetLibItemName().wx_str(),
|
|
|
|
aLibId.GetLibNickname().wx_str(),
|
|
|
|
ioe.What() ) );
|
|
|
|
}
|
|
|
|
|
2018-07-27 20:47:51 +00:00
|
|
|
if( !alias )
|
2017-09-15 14:17:44 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
LIB_FIELD* fp_field = alias->GetPart()->GetField( FOOTPRINT );
|
2017-03-23 00:59:25 +00:00
|
|
|
wxString fp_name = fp_field ? fp_field->GetFullText() : wxString( "" );
|
|
|
|
|
|
|
|
ShowFootprint( fp_name );
|
|
|
|
}
|
2017-02-19 02:39:55 +00:00
|
|
|
|
2017-03-23 00:59:25 +00:00
|
|
|
|
|
|
|
void DIALOG_CHOOSE_COMPONENT::ShowFootprint( wxString const& aName )
|
|
|
|
{
|
2018-07-27 20:47:51 +00:00
|
|
|
if( !m_fp_preview || !m_fp_preview->IsInitialized() )
|
2018-01-03 02:52:35 +00:00
|
|
|
return;
|
|
|
|
|
2017-03-23 00:59:25 +00:00
|
|
|
if( aName == wxEmptyString )
|
2017-02-19 02:39:55 +00:00
|
|
|
{
|
2018-07-27 20:47:51 +00:00
|
|
|
m_fp_preview->SetStatusText( _( "No footprint specified" ) );
|
2017-03-23 00:59:25 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-09-15 14:17:44 +00:00
|
|
|
LIB_ID lib_id;
|
|
|
|
|
2018-07-26 14:38:30 +00:00
|
|
|
if( lib_id.Parse( aName, LIB_ID::ID_PCB ) == -1 && lib_id.IsValid() )
|
2017-09-15 14:17:44 +00:00
|
|
|
{
|
2018-07-27 20:47:51 +00:00
|
|
|
m_fp_preview->ClearStatus();
|
|
|
|
m_fp_preview->CacheFootprint( lib_id );
|
|
|
|
m_fp_preview->DisplayFootprint( lib_id );
|
2017-09-15 14:17:44 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-07-27 20:47:51 +00:00
|
|
|
m_fp_preview->SetStatusText( _( "Invalid footprint specified" ) );
|
2017-09-15 14:17:44 +00:00
|
|
|
}
|
2017-03-23 00:59:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-09-15 14:17:44 +00:00
|
|
|
void DIALOG_CHOOSE_COMPONENT::PopulateFootprintSelector( LIB_ID const& aLibId )
|
2017-03-23 00:59:25 +00:00
|
|
|
{
|
|
|
|
if( !m_fp_sel_ctrl )
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_fp_sel_ctrl->ClearFilters();
|
|
|
|
|
2017-09-15 14:17:44 +00:00
|
|
|
LIB_ALIAS* alias = nullptr;
|
|
|
|
|
2017-10-06 18:07:43 +00:00
|
|
|
if( aLibId.IsValid() )
|
2017-09-15 14:17:44 +00:00
|
|
|
{
|
2017-10-06 18:07:43 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
alias = Prj().SchSymbolLibTable()->LoadSymbol( aLibId );
|
|
|
|
}
|
|
|
|
catch( const IO_ERROR& ioe )
|
|
|
|
{
|
|
|
|
wxLogError( wxString::Format( _( "Error occurred loading symbol %s from library %s."
|
|
|
|
"\n\n%s" ),
|
|
|
|
aLibId.GetLibItemName().wx_str(),
|
|
|
|
aLibId.GetLibNickname().wx_str(),
|
|
|
|
ioe.What() ) );
|
|
|
|
}
|
2017-09-15 14:17:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if( alias != nullptr )
|
2017-03-23 00:59:25 +00:00
|
|
|
{
|
|
|
|
LIB_PINS temp_pins;
|
2017-09-15 14:17:44 +00:00
|
|
|
LIB_FIELD* fp_field = alias->GetPart()->GetField( FOOTPRINT );
|
2017-03-23 00:59:25 +00:00
|
|
|
wxString fp_name = fp_field ? fp_field->GetFullText() : wxString( "" );
|
|
|
|
|
2017-09-15 14:17:44 +00:00
|
|
|
alias->GetPart()->GetPins( temp_pins );
|
2017-03-23 00:59:25 +00:00
|
|
|
|
|
|
|
m_fp_sel_ctrl->FilterByPinCount( temp_pins.size() );
|
2017-12-01 16:49:19 +00:00
|
|
|
m_fp_sel_ctrl->FilterByFootprintFilters( alias->GetPart()->GetFootprints(), true );
|
2017-03-23 00:59:25 +00:00
|
|
|
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();
|
2017-02-19 02:39:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-27 20:47:51 +00:00
|
|
|
void DIALOG_CHOOSE_COMPONENT::OnSymbolPreviewPaint( wxPaintEvent& aEvent )
|
2014-02-18 21:41:27 +00:00
|
|
|
{
|
2017-04-10 14:22:41 +00:00
|
|
|
int unit = 0;
|
2017-09-15 14:17:44 +00:00
|
|
|
LIB_ID id = m_tree->GetSelectedLibId( &unit );
|
|
|
|
|
|
|
|
if( !id.IsValid() )
|
2017-11-23 12:24:02 +00:00
|
|
|
{
|
|
|
|
// No symbol to show, display a tooltip
|
|
|
|
RenderPreview( nullptr, unit );
|
2017-09-15 14:17:44 +00:00
|
|
|
return;
|
2017-11-23 12:24:02 +00:00
|
|
|
}
|
2017-09-15 14:17:44 +00:00
|
|
|
|
|
|
|
LIB_ALIAS* alias = nullptr;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
alias = Prj().SchSymbolLibTable()->LoadSymbol( id );
|
|
|
|
}
|
|
|
|
catch( const IO_ERROR& ioe )
|
|
|
|
{
|
|
|
|
wxLogError( wxString::Format( _( "Error occurred loading symbol %s from library %s."
|
|
|
|
"\n\n%s" ),
|
|
|
|
id.GetLibItemName().wx_str(),
|
|
|
|
id.GetLibNickname().wx_str(),
|
|
|
|
ioe.What() ) );
|
|
|
|
}
|
|
|
|
|
2018-07-27 20:47:51 +00:00
|
|
|
if( !alias )
|
2017-09-15 14:17:44 +00:00
|
|
|
return;
|
|
|
|
|
2018-07-27 20:47:51 +00:00
|
|
|
LIB_PART* part = alias->GetPart();
|
2014-10-09 00:49:29 +00:00
|
|
|
|
2018-08-05 13:22:29 +00:00
|
|
|
// Don't draw if we don't have a part to show, just display a tooltip
|
2014-10-09 00:49:29 +00:00
|
|
|
if( !part )
|
2018-08-05 13:22:29 +00:00
|
|
|
{
|
|
|
|
RenderPreview( nullptr, unit );
|
2014-10-09 00:49:29 +00:00
|
|
|
return;
|
2018-08-05 13:22:29 +00:00
|
|
|
}
|
2014-02-18 21:41:27 +00:00
|
|
|
|
2017-03-06 14:50:48 +00:00
|
|
|
if( alias->IsRoot() )
|
2014-10-09 00:49:29 +00:00
|
|
|
{
|
|
|
|
// just show the part directly
|
2017-03-08 17:00:07 +00:00
|
|
|
RenderPreview( part, unit );
|
2014-10-09 00:49:29 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// switch out the name temporarily for the alias name
|
|
|
|
wxString tmp( part->GetName() );
|
2017-03-06 14:50:48 +00:00
|
|
|
part->SetName( alias->GetName() );
|
2014-10-09 00:49:29 +00:00
|
|
|
|
2017-03-08 17:00:07 +00:00
|
|
|
RenderPreview( part, unit );
|
2014-10-09 00:49:29 +00:00
|
|
|
|
|
|
|
part->SetName( tmp );
|
|
|
|
}
|
2014-02-14 08:05:04 +00:00
|
|
|
}
|
|
|
|
|
2014-02-18 21:41:27 +00:00
|
|
|
|
2017-03-23 00:59:25 +00:00
|
|
|
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 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-06-25 21:13:39 +00:00
|
|
|
void DIALOG_CHOOSE_COMPONENT::OnComponentPreselected( wxCommandEvent& aEvent )
|
|
|
|
{
|
|
|
|
int unit = 0;
|
2017-09-15 14:17:44 +00:00
|
|
|
|
|
|
|
LIB_ID id = m_tree->GetSelectedLibId( &unit );
|
2017-06-25 21:13:39 +00:00
|
|
|
|
2018-07-27 20:47:51 +00:00
|
|
|
m_symbol_preview->Refresh();
|
2017-06-25 21:13:39 +00:00
|
|
|
|
2017-09-15 14:17:44 +00:00
|
|
|
if( id.IsValid() )
|
2017-06-25 21:13:39 +00:00
|
|
|
{
|
2017-09-15 14:17:44 +00:00
|
|
|
ShowFootprintFor( id );
|
|
|
|
PopulateFootprintSelector( id );
|
2017-06-25 21:13:39 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-07-27 20:47:51 +00:00
|
|
|
if( m_fp_preview && m_fp_preview->IsInitialized() )
|
|
|
|
m_fp_preview->SetStatusText( wxEmptyString );
|
2017-06-25 21:13:39 +00:00
|
|
|
|
2017-09-15 14:17:44 +00:00
|
|
|
PopulateFootprintSelector( id );
|
2017-06-25 21:13:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DIALOG_CHOOSE_COMPONENT::OnComponentSelected( wxCommandEvent& aEvent )
|
|
|
|
{
|
2017-09-15 14:17:44 +00:00
|
|
|
if( m_tree->GetSelectedLibId().IsValid() )
|
2017-06-25 21:13:39 +00:00
|
|
|
{
|
|
|
|
// Got a selection. We can't just end the modal dialog here, because
|
|
|
|
// wx leaks some events back to the parent window (in particular, the
|
|
|
|
// MouseUp following a double click).
|
|
|
|
//
|
|
|
|
// NOW, here's where it gets really fun. wxTreeListCtrl eats MouseUp.
|
|
|
|
// This isn't really feasible to bypass without a fully custom
|
|
|
|
// wxDataViewCtrl implementation, and even then might not be fully
|
|
|
|
// possible (docs are vague). To get around this, we use a one-shot
|
|
|
|
// timer to schedule the dialog close.
|
|
|
|
//
|
|
|
|
// See DIALOG_CHOOSE_COMPONENT::OnCloseTimer for the other end of this
|
|
|
|
// spaghetti noodle.
|
|
|
|
m_dbl_click_timer->StartOnce( DIALOG_CHOOSE_COMPONENT::DblClickDelay );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-08 17:00:07 +00:00
|
|
|
void DIALOG_CHOOSE_COMPONENT::RenderPreview( LIB_PART* aComponent, int aUnit )
|
2014-02-18 21:41:27 +00:00
|
|
|
{
|
2018-07-27 20:47:51 +00:00
|
|
|
wxPaintDC dc( m_symbol_preview );
|
2015-08-30 14:46:34 +00:00
|
|
|
|
|
|
|
const wxSize dc_size = dc.GetSize();
|
|
|
|
|
|
|
|
// Avoid rendering when either dimension is zero
|
|
|
|
if( dc_size.x == 0 || dc_size.y == 0 )
|
|
|
|
return;
|
|
|
|
|
|
|
|
GRResetPenAndBrush( &dc );
|
|
|
|
|
2017-02-20 16:57:41 +00:00
|
|
|
COLOR4D bgColor = m_parent->GetDrawBgColor();
|
2014-10-09 00:49:29 +00:00
|
|
|
|
2017-02-20 16:57:41 +00:00
|
|
|
dc.SetBackground( wxBrush( bgColor.ToColour() ) );
|
2014-02-18 21:41:27 +00:00
|
|
|
dc.Clear();
|
|
|
|
|
2018-08-05 15:00:17 +00:00
|
|
|
if( !aComponent ) // display a tooltip
|
|
|
|
{
|
|
|
|
wxString tooltip = _( "No symbol selected" );
|
|
|
|
GRDrawWrappedText( dc, tooltip );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-07-19 17:43:18 +00:00
|
|
|
int unit = aUnit > 0 ? aUnit : 1;
|
|
|
|
int convert = m_deMorganConvert > 0 ? m_deMorganConvert : 1;
|
2014-02-18 21:41:27 +00:00
|
|
|
|
|
|
|
dc.SetDeviceOrigin( dc_size.x / 2, dc_size.y / 2 );
|
|
|
|
|
|
|
|
// Find joint bounding box for everything we are about to draw.
|
2017-07-19 17:43:18 +00:00
|
|
|
EDA_RECT bBox = aComponent->GetUnitBoundingBox( unit, convert );
|
2014-02-18 21:41:27 +00:00
|
|
|
const double xscale = (double) dc_size.x / bBox.GetWidth();
|
|
|
|
const double yscale = (double) dc_size.y / bBox.GetHeight();
|
2017-03-23 00:59:25 +00:00
|
|
|
const double scale = std::min( xscale, yscale ) * 0.85;
|
2014-02-18 21:41:27 +00:00
|
|
|
|
|
|
|
dc.SetUserScale( scale, scale );
|
|
|
|
|
2015-06-26 13:41:56 +00:00
|
|
|
wxPoint offset = -bBox.Centre();
|
2014-02-18 21:41:27 +00:00
|
|
|
|
2017-02-19 18:40:26 +00:00
|
|
|
auto opts = PART_DRAW_OPTIONS::Default();
|
2017-02-19 18:43:50 +00:00
|
|
|
opts.draw_hidden_fields = false;
|
2017-07-19 17:43:18 +00:00
|
|
|
aComponent->Draw( nullptr, &dc, offset, unit, convert, opts );
|
2014-02-18 21:41:27 +00:00
|
|
|
}
|