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