diff --git a/.gitignore b/.gitignore index 7273096724..73f4cd0ee6 100644 --- a/.gitignore +++ b/.gitignore @@ -113,6 +113,10 @@ compile_commands.json .kdev4/ *.kdev4 +# Qt Creator +CMakeLists.txt.user +*.autosave + # Translations *.mo i18n_status.svg diff --git a/AUTHORS.txt b/AUTHORS.txt index 3ac31a167b..2b3cc40d88 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -51,6 +51,7 @@ Thomas Pointhuber Roberto Fernandez Bautista Mikołaj Wielgus Mike Williams +Emile Cormier See git repo on GitLab for contributors at https://gitlab.com/kicad/code/kicad/-/graphs/master diff --git a/common/bitmap_info.cpp b/common/bitmap_info.cpp index e372fc2d1c..1bda9c334b 100644 --- a/common/bitmap_info.cpp +++ b/common/bitmap_info.cpp @@ -755,6 +755,10 @@ void BuildBitmapInfo( std::unordered_map>& aBi aBitmapInfoCache[BITMAPS::zoom_center_on_screen].emplace_back( BITMAPS::zoom_center_on_screen, wxT( "zoom_center_on_screen_24.png" ), 24, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::zoom_in].emplace_back( BITMAPS::zoom_in, wxT( "zoom_in_24.png" ), 24, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::zoom_out].emplace_back( BITMAPS::zoom_out, wxT( "zoom_out_24.png" ), 24, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::zoom_in_horizontally].emplace_back( BITMAPS::zoom_in_horizontally, wxT( "zoom_in_horizontally_24.png" ), 24, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::zoom_out_horizontally].emplace_back( BITMAPS::zoom_out_horizontally, wxT( "zoom_out_horizontally_24.png" ), 24, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::zoom_in_vertically].emplace_back( BITMAPS::zoom_in_vertically, wxT( "zoom_in_vertically_24.png" ), 24, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::zoom_out_vertically].emplace_back( BITMAPS::zoom_out_vertically, wxT( "zoom_out_vertically_24.png" ), 24, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::zoom_selection].emplace_back( BITMAPS::zoom_selection, wxT( "zoom_selection_24.png" ), 24, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::about].emplace_back( BITMAPS::about, wxT( "about_dark_24.png" ), 24, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::add_aligned_dimension].emplace_back( BITMAPS::add_aligned_dimension, wxT( "add_aligned_dimension_dark_24.png" ), 24, wxT( "dark" ) ); @@ -1157,6 +1161,10 @@ void BuildBitmapInfo( std::unordered_map>& aBi aBitmapInfoCache[BITMAPS::zoom_center_on_screen].emplace_back( BITMAPS::zoom_center_on_screen, wxT( "zoom_center_on_screen_dark_24.png" ), 24, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::zoom_in].emplace_back( BITMAPS::zoom_in, wxT( "zoom_in_dark_24.png" ), 24, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::zoom_out].emplace_back( BITMAPS::zoom_out, wxT( "zoom_out_dark_24.png" ), 24, wxT( "dark" ) ); + aBitmapInfoCache[BITMAPS::zoom_in_horizontally].emplace_back( BITMAPS::zoom_in_horizontally, wxT( "zoom_in_horizontally_dark_24.png" ), 24, wxT( "dark" ) ); + aBitmapInfoCache[BITMAPS::zoom_out_horizontally].emplace_back( BITMAPS::zoom_out_horizontally, wxT( "zoom_out_horizontally_dark_24.png" ), 24, wxT( "dark" ) ); + aBitmapInfoCache[BITMAPS::zoom_in_vertically].emplace_back( BITMAPS::zoom_in_vertically, wxT( "zoom_in_vertically_dark_24.png" ), 24, wxT( "dark" ) ); + aBitmapInfoCache[BITMAPS::zoom_out_vertically].emplace_back( BITMAPS::zoom_out_vertically, wxT( "zoom_out_vertically_dark_24.png" ), 24, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::zoom_selection].emplace_back( BITMAPS::zoom_selection, wxT( "zoom_selection_dark_24.png" ), 24, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::about].emplace_back( BITMAPS::about, wxT( "about_16.png" ), 16, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::add_aligned_dimension].emplace_back( BITMAPS::add_aligned_dimension, wxT( "add_aligned_dimension_16.png" ), 16, wxT( "light" ) ); @@ -1559,6 +1567,10 @@ void BuildBitmapInfo( std::unordered_map>& aBi aBitmapInfoCache[BITMAPS::zoom_center_on_screen].emplace_back( BITMAPS::zoom_center_on_screen, wxT( "zoom_center_on_screen_16.png" ), 16, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::zoom_in].emplace_back( BITMAPS::zoom_in, wxT( "zoom_in_16.png" ), 16, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::zoom_out].emplace_back( BITMAPS::zoom_out, wxT( "zoom_out_16.png" ), 16, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::zoom_in_horizontally].emplace_back( BITMAPS::zoom_in_horizontally, wxT( "zoom_in_horizontally_16.png" ), 16, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::zoom_out_horizontally].emplace_back( BITMAPS::zoom_out_horizontally, wxT( "zoom_out_horizontally_16.png" ), 16, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::zoom_in_vertically].emplace_back( BITMAPS::zoom_in_vertically, wxT( "zoom_in_vertically_16.png" ), 16, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::zoom_out_vertically].emplace_back( BITMAPS::zoom_out_vertically, wxT( "zoom_out_vertically_16.png" ), 16, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::zoom_selection].emplace_back( BITMAPS::zoom_selection, wxT( "zoom_selection_16.png" ), 16, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::about].emplace_back( BITMAPS::about, wxT( "about_dark_16.png" ), 16, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::add_aligned_dimension].emplace_back( BITMAPS::add_aligned_dimension, wxT( "add_aligned_dimension_dark_16.png" ), 16, wxT( "dark" ) ); @@ -1961,6 +1973,10 @@ void BuildBitmapInfo( std::unordered_map>& aBi aBitmapInfoCache[BITMAPS::zoom_center_on_screen].emplace_back( BITMAPS::zoom_center_on_screen, wxT( "zoom_center_on_screen_dark_16.png" ), 16, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::zoom_in].emplace_back( BITMAPS::zoom_in, wxT( "zoom_in_dark_16.png" ), 16, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::zoom_out].emplace_back( BITMAPS::zoom_out, wxT( "zoom_out_dark_16.png" ), 16, wxT( "dark" ) ); + aBitmapInfoCache[BITMAPS::zoom_in_horizontally].emplace_back( BITMAPS::zoom_in_horizontally, wxT( "zoom_in_horizontally_dark_16.png" ), 16, wxT( "dark" ) ); + aBitmapInfoCache[BITMAPS::zoom_out_horizontally].emplace_back( BITMAPS::zoom_out_horizontally, wxT( "zoom_out_horizontally_dark_16.png" ), 16, wxT( "dark" ) ); + aBitmapInfoCache[BITMAPS::zoom_in_vertically].emplace_back( BITMAPS::zoom_in_vertically, wxT( "zoom_in_vertically_dark_16.png" ), 16, wxT( "dark" ) ); + aBitmapInfoCache[BITMAPS::zoom_out_vertically].emplace_back( BITMAPS::zoom_out_vertically, wxT( "zoom_out_vertically_dark_16.png" ), 16, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::zoom_selection].emplace_back( BITMAPS::zoom_selection, wxT( "zoom_selection_dark_16.png" ), 16, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::about].emplace_back( BITMAPS::about, wxT( "about_32.png" ), 32, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::add_aligned_dimension].emplace_back( BITMAPS::add_aligned_dimension, wxT( "add_aligned_dimension_32.png" ), 32, wxT( "light" ) ); @@ -2363,6 +2379,10 @@ void BuildBitmapInfo( std::unordered_map>& aBi aBitmapInfoCache[BITMAPS::zoom_center_on_screen].emplace_back( BITMAPS::zoom_center_on_screen, wxT( "zoom_center_on_screen_32.png" ), 32, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::zoom_in].emplace_back( BITMAPS::zoom_in, wxT( "zoom_in_32.png" ), 32, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::zoom_out].emplace_back( BITMAPS::zoom_out, wxT( "zoom_out_32.png" ), 32, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::zoom_in_horizontally].emplace_back( BITMAPS::zoom_in_horizontally, wxT( "zoom_in_horizontally_32.png" ), 32, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::zoom_out_horizontally].emplace_back( BITMAPS::zoom_out_horizontally, wxT( "zoom_out_horizontally_32.png" ), 32, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::zoom_in_vertically].emplace_back( BITMAPS::zoom_in_vertically, wxT( "zoom_in_vertically_32.png" ), 32, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::zoom_out_vertically].emplace_back( BITMAPS::zoom_out_vertically, wxT( "zoom_out_vertically_32.png" ), 32, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::zoom_selection].emplace_back( BITMAPS::zoom_selection, wxT( "zoom_selection_32.png" ), 32, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::about].emplace_back( BITMAPS::about, wxT( "about_dark_32.png" ), 32, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::add_aligned_dimension].emplace_back( BITMAPS::add_aligned_dimension, wxT( "add_aligned_dimension_dark_32.png" ), 32, wxT( "dark" ) ); @@ -2765,6 +2785,10 @@ void BuildBitmapInfo( std::unordered_map>& aBi aBitmapInfoCache[BITMAPS::zoom_center_on_screen].emplace_back( BITMAPS::zoom_center_on_screen, wxT( "zoom_center_on_screen_dark_32.png" ), 32, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::zoom_in].emplace_back( BITMAPS::zoom_in, wxT( "zoom_in_dark_32.png" ), 32, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::zoom_out].emplace_back( BITMAPS::zoom_out, wxT( "zoom_out_dark_32.png" ), 32, wxT( "dark" ) ); + aBitmapInfoCache[BITMAPS::zoom_in_horizontally].emplace_back( BITMAPS::zoom_in_horizontally, wxT( "zoom_in_horizontally_dark_32.png" ), 32, wxT( "dark" ) ); + aBitmapInfoCache[BITMAPS::zoom_out_horizontally].emplace_back( BITMAPS::zoom_out_horizontally, wxT( "zoom_out_horizontally_dark_32.png" ), 32, wxT( "dark" ) ); + aBitmapInfoCache[BITMAPS::zoom_in_vertically].emplace_back( BITMAPS::zoom_in_vertically, wxT( "zoom_in_vertically_dark_32.png" ), 32, wxT( "dark" ) ); + aBitmapInfoCache[BITMAPS::zoom_out_vertically].emplace_back( BITMAPS::zoom_out_vertically, wxT( "zoom_out_vertically_dark_32.png" ), 32, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::zoom_selection].emplace_back( BITMAPS::zoom_selection, wxT( "zoom_selection_dark_32.png" ), 32, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::about].emplace_back( BITMAPS::about, wxT( "about_48.png" ), 48, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::add_aligned_dimension].emplace_back( BITMAPS::add_aligned_dimension, wxT( "add_aligned_dimension_48.png" ), 48, wxT( "light" ) ); @@ -3167,6 +3191,10 @@ void BuildBitmapInfo( std::unordered_map>& aBi aBitmapInfoCache[BITMAPS::zoom_center_on_screen].emplace_back( BITMAPS::zoom_center_on_screen, wxT( "zoom_center_on_screen_48.png" ), 48, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::zoom_in].emplace_back( BITMAPS::zoom_in, wxT( "zoom_in_48.png" ), 48, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::zoom_out].emplace_back( BITMAPS::zoom_out, wxT( "zoom_out_48.png" ), 48, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::zoom_in_horizontally].emplace_back( BITMAPS::zoom_in_horizontally, wxT( "zoom_in_horizontally_48.png" ), 48, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::zoom_out_horizontally].emplace_back( BITMAPS::zoom_out_horizontally, wxT( "zoom_out_horizontally_48.png" ), 48, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::zoom_in_vertically].emplace_back( BITMAPS::zoom_in_vertically, wxT( "zoom_in_vertically_48.png" ), 48, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::zoom_out_vertically].emplace_back( BITMAPS::zoom_out_vertically, wxT( "zoom_out_vertically_48.png" ), 48, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::zoom_selection].emplace_back( BITMAPS::zoom_selection, wxT( "zoom_selection_48.png" ), 48, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::about].emplace_back( BITMAPS::about, wxT( "about_dark_48.png" ), 48, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::add_aligned_dimension].emplace_back( BITMAPS::add_aligned_dimension, wxT( "add_aligned_dimension_dark_48.png" ), 48, wxT( "dark" ) ); @@ -3569,6 +3597,10 @@ void BuildBitmapInfo( std::unordered_map>& aBi aBitmapInfoCache[BITMAPS::zoom_center_on_screen].emplace_back( BITMAPS::zoom_center_on_screen, wxT( "zoom_center_on_screen_dark_48.png" ), 48, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::zoom_in].emplace_back( BITMAPS::zoom_in, wxT( "zoom_in_dark_48.png" ), 48, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::zoom_out].emplace_back( BITMAPS::zoom_out, wxT( "zoom_out_dark_48.png" ), 48, wxT( "dark" ) ); + aBitmapInfoCache[BITMAPS::zoom_in_horizontally].emplace_back( BITMAPS::zoom_in_horizontally, wxT( "zoom_in_horizontally_dark_48.png" ), 48, wxT( "dark" ) ); + aBitmapInfoCache[BITMAPS::zoom_out_horizontally].emplace_back( BITMAPS::zoom_out_horizontally, wxT( "zoom_out_horizontally_dark_48.png" ), 48, wxT( "dark" ) ); + aBitmapInfoCache[BITMAPS::zoom_in_vertically].emplace_back( BITMAPS::zoom_in_vertically, wxT( "zoom_in_vertically_dark_48.png" ), 48, wxT( "dark" ) ); + aBitmapInfoCache[BITMAPS::zoom_out_vertically].emplace_back( BITMAPS::zoom_out_vertically, wxT( "zoom_out_vertically_dark_48.png" ), 48, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::zoom_selection].emplace_back( BITMAPS::zoom_selection, wxT( "zoom_selection_dark_48.png" ), 48, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::about].emplace_back( BITMAPS::about, wxT( "about_64.png" ), 64, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::add_aligned_dimension].emplace_back( BITMAPS::add_aligned_dimension, wxT( "add_aligned_dimension_64.png" ), 64, wxT( "light" ) ); @@ -3971,6 +4003,10 @@ void BuildBitmapInfo( std::unordered_map>& aBi aBitmapInfoCache[BITMAPS::zoom_center_on_screen].emplace_back( BITMAPS::zoom_center_on_screen, wxT( "zoom_center_on_screen_64.png" ), 64, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::zoom_in].emplace_back( BITMAPS::zoom_in, wxT( "zoom_in_64.png" ), 64, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::zoom_out].emplace_back( BITMAPS::zoom_out, wxT( "zoom_out_64.png" ), 64, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::zoom_in_horizontally].emplace_back( BITMAPS::zoom_in_horizontally, wxT( "zoom_in_horizontally_64.png" ), 64, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::zoom_out_horizontally].emplace_back( BITMAPS::zoom_out_horizontally, wxT( "zoom_out_horizontally_64.png" ), 64, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::zoom_in_vertically].emplace_back( BITMAPS::zoom_in_vertically, wxT( "zoom_in_vertically_64.png" ), 64, wxT( "light" ) ); + aBitmapInfoCache[BITMAPS::zoom_out_vertically].emplace_back( BITMAPS::zoom_out_vertically, wxT( "zoom_out_vertically_64.png" ), 64, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::zoom_selection].emplace_back( BITMAPS::zoom_selection, wxT( "zoom_selection_64.png" ), 64, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::about].emplace_back( BITMAPS::about, wxT( "about_dark_64.png" ), 64, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::add_aligned_dimension].emplace_back( BITMAPS::add_aligned_dimension, wxT( "add_aligned_dimension_dark_64.png" ), 64, wxT( "dark" ) ); @@ -4373,6 +4409,10 @@ void BuildBitmapInfo( std::unordered_map>& aBi aBitmapInfoCache[BITMAPS::zoom_center_on_screen].emplace_back( BITMAPS::zoom_center_on_screen, wxT( "zoom_center_on_screen_dark_64.png" ), 64, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::zoom_in].emplace_back( BITMAPS::zoom_in, wxT( "zoom_in_dark_64.png" ), 64, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::zoom_out].emplace_back( BITMAPS::zoom_out, wxT( "zoom_out_dark_64.png" ), 64, wxT( "dark" ) ); + aBitmapInfoCache[BITMAPS::zoom_in_horizontally].emplace_back( BITMAPS::zoom_in_horizontally, wxT( "zoom_in_horizontally_dark_64.png" ), 64, wxT( "dark" ) ); + aBitmapInfoCache[BITMAPS::zoom_out_horizontally].emplace_back( BITMAPS::zoom_out_horizontally, wxT( "zoom_out_horizontally_dark_64.png" ), 64, wxT( "dark" ) ); + aBitmapInfoCache[BITMAPS::zoom_in_vertically].emplace_back( BITMAPS::zoom_in_vertically, wxT( "zoom_in_vertically_dark_64.png" ), 64, wxT( "dark" ) ); + aBitmapInfoCache[BITMAPS::zoom_out_vertically].emplace_back( BITMAPS::zoom_out_vertically, wxT( "zoom_out_vertically_dark_64.png" ), 64, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::zoom_selection].emplace_back( BITMAPS::zoom_selection, wxT( "zoom_selection_dark_64.png" ), 64, wxT( "dark" ) ); aBitmapInfoCache[BITMAPS::icon_bitmap2component_32].emplace_back( BITMAPS::icon_bitmap2component_32, wxT( "icon_bitmap2component_32_32.png" ), 32, wxT( "light" ) ); aBitmapInfoCache[BITMAPS::icon_eeschema_32].emplace_back( BITMAPS::icon_eeschema_32, wxT( "icon_eeschema_32_32.png" ), 32, wxT( "light" ) ); diff --git a/common/eda_base_frame.cpp b/common/eda_base_frame.cpp index 441e197719..b014763608 100644 --- a/common/eda_base_frame.cpp +++ b/common/eda_base_frame.cpp @@ -1137,6 +1137,7 @@ void EDA_BASE_FRAME::ShowPreferences( wxString aStartPage, wxString aStartParent book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_ANNO_OPTIONS ), _( "Annotation Options" ) ); book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_COLORS ), _( "Colors" ) ); book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_FIELD_NAME_TEMPLATES ), _( "Field Name Templates" ) ); + book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_SIMULATOR ), _( "Simulator" ) ); } catch( ... ) { diff --git a/common/tool/actions.cpp b/common/tool/actions.cpp index b9417347ca..bbb32aca68 100644 --- a/common/tool/actions.cpp +++ b/common/tool/actions.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2019-2023 CERN - * Copyright (C) 2021-2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2021-2024 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -568,6 +568,34 @@ TOOL_ACTION ACTIONS::zoomOutCenter( TOOL_ACTION_ARGS() .FriendlyName( _( "Zoom Out" ) ) .Icon( BITMAPS::zoom_out ) ); +TOOL_ACTION ACTIONS::zoomInHorizontally( TOOL_ACTION_ARGS() + .Name( "common.Control.zoomInHorizontally" ) + .Scope( AS_GLOBAL ) + .FriendlyName( _( "Zoom In Horizontally" ) ) + .Tooltip( _( "Zoom In Horizontally" ) ) + .Icon( BITMAPS::zoom_in_horizontally ) ); + +TOOL_ACTION ACTIONS::zoomOutHorizontally( TOOL_ACTION_ARGS() + .Name( "common.Control.zoomOutHorizontally" ) + .Scope( AS_GLOBAL ) + .FriendlyName( _( "Zoom Out Horizontally" ) ) + .Tooltip( _( "Zoom Out Horizontally" ) ) + .Icon( BITMAPS::zoom_out_horizontally ) ); + +TOOL_ACTION ACTIONS::zoomInVertically( TOOL_ACTION_ARGS() + .Name( "common.Control.zoomInVertically" ) + .Scope( AS_GLOBAL ) + .FriendlyName( _( "Zoom In Vertically" ) ) + .Tooltip( _( "Zoom In Vertically" ) ) + .Icon( BITMAPS::zoom_in_vertically ) ); + +TOOL_ACTION ACTIONS::zoomOutVertically( TOOL_ACTION_ARGS() + .Name( "common.Control.zoomOutVertically" ) + .Scope( AS_GLOBAL ) + .FriendlyName( _( "Zoom Out Vertically" ) ) + .Tooltip( _( "Zoom Out Vertically" ) ) + .Icon( BITMAPS::zoom_out_vertically ) ); + TOOL_ACTION ACTIONS::zoomCenter( TOOL_ACTION_ARGS() .Name( "common.Control.zoomCenter" ) .Scope( AS_GLOBAL ) diff --git a/common/widgets/mathplot.cpp b/common/widgets/mathplot.cpp index cc27b9e49a..b8fd77ce59 100644 --- a/common/widgets/mathplot.cpp +++ b/common/widgets/mathplot.cpp @@ -5,9 +5,9 @@ // Maintainer: Davide Rondini // Contributors: Jose Luis Blanco, Val Greene, Maciej Suminski, Tomasz Wlostowski // Created: 21/07/2003 -// Last edit: 2023 +// Last edit: 2024 // Copyright: (c) David Schalig, Davide Rondini -// Copyright (c) 2021-2023 KiCad Developers, see AUTHORS.txt for contributors. +// Copyright (c) 2021-2024 KiCad Developers, see AUTHORS.txt for contributors. // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -1367,82 +1367,14 @@ EVT_MENU( mpID_ZOOM_REDO, mpWindow::onZoomRedo ) END_EVENT_TABLE() mpWindow::mpWindow() : - wxWindow(), - m_minX( 0.0 ), - m_maxX( 0.0 ), - m_minY( 0.0 ), - m_maxY( 0.0 ), - m_scaleX( 1.0 ), - m_scaleY( 1.0 ), - m_posX( 0.0 ), - m_posY( 0.0 ), - m_scrX( 64 ), - m_scrY( 64 ), - m_clickedX( 0 ), - m_clickedY( 0 ), - m_yLocked( false ), - m_desiredXmin( 0.0 ), - m_desiredXmax( 1.0 ), - m_desiredYmin( 0.0 ), - m_desiredYmax( 1.0 ), - m_marginTop( 0 ), - m_marginRight( 0 ), - m_marginBottom( 0 ), - m_marginLeft( 0 ), - m_last_lx( 0 ), - m_last_ly( 0 ), - m_buff_bmp( nullptr ), - m_enableDoubleBuffer( false ), - m_enableMouseNavigation( true ), - m_enableMouseWheelPan( false ), - m_enableLimitedView( false ), - m_movingInfoLayer( nullptr ), - m_zooming( false ) + mpWindow( DelegatingContructorTag() ) { - if( wxGraphicsContext *ctx = m_buff_dc.GetGraphicsContext() ) - { - if( !ctx->SetInterpolationQuality( wxINTERPOLATION_BEST ) - || !ctx->SetInterpolationQuality( wxINTERPOLATION_GOOD ) ) - { - ctx->SetInterpolationQuality( wxINTERPOLATION_FAST ); - } - - ctx->SetAntialiasMode( wxANTIALIAS_DEFAULT ); - } + initializeGraphicsContext(); } mpWindow::mpWindow( wxWindow* parent, wxWindowID id ) : - wxWindow( parent, id, wxDefaultPosition, wxDefaultSize, 0, wxT( "mathplot" ) ), - m_minX( 0.0 ), - m_maxX( 0.0 ), - m_minY( 0.0 ), - m_maxY( 0.0 ), - m_scaleX( 1.0 ), - m_scaleY( 1.0 ), - m_posX( 0.0 ), - m_posY( 0.0 ), - m_scrX( 64 ), - m_scrY( 64 ), - m_clickedX( 0 ), - m_clickedY( 0 ), - m_yLocked( false ), - m_desiredXmin( 0.0 ), - m_desiredXmax( 1.0 ), - m_desiredYmin( 0.0 ), - m_desiredYmax( 1.0 ), - m_marginTop( 0 ), - m_marginRight( 0 ), - m_marginBottom( 0 ), - m_marginLeft( 0 ), - m_last_lx( 0 ), - m_last_ly( 0 ), - m_buff_bmp( nullptr ), - m_enableDoubleBuffer( false ), - m_enableMouseNavigation( true ), - m_enableMouseWheelPan( false ), - m_enableLimitedView( false ), - m_movingInfoLayer( nullptr ), - m_zooming( false ) + mpWindow( DelegatingContructorTag(), + parent, id, wxDefaultPosition, wxDefaultSize, 0, wxT( "mathplot" ) ) { m_popmenu.Append( mpID_ZOOM_UNDO, _( "Undo Last Zoom" ), _( "Return zoom to level prior to last zoom action" ) ); m_popmenu.Append( mpID_ZOOM_REDO, _( "Redo Last Zoom" ), _( "Return zoom to level prior to last zoom undo" ) ); @@ -1462,17 +1394,7 @@ mpWindow::mpWindow( wxWindow* parent, wxWindowID id ) : // J.L.Blanco: Eliminates the "flick" with the double buffer. SetBackgroundStyle( wxBG_STYLE_CUSTOM ); - if( wxGraphicsContext* ctx = m_buff_dc.GetGraphicsContext() ) - { - if( !ctx->SetInterpolationQuality( wxINTERPOLATION_BEST ) - || !ctx->SetInterpolationQuality( wxINTERPOLATION_GOOD ) ) - { - ctx->SetInterpolationQuality( wxINTERPOLATION_FAST ); - } - - ctx->SetAntialiasMode( wxANTIALIAS_DEFAULT ); - } - + initializeGraphicsContext(); UpdateAll(); } @@ -1524,56 +1446,37 @@ void mpWindow::onMouseWheel( wxMouseEvent& event ) return; } - int change = event.GetWheelRotation(); - const int axis = event.GetWheelAxis(); - double changeUnitsX = change / m_scaleX; - double changeUnitsY = change / m_scaleY; + const wxMouseWheelAxis axis = event.GetWheelAxis(); + const int modifiers = event.GetModifiers(); + MouseWheelAction action = MouseWheelAction::NONE; - if( ( !m_enableMouseWheelPan && ( event.ControlDown() || event.ShiftDown() ) ) - || ( m_enableMouseWheelPan && !event.ControlDown() ) ) + if( axis == wxMOUSE_WHEEL_HORIZONTAL ) { - // Scrolling - if( m_enableMouseWheelPan ) - { - if( axis == wxMOUSE_WHEEL_HORIZONTAL || event.ShiftDown() ) - { - SetXView( m_posX + changeUnitsX, m_desiredXmax + changeUnitsX, - m_desiredXmin + changeUnitsX ); - } - else if( !m_yLocked ) - { - SetYView( m_posY + changeUnitsY, m_desiredYmax + changeUnitsY, - m_desiredYmin + changeUnitsY ); - } - } - else - { - if( event.ControlDown() ) - { - SetXView( m_posX + changeUnitsX, m_desiredXmax + changeUnitsX, - m_desiredXmin + changeUnitsX ); - } - else if( !m_yLocked ) - { - SetYView( m_posY + changeUnitsY, m_desiredYmax + changeUnitsY, - m_desiredYmin + changeUnitsY ); - } - } - - UpdateAll(); + action = m_mouseWheelActions.horizontal; + } + else if( modifiers == wxMOD_NONE ) + { + action = m_mouseWheelActions.verticalUnmodified; + } + else if( modifiers == wxMOD_CONTROL ) + { + action = m_mouseWheelActions.verticalWithCtrl; + } + else if( modifiers == wxMOD_SHIFT ) + { + action = m_mouseWheelActions.verticalWithShift; + } + else if( modifiers == wxMOD_ALT ) + { + action = m_mouseWheelActions.verticalWithAlt; } else { - // zoom in/out - wxPoint clickPt( event.GetX(), event.GetY() ); - - if( event.GetWheelRotation() > 0 ) - ZoomIn( clickPt ); - else - ZoomOut( clickPt ); - + event.Skip(); return; } + + PerformMouseWheelAction( event, action ); } @@ -1716,107 +1619,151 @@ void mpWindow::Fit() // JL void mpWindow::Fit( double xMin, double xMax, double yMin, double yMax, - const wxCoord* printSizeX, const wxCoord* printSizeY ) + const wxCoord* printSizeX, const wxCoord* printSizeY, + wxOrientation directions ) { + const bool isPrinting = printSizeX != nullptr && printSizeY != nullptr; + // Save desired borders: - m_desiredXmin = xMin; m_desiredXmax = xMax; - m_desiredYmin = yMin; m_desiredYmax = yMax; + double newDesiredXmin = xMin; + double newDesiredXmax = xMax; + double newDesiredYmin = yMin; + double newDesiredYmax = yMax; - // Give a small margin to plot area - double xExtra = fabs( xMax - xMin ) * 0.00; - double yExtra = fabs( yMax - yMin ) * 0.03; + // Provide a gap between the extrema of the curve and the top/bottom edges of the + // plot area. Not to be confused with the left/right/top/bottom margins outside the plot area. + const double xGap = fabs( xMax - xMin ) * m_leftRightPlotGapFactor; + const double yGap = fabs( yMax - yMin ) * m_topBottomPlotGapFactor; + xMin -= xGap; + xMax += xGap; + yMin -= yGap; + yMax += yGap; - xMin -= xExtra; - xMax += xExtra; - yMin -= yExtra; - yMax += yExtra; + int newScrX = m_scrX; + int newScrY = m_scrY; - if( printSizeX != nullptr && printSizeY != nullptr ) + if( isPrinting ) { // Printer: - m_scrX = *printSizeX; - m_scrY = *printSizeY; + newScrX = *printSizeX; + newScrY = *printSizeY; } else { // Normal case (screen): - GetClientSize( &m_scrX, &m_scrY ); + GetClientSize( &newScrX, &newScrY ); } - double Ax = xMax - xMin; - double Ay = yMax - yMin; + // Compute the width/height in pixels for the plot area. + const int plotScreenWidth = newScrX - m_marginLeft - m_marginRight; + const int plotScreenHeight = newScrY - m_marginTop - m_marginBottom; - m_scaleX = (Ax != 0) ? (m_scrX - m_marginLeft - m_marginRight) / Ax : 1; - m_scaleY = (Ay != 0) ? (m_scrY - m_marginTop - m_marginBottom) / Ay : 1; + // Adjust scale so that desired X/Y span plus extra gap fits in the plot area + double desiredSpanX = xMax - xMin; + double desiredSpanY = yMax - yMin; + double newScaleX = (desiredSpanX != 0) ? double(plotScreenWidth) / desiredSpanX : 1; + double newScaleY = (desiredSpanY != 0) ? double(plotScreenHeight) / desiredSpanY : 1; - // Adjusts corner coordinates: This should be simply: - // m_posX = m_minX; - // m_posY = m_maxY; - // But account for centering if we have lock aspect: - m_posX = (xMin + xMax) / 2 - ( (m_scrX - m_marginLeft - m_marginRight) / 2 + m_marginLeft ) / - m_scaleX; - m_posY = (yMin + yMax) / 2 + ( (m_scrY - m_marginTop - m_marginBottom) / 2 + m_marginTop ) / - m_scaleY; + // Adjust corner coordinates: + // Upstream's aspect lock code has been removed, so no need to account for centering. + double newPosX = xMin - (m_marginLeft / newScaleX); + double newPosY = yMax + (m_marginTop / newScaleY); - // It is VERY IMPORTANT to DO NOT call Refresh if we are drawing to the printer!! + // Commit above changes to member variables only if enabled for their respective dimension. + if( ((directions & wxHORIZONTAL) != 0) || isPrinting ) + { + // Don't commit the passed desired bounds when printing + if (!isPrinting) + { + m_desiredXmin = newDesiredXmin; + m_desiredXmax = newDesiredXmax; + } + + m_scrX = newScrX; + m_scaleX = newScaleX; + m_posX = newPosX; + } + + if( ((directions & wxVERTICAL) != 0) || isPrinting ) + { + // Don't commit the passed desired bounds when printing + if (!isPrinting) + { + m_desiredYmin = newDesiredYmin; + m_desiredYmax = newDesiredYmax; + } + + m_scrY = newScrY; + m_scaleY = newScaleY; + m_posY = newPosY; + } + + // It is VERY IMPORTANT to NOT call Refresh if we are drawing to the printer!! // Otherwise, the DC dimensions will be those of the window instead of the printer device - if( printSizeX == nullptr || printSizeY == nullptr ) + // The caller wanting to print should perform another Fit() afterwards to restore this + // object's state. + if( !isPrinting ) UpdateAll(); } -void mpWindow::AdjustLimitedView() +void mpWindow::AdjustLimitedView( wxOrientation directions ) { if( !m_enableLimitedView ) return; - // m_min and m_max are plot limits for curves - // xMin, xMax, yMin, yMax are the full limits (plot limit + margin) - const double xMin = m_minX - m_marginLeft / m_scaleX; - const double xMax = m_maxX + m_marginRight / m_scaleX; - const double yMin = m_minY - m_marginBottom / m_scaleY; - const double yMax = m_maxY + m_marginTop / m_scaleY; + // The m_desired* members are expressed in plot coordinates. + // They should be clamped against their respective m_minX, m_maxX, m_minY, m_maxY limits. - if( m_desiredXmin < xMin ) + if( (directions & wxHORIZONTAL) != 0 ) { - double diff = xMin - m_desiredXmin; - m_posX += diff; - m_desiredXmax += diff; - m_desiredXmin = xMin; + if( m_desiredXmin < m_minX ) + { + double diff = m_minX - m_desiredXmin; + m_posX += diff; + m_desiredXmax += diff; + m_desiredXmin = m_minX; + } + + if( m_desiredXmax > m_maxX ) + { + double diff = m_desiredXmax - m_maxX; + m_posX -= diff; + m_desiredXmin -= diff; + m_desiredXmax = m_maxX; + } } - if( m_desiredXmax > xMax ) + if( (directions & wxVERTICAL) != 0 ) { - double diff = m_desiredXmax - xMax; - m_posX -= diff; - m_desiredXmin -= diff; - m_desiredXmax = xMax; - } + if( m_desiredYmin < m_minY ) + { + double diff = m_minY - m_desiredYmin; + m_posY += diff; + m_desiredYmax += diff; + m_desiredYmin = m_minY; + } - if( m_desiredYmin < yMin ) - { - double diff = yMin - m_desiredYmin; - m_posY += diff; - m_desiredYmax += diff; - m_desiredYmin = yMin; - } - - if( m_desiredYmax > yMax ) - { - double diff = m_desiredYmax - yMax; - m_posY -= diff; - m_desiredYmin -= diff; - m_desiredYmax = yMax; + if( m_desiredYmax > m_maxY ) + { + double diff = m_desiredYmax - m_maxY; + m_posY -= diff; + m_desiredYmin -= diff; + m_desiredYmax = m_maxY; + } } } bool mpWindow::SetXView( double pos, double desiredMax, double desiredMin ) { + // TODO (ecorm): Investigate X scale flickering when panning at minimum zoom level + // Possible cause: When AdjustLimitedView subtracts the out-of-bound delta, it does not + // revert back to the exact same original coordinates due to floating point rounding errors. m_posX = pos; m_desiredXmax = desiredMax; m_desiredXmin = desiredMin; - AdjustLimitedView(); + AdjustLimitedView( wxHORIZONTAL ); return true; } @@ -1827,7 +1774,7 @@ bool mpWindow::SetYView( double pos, double desiredMax, double desiredMin ) m_posY = pos; m_desiredYmax = desiredMax; m_desiredYmin = desiredMin; - AdjustLimitedView(); + AdjustLimitedView( wxVERTICAL ); return true; } @@ -1835,116 +1782,28 @@ bool mpWindow::SetYView( double pos, double desiredMax, double desiredMin ) void mpWindow::ZoomIn( const wxPoint& centerPoint ) { - ZoomIn( centerPoint, zoomIncrementalFactor ); + ZoomIn( centerPoint, zoomIncrementalFactor, wxBOTH ); } -void mpWindow::ZoomIn( const wxPoint& centerPoint, double zoomFactor ) +void mpWindow::ZoomIn( const wxPoint& centerPoint, double zoomFactor, wxOrientation directions ) { - pushZoomUndo( { m_desiredXmin, m_desiredXmax, m_desiredYmin, m_desiredYmax } ); - - wxPoint c( centerPoint ); - - if( c == wxDefaultPosition ) - { - GetClientSize( &m_scrX, &m_scrY ); - c.x = (m_scrX - m_marginLeft - m_marginRight) / 2 + m_marginLeft; // c.x = m_scrX/2; - c.y = (m_scrY - m_marginTop - m_marginBottom) / 2 - m_marginTop; // c.y = m_scrY/2; - } - else - { - c.x = std::max( c.x, m_marginLeft ); - c.x = std::min( c.x, m_scrX - m_marginRight ); - c.y = std::max( c.y, m_marginTop ); - c.y = std::min( c.y, m_scrY - m_marginBottom ); - } - - // Preserve the position of the clicked point: - double prior_layer_x = p2x( c.x ); - double prior_layer_y = p2y( c.y ); - - // Zoom in: - const double MAX_SCALE = 1e6; - double newScaleX = m_scaleX * zoomFactor; - double newScaleY = m_scaleY * zoomFactor; - - // Baaaaad things happen when you zoom in too much.. - if( newScaleX <= MAX_SCALE && newScaleY <= MAX_SCALE ) - { - m_scaleX = newScaleX; - - if( !m_yLocked ) - m_scaleY = newScaleY; - } - else - { - return; - } - - // Adjust the new m_posx/y: - m_posX = prior_layer_x - c.x / m_scaleX; - - if( !m_yLocked ) - m_posY = prior_layer_y + c.y / m_scaleY; - - m_desiredXmin = m_posX; - m_desiredXmax = m_posX + (m_scrX - m_marginLeft - m_marginRight) / m_scaleX; - m_desiredYmax = m_posY; - m_desiredYmin = m_posY - (m_scrY - m_marginTop - m_marginBottom) / m_scaleY; - AdjustLimitedView(); - UpdateAll(); + DoZoom( centerPoint, zoomFactor, directions ); } void mpWindow::ZoomOut( const wxPoint& centerPoint ) { - ZoomOut( centerPoint, zoomIncrementalFactor ); + ZoomOut( centerPoint, zoomIncrementalFactor, wxBOTH ); } -void mpWindow::ZoomOut( const wxPoint& centerPoint, double zoomFactor ) +void mpWindow::ZoomOut( const wxPoint& centerPoint, double zoomFactor, + wxOrientation directions ) { - pushZoomUndo( { m_desiredXmin, m_desiredXmax, m_desiredYmin, m_desiredYmax } ); - - wxPoint c( centerPoint ); - - if( c == wxDefaultPosition ) - { - GetClientSize( &m_scrX, &m_scrY ); - c.x = (m_scrX - m_marginLeft - m_marginRight) / 2 + m_marginLeft; - c.y = (m_scrY - m_marginTop - m_marginBottom) / 2 - m_marginTop; - } - - // Preserve the position of the clicked point: - double prior_layer_x = p2x( c.x ); - double prior_layer_y = p2y( c.y ); - - // Zoom out: - m_scaleX = m_scaleX / zoomFactor; - - if( !m_yLocked ) - m_scaleY = m_scaleY / zoomFactor; - - // Adjust the new m_posx/y: - m_posX = prior_layer_x - c.x / m_scaleX; - - if( !m_yLocked ) - m_posY = prior_layer_y + c.y / m_scaleY; - - m_desiredXmin = m_posX; - m_desiredXmax = m_posX + (m_scrX - m_marginLeft - m_marginRight) / m_scaleX; - m_desiredYmax = m_posY; - m_desiredYmin = m_posY - (m_scrY - m_marginTop - m_marginBottom) / m_scaleY; - - AdjustLimitedView(); - - if( !CheckXLimits( m_desiredXmax, m_desiredXmin ) - || !CheckYLimits( m_desiredYmax, m_desiredYmin ) ) - { - Fit(); - } - - UpdateAll(); + if (zoomFactor == 0) + zoomFactor = 1.0; + DoZoom( centerPoint, 1.0 / zoomFactor, directions ); } @@ -1952,6 +1811,20 @@ void mpWindow::ZoomRect( wxPoint p0, wxPoint p1 ) { pushZoomUndo( { m_desiredXmin, m_desiredXmax, m_desiredYmin, m_desiredYmax } ); + // Constrain given rectangle to plot area + const int pMinX = m_marginLeft; + const int pMaxX = m_scrX - m_marginRight; + const int pMinY = m_marginTop; + const int pMaxY = m_scrY - m_marginBottom; + p0.x = std::max( p0.x, pMinX ); + p0.x = std::min( p0.x, pMaxX ); + p0.y = std::max( p0.y, pMinY ); + p0.y = std::min( p0.y, pMaxY ); + p1.x = std::max( p1.x, pMinX ); + p1.x = std::min( p1.x, pMaxX ); + p1.y = std::max( p1.y, pMinY ); + p1.y = std::min( p1.y, pMaxY ); + // Compute the 2 corners in graph coordinates: double p0x = p2x( p0.x ); double p0y = p2y( p0.y ); @@ -1971,7 +1844,16 @@ void mpWindow::ZoomRect( wxPoint p0, wxPoint p1 ) } Fit( zoom_x_min, zoom_x_max, zoom_y_min, zoom_y_max ); + + // Even with the input rectangle contrained to the plot area, it's still possible for the + // resulting view to exceed limits when a portion of the gap is grabbed. AdjustLimitedView(); + + // These additional checks are needed because AdjustLimitedView only adjusts the position + // and not the scale. + wxOrientation directionsNeedingRefitting = ViewNeedsRefitting( wxBOTH ); + if( directionsNeedingRefitting != 0 ) + Fit( m_minX, m_maxX, m_minY, m_maxY, nullptr, nullptr, directionsNeedingRefitting ); } @@ -2043,6 +1925,18 @@ void mpWindow::OnCenter( wxCommandEvent& WXUNUSED( event ) ) } +mpWindow::MouseWheelActionSet mpWindow::defaultMouseWheelActions() +{ + MouseWheelActionSet actions; + actions.verticalUnmodified = MouseWheelAction::ZOOM; + actions.verticalWithCtrl = MouseWheelAction::PAN_LEFT_RIGHT; + actions.verticalWithShift = MouseWheelAction::PAN_UP_DOWN; + actions.verticalWithAlt = MouseWheelAction::NONE; + actions.horizontal = MouseWheelAction::NONE; + return actions; +} + + void mpWindow::onZoomIn( wxCommandEvent& WXUNUSED( event ) ) { ZoomIn( wxPoint( m_mouseMClick.x, m_mouseMClick.y ) ); @@ -2188,6 +2082,199 @@ void mpWindow::OnPaint( wxPaintEvent& WXUNUSED( event ) ) paintDC.Blit( 0, 0, m_scrX, m_scrY, targetDC, 0, 0 ); } +void mpWindow::DoZoom( const wxPoint& centerPoint, double zoomFactor, + wxOrientation directions ) +{ + if( m_yLocked ) + { + if( directions == wxVERTICAL ) + return; + directions = wxHORIZONTAL; + } + + const bool horizontally = (directions & wxHORIZONTAL) != 0; + const bool vertically = (directions & wxVERTICAL) != 0; + + pushZoomUndo( { m_desiredXmin, m_desiredXmax, m_desiredYmin, m_desiredYmax } ); + + // Preserve the position of the clicked point: + wxPoint c( centerPoint ); + if( c == wxDefaultPosition ) + { + GetClientSize( &m_scrX, &m_scrY ); + c.x = (m_scrX - m_marginLeft - m_marginRight) / 2 + m_marginLeft; + c.y = (m_scrY - m_marginTop - m_marginBottom) / 2 + m_marginTop; + } + else + { + c.x = std::max( c.x, m_marginLeft ); + c.x = std::min( c.x, m_scrX - m_marginRight ); + c.y = std::max( c.y, m_marginTop ); + c.y = std::min( c.y, m_scrY - m_marginBottom ); + } + + // Zoom in/out: + const double MAX_SCALE = 1e6; + const double newScaleX = horizontally ? (m_scaleX * zoomFactor) : m_scaleX; + const double newScaleY = vertically ? (m_scaleY * zoomFactor) : m_scaleY; + + // Baaaaad things happen when you zoom in too much.. + if( newScaleX > MAX_SCALE || newScaleY > MAX_SCALE ) + return; + + if ( horizontally ) + { + // Transform the clicked X point to layer coordinates: + const double prior_layer_x = p2x( c.x ); + + // Adjust the new X scale and plot X origin: + m_scaleX = newScaleX; + m_posX = prior_layer_x - c.x / newScaleX; + + // Recompute the desired X view extents: + RecomputeDesiredX( m_desiredXmin, m_desiredXmax ); + } + + if ( vertically ) + { + // Transform the clicked Y point to layer coordinates: + const double prior_layer_y = p2y( c.y ); + + // Adjust the new Y scale and plot Y origin: + m_scaleY = newScaleY; + m_posY = prior_layer_y + c.y / newScaleY; + + // Recompute the desired Y view extents: + RecomputeDesiredY( m_desiredYmin, m_desiredYmax ); + } + + AdjustLimitedView( directions ); + + if (zoomFactor < 1.0) + { + // These additional checks are needed because AdjustLimitedView only adjusts the position + // and not the scale. + wxOrientation directionsNeedingRefitting = ViewNeedsRefitting( directions ); + + // If the view is still out-of-limits after AdjustLimitedView is called, perform a Fit + // along the offending dimension(s). + if( directionsNeedingRefitting != 0 ) + Fit( m_minX, m_maxX, m_minY, m_maxY, nullptr, nullptr, directionsNeedingRefitting ); + } + + UpdateAll(); +} + + +void mpWindow::RecomputeDesiredX( double& min, double& max ) +{ + const int plotScreenWidth = m_scrX - m_marginLeft - m_marginRight; + const double plotSpanX = plotScreenWidth / m_scaleX; + const double desiredSpanX = plotSpanX / ( 2*m_leftRightPlotGapFactor + 1 ); + const double xGap = desiredSpanX * m_leftRightPlotGapFactor; + min = m_posX + ( m_marginLeft / m_scaleX ) + xGap; + max = m_desiredXmin + desiredSpanX; +} + + +void mpWindow::RecomputeDesiredY( double& min, double& max ) +{ + const int plotScreenHeight = m_scrY - m_marginTop - m_marginBottom; + const double plotSpanY = plotScreenHeight / m_scaleY; + const double desiredSpanY = plotSpanY / ( 2*m_topBottomPlotGapFactor + 1 ); + const double yGap = desiredSpanY * m_topBottomPlotGapFactor; + max = m_posY - ( m_marginTop / m_scaleY) - yGap; + min = m_desiredYmax - desiredSpanY; +} + + +wxOrientation mpWindow::ViewNeedsRefitting( wxOrientation directions ) const +{ + if( !m_enableLimitedView ) + return static_cast( 0 ); + + // Allow a gap between the extrema of the curve and the edges of the plot area. Not to be + // confused with the left/right/top/bottom margins outside the plot area. + const double xGap = fabs( m_maxX - m_minX ) * m_leftRightPlotGapFactor; + const double yGap = fabs( m_maxY - m_minY ) * m_topBottomPlotGapFactor; + + wxOrientation result = {}; + + if ( (directions & wxHORIZONTAL) != 0 ) + { + if ( ( m_desiredXmax > m_maxX + xGap ) || ( m_desiredXmin < m_minX - xGap ) ) + result = static_cast( result | wxHORIZONTAL ); + } + + if ( (directions & wxVERTICAL) != 0 ) + { + if ( ( m_desiredYmax > m_maxY + yGap ) || ( m_desiredYmin < m_minY - yGap ) ) + result = static_cast( result | wxVERTICAL ); + } + + return result; +} + + +void mpWindow::PerformMouseWheelAction( wxMouseEvent& event, MouseWheelAction action ) +{ + const int change = event.GetWheelRotation(); + const double changeUnitsX = change / m_scaleX; + const double changeUnitsY = change / m_scaleY; + const wxPoint clickPt( event.GetX(), event.GetY() ); + + switch (action) + { + case MouseWheelAction::NONE: + break; + + case MouseWheelAction::PAN_LEFT_RIGHT: + SetXView( m_posX + changeUnitsX, m_desiredXmax + changeUnitsX, + m_desiredXmin + changeUnitsX ); + UpdateAll(); + break; + + case MouseWheelAction::PAN_RIGHT_LEFT: + SetXView( m_posX - changeUnitsX, m_desiredXmax - changeUnitsX, + m_desiredXmin - changeUnitsX ); + UpdateAll(); + break; + + case MouseWheelAction::PAN_UP_DOWN: + if( !m_yLocked ) + { + SetYView( m_posY + changeUnitsY, m_desiredYmax + changeUnitsY, + m_desiredYmin + changeUnitsY ); + UpdateAll(); + } + break; + + case MouseWheelAction::ZOOM: + if( event.GetWheelRotation() > 0 ) + ZoomIn( clickPt ); + else + ZoomOut( clickPt ); + break; + + case MouseWheelAction::ZOOM_HORIZONTALLY: + if( event.GetWheelRotation() > 0 ) + ZoomIn( clickPt, zoomIncrementalFactor, wxHORIZONTAL ); + else + ZoomOut( clickPt, zoomIncrementalFactor, wxHORIZONTAL ); + break; + + case MouseWheelAction::ZOOM_VERTICALLY: + if( event.GetWheelRotation() > 0 ) + ZoomIn( clickPt, zoomIncrementalFactor, wxVERTICAL ); + else + ZoomOut( clickPt, zoomIncrementalFactor, wxVERTICAL ); + break; + + default: + break; + } +} + bool mpWindow::UpdateBBox() { @@ -2392,6 +2479,59 @@ void mpWindow::SetColourTheme( const wxColour& bgColour, const wxColour& drawCol } +template +mpWindow::mpWindow( DelegatingContructorTag, Ts&&... windowArgs ) : + wxWindow( std::forward( windowArgs )... ), + m_minX( 0.0 ), + m_maxX( 0.0 ), + m_minY( 0.0 ), + m_maxY( 0.0 ), + m_scaleX( 1.0 ), + m_scaleY( 1.0 ), + m_posX( 0.0 ), + m_posY( 0.0 ), + m_scrX( 64 ), + m_scrY( 64 ), + m_clickedX( 0 ), + m_clickedY( 0 ), + m_yLocked( false ), + m_desiredXmin( 0.0 ), + m_desiredXmax( 1.0 ), + m_desiredYmin( 0.0 ), + m_desiredYmax( 1.0 ), + m_topBottomPlotGapFactor( 0.03 ), + m_leftRightPlotGapFactor( 0.0 ), + m_marginTop( 0 ), + m_marginRight( 0 ), + m_marginBottom( 0 ), + m_marginLeft( 0 ), + m_last_lx( 0 ), + m_last_ly( 0 ), + m_buff_bmp( nullptr ), + m_enableDoubleBuffer( false ), + m_enableMouseNavigation( true ), + m_enableLimitedView( false ), + m_mouseWheelActions( defaultMouseWheelActions() ), + m_movingInfoLayer( nullptr ), + m_zooming( false ) +{} + + +void mpWindow::initializeGraphicsContext() +{ + if( wxGraphicsContext* ctx = m_buff_dc.GetGraphicsContext() ) + { + if( !ctx->SetInterpolationQuality( wxINTERPOLATION_BEST ) + || !ctx->SetInterpolationQuality( wxINTERPOLATION_GOOD ) ) + { + ctx->SetInterpolationQuality( wxINTERPOLATION_FAST ); + } + + ctx->SetAntialiasMode( wxANTIALIAS_DEFAULT ); + } +} + + // ----------------------------------------------------------------------------- // mpFXYVector implementation - by Jose Luis Blanco (AGO-2007) // ----------------------------------------------------------------------------- diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index 014ce6ca40..801970d72c 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -186,6 +186,8 @@ set( EESCHEMA_DLGS dialogs/panel_setup_formatting_base.cpp dialogs/panel_setup_pinmap.cpp dialogs/panel_setup_pinmap_base.cpp + dialogs/panel_simulator_preferences.cpp + dialogs/panel_simulator_preferences_base.cpp dialogs/panel_sym_color_settings.cpp dialogs/panel_sym_color_settings_base.cpp dialogs/panel_sym_display_options.cpp diff --git a/eeschema/dialogs/panel_simulator_preferences.cpp b/eeschema/dialogs/panel_simulator_preferences.cpp new file mode 100644 index 0000000000..fe5f3e9097 --- /dev/null +++ b/eeschema/dialogs/panel_simulator_preferences.cpp @@ -0,0 +1,168 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include +#include +#include +#include +#include "panel_simulator_preferences.h" +#include "../eeschema_settings.h" + + +PANEL_SIMULATOR_PREFERENCES::PANEL_SIMULATOR_PREFERENCES( wxWindow* aParent ) : + PANEL_SIMULATOR_PREFERENCES_BASE( aParent ) +{ +#ifdef __WXOSX_MAC__ + m_lblVScrollCtrl->SetLabel( _( "Cmd" ) ); + m_lblVScrollAlt->SetLabel( _( "Option" ) ); +#endif + + // Populate the wxChoice items programmatically here instead of via the form builder + // to ease maintenance. + + static const wxString verticalChoiceItems[] = + { + _("No action"), + _("Pan left/right"), + _("Pan right/left"), + _("Pan up/down"), + _("Zoom"), + _("Zoom horizontally"), + _("Zoom vertically") + }; + + static constexpr auto ACTION_COUNT = static_cast( SIM_MOUSE_WHEEL_ACTION::COUNT ); + + static_assert( std::extent::value == ACTION_COUNT, + "verticalChoiceItems size does not match VERTICAL_SCROLL_ACTION::COUNT" ); + + m_choiceVScrollUnmodified->Set( ACTION_COUNT, verticalChoiceItems ); + m_choiceVScrollCtrl ->Set( ACTION_COUNT, verticalChoiceItems ); + m_choiceVScrollShift ->Set( ACTION_COUNT, verticalChoiceItems ); + m_choiceVScrollAlt ->Set( ACTION_COUNT, verticalChoiceItems ); + + static const wxString horizontalChoiceItems[] = + { + _("No action"), + _("Pan left/right"), + _("Zoom horizontally") + }; + + m_choiceHScroll->Set( std::extent::value, + horizontalChoiceItems ); +} + + +PANEL_SIMULATOR_PREFERENCES::~PANEL_SIMULATOR_PREFERENCES() = default; + + +void PANEL_SIMULATOR_PREFERENCES::ResetPanel() +{ + applyMouseScrollActionsToPanel( SIM_MOUSE_WHEEL_ACTION_SET::GetMouseDefaults() ); +} + + +bool PANEL_SIMULATOR_PREFERENCES::TransferDataFromWindow() +{ + static constexpr auto toAction = + []( const wxChoice* aChoice ) + { + return static_cast( aChoice->GetSelection() ); + }; + + SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager(); + EESCHEMA_SETTINGS* settings = mgr.GetAppSettings(); + SIM_MOUSE_WHEEL_ACTION_SET& actions = settings->m_Simulator.preferences.mouse_wheel_actions; + + actions.vertical_unmodified = toAction( m_choiceVScrollUnmodified ); + actions.vertical_with_ctrl = toAction( m_choiceVScrollCtrl ); + actions.vertical_with_shift = toAction( m_choiceVScrollShift ); + actions.vertical_with_alt = toAction( m_choiceVScrollAlt ); + + actions.horizontal = horizontalScrollSelectionToAction( m_choiceHScroll->GetSelection() ); + + return true; +} + + +bool PANEL_SIMULATOR_PREFERENCES::TransferDataToWindow() +{ + SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager(); + const EESCHEMA_SETTINGS* settings = mgr.GetAppSettings(); + applyMouseScrollActionsToPanel( settings->m_Simulator.preferences.mouse_wheel_actions ); + return true; +} + + +void PANEL_SIMULATOR_PREFERENCES::onMouseDefaults( wxCommandEvent& ) +{ + applyMouseScrollActionsToPanel( SIM_MOUSE_WHEEL_ACTION_SET::GetMouseDefaults() ); +} + + +void PANEL_SIMULATOR_PREFERENCES::onTrackpadDefaults( wxCommandEvent& ) +{ + applyMouseScrollActionsToPanel( SIM_MOUSE_WHEEL_ACTION_SET::GetTrackpadDefaults() ); +} + + +SIM_MOUSE_WHEEL_ACTION +PANEL_SIMULATOR_PREFERENCES::horizontalScrollSelectionToAction( int aSelection ) +{ + switch( aSelection ) + { + case 0: return SIM_MOUSE_WHEEL_ACTION::NONE; + case 1: return SIM_MOUSE_WHEEL_ACTION::PAN_LEFT_RIGHT; + case 2: return SIM_MOUSE_WHEEL_ACTION::ZOOM_HORIZONTALLY; + default: break; + } + + return SIM_MOUSE_WHEEL_ACTION::NONE; +} + +int PANEL_SIMULATOR_PREFERENCES::actionToHorizontalScrollSelection( SIM_MOUSE_WHEEL_ACTION a ) +{ + switch( a ) + { + case SIM_MOUSE_WHEEL_ACTION::NONE: return 0; + case SIM_MOUSE_WHEEL_ACTION::PAN_LEFT_RIGHT: return 1; + case SIM_MOUSE_WHEEL_ACTION::ZOOM_HORIZONTALLY: return 2; + default: break; + } + + return 0; +} + + +void PANEL_SIMULATOR_PREFERENCES::applyMouseScrollActionsToPanel( + const SIM_MOUSE_WHEEL_ACTION_SET& anActionSet ) +{ + static constexpr auto setSelection = + []( wxChoice* aChoice, auto action ) + { + aChoice->SetSelection( static_cast( action ) ); + }; + + setSelection( m_choiceVScrollUnmodified, anActionSet.vertical_unmodified ); + setSelection( m_choiceVScrollCtrl, anActionSet.vertical_with_ctrl ); + setSelection( m_choiceVScrollShift, anActionSet.vertical_with_shift ); + setSelection( m_choiceVScrollAlt, anActionSet.vertical_with_alt ); + + m_choiceHScroll->SetSelection( actionToHorizontalScrollSelection( anActionSet.horizontal ) ); +} diff --git a/eeschema/dialogs/panel_simulator_preferences.fbp b/eeschema/dialogs/panel_simulator_preferences.fbp new file mode 100644 index 0000000000..9dfe23403a --- /dev/null +++ b/eeschema/dialogs/panel_simulator_preferences.fbp @@ -0,0 +1,1431 @@ + + + + + ; + C++ + 1 + source_name + 0 + 0 + res + UTF-8 + connect + panel_simulator_preferences_base + 1000 + none + + + 1 + PANEL_SIMULATOR_PREFERENCES_BASE + + . + + 1 + 1 + 1 + 1 + UI + 0 + 1 + 0 + + 0 + wxAUI_MGR_DEFAULT + + + 1 + 1 + impl_virtual + + + 0 + wxID_ANY + + + PANEL_SIMULATOR_PREFERENCES_BASE + + -1,-1 + RESETTABLE_PANEL; widgets/resettable_panel.h; Not forward_declare + + 0 + + + wxTAB_TRAVERSAL + + + bMainSizer + wxVERTICAL + none + + 5 + + 1 + + + bScrollSizer + wxVERTICAL + none + + 13 + wxEXPAND|wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Scroll Gestures + 0 + + 0 + + + 0 + + 1 + m_lblScrollHeading + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxEXPAND|wxBOTTOM + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_scrollLine + 1 + + + protected + 1 + + Resizable + 1 + + wxLI_HORIZONTAL + ; ; forward_declare + 0 + + + + + + + + 10 + wxEXPAND|wxTOP|wxRIGHT + 1 + + + bScrollMargins + wxHORIZONTAL + none + + 5 + wxEXPAND|wxLEFT + 0 + + + bScrollSizerLeft + wxVERTICAL + none + + 5 + wxLEFT|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Vertical touchpad or scroll wheel movement: + 0 + + 0 + + + 0 + + 1 + m_lblVScrollMovement + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxEXPAND + 0 + + 10 + protected + 0 + + + + 24 + wxRIGHT|wxLEFT + 0 + + 2 + wxBOTH + 0 + + 0 + + fgVScroll + wxFLEX_GROWMODE_SPECIFIED + none + 0 + 0 + + 5 + wxALIGN_BOTTOM + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Modifier + 0 + + 0 + + + 0 + + 1 + m_lblVScrollModifier + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Action + 0 + + 0 + + + 0 + -1,-1 + 1 + m_lblVScrollAction + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + None: + 0 + + 0 + + + 0 + + 1 + m_lblVScrollUnmodified + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALL|wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_choiceVScrollUnmodified + 1 + + + protected + 1 + + Resizable + 0 + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Ctrl: + 0 + + 0 + + + 0 + + 1 + m_lblVScrollCtrl + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALL|wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_choiceVScrollCtrl + 1 + + + protected + 1 + + Resizable + 0 + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Shift: + 0 + + 0 + + + 0 + + 1 + m_lblVScrollShift + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALL|wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_choiceVScrollShift + 1 + + + protected + 1 + + Resizable + 0 + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Alt: + 0 + + 0 + + + 0 + + 1 + m_lblVScrollAlt + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALL|wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_choiceVScrollAlt + 1 + + + protected + 1 + + Resizable + 0 + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + 5 + wxEXPAND + 0 + + 10 + protected + 0 + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Horizontal touchpad movement: + 0 + + 0 + + + 0 + + 1 + m_lblHScrollMovement + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxEXPAND + 0 + + 10 + protected + 0 + + + + 24 + wxRIGHT|wxLEFT + 0 + + 2 + wxBOTH + 0 + + 0 + + fgHScroll + wxFLEX_GROWMODE_SPECIFIED + none + 0 + 0 + + 5 + wxALIGN_BOTTOM + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Modifier + 0 + + 0 + + + 0 + + 1 + m_lblHScrollModifier + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Action + 0 + + 0 + + + 0 + -1,-1 + 1 + m_lblHScrollAction + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Any: + 0 + + 0 + + + 0 + + 1 + m_lblHScrollAny + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALL|wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_choiceHScroll + 1 + + + protected + 1 + + Resizable + 0 + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + 5 + wxTOP|wxLEFT|wxEXPAND + 0 + + + bScrollSizerRight + wxVERTICAL + none + + 5 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 1 + + 1 + + + 0 + 0 + wxID_ANY + Reset to Mouse Defaults + + 0 + + 0 + + + 0 + + 1 + m_btnMouseDefaults + 1 + + + protected + 1 + + + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + onMouseDefaults + + + + 5 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 1 + + 1 + + + 0 + 0 + wxID_ANY + Reset to Trackpad Defaults + + 0 + + 0 + + + 0 + + 1 + m_btnTrackpadDefaults + 1 + + + protected + 1 + + + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + onTrackpadDefaults + + + + + + + + + + + + diff --git a/eeschema/dialogs/panel_simulator_preferences.h b/eeschema/dialogs/panel_simulator_preferences.h new file mode 100644 index 0000000000..5704f536ab --- /dev/null +++ b/eeschema/dialogs/panel_simulator_preferences.h @@ -0,0 +1,49 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef KICAD_PANEL_SIMULATOR_PREFERENCES_H +#define KICAD_PANEL_SIMULATOR_PREFERENCES_H + +#include "panel_simulator_preferences_base.h" +#include + + +class PANEL_SIMULATOR_PREFERENCES : public PANEL_SIMULATOR_PREFERENCES_BASE +{ +public: + PANEL_SIMULATOR_PREFERENCES( wxWindow* aParent ); + ~PANEL_SIMULATOR_PREFERENCES(); + void ResetPanel() override; + +protected: + bool TransferDataFromWindow() override; + bool TransferDataToWindow() override; + void onMouseDefaults( wxCommandEvent& ) override; + void onTrackpadDefaults( wxCommandEvent& ) override; + +private: + static SIM_MOUSE_WHEEL_ACTION horizontalScrollSelectionToAction( int aSelection ); + + static int actionToHorizontalScrollSelection( SIM_MOUSE_WHEEL_ACTION anAction ); + + void applyMouseScrollActionsToPanel( const SIM_MOUSE_WHEEL_ACTION_SET& anActionSet ); +}; + + +#endif diff --git a/eeschema/dialogs/panel_simulator_preferences_base.cpp b/eeschema/dialogs/panel_simulator_preferences_base.cpp new file mode 100644 index 0000000000..f1c0dcbd6b --- /dev/null +++ b/eeschema/dialogs/panel_simulator_preferences_base.cpp @@ -0,0 +1,166 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "panel_simulator_preferences_base.h" + +/////////////////////////////////////////////////////////////////////////// + +PANEL_SIMULATOR_PREFERENCES_BASE::PANEL_SIMULATOR_PREFERENCES_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : RESETTABLE_PANEL( parent, id, pos, size, style, name ) +{ + wxBoxSizer* bMainSizer; + bMainSizer = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bScrollSizer; + bScrollSizer = new wxBoxSizer( wxVERTICAL ); + + m_lblScrollHeading = new wxStaticText( this, wxID_ANY, _("Scroll Gestures"), wxDefaultPosition, wxDefaultSize, 0 ); + m_lblScrollHeading->Wrap( -1 ); + bScrollSizer->Add( m_lblScrollHeading, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 13 ); + + m_scrollLine = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bScrollSizer->Add( m_scrollLine, 0, wxEXPAND|wxBOTTOM, 5 ); + + wxBoxSizer* bScrollMargins; + bScrollMargins = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bScrollSizerLeft; + bScrollSizerLeft = new wxBoxSizer( wxVERTICAL ); + + m_lblVScrollMovement = new wxStaticText( this, wxID_ANY, _("Vertical touchpad or scroll wheel movement:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_lblVScrollMovement->Wrap( -1 ); + bScrollSizerLeft->Add( m_lblVScrollMovement, 0, wxLEFT|wxRIGHT, 5 ); + + + bScrollSizerLeft->Add( 0, 10, 0, wxEXPAND, 5 ); + + wxFlexGridSizer* fgVScroll; + fgVScroll = new wxFlexGridSizer( 0, 2, 0, 0 ); + fgVScroll->AddGrowableCol( 0 ); + fgVScroll->SetFlexibleDirection( wxBOTH ); + fgVScroll->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_lblVScrollModifier = new wxStaticText( this, wxID_ANY, _("Modifier"), wxDefaultPosition, wxDefaultSize, 0 ); + m_lblVScrollModifier->Wrap( -1 ); + fgVScroll->Add( m_lblVScrollModifier, 0, wxALIGN_BOTTOM, 5 ); + + m_lblVScrollAction = new wxStaticText( this, wxID_ANY, _("Action"), wxDefaultPosition, wxDefaultSize, 0 ); + m_lblVScrollAction->Wrap( -1 ); + fgVScroll->Add( m_lblVScrollAction, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 5 ); + + m_lblVScrollUnmodified = new wxStaticText( this, wxID_ANY, _("None:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_lblVScrollUnmodified->Wrap( -1 ); + fgVScroll->Add( m_lblVScrollUnmodified, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + wxArrayString m_choiceVScrollUnmodifiedChoices; + m_choiceVScrollUnmodified = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceVScrollUnmodifiedChoices, 0 ); + m_choiceVScrollUnmodified->SetSelection( 0 ); + fgVScroll->Add( m_choiceVScrollUnmodified, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_lblVScrollCtrl = new wxStaticText( this, wxID_ANY, _("Ctrl:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_lblVScrollCtrl->Wrap( -1 ); + fgVScroll->Add( m_lblVScrollCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + wxArrayString m_choiceVScrollCtrlChoices; + m_choiceVScrollCtrl = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceVScrollCtrlChoices, 0 ); + m_choiceVScrollCtrl->SetSelection( 0 ); + fgVScroll->Add( m_choiceVScrollCtrl, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_lblVScrollShift = new wxStaticText( this, wxID_ANY, _("Shift:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_lblVScrollShift->Wrap( -1 ); + fgVScroll->Add( m_lblVScrollShift, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + wxArrayString m_choiceVScrollShiftChoices; + m_choiceVScrollShift = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceVScrollShiftChoices, 0 ); + m_choiceVScrollShift->SetSelection( 0 ); + fgVScroll->Add( m_choiceVScrollShift, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_lblVScrollAlt = new wxStaticText( this, wxID_ANY, _("Alt:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_lblVScrollAlt->Wrap( -1 ); + fgVScroll->Add( m_lblVScrollAlt, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + wxArrayString m_choiceVScrollAltChoices; + m_choiceVScrollAlt = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceVScrollAltChoices, 0 ); + m_choiceVScrollAlt->SetSelection( 0 ); + fgVScroll->Add( m_choiceVScrollAlt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bScrollSizerLeft->Add( fgVScroll, 0, wxRIGHT|wxLEFT, 24 ); + + + bScrollSizerLeft->Add( 0, 10, 0, wxEXPAND, 5 ); + + m_lblHScrollMovement = new wxStaticText( this, wxID_ANY, _("Horizontal touchpad movement:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_lblHScrollMovement->Wrap( -1 ); + bScrollSizerLeft->Add( m_lblHScrollMovement, 0, wxALL, 5 ); + + + bScrollSizerLeft->Add( 0, 10, 0, wxEXPAND, 5 ); + + wxFlexGridSizer* fgHScroll; + fgHScroll = new wxFlexGridSizer( 0, 2, 0, 0 ); + fgHScroll->AddGrowableCol( 0 ); + fgHScroll->SetFlexibleDirection( wxBOTH ); + fgHScroll->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_lblHScrollModifier = new wxStaticText( this, wxID_ANY, _("Modifier"), wxDefaultPosition, wxDefaultSize, 0 ); + m_lblHScrollModifier->Wrap( -1 ); + fgHScroll->Add( m_lblHScrollModifier, 0, wxALIGN_BOTTOM, 5 ); + + m_lblHScrollAction = new wxStaticText( this, wxID_ANY, _("Action"), wxDefaultPosition, wxDefaultSize, 0 ); + m_lblHScrollAction->Wrap( -1 ); + fgHScroll->Add( m_lblHScrollAction, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 5 ); + + m_lblHScrollAny = new wxStaticText( this, wxID_ANY, _("Any:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_lblHScrollAny->Wrap( -1 ); + fgHScroll->Add( m_lblHScrollAny, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + wxArrayString m_choiceHScrollChoices; + m_choiceHScroll = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceHScrollChoices, 0 ); + m_choiceHScroll->SetSelection( 0 ); + fgHScroll->Add( m_choiceHScroll, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bScrollSizerLeft->Add( fgHScroll, 0, wxRIGHT|wxLEFT, 24 ); + + + bScrollMargins->Add( bScrollSizerLeft, 0, wxEXPAND|wxLEFT, 5 ); + + wxBoxSizer* bScrollSizerRight; + bScrollSizerRight = new wxBoxSizer( wxVERTICAL ); + + m_btnMouseDefaults = new wxButton( this, wxID_ANY, _("Reset to Mouse Defaults"), wxDefaultPosition, wxDefaultSize, 0 ); + bScrollSizerRight->Add( m_btnMouseDefaults, 0, wxALL|wxEXPAND, 5 ); + + m_btnTrackpadDefaults = new wxButton( this, wxID_ANY, _("Reset to Trackpad Defaults"), wxDefaultPosition, wxDefaultSize, 0 ); + bScrollSizerRight->Add( m_btnTrackpadDefaults, 0, wxALL|wxEXPAND, 5 ); + + + bScrollMargins->Add( bScrollSizerRight, 0, wxTOP|wxLEFT|wxEXPAND, 5 ); + + + bScrollSizer->Add( bScrollMargins, 1, wxEXPAND|wxTOP|wxRIGHT, 10 ); + + + bMainSizer->Add( bScrollSizer, 1, 0, 5 ); + + + this->SetSizer( bMainSizer ); + this->Layout(); + bMainSizer->Fit( this ); + + // Connect Events + m_btnMouseDefaults->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SIMULATOR_PREFERENCES_BASE::onMouseDefaults ), NULL, this ); + m_btnTrackpadDefaults->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SIMULATOR_PREFERENCES_BASE::onTrackpadDefaults ), NULL, this ); +} + +PANEL_SIMULATOR_PREFERENCES_BASE::~PANEL_SIMULATOR_PREFERENCES_BASE() +{ + // Disconnect Events + m_btnMouseDefaults->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SIMULATOR_PREFERENCES_BASE::onMouseDefaults ), NULL, this ); + m_btnTrackpadDefaults->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SIMULATOR_PREFERENCES_BASE::onTrackpadDefaults ), NULL, this ); + +} diff --git a/eeschema/dialogs/panel_simulator_preferences_base.h b/eeschema/dialogs/panel_simulator_preferences_base.h new file mode 100644 index 0000000000..945c07ba1c --- /dev/null +++ b/eeschema/dialogs/panel_simulator_preferences_base.h @@ -0,0 +1,72 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include +#include +#include "widgets/resettable_panel.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +/// Class PANEL_SIMULATOR_PREFERENCES_BASE +/////////////////////////////////////////////////////////////////////////////// +class PANEL_SIMULATOR_PREFERENCES_BASE : public RESETTABLE_PANEL +{ + private: + + protected: + wxStaticText* m_lblScrollHeading; + wxStaticLine* m_scrollLine; + wxStaticText* m_lblVScrollMovement; + wxStaticText* m_lblVScrollModifier; + wxStaticText* m_lblVScrollAction; + wxStaticText* m_lblVScrollUnmodified; + wxChoice* m_choiceVScrollUnmodified; + wxStaticText* m_lblVScrollCtrl; + wxChoice* m_choiceVScrollCtrl; + wxStaticText* m_lblVScrollShift; + wxChoice* m_choiceVScrollShift; + wxStaticText* m_lblVScrollAlt; + wxChoice* m_choiceVScrollAlt; + wxStaticText* m_lblHScrollMovement; + wxStaticText* m_lblHScrollModifier; + wxStaticText* m_lblHScrollAction; + wxStaticText* m_lblHScrollAny; + wxChoice* m_choiceHScroll; + wxButton* m_btnMouseDefaults; + wxButton* m_btnTrackpadDefaults; + + // Virtual event handlers, override them in your derived class + virtual void onMouseDefaults( wxCommandEvent& event ) { event.Skip(); } + virtual void onTrackpadDefaults( wxCommandEvent& event ) { event.Skip(); } + + + public: + + PANEL_SIMULATOR_PREFERENCES_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 ); + + ~PANEL_SIMULATOR_PREFERENCES_BASE(); + +}; + diff --git a/eeschema/eeschema.cpp b/eeschema/eeschema.cpp index 006bda132b..3a9c131e69 100644 --- a/eeschema/eeschema.cpp +++ b/eeschema/eeschema.cpp @@ -3,7 +3,7 @@ * * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com * Copyright (C) 2008 Wayne Stambaugh - * Copyright (C) 2004-2023 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 2004-2024 KiCad Developers, see change_log.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -294,6 +295,9 @@ static struct IFACE : public KIFACE_BASE, public UNITS_PROVIDER case PANEL_SCH_FIELD_NAME_TEMPLATES: return new PANEL_TEMPLATE_FIELDNAMES( aParent, nullptr ); + case PANEL_SCH_SIMULATOR: + return new PANEL_SIMULATOR_PREFERENCES( aParent ); + default: return nullptr; } diff --git a/eeschema/eeschema_settings.cpp b/eeschema/eeschema_settings.cpp index 941aa39ea8..0a74b561b7 100644 --- a/eeschema/eeschema_settings.cpp +++ b/eeschema/eeschema_settings.cpp @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * -* Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors. +* Copyright (C) 2020-2024 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -531,22 +531,57 @@ EESCHEMA_SETTINGS::EESCHEMA_SETTINGS() : &m_Simulator.window.perspective, "" ) ); m_params.emplace_back( new PARAM( "simulator.plot_panel_width", - &m_Simulator.plot_panel_width, 0 ) ); + &m_Simulator.view.plot_panel_width, 0 ) ); m_params.emplace_back( new PARAM( "simulator.plot_panel_height", - &m_Simulator.plot_panel_height, 0 ) ); + &m_Simulator.view.plot_panel_height, 0 ) ); m_params.emplace_back( new PARAM( "simulator.signal_panel_height", - &m_Simulator.signal_panel_height, 0 ) ); + &m_Simulator.view.signal_panel_height, 0 ) ); m_params.emplace_back( new PARAM( "simulator.cursors_panel_height", - &m_Simulator.cursors_panel_height, 0 ) ); + &m_Simulator.view.cursors_panel_height, 0 ) ); m_params.emplace_back( new PARAM( "simulator.measurements_panel_height", - &m_Simulator.measurements_panel_height, 0 ) ); + &m_Simulator.view.measurements_panel_height, 0 ) ); m_params.emplace_back( new PARAM( "simulator.white_background", - &m_Simulator.white_background, false ) ); + &m_Simulator.view.white_background, false ) ); + + m_params.emplace_back( new PARAM_ENUM( + "simulator.mouse_wheel_actions.vertical_unmodified", + &m_Simulator.preferences.mouse_wheel_actions.vertical_unmodified, + SIM_MOUSE_WHEEL_ACTION::ZOOM, + SIM_MOUSE_WHEEL_ACTION::NONE, + SIM_MOUSE_WHEEL_ACTION::ZOOM_VERTICALLY ) ); + + m_params.emplace_back( new PARAM_ENUM( + "simulator.mouse_wheel_actions.vertical_with_ctrl", + &m_Simulator.preferences.mouse_wheel_actions.vertical_with_ctrl, + SIM_MOUSE_WHEEL_ACTION::PAN_LEFT_RIGHT, + SIM_MOUSE_WHEEL_ACTION::NONE, + SIM_MOUSE_WHEEL_ACTION::ZOOM_VERTICALLY ) ); + + m_params.emplace_back( new PARAM_ENUM( + "simulator.mouse_wheel_actions.vertical_with_shift", + &m_Simulator.preferences.mouse_wheel_actions.vertical_with_shift, + SIM_MOUSE_WHEEL_ACTION::PAN_UP_DOWN, + SIM_MOUSE_WHEEL_ACTION::NONE, + SIM_MOUSE_WHEEL_ACTION::ZOOM_VERTICALLY) ); + + m_params.emplace_back( new PARAM_ENUM( + "simulator.mouse_wheel_actions.vertical_with_alt", + &m_Simulator.preferences.mouse_wheel_actions.vertical_with_alt, + SIM_MOUSE_WHEEL_ACTION::NONE, + SIM_MOUSE_WHEEL_ACTION::NONE, + SIM_MOUSE_WHEEL_ACTION::ZOOM_VERTICALLY) ); + + m_params.emplace_back( new PARAM_ENUM( + "simulator.mouse_wheel_actions.horizontal", + &m_Simulator.preferences.mouse_wheel_actions.horizontal, + SIM_MOUSE_WHEEL_ACTION::NONE, + SIM_MOUSE_WHEEL_ACTION::NONE, + SIM_MOUSE_WHEEL_ACTION::ZOOM_VERTICALLY) ); m_params.emplace_back( new PARAM( "symbol_chooser.sash_pos_h", &m_SymChooserPanel.sash_pos_h, -1 ) ); diff --git a/eeschema/eeschema_settings.h b/eeschema/eeschema_settings.h index 425e9b6d6d..374d144dcd 100644 --- a/eeschema/eeschema_settings.h +++ b/eeschema/eeschema_settings.h @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * -* Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors. +* Copyright (C) 2020-2024 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -27,7 +27,7 @@ #include #include - +#include using KIGFX::COLOR4D; @@ -278,13 +278,19 @@ public: struct SIMULATOR { - int plot_panel_width; - int plot_panel_height; - int signal_panel_height; - int cursors_panel_height; - int measurements_panel_height; - bool white_background; + struct VIEW + { + int plot_panel_width; + int plot_panel_height; + int signal_panel_height; + int cursors_panel_height; + int measurements_panel_height; + bool white_background; + }; + + VIEW view; WINDOW_SETTINGS window; + SIM_PREFERENCES preferences; }; struct FIND_REPLACE_EXTRA diff --git a/eeschema/sim/sim_plot_tab.h b/eeschema/sim/sim_plot_tab.h index aa6c5b475e..40d76c45bf 100644 --- a/eeschema/sim/sim_plot_tab.h +++ b/eeschema/sim/sim_plot_tab.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2016-2023 CERN - * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2024 KiCad Developers, see AUTHORS.txt for contributors. * * @author Tomasz Wlostowski * @author Maciej Suminski @@ -195,6 +195,12 @@ public: virtual ~SIM_PLOT_TAB(); + void ApplyPreferences( const SIM_PREFERENCES& aPrefs ) override + { + m_plotWin->SetMouseWheelActions( + convertMouseWheelActions( aPrefs.mouse_wheel_actions ) ); + } + wxString GetLabelX() const { return m_axis_x ? m_axis_x->GetName() : wxString( wxS( "" ) ); @@ -359,6 +365,22 @@ public: wxPoint m_LastLegendPosition; private: + static mpWindow::MouseWheelActionSet + convertMouseWheelActions(const SIM_MOUSE_WHEEL_ACTION_SET& s) + { + static_assert( static_cast(mpWindow::MouseWheelAction::COUNT) == + static_cast(SIM_MOUSE_WHEEL_ACTION::COUNT), + "mpWindow::MouseWheelAction enum must match SIM_MOUSE_WHEEL_ACTION" ); + + using A = mpWindow::MouseWheelAction; + mpWindow::MouseWheelActionSet m; + m.verticalUnmodified = static_cast( s.vertical_unmodified ); + m.verticalWithCtrl = static_cast( s.vertical_with_ctrl ); + m.verticalWithShift = static_cast( s.vertical_with_shift ); + m.verticalWithAlt = static_cast( s.vertical_with_alt ); + return m; + } + wxString getTraceId( const wxString& aVectorName, int aType ) const { return wxString::Format( wxS( "%s%d" ), aVectorName, aType & SPT_Y_AXIS_MASK ); diff --git a/eeschema/sim/sim_preferences.h b/eeschema/sim/sim_preferences.h new file mode 100644 index 0000000000..b415aa5054 --- /dev/null +++ b/eeschema/sim/sim_preferences.h @@ -0,0 +1,101 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 3 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * https://www.gnu.org/licenses/gpl-3.0.html + * or you may search the http://www.gnu.org website for the version 3 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __SIM_PREFERENCES__ +#define __SIM_PREFERENCES__ + + +/** + * @file sim_preferences.h + * + * Contains preferences pertaining to the simulator. + */ + +/** + * Enumerates the possible mouse wheel actions that can be performed on simulator plots. + */ +enum class SIM_MOUSE_WHEEL_ACTION +{ + // Directly using mpWindow::MouseWheelAction would leak wxMathPlot via the eeschema_settings.h + // header, so we duplicate it here in this miminal header. + + NONE, + PAN_LEFT_RIGHT, + PAN_RIGHT_LEFT, + PAN_UP_DOWN, + ZOOM, + ZOOM_HORIZONTALLY, + ZOOM_VERTICALLY, + COUNT // Internal use only +}; + +/** + * Contains the set of modified mouse wheel actions that can be performed on a simulator plot. + */ +struct SIM_MOUSE_WHEEL_ACTION_SET +{ + // Directly using mpWindow::MouseWheelActionSet would leak wxMathPlot via the + // eeschema_settings.h header, so we duplicate it here in this miminal header. + + SIM_MOUSE_WHEEL_ACTION vertical_unmodified; + SIM_MOUSE_WHEEL_ACTION vertical_with_ctrl; + SIM_MOUSE_WHEEL_ACTION vertical_with_shift; + SIM_MOUSE_WHEEL_ACTION vertical_with_alt; + SIM_MOUSE_WHEEL_ACTION horizontal; + + static SIM_MOUSE_WHEEL_ACTION_SET GetMouseDefaults() + { + // Returns defaults equivalent to the global Mouse and Touchpad default settings + + SIM_MOUSE_WHEEL_ACTION_SET actions; + actions.vertical_unmodified = SIM_MOUSE_WHEEL_ACTION::ZOOM; + actions.vertical_with_ctrl = SIM_MOUSE_WHEEL_ACTION::PAN_LEFT_RIGHT; + actions.vertical_with_shift = SIM_MOUSE_WHEEL_ACTION::PAN_UP_DOWN; + actions.vertical_with_alt = SIM_MOUSE_WHEEL_ACTION::NONE; + actions.horizontal = SIM_MOUSE_WHEEL_ACTION::NONE; + return actions; + } + + static SIM_MOUSE_WHEEL_ACTION_SET GetTrackpadDefaults() + { + // Returns defaults equivalent to the global Mouse and Touchpad default settings + + SIM_MOUSE_WHEEL_ACTION_SET actions; + actions.vertical_unmodified = SIM_MOUSE_WHEEL_ACTION::PAN_UP_DOWN; + actions.vertical_with_ctrl = SIM_MOUSE_WHEEL_ACTION::ZOOM; + actions.vertical_with_shift = SIM_MOUSE_WHEEL_ACTION::PAN_LEFT_RIGHT; + actions.vertical_with_alt = SIM_MOUSE_WHEEL_ACTION::NONE; + actions.horizontal = SIM_MOUSE_WHEEL_ACTION::PAN_LEFT_RIGHT; + return actions; + } +}; + +/** + * Contains preferences pertaining to the simulator. + */ +struct SIM_PREFERENCES +{ + SIM_MOUSE_WHEEL_ACTION_SET mouse_wheel_actions; +}; + +#endif // __SIM_PREFERENCES__ diff --git a/eeschema/sim/sim_tab.cpp b/eeschema/sim/sim_tab.cpp index 3ba2931860..4904cb8d25 100644 --- a/eeschema/sim/sim_tab.cpp +++ b/eeschema/sim/sim_tab.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2016-2023 CERN - * Copyright (C) 2021-2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2021-2024 KiCad Developers, see AUTHORS.txt for contributors. * @author Sylwester Kocjan * * This program is free software; you can redistribute it and/or @@ -67,6 +67,10 @@ bool SIM_TAB::IsPlottable( SIM_TYPE aSimType ) } } +void SIM_TAB::ApplyPreferences( const SIM_PREFERENCES& /*aPrefs*/ ) +{ +} + SIM_TYPE SIM_TAB::GetSimType() const { diff --git a/eeschema/sim/sim_tab.h b/eeschema/sim/sim_tab.h index af70d528c9..ebdeaa20af 100644 --- a/eeschema/sim/sim_tab.h +++ b/eeschema/sim/sim_tab.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2016-2023 CERN - * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2024 KiCad Developers, see AUTHORS.txt for contributors. * @author Sylwester Kocjan * * This program is free software; you can redistribute it and/or @@ -26,6 +26,7 @@ #ifndef __SIM_PLOT_PANEL_BASE_H #define __SIM_PLOT_PANEL_BASE_H +#include #include #include #include @@ -44,6 +45,8 @@ public: virtual void OnLanguageChanged() = 0; + virtual void ApplyPreferences( const SIM_PREFERENCES& aPrefs ); + SIM_TYPE GetSimType() const; const wxString& GetSimCommand() const { return m_simCommand; } diff --git a/eeschema/sim/simulator_frame.cpp b/eeschema/sim/simulator_frame.cpp index 14bbfa7191..8871517303 100644 --- a/eeschema/sim/simulator_frame.cpp +++ b/eeschema/sim/simulator_frame.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2016-2023 CERN - * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2024 KiCad Developers, see AUTHORS.txt for contributors. * @author Tomasz Wlostowski * @author Maciej Suminski * @@ -272,6 +272,16 @@ void SIMULATOR_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg ) } +void SIMULATOR_FRAME::CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVarsChanged ) +{ + KIWAY_PLAYER::CommonSettingsChanged( aEnvVarsChanged, aTextVarsChanged ); + + auto* cfg = dynamic_cast( m_toolManager->GetSettings() ); + wxASSERT( cfg != nullptr ); + m_ui->ApplyPreferences( cfg->m_Simulator.preferences ); +} + + WINDOW_SETTINGS* SIMULATOR_FRAME::GetWindowSettings( APP_SETTINGS_BASE* aCfg ) { EESCHEMA_SETTINGS* cfg = dynamic_cast( aCfg ); diff --git a/eeschema/sim/simulator_frame.h b/eeschema/sim/simulator_frame.h index 4da48bbcf5..39dc92c6d0 100644 --- a/eeschema/sim/simulator_frame.h +++ b/eeschema/sim/simulator_frame.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2016-2023 CERN - * Copyright (C) 2017-2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2017-2024 KiCad Developers, see AUTHORS.txt for contributors. * * @author Tomasz Wlostowski * @author Maciej Suminski @@ -162,6 +162,8 @@ public: void SaveSettings( APP_SETTINGS_BASE* aCfg ) override; + void CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVarsChanged ) override; + WINDOW_SETTINGS* GetWindowSettings( APP_SETTINGS_BASE* aCfg ) override; SCH_EDIT_FRAME* GetSchematicFrame() const { return m_schematicFrame; } diff --git a/eeschema/sim/simulator_frame_ui.cpp b/eeschema/sim/simulator_frame_ui.cpp index 3b29c47652..ea268eb309 100644 --- a/eeschema/sim/simulator_frame_ui.cpp +++ b/eeschema/sim/simulator_frame_ui.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2016-2023 CERN - * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2024 KiCad Developers, see AUTHORS.txt for contributors. * @author Tomasz Wlostowski * @author Maciej Suminski * @@ -605,24 +605,45 @@ void SIMULATOR_FRAME_UI::ShowChangedLanguage() void SIMULATOR_FRAME_UI::LoadSettings( EESCHEMA_SETTINGS* aCfg ) { + const EESCHEMA_SETTINGS::SIMULATOR& settings = aCfg->m_Simulator; + // Read subwindows sizes (should be > 0 ) - m_splitterLeftRightSashPosition = aCfg->m_Simulator.plot_panel_width; - m_splitterPlotAndConsoleSashPosition = aCfg->m_Simulator.plot_panel_height; - m_splitterSignalsSashPosition = aCfg->m_Simulator.signal_panel_height; - m_splitterCursorsSashPosition = aCfg->m_Simulator.cursors_panel_height; - m_splitterTuneValuesSashPosition = aCfg->m_Simulator.measurements_panel_height; - m_darkMode = !aCfg->m_Simulator.white_background; + m_splitterLeftRightSashPosition = settings.view.plot_panel_width; + m_splitterPlotAndConsoleSashPosition = settings.view.plot_panel_height; + m_splitterSignalsSashPosition = settings.view.signal_panel_height; + m_splitterCursorsSashPosition = settings.view.cursors_panel_height; + m_splitterTuneValuesSashPosition = settings.view.measurements_panel_height; + m_darkMode = !settings.view.white_background; + + m_preferences = settings.preferences; } void SIMULATOR_FRAME_UI::SaveSettings( EESCHEMA_SETTINGS* aCfg ) { - aCfg->m_Simulator.plot_panel_width = m_splitterLeftRight->GetSashPosition(); - aCfg->m_Simulator.plot_panel_height = m_splitterPlotAndConsole->GetSashPosition(); - aCfg->m_Simulator.signal_panel_height = m_splitterSignals->GetSashPosition(); - aCfg->m_Simulator.cursors_panel_height = m_splitterCursors->GetSashPosition(); - aCfg->m_Simulator.measurements_panel_height = m_splitterMeasurements->GetSashPosition(); - aCfg->m_Simulator.white_background = !m_darkMode; + EESCHEMA_SETTINGS::SIMULATOR& settings = aCfg->m_Simulator; + + settings.view.plot_panel_width = m_splitterLeftRight->GetSashPosition(); + settings.view.plot_panel_height = m_splitterPlotAndConsole->GetSashPosition(); + settings.view.signal_panel_height = m_splitterSignals->GetSashPosition(); + settings.view.cursors_panel_height = m_splitterCursors->GetSashPosition(); + settings.view.measurements_panel_height = m_splitterMeasurements->GetSashPosition(); + settings.view.white_background = !m_darkMode; +} + + +void SIMULATOR_FRAME_UI::ApplyPreferences( const SIM_PREFERENCES& aPrefs ) +{ + m_preferences = aPrefs; + + const std::size_t pageCount = m_plotNotebook->GetPageCount(); + for( std::size_t i = 0; iGetPage( i ); + auto simTab = dynamic_cast( page ); + wxASSERT( simTab != nullptr ); + simTab->ApplyPreferences( aPrefs ); + } } @@ -943,9 +964,7 @@ SIM_TAB* SIMULATOR_FRAME_UI::NewSimTab( const wxString& aSimCommand ) { SIM_PLOT_TAB* panel = new SIM_PLOT_TAB( aSimCommand, m_plotNotebook ); simTab = panel; - - COMMON_SETTINGS::INPUT cfg = Pgm().GetCommonSettings()->m_Input; - panel->GetPlotWin()->EnableMouseWheelPan( cfg.scroll_modifier_zoom != 0 ); + panel->ApplyPreferences( m_preferences ); } else { diff --git a/eeschema/sim/simulator_frame_ui.h b/eeschema/sim/simulator_frame_ui.h index 157a195274..f8537f315a 100644 --- a/eeschema/sim/simulator_frame_ui.h +++ b/eeschema/sim/simulator_frame_ui.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2016-2023 CERN - * Copyright (C) 2017-2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2017-2024 KiCad Developers, see AUTHORS.txt for contributors. * * @author Tomasz Wlostowski * @author Maciej Suminski @@ -32,6 +32,7 @@ #include #include #include +#include #include @@ -185,6 +186,11 @@ public: void SaveSettings( EESCHEMA_SETTINGS* aCfg ); + /** + * Called when settings are changed via the common Preferences dialog. + */ + void ApplyPreferences( const SIM_PREFERENCES& aPrefs ); + // adjust the sash dimension of splitter windows after reading // the config settings // must be called after the config settings are read, and once the @@ -342,6 +348,7 @@ private: bool m_darkMode; unsigned int m_plotNumber; wxTimer m_refreshTimer; + SIM_PREFERENCES m_preferences; }; #endif // SIMULATOR_FRAME_UI_H diff --git a/eeschema/sim/toolbars_simulator_frame.cpp b/eeschema/sim/toolbars_simulator_frame.cpp index 4d0edaf869..d8c2ad5dcd 100644 --- a/eeschema/sim/toolbars_simulator_frame.cpp +++ b/eeschema/sim/toolbars_simulator_frame.cpp @@ -58,6 +58,10 @@ void SIMULATOR_FRAME::ReCreateHToolbar() m_toolBar->AddScaledSeparator( this ); m_toolBar->Add( ACTIONS::zoomInCenter ); m_toolBar->Add( ACTIONS::zoomOutCenter ); + m_toolBar->Add( ACTIONS::zoomInHorizontally ); + m_toolBar->Add( ACTIONS::zoomOutHorizontally ); + m_toolBar->Add( ACTIONS::zoomInVertically ); + m_toolBar->Add( ACTIONS::zoomOutVertically ); m_toolBar->Add( ACTIONS::zoomFitScreen ); m_toolBar->AddScaledSeparator( this ); @@ -117,6 +121,10 @@ void SIMULATOR_FRAME::doReCreateMenuBar() viewMenu->AppendSeparator(); viewMenu->Add( ACTIONS::zoomInCenter ); viewMenu->Add( ACTIONS::zoomOutCenter ); + viewMenu->Add( ACTIONS::zoomInHorizontally ); + viewMenu->Add( ACTIONS::zoomOutHorizontally ); + viewMenu->Add( ACTIONS::zoomInVertically ); + viewMenu->Add( ACTIONS::zoomOutVertically ); viewMenu->Add( ACTIONS::zoomFitScreen ); viewMenu->AppendSeparator(); diff --git a/eeschema/tools/simulator_control.cpp b/eeschema/tools/simulator_control.cpp index f171f4d5a6..2caf3a1087 100644 --- a/eeschema/tools/simulator_control.cpp +++ b/eeschema/tools/simulator_control.cpp @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2023-2024 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -248,18 +248,36 @@ int SIMULATOR_CONTROL::Zoom( const TOOL_EVENT& aEvent ) { if( SIM_PLOT_TAB* plotTab = dynamic_cast( getCurrentSimTab() ) ) { + mpWindow* plot = plotTab->GetPlotWin(); + if( aEvent.IsAction( &ACTIONS::zoomInCenter ) ) { - plotTab->GetPlotWin()->ZoomIn(); + plot->ZoomIn(); } else if( aEvent.IsAction( &ACTIONS::zoomOutCenter ) ) { - plotTab->GetPlotWin()->ZoomOut(); + plot->ZoomOut(); + } + else if( aEvent.IsAction( &ACTIONS::zoomInHorizontally ) ) + { + plot->ZoomIn( wxDefaultPosition, mpWindow::zoomIncrementalFactor, wxHORIZONTAL ); + } + else if( aEvent.IsAction( &ACTIONS::zoomOutHorizontally ) ) + { + plot->ZoomOut( wxDefaultPosition, mpWindow::zoomIncrementalFactor, wxHORIZONTAL ); + } + else if( aEvent.IsAction( &ACTIONS::zoomInVertically ) ) + { + plot->ZoomIn( wxDefaultPosition, mpWindow::zoomIncrementalFactor, wxVERTICAL ); + } + else if( aEvent.IsAction( &ACTIONS::zoomOutVertically ) ) + { + plot->ZoomOut( wxDefaultPosition, mpWindow::zoomIncrementalFactor, wxVERTICAL ); } else if( aEvent.IsAction( &ACTIONS::zoomFitScreen ) ) { wxCommandEvent dummy; - plotTab->GetPlotWin()->OnFit( dummy ); + plot->OnFit( dummy ); } } @@ -519,6 +537,10 @@ void SIMULATOR_CONTROL::setTransitions() Go( &SIMULATOR_CONTROL::Zoom, ACTIONS::zoomInCenter.MakeEvent() ); Go( &SIMULATOR_CONTROL::Zoom, ACTIONS::zoomOutCenter.MakeEvent() ); + Go( &SIMULATOR_CONTROL::Zoom, ACTIONS::zoomInHorizontally.MakeEvent() ); + Go( &SIMULATOR_CONTROL::Zoom, ACTIONS::zoomOutHorizontally.MakeEvent() ); + Go( &SIMULATOR_CONTROL::Zoom, ACTIONS::zoomInVertically.MakeEvent() ); + Go( &SIMULATOR_CONTROL::Zoom, ACTIONS::zoomOutVertically.MakeEvent() ); Go( &SIMULATOR_CONTROL::Zoom, ACTIONS::zoomFitScreen.MakeEvent() ); Go( &SIMULATOR_CONTROL::UndoZoom, ACTIONS::zoomUndo.MakeEvent() ); Go( &SIMULATOR_CONTROL::RedoZoom, ACTIONS::zoomRedo.MakeEvent() ); diff --git a/eeschema/tools/simulator_control.h b/eeschema/tools/simulator_control.h index 596b68bcfa..b02a877896 100644 --- a/eeschema/tools/simulator_control.h +++ b/eeschema/tools/simulator_control.h @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2023-2024 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -28,6 +28,7 @@ #include class SIMULATOR_FRAME; +class SCH_EDIT_FRAME; class SPICE_CIRCUIT_MODEL; class SPICE_SIMULATOR; class SIM_TAB; diff --git a/include/bitmaps/bitmaps_list.h b/include/bitmaps/bitmaps_list.h index 642433e460..dba30cc731 100644 --- a/include/bitmaps/bitmaps_list.h +++ b/include/bitmaps/bitmaps_list.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2007-2017 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.TXT for contributors. + * Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.TXT for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -653,6 +653,10 @@ enum class BITMAPS : unsigned int zoom_fit_to_objects, zoom_in, zoom_out, + zoom_in_horizontally, + zoom_out_horizontally, + zoom_in_vertically, + zoom_out_vertically, zoom_page, zoom_selection, }; diff --git a/include/frame_type.h b/include/frame_type.h index 803bd89e0f..c5b7bca780 100644 --- a/include/frame_type.h +++ b/include/frame_type.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2014 CERN - * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors. * @author Maciej Suminski * * This program is free software; you can redistribute it and/or @@ -80,6 +80,7 @@ enum FRAME_T PANEL_SCH_ANNO_OPTIONS, PANEL_SCH_COLORS, PANEL_SCH_FIELD_NAME_TEMPLATES, + PANEL_SCH_SIMULATOR, PANEL_FP_DISPLAY_OPTIONS, PANEL_FP_GRIDS, diff --git a/include/tool/actions.h b/include/tool/actions.h index 365ab175b5..d131e916df 100644 --- a/include/tool/actions.h +++ b/include/tool/actions.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2013-2016 CERN - * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2024 KiCad Developers, see AUTHORS.txt for contributors. * @author Maciej Suminski * * This program is free software; you can redistribute it and/or @@ -116,6 +116,10 @@ public: static TOOL_ACTION zoomOut; static TOOL_ACTION zoomInCenter; static TOOL_ACTION zoomOutCenter; + static TOOL_ACTION zoomInHorizontally; + static TOOL_ACTION zoomOutHorizontally; + static TOOL_ACTION zoomInVertically; + static TOOL_ACTION zoomOutVertically; static TOOL_ACTION zoomCenter; static TOOL_ACTION zoomFitScreen; static TOOL_ACTION zoomFitObjects; // Zooms to bbox of items on screen (except page border) diff --git a/include/widgets/mathplot.h b/include/widgets/mathplot.h index 2b31bfea6d..990cc4e647 100644 --- a/include/widgets/mathplot.h +++ b/include/widgets/mathplot.h @@ -7,7 +7,7 @@ // Created: 21/07/2003 // Last edit: 05/08/2016 // Copyright: (c) David Schalig, Davide Rondini -// Copyright (c) 2021-2023 KiCad Developers, see AUTHORS.txt for contributors. +// Copyright (c) 2021-2024 KiCad Developers, see AUTHORS.txt for contributors. // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -905,6 +905,38 @@ typedef std::deque wxLayerList; class WXDLLIMPEXP_MATHPLOT mpWindow : public wxWindow { public: + /** + * Enumerates the possible mouse wheel actions that can be performed on the plot. + */ + enum class MouseWheelAction + { + NONE, + PAN_LEFT_RIGHT, + PAN_RIGHT_LEFT, + PAN_UP_DOWN, + ZOOM, + ZOOM_HORIZONTALLY, + ZOOM_VERTICALLY, + COUNT // Internal use only + }; + + /** + * Contains the set of modified mouse wheel actions that can be performed on the plot. + */ + struct MouseWheelActionSet + { + /* If this bundled wxMathPlot implementation is to remain single-header and not dependent + * on any part of KiCad, then the SIM_MOUSE_WHEEL_ACTION_SET struct must be duplicated + * here. SIM_PLOT_TAB::convertMouseWheelActions is used to convert from + * SIM_MOUSE_WHEEL_ACTION_SET to mpWindow::MouseWheelActionSet. */ + + MouseWheelAction verticalUnmodified; + MouseWheelAction verticalWithCtrl; + MouseWheelAction verticalWithShift; + MouseWheelAction verticalWithAlt; + MouseWheelAction horizontal; + }; + mpWindow(); mpWindow( wxWindow* parent, wxWindowID id ); ~mpWindow(); @@ -1068,9 +1100,8 @@ public: */ void EnableMousePanZoom( bool enabled ) { m_enableMouseNavigation = enabled; } - /** Enable/disable trackpad friendly panning (2-axis scroll wheel) - */ - void EnableMouseWheelPan( bool enabled ) { m_enableMouseWheelPan = enabled; } + /** Set the pan/zoom actions corresponding to mousewheel/trackpad events. */ + void SetMouseWheelActions( const MouseWheelActionSet& s ) {m_mouseWheelActions = s;} /** Set view to fit global bounding box of all plot layers and refresh display. * Scale and position will be set to show all attached mpLayers. @@ -1085,21 +1116,24 @@ public: * as the "desired borders", since this use will be invoked only when printing. */ void Fit( double xMin, double xMax, double yMin, double yMax, - const wxCoord* printSizeX = nullptr, const wxCoord* printSizeY = nullptr ); + const wxCoord* printSizeX = nullptr, const wxCoord* printSizeY = nullptr, + wxOrientation directions = wxBOTH ); /** Zoom into current view and refresh display * @param centerPoint The point (pixel coordinates) that will stay in the same * position on the screen after the zoom (by default, the center of the mpWindow). */ void ZoomIn( const wxPoint& centerPoint = wxDefaultPosition ); - void ZoomIn( const wxPoint& centerPoint, double zoomFactor ); + void ZoomIn( const wxPoint& centerPoint, double zoomFactor, + wxOrientation directions = wxBOTH ); /** Zoom out current view and refresh display * @param centerPoint The point (pixel coordinates) that will stay in the same * position on the screen after the zoom (by default, the center of the mpWindow). */ void ZoomOut( const wxPoint& centerPoint = wxDefaultPosition ); - void ZoomOut( const wxPoint& centerPoint, double zoomFactor ); + void ZoomOut( const wxPoint& centerPoint, double zoomFactor, + wxOrientation directions = wxBOTH ); /** Zoom view fitting given coordinates to the window (p0 and p1 do not need to be in any specific order) */ @@ -1219,7 +1253,7 @@ public: * @return reference to axis colour used in theme */ const wxColour& GetAxesColour() { return m_axColour; }; - /** Limit zooming & panning to the area used by the plots */ + /** Enable limiting of zooming & panning to the area used by the plots */ void LimitView( bool aEnable ) { m_enableLimitedView = aEnable; @@ -1233,12 +1267,15 @@ public: int UndoZoomStackSize() const { return m_undoZoomStack.size(); } int RedoZoomStackSize() const { return m_redoZoomStack.size(); } - void AdjustLimitedView(); + /** Limits the zoomed or panned view to the area used by the plots. */ + void AdjustLimitedView( wxOrientation directions = wxBOTH ); void OnFit( wxCommandEvent& event ); void OnCenter( wxCommandEvent& event ); protected: + static MouseWheelActionSet defaultMouseWheelActions(); + void pushZoomUndo( const std::array& aZoom ); void OnPaint( wxPaintEvent& event ); // !< Paint handler, will plot all attached layers @@ -1258,19 +1295,12 @@ protected: void onMouseLeftDown( wxMouseEvent& event ); // !< Mouse left click (for rect zoom) void onMouseLeftRelease( wxMouseEvent& event ); // !< Mouse left click (for rect zoom) - bool CheckXLimits( double& desiredMax, double& desiredMin ) const - { - return !( m_enableLimitedView - && (desiredMax > m_maxX - m_marginRight / m_scaleX - || desiredMin < m_minX - m_marginLeft / m_scaleX) ); - } + void DoZoom( const wxPoint& centerPoint, double zoomFactor, wxOrientation directions ); + void RecomputeDesiredX( double& min, double& max ); + void RecomputeDesiredY( double& min, double& max ); + wxOrientation ViewNeedsRefitting( wxOrientation directions ) const; - bool CheckYLimits( double& desiredMax, double& desiredMin ) const - { - return !( m_enableLimitedView - && (desiredMax > m_maxY + m_marginTop / m_scaleY - || desiredMin < m_minY - m_marginBottom / m_scaleY) ); - } + void PerformMouseWheelAction( wxMouseEvent& event, MouseWheelAction action ); /** Recalculate global layer bounding box, and save it in m_minX,... * \return true if there is any valid BBox information. @@ -1309,11 +1339,19 @@ protected: bool m_yLocked; - /** These are updated in Fit() only, and may be different from the real borders - * (layer coordinates) only if lock aspect ratio is true. + /** These are updated in Fit, ZoomIn, ZoomOut, ZoomRect, SetXView, SetYView and may be different + * from the real borders (layer coordinates) only if lock aspect ratio is true. + * + * @note They use the plot area as their coordinate system, and not the layer coordinate + * system used by m_posX/Y. */ double m_desiredXmin, m_desiredXmax, m_desiredYmin, m_desiredYmax; + // These are gaps between the curve extrema and the edges of the plot area, expressed as + // a factor of global layer bounding box width/height. + double m_topBottomPlotGapFactor; + double m_leftRightPlotGapFactor; + int m_marginTop, m_marginRight, m_marginBottom, m_marginLeft; int m_last_lx, m_last_ly; // !< For double buffering @@ -1321,11 +1359,11 @@ protected: wxBitmap* m_buff_bmp; // !< For double buffering bool m_enableDoubleBuffer; // !< For double buffering bool m_enableMouseNavigation; // !< For pan/zoom with the mouse. - bool m_enableMouseWheelPan; // !< Trackpad pan/zoom bool m_enableLimitedView; + MouseWheelActionSet m_mouseWheelActions; wxPoint m_mouseMClick; // !< For the middle button "drag" feature wxPoint m_mouseLClick; // !< Starting coords for rectangular zoom selection - mpInfoLayer* m_movingInfoLayer; // !< For moving info layers over the window area + mpInfoLayer* m_movingInfoLayer; // !< For moving info layers over the window area bool m_zooming; wxRect m_zoomRect; std::stack> m_undoZoomStack; @@ -1333,6 +1371,14 @@ protected: DECLARE_DYNAMIC_CLASS( mpWindow ) DECLARE_EVENT_TABLE() + +private: + struct DelegatingContructorTag {}; + + template + mpWindow( DelegatingContructorTag, Ts&&... windowArgs ); + + void initializeGraphicsContext(); }; // ----------------------------------------------------------------------------- diff --git a/resources/bitmaps_png/png/zoom_in_horizontally_16.png b/resources/bitmaps_png/png/zoom_in_horizontally_16.png new file mode 100644 index 0000000000..b9712f40cc Binary files /dev/null and b/resources/bitmaps_png/png/zoom_in_horizontally_16.png differ diff --git a/resources/bitmaps_png/png/zoom_in_horizontally_24.png b/resources/bitmaps_png/png/zoom_in_horizontally_24.png new file mode 100644 index 0000000000..df58ddc027 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_in_horizontally_24.png differ diff --git a/resources/bitmaps_png/png/zoom_in_horizontally_32.png b/resources/bitmaps_png/png/zoom_in_horizontally_32.png new file mode 100644 index 0000000000..529a7a0d60 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_in_horizontally_32.png differ diff --git a/resources/bitmaps_png/png/zoom_in_horizontally_48.png b/resources/bitmaps_png/png/zoom_in_horizontally_48.png new file mode 100644 index 0000000000..8221f8e489 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_in_horizontally_48.png differ diff --git a/resources/bitmaps_png/png/zoom_in_horizontally_64.png b/resources/bitmaps_png/png/zoom_in_horizontally_64.png new file mode 100644 index 0000000000..a97206b518 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_in_horizontally_64.png differ diff --git a/resources/bitmaps_png/png/zoom_in_horizontally_dark_16.png b/resources/bitmaps_png/png/zoom_in_horizontally_dark_16.png new file mode 100644 index 0000000000..c44f8b2d15 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_in_horizontally_dark_16.png differ diff --git a/resources/bitmaps_png/png/zoom_in_horizontally_dark_24.png b/resources/bitmaps_png/png/zoom_in_horizontally_dark_24.png new file mode 100644 index 0000000000..ccbe647d4f Binary files /dev/null and b/resources/bitmaps_png/png/zoom_in_horizontally_dark_24.png differ diff --git a/resources/bitmaps_png/png/zoom_in_horizontally_dark_32.png b/resources/bitmaps_png/png/zoom_in_horizontally_dark_32.png new file mode 100644 index 0000000000..234a555fa6 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_in_horizontally_dark_32.png differ diff --git a/resources/bitmaps_png/png/zoom_in_horizontally_dark_48.png b/resources/bitmaps_png/png/zoom_in_horizontally_dark_48.png new file mode 100644 index 0000000000..1d50790eb4 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_in_horizontally_dark_48.png differ diff --git a/resources/bitmaps_png/png/zoom_in_horizontally_dark_64.png b/resources/bitmaps_png/png/zoom_in_horizontally_dark_64.png new file mode 100644 index 0000000000..f8aa064ab6 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_in_horizontally_dark_64.png differ diff --git a/resources/bitmaps_png/png/zoom_in_vertically_16.png b/resources/bitmaps_png/png/zoom_in_vertically_16.png new file mode 100644 index 0000000000..63b5fd8822 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_in_vertically_16.png differ diff --git a/resources/bitmaps_png/png/zoom_in_vertically_24.png b/resources/bitmaps_png/png/zoom_in_vertically_24.png new file mode 100644 index 0000000000..f6b57256e8 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_in_vertically_24.png differ diff --git a/resources/bitmaps_png/png/zoom_in_vertically_32.png b/resources/bitmaps_png/png/zoom_in_vertically_32.png new file mode 100644 index 0000000000..336db9af1f Binary files /dev/null and b/resources/bitmaps_png/png/zoom_in_vertically_32.png differ diff --git a/resources/bitmaps_png/png/zoom_in_vertically_48.png b/resources/bitmaps_png/png/zoom_in_vertically_48.png new file mode 100644 index 0000000000..685f44cf1d Binary files /dev/null and b/resources/bitmaps_png/png/zoom_in_vertically_48.png differ diff --git a/resources/bitmaps_png/png/zoom_in_vertically_64.png b/resources/bitmaps_png/png/zoom_in_vertically_64.png new file mode 100644 index 0000000000..9d7b02c1e3 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_in_vertically_64.png differ diff --git a/resources/bitmaps_png/png/zoom_in_vertically_dark_16.png b/resources/bitmaps_png/png/zoom_in_vertically_dark_16.png new file mode 100644 index 0000000000..8e9305f5cf Binary files /dev/null and b/resources/bitmaps_png/png/zoom_in_vertically_dark_16.png differ diff --git a/resources/bitmaps_png/png/zoom_in_vertically_dark_24.png b/resources/bitmaps_png/png/zoom_in_vertically_dark_24.png new file mode 100644 index 0000000000..1b566ccb28 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_in_vertically_dark_24.png differ diff --git a/resources/bitmaps_png/png/zoom_in_vertically_dark_32.png b/resources/bitmaps_png/png/zoom_in_vertically_dark_32.png new file mode 100644 index 0000000000..735a479896 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_in_vertically_dark_32.png differ diff --git a/resources/bitmaps_png/png/zoom_in_vertically_dark_48.png b/resources/bitmaps_png/png/zoom_in_vertically_dark_48.png new file mode 100644 index 0000000000..6e42761042 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_in_vertically_dark_48.png differ diff --git a/resources/bitmaps_png/png/zoom_in_vertically_dark_64.png b/resources/bitmaps_png/png/zoom_in_vertically_dark_64.png new file mode 100644 index 0000000000..9640242649 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_in_vertically_dark_64.png differ diff --git a/resources/bitmaps_png/png/zoom_out_horizontally_16.png b/resources/bitmaps_png/png/zoom_out_horizontally_16.png new file mode 100644 index 0000000000..5b9ad0a0d1 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_out_horizontally_16.png differ diff --git a/resources/bitmaps_png/png/zoom_out_horizontally_24.png b/resources/bitmaps_png/png/zoom_out_horizontally_24.png new file mode 100644 index 0000000000..eb37664a31 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_out_horizontally_24.png differ diff --git a/resources/bitmaps_png/png/zoom_out_horizontally_32.png b/resources/bitmaps_png/png/zoom_out_horizontally_32.png new file mode 100644 index 0000000000..d39e9d2dab Binary files /dev/null and b/resources/bitmaps_png/png/zoom_out_horizontally_32.png differ diff --git a/resources/bitmaps_png/png/zoom_out_horizontally_48.png b/resources/bitmaps_png/png/zoom_out_horizontally_48.png new file mode 100644 index 0000000000..7db4e660e6 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_out_horizontally_48.png differ diff --git a/resources/bitmaps_png/png/zoom_out_horizontally_64.png b/resources/bitmaps_png/png/zoom_out_horizontally_64.png new file mode 100644 index 0000000000..7703932251 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_out_horizontally_64.png differ diff --git a/resources/bitmaps_png/png/zoom_out_horizontally_dark_16.png b/resources/bitmaps_png/png/zoom_out_horizontally_dark_16.png new file mode 100644 index 0000000000..d3783002f3 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_out_horizontally_dark_16.png differ diff --git a/resources/bitmaps_png/png/zoom_out_horizontally_dark_24.png b/resources/bitmaps_png/png/zoom_out_horizontally_dark_24.png new file mode 100644 index 0000000000..da7369b1f9 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_out_horizontally_dark_24.png differ diff --git a/resources/bitmaps_png/png/zoom_out_horizontally_dark_32.png b/resources/bitmaps_png/png/zoom_out_horizontally_dark_32.png new file mode 100644 index 0000000000..ea2a6a0cf4 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_out_horizontally_dark_32.png differ diff --git a/resources/bitmaps_png/png/zoom_out_horizontally_dark_48.png b/resources/bitmaps_png/png/zoom_out_horizontally_dark_48.png new file mode 100644 index 0000000000..ab734c968f Binary files /dev/null and b/resources/bitmaps_png/png/zoom_out_horizontally_dark_48.png differ diff --git a/resources/bitmaps_png/png/zoom_out_horizontally_dark_64.png b/resources/bitmaps_png/png/zoom_out_horizontally_dark_64.png new file mode 100644 index 0000000000..3c910fb464 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_out_horizontally_dark_64.png differ diff --git a/resources/bitmaps_png/png/zoom_out_vertically_16.png b/resources/bitmaps_png/png/zoom_out_vertically_16.png new file mode 100644 index 0000000000..464f9769eb Binary files /dev/null and b/resources/bitmaps_png/png/zoom_out_vertically_16.png differ diff --git a/resources/bitmaps_png/png/zoom_out_vertically_24.png b/resources/bitmaps_png/png/zoom_out_vertically_24.png new file mode 100644 index 0000000000..cac80014e3 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_out_vertically_24.png differ diff --git a/resources/bitmaps_png/png/zoom_out_vertically_32.png b/resources/bitmaps_png/png/zoom_out_vertically_32.png new file mode 100644 index 0000000000..0e3dbb7beb Binary files /dev/null and b/resources/bitmaps_png/png/zoom_out_vertically_32.png differ diff --git a/resources/bitmaps_png/png/zoom_out_vertically_48.png b/resources/bitmaps_png/png/zoom_out_vertically_48.png new file mode 100644 index 0000000000..a05151e4d2 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_out_vertically_48.png differ diff --git a/resources/bitmaps_png/png/zoom_out_vertically_64.png b/resources/bitmaps_png/png/zoom_out_vertically_64.png new file mode 100644 index 0000000000..eb2bf2abcd Binary files /dev/null and b/resources/bitmaps_png/png/zoom_out_vertically_64.png differ diff --git a/resources/bitmaps_png/png/zoom_out_vertically_dark_16.png b/resources/bitmaps_png/png/zoom_out_vertically_dark_16.png new file mode 100644 index 0000000000..ad15715f5c Binary files /dev/null and b/resources/bitmaps_png/png/zoom_out_vertically_dark_16.png differ diff --git a/resources/bitmaps_png/png/zoom_out_vertically_dark_24.png b/resources/bitmaps_png/png/zoom_out_vertically_dark_24.png new file mode 100644 index 0000000000..96410f211a Binary files /dev/null and b/resources/bitmaps_png/png/zoom_out_vertically_dark_24.png differ diff --git a/resources/bitmaps_png/png/zoom_out_vertically_dark_32.png b/resources/bitmaps_png/png/zoom_out_vertically_dark_32.png new file mode 100644 index 0000000000..a061bceefd Binary files /dev/null and b/resources/bitmaps_png/png/zoom_out_vertically_dark_32.png differ diff --git a/resources/bitmaps_png/png/zoom_out_vertically_dark_48.png b/resources/bitmaps_png/png/zoom_out_vertically_dark_48.png new file mode 100644 index 0000000000..600f3d567f Binary files /dev/null and b/resources/bitmaps_png/png/zoom_out_vertically_dark_48.png differ diff --git a/resources/bitmaps_png/png/zoom_out_vertically_dark_64.png b/resources/bitmaps_png/png/zoom_out_vertically_dark_64.png new file mode 100644 index 0000000000..a8d20325b6 Binary files /dev/null and b/resources/bitmaps_png/png/zoom_out_vertically_dark_64.png differ diff --git a/resources/bitmaps_png/sources/dark/zoom_in_horizontally.svg b/resources/bitmaps_png/sources/dark/zoom_in_horizontally.svg new file mode 100644 index 0000000000..e6eb885982 --- /dev/null +++ b/resources/bitmaps_png/sources/dark/zoom_in_horizontally.svg @@ -0,0 +1,122 @@ + + + + + + + + + + image/svg+xml + + zoom_in + + + + + + + + + + + + + + + zoom_in + + + + + + + diff --git a/resources/bitmaps_png/sources/dark/zoom_in_vertically.svg b/resources/bitmaps_png/sources/dark/zoom_in_vertically.svg new file mode 100644 index 0000000000..de6e48affd --- /dev/null +++ b/resources/bitmaps_png/sources/dark/zoom_in_vertically.svg @@ -0,0 +1,122 @@ + + + + + + + + + + image/svg+xml + + zoom_in + + + + + + + + + + + + + + + zoom_in + + + + + + + diff --git a/resources/bitmaps_png/sources/dark/zoom_out_horizontally.svg b/resources/bitmaps_png/sources/dark/zoom_out_horizontally.svg new file mode 100644 index 0000000000..a8a667e6a9 --- /dev/null +++ b/resources/bitmaps_png/sources/dark/zoom_out_horizontally.svg @@ -0,0 +1,114 @@ + + + + + + + + + + image/svg+xml + + zoom_in + + + + + + + + + + + + + + + zoom_in + + + + + + diff --git a/resources/bitmaps_png/sources/dark/zoom_out_vertically.svg b/resources/bitmaps_png/sources/dark/zoom_out_vertically.svg new file mode 100644 index 0000000000..b2e901c37f --- /dev/null +++ b/resources/bitmaps_png/sources/dark/zoom_out_vertically.svg @@ -0,0 +1,114 @@ + + + + + + + + + + image/svg+xml + + zoom_in + + + + + + + + + + + + + + + zoom_in + + + + + + diff --git a/resources/bitmaps_png/sources/light/zoom_in_horizontally.svg b/resources/bitmaps_png/sources/light/zoom_in_horizontally.svg new file mode 100644 index 0000000000..48476a11ef --- /dev/null +++ b/resources/bitmaps_png/sources/light/zoom_in_horizontally.svg @@ -0,0 +1,122 @@ + + + + + + + + + + image/svg+xml + + zoom_in + + + + + + + + + + + + + + + zoom_in + + + + + + + diff --git a/resources/bitmaps_png/sources/light/zoom_in_vertically.svg b/resources/bitmaps_png/sources/light/zoom_in_vertically.svg new file mode 100644 index 0000000000..73d63ad31f --- /dev/null +++ b/resources/bitmaps_png/sources/light/zoom_in_vertically.svg @@ -0,0 +1,122 @@ + + + + + + + + + + image/svg+xml + + zoom_in + + + + + + + + + + + + + + + zoom_in + + + + + + + diff --git a/resources/bitmaps_png/sources/light/zoom_out_horizontally.svg b/resources/bitmaps_png/sources/light/zoom_out_horizontally.svg new file mode 100644 index 0000000000..30a0a5a52f --- /dev/null +++ b/resources/bitmaps_png/sources/light/zoom_out_horizontally.svg @@ -0,0 +1,114 @@ + + + + + + + + + + image/svg+xml + + zoom_in + + + + + + + + + + + + + + + zoom_in + + + + + + diff --git a/resources/bitmaps_png/sources/light/zoom_out_vertically.svg b/resources/bitmaps_png/sources/light/zoom_out_vertically.svg new file mode 100644 index 0000000000..8021dd0d0f --- /dev/null +++ b/resources/bitmaps_png/sources/light/zoom_out_vertically.svg @@ -0,0 +1,114 @@ + + + + + + + + + + image/svg+xml + + zoom_in + + + + + + + + + + + + + + + zoom_in + + + + + +