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 <utility>
36 #include <make_unique.h>
37 #include <colors_design_settings.h>
38 
39 #include <wx/stattext.h>
40 
41 
46 {
48 
49  public:
52  {
53  MUTLOCK lock( m_lock );
54  auto it = m_cachedFootprints.find( aFPID );
55 
56  if( it != m_cachedFootprints.end() )
57  return it->second;
58  else
59  return NULLOPT;
60  }
61 
66  CACHE_ENTRY AddToQueue( LIB_ID const & aEntry )
67  {
68  MUTLOCK lock( m_lock );
69 
70  CACHE_ENTRY ent = { aEntry, NULL, FPS_LOADING };
71  m_cachedFootprints[aEntry] = ent;
72  m_loaderQueue.push_back( ent );
73 
74  return ent;
75  }
76 
79  {
80  MUTLOCK lock( m_lock );
81 
82  if( m_loaderQueue.empty() )
83  {
84  return NULLOPT;
85  }
86  else
87  {
88  auto ent = m_loaderQueue.front();
89  m_loaderQueue.pop_front();
90  return ent;
91  }
92  }
93 
95  void AddToCache( CACHE_ENTRY const & aEntry )
96  {
97  MUTLOCK lock( m_lock );
98  m_cachedFootprints[aEntry.fpid] = aEntry;
99  }
100 
105  {
106  MUTLOCK lock( m_lock );
107  m_current_fp = std::move( aFp );
108  }
109 
114  {
115  MUTLOCK lock( m_lock );
116  return m_current_fp;
117  }
118 
123  {
124  MUTLOCK lock( m_lock );
125  m_panel = aPanel;
126  }
127 
132  {
133  MUTLOCK lock( m_lock );
134  return m_panel;
135  }
136 
141  bool QueueEvent( wxEvent const& aEvent )
142  {
143  MUTLOCK lock( m_lock );
144 
145  if( m_panel )
146  {
147  m_panel->GetEventHandler()->QueueEvent( aEvent.Clone() );
148  return true;
149  }
150  else
151  {
152  return false;
153  }
154  }
155 
160  {
161  MUTLOCK locK( m_lock );
162  return m_panel ? m_panel->Prj().PcbFootprintLibs() : nullptr;
163  }
164 
165  private:
166  std::deque<CACHE_ENTRY> m_loaderQueue;
167  std::map<LIB_ID, CACHE_ENTRY> m_cachedFootprints;
171 };
172 
173 
178 class FP_LOADER_THREAD: public wxThread
179 {
181 
182  std::shared_ptr<FP_THREAD_IFACE> m_iface;
183 
184 public:
185  FP_LOADER_THREAD( std::shared_ptr<FP_THREAD_IFACE> const& aIface ):
186  wxThread( wxTHREAD_DETACHED ),
187  m_iface( aIface )
188  {}
189 
190 
192  {}
193 
194 
195  void ProcessEntry( CACHE_ENTRY& aEntry )
196  {
197  FP_LIB_TABLE* fptbl = m_iface->GetTable();
198 
199  if( !fptbl )
200  return;
201 
202  aEntry.module = NULL;
203 
204  try {
205  aEntry.module = fptbl->FootprintLoadWithOptionalNickname( aEntry.fpid );
206 
207  if( !aEntry.module )
208  aEntry.status = FPS_NOT_FOUND;
209 
210  } catch( const IO_ERROR& )
211  {
212  aEntry.status = FPS_NOT_FOUND;
213  }
214 
215 
216  if( aEntry.status != FPS_NOT_FOUND )
217  aEntry.status = FPS_READY;
218 
219  m_iface->AddToCache( aEntry );
220 
221  if( aEntry.fpid == m_iface->GetCurrentFootprint() )
222  {
223  wxCommandEvent evt( wxEVT_COMMAND_TEXT_UPDATED, 1 );
224  m_iface->QueueEvent( evt );
225  }
226  }
227 
228 
229  virtual void* Entry() override
230  {
231  while( m_iface->GetPanel() )
232  {
233  auto ent = m_iface->PopFromQueue();
234 
235  if( ent )
236  ProcessEntry( *ent );
237  else
238  wxMilliSleep( 100 );
239  }
240 
241  return nullptr;
242  }
243 };
244 
245 
247  KIWAY* aKiway, wxWindow* aParent, KIGFX::GAL_DISPLAY_OPTIONS& aOpts, GAL_TYPE aGalType )
248  : PCB_DRAW_PANEL_GAL ( aParent, -1, wxPoint( 0, 0 ), wxSize(200, 200), aOpts, aGalType ),
249  KIWAY_HOLDER( aKiway ),
250  m_footprintDisplayed( true )
251 {
252 
253  m_iface = std::make_shared<FP_THREAD_IFACE>();
254  m_iface->SetPanel( this );
256  m_loader->Run();
257 
258  SetStealsFocus( false );
259  ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER );
260  EnableScrolling( false, false ); // otherwise Zoom Auto disables GAL canvas
261 
262  m_dummyBoard = std::make_unique<BOARD>();
263  m_colorsSettings = std::make_unique<COLORS_DESIGN_SETTINGS>( FRAME_PCB_FOOTPRINT_PREVIEW );
264 
265  UseColorScheme( m_colorsSettings.get() );
267 
268  Raise();
269  Show(true);
270  StartDrawing();
271 
272  Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( FOOTPRINT_PREVIEW_PANEL::OnLoaderThreadUpdate ), NULL, this );
273 }
274 
275 
277 {
278  m_iface->SetPanel( nullptr );
279 }
280 
281 
283 {
284  auto opt_ent = m_iface->GetFromCache( aFPID );
285 
286  if( opt_ent )
287  return *opt_ent;
288  else
289  return m_iface->AddToQueue( aFPID );
290 }
291 
292 
293 // This is separate to avoid having to export CACHE_ENTRY to the global namespace
295 {
296  (void) CacheAndReturn( aFPID );
297 }
298 
299 
301 {
302  GetView()->Clear();
303  module->SetParent ( &*m_dummyBoard );
304 
305  GetView()->Add ( module );
306  GetView()->SetVisible( module, true );
307  GetView()->Update( module, KIGFX::ALL );
308 
309  BOX2I bbox = module->ViewBBox();
310  bbox.Merge ( module->Value().ViewBBox() );
311  bbox.Merge ( module->Reference().ViewBBox() );
312 
313  if( bbox.GetSize().x > 0 && bbox.GetSize().y > 0 )
314  {
315  // Autozoom
316  GetView()->SetViewport( BOX2D( bbox.GetOrigin(), bbox.GetSize() ) );
317 
318  // Add a margin
319  GetView()->SetScale( GetView()->GetScale() * 0.7 );
320 
321  Refresh();
322  }
323 }
324 
325 
327 {
328  m_currentFPID = aFPID;
329  m_iface->SetCurrentFootprint( aFPID );
330  m_footprintDisplayed = false;
331 
333 
334  if( m_handler )
335  m_handler( fpe.status );
336 
337  if( fpe.status == FPS_READY )
338  {
339  if ( !m_footprintDisplayed )
340  {
341  renderFootprint( fpe.module );
342  m_footprintDisplayed = true;
343  Refresh();
344  }
345  }
346 }
347 
348 
350 {
352 }
353 
354 
356 {
357  m_handler = aHandler;
358 }
359 
360 
362 {
363  return static_cast<wxWindow*>( this );
364 }
365 
366 
368 {
370 
371  return new FOOTPRINT_PREVIEW_PANEL(
372  aKiway, aParent, gal_opts, EDA_DRAW_PANEL_GAL::GAL_TYPE_CAIRO );
373 }
const Vec & GetOrigin() const
Definition: box2.h:181
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:502
FOOTPRINT_STATUS status
void SetViewport(const BOX2D &aViewport)
Function SetViewport() Sets the visible area of the VIEW.
Definition: view.cpp:536
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: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.
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: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.
const auto NULLOPT
Definition: optional.h:9
std::unique_ptr< BOARD > m_dummyBoard
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:224
void Clear()
Function Clear() Removes all items from the view.
Definition: view.cpp:1051
TEXTE_MODULE & Value()
read/write accessors:
Definition: class_module.h:501
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 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
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...
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:1499
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
Update the board display after modifying it bu 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.
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)
FOOTPRINT_STATUS_HANDLER m_handler
MODULE * module
std::shared_ptr< FP_THREAD_IFACE > m_iface
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:1445
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:334
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
FOOTPRINT_PREVIEW_PANEL * m_panel
std::function< void(FOOTPRINT_STATUS)> FOOTPRINT_STATUS_HANDLER