call Show(false) from ~wxDialog to call EndModal if the dialog is still modal consist...
[wxWidgets.git] / src / univ / dialog.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/univ/dialog.cpp
3 // Author: Robert Roebling, Vaclav Slavik
4 // Id: $Id$
5 // Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
6 // Licence: wxWindows licence
7 /////////////////////////////////////////////////////////////////////////////
8
9 // ============================================================================
10 // declarations
11 // ============================================================================
12
13 // ----------------------------------------------------------------------------
14 // headers
15 // ----------------------------------------------------------------------------
16
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
19
20 #ifdef __BORLANDC__
21 #pragma hdrstop
22 #endif
23
24 #include "wx/dialog.h"
25
26 #ifndef WX_PRECOMP
27 #include "wx/utils.h"
28 #include "wx/app.h"
29 #endif
30
31 #include "wx/evtloop.h"
32
33 //-----------------------------------------------------------------------------
34 // wxDialog
35 //-----------------------------------------------------------------------------
36
37 BEGIN_EVENT_TABLE(wxDialog,wxDialogBase)
38 EVT_BUTTON (wxID_OK, wxDialog::OnOK)
39 EVT_BUTTON (wxID_CANCEL, wxDialog::OnCancel)
40 EVT_BUTTON (wxID_APPLY, wxDialog::OnApply)
41 EVT_CLOSE (wxDialog::OnCloseWindow)
42 END_EVENT_TABLE()
43
44 IMPLEMENT_DYNAMIC_CLASS(wxDialog,wxTopLevelWindow)
45
46 void wxDialog::Init()
47 {
48 m_returnCode = 0;
49 m_windowDisabler = NULL;
50 m_eventLoop = NULL;
51 m_isShowingModal = false;
52 }
53
54 wxDialog::~wxDialog()
55 {
56 m_isBeingDeleted = true;
57
58 // if the dialog is modal, this will end its event loop
59 Show(false);
60
61 delete m_eventLoop;
62 }
63
64 bool wxDialog::Create(wxWindow *parent,
65 wxWindowID id, const wxString &title,
66 const wxPoint &pos, const wxSize &size,
67 long style, const wxString &name)
68 {
69 SetExtraStyle(GetExtraStyle() | wxTOPLEVEL_EX_DIALOG);
70
71 // all dialogs should have tab traversal enabled
72 style |= wxTAB_TRAVERSAL;
73
74 return wxTopLevelWindow::Create(parent, id, title, pos, size, style, name);
75 }
76
77 void wxDialog::OnApply(wxCommandEvent &WXUNUSED(event))
78 {
79 if ( Validate() )
80 TransferDataFromWindow();
81 }
82
83 void wxDialog::OnCancel(wxCommandEvent &WXUNUSED(event))
84 {
85 if ( IsModal() )
86 {
87 EndModal(wxID_CANCEL);
88 }
89 else
90 {
91 SetReturnCode(wxID_CANCEL);
92 Show(false);
93 }
94 }
95
96 void wxDialog::OnOK(wxCommandEvent &WXUNUSED(event))
97 {
98 if ( Validate() && TransferDataFromWindow() )
99 {
100 if ( IsModal() )
101 {
102 EndModal(wxID_OK);
103 }
104 else
105 {
106 SetReturnCode(wxID_OK);
107 Show(false);
108 }
109 }
110 }
111
112 void wxDialog::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
113 {
114 // We'll send a Cancel message by default,
115 // which may close the dialog.
116 // Check for looping if the Cancel event handler calls Close().
117
118 // Note that if a cancel button and handler aren't present in the dialog,
119 // nothing will happen when you close the dialog via the window manager, or
120 // via Close().
121 // We wouldn't want to destroy the dialog by default, since the dialog may have been
122 // created on the stack.
123 // However, this does mean that calling dialog->Close() won't delete the dialog
124 // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be
125 // sure to destroy the dialog.
126 // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog.
127
128 static wxList s_closing;
129
130 if (s_closing.Member(this))
131 return; // no loops
132
133 s_closing.Append(this);
134
135 wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
136 cancelEvent.SetEventObject(this);
137 GetEventHandler()->ProcessEvent(cancelEvent);
138 s_closing.DeleteObject(this);
139 }
140
141 bool wxDialog::Show(bool show)
142 {
143 if ( !show )
144 {
145 // if we had disabled other app windows, reenable them back now because
146 // if they stay disabled Windows will activate another window (one
147 // which is enabled, anyhow) and we will lose activation
148 if ( m_windowDisabler )
149 {
150 delete m_windowDisabler;
151 m_windowDisabler = NULL;
152 }
153
154 if ( IsModal() )
155 EndModal(wxID_CANCEL);
156 }
157
158 if (show && CanDoLayoutAdaptation())
159 DoLayoutAdaptation();
160
161 bool ret = wxDialogBase::Show(show);
162
163 if ( show )
164 InitDialog();
165
166 return ret;
167 }
168
169 bool wxDialog::IsModal() const
170 {
171 return m_isShowingModal;
172 }
173
174 int wxDialog::ShowModal()
175 {
176 if ( IsModal() )
177 {
178 wxFAIL_MSG( wxT("wxDialog:ShowModal called twice") );
179 return GetReturnCode();
180 }
181
182 // use the apps top level window as parent if none given unless explicitly
183 // forbidden
184 if ( !GetParent() && !(GetWindowStyleFlag() & wxDIALOG_NO_PARENT) )
185 {
186 wxWindow * const parent = GetParentForModalDialog();
187 if ( parent && parent != this )
188 {
189 m_parent = parent;
190 }
191 }
192
193 Show(true);
194
195 m_isShowingModal = true;
196
197 wxASSERT_MSG( !m_windowDisabler, _T("disabling windows twice?") );
198
199 #if defined(__WXGTK__) || defined(__WXMGL__)
200 wxBusyCursorSuspender suspender;
201 // FIXME (FIXME_MGL) - make sure busy cursor disappears under MSW too
202 #endif
203
204 m_windowDisabler = new wxWindowDisabler(this);
205 if ( !m_eventLoop )
206 m_eventLoop = new wxEventLoop;
207
208 m_eventLoop->Run();
209
210 return GetReturnCode();
211 }
212
213 void wxDialog::EndModal(int retCode)
214 {
215 wxASSERT_MSG( m_eventLoop, _T("wxDialog is not modal") );
216
217 SetReturnCode(retCode);
218
219 if ( !IsModal() )
220 {
221 wxFAIL_MSG( wxT("wxDialog:EndModal called twice") );
222 return;
223 }
224
225 m_isShowingModal = false;
226
227 m_eventLoop->Exit();
228
229 Show(false);
230 }