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