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 <math/vector2wx.h>
24#include <symbol_lib_table.h>
25#include <sch_preview_panel.h>
26#include <pgm_base.h>
27#include <sch_painter.h>
28#include <eda_draw_frame.h>
29#include <eeschema_settings.h>
31#include <wx/log.h>
32#include <wx/stattext.h>
33
34
36 EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType ) :
37 wxPanel( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ),
38 m_kiway( aKiway ),
39 m_preview( nullptr ), m_status( nullptr ), m_statusSizer( nullptr ), m_previewItem( nullptr )
40{
41 auto common_settings = Pgm().GetCommonSettings();
42 auto app_settings = Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>();
43
44 m_galDisplayOptions.ReadConfig( *common_settings, app_settings->m_Window, this );
46
47 EDA_DRAW_PANEL_GAL::GAL_TYPE canvasType = aCanvasType;
48
49 // Allows only a CAIRO or OPENGL canvas:
51 && canvasType != EDA_DRAW_PANEL_GAL::GAL_FALLBACK )
52 {
54 }
55
56 m_preview = new SCH_PREVIEW_PANEL( this, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ),
57 m_galDisplayOptions, canvasType );
58 m_preview->SetStealsFocus( false );
59 m_preview->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER );
60 m_preview->GetGAL()->SetAxesEnabled( false );
61
62 // Do not display the grid: the look is not good for a small canvas area.
63 // But mainly, due to some strange bug I (JPC) was unable to fix, the grid creates
64 // strange artifacts on Windows when Eeschema is run from KiCad manager (but not in
65 // stand alone...).
67
68 // Early initialization of the canvas background color,
69 // before any OnPaint event is fired for the canvas using a wrong bg color
70 KIGFX::VIEW* view = m_preview->GetView();
71 auto settings = static_cast<KIGFX::SCH_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
72
73 if( auto* theme = Pgm().GetSettingsManager().GetColorSettings( app_settings->m_ColorTheme ) )
74 settings->LoadColors( theme );
75
76 const COLOR4D& backgroundColor = settings->GetBackgroundColor();
77 const COLOR4D& foregroundColor = settings->GetCursorColor();
78
79 m_preview->GetGAL()->SetClearColor( backgroundColor );
80
81 settings->m_ShowPinsElectricalType = app_settings->m_LibViewPanel.show_pin_electrical_type;
82 settings->m_ShowPinNumbers = app_settings->m_LibViewPanel.show_pin_numbers;
83
84 m_statusPanel = new wxPanel( this );
85 m_statusPanel->SetBackgroundColour( backgroundColor.ToColour() );
86 m_status = new wxStaticText( m_statusPanel, wxID_ANY, wxEmptyString );
87 m_status->SetForegroundColour( settings->GetLayerColor( LAYER_REFERENCEPART ).ToColour() );
88 m_statusSizer = new wxBoxSizer( wxVERTICAL );
89 m_statusSizer->Add( 0, 0, 1 ); // add a spacer
90 m_statusSizer->Add( m_status, 0, wxALIGN_CENTER );
91 m_statusSizer->Add( 0, 0, 1 ); // add a spacer
92 m_statusPanel->SetSizer( m_statusSizer );
93
94 // Give the status panel the same color scheme as the canvas so it isn't jarring when
95 // switched to.
96 m_statusPanel->SetBackgroundColour( backgroundColor.ToColour() );
97 m_statusPanel->SetForegroundColour( foregroundColor.ToColour() );
98
99 // Give the preview panel a small top border to align its top with the status panel,
100 // and give the status panel a small bottom border to align its bottom with the preview
101 // panel.
102 m_outerSizer = new wxBoxSizer( wxVERTICAL );
103 m_outerSizer->Add( m_preview, 1, wxTOP | wxEXPAND, 5 );
104 m_outerSizer->Add( m_statusPanel, 1, wxBOTTOM | wxEXPAND, 5 );
105
106 // Hide the status panel to start
107 m_statusPanel->Hide();
108
109 SetSizer( m_outerSizer );
110 Layout();
111
112 Connect( wxEVT_SIZE, wxSizeEventHandler( SYMBOL_PREVIEW_WIDGET::onSize ), nullptr, this );
113}
114
115
117{
118 if( m_previewItem )
120
121 delete m_previewItem;
122}
123
124
125void SYMBOL_PREVIEW_WIDGET::SetStatusText( wxString const& aText )
126{
127 m_status->SetLabel( aText );
128 m_preview->Hide();
129 m_statusPanel->Show();
130 Layout();
131}
132
133
134void SYMBOL_PREVIEW_WIDGET::onSize( wxSizeEvent& aEvent )
135{
136 if( m_previewItem )
137 {
140 }
141
142 aEvent.Skip();
143}
144
145
147{
148 if( !m_previewItem )
149 return;
150
151 // set the view scale to fit the item on screen
152 KIGFX::VIEW* view = m_preview->GetView();
153
154 // Calculate the drawing area size, in internal units, for a scaling factor = 1.0
155 view->SetScale( 1.0 );
156 VECTOR2D clientSize = view->ToWorld( ToVECTOR2D( m_preview->GetClientSize() ), false );
157 // Calculate the draw scale to fit the drawing area
158 double scale = std::min( fabs( clientSize.x / m_itemBBox.GetWidth() ),
159 fabs( clientSize.y / m_itemBBox.GetHeight() ) );
160
161 // Above calculation will yield an exact fit; add a bit of whitespace around symbol
162 scale /= 1.2;
163
164 // Now fix the best scale
165 view->SetScale( scale );
166 view->SetCenter( m_itemBBox.Centre() );
167}
168
169
170void SYMBOL_PREVIEW_WIDGET::DisplaySymbol( const LIB_ID& aSymbolID, int aUnit, int aConvert )
171{
172 KIGFX::VIEW* view = m_preview->GetView();
173 auto settings = static_cast<KIGFX::SCH_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
174 std::unique_ptr< LIB_SYMBOL > symbol;
175
176 try
177 {
178 LIB_SYMBOL* tmp = m_kiway.Prj().SchSymbolLibTable()->LoadSymbol( aSymbolID );
179
180 if( tmp )
181 symbol = tmp->Flatten();
182 }
183 catch( const IO_ERROR& ioe )
184 {
185 wxLogError( _( "Error loading symbol %s from library '%s'." ) + wxS( "\n%s" ),
186 aSymbolID.GetLibItemName().wx_str(),
187 aSymbolID.GetLibNickname().wx_str(),
188 ioe.What() );
189 }
190
191 if( m_previewItem )
192 {
193 view->Remove( m_previewItem );
194 delete m_previewItem;
195 m_previewItem = nullptr;
196 }
197
198 if( symbol )
199 {
200 // This will flatten derived parts so that the correct final symbol can be shown.
201 m_previewItem = symbol.release();
202
203 // Hide fields that were added automatically by the library (for example, when using
204 // database libraries) as they don't have a valid position yet, and we don't support
205 // autoplacing fields on library symbols yet.
206 std::vector<LIB_FIELD*> previewFields;
207 m_previewItem->GetFields( previewFields );
208
209 for( LIB_FIELD* field : previewFields )
210 {
211 if( field->IsAutoAdded() )
212 field->SetVisible( false );
213 }
214
215 // If unit isn't specified for a multi-unit part, pick the first. (Otherwise we'll
216 // draw all of them.)
217 settings->m_ShowUnit = ( m_previewItem->IsMulti() && aUnit == 0 ) ? 1 : aUnit;
218
219 // For symbols having a De Morgan body style, use the first style
220 settings->m_ShowConvert =
221 ( m_previewItem->HasConversion() && aConvert == 0 ) ? 1 : aConvert;
222
223 view->Add( m_previewItem );
224
225 // Get the symbol size, in internal units
226 m_itemBBox = m_previewItem->GetUnitBoundingBox( settings->m_ShowUnit,
227 settings->m_ShowConvert );
228
229 if( !m_preview->IsShown() )
230 {
231 m_preview->Show();
232 m_statusPanel->Hide();
233 Layout(); // Ensure panel size is up to date.
234 }
235
236 // Calculate the draw scale to fit the drawing area
238 }
239
241}
242
243
244void SYMBOL_PREVIEW_WIDGET::DisplayPart( LIB_SYMBOL* aSymbol, int aUnit, int aConvert )
245{
246 KIGFX::VIEW* view = m_preview->GetView();
247
248 if( m_previewItem )
249 {
250 view->Remove( m_previewItem );
251 delete m_previewItem;
252 m_previewItem = nullptr;
253 }
254
255 if( aSymbol )
256 {
257 m_previewItem = new LIB_SYMBOL( *aSymbol );
258
259 // For symbols having a De Morgan body style, use the first style
260 auto settings =
261 static_cast<KIGFX::SCH_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
262
263 // If unit isn't specified for a multi-unit part, pick the first. (Otherwise we'll
264 // draw all of them.)
265 settings->m_ShowUnit = ( m_previewItem->IsMulti() && aUnit == 0 ) ? 1 : aUnit;
266
267 settings->m_ShowConvert =
268 ( m_previewItem->HasConversion() && aConvert == 0 ) ? 1 : aConvert;
269
270 view->Add( m_previewItem );
271
272 // Get the symbol size, in internal units
273 m_itemBBox = aSymbol->GetUnitBoundingBox( settings->m_ShowUnit, settings->m_ShowConvert );
274
275 // Calculate the draw scale to fit the drawing area
277 }
278
280 m_preview->Show();
281 m_statusPanel->Hide();
282 Layout();
283}
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:102
wxColour ToColour() const
Definition: color4d.cpp:219
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:551
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:349
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:448
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:577
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition: kiway.h:279
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:61
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:102
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:99
bool IsMulti() const
Definition: lib_symbol.h:557
void GetFields(std::vector< LIB_FIELD * > &aList)
Return a list of fields within this symbol.
const BOX2I GetUnitBoundingBox(int aUnit, int aConvert, bool aIgnoreHiddenFields=true) const
Get the bounding box for the symbol.
Definition: lib_symbol.cpp:953
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
Definition: lib_symbol.cpp:453
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
VECTOR2D ToVECTOR2D(const wxPoint &aPoint)
Definition: vector2wx.h:40