]> git.saurik.com Git - wxWidgets.git/blob - src/common/event.cpp
Fix for TextCtrl problem as reported by Vegh
[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, wxCommandEvent)
58 IMPLEMENT_DYNAMIC_CLASS(wxNavigationKeyEvent, wxCommandEvent)
59 IMPLEMENT_DYNAMIC_CLASS(wxPaletteChangedEvent, wxEvent)
60 IMPLEMENT_DYNAMIC_CLASS(wxQueryNewPaletteEvent, wxEvent)
61
62 const wxEventTable *wxEvtHandler::GetEventTable() const { return &wxEvtHandler::sm_eventTable; }
63
64 const wxEventTable wxEvtHandler::sm_eventTable =
65 { (const wxEventTable *) NULL, &wxEvtHandler::sm_eventTableEntries[0] };
66
67 const 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 };
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
87 wxEvent::wxEvent(int theId)
88 {
89 m_eventType = wxEVT_NULL;
90 m_eventObject = (wxObject *) NULL;
91 m_eventHandle = (char *) NULL;
92 m_timeStamp = 0;
93 m_id = theId;
94 m_skipped = FALSE;
95 m_callbackUserData = (wxObject *) NULL;
96 }
97
98 /*
99 * Command events
100 *
101 */
102
103 wxCommandEvent::wxCommandEvent(wxEventType commandType, int theId)
104 {
105 m_eventType = commandType;
106 m_clientData = (char *) NULL;
107 m_extraLong = 0;
108 m_commandInt = 0;
109 m_id = theId;
110 m_commandString = (char *) NULL;
111 }
112
113 /*
114 * Scroll events
115 */
116
117 wxScrollEvent::wxScrollEvent(wxEventType commandType, int id, int pos, int orient):
118 wxCommandEvent(commandType, id)
119 {
120 m_extraLong = orient;
121 m_commandInt = pos;
122 }
123
124
125 /*
126 * Mouse events
127 *
128 */
129
130 wxMouseEvent::wxMouseEvent(wxEventType commandType)
131 {
132 m_eventType = commandType;
133 m_metaDown = FALSE;
134 m_altDown = FALSE;
135 m_controlDown = FALSE;
136 m_shiftDown = FALSE;
137 m_leftDown = FALSE;
138 m_rightDown = FALSE;
139 m_middleDown = FALSE;
140 m_x = 0;
141 m_y = 0;
142 }
143
144 // True if was a button dclick event (1 = left, 2 = middle, 3 = right)
145 // or any button dclick event (but = -1)
146 bool wxMouseEvent::ButtonDClick(int but) const
147 {
148 switch (but) {
149 case -1:
150 return (LeftDClick() || MiddleDClick() || RightDClick());
151 case 1:
152 return LeftDClick();
153 case 2:
154 return MiddleDClick();
155 case 3:
156 return RightDClick();
157 default:
158 return FALSE;
159 }
160 // NOTREACHED
161 }
162
163 // True if was a button down event (1 = left, 2 = middle, 3 = right)
164 // or any button down event (but = -1)
165 bool wxMouseEvent::ButtonDown(int but) const
166 {
167 switch (but) {
168 case -1:
169 return (LeftDown() || MiddleDown() || RightDown());
170 case 1:
171 return LeftDown();
172 case 2:
173 return MiddleDown();
174 case 3:
175 return RightDown();
176 default:
177 return FALSE;
178 }
179 // NOTREACHED
180 }
181
182 // True if was a button up event (1 = left, 2 = middle, 3 = right)
183 // or any button up event (but = -1)
184 bool wxMouseEvent::ButtonUp(int but) const
185 {
186 switch (but) {
187 case -1:
188 return (LeftUp() || MiddleUp() || RightUp());
189 case 1:
190 return LeftUp();
191 case 2:
192 return MiddleUp();
193 case 3:
194 return RightUp();
195 default:
196 return FALSE;
197 }
198 // NOTREACHED
199 }
200
201 // True if the given button is currently changing state
202 bool wxMouseEvent::Button(int but) const
203 {
204 switch (but) {
205 case -1:
206 return (ButtonUp(-1) || ButtonDown(-1) || ButtonDClick(-1)) ;
207 case 1:
208 return (LeftDown() || LeftUp() || LeftDClick());
209 case 2:
210 return (MiddleDown() || MiddleUp() || MiddleDClick());
211 case 3:
212 return (RightDown() || RightUp() || RightDClick());
213 default:
214 return FALSE;
215 }
216 // NOTREACHED
217 }
218
219 bool wxMouseEvent::ButtonIsDown(int but) const
220 {
221 switch (but) {
222 case -1:
223 return (LeftIsDown() || MiddleIsDown() || RightIsDown());
224 case 1:
225 return LeftIsDown();
226 case 2:
227 return MiddleIsDown();
228 case 3:
229 return RightIsDown();
230 default:
231 return FALSE;
232 }
233 // NOTREACHED
234 }
235
236 // Find the logical position of the event given the DC
237 wxPoint wxMouseEvent::GetLogicalPosition(const wxDC& dc) const
238 {
239 wxPoint pt(dc.DeviceToLogicalX(m_x), dc.DeviceToLogicalY(m_y));
240 return pt;
241 }
242
243
244 /*
245 * Keyboard events
246 *
247 */
248
249 wxKeyEvent::wxKeyEvent(wxEventType type)
250 {
251 m_eventType = type;
252 m_shiftDown = FALSE;
253 m_controlDown = FALSE;
254 m_metaDown = FALSE;
255 m_altDown = FALSE;
256 m_keyCode = 0;
257 }
258
259 /*
260 * Event handler
261 */
262
263 wxEvtHandler::wxEvtHandler(void)
264 {
265 m_clientData = (char *) NULL;
266 m_nextHandler = (wxEvtHandler *) NULL;
267 m_previousHandler = (wxEvtHandler *) NULL;
268 m_enabled = TRUE;
269 m_dynamicEvents = (wxList *) NULL;
270 }
271
272 wxEvtHandler::~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;
280
281 if (m_dynamicEvents)
282 {
283 wxNode *node = m_dynamicEvents->First();
284 while (node)
285 {
286 wxEventTableEntry *entry = (wxEventTableEntry*)node->Data();
287 if (entry->m_callbackUserData) delete entry->m_callbackUserData;
288 delete entry;
289 node = node->Next();
290 }
291 delete m_dynamicEvents;
292 };
293 }
294
295 /*
296 * Event table stuff
297 */
298
299 bool wxEvtHandler::ProcessEvent(wxEvent& event)
300 {
301 // An event handler can be enabled or disabled
302 if ( GetEvtHandlerEnabled() )
303 {
304 // Handle per-instance dynamic event tables first
305
306 if (SearchDynamicEventTable( event )) return TRUE;
307
308 // Then static per-class event tables
309
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 {
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;
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 {
344 if ( GetNextHandler()->ProcessEvent(event) )
345 return TRUE;
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;
354 wxWindow *parent = win->GetParent();
355 if (parent && !parent->IsBeingDeleted())
356 return win->GetParent()->GetEventHandler()->ProcessEvent(event);
357 }
358
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))
364 return TRUE;
365 else
366 return FALSE;
367 }
368
369 bool wxEvtHandler::SearchEventTable(wxEventTable& table, wxEvent& event)
370 {
371 int i = 0;
372 int commandId = event.GetId();
373
374 while (table.entries[i].m_fn !=
375 #ifdef __SGI_CC__
376 0L
377 #else
378 NULL
379 #endif
380 )
381 {
382 // wxEventType eventType = (wxEventType) table.entries[i].m_eventType;
383
384 if ((event.GetEventType() == table.entries[i].m_eventType) &&
385 (table.entries[i].m_id == -1 || // Match, if event spec says any id will do (id == -1)
386 (table.entries[i].m_lastId == -1 && commandId == table.entries[i].m_id) ||
387 (table.entries[i].m_lastId != -1 &&
388 (commandId >= table.entries[i].m_id && commandId <= table.entries[i].m_lastId))))
389 {
390 event.Skip(FALSE);
391 event.m_callbackUserData = table.entries[i].m_callbackUserData;
392
393 (this->*((wxEventFunction) (table.entries[i].m_fn)))(event);
394
395 if ( event.GetSkipped() )
396 return FALSE;
397 else
398 return TRUE;
399 }
400 i ++;
401 }
402 return FALSE;
403 }
404
405 void wxEvtHandler::Connect( int id, int lastId,
406 int eventType,
407 wxObjectEventFunction func,
408 wxObject *userData )
409 {
410 wxEventTableEntry *entry = new wxEventTableEntry;
411 entry->m_id = id;
412 entry->m_lastId = lastId;
413 entry->m_eventType = eventType;
414 entry->m_fn = func;
415 entry->m_callbackUserData = userData;
416
417 if (!m_dynamicEvents)
418 m_dynamicEvents = new wxList;
419
420 m_dynamicEvents->Append( (wxObject*) entry );
421 }
422
423 bool wxEvtHandler::SearchDynamicEventTable( wxEvent& event )
424 {
425 if (!m_dynamicEvents) return FALSE;
426
427 int commandId = event.GetId();
428
429 wxNode *node = m_dynamicEvents->First();
430 while (node)
431 {
432 wxEventTableEntry *entry = (wxEventTableEntry*)node->Data();
433
434 // wxEventType eventType = (wxEventType) entry->m_eventType;
435
436 if (entry->m_fn)
437 {
438 if ((event.GetEventType() == entry->m_eventType) &&
439 (entry->m_id == -1 || // Match, if event spec says any id will do (id == -1)
440 (entry->m_lastId == -1 && commandId == entry->m_id) ||
441 (entry->m_lastId != -1 &&
442 (commandId >= entry->m_id && commandId <= entry->m_lastId))))
443 {
444 event.Skip(FALSE);
445 event.m_callbackUserData = entry->m_callbackUserData;
446
447 (this->*((wxEventFunction) (entry->m_fn)))(event);
448
449 if (event.GetSkipped())
450 return FALSE;
451 else
452 return TRUE;
453 }
454 };
455 node = node->Next();
456 }
457 return FALSE;
458 };
459
460 bool wxEvtHandler::OnClose(void)
461 {
462 if (GetNextHandler()) return GetNextHandler()->OnClose();
463 else return FALSE;
464 }
465
466