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-2020 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 
20 #include "symbol_preview_widget.h"
21 #include <wx/stattext.h>
22 #include <wx/sizer.h>
23 #include <kiway.h>
24 #include <sch_view.h>
26 #include <class_libentry.h>
27 #include <symbol_lib_table.h>
28 #include <sch_preview_panel.h>
29 #include <pgm_base.h>
30 #include <sch_painter.h>
31 #include <eda_draw_frame.h>
32 #include <eeschema_settings.h>
34 
35 
37  EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType ) :
38  wxPanel( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ),
39  m_kiway( aKiway ),
40  m_preview( nullptr ), m_status( nullptr ), m_statusSizer( nullptr ), m_previewItem( nullptr )
41 {
42  auto common_settings = Pgm().GetCommonSettings();
43  auto app_settings = Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>();
44 
45  m_galDisplayOptions.ReadConfig( *common_settings, app_settings->m_Window, this );
47 
48  EDA_DRAW_PANEL_GAL::GAL_TYPE canvasType = aCanvasType;
49 
50  // Allows only a CAIRO or OPENGL canvas:
51  if( canvasType != EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL
52  && canvasType != EDA_DRAW_PANEL_GAL::GAL_FALLBACK )
53  {
55  }
56 
57  m_preview = new SCH_PREVIEW_PANEL( aParent, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ),
58  m_galDisplayOptions, canvasType );
59  m_preview->SetStealsFocus( false );
60  m_preview->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER );
61  m_preview->GetGAL()->SetAxesEnabled( false );
62 
63  // Do not display the grid: the look is not good for a small canvas area.
64  // But mainly, due to some strange bug I (JPC) was unable to fix, the grid creates
65  // strange artifacts on Windows when eeschema is run from Kicad manager (but not in
66  // stand alone...).
67  m_preview->GetGAL()->SetGridVisibility( false );
68 
69  // Early initialization of the canvas background color,
70  // before any OnPaint event is fired for the canvas using a wrong bg color
71  KIGFX::VIEW* view = m_preview->GetView();
72  auto settings = static_cast<KIGFX::SCH_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
73 
74  if( auto* theme = Pgm().GetSettingsManager().GetColorSettings( app_settings->m_ColorTheme ) )
75  settings->LoadColors( theme );
76 
77  const COLOR4D& backgroundColor = settings->GetBackgroundColor();
78  const COLOR4D& foregroundColor = settings->GetCursorColor();
79 
80  m_preview->GetGAL()->SetClearColor( backgroundColor );
81 
82  m_statusPanel = new wxPanel( this );
83  m_statusPanel->SetBackgroundColour( backgroundColor.ToColour() );
84  m_status = new wxStaticText( m_statusPanel, wxID_ANY, wxEmptyString );
85  m_status->SetForegroundColour( settings->GetLayerColor( LAYER_REFERENCEPART ).ToColour() );
86  m_statusSizer = new wxBoxSizer( wxVERTICAL );
87  m_statusSizer->Add( 0, 0, 1 ); // add a spacer
88  m_statusSizer->Add( m_status, 0, wxALIGN_CENTER );
89  m_statusSizer->Add( 0, 0, 1 ); // add a spacer
90  m_statusPanel->SetSizer( m_statusSizer );
91 
92  // Give the status panel the same color scheme as the canvas so it isn't jarring when switched to
93  m_statusPanel->SetBackgroundColour( backgroundColor.ToColour() );
94  m_statusPanel->SetForegroundColour( foregroundColor.ToColour() );
95 
96  // Give the preview panel a small top border to align its top with the status panel,
97  // and give the status panel a small bottom border to align its bottom with the preview
98  // panel.
99  m_outerSizer = new wxBoxSizer( wxVERTICAL );
100  m_outerSizer->Add( m_preview, 1, wxTOP | wxEXPAND, 5 );
101  m_outerSizer->Add( m_statusPanel, 1, wxBOTTOM | wxEXPAND, 5 );
102 
103  // Hide the status panel to start
104  m_statusPanel->Hide();
105 
106  SetSizer( m_outerSizer );
107  Layout();
108 
109  Connect( wxEVT_SIZE, wxSizeEventHandler( SYMBOL_PREVIEW_WIDGET::onSize ), NULL, this );
110 }
111 
112 
114 {
115  if( m_previewItem )
117 
118  delete m_previewItem;
119 }
120 
121 
122 void SYMBOL_PREVIEW_WIDGET::SetStatusText( wxString const& aText )
123 {
124  m_status->SetLabel( aText );
125  m_preview->Hide();
126  m_statusPanel->Show();
127  Layout();
128 }
129 
130 
131 void SYMBOL_PREVIEW_WIDGET::onSize( wxSizeEvent& aEvent )
132 {
133  if( m_previewItem )
134  {
135  fitOnDrawArea();
137  }
138 
139  aEvent.Skip();
140 }
141 
142 
144 {
145  if( !m_previewItem )
146  return;
147 
148  // set the view scale to fit the item on screen
149  KIGFX::VIEW* view = m_preview->GetView();
150 
151  // Calculate the drawing area size, in internal units, for a scaling factor = 1.0
152  view->SetScale( 1.0 );
153  VECTOR2D clientSize = view->ToWorld( m_preview->GetClientSize(), false );
154  // Calculate the draw scale to fit the drawing area
155  double scale = std::min( fabs( clientSize.x / m_itemBBox.GetWidth() ),
156  fabs( clientSize.y / m_itemBBox.GetHeight() ) );
157 
158  // Above calculation will yield an exact fit; add a bit of whitespace around symbol
159  scale /= 1.2;
160 
161  // Now fix the best scale
162  view->SetScale( scale );
163  view->SetCenter( m_itemBBox.Centre() );
164 }
165 
166 
167 void SYMBOL_PREVIEW_WIDGET::DisplaySymbol( const LIB_ID& aSymbolID, int aUnit, int aConvert )
168 {
169  KIGFX::VIEW* view = m_preview->GetView();
170  auto settings = static_cast<KIGFX::SCH_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
171  std::unique_ptr< LIB_PART > symbol;
172 
173  try
174  {
175  LIB_PART* tmp = m_kiway.Prj().SchSymbolLibTable()->LoadSymbol( aSymbolID );
176 
177  if( tmp )
178  symbol = tmp->Flatten();
179  }
180  catch( const IO_ERROR& ioe )
181  {
182  wxLogError( wxString::Format( _( "Error loading symbol %s from library %s.\n\n%s" ),
183  aSymbolID.GetLibItemName().wx_str(),
184  aSymbolID.GetLibNickname().wx_str(),
185  ioe.What() ) );
186  }
187 
188  if( m_previewItem )
189  {
190  view->Remove( m_previewItem );
191  delete m_previewItem;
192  m_previewItem = nullptr;
193  }
194 
195  if( symbol )
196  {
197  // This will flatten derived parts so that the correct final symbol can be shown.
198  m_previewItem = symbol.release();
199 
200  // If unit isn't specified for a multi-unit part, pick the first. (Otherwise we'll
201  // draw all of them.)
202  settings->m_ShowUnit = ( m_previewItem->IsMulti() && aUnit == 0 ) ? 1 : aUnit;
203 
204  // For symbols having a De Morgan body style, use the first style
205  settings->m_ShowConvert =
206  ( m_previewItem->HasConversion() && aConvert == 0 ) ? 1 : aConvert;
207 
208  view->Add( m_previewItem );
209 
210  // Get the symbole size, in internal units
211  m_itemBBox = m_previewItem->GetUnitBoundingBox( settings->m_ShowUnit,
212  settings->m_ShowConvert );
213 
214  if( !m_preview->IsShown() )
215  {
216  m_preview->Show();
217  m_statusPanel->Hide();
218  Layout(); // Ensure panel size is up to date.
219  }
220 
221  // Calculate the draw scale to fit the drawing area
222  fitOnDrawArea();
223  }
224 
226 }
227 
228 
229 void SYMBOL_PREVIEW_WIDGET::DisplayPart( LIB_PART* aPart, int aUnit, int aConvert )
230 {
231  KIGFX::VIEW* view = m_preview->GetView();
232 
233  if( m_previewItem )
234  {
235  view->Remove( m_previewItem );
236  delete m_previewItem;
237  m_previewItem = nullptr;
238  }
239 
240  if( aPart )
241  {
242  m_previewItem = new LIB_PART( *aPart );
243 
244  // For symbols having a De Morgan body style, use the first style
245  auto settings = static_cast<KIGFX::SCH_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
246  // If unit isn't specified for a multi-unit part, pick the first. (Otherwise we'll
247  // draw all of them.)
248  settings->m_ShowUnit = ( m_previewItem->IsMulti() && aUnit == 0 ) ? 1 : aUnit;
249 
250  settings->m_ShowConvert =
251  ( m_previewItem->HasConversion() && aConvert == 0 ) ? 1 : aConvert;
252 
253  view->Add( m_previewItem );
254 
255  // Get the symbole size, in internal units
256  m_itemBBox = aPart->GetUnitBoundingBox( settings->m_ShowUnit, settings->m_ShowConvert );
257 
258  // Calculate the draw scale to fit the drawing area
259  fitOnDrawArea();
260  }
261 
263  m_preview->Show();
264  m_statusPanel->Hide();
265  Layout();
266 }
SYMBOL_PREVIEW_WIDGET(wxWindow *aParent, KIWAY &aKiway, EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType)
Construct a symbol preview widget.
void SetClearColor(const COLOR4D &aColor)
const UTF8 & GetLibItemName() const
Definition: lib_id.h:114
void ForceRefresh()
Function ForceRefresh() Forces a redraw.
void onSize(wxSizeEvent &aEvent)
VECTOR2D ToWorld(const VECTOR2D &aCoord, bool aAbsolute=true) const
Function ToWorld() Converts a screen space point/vector to a point/vector in world space coordinates.
Definition: view.cpp:456
void DisplayPart(LIB_PART *aPart, int aUnit, int aConvert=0)
bool HasConversion() const
Test if part has more than one body conversion type (DeMorgan).
VTBL_ENTRY PROJECT & Prj() const
Function Prj returns the PROJECT associated with this KIWAY.
Definition: kiway.cpp:173
virtual void Remove(VIEW_ITEM *aItem)
Function Remove() Removes a VIEW_ITEM from the view.
Definition: view.cpp:357
static constexpr GAL_TYPE GAL_FALLBACK
bool m_forceDisplayCursor
Force cursor display
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:102
void SetStatusText(wxString const &aText)
Set the contents of the status label and display it.
PAINTER * GetPainter() const
Function GetPainter() Returns the painter object used by the view for drawing VIEW_ITEMS.
Definition: view.h:201
void SetCenter(const VECTOR2D &aCenter)
Function SetCenter() Sets the center point of the VIEW (i.e.
Definition: view.cpp:585
#define NULL
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:29
KIGFX::GAL_DISPLAY_OPTIONS m_galDisplayOptions
coord_type GetWidth() const
Definition: box2.h:197
EDA_DRAW_PANEL_GAL * m_preview
void SetStealsFocus(bool aStealsFocus)
Set whether focus is taken on certain events (mouseover, keys, etc).
Define a library symbol object.
KIWAY is a minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the s...
Definition: kiway.h:273
KIGFX::GAL * GetGAL() const
Function GetGAL() Returns a pointer to the GAL instance used in the panel.
virtual KIGFX::VIEW * GetView() const
Function GetView() Returns a pointer to the VIEW instance used in the panel.
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:97
std::unique_ptr< LIB_PART > Flatten() const
Return a flattened symbol inheritance to the caller.
void SetAxesEnabled(bool aAxesEnabled)
Enables drawing the axes.
LIB_PART * m_previewItem
A local copy of the LIB_PART to display on the canvas.
virtual void SetScale(double aScale, VECTOR2D aAnchor={ 0, 0 })
Function SetScale() Sets the scaling factor, zooming around a given anchor point.
Definition: view.cpp:559
virtual RENDER_SETTINGS * GetSettings()=0
Function GetAdapter Returns pointer to current settings that are going to be used when drawing items.
void DisplaySymbol(const LIB_ID &aSymbolID, int aUnit, int aConvert=0)
Set the currently displayed symbol.
const int scale
see class PGM_BASE
Vec Centre() const
Definition: box2.h:79
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:201
#define _(s)
Definition: 3d_actions.cpp:33
const EDA_RECT GetUnitBoundingBox(int aUnit, int aConvert) const
Get the bounding box for the symbol.
wxString wx_str() const
Definition: utf8.cpp:51
void ReadConfig(COMMON_SETTINGS &aCommonConfig, WINDOW_SETTINGS &aWindowConfig, wxWindow *aWindow)
Read application and common configs.
coord_type GetHeight() const
Definition: box2.h:198
bool IsMulti() const
void SetGridVisibility(bool aVisibility)
Sets the visibility setting of the grid.
BOX2I m_itemBBox
The bounding box of the current item.
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Function Add() Adds a VIEW_ITEM to the view.
Definition: view.cpp:327
VIEW.
Definition: view.h:63
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:76
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:100