]> git.saurik.com Git - wxWidgets.git/blame - src/mgl/app.cpp
a temporary hack to make testing wxTLW/Univ easier
[wxWidgets.git] / src / mgl / app.cpp
CommitLineData
32b8ec41
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: app.cpp
32b8ec41 3// Author: Vaclav Slavik
7bdc1879 4// based on GTK and MSW implementations
32b8ec41 5// Id: $Id$
8f7b34a8 6// Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
32b8ec41
VZ
7// Licence: wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
10#ifdef __GNUG__
11 #pragma implementation "app.h"
12#endif
13
7bdc1879
VS
14// For compilers that support precompilation, includes "wx.h".
15#include "wx/wxprec.h"
16
17#ifdef __BORLANDC__
18 #pragma hdrstop
19#endif
20
2ec3892d 21
7bdc1879
VS
22#ifndef WX_PRECOMP
23 #include "wx/settings.h"
24 #include "wx/module.h"
25 #include "wx/evtloop.h"
26 #include "wx/frame.h"
27 #include "wx/dialog.h"
2ec3892d 28 #include "wx/log.h"
7bdc1879
VS
29 #include "wx/intl.h"
30#endif
32b8ec41 31
7bdc1879 32#include "wx/app.h"
ef344ff8 33#include "wx/fontutil.h"
7bdc1879 34#include "wx/mgl/private.h"
32b8ec41 35
2ec3892d
VS
36#define MGL_DEBUG
37
38#if defined(MGL_DEBUG) && !defined(__WXDEBUG__)
39#undef MGL_DEBUG
40#endif
41
32b8ec41
VZ
42//-----------------------------------------------------------------------------
43// Global data
44//-----------------------------------------------------------------------------
45
7bdc1879 46wxApp *wxTheApp = NULL;
32b8ec41
VZ
47wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
48
32b8ec41 49
7bdc1879
VS
50//-----------------------------------------------------------------------------
51// wxExit
52//-----------------------------------------------------------------------------
32b8ec41
VZ
53
54void wxExit()
55{
7bdc1879 56 MGL_exit();
32b8ec41
VZ
57 exit(0);
58}
59
60//-----------------------------------------------------------------------------
61// wxYield
62//-----------------------------------------------------------------------------
63
7bdc1879
VS
64static bool gs_inYield = FALSE;
65
32b8ec41
VZ
66bool wxYield()
67{
7bdc1879
VS
68#if wxUSE_THREADS
69 if ( !wxThread::IsMain() )
70 {
71 // can't process events from other threads, MGL is thread-unsafe
72 return TRUE;
73 }
74#endif // wxUSE_THREADS
75
76 gs_inYield = TRUE;
77
78 wxLog::Suspend();
79
ef344ff8
VS
80 if ( wxEventLoop::GetActive() )
81 {
82 while (wxEventLoop::GetActive()->Pending())
83 wxEventLoop::GetActive()->Dispatch();
84 }
7bdc1879
VS
85
86 /* it's necessary to call ProcessIdle() to update the frames sizes which
87 might have been changed (it also will update other things set from
88 OnUpdateUI() which is a nice (and desired) side effect) */
89 while (wxTheApp->ProcessIdle()) { }
90
91 wxLog::Resume();
92
93 gs_inYield = FALSE;
94
32b8ec41
VZ
95 return TRUE;
96}
97
7bdc1879
VS
98bool wxYieldIfNeeded()
99{
100 if (gs_inYield)
101 return FALSE;
102
103 return wxYield();
104}
105
106
32b8ec41
VZ
107//-----------------------------------------------------------------------------
108// wxWakeUpIdle
109//-----------------------------------------------------------------------------
110
111void wxWakeUpIdle()
112{
7bdc1879
VS
113#if wxUSE_THREADS
114 if (!wxThread::IsMain())
115 wxMutexGuiEnter();
116#endif
117
118 while (wxTheApp->ProcessIdle()) {}
119
120#if wxUSE_THREADS
121 if (!wxThread::IsMain())
122 wxMutexGuiLeave();
123#endif
32b8ec41
VZ
124}
125
126//-----------------------------------------------------------------------------
127// wxApp
128//-----------------------------------------------------------------------------
129
130IMPLEMENT_DYNAMIC_CLASS(wxApp,wxEvtHandler)
131
132BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
133 EVT_IDLE(wxApp::OnIdle)
134END_EVENT_TABLE()
135
136
ef344ff8 137wxApp::wxApp() : m_mainLoop(NULL)
7bdc1879
VS
138{
139}
140
141wxApp::~wxApp()
142{
143}
144
145bool wxApp::OnInitGui()
146{
7bdc1879
VS
147 if ( !wxCreateMGL_WM() )
148 return FALSE;
149
150 // This has to be done *after* wxCreateMGL_WM() because it initializes
151 // wxUniv's themes
152 if ( !wxAppBase::OnInitGui() )
153 return FALSE;
154
2ec3892d
VS
155#ifdef MGL_DEBUG
156 // That damn MGL redirects stdin and stdout to physical console
157 FILE *file = fopen("stderr", "wt");
158 wxLog::SetActiveTarget(new wxLogStderr(file));
159#endif
160
7bdc1879
VS
161 return TRUE;
162}
163
164bool wxApp::ProcessIdle()
165{
166 wxIdleEvent event;
167 event.SetEventObject(this);
168 ProcessEvent(event);
169
170 return event.MoreRequested();
171}
172
173void wxApp::OnIdle(wxIdleEvent &event)
174{
175 static bool s_inOnIdle = FALSE;
176
177 /* Avoid recursion (via ProcessEvent default case) */
178 if (s_inOnIdle)
179 return;
180
181 s_inOnIdle = TRUE;
182
183 /* Resend in the main thread events which have been prepared in other
184 threads */
185 ProcessPendingEvents();
186
187 // 'Garbage' collection of windows deleted with Close().
188 DeletePendingObjects();
189
190 // Send OnIdle events to all windows
191 if ( SendIdleEvents() )
192 event.RequestMore(TRUE);
193
194 s_inOnIdle = FALSE;
195}
196
197bool wxApp::SendIdleEvents()
198{
199 bool needMore = FALSE;
200
201 wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
202 while (node)
203 {
204 wxWindow* win = node->GetData();
205 if ( SendIdleEvents(win) )
206 needMore = TRUE;
207 node = node->GetNext();
208 }
209
210 return needMore;
211}
212
213bool wxApp::SendIdleEvents(wxWindow* win)
214{
215 bool needMore = FALSE;
216
217 wxIdleEvent event;
218 event.SetEventObject(win);
219
220 win->GetEventHandler()->ProcessEvent(event);
221
7bdc1879
VS
222 if ( event.MoreRequested() )
223 needMore = TRUE;
7bdc1879
VS
224
225 wxNode* node = win->GetChildren().First();
226 while (node)
227 {
228 wxWindow* win = (wxWindow*) node->Data();
229 if ( SendIdleEvents(win) )
230 needMore = TRUE;
231
232 node = node->Next();
233 }
234 return needMore;
235}
236
237int wxApp::MainLoop()
238{
fd495ab3 239 int rt;
ef344ff8
VS
240 m_mainLoop = new wxEventLoop;
241
242 rt = m_mainLoop->Run();
243
244 delete m_mainLoop;
245 m_mainLoop = NULL;
fd495ab3 246 return rt;
7bdc1879
VS
247}
248
249void wxApp::ExitMainLoop()
250{
ef344ff8
VS
251 if ( m_mainLoop )
252 m_mainLoop->Exit(0);
7bdc1879
VS
253}
254
255bool wxApp::Initialized()
256{
bd73ba41 257 return (wxTopLevelWindows.GetCount() != 0);
7bdc1879
VS
258}
259
260bool wxApp::Pending()
261{
ef344ff8 262 return wxEventLoop::GetActive()->Pending();
7bdc1879
VS
263}
264
265void wxApp::Dispatch()
32b8ec41 266{
ef344ff8 267 wxEventLoop::GetActive()->Dispatch();
32b8ec41
VZ
268}
269
7bdc1879
VS
270void wxApp::DeletePendingObjects()
271{
272 wxNode *node = wxPendingDelete.First();
273 while (node)
274 {
275 wxObject *obj = (wxObject *)node->Data();
276
277 delete obj;
278
279 if ( wxPendingDelete.Find(obj) )
280 delete node;
32b8ec41 281
7bdc1879
VS
282 node = wxPendingDelete.First();
283 }
284}
285
286bool wxApp::Initialize()
32b8ec41 287{
bd73ba41
VS
288 if ( MGL_init(".", NULL) == 0 )
289 return FALSE;
290
32b8ec41
VZ
291 wxBuffer = new wxChar[BUFSIZ + 512];
292
293 wxClassInfo::InitializeClasses();
7bdc1879 294
32b8ec41 295 wxSystemSettings::Init();
7bdc1879
VS
296
297#if wxUSE_INTL
298 wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding());
299#endif
300
301 // GL: I'm annoyed ... I don't know where to put this and I don't want to
302 // create a module for that as it's part of the core.
303#if wxUSE_THREADS
304 wxPendingEvents = new wxList;
305 wxPendingEventsLocker = new wxCriticalSection;
306#endif
307
308 wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
32b8ec41 309 wxTheColourDatabase->Initialize();
ef344ff8
VS
310
311 // Can't do this in wxModule, because fonts are needed by stock lists
312 wxTheFontsManager = new wxFontsManager;
7bdc1879 313
32b8ec41
VZ
314 wxInitializeStockLists();
315 wxInitializeStockObjects();
7bdc1879
VS
316
317#if wxUSE_WX_RESOURCES
318 wxInitializeResourceSystem();
319#endif
320
32b8ec41
VZ
321 wxModule::RegisterModules();
322 if (!wxModule::InitializeModules()) return FALSE;
7bdc1879 323
32b8ec41
VZ
324 return TRUE;
325}
326
7bdc1879
VS
327#include "info.xpm"
328#include "error.xpm"
329#include "question.xpm"
330#include "warning.xpm"
331
332wxIcon wxApp::GetStdIcon(int which) const
333{
334 switch(which)
335 {
336 case wxICON_INFORMATION:
337 return wxIcon(info_xpm);
338 case wxICON_QUESTION:
339 return wxIcon(question_xpm);
340 case wxICON_EXCLAMATION:
341 return wxIcon(warning_xpm);
342 default:
343 wxFAIL_MSG(wxT("requested non existent standard icon"));
344 // still fall through
345 case wxICON_HAND:
346 return wxIcon(error_xpm);
347 }
348}
349
350void wxApp::CleanUp()
351{
352#if wxUSE_LOG
353 // flush the logged messages if any
354 wxLog *log = wxLog::GetActiveTarget();
355 if (log != NULL && log->HasPendingMessages())
356 log->Flush();
357
358 // continuing to use user defined log target is unsafe from now on because
359 // some resources may be already unavailable, so replace it by something
360 // more safe
361 wxLog *oldlog = wxLog::SetActiveTarget(new wxLogStderr);
362 if ( oldlog )
363 delete oldlog;
364#endif // wxUSE_LOG
365
366 wxModule::CleanUpModules();
367
368#if wxUSE_WX_RESOURCES
369 wxCleanUpResourceSystem();
370#endif
371
372 if (wxTheColourDatabase)
373 delete wxTheColourDatabase;
374
375 wxTheColourDatabase = (wxColourDatabase*) NULL;
376
377 wxDeleteStockObjects();
7bdc1879
VS
378 wxDeleteStockLists();
379
ef344ff8
VS
380 // Can't do this in wxModule, because fonts are needed by stock lists
381 delete wxTheFontsManager;
382 wxTheFontsManager = (wxFontsManager*) NULL;
383
7bdc1879
VS
384 delete wxTheApp;
385 wxTheApp = (wxApp*) NULL;
386
387 // GL: I'm annoyed ... I don't know where to put this and I don't want to
388 // create a module for that as it's part of the core.
389#if wxUSE_THREADS
390 delete wxPendingEvents;
391 delete wxPendingEventsLocker;
392#endif
393
394 wxSystemSettings::Done();
395
396 delete[] wxBuffer;
397
398 wxClassInfo::CleanUpClasses();
399
400 // check for memory leaks
401#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
402 if (wxDebugContext::CountObjectsLeft(TRUE) > 0)
403 {
404 wxLogDebug(wxT("There were memory leaks.\n"));
405 wxDebugContext::Dump();
406 wxDebugContext::PrintStatistics();
407 }
408#endif // Debug
409
410#if wxUSE_LOG
411 // do this as the very last thing because everything else can log messages
412 wxLog::DontCreateOnDemand();
413
414 wxLog *oldLog = wxLog::SetActiveTarget( (wxLog*) NULL );
415 if (oldLog)
416 delete oldLog;
417#endif // wxUSE_LOG
418
419 wxDestroyMGL_WM();
420 MGL_exit();
421}
422
423
424int wxEntryStart(int argc, char *argv[])
425{
426 return wxApp::Initialize() ? 0 : -1;
427}
428
429
430int wxEntryInitGui()
431{
432 return wxTheApp->OnInitGui() ? 0 : -1;
433}
434
435
436void wxEntryCleanup()
437{
438 wxApp::CleanUp();
439}
440
441
442
443int wxEntry(int argc, char *argv[])
444{
445#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
446 // This seems to be necessary since there are 'rogue'
447 // objects present at this point (perhaps global objects?)
448 // Setting a checkpoint will ignore them as far as the
449 // memory checking facility is concerned.
450 // Of course you may argue that memory allocated in globals should be
451 // checked, but this is a reasonable compromise.
452 wxDebugContext::SetCheckpoint();
453#endif
454 int err = wxEntryStart(argc, argv);
455 if ( err )
456 return err;
457
458 if ( !wxTheApp )
459 {
460 wxCHECK_MSG( wxApp::GetInitializerFunction(), -1,
461 wxT("wxWindows error: No initializer - use IMPLEMENT_APP macro.\n") );
462
463 wxAppInitializerFunction app_ini = wxApp::GetInitializerFunction();
464
465 wxObject *test_app = app_ini();
466
467 wxTheApp = (wxApp*) test_app;
468 }
469
470 wxCHECK_MSG( wxTheApp, -1, wxT("wxWindows error: no application object") );
471
472 wxTheApp->argc = argc;
473#if wxUSE_UNICODE
474 wxTheApp->argv = new wxChar*[argc+1];
475 int mb_argc = 0;
476 while (mb_argc < argc)
477 {
478 wxTheApp->argv[mb_argc] = wxStrdup(wxConvLibc.cMB2WX(argv[mb_argc]));
479 mb_argc++;
480 }
481 wxTheApp->argv[mb_argc] = (wxChar *)NULL;
482#else
483 wxTheApp->argv = argv;
484#endif
485
486 wxString name(wxFileNameFromPath(argv[0]));
487 wxStripExtension(name);
488 wxTheApp->SetAppName(name);
489
490 int retValue;
491 retValue = wxEntryInitGui();
492
493 // Here frames insert themselves automatically into wxTopLevelWindows by
494 // getting created in OnInit().
495 if ( retValue == 0 )
496 {
497 if ( !wxTheApp->OnInit() )
498 retValue = -1;
499 }
500
501 if ( retValue == 0 )
502 {
503 /* delete pending toplevel windows (typically a single
504 dialog) so that, if there isn't any left, we don't
505 call OnRun() */
506 wxTheApp->DeletePendingObjects();
507
fd495ab3 508 if ( wxTheApp->Initialized() )
7bdc1879
VS
509 {
510 wxTheApp->OnRun();
511
512 wxWindow *topWindow = wxTheApp->GetTopWindow();
513 if ( topWindow )
514 {
515 /* Forcibly delete the window. */
516 if (topWindow->IsKindOf(CLASSINFO(wxFrame)) ||
517 topWindow->IsKindOf(CLASSINFO(wxDialog)) )
518 {
519 topWindow->Close(TRUE);
520 wxTheApp->DeletePendingObjects();
521 }
522 else
523 {
524 delete topWindow;
525 wxTheApp->SetTopWindow((wxWindow*) NULL);
526 }
527 }
528
529 retValue = wxTheApp->OnExit();
530 }
531 }
532
533 wxEntryCleanup();
534
535 return retValue;
536}