fix divide by 0 bug in UpdateScrollbars() (part of patch 1716763)
[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 delete m_eventLoop;
57 }
58
59 bool wxDialog::Create(wxWindow *parent,
60 wxWindowID id, const wxString &title,
61 const wxPoint &pos, const wxSize &size,
62 long style, const wxString &name)
63 {
64 SetExtraStyle(GetExtraStyle() | wxTOPLEVEL_EX_DIALOG);
65
66 // all dialogs should have tab traversal enabled
67 style |= wxTAB_TRAVERSAL;
68
69 return wxTopLevelWindow::Create(parent, id, title, pos, size, style, name);
70 }
71
72 void wxDialog::OnApply(wxCommandEvent &WXUNUSED(event))
73 {
74 if ( Validate() )
75 TransferDataFromWindow();
76 }
77
78 void wxDialog::OnCancel(wxCommandEvent &WXUNUSED(event))
79 {
80 if ( IsModal() )
81 {
82 EndModal(wxID_CANCEL);
83 }
84 else
85 {
86 SetReturnCode(wxID_CANCEL);
87 Show(false);
88 }
89 }
90
91 void wxDialog::OnOK(wxCommandEvent &WXUNUSED(event))
92 {
93 if ( Validate() && TransferDataFromWindow() )
94 {
95 if ( IsModal() )
96 {
97 EndModal(wxID_OK);
98 }
99 else
100 {
101 SetReturnCode(wxID_OK);
102 Show(false);
103 }
104 }
105 }
106
107 void wxDialog::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
108 {
109 // We'll send a Cancel message by default,
110 // which may close the dialog.
111 // Check for looping if the Cancel event handler calls Close().
112
113 // Note that if a cancel button and handler aren't present in the dialog,
114 // nothing will happen when you close the dialog via the window manager, or
115 // via Close().
116 // We wouldn't want to destroy the dialog by default, since the dialog may have been
117 // created on the stack.
118 // However, this does mean that calling dialog->Close() won't delete the dialog
119 // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be
120 // sure to destroy the dialog.
121 // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog.
122
123 static wxList s_closing;
124
125 if (s_closing.Member(this))
126 return; // no loops
127
128 s_closing.Append(this);
129
130 wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
131 cancelEvent.SetEventObject(this);
132 GetEventHandler()->ProcessEvent(cancelEvent);
133 s_closing.DeleteObject(this);
134 }
135
136 bool wxDialog::Show(bool show)
137 {
138 if ( !show )
139 {
140 // if we had disabled other app windows, reenable them back now because
141 // if they stay disabled Windows will activate another window (one
142 // which is enabled, anyhow) and we will lose activation
143 if ( m_windowDisabler )
144 {
145 delete m_windowDisabler;
146 m_windowDisabler = NULL;
147 }
148
149 if ( IsModal() )
150 EndModal(wxID_CANCEL);
151 }
152
153 bool ret = wxDialogBase::Show(show);
154
155 if ( show )
156 InitDialog();
157
158 return ret;
159 }
160
161 bool wxDialog::IsModal() const
162 {
163 return m_isShowingModal;
164 }
165
166 int wxDialog::ShowModal()
167 {
168 if ( IsModal() )
169 {
170 wxFAIL_MSG( wxT("wxDialog:ShowModal called twice") );
171 return GetReturnCode();
172 }
173
174 // use the apps top level window as parent if none given unless explicitly
175 // forbidden
176 if ( !GetParent() && !(GetWindowStyleFlag() & wxDIALOG_NO_PARENT) )
177 {
178 wxWindow *parent = wxTheApp->GetTopWindow();
179 if ( parent && parent != this )
180 {
181 m_parent = parent;
182 }
183 }
184
185 Show(true);
186
187 m_isShowingModal = true;
188
189 wxASSERT_MSG( !m_windowDisabler, _T("disabling windows twice?") );
190
191 #if defined(__WXGTK__) || defined(__WXMGL__)
192 wxBusyCursorSuspender suspender;
193 // FIXME (FIXME_MGL) - make sure busy cursor disappears under MSW too
194 #endif
195
196 m_windowDisabler = new wxWindowDisabler(this);
197 if ( !m_eventLoop )
198 m_eventLoop = new wxEventLoop;
199
200 m_eventLoop->Run();
201
202 return GetReturnCode();
203 }
204
205 void wxDialog::EndModal(int retCode)
206 {
207 wxASSERT_MSG( m_eventLoop, _T("wxDialog is not modal") );
208
209 SetReturnCode(retCode);
210
211 if ( !IsModal() )
212 {
213 wxFAIL_MSG( wxT("wxDialog:EndModal called twice") );
214 return;
215 }
216
217 m_isShowingModal = false;
218
219 m_eventLoop->Exit();
220
221 Show(false);
222 }