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