KiCad PCB EDA Suite
kiway.h
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) 2016 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 #ifndef KIWAY_H_
26 #define KIWAY_H_
27 
28 /*
29 
30 The KIWAY and KIFACE classes are used to communicate between various process
31 modules, all residing within a single process. The program modules are either
32 top level like an *.exe or subsidiary like a *.dll. In much of the documentation
33 the term DSO is used to refer to the *.dll portions, that is the term used on
34 linux. But it should be taken to mean DLL on Windows.
35 
36 <p>These are a couple of reasons why this design was chosen:
37 
38 <ol>
39 
40 <li>By using DSOs within a single process, it is not necessary to use IPC.
41 The DSOs can send wxEvents between themselves using wxEvtHandler interfaces in
42 a platform independent way. There can also be function calls from one DSO to
43 another.</li>
44 
45 <li>The use of a number of separately linked DSOs closely resembles the original
46 KiCad program design, consisting of Eeschema and Pcbnew. But it also allows
47 separate compilation and linking of those two DSOs without a ton of inter-DSO
48 dependencies and common data structures. Linking smaller, purpose specific DSOs
49 is thought to be better for maintenance simplicity than a large single link
50 image. </li>
51 
52 <li>By keeping the core functionality in DSOs rather than EXE tops, it becomes
53 possible to re-use the DSOs under different program tops. For example, a DSO
54 named _pcbnew.so can be used under a C++ top or under a python top. Only one
55 CMake target must be defined to build either. Whether that is a separate build
56 or not is not the important thing. Simply having a single CMake target has
57 advantages. (Each builder person will have his/her own intentions relative to
58 use of python or not.) Once a DSO is python capable, it can be driven by any
59 number of python program tops, including demo-ing (automation) and testing
60 separately.</li>
61 
62 
63 </ol>
64 
65 All KiCad source code is UTF8 encoded by law, so make sure your editor is set
66 as such! As such, it is OK to use UTF8 characters:
67 
68 ┏ ┗ ┓ ┛ ━ ┃
69 
70 <pre>
71 
72  ┏━━━process top━━━━━┓
73  ┃ ┃ wxEvent channels
74  ┏━━━━━━━━━━━━━━━━━━━-━[KIWAY project 1]━-━━━━━━━━━━━━━━━━━━━━━━┓
75  ┃ ┃ ┃ ┃
76  ┃ ┏━━━━━━━━━━━━━-━[KIWAY project 2]━-━━━━━━━━━━┓ ┃
77  ┃ ┃ ┃ ┃ ┃ ┃
78  ┃ ┃ ┏━-━[KIWAY project 3]━-━┓ ┃ ┃
79  ┃ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━┛ ┃ ┃ ┃
80  ┃ ┃ ┃ ┃ ┃ ┃
81  ┃ ┃ ┃ ┃ ┃ ┃
82 ┏━━━━━━━━|━━━━━|━━━━━━━━━━━|━━━━━━━━━┓ ┏━━━━━━━━|━━━━━━━━|━━━━━━━━━━━|━━━━━┓
83 ┃ KIFACE ┃ ┃ ┃ ┃ ┃ KIFACE ┃ ┃ ┃ ┃
84 ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃
85 ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃
86 ┃┏━━━━━━━+━┓ ┏━+━━━━━━━┓ ┏━+━━━━━━━┓ ┃ ┃┏━━━━━━━+━┓ ┏━━━━+━━━━┓ ┏━━━━+━━━━┓┃
87 ┃┃wxFrame ┃ ┃wxFrame ┃ ┃wxFrame ┃ ┃ ┃┃wxFrame ┃ ┃wxFrame ┃ ┃wxFrame ┃┃
88 ┃┃project 1┃ ┃project 2┃ ┃project 3┃ ┃ ┃┃project 3┃ ┃project 2┃ ┃project 1┃┃
89 ┃┗━━━━━━━━━┛ ┗━━━━━━━━━┛ ┗━━━━━━━━━┛ ┃ ┃┗━━━━━━━━━┛ ┗━━━━━━━━━┛ ┗━━━━━━━━━┛┃
90 ┃ ┃ ┃ ┃
91 ┃ ┃ ┃ ┃
92 ┗━━━━━━ eeschema DSO ━━━━━━━━━━━━━━━━┛ ┗━━━━━━ pcbnew DSO ━━━━━━━━━━━━━━━━━┛
93 
94 </pre>
95 
96 */
97 
98 
99 #include <wx/event.h>
100 #include <wx/dynlib.h>
101 #include <import_export.h>
102 #include <search_stack.h>
103 #include <project.h>
104 #include <frame_type.h>
105 #include <mail_type.h>
106 #include <ki_exception.h>
107 
108 
109 #define VTBL_ENTRY virtual
110 
111 #define KIFACE_VERSION 1
112 #define KIFACE_GETTER KIFACE_1
113 
114 // The KIFACE acquistion function is declared extern "C" so its name should not
115 // be mangled.
116 #define KIFACE_INSTANCE_NAME_AND_VERSION "KIFACE_1"
117 
118 #ifndef SWIG
119 #if defined(__linux__) || defined(__FreeBSD__)
120  #define LIB_ENV_VAR wxT( "LD_LIBRARY_PATH" )
121 #elif defined(__WXMAC__)
122  #define LIB_ENV_VAR wxT( "DYLD_LIBRARY_PATH" )
123 #elif defined(_WIN32)
124  #define LIB_ENV_VAR wxT( "PATH" )
125 #else
126  #error Platform support missing
127 #endif
128 #endif // SWIG
129 
130 class wxConfigBase;
131 class wxWindow;
132 class PGM_BASE;
133 class KIWAY;
134 class KIWAY_PLAYER;
135 class wxTopLevelWindow;
136 
137 
150 struct KIFACE
151 {
152  // The order of functions establishes the vtable sequence, do not change the
153  // order of functions in this listing unless you recompile all clients of
154  // this interface.
155 
156  virtual ~KIFACE() throw() {}
157 
158 #define KFCTL_STANDALONE (1<<0)
159 #define KFCTL_CPP_PROJECT_SUITE (1<<1)
160 #define KFCTL_PY_PROJECT_SUITE (1<<2)
161 
162 
181  VTBL_ENTRY bool OnKifaceStart( PGM_BASE* aProgram, int aCtlBits ) = 0;
182 
188  VTBL_ENTRY void OnKifaceEnd() = 0;
189 
210  VTBL_ENTRY wxWindow* CreateWindow( wxWindow* aParent, int aClassId,
211  KIWAY* aKIWAY, int aCtlBits = 0 ) = 0;
212 
219  VTBL_ENTRY void SaveFileAs( const wxString& srcProjectBasePath,
220  const wxString& srcProjectName,
221  const wxString& newProjectBasePath,
222  const wxString& newProjectName,
223  const wxString& srcFilePath,
224  wxString& aErrors )
225  {
226  // If a KIFACE owns files then it needs to implement this....
227  }
228 
241  VTBL_ENTRY void* IfaceOrAddress( int aDataId ) = 0;
242 };
243 
244 
273 class KIWAY : public wxEvtHandler
274 {
275  friend struct PGM_SINGLE_TOP; // can use set_kiface()
276 
277 public:
279  enum FACE_T
280  {
288 
290  };
291 
292  ~KIWAY() throw () {}
293 
301  static FACE_T KifaceType( FRAME_T aFrameType );
302 
303  // If you change the vtable, recompile all of KiCad.
304 
310  VTBL_ENTRY KIFACE* KiFACE( FACE_T aFaceId, bool doLoad = true );
311 
331  VTBL_ENTRY KIWAY_PLAYER* Player( FRAME_T aFrameType, bool doCreate = true,
332  wxTopLevelWindow* aParent = NULL );
333 
342  VTBL_ENTRY bool PlayerClose( FRAME_T aFrameType, bool doForce );
343 
353  VTBL_ENTRY bool PlayersClose( bool doForce );
354 
361  VTBL_ENTRY void ExpressMail( FRAME_T aDestination, MAIL_T aCommand,
362  std::string& aPayload, wxWindow* aSource = NULL );
363 
370  VTBL_ENTRY PROJECT& Prj() const;
371 
376  VTBL_ENTRY void SetLanguage( int aLanguage );
377 
383  VTBL_ENTRY void CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVarsChanged );
384 
389  VTBL_ENTRY void ProjectChanged();
390 
391  KIWAY( PGM_BASE* aProgram, int aCtlBits, wxFrame* aTop = NULL );
392 
401  void SetTop( wxFrame* aTop );
402 
403  void OnKiCadExit();
404 
405  void OnKiwayEnd();
406 
407  bool ProcessEvent( wxEvent& aEvent ) override;
408 
409 private:
410 
412  const wxString dso_search_path( FACE_T aFaceId );
413 
414 #if 0
415  void player_destroy_handler( wxWindowDestroyEvent& event );
417 #endif
418 
419  bool set_kiface( FACE_T aFaceType, KIFACE* aKiface )
420  {
421  if( (unsigned) aFaceType < (unsigned) KIWAY_FACE_COUNT )
422  {
423  m_kiface[aFaceType] = aKiface;
424  return true;
425  }
426  return false;
427  }
428 
433  KIWAY_PLAYER* GetPlayerFrame( FRAME_T aFrameType );
434 
437 
439  int m_ctl;
440 
441  wxFrame* m_top; // Usually m_top is the Project manager
442 
443  // a string array ( size KIWAY_PLAYER_COUNT ) to Store the frame name
444  // of PLAYER frames which were run.
445  // A non empty name means only a PLAYER was run at least one time.
446  // It can be closed. Call :
447  // wxWindow::FindWindowByName( m_playerFrameName[aFrameType] )
448  // to know if still exists (or GetPlayerFrame( FRAME_T aFrameType )
449  wxArrayString m_playerFrameName;
450 };
451 
452 
453 #ifndef SWIG
454 // provided by single_top.cpp and kicad.cpp;
455 extern KIWAY Kiway;
456 // whereas python launchers: single_top.py and project manager instantiate as a python object
457 #endif
458 
459 
473 typedef KIFACE* KIFACE_GETTER_FUNC( int* aKIFACEversion, int aKIWAYversion, PGM_BASE* aProgram );
474 
475 
476 #ifndef SWIG
477 
479 extern "C" {
480 #if defined(BUILD_KIWAY_DLL)
481  MY_API( KIFACE* ) KIFACE_GETTER( int* aKIFACEversion, int aKIWAYversion, PGM_BASE* aProgram );
482 #else
483  KIFACE* KIFACE_GETTER( int* aKIFACEversion, int aKIWAYversion, PGM_BASE* aProgram );
484 #endif
485 }
486 
487 #endif // SWIG
488 
489 #endif // KIWAY_H_
VTBL_ENTRY bool PlayersClose(bool doForce)
Function PlayersClose calls the KIWAY_PLAYER::Close( bool force ) function on all the windows and if ...
Definition: kiway.cpp:426
KIWAY_PLAYER is a wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of ...
Definition: kiway_player.h:61
void OnKiCadExit()
Definition: kiway.cpp:587
Struct PGM_SINGLE_TOP implements PGM_BASE with its own OnPgmInit() and OnPgmExit().
Definition: single_top.cpp:62
PROJECT holds project specific data.
Definition: project.h:63
static FACE_T KifaceType(FRAME_T aFrameType)
Function KifaceType is a simple mapping function which returns the FACE_T which is known to implement...
Definition: kiway.cpp:295
KIWAY_PLAYER * GetPlayerFrame(FRAME_T aFrameType)
Definition: kiway.cpp:336
virtual ~KIFACE()
Definition: kiway.h:156
PGM_BASE keeps program (whole process) data for KiCad programs.
Definition: pgm_base.h:137
FRAME_T
Enum FRAME_T is the set of EDA_BASE_FRAME derivatives, typically stored in EDA_BASE_FRAME::m_Ident.
Definition: frame_type.h:34
VTBL_ENTRY PROJECT & Prj() const
Function Prj returns the PROJECT associated with this KIWAY.
Definition: kiway.cpp:174
KIWAY(PGM_BASE *aProgram, int aCtlBits, wxFrame *aTop=NULL)
Definition: kiway.cpp:48
VTBL_ENTRY void OnKifaceEnd()=0
Function OnKifaceEnd is called just once just before the DSO is to be unloaded.
PGM_BASE * m_program
Definition: kiway.h:438
VTBL_ENTRY void SaveFileAs(const wxString &srcProjectBasePath, const wxString &srcProjectName, const wxString &newProjectBasePath, const wxString &newProjectName, const wxString &srcFilePath, wxString &aErrors)
Function SaveFileAs Saving a file under a different name is delegated to the various KIFACEs because ...
Definition: kiway.h:219
VTBL_ENTRY void SetLanguage(int aLanguage)
Function SetLanguage changes the language and then calls ShowChangedLanguage() on all KIWAY_PLAYERs.
Definition: kiway.cpp:447
~KIWAY()
Definition: kiway.h:292
void OnKiwayEnd()
Definition: kiway.cpp:602
VTBL_ENTRY void * IfaceOrAddress(int aDataId)=0
Function IfaceOrAddress returns a pointer to the requested object.
#define VTBL_ENTRY
Definition: kiway.h:109
bool set_kiface(FACE_T aFaceType, KIFACE *aKiface)
Definition: kiway.h:419
MAIL_T
Enum MAIL_T is the set of mail types sendable via KIWAY::ExpressMail() and supplied as the aCommand p...
Definition: mail_type.h:37
#define MY_API(rettype)
Definition: import_export.h:55
VTBL_ENTRY wxWindow * CreateWindow(wxWindow *aParent, int aClassId, KIWAY *aKIWAY, int aCtlBits=0)=0
Function CreateWindow creates a wxWindow for the current project.
#define NULL
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:345
VTBL_ENTRY bool PlayerClose(FRAME_T aFrameType, bool doForce)
Function PlayerClose calls the KIWAY_PLAYER::Close( bool force ) function on the window and if not ve...
Definition: kiway.cpp:401
bool ProcessEvent(wxEvent &aEvent) override
Definition: kiway.cpp:561
KIFACE * KIFACE_GETTER_FUNC(int *aKIFACEversion, int aKIWAYversion, PGM_BASE *aProgram)
Function Pointer KIFACE_GETTER_FUNC points to the one and only KIFACE export.
Definition: kiway.h:473
VTBL_ENTRY void ProjectChanged()
Calls ProjectChanged() on all KIWAY_PLAYERs.
Definition: kiway.cpp:538
int m_ctl
Definition: kiway.h:439
KIWAY is a minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the s...
Definition: kiway.h:273
pcbnew DSO
Definition: kiway.h:282
#define KIFACE_GETTER
Definition: kiway.h:112
const wxString dso_search_path(FACE_T aFaceId)
Get the [path &] name of the DSO holding the requested FACE_T.
Definition: kiway.cpp:98
VTBL_ENTRY KIFACE * KiFACE(FACE_T aFaceId, bool doLoad=true)
Function KiFACE returns the KIFACE* given a FACE_T.
Definition: kiway.cpp:180
int PGM_BASE * aProgram
Definition: cvpcb/cvpcb.cpp:97
void SetTop(wxFrame *aTop)
Function SetTop tells this KIWAY about the top most frame in the program and optionally allows it to ...
Definition: kiway.cpp:80
FACE_T
Known KIFACE implementations.
Definition: kiway.h:279
eeschema DSO
Definition: kiway.h:281
VTBL_ENTRY void ExpressMail(FRAME_T aDestination, MAIL_T aCommand, std::string &aPayload, wxWindow *aSource=NULL)
Function ExpressMail send aPayload to aDestination from aSource.
Definition: kiway.cpp:439
KIFACE is used by a participant in the KIWAY alchemy.
Definition: kiway.h:150
int aKIWAYversion
Definition: cvpcb/cvpcb.cpp:96
static int m_kiface_version[KIWAY_FACE_COUNT]
Definition: kiway.h:436
VTBL_ENTRY bool OnKifaceStart(PGM_BASE *aProgram, int aCtlBits)=0
Function OnKifaceStart is called just once shortly after the DSO is loaded.
VTBL_ENTRY void CommonSettingsChanged(bool aEnvVarsChanged, bool aTextVarsChanged)
Function CommonSettingsChanged Calls CommonSettingsChanged() on all KIWAY_PLAYERs.
Definition: kiway.cpp:515
wxArrayString m_playerFrameName
Definition: kiway.h:449
wxFrame * m_top
Definition: kiway.h:441
static KIFACE * m_kiface[KIWAY_FACE_COUNT]
Definition: kiway.h:435
KIWAY Kiway