]> git.saurik.com Git - wxWidgets.git/blob - src/common/event.cpp
*** empty log message ***
[wxWidgets.git] / src / common / event.cpp
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
35 IMPLEMENT_DYNAMIC_CLASS(wxEvtHandler, wxObject)
36 IMPLEMENT_ABSTRACT_CLASS(wxEvent, wxObject)
37 IMPLEMENT_DYNAMIC_CLASS(wxCommandEvent, wxEvent)
38 IMPLEMENT_DYNAMIC_CLASS(wxScrollEvent, wxCommandEvent)
39 IMPLEMENT_DYNAMIC_CLASS(wxMouseEvent, wxEvent)
40 IMPLEMENT_DYNAMIC_CLASS(wxKeyEvent, wxEvent)
41 IMPLEMENT_DYNAMIC_CLASS(wxSizeEvent, wxEvent)
42 IMPLEMENT_DYNAMIC_CLASS(wxPaintEvent, wxEvent)
43 IMPLEMENT_DYNAMIC_CLASS(wxEraseEvent, wxEvent)
44 IMPLEMENT_DYNAMIC_CLASS(wxMoveEvent, wxEvent)
45 IMPLEMENT_DYNAMIC_CLASS(wxFocusEvent, wxEvent)
46 IMPLEMENT_DYNAMIC_CLASS(wxCloseEvent, wxEvent)
47 IMPLEMENT_DYNAMIC_CLASS(wxShowEvent, wxEvent)
48 IMPLEMENT_DYNAMIC_CLASS(wxMaximizeEvent, wxEvent)
49 IMPLEMENT_DYNAMIC_CLASS(wxIconizeEvent, wxEvent)
50 IMPLEMENT_DYNAMIC_CLASS(wxMenuEvent, wxEvent)
51 IMPLEMENT_DYNAMIC_CLASS(wxJoystickEvent, wxEvent)
52 IMPLEMENT_DYNAMIC_CLASS(wxDropFilesEvent, wxEvent)
53 IMPLEMENT_DYNAMIC_CLASS(wxActivateEvent, wxEvent)
54 IMPLEMENT_DYNAMIC_CLASS(wxInitDialogEvent, wxEvent)
55 IMPLEMENT_DYNAMIC_CLASS(wxSysColourChangedEvent, wxEvent)
56 IMPLEMENT_DYNAMIC_CLASS(wxIdleEvent, wxEvent)
57 IMPLEMENT_DYNAMIC_CLASS(wxUpdateUIEvent, wxEvent)
58
59 const wxEventTable *wxEvtHandler::GetEventTable() const { return &wxEvtHandler::sm_eventTable; }
60
61 const wxEventTable wxEvtHandler::sm_eventTable =
62 { NULL, &wxEvtHandler::sm_eventTableEntries[0] };
63
64 const 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
77 wxEvent::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;
85 }
86
87 /*
88 * Command events
89 *
90 */
91
92 wxCommandEvent::wxCommandEvent(WXTYPE commandType, int theId)
93 {
94 m_eventType = commandType;
95 m_clientData = NULL;
96 m_extraLong = 0;
97 m_commandInt = 0;
98 m_id = theId;
99 m_commandString = NULL;
100 }
101
102 /*
103 * Scroll events
104 */
105
106 wxScrollEvent::wxScrollEvent(WXTYPE commandType, int id, int pos, int orient):
107 wxCommandEvent(commandType, id)
108 {
109 m_extraLong = orient;
110 m_commandInt = pos;
111 }
112
113
114 /*
115 * Mouse events
116 *
117 */
118
119 wxMouseEvent::wxMouseEvent(WXTYPE commandType)
120 {
121 m_eventType = commandType;
122 m_metaDown = FALSE;
123 m_altDown = FALSE;
124 m_controlDown = FALSE;
125 m_shiftDown = FALSE;
126 }
127
128 // True if was a button dclick event (1 = left, 2 = middle, 3 = right)
129 // or any button dclick event (but = -1)
130 bool wxMouseEvent::ButtonDClick(int but) const
131 {
132 switch (but) {
133 case -1:
134 return (LeftDClick() || MiddleDClick() || RightDClick());
135 case 1:
136 return LeftDClick();
137 case 2:
138 return MiddleDClick();
139 case 3:
140 return RightDClick();
141 default:
142 return FALSE;
143 }
144 // NOTREACHED
145 }
146
147 // True if was a button down event (1 = left, 2 = middle, 3 = right)
148 // or any button down event (but = -1)
149 bool wxMouseEvent::ButtonDown(int but) const
150 {
151 switch (but) {
152 case -1:
153 return (LeftDown() || MiddleDown() || RightDown());
154 case 1:
155 return LeftDown();
156 case 2:
157 return MiddleDown();
158 case 3:
159 return RightDown();
160 default:
161 return FALSE;
162 }
163 // NOTREACHED
164 }
165
166 // True if was a button up event (1 = left, 2 = middle, 3 = right)
167 // or any button up event (but = -1)
168 bool wxMouseEvent::ButtonUp(int but) const
169 {
170 switch (but) {
171 case -1:
172 return (LeftUp() || MiddleUp() || RightUp());
173 case 1:
174 return LeftUp();
175 case 2:
176 return MiddleUp();
177 case 3:
178 return RightUp();
179 default:
180 return FALSE;
181 }
182 // NOTREACHED
183 }
184
185 // True if the given button is currently changing state
186 bool wxMouseEvent::Button(int but) const
187 {
188 switch (but) {
189 case -1:
190 return (ButtonUp(-1) || ButtonDown(-1) || ButtonDClick(-1)) ;
191 case 1:
192 return (LeftDown() || LeftUp() || LeftDClick());
193 case 2:
194 return (MiddleDown() || MiddleUp() || MiddleDClick());
195 case 3:
196 return (RightDown() || RightUp() || RightDClick());
197 default:
198 return FALSE;
199 }
200 // NOTREACHED
201 }
202
203 bool wxMouseEvent::ButtonIsDown(int but) const
204 {
205 switch (but) {
206 case -1:
207 return (LeftIsDown() || MiddleIsDown() || RightIsDown());
208 case 1:
209 return LeftIsDown();
210 case 2:
211 return MiddleIsDown();
212 case 3:
213 return RightIsDown();
214 default:
215 return FALSE;
216 }
217 // NOTREACHED
218 }
219
220 // Find the logical position of the event given the DC
221 wxPoint wxMouseEvent::GetLogicalPosition(const wxDC& dc) const
222 {
223 wxPoint pt(dc.DeviceToLogicalX(m_x), dc.DeviceToLogicalY(m_y));
224 return pt;
225 }
226
227
228 /*
229 * Keyboard events
230 *
231 */
232
233 wxKeyEvent::wxKeyEvent(WXTYPE type)
234 {
235 m_eventType = type;
236 m_shiftDown = FALSE;
237 m_controlDown = FALSE;
238 m_metaDown = FALSE;
239 m_altDown = FALSE;
240 m_keyCode = 0;
241 }
242
243 /*
244 * Event handler
245 */
246
247 wxEvtHandler::wxEvtHandler(void)
248 {
249 m_clientData = NULL;
250 m_nextHandler = NULL;
251 m_previousHandler = NULL;
252 m_enabled = TRUE;
253 }
254
255 wxEvtHandler::~wxEvtHandler(void)
256 {
257 // Takes itself out of the list of handlers
258 if (m_previousHandler)
259 m_previousHandler->m_nextHandler = m_nextHandler;
260
261 if (m_nextHandler)
262 m_nextHandler->m_previousHandler = m_previousHandler;
263 }
264
265 /*
266 * Event table stuff
267 */
268
269 bool wxEvtHandler::ProcessEvent(wxEvent& event)
270 {
271 // An event handler can be enabled or disabled
272 if ( GetEvtHandlerEnabled() )
273 {
274 const wxEventTable *table = GetEventTable();
275
276 // Try the associated validator first, if this is a window.
277 // Problem: if the event handler of the window has been replaced,
278 // this wxEvtHandler may no longer be a window.
279 // Therefore validators won't be processed if the handler
280 // has been replaced with SetEventHandler.
281 // THIS CAN BE CURED if PushEventHandler is used instead of
282 // SetEventHandler, and then processing will be passed down the
283 // chain of event handlers.
284 if (IsKindOf(CLASSINFO(wxWindow)))
285 {
286 wxWindow *win = (wxWindow *)this;
287
288 // Can only use the validator of the window which
289 // is receiving the event
290 if ( (win == event.GetEventObject()) &&
291 win->GetValidator() &&
292 win->GetValidator()->ProcessEvent(event))
293 return TRUE;
294 }
295
296 // Search upwards through the inheritance hierarchy
297 while (table)
298 {
299 if (SearchEventTable((wxEventTable&)*table, event))
300 return TRUE;
301 table = table->baseTable;
302 }
303 }
304
305 // Try going down the event handler chain
306 if ( GetNextHandler() )
307 {
308 if ( GetNextHandler()->ProcessEvent(event) )
309 return TRUE;
310 }
311
312 // Carry on up the parent-child hierarchy,
313 // but only if event is a command event: it wouldn't
314 // make sense for a parent to receive a child's size event, for example
315 if (IsKindOf(CLASSINFO(wxWindow)) && event.IsKindOf(CLASSINFO(wxCommandEvent)))
316 {
317 wxWindow *win = (wxWindow *)this;
318 wxWindow *parent = win->GetParent();
319 if (parent && !parent->IsBeingDeleted())
320 return win->GetParent()->GetEventHandler()->ProcessEvent(event);
321 }
322
323 // Last try - application object
324 if (wxTheApp && this != wxTheApp && wxTheApp->ProcessEvent(event))
325 return TRUE;
326 else
327 return FALSE;
328 }
329
330 bool wxEvtHandler::SearchEventTable(wxEventTable& table, wxEvent& event)
331 {
332 int i = 0;
333 int commandId = event.GetId();
334
335 while (table.entries[i].m_fn != NULL)
336 {
337 if ((event.GetEventType() == table.entries[i].m_eventType) &&
338 (table.entries[i].m_id == -1 || // Match, if event spec says any id will do (id == -1)
339 (table.entries[i].m_lastId == -1 && commandId == table.entries[i].m_id) ||
340 (table.entries[i].m_lastId != -1 &&
341 (commandId >= table.entries[i].m_id && commandId <= table.entries[i].m_lastId))))
342 {
343 event.Skip(FALSE);
344
345 (this->*((wxEventFunction) (table.entries[i].m_fn)))(event);
346
347 if ( event.GetSkipped() )
348 return FALSE;
349 else
350 return TRUE;
351 }
352 i ++;
353 }
354 return FALSE;
355 }
356
357 #if WXWIN_COMPATIBILITY
358 void wxEvtHandler::OldOnMenuCommand(int cmd)
359 {
360 if (GetNextHandler()) GetNextHandler()->OldOnMenuCommand(cmd);
361 }
362
363 void wxEvtHandler::OldOnMenuSelect(int cmd)
364 {
365 if (GetNextHandler()) GetNextHandler()->OldOnMenuSelect(cmd);
366 }
367
368 void wxEvtHandler::OldOnInitMenuPopup(int pos)
369 {
370 if (GetNextHandler()) GetNextHandler()->OldOnInitMenuPopup(pos);
371 }
372
373 void wxEvtHandler::OldOnScroll(wxCommandEvent& event)
374 {
375 if (GetNextHandler()) GetNextHandler()->OldOnScroll(event);
376 }
377
378 void wxEvtHandler::OldOnPaint(void)
379 {
380 if (GetNextHandler()) GetNextHandler()->OldOnPaint();
381 }
382 void wxEvtHandler::OldOnSize(int width, int height)
383 {
384 if (GetNextHandler()) GetNextHandler()->OldOnSize(width, height);
385 }
386
387 void wxEvtHandler::OldOnMove(int x, int y)
388 {
389 if (GetNextHandler()) GetNextHandler()->OldOnMove(x, y);
390 }
391
392 void wxEvtHandler::OldOnMouseEvent(wxMouseEvent& event)
393 {
394 if (GetNextHandler()) GetNextHandler()->OldOnMouseEvent(event);
395 }
396
397 void wxEvtHandler::OldOnChar(wxKeyEvent& event)
398 {
399 if (GetNextHandler()) GetNextHandler()->OldOnChar(event);
400 }
401
402 // Under Windows, we can intercept character input per dialog or frame
403 bool wxEvtHandler::OldOnCharHook(wxKeyEvent& event)
404 {
405 if (GetNextHandler()) return GetNextHandler()->OldOnCharHook(event);
406 else return FALSE;
407 }
408
409 void wxEvtHandler::OldOnActivate(bool active)
410 {
411 if (GetNextHandler()) GetNextHandler()->OldOnActivate(active);
412 }
413
414 void wxEvtHandler::OldOnSetFocus(void)
415 {
416 if (GetNextHandler()) GetNextHandler()->OldOnSetFocus();
417 }
418
419 void wxEvtHandler::OldOnKillFocus(void)
420 {
421 if (GetNextHandler()) GetNextHandler()->OldOnKillFocus();
422 }
423
424 bool wxEvtHandler::OldOnSysColourChange(void)
425 {
426 if (GetNextHandler()) return GetNextHandler()->OldOnSysColourChange();
427 return FALSE;
428 }
429
430 void wxEvtHandler::OldOnDropFiles(int n, char *files[], int x, int y)
431 {
432 if (GetNextHandler()) GetNextHandler()->OldOnDropFiles(n, files, x, y);
433 }
434 #endif
435
436 bool wxEvtHandler::OnClose(void)
437 {
438 if (GetNextHandler()) return GetNextHandler()->OnClose();
439 else return FALSE;
440 }
441
442