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