]> git.saurik.com Git - wxWidgets.git/blob - src/generic/preferencesg.cpp
30365e7ebc44ceb2c8f710a010d73688a6492c6a
[wxWidgets.git] / src / generic / preferencesg.cpp
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
30 #include "wx/app.h"
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"
36 #include "wx/vector.h"
37
38 namespace
39 {
40
41 class wxGenericPrefsDialog : public wxDialog
42 {
43 public:
44 wxGenericPrefsDialog(wxWindow *parent, const wxString& title)
45 : wxDialog(parent, wxID_ANY, title,
46 wxDefaultPosition, wxDefaultSize,
47 wxDEFAULT_FRAME_STYLE & ~(wxRESIZE_BORDER | wxMAXIMIZE_BOX | wxMINIMIZE_BOX))
48 {
49 SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
50
51 wxSizer *sizer = new wxBoxSizer(wxVERTICAL);
52
53 m_notebook = new wxNotebook(this, wxID_ANY);
54 sizer->Add(m_notebook, wxSizerFlags(1).Expand().DoubleBorder());
55
56 #ifdef __WXGTK__
57 SetEscapeId(wxID_CLOSE);
58 sizer->Add(CreateButtonSizer(wxCLOSE), wxSizerFlags().Expand().DoubleBorder(wxBOTTOM));
59 #else
60 sizer->Add(CreateButtonSizer(wxOK | wxCANCEL),
61 wxSizerFlags().Expand().DoubleBorder(wxLEFT|wxRIGHT|wxBOTTOM));
62 #endif
63 SetSizer(sizer);
64 }
65
66 void AddPage(wxPreferencesPage *page)
67 {
68 wxWindow *win = page->CreateWindow(m_notebook);
69 m_notebook->AddPage(win, page->GetName());
70 }
71
72 int GetSelectedPage() const
73 {
74 return m_notebook->GetSelection();
75 }
76
77 void SelectPage(int page)
78 {
79 m_notebook->ChangeSelection(page);
80 }
81
82 private:
83 wxNotebook *m_notebook;
84 };
85
86
87 class wxGenericPreferencesEditorImplBase : public wxPreferencesEditorImpl
88 {
89 public:
90 void SetTitle(const wxString& title)
91 {
92 m_title = title;
93 }
94
95 virtual void AddPage(wxPreferencesPage* page)
96 {
97 m_pages.push_back(wxSharedPtr<wxPreferencesPage>(page));
98 }
99
100 protected:
101 wxGenericPrefsDialog *CreateDialog(wxWindow *parent)
102 {
103 if ( m_title.empty() )
104 {
105 // Use the default title, which should include the application name
106 // under both MSW and GTK (and OSX uses its own native
107 // implementation anyhow).
108 m_title.Printf(_("%s Preferences"), wxTheApp->GetAppDisplayName());
109 }
110
111 wxGenericPrefsDialog *dlg = new wxGenericPrefsDialog(parent, m_title);
112
113 // TODO: Don't create all pages immediately like this, do it on demand
114 // when a page is selected in the notebook (as is done on OS X).
115 //
116 // Currently, creating all pages is necessary so that the notebook
117 // can determine its best size. We'll need to extend
118 // wxPreferencesPage with a GetBestSize() virtual method to make
119 // it possible to defer the creation.
120 for ( Pages::const_iterator i = m_pages.begin();
121 i != m_pages.end();
122 ++i )
123 {
124 dlg->AddPage(i->get());
125 }
126
127 return dlg;
128 }
129
130 typedef wxVector< wxSharedPtr<wxPreferencesPage> > Pages;
131 Pages m_pages;
132
133 private:
134 wxString m_title;
135 };
136
137
138 #ifdef wxHAS_PREF_EDITOR_MODELESS
139
140 class wxModelessPreferencesEditorImpl : public wxGenericPreferencesEditorImplBase
141 {
142 public:
143 virtual ~wxModelessPreferencesEditorImpl()
144 {
145 // m_win may already be destroyed if this destructor is called from
146 // wxApp's destructor. In that case, all windows -- including this
147 // one -- would already be destroyed by now.
148 if ( m_win )
149 m_win->Destroy();
150 }
151
152 virtual void Show(wxWindow* parent)
153 {
154 if ( !m_win )
155 {
156 wxWindow *win = CreateDialog(parent);
157 win->Show();
158 m_win = win;
159 }
160 else
161 {
162 // Ideally, we'd reparent the dialog under 'parent', but it's
163 // probably not worth the hassle. We know the old parent is still
164 // valid, because otherwise Dismiss() would have been called and
165 // m_win cleared.
166 m_win->Raise();
167 }
168 }
169
170 virtual void Dismiss()
171 {
172 if ( m_win )
173 {
174 m_win->Close(/*force=*/true);
175 m_win = NULL;
176 }
177 }
178
179 private:
180 wxWeakRef<wxWindow> m_win;
181 };
182
183 inline
184 wxGenericPreferencesEditorImplBase* NewGenericImpl()
185 {
186 return new wxModelessPreferencesEditorImpl;
187 }
188
189 #else // !wxHAS_PREF_EDITOR_MODELESS
190
191 class wxModalPreferencesEditorImpl : public wxGenericPreferencesEditorImplBase
192 {
193 public:
194 wxModalPreferencesEditorImpl()
195 {
196 m_currentPage = -1;
197 }
198
199 virtual void Show(wxWindow* parent)
200 {
201 wxScopedPtr<wxGenericPrefsDialog> dlg(CreateDialog(parent));
202 dlg->Fit();
203
204 // Restore the previously selected page, if any.
205 if ( m_currentPage != -1 )
206 dlg->SelectPage(m_currentPage);
207
208 // Don't remember the last selected page if the dialog was cancelled.
209 if ( dlg->ShowModal() != wxID_CANCEL )
210 m_currentPage = dlg->GetSelectedPage();
211 }
212
213 virtual void Dismiss()
214 {
215 // nothing to do
216 }
217
218 private:
219 int m_currentPage;
220 };
221
222 inline
223 wxGenericPreferencesEditorImplBase* NewGenericImpl()
224 {
225 return new wxModalPreferencesEditorImpl;
226 }
227
228 #endif // !wxHAS_PREF_EDITOR_MODELESS
229
230 } // anonymous namespace
231
232 /*static*/
233 wxPreferencesEditorImpl* wxPreferencesEditorImpl::Create(const wxString& title)
234 {
235 wxGenericPreferencesEditorImplBase* const impl = NewGenericImpl();
236
237 impl->SetTitle(title);
238
239 return impl;
240 }
241
242 #endif // !wxHAS_PREF_EDITOR_NATIVE