2017-02-19 02:39:55 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
2020-12-21 22:02:13 +00:00
|
|
|
* Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors.
|
2017-02-19 02:39:55 +00:00
|
|
|
* Copyright (C) 2017 Chris Pavlina <pavlina.chris@gmail.com>
|
|
|
|
* Copyright (C) 2016 Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
|
|
|
*
|
|
|
|
* 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/>.
|
|
|
|
*/
|
|
|
|
|
2020-01-09 13:44:57 +00:00
|
|
|
#include <memory>
|
|
|
|
#include <utility>
|
|
|
|
|
2020-01-13 01:44:19 +00:00
|
|
|
#include "pcbnew_settings.h"
|
2022-08-27 17:23:43 +00:00
|
|
|
#include <base_units.h>
|
2020-11-12 20:19:22 +00:00
|
|
|
#include <board.h>
|
|
|
|
#include <footprint.h>
|
2023-01-02 22:11:44 +00:00
|
|
|
#include <pcb_dimension.h>
|
2020-01-09 13:44:57 +00:00
|
|
|
#include <eda_draw_frame.h>
|
2017-03-10 19:11:41 +00:00
|
|
|
#include <footprint_preview_panel.h>
|
2020-01-09 13:44:57 +00:00
|
|
|
#include <fp_lib_table.h>
|
2017-02-19 02:39:55 +00:00
|
|
|
#include <kiway.h>
|
|
|
|
#include <math/box2.h>
|
2020-07-26 11:17:38 +00:00
|
|
|
#include <pcb_painter.h>
|
2020-01-09 13:44:57 +00:00
|
|
|
#include <pcb_draw_panel_gal.h>
|
2018-11-03 12:35:17 +00:00
|
|
|
#include <pcb_edit_frame.h>
|
|
|
|
#include <pgm_base.h>
|
2020-01-13 01:44:19 +00:00
|
|
|
#include <settings/settings_manager.h>
|
2020-01-09 13:44:57 +00:00
|
|
|
#include <view/view.h>
|
|
|
|
#include <wx/stattext.h>
|
2020-12-01 19:27:42 +00:00
|
|
|
#include <zoom_defines.h>
|
2023-06-10 12:34:54 +00:00
|
|
|
#include <dialog_shim.h>
|
2017-02-19 02:39:55 +00:00
|
|
|
|
2018-09-11 15:28:57 +00:00
|
|
|
FOOTPRINT_PREVIEW_PANEL::FOOTPRINT_PREVIEW_PANEL( KIWAY* aKiway, wxWindow* aParent,
|
2020-12-21 22:02:13 +00:00
|
|
|
std::unique_ptr<KIGFX::GAL_DISPLAY_OPTIONS> aOpts,
|
|
|
|
GAL_TYPE aGalType ) :
|
|
|
|
PCB_DRAW_PANEL_GAL( aParent, -1, wxPoint( 0, 0 ), wxSize( 200, 200 ), *aOpts, aGalType ),
|
|
|
|
KIWAY_HOLDER( aKiway, KIWAY_HOLDER::PANEL ),
|
|
|
|
m_displayOptions( std::move( aOpts ) ),
|
|
|
|
m_currentFootprint( nullptr )
|
2017-02-19 02:39:55 +00:00
|
|
|
{
|
2017-03-03 21:05:13 +00:00
|
|
|
SetStealsFocus( false );
|
2017-02-19 02:39:55 +00:00
|
|
|
ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER );
|
|
|
|
EnableScrolling( false, false ); // otherwise Zoom Auto disables GAL canvas
|
|
|
|
|
2023-06-10 12:34:54 +00:00
|
|
|
wxWindow* topLevelParent = aParent;
|
|
|
|
|
|
|
|
while( topLevelParent && !topLevelParent->IsTopLevel() )
|
|
|
|
topLevelParent = topLevelParent->GetParent();
|
|
|
|
|
|
|
|
if( topLevelParent )
|
|
|
|
{
|
|
|
|
if( DIALOG_SHIM* parentDlg = dynamic_cast<DIALOG_SHIM*>( topLevelParent ) )
|
|
|
|
m_userUnits = parentDlg->GetUserUnits();
|
|
|
|
else if( UNITS_PROVIDER* parentFrame = dynamic_cast<UNITS_PROVIDER*>( topLevelParent ) )
|
|
|
|
m_userUnits = parentFrame->GetUserUnits();
|
|
|
|
}
|
|
|
|
|
2017-02-19 02:39:55 +00:00
|
|
|
m_dummyBoard = std::make_unique<BOARD>();
|
2023-03-05 13:27:22 +00:00
|
|
|
m_dummyBoard->SetUserUnits( m_userUnits );
|
2023-06-10 12:34:54 +00:00
|
|
|
m_dummyBoard->SetBoardUse( BOARD_USE::FPHOLDER );
|
2020-01-13 01:44:19 +00:00
|
|
|
UpdateColors();
|
2020-01-09 14:18:41 +00:00
|
|
|
SyncLayersVisibility( m_dummyBoard.get() );
|
2017-02-19 02:39:55 +00:00
|
|
|
|
|
|
|
Raise();
|
2018-09-11 15:28:57 +00:00
|
|
|
Show( true );
|
2017-02-19 02:39:55 +00:00
|
|
|
StartDrawing();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FOOTPRINT_PREVIEW_PANEL::~FOOTPRINT_PREVIEW_PANEL( )
|
|
|
|
{
|
2020-10-14 23:37:26 +00:00
|
|
|
if( m_currentFootprint )
|
2020-01-09 13:44:57 +00:00
|
|
|
{
|
2020-10-14 23:37:26 +00:00
|
|
|
GetView()->Remove( m_currentFootprint.get() );
|
2020-01-09 13:44:57 +00:00
|
|
|
GetView()->Clear();
|
2020-10-14 23:37:26 +00:00
|
|
|
m_currentFootprint->SetParent( nullptr );
|
2020-01-09 13:44:57 +00:00
|
|
|
}
|
2017-02-19 02:39:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-09-16 16:20:36 +00:00
|
|
|
const COLOR4D& FOOTPRINT_PREVIEW_PANEL::GetBackgroundColor() const
|
2020-08-10 01:29:15 +00:00
|
|
|
{
|
|
|
|
KIGFX::PAINTER* painter = GetView()->GetPainter();
|
|
|
|
auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( painter->GetSettings() );
|
|
|
|
|
|
|
|
return settings->GetBackgroundColor();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-09-16 16:20:36 +00:00
|
|
|
const COLOR4D& FOOTPRINT_PREVIEW_PANEL::GetForegroundColor() const
|
2020-08-10 01:29:15 +00:00
|
|
|
{
|
|
|
|
KIGFX::PAINTER* painter = GetView()->GetPainter();
|
|
|
|
auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( painter->GetSettings() );
|
|
|
|
|
2022-06-05 17:58:27 +00:00
|
|
|
return settings->GetLayerColor( F_Fab );
|
2020-08-10 01:29:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-11-13 15:15:52 +00:00
|
|
|
void FOOTPRINT_PREVIEW_PANEL::renderFootprint( std::shared_ptr<FOOTPRINT> aFootprint )
|
2017-02-19 02:39:55 +00:00
|
|
|
{
|
2020-10-14 23:37:26 +00:00
|
|
|
if( m_currentFootprint )
|
2020-01-09 13:44:57 +00:00
|
|
|
{
|
2020-10-14 23:37:26 +00:00
|
|
|
GetView()->Remove( m_currentFootprint.get() );
|
2020-01-09 13:44:57 +00:00
|
|
|
GetView()->Clear();
|
2020-10-14 23:37:26 +00:00
|
|
|
m_currentFootprint->SetParent( nullptr );
|
2020-01-09 13:44:57 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 22:02:13 +00:00
|
|
|
m_currentFootprint = aFootprint;
|
|
|
|
|
|
|
|
if( !m_currentFootprint )
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_currentFootprint->SetParent( m_dummyBoard.get() );
|
2020-01-09 13:44:57 +00:00
|
|
|
|
2023-01-02 22:11:44 +00:00
|
|
|
INSPECTOR_FUNC inspector =
|
|
|
|
[&]( EDA_ITEM* descendant, void* aTestData )
|
|
|
|
{
|
2023-03-05 13:27:22 +00:00
|
|
|
static_cast<PCB_DIMENSION_BASE*>( descendant )->UpdateUnits();
|
2023-01-02 22:11:44 +00:00
|
|
|
return INSPECT_RESULT::CONTINUE;
|
|
|
|
};
|
|
|
|
|
|
|
|
m_currentFootprint->Visit( inspector, nullptr, { PCB_FP_DIM_LEADER_T,
|
|
|
|
PCB_FP_DIM_ORTHOGONAL_T,
|
|
|
|
PCB_FP_DIM_CENTER_T,
|
|
|
|
PCB_FP_DIM_RADIAL_T } );
|
|
|
|
|
2020-07-26 11:17:38 +00:00
|
|
|
// Ensure we are not using the high contrast mode to display the selected footprint
|
|
|
|
KIGFX::PAINTER* painter = GetView()->GetPainter();
|
|
|
|
auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( painter->GetSettings() );
|
2021-12-26 00:36:12 +00:00
|
|
|
settings->m_ContrastModeDisplay = HIGH_CONTRAST_MODE::NORMAL;
|
2020-07-26 11:17:38 +00:00
|
|
|
|
2020-12-21 22:02:13 +00:00
|
|
|
GetView()->Add( m_currentFootprint.get() );
|
|
|
|
GetView()->SetVisible( m_currentFootprint.get(), true );
|
|
|
|
GetView()->Update( m_currentFootprint.get(), KIGFX::ALL );
|
2017-02-19 02:39:55 +00:00
|
|
|
|
2020-12-21 22:02:13 +00:00
|
|
|
BOX2I bbox = m_currentFootprint->ViewBBox();
|
|
|
|
bbox.Merge( m_currentFootprint->Value().ViewBBox() );
|
|
|
|
bbox.Merge( m_currentFootprint->Reference().ViewBBox() );
|
2017-02-19 02:39:55 +00:00
|
|
|
|
|
|
|
if( bbox.GetSize().x > 0 && bbox.GetSize().y > 0 )
|
|
|
|
{
|
|
|
|
// Autozoom
|
|
|
|
GetView()->SetViewport( BOX2D( bbox.GetOrigin(), bbox.GetSize() ) );
|
|
|
|
|
|
|
|
// Add a margin
|
|
|
|
GetView()->SetScale( GetView()->GetScale() * 0.7 );
|
|
|
|
|
|
|
|
Refresh();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-12-21 22:02:13 +00:00
|
|
|
bool FOOTPRINT_PREVIEW_PANEL::DisplayFootprint( const LIB_ID& aFPID )
|
2017-02-19 02:39:55 +00:00
|
|
|
{
|
2020-12-21 22:02:13 +00:00
|
|
|
FP_LIB_TABLE* fptbl = Prj().PcbFootprintLibs();
|
2017-02-19 02:39:55 +00:00
|
|
|
|
2020-12-21 22:02:13 +00:00
|
|
|
try
|
2017-03-10 19:11:41 +00:00
|
|
|
{
|
2023-01-02 22:11:44 +00:00
|
|
|
const FOOTPRINT* fp = fptbl->GetEnumeratedFootprint( aFPID.GetLibNickname(),
|
|
|
|
aFPID.GetLibItemName() );
|
2021-02-25 23:42:12 +00:00
|
|
|
|
|
|
|
if( fp )
|
|
|
|
m_currentFootprint.reset( static_cast<FOOTPRINT*>( fp->Duplicate() ) );
|
|
|
|
else
|
|
|
|
m_currentFootprint.reset();
|
2020-12-21 22:02:13 +00:00
|
|
|
}
|
|
|
|
catch( ... )
|
|
|
|
{
|
|
|
|
m_currentFootprint.reset();
|
2017-02-19 02:39:55 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 22:02:13 +00:00
|
|
|
renderFootprint( m_currentFootprint );
|
|
|
|
Refresh();
|
2017-02-19 02:39:55 +00:00
|
|
|
|
2020-12-21 22:02:13 +00:00
|
|
|
return m_currentFootprint != nullptr;
|
2017-02-19 02:39:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-10 19:11:41 +00:00
|
|
|
wxWindow* FOOTPRINT_PREVIEW_PANEL::GetWindow()
|
2017-02-19 02:39:55 +00:00
|
|
|
{
|
2017-03-10 19:11:41 +00:00
|
|
|
return static_cast<wxWindow*>( this );
|
2017-02-19 02:39:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FOOTPRINT_PREVIEW_PANEL* FOOTPRINT_PREVIEW_PANEL::New( KIWAY* aKiway, wxWindow* aParent )
|
|
|
|
{
|
2020-01-13 01:44:19 +00:00
|
|
|
PCBNEW_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>();
|
2018-11-03 12:35:17 +00:00
|
|
|
|
2021-02-21 20:32:52 +00:00
|
|
|
if( cfg->m_Window.grid.sizes.empty() )
|
|
|
|
cfg->m_Window.grid.sizes = cfg->DefaultGridSizeList();
|
2020-01-13 01:44:19 +00:00
|
|
|
|
2020-12-01 19:27:42 +00:00
|
|
|
// Currently values read from config file are not used because the user cannot
|
|
|
|
// change this config
|
|
|
|
//if( cfg->m_Window.zoom_factors.empty() )
|
2020-06-17 18:00:58 +00:00
|
|
|
{
|
2020-12-02 14:34:05 +00:00
|
|
|
cfg->m_Window.zoom_factors = { ZOOM_LIST_PCBNEW };
|
2018-11-03 12:35:17 +00:00
|
|
|
}
|
2017-02-19 02:39:55 +00:00
|
|
|
|
2020-06-17 18:00:58 +00:00
|
|
|
std::unique_ptr<KIGFX::GAL_DISPLAY_OPTIONS> gal_opts;
|
|
|
|
|
|
|
|
gal_opts = std::make_unique<KIGFX::GAL_DISPLAY_OPTIONS>();
|
|
|
|
gal_opts->ReadConfig( *Pgm().GetCommonSettings(), cfg->m_Window, aParent );
|
|
|
|
|
2020-01-13 01:44:19 +00:00
|
|
|
auto canvasType = static_cast<EDA_DRAW_PANEL_GAL::GAL_TYPE>( cfg->m_Graphics.canvas_type );
|
Pcbnew: FOOTPRINT_PREVIEW_PANEL passes reference to local
Previously, the GAL_DISPLAY_OPTIONS object in FOOTPRINT_PREVIEW_PANEL::New
was passed by reference in the ctor, down to EDA_DRAW_PANEL_GAL, which stored
it as a reference. The object in New() then goes out of scope, so the
referencing panel outlives the options.
Fix this by making a copy in a std::unique_ptr of the options, and giving
ownership to the panel.
There is another issue here: when the Pcbnew options are copies, the
OBSERVABLE subscriber list is copied too. This means if the panel called
NotifyChanged() on the options, Pcbnew would get updates, even though a copy
of the options changed. However, the panel doesn't change the options or
notify, so it's OK for now.
2019-04-11 11:06:50 +00:00
|
|
|
auto panel = new FOOTPRINT_PREVIEW_PANEL( aKiway, aParent, std::move( gal_opts ), canvasType );
|
2018-11-03 12:35:17 +00:00
|
|
|
|
2020-06-17 18:00:58 +00:00
|
|
|
panel->UpdateColors();
|
2018-11-03 12:35:17 +00:00
|
|
|
|
2020-06-12 10:58:56 +00:00
|
|
|
const GRID_SETTINGS& gridCfg = cfg->m_Window.grid;
|
2020-05-06 01:45:48 +00:00
|
|
|
|
2020-06-12 10:58:56 +00:00
|
|
|
panel->GetGAL()->SetGridVisibility( gridCfg.show );
|
|
|
|
|
2020-07-07 14:53:04 +00:00
|
|
|
//Bounds checking cannot include number of elements as an index!
|
2022-10-05 16:42:03 +00:00
|
|
|
int gridIdx = std::max( 0, std::min( gridCfg.last_size_idx, (int) gridCfg.sizes.size() - 1 ) );
|
|
|
|
double gridSize = EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, EDA_UNITS::MILS,
|
|
|
|
gridCfg.sizes[ gridIdx ] );
|
2020-06-12 10:58:56 +00:00
|
|
|
panel->GetGAL()->SetGridSize( VECTOR2D( gridSize, gridSize ) );
|
2018-11-03 12:35:17 +00:00
|
|
|
|
|
|
|
return panel;
|
2017-02-19 02:39:55 +00:00
|
|
|
}
|