Implement wxSTAY_ON_TOP for wxMessageDialog in wxGTK.
[wxWidgets.git] / src / gtk / msgdlg.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/msgdlg.cpp
3 // Purpose: wxMessageDialog for GTK+2
4 // Author: Vaclav Slavik
5 // Modified by:
6 // Created: 2003/02/28
7 // RCS-ID: $Id$
8 // Copyright: (c) Vaclav Slavik, 2003
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #if wxUSE_MSGDLG && !defined(__WXGPE__)
20
21 #include "wx/msgdlg.h"
22
23 #ifndef WX_PRECOMP
24 #include "wx/intl.h"
25 #endif
26
27 #include "wx/gtk/private.h"
28 #include "wx/gtk/private/mnemonics.h"
29 #include <gtk/gtk.h>
30
31 #if wxUSE_LIBHILDON
32 #include <hildon-widgets/hildon-note.h>
33 #endif // wxUSE_LIBHILDON
34
35 IMPLEMENT_CLASS(wxMessageDialog, wxDialog)
36
37 wxMessageDialog::wxMessageDialog(wxWindow *parent,
38 const wxString& message,
39 const wxString& caption,
40 long style,
41 const wxPoint& WXUNUSED(pos))
42 : wxMessageDialogWithCustomLabels(GetParentForModalDialog(parent),
43 message,
44 caption,
45 style)
46 {
47 }
48
49 wxString wxMessageDialog::GetDefaultYesLabel() const
50 {
51 return GTK_STOCK_YES;
52 }
53
54 wxString wxMessageDialog::GetDefaultNoLabel() const
55 {
56 return GTK_STOCK_NO;
57 }
58
59 wxString wxMessageDialog::GetDefaultOKLabel() const
60 {
61 return GTK_STOCK_OK;
62 }
63
64 wxString wxMessageDialog::GetDefaultCancelLabel() const
65 {
66 return GTK_STOCK_CANCEL;
67 }
68
69 void wxMessageDialog::DoSetCustomLabel(wxString& var, const ButtonLabel& label)
70 {
71 int stockId = label.GetStockId();
72 if ( stockId == wxID_NONE )
73 {
74 wxMessageDialogWithCustomLabels::DoSetCustomLabel(var, label);
75 var = wxConvertMnemonicsToGTK(var);
76 }
77 else // stock label
78 {
79 var = wxGetStockGtkID(stockId);
80 }
81 }
82
83 void wxMessageDialog::GTKCreateMsgDialog()
84 {
85 GtkWindow * const parent = m_parent ? GTK_WINDOW(m_parent->m_widget) : NULL;
86
87 #if wxUSE_LIBHILDON
88 const char *stockIcon;
89 if ( m_dialogStyle & wxICON_NONE )
90 stockIcon = "";
91 else if ( m_dialogStyle & wxICON_ERROR )
92 stockIcon = "qgn_note_gene_syserror";
93 else if ( m_dialogStyle & wxICON_EXCLAMATION )
94 stockIcon = "qgn_note_gene_syswarning";
95 else if ( m_dialogStyle & wxICON_INFORMATION )
96 stockIcon = "qgn_note_info";
97 else if ( m_dialogStyle & wxICON_QUESTION )
98 stockIcon = "qgn_note_confirm";
99 else
100 stockIcon = "";
101
102 // there is no generic note creation function in public API so we have no
103 // choice but to use g_object_new() directly
104 m_widget = (GtkWidget *)g_object_new
105 (
106 HILDON_TYPE_NOTE,
107 "note_type", HILDON_NOTE_CONFIRMATION_BUTTON_TYPE,
108 "description", (const char *)GetFullMessage().utf8_str(),
109 "icon", stockIcon,
110 NULL
111 );
112 #else // !wxUSE_LIBHILDON
113 GtkMessageType type = GTK_MESSAGE_ERROR;
114 GtkButtonsType buttons = GTK_BUTTONS_NONE;
115
116 // when using custom labels, we have to add all the buttons ourselves
117 if ( !HasCustomLabels() )
118 {
119 if ( m_dialogStyle & wxYES_NO )
120 {
121 if ( !(m_dialogStyle & wxCANCEL) )
122 buttons = GTK_BUTTONS_YES_NO;
123 //else: no standard GTK_BUTTONS_YES_NO_CANCEL so leave as NONE
124 }
125 else if ( m_dialogStyle & wxOK )
126 {
127 buttons = m_dialogStyle & wxCANCEL ? GTK_BUTTONS_OK_CANCEL
128 : GTK_BUTTONS_OK;
129 }
130 }
131
132 #ifdef __WXGTK210__
133 if ( gtk_check_version(2, 10, 0) == NULL && (m_dialogStyle & wxICON_NONE))
134 type = GTK_MESSAGE_OTHER;
135 else
136 #endif // __WXGTK210__
137 if (m_dialogStyle & wxICON_EXCLAMATION)
138 type = GTK_MESSAGE_WARNING;
139 else if (m_dialogStyle & wxICON_ERROR)
140 type = GTK_MESSAGE_ERROR;
141 else if (m_dialogStyle & wxICON_INFORMATION)
142 type = GTK_MESSAGE_INFO;
143 else if (m_dialogStyle & wxICON_QUESTION)
144 type = GTK_MESSAGE_QUESTION;
145 else
146 {
147 // if no style is explicitly specified, detect the suitable icon
148 // ourselves (this can be disabled by using wxICON_NONE)
149 type = m_dialogStyle & wxYES ? GTK_MESSAGE_QUESTION : GTK_MESSAGE_INFO;
150 }
151
152 wxString message;
153 #if GTK_CHECK_VERSION(2, 6, 0)
154 bool needsExtMessage = false;
155 if ( gtk_check_version(2, 6, 0) == NULL && !m_extendedMessage.empty() )
156 {
157 message = m_message;
158 needsExtMessage = true;
159 }
160 else // extended message not needed or not supported
161 #endif // GTK+ 2.6+
162 {
163 message = GetFullMessage();
164 }
165
166 m_widget = gtk_message_dialog_new(parent,
167 GTK_DIALOG_MODAL,
168 type,
169 buttons,
170 "%s",
171 (const char*)wxGTK_CONV(message));
172
173 #if GTK_CHECK_VERSION(2, 6, 0)
174 if ( needsExtMessage )
175 {
176 gtk_message_dialog_format_secondary_text
177 (
178 (GtkMessageDialog *)m_widget,
179 "%s",
180 (const char *)wxGTK_CONV(m_extendedMessage)
181 );
182 }
183 #endif // GTK+ 2.6+
184 #endif // wxUSE_LIBHILDON/!wxUSE_LIBHILDON
185
186 g_object_ref(m_widget);
187
188 if (m_caption != wxMessageBoxCaptionStr)
189 gtk_window_set_title(GTK_WINDOW(m_widget), wxGTK_CONV(m_caption));
190
191 GtkDialog * const dlg = GTK_DIALOG(m_widget);
192
193 if ( m_dialogStyle & wxSTAY_ON_TOP )
194 {
195 gtk_window_set_keep_above(GTK_WINDOW(m_widget), TRUE);
196 }
197
198 // we need to add buttons manually if we use custom labels or always for
199 // Yes/No/Cancel dialog as GTK+ doesn't support it natively and when using
200 // Hildon we add all the buttons manually as it doesn't support too many of
201 // the combinations we may have
202 #if wxUSE_LIBHILDON
203 static const bool addButtons = true;
204 #else // !wxUSE_LIBHILDON
205 const bool addButtons = buttons == GTK_BUTTONS_NONE;
206 #endif // wxUSE_LIBHILDON/!wxUSE_LIBHILDON
207
208 if ( m_dialogStyle & wxYES_NO ) // Yes/No or Yes/No/Cancel dialog
209 {
210 if ( addButtons )
211 {
212 gtk_dialog_add_button(dlg, wxGTK_CONV(GetNoLabel()),
213 GTK_RESPONSE_NO);
214 gtk_dialog_add_button(dlg, wxGTK_CONV(GetYesLabel()),
215 GTK_RESPONSE_YES);
216
217 if ( m_dialogStyle & wxCANCEL )
218 {
219 gtk_dialog_add_button(dlg, wxGTK_CONV(GetCancelLabel()),
220 GTK_RESPONSE_CANCEL);
221 }
222 }
223
224 // it'd probably be harmless to call gtk_dialog_set_default_response()
225 // twice but why do it if we're going to change the default below
226 // anyhow
227 if ( !(m_dialogStyle & wxCANCEL_DEFAULT) )
228 {
229 gtk_dialog_set_default_response(dlg,
230 m_dialogStyle & wxNO_DEFAULT
231 ? GTK_RESPONSE_NO
232 : GTK_RESPONSE_YES);
233 }
234 }
235 else if ( addButtons ) // Ok or Ok/Cancel dialog
236 {
237 gtk_dialog_add_button(dlg, wxGTK_CONV(GetOKLabel()), GTK_RESPONSE_OK);
238 if ( m_dialogStyle & wxCANCEL )
239 {
240 gtk_dialog_add_button(dlg, wxGTK_CONV(GetCancelLabel()),
241 GTK_RESPONSE_CANCEL);
242 }
243 }
244
245 if ( m_dialogStyle & wxCANCEL_DEFAULT )
246 {
247 gtk_dialog_set_default_response(dlg, GTK_RESPONSE_CANCEL);
248 }
249 }
250
251 int wxMessageDialog::ShowModal()
252 {
253 // break the mouse capture as it would interfere with modal dialog (see
254 // wxDialog::ShowModal)
255 wxWindow * const win = wxWindow::GetCapture();
256 if ( win )
257 win->GTKReleaseMouseAndNotify();
258
259 if ( !m_widget )
260 {
261 GTKCreateMsgDialog();
262 wxCHECK_MSG( m_widget, wxID_CANCEL,
263 wxT("failed to create GtkMessageDialog") );
264 }
265
266 // This should be necessary, but otherwise the
267 // parent TLW will disappear..
268 if (m_parent)
269 gtk_window_present( GTK_WINDOW(m_parent->m_widget) );
270
271 gint result = gtk_dialog_run(GTK_DIALOG(m_widget));
272 gtk_widget_destroy(m_widget);
273 g_object_unref(m_widget);
274 m_widget = NULL;
275
276 switch (result)
277 {
278 default:
279 wxFAIL_MSG(wxT("unexpected GtkMessageDialog return code"));
280 // fall through
281
282 case GTK_RESPONSE_CANCEL:
283 case GTK_RESPONSE_DELETE_EVENT:
284 case GTK_RESPONSE_CLOSE:
285 return wxID_CANCEL;
286 case GTK_RESPONSE_OK:
287 return wxID_OK;
288 case GTK_RESPONSE_YES:
289 return wxID_YES;
290 case GTK_RESPONSE_NO:
291 return wxID_NO;
292 }
293 }
294
295
296 #endif // wxUSE_MSGDLG && !defined(__WXGPE__)