KiCad PCB EDA Suite
Loading...
Searching...
No Matches
panel_common_settings.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
21
22#include <advanced_config.h>
23#include <bitmaps.h>
25#include <dpi_scaling_common.h>
26#include <eda_draw_frame.h>
28#include <kiface_base.h>
29#include <kiplatform/ui.h>
30#include <pgm_base.h>
31#include <id.h>
35#include <wx/filedlg.h>
36
37/*
38 * What follows is a whole lot of ugly to handle various platform GUI deficiences with respect
39 * to light/dark mode, DPI scaling, and other foibles.
40 *
41 * Ugly as it all is, it does improve our usability on various platforms.
42 */
43
46{
47 // Rendering engine
48#ifdef __WXMAC__
49 // On MAC, Cairo render does not work.
50 m_renderingSizer->Show( false );
51#endif
52
54
57
58 /*
59 * Automatic dark mode detection works fine on Mac, so no need for the explicit options.
60 */
61#ifdef __WXMAC__
62 m_stIconTheme->Show( false );
63 m_rbIconThemeLight->Show( false );
64 m_rbIconThemeDark->Show( false );
65 m_rbIconThemeAuto->Show( false );
66#endif
67
68 // It's common on Windows to have separate app and system settings for light/dark
69#ifndef __WXMSW__
70 m_stAppTheme->Show( false );
71 m_rbAppThemeLight->Show( false );
72 m_rbAppThemeDark->Show( false );
73 m_rbAppThemeAuto->Show( false );
74#endif
75
76 /*
77 * Automatic canvas scaling works fine on all supported platforms, so manual scaling is disabled
78 */
79 if( ADVANCED_CFG::GetCfg().m_AllowManualCanvasScale )
80 {
81 static constexpr int dpi_scaling_precision = 1;
82 static constexpr double dpi_scaling_increment = 0.5;
83
86 m_canvasScaleCtrl->SetDigits( dpi_scaling_precision );
87 m_canvasScaleCtrl->SetIncrement( dpi_scaling_increment );
89
90 m_canvasScaleCtrl->SetToolTip( _( "Set the scale for the canvas."
91 "\n\n"
92 "On high-DPI displays on some platforms, KiCad cannot determine the "
93 "scaling factor. In this case you may need to set this to a value to "
94 "match your system's DPI scaling. 2.0 is a common value. "
95 "\n\n"
96 "If this does not match the system DPI scaling, the canvas will "
97 "not match the window size and cursor position." ) );
98
99 m_canvasScaleAuto->SetToolTip( _( "Use an automatic value for the canvas scale."
100 "\n\n"
101 "On some platforms, the automatic value is incorrect and should be "
102 "set manually." ) );
103 }
104 else
105 {
106 m_staticTextCanvasScale->Show( false );
107 m_canvasScaleCtrl->Show( false );
108 m_canvasScaleCtrl = nullptr;
109 m_canvasScaleAuto->Show( false );
110 }
111
113 Pgm().GetCommonSettings()->m_Appearance.zoom_correction_factor,
114 ADVANCED_CFG::GetCfg().m_ScreenDPI );
115
116 m_scalingSizer->Add( m_zoomCorrectionCtrl, 1, wxEXPAND );
117
118 // Hide the option of icons in menus for platforms that do not support them
120
121 m_scaleFonts->Show( false );
122 m_fontScalingHelp->Show( false );
123
125 {
126 m_canvasScaleCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED,
127 wxCommandEventHandler( PANEL_COMMON_SETTINGS::OnCanvasScaleChange ),
128 nullptr, this );
129 }
130
131 wxSize minSize = m_highContrastCtrl->GetMinSize();
132 int minWidth = m_highContrastCtrl->GetTextExtent( wxT( "XXX.XXX" ) ).GetWidth();
133
134 m_highContrastCtrl->SetMinSize( wxSize( minWidth, minSize.GetHeight() ) );
135}
136
137
139{
141 {
142 m_canvasScaleCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED,
143 wxCommandEventHandler( PANEL_COMMON_SETTINGS::OnCanvasScaleChange ),
144 nullptr, this );
145 }
146}
147
148
150{
151 COMMON_SETTINGS* commonSettings = Pgm().GetCommonSettings();
152
153 applySettingsToPanel( *commonSettings );
154
155 m_textCtrlFileManager->SetValue( commonSettings->m_System.file_explorer );
156
157 // TODO(JE) Move these into COMMON_SETTINGS probably
158 m_textEditorPath->SetValue( Pgm().GetTextEditor( false ) );
159 m_defaultPDFViewer->SetValue( Pgm().UseSystemPdfBrowser() );
160 m_otherPDFViewer->SetValue( !Pgm().UseSystemPdfBrowser() );
161 m_PDFViewerPath->SetValue( Pgm().GetPdfBrowserName() );
163
164 return true;
165}
166
167
169{
170 COMMON_SETTINGS* commonSettings = Pgm().GetCommonSettings();
171
172 commonSettings->m_System.file_explorer = m_textCtrlFileManager->GetValue();
173 commonSettings->m_System.file_history_size = m_fileHistorySize->GetValue();
174
175 commonSettings->m_Graphics.aa_mode = m_antialiasing->GetSelection();
176
177 if( m_rbAccelerated->GetValue() )
179 else
181
183 {
184 DPI_SCALING_COMMON dpi( commonSettings, this );
185 dpi.SetDpiConfig( m_canvasScaleAuto->GetValue(), m_canvasScaleCtrl->GetValue() );
186 }
187
188 if( m_rbIconThemeLight->GetValue() )
189 commonSettings->m_Appearance.icon_theme = ICON_THEME::LIGHT;
190 else if( m_rbIconThemeDark->GetValue() )
191 commonSettings->m_Appearance.icon_theme = ICON_THEME::DARK;
192 else if( m_rbIconThemeAuto->GetValue() )
193 commonSettings->m_Appearance.icon_theme = ICON_THEME::AUTO;
194
195 if( m_rbAppThemeLight->GetValue() )
196 commonSettings->m_Appearance.app_theme = APP_THEME::LIGHT;
197 else if( m_rbAppThemeDark->GetValue() )
198 commonSettings->m_Appearance.app_theme = APP_THEME::DARK;
199 else if( m_rbAppThemeAuto->GetValue() )
200 commonSettings->m_Appearance.app_theme = APP_THEME::AUTO;
201
202 if( m_rbIconSizeSmall->GetValue() )
203 commonSettings->m_Appearance.toolbar_icon_size = 16;
204 else if( m_rbIconSizeNormal->GetValue() )
205 commonSettings->m_Appearance.toolbar_icon_size = 24;
206 else if( m_rbIconSizeLarge->GetValue() )
207 commonSettings->m_Appearance.toolbar_icon_size = 32;
208
209 commonSettings->m_Appearance.use_icons_in_menus = m_checkBoxIconsInMenus->GetValue();
210 commonSettings->m_Appearance.apply_icon_scale_to_fonts = m_scaleFonts->GetValue();
211
212 commonSettings->m_Appearance.show_scrollbars = m_showScrollbars->GetValue();
213
214 commonSettings->m_Appearance.grid_striping = m_gridStriping->GetValue();
215
216 commonSettings->m_Appearance.use_custom_cursors = !m_disableCustomCursors->GetValue();
217
218 commonSettings->m_Appearance.zoom_correction_factor = m_zoomCorrectionCtrl->GetValue();
219
220 double dimmingPercent = 80;
221 m_highContrastCtrl->GetValue().ToDouble( &dimmingPercent );
222 commonSettings->m_Appearance.hicontrast_dimming_factor = dimmingPercent / 100.0f;
223
224 commonSettings->m_Input.focus_follow_sch_pcb = m_focusFollowSchPcb->GetValue();
225 commonSettings->m_Input.hotkey_feedback = m_hotkeyFeedback->GetValue();
226 commonSettings->m_Input.immediate_actions = !m_NonImmediateActions->GetValue();
227 commonSettings->m_Input.warp_mouse_on_move = m_warpMouseOnMove->GetValue();
228
229 commonSettings->m_Backup.enabled = m_cbBackupEnabled->GetValue();
230 commonSettings->m_Backup.limit_total_size = m_backupLimitTotalSize->GetValue() * 1024ULL * 1024ULL;
231
232 // The radio-box choice order is constructed to match these enum values; if the enum
233 // is reordered in common_settings.h the ternaries below silently flip without these.
234 static_assert( static_cast<int>( BACKUP_FORMAT::INCREMENTAL ) == 0 );
235 static_assert( static_cast<int>( BACKUP_FORMAT::ZIP ) == 1 );
236 static_assert( static_cast<int>( BACKUP_LOCATION::PROJECT_DIR ) == 0 );
237 static_assert( static_cast<int>( BACKUP_LOCATION::USER_DIR ) == 1 );
238
239 commonSettings->m_Backup.format = ( m_choiceBackupFormat->GetSelection() == 0 )
242
243 commonSettings->m_Backup.location = ( m_choiceBackupLocation->GetSelection() == 0 )
246
247 commonSettings->m_Session.remember_open_files = m_cbRememberOpenFiles->GetValue();
248
249 Pgm().SetTextEditor( m_textEditorPath->GetValue());
250
251 Pgm().SetPdfBrowserName( m_PDFViewerPath->GetValue() );
254
255 Pgm().GetSettingsManager().Save( commonSettings );
256
257 return true;
258}
259
260
262{
263 COMMON_SETTINGS defaultSettings;
264
265 defaultSettings.ResetToDefaults();
266
267 applySettingsToPanel( defaultSettings );
268
269 // TODO(JE) Move these into COMMON_SETTINGS probably
270 m_textEditorPath->SetValue( defaultSettings.m_System.text_editor );
271 m_defaultPDFViewer->SetValue( defaultSettings.m_System.use_system_pdf_viewer );
272 m_otherPDFViewer->SetValue( !defaultSettings.m_System.use_system_pdf_viewer );
273 m_PDFViewerPath->SetValue( defaultSettings.m_System.pdf_viewer_name );
275}
276
277
279{
280 m_fileHistorySize->SetValue( aSettings.m_System.file_history_size );
281
282 m_antialiasing->SetSelection( aSettings.m_Graphics.aa_mode );
283
285 m_rbAccelerated->SetValue( true );
286 else
287 m_rbFallback->SetValue( true );
288
290 {
291 const DPI_SCALING_COMMON dpi( &aSettings, this );
292 m_canvasScaleCtrl->SetValue( dpi.GetScaleFactor() );
293 m_canvasScaleAuto->SetValue( dpi.GetCanvasIsAutoScaled() );
294 }
295
296 switch( aSettings.m_Appearance.icon_theme )
297 {
298 case ICON_THEME::LIGHT: m_rbIconThemeLight->SetValue( true ); break;
299 case ICON_THEME::DARK: m_rbIconThemeDark->SetValue( true ); break;
300 case ICON_THEME::AUTO: m_rbIconThemeAuto->SetValue( true ); break;
301 }
302
303 switch( aSettings.m_Appearance.app_theme )
304 {
305 case APP_THEME::LIGHT: m_rbAppThemeLight->SetValue( true ); break;
306 case APP_THEME::DARK: m_rbAppThemeDark->SetValue( true ); break;
307 case APP_THEME::AUTO: m_rbAppThemeAuto->SetValue( true ); break;
308 }
309
310 switch( aSettings.m_Appearance.toolbar_icon_size )
311 {
312 case 16: m_rbIconSizeSmall->SetValue( true ); break;
313 case 24: m_rbIconSizeNormal->SetValue( true ); break;
314 case 32: m_rbIconSizeLarge->SetValue( true ); break;
315 }
316
319
320 m_gridStriping->SetValue( aSettings.m_Appearance.grid_striping );
321
323
324 m_zoomCorrectionCtrl->SetDisplayedValue( aSettings.m_Appearance.zoom_correction_factor );
325
326 double dimmingPercent = aSettings.m_Appearance.hicontrast_dimming_factor * 100.0f;
327 m_highContrastCtrl->SetValue( wxString::Format( "%.0f", dimmingPercent ) );
328
329 m_focusFollowSchPcb->SetValue( aSettings.m_Input.focus_follow_sch_pcb );
330 m_hotkeyFeedback->SetValue( aSettings.m_Input.hotkey_feedback );
331 m_warpMouseOnMove->SetValue( aSettings.m_Input.warp_mouse_on_move );
332 m_NonImmediateActions->SetValue( !aSettings.m_Input.immediate_actions );
333
335
336 m_cbBackupEnabled->SetValue( aSettings.m_Backup.enabled );
337 m_backupLimitTotalSize->SetValue( aSettings.m_Backup.limit_total_size / ( 1024 * 1024 ) );
338
339 m_choiceBackupFormat->SetSelection(
340 aSettings.m_Backup.format == BACKUP_FORMAT::INCREMENTAL ? 0 : 1 );
341
342 m_choiceBackupLocation->SetSelection(
343 aSettings.m_Backup.location == BACKUP_LOCATION::PROJECT_DIR ? 0 : 1 );
344
345 m_showScrollbars->SetValue( aSettings.m_Appearance.show_scrollbars );
346}
347
348
349void PANEL_COMMON_SETTINGS::OnCanvasScaleChange( wxCommandEvent& aEvent )
350{
351 m_canvasScaleAuto->SetValue( false );
352}
353
354
355void PANEL_COMMON_SETTINGS::OnCanvasScaleAuto( wxCommandEvent& aEvent )
356{
357 const bool automatic = m_canvasScaleAuto->GetValue();
358
359 if( automatic && m_canvasScaleCtrl )
360 {
361 // set the scale to the auto value, without consulting the config
362 DPI_SCALING_COMMON dpi( nullptr, this );
363
364 // update the field (no events sent)
365 m_canvasScaleCtrl->SetValue( dpi.GetScaleFactor() );
366 }
367}
368
369
370void PANEL_COMMON_SETTINGS::OnTextEditorClick( wxCommandEvent& event )
371{
372 // Ask the user to select a new editor, but suggest the current one as the default.
373 wxString editorname = Pgm().AskUserForPreferredEditor( m_textEditorPath->GetValue() );
374
375 // If we have a new editor name request it to be copied to m_text_editor and saved
376 // to the preferences file. If the user cancelled the dialog then the previous
377 // value will be retained.
378 if( !editorname.IsEmpty() )
379 m_textEditorPath->SetValue( editorname );
380}
381
382
384{
385 m_staticTextFileManager->Show( aBool );
386 m_textCtrlFileManager->Show( aBool );
387
388 if( aBool )
389 {
390#if defined( __WINDOWS__ )
391 wxString msg = _( "Default 'explorer.exe /n,/select,%F' for this OS." );
392 m_textCtrlFileManager->SetToolTip( msg );
393 wxString str = "%F";
394#else
395 wxString msg = _( "File explorer command.\nexample:" ) + wxS( " 'nemo -n %F'" );
396 m_textCtrlFileManager->SetToolTip( msg );
397 wxString str= " %F";
398#endif
399 msg = _( "Explorer command with mandatory '%s' suffix after last entered character." );
400 m_staticTextFileManager->SetToolTip( wxString::Format( msg, str ) );
401 }
402}
403
404
405void PANEL_COMMON_SETTINGS::OnPDFViewerClick( wxCommandEvent& event )
406{
407 wxString mask( wxT( "*" ) );
408
409#ifdef __WINDOWS__
410 mask += wxT( ".exe" );
411#endif
412
413 wxString wildcard = _( "Executable files (" ) + mask + wxT( ")|" ) + mask;
414
416 wxFileName fn = Pgm().GetPdfBrowserName();
417
418 wxWindow* topLevelParent = wxGetTopLevelParent( this );
419
420 wxFileDialog dlg( topLevelParent, _( "Select Preferred PDF Viewer" ), fn.GetPath(),
421 fn.GetFullPath(), wildcard, wxFD_OPEN | wxFD_FILE_MUST_EXIST );
422
424
425 if( dlg.ShowModal() == wxID_CANCEL )
426 return;
427
428 m_otherPDFViewer->SetValue( true );
429 m_PDFViewerPath->SetValue( dlg.GetPath() );
430}
431
432
434{
436}
437
438
440{
441 m_PDFViewerPath->Enable( m_otherPDFViewer->GetValue() );
442 m_pdfViewerBtn->Enable( m_otherPDFViewer->GetValue() );
443}
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:106
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
APPEARANCE m_Appearance
AUTO_BACKUP m_Backup
Class to handle configuration and automatic determination of the DPI scale to use for canvases.
bool GetCanvasIsAutoScaled() const override
Is the current value auto scaled, or is it user-set in the config.
double GetScaleFactor() const override
Get the DPI scale from all known sources in order:
void SetDpiConfig(bool aAuto, double aValue) override
Set the common DPI config in a given config object.
static double GetDefaultScaleFactor()
Get the "default" scaling factor to use if not other config is available.
static double GetMaxScaleFactor()
Get the maximum scaling factor that should be presented to the user.
static double GetMinScaleFactor()
Get the minimum scaling factor that should be presented to the user.
@ GAL_TYPE_OPENGL
OpenGL implementation.
@ GAL_TYPE_CAIRO
Cairo implementation.
void ResetToDefaults()
Resets all parameters to default values.
PANEL_COMMON_SETTINGS_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxTAB_TRAVERSAL, const wxString &name=wxEmptyString)
void OnTextEditorClick(wxCommandEvent &event) override
ZOOM_CORRECTION_CTRL * m_zoomCorrectionCtrl
void OnCanvasScaleChange(wxCommandEvent &aEvent)
Event fired when the canvas scale field is modified.
void ShowFileManagerWidgets(bool aBool)
PANEL_COMMON_SETTINGS(wxWindow *aParent)
void applySettingsToPanel(COMMON_SETTINGS &aSettings)
void OnPDFViewerClick(wxCommandEvent &event) override
void OnCanvasScaleAuto(wxCommandEvent &aEvent) override
Event fired when the canvas auto-scale option is changed.
void ResetPanel() override
Reset the contents of this panel.
void OnRadioButtonPdfViewer(wxCommandEvent &event) override
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition pgm_base.cpp:528
virtual void SetPdfBrowserName(const wxString &aFileName)
Definition pgm_base.h:179
virtual void ReadPdfBrowserInfos()
Read the PDF browser choice from the common configuration.
Definition pgm_base.cpp:860
virtual const wxString & GetPdfBrowserName() const
Definition pgm_base.h:177
virtual void SetTextEditor(const wxString &aFileName)
Definition pgm_base.cpp:211
virtual void ForceSystemPdfBrowser(bool aFlg)
Force the use of system PDF browser, even if a preferred PDF browser is set.
Definition pgm_base.h:194
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:124
virtual void WritePdfBrowserInfos()
Save the PDF browser choice to the common configuration.
Definition pgm_base.cpp:867
virtual const wxString AskUserForPreferredEditor(const wxString &aDefaultEditor=wxEmptyString)
Show a dialog that instructs the user to select a new preferred editor.
Definition pgm_base.cpp:254
Control to calibrate screen zoom to match real-world size.
@ ZIP
Zip archive snapshots; autosave uses recovery files.
@ INCREMENTAL
Git-based local history (default)
@ USER_DIR
Under the KiCad user data directory.
@ PROJECT_DIR
Inside the project directory (default)
const int minSize
Push and Shove router track width and via size dialog.
#define _(s)
bool AllowIconsInMenus()
If the user has disabled icons system-wide, we check that here.
Definition wxgtk/ui.cpp:308
void AllowNetworkFileSystems(wxDialog *aDialog)
Configure a file dialog to show network and virtual file systems.
Definition wxgtk/ui.cpp:448
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
unsigned long long limit_total_size
Maximum total size of backups (bytes), 0 for unlimited.
BACKUP_LOCATION location
Where backups, history, and autosave files live.
BACKUP_FORMAT format
Backup format (incremental git history vs zip archives)
bool enabled
Automatically back up the project when files are saved.
int canvas_type
EDA_DRAW_PANEL_GAL::GAL_TYPE_* value, see gal_options_panel.cpp.