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