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 
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 
34 #include <boost/bind.hpp>
35 #include <make_unique.h>
37 
38 #include <wx/stattext.h>
39 
40 
45 {
47 
48  public:
51  {
52  MUTLOCK lock( m_lock );
53  auto it = m_cachedFootprints.find( aFPID );
54 
55  if( it != m_cachedFootprints.end() )
56  return it->second;
57  else
58  return boost::none;
59  }
60 
65  CACHE_ENTRY AddToQueue( LIB_ID const & aEntry )
66  {
67  MUTLOCK lock( m_lock );
68 
69  CACHE_ENTRY ent = { aEntry, NULL, FPS_LOADING };
70  m_cachedFootprints[aEntry] = ent;
71  m_loaderQueue.push_back( ent );
72 
73  return ent;
74  }
75 
78  {
79  MUTLOCK lock( m_lock );
80 
81  if( m_loaderQueue.empty() )
82  {
83  return boost::none;
84  }
85  else
86  {
87  auto ent = m_loaderQueue.front();
88  m_loaderQueue.pop_front();
89  return ent;
90  }
91  }
92 
94  void AddToCache( CACHE_ENTRY const & aEntry )
95  {
96  MUTLOCK lock( m_lock );
97  m_cachedFootprints[aEntry.fpid] = aEntry;
98  }
99 
104  {
105  MUTLOCK lock( m_lock );
106  m_current_fp = aFp;
107  }
108 
113  {
114  MUTLOCK lock( m_lock );
115  return m_current_fp;
116  }
117 
122  {
123  MUTLOCK lock( m_lock );
124  m_panel = aPanel;
125  }
126 
131  {
132  MUTLOCK lock( m_lock );
133  return m_panel;
134  }
135 
140  bool QueueEvent( wxEvent const& aEvent )
141  {
142  MUTLOCK lock( m_lock );
143 
144  if( m_panel )
145  {
146  m_panel->GetEventHandler()->QueueEvent( aEvent.Clone() );
147  return true;
148  }
149  else
150  {
151  return false;
152  }
153  }
154 
159  {
160  MUTLOCK locK( m_lock );
161  return m_panel ? m_panel->Prj().PcbFootprintLibs() : nullptr;
162  }
163 
164  private:
165  std::deque<CACHE_ENTRY> m_loaderQueue;
166  std::map<LIB_ID, CACHE_ENTRY> m_cachedFootprints;
170 };
171 
172 
177 class FP_LOADER_THREAD: public wxThread
178 {
180 
181  std::shared_ptr<FP_THREAD_IFACE> m_iface;
182 
183 public:
184  FP_LOADER_THREAD( std::shared_ptr<FP_THREAD_IFACE> const& aIface ):
185  wxThread( wxTHREAD_DETACHED ),
186  m_iface( aIface )
187  {}
188 
189 
191  {}
192 
193 
194  void ProcessEntry( CACHE_ENTRY& aEntry )
195  {
196  FP_LIB_TABLE* fptbl = m_iface->GetTable();
197 
198  if( !fptbl )
199  return;
200 
201  aEntry.module = NULL;
202 
203  try {
204  aEntry.module = fptbl->FootprintLoadWithOptionalNickname( aEntry.fpid );
205 
206  if( !aEntry.module )
207  aEntry.status = FPS_NOT_FOUND;
208 
209  } catch( const IO_ERROR& )
210  {
211  aEntry.status = FPS_NOT_FOUND;
212  }
213 
214 
215  if( aEntry.status != FPS_NOT_FOUND )
216  aEntry.status = FPS_READY;
217 
218  m_iface->AddToCache( aEntry );
219 
220  if( aEntry.fpid == m_iface->GetCurrentFootprint() )
221  {
222  wxCommandEvent evt( wxEVT_COMMAND_TEXT_UPDATED, 1 );
223  m_iface->QueueEvent( evt );
224  }
225  }
226 
227 
228  virtual void* Entry() override
229  {
230  while( m_iface->GetPanel() )
231  {
232  auto ent = m_iface->PopFromQueue();
233 
234  if( ent )
235  ProcessEntry( *ent );
236  else
237  wxMilliSleep( 100 );
238  }
239 
240  return nullptr;
241  }
242 };
243 
244 
246  KIWAY* aKiway, wxWindow* aParent, KIGFX::GAL_DISPLAY_OPTIONS& aOpts, GAL_TYPE aGalType )
247  : PCB_DRAW_PANEL_GAL ( aParent, -1, wxPoint( 0, 0 ), wxSize(200, 200), aOpts, aGalType ),
248  KIWAY_HOLDER( aKiway ),
249  m_footprintDisplayed( true )
250 {
251 
252  m_iface = std::make_shared<FP_THREAD_IFACE>();
253  m_iface->SetPanel( this );
255  m_loader->Run();
256 
257  SetStealsFocus( false );
258  ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER );
259  EnableScrolling( false, false ); // otherwise Zoom Auto disables GAL canvas
260 
261  m_dummyBoard = std::make_unique<BOARD>();
262  m_colorsSettings = std::make_unique<COLORS_DESIGN_SETTINGS>();
263 
264  UseColorScheme( m_colorsSettings.get() );
266 
267  Raise();
268  Show(true);
269  StartDrawing();
270 
271  Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( FOOTPRINT_PREVIEW_PANEL::OnLoaderThreadUpdate ), NULL, this );
272 }
273 
274 
276 {
277  m_iface->SetPanel( nullptr );
278 }
279 
280 
282 {
283  auto opt_ent = m_iface->GetFromCache( aFPID );
284 
285  if( opt_ent )
286  return *opt_ent;
287  else
288  return m_iface->AddToQueue( aFPID );
289 }
290 
291 
292 // This is separate to avoid having to export CACHE_ENTRY to the global namespace
294 {
295  (void) CacheAndReturn( aFPID );
296 }
297 
298 
300 {
301  GetView()->Clear();
302  module->SetParent ( &*m_dummyBoard );
303  module->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, GetView(), _1, -1 ) );
304 
305  GetView()->Add ( module );
306 
307  GetView()->SetVisible( module, true );
308  GetView()->Update( module, KIGFX::ALL );
309 
310  BOX2I bbox = module->ViewBBox();
311  bbox.Merge ( module->Value().ViewBBox() );
312  bbox.Merge ( module->Reference().ViewBBox() );
313 
314  if( bbox.GetSize().x > 0 && bbox.GetSize().y > 0 )
315  {
316  // Autozoom
317  GetView()->SetViewport( BOX2D( bbox.GetOrigin(), bbox.GetSize() ) );
318 
319  // Add a margin
320  GetView()->SetScale( GetView()->GetScale() * 0.7 );
321 
322  Refresh();
323  }
324 }
325 
326 
328 {
329  m_currentFPID = aFPID;
330  m_iface->SetCurrentFootprint( aFPID );
331  m_footprintDisplayed = false;
332 
334 
335  if( m_handler )
336  m_handler( fpe.status );
337 
338  if( fpe.status == FPS_READY )
339  {
340  if ( !m_footprintDisplayed )
341  {
342  renderFootprint( fpe.module );
343  m_footprintDisplayed = true;
344  Refresh();
345  }
346  }
347 }
348 
349 
351 {
353 }
354 
355 
357 {
358  m_handler = aHandler;
359 }
360 
361 
363 {
364  return static_cast<wxWindow*>( this );
365 }
366 
367 
369 {
371 
372  return new FOOTPRINT_PREVIEW_PANEL(
373  aKiway, aParent, gal_opts, EDA_DRAW_PANEL_GAL::GAL_TYPE_CAIRO );
374 }
const Vec & GetOrigin() const
Definition: box2.h:181
Class KIWAY_HOLDER is a mix in class which holds the location of a wxWindow's KIWAY.
Definition: kiway_player.h:48
LIB_ID fpid
Footprint loader thread to prevent footprint loading from locking the UI.
void RunOnChildren(std::function< void(BOARD_ITEM *)> aFunction)
Function RunOnChildren.
bool QueueEvent(wxEvent const &aEvent)
Post an event to the panel, if the panel still exists.
TEXTE_MODULE & Reference()
Definition: class_module.h:463
FOOTPRINT_STATUS status
void SetViewport(const BOX2D &aViewport)
Function SetViewport() Sets the visible area of the VIEW.
Definition: view.cpp:513
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:469
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
virtual void * Entry() override
LIB_ID GetCurrentFootprint()
Threadsafe accessor to get the current footprint.
KIGFX::VIEW * GetView() const
Function GetView() Returns a pointer to the VIEW instance used in the panel.
void ProcessEntry(CACHE_ENTRY &aEntry)
Class LIB_ID.
Definition: lib_id.h:56
Layers have changed.
Definition: view_item.h:59
const Vec & GetSize() const
Definition: box2.h:177
void SetScale(double aScale)
Function SetScale() Sets the scaling factor.
Definition: view.h:247
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.
FOOTPRINT_PREVIEW_PANEL * GetPanel()
Get the associated panel.
virtual wxWindow * GetWindow() override
Get the underlying wxWindow.
std::unique_ptr< BOARD > m_dummyBoard
Threadsafe interface class between loader thread and panel class.
void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:213
void Clear()
Function Clear() Removes all items from the view.
Definition: view.cpp:982
TEXTE_MODULE & Value()
read/write accessors:
Definition: class_module.h:462
void AddToCache(CACHE_ENTRY const &aEntry)
Add an entry to the cache.
boost::optional< CACHE_ENTRY > GetFromCache(LIB_ID const &aFPID)
Retrieve a cache entry by LIB_ID.
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 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:257
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:350
void SyncLayersVisibility(const BOARD *aBoard)
Function SyncLayersVisibility Updates "visibility" property of each layer of a given BOARD...
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:1389
void SetCurrentFootprint(LIB_ID aFp)
Threadsafe accessor to set the current footprint.
void StartDrawing()
Function StartDrawing() Begins drawing if it was stopped previously.
void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
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.
boost::interprocess::scoped_lock< MUTEX > MUTLOCK
Definition: ki_mutex.h:43
FP_LOADER_THREAD(std::shared_ptr< FP_THREAD_IFACE > const &aIface)
void SetPanel(FOOTPRINT_PREVIEW_PANEL *aPanel)
Set the associated panel, for QueueEvent() and GetTable().
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)
boost::optional< CACHE_ENTRY > PopFromQueue()
Pop an entry from the queue, or empty option if none is available.
FOOTPRINT_STATUS_HANDLER m_handler
MODULE * module
std::shared_ptr< FP_THREAD_IFACE > m_iface
std::deque< CACHE_ENTRY > m_loaderQueue
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Sets the item visibility.
Definition: view.cpp:1335
MODULE * FootprintLoadWithOptionalNickname(const LIB_ID &aFootprintId)
Function FootprintLoadWithOptionalNickname loads a footprint having aFootprintId with possibly an emp...
void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Function Add() Adds a VIEW_ITEM to the view.
Definition: view.cpp:311
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:47
Handle colors used to draw all items or layers.
FOOTPRINT_PREVIEW_PANEL * m_panel
std::function< void(FOOTPRINT_STATUS)> FOOTPRINT_STATUS_HANDLER