set m_isBeingDeleted to true (only) in SendDestroyEvent(); call it as early as possib...
[wxWidgets.git] / src / motif / msgdlg.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/motif/msgdlg.cpp
3 // Purpose: wxMessageDialog
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __VMS
24 #pragma message disable nosimpint
25 #include "wx/vms_x_fix.h"
26 #endif
27 #include <X11/Xlib.h>
28
29 #include <Xm/Xm.h>
30 #include <Xm/MessageB.h>
31 #ifdef __VMS
32 #pragma message enable nosimpint
33 #endif
34
35 #include "wx/msgdlg.h"
36
37 #ifndef WX_PRECOMP
38 #include "wx/intl.h"
39 #include "wx/app.h"
40 #include "wx/settings.h"
41 #endif
42
43 #include "wx/motif/private.h"
44
45 // ----------------------------------------------------------------------------
46 // macros
47 // ----------------------------------------------------------------------------
48
49 IMPLEMENT_CLASS(wxMessageDialog, wxDialog)
50
51 // ============================================================================
52 // implementation
53 // ============================================================================
54
55 // ----------------------------------------------------------------------------
56 // the callbacks for message box buttons
57 // ----------------------------------------------------------------------------
58
59 // the common part
60 static void msgboxCallBack(Widget w, void* client_data, int id)
61 {
62 // close the dialog
63 XtUnmanageChild(w);
64
65 wxMessageDialog *dlg = (wxMessageDialog *)client_data;
66 dlg->SetResult(id);
67 }
68
69 static void msgboxCallBackOk(Widget w,
70 void* client_data,
71 XmAnyCallbackStruct *WXUNUSED(call_data))
72 {
73 msgboxCallBack(w, client_data, wxID_OK);
74 }
75
76 static void msgboxCallBackCancel(Widget w,
77 void* client_data,
78 XmAnyCallbackStruct *WXUNUSED(call_data))
79 {
80 msgboxCallBack(w, client_data, wxID_CANCEL);
81 }
82
83 static void msgboxCallBackHelp(Widget w,
84 void* client_data,
85 XmAnyCallbackStruct *WXUNUSED(call_data))
86 {
87 msgboxCallBack(w, client_data, wxID_HELP);
88 }
89
90 static void msgboxCallBackClose(Widget w,
91 void* client_data,
92 XmAnyCallbackStruct *WXUNUSED(call_data))
93 {
94 msgboxCallBack(w, client_data, wxID_CANCEL);
95 }
96
97 // ----------------------------------------------------------------------------
98 // wxMessageDialog
99 // ----------------------------------------------------------------------------
100
101 extern "C"
102 {
103 typedef Widget (*DialogCreateFunction)(Widget, String, ArgList, Cardinal);
104 }
105
106 int wxMessageDialog::ShowModal()
107 {
108 const long style = GetMessageDialogStyle();
109
110 DialogCreateFunction dialogCreateFunction;
111 if ( style & wxYES_NO )
112 {
113 // if we have [Yes], it must be a question
114 dialogCreateFunction = XmCreateQuestionDialog;
115 }
116 else if ( style & wxICON_STOP )
117 {
118 // error dialog is the one with error icon...
119 dialogCreateFunction = XmCreateErrorDialog;
120 }
121 else if ( style & wxICON_EXCLAMATION )
122 {
123 // ...and the warning dialog too
124 dialogCreateFunction = XmCreateWarningDialog;
125 }
126 else
127 {
128 // finally, use the info dialog by default
129 dialogCreateFunction = XmCreateInformationDialog;
130 }
131
132 Widget wParent = m_parent ? GetWidget(m_parent) : (Widget) 0;
133 if ( !wParent )
134 {
135 wxWindow *window = wxTheApp->GetTopWindow();
136 if ( !window )
137 {
138 wxFAIL_MSG("can't show message box without parent window");
139
140 return wxID_CANCEL;
141 }
142
143 wParent = GetWidget(window);
144 }
145
146 // prepare the arg list
147 Arg args[10];
148 int ac = 0;
149
150 wxXmString text(GetFullMessage());
151 wxXmString title(m_caption);
152 XtSetArg(args[ac], XmNmessageString, text()); ac++;
153 XtSetArg(args[ac], XmNdialogTitle, title()); ac++;
154
155 Display* dpy = XtDisplay(wParent);
156
157 if (m_backgroundColour.Ok())
158 {
159 wxComputeColours (dpy, & m_backgroundColour, NULL);
160
161 XtSetArg(args[ac], XmNbackground, g_itemColors[wxBACK_INDEX].pixel); ac++;
162 XtSetArg(args[ac], XmNtopShadowColor, g_itemColors[wxTOPS_INDEX].pixel); ac++;
163 XtSetArg(args[ac], XmNbottomShadowColor, g_itemColors[wxBOTS_INDEX].pixel); ac++;
164 XtSetArg(args[ac], XmNforeground, g_itemColors[wxFORE_INDEX].pixel); ac++;
165 }
166
167 wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
168
169 #if __WXMOTIF20__ && !__WXLESSTIF__
170 XtSetArg(args[ac], XmNbuttonRenderTable, font.GetFontTypeC(dpy)); ac++;
171 XtSetArg(args[ac], XmNlabelRenderTable, font.GetFontTypeC(dpy)); ac++;
172 XtSetArg(args[ac], XmNtextRenderTable, font.GetFontTypeC(dpy)); ac++;
173 #else
174 XtSetArg(args[ac], XmNbuttonFontList, font.GetFontTypeC(dpy)); ac++;
175 XtSetArg(args[ac], XmNlabelFontList, font.GetFontTypeC(dpy)); ac++;
176 XtSetArg(args[ac], XmNtextFontList, font.GetFontTypeC(dpy)); ac++;
177 #endif
178
179 // do create message box
180
181 Widget wMsgBox = (*dialogCreateFunction)(wParent, wxMOTIF_STR(""), args, ac);
182
183 wxCHECK_MSG( wMsgBox, wxID_CANCEL, "msg box creation failed" );
184
185 // get the buttons which we might either remove or rename
186 // depending on the requested style
187 //
188 Widget wBtnOk = XmMessageBoxGetChild(wMsgBox, XmDIALOG_OK_BUTTON);
189 Widget wBtnHelp = XmMessageBoxGetChild(wMsgBox, XmDIALOG_HELP_BUTTON);
190 Widget wBtnCancel = XmMessageBoxGetChild(wMsgBox, XmDIALOG_CANCEL_BUTTON);
191
192 if ( style & wxYES_NO )
193 {
194 wxXmString yes(_("Yes")), no(_("No")), cancel(_("Cancel"));
195
196 if ( style & wxCANCEL )
197 {
198 // use the cancel button for No and the help button for
199 // Cancel Yuk :-) MB
200 //
201 XtVaSetValues(wBtnOk, XmNlabelString, yes(), NULL);
202 XtVaSetValues(wBtnCancel, XmNlabelString, no(), NULL);
203 XtVaSetValues(wBtnHelp, XmNlabelString, cancel(), NULL);
204 }
205 else
206 {
207 // no cancel button requested...
208 // remove the help button and use cancel for no
209 //
210 XtVaSetValues(wBtnCancel, XmNlabelString, no(), NULL);
211 XtUnmanageChild(wBtnHelp);
212 }
213 }
214 else
215 {
216 // remove the help button and the cancel button (unless it was
217 // requested)
218 //
219 XtUnmanageChild(wBtnHelp);
220 if ( !(style & wxCANCEL ) ) XtUnmanageChild(wBtnCancel);
221 }
222
223 // set the callbacks for the message box buttons
224 XtAddCallback(wMsgBox, XmNokCallback,
225 (XtCallbackProc)msgboxCallBackOk, (XtPointer)this);
226 XtAddCallback(wMsgBox, XmNcancelCallback,
227 (XtCallbackProc)msgboxCallBackCancel, (XtPointer)this);
228 XtAddCallback(wMsgBox, XmNhelpCallback,
229 (XtCallbackProc)msgboxCallBackHelp, (XtPointer)this);
230 XtAddCallback(wMsgBox, XmNunmapCallback,
231 (XtCallbackProc)msgboxCallBackClose, (XtPointer)this);
232
233 // show it as a modal dialog
234 XtManageChild(wMsgBox);
235 XtAddGrab(wMsgBox, True, False);
236
237 // the m_result will be changed when message box goes away
238 m_result = -1;
239
240 // local message loop
241 XtAppContext context = XtWidgetToApplicationContext(wParent);
242 XEvent event;
243 while ( m_result == -1 )
244 {
245 XtAppNextEvent(context, &event);
246 XtDispatchEvent(&event);
247 }
248
249 // translate the result if necessary
250 if ( style & wxYES_NO )
251 {
252 if ( m_result == wxID_OK )
253 m_result = wxID_YES;
254 else if ( m_result == wxID_CANCEL )
255 m_result = wxID_NO;
256 else if ( m_result == wxID_HELP )
257 m_result = wxID_CANCEL;
258 }
259
260 return m_result;
261 }