wxMGL wxWindow and wxApp mostly complete, now hunting bugs
[wxWidgets.git] / src / mgl / evtloop.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: mgl/evtloop.cpp
3 // Purpose: implements wxEventLoop for MGL
4 // Author: Vaclav Slavik
5 // RCS-ID: $Id$
6 // Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
7 // License: wxWindows license
8 ///////////////////////////////////////////////////////////////////////////////
9
10 // ----------------------------------------------------------------------------
11 // headers
12 // ----------------------------------------------------------------------------
13
14 #ifdef __GNUG__
15 #pragma implementation "evtloop.h"
16 #endif
17
18 // For compilers that support precompilation, includes "wx.h".
19 #include "wx/wxprec.h"
20
21 #ifdef __BORLANDC__
22 #pragma hdrstop
23 #endif
24
25 #ifndef WX_PRECOMP
26 #include "wx/window.h"
27 #include "wx/app.h"
28 #include "wx/thread.h"
29 #endif //WX_PRECOMP
30
31 #include "wx/evtloop.h"
32
33 #include "wx/mgl/private.h"
34
35 // ----------------------------------------------------------------------------
36 // wxEventLoopImpl
37 // ----------------------------------------------------------------------------
38
39 class WXDLLEXPORT wxEventLoopImpl
40 {
41 public:
42 // ctor
43 wxEventLoopImpl()
44 {
45 SetExitCode(0);
46 SetKeepLooping(TRUE);
47 }
48
49 // process a message
50 void ProcessEvent(event_t *evt);
51
52 // generate an idle message, return TRUE if more idle time requested
53 bool SendIdleMessage();
54
55 // set/get the exit code
56 void SetExitCode(int exitcode) { m_exitcode = exitcode; }
57 int GetExitCode() const { return m_exitcode; }
58
59 void SetKeepLooping(bool k) { m_keepLooping = k; }
60 bool GetKeepLooping() const { return m_keepLooping; }
61
62 private:
63
64 // the exit code of the event loop
65 int m_exitcode;
66 // FALSE if the loop should end
67 bool m_keepLooping;
68 };
69
70 // ============================================================================
71 // wxEventLoopImpl implementation
72 // ============================================================================
73
74 void wxEventLoopImpl::ProcessEvent(event_t *evt)
75 {
76 MGL_wmProcessEvent(g_winMng, evt);
77 }
78
79 bool wxEventLoopImpl::SendIdleMessage()
80 {
81 wxIdleEvent event;
82
83 return wxTheApp->ProcessEvent(event) && event.MoreRequested();
84 }
85
86 // ============================================================================
87 // wxEventLoop implementation
88 // ============================================================================
89
90 // ----------------------------------------------------------------------------
91 // wxEventLoop running and exiting
92 // ----------------------------------------------------------------------------
93
94 wxEventLoop::~wxEventLoop()
95 {
96 wxASSERT_MSG( !m_impl, _T("should have been deleted in Run()") );
97 }
98
99 bool wxEventLoop::IsRunning() const
100 {
101 return m_impl != NULL;
102 }
103
104 int wxEventLoop::Run()
105 {
106 // event loops are not recursive, you need to create another loop!
107 wxCHECK_MSG( !IsRunning(), -1, _T("can't reenter a message loop") );
108
109 m_impl = new wxEventLoopImpl;
110
111 for ( ;; )
112 {
113 #if wxUSE_THREADS
114 //wxMutexGuiLeaveOrEnter(); // FIXME_MGL - huh?
115 #endif // wxUSE_THREADS
116
117 // generate and process idle events for as long as we don't have
118 // anything else to do
119 while ( !Pending() && m_impl->SendIdleMessage() ) {}
120
121 // a message came or no more idle processing to do, sit in Dispatch()
122 // waiting for the next message
123 if ( !Dispatch() )
124 {
125 // app terminated
126 break;
127 }
128 }
129
130 int exitcode = m_impl->GetExitCode();
131 delete m_impl;
132 m_impl = NULL;
133
134 return exitcode;
135 }
136
137 void wxEventLoop::Exit(int rc)
138 {
139 wxCHECK_RET( IsRunning(), _T("can't call Exit() if not running") );
140
141 m_impl->SetExitCode(rc);
142 m_impl->SetKeepLooping(FALSE);
143 }
144
145 // ----------------------------------------------------------------------------
146 // wxEventLoop message processing dispatching
147 // ----------------------------------------------------------------------------
148
149 bool wxEventLoop::Pending() const
150 {
151 event_t evt;
152 return EVT_peekNext(&evt, EVT_EVERYEVT);
153 }
154
155 bool wxEventLoop::Dispatch()
156 {
157 wxCHECK_MSG( IsRunning(), FALSE, _T("can't call Dispatch() if not running") );
158
159 event_t evt;
160 ibool rc = EVT_getNext(&evt, EVT_EVERYEVT);
161
162 if ( !rc )
163 {
164 wxLogError(_T("events queue empty even though Pending() returned true"));
165 return FALSE;
166 }
167
168 // FIXME_MGL -- there must be some way to programatically exit
169 // the loop, like WM_QUIT under Windows -- perhaps we need custom
170 // event to indicate this??
171
172 m_impl->ProcessEvent(&evt);
173
174 return m_impl->GetKeepLooping();
175 }
176