]> git.saurik.com Git - wxWidgets.git/blob - src/common/appcmn.cpp
Added SetActive to wxEventLoop
[wxWidgets.git] / src / common / appcmn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: common/appcmn.cpp
3 // Purpose: wxAppBase methods common to all platforms
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 18.10.99
7 // RCS-ID: $Id$
8 // Copyright: (c) Vadim Zeitlin
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ---------------------------------------------------------------------------
17 // headers
18 // ---------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "appbase.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #if defined(__BORLANDC__)
28 #pragma hdrstop
29 #endif
30
31 #ifndef WX_PRECOMP
32 #include "wx/app.h"
33 #include "wx/intl.h"
34 #include "wx/list.h"
35 #if wxUSE_GUI
36 #include "wx/msgdlg.h"
37 #endif // wxUSE_GUI
38 #endif
39
40 #include "wx/cmdline.h"
41 #include "wx/thread.h"
42 #include "wx/confbase.h"
43 #include "wx/tokenzr.h"
44 #include "wx/utils.h"
45 #include "wx/artprov.h"
46
47 #if !defined(__WXMSW__) || defined(__WXMICROWIN__)
48 #include <signal.h> // for SIGTRAP used by wxTrap()
49 #endif //Win/Unix
50
51 #if defined(__WXMSW__)
52 #include "wx/msw/private.h" // includes windows.h for MessageBox()
53 #endif
54
55 #if defined(__WXMAC__)
56 #include "wx/mac/private.h" // includes mac headers
57 #endif
58
59 // ===========================================================================
60 // implementation
61 // ===========================================================================
62
63 // ----------------------------------------------------------------------------
64 // initialization and termination
65 // ----------------------------------------------------------------------------
66
67 #ifdef __WXDEBUG__
68 static void LINKAGEMODE SetTraceMasks()
69 {
70 wxString mask;
71 if ( wxGetEnv(wxT("WXTRACE"), &mask) )
72 {
73 wxStringTokenizer tkn(mask, wxT(","));
74 while ( tkn.HasMoreTokens() )
75 wxLog::AddTraceMask(tkn.GetNextToken());
76 }
77 }
78 #endif
79
80 wxAppBase::wxAppBase()
81 {
82 wxTheApp = (wxApp *)this;
83
84 #if WXWIN_COMPATIBILITY_2_2
85 m_wantDebugOutput = FALSE;
86 #endif // WXWIN_COMPATIBILITY_2_2
87
88 #if wxUSE_GUI
89 m_topWindow = (wxWindow *)NULL;
90 m_useBestVisual = FALSE;
91 m_exitOnFrameDelete = TRUE;
92 m_isActive = TRUE;
93 #endif // wxUSE_GUI
94
95 #ifdef __WXDEBUG__
96 SetTraceMasks();
97 #endif
98 }
99
100 wxAppBase::~wxAppBase()
101 {
102 // this destructor is required for Darwin
103 }
104
105 #if wxUSE_GUI
106 bool wxAppBase::OnInitGui()
107 {
108 #ifdef __WXUNIVERSAL__
109 if ( !wxTheme::Get() && !wxTheme::CreateDefault() )
110 return FALSE;
111 wxArtProvider *art = wxTheme::Get()->GetArtProvider();
112 if ( art )
113 wxArtProvider::PushProvider(art);
114 #endif // __WXUNIVERSAL__
115
116 return TRUE;
117 }
118 #endif // wxUSE_GUI
119
120 int wxAppBase::OnExit()
121 {
122 #if wxUSE_CONFIG
123 // delete the config object if any (don't use Get() here, but Set()
124 // because Get() could create a new config object)
125 delete wxConfigBase::Set((wxConfigBase *) NULL);
126 #endif // wxUSE_CONFIG
127
128 #ifdef __WXUNIVERSAL__
129 delete wxTheme::Set(NULL);
130 #endif // __WXUNIVERSAL__
131
132 return 0;
133 }
134
135 // ---------------------------------------------------------------------------
136 // wxAppBase
137 // ----------------------------------------------------------------------------
138
139 void wxAppBase::ProcessPendingEvents()
140 {
141 // ensure that we're the only thread to modify the pending events list
142 wxENTER_CRIT_SECT( *wxPendingEventsLocker );
143
144 if ( !wxPendingEvents )
145 {
146 wxLEAVE_CRIT_SECT( *wxPendingEventsLocker );
147 return;
148 }
149
150 // iterate until the list becomes empty
151 wxNode *node = wxPendingEvents->First();
152 while (node)
153 {
154 wxEvtHandler *handler = (wxEvtHandler *)node->Data();
155 delete node;
156
157 // In ProcessPendingEvents(), new handlers might be add
158 // and we can safely leave the critical section here.
159 wxLEAVE_CRIT_SECT( *wxPendingEventsLocker );
160 handler->ProcessPendingEvents();
161 wxENTER_CRIT_SECT( *wxPendingEventsLocker );
162
163 node = wxPendingEvents->First();
164 }
165
166 wxLEAVE_CRIT_SECT( *wxPendingEventsLocker );
167 }
168
169 // ----------------------------------------------------------------------------
170 // misc
171 // ----------------------------------------------------------------------------
172
173 #if wxUSE_GUI
174
175 void wxAppBase::SetActive(bool active, wxWindow * WXUNUSED(lastFocus))
176 {
177 if ( active == m_isActive )
178 return;
179
180 m_isActive = active;
181
182 wxActivateEvent event(wxEVT_ACTIVATE_APP, active);
183 event.SetEventObject(this);
184
185 (void)ProcessEvent(event);
186 }
187
188 #endif // wxUSE_GUI
189
190 // ----------------------------------------------------------------------------
191 // cmd line parsing
192 // ----------------------------------------------------------------------------
193
194 bool wxAppBase::OnInit()
195 {
196 #if wxUSE_CMDLINE_PARSER
197 wxCmdLineParser parser(argc, argv);
198
199 OnInitCmdLine(parser);
200
201 bool cont;
202 switch ( parser.Parse(FALSE /* don't show usage */) )
203 {
204 case -1:
205 cont = OnCmdLineHelp(parser);
206 break;
207
208 case 0:
209 cont = OnCmdLineParsed(parser);
210 break;
211
212 default:
213 cont = OnCmdLineError(parser);
214 break;
215 }
216
217 if ( !cont )
218 return FALSE;
219 #endif // wxUSE_CMDLINE_PARSER
220
221 return TRUE;
222 }
223
224 #if wxUSE_CMDLINE_PARSER
225
226 #define OPTION_VERBOSE _T("verbose")
227 #define OPTION_THEME _T("theme")
228 #define OPTION_MODE _T("mode")
229
230 void wxAppBase::OnInitCmdLine(wxCmdLineParser& parser)
231 {
232 // the standard command line options
233 static const wxCmdLineEntryDesc cmdLineDesc[] =
234 {
235 {
236 wxCMD_LINE_SWITCH,
237 _T("h"),
238 _T("help"),
239 gettext_noop("show this help message"),
240 wxCMD_LINE_VAL_NONE,
241 wxCMD_LINE_OPTION_HELP
242 },
243
244 #if wxUSE_LOG
245 {
246 wxCMD_LINE_SWITCH,
247 _T(""),
248 OPTION_VERBOSE,
249 gettext_noop("generate verbose log messages")
250 },
251 #endif // wxUSE_LOG
252
253 #ifdef __WXUNIVERSAL__
254 {
255 wxCMD_LINE_OPTION,
256 _T(""),
257 OPTION_THEME,
258 gettext_noop("specify the theme to use"),
259 wxCMD_LINE_VAL_STRING
260 },
261 #endif // __WXUNIVERSAL__
262
263 #if defined(__WXMGL__)
264 // VS: this is not specific to wxMGL, all fullscreen (framebuffer) ports
265 // should provide this option. That's why it is in common/appcmn.cpp
266 // and not mgl/app.cpp
267 {
268 wxCMD_LINE_OPTION,
269 _T(""),
270 OPTION_MODE,
271 gettext_noop("specify display mode to use (e.g. 640x480-16)"),
272 wxCMD_LINE_VAL_STRING
273 },
274 #endif // __WXMGL__
275
276 // terminator
277 { wxCMD_LINE_NONE }
278 };
279
280 parser.SetDesc(cmdLineDesc);
281 }
282
283 bool wxAppBase::OnCmdLineParsed(wxCmdLineParser& parser)
284 {
285 #if wxUSE_LOG
286 if ( parser.Found(OPTION_VERBOSE) )
287 {
288 wxLog::SetVerbose(TRUE);
289 }
290 #endif // wxUSE_LOG
291
292 #ifdef __WXUNIVERSAL__
293 wxString themeName;
294 if ( parser.Found(OPTION_THEME, &themeName) )
295 {
296 wxTheme *theme = wxTheme::Create(themeName);
297 if ( !theme )
298 {
299 wxLogError(_("Unsupported theme '%s'."), themeName.c_str());
300
301 return FALSE;
302 }
303
304 wxTheme::Set(theme);
305 }
306 #endif // __WXUNIVERSAL__
307
308 #if defined(__WXMGL__)
309 wxString modeDesc;
310 if ( parser.Found(OPTION_MODE, &modeDesc) )
311 {
312 unsigned w, h, bpp;
313 if ( wxSscanf(modeDesc.c_str(), _T("%ux%u-%u"), &w, &h, &bpp) != 3 )
314 {
315 wxLogError(_("Invalid display mode specification '%s'."), modeDesc.c_str());
316
317 return FALSE;
318 }
319
320 if ( !SetDisplayMode(wxDisplayModeInfo(w, h, bpp)) )
321 return FALSE;
322 }
323 #endif // __WXMGL__
324
325 return TRUE;
326 }
327
328 bool wxAppBase::OnCmdLineHelp(wxCmdLineParser& parser)
329 {
330 parser.Usage();
331
332 return FALSE;
333 }
334
335 bool wxAppBase::OnCmdLineError(wxCmdLineParser& parser)
336 {
337 parser.Usage();
338
339 return FALSE;
340 }
341
342 #endif // wxUSE_CMDLINE_PARSER
343
344 // ----------------------------------------------------------------------------
345 // debugging support
346 // ----------------------------------------------------------------------------
347
348 #ifdef __WXDEBUG__
349
350 // wxASSERT() helper
351 bool wxAssertIsEqual(int x, int y)
352 {
353 return x == y;
354 }
355
356 // break into the debugger
357 void wxTrap()
358 {
359 #if defined(__WXMSW__) && !defined(__WXMICROWIN__)
360 DebugBreak();
361 #elif defined(__WXMAC__) && !defined(__DARWIN__)
362 #if __powerc
363 Debugger();
364 #else
365 SysBreak();
366 #endif
367 #elif defined(__UNIX__)
368 raise(SIGTRAP);
369 #else
370 // TODO
371 #endif // Win/Unix
372 }
373
374 // show the assert modal dialog
375 static
376 void ShowAssertDialog(const wxChar *szFile, int nLine, const wxChar *szMsg)
377 {
378 // this variable can be set to true to suppress "assert failure" messages
379 static bool s_bNoAsserts = FALSE;
380
381 wxChar szBuf[4096];
382
383 // make life easier for people using VC++ IDE: clicking on the message
384 // will take us immediately to the place of the failed assert
385 wxSnprintf(szBuf, WXSIZEOF(szBuf),
386 #ifdef __VISUALC__
387 wxT("%s(%d): assert failed"),
388 #else // !VC++
389 // make the error message more clear for all the others
390 wxT("Assert failed in file %s at line %d"),
391 #endif // VC/!VC
392 szFile, nLine);
393
394 if ( szMsg != NULL )
395 {
396 wxStrcat(szBuf, wxT(": "));
397 wxStrcat(szBuf, szMsg);
398 }
399 else // no message given
400 {
401 wxStrcat(szBuf, wxT("."));
402 }
403
404 if ( !s_bNoAsserts )
405 {
406 // send it to the normal log destination
407 wxLogDebug(szBuf);
408
409 #if (wxUSE_GUI && wxUSE_MSGDLG) || defined(__WXMSW__)
410 // this message is intentionally not translated - it is for
411 // developpers only
412 wxStrcat(szBuf, wxT("\nDo you want to stop the program?\nYou can also choose [Cancel] to suppress further warnings."));
413
414 // use the native message box if available: this is more robust than
415 // using our own
416 #if defined(__WXMSW__) && !defined(__WXMICROWIN__)
417 switch ( ::MessageBox(NULL, szBuf, _T("Debug"),
418 MB_YESNOCANCEL | MB_ICONSTOP ) )
419 {
420 case IDYES:
421 wxTrap();
422 break;
423
424 case IDCANCEL:
425 s_bNoAsserts = TRUE;
426 break;
427
428 //case IDNO: nothing to do
429 }
430 #else // !MSW
431 switch ( wxMessageBox(szBuf, wxT("Debug"),
432 wxYES_NO | wxCANCEL | wxICON_STOP ) )
433 {
434 case wxYES:
435 wxTrap();
436 break;
437
438 case wxCANCEL:
439 s_bNoAsserts = TRUE;
440 break;
441
442 //case wxNO: nothing to do
443 }
444 #endif // GUI or MSW
445
446 #else // !GUI
447 wxTrap();
448 #endif // GUI/!GUI
449 }
450 }
451
452 // this function is called when an assert fails
453 void wxOnAssert(const wxChar *szFile, int nLine, const wxChar *szMsg)
454 {
455 // FIXME MT-unsafe
456 static bool s_bInAssert = FALSE;
457
458 if ( s_bInAssert )
459 {
460 // He-e-e-e-elp!! we're trapped in endless loop
461 wxTrap();
462
463 s_bInAssert = FALSE;
464
465 return;
466 }
467
468 s_bInAssert = TRUE;
469
470 if ( !wxTheApp )
471 {
472 // by default, show the assert dialog box - we can't customize this
473 // behaviour
474 ShowAssertDialog(szFile, nLine, szMsg);
475 }
476 else
477 {
478 // let the app process it as it wants
479 wxTheApp->OnAssert(szFile, nLine, szMsg);
480 }
481
482 s_bInAssert = FALSE;
483 }
484
485 void wxAppBase::OnAssert(const wxChar *file, int line, const wxChar *msg)
486 {
487 ShowAssertDialog(file, line, msg);
488 }
489
490 #endif //WXDEBUG
491