Add wxPreferencesEditor class.

Implements native UI for preferences editing.  In particular, the API
handles the differences between modal (Windows) and non-modal (OS X) preferences windows and provides platform's native look.

Currently implemented natively for wxOSX/Cocoa, wxGTK and Windows (the latter is used as a fallback generic implementation as well).

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@73576 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Václav Slavík
2013-02-28 16:29:05 +00:00
parent d52a1abad3
commit 2aab96f58d
16 changed files with 4401 additions and 3173 deletions

View File

@@ -0,0 +1,184 @@
///////////////////////////////////////////////////////////////////////////////
// Name: src/generic/preferencesg.cpp
// Purpose: Implementation of wxPreferencesEditor.
// Author: Vaclav Slavik
// Created: 2013-02-19
// RCS-ID: $Id$
// Copyright: (c) 2013 Vaclav Slavik <vslavik@fastmail.fm>
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// for compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "wx/private/preferences.h"
#ifndef wxHAS_PREF_EDITOR_NATIVE
#include "wx/dialog.h"
#include "wx/notebook.h"
#include "wx/sizer.h"
#include "wx/sharedptr.h"
#include "wx/scopedptr.h"
#include "wx/vector.h"
class wxGenericPrefsDialog : public wxDialog
{
public:
wxGenericPrefsDialog(wxWindow *parent)
: wxDialog(parent, wxID_ANY, _("Preferences"),
wxDefaultPosition, wxDefaultSize,
wxDEFAULT_FRAME_STYLE & ~(wxRESIZE_BORDER | wxMAXIMIZE_BOX | wxMINIMIZE_BOX))
{
SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
wxSizer *sizer = new wxBoxSizer(wxVERTICAL);
m_notebook = new wxNotebook(this, wxID_ANY);
sizer->Add(m_notebook, wxSizerFlags(1).Expand().DoubleBorder());
#ifdef __WXGTK__
SetEscapeId(wxID_CLOSE);
sizer->Add(CreateButtonSizer(wxCLOSE), wxSizerFlags().Expand().DoubleBorder(wxBOTTOM));
#else
sizer->Add(CreateButtonSizer(wxOK | wxCANCEL),
wxSizerFlags().Expand().DoubleBorder(wxLEFT|wxRIGHT|wxBOTTOM));
#endif
SetSizer(sizer);
}
void AddPage(wxPreferencesPage *page)
{
wxWindow *win = page->CreateWindow(m_notebook);
m_notebook->AddPage(win, page->GetName());
}
private:
wxNotebook *m_notebook;
};
class wxGenericPreferencesEditorImplBase : public wxPreferencesEditorImpl
{
public:
virtual void AddPage(wxPreferencesPage* page)
{
m_pages.push_back(wxSharedPtr<wxPreferencesPage>(page));
}
protected:
virtual wxDialog *CreateWindow(wxWindow *parent)
{
wxGenericPrefsDialog *dlg = new wxGenericPrefsDialog(parent);
// TODO: Don't create all pages immediately like this, do it on demand
// when a page is selected in the notebook (as is done on OS X).
//
// Currently, creating all pages is necessary so that the notebook
// can determine its best size. We'll need to extend
// wxPreferencesPage with a GetBestSize() virtual method to make
// it possible to defer the creation.
for ( Pages::const_iterator i = m_pages.begin();
i != m_pages.end();
++i )
{
dlg->AddPage(i->get());
}
return dlg;
}
typedef wxVector< wxSharedPtr<wxPreferencesPage> > Pages;
Pages m_pages;
};
#ifdef wxHAS_PREF_EDITOR_MODELESS
class wxModelessPreferencesEditorImpl : public wxGenericPreferencesEditorImplBase
{
public:
virtual ~wxModelessPreferencesEditorImpl()
{
// m_win may already be destroyed if this destructor is called from
// wxApp's destructor. In that case, all windows -- including this
// one -- would already be destroyed by now.
if ( m_win )
m_win->Destroy();
}
virtual void Show(wxWindow* parent)
{
if ( !m_win )
{
wxWindow *win = CreateWindow(parent);
win->Show();
m_win = win;
}
else
{
// Ideally, we'd reparent the dialog under 'parent', but it's
// probably not worth the hassle. We know the old parent is still
// valid, because otherwise Dismiss() would have been called and
// m_win cleared.
m_win->Raise();
}
}
virtual void Dismiss()
{
if ( m_win )
{
m_win->Close(/*force=*/true);
m_win = NULL;
}
}
private:
wxWeakRef<wxWindow> m_win;
};
#else // !wxHAS_PREF_EDITOR_MODELESS
class wxModalPreferencesEditorImpl : public wxGenericPreferencesEditorImplBase
{
public:
virtual void Show(wxWindow* parent)
{
wxScopedPtr<wxDialog> dlg(CreateWindow(parent));
dlg->ShowModal();
}
virtual void Dismiss()
{
// nothing to do
}
};
#endif // !wxHAS_PREF_EDITOR_MODELESS
/*static*/
wxPreferencesEditorImpl* wxPreferencesEditorImpl::Create()
{
#ifdef wxHAS_PREF_EDITOR_MODELESS
return new wxModelessPreferencesEditorImpl();
#else
return new wxModalPreferencesEditorImpl();
#endif
}
#endif // !wxHAS_PREF_EDITOR_NATIVE