1/////////////////////////////////////////////////////////////////////////////
2// Name:        src/univ/dialog.cpp
3// Author:      Robert Roebling, Vaclav Slavik
4// Id:          $Id: dialog.cpp 39273 2006-05-22 20:54:04Z ABX $
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
37BEGIN_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)
42END_EVENT_TABLE()
43
44IMPLEMENT_DYNAMIC_CLASS(wxDialog,wxTopLevelWindow)
45
46void wxDialog::Init()
47{
48    m_returnCode = 0;
49    m_windowDisabler = NULL;
50    m_eventLoop = NULL;
51    m_isShowingModal = false;
52}
53
54wxDialog::~wxDialog()
55{
56    delete m_eventLoop;
57}
58
59bool 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
72void wxDialog::OnApply(wxCommandEvent &WXUNUSED(event))
73{
74    if ( Validate() )
75        TransferDataFromWindow();
76}
77
78void 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
91void 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
107void 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
136bool 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
161bool wxDialog::IsModal() const
162{
163    return m_isShowingModal;
164}
165
166int 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
205void 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}
223