KiCad PCB EDA Suite
footprint_preview_panel.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) 2016-2017 KiCad Developers, see AUTHORS.txt for contributors.
5  * Copyright (C) 2017 Chris Pavlina <pavlina.chris@gmail.com>
6  * Copyright (C) 2016 Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
7  *
8  * This program is free software: you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the
10  * Free Software Foundation, either version 3 of the License, or (at your
11  * option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
23 #include <pcb_draw_panel_gal.h>
24 #include <kiface_i.h>
25 #include <kiway.h>
26 #include <io_mgr.h>
27 #include <fp_lib_table.h>
28 #include <view/view.h>
29 #include <math/box2.h>
30 #include <class_module.h>
31 #include <class_board.h>
32 #include <ki_mutex.h>
33 #include <draw_frame.h>
34 #include <boost/bind.hpp>
35 #include <utility>
36 #include <make_unique.h>
37 #include <colors_design_settings.h>
38 #include <pcb_edit_frame.h>
39 #include <wx/stattext.h>
40 #include <pgm_base.h>
41 #include <painter.h>
42 
47 {
49 
50  public:
53  {
54  MUTLOCK lock( m_lock );
55  auto it = m_cachedFootprints.find( aFPID );
56 
57  if( it != m_cachedFootprints.end() )
58  return it->second;
59  else
60  return NULLOPT;
61  }
62 
67  CACHE_ENTRY AddToQueue( LIB_ID const & aEntry )
68  {
69  MUTLOCK lock( m_lock );
70 
71  CACHE_ENTRY ent = { aEntry, NULL, FPS_LOADING };
72  m_cachedFootprints[aEntry] = ent;
73  m_loaderQueue.push_back( ent );
74 
75  return ent;
76  }
77 
80  {
81  MUTLOCK lock( m_lock );
82 
83  if( m_loaderQueue.empty() )
84  {
85  return NULLOPT;
86  }
87  else
88  {
89  auto ent = m_loaderQueue.front();
90  m_loaderQueue.pop_front();
91  return ent;
92  }
93  }
94 
96  void AddToCache( CACHE_ENTRY const & aEntry )
97  {
98  MUTLOCK lock( m_lock );
99  m_cachedFootprints[aEntry.fpid] = aEntry;
100  }
101 
106  {
107  MUTLOCK lock( m_lock );
108  m_current_fp = std::move( aFp );
109  }
110 
115  {
116  MUTLOCK lock( m_lock );
117  return m_current_fp;
118  }
119 
124  {
125  MUTLOCK lock( m_lock );
126  m_panel = aPanel;
127  }
128 
133  {
134  MUTLOCK lock( m_lock );
135  return m_panel;
136  }
137 
142  bool QueueEvent( wxEvent const& aEvent )
143  {
144  MUTLOCK lock( m_lock );
145 
146  if( m_panel )
147  {
148  m_panel->GetEventHandler()->QueueEvent( aEvent.Clone() );
149  return true;
150  }
151  else
152  {
153  return false;
154  }
155  }
156 
161  {
162  MUTLOCK locK( m_lock );
163  return m_panel ? m_panel->Prj().PcbFootprintLibs() : nullptr;
164  }
165 
166  private:
167  std::deque<CACHE_ENTRY> m_loaderQueue;
168  std::map<LIB_ID, CACHE_ENTRY> m_cachedFootprints;
172 };
173 
174 
179 class FP_LOADER_THREAD: public wxThread
180 {
182 
183  std::shared_ptr<FP_THREAD_IFACE> m_iface;
184 
185 public:
186  FP_LOADER_THREAD( std::shared_ptr<FP_THREAD_IFACE> const& aIface ):
187  wxThread( wxTHREAD_DETACHED ),
188  m_iface( aIface )
189  {}
190 
191 
193  {}
194 
195 
196  void ProcessEntry( CACHE_ENTRY& aEntry )
197  {
198  FP_LIB_TABLE* fptbl = m_iface->GetTable();
199 
200  if( !fptbl )
201  return;
202 
203  aEntry.module = NULL;
204 
205  try {
206  aEntry.module = fptbl->FootprintLoadWithOptionalNickname( aEntry.fpid );
207 
208  if( !aEntry.module )
209  aEntry.status = FPS_NOT_FOUND;
210 
211  } catch( const IO_ERROR& )
212  {
213  aEntry.status = FPS_NOT_FOUND;
214  }
215 
216 
217  if( aEntry.status != FPS_NOT_FOUND )
218  aEntry.status = FPS_READY;
219 
220  m_iface->AddToCache( aEntry );
221 
222  if( aEntry.fpid == m_iface->GetCurrentFootprint() )
223  {
224  wxCommandEvent evt( wxEVT_COMMAND_TEXT_UPDATED, 1 );
225  m_iface->QueueEvent( evt );
226  }
227  }
228 
229 
230  virtual void* Entry() override
231  {
232  while( m_iface->GetPanel() )
233  {
234  auto ent = m_iface->PopFromQueue();
235 
236  if( ent )
237  ProcessEntry( *ent );
238  else
239  wxMilliSleep( 100 );
240  }
241 
242  return nullptr;
243  }
244 };
245 
246 
249  GAL_TYPE aGalType )
250  : PCB_DRAW_PANEL_GAL ( aParent, -1, wxPoint( 0, 0 ), wxSize(200, 200), aOpts, aGalType ),
251  KIWAY_HOLDER( aKiway ),
252  m_footprintDisplayed( true )
253 {
254  m_iface = std::make_shared<FP_THREAD_IFACE>();
255  m_iface->SetPanel( this );
257  m_loader->Run();
258 
259  SetStealsFocus( false );
260  ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER );
261  EnableScrolling( false, false ); // otherwise Zoom Auto disables GAL canvas
262 
263  m_dummyBoard = std::make_unique<BOARD>();
264  m_colorsSettings = std::make_unique<COLORS_DESIGN_SETTINGS>( FRAME_PCB_FOOTPRINT_PREVIEW );
265  m_colorsSettings->Load( Kiface().KifaceSettings() );
266 
267  UseColorScheme( m_colorsSettings.get() );
269 
270  Raise();
271  Show( true );
272  StartDrawing();
273 
274  Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( FOOTPRINT_PREVIEW_PANEL::OnLoaderThreadUpdate ), NULL, this );
275 }
276 
277 
279 {
280  m_iface->SetPanel( nullptr );
281 }
282 
283 
285 {
286  auto opt_ent = m_iface->GetFromCache( aFPID );
287 
288  if( opt_ent )
289  return *opt_ent;
290  else
291  return m_iface->AddToQueue( aFPID );
292 }
293 
294 
295 // This is separate to avoid having to export CACHE_ENTRY to the global namespace
297 {
298  (void) CacheAndReturn( aFPID );
299 }
300 
301 
303 {
304  GetView()->Clear();
305  module->SetParent( &*m_dummyBoard );
306 
307  GetView()->Add( module );
308  GetView()->SetVisible( module, true );
309  GetView()->Update( module, KIGFX::ALL );
310 
311  BOX2I bbox = module->ViewBBox();
312  bbox.Merge ( module->Value().ViewBBox() );
313  bbox.Merge ( module->Reference().ViewBBox() );
314 
315  if( bbox.GetSize().x > 0 && bbox.GetSize().y > 0 )
316  {
317  // Autozoom
318  GetView()->SetViewport( BOX2D( bbox.GetOrigin(), bbox.GetSize() ) );
319 
320  // Add a margin
321  GetView()->SetScale( GetView()->GetScale() * 0.7 );
322 
323  Refresh();
324  }
325 }
326 
327 
329 {
330  m_currentFPID = aFPID;
331  m_iface->SetCurrentFootprint( aFPID );
332  m_footprintDisplayed = false;
333 
335 
336  if( m_handler )
337  m_handler( fpe.status );
338 
339  if( fpe.status == FPS_READY )
340  {
341  if ( !m_footprintDisplayed )
342  {
343  renderFootprint( fpe.module );
344  m_footprintDisplayed = true;
345  Refresh();
346  }
347  }
348 }
349 
350 
352 {
354 }
355 
356 
358 {
359  m_handler = aHandler;
360 }
361 
362 
364 {
365  return static_cast<wxWindow*>( this );
366 }
367 
368 
370 {
371  PCB_EDIT_FRAME* pcbnew = static_cast<PCB_EDIT_FRAME*>( aKiway->Player( FRAME_PCB, false ) );
373  wxConfigBase* cfg = Kiface().KifaceSettings();
374  wxConfigBase* commonCfg = Pgm().CommonSettings();
375  bool btemp;
376  int itemp;
377  wxString msg;
378  COLOR4D ctemp;
379 
380  // Fetch grid & display settings from PCBNew if it's running; otherwise fetch them
381  // from PCBNew's config settings.
382 
383  if( pcbnew )
384  {
385  gal_opts = pcbnew->GetGalDisplayOptions();
386  }
387  else
388  {
389  gal_opts.ReadConfig( cfg, wxString( PCB_EDIT_FRAME_NAME ) + GAL_DISPLAY_OPTIONS_KEY );
390 
391  commonCfg->Read( GAL_ANTIALIASING_MODE_KEY, &itemp, (int) KIGFX::OPENGL_ANTIALIASING_MODE::NONE );
393  }
394 
395 #ifdef __WXMAC__
396  // Cairo renderer doesn't handle Retina displays
398 #else
400 #endif
401 
402  auto panel = new FOOTPRINT_PREVIEW_PANEL( aKiway, aParent, gal_opts, backend );
403 
404  if( pcbnew )
405  {
406  panel->GetGAL()->SetGridVisibility( pcbnew->IsGridVisible() );
407  panel->GetGAL()->SetGridSize( VECTOR2D( pcbnew->GetScreen()->GetGridSize() ) );
408 
409  // Grid color (among other things):
410  KIGFX::PAINTER* pcbnew_painter = pcbnew->GetGalCanvas()->GetView()->GetPainter();
411  panel->GetView()->GetPainter()->ApplySettings( pcbnew_painter->GetSettings() );
412  }
413  else
414  {
415  btemp = cfg->ReadBool( wxString( PCB_EDIT_FRAME_NAME ) + ShowGridEntryKeyword, true );
416  panel->GetGAL()->SetGridVisibility( btemp );
417 
418  // Read grid size:
419  std::unique_ptr<PCB_SCREEN> temp_screen = std::make_unique<PCB_SCREEN>( wxSize() );
420  cfg->Read( wxString( PCB_EDIT_FRAME_NAME ) + LastGridSizeIdKeyword, &itemp, 0L );
421  temp_screen->SetGrid( itemp + ID_POPUP_GRID_LEVEL_1000 );
422  panel->GetGAL()->SetGridSize( VECTOR2D( temp_screen->GetGridSize() ) );
423 
424  // Read grid color:
425  msg = cfg->Read( wxString( PCB_EDIT_FRAME_NAME ) + GridColorEntryKeyword, wxT( "NONE" ) );
426  ctemp.SetFromWxString( msg );
427  panel->GetGAL()->SetGridColor( ctemp );
428  }
429 
430  return panel;
431 }
const Vec & GetOrigin() const
Definition: box2.h:191
Class KIWAY_HOLDER is a mix in class which holds the location of a wxWindow&#39;s KIWAY.
Definition: kiway_player.h:48
LIB_ID fpid
Footprint loader thread to prevent footprint loading from locking the UI.
bool QueueEvent(wxEvent const &aEvent)
Post an event to the panel, if the panel still exists.
TEXTE_MODULE & Reference()
Definition: class_module.h:513
FOOTPRINT_STATUS status
void SetViewport(const BOX2D &aViewport)
Function SetViewport() Sets the visible area of the VIEW.
Definition: view.cpp:548
KIGFX::GAL_DISPLAY_OPTIONS & GetGalDisplayOptions()
Return a reference to the gal rendering options used by GAL for rendering.
Definition: draw_frame.h:946
Handle colors used to draw all items or layers.
virtual const BOX2I ViewBBox() const override
Function ViewBBox() returns the bounding box of the item covering all its layers. ...
Class BOARD to handle a board.
void renderFootprint(MODULE *module)
BOX2< VECTOR2D > BOX2D
Definition: box2.h:521
virtual CACHE_ENTRY CacheAndReturn(LIB_ID const &aFPID)
std::shared_ptr< FP_THREAD_IFACE > m_iface
boost::interprocess::interprocess_mutex MUTEX
Establish KiCad MUTEX choices here in this file: typedef MUTEX and typedef MUTLOCK.
Definition: ki_mutex.h:42
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: kicad.cpp:66
virtual void * Entry() override
LIB_ID GetCurrentFootprint()
Threadsafe accessor to get the current footprint.
OPT< CACHE_ENTRY > PopFromQueue()
Pop an entry from the queue, or empty option if none is available.
KIGFX::VIEW * GetView() const
Function GetView() Returns a pointer to the VIEW instance used in the panel.
void ProcessEntry(CACHE_ENTRY &aEntry)
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
Item needs to be redrawn.
Definition: view_item.h:61
const Vec & GetSize() const
Definition: box2.h:187
OPENGL_ANTIALIASING_MODE gl_antialiasing_mode
void SetScale(double aScale)
Function SetScale() Sets the scaling factor.
Definition: view.h:250
virtual void ApplySettings(const RENDER_SETTINGS *aSettings)=0
Function ApplySettings Loads colors and display modes settings that are going to be used when drawing...
virtual bool IsGridVisible() const override
Function IsGridVisible() , virtual.
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
Definition: kicad.cpp:52
#define PCB_EDIT_FRAME_NAME
Definition: draw_frame.h:56
Panel that renders a single footprint via Cairo GAL, meant to be exported through Kiface...
CACHE_ENTRY AddToQueue(LIB_ID const &aEntry)
Push an entry to the loading queue and a placeholder to the cache; return the placeholder.
FP_LIB_TABLE * GetTable()
Get an FP_LIB_TABLE, or null if the panel is dead.
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
#define GAL_DISPLAY_OPTIONS_KEY
Definition: pgm_base.h:52
void ReadConfig(wxConfigBase *aCfg, const wxString &aBaseName)
FOOTPRINT_PREVIEW_PANEL * GetPanel()
Get the associated panel.
Class PAINTER contains all the knowledge about how to draw graphical object onto any particular outpu...
Definition: painter.h:308
virtual wxWindow * GetWindow() override
Get the underlying wxWindow.
const auto NULLOPT
Definition: optional.h:9
VECTOR2< double > VECTOR2D
Definition: vector2d.h:586
std::unique_ptr< BOARD > m_dummyBoard
VTBL_ENTRY KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=NULL)
Function Player returns the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:300
OPT< CACHE_ENTRY > GetFromCache(LIB_ID const &aFPID)
Retrieve a cache entry by LIB_ID.
Threadsafe interface class between loader thread and panel class.
void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:216
void Clear()
Function Clear() Removes all items from the view.
Definition: view.cpp:1108
TEXTE_MODULE & Value()
read/write accessors:
Definition: class_module.h:512
void AddToCache(CACHE_ENTRY const &aEntry)
Add an entry to the cache.
virtual const BOX2I ViewBBox() const override
Function ViewBBox() returns the bounding box of the item covering all its layers. ...
void SetStealsFocus(bool aStealsFocus)
Set whether focus is taken on certain events (mouseover, keys, etc).
virtual void SetStatusHandler(FOOTPRINT_STATUS_HANDLER aHandler) override
Set the callback to receive status updates.
static const wxString ShowGridEntryKeyword(wxT("ShowGrid"))
Nonzero to show grid (suffix)
static FOOTPRINT_PREVIEW_PANEL * New(KIWAY *aKiway, wxWindow *aParent)
Class KIWAY is a minimalistic software bus for communications between various DLLs/DSOs (DSOs) within...
Definition: kiway.h:258
wxConfigBase * KifaceSettings() const
Definition: kiface_i.h:103
PAINTER * GetPainter() const
Function GetPainter() Returns the painter object used by the view for drawing VIEW_ITEMS.
Definition: view.h:199
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Function Merge modifies the position and size of the rectangle in order to contain aRect...
Definition: box2.h:384
void SyncLayersVisibility(const BOARD *aBoard)
Function SyncLayersVisibility Updates "visibility" property of each layer of a given BOARD...
virtual void Update(VIEW_ITEM *aItem, int aUpdateFlags)
For dynamic VIEWs, informs the associated VIEW that the graphical representation of this item has cha...
Definition: view.cpp:1530
void SetCurrentFootprint(LIB_ID aFp)
Threadsafe accessor to set the current footprint.
void StartDrawing()
Function StartDrawing() Begins drawing if it was stopped previously.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
void UseColorScheme(const COLORS_DESIGN_SETTINGS *aSettings)
Function UseColorScheme Applies layer color settings.
std::map< LIB_ID, CACHE_ENTRY > m_cachedFootprints
VTBL_ENTRY FP_LIB_TABLE * PcbFootprintLibs(KIWAY &aKiway)
Return the table of footprint libraries.
static const wxString LastGridSizeIdKeyword(wxT("_LastGridSize"))
Most recently used grid size (suffix)
virtual RENDER_SETTINGS * GetSettings()=0
Function GetSettings Returns pointer to current settings that are going to be used when drawing items...
boost::interprocess::scoped_lock< MUTEX > MUTLOCK
Definition: ki_mutex.h:43
FP_LOADER_THREAD(std::shared_ptr< FP_THREAD_IFACE > const &aIface)
#define GAL_ANTIALIASING_MODE_KEY
Definition: pgm_base.h:53
void SetPanel(FOOTPRINT_PREVIEW_PANEL *aPanel)
Set the associated panel, for QueueEvent() and GetTable().
see class PGM_BASE
virtual void CacheFootprint(LIB_ID const &aFPID) override
Preload a footprint into the cache.
Implementation of std::make_unique for pre C++14 compilation environments.
void OnLoaderThreadUpdate(wxCommandEvent &aEvent)
FOOTPRINT_STATUS_HANDLER m_handler
MODULE * module
VTBL_ENTRY wxConfigBase * CommonSettings() const
Definition: pgm_base.h:187
const wxRealPoint & GetGridSize() const
Return the grid size of the currently selected grid.
Definition: base_screen.h:410
Class PCB_EDIT_FRAME is the main frame for Pcbnew.
std::shared_ptr< FP_THREAD_IFACE > m_iface
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
boost::optional< T > OPT
Definition: optional.h:7
std::deque< CACHE_ENTRY > m_loaderQueue
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Sets the item visibility.
Definition: view.cpp:1476
EDA_DRAW_PANEL_GAL * GetGalCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
Definition: draw_frame.h:928
MODULE * FootprintLoadWithOptionalNickname(const LIB_ID &aFootprintId)
Function FootprintLoadWithOptionalNickname loads a footprint having aFootprintId with possibly an emp...
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Function Add() Adds a VIEW_ITEM to the view.
Definition: view.cpp:344
static const wxString GridColorEntryKeyword(wxT("GridColor"))
Grid color ID (suffix)
virtual void DisplayFootprint(LIB_ID const &aFPID) override
Set the currently displayed footprint.
Module description (excepted pads)
FOOTPRINT_PREVIEW_PANEL(KIWAY *aKiway, wxWindow *aParent, KIGFX::GAL_DISPLAY_OPTIONS &aOpts, GAL_TYPE aGalType)
std::unique_ptr< COLORS_DESIGN_SETTINGS > m_colorsSettings
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
FOOTPRINT_PREVIEW_PANEL * m_panel
std::function< void(FOOTPRINT_STATUS)> FOOTPRINT_STATUS_HANDLER
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39