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