]> git.saurik.com Git - wxWidgets.git/blame - src/generic/preferencesg.cpp
Add a public wxModalDialogHook class for intercepting modal dialogs.
[wxWidgets.git] / src / generic / preferencesg.cpp
CommitLineData
2aab96f5
VS
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/generic/preferencesg.cpp
3// Purpose: Implementation of wxPreferencesEditor.
4// Author: Vaclav Slavik
5// Created: 2013-02-19
6// RCS-ID: $Id$
7// Copyright: (c) 2013 Vaclav Slavik <vslavik@fastmail.fm>
8// Licence: wxWindows licence
9///////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// for compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
26#include "wx/private/preferences.h"
27
28#ifndef wxHAS_PREF_EDITOR_NATIVE
29
dc5d118e 30#include "wx/app.h"
2aab96f5
VS
31#include "wx/dialog.h"
32#include "wx/notebook.h"
33#include "wx/sizer.h"
34#include "wx/sharedptr.h"
35#include "wx/scopedptr.h"
615f9ff0 36#include "wx/scopeguard.h"
2aab96f5
VS
37#include "wx/vector.h"
38
654c4b7b
VZ
39namespace
40{
41
2aab96f5
VS
42class wxGenericPrefsDialog : public wxDialog
43{
44public:
654c4b7b
VZ
45 wxGenericPrefsDialog(wxWindow *parent, const wxString& title)
46 : wxDialog(parent, wxID_ANY, title,
2aab96f5
VS
47 wxDefaultPosition, wxDefaultSize,
48 wxDEFAULT_FRAME_STYLE & ~(wxRESIZE_BORDER | wxMAXIMIZE_BOX | wxMINIMIZE_BOX))
49 {
50 SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
51
52 wxSizer *sizer = new wxBoxSizer(wxVERTICAL);
53
54 m_notebook = new wxNotebook(this, wxID_ANY);
55 sizer->Add(m_notebook, wxSizerFlags(1).Expand().DoubleBorder());
56
57#ifdef __WXGTK__
58 SetEscapeId(wxID_CLOSE);
59 sizer->Add(CreateButtonSizer(wxCLOSE), wxSizerFlags().Expand().DoubleBorder(wxBOTTOM));
60#else
61 sizer->Add(CreateButtonSizer(wxOK | wxCANCEL),
62 wxSizerFlags().Expand().DoubleBorder(wxLEFT|wxRIGHT|wxBOTTOM));
63#endif
64 SetSizer(sizer);
65 }
66
67 void AddPage(wxPreferencesPage *page)
68 {
69 wxWindow *win = page->CreateWindow(m_notebook);
70 m_notebook->AddPage(win, page->GetName());
71 }
72
f3c0bcfa
VZ
73 int GetSelectedPage() const
74 {
75 return m_notebook->GetSelection();
76 }
77
78 void SelectPage(int page)
79 {
80 m_notebook->ChangeSelection(page);
81 }
82
2aab96f5
VS
83private:
84 wxNotebook *m_notebook;
85};
86
87
88class wxGenericPreferencesEditorImplBase : public wxPreferencesEditorImpl
89{
90public:
654c4b7b
VZ
91 void SetTitle(const wxString& title)
92 {
93 m_title = title;
94 }
95
2aab96f5
VS
96 virtual void AddPage(wxPreferencesPage* page)
97 {
98 m_pages.push_back(wxSharedPtr<wxPreferencesPage>(page));
99 }
100
101protected:
2c544b40 102 wxGenericPrefsDialog *CreateDialog(wxWindow *parent)
2aab96f5 103 {
654c4b7b 104 if ( m_title.empty() )
dc5d118e
VZ
105 {
106 // Use the default title, which should include the application name
107 // under both MSW and GTK (and OSX uses its own native
108 // implementation anyhow).
109 m_title.Printf(_("%s Preferences"), wxTheApp->GetAppDisplayName());
110 }
654c4b7b
VZ
111
112 wxGenericPrefsDialog *dlg = new wxGenericPrefsDialog(parent, m_title);
2aab96f5
VS
113
114 // TODO: Don't create all pages immediately like this, do it on demand
115 // when a page is selected in the notebook (as is done on OS X).
116 //
117 // Currently, creating all pages is necessary so that the notebook
118 // can determine its best size. We'll need to extend
119 // wxPreferencesPage with a GetBestSize() virtual method to make
120 // it possible to defer the creation.
121 for ( Pages::const_iterator i = m_pages.begin();
122 i != m_pages.end();
123 ++i )
124 {
125 dlg->AddPage(i->get());
126 }
127
128 return dlg;
129 }
130
131 typedef wxVector< wxSharedPtr<wxPreferencesPage> > Pages;
132 Pages m_pages;
133
654c4b7b
VZ
134private:
135 wxString m_title;
2aab96f5
VS
136};
137
138
139#ifdef wxHAS_PREF_EDITOR_MODELESS
140
141class wxModelessPreferencesEditorImpl : public wxGenericPreferencesEditorImplBase
142{
143public:
144 virtual ~wxModelessPreferencesEditorImpl()
145 {
146 // m_win may already be destroyed if this destructor is called from
147 // wxApp's destructor. In that case, all windows -- including this
148 // one -- would already be destroyed by now.
149 if ( m_win )
150 m_win->Destroy();
151 }
152
153 virtual void Show(wxWindow* parent)
154 {
155 if ( !m_win )
156 {
2c544b40 157 wxWindow *win = CreateDialog(parent);
2aab96f5
VS
158 win->Show();
159 m_win = win;
160 }
161 else
162 {
163 // Ideally, we'd reparent the dialog under 'parent', but it's
164 // probably not worth the hassle. We know the old parent is still
165 // valid, because otherwise Dismiss() would have been called and
166 // m_win cleared.
167 m_win->Raise();
168 }
169 }
170
171 virtual void Dismiss()
172 {
173 if ( m_win )
174 {
175 m_win->Close(/*force=*/true);
176 m_win = NULL;
177 }
178 }
179
180private:
181 wxWeakRef<wxWindow> m_win;
182};
183
654c4b7b
VZ
184inline
185wxGenericPreferencesEditorImplBase* NewGenericImpl()
186{
187 return new wxModelessPreferencesEditorImpl;
188}
189
2aab96f5
VS
190#else // !wxHAS_PREF_EDITOR_MODELESS
191
192class wxModalPreferencesEditorImpl : public wxGenericPreferencesEditorImplBase
193{
194public:
f3c0bcfa
VZ
195 wxModalPreferencesEditorImpl()
196 {
615f9ff0 197 m_dlg = NULL;
f3c0bcfa
VZ
198 m_currentPage = -1;
199 }
200
2aab96f5
VS
201 virtual void Show(wxWindow* parent)
202 {
2c544b40 203 wxScopedPtr<wxGenericPrefsDialog> dlg(CreateDialog(parent));
615f9ff0
VZ
204
205 // Store it for Dismiss() but ensure that the pointer is reset to NULL
206 // when the dialog is destroyed on leaving this function.
207 m_dlg = dlg.get();
208 wxON_BLOCK_EXIT_NULL(m_dlg);
209
06a32e04 210 dlg->Fit();
f3c0bcfa
VZ
211
212 // Restore the previously selected page, if any.
213 if ( m_currentPage != -1 )
214 dlg->SelectPage(m_currentPage);
215
216 // Don't remember the last selected page if the dialog was cancelled.
217 if ( dlg->ShowModal() != wxID_CANCEL )
218 m_currentPage = dlg->GetSelectedPage();
2aab96f5
VS
219 }
220
221 virtual void Dismiss()
222 {
615f9ff0
VZ
223 if ( m_dlg )
224 {
225 m_dlg->EndModal(wxID_CANCEL);
226 m_dlg = NULL;
227 }
2aab96f5 228 }
f3c0bcfa
VZ
229
230private:
615f9ff0 231 wxGenericPrefsDialog* m_dlg;
f3c0bcfa 232 int m_currentPage;
615f9ff0
VZ
233
234 wxDECLARE_NO_COPY_CLASS(wxModalPreferencesEditorImpl);
2aab96f5
VS
235};
236
654c4b7b
VZ
237inline
238wxGenericPreferencesEditorImplBase* NewGenericImpl()
239{
240 return new wxModalPreferencesEditorImpl;
241}
242
2aab96f5
VS
243#endif // !wxHAS_PREF_EDITOR_MODELESS
244
654c4b7b 245} // anonymous namespace
2aab96f5
VS
246
247/*static*/
654c4b7b 248wxPreferencesEditorImpl* wxPreferencesEditorImpl::Create(const wxString& title)
2aab96f5 249{
654c4b7b
VZ
250 wxGenericPreferencesEditorImplBase* const impl = NewGenericImpl();
251
252 impl->SetTitle(title);
253
254 return impl;
2aab96f5
VS
255}
256
257#endif // !wxHAS_PREF_EDITOR_NATIVE