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
286 m_rbAccelerated->SetValue( true );
287 else
288 m_rbFallback->SetValue( true );
289
291 {
292 const DPI_SCALING_COMMON dpi( &aSettings, this );
293 m_canvasScaleCtrl->SetValue( dpi.GetScaleFactor() );
294 m_canvasScaleAuto->SetValue( dpi.GetCanvasIsAutoScaled() );
295 }
296
297 switch( aSettings.m_Appearance.icon_theme )
298 {
299 case ICON_THEME::LIGHT: m_rbIconThemeLight->SetValue( true ); break;
300 case ICON_THEME::DARK: m_rbIconThemeDark->SetValue( true ); break;
301 case ICON_THEME::AUTO: m_rbIconThemeAuto->SetValue( true ); break;
302 }
303
304 switch( aSettings.m_Appearance.app_theme )
305 {
306 case APP_THEME::LIGHT: m_rbAppThemeLight->SetValue( true ); break;
307 case APP_THEME::DARK: m_rbAppThemeDark->SetValue( true ); break;
308 case APP_THEME::AUTO: m_rbAppThemeAuto->SetValue( true ); break;
309 }
310
311 switch( aSettings.m_Appearance.toolbar_icon_size )
312 {
313 case 16: m_rbIconSizeSmall->SetValue( true ); break;
314 case 24: m_rbIconSizeNormal->SetValue( true ); break;
315 case 32: m_rbIconSizeLarge->SetValue( true ); break;
316 }
317
320
321 m_gridStriping->SetValue( aSettings.m_Appearance.grid_striping );
322
324
325 m_zoomCorrectionCtrl->SetDisplayedValue( aSettings.m_Appearance.zoom_correction_factor );
326
327 double dimmingPercent = aSettings.m_Appearance.hicontrast_dimming_factor * 100.0f;
328 m_highContrastCtrl->SetValue( wxString::Format( "%.0f", dimmingPercent ) );
329
330 m_focusFollowSchPcb->SetValue( aSettings.m_Input.focus_follow_sch_pcb );
331 m_hotkeyFeedback->SetValue( aSettings.m_Input.hotkey_feedback );
332 m_warpMouseOnMove->SetValue( aSettings.m_Input.warp_mouse_on_move );
333 m_NonImmediateActions->SetValue( !aSettings.m_Input.immediate_actions );
334
336
337 m_cbBackupEnabled->SetValue( aSettings.m_Backup.enabled );
338 m_backupLimitTotalSize->SetValue( aSettings.m_Backup.limit_total_size / ( 1024 * 1024 ) );
339
340 m_choiceBackupFormat->SetSelection(
341 aSettings.m_Backup.format == BACKUP_FORMAT::INCREMENTAL ? 0 : 1 );
342
343 m_choiceBackupLocation->SetSelection(
344 aSettings.m_Backup.location == BACKUP_LOCATION::PROJECT_DIR ? 0 : 1 );
345
346 m_showScrollbars->SetValue( aSettings.m_Appearance.show_scrollbars );
347}
348
349
350void PANEL_COMMON_SETTINGS::OnCanvasScaleChange( wxCommandEvent& aEvent )
351{
352 m_canvasScaleAuto->SetValue( false );
353}
354
355
356void PANEL_COMMON_SETTINGS::OnCanvasScaleAuto( wxCommandEvent& aEvent )
357{
358 const bool automatic = m_canvasScaleAuto->GetValue();
359
360 if( automatic && m_canvasScaleCtrl )
361 {
362 // set the scale to the auto value, without consulting the config
363 DPI_SCALING_COMMON dpi( nullptr, this );
364
365 // update the field (no events sent)
366 m_canvasScaleCtrl->SetValue( dpi.GetScaleFactor() );
367 }
368}
369
370
371void PANEL_COMMON_SETTINGS::OnTextEditorClick( wxCommandEvent& event )
372{
373 // Ask the user to select a new editor, but suggest the current one as the default.
374 wxString editorname = Pgm().AskUserForPreferredEditor( m_textEditorPath->GetValue() );
375
376 // If we have a new editor name request it to be copied to m_text_editor and saved
377 // to the preferences file. If the user cancelled the dialog then the previous
378 // value will be retained.
379 if( !editorname.IsEmpty() )
380 m_textEditorPath->SetValue( editorname );
381}
382
383
385{
386 m_staticTextFileManager->Show( aBool );
387 m_textCtrlFileManager->Show( aBool );
388
389 if( aBool )
390 {
391#if defined( __WINDOWS__ )
392 wxString msg = _( "Default 'explorer.exe /n,/select,%F' for this OS." );
393 m_textCtrlFileManager->SetToolTip( msg );
394 wxString str = "%F";
395#else
396 wxString msg = _( "File explorer command.\nexample:" ) + wxS( " 'nemo -n %F'" );
397 m_textCtrlFileManager->SetToolTip( msg );
398 wxString str= " %F";
399#endif
400 msg = _( "Explorer command with mandatory '%s' suffix after last entered character." );
401 m_staticTextFileManager->SetToolTip( wxString::Format( msg, str ) );
402 }
403}
404
405
406void PANEL_COMMON_SETTINGS::OnPDFViewerClick( wxCommandEvent& event )
407{
408 wxString mask( wxT( "*" ) );
409
410#ifdef __WINDOWS__
411 mask += wxT( ".exe" );
412#endif
413
414 wxString wildcard = _( "Executable files (" ) + mask + wxT( ")|" ) + mask;
415
417 wxFileName fn = Pgm().GetPdfBrowserName();
418
419 wxWindow* topLevelParent = wxGetTopLevelParent( this );
420
421 wxFileDialog dlg( topLevelParent, _( "Select Preferred PDF Viewer" ), fn.GetPath(),
422 fn.GetFullPath(), wildcard, wxFD_OPEN | wxFD_FILE_MUST_EXIST );
423
425
426 if( dlg.ShowModal() == wxID_CANCEL )
427 return;
428
429 m_otherPDFViewer->SetValue( true );
430 m_PDFViewerPath->SetValue( dlg.GetPath() );
431}
432
433
435{
437}
438
439
441{
442 m_PDFViewerPath->Enable( m_otherPDFViewer->GetValue() );
443 m_pdfViewerBtn->Enable( m_otherPDFViewer->GetValue() );
444}
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.
static GAL_TYPE ResolveStoredCanvasType(int aStoredCanvasType)
Convert a stored canvas type setting into a backend that can actually be used.
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:546
virtual void SetPdfBrowserName(const wxString &aFileName)
Definition pgm_base.h:178
virtual void ReadPdfBrowserInfos()
Read the PDF browser choice from the common configuration.
Definition pgm_base.cpp:878
virtual const wxString & GetPdfBrowserName() const
Definition pgm_base.h:176
virtual void SetTextEditor(const wxString &aFileName)
Definition pgm_base.cpp:209
virtual void ForceSystemPdfBrowser(bool aFlg)
Force the use of system PDF browser, even if a preferred PDF browser is set.
Definition pgm_base.h:193
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:123
virtual void WritePdfBrowserInfos()
Save the PDF browser choice to the common configuration.
Definition pgm_base.cpp:885
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:252
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:381
void AllowNetworkFileSystems(wxDialog *aDialog)
Configure a file dialog to show network and virtual file systems.
Definition wxgtk/ui.cpp:533
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.