]> git.saurik.com Git - wxWidgets.git/blob - src/common/appcmn.cpp
resource loader structure added for loading menu bar, apple menu will not get multipl...
[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
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__
66 static 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
78 wxAppBase::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
97 wxAppBase::~wxAppBase()
98 {
99 // this destructor is required for Darwin
100 }
101
102 #if wxUSE_GUI
103 bool 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
114 int 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
133 void 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
169 void 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
188 bool 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
224 void 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
277 bool 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
322 bool wxAppBase::OnCmdLineHelp(wxCmdLineParser& parser)
323 {
324 parser.Usage();
325
326 return FALSE;
327 }
328
329 bool 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
345 bool wxAssertIsEqual(int x, int y)
346 {
347 return x == y;
348 }
349
350 // break into the debugger
351 void 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
369 static
370 void 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
447 void 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
479 void wxAppBase::OnAssert(const wxChar *file, int line, const wxChar *msg)
480 {
481 ShowAssertDialog(file, line, msg);
482 }
483
484 #endif //WXDEBUG
485