]> git.saurik.com Git - wxWidgets.git/blob - src/common/event.cpp
Various bug fixes, cosmetic changes
[wxWidgets.git] / src / common / event.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: event.cpp
3 // Purpose: Event classes
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 01/02/97
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "event.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/defs.h"
25 #include "wx/control.h"
26 #include "wx/utils.h"
27 #include "wx/app.h"
28 #include "wx/dc.h"
29 #endif
30
31 #include "wx/event.h"
32 #include "wx/validate.h"
33
34 #if !USE_SHARED_LIBRARY
35 IMPLEMENT_DYNAMIC_CLASS(wxEvtHandler, wxObject)
36 IMPLEMENT_ABSTRACT_CLASS(wxEvent, wxObject)
37 IMPLEMENT_DYNAMIC_CLASS(wxCommandEvent, wxEvent)
38 IMPLEMENT_DYNAMIC_CLASS(wxScrollEvent, wxCommandEvent)
39 IMPLEMENT_DYNAMIC_CLASS(wxMouseEvent, wxEvent)
40 IMPLEMENT_DYNAMIC_CLASS(wxKeyEvent, wxEvent)
41 IMPLEMENT_DYNAMIC_CLASS(wxSizeEvent, wxEvent)
42 IMPLEMENT_DYNAMIC_CLASS(wxPaintEvent, wxEvent)
43 IMPLEMENT_DYNAMIC_CLASS(wxEraseEvent, wxEvent)
44 IMPLEMENT_DYNAMIC_CLASS(wxMoveEvent, wxEvent)
45 IMPLEMENT_DYNAMIC_CLASS(wxFocusEvent, wxEvent)
46 IMPLEMENT_DYNAMIC_CLASS(wxCloseEvent, wxEvent)
47 IMPLEMENT_DYNAMIC_CLASS(wxShowEvent, wxEvent)
48 IMPLEMENT_DYNAMIC_CLASS(wxMaximizeEvent, wxEvent)
49 IMPLEMENT_DYNAMIC_CLASS(wxIconizeEvent, wxEvent)
50 IMPLEMENT_DYNAMIC_CLASS(wxMenuEvent, wxEvent)
51 IMPLEMENT_DYNAMIC_CLASS(wxJoystickEvent, wxEvent)
52 IMPLEMENT_DYNAMIC_CLASS(wxDropFilesEvent, wxEvent)
53 IMPLEMENT_DYNAMIC_CLASS(wxActivateEvent, wxEvent)
54 IMPLEMENT_DYNAMIC_CLASS(wxInitDialogEvent, wxEvent)
55 IMPLEMENT_DYNAMIC_CLASS(wxSysColourChangedEvent, wxEvent)
56 IMPLEMENT_DYNAMIC_CLASS(wxIdleEvent, wxEvent)
57 IMPLEMENT_DYNAMIC_CLASS(wxUpdateUIEvent, wxEvent)
58
59 const wxEventTable *wxEvtHandler::GetEventTable() const { return &wxEvtHandler::sm_eventTable; }
60
61 const wxEventTable wxEvtHandler::sm_eventTable =
62 { NULL, &wxEvtHandler::sm_eventTableEntries[0] };
63
64 const wxEventTableEntry wxEvtHandler::sm_eventTableEntries[] = { { 0, 0, 0, NULL } };
65
66 #endif
67
68 /*
69 * General wxWindows events, covering
70 * all interesting things that might happen (button clicking, resizing,
71 * setting text in widgets, etc.).
72 *
73 * For each completely new event type, derive a new event class.
74 *
75 */
76
77 wxEvent::wxEvent(int theId)
78 {
79 m_eventType = wxEVT_NULL;
80 m_eventObject = NULL;
81 m_eventHandle = NULL;
82 m_timeStamp = 0;
83 m_id = theId;
84 m_skipped = FALSE;
85 m_callbackUserData = NULL;
86 }
87
88 /*
89 * Command events
90 *
91 */
92
93 wxCommandEvent::wxCommandEvent(wxEventType commandType, int theId)
94 {
95 m_eventType = commandType;
96 m_clientData = NULL;
97 m_extraLong = 0;
98 m_commandInt = 0;
99 m_id = theId;
100 m_commandString = NULL;
101 }
102
103 /*
104 * Scroll events
105 */
106
107 wxScrollEvent::wxScrollEvent(wxEventType commandType, int id, int pos, int orient):
108 wxCommandEvent(commandType, id)
109 {
110 m_extraLong = orient;
111 m_commandInt = pos;
112 }
113
114
115 /*
116 * Mouse events
117 *
118 */
119
120 wxMouseEvent::wxMouseEvent(wxEventType commandType)
121 {
122 m_eventType = commandType;
123 m_metaDown = FALSE;
124 m_altDown = FALSE;
125 m_controlDown = FALSE;
126 m_shiftDown = FALSE;
127 }
128
129 // True if was a button dclick event (1 = left, 2 = middle, 3 = right)
130 // or any button dclick event (but = -1)
131 bool wxMouseEvent::ButtonDClick(int but) const
132 {
133 switch (but) {
134 case -1:
135 return (LeftDClick() || MiddleDClick() || RightDClick());
136 case 1:
137 return LeftDClick();
138 case 2:
139 return MiddleDClick();
140 case 3:
141 return RightDClick();
142 default:
143 return FALSE;
144 }
145 // NOTREACHED
146 }
147
148 // True if was a button down event (1 = left, 2 = middle, 3 = right)
149 // or any button down event (but = -1)
150 bool wxMouseEvent::ButtonDown(int but) const
151 {
152 switch (but) {
153 case -1:
154 return (LeftDown() || MiddleDown() || RightDown());
155 case 1:
156 return LeftDown();
157 case 2:
158 return MiddleDown();
159 case 3:
160 return RightDown();
161 default:
162 return FALSE;
163 }
164 // NOTREACHED
165 }
166
167 // True if was a button up event (1 = left, 2 = middle, 3 = right)
168 // or any button up event (but = -1)
169 bool wxMouseEvent::ButtonUp(int but) const
170 {
171 switch (but) {
172 case -1:
173 return (LeftUp() || MiddleUp() || RightUp());
174 case 1:
175 return LeftUp();
176 case 2:
177 return MiddleUp();
178 case 3:
179 return RightUp();
180 default:
181 return FALSE;
182 }
183 // NOTREACHED
184 }
185
186 // True if the given button is currently changing state
187 bool wxMouseEvent::Button(int but) const
188 {
189 switch (but) {
190 case -1:
191 return (ButtonUp(-1) || ButtonDown(-1) || ButtonDClick(-1)) ;
192 case 1:
193 return (LeftDown() || LeftUp() || LeftDClick());
194 case 2:
195 return (MiddleDown() || MiddleUp() || MiddleDClick());
196 case 3:
197 return (RightDown() || RightUp() || RightDClick());
198 default:
199 return FALSE;
200 }
201 // NOTREACHED
202 }
203
204 bool wxMouseEvent::ButtonIsDown(int but) const
205 {
206 switch (but) {
207 case -1:
208 return (LeftIsDown() || MiddleIsDown() || RightIsDown());
209 case 1:
210 return LeftIsDown();
211 case 2:
212 return MiddleIsDown();
213 case 3:
214 return RightIsDown();
215 default:
216 return FALSE;
217 }
218 // NOTREACHED
219 }
220
221 // Find the logical position of the event given the DC
222 wxPoint wxMouseEvent::GetLogicalPosition(const wxDC& dc) const
223 {
224 wxPoint pt(dc.DeviceToLogicalX(m_x), dc.DeviceToLogicalY(m_y));
225 return pt;
226 }
227
228
229 /*
230 * Keyboard events
231 *
232 */
233
234 wxKeyEvent::wxKeyEvent(wxEventType type)
235 {
236 m_eventType = type;
237 m_shiftDown = FALSE;
238 m_controlDown = FALSE;
239 m_metaDown = FALSE;
240 m_altDown = FALSE;
241 m_keyCode = 0;
242 }
243
244 /*
245 * Event handler
246 */
247
248 wxEvtHandler::wxEvtHandler(void)
249 {
250 m_clientData = NULL;
251 m_nextHandler = NULL;
252 m_previousHandler = NULL;
253 m_enabled = TRUE;
254 m_dynamicEvents = NULL;
255 }
256
257 wxEvtHandler::~wxEvtHandler(void)
258 {
259 // Takes itself out of the list of handlers
260 if (m_previousHandler)
261 m_previousHandler->m_nextHandler = m_nextHandler;
262
263 if (m_nextHandler)
264 m_nextHandler->m_previousHandler = m_previousHandler;
265
266 if (m_dynamicEvents)
267 {
268 wxNode *node = m_dynamicEvents->First();
269 while (node)
270 {
271 wxEventTableEntry *entry = (wxEventTableEntry*)node->Data();
272 if (entry->m_callbackUserData) delete entry->m_callbackUserData;
273 delete entry;
274 node = node->Next();
275 }
276 delete m_dynamicEvents;
277 };
278 }
279
280 /*
281 * Event table stuff
282 */
283
284 bool wxEvtHandler::ProcessEvent(wxEvent& event)
285 {
286 // An event handler can be enabled or disabled
287 if ( GetEvtHandlerEnabled() )
288 {
289 // Handle per-instance dynamic event tables first
290
291 if (SearchDynamicEventTable( event )) return TRUE;
292
293 // Then static per-class event tables
294
295 const wxEventTable *table = GetEventTable();
296
297 // Try the associated validator first, if this is a window.
298 // Problem: if the event handler of the window has been replaced,
299 // this wxEvtHandler may no longer be a window.
300 // Therefore validators won't be processed if the handler
301 // has been replaced with SetEventHandler.
302 // THIS CAN BE CURED if PushEventHandler is used instead of
303 // SetEventHandler, and then processing will be passed down the
304 // chain of event handlers.
305 if (IsKindOf(CLASSINFO(wxWindow)))
306 {
307 wxWindow *win = (wxWindow *)this;
308
309 // Can only use the validator of the window which
310 // is receiving the event
311 if ( (win == event.GetEventObject()) &&
312 win->GetValidator() &&
313 win->GetValidator()->ProcessEvent(event))
314 return TRUE;
315 }
316
317 // Search upwards through the inheritance hierarchy
318 while (table)
319 {
320 if (SearchEventTable((wxEventTable&)*table, event))
321 return TRUE;
322 table = table->baseTable;
323 }
324 }
325
326 // Try going down the event handler chain
327 if ( GetNextHandler() )
328 {
329 if ( GetNextHandler()->ProcessEvent(event) )
330 return TRUE;
331 }
332
333 // Carry on up the parent-child hierarchy,
334 // but only if event is a command event: it wouldn't
335 // make sense for a parent to receive a child's size event, for example
336 if (IsKindOf(CLASSINFO(wxWindow)) && event.IsKindOf(CLASSINFO(wxCommandEvent)))
337 {
338 wxWindow *win = (wxWindow *)this;
339 wxWindow *parent = win->GetParent();
340 if (parent && !parent->IsBeingDeleted())
341 return win->GetParent()->GetEventHandler()->ProcessEvent(event);
342 }
343
344 // Last try - application object
345 if (wxTheApp && this != wxTheApp && wxTheApp->ProcessEvent(event))
346 return TRUE;
347 else
348 return FALSE;
349 }
350
351 bool wxEvtHandler::SearchEventTable(wxEventTable& table, wxEvent& event)
352 {
353 int i = 0;
354 int commandId = event.GetId();
355
356 while (table.entries[i].m_fn != NULL)
357 {
358 wxEventType eventType = (wxEventType) table.entries[i].m_eventType;
359
360 if ((event.GetEventType() == table.entries[i].m_eventType) &&
361 (table.entries[i].m_id == -1 || // Match, if event spec says any id will do (id == -1)
362 (table.entries[i].m_lastId == -1 && commandId == table.entries[i].m_id) ||
363 (table.entries[i].m_lastId != -1 &&
364 (commandId >= table.entries[i].m_id && commandId <= table.entries[i].m_lastId))))
365 {
366 event.Skip(FALSE);
367 event.m_callbackUserData = table.entries[i].m_callbackUserData;
368
369 (this->*((wxEventFunction) (table.entries[i].m_fn)))(event);
370
371 if ( event.GetSkipped() )
372 return FALSE;
373 else
374 return TRUE;
375 }
376 i ++;
377 }
378 return FALSE;
379 }
380
381 void wxEvtHandler::Connect( int id, int lastId,
382 int eventType,
383 wxObjectEventFunction func,
384 wxObject *userData )
385 {
386 wxEventTableEntry *entry = new wxEventTableEntry;
387 entry->m_id = id;
388 entry->m_lastId = lastId;
389 entry->m_eventType = eventType;
390 entry->m_fn = func;
391 entry->m_callbackUserData = userData;
392
393 if (!m_dynamicEvents)
394 m_dynamicEvents = new wxList;
395
396 m_dynamicEvents->Append( (wxObject*) entry );
397 }
398
399 bool wxEvtHandler::SearchDynamicEventTable( wxEvent& event )
400 {
401 if (!m_dynamicEvents) return FALSE;
402
403 int commandId = event.GetId();
404
405 wxNode *node = m_dynamicEvents->First();
406 while (node)
407 {
408 wxEventTableEntry *entry = (wxEventTableEntry*)node->Data();
409 wxEventType eventType = (wxEventType) entry->m_eventType;
410
411 if (entry->m_fn)
412 {
413 if ((event.GetEventType() == entry->m_eventType) &&
414 (entry->m_id == -1 || // Match, if event spec says any id will do (id == -1)
415 (entry->m_lastId == -1 && commandId == entry->m_id) ||
416 (entry->m_lastId != -1 &&
417 (commandId >= entry->m_id && commandId <= entry->m_lastId))))
418 {
419 event.Skip(FALSE);
420 event.m_callbackUserData = entry->m_callbackUserData;
421
422 (this->*((wxEventFunction) (entry->m_fn)))(event);
423
424 if (event.GetSkipped())
425 return FALSE;
426 else
427 return TRUE;
428 }
429 };
430 node = node->Next();
431 }
432 return FALSE;
433 };
434
435 bool wxEvtHandler::OnClose(void)
436 {
437 if (GetNextHandler()) return GetNextHandler()->OnClose();
438 else return FALSE;
439 }
440
441