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