]> git.saurik.com Git - wxWidgets.git/blame - src/common/event.cpp
corrected "of by 1" error in wxString::insert()
[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();
7f4dc78d 272 if (entry->m_callbackUserData) delete entry->m_callbackUserData;
fe71f65c
RR
273 delete entry;
274 node = node->Next();
275 }
276 delete m_dynamicEvents;
277 };
c801d85f
KB
278}
279
280/*
281 * Event table stuff
282 */
283
284bool wxEvtHandler::ProcessEvent(wxEvent& event)
285{
286 // An event handler can be enabled or disabled
287 if ( GetEvtHandlerEnabled() )
288 {
fe71f65c
RR
289 // Handle per-instance dynamic event tables first
290
291 if (SearchDynamicEventTable( event )) return TRUE;
292
293 // Then static per-class event tables
294
c801d85f
KB
295 const wxEventTable *table = GetEventTable();
296
297 // Try the associated validator first, if this is a window.
298 // Problem: if the event handler of the window has been replaced,
299 // this wxEvtHandler may no longer be a window.
300 // Therefore validators won't be processed if the handler
301 // has been replaced with SetEventHandler.
302 // THIS CAN BE CURED if PushEventHandler is used instead of
303 // SetEventHandler, and then processing will be passed down the
304 // chain of event handlers.
305 if (IsKindOf(CLASSINFO(wxWindow)))
306 {
307 wxWindow *win = (wxWindow *)this;
308
309 // Can only use the validator of the window which
310 // is receiving the event
311 if ( (win == event.GetEventObject()) &&
312 win->GetValidator() &&
313 win->GetValidator()->ProcessEvent(event))
314 return TRUE;
315 }
316
317 // Search upwards through the inheritance hierarchy
318 while (table)
319 {
320 if (SearchEventTable((wxEventTable&)*table, event))
321 return TRUE;
322 table = table->baseTable;
323 }
324 }
325
326 // Try going down the event handler chain
327 if ( GetNextHandler() )
328 {
329 if ( GetNextHandler()->ProcessEvent(event) )
330 return TRUE;
331 }
332
333 // Carry on up the parent-child hierarchy,
334 // but only if event is a command event: it wouldn't
335 // make sense for a parent to receive a child's size event, for example
336 if (IsKindOf(CLASSINFO(wxWindow)) && event.IsKindOf(CLASSINFO(wxCommandEvent)))
337 {
338 wxWindow *win = (wxWindow *)this;
339 wxWindow *parent = win->GetParent();
340 if (parent && !parent->IsBeingDeleted())
341 return win->GetParent()->GetEventHandler()->ProcessEvent(event);
342 }
343
344 // Last try - application object
345 if (wxTheApp && this != wxTheApp && wxTheApp->ProcessEvent(event))
346 return TRUE;
347 else
348 return FALSE;
349}
350
351bool wxEvtHandler::SearchEventTable(wxEventTable& table, wxEvent& event)
352{
353 int i = 0;
354 int commandId = event.GetId();
355
356 while (table.entries[i].m_fn != NULL)
357 {
358 if ((event.GetEventType() == table.entries[i].m_eventType) &&
359 (table.entries[i].m_id == -1 || // Match, if event spec says any id will do (id == -1)
360 (table.entries[i].m_lastId == -1 && commandId == table.entries[i].m_id) ||
361 (table.entries[i].m_lastId != -1 &&
362 (commandId >= table.entries[i].m_id && commandId <= table.entries[i].m_lastId))))
363 {
364 event.Skip(FALSE);
fe71f65c
RR
365 event.m_callbackUserData = table.entries[i].m_callbackUserData;
366
c801d85f
KB
367 (this->*((wxEventFunction) (table.entries[i].m_fn)))(event);
368
369 if ( event.GetSkipped() )
370 return FALSE;
371 else
372 return TRUE;
373 }
374 i ++;
375 }
376 return FALSE;
377}
378
fe71f65c
RR
379void wxEvtHandler::Connect( const int id, const int lastId,
380 const int eventType,
381 wxObjectEventFunction func,
382 wxObject *userData )
383{
384 wxEventTableEntry *entry = new wxEventTableEntry;
385 entry->m_id = id;
386 entry->m_lastId = lastId;
387 entry->m_eventType = eventType;
388 entry->m_fn = func;
389 entry->m_callbackUserData = userData;
390
391 if (!m_dynamicEvents)
392 m_dynamicEvents = new wxList;
393
394 m_dynamicEvents->Append( (wxObject*) entry );
395}
396
397bool wxEvtHandler::SearchDynamicEventTable( wxEvent& event )
398{
399 if (!m_dynamicEvents) return FALSE;
400
401 int commandId = event.GetId();
402
403 wxNode *node = m_dynamicEvents->First();
404 while (node)
405 {
406 wxEventTableEntry *entry = (wxEventTableEntry*)node->Data();
407 if (entry->m_fn)
408 {
409 if ((event.GetEventType() == entry->m_eventType) &&
410 (entry->m_id == -1 || // Match, if event spec says any id will do (id == -1)
411 (entry->m_lastId == -1 && commandId == entry->m_id) ||
412 (entry->m_lastId != -1 &&
413 (commandId >= entry->m_id && commandId <= entry->m_lastId))))
414 {
415 event.Skip(FALSE);
416 event.m_callbackUserData = entry->m_callbackUserData;
417
418 (this->*((wxEventFunction) (entry->m_fn)))(event);
419
420 if (event.GetSkipped())
421 return FALSE;
422 else
423 return TRUE;
424 }
425 };
426 node = node->Next();
427 }
428 return FALSE;
429};
430
c801d85f
KB
431#if WXWIN_COMPATIBILITY
432void wxEvtHandler::OldOnMenuCommand(int cmd)
433{
434 if (GetNextHandler()) GetNextHandler()->OldOnMenuCommand(cmd);
435}
436
437void wxEvtHandler::OldOnMenuSelect(int cmd)
438{
439 if (GetNextHandler()) GetNextHandler()->OldOnMenuSelect(cmd);
440}
441
442void wxEvtHandler::OldOnInitMenuPopup(int pos)
443{
444 if (GetNextHandler()) GetNextHandler()->OldOnInitMenuPopup(pos);
445}
446
447void wxEvtHandler::OldOnScroll(wxCommandEvent& event)
448{
449 if (GetNextHandler()) GetNextHandler()->OldOnScroll(event);
450}
451
452void wxEvtHandler::OldOnPaint(void)
453{
454 if (GetNextHandler()) GetNextHandler()->OldOnPaint();
455}
456void wxEvtHandler::OldOnSize(int width, int height)
457{
458 if (GetNextHandler()) GetNextHandler()->OldOnSize(width, height);
459}
460
461void wxEvtHandler::OldOnMove(int x, int y)
462{
463 if (GetNextHandler()) GetNextHandler()->OldOnMove(x, y);
464}
465
466void wxEvtHandler::OldOnMouseEvent(wxMouseEvent& event)
467{
468 if (GetNextHandler()) GetNextHandler()->OldOnMouseEvent(event);
469}
470
471void wxEvtHandler::OldOnChar(wxKeyEvent& event)
472{
473 if (GetNextHandler()) GetNextHandler()->OldOnChar(event);
474}
475
476// Under Windows, we can intercept character input per dialog or frame
477bool wxEvtHandler::OldOnCharHook(wxKeyEvent& event)
478{
479 if (GetNextHandler()) return GetNextHandler()->OldOnCharHook(event);
480 else return FALSE;
481}
482
483void wxEvtHandler::OldOnActivate(bool active)
484{
485 if (GetNextHandler()) GetNextHandler()->OldOnActivate(active);
486}
487
488void wxEvtHandler::OldOnSetFocus(void)
489{
490 if (GetNextHandler()) GetNextHandler()->OldOnSetFocus();
491}
492
493void wxEvtHandler::OldOnKillFocus(void)
494{
495 if (GetNextHandler()) GetNextHandler()->OldOnKillFocus();
496}
497
498bool wxEvtHandler::OldOnSysColourChange(void)
499{
500 if (GetNextHandler()) return GetNextHandler()->OldOnSysColourChange();
501 return FALSE;
502}
503
504void wxEvtHandler::OldOnDropFiles(int n, char *files[], int x, int y)
505{
506 if (GetNextHandler()) GetNextHandler()->OldOnDropFiles(n, files, x, y);
507}
508#endif
509
510bool wxEvtHandler::OnClose(void)
511{
512 if (GetNextHandler()) return GetNextHandler()->OnClose();
513 else return FALSE;
514}
515
516