KiCad PCB EDA Suite
kiway_player.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-2017 KiCad Developers, see AUTHORS.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 
26 #include <pgm_base.h>
27 #include <kiway_player.h>
28 #include <kiway_express.h>
29 #include <kiway.h>
30 #include <id.h>
31 #include <macros.h>
32 #include <typeinfo>
33 #include <wx/utils.h>
34 #include <wx/evtloop.h>
35 
36 
37 BEGIN_EVENT_TABLE( KIWAY_PLAYER, EDA_BASE_FRAME )
40 END_EVENT_TABLE()
41 
42 
43 KIWAY_PLAYER::KIWAY_PLAYER( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType,
44  const wxString& aTitle, const wxPoint& aPos, const wxSize& aSize,
45  long aStyle, const wxString& aWdoName ) :
46  EDA_BASE_FRAME( aParent, aFrameType, aTitle, aPos, aSize, aStyle, aWdoName, aKiway ),
47  m_modal( false ),
48  m_modal_loop( 0 ), m_modal_resultant_parent( 0 )
49 {
50  m_modal_ret_val = 0;
51 }
52 
53 
54 KIWAY_PLAYER::KIWAY_PLAYER( wxWindow* aParent, wxWindowID aId, const wxString& aTitle,
55  const wxPoint& aPos, const wxSize& aSize, long aStyle,
56  const wxString& aWdoName ) :
57  EDA_BASE_FRAME( aParent, (FRAME_T) aId, aTitle, aPos, aSize, aStyle, aWdoName, nullptr ),
58  m_modal( false ),
59  m_modal_loop( 0 ),
60  m_modal_resultant_parent( 0 ),
61  m_modal_ret_val( false )
62 {
63 }
64 
65 
67 
68 
70 {
71  // override this in derived classes.
72 }
73 
74 
75 bool KIWAY_PLAYER::ShowModal( wxString* aResult, wxWindow* aResultantFocusWindow )
76 {
77  wxASSERT_MSG( IsModal(), wxT( "ShowModal() shouldn't be called on non-modal frame" ) );
78 
79  /*
80  This function has a nice interface but a necessarily unsightly implementation.
81  Now the implementation is encapsulated, localizing future changes.
82 
83  It works in tandem with DismissModal(). But only ShowModal() is in the
84  vtable and therefore cross-module capable.
85  */
86 
87  // This is an exception safe way to zero a pointer before returning.
88  // Yes, even though DismissModal() clears this first normally, this is
89  // here in case there's an exception before the dialog is dismissed.
90  struct NULLER
91  {
92  void*& m_what;
93  NULLER( void*& aPtr ) : m_what( aPtr ) {}
94  ~NULLER() { m_what = 0; } // indeed, set it to NULL on destruction
95  } clear_this( (void*&) m_modal_loop );
96 
97 
98  m_modal_resultant_parent = aResultantFocusWindow;
99 
100  Show( true );
101  Raise(); // Needed on some Window managers to always display the frame
102 
103  SetFocus();
104 
105  {
106  // We have to disable all frames but the the modal one.
107  // wxWindowDisabler does that, but it also disables all top level windows
108  // We do not want to disable top level windows which are child of the modal one,
109  // if they are enabled.
110  // An example is an aui toolbar which was moved
111  // or a dialog or another frame or miniframe opened by the modal one.
112  wxWindowList wlist = GetChildren();
113  std::vector<wxWindow*> enabledTopLevelWindows;
114 
115  for( unsigned ii = 0; ii < wlist.size(); ii++ )
116  if( wlist[ii]->IsTopLevel() && wlist[ii]->IsEnabled() )
117  enabledTopLevelWindows.push_back( wlist[ii] );
118 
119  // exception safe way to disable all top level windows except the modal one,
120  // re-enables only those that were disabled on exit
121  wxWindowDisabler toggle( this );
122 
123  for( unsigned ii = 0; ii < enabledTopLevelWindows.size(); ii++ )
124  enabledTopLevelWindows[ii]->Enable( true );
125 
126  WX_EVENT_LOOP event_loop;
127  m_modal_loop = &event_loop;
128  event_loop.Run();
129 
130  } // End of scope for some variables.
131  // End nesting before setting focus below.
132 
133  if( aResult )
134  *aResult = m_modal_string;
135 
136  if( aResultantFocusWindow )
137  {
138  aResultantFocusWindow->Raise();
139 
140  // have the final say, after wxWindowDisabler reenables my parent and
141  // the events settle down, set the focus
142  wxSafeYield();
143  aResultantFocusWindow->SetFocus();
144  }
145 
146  return m_modal_ret_val;
147 }
148 
150 {
151  return EDA_BASE_FRAME::Destroy();
152 }
153 
155 {
156  return !m_modal_loop;
157 }
158 
159 
160 void KIWAY_PLAYER::DismissModal( bool aRetVal, const wxString& aResult )
161 {
162  m_modal_ret_val = aRetVal;
163  m_modal_string = aResult;
164 
165  if( m_modal_loop )
166  {
167  m_modal_loop->Exit();
168  m_modal_loop = 0; // this marks it as dismissed.
169  }
170 
171  Show( false );
172 }
173 
174 
176 {
177  // logging support
178  KiwayMailIn( aEvent ); // call the virtual, override in derived.
179 }
180 
181 
182 void KIWAY_PLAYER::language_change( wxCommandEvent& event )
183 {
184  int id = event.GetId();
185 
186  // tell all the KIWAY_PLAYERs about the language change.
187  Kiway().SetLanguage( id );
188 }
189 
190 
bool m_modal_ret_val
Definition: kiway_player.h:192
Class KIWAY_PLAYER is a wxFrame capable of the OpenProjectFiles function, meaning it can load a porti...
Definition: kiway_player.h:59
Class KIWAY_EXPRESS carries a payload from one KIWAY_PLAYER to another within a PROJECT.
Definition: kiway_express.h:39
#define WX_EVENT_LOOP
Definition: kiway_player.h:41
wxWindow * m_modal_resultant_parent
Definition: kiway_player.h:190
KIWAY & Kiway() const
Function Kiway returns a reference to the KIWAY that this object has an opportunity to participate in...
Definition: kiway_holder.h:56
wxString m_modal_string
Definition: kiway_player.h:191
bool IsDismissed()
Function IsDismissed returns false only if both the frame is acting in modal mode and it has not been...
KIWAY_PLAYER(KIWAY *aKiway, wxWindow *aParent, FRAME_T aFrameType, const wxString &aTitle, const wxPoint &aPos, const wxSize &aSize, long aStyle, const wxString &aWdoName=wxFrameNameStr)
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 void SetLanguage(int aLanguage)
Function SetLanguage changes the language and then calls ShowChangedLanguage() on all KIWAY_PLAYERs.
Definition: kiway.cpp:415
This file contains miscellaneous commonly used macros and functions.
void language_change(wxCommandEvent &event)
Function language_change is an event handler called on a language menu selection.
#define EVT_KIWAY_EXPRESS(func)
Definition: kiway_express.h:95
Class KIWAY is a minimalistic software bus for communications between various DLLs/DSOs (DSOs) within...
Definition: kiway.h:258
virtual void KiwayMailIn(KIWAY_EXPRESS &aEvent)
Function KiwayMailIn receives KIWAY_EXPRESS messages from other players.
void kiway_express(KIWAY_EXPRESS &aEvent)
event handler, routes to derivative specific virtual KiwayMailIn()
bool IsModal()
Definition: kiway_player.h:163
EVT_MENU_RANGE(ID_LANGUAGE_CHOICE, ID_LANGUAGE_CHOICE_END, KICAD_MANAGER_FRAME::language_change) KICAD_MANAGER_FRAME
see class PGM_BASE
void DismissModal(bool aRetVal, const wxString &aResult=wxEmptyString)
The base frame for deriving all KiCad main window classes.
WX_EVENT_LOOP * m_modal_loop
Definition: kiway_player.h:189
bool Destroy() override
Our version of Destroy() which is virtual from wxWidgets.
virtual bool ShowModal(wxString *aResult=NULL, wxWindow *aResultantFocusWindow=NULL)
Function ShowModal puts up this wxFrame as if it were a modal dialog, with all other instantiated wxF...