KiCad PCB EDA Suite
kiway.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) 2014 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
5  * Copyright (C) 2014-2021 KiCad Developers, see CHANGELOG.TXT for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <cstring>
26 
27 #include <macros.h>
28 #include <kiway.h>
29 #include <kiway_player.h>
30 #include <kiway_express.h>
31 #include <pgm_base.h>
32 #include <config.h>
33 #include <core/arraydim.h>
34 #include <id.h>
35 #include <kiplatform/app.h>
37 #include <logging.h>
38 
39 #include <wx/dynlib.h>
40 #include <wx/stdpaths.h>
41 #include <wx/debug.h>
42 #include <wx/utils.h>
43 #include <confirm.h>
44 
45 KIFACE* KIWAY::m_kiface[KIWAY_FACE_COUNT];
46 int KIWAY::m_kiface_version[KIWAY_FACE_COUNT];
47 
48 
49 
50 KIWAY::KIWAY( PGM_BASE* aProgram, int aCtlBits, wxFrame* aTop ):
51  m_program( aProgram ), m_ctl( aCtlBits ), m_top( nullptr )
52 {
53  SetTop( aTop ); // hook player_destroy_handler() into aTop.
54 
55  // Set the array of all known frame window IDs to empty = wxID_NONE,
56  // once they are be created, they are added with FRAME_T as index to this array.
57  // Note: A non empty entry does not mean the frame still exists.
58  // It means only the frame was created at least once. It can be destroyed after.
59  // These entries are not cleared automatically on window closing. The purpose is just
60  // to allow a call to wxWindow::FindWindowById() using a FRAME_T frame type
61  for( int n = 0; n < KIWAY_PLAYER_COUNT; n++ )
62  m_playerFrameId[n] = wxID_NONE;
63 }
64 
65 
66 #if 0
67 // Any event types derived from wxCommandEvt, like wxWindowDestroyEvent, are
68 // propagated upwards to parent windows if not handled below. Therefore the
69 // m_top window should receive all wxWindowDestroyEvents originating from
70 // KIWAY_PLAYERs. It does anyways, but now player_destroy_handler eavesdrops
71 // on that event stream looking for KIWAY_PLAYERs being closed.
72 
73 void KIWAY::player_destroy_handler( wxWindowDestroyEvent& event )
74 {
75  // Currently : do nothing
76  event.Skip(); // skip to who, the wxApp? I'm the top window.
77 }
78 #endif
79 
80 
81 void KIWAY::SetTop( wxFrame* aTop )
82 {
83 #if 0
84  if( m_top )
85  {
86  m_top->Disconnect( wxEVT_DESTROY,
87  wxWindowDestroyEventHandler( KIWAY::player_destroy_handler ),
88  nullptr, this );
89  }
90 
91  if( aTop )
92  {
93  aTop->Connect( wxEVT_DESTROY,
94  wxWindowDestroyEventHandler( KIWAY::player_destroy_handler ),
95  nullptr, this );
96  }
97 #endif
98 
99  m_top = aTop;
100 }
101 
102 
103 const wxString KIWAY::dso_search_path( FACE_T aFaceId )
104 {
105  const char* name;
106 
107  switch( aFaceId )
108  {
109  case FACE_SCH: name = KIFACE_PREFIX "eeschema"; break;
110  case FACE_PCB: name = KIFACE_PREFIX "pcbnew"; break;
111  case FACE_CVPCB: name = KIFACE_PREFIX "cvpcb"; break;
112  case FACE_GERBVIEW: name = KIFACE_PREFIX "gerbview"; break;
113  case FACE_PL_EDITOR: name = KIFACE_PREFIX "pl_editor"; break;
114  case FACE_PCB_CALCULATOR: name = KIFACE_PREFIX "pcb_calculator"; break;
115  case FACE_BMP2CMP: name = KIFACE_PREFIX "bitmap2component"; break;
116  case FACE_PYTHON: name = KIFACE_PREFIX "kipython"; break;
117 
118  default:
119  wxASSERT_MSG( 0, wxT( "caller has a bug, passed a bad aFaceId" ) );
120  return wxEmptyString;
121  }
122 
123 #ifndef __WXMAC__
124  wxString path;
125 
127  {
128  // The 2 *.cpp program launchers: single_top.cpp and kicad.cpp expect
129  // the *.kiface's to reside in same directory as their binaries do.
130  path = wxStandardPaths::Get().GetExecutablePath();
131  }
132 
133  wxFileName fn = path;
134 #else
135  // we have the dso's in main OSX bundle kicad.app/Contents/PlugIns
136  wxFileName fn = Pgm().GetExecutablePath();
137  fn.AppendDir( wxT( "Contents" ) );
138  fn.AppendDir( wxT( "PlugIns" ) );
139 #endif
140 
141  fn.SetName( name );
142 
143  // To speed up development, it's sometimes nice to run kicad from inside
144  // the build path. In that case, each program will be in a subdirectory.
145  // To find the DSOs, we need to go up one directory and then enter a subdirectory.
146 
147  if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
148  {
149 #ifdef __WXMAC__
150  // On Mac, all of the kifaces are placed in the kicad.app bundle, even though the individual
151  // standalone binaries are placed in separate bundles before the make install step runs.
152  // So, we have to jump up to the kicad directory, then the PlugIns section of the kicad
153  // bundle.
154  fn = wxStandardPaths::Get().GetExecutablePath();
155 
156  fn.RemoveLastDir();
157  fn.RemoveLastDir();
158  fn.RemoveLastDir();
159  fn.RemoveLastDir();
160  fn.AppendDir( wxT( "kicad" ) );
161  fn.AppendDir( wxT( "kicad.app" ) );
162  fn.AppendDir( wxT( "Contents" ) );
163  fn.AppendDir( wxT( "PlugIns" ) );
164  fn.SetName( name );
165 #else
166  const char* dirName;
167 
168  // The subdirectories usually have the same name as the kiface
169  switch( aFaceId )
170  {
171  case FACE_PL_EDITOR: dirName = "pagelayout_editor"; break;
172  case FACE_PYTHON: dirName = "scripting"; break;
173  default: dirName = name + 1; break;
174  }
175 
176  fn.RemoveLastDir();
177  fn.AppendDir( dirName );
178 #endif
179  }
180 
181  // Here a "suffix" == an extension with a preceding '.',
182  // so skip the preceding '.' to get an extension
183  fn.SetExt( &KIFACE_SUFFIX[1] );
184 
185  return fn.GetFullPath();
186 }
187 
188 
190 {
191  return Pgm().GetSettingsManager().Prj();
192 }
193 
194 
195 KIFACE* KIWAY::KiFACE( FACE_T aFaceId, bool doLoad )
196 {
197  // Since this will be called from python, cannot assume that code will
198  // not pass a bad aFaceId.
199  if( (unsigned) aFaceId >= arrayDim( m_kiface ) )
200  {
201  // @todo : throw an exception here for python's benefit, at least that
202  // way it gets some explanatory text.
203 
204  wxASSERT_MSG( 0, wxT( "caller has a bug, passed a bad aFaceId" ) );
205  return nullptr;
206  }
207 
208  // return the previously loaded KIFACE, if it was.
209  if( m_kiface[aFaceId] )
210  return m_kiface[aFaceId];
211 
212  wxString msg;
213 
214  // DSO with KIFACE has not been loaded yet, does caller want to load it?
215  if( doLoad )
216  {
217  wxString dname = dso_search_path( aFaceId );
218 
219  // Insert DLL search path for kicad_3dsg from build dir
220  if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
221  {
222  wxFileName myPath = wxStandardPaths::Get().GetExecutablePath();
223 
224  if( !myPath.GetPath().EndsWith( wxT( "pcbnew" ) ) )
225  {
226  myPath.RemoveLastDir();
227  myPath.AppendDir( wxT( "pcbnew" ) );
229  }
230  }
231 
232  wxDynamicLibrary dso;
233 
234  void* addr = nullptr;
235 
236  // For some reason wxDynamicLibrary::Load() crashes in some languages
237  // (chinese for instance) when loading the dynamic library.
238  // The crash happens for Eeschema.
239  // So switch to "C" locale during loading (LC_COLLATE is enough).
240  int lc_new_type = LC_COLLATE;
241  std::string user_locale = setlocale( lc_new_type, nullptr );
242  setlocale( lc_new_type, "C" );
243 
244  bool success = dso.Load( dname, wxDL_VERBATIM | wxDL_NOW | wxDL_GLOBAL );
245 
246  setlocale( lc_new_type, user_locale.c_str() );
247 
248  if( !success )
249  {
250  // Failure: error reporting UI was done via wxLogSysError().
251  // No further reporting required here. Apparently this is not true on all
252  // platforms and/or wxWidgets builds and KiCad will crash. Throwing the exception
253  // here and catching it in the KiCad launcher resolves the crash issue. See bug
254  // report https://bugs.launchpad.net/kicad/+bug/1577786.
255 
256  msg.Printf( _( "Failed to load kiface library '%s'." ), dname );
257  THROW_IO_ERROR( msg );
258  }
259  else if( ( addr = dso.GetSymbol( wxT( KIFACE_INSTANCE_NAME_AND_VERSION ) ) ) == nullptr )
260  {
261  // Failure: error reporting UI was done via wxLogSysError().
262  // No further reporting required here. Assume the same thing applies here as
263  // above with the Load() call. This has not been tested.
264  msg.Printf( _( "Could not read instance name and version from kiface library '%s'." ),
265  dname );
266  THROW_IO_ERROR( msg );
267  }
268  else
269  {
270  KIFACE_GETTER_FUNC* ki_getter = (KIFACE_GETTER_FUNC*) addr;
271 
272  KIFACE* kiface = ki_getter( &m_kiface_version[aFaceId], KIFACE_VERSION, m_program );
273 
274  // KIFACE_GETTER_FUNC function comment (API) says the non-NULL is unconditional.
275  wxASSERT_MSG( kiface,
276  wxT( "attempted DSO has a bug, failed to return a KIFACE*" ) );
277 
278  // Give the DSO a single chance to do its "process level" initialization.
279  // "Process level" specifically means stay away from any projects in there.
280  if( kiface->OnKifaceStart( m_program, m_ctl ) )
281  {
282  // Tell dso's wxDynamicLibrary destructor not to Unload() the program image.
283  (void) dso.Detach();
284 
285  return m_kiface[aFaceId] = kiface;
286  }
287  }
288 
289  // In any of the failure cases above, dso.Unload() should be called here
290  // by dso destructor.
291  // However:
292 
293  // There is a file installation bug. We only look for KIFACE's which we know
294  // to exist, and we did not find one. If we do not find one, this is an
295  // installation bug.
296 
297  msg = wxString::Format( _( "Fatal Installation Bug. File:\n"
298  "'%s'\ncould not be loaded\n" ), dname );
299 
300  if( ! wxFileExists( dname ) )
301  msg << _( "It is missing.\n" );
302  else
303  msg << _( "Perhaps a shared library (.dll or .so) file is missing.\n" );
304 
305  msg << _( "From command line: argv[0]:\n'" );
306  msg << wxStandardPaths::Get().GetExecutablePath() << wxT( "'\n" );
307 
308  // This is a fatal error, one from which we cannot recover, nor do we want
309  // to protect against in client code which would require numerous noisy
310  // tests in numerous places. So we inform the user that the installation
311  // is bad. This exception will likely not get caught until way up in the
312  // wxApp derivative, at which point the process will exit gracefully.
313  THROW_IO_ERROR( msg );
314  }
315 
316  return nullptr;
317 }
318 
319 
321 {
322  switch( aFrameType )
323  {
324  case FRAME_SCH:
326  case FRAME_SCH_VIEWER:
328  case FRAME_SIMULATOR:
329  return FACE_SCH;
330 
331  case FRAME_PCB_EDITOR:
336  case FRAME_PCB_DISPLAY3D:
337  return FACE_PCB;
338 
339  case FRAME_CVPCB:
340  case FRAME_CVPCB_DISPLAY:
341  return FACE_CVPCB;
342 
343  case FRAME_PYTHON:
344  return FACE_PYTHON;
345 
346  case FRAME_GERBER:
347  return FACE_GERBVIEW;
348 
349  case FRAME_PL_EDITOR:
350  return FACE_PL_EDITOR;
351 
352  case FRAME_CALC:
353  return FACE_PCB_CALCULATOR;
354 
355  case FRAME_BM2CMP:
356  return FACE_BMP2CMP;
357 
358  default:
359  return FACE_T( -1 );
360  }
361 }
362 
363 
365 {
366  wxWindowID storedId = m_playerFrameId[aFrameType];
367 
368  if( storedId == wxID_NONE )
369  return nullptr;
370 
371  wxWindow* frame = wxWindow::FindWindowById( storedId );
372 
373  // Since wxWindow::FindWindow*() is not cheap (especially if the window does not exist),
374  // clear invalid entries to save CPU on repeated calls that do not lead to frame creation
375  if( !frame )
376  m_playerFrameId[aFrameType].compare_exchange_strong( storedId, wxID_NONE );
377 
378  return static_cast<KIWAY_PLAYER*>( frame );
379 }
380 
381 
382 KIWAY_PLAYER* KIWAY::Player( FRAME_T aFrameType, bool doCreate, wxTopLevelWindow* aParent )
383 {
384  // Since this will be called from python, cannot assume that code will
385  // not pass a bad aFrameType.
386  if( (unsigned) aFrameType >= KIWAY_PLAYER_COUNT )
387  {
388  // @todo : throw an exception here for python's benefit, at least that
389  // way it gets some explanatory text.
390 
391  wxASSERT_MSG( 0, wxT( "caller has a bug, passed a bad aFrameType" ) );
392  return nullptr;
393  }
394 
395  // return the previously opened window
396  KIWAY_PLAYER* frame = GetPlayerFrame( aFrameType );
397 
398  if( frame )
399  return frame;
400 
401  if( doCreate )
402  {
403  try
404  {
405  FACE_T face_type = KifaceType( aFrameType );
406  KIFACE* kiface = KiFACE( face_type );
407 
408  frame = (KIWAY_PLAYER*) kiface->CreateWindow(
409  aParent, // Parent window of frame in modal mode,
410  // NULL in non modal mode
411  aFrameType,
412  this,
413  m_ctl // questionable need, these same flags
414  // were passed to KIFACE::OnKifaceStart()
415  );
416 
417  m_playerFrameId[aFrameType].store( frame->GetId() );
418  return frame;
419  }
420  catch( const IO_ERROR& ioe )
421  {
422  DisplayErrorMessage( nullptr, _( "Error loading editor." ), ioe.What() );
423  }
424  catch( const std::exception& e)
425  {
426  DisplayErrorMessage( nullptr, _( "Error loading editor." ), e.what() );
427  }
428  catch( ... )
429  {
430  DisplayErrorMessage( nullptr, _( "Error loading editor." ) );
431  }
432  }
433 
434  return nullptr;
435 }
436 
437 
438 bool KIWAY::PlayerClose( FRAME_T aFrameType, bool doForce )
439 {
440  // Since this will be called from python, cannot assume that code will
441  // not pass a bad aFrameType.
442  if( (unsigned) aFrameType >= KIWAY_PLAYER_COUNT )
443  {
444  // @todo : throw an exception here for python's benefit, at least that
445  // way it gets some explanatory text.
446 
447  wxASSERT_MSG( 0, wxT( "caller has a bug, passed a bad aFrameType" ) );
448  return false;
449  }
450 
451  KIWAY_PLAYER* frame = GetPlayerFrame( aFrameType );
452 
453  if( frame == nullptr ) // Already closed
454  return true;
455 
456  if( frame->NonUserClose( doForce ) )
457  return true;
458 
459  return false;
460 }
461 
462 
463 bool KIWAY::PlayersClose( bool doForce )
464 {
465  bool ret = true;
466 
467  for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
468  {
469  ret = ret && PlayerClose( FRAME_T( i ), doForce );
470  }
471 
472  return ret;
473 }
474 
475 
476 void KIWAY::ExpressMail( FRAME_T aDestination, MAIL_T aCommand, std::string& aPayload,
477  wxWindow* aSource )
478 {
479  KIWAY_EXPRESS mail( aDestination, aCommand, aPayload, aSource );
480 
481  ProcessEvent( mail );
482 }
483 
484 
485 void KIWAY::SetLanguage( int aLanguage )
486 {
487  wxString errMsg;
488  bool ret = false;
489 
490  {
491  // Only allow the traces to be logged by wx. We use our own system to log when the
492  // OS doesn't support the language, so we want to hide the wx error.
493  WX_LOG_TRACE_ONLY logtraceOnly;
494  Pgm().SetLanguageIdentifier( aLanguage );
495  ret = Pgm().SetLanguage( errMsg );
496  }
497 
498  if( !ret )
499  {
500  wxString lang;
501 
502  for( unsigned ii = 0; LanguagesList[ii].m_KI_Lang_Identifier != 0; ii++ )
503  {
504  if( aLanguage == LanguagesList[ii].m_KI_Lang_Identifier )
505  {
506  if( LanguagesList[ii].m_DoNotTranslate )
507  lang = LanguagesList[ii].m_Lang_Label;
508  else
509  lang = wxGetTranslation( LanguagesList[ii].m_Lang_Label );
510 
511  break;
512  }
513  }
514 
515  DisplayErrorMessage( nullptr,
516  wxString::Format( _( "Unable to switch language to %s" ), lang ),
517  errMsg );
518  return;
519  }
520 
521 #if 1
522  // This is a risky hack that goes away if we allow the language to be
523  // set only from the top most frame if !Kiface.IsSingle()
524 
525  // Only for the C++ project manager, and not for the python one and not for
526  // single_top do we look for the EDA_BASE_FRAME as the top level window.
527  // For single_top this is not needed because that window is registered in
528  // the array below.
530  {
531  // A dynamic_cast could be better, but creates link issues
532  // (some basic_frame functions not found) on some platforms,
533  // so a static_cast is used.
534  EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
535 
536  if( top )
537  top->ShowChangedLanguage();
538  }
539 #endif
540 
541  for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
542  {
543  KIWAY_PLAYER* frame = GetPlayerFrame( ( FRAME_T )i );
544 
545  if( frame )
546  {
547  frame->ShowChangedLanguage();
548  }
549  }
550 }
551 
552 
553 void KIWAY::CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVarsChanged )
554 {
556  {
557  // A dynamic_cast could be better, but creates link issues
558  // (some basic_frame functions not found) on some platforms,
559  // so a static_cast is used.
560  EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
561 
562  if( top )
563  top->CommonSettingsChanged( aEnvVarsChanged, aTextVarsChanged );
564  }
565 
566  for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
567  {
568  KIWAY_PLAYER* frame = GetPlayerFrame( ( FRAME_T )i );
569 
570  if( frame )
571  frame->CommonSettingsChanged( aEnvVarsChanged, aTextVarsChanged );
572  }
573 }
574 
575 
577 {
579  {
580  // A dynamic_cast could be better, but creates link issues
581  // (some basic_frame functions not found) on some platforms,
582  // so a static_cast is used.
583  EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
584 
585  if( top )
586  top->ProjectChanged();
587  }
588 
589  for( unsigned i=0; i < KIWAY_PLAYER_COUNT; ++i )
590  {
591  KIWAY_PLAYER* frame = GetPlayerFrame( ( FRAME_T )i );
592 
593  if( frame )
594  frame->ProjectChanged();
595  }
596 }
597 
598 
599 bool KIWAY::ProcessEvent( wxEvent& aEvent )
600 {
601  KIWAY_EXPRESS* mail = dynamic_cast<KIWAY_EXPRESS*>( &aEvent );
602 
603  if( mail )
604  {
605  FRAME_T dest = mail->Dest();
606 
607  // see if recipient is alive
608  KIWAY_PLAYER* alive = Player( dest, false );
609 
610  if( alive )
611  {
612 #if 1
613  return alive->ProcessEvent( aEvent );
614 #else
615  alive->KiwayMailIn( *mail );
616  return true;
617 #endif
618  }
619  }
620 
621  return false;
622 }
623 
624 
626 {
628  {
629  // A dynamic_cast could be better, but creates link issues
630  // (some basic_frame functions not found) on some platforms,
631  // so a static_cast is used.
632  EDA_BASE_FRAME* top = static_cast<EDA_BASE_FRAME*>( m_top );
633 
634  if( top )
635  top->Close( false );
636  }
637 }
638 
639 
641 {
642  for( KIFACE* i : m_kiface )
643  {
644  if( i )
645  i->OnKifaceEnd();
646  }
647 }
#define KFCTL_CPP_PROJECT_SUITE
Running under C++ project mgr, possibly with others.
Definition: kiway.h:157
LANGUAGE_DESCR LanguagesList[]
An array containing all the languages that KiCad supports.
Definition: pgm_base.cpp:70
BITMAP2CMP_SETTINGS kiface
virtual bool PlayersClose(bool doForce)
Call the KIWAY_PLAYER::Close( bool force ) function on all the windows and if none are vetoed,...
Definition: kiway.cpp:463
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
Definition: kiway_player.h:64
Carry a payload from one KIWAY_PLAYER to another within a PROJECT.
Definition: kiway_express.h:38
void OnKiCadExit()
Definition: kiway.cpp:625
std::atomic< wxWindowID > m_playerFrameId[KIWAY_PLAYER_COUNT]
Definition: kiway.h:435
Container for project specific data.
Definition: project.h:62
static FACE_T KifaceType(FRAME_T aFrameType)
A simple mapping function which returns the FACE_T which is known to implement aFrameType.
Definition: kiway.cpp:320
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:284
void ShowChangedLanguage() override
Redraw the menus and what not in current language.
KIWAY_PLAYER * GetPlayerFrame(FRAME_T aFrameType)
Definition: kiway.cpp:364
This file is part of the common library.
Container for data for KiCad programs.
Definition: pgm_base.h:93
#define KIFACE_VERSION
The KIWAY and KIFACE classes are used to communicate between various process modules,...
Definition: kiway.h:109
FRAME_T
The set of EDA_BASE_FRAME derivatives, typically stored in EDA_BASE_FRAME::m_Ident.
Definition: frame_type.h:32
virtual PROJECT & Prj() const
Return the PROJECT associated with this KIWAY.
Definition: kiway.cpp:189
int m_KI_Lang_Identifier
KiCad identifier used in menu selection (See id.h)
Definition: pgm_base.h:65
PGM_BASE * m_program
Definition: kiway.h:424
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:382
virtual void ExpressMail(FRAME_T aDestination, MAIL_T aCommand, std::string &aPayload, wxWindow *aSource=nullptr)
Send aPayload to aDestination from aSource.
Definition: kiway.cpp:476
virtual void SetLanguage(int aLanguage)
Change the language and then calls ShowChangedLanguage() on all #KIWAY_PLAYERs.
Definition: kiway.cpp:485
void OnKiwayEnd()
Definition: kiway.cpp:640
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
void AddDynamicLibrarySearchPath(const wxString &aPath)
Inserts a search path for loading dynamic libraries.
Definition: gtk/app.cpp:93
#define KIFACE_INSTANCE_NAME_AND_VERSION
Definition: kiway.h:114
This file contains miscellaneous commonly used macros and functions.
MAIL_T
The set of mail types sendable via KIWAY::ExpressMail() and supplied as the aCommand parameter to tha...
Definition: mail_type.h:37
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
bool NonUserClose(bool aForce)
virtual bool PlayerClose(FRAME_T aFrameType, bool doForce)
Call the KIWAY_PLAYER::Close( bool force ) function on the window and if not vetoed,...
Definition: kiway.cpp:438
bool ProcessEvent(wxEvent &aEvent) override
Definition: kiway.cpp:599
KIFACE * KIFACE_GETTER_FUNC(int *aKIFACEversion, int aKIWAYversion, PGM_BASE *aProgram)
Point to the one and only KIFACE export.
Definition: kiway.h:458
virtual void ProjectChanged()
Calls ProjectChanged() on all KIWAY_PLAYERs.
Definition: kiway.cpp:576
int m_ctl
Definition: kiway.h:425
virtual void KiwayMailIn(KIWAY_EXPRESS &aEvent)
Receive KIWAY_EXPRESS messages from other players.
#define _(s)
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
pcbnew DSO
Definition: kiway.h:269
const wxString dso_search_path(FACE_T aFaceId)
Get the [path &] name of the DSO holding the requested FACE_T.
Definition: kiway.cpp:103
virtual KIFACE * KiFACE(FACE_T aFaceId, bool doLoad=true)
Return the KIFACE* given a FACE_T.
Definition: kiway.cpp:195
wxString m_Lang_Label
Labels used in menus.
Definition: pgm_base.h:68
void SetTop(wxFrame *aTop)
Tell this KIWAY about the top most frame in the program and optionally allows it to play the role of ...
Definition: kiway.cpp:81
A logger class that filters out all log messages that are not generated by wxLogTrace and ignores the...
Definition: logging.h:31
FACE_T
Known KIFACE implementations.
Definition: kiway.h:266
eeschema DSO
Definition: kiway.h:268
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
void CommonSettingsChanged(bool aEnvVarsChanged, bool aTextVarsChanged) override
Notification event that some of the common (suite-wide) settings have changed.
FRAME_T Dest()
Return the destination player id of the message.
Definition: kiway_express.h:44
see class PGM_BASE
const char * name
Definition: DXF_plotter.cpp:56
The base frame for deriving all KiCad main window classes.
Implement a participant in the KIWAY alchemy.
Definition: kiway.h:148
KIWAY(PGM_BASE *aProgram, int aCtlBits, wxFrame *aTop=nullptr)
Definition: kiway.cpp:50
static int m_kiface_version[KIWAY_FACE_COUNT]
Definition: kiway.h:422
virtual void ProjectChanged()
Notification event that the project has changed.
virtual void CommonSettingsChanged(bool aEnvVarsChanged, bool aTextVarsChanged)
Call CommonSettingsChanged() on all KIWAY_PLAYERs.
Definition: kiway.cpp:553
wxFrame * m_top
Definition: kiway.h:427
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:75
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
bool ProcessEvent(wxEvent &aEvent) override
Override the default process event handler to implement the auto save feature.
int PGM_BASE * aProgram
Definition: cvpcb.cpp:110
static KIFACE * m_kiface[KIWAY_FACE_COUNT]
Definition: kiway.h:421
#define KFCTL_STANDALONE
Running as a standalone Top.
Definition: kiway.h:156