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