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