This is more useful than leaving the focus on the "OK" button, which can already be easily activated from keyboard. Closes #19277.
263 lines
6.8 KiB
C++
263 lines
6.8 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/generic/preferencesg.cpp
|
|
// Purpose: Implementation of wxPreferencesEditor.
|
|
// Author: Vaclav Slavik
|
|
// Created: 2013-02-19
|
|
// 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"
|
|
|
|
|
|
#if wxUSE_PREFERENCES_EDITOR
|
|
|
|
#include "wx/private/preferences.h"
|
|
|
|
#ifndef wxHAS_PREF_EDITOR_NATIVE
|
|
|
|
#include "wx/app.h"
|
|
#include "wx/dialog.h"
|
|
#include "wx/notebook.h"
|
|
#include "wx/sizer.h"
|
|
#include "wx/sharedptr.h"
|
|
#include "wx/scopedptr.h"
|
|
#include "wx/scopeguard.h"
|
|
#include "wx/vector.h"
|
|
|
|
namespace
|
|
{
|
|
|
|
class wxGenericPrefsDialog : public wxDialog
|
|
{
|
|
public:
|
|
wxGenericPrefsDialog(wxWindow *parent, const wxString& title)
|
|
: wxDialog(parent, wxID_ANY, title,
|
|
wxDefaultPosition, wxDefaultSize,
|
|
wxDEFAULT_FRAME_STYLE & ~(wxRESIZE_BORDER | wxMAXIMIZE_BOX | wxMINIMIZE_BOX))
|
|
{
|
|
wxSizer *sizer = new wxBoxSizer(wxVERTICAL);
|
|
|
|
m_notebook = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_MULTILINE);
|
|
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);
|
|
|
|
m_notebook->SetFocus();
|
|
}
|
|
|
|
void AddPage(wxPreferencesPage *page)
|
|
{
|
|
wxWindow *win = page->CreateWindow(m_notebook);
|
|
m_notebook->AddPage(win, page->GetName());
|
|
}
|
|
|
|
int GetSelectedPage() const
|
|
{
|
|
return m_notebook->GetSelection();
|
|
}
|
|
|
|
void SelectPage(int page)
|
|
{
|
|
m_notebook->ChangeSelection(page);
|
|
}
|
|
|
|
bool ShouldPreventAppExit() const wxOVERRIDE
|
|
{
|
|
return false;
|
|
}
|
|
|
|
private:
|
|
wxNotebook *m_notebook;
|
|
};
|
|
|
|
|
|
class wxGenericPreferencesEditorImplBase : public wxPreferencesEditorImpl
|
|
{
|
|
public:
|
|
void SetTitle(const wxString& title)
|
|
{
|
|
m_title = title;
|
|
}
|
|
|
|
virtual void AddPage(wxPreferencesPage* page) wxOVERRIDE
|
|
{
|
|
m_pages.push_back(wxSharedPtr<wxPreferencesPage>(page));
|
|
}
|
|
|
|
protected:
|
|
wxGenericPrefsDialog *CreateDialog(wxWindow *parent)
|
|
{
|
|
if ( m_title.empty() )
|
|
{
|
|
// Use the default title, which should include the application name
|
|
// under both MSW and GTK (and OSX uses its own native
|
|
// implementation anyhow).
|
|
m_title.Printf(_("%s Preferences"), wxTheApp->GetAppDisplayName());
|
|
}
|
|
|
|
wxGenericPrefsDialog *dlg = new wxGenericPrefsDialog(parent, m_title);
|
|
|
|
// 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());
|
|
}
|
|
|
|
dlg->Fit();
|
|
|
|
return dlg;
|
|
}
|
|
|
|
typedef wxVector< wxSharedPtr<wxPreferencesPage> > Pages;
|
|
Pages m_pages;
|
|
|
|
private:
|
|
wxString m_title;
|
|
};
|
|
|
|
|
|
#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) wxOVERRIDE
|
|
{
|
|
if ( !m_win )
|
|
{
|
|
wxWindow *win = CreateDialog(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() wxOVERRIDE
|
|
{
|
|
if ( m_win )
|
|
{
|
|
m_win->Close(/*force=*/true);
|
|
m_win = NULL;
|
|
}
|
|
}
|
|
|
|
private:
|
|
wxWeakRef<wxWindow> m_win;
|
|
};
|
|
|
|
inline
|
|
wxGenericPreferencesEditorImplBase* NewGenericImpl()
|
|
{
|
|
return new wxModelessPreferencesEditorImpl;
|
|
}
|
|
|
|
#else // !wxHAS_PREF_EDITOR_MODELESS
|
|
|
|
class wxModalPreferencesEditorImpl : public wxGenericPreferencesEditorImplBase
|
|
{
|
|
public:
|
|
wxModalPreferencesEditorImpl()
|
|
{
|
|
m_dlg = NULL;
|
|
m_currentPage = -1;
|
|
}
|
|
|
|
virtual void Show(wxWindow* parent) wxOVERRIDE
|
|
{
|
|
wxScopedPtr<wxGenericPrefsDialog> dlg(CreateDialog(parent));
|
|
|
|
// Store it for Dismiss() but ensure that the pointer is reset to NULL
|
|
// when the dialog is destroyed on leaving this function.
|
|
m_dlg = dlg.get();
|
|
wxON_BLOCK_EXIT_NULL(m_dlg);
|
|
|
|
// Restore the previously selected page, if any.
|
|
if ( m_currentPage != -1 )
|
|
dlg->SelectPage(m_currentPage);
|
|
|
|
// Don't remember the last selected page if the dialog was cancelled.
|
|
if ( dlg->ShowModal() != wxID_CANCEL )
|
|
m_currentPage = dlg->GetSelectedPage();
|
|
}
|
|
|
|
virtual void Dismiss() wxOVERRIDE
|
|
{
|
|
if ( m_dlg )
|
|
{
|
|
m_dlg->EndModal(wxID_CANCEL);
|
|
m_dlg = NULL;
|
|
}
|
|
}
|
|
|
|
private:
|
|
wxGenericPrefsDialog* m_dlg;
|
|
int m_currentPage;
|
|
|
|
wxDECLARE_NO_COPY_CLASS(wxModalPreferencesEditorImpl);
|
|
};
|
|
|
|
inline
|
|
wxGenericPreferencesEditorImplBase* NewGenericImpl()
|
|
{
|
|
return new wxModalPreferencesEditorImpl;
|
|
}
|
|
|
|
#endif // !wxHAS_PREF_EDITOR_MODELESS
|
|
|
|
} // anonymous namespace
|
|
|
|
/*static*/
|
|
wxPreferencesEditorImpl* wxPreferencesEditorImpl::Create(const wxString& title)
|
|
{
|
|
wxGenericPreferencesEditorImplBase* const impl = NewGenericImpl();
|
|
|
|
impl->SetTitle(title);
|
|
|
|
return impl;
|
|
}
|
|
|
|
#endif // !wxHAS_PREF_EDITOR_NATIVE
|
|
|
|
#endif // wxUSE_PREFERENCES_EDITOR
|