]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/generic/preferencesg.cpp
Don't crash in wxGridCellAutoWrapStringRenderer when the column is hidden.
[wxWidgets.git] / src / generic / preferencesg.cpp
... / ...
CommitLineData
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
40namespace
41{
42
43class wxGenericPrefsDialog : public wxDialog
44{
45public:
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
84private:
85 wxNotebook *m_notebook;
86};
87
88
89class wxGenericPreferencesEditorImplBase : public wxPreferencesEditorImpl
90{
91public:
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
102protected:
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
137private:
138 wxString m_title;
139};
140
141
142#ifdef wxHAS_PREF_EDITOR_MODELESS
143
144class wxModelessPreferencesEditorImpl : public wxGenericPreferencesEditorImplBase
145{
146public:
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
183private:
184 wxWeakRef<wxWindow> m_win;
185};
186
187inline
188wxGenericPreferencesEditorImplBase* NewGenericImpl()
189{
190 return new wxModelessPreferencesEditorImpl;
191}
192
193#else // !wxHAS_PREF_EDITOR_MODELESS
194
195class wxModalPreferencesEditorImpl : public wxGenericPreferencesEditorImplBase
196{
197public:
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
231private:
232 wxGenericPrefsDialog* m_dlg;
233 int m_currentPage;
234
235 wxDECLARE_NO_COPY_CLASS(wxModalPreferencesEditorImpl);
236};
237
238inline
239wxGenericPreferencesEditorImplBase* NewGenericImpl()
240{
241 return new wxModalPreferencesEditorImpl;
242}
243
244#endif // !wxHAS_PREF_EDITOR_MODELESS
245
246} // anonymous namespace
247
248/*static*/
249wxPreferencesEditorImpl* 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