]> git.saurik.com Git - wxWidgets.git/blame - src/motif/dialog.cpp
Applied patch for multiple file selection, documented.
[wxWidgets.git] / src / motif / dialog.cpp
CommitLineData
4bb6408c
JS
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
dfe1eee3 9// Licence: wxWindows licence
4bb6408c
JS
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
338dd992
JJ
22#ifdef __VMS__
23#pragma message disable nosimpint
24#endif
dfc54541
JS
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
338dd992
JJ
44#ifdef __VMS__
45#pragma message enable nosimpint
46#endif
dfc54541
JS
47
48#include "wx/motif/private.h"
49
50static void wxCloseDialogCallback(Widget widget, XtPointer client_data, XmAnyCallbackStruct *cbs);
dfc54541 51static void wxDialogBoxEventHandler (Widget wid,
2d120f83
JS
52 XtPointer client_data,
53 XEvent* event,
54 Boolean *continueToDispatch);
dfc54541
JS
55
56static 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.
61static wxList wxModalShowingStack;
62
4bb6408c
JS
63// Lists to keep track of windows, so we can disable/enable them
64// for modal dialogs
65wxList wxModalDialogs;
66wxList wxModelessWindows; // Frames and modeless dialogs
67extern wxList wxPendingDelete;
68
47d67540 69#define wxUSE_INVISIBLE_RESIZE 1
dfc54541 70
4bb6408c
JS
71#if !USE_SHARED_LIBRARY
72IMPLEMENT_DYNAMIC_CLASS(wxDialog, wxPanel)
73
74BEGIN_EVENT_TABLE(wxDialog, wxPanel)
8e877c19
RR
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)
4bb6408c
JS
82END_EVENT_TABLE()
83
84#endif
85
86wxDialog::wxDialog()
87{
dfc54541 88 m_modalShowing = FALSE;
0d57be45 89 m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE);
4bb6408c
JS
90}
91
92bool wxDialog::Create(wxWindow *parent, wxWindowID id,
2d120f83
JS
93 const wxString& title,
94 const wxPoint& pos,
95 const wxSize& size,
96 long style,
97 const wxString& name)
4bb6408c 98{
dfc54541
JS
99 m_windowStyle = style;
100 m_modalShowing = FALSE;
101 m_dialogTitle = title;
dfe1eee3 102
0d57be45
JS
103 m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE);
104 m_foregroundColour = *wxBLACK;
dfe1eee3 105
dfc54541 106 SetName(name);
dfe1eee3 107
dfc54541
JS
108 if (!parent)
109 wxTopLevelWindows.Append(this);
dfe1eee3 110
dfc54541 111 if (parent) parent->AddChild(this);
dfe1eee3 112
dfc54541
JS
113 if ( id == -1 )
114 m_windowId = (int)NewControlId();
115 else
116 m_windowId = id;
dfe1eee3 117
dfc54541
JS
118 Widget parentWidget = (Widget) 0;
119 if (parent)
120 parentWidget = (Widget) parent->GetTopWidget();
121 if (!parent)
122 parentWidget = (Widget) wxTheApp->GetTopLevelWidget();
dfe1eee3 123
dfc54541 124 wxASSERT_MSG( (parentWidget != (Widget) 0), "Could not find a suitable parent shell for dialog." );
dfe1eee3 125
94b49b93 126 Arg args[2];
dfc54541 127 XtSetArg (args[0], XmNdefaultPosition, False);
94b49b93
JS
128 XtSetArg (args[1], XmNautoUnmanage, False);
129 Widget dialogShell = XmCreateBulletinBoardDialog(parentWidget, (char*) (const char*) name, args, 2);
dfc54541 130 m_mainWidget = (WXWidget) dialogShell;
dfe1eee3 131
dfc54541
JS
132 // We don't want margins, since there is enough elsewhere.
133 XtVaSetValues(dialogShell,
2d120f83
JS
134 XmNmarginHeight, 0,
135 XmNmarginWidth, 0,
136 XmNresizePolicy, XmRESIZE_NONE,
137 NULL) ;
dfe1eee3 138
dfc54541
JS
139 Widget shell = XtParent(dialogShell) ;
140 if (!title.IsNull())
141 {
142 XmString str = XmStringCreateSimple((char*) (const char*)title);
143 XtVaSetValues(dialogShell,
2d120f83
JS
144 XmNdialogTitle, str,
145 NULL);
dfc54541
JS
146 XmStringFree(str);
147 }
dfe1eee3 148
da175b2c 149 m_font = wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT);
4b5f3fe6 150 ChangeFont(FALSE);
dfe1eee3 151
dfc54541 152 wxAddWindowToTable(dialogShell, this);
dfe1eee3 153
dfc54541
JS
154 // Intercept CLOSE messages from the window manager
155 Atom WM_DELETE_WINDOW = XmInternAtom(XtDisplay(shell), "WM_DELETE_WINDOW", False);
dfe1eee3 156
4b5f3fe6 157 /* Remove and add WM_DELETE_WINDOW so ours is only handler */
dfc54541
JS
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);
dfe1eee3 162
dfc54541
JS
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
dfe1eee3 171
dfc54541
JS
172 XtTranslations ptr ;
173 XtOverrideTranslations(dialogShell,
2d120f83 174 ptr = XtParseTranslationTable("<Configure>: resize()"));
dfc54541 175 XtFree((char *)ptr);
dfe1eee3 176
dfc54541 177 // Can't remember what this was about... but I think it's necessary.
dfe1eee3 178
dfad0599 179 if (wxUSE_INVISIBLE_RESIZE)
dfc54541 180 {
2d120f83
JS
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);
dfe1eee3 187
2d120f83
JS
188 if (size.x > -1)
189 XtVaSetValues(dialogShell, XmNwidth, size.x, NULL);
190 if (size.y > -1)
191 XtVaSetValues(dialogShell, XmNheight, size.y, NULL);
dfc54541 192 }
dfe1eee3 193
dfc54541
JS
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)
2d120f83 199 decor |= MWM_DECOR_RESIZEH ;
dfc54541 200 if (m_windowStyle & wxSYSTEM_MENU)
2d120f83 201 decor |= MWM_DECOR_MENU;
dfc54541
JS
202 if ((m_windowStyle & wxCAPTION) ||
203 (m_windowStyle & wxTINY_CAPTION_HORIZ) ||
204 (m_windowStyle & wxTINY_CAPTION_VERT))
2d120f83 205 decor |= MWM_DECOR_TITLE;
dfc54541 206 if (m_windowStyle & wxTHICK_FRAME)
2d120f83 207 decor |= MWM_DECOR_BORDER;
dfc54541 208 if (m_windowStyle & wxMINIMIZE_BOX)
2d120f83 209 decor |= MWM_DECOR_MINIMIZE;
dfc54541 210 if (m_windowStyle & wxMAXIMIZE_BOX)
2d120f83 211 decor |= MWM_DECOR_MAXIMIZE;
dfe1eee3 212
dfc54541
JS
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 {
2d120f83
JS
219 if ((m_windowStyle & wxCAPTION) != wxCAPTION)
220 XtVaSetValues((Widget) shell,XmNoverrideRedirect,TRUE,NULL);
dfc54541 221 }
dfe1eee3 222
dfc54541 223 XtRealizeWidget(dialogShell);
dfe1eee3 224
dfc54541 225 XtAddCallback(dialogShell,XmNunmapCallback,
2d120f83 226 (XtCallbackProc)wxUnmapBulletinBoard,this) ;
dfe1eee3 227
dfc54541
JS
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).
dfad0599 231 if (!wxUSE_INVISIBLE_RESIZE)
dfc54541 232 XtVaSetValues(shell, XmNmappedWhenManaged, FALSE, NULL);
dfe1eee3 233
dfad0599 234 if (!wxUSE_INVISIBLE_RESIZE)
dfc54541
JS
235 {
236 XtManageChild(dialogShell);
237 SetSize(pos.x, pos.y, size.x, size.y);
238 }
239 XtAddEventHandler(dialogShell,ExposureMask,FALSE,
2e35f56f 240 wxUniversalRepaintProc, (XtPointer) this);
dfe1eee3 241
dfc54541 242 XtAddEventHandler(dialogShell,
2d120f83
JS
243 ButtonPressMask | ButtonReleaseMask | PointerMotionMask | KeyPressMask,
244 FALSE,
245 wxDialogBoxEventHandler,
246 (XtPointer)this);
dfe1eee3 247
0d57be45 248 ChangeBackgroundColour();
dfe1eee3 249
dfc54541 250 return TRUE;
4bb6408c
JS
251}
252
253void wxDialog::SetModal(bool flag)
254{
dfc54541
JS
255 if ( flag )
256 m_windowStyle |= wxDIALOG_MODAL ;
257 else
258 if ( m_windowStyle & wxDIALOG_MODAL )
2d120f83 259 m_windowStyle -= wxDIALOG_MODAL ;
dfe1eee3 260
2d120f83
JS
261 wxModelessWindows.DeleteObject(this);
262 if (!flag)
263 wxModelessWindows.Append(this);
4bb6408c
JS
264}
265
266wxDialog::~wxDialog()
267{
3ab377bd
MB
268 m_isBeingDeleted = TRUE;
269
2e35f56f
JS
270 if (m_mainWidget)
271 XtRemoveEventHandler((Widget) m_mainWidget, ExposureMask, FALSE,
272 wxUniversalRepaintProc, (XtPointer) this);
dfe1eee3 273
dfc54541 274 m_modalShowing = FALSE;
dfad0599 275 if (!wxUSE_INVISIBLE_RESIZE && m_mainWidget)
dfc54541 276 {
2d120f83 277 XtUnmapWidget((Widget) m_mainWidget);
dfc54541 278 }
dfe1eee3 279
4bb6408c 280 wxTopLevelWindows.DeleteObject(this);
dfe1eee3 281
4bb6408c 282 if ( (GetWindowStyleFlag() & wxDIALOG_MODAL) != wxDIALOG_MODAL )
2d120f83 283 wxModelessWindows.DeleteObject(this);
dfe1eee3 284
4bb6408c
JS
285 // If this is the last top-level window, exit.
286 if (wxTheApp && (wxTopLevelWindows.Number() == 0))
287 {
2d120f83 288 wxTheApp->SetTopWindow(NULL);
dfe1eee3 289
2d120f83
JS
290 if (wxTheApp->GetExitOnFrameDelete())
291 {
292 wxTheApp->ExitMainLoop();
293 }
4bb6408c 294 }
dfe1eee3 295
dfc54541
JS
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();
cba2db0c
JS
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);
dfc54541 309 }
4bb6408c
JS
310}
311
312// By default, pressing escape cancels the dialog
313void wxDialog::OnCharHook(wxKeyEvent& event)
314{
2d120f83
JS
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);
dfe1eee3 322
2d120f83
JS
323 return;
324 }
325 // We didn't process this event.
326 event.Skip();
4bb6408c
JS
327}
328
329void wxDialog::Iconize(bool WXUNUSED(iconize))
330{
2d120f83
JS
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);
4bb6408c
JS
334}
335
8e877c19
RR
336// Default resizing behaviour - if only ONE subwindow,
337// resize to client rectangle size
af111fc3 338void wxDialog::OnSize(wxSizeEvent& WXUNUSED(event))
8e877c19
RR
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
4bb6408c
JS
375bool wxDialog::IsIconized() const
376{
2d120f83
JS
377/*
378Boolean iconic;
379XtVaGetValues((Widget) m_mainWidget, XmNiconic, &iconic, NULL);
dfc54541 380
2d120f83
JS
381 return iconic;
382 */
4bb6408c
JS
383 return FALSE;
384}
385
bfc6fde4 386void wxDialog::DoSetSize(int x, int y, int width, int height, int sizeFlags)
4bb6408c 387{
dfc54541 388 XtVaSetValues((Widget) m_mainWidget, XmNresizePolicy, XmRESIZE_ANY, NULL);
bfc6fde4 389 wxWindow::DoSetSize(x, y, width, height, sizeFlags);
dfc54541 390 XtVaSetValues((Widget) m_mainWidget, XmNresizePolicy, XmRESIZE_NONE, NULL);
4bb6408c
JS
391}
392
ad813b00
JS
393void wxDialog::DoSetClientSize(int width, int height)
394{
395 wxWindow::SetSize(-1, -1, width, height);
396}
397
4bb6408c
JS
398void wxDialog::SetTitle(const wxString& title)
399{
dfc54541
JS
400 m_dialogTitle = title;
401 if (!title.IsNull())
402 {
403 XmString str = XmStringCreateSimple((char*) (const char*) title);
dfe1eee3 404 XtVaSetValues((Widget) m_mainWidget,
2d120f83
JS
405 XmNtitle, (char*) (const char*) title,
406 XmNdialogTitle, str, // Roberto Cocchi
407 XmNiconName, (char*) (const char*) title,
408 NULL);
dfc54541
JS
409 XmStringFree(str);
410 }
4bb6408c
JS
411}
412
413wxString wxDialog::GetTitle() const
414{
2d120f83 415 return m_dialogTitle;
4bb6408c
JS
416}
417
dfc54541
JS
418void wxDialog::Raise()
419{
420 Window parent_window = XtWindow((Widget) m_mainWidget),
2d120f83
JS
421 next_parent = XtWindow((Widget) m_mainWidget),
422 root = RootWindowOfScreen(XtScreen((Widget) m_mainWidget));
dfc54541
JS
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) {
2d120f83
JS
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
dfc54541
JS
431 }
432 XRaiseWindow(XtDisplay((Widget) m_mainWidget), parent_window);
433}
434
435void wxDialog::Lower()
436{
437 Window parent_window = XtWindow((Widget) m_mainWidget),
2d120f83
JS
438 next_parent = XtWindow((Widget) m_mainWidget),
439 root = RootWindowOfScreen(XtScreen((Widget) m_mainWidget));
dfc54541
JS
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) {
2d120f83
JS
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
dfc54541
JS
448 }
449 XLowerWindow(XtDisplay((Widget) m_mainWidget), parent_window);
450}
451
452bool wxDialog::Show(bool show)
453{
454 m_isShown = show;
dfe1eee3 455
dfc54541
JS
456 if (show)
457 {
dfad0599 458 if (!wxUSE_INVISIBLE_RESIZE)
2d120f83 459 XtMapWidget(XtParent((Widget) m_mainWidget));
dfc54541 460 else
dfe1eee3
VZ
461 XtManageChild((Widget) m_mainWidget) ;
462
dfc54541 463 XRaiseWindow(XtDisplay((Widget) m_mainWidget), XtWindow((Widget) m_mainWidget));
dfe1eee3 464
dfc54541
JS
465 }
466 else
467 {
dfad0599 468 if (!wxUSE_INVISIBLE_RESIZE)
dfc54541
JS
469 XtUnmapWidget(XtParent((Widget) m_mainWidget));
470 else
471 XtUnmanageChild((Widget) m_mainWidget) ;
dfe1eee3 472
2d120f83
JS
473 XFlush(XtDisplay((Widget) wxTheApp->GetTopLevelWidget()));
474 XSync(XtDisplay((Widget) wxTheApp->GetTopLevelWidget()), FALSE);
dfc54541 475 }
dfe1eee3 476
dfc54541
JS
477 return TRUE;
478}
479
480// Shows a dialog modally, returning a return code
4bb6408c
JS
481int wxDialog::ShowModal()
482{
483 m_windowStyle |= wxDIALOG_MODAL;
dfe1eee3 484
dfc54541 485 Show(TRUE);
dfe1eee3 486
dfc54541
JS
487 if (m_modalShowing)
488 return 0;
dfe1eee3 489
dfc54541 490 wxModalShowingStack.Insert((wxObject *)TRUE);
dfe1eee3 491
dfc54541 492 m_modalShowing = TRUE;
793f619f 493 XtAddGrab((Widget) m_mainWidget, TRUE, FALSE);
dfe1eee3 494
dfc54541 495 XEvent event;
dfe1eee3 496
dfc54541 497 // Loop until we signal that the dialog should be closed
5dcf05ae 498 while ((wxModalShowingStack.Number() > 0) && ((int)(wxModalShowingStack.First()->Data()) != 0))
dfc54541 499 {
2d120f83 500 // XtAppProcessEvent((XtAppContext) wxTheApp->GetAppContext(), XtIMAll);
dfe1eee3 501
8aa04e8b
JS
502 XtAppNextEvent((XtAppContext) wxTheApp->GetAppContext(), &event);
503 wxTheApp->ProcessXEvent((WXEvent*) &event);
dfc54541 504 }
dfe1eee3 505
dfc54541
JS
506 // Remove modal dialog flag from stack
507 wxNode *node = wxModalShowingStack.First();
508 if (node)
2d120f83 509 delete node;
dfe1eee3 510
dfc54541
JS
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);
dfe1eee3 517
8aa04e8b 518 wxTheApp->ProcessXEvent((WXEvent*) &event);
dfc54541 519 }
dfe1eee3 520
dfc54541
JS
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();
4bb6408c
JS
524}
525
526void wxDialog::EndModal(int retCode)
527{
dfc54541
JS
528 if (!m_modalShowing)
529 return;
dfe1eee3 530
dfc54541 531 SetReturnCode(retCode);
dfe1eee3 532
88150e60
JS
533 // Strangely, we don't seem to need this now.
534 // XtRemoveGrab((Widget) m_mainWidget);
dfe1eee3 535
dfc54541 536 Show(FALSE);
dfe1eee3 537
dfc54541 538 m_modalShowing = FALSE;
dfe1eee3 539
dfc54541
JS
540 wxNode *node = wxModalShowingStack.First();
541 if (node)
2d120f83 542 node->SetData((wxObject *)FALSE);
4bb6408c
JS
543}
544
545// Standard buttons
f9e02ac7 546void wxDialog::OnOK(wxCommandEvent& WXUNUSED(event))
4bb6408c 547{
2d120f83
JS
548 if ( Validate() && TransferDataFromWindow() )
549 {
4bb6408c
JS
550 if ( IsModal() )
551 EndModal(wxID_OK);
552 else
553 {
2d120f83
JS
554 SetReturnCode(wxID_OK);
555 this->Show(FALSE);
4bb6408c 556 }
2d120f83 557 }
4bb6408c
JS
558}
559
f9e02ac7 560void wxDialog::OnApply(wxCommandEvent& WXUNUSED(event))
4bb6408c 561{
2d120f83
JS
562 if (Validate())
563 TransferDataFromWindow();
564 // TODO probably need to disable the Apply button until things change again
4bb6408c
JS
565}
566
f9e02ac7 567void wxDialog::OnCancel(wxCommandEvent& WXUNUSED(event))
4bb6408c
JS
568{
569 if ( IsModal() )
570 EndModal(wxID_CANCEL);
571 else
572 {
573 SetReturnCode(wxID_CANCEL);
2d120f83 574 this->Show(FALSE);
4bb6408c
JS
575 }
576}
577
af111fc3 578void wxDialog::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
4bb6408c 579{
e3065973 580 // We'll send a Cancel message by default,
4bb6408c 581 // which may close the dialog.
e3065973
JS
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
4bb6408c 594 static wxList closing;
dfe1eee3 595
4bb6408c 596 if ( closing.Member(this) )
e3065973 597 return;
dfe1eee3 598
4bb6408c 599 closing.Append(this);
dfe1eee3 600
2d120f83
JS
601 wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
602 cancelEvent.SetEventObject( this );
e3065973 603 GetEventHandler()->ProcessEvent(cancelEvent); // This may close the dialog
4bb6408c 604
e3065973 605 closing.DeleteObject(this);
4bb6408c
JS
606}
607
d75638f8
RR
608void wxDialog::OnPaint(wxPaintEvent &WXUNUSED(event))
609{
610 // added for compatiblity only
611}
612
4bb6408c
JS
613// Destroy the window (delayed, if a managed window)
614bool wxDialog::Destroy()
615{
2d120f83
JS
616 if (!wxPendingDelete.Member(this))
617 wxPendingDelete.Append(this);
618 return TRUE;
4bb6408c
JS
619}
620
f9e02ac7 621void wxDialog::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event))
4bb6408c 622{
2d120f83
JS
623 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
624 Refresh();
4bb6408c
JS
625}
626
dfc54541 627// Handle a close event from the window manager
dfe1eee3 628static void wxCloseDialogCallback( Widget WXUNUSED(widget), XtPointer client_data,
2d120f83 629 XmAnyCallbackStruct *WXUNUSED(cbs))
dfc54541 630{
2d120f83
JS
631 wxDialog *dialog = (wxDialog *)client_data;
632 wxCloseEvent closeEvent(wxEVT_CLOSE_WINDOW, dialog->GetId());
633 closeEvent.SetEventObject(dialog);
dfe1eee3 634
2d120f83
JS
635 // May delete the dialog (with delayed deletion)
636 dialog->GetEventHandler()->ProcessEvent(closeEvent);
dfc54541
JS
637}
638
dfe1eee3
VZ
639void wxDialogBoxEventHandler(Widget wid,
640 XtPointer WXUNUSED(client_data),
641 XEvent* event,
642 Boolean* continueToDispatch)
2d120f83 643{
dfe1eee3 644 wxDialog *dialog = (wxDialog *)wxGetWindowFromTable(wid);
2d120f83 645 if (dialog)
dfc54541 646 {
2d120f83
JS
647 wxMouseEvent wxevent(wxEVT_NULL);
648 if (wxTranslateMouseEvent(wxevent, dialog, wid, event))
dfc54541 649 {
2d120f83
JS
650 wxevent.SetEventObject(dialog);
651 wxevent.SetId(dialog->GetId());
652 dialog->GetEventHandler()->ProcessEvent(wxevent);
dfc54541
JS
653 }
654 else
655 {
2d120f83
JS
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.
c75e6695 660 wxKeyEvent keyEvent(wxEVT_CHAR);
2d120f83
JS
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 {
a91b47e8
JS
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);
dfe1eee3 682 }
2d120f83
JS
683 }
684 }
685 }
dfc54541 686 }
2d120f83 687 *continueToDispatch = True;
dfc54541
JS
688}
689
f9e02ac7 690static void wxUnmapBulletinBoard(Widget WXUNUSED(dialog), wxDialog *WXUNUSED(client), XtPointer WXUNUSED(call) )
dfc54541 691{
2d120f83
JS
692/* This gets called when the dialog is being shown, which
693* defeats modal showing.
694client->m_modalShowing = FALSE ;
695client->m_isShown = FALSE;
696 */
dfc54541 697}
0d57be45 698
94b49b93 699void wxDialog::ChangeFont(bool keepOriginalSize)
0d57be45 700{
94b49b93 701 wxWindow::ChangeFont(keepOriginalSize);
0d57be45
JS
702}
703
704void wxDialog::ChangeBackgroundColour()
705{
94b49b93
JS
706 if (GetMainWidget())
707 DoChangeBackgroundColour(GetMainWidget(), m_backgroundColour);
0d57be45
JS
708}
709
710void wxDialog::ChangeForegroundColour()
711{
94b49b93
JS
712 if (GetMainWidget())
713 DoChangeForegroundColour(GetMainWidget(), m_foregroundColour);
0d57be45
JS
714}
715