You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							746 lines
						
					
					
						
							22 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							746 lines
						
					
					
						
							22 KiB
						
					
					
				| /* | |
|  * This program source code file is part of KiCad, a free EDA CAD application. | |
|  * | |
|  * Copyright (C) 2014-2016 CERN | |
|  * Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors. | |
|  * @author Maciej Suminski <maciej.suminski@cern.ch> | |
|  * | |
|  * 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 2 | |
|  * 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: | |
|  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html | |
|  * or you may search the http://www.gnu.org website for the version 2 license, | |
|  * or you may write to the Free Software Foundation, Inc., | |
|  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA | |
|  */ | |
| 
 | |
| #include <base_screen.h> | |
| #include <base_units.h> | |
| #include <gal/painter.h> | |
| #include <bitmaps.h> | |
| #include <class_draw_panel_gal.h> | |
| #include <dialogs/dialog_configure_paths.h> | |
| #include <dialogs/dialog_unit_entry.h> | |
| #include <eda_draw_frame.h> | |
| #include <gal/graphics_abstraction_layer.h> | |
| #include <id.h> | |
| #include <math/vector2wx.h> | |
| #include <core/kicad_algo.h> | |
| #include <kiface_base.h> | |
| #include <settings/app_settings.h> | |
| #include <tool/actions.h> | |
| #include <tool/common_tools.h> | |
| #include <tool/tool_manager.h> | |
| #include <view/view.h> | |
| #include <view/view_controls.h> | |
| #include "macros.h" | |
|  | |
| 
 | |
| COMMON_TOOLS::COMMON_TOOLS() : | |
|     TOOL_INTERACTIVE( "common.Control" ), | |
|     m_frame( nullptr ), | |
|     m_imperialUnit( EDA_UNITS::INCHES ), | |
|     m_metricUnit( EDA_UNITS::MILLIMETRES ) | |
| { | |
| } | |
| 
 | |
| void COMMON_TOOLS::Reset( RESET_REASON aReason ) | |
| { | |
|     m_frame = getEditFrame<EDA_DRAW_FRAME>(); | |
| 
 | |
|     GRID_SETTINGS& settings = m_toolMgr->GetSettings()->m_Window.grid; | |
|     EDA_IU_SCALE   scale = m_frame->GetIuScale(); | |
| 
 | |
|     m_grids.clear(); | |
| 
 | |
|     for( GRID& gridDef : settings.grids ) | |
|     { | |
|         double gridSizeX = EDA_UNIT_UTILS::UI::DoubleValueFromString( scale, EDA_UNITS::MILLIMETRES, | |
|                                                                       gridDef.x ); | |
|         double gridSizeY = EDA_UNIT_UTILS::UI::DoubleValueFromString( scale, EDA_UNITS::MILLIMETRES, | |
|                                                                       gridDef.y ); | |
| 
 | |
|         m_grids.emplace_back( KiROUND<double, int>( gridSizeX ), | |
|                               KiROUND<double, int>( gridSizeY ) ); | |
|     } | |
| 
 | |
|     OnGridChanged( false ); | |
| } | |
| 
 | |
| 
 | |
| void COMMON_TOOLS::SetLastUnits( EDA_UNITS aUnit ) | |
| { | |
|     if( EDA_UNIT_UTILS::IsImperialUnit( aUnit ) ) | |
|         m_imperialUnit = aUnit; | |
|     else if( EDA_UNIT_UTILS::IsMetricUnit( aUnit ) ) | |
|         m_metricUnit = aUnit; | |
|     else | |
|         wxASSERT_MSG( false, wxS( "Invalid unit" ) ); | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::SelectionTool( const TOOL_EVENT& aEvent ) | |
| { | |
|     // Since selection tools are run permanently underneath the toolStack, this is really | |
|     // just a cancel of whatever other tools might be running. | |
|  | |
|     m_toolMgr->ProcessEvent( TOOL_EVENT( TC_COMMAND, TA_CANCEL_TOOL ) ); | |
|     return 0; | |
| } | |
| 
 | |
| 
 | |
| // Cursor control | |
| int COMMON_TOOLS::CursorControl( const TOOL_EVENT& aEvent ) | |
| { | |
|     ACTIONS::CURSOR_EVENT_TYPE type = aEvent.Parameter<ACTIONS::CURSOR_EVENT_TYPE>(); | |
| 
 | |
|     bool     mirroredX = getView()->IsMirroredX(); | |
|     VECTOR2D cursor = getViewControls()->GetRawCursorPosition( false ); | |
|     VECTOR2D gridSize = getView()->GetGAL()->GetGridSize(); | |
| 
 | |
|     switch( type ) | |
|     { | |
|     case ACTIONS::CURSOR_UP_FAST: | |
|         gridSize *= 10; | |
|         KI_FALLTHROUGH; | |
|     case ACTIONS::CURSOR_UP: | |
|         cursor -= VECTOR2D( 0, gridSize.y ); | |
|         break; | |
| 
 | |
|     case ACTIONS::CURSOR_DOWN_FAST: | |
|         gridSize *= 10; | |
|         KI_FALLTHROUGH; | |
|     case ACTIONS::CURSOR_DOWN: | |
|         cursor += VECTOR2D( 0, gridSize.y ); | |
|         break; | |
| 
 | |
|     case ACTIONS::CURSOR_LEFT_FAST: | |
|         gridSize *= 10; | |
|         KI_FALLTHROUGH; | |
|     case ACTIONS::CURSOR_LEFT: | |
|         cursor -= VECTOR2D( mirroredX ? -gridSize.x : gridSize.x, 0 ); | |
|         break; | |
| 
 | |
|     case ACTIONS::CURSOR_RIGHT_FAST: | |
|         gridSize *= 10; | |
|         KI_FALLTHROUGH; | |
|     case ACTIONS::CURSOR_RIGHT: | |
|         cursor += VECTOR2D( mirroredX ? -gridSize.x : gridSize.x, 0 ); | |
|         break; | |
| 
 | |
|     case ACTIONS::CURSOR_CLICK:              // fall through | |
|     case ACTIONS::CURSOR_DBL_CLICK: | |
|     case ACTIONS::CURSOR_RIGHT_CLICK: | |
|     { | |
|         TOOL_ACTIONS       action = TA_MOUSE_CLICK; | |
|         TOOL_MOUSE_BUTTONS button = BUT_LEFT; | |
|         int                modifiers = 0; | |
| 
 | |
|         modifiers |= wxGetKeyState( WXK_SHIFT ) ? MD_SHIFT : 0; | |
|         modifiers |= wxGetKeyState( WXK_CONTROL ) ? MD_CTRL : 0; | |
|         modifiers |= wxGetKeyState( WXK_ALT ) ? MD_ALT : 0; | |
| 
 | |
|         if( type == ACTIONS::CURSOR_DBL_CLICK ) | |
|             action = TA_MOUSE_DBLCLICK; | |
|         else if( type == ACTIONS::CURSOR_RIGHT_CLICK ) | |
|             button = BUT_RIGHT; | |
| 
 | |
|         TOOL_EVENT evt( TC_MOUSE, action, static_cast<int>( button | modifiers ) ); | |
|         evt.SetParameter( type ); | |
|         evt.SetMousePosition( getViewControls()->GetMousePosition() ); | |
|         m_toolMgr->ProcessEvent( evt ); | |
| 
 | |
|         return 0; | |
|     } | |
|     default: | |
|         wxFAIL_MSG( wxS( "CursorControl(): unexpected request" ) ); | |
|     } | |
| 
 | |
|     getViewControls()->SetCursorPosition( cursor, true, true, type ); | |
|     m_toolMgr->PostAction( ACTIONS::refreshPreview ); | |
| 
 | |
|     return 0; | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::PanControl( const TOOL_EVENT& aEvent ) | |
| { | |
|     ACTIONS::CURSOR_EVENT_TYPE type = aEvent.Parameter<ACTIONS::CURSOR_EVENT_TYPE>(); | |
|     KIGFX::VIEW* view = getView(); | |
|     VECTOR2D center = view->GetCenter(); | |
|     VECTOR2D gridSize = getView()->GetGAL()->GetGridSize() * 10; | |
|     bool mirroredX = view->IsMirroredX(); | |
| 
 | |
|     switch( type ) | |
|     { | |
|     case ACTIONS::CURSOR_UP: | |
|         center -= VECTOR2D( 0, gridSize.y ); | |
|         break; | |
| 
 | |
|     case ACTIONS::CURSOR_DOWN: | |
|         center += VECTOR2D( 0, gridSize.y ); | |
|         break; | |
| 
 | |
|     case ACTIONS::CURSOR_LEFT: | |
|         center -= VECTOR2D( mirroredX ? -gridSize.x : gridSize.x, 0 ); | |
|         break; | |
| 
 | |
|     case ACTIONS::CURSOR_RIGHT: | |
|         center += VECTOR2D( mirroredX ? -gridSize.x : gridSize.x, 0 ); | |
|         break; | |
| 
 | |
|     default: | |
|         wxFAIL; | |
|         break; | |
|     } | |
| 
 | |
|     view->SetCenter( center ); | |
| 
 | |
|     return 0; | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::ZoomRedraw( const TOOL_EVENT& aEvent ) | |
| { | |
|     m_frame->HardRedraw(); | |
|     return 0; | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::ZoomInOut( const TOOL_EVENT& aEvent ) | |
| { | |
|     bool direction = aEvent.IsAction( &ACTIONS::zoomIn ); | |
|     return doZoomInOut( direction, true ); | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::ZoomInOutCenter( const TOOL_EVENT& aEvent ) | |
| { | |
|     bool direction = aEvent.IsAction( &ACTIONS::zoomInCenter ); | |
|     return doZoomInOut( direction, false ); | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::doZoomInOut( bool aDirection, bool aCenterOnCursor ) | |
| { | |
|     double zoom = getView()->GetGAL()->GetZoomFactor(); | |
| 
 | |
|     // Step must be AT LEAST 1.3 | |
|     if( aDirection ) | |
|         zoom *= 1.3; | |
|     else | |
|         zoom /= 1.3; | |
| 
 | |
|     // Now look for the next closest menu step | |
|     std::vector<double>& zoomList = m_toolMgr->GetSettings()->m_Window.zoom_factors; | |
|     int idx; | |
| 
 | |
|     if( aDirection ) | |
|     { | |
|         for( idx = 0; idx < int( zoomList.size() ); ++idx ) | |
|         { | |
|             if( zoomList[idx] >= zoom ) | |
|                 break; | |
|         } | |
| 
 | |
|         if( idx >= int( zoomList.size() ) ) | |
|             idx = (int) zoomList.size() - 1;        // if we ran off the end then peg to the end | |
|     } | |
|     else | |
|     { | |
|         for( idx = int( zoomList.size() ) - 1; idx >= 0; --idx ) | |
|         { | |
|             if( zoomList[idx] <= zoom ) | |
|                 break; | |
|         } | |
| 
 | |
|         if( idx < 0 ) | |
|             idx = 0;        // if we ran off the end then peg to the end | |
|     } | |
| 
 | |
|     // Note: idx == 0 is Auto; idx == 1 is first entry in zoomList | |
|     return doZoomToPreset( idx + 1, aCenterOnCursor ); | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::ZoomCenter( const TOOL_EVENT& aEvent ) | |
| { | |
|     KIGFX::VIEW_CONTROLS* ctls = getViewControls(); | |
| 
 | |
|     ctls->CenterOnCursor(); | |
| 
 | |
|     return 0; | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::ZoomFitScreen( const TOOL_EVENT& aEvent ) | |
| { | |
|     return doZoomFit( ZOOM_FIT_ALL ); | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::ZoomFitObjects( const TOOL_EVENT& aEvent ) | |
| { | |
|     return doZoomFit( ZOOM_FIT_OBJECTS ); | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::doZoomFit( ZOOM_FIT_TYPE_T aFitType ) | |
| { | |
|     KIGFX::VIEW*        view   = getView(); | |
|     EDA_DRAW_PANEL_GAL* canvas = m_frame->GetCanvas(); | |
|     EDA_DRAW_FRAME*     frame  = getEditFrame<EDA_DRAW_FRAME>(); | |
| 
 | |
|     BOX2I    bBox = frame->GetDocumentExtents(); | |
|     BOX2I    defaultBox = canvas->GetDefaultViewBBox(); | |
| 
 | |
|     view->SetScale( 1.0 );  // The best scale will be determined later, but this initial | |
|                             // value ensures all view parameters are up to date (especially | |
|                             // at init time) | |
|     VECTOR2D screenSize = view->ToWorld( ToVECTOR2I( canvas->GetClientSize() ), false ); | |
| 
 | |
|     // Currently "Zoom to Objects" is only supported in Eeschema & Pcbnew.  Support for other | |
|     // programs in the suite can be added as needed. | |
|  | |
|     if( aFitType == ZOOM_FIT_ALL ) | |
|     { | |
|         if( frame->IsType( FRAME_PCB_EDITOR ) ) | |
|             bBox = m_frame->GetDocumentExtents( false ); | |
|     } | |
| 
 | |
|     if( aFitType == ZOOM_FIT_OBJECTS ) | |
|     { | |
|         if( frame->IsType( FRAME_SCH ) ) | |
|             bBox = m_frame->GetDocumentExtents( false ); | |
|         else | |
|             aFitType = ZOOM_FIT_ALL; // Just do a "Zoom to Fit" for unsupported editors | |
|     } | |
| 
 | |
|     // If the screen is empty then use the default view bbox | |
|  | |
|     if( bBox.GetWidth() == 0 || bBox.GetHeight() == 0 ) | |
|         bBox = defaultBox; | |
| 
 | |
|     VECTOR2D vsize = bBox.GetSize(); | |
|     double scale = view->GetScale() / std::max( fabs( vsize.x / screenSize.x ), | |
|                                                 fabs( vsize.y / screenSize.y ) ); | |
| 
 | |
|     // if the scale isn't finite (most likely due to an empty canvas) | |
|     // simply just make sure we are centered and quit out of trying to zoom to fit | |
|     if( !std::isfinite( scale ) ) | |
|     { | |
|         view->SetCenter( VECTOR2D( 0, 0 ) ); | |
|         canvas->Refresh(); | |
|         return 0; | |
|     } | |
| 
 | |
|     // Reserve enough margin to limit the amount of the view that might be obscured behind the | |
|     // infobar. | |
|     double margin_scale_factor = 1.04; | |
| 
 | |
|     if( canvas->GetClientSize().y < 768 ) | |
|         margin_scale_factor = 1.10; | |
| 
 | |
|     if( aFitType == ZOOM_FIT_ALL ) | |
|     { | |
|         // Leave a bigger margin for library editors & viewers | |
|  | |
|         if( frame->IsType( FRAME_FOOTPRINT_VIEWER ) | |
|                 || frame->IsType( FRAME_SCH_VIEWER ) ) | |
|         { | |
|             margin_scale_factor = 1.30; | |
|         } | |
|         else if( frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) | |
|                 || frame->IsType( FRAME_FOOTPRINT_EDITOR ) ) | |
|         { | |
|             margin_scale_factor = 1.48; | |
|         } | |
|     } | |
| 
 | |
|     view->SetScale( scale / margin_scale_factor ); | |
|     view->SetCenter( bBox.Centre() ); | |
|     canvas->Refresh(); | |
| 
 | |
|     return 0; | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::CenterContents( const TOOL_EVENT& aEvent ) | |
| { | |
|     EDA_DRAW_PANEL_GAL* canvas = m_frame->GetCanvas(); | |
|     BOX2I bBox = getModel<EDA_ITEM>()->ViewBBox(); | |
| 
 | |
|     if( bBox.GetWidth() == 0 || bBox.GetHeight() == 0 ) | |
|         bBox = canvas->GetDefaultViewBBox(); | |
| 
 | |
|     getView()->SetCenter( bBox.Centre() ); | |
| 
 | |
|     // Take scrollbars into account | |
|     VECTOR2D scrollbarSize = VECTOR2D( ToVECTOR2D( canvas->GetSize() - canvas->GetClientSize() ) ); | |
|     VECTOR2D worldScrollbarSize = getView()->ToWorld( scrollbarSize, false ); | |
|     getView()->SetCenter( getView()->GetCenter() + worldScrollbarSize / 2.0 ); | |
|     canvas->Refresh(); | |
| 
 | |
|     return 0; | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::ZoomPreset( const TOOL_EVENT& aEvent ) | |
| { | |
|     int idx = aEvent.Parameter<int>(); | |
|     return doZoomToPreset( idx, false ); | |
| } | |
| 
 | |
| 
 | |
| // Note: idx == 0 is Auto; idx == 1 is first entry in zoomList | |
| int COMMON_TOOLS::doZoomToPreset( int idx, bool aCenterOnCursor ) | |
| { | |
|     std::vector<double>& zoomList = m_toolMgr->GetSettings()->m_Window.zoom_factors; | |
| 
 | |
|     if( idx == 0 )      // Zoom Auto | |
|     { | |
|         TOOL_EVENT dummy; | |
|         return ZoomFitScreen( dummy ); | |
|     } | |
|     else | |
|     { | |
|         idx--; | |
|     } | |
| 
 | |
|     double scale = zoomList[idx]; | |
| 
 | |
|     if( aCenterOnCursor ) | |
|     { | |
|         getView()->SetScale( scale, getViewControls()->GetCursorPosition() ); | |
| 
 | |
|         if( getViewControls()->IsCursorWarpingEnabled() ) | |
|             getViewControls()->CenterOnCursor(); | |
|     } | |
|     else | |
|     { | |
|         getView()->SetScale( scale ); | |
|     } | |
| 
 | |
|     m_frame->GetCanvas()->Refresh(); | |
| 
 | |
|     return 0; | |
| } | |
| 
 | |
| 
 | |
| // Grid control | |
| int COMMON_TOOLS::GridNext( const TOOL_EVENT& aEvent ) | |
| { | |
|     int& currentGrid = m_toolMgr->GetSettings()->m_Window.grid.last_size_idx; | |
| 
 | |
|     currentGrid++; | |
| 
 | |
|     if( currentGrid >= int( m_grids.size() ) ) | |
|         currentGrid = 0; | |
| 
 | |
|     return OnGridChanged( true ); | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::GridPrev( const TOOL_EVENT& aEvent ) | |
| { | |
|     int& currentGrid = m_toolMgr->GetSettings()->m_Window.grid.last_size_idx; | |
| 
 | |
|     currentGrid--; | |
| 
 | |
|     if( currentGrid < 0 ) | |
|         currentGrid = (int) m_grids.size() - 1; | |
| 
 | |
|     return OnGridChanged( true ); | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::GridPreset( const TOOL_EVENT& aEvent ) | |
| { | |
|     return GridPreset( aEvent.Parameter<int>(), false ); | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::GridPreset( int idx, bool aFromHotkey ) | |
| { | |
|     int& currentGrid = m_toolMgr->GetSettings()->m_Window.grid.last_size_idx; | |
| 
 | |
|     currentGrid = alg::clamp( 0, idx, (int) m_grids.size() - 1 ); | |
| 
 | |
|     return OnGridChanged( aFromHotkey ); | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::OnGridChanged( bool aFromHotkey ) | |
| { | |
|     int& currentGrid = m_toolMgr->GetSettings()->m_Window.grid.last_size_idx; | |
| 
 | |
|     currentGrid = std::max( 0, std::min( currentGrid, static_cast<int>( m_grids.size() ) - 1 ) ); | |
| 
 | |
|     // Update the combobox (if any) | |
|     wxUpdateUIEvent dummy; | |
|     m_frame->OnUpdateSelectGrid( dummy ); | |
| 
 | |
|     // Update GAL canvas from screen | |
|     getView()->GetGAL()->SetGridSize( m_grids[ currentGrid ] ); | |
|     getView()->GetGAL()->SetGridVisibility( m_toolMgr->GetSettings()->m_Window.grid.show ); | |
|     getView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED ); | |
| 
 | |
|     // Put cursor on new grid | |
|     VECTOR2D gridCursor = getViewControls()->GetCursorPosition( true ); | |
|     getViewControls()->SetCrossHairCursorPosition( gridCursor, false ); | |
| 
 | |
|     // Show feedback | |
|     if( aFromHotkey ) | |
|         m_toolMgr->PostEvent( EVENTS::GridChangedByKeyEvent ); | |
| 
 | |
|     return 0; | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::GridFast1( const TOOL_EVENT& aEvent ) | |
| { | |
|     return GridPreset( m_frame->config()->m_Window.grid.fast_grid_1, true ); | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::GridFast2( const TOOL_EVENT& aEvent ) | |
| { | |
|     return GridPreset( m_frame->config()->m_Window.grid.fast_grid_2, true ); | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::GridFastCycle( const TOOL_EVENT& aEvent ) | |
| { | |
|     if( m_toolMgr->GetSettings()->m_Window.grid.last_size_idx | |
|         == m_frame->config()->m_Window.grid.fast_grid_1 ) | |
|     { | |
|         return GridPreset( m_frame->config()->m_Window.grid.fast_grid_2, true ); | |
|     } | |
| 
 | |
|     return GridPreset( m_frame->config()->m_Window.grid.fast_grid_1, true ); | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::ToggleGrid( const TOOL_EVENT& aEvent ) | |
| { | |
|     m_frame->SetGridVisibility( !m_frame->IsGridVisible() ); | |
|     return 0; | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::ToggleGridOverrides( const TOOL_EVENT& aEvent ) | |
| { | |
|     m_frame->SetGridOverrides( !m_frame->IsGridOverridden() ); | |
|     return 0; | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::GridProperties( const TOOL_EVENT& aEvent ) | |
| { | |
|     auto showGridPrefs = | |
|             [this]( wxString aParentName ) | |
|             { | |
|                 m_frame->CallAfter( | |
|                         [this, aParentName]() | |
|                         { | |
|                             m_frame->ShowPreferences( _( "Grids" ), aParentName ); | |
|                         } ); | |
|             }; | |
| 
 | |
|     switch( m_frame->GetFrameType() ) | |
|     { | |
|     case FRAME_SCH:               showGridPrefs( _( "Schematic Editor" ) );     break; | |
|     case FRAME_SCH_SYMBOL_EDITOR: showGridPrefs( _( "Symbol Editor" ) );        break; | |
|     case FRAME_PCB_EDITOR:        showGridPrefs( _( "PCB Editor" ) );           break; | |
|     case FRAME_FOOTPRINT_EDITOR:  showGridPrefs( _( "Footprint Editor" ) );     break; | |
|     case FRAME_PL_EDITOR:         showGridPrefs( _( "Drawing Sheet Editor" ) ); break; | |
|     default:                      wxFAIL_MSG( "Unknown frame: " + GetName() );  break; | |
|     } | |
| 
 | |
|     return 0; | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::GridOrigin( const TOOL_EVENT& aEvent ) | |
| { | |
|     VECTOR2I           origin = m_frame->GetGridOrigin(); | |
|     WX_PT_ENTRY_DIALOG dlg( m_frame, _( "Grid Origin" ), _( "X:" ), _( "Y:" ), origin ); | |
| 
 | |
|     if( dlg.ShowModal() == wxID_OK ) | |
|     { | |
|         m_frame->SetGridOrigin( dlg.GetValue() ); | |
| 
 | |
|         m_toolMgr->ResetTools( TOOL_BASE::REDRAW ); | |
|         m_toolMgr->RunAction( ACTIONS::gridSetOrigin, new VECTOR2D( m_frame->GetGridOrigin() ) ); | |
|         m_frame->GetCanvas()->ForceRefresh(); | |
|     } | |
| 
 | |
|     return 0; | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::SwitchUnits( const TOOL_EVENT& aEvent ) | |
| { | |
|     EDA_UNITS newUnit = aEvent.Parameter<EDA_UNITS>(); | |
| 
 | |
|     if( EDA_UNIT_UTILS::IsMetricUnit( newUnit ) ) | |
|         m_metricUnit = newUnit; | |
|     else if( EDA_UNIT_UTILS::IsImperialUnit( newUnit ) ) | |
|         m_imperialUnit = newUnit; | |
|     else | |
|         wxASSERT_MSG( false, wxS( "Invalid unit for the frame" ) ); | |
| 
 | |
|     m_frame->ChangeUserUnits( newUnit ); | |
|     return 0; | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::ToggleUnits( const TOOL_EVENT& aEvent ) | |
| { | |
|     m_frame->ChangeUserUnits( EDA_UNIT_UTILS::IsImperialUnit( m_frame->GetUserUnits() ) ? | |
|                                       m_metricUnit : | |
|                                       m_imperialUnit ); | |
|     return 0; | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::TogglePolarCoords( const TOOL_EVENT& aEvent ) | |
| { | |
|     m_frame->SetStatusText( wxEmptyString ); | |
|     m_frame->SetShowPolarCoords( !m_frame->GetShowPolarCoords() ); | |
|     m_frame->UpdateStatusBar(); | |
| 
 | |
|     return 0; | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::ResetLocalCoords( const TOOL_EVENT& aEvent ) | |
| { | |
|     auto vcSettings = m_toolMgr->GetCurrentToolVC(); | |
| 
 | |
|     // Use either the active tool forced cursor position or the general settings | |
|     if( vcSettings.m_forceCursorPosition ) | |
|         m_frame->GetScreen()->m_LocalOrigin = vcSettings.m_forcedPosition; | |
|     else | |
|         m_frame->GetScreen()->m_LocalOrigin = getViewControls()->GetCursorPosition(); | |
| 
 | |
|     m_frame->UpdateStatusBar(); | |
| 
 | |
|     return 0; | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::ToggleCursor( const TOOL_EVENT& aEvent ) | |
| { | |
|     auto& galOpts = m_frame->GetGalDisplayOptions(); | |
| 
 | |
|     galOpts.m_forceDisplayCursor = !galOpts.m_forceDisplayCursor; | |
|     galOpts.WriteConfig( m_toolMgr->GetSettings()->m_Window ); | |
|     galOpts.NotifyChanged(); | |
| 
 | |
|     return 0; | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::ToggleCursorStyle( const TOOL_EVENT& aEvent ) | |
| { | |
|     GAL_DISPLAY_OPTIONS_IMPL& galOpts = m_frame->GetGalDisplayOptions(); | |
| 
 | |
|     galOpts.m_fullscreenCursor = !galOpts.m_fullscreenCursor; | |
|     galOpts.WriteConfig( m_toolMgr->GetSettings()->m_Window ); | |
|     galOpts.NotifyChanged(); | |
| 
 | |
|     return 0; | |
| } | |
| 
 | |
| 
 | |
| int COMMON_TOOLS::ToggleBoundingBoxes( const TOOL_EVENT& aEvent ) | |
| { | |
|     EDA_DRAW_PANEL_GAL* canvas = m_frame->GetCanvas(); | |
| 
 | |
|     if( canvas ) | |
|     { | |
|         KIGFX::RENDER_SETTINGS* rs = canvas->GetView()->GetPainter()->GetSettings(); | |
| 
 | |
|         rs->SetDrawBoundingBoxes( !rs->GetDrawBoundingBoxes() ); | |
| 
 | |
|         canvas->GetView()->UpdateAllItems( KIGFX::ALL ); | |
|         canvas->ForceRefresh(); | |
|     } | |
| 
 | |
|     return 0; | |
| } | |
| 
 | |
| 
 | |
| void COMMON_TOOLS::setTransitions() | |
| { | |
|     Go( &COMMON_TOOLS::SelectionTool,       ACTIONS::selectionTool.MakeEvent() ); | |
| 
 | |
|     // Cursor control | |
|     Go( &COMMON_TOOLS::CursorControl,       ACTIONS::cursorUp.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::CursorControl,       ACTIONS::cursorDown.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::CursorControl,       ACTIONS::cursorLeft.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::CursorControl,       ACTIONS::cursorRight.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::CursorControl,       ACTIONS::cursorUpFast.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::CursorControl,       ACTIONS::cursorDownFast.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::CursorControl,       ACTIONS::cursorLeftFast.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::CursorControl,       ACTIONS::cursorRightFast.MakeEvent() ); | |
| 
 | |
|     Go( &COMMON_TOOLS::CursorControl,       ACTIONS::cursorClick.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::CursorControl,       ACTIONS::cursorDblClick.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::CursorControl,       ACTIONS::showContextMenu.MakeEvent() ); | |
| 
 | |
|     // Pan control | |
|     Go( &COMMON_TOOLS::PanControl,          ACTIONS::panUp.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::PanControl,          ACTIONS::panDown.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::PanControl,          ACTIONS::panLeft.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::PanControl,          ACTIONS::panRight.MakeEvent() ); | |
| 
 | |
|     // Zoom control | |
|     Go( &COMMON_TOOLS::ZoomRedraw,          ACTIONS::zoomRedraw.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::ZoomInOut,           ACTIONS::zoomIn.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::ZoomInOut,           ACTIONS::zoomOut.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::ZoomInOutCenter,     ACTIONS::zoomInCenter.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::ZoomInOutCenter,     ACTIONS::zoomOutCenter.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::ZoomCenter,          ACTIONS::zoomCenter.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::ZoomFitScreen,       ACTIONS::zoomFitScreen.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::ZoomFitObjects,      ACTIONS::zoomFitObjects.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::ZoomPreset,          ACTIONS::zoomPreset.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::CenterContents,      ACTIONS::centerContents.MakeEvent() ); | |
| 
 | |
|     // Grid control | |
|     Go( &COMMON_TOOLS::GridNext,            ACTIONS::gridNext.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::GridPrev,            ACTIONS::gridPrev.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::GridPreset,          ACTIONS::gridPreset.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::GridFast1,           ACTIONS::gridFast1.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::GridFast2,           ACTIONS::gridFast2.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::GridFastCycle,       ACTIONS::gridFastCycle.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::ToggleGrid,          ACTIONS::toggleGrid.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::ToggleGridOverrides, ACTIONS::toggleGridOverrides.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::GridProperties,      ACTIONS::gridProperties.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::GridOrigin,          ACTIONS::gridOrigin.MakeEvent() ); | |
| 
 | |
|     // Units and coordinates | |
|     Go( &COMMON_TOOLS::SwitchUnits,         ACTIONS::inchesUnits.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::SwitchUnits,         ACTIONS::milsUnits.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::SwitchUnits,         ACTIONS::millimetersUnits.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::ToggleUnits,         ACTIONS::toggleUnits.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::TogglePolarCoords,   ACTIONS::togglePolarCoords.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::ResetLocalCoords,    ACTIONS::resetLocalCoords.MakeEvent() ); | |
| 
 | |
|     // Misc | |
|     Go( &COMMON_TOOLS::ToggleCursor,        ACTIONS::toggleCursor.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::ToggleCursorStyle,   ACTIONS::toggleCursorStyle.MakeEvent() ); | |
|     Go( &COMMON_TOOLS::ToggleBoundingBoxes, ACTIONS::toggleBoundingBoxes.MakeEvent() ); | |
| } | |
| 
 | |
| 
 |