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