Committing in .
[wxWidgets.git] / src / motif / dialog.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: dialog.cpp
3 // Purpose: wxDialog class
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 17/09/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "dialog.h"
14 #endif
15
16 #include "wx/dialog.h"
17 #include "wx/utils.h"
18 #include "wx/frame.h"
19 #include "wx/app.h"
20 #include "wx/settings.h"
21
22 #ifdef __VMS__
23 #pragma message disable nosimpint
24 #endif
25 #include <Xm/Xm.h>
26
27 #include <X11/Shell.h>
28 #if XmVersion >= 1002
29 #include <Xm/XmAll.h>
30 #endif
31 #include <Xm/MwmUtil.h>
32 #include <Xm/Label.h>
33 #include <Xm/BulletinB.h>
34 #include <Xm/Frame.h>
35 #include <Xm/Text.h>
36 #include <Xm/DialogS.h>
37 #include <Xm/FileSB.h>
38 #include <Xm/RowColumn.h>
39 #include <Xm/LabelG.h>
40 #include <Xm/AtomMgr.h>
41 #if XmVersion > 1000
42 #include <Xm/Protocols.h>
43 #endif
44 #ifdef __VMS__
45 #pragma message enable nosimpint
46 #endif
47
48 #include "wx/motif/private.h"
49
50 static void wxCloseDialogCallback(Widget widget, XtPointer client_data, XmAnyCallbackStruct *cbs);
51 static void wxDialogBoxEventHandler (Widget wid,
52 XtPointer client_data,
53 XEvent* event,
54 Boolean *continueToDispatch);
55
56 static void wxUnmapBulletinBoard(Widget dialog, wxDialog *client,XtPointer call);
57
58 // A stack of modal_showing flags, since we can't rely
59 // on accessing wxDialog::m_modalShowing within
60 // wxDialog::Show in case a callback has deleted the wxDialog.
61 static wxList wxModalShowingStack;
62
63 // Lists to keep track of windows, so we can disable/enable them
64 // for modal dialogs
65 wxList wxModalDialogs;
66 wxList wxModelessWindows; // Frames and modeless dialogs
67 extern wxList wxPendingDelete;
68
69 #define wxUSE_INVISIBLE_RESIZE 1
70
71 #if !USE_SHARED_LIBRARY
72 IMPLEMENT_DYNAMIC_CLASS(wxDialog, wxPanel)
73
74 BEGIN_EVENT_TABLE(wxDialog, wxPanel)
75 EVT_SIZE(wxDialog::OnSize)
76 EVT_BUTTON(wxID_OK, wxDialog::OnOK)
77 EVT_BUTTON(wxID_APPLY, wxDialog::OnApply)
78 EVT_BUTTON(wxID_CANCEL, wxDialog::OnCancel)
79 EVT_CHAR_HOOK(wxDialog::OnCharHook)
80 EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged)
81 EVT_CLOSE(wxDialog::OnCloseWindow)
82 END_EVENT_TABLE()
83
84 #endif
85
86 wxDialog::wxDialog()
87 {
88 m_modalShowing = FALSE;
89 m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE);
90 }
91
92 bool wxDialog::Create(wxWindow *parent, wxWindowID id,
93 const wxString& title,
94 const wxPoint& pos,
95 const wxSize& size,
96 long style,
97 const wxString& name)
98 {
99 m_windowStyle = style;
100 m_modalShowing = FALSE;
101 m_dialogTitle = title;
102
103 m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE);
104 m_foregroundColour = *wxBLACK;
105
106 SetName(name);
107
108 if (!parent)
109 wxTopLevelWindows.Append(this);
110
111 if (parent) parent->AddChild(this);
112
113 if ( id == -1 )
114 m_windowId = (int)NewControlId();
115 else
116 m_windowId = id;
117
118 Widget parentWidget = (Widget) 0;
119 if (parent)
120 parentWidget = (Widget) parent->GetTopWidget();
121 if (!parent)
122 parentWidget = (Widget) wxTheApp->GetTopLevelWidget();
123
124 wxASSERT_MSG( (parentWidget != (Widget) 0), "Could not find a suitable parent shell for dialog." );
125
126 Arg args[2];
127 XtSetArg (args[0], XmNdefaultPosition, False);
128 XtSetArg (args[1], XmNautoUnmanage, False);
129 Widget dialogShell = XmCreateBulletinBoardDialog(parentWidget, (char*) (const char*) name, args, 2);
130 m_mainWidget = (WXWidget) dialogShell;
131
132 // We don't want margins, since there is enough elsewhere.
133 XtVaSetValues(dialogShell,
134 XmNmarginHeight, 0,
135 XmNmarginWidth, 0,
136 XmNresizePolicy, XmRESIZE_NONE,
137 NULL) ;
138
139 Widget shell = XtParent(dialogShell) ;
140 if (!title.IsNull())
141 {
142 XmString str = XmStringCreateSimple((char*) (const char*)title);
143 XtVaSetValues(dialogShell,
144 XmNdialogTitle, str,
145 NULL);
146 XmStringFree(str);
147 }
148
149 m_font = wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT);
150 ChangeFont(FALSE);
151
152 wxAddWindowToTable(dialogShell, this);
153
154 // Intercept CLOSE messages from the window manager
155 Atom WM_DELETE_WINDOW = XmInternAtom(XtDisplay(shell), "WM_DELETE_WINDOW", False);
156
157 /* Remove and add WM_DELETE_WINDOW so ours is only handler */
158 /* Why do we have to do this for wxDialog, but not wxFrame? */
159 XmRemoveWMProtocols(shell, &WM_DELETE_WINDOW, 1);
160 XmAddWMProtocols(shell, &WM_DELETE_WINDOW, 1);
161 XmActivateWMProtocol(shell, WM_DELETE_WINDOW);
162
163 // Modified Steve Hammes for Motif 2.0
164 #if (XmREVISION > 1 || XmVERSION > 1)
165 XmAddWMProtocolCallback(shell, WM_DELETE_WINDOW, (XtCallbackProc) wxCloseDialogCallback, (XtPointer)this);
166 #elif XmREVISION == 1
167 XmAddWMProtocolCallback(shell, WM_DELETE_WINDOW, (XtCallbackProc) wxCloseDialogCallback, (caddr_t)this);
168 #else
169 XmAddWMProtocolCallback(shell, WM_DELETE_WINDOW, (void (*)())wxCloseDialogCallback, (caddr_t)this);
170 #endif
171
172 XtTranslations ptr ;
173 XtOverrideTranslations(dialogShell,
174 ptr = XtParseTranslationTable("<Configure>: resize()"));
175 XtFree((char *)ptr);
176
177 // Can't remember what this was about... but I think it's necessary.
178
179 if (wxUSE_INVISIBLE_RESIZE)
180 {
181 if (pos.x > -1)
182 XtVaSetValues(dialogShell, XmNx, pos.x,
183 NULL);
184 if (pos.y > -1)
185 XtVaSetValues(dialogShell, XmNy, pos.y,
186 NULL);
187
188 if (size.x > -1)
189 XtVaSetValues(dialogShell, XmNwidth, size.x, NULL);
190 if (size.y > -1)
191 XtVaSetValues(dialogShell, XmNheight, size.y, NULL);
192 }
193
194 // This patch come from Torsten Liermann lier@lier1.muc.de
195 if (XmIsMotifWMRunning(shell))
196 {
197 int decor = 0 ;
198 if (m_windowStyle & wxRESIZE_BORDER)
199 decor |= MWM_DECOR_RESIZEH ;
200 if (m_windowStyle & wxSYSTEM_MENU)
201 decor |= MWM_DECOR_MENU;
202 if ((m_windowStyle & wxCAPTION) ||
203 (m_windowStyle & wxTINY_CAPTION_HORIZ) ||
204 (m_windowStyle & wxTINY_CAPTION_VERT))
205 decor |= MWM_DECOR_TITLE;
206 if (m_windowStyle & wxTHICK_FRAME)
207 decor |= MWM_DECOR_BORDER;
208 if (m_windowStyle & wxMINIMIZE_BOX)
209 decor |= MWM_DECOR_MINIMIZE;
210 if (m_windowStyle & wxMAXIMIZE_BOX)
211 decor |= MWM_DECOR_MAXIMIZE;
212
213 XtVaSetValues(shell,XmNmwmDecorations,decor,NULL) ;
214 }
215 // This allows non-Motif window managers to support at least the
216 // no-decorations case.
217 else
218 {
219 if ((m_windowStyle & wxCAPTION) != wxCAPTION)
220 XtVaSetValues((Widget) shell,XmNoverrideRedirect,TRUE,NULL);
221 }
222
223 XtRealizeWidget(dialogShell);
224
225 XtAddCallback(dialogShell,XmNunmapCallback,
226 (XtCallbackProc)wxUnmapBulletinBoard,this) ;
227
228 // Positioning of the dialog doesn't work properly unless the dialog
229 // is managed, so we manage without mapping to the screen.
230 // To show, we map the shell (actually it's parent).
231 if (!wxUSE_INVISIBLE_RESIZE)
232 XtVaSetValues(shell, XmNmappedWhenManaged, FALSE, NULL);
233
234 if (!wxUSE_INVISIBLE_RESIZE)
235 {
236 XtManageChild(dialogShell);
237 SetSize(pos.x, pos.y, size.x, size.y);
238 }
239 XtAddEventHandler(dialogShell,ExposureMask,FALSE,
240 wxUniversalRepaintProc, (XtPointer) this);
241
242 XtAddEventHandler(dialogShell,
243 ButtonPressMask | ButtonReleaseMask | PointerMotionMask | KeyPressMask,
244 FALSE,
245 wxDialogBoxEventHandler,
246 (XtPointer)this);
247
248 ChangeBackgroundColour();
249
250 return TRUE;
251 }
252
253 void wxDialog::SetModal(bool flag)
254 {
255 if ( flag )
256 m_windowStyle |= wxDIALOG_MODAL ;
257 else
258 if ( m_windowStyle & wxDIALOG_MODAL )
259 m_windowStyle -= wxDIALOG_MODAL ;
260
261 wxModelessWindows.DeleteObject(this);
262 if (!flag)
263 wxModelessWindows.Append(this);
264 }
265
266 wxDialog::~wxDialog()
267 {
268 m_isBeingDeleted = TRUE;
269
270 if (m_mainWidget)
271 XtRemoveEventHandler((Widget) m_mainWidget, ExposureMask, FALSE,
272 wxUniversalRepaintProc, (XtPointer) this);
273
274 m_modalShowing = FALSE;
275 if (!wxUSE_INVISIBLE_RESIZE && m_mainWidget)
276 {
277 XtUnmapWidget((Widget) m_mainWidget);
278 }
279
280 wxTopLevelWindows.DeleteObject(this);
281
282 if ( (GetWindowStyleFlag() & wxDIALOG_MODAL) != wxDIALOG_MODAL )
283 wxModelessWindows.DeleteObject(this);
284
285 // If this is the last top-level window, exit.
286 if (wxTheApp && (wxTopLevelWindows.Number() == 0))
287 {
288 wxTheApp->SetTopWindow(NULL);
289
290 if (wxTheApp->GetExitOnFrameDelete())
291 {
292 wxTheApp->ExitMainLoop();
293 }
294 }
295
296 // This event-flushing code used to be in wxWindow::PostDestroyChildren (wx_dialog.cpp)
297 // but I think this should work, if we destroy the children first.
298 // Note that this might need to be done for wxFrame also.
299 DestroyChildren();
300
301 // The idea about doing it here is that if you have to remove the
302 // XtDestroyWidget from ~wxWindow, at least top-level windows
303 // will still be deleted (and destroy children implicitly).
304 if (GetMainWidget())
305 {
306 DetachWidget(GetMainWidget()); // Removes event handlers
307 XtDestroyWidget((Widget) GetMainWidget());
308 SetMainWidget((WXWidget) NULL);
309 }
310 }
311
312 // By default, pressing escape cancels the dialog
313 void wxDialog::OnCharHook(wxKeyEvent& event)
314 {
315 if (event.m_keyCode == WXK_ESCAPE)
316 {
317 // Behaviour changed in 2.0: we'll send a Cancel message
318 // to the dialog instead of Close.
319 wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
320 cancelEvent.SetEventObject( this );
321 GetEventHandler()->ProcessEvent(cancelEvent);
322
323 return;
324 }
325 // We didn't process this event.
326 event.Skip();
327 }
328
329 void wxDialog::Iconize(bool WXUNUSED(iconize))
330 {
331 // Can't iconize a dialog in Motif, apparently
332 // TODO: try using the parent of m_mainShell.
333 // XtVaSetValues((Widget) m_mainWidget, XmNiconic, iconize, NULL);
334 }
335
336 // Default resizing behaviour - if only ONE subwindow,
337 // resize to client rectangle size
338 void wxDialog::OnSize(wxSizeEvent& WXUNUSED(event))
339 {
340 // if we're using constraints - do use them
341 #if wxUSE_CONSTRAINTS
342 if ( GetAutoLayout() ) {
343 Layout();
344 return;
345 }
346 #endif
347
348 // do we have _exactly_ one child?
349 wxWindow *child = NULL;
350 for ( wxNode *node = GetChildren().First(); node; node = node->Next() )
351 {
352 wxWindow *win = (wxWindow *)node->Data();
353 if ( !win->IsKindOf(CLASSINFO(wxFrame)) &&
354 !win->IsKindOf(CLASSINFO(wxDialog)) )
355 {
356 if ( child )
357 return; // it's our second subwindow - nothing to do
358 child = win;
359 }
360 }
361
362 if ( child ) {
363 // we have exactly one child - set it's size to fill the whole frame
364 int clientW, clientH;
365 GetClientSize(&clientW, &clientH);
366
367 int x = 0;
368 int y = 0;
369
370 child->SetSize(x, y, clientW, clientH);
371 }
372 }
373
374
375 bool wxDialog::IsIconized() const
376 {
377 /*
378 Boolean iconic;
379 XtVaGetValues((Widget) m_mainWidget, XmNiconic, &iconic, NULL);
380
381 return iconic;
382 */
383 return FALSE;
384 }
385
386 void wxDialog::DoSetSize(int x, int y, int width, int height, int sizeFlags)
387 {
388 XtVaSetValues((Widget) m_mainWidget, XmNresizePolicy, XmRESIZE_ANY, NULL);
389 wxWindow::DoSetSize(x, y, width, height, sizeFlags);
390 XtVaSetValues((Widget) m_mainWidget, XmNresizePolicy, XmRESIZE_NONE, NULL);
391 }
392
393 void wxDialog::DoSetClientSize(int width, int height)
394 {
395 wxWindow::SetSize(-1, -1, width, height);
396 }
397
398 void wxDialog::SetTitle(const wxString& title)
399 {
400 m_dialogTitle = title;
401 if (!title.IsNull())
402 {
403 XmString str = XmStringCreateSimple((char*) (const char*) title);
404 XtVaSetValues((Widget) m_mainWidget,
405 XmNtitle, (char*) (const char*) title,
406 XmNdialogTitle, str, // Roberto Cocchi
407 XmNiconName, (char*) (const char*) title,
408 NULL);
409 XmStringFree(str);
410 }
411 }
412
413 wxString wxDialog::GetTitle() const
414 {
415 return m_dialogTitle;
416 }
417
418 void wxDialog::Raise()
419 {
420 Window parent_window = XtWindow((Widget) m_mainWidget),
421 next_parent = XtWindow((Widget) m_mainWidget),
422 root = RootWindowOfScreen(XtScreen((Widget) m_mainWidget));
423 // search for the parent that is child of ROOT, because the WM may
424 // reparent twice and notify only the next parent (like FVWM)
425 while (next_parent != root) {
426 Window *theChildren; unsigned int n;
427 parent_window = next_parent;
428 XQueryTree(XtDisplay((Widget) m_mainWidget), parent_window, &root,
429 &next_parent, &theChildren, &n);
430 XFree(theChildren); // not needed
431 }
432 XRaiseWindow(XtDisplay((Widget) m_mainWidget), parent_window);
433 }
434
435 void wxDialog::Lower()
436 {
437 Window parent_window = XtWindow((Widget) m_mainWidget),
438 next_parent = XtWindow((Widget) m_mainWidget),
439 root = RootWindowOfScreen(XtScreen((Widget) m_mainWidget));
440 // search for the parent that is child of ROOT, because the WM may
441 // reparent twice and notify only the next parent (like FVWM)
442 while (next_parent != root) {
443 Window *theChildren; unsigned int n;
444 parent_window = next_parent;
445 XQueryTree(XtDisplay((Widget) m_mainWidget), parent_window, &root,
446 &next_parent, &theChildren, &n);
447 XFree(theChildren); // not needed
448 }
449 XLowerWindow(XtDisplay((Widget) m_mainWidget), parent_window);
450 }
451
452 bool wxDialog::Show(bool show)
453 {
454 m_isShown = show;
455
456 if (show)
457 {
458 if (!wxUSE_INVISIBLE_RESIZE)
459 XtMapWidget(XtParent((Widget) m_mainWidget));
460 else
461 XtManageChild((Widget) m_mainWidget) ;
462
463 XRaiseWindow(XtDisplay((Widget) m_mainWidget), XtWindow((Widget) m_mainWidget));
464
465 }
466 else
467 {
468 if (!wxUSE_INVISIBLE_RESIZE)
469 XtUnmapWidget(XtParent((Widget) m_mainWidget));
470 else
471 XtUnmanageChild((Widget) m_mainWidget) ;
472
473 XFlush(XtDisplay((Widget) wxTheApp->GetTopLevelWidget()));
474 XSync(XtDisplay((Widget) wxTheApp->GetTopLevelWidget()), FALSE);
475 }
476
477 return TRUE;
478 }
479
480 // Shows a dialog modally, returning a return code
481 int wxDialog::ShowModal()
482 {
483 m_windowStyle |= wxDIALOG_MODAL;
484
485 Show(TRUE);
486
487 if (m_modalShowing)
488 return 0;
489
490 wxModalShowingStack.Insert((wxObject *)TRUE);
491
492 m_modalShowing = TRUE;
493 XtAddGrab((Widget) m_mainWidget, TRUE, FALSE);
494
495 XEvent event;
496
497 // Loop until we signal that the dialog should be closed
498 while ((wxModalShowingStack.Number() > 0) && ((int)(wxModalShowingStack.First()->Data()) != 0))
499 {
500 // XtAppProcessEvent((XtAppContext) wxTheApp->GetAppContext(), XtIMAll);
501
502 XtAppNextEvent((XtAppContext) wxTheApp->GetAppContext(), &event);
503 wxTheApp->ProcessXEvent((WXEvent*) &event);
504 }
505
506 // Remove modal dialog flag from stack
507 wxNode *node = wxModalShowingStack.First();
508 if (node)
509 delete node;
510
511 // Now process all events in case they get sent to a destroyed dialog
512 XSync(XtDisplay((Widget) wxTheApp->GetTopLevelWidget()), FALSE);
513 while (XtAppPending((XtAppContext) wxTheApp->GetAppContext()))
514 {
515 XFlush(XtDisplay((Widget) wxTheApp->GetTopLevelWidget()));
516 XtAppNextEvent((XtAppContext) wxTheApp->GetAppContext(), &event);
517
518 wxTheApp->ProcessXEvent((WXEvent*) &event);
519 }
520
521 // TODO: is it safe to call this, if the dialog may have been deleted
522 // by now? Probably only if we're using delayed deletion of dialogs.
523 return GetReturnCode();
524 }
525
526 void wxDialog::EndModal(int retCode)
527 {
528 if (!m_modalShowing)
529 return;
530
531 SetReturnCode(retCode);
532
533 // Strangely, we don't seem to need this now.
534 // XtRemoveGrab((Widget) m_mainWidget);
535
536 Show(FALSE);
537
538 m_modalShowing = FALSE;
539
540 wxNode *node = wxModalShowingStack.First();
541 if (node)
542 node->SetData((wxObject *)FALSE);
543 }
544
545 // Standard buttons
546 void wxDialog::OnOK(wxCommandEvent& WXUNUSED(event))
547 {
548 if ( Validate() && TransferDataFromWindow() )
549 {
550 if ( IsModal() )
551 EndModal(wxID_OK);
552 else
553 {
554 SetReturnCode(wxID_OK);
555 this->Show(FALSE);
556 }
557 }
558 }
559
560 void wxDialog::OnApply(wxCommandEvent& WXUNUSED(event))
561 {
562 if (Validate())
563 TransferDataFromWindow();
564 // TODO probably need to disable the Apply button until things change again
565 }
566
567 void wxDialog::OnCancel(wxCommandEvent& WXUNUSED(event))
568 {
569 if ( IsModal() )
570 EndModal(wxID_CANCEL);
571 else
572 {
573 SetReturnCode(wxID_CANCEL);
574 this->Show(FALSE);
575 }
576 }
577
578 void wxDialog::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
579 {
580 // We'll send a Cancel message by default,
581 // which may close the dialog.
582 // Check for looping if the Cancel event handler calls Close().
583
584 // Note that if a cancel button and handler aren't present in the dialog,
585 // nothing will happen when you close the dialog via the window manager, or
586 // via Close().
587 // We wouldn't want to destroy the dialog by default, since the dialog may have been
588 // created on the stack.
589 // However, this does mean that calling dialog->Close() won't delete the dialog
590 // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be
591 // sure to destroy the dialog.
592 // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog.
593
594 static wxList closing;
595
596 if ( closing.Member(this) )
597 return;
598
599 closing.Append(this);
600
601 wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
602 cancelEvent.SetEventObject( this );
603 GetEventHandler()->ProcessEvent(cancelEvent); // This may close the dialog
604
605 closing.DeleteObject(this);
606 }
607
608 void wxDialog::OnPaint(wxPaintEvent &WXUNUSED(event))
609 {
610 // added for compatiblity only
611 }
612
613 // Destroy the window (delayed, if a managed window)
614 bool wxDialog::Destroy()
615 {
616 if (!wxPendingDelete.Member(this))
617 wxPendingDelete.Append(this);
618 return TRUE;
619 }
620
621 void wxDialog::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event))
622 {
623 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
624 Refresh();
625 }
626
627 // Handle a close event from the window manager
628 static void wxCloseDialogCallback( Widget WXUNUSED(widget), XtPointer client_data,
629 XmAnyCallbackStruct *WXUNUSED(cbs))
630 {
631 wxDialog *dialog = (wxDialog *)client_data;
632 wxCloseEvent closeEvent(wxEVT_CLOSE_WINDOW, dialog->GetId());
633 closeEvent.SetEventObject(dialog);
634
635 // May delete the dialog (with delayed deletion)
636 dialog->GetEventHandler()->ProcessEvent(closeEvent);
637 }
638
639 void wxDialogBoxEventHandler(Widget wid,
640 XtPointer WXUNUSED(client_data),
641 XEvent* event,
642 Boolean* continueToDispatch)
643 {
644 wxDialog *dialog = (wxDialog *)wxGetWindowFromTable(wid);
645 if (dialog)
646 {
647 wxMouseEvent wxevent(wxEVT_NULL);
648 if (wxTranslateMouseEvent(wxevent, dialog, wid, event))
649 {
650 wxevent.SetEventObject(dialog);
651 wxevent.SetId(dialog->GetId());
652 dialog->GetEventHandler()->ProcessEvent(wxevent);
653 }
654 else
655 {
656 // An attempt to implement OnCharHook by calling OnCharHook first;
657 // if this returns TRUE, set continueToDispatch to False
658 // (don't continue processing).
659 // Otherwise set it to True and call OnChar.
660 wxKeyEvent keyEvent(wxEVT_CHAR);
661 if (wxTranslateKeyEvent(keyEvent, dialog, wid, event))
662 {
663 keyEvent.SetEventObject(dialog);
664 keyEvent.SetId(dialog->GetId());
665 keyEvent.SetEventType(wxEVT_CHAR_HOOK);
666 if (dialog->GetEventHandler()->ProcessEvent(keyEvent))
667 {
668 *continueToDispatch = False;
669 return;
670 }
671 else
672 {
673 // For simplicity, OnKeyDown is the same as OnChar
674 // TODO: filter modifier key presses from OnChar
675 keyEvent.SetEventType(wxEVT_KEY_DOWN);
676
677 // Only process OnChar if OnKeyDown didn't swallow it
678 if (!dialog->GetEventHandler()->ProcessEvent (keyEvent))
679 {
680 keyEvent.SetEventType(wxEVT_CHAR);
681 dialog->GetEventHandler()->ProcessEvent(keyEvent);
682 }
683 }
684 }
685 }
686 }
687 *continueToDispatch = True;
688 }
689
690 static void wxUnmapBulletinBoard(Widget WXUNUSED(dialog), wxDialog *WXUNUSED(client), XtPointer WXUNUSED(call) )
691 {
692 /* This gets called when the dialog is being shown, which
693 * defeats modal showing.
694 client->m_modalShowing = FALSE ;
695 client->m_isShown = FALSE;
696 */
697 }
698
699 void wxDialog::ChangeFont(bool keepOriginalSize)
700 {
701 wxWindow::ChangeFont(keepOriginalSize);
702 }
703
704 void wxDialog::ChangeBackgroundColour()
705 {
706 if (GetMainWidget())
707 DoChangeBackgroundColour(GetMainWidget(), m_backgroundColour);
708 }
709
710 void wxDialog::ChangeForegroundColour()
711 {
712 if (GetMainWidget())
713 DoChangeForegroundColour(GetMainWidget(), m_foregroundColour);
714 }
715