]> git.saurik.com Git - wxWidgets.git/blob - src/common/event.cpp
*** empty log message ***
[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 = 0;
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(WXTYPE 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(WXTYPE 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(WXTYPE 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(WXTYPE 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 delete entry;
273 node = node->Next();
274 }
275 delete m_dynamicEvents;
276 };
277 }
278
279 /*
280 * Event table stuff
281 */
282
283 bool wxEvtHandler::ProcessEvent(wxEvent& event)
284 {
285 // An event handler can be enabled or disabled
286 if ( GetEvtHandlerEnabled() )
287 {
288 // Handle per-instance dynamic event tables first
289
290 if (SearchDynamicEventTable( event )) return TRUE;
291
292 // Then static per-class event tables
293
294 const wxEventTable *table = GetEventTable();
295
296 // Try the associated validator first, if this is a window.
297 // Problem: if the event handler of the window has been replaced,
298 // this wxEvtHandler may no longer be a window.
299 // Therefore validators won't be processed if the handler
300 // has been replaced with SetEventHandler.
301 // THIS CAN BE CURED if PushEventHandler is used instead of
302 // SetEventHandler, and then processing will be passed down the
303 // chain of event handlers.
304 if (IsKindOf(CLASSINFO(wxWindow)))
305 {
306 wxWindow *win = (wxWindow *)this;
307
308 // Can only use the validator of the window which
309 // is receiving the event
310 if ( (win == event.GetEventObject()) &&
311 win->GetValidator() &&
312 win->GetValidator()->ProcessEvent(event))
313 return TRUE;
314 }
315
316 // Search upwards through the inheritance hierarchy
317 while (table)
318 {
319 if (SearchEventTable((wxEventTable&)*table, event))
320 return TRUE;
321 table = table->baseTable;
322 }
323 }
324
325 // Try going down the event handler chain
326 if ( GetNextHandler() )
327 {
328 if ( GetNextHandler()->ProcessEvent(event) )
329 return TRUE;
330 }
331
332 // Carry on up the parent-child hierarchy,
333 // but only if event is a command event: it wouldn't
334 // make sense for a parent to receive a child's size event, for example
335 if (IsKindOf(CLASSINFO(wxWindow)) && event.IsKindOf(CLASSINFO(wxCommandEvent)))
336 {
337 wxWindow *win = (wxWindow *)this;
338 wxWindow *parent = win->GetParent();
339 if (parent && !parent->IsBeingDeleted())
340 return win->GetParent()->GetEventHandler()->ProcessEvent(event);
341 }
342
343 // Last try - application object
344 if (wxTheApp && this != wxTheApp && wxTheApp->ProcessEvent(event))
345 return TRUE;
346 else
347 return FALSE;
348 }
349
350 bool wxEvtHandler::SearchEventTable(wxEventTable& table, wxEvent& event)
351 {
352 int i = 0;
353 int commandId = event.GetId();
354
355 while (table.entries[i].m_fn != NULL)
356 {
357 if ((event.GetEventType() == table.entries[i].m_eventType) &&
358 (table.entries[i].m_id == -1 || // Match, if event spec says any id will do (id == -1)
359 (table.entries[i].m_lastId == -1 && commandId == table.entries[i].m_id) ||
360 (table.entries[i].m_lastId != -1 &&
361 (commandId >= table.entries[i].m_id && commandId <= table.entries[i].m_lastId))))
362 {
363 event.Skip(FALSE);
364 event.m_callbackUserData = table.entries[i].m_callbackUserData;
365
366 (this->*((wxEventFunction) (table.entries[i].m_fn)))(event);
367
368 if ( event.GetSkipped() )
369 return FALSE;
370 else
371 return TRUE;
372 }
373 i ++;
374 }
375 return FALSE;
376 }
377
378 void wxEvtHandler::Connect( const int id, const int lastId,
379 const int eventType,
380 wxObjectEventFunction func,
381 wxObject *userData )
382 {
383 wxEventTableEntry *entry = new wxEventTableEntry;
384 entry->m_id = id;
385 entry->m_lastId = lastId;
386 entry->m_eventType = eventType;
387 entry->m_fn = func;
388 entry->m_callbackUserData = userData;
389
390 if (!m_dynamicEvents)
391 m_dynamicEvents = new wxList;
392
393 m_dynamicEvents->Append( (wxObject*) entry );
394 }
395
396 bool wxEvtHandler::SearchDynamicEventTable( wxEvent& event )
397 {
398 if (!m_dynamicEvents) return FALSE;
399
400 int commandId = event.GetId();
401
402 wxNode *node = m_dynamicEvents->First();
403 while (node)
404 {
405 wxEventTableEntry *entry = (wxEventTableEntry*)node->Data();
406 if (entry->m_fn)
407 {
408 if ((event.GetEventType() == entry->m_eventType) &&
409 (entry->m_id == -1 || // Match, if event spec says any id will do (id == -1)
410 (entry->m_lastId == -1 && commandId == entry->m_id) ||
411 (entry->m_lastId != -1 &&
412 (commandId >= entry->m_id && commandId <= entry->m_lastId))))
413 {
414 event.Skip(FALSE);
415 event.m_callbackUserData = entry->m_callbackUserData;
416
417 (this->*((wxEventFunction) (entry->m_fn)))(event);
418
419 if (event.GetSkipped())
420 return FALSE;
421 else
422 return TRUE;
423 }
424 };
425 node = node->Next();
426 }
427 return FALSE;
428 };
429
430 #if WXWIN_COMPATIBILITY
431 void wxEvtHandler::OldOnMenuCommand(int cmd)
432 {
433 if (GetNextHandler()) GetNextHandler()->OldOnMenuCommand(cmd);
434 }
435
436 void wxEvtHandler::OldOnMenuSelect(int cmd)
437 {
438 if (GetNextHandler()) GetNextHandler()->OldOnMenuSelect(cmd);
439 }
440
441 void wxEvtHandler::OldOnInitMenuPopup(int pos)
442 {
443 if (GetNextHandler()) GetNextHandler()->OldOnInitMenuPopup(pos);
444 }
445
446 void wxEvtHandler::OldOnScroll(wxCommandEvent& event)
447 {
448 if (GetNextHandler()) GetNextHandler()->OldOnScroll(event);
449 }
450
451 void wxEvtHandler::OldOnPaint(void)
452 {
453 if (GetNextHandler()) GetNextHandler()->OldOnPaint();
454 }
455 void wxEvtHandler::OldOnSize(int width, int height)
456 {
457 if (GetNextHandler()) GetNextHandler()->OldOnSize(width, height);
458 }
459
460 void wxEvtHandler::OldOnMove(int x, int y)
461 {
462 if (GetNextHandler()) GetNextHandler()->OldOnMove(x, y);
463 }
464
465 void wxEvtHandler::OldOnMouseEvent(wxMouseEvent& event)
466 {
467 if (GetNextHandler()) GetNextHandler()->OldOnMouseEvent(event);
468 }
469
470 void wxEvtHandler::OldOnChar(wxKeyEvent& event)
471 {
472 if (GetNextHandler()) GetNextHandler()->OldOnChar(event);
473 }
474
475 // Under Windows, we can intercept character input per dialog or frame
476 bool wxEvtHandler::OldOnCharHook(wxKeyEvent& event)
477 {
478 if (GetNextHandler()) return GetNextHandler()->OldOnCharHook(event);
479 else return FALSE;
480 }
481
482 void wxEvtHandler::OldOnActivate(bool active)
483 {
484 if (GetNextHandler()) GetNextHandler()->OldOnActivate(active);
485 }
486
487 void wxEvtHandler::OldOnSetFocus(void)
488 {
489 if (GetNextHandler()) GetNextHandler()->OldOnSetFocus();
490 }
491
492 void wxEvtHandler::OldOnKillFocus(void)
493 {
494 if (GetNextHandler()) GetNextHandler()->OldOnKillFocus();
495 }
496
497 bool wxEvtHandler::OldOnSysColourChange(void)
498 {
499 if (GetNextHandler()) return GetNextHandler()->OldOnSysColourChange();
500 return FALSE;
501 }
502
503 void wxEvtHandler::OldOnDropFiles(int n, char *files[], int x, int y)
504 {
505 if (GetNextHandler()) GetNextHandler()->OldOnDropFiles(n, files, x, y);
506 }
507 #endif
508
509 bool wxEvtHandler::OnClose(void)
510 {
511 if (GetNextHandler()) return GetNextHandler()->OnClose();
512 else return FALSE;
513 }
514
515