~ubuntu-dev/wxwidgets2.6/upstream-debian

« back to all changes in this revision

Viewing changes to src/common/appcmn.cpp

  • Committer: Daniel T Chen
  • Date: 2006-06-26 10:15:11 UTC
  • Revision ID: crimsun@ubuntu.com-20060626101511-a4436cec4c6d9b35
ImportĀ DebianĀ 2.6.3.2.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/////////////////////////////////////////////////////////////////////////////
 
2
// Name:        common/appcmn.cpp
 
3
// Purpose:     wxAppConsole and wxAppBase methods common to all platforms
 
4
// Author:      Vadim Zeitlin
 
5
// Modified by:
 
6
// Created:     18.10.99
 
7
// RCS-ID:      $Id: appcmn.cpp,v 1.106 2005/09/14 14:22:16 VZ Exp $
 
8
// Copyright:   (c) Vadim Zeitlin
 
9
// Licence:     wxWindows licence
 
10
/////////////////////////////////////////////////////////////////////////////
 
11
 
 
12
// ============================================================================
 
13
// declarations
 
14
// ============================================================================
 
15
 
 
16
// ---------------------------------------------------------------------------
 
17
// headers
 
18
// ---------------------------------------------------------------------------
 
19
 
 
20
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
 
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/bitmap.h"
 
34
    #include "wx/intl.h"
 
35
    #include "wx/list.h"
 
36
    #include "wx/log.h"
 
37
    #include "wx/msgdlg.h"
 
38
    #include "wx/bitmap.h"
 
39
    #include "wx/confbase.h"
 
40
#endif
 
41
 
 
42
#include "wx/apptrait.h"
 
43
#include "wx/cmdline.h"
 
44
#include "wx/evtloop.h"
 
45
#include "wx/msgout.h"
 
46
#include "wx/thread.h"
 
47
#include "wx/utils.h"
 
48
#include "wx/ptr_scpd.h"
 
49
 
 
50
#if defined(__WXMSW__)
 
51
    #include  "wx/msw/private.h"  // includes windows.h for LOGFONT
 
52
#endif
 
53
 
 
54
#if wxUSE_FONTMAP
 
55
    #include "wx/fontmap.h"
 
56
#endif // wxUSE_FONTMAP
 
57
 
 
58
// DLL options compatibility check:
 
59
#include "wx/build.h"
 
60
WX_CHECK_BUILD_OPTIONS("wxCore")
 
61
 
 
62
 
 
63
// ----------------------------------------------------------------------------
 
64
// wxEventLoopPtr
 
65
// ----------------------------------------------------------------------------
 
66
 
 
67
// this defines wxEventLoopPtr
 
68
wxDEFINE_TIED_SCOPED_PTR_TYPE(wxEventLoop);
 
69
 
 
70
// ============================================================================
 
71
// wxAppBase implementation
 
72
// ============================================================================
 
73
 
 
74
// ----------------------------------------------------------------------------
 
75
// initialization
 
76
// ----------------------------------------------------------------------------
 
77
 
 
78
wxAppBase::wxAppBase()
 
79
{
 
80
    m_topWindow = (wxWindow *)NULL;
 
81
    m_useBestVisual = false;
 
82
    m_isActive = true;
 
83
 
 
84
#if wxUSE_EVTLOOP_IN_APP
 
85
    m_mainLoop = NULL;
 
86
#endif // wxUSE_EVTLOOP_IN_APP
 
87
 
 
88
    // We don't want to exit the app if the user code shows a dialog from its
 
89
    // OnInit() -- but this is what would happen if we set m_exitOnFrameDelete
 
90
    // to Yes initially as this dialog would be the last top level window.
 
91
    // OTOH, if we set it to No initially we'll have to overwrite it with Yes
 
92
    // when we enter our OnRun() because we do want the default behaviour from
 
93
    // then on. But this would be a problem if the user code calls
 
94
    // SetExitOnFrameDelete(false) from OnInit().
 
95
    //
 
96
    // So we use the special "Later" value which is such that
 
97
    // GetExitOnFrameDelete() returns false for it but which we know we can
 
98
    // safely (i.e. without losing the effect of the users SetExitOnFrameDelete
 
99
    // call) overwrite in OnRun()
 
100
    m_exitOnFrameDelete = Later;
 
101
}
 
102
 
 
103
bool wxAppBase::Initialize(int& argcOrig, wxChar **argvOrig)
 
104
{
 
105
    if ( !wxAppConsole::Initialize(argcOrig, argvOrig) )
 
106
        return false;
 
107
 
 
108
#if wxUSE_THREADS
 
109
    wxPendingEventsLocker = new wxCriticalSection;
 
110
#endif
 
111
 
 
112
    wxInitializeStockLists();
 
113
    wxInitializeStockObjects();
 
114
 
 
115
    wxBitmap::InitStandardHandlers();
 
116
 
 
117
    return true;
 
118
}
 
119
 
 
120
// ----------------------------------------------------------------------------
 
121
// cleanup
 
122
// ----------------------------------------------------------------------------
 
123
 
 
124
wxAppBase::~wxAppBase()
 
125
{
 
126
    // this destructor is required for Darwin
 
127
}
 
128
 
 
129
void wxAppBase::CleanUp()
 
130
{
 
131
    // clean up all the pending objects
 
132
    DeletePendingObjects();
 
133
 
 
134
    // and any remaining TLWs (they remove themselves from wxTopLevelWindows
 
135
    // when destroyed, so iterate until none are left)
 
136
    while ( !wxTopLevelWindows.empty() )
 
137
    {
 
138
        // do not use Destroy() here as it only puts the TLW in pending list
 
139
        // but we want to delete them now
 
140
        delete wxTopLevelWindows.GetFirst()->GetData();
 
141
    }
 
142
 
 
143
    // undo everything we did in Initialize() above
 
144
    wxBitmap::CleanUpHandlers();
 
145
 
 
146
    wxDeleteStockObjects();
 
147
 
 
148
    wxDeleteStockLists();
 
149
 
 
150
    delete wxTheColourDatabase;
 
151
    wxTheColourDatabase = NULL;
 
152
 
 
153
    delete wxPendingEvents;
 
154
    wxPendingEvents = NULL;
 
155
 
 
156
#if wxUSE_THREADS
 
157
    delete wxPendingEventsLocker;
 
158
    wxPendingEventsLocker = NULL;
 
159
 
 
160
    #if wxUSE_VALIDATORS
 
161
        // If we don't do the following, we get an apparent memory leak.
 
162
        ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker();
 
163
    #endif // wxUSE_VALIDATORS
 
164
#endif // wxUSE_THREADS
 
165
}
 
166
 
 
167
#if wxUSE_CMDLINE_PARSER
 
168
 
 
169
// ----------------------------------------------------------------------------
 
170
// GUI-specific command line options handling
 
171
// ----------------------------------------------------------------------------
 
172
 
 
173
#define OPTION_THEME   _T("theme")
 
174
#define OPTION_MODE    _T("mode")
 
175
 
 
176
void wxAppBase::OnInitCmdLine(wxCmdLineParser& parser)
 
177
{
 
178
    // first add the standard non GUI options
 
179
    wxAppConsole::OnInitCmdLine(parser);
 
180
 
 
181
    // the standard command line options
 
182
    static const wxCmdLineEntryDesc cmdLineGUIDesc[] =
 
183
    {
 
184
#ifdef __WXUNIVERSAL__
 
185
        {
 
186
            wxCMD_LINE_OPTION,
 
187
            wxEmptyString,
 
188
            OPTION_THEME,
 
189
            gettext_noop("specify the theme to use"),
 
190
            wxCMD_LINE_VAL_STRING,
 
191
            0x0
 
192
        },
 
193
#endif // __WXUNIVERSAL__
 
194
 
 
195
#if defined(__WXMGL__)
 
196
        // VS: this is not specific to wxMGL, all fullscreen (framebuffer) ports
 
197
        //     should provide this option. That's why it is in common/appcmn.cpp
 
198
        //     and not mgl/app.cpp
 
199
        {
 
200
            wxCMD_LINE_OPTION,
 
201
            wxEmptyString,
 
202
            OPTION_MODE,
 
203
            gettext_noop("specify display mode to use (e.g. 640x480-16)"),
 
204
            wxCMD_LINE_VAL_STRING,
 
205
            0x0
 
206
        },
 
207
#endif // __WXMGL__
 
208
 
 
209
        // terminator
 
210
        {
 
211
            wxCMD_LINE_NONE,
 
212
            wxEmptyString,
 
213
            wxEmptyString,
 
214
            wxEmptyString,
 
215
            wxCMD_LINE_VAL_NONE,
 
216
            0x0
 
217
        }
 
218
    };
 
219
 
 
220
    parser.SetDesc(cmdLineGUIDesc);
 
221
}
 
222
 
 
223
bool wxAppBase::OnCmdLineParsed(wxCmdLineParser& parser)
 
224
{
 
225
#ifdef __WXUNIVERSAL__
 
226
    wxString themeName;
 
227
    if ( parser.Found(OPTION_THEME, &themeName) )
 
228
    {
 
229
        wxTheme *theme = wxTheme::Create(themeName);
 
230
        if ( !theme )
 
231
        {
 
232
            wxLogError(_("Unsupported theme '%s'."), themeName.c_str());
 
233
            return false;
 
234
        }
 
235
 
 
236
        // Delete the defaultly created theme and set the new theme.
 
237
        delete wxTheme::Get();
 
238
        wxTheme::Set(theme);
 
239
    }
 
240
#endif // __WXUNIVERSAL__
 
241
 
 
242
#if defined(__WXMGL__)
 
243
    wxString modeDesc;
 
244
    if ( parser.Found(OPTION_MODE, &modeDesc) )
 
245
    {
 
246
        unsigned w, h, bpp;
 
247
        if ( wxSscanf(modeDesc.c_str(), _T("%ux%u-%u"), &w, &h, &bpp) != 3 )
 
248
        {
 
249
            wxLogError(_("Invalid display mode specification '%s'."), modeDesc.c_str());
 
250
            return false;
 
251
        }
 
252
 
 
253
        if ( !SetDisplayMode(wxVideoMode(w, h, bpp)) )
 
254
            return false;
 
255
    }
 
256
#endif // __WXMGL__
 
257
 
 
258
    return wxAppConsole::OnCmdLineParsed(parser);
 
259
}
 
260
 
 
261
#endif // wxUSE_CMDLINE_PARSER
 
262
 
 
263
// ----------------------------------------------------------------------------
 
264
// main event loop implementation
 
265
// ----------------------------------------------------------------------------
 
266
 
 
267
int wxAppBase::MainLoop()
 
268
{
 
269
#if wxUSE_EVTLOOP_IN_APP
 
270
    wxEventLoopTiedPtr mainLoop(&m_mainLoop, new wxEventLoop);
 
271
 
 
272
    return m_mainLoop->Run();
 
273
#else // !wxUSE_EVTLOOP_IN_APP
 
274
    return 0;
 
275
#endif // wxUSE_EVTLOOP_IN_APP/!wxUSE_EVTLOOP_IN_APP
 
276
}
 
277
 
 
278
void wxAppBase::ExitMainLoop()
 
279
{
 
280
#if wxUSE_EVTLOOP_IN_APP
 
281
    // we should exit from the main event loop, not just any currently active
 
282
    // (e.g. modal dialog) event loop
 
283
    if ( m_mainLoop && m_mainLoop->IsRunning() )
 
284
    {
 
285
        m_mainLoop->Exit(0);
 
286
    }
 
287
#endif // wxUSE_EVTLOOP_IN_APP
 
288
}
 
289
 
 
290
bool wxAppBase::Pending()
 
291
{
 
292
#if wxUSE_EVTLOOP_IN_APP
 
293
    // use the currently active message loop here, not m_mainLoop, because if
 
294
    // we're showing a modal dialog (with its own event loop) currently the
 
295
    // main event loop is not running anyhow
 
296
    wxEventLoop * const loop = wxEventLoop::GetActive();
 
297
 
 
298
    return loop && loop->Pending();
 
299
#else // wxUSE_EVTLOOP_IN_APP
 
300
    return false;
 
301
#endif // wxUSE_EVTLOOP_IN_APP/!wxUSE_EVTLOOP_IN_APP
 
302
}
 
303
 
 
304
bool wxAppBase::Dispatch()
 
305
{
 
306
#if wxUSE_EVTLOOP_IN_APP
 
307
    // see comment in Pending()
 
308
    wxEventLoop * const loop = wxEventLoop::GetActive();
 
309
 
 
310
    return loop && loop->Dispatch();
 
311
#else // wxUSE_EVTLOOP_IN_APP
 
312
    return true;
 
313
#endif // wxUSE_EVTLOOP_IN_APP/!wxUSE_EVTLOOP_IN_APP
 
314
}
 
315
 
 
316
// ----------------------------------------------------------------------------
 
317
// OnXXX() hooks
 
318
// ----------------------------------------------------------------------------
 
319
 
 
320
bool wxAppBase::OnInitGui()
 
321
{
 
322
#ifdef __WXUNIVERSAL__
 
323
    if ( !wxTheme::Get() && !wxTheme::CreateDefault() )
 
324
        return false;
 
325
#endif // __WXUNIVERSAL__
 
326
 
 
327
    return true;
 
328
}
 
329
 
 
330
int wxAppBase::OnRun()
 
331
{
 
332
    // see the comment in ctor: if the initial value hasn't been changed, use
 
333
    // the default Yes from now on
 
334
    if ( m_exitOnFrameDelete == Later )
 
335
    {
 
336
        m_exitOnFrameDelete = Yes;
 
337
    }
 
338
    //else: it has been changed, assume the user knows what he is doing
 
339
 
 
340
    return MainLoop();
 
341
}
 
342
 
 
343
int wxAppBase::OnExit()
 
344
{
 
345
#ifdef __WXUNIVERSAL__
 
346
    delete wxTheme::Set(NULL);
 
347
#endif // __WXUNIVERSAL__
 
348
 
 
349
    return wxAppConsole::OnExit();
 
350
}
 
351
 
 
352
void wxAppBase::Exit()
 
353
{
 
354
    ExitMainLoop();
 
355
}
 
356
 
 
357
wxAppTraits *wxAppBase::CreateTraits()
 
358
{
 
359
    return new wxGUIAppTraits;
 
360
}
 
361
 
 
362
// ----------------------------------------------------------------------------
 
363
// misc
 
364
// ----------------------------------------------------------------------------
 
365
 
 
366
void wxAppBase::SetActive(bool active, wxWindow * WXUNUSED(lastFocus))
 
367
{
 
368
    if ( active == m_isActive )
 
369
        return;
 
370
 
 
371
    m_isActive = active;
 
372
 
 
373
    wxActivateEvent event(wxEVT_ACTIVATE_APP, active);
 
374
    event.SetEventObject(this);
 
375
 
 
376
    (void)ProcessEvent(event);
 
377
}
 
378
 
 
379
void wxAppBase::DeletePendingObjects()
 
380
{
 
381
    wxList::compatibility_iterator node = wxPendingDelete.GetFirst();
 
382
    while (node)
 
383
    {
 
384
        wxObject *obj = node->GetData();
 
385
 
 
386
        delete obj;
 
387
 
 
388
        if (wxPendingDelete.Member(obj))
 
389
            wxPendingDelete.Erase(node);
 
390
 
 
391
        // Deleting one object may have deleted other pending
 
392
        // objects, so start from beginning of list again.
 
393
        node = wxPendingDelete.GetFirst();
 
394
    }
 
395
}
 
396
 
 
397
// Returns true if more time is needed.
 
398
bool wxAppBase::ProcessIdle()
 
399
{
 
400
    wxIdleEvent event;
 
401
    bool needMore = false;
 
402
    wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
 
403
    while (node)
 
404
    {
 
405
        wxWindow* win = node->GetData();
 
406
        if (SendIdleEvents(win, event))
 
407
            needMore = true;
 
408
        node = node->GetNext();
 
409
    }
 
410
 
 
411
    event.SetEventObject(this);
 
412
    (void) ProcessEvent(event);
 
413
    if (event.MoreRequested())
 
414
        needMore = true;
 
415
 
 
416
    wxUpdateUIEvent::ResetUpdateTime();
 
417
 
 
418
    return needMore;
 
419
}
 
420
 
 
421
// Send idle event to window and all subwindows
 
422
bool wxAppBase::SendIdleEvents(wxWindow* win, wxIdleEvent& event)
 
423
{
 
424
    bool needMore = false;
 
425
 
 
426
    win->OnInternalIdle();
 
427
 
 
428
    if (wxIdleEvent::CanSend(win))
 
429
    {
 
430
        event.SetEventObject(win);
 
431
        win->GetEventHandler()->ProcessEvent(event);
 
432
 
 
433
        if (event.MoreRequested())
 
434
            needMore = true;
 
435
    }
 
436
    wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
 
437
    while ( node )
 
438
    {
 
439
        wxWindow *child = node->GetData();
 
440
        if (SendIdleEvents(child, event))
 
441
            needMore = true;
 
442
 
 
443
        node = node->GetNext();
 
444
    }
 
445
 
 
446
    return needMore;
 
447
}
 
448
 
 
449
void wxAppBase::OnIdle(wxIdleEvent& WXUNUSED(event))
 
450
{
 
451
    // If there are pending events, we must process them: pending events
 
452
    // are either events to the threads other than main or events posted
 
453
    // with wxPostEvent() functions
 
454
    // GRG: I have moved this here so that all pending events are processed
 
455
    //   before starting to delete any objects. This behaves better (in
 
456
    //   particular, wrt wxPostEvent) and is coherent with wxGTK's current
 
457
    //   behaviour. Changed Feb/2000 before 2.1.14
 
458
    ProcessPendingEvents();
 
459
 
 
460
    // 'Garbage' collection of windows deleted with Close().
 
461
    DeletePendingObjects();
 
462
 
 
463
#if wxUSE_LOG
 
464
    // flush the logged messages if any
 
465
    wxLog::FlushActive();
 
466
#endif // wxUSE_LOG
 
467
 
 
468
}
 
469
 
 
470
// ----------------------------------------------------------------------------
 
471
// wxGUIAppTraitsBase
 
472
// ----------------------------------------------------------------------------
 
473
 
 
474
#if wxUSE_LOG
 
475
 
 
476
wxLog *wxGUIAppTraitsBase::CreateLogTarget()
 
477
{
 
478
#if wxUSE_LOGGUI
 
479
    return new wxLogGui;
 
480
#else
 
481
    // we must have something!
 
482
    return new wxLogStderr;
 
483
#endif
 
484
}
 
485
 
 
486
#endif // wxUSE_LOG
 
487
 
 
488
wxMessageOutput *wxGUIAppTraitsBase::CreateMessageOutput()
 
489
{
 
490
    // The standard way of printing help on command line arguments (app --help)
 
491
    // is (according to common practice):
 
492
    //     - console apps: to stderr (on any platform)
 
493
    //     - GUI apps: stderr on Unix platforms (!)
 
494
    //                 message box under Windows and others
 
495
#ifdef __UNIX__
 
496
    return new wxMessageOutputStderr;
 
497
#else // !__UNIX__
 
498
    // wxMessageOutputMessageBox doesn't work under Motif
 
499
    #ifdef __WXMOTIF__
 
500
        return new wxMessageOutputLog;
 
501
    #else
 
502
        return new wxMessageOutputMessageBox;
 
503
    #endif
 
504
#endif // __UNIX__/!__UNIX__
 
505
}
 
506
 
 
507
#if wxUSE_FONTMAP
 
508
 
 
509
wxFontMapper *wxGUIAppTraitsBase::CreateFontMapper()
 
510
{
 
511
    return new wxFontMapper;
 
512
}
 
513
 
 
514
#endif // wxUSE_FONTMAP
 
515
 
 
516
wxRendererNative *wxGUIAppTraitsBase::CreateRenderer()
 
517
{
 
518
    // use the default native renderer by default
 
519
    return NULL;
 
520
}
 
521
 
 
522
#ifdef __WXDEBUG__
 
523
 
 
524
bool wxGUIAppTraitsBase::ShowAssertDialog(const wxString& msg)
 
525
{
 
526
    // under MSW we prefer to use the base class version using ::MessageBox()
 
527
    // even if wxMessageBox() is available because it has less chances to
 
528
    // double fault our app than our wxMessageBox()
 
529
#if defined(__WXMSW__) || !wxUSE_MSGDLG
 
530
    return wxAppTraitsBase::ShowAssertDialog(msg);
 
531
#else // wxUSE_MSGDLG
 
532
    // this message is intentionally not translated -- it is for
 
533
    // developpers only
 
534
    wxString msgDlg(msg);
 
535
    msgDlg += wxT("\nDo you want to stop the program?\n")
 
536
              wxT("You can also choose [Cancel] to suppress ")
 
537
              wxT("further warnings.");
 
538
 
 
539
    switch ( wxMessageBox(msgDlg, wxT("wxWidgets Debug Alert"),
 
540
                          wxYES_NO | wxCANCEL | wxICON_STOP ) )
 
541
    {
 
542
        case wxYES:
 
543
            wxTrap();
 
544
            break;
 
545
 
 
546
        case wxCANCEL:
 
547
            // no more asserts
 
548
            return true;
 
549
 
 
550
        //case wxNO: nothing to do
 
551
    }
 
552
 
 
553
    return false;
 
554
#endif // !wxUSE_MSGDLG/wxUSE_MSGDLG
 
555
}
 
556
 
 
557
#endif // __WXDEBUG__
 
558
 
 
559
bool wxGUIAppTraitsBase::HasStderr()
 
560
{
 
561
    // we consider that under Unix stderr always goes somewhere, even if the
 
562
    // user doesn't always see it under GUI desktops
 
563
#ifdef __UNIX__
 
564
    return true;
 
565
#else
 
566
    return false;
 
567
#endif
 
568
}
 
569
 
 
570
void wxGUIAppTraitsBase::ScheduleForDestroy(wxObject *object)
 
571
{
 
572
    if ( !wxPendingDelete.Member(object) )
 
573
        wxPendingDelete.Append(object);
 
574
}
 
575
 
 
576
void wxGUIAppTraitsBase::RemoveFromPendingDelete(wxObject *object)
 
577
{
 
578
    wxPendingDelete.DeleteObject(object);
 
579
}
 
580
 
 
581
#if wxUSE_SOCKETS
 
582
 
 
583
#if defined(__WINDOWS__)
 
584
    #include "wx/msw/gsockmsw.h"
 
585
#elif defined(__UNIX__) || defined(__DARWIN__) || defined(__OS2__)
 
586
    #include "wx/unix/gsockunx.h"
 
587
#elif defined(__WXMAC__)
 
588
  #include <MacHeaders.c>
 
589
  #define OTUNIXERRORS 1
 
590
  #include <OpenTransport.h>
 
591
  #include <OpenTransportProviders.h>
 
592
  #include <OpenTptInternet.h>
 
593
 
 
594
  #include "wx/mac/gsockmac.h"
 
595
#else
 
596
    #error "Must include correct GSocket header here"
 
597
#endif
 
598
 
 
599
GSocketGUIFunctionsTable* wxGUIAppTraitsBase::GetSocketGUIFunctionsTable()
 
600
{
 
601
#if defined(__WXMAC__) && !defined(__DARWIN__)
 
602
    // NB: wxMac CFM does not have any GUI-specific functions in gsocket.c and
 
603
    //     so it doesn't need this table at all
 
604
    return NULL;
 
605
#else // !__WXMAC__ || __DARWIN__
 
606
    static GSocketGUIFunctionsTableConcrete table;
 
607
    return &table;
 
608
#endif // !__WXMAC__ || __DARWIN__
 
609
}
 
610
 
 
611
#endif
 
612