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