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