mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 02:03:12 +02:00
Recommendation is to avoid using the year nomenclature as this information is already encoded in the git repo. Avoids needing to repeatly update. Also updates AUTHORS.txt from current repo with contributor names
718 lines
23 KiB
C++
718 lines
23 KiB
C++
/*
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
*
|
|
* Copyright (C) 2023 CERN
|
|
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, you may find one here:
|
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
|
* or you may write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#include <pgm_base.h>
|
|
#include <kiface_base.h>
|
|
#include <kiway.h>
|
|
#include <kiway_express.h>
|
|
#include <board.h>
|
|
#include <wx/button.h>
|
|
#include <wx/checkbox.h>
|
|
#include <kiplatform/ui.h>
|
|
#include <lset.h>
|
|
#include <widgets/panel_footprint_chooser.h>
|
|
#include <settings/settings_manager.h>
|
|
#include <footprint_editor_settings.h>
|
|
#include <footprint_chooser_frame.h>
|
|
#include "wx/display.h"
|
|
#include <3d_canvas/eda_3d_canvas.h>
|
|
#include <project_pcb.h>
|
|
#include <widgets/bitmap_button.h>
|
|
#include <3d_viewer/eda_3d_viewer_frame.h>
|
|
|
|
|
|
static wxArrayString s_FootprintHistoryList;
|
|
static unsigned s_FootprintHistoryMaxCount = 8;
|
|
|
|
static void AddFootprintToHistory( const wxString& aName )
|
|
{
|
|
// Remove duplicates
|
|
for( int ii = (int) s_FootprintHistoryList.GetCount() - 1; ii >= 0; --ii )
|
|
{
|
|
if( s_FootprintHistoryList[ ii ] == aName )
|
|
s_FootprintHistoryList.RemoveAt( (size_t) ii );
|
|
}
|
|
|
|
// Add the new name at the beginning of the history list
|
|
s_FootprintHistoryList.Insert( aName, 0 );
|
|
|
|
// Remove extra names
|
|
while( s_FootprintHistoryList.GetCount() >= s_FootprintHistoryMaxCount )
|
|
s_FootprintHistoryList.RemoveAt( s_FootprintHistoryList.GetCount() - 1 );
|
|
}
|
|
|
|
|
|
BEGIN_EVENT_TABLE( FOOTPRINT_CHOOSER_FRAME, PCB_BASE_FRAME )
|
|
EVT_MENU( wxID_CLOSE, FOOTPRINT_CHOOSER_FRAME::closeFootprintChooser )
|
|
EVT_BUTTON( wxID_OK, FOOTPRINT_CHOOSER_FRAME::OnOK )
|
|
EVT_BUTTON( wxID_CANCEL, FOOTPRINT_CHOOSER_FRAME::closeFootprintChooser )
|
|
EVT_PAINT( FOOTPRINT_CHOOSER_FRAME::OnPaint )
|
|
END_EVENT_TABLE()
|
|
|
|
|
|
#define MODAL_FRAME ( wxRESIZE_BORDER | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN \
|
|
| wxWANTS_CHARS | wxFRAME_NO_TASKBAR | wxFRAME_FLOAT_ON_PARENT )
|
|
|
|
|
|
FOOTPRINT_CHOOSER_FRAME::FOOTPRINT_CHOOSER_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
|
PCB_BASE_FRAME( aKiway, aParent, FRAME_FOOTPRINT_CHOOSER, _( "Footprint Chooser" ),
|
|
wxDefaultPosition, wxDefaultSize, MODAL_FRAME,
|
|
FOOTPRINT_CHOOSER_FRAME_NAME ),
|
|
m_filterByPinCount( nullptr ),
|
|
m_filterByFPFilters( nullptr ),
|
|
m_boardAdapter(),
|
|
m_currentCamera( m_trackBallCamera ),
|
|
m_trackBallCamera( 2 * RANGE_SCALE_3D ),
|
|
m_pinCount( 0 ),
|
|
m_firstPaintEvent( true )
|
|
{
|
|
SetModal( true );
|
|
|
|
m_showFpMode = true;
|
|
m_show3DMode = false;
|
|
m_messagePanel->Hide();
|
|
|
|
wxPanel* bottomPanel = new wxPanel( this );
|
|
wxBoxSizer* bottomSizer = new wxBoxSizer( wxVERTICAL );
|
|
wxBoxSizer* frameSizer = new wxBoxSizer( wxVERTICAL );
|
|
|
|
m_chooserPanel = new PANEL_FOOTPRINT_CHOOSER( this, this, s_FootprintHistoryList,
|
|
// Filter
|
|
[this]( LIB_TREE_NODE& aNode ) -> bool
|
|
{
|
|
return filterFootprint( aNode );
|
|
},
|
|
// Accept handler
|
|
[this]()
|
|
{
|
|
wxCommandEvent dummy;
|
|
OnOK( dummy );
|
|
},
|
|
// Escape handler
|
|
[this]()
|
|
{
|
|
DismissModal( false );
|
|
} );
|
|
|
|
frameSizer->Add( m_chooserPanel, 1, wxEXPAND );
|
|
|
|
SetBoard( new BOARD() );
|
|
|
|
// This board will only be used to hold a footprint for viewing
|
|
GetBoard()->SetBoardUse( BOARD_USE::FPHOLDER );
|
|
|
|
build3DCanvas(); // must be called after creating m_chooserPanel
|
|
m_preview3DCanvas->Show( !m_showFpMode );
|
|
|
|
// buttonsSizer contains the BITMAP buttons
|
|
wxBoxSizer* buttonsSizer = new wxBoxSizer( wxHORIZONTAL );
|
|
|
|
buttonsSizer->Add( 0, 0, 1, 0, 5 ); // Add spacer to right-align buttons
|
|
|
|
BITMAP_BUTTON* separator = new BITMAP_BUTTON( bottomPanel, wxID_ANY, wxNullBitmap );
|
|
separator->SetIsSeparator();
|
|
buttonsSizer->Add( separator, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 1 );
|
|
|
|
m_grButton3DView = new BITMAP_BUTTON( bottomPanel, wxID_ANY, wxNullBitmap );
|
|
m_grButton3DView->SetIsRadioButton();
|
|
m_grButton3DView->SetBitmap( KiBitmapBundle( BITMAPS::shape_3d ) );
|
|
m_grButton3DView->Check( !m_showFpMode );
|
|
buttonsSizer->Add( m_grButton3DView, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 1 );
|
|
|
|
m_grButtonFpView = new BITMAP_BUTTON( bottomPanel, wxID_ANY, wxNullBitmap );
|
|
m_grButtonFpView->SetIsRadioButton();
|
|
m_grButtonFpView->SetBitmap( KiBitmapBundle( BITMAPS::module ) );
|
|
m_grButtonFpView->Check( m_showFpMode );
|
|
buttonsSizer->Add( m_grButtonFpView, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 1 );
|
|
|
|
separator = new BITMAP_BUTTON( bottomPanel, wxID_ANY, wxNullBitmap );
|
|
separator->SetIsSeparator();
|
|
buttonsSizer->Add( separator, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 1 );
|
|
|
|
m_show3DViewer = new wxCheckBox( bottomPanel, wxID_ANY, _( "Show 3D viewer in own window" ) );
|
|
buttonsSizer->Add( m_show3DViewer, 0, wxALL | wxALIGN_CENTER_VERTICAL, 3 );
|
|
|
|
wxStdDialogButtonSizer* sdbSizer = new wxStdDialogButtonSizer();
|
|
wxButton* okButton = new wxButton( bottomPanel, wxID_OK );
|
|
wxButton* cancelButton = new wxButton( bottomPanel, wxID_CANCEL );
|
|
|
|
sdbSizer->AddButton( okButton );
|
|
sdbSizer->AddButton( cancelButton );
|
|
sdbSizer->Realize();
|
|
|
|
buttonsSizer->Add( 20, 0, 0, 0, 5 ); // Add spacer
|
|
buttonsSizer->Add( sdbSizer, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
|
|
bottomSizer->Add( buttonsSizer, 0, wxEXPAND, 5 );
|
|
|
|
bottomPanel->SetSizer( bottomSizer );
|
|
frameSizer->Add( bottomPanel, 0, wxEXPAND );
|
|
|
|
SetSizer( frameSizer );
|
|
|
|
SetTitle( GetTitle() + wxString::Format( _( " (%d items loaded)" ),
|
|
m_chooserPanel->GetItemCount() ) );
|
|
|
|
Layout();
|
|
m_chooserPanel->FinishSetup();
|
|
|
|
// Connect Events
|
|
m_grButton3DView->Connect( wxEVT_COMMAND_BUTTON_CLICKED ,
|
|
wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::on3DviewReq ),
|
|
nullptr, this );
|
|
|
|
m_grButtonFpView->Connect( wxEVT_COMMAND_BUTTON_CLICKED ,
|
|
wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::onFpViewReq ),
|
|
nullptr, this );
|
|
|
|
m_show3DViewer->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED ,
|
|
wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::onExternalViewer3DEnable ),
|
|
nullptr, this );
|
|
|
|
Connect( FP_SELECTION_EVENT, // custom event fired by a PANEL_FOOTPRINT_CHOOSER
|
|
wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::onFpChanged ), nullptr, this );
|
|
|
|
// Needed on Linux to fix the position of widgets in bottomPanel
|
|
PostSizeEvent();
|
|
}
|
|
|
|
|
|
FOOTPRINT_CHOOSER_FRAME::~FOOTPRINT_CHOOSER_FRAME()
|
|
{
|
|
// Work around assertion firing when we try to LockCtx on a hidden 3D canvas during dtor
|
|
wxCloseEvent dummy;
|
|
m_preview3DCanvas->Show();
|
|
m_preview3DCanvas->OnCloseWindow( dummy );
|
|
|
|
// Disconnect Events
|
|
m_grButton3DView->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED,
|
|
wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::on3DviewReq ),
|
|
nullptr, this );
|
|
m_grButtonFpView->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED,
|
|
wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::onFpViewReq ),
|
|
nullptr, this );
|
|
|
|
m_show3DViewer->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED ,
|
|
wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::onExternalViewer3DEnable ),
|
|
nullptr, this );
|
|
|
|
Disconnect( FP_SELECTION_EVENT,
|
|
wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::onFpChanged ), nullptr, this );
|
|
|
|
if( PCBNEW_SETTINGS* cfg = dynamic_cast<PCBNEW_SETTINGS*>( Kiface().KifaceSettings() ) )
|
|
{
|
|
if( m_filterByFPFilters )
|
|
cfg->m_FootprintChooser.use_fp_filters = m_filterByFPFilters->GetValue();
|
|
|
|
if( m_filterByPinCount )
|
|
cfg->m_FootprintChooser.filter_on_pin_count = m_filterByPinCount->GetValue();
|
|
}
|
|
}
|
|
|
|
|
|
void FOOTPRINT_CHOOSER_FRAME::onExternalViewer3DEnable( wxCommandEvent& aEvent )
|
|
{
|
|
if( aEvent.IsChecked() )
|
|
{
|
|
if( m_grButton3DView->IsChecked() )
|
|
Show3DViewerFrame(); // show external 3D viewer
|
|
}
|
|
else
|
|
{
|
|
// Close the external 3D viewer frame, if it is still enabled
|
|
EDA_3D_VIEWER_FRAME* viewer3D = Get3DViewerFrame();
|
|
|
|
if( viewer3D )
|
|
viewer3D->Close( true );
|
|
}
|
|
|
|
updatePanelsVisibility();
|
|
}
|
|
|
|
|
|
void FOOTPRINT_CHOOSER_FRAME::Show3DViewerFrame()
|
|
{
|
|
bool do_reload_board = true; // reload board flag
|
|
|
|
// At EDA_3D_VIEWER_FRAME creation, the current board is loaded, so disable loading
|
|
// the current board if the 3D frame is not yet created
|
|
if( Get3DViewerFrame() == nullptr )
|
|
do_reload_board = false;
|
|
|
|
EDA_3D_VIEWER_FRAME* draw3DFrame = CreateAndShow3D_Frame();
|
|
|
|
// A stronger version of Raise() which promotes the window to its parent's level.
|
|
KIPLATFORM::UI::ReparentModal( draw3DFrame );
|
|
|
|
// And load or update the current board (if needed)
|
|
if( do_reload_board )
|
|
Update3DView( true, true );
|
|
}
|
|
|
|
|
|
void FOOTPRINT_CHOOSER_FRAME::Update3DView( bool aMarkDirty,
|
|
bool aRefresh, const wxString* aTitle )
|
|
{
|
|
LIB_ID fpID = m_chooserPanel->GetSelectedLibId();
|
|
wxString footprintName;
|
|
|
|
if( fpID.IsValid() )
|
|
footprintName << fpID.Format();
|
|
|
|
wxString title = _( "3D Viewer" ) + wxT( " \u2014 " ) + footprintName;
|
|
PCB_BASE_FRAME::Update3DView( aMarkDirty, aRefresh, &title );
|
|
}
|
|
|
|
|
|
bool FOOTPRINT_CHOOSER_FRAME::filterByPinCount()
|
|
{
|
|
if( m_filterByPinCount )
|
|
return m_filterByPinCount->GetValue();
|
|
|
|
if( PCBNEW_SETTINGS* cfg = dynamic_cast<PCBNEW_SETTINGS*>( Kiface().KifaceSettings() ) )
|
|
return cfg->m_FootprintChooser.filter_on_pin_count;
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
bool FOOTPRINT_CHOOSER_FRAME::filterByFPFilters()
|
|
{
|
|
if( m_filterByFPFilters )
|
|
return m_filterByFPFilters->GetValue();
|
|
|
|
if( PCBNEW_SETTINGS* cfg = dynamic_cast<PCBNEW_SETTINGS*>( Kiface().KifaceSettings() ) )
|
|
return cfg->m_FootprintChooser.use_fp_filters;
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
bool FOOTPRINT_CHOOSER_FRAME::filterFootprint( LIB_TREE_NODE& aNode )
|
|
{
|
|
if( aNode.m_Type == LIB_TREE_NODE::TYPE::LIBRARY )
|
|
{
|
|
// Normally lib nodes get scored by the max of their children's scores. However, if a
|
|
// lib node *has* no children then the scorer will call the filter on the lib node itself,
|
|
// and we just want to return true if we're not filtering at all.
|
|
return !filterByPinCount() && !filterByFPFilters();
|
|
}
|
|
|
|
auto patternMatch =
|
|
[]( LIB_ID& id, std::vector<std::unique_ptr<EDA_PATTERN_MATCH>>& filters ) -> bool
|
|
{
|
|
// The matching is case insensitive
|
|
wxString name;
|
|
|
|
for( const std::unique_ptr<EDA_PATTERN_MATCH>& filter : filters )
|
|
{
|
|
name.Empty();
|
|
|
|
// If the filter contains a ':' then include the library name in the pattern
|
|
if( filter->GetPattern().Contains( wxS( ":" ) ) )
|
|
name = id.GetUniStringLibNickname().Lower() + wxS( ":" );
|
|
|
|
name += id.GetUniStringLibItemName().Lower();
|
|
|
|
if( filter->Find( name ) )
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
if( m_pinCount > 0 && filterByPinCount() )
|
|
{
|
|
if( aNode.m_PinCount != m_pinCount )
|
|
return false;
|
|
}
|
|
|
|
if( !m_fpFilters.empty() && filterByFPFilters() )
|
|
{
|
|
if( !patternMatch( aNode.m_LibId, m_fpFilters ) )
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void FOOTPRINT_CHOOSER_FRAME::doCloseWindow()
|
|
{
|
|
// Only dismiss a modal frame once, so that the return values set by
|
|
// the prior DismissModal() are not bashed for ShowModal().
|
|
if( !IsDismissed() )
|
|
DismissModal( false );
|
|
|
|
// window to be destroyed by the caller of KIWAY_PLAYER::ShowModal()
|
|
}
|
|
|
|
|
|
WINDOW_SETTINGS* FOOTPRINT_CHOOSER_FRAME::GetWindowSettings( APP_SETTINGS_BASE* aCfg )
|
|
{
|
|
PCBNEW_SETTINGS* cfg = dynamic_cast<PCBNEW_SETTINGS*>( aCfg );
|
|
wxCHECK_MSG( cfg, nullptr, wxT( "config not existing" ) );
|
|
|
|
return &cfg->m_FootprintViewer;
|
|
}
|
|
|
|
|
|
COLOR_SETTINGS* FOOTPRINT_CHOOSER_FRAME::GetColorSettings( bool aForceRefresh ) const
|
|
{
|
|
auto* cfg = Pgm().GetSettingsManager().GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>( "fpedit" );
|
|
|
|
if( cfg )
|
|
return Pgm().GetSettingsManager().GetColorSettings( cfg->m_ColorTheme );
|
|
else
|
|
return Pgm().GetSettingsManager().GetColorSettings();
|
|
}
|
|
|
|
|
|
static wxRect s_dialogRect( 0, 0, 0, 0 );
|
|
|
|
|
|
void FOOTPRINT_CHOOSER_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
|
|
{
|
|
const std::string& payload = mail.GetPayload();
|
|
|
|
switch( mail.Command() )
|
|
{
|
|
case MAIL_SYMBOL_NETLIST:
|
|
{
|
|
wxSizer* filtersSizer = m_chooserPanel->GetFiltersSizer();
|
|
wxWindow* filtersWindow = filtersSizer->GetContainingWindow();
|
|
wxString msg;
|
|
|
|
m_pinCount = 0;
|
|
m_fpFilters.clear();
|
|
|
|
/*
|
|
* Symbol netlist format:
|
|
* pinNumber pinName <tab> pinNumber pinName...
|
|
* fpFilter fpFilter...
|
|
*/
|
|
std::map<wxString, wxString> pinNames;
|
|
std::vector<std::string> strings = split( payload, "\r" );
|
|
|
|
if( strings.size() >= 1 && !strings[0].empty() )
|
|
{
|
|
for( const wxString& pin : wxSplit( strings[0], '\t' ) )
|
|
pinNames[ pin.BeforeFirst( ' ' ) ] = pin.AfterFirst( ' ' );
|
|
|
|
m_pinCount = pinNames.size();
|
|
|
|
if( m_pinCount > 0 )
|
|
{
|
|
msg.Printf( _( "Filter by pin count (%d)" ), m_pinCount );
|
|
m_filterByPinCount = new wxCheckBox( filtersWindow, wxID_ANY, msg );
|
|
|
|
m_filterByPinCount->Bind( wxEVT_CHECKBOX,
|
|
[&]( wxCommandEvent& evt )
|
|
{
|
|
m_chooserPanel->Regenerate();
|
|
} );
|
|
|
|
if( PCBNEW_SETTINGS* cfg = dynamic_cast<PCBNEW_SETTINGS*>( Kiface().KifaceSettings() ) )
|
|
m_filterByPinCount->SetValue( cfg->m_FootprintChooser.filter_on_pin_count );
|
|
}
|
|
}
|
|
|
|
if( strings.size() >= 2 && !strings[1].empty() )
|
|
{
|
|
for( const wxString& filter : wxSplit( strings[1], ' ' ) )
|
|
{
|
|
m_fpFilters.push_back( std::make_unique<EDA_PATTERN_MATCH_WILDCARD_ANCHORED>() );
|
|
m_fpFilters.back()->SetPattern( filter.Lower() );
|
|
}
|
|
|
|
msg.Printf( _( "Apply footprint filters (%s)" ), strings[1] );
|
|
m_filterByFPFilters = new wxCheckBox( filtersWindow, wxID_ANY, msg );
|
|
|
|
m_filterByFPFilters->Bind( wxEVT_CHECKBOX,
|
|
[&]( wxCommandEvent& evt )
|
|
{
|
|
m_chooserPanel->Regenerate();
|
|
} );
|
|
|
|
if( PCBNEW_SETTINGS* cfg = dynamic_cast<PCBNEW_SETTINGS*>( Kiface().KifaceSettings() ) )
|
|
m_filterByFPFilters->SetValue( cfg->m_FootprintChooser.use_fp_filters );
|
|
}
|
|
|
|
if( m_filterByFPFilters )
|
|
m_chooserPanel->GetFiltersSizer()->Add( m_filterByFPFilters, 0, wxEXPAND|wxBOTTOM, 4 );
|
|
|
|
if( m_filterByPinCount )
|
|
m_chooserPanel->GetFiltersSizer()->Add( m_filterByPinCount, 0, wxEXPAND|wxBOTTOM, 4 );
|
|
|
|
m_chooserPanel->GetViewerPanel()->SetPinFunctions( pinNames );
|
|
|
|
// Save the wxFormBuilder size of the dialog...
|
|
if( s_dialogRect.GetSize().x == 0 || s_dialogRect.GetSize().y == 0 )
|
|
s_dialogRect = wxRect( wxWindow::GetPosition(), wxWindow::GetSize() );
|
|
|
|
// ... and then give it a kick to get it to layout the new items
|
|
GetSizer()->SetSizeHints( this );
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
bool FOOTPRINT_CHOOSER_FRAME::ShowModal( wxString* aFootprint, wxWindow* aParent )
|
|
{
|
|
if( aFootprint && !aFootprint->IsEmpty() )
|
|
{
|
|
LIB_ID fpid;
|
|
|
|
fpid.Parse( *aFootprint, true );
|
|
|
|
if( fpid.IsValid() )
|
|
m_chooserPanel->SetPreselect( fpid );
|
|
}
|
|
|
|
return KIWAY_PLAYER::ShowModal( aFootprint, aParent );
|
|
}
|
|
|
|
|
|
void FOOTPRINT_CHOOSER_FRAME::SetPosition( const wxPoint& aNewPosition )
|
|
{
|
|
PCB_BASE_FRAME::SetPosition( aNewPosition );
|
|
|
|
s_dialogRect.SetPosition( aNewPosition );
|
|
}
|
|
|
|
|
|
bool FOOTPRINT_CHOOSER_FRAME::Show( bool show )
|
|
{
|
|
bool ret;
|
|
|
|
// Show or hide the window. If hiding, save current position and size.
|
|
// If showing, use previous position and size.
|
|
if( show )
|
|
{
|
|
#ifndef __WINDOWS__
|
|
PCB_BASE_FRAME::Raise(); // Needed on OS X and some other window managers (i.e. Unity)
|
|
#endif
|
|
ret = PCB_BASE_FRAME::Show( show );
|
|
|
|
// returns a zeroed-out default wxRect if none existed before.
|
|
wxRect savedDialogRect = s_dialogRect;
|
|
|
|
if( savedDialogRect.GetSize().x != 0 && savedDialogRect.GetSize().y != 0 )
|
|
{
|
|
SetSize( savedDialogRect.GetPosition().x, savedDialogRect.GetPosition().y,
|
|
std::max( wxWindow::GetSize().x, savedDialogRect.GetSize().x ),
|
|
std::max( wxWindow::GetSize().y, savedDialogRect.GetSize().y ),
|
|
0 );
|
|
}
|
|
|
|
// Be sure that the dialog appears in a visible area
|
|
// (the dialog position might have been stored at the time when it was
|
|
// shown on another display)
|
|
if( wxDisplay::GetFromWindow( this ) == wxNOT_FOUND )
|
|
Centre();
|
|
}
|
|
else
|
|
{
|
|
s_dialogRect = wxRect( wxWindow::GetPosition(), wxWindow::GetSize() );
|
|
ret = PCB_BASE_FRAME::Show( show );
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
void FOOTPRINT_CHOOSER_FRAME::OnPaint( wxPaintEvent& aEvent )
|
|
{
|
|
if( m_firstPaintEvent )
|
|
{
|
|
KIPLATFORM::UI::FixupCancelButtonCmdKeyCollision( this );
|
|
KIPLATFORM::UI::ForceFocus( m_chooserPanel->GetFocusTarget() );
|
|
|
|
m_firstPaintEvent = false;
|
|
}
|
|
|
|
aEvent.Skip();
|
|
}
|
|
|
|
|
|
void FOOTPRINT_CHOOSER_FRAME::OnOK( wxCommandEvent& aEvent )
|
|
{
|
|
LIB_ID fpID = m_chooserPanel->GetSelectedLibId();
|
|
|
|
if( fpID.IsValid() )
|
|
{
|
|
wxString footprint = fpID.Format();
|
|
|
|
AddFootprintToHistory( footprint );
|
|
DismissModal( true, footprint );
|
|
}
|
|
else
|
|
{
|
|
DismissModal( false );
|
|
}
|
|
}
|
|
|
|
|
|
void FOOTPRINT_CHOOSER_FRAME::closeFootprintChooser( wxCommandEvent& aEvent )
|
|
{
|
|
Close( false );
|
|
}
|
|
|
|
|
|
void FOOTPRINT_CHOOSER_FRAME::onFpChanged( wxCommandEvent& event )
|
|
{
|
|
updateViews();
|
|
}
|
|
|
|
|
|
void FOOTPRINT_CHOOSER_FRAME::build3DCanvas()
|
|
{
|
|
// Create the dummy board used by the 3D canvas
|
|
m_dummyBoard = GetBoard();
|
|
m_dummyBoard->SetProject( &Prj(), true );
|
|
|
|
// This board will only be used to hold a footprint for viewing
|
|
m_dummyBoard->SetBoardUse( BOARD_USE::FPHOLDER );
|
|
|
|
m_boardAdapter.SetBoard( m_dummyBoard );
|
|
m_boardAdapter.m_IsBoardView = false;
|
|
m_boardAdapter.m_IsPreviewer = true; // Force display 3D models, regardless the 3D viewer options
|
|
|
|
SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
|
|
EDA_3D_VIEWER_SETTINGS* cfg = mgr.GetAppSettings<EDA_3D_VIEWER_SETTINGS>( "3d_viewer" );
|
|
|
|
m_boardAdapter.m_Cfg = cfg;
|
|
|
|
// Build the 3D canvas
|
|
m_preview3DCanvas = new EDA_3D_CANVAS( m_chooserPanel->m_RightPanel,
|
|
OGL_ATT_LIST::GetAttributesList( ANTIALIASING_MODE::AA_8X ),
|
|
m_boardAdapter, m_currentCamera,
|
|
PROJECT_PCB::Get3DCacheManager( &Prj() ) );
|
|
|
|
m_chooserPanel->m_RightPanelSizer->Add( m_preview3DCanvas, 1, wxEXPAND, 5 );
|
|
m_chooserPanel->m_RightPanel->Layout();
|
|
|
|
BOARD_DESIGN_SETTINGS& dummy_bds = m_dummyBoard->GetDesignSettings();
|
|
dummy_bds.SetBoardThickness( pcbIUScale.mmToIU( 1.6 ) );
|
|
dummy_bds.SetEnabledLayers( LSET::FrontMask() | LSET::BackMask() );
|
|
BOARD_STACKUP& dummy_board_stackup = m_dummyBoard->GetDesignSettings().GetStackupDescriptor();
|
|
dummy_board_stackup.RemoveAll();
|
|
dummy_board_stackup.BuildDefaultStackupList( &dummy_bds, 2 );
|
|
}
|
|
|
|
|
|
void FOOTPRINT_CHOOSER_FRAME::on3DviewReq( wxCommandEvent& event )
|
|
{
|
|
if( m_show3DMode == true )
|
|
{
|
|
if( m_showFpMode == true )
|
|
{
|
|
m_show3DMode = false;
|
|
m_grButton3DView->Check( m_show3DMode );
|
|
updatePanelsVisibility();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( m_show3DViewer->IsChecked() )
|
|
{
|
|
Show3DViewerFrame();
|
|
}
|
|
else
|
|
{
|
|
// Close 3D viewer frame, if it is still enabled
|
|
EDA_3D_VIEWER_FRAME* viewer3D = Get3DViewerFrame();
|
|
if( viewer3D )
|
|
viewer3D->Close( true );
|
|
}
|
|
|
|
m_show3DMode = true;
|
|
m_grButton3DView->Check( m_show3DMode );
|
|
updatePanelsVisibility();
|
|
}
|
|
}
|
|
|
|
|
|
void FOOTPRINT_CHOOSER_FRAME::onFpViewReq( wxCommandEvent& event )
|
|
{
|
|
if( m_showFpMode == true )
|
|
{
|
|
if( m_show3DMode == true )
|
|
{
|
|
m_showFpMode = false;
|
|
m_grButtonFpView->Check( m_showFpMode );
|
|
updatePanelsVisibility();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_showFpMode = true;
|
|
m_grButtonFpView->Check( m_showFpMode );
|
|
updatePanelsVisibility();
|
|
}
|
|
}
|
|
|
|
|
|
void FOOTPRINT_CHOOSER_FRAME::updateViews()
|
|
{
|
|
EDA_3D_VIEWER_FRAME* viewer3D = Get3DViewerFrame();
|
|
bool reloadFp = viewer3D || m_preview3DCanvas->IsShown();
|
|
|
|
if( reloadFp )
|
|
{
|
|
m_dummyBoard->DeleteAllFootprints();
|
|
|
|
if( m_chooserPanel->m_CurrFootprint )
|
|
m_dummyBoard->Add( (FOOTPRINT*)m_chooserPanel->m_CurrFootprint->Clone() );
|
|
|
|
}
|
|
|
|
if( m_preview3DCanvas->IsShown() )
|
|
{
|
|
m_preview3DCanvas->ReloadRequest();
|
|
m_preview3DCanvas->Request_refresh();
|
|
}
|
|
|
|
if( viewer3D )
|
|
{
|
|
Update3DView( true, true );
|
|
}
|
|
|
|
m_chooserPanel->m_RightPanel->Layout();
|
|
m_chooserPanel->m_RightPanel->Refresh();
|
|
}
|
|
|
|
void FOOTPRINT_CHOOSER_FRAME::updatePanelsVisibility()
|
|
{
|
|
FOOTPRINT_PREVIEW_WIDGET* viewFpPanel = m_chooserPanel->GetViewerPanel();
|
|
viewFpPanel->Show( m_showFpMode );
|
|
m_preview3DCanvas->Show( m_show3DMode );
|
|
|
|
updateViews();
|
|
}
|
|
|