2018-08-28 13:26:39 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
2021-06-10 18:51:46 +00:00
|
|
|
* Copyright (C) 2018-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
2018-08-28 13:26:39 +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 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 "symbol_preview_widget.h"
|
|
|
|
#include <sch_view.h>
|
|
|
|
#include <gal/gal_display_options.h>
|
2023-09-18 23:52:27 +00:00
|
|
|
#include <gal/graphics_abstraction_layer.h>
|
2023-02-19 03:40:07 +00:00
|
|
|
#include <math/vector2wx.h>
|
2018-08-28 13:26:39 +00:00
|
|
|
#include <symbol_lib_table.h>
|
2024-04-27 19:57:24 +00:00
|
|
|
#include <lib_symbol.h>
|
2018-08-28 13:26:39 +00:00
|
|
|
#include <sch_preview_panel.h>
|
|
|
|
#include <pgm_base.h>
|
2018-09-02 20:19:22 +00:00
|
|
|
#include <sch_painter.h>
|
2019-06-08 22:14:57 +00:00
|
|
|
#include <eda_draw_frame.h>
|
2023-09-28 03:04:53 +00:00
|
|
|
#include <project_sch.h>
|
2020-01-13 01:44:19 +00:00
|
|
|
#include <eeschema_settings.h>
|
|
|
|
#include <settings/settings_manager.h>
|
2021-06-03 12:11:15 +00:00
|
|
|
#include <wx/log.h>
|
2021-06-03 11:49:49 +00:00
|
|
|
#include <wx/stattext.h>
|
2018-10-17 10:13:32 +00:00
|
|
|
|
2018-08-28 13:26:39 +00:00
|
|
|
|
2023-09-02 21:13:48 +00:00
|
|
|
SYMBOL_PREVIEW_WIDGET::SYMBOL_PREVIEW_WIDGET( wxWindow* aParent, KIWAY* aKiway, bool aIncludeStatus,
|
2018-09-15 07:00:13 +00:00
|
|
|
EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType ) :
|
2023-03-09 17:41:18 +00:00
|
|
|
wxPanel( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ),
|
|
|
|
m_kiway( aKiway ),
|
|
|
|
m_preview( nullptr ),
|
|
|
|
m_status( nullptr ),
|
2023-09-02 21:13:48 +00:00
|
|
|
m_statusPanel( nullptr ),
|
2023-03-09 17:41:18 +00:00
|
|
|
m_statusSizer( nullptr ),
|
|
|
|
m_previewItem( nullptr )
|
2018-08-28 13:26:39 +00:00
|
|
|
{
|
2020-01-13 01:44:19 +00:00
|
|
|
auto common_settings = Pgm().GetCommonSettings();
|
|
|
|
auto app_settings = Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>();
|
2019-04-27 13:26:19 +00:00
|
|
|
|
2020-01-13 01:44:19 +00:00
|
|
|
m_galDisplayOptions.ReadConfig( *common_settings, app_settings->m_Window, this );
|
2020-03-09 02:09:54 +00:00
|
|
|
m_galDisplayOptions.m_forceDisplayCursor = false;
|
2018-08-28 22:32:36 +00:00
|
|
|
|
2018-09-15 07:00:13 +00:00
|
|
|
EDA_DRAW_PANEL_GAL::GAL_TYPE canvasType = aCanvasType;
|
|
|
|
|
|
|
|
// Allows only a CAIRO or OPENGL canvas:
|
2020-08-31 17:47:44 +00:00
|
|
|
if( canvasType != EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL
|
|
|
|
&& canvasType != EDA_DRAW_PANEL_GAL::GAL_FALLBACK )
|
|
|
|
{
|
2018-09-15 07:00:13 +00:00
|
|
|
canvasType = EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL;
|
2020-08-31 17:47:44 +00:00
|
|
|
}
|
2018-09-15 07:00:13 +00:00
|
|
|
|
2022-05-15 14:26:53 +00:00
|
|
|
m_preview = new SCH_PREVIEW_PANEL( this, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ),
|
2018-09-15 07:00:13 +00:00
|
|
|
m_galDisplayOptions, canvasType );
|
2018-08-28 13:26:39 +00:00
|
|
|
m_preview->SetStealsFocus( false );
|
2020-08-10 01:29:15 +00:00
|
|
|
m_preview->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER );
|
|
|
|
m_preview->GetGAL()->SetAxesEnabled( false );
|
2018-08-28 13:26:39 +00:00
|
|
|
|
2018-11-12 19:40:41 +00:00
|
|
|
// Do not display the grid: the look is not good for a small canvas area.
|
|
|
|
// But mainly, due to some strange bug I (JPC) was unable to fix, the grid creates
|
2021-07-16 20:13:26 +00:00
|
|
|
// strange artifacts on Windows when Eeschema is run from KiCad manager (but not in
|
2020-04-02 00:17:25 +00:00
|
|
|
// stand alone...).
|
2018-11-12 19:40:41 +00:00
|
|
|
m_preview->GetGAL()->SetGridVisibility( false );
|
|
|
|
|
2019-01-25 19:18:22 +00:00
|
|
|
// Early initialization of the canvas background color,
|
|
|
|
// before any OnPaint event is fired for the canvas using a wrong bg color
|
|
|
|
KIGFX::VIEW* view = m_preview->GetView();
|
2024-04-02 17:28:17 +00:00
|
|
|
auto settings = static_cast<SCH_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
|
2020-05-18 21:47:22 +00:00
|
|
|
|
|
|
|
if( auto* theme = Pgm().GetSettingsManager().GetColorSettings( app_settings->m_ColorTheme ) )
|
|
|
|
settings->LoadColors( theme );
|
|
|
|
|
2020-08-09 23:51:36 +00:00
|
|
|
const COLOR4D& backgroundColor = settings->GetBackgroundColor();
|
|
|
|
const COLOR4D& foregroundColor = settings->GetCursorColor();
|
2019-01-25 19:18:22 +00:00
|
|
|
|
2020-08-09 23:51:36 +00:00
|
|
|
m_preview->GetGAL()->SetClearColor( backgroundColor );
|
2018-08-28 13:26:39 +00:00
|
|
|
|
2022-09-06 16:28:44 +00:00
|
|
|
settings->m_ShowPinsElectricalType = app_settings->m_LibViewPanel.show_pin_electrical_type;
|
|
|
|
settings->m_ShowPinNumbers = app_settings->m_LibViewPanel.show_pin_numbers;
|
2024-04-08 11:26:56 +00:00
|
|
|
settings->m_ShowHiddenPins = false;
|
|
|
|
settings->m_ShowHiddenFields = false;
|
2022-09-06 16:28:44 +00:00
|
|
|
|
2020-08-09 23:51:36 +00:00
|
|
|
m_outerSizer = new wxBoxSizer( wxVERTICAL );
|
2018-08-28 13:26:39 +00:00
|
|
|
|
2023-09-02 21:13:48 +00:00
|
|
|
if( aIncludeStatus )
|
|
|
|
{
|
|
|
|
m_statusPanel = new wxPanel( this );
|
|
|
|
m_statusPanel->SetBackgroundColour( backgroundColor.ToColour() );
|
|
|
|
m_status = new wxStaticText( m_statusPanel, wxID_ANY, wxEmptyString );
|
|
|
|
m_status->SetForegroundColour( settings->GetLayerColor( LAYER_REFERENCEPART ).ToColour() );
|
|
|
|
m_statusSizer = new wxBoxSizer( wxVERTICAL );
|
|
|
|
m_statusSizer->Add( 0, 0, 1 ); // add a spacer
|
|
|
|
m_statusSizer->Add( m_status, 0, wxALIGN_CENTER );
|
|
|
|
m_statusSizer->Add( 0, 0, 1 ); // add a spacer
|
|
|
|
m_statusPanel->SetSizer( m_statusSizer );
|
|
|
|
|
|
|
|
// Give the status panel the same color scheme as the canvas so it isn't jarring when
|
|
|
|
// switched to.
|
|
|
|
m_statusPanel->SetBackgroundColour( backgroundColor.ToColour() );
|
|
|
|
m_statusPanel->SetForegroundColour( foregroundColor.ToColour() );
|
|
|
|
|
|
|
|
// Give the preview panel a small top border to align its top with the status panel,
|
|
|
|
// and give the status panel a small bottom border to align its bottom with the preview
|
|
|
|
// panel.
|
|
|
|
m_outerSizer->Add( m_preview, 1, wxTOP | wxEXPAND, 5 );
|
|
|
|
m_outerSizer->Add( m_statusPanel, 1, wxBOTTOM | wxEXPAND, 5 );
|
|
|
|
|
|
|
|
// Hide the status panel to start
|
|
|
|
m_statusPanel->Hide();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_outerSizer->Add( m_preview, 1, wxEXPAND, 0 );
|
|
|
|
}
|
2020-08-09 23:51:36 +00:00
|
|
|
|
|
|
|
SetSizer( m_outerSizer );
|
|
|
|
Layout();
|
2018-09-17 09:22:11 +00:00
|
|
|
|
2021-07-16 20:13:26 +00:00
|
|
|
Connect( wxEVT_SIZE, wxSizeEventHandler( SYMBOL_PREVIEW_WIDGET::onSize ), nullptr, this );
|
2018-08-28 13:26:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-29 18:31:43 +00:00
|
|
|
SYMBOL_PREVIEW_WIDGET::~SYMBOL_PREVIEW_WIDGET()
|
|
|
|
{
|
|
|
|
if( m_previewItem )
|
|
|
|
m_preview->GetView()->Remove( m_previewItem );
|
2018-10-31 14:52:10 +00:00
|
|
|
|
|
|
|
delete m_previewItem;
|
2018-08-29 18:31:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-28 13:26:39 +00:00
|
|
|
void SYMBOL_PREVIEW_WIDGET::SetStatusText( wxString const& aText )
|
|
|
|
{
|
2023-09-02 21:13:48 +00:00
|
|
|
wxCHECK( m_statusPanel, /* void */ );
|
|
|
|
|
2018-08-28 13:26:39 +00:00
|
|
|
m_status->SetLabel( aText );
|
|
|
|
m_preview->Hide();
|
2020-08-09 23:51:36 +00:00
|
|
|
m_statusPanel->Show();
|
2018-08-28 13:26:39 +00:00
|
|
|
Layout();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-17 09:22:11 +00:00
|
|
|
void SYMBOL_PREVIEW_WIDGET::onSize( wxSizeEvent& aEvent )
|
|
|
|
{
|
|
|
|
if( m_previewItem )
|
|
|
|
{
|
|
|
|
fitOnDrawArea();
|
|
|
|
m_preview->ForceRefresh();
|
|
|
|
}
|
2018-11-12 19:40:41 +00:00
|
|
|
|
|
|
|
aEvent.Skip();
|
2018-09-17 09:22:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SYMBOL_PREVIEW_WIDGET::fitOnDrawArea()
|
|
|
|
{
|
|
|
|
if( !m_previewItem )
|
|
|
|
return;
|
|
|
|
|
|
|
|
// set the view scale to fit the item on screen
|
|
|
|
KIGFX::VIEW* view = m_preview->GetView();
|
|
|
|
|
|
|
|
// Calculate the drawing area size, in internal units, for a scaling factor = 1.0
|
|
|
|
view->SetScale( 1.0 );
|
2023-02-19 03:40:07 +00:00
|
|
|
VECTOR2D clientSize = view->ToWorld( ToVECTOR2D( m_preview->GetClientSize() ), false );
|
2018-11-12 19:40:41 +00:00
|
|
|
// Calculate the draw scale to fit the drawing area
|
2018-09-17 09:22:11 +00:00
|
|
|
double scale = std::min( fabs( clientSize.x / m_itemBBox.GetWidth() ),
|
|
|
|
fabs( clientSize.y / m_itemBBox.GetHeight() ) );
|
|
|
|
|
|
|
|
// Above calculation will yield an exact fit; add a bit of whitespace around symbol
|
|
|
|
scale /= 1.2;
|
|
|
|
|
|
|
|
// Now fix the best scale
|
|
|
|
view->SetScale( scale );
|
|
|
|
view->SetCenter( m_itemBBox.Centre() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-01-26 16:16:13 +00:00
|
|
|
void SYMBOL_PREVIEW_WIDGET::DisplaySymbol( const LIB_ID& aSymbolID, int aUnit, int aBodyStyle )
|
2018-08-28 13:26:39 +00:00
|
|
|
{
|
|
|
|
KIGFX::VIEW* view = m_preview->GetView();
|
2024-04-02 17:28:17 +00:00
|
|
|
auto settings = static_cast<SCH_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
|
2021-06-10 18:51:46 +00:00
|
|
|
std::unique_ptr< LIB_SYMBOL > symbol;
|
2018-08-28 13:26:39 +00:00
|
|
|
|
|
|
|
try
|
|
|
|
{
|
2023-09-28 03:04:53 +00:00
|
|
|
LIB_SYMBOL* tmp = PROJECT_SCH::SchSymbolLibTable( &m_kiway->Prj() )->LoadSymbol( aSymbolID );
|
2019-11-06 19:15:42 +00:00
|
|
|
|
|
|
|
if( tmp )
|
|
|
|
symbol = tmp->Flatten();
|
2018-08-28 13:26:39 +00:00
|
|
|
}
|
|
|
|
catch( const IO_ERROR& ioe )
|
|
|
|
{
|
2021-06-26 19:21:30 +00:00
|
|
|
wxLogError( _( "Error loading symbol %s from library '%s'." ) + wxS( "\n%s" ),
|
|
|
|
aSymbolID.GetLibItemName().wx_str(),
|
|
|
|
aSymbolID.GetLibNickname().wx_str(),
|
|
|
|
ioe.What() );
|
2018-08-28 13:26:39 +00:00
|
|
|
}
|
|
|
|
|
2018-08-29 18:31:43 +00:00
|
|
|
if( m_previewItem )
|
|
|
|
{
|
|
|
|
view->Remove( m_previewItem );
|
2018-10-31 14:52:10 +00:00
|
|
|
delete m_previewItem;
|
2018-08-29 18:31:43 +00:00
|
|
|
m_previewItem = nullptr;
|
|
|
|
}
|
2018-08-28 13:26:39 +00:00
|
|
|
|
2019-11-06 19:15:42 +00:00
|
|
|
if( symbol )
|
2018-08-28 13:26:39 +00:00
|
|
|
{
|
2019-11-06 19:15:42 +00:00
|
|
|
// This will flatten derived parts so that the correct final symbol can be shown.
|
|
|
|
m_previewItem = symbol.release();
|
2018-08-28 17:45:30 +00:00
|
|
|
|
2022-05-29 19:29:32 +00:00
|
|
|
// Hide fields that were added automatically by the library (for example, when using
|
|
|
|
// database libraries) as they don't have a valid position yet, and we don't support
|
|
|
|
// autoplacing fields on library symbols yet.
|
2024-04-12 21:00:41 +00:00
|
|
|
std::vector<SCH_FIELD*> previewFields;
|
2022-05-29 19:29:32 +00:00
|
|
|
m_previewItem->GetFields( previewFields );
|
|
|
|
|
2024-04-12 21:00:41 +00:00
|
|
|
for( SCH_FIELD* field : previewFields )
|
2022-05-29 19:29:32 +00:00
|
|
|
{
|
|
|
|
if( field->IsAutoAdded() )
|
|
|
|
field->SetVisible( false );
|
|
|
|
}
|
|
|
|
|
2018-08-28 17:45:30 +00:00
|
|
|
// If unit isn't specified for a multi-unit part, pick the first. (Otherwise we'll
|
|
|
|
// draw all of them.)
|
2020-04-02 00:17:25 +00:00
|
|
|
settings->m_ShowUnit = ( m_previewItem->IsMulti() && aUnit == 0 ) ? 1 : aUnit;
|
2018-08-29 18:31:43 +00:00
|
|
|
|
2018-09-16 11:30:18 +00:00
|
|
|
// For symbols having a De Morgan body style, use the first style
|
2024-01-26 16:16:13 +00:00
|
|
|
settings->m_ShowBodyStyle =
|
|
|
|
( m_previewItem->HasAlternateBodyStyle() && aBodyStyle == 0 ) ? 1 : aBodyStyle;
|
2018-09-16 11:30:18 +00:00
|
|
|
|
2018-10-31 14:52:10 +00:00
|
|
|
view->Add( m_previewItem );
|
2018-08-28 13:26:39 +00:00
|
|
|
|
2021-07-16 20:13:26 +00:00
|
|
|
// Get the symbol size, in internal units
|
2020-04-02 00:17:25 +00:00
|
|
|
m_itemBBox = m_previewItem->GetUnitBoundingBox( settings->m_ShowUnit,
|
2024-01-26 16:16:13 +00:00
|
|
|
settings->m_ShowBodyStyle );
|
2018-08-28 13:26:39 +00:00
|
|
|
|
2021-08-19 21:28:54 +00:00
|
|
|
if( !m_preview->IsShownOnScreen() )
|
2018-11-12 19:40:41 +00:00
|
|
|
{
|
|
|
|
m_preview->Show();
|
2023-09-02 21:13:48 +00:00
|
|
|
|
|
|
|
if( m_statusPanel )
|
|
|
|
m_statusPanel->Hide();
|
|
|
|
|
2018-11-12 19:40:41 +00:00
|
|
|
Layout(); // Ensure panel size is up to date.
|
|
|
|
}
|
|
|
|
|
2018-09-17 09:22:11 +00:00
|
|
|
// Calculate the draw scale to fit the drawing area
|
|
|
|
fitOnDrawArea();
|
2018-08-28 13:26:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
m_preview->ForceRefresh();
|
2018-08-30 21:44:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-01-26 16:16:13 +00:00
|
|
|
void SYMBOL_PREVIEW_WIDGET::DisplayPart( LIB_SYMBOL* aSymbol, int aUnit, int aBodyStyle )
|
2018-08-30 21:44:50 +00:00
|
|
|
{
|
|
|
|
KIGFX::VIEW* view = m_preview->GetView();
|
|
|
|
|
|
|
|
if( m_previewItem )
|
|
|
|
{
|
|
|
|
view->Remove( m_previewItem );
|
2018-10-31 14:52:10 +00:00
|
|
|
delete m_previewItem;
|
2018-08-30 21:44:50 +00:00
|
|
|
m_previewItem = nullptr;
|
|
|
|
}
|
|
|
|
|
2021-06-10 18:51:46 +00:00
|
|
|
if( aSymbol )
|
2018-08-30 21:44:50 +00:00
|
|
|
{
|
2021-06-10 18:51:46 +00:00
|
|
|
m_previewItem = new LIB_SYMBOL( *aSymbol );
|
2019-11-06 19:15:42 +00:00
|
|
|
|
2020-04-02 00:17:25 +00:00
|
|
|
// For symbols having a De Morgan body style, use the first style
|
2024-04-02 17:28:17 +00:00
|
|
|
auto settings = static_cast<SCH_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
|
2021-07-16 20:13:26 +00:00
|
|
|
|
2018-08-30 21:44:50 +00:00
|
|
|
// If unit isn't specified for a multi-unit part, pick the first. (Otherwise we'll
|
|
|
|
// draw all of them.)
|
2020-04-02 00:17:25 +00:00
|
|
|
settings->m_ShowUnit = ( m_previewItem->IsMulti() && aUnit == 0 ) ? 1 : aUnit;
|
|
|
|
|
2024-01-26 16:16:13 +00:00
|
|
|
settings->m_ShowBodyStyle =
|
|
|
|
( m_previewItem->HasAlternateBodyStyle() && aBodyStyle == 0 ) ? 1 : aBodyStyle;
|
2018-08-30 21:44:50 +00:00
|
|
|
|
2018-10-31 14:52:10 +00:00
|
|
|
view->Add( m_previewItem );
|
2018-08-30 21:44:50 +00:00
|
|
|
|
2021-07-16 20:13:26 +00:00
|
|
|
// Get the symbol size, in internal units
|
2024-01-26 16:16:13 +00:00
|
|
|
m_itemBBox = aSymbol->GetUnitBoundingBox( settings->m_ShowUnit, settings->m_ShowBodyStyle );
|
2018-09-15 07:00:13 +00:00
|
|
|
|
2018-09-17 09:22:11 +00:00
|
|
|
// Calculate the draw scale to fit the drawing area
|
|
|
|
fitOnDrawArea();
|
2018-08-30 21:44:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
m_preview->ForceRefresh();
|
|
|
|
m_preview->Show();
|
2023-09-02 21:13:48 +00:00
|
|
|
|
|
|
|
if( m_statusPanel )
|
|
|
|
m_statusPanel->Hide();
|
|
|
|
|
2020-08-09 23:51:36 +00:00
|
|
|
Layout();
|
2018-08-28 13:26:39 +00:00
|
|
|
}
|