KiCad PCB EDA Suite
symbol_preview_widget.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2018-2021 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
21#include <sch_view.h>
23#include <symbol_lib_table.h>
24#include <sch_preview_panel.h>
25#include <pgm_base.h>
26#include <sch_painter.h>
27#include <eda_draw_frame.h>
28#include <eeschema_settings.h>
30#include <wx/log.h>
31#include <wx/stattext.h>
32
33
35 EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType ) :
36 wxPanel( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ),
37 m_kiway( aKiway ),
38 m_preview( nullptr ), m_status( nullptr ), m_statusSizer( nullptr ), m_previewItem( nullptr )
39{
40 auto common_settings = Pgm().GetCommonSettings();
41 auto app_settings = Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>();
42
43 m_galDisplayOptions.ReadConfig( *common_settings, app_settings->m_Window, this );
45
46 EDA_DRAW_PANEL_GAL::GAL_TYPE canvasType = aCanvasType;
47
48 // Allows only a CAIRO or OPENGL canvas:
50 && canvasType != EDA_DRAW_PANEL_GAL::GAL_FALLBACK )
51 {
53 }
54
55 m_preview = new SCH_PREVIEW_PANEL( this, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ),
56 m_galDisplayOptions, canvasType );
57 m_preview->SetStealsFocus( false );
58 m_preview->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER );
59 m_preview->GetGAL()->SetAxesEnabled( false );
60
61 // Do not display the grid: the look is not good for a small canvas area.
62 // But mainly, due to some strange bug I (JPC) was unable to fix, the grid creates
63 // strange artifacts on Windows when Eeschema is run from KiCad manager (but not in
64 // stand alone...).
66
67 // Early initialization of the canvas background color,
68 // before any OnPaint event is fired for the canvas using a wrong bg color
69 KIGFX::VIEW* view = m_preview->GetView();
70 auto settings = static_cast<KIGFX::SCH_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
71
72 if( auto* theme = Pgm().GetSettingsManager().GetColorSettings( app_settings->m_ColorTheme ) )
73 settings->LoadColors( theme );
74
75 const COLOR4D& backgroundColor = settings->GetBackgroundColor();
76 const COLOR4D& foregroundColor = settings->GetCursorColor();
77
78 m_preview->GetGAL()->SetClearColor( backgroundColor );
79
80 settings->m_ShowPinsElectricalType = app_settings->m_LibViewPanel.show_pin_electrical_type;
81 settings->m_ShowPinNumbers = app_settings->m_LibViewPanel.show_pin_numbers;
82
83 m_statusPanel = new wxPanel( this );
84 m_statusPanel->SetBackgroundColour( backgroundColor.ToColour() );
85 m_status = new wxStaticText( m_statusPanel, wxID_ANY, wxEmptyString );
86 m_status->SetForegroundColour( settings->GetLayerColor( LAYER_REFERENCEPART ).ToColour() );
87 m_statusSizer = new wxBoxSizer( wxVERTICAL );
88 m_statusSizer->Add( 0, 0, 1 ); // add a spacer
89 m_statusSizer->Add( m_status, 0, wxALIGN_CENTER );
90 m_statusSizer->Add( 0, 0, 1 ); // add a spacer
91 m_statusPanel->SetSizer( m_statusSizer );
92
93 // Give the status panel the same color scheme as the canvas so it isn't jarring when
94 // switched to.
95 m_statusPanel->SetBackgroundColour( backgroundColor.ToColour() );
96 m_statusPanel->SetForegroundColour( foregroundColor.ToColour() );
97
98 // Give the preview panel a small top border to align its top with the status panel,
99 // and give the status panel a small bottom border to align its bottom with the preview
100 // panel.
101 m_outerSizer = new wxBoxSizer( wxVERTICAL );
102 m_outerSizer->Add( m_preview, 1, wxTOP | wxEXPAND, 5 );
103 m_outerSizer->Add( m_statusPanel, 1, wxBOTTOM | wxEXPAND, 5 );
104
105 // Hide the status panel to start
106 m_statusPanel->Hide();
107
108 SetSizer( m_outerSizer );
109 Layout();
110
111 Connect( wxEVT_SIZE, wxSizeEventHandler( SYMBOL_PREVIEW_WIDGET::onSize ), nullptr, this );
112}
113
114
116{
117 if( m_previewItem )
119
120 delete m_previewItem;
121}
122
123
124void SYMBOL_PREVIEW_WIDGET::SetStatusText( wxString const& aText )
125{
126 m_status->SetLabel( aText );
127 m_preview->Hide();
128 m_statusPanel->Show();
129 Layout();
130}
131
132
133void SYMBOL_PREVIEW_WIDGET::onSize( wxSizeEvent& aEvent )
134{
135 if( m_previewItem )
136 {
139 }
140
141 aEvent.Skip();
142}
143
144
146{
147 if( !m_previewItem )
148 return;
149
150 // set the view scale to fit the item on screen
151 KIGFX::VIEW* view = m_preview->GetView();
152
153 // Calculate the drawing area size, in internal units, for a scaling factor = 1.0
154 view->SetScale( 1.0 );
155 VECTOR2D clientSize = view->ToWorld( m_preview->GetClientSize(), false );
156 // Calculate the draw scale to fit the drawing area
157 double scale = std::min( fabs( clientSize.x / m_itemBBox.GetWidth() ),
158 fabs( clientSize.y / m_itemBBox.GetHeight() ) );
159
160 // Above calculation will yield an exact fit; add a bit of whitespace around symbol
161 scale /= 1.2;
162
163 // Now fix the best scale
164 view->SetScale( scale );
165 view->SetCenter( m_itemBBox.Centre() );
166}
167
168
169void SYMBOL_PREVIEW_WIDGET::DisplaySymbol( const LIB_ID& aSymbolID, int aUnit, int aConvert )
170{
171 KIGFX::VIEW* view = m_preview->GetView();
172 auto settings = static_cast<KIGFX::SCH_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
173 std::unique_ptr< LIB_SYMBOL > symbol;
174
175 try
176 {
177 LIB_SYMBOL* tmp = m_kiway.Prj().SchSymbolLibTable()->LoadSymbol( aSymbolID );
178
179 if( tmp )
180 symbol = tmp->Flatten();
181 }
182 catch( const IO_ERROR& ioe )
183 {
184 wxLogError( _( "Error loading symbol %s from library '%s'." ) + wxS( "\n%s" ),
185 aSymbolID.GetLibItemName().wx_str(),
186 aSymbolID.GetLibNickname().wx_str(),
187 ioe.What() );
188 }
189
190 if( m_previewItem )
191 {
192 view->Remove( m_previewItem );
193 delete m_previewItem;
194 m_previewItem = nullptr;
195 }
196
197 if( symbol )
198 {
199 // This will flatten derived parts so that the correct final symbol can be shown.
200 m_previewItem = symbol.release();
201
202 // Hide fields that were added automatically by the library (for example, when using
203 // database libraries) as they don't have a valid position yet, and we don't support
204 // autoplacing fields on library symbols yet.
205 std::vector<LIB_FIELD*> previewFields;
206 m_previewItem->GetFields( previewFields );
207
208 for( LIB_FIELD* field : previewFields )
209 {
210 if( field->IsAutoAdded() )
211 field->SetVisible( false );
212 }
213
214 // If unit isn't specified for a multi-unit part, pick the first. (Otherwise we'll
215 // draw all of them.)
216 settings->m_ShowUnit = ( m_previewItem->IsMulti() && aUnit == 0 ) ? 1 : aUnit;
217
218 // For symbols having a De Morgan body style, use the first style
219 settings->m_ShowConvert =
220 ( m_previewItem->HasConversion() && aConvert == 0 ) ? 1 : aConvert;
221
222 view->Add( m_previewItem );
223
224 // Get the symbol size, in internal units
225 m_itemBBox = m_previewItem->GetUnitBoundingBox( settings->m_ShowUnit,
226 settings->m_ShowConvert );
227
228 if( !m_preview->IsShown() )
229 {
230 m_preview->Show();
231 m_statusPanel->Hide();
232 Layout(); // Ensure panel size is up to date.
233 }
234
235 // Calculate the draw scale to fit the drawing area
237 }
238
240}
241
242
243void SYMBOL_PREVIEW_WIDGET::DisplayPart( LIB_SYMBOL* aSymbol, int aUnit, int aConvert )
244{
245 KIGFX::VIEW* view = m_preview->GetView();
246
247 if( m_previewItem )
248 {
249 view->Remove( m_previewItem );
250 delete m_previewItem;
251 m_previewItem = nullptr;
252 }
253
254 if( aSymbol )
255 {
256 m_previewItem = new LIB_SYMBOL( *aSymbol );
257
258 // For symbols having a De Morgan body style, use the first style
259 auto settings =
260 static_cast<KIGFX::SCH_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
261
262 // If unit isn't specified for a multi-unit part, pick the first. (Otherwise we'll
263 // draw all of them.)
264 settings->m_ShowUnit = ( m_previewItem->IsMulti() && aUnit == 0 ) ? 1 : aUnit;
265
266 settings->m_ShowConvert =
267 ( m_previewItem->HasConversion() && aConvert == 0 ) ? 1 : aConvert;
268
269 view->Add( m_previewItem );
270
271 // Get the symbol size, in internal units
272 m_itemBBox = aSymbol->GetUnitBoundingBox( settings->m_ShowUnit, settings->m_ShowConvert );
273
274 // Calculate the draw scale to fit the drawing area
276 }
277
279 m_preview->Show();
280 m_statusPanel->Hide();
281 Layout();
282}
coord_type GetHeight() const
Definition: box2.h:188
coord_type GetWidth() const
Definition: box2.h:187
Vec Centre() const
Definition: box2.h:70
static constexpr GAL_TYPE GAL_FALLBACK
virtual KIGFX::VIEW * GetView() const
Return a pointer to the #VIEW instance used in the panel.
void ForceRefresh()
Force a redraw.
@ GAL_TYPE_OPENGL
OpenGL implementation.
KIGFX::GAL * GetGAL() const
Return a pointer to the GAL instance used in the panel.
void SetStealsFocus(bool aStealsFocus)
Set whether focus is taken on certain events (mouseover, keys, etc).
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:76
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
void ReadConfig(COMMON_SETTINGS &aCommonConfig, WINDOW_SETTINGS &aWindowConfig, wxWindow *aWindow)
Read application and common configs.
bool m_forceDisplayCursor
The pixel scale factor (>1 for hi-DPI scaled displays)
void SetAxesEnabled(bool aAxesEnabled)
Enable drawing the axes.
void SetClearColor(const COLOR4D &aColor)
void SetGridVisibility(bool aVisibility)
Set the visibility setting of the grid.
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
Store schematic specific render settings.
Definition: sch_painter.h:71
void LoadColors(const COLOR_SETTINGS *aSettings) override
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:69
virtual void SetScale(double aScale, VECTOR2D aAnchor={ 0, 0 })
Set the scaling factor, zooming around a given anchor point.
Definition: view.cpp:548
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:316
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:346
VECTOR2D ToWorld(const VECTOR2D &aCoord, bool aAbsolute=true) const
Converts a screen space point/vector to a point/vector in world space coordinates.
Definition: view.cpp:445
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:213
void SetCenter(const VECTOR2D &aCenter)
Set the center point of the VIEW (i.e.
Definition: view.cpp:574
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition: kiway.h:273
virtual PROJECT & Prj() const
Return the PROJECT associated with this KIWAY.
Definition: kiway.cpp:192
Field object used in symbol libraries.
Definition: lib_field.h:60
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
const UTF8 & GetLibItemName() const
Definition: lib_id.h:101
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:87
Define a library symbol object.
Definition: lib_symbol.h:98
bool IsMulti() const
Definition: lib_symbol.h:568
void GetFields(std::vector< LIB_FIELD * > &aList)
Return a list of fields within this symbol.
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:460
const BOX2I GetUnitBoundingBox(int aUnit, int aConvert) const
Get the bounding box for the symbol.
Definition: lib_symbol.cpp:968
bool HasConversion() const
Test if symbol has more than one body conversion type (DeMorgan).
LIB_SYMBOL * m_previewItem
A local copy of the LIB_SYMBOL to display on the canvas.
SYMBOL_PREVIEW_WIDGET(wxWindow *aParent, KIWAY &aKiway, EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType)
Construct a symbol preview widget.
void SetStatusText(const wxString &aText)
Set the contents of the status label and display it.
EDA_DRAW_PANEL_GAL * m_preview
void onSize(wxSizeEvent &aEvent)
void DisplayPart(LIB_SYMBOL *aSymbol, int aUnit, int aConvert=0)
BOX2I m_itemBBox
The bounding box of the current item.
void DisplaySymbol(const LIB_ID &aSymbolID, int aUnit, int aConvert=0)
Set the currently displayed symbol.
KIGFX::GAL_DISPLAY_OPTIONS m_galDisplayOptions
wxString wx_str() const
Definition: utf8.cpp:46
#define _(s)
@ LAYER_REFERENCEPART
Definition: layer_ids.h:352
see class PGM_BASE
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:111
const int scale