KiCad PCB EDA Suite
Loading...
Searching...
No Matches
startwizard.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2023 Mark Roszko <[email protected]>
5 * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <build_version.h>
22#include <confirm.h>
23#include <kiface_base.h>
24#include <pgm_base.h>
25#include <wx/display.h>
26#include <wx/statline.h>
27#include <wx/wx.h>
28#include <wx/wizard.h>
34#include <wx/hyperlink.h>
35
36
37class STARTWIZARD_PAGE : public wxWizardPageSimple
38{
39public:
40 STARTWIZARD_PAGE( wxWizard* aParent, const wxString& aPageTitle ) :
41 wxWizardPageSimple( aParent )
42 {
43 wxBoxSizer* outerSizer = new wxBoxSizer( wxVERTICAL );
44
45 m_scrolledWindow = new wxScrolledWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
46 wxVSCROLL | wxBORDER_NONE );
47 m_scrolledWindow->SetScrollRate( 0, 5 );
48
49 m_mainSizer = new wxBoxSizer( wxVERTICAL );
50
51 wxStaticText* pageTitle = new wxStaticText( m_scrolledWindow, -1, aPageTitle );
52 pageTitle->SetFont(
53 wxFont( 14, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD ) );
54 m_mainSizer->Add( pageTitle, 0, wxALIGN_CENTRE | wxALL, 5 );
55
56 wxStaticLine* pageDivider = new wxStaticLine( m_scrolledWindow, wxID_ANY,
57 wxDefaultPosition, wxDefaultSize,
58 wxLI_HORIZONTAL );
59 m_mainSizer->Add( pageDivider, 0, wxEXPAND | wxALL, 5 );
60
61 m_scrolledWindow->SetSizer( m_mainSizer );
62
63 outerSizer->Add( m_scrolledWindow, 1, wxEXPAND );
64 SetSizer( outerSizer );
65 }
66
67 // Returns the scrolled content area; use this as the parent for panel content
68 // so the content is scrollable when the wizard is smaller than the page requires.
69 wxWindow* GetContentParent() const { return m_scrolledWindow; }
70
71 void AddContent( wxPanel* aContent )
72 {
73 m_mainSizer->Add( aContent, 0, wxEXPAND );
74 m_scrolledWindow->FitInside();
75 }
76
77 // Returns the minimum size of the scrolled content, independent of the page size.
78 wxSize GetContentMinSize() const { return m_mainSizer->CalcMin(); }
79
80private:
81 wxScrolledWindow* m_scrolledWindow;
82 wxBoxSizer* m_mainSizer;
83};
84
85
86class STARTWIZARD_WELCOME_PAGE : public wxWizardPageSimple
87{
88public:
89 STARTWIZARD_WELCOME_PAGE( wxWizard* aParent ) : wxWizardPageSimple( aParent )
90 {
91 m_mainSizer = new wxBoxSizer( wxVERTICAL );
92
93 wxStaticText* pageTitle = new wxStaticText(
94 this, -1, wxString::Format( _( "Welcome to KiCad %s" ), GetMajorMinorVersion() ) );
95 pageTitle->SetFont(
96 wxFont( 14, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD ) );
97 m_mainSizer->Add( pageTitle, 0, wxALIGN_CENTRE | wxALL, 5 );
98
99 wxStaticLine* pageDivider = new wxStaticLine( this, wxID_ANY, wxDefaultPosition,
100 wxDefaultSize, wxLI_HORIZONTAL );
101 m_mainSizer->Add( pageDivider, 0, wxEXPAND | wxALL, 5 );
102
103 m_welcomeText = new wxStaticText( this, -1,
104 _( "KiCad is starting for the first time, or some of its configuration files are missing.\n\n"
105 "Let's take a moment to configure some basic settings. You can always modify these "
106 "settings later by opening the Preferences dialog." ) );
107 m_mainSizer->Add( m_welcomeText, 0, wxEXPAND | wxALL, 5 );
108
109 wxBoxSizer* helpSizer = new wxBoxSizer( wxHORIZONTAL );
110 wxStaticText* helpLabel = new wxStaticText( this, -1, _( "For help, please visit " ) );
111 wxString docsUrl = wxString::Format( "https://go.kicad.org/docs/%s", GetMajorMinorVersion() );
112 wxHyperlinkCtrl* helpLink = new wxHyperlinkCtrl( this, -1, wxT( "docs.kicad.org" ), docsUrl );
113 helpSizer->Add( helpLabel, 0, wxLEFT | wxTOP | wxBOTTOM | wxALIGN_CENTER_VERTICAL, 5 );
114 helpSizer->Add( helpLink, 0, wxRIGHT | wxTOP | wxBOTTOM | wxALIGN_CENTER_VERTICAL, 5 );
115 m_mainSizer->Add( helpSizer, 0, wxEXPAND, 5 );
116
117 SetSizerAndFit( m_mainSizer );
118 }
119
120 void SetWrap( int aWidth ) const
121 {
122 m_welcomeText->Wrap( aWidth );
123 }
124
125private:
126 wxBoxSizer* m_mainSizer;
127 wxStaticText* m_welcomeText;
128};
129
130
132 m_wizard( nullptr )
133{
134}
135
136
140
141
143{
144 if( auto it = std::ranges::find_if( m_providers,
145 [&]( const std::unique_ptr<STARTWIZARD_PROVIDER>& aProvider )
146 {
147 return aProvider->Name() == aName;
148 } ); it != m_providers.end() )
149 {
150 return it->get();
151 }
152
153 return nullptr;
154}
155
156
157void STARTWIZARD::CheckAndRun( wxWindow* aParent )
158{
159 m_providers.clear();
160
161 m_providers.push_back( std::make_unique<STARTWIZARD_PROVIDER_SETTINGS>() );
162 m_providers.push_back( std::make_unique<STARTWIZARD_PROVIDER_LIBRARIES>() );
163 m_providers.push_back( std::make_unique<STARTWIZARD_PROVIDER_PRIVACY>() );
164 //providers.push_back( std::make_unique<STARTWIZARD_PROVIDER_LOOK_AND_FEEL>() );
165
166 if( m_providers.size() == 0 )
167 return;
168
169 bool wizardRequired = std::ranges::any_of( std::as_const( m_providers ),
170 []( const std::unique_ptr<STARTWIZARD_PROVIDER>& aProvider ) -> bool
171 {
172 return aProvider->NeedsUserInput();
173 } );
174
175 if( !wizardRequired )
176 return;
177
178 Pgm().HideSplash();
179
180 m_wizard = new wxWizard( aParent, wxID_ANY, _( "KiCad Setup" ) );
181 m_wizard->SetWindowStyleFlag( wxRESIZE_BORDER );
182
184 wxWizardPageSimple* lastPage = nullptr;
185 wxSize minPageSize;
186
187 for( std::unique_ptr<STARTWIZARD_PROVIDER>& provider : m_providers )
188 {
189 if( !provider->NeedsUserInput() )
190 continue;
191
192 provider->SetWasShown( true );
193
194 STARTWIZARD_PAGE* page = new STARTWIZARD_PAGE( m_wizard, provider->GetPageName() );
195 wxPanel* panel = provider->GetWizardPanel( page->GetContentParent(), this );
196 page->AddContent( panel );
197
198 if( lastPage != nullptr )
199 {
200 lastPage->Chain( page );
201 }
202 else
203 {
204 firstPage->Chain( page );
205 }
206
207 lastPage = page;
208
209 wxSize size = page->GetContentMinSize();
210
211 if( size.x > minPageSize.x )
212 minPageSize.x = size.x;
213
214 if( size.y > minPageSize.y )
215 minPageSize.y = size.y;
216 }
217
218 // Clamp the page size to the available display area so the wizard is fully
219 // accessible on small or low-resolution screens. Reserve space for the
220 // wizard title bar, the Back/Next/Cancel button row, and a small margin.
221 static constexpr int WIZARD_CHROME_HEIGHT = 120;
222 static constexpr int WIZARD_MARGIN = 40;
223
224 wxSize pageSize = minPageSize + wxSize( 10, 10 );
225
226 int displayIdx = wxDisplay::GetFromWindow( aParent ? aParent : wxTheApp->GetTopWindow() );
227
228 if( displayIdx == wxNOT_FOUND )
229 displayIdx = 0;
230
231 wxRect displayArea = wxDisplay( (unsigned int) displayIdx ).GetClientArea();
232 int maxPageHeight = displayArea.GetHeight() - WIZARD_CHROME_HEIGHT - WIZARD_MARGIN;
233
234 if( maxPageHeight > 0 && pageSize.y > maxPageHeight )
235 pageSize.y = maxPageHeight;
236
237 m_wizard->SetPageSize( pageSize );
238 firstPage->SetWrap( pageSize.x );
239
240 m_wizard->Bind( wxEVT_WIZARD_CANCEL,
241 [&]( wxWizardEvent& aEvt )
242 {
243 if( IsOK( aParent, _( "Are you sure? If you cancel KiCad setup, default settings "
244 "will be chosen for you." ) ) )
245 {
246 for( std::unique_ptr<STARTWIZARD_PROVIDER>& provider : m_providers )
247 {
248 provider->ApplyDefaults();
249 }
250 }
251 else
252 {
253 aEvt.Veto();
254 }
255 } );
256
257 if( m_wizard->RunWizard( firstPage ) )
258 {
259 for( std::unique_ptr<STARTWIZARD_PROVIDER>& provider : m_providers )
260 {
261 if( !provider->WasShown() )
262 continue;
263
264 provider->Finish();
265 }
266 }
267
268 m_wizard->Destroy();
269 m_wizard = nullptr;
270}
wxString GetMajorMinorVersion()
Get only the major and minor version in a string major.minor.
void HideSplash()
Definition pgm_base.cpp:317
STARTWIZARD_PAGE(wxWizard *aParent, const wxString &aPageTitle)
wxScrolledWindow * m_scrolledWindow
wxBoxSizer * m_mainSizer
void AddContent(wxPanel *aContent)
wxSize GetContentMinSize() const
wxWindow * GetContentParent() const
void SetWrap(int aWidth) const
wxStaticText * m_welcomeText
STARTWIZARD_WELCOME_PAGE(wxWizard *aParent)
STARTWIZARD_PROVIDER * GetProvider(const wxString &aName)
std::vector< std::unique_ptr< STARTWIZARD_PROVIDER > > m_providers
Definition startwizard.h:46
void CheckAndRun(wxWindow *parent)
wxWizard * m_wizard
Definition startwizard.h:45
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:259
This file is part of the common library.
#define _(s)
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE