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