Switch to showing metric/imperial units in comboboxes and menus

This will always show 1 unit from each system, with the primary unit
being the current frame unit and the secondary unit being the
most recent unit used from the other system. These are saved in
the settings, so they are saved between runs.
This commit is contained in:
Ian McInerney 2020-10-05 20:26:33 +01:00
parent 9d3aca56bb
commit 43c14face0
20 changed files with 229 additions and 57 deletions

View File

@ -44,7 +44,7 @@ DIALOG_GRID_SETTINGS::DIALOG_GRID_SETTINGS( EDA_DRAW_FRAME* aParent ):
m_gridOriginY.SetCoordType( ORIGIN_TRANSFORMS::ABS_Y_COORD );
wxArrayString grids;
GRID_MENU::BuildChoiceList( &grids, m_parent->config(), GetUserUnits() != EDA_UNITS::INCHES );
GRID_MENU::BuildChoiceList( &grids, m_parent->config(), m_parent );
m_currentGridCtrl->Append( grids );
m_grid1Ctrl->Append( grids );
m_grid2Ctrl->Append( grids );

View File

@ -241,7 +241,7 @@ void EDA_DRAW_FRAME::UpdateGridSelectBox()
m_gridSelectBox->Clear();
wxArrayString gridsList;
GRID_MENU::BuildChoiceList( &gridsList, config(), GetUserUnits() != EDA_UNITS::INCHES );
GRID_MENU::BuildChoiceList( &gridsList, config(), this );
for( const wxString& grid : gridsList )
m_gridSelectBox->Append( grid );
@ -576,11 +576,25 @@ void EDA_DRAW_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
aCfg->m_FindReplace.replace_history.clear();
for( size_t i = 0; i < m_findStringHistoryList.GetCount() && i < FR_HISTORY_LIST_CNT; i++ )
{
aCfg->m_FindReplace.find_history.push_back( m_findStringHistoryList[ i ].ToStdString() );
}
for( size_t i = 0; i < m_replaceStringHistoryList.GetCount() && i < FR_HISTORY_LIST_CNT; i++ )
{
aCfg->m_FindReplace.replace_history.push_back(
m_replaceStringHistoryList[ i ].ToStdString() );
}
// Save the units used in this frame
if( m_toolManager )
{
if( COMMON_TOOLS* cmnTool = m_toolManager->GetTool<COMMON_TOOLS>() )
{
aCfg->m_System.last_imperial_units = static_cast<int>( cmnTool->GetLastImperialUnits() );
aCfg->m_System.last_metric_units = static_cast<int>( cmnTool->GetLastMetricUnits() );
}
}
}
@ -924,3 +938,49 @@ COLOR_SETTINGS* EDA_DRAW_FRAME::GetColorSettings()
return m_colorSettings;
}
void EDA_DRAW_FRAME::setupUnits( APP_SETTINGS_BASE* aCfg )
{
COMMON_TOOLS* cmnTool = m_toolManager->GetTool<COMMON_TOOLS>();
if( cmnTool )
{
// Tell the tool what the units used last session
cmnTool->SetLastUnits( static_cast<EDA_UNITS>( aCfg->m_System.last_imperial_units ) );
cmnTool->SetLastUnits( static_cast<EDA_UNITS>( aCfg->m_System.last_metric_units ) );
}
// Tell the tool what units the frame is currently using
switch( static_cast<EDA_UNITS>( aCfg->m_System.units ) )
{
default:
case EDA_UNITS::MILLIMETRES: m_toolManager->RunAction( ACTIONS::millimetersUnits ); break;
case EDA_UNITS::INCHES: m_toolManager->RunAction( ACTIONS::inchesUnits ); break;
case EDA_UNITS::MILS: m_toolManager->RunAction( ACTIONS::milsUnits ); break;
}
}
void EDA_DRAW_FRAME::GetUnitPair( EDA_UNITS& aPrimaryUnit, EDA_UNITS& aSecondaryUnits )
{
COMMON_TOOLS* cmnTool = m_toolManager->GetTool<COMMON_TOOLS>();
aPrimaryUnit = GetUserUnits();
aSecondaryUnits = EDA_UNITS::MILS;
if( IsImperialUnit( aPrimaryUnit ) )
{
if( cmnTool )
aSecondaryUnits = cmnTool->GetLastMetricUnits();
else
aSecondaryUnits = EDA_UNITS::MILLIMETRES;
}
else
{
if( cmnTool )
aSecondaryUnits = cmnTool->GetLastImperialUnits();
else
aSecondaryUnits = EDA_UNITS::MILS;
}
}

View File

@ -114,6 +114,12 @@ APP_SETTINGS_BASE::APP_SETTINGS_BASE( const std::string& aFilename, int aSchemaV
m_params.emplace_back( new PARAM<int>( "system.units",
&m_System.units, static_cast<int>( EDA_UNITS::MILLIMETRES ) ) );
m_params.emplace_back( new PARAM<int>( "system.last_metric_units",
&m_System.last_metric_units, static_cast<int>( EDA_UNITS::MILLIMETRES ) ) );
m_params.emplace_back( new PARAM<int>( "system.last_imperial_units",
&m_System.last_imperial_units, static_cast<int>( EDA_UNITS::INCHES ) ) );
m_params.emplace_back( new PARAM<wxString>( "appearance.color_theme",
&m_ColorTheme, "user" ) );

View File

@ -41,11 +41,17 @@
#include <view/view_controls.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>();
m_metricUnit = EDA_UNITS::MILLIMETRES;
m_imperialUnit = EDA_UNITS::INCHES;
m_frame = getEditFrame<EDA_DRAW_FRAME>();
GRID_SETTINGS& settings = m_toolMgr->GetSettings()->m_Window.grid;
@ -64,6 +70,17 @@ void COMMON_TOOLS::Reset( RESET_REASON aReason )
}
void COMMON_TOOLS::SetLastUnits( EDA_UNITS aUnit )
{
if( IsImperialUnit( aUnit ) )
m_imperialUnit = aUnit;
else if( IsMetricUnit( aUnit ) )
m_metricUnit = aUnit;
else
wxASSERT_MSG( false, "Invalid unit" );
}
int COMMON_TOOLS::SelectionTool( const TOOL_EVENT& aEvent )
{
// Since selection tools are run permanently underneath the toolStack, this is really

View File

@ -44,7 +44,7 @@ GRID_MENU::GRID_MENU( EDA_DRAW_FRAME* aParent ) :
wxArrayString gridsList;
int i = ID_POPUP_GRID_START;
BuildChoiceList( &gridsList, settings, IsMetricUnit( m_parent->GetUserUnits() ) );
BuildChoiceList( &gridsList, settings, m_parent );
for( const wxString& grid : gridsList )
Append( i++, grid, wxEmptyString, wxITEM_CHECK );
@ -65,7 +65,7 @@ void GRID_MENU::update()
unsigned int current = settings->m_Window.grid.last_size_idx;
wxArrayString gridsList;
BuildChoiceList( &gridsList, settings, m_parent->GetUserUnits() != EDA_UNITS::INCHES );
GRID_MENU::BuildChoiceList( &gridsList, settings, m_parent );
for( unsigned int i = 0; i < GetMenuItemCount(); ++i )
{
@ -76,39 +76,56 @@ void GRID_MENU::update()
}
}
wxString GRID_MENU::GridMenuUnits( EDA_UNITS aUnits, double aValue )
{
wxString text;
const wxChar* format;
void GRID_MENU::BuildChoiceList( wxArrayString* aGridsList, APP_SETTINGS_BASE* aCfg, bool mmFirst )
switch( aUnits )
{
default: wxASSERT_MSG( false, "Invalid unit" ); KI_FALLTHROUGH;
case EDA_UNITS::UNSCALED: format = wxT( "%.0f" ); break;
case EDA_UNITS::MILLIMETRES: format = wxT( "%.4f" ); break;
case EDA_UNITS::MILS: format = wxT( "%.2f" ); break;
case EDA_UNITS::INCHES: format = wxT( "%.4f" ); break;
}
text.Printf( format, To_User_Unit( aUnits, aValue ) );
text += " ";
text += GetAbbreviatedUnitsLabel( aUnits, EDA_DATA_TYPE::DISTANCE );
return text;
}
void GRID_MENU::BuildChoiceList( wxArrayString* aGridsList, APP_SETTINGS_BASE* aCfg,
EDA_DRAW_FRAME* aParent )
{
wxString msg;
EDA_UNITS primaryUnit;
EDA_UNITS secondaryUnit;
aParent->GetUnitPair( primaryUnit, secondaryUnit );
for( const wxString& gridSize : aCfg->m_Window.grid.sizes )
{
int val = (int) ValueFromString( EDA_UNITS::MILLIMETRES, gridSize );
double gridValueMils = To_User_Unit( EDA_UNITS::INCHES, val ) * 1000;
double gridValue_mm = To_User_Unit( EDA_UNITS::MILLIMETRES, val );
if( mmFirst )
msg.Printf( _( "Grid: %.4f mm (%.2f mils)" ), gridValue_mm, gridValueMils );
else
msg.Printf( _( "Grid: %.2f mils (%.4f mm)" ), gridValueMils, gridValue_mm );
msg.Printf( _( "Grid: %s (%s)" ), GRID_MENU::GridMenuUnits( primaryUnit, val ),
GRID_MENU::GridMenuUnits( secondaryUnit, val ) );
aGridsList->Add( msg );
}
if( !aCfg->m_Window.grid.user_grid_x.empty() )
{
int val = (int) ValueFromString( EDA_UNITS::INCHES, aCfg->m_Window.grid.user_grid_x );
double gridValueMils = To_User_Unit( EDA_UNITS::INCHES, val ) * 1000;
double gridValue_mm = To_User_Unit( EDA_UNITS::MILLIMETRES, val );
if( mmFirst )
msg.Printf( _( "User grid: %.4f mm (%.2f mils)" ), gridValue_mm, gridValueMils );
else
msg.Printf( _( "User grid: %.2f mils (%.4f mm)" ), gridValueMils, gridValue_mm );
msg.Printf( _( "User grid: %s (%s)" ), GRID_MENU::GridMenuUnits( primaryUnit, val ),
GRID_MENU::GridMenuUnits( secondaryUnit, val ) );
aGridsList->Add( msg );
}
}

View File

@ -151,6 +151,8 @@ DISPLAY_FOOTPRINTS_FRAME::DISPLAY_FOOTPRINTS_FRAME( KIWAY* aKiway, wxWindow* aPa
ActivateGalCanvas();
setupUnits( config() );
// Restore last zoom. (If auto-zooming we'll adjust when we load the footprint.)
CVPCB_SETTINGS* cfg = dynamic_cast<CVPCB_SETTINGS*>( config() );

View File

@ -195,6 +195,8 @@ LIB_VIEW_FRAME::LIB_VIEW_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrame
SyncView();
GetCanvas()->SetCanFocus( false );
setupUnits( config() );
// Set the working/draw area size to display a symbol to a reasonable value:
// A 450mm x 450mm with a origin at the area center looks like a large working area
double max_size_x = Millimeter2iu( 450 );

View File

@ -177,6 +177,8 @@ LIB_EDIT_FRAME::LIB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
GetCanvas()->GetView()->UseDrawPriority( true );
GetCanvas()->GetGAL()->SetAxesEnabled( true );
setupUnits( m_settings );
// Set the working/draw area size to display a symbol to a reasonable value:
// A 600mm x 600mm with a origin at the area center looks like a large working area
double max_size_x = Millimeter2iu( 600 );

View File

@ -290,6 +290,7 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ):
}
InitExitKey();
setupUnits( eeconfig() );
// Net list generator
DefaultExecFlags();

View File

@ -192,6 +192,8 @@ GERBVIEW_FRAME::GERBVIEW_FRAME( KIWAY* aKiway, wxWindow* aParent )
SwitchCanvas( canvasType );
setupUnits( config() );
// Enable the axes to match legacy draw style
auto& galOptions = GetGalDisplayOptions();
galOptions.m_axesEnabled = true;

View File

@ -117,6 +117,8 @@ protected:
void unitsChangeRefresh() override;
void setupUnits( APP_SETTINGS_BASE* aCfg );
void CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVarsChanged ) override;
/**
@ -187,6 +189,13 @@ public:
void ToggleUserUnits() override;
/**
* Get the pair or units in current use. The primary unit is the main
* unit of the frame, and the secondary unit is the unit of the other
* system that was used most recently.
*/
void GetUnitPair( EDA_UNITS& aPrimaryUnit, EDA_UNITS& aSecondaryUnits );
/**
* Return the absolute coordinates of the origin of the snap grid. This is
* treated as a relative offset, and snapping will occur at multiples of the grid
@ -476,11 +485,11 @@ public:
/**
* Returns bbox of document with option to not include some items.
*
*
* Used most commonly by "Zoom to Fit" and "Zoom to Objects". In Eeschema
* for "Zoom to Fit", it's passed "true" to include worksheet border. It's
* passed false by "Zoom To Objects" to ignore worksheet border. In Pcbnew,
* false makes it ignore any items outside the PCB edge such as fabrication
* for "Zoom to Fit", it's passed "true" to include worksheet border. It's
* passed false by "Zoom To Objects" to ignore worksheet border. In Pcbnew,
* false makes it ignore any items outside the PCB edge such as fabrication
* notes.
*
* @param aIncludeAllVisible - True = Include everything visible in bbox calculations

View File

@ -145,6 +145,8 @@ public:
int max_undo_items;
std::vector<wxString> file_history;
int units;
int last_metric_units;
int last_imperial_units;
};
APP_SETTINGS_BASE( const std::string& aFilename, int aSchemaVersion );

View File

@ -38,10 +38,7 @@ class EDA_DRAW_FRAME;
class COMMON_TOOLS : public TOOL_INTERACTIVE
{
public:
COMMON_TOOLS() :
TOOL_INTERACTIVE( "common.Control" ),
m_frame( nullptr )
{ }
COMMON_TOOLS();
~COMMON_TOOLS() override { }
@ -74,6 +71,10 @@ public:
int TogglePolarCoords( const TOOL_EVENT& aEvent );
int ResetLocalCoords( const TOOL_EVENT& aEvent );
void SetLastUnits( EDA_UNITS aUnit );
EDA_UNITS GetLastMetricUnits() { return m_metricUnit; }
EDA_UNITS GetLastImperialUnits() { return m_imperialUnit; }
// Grid control
int GridNext( const TOOL_EVENT& aEvent );
int GridPrev( const TOOL_EVENT& aEvent );

View File

@ -25,6 +25,7 @@
#ifndef GRID_MENU_H
#define GRID_MENU_H
#include <common.h>
#include <tool/action_menu.h>
class EDA_DRAW_FRAME;
@ -35,7 +36,10 @@ class GRID_MENU : public ACTION_MENU
public:
GRID_MENU( EDA_DRAW_FRAME* aParent );
static void BuildChoiceList( wxArrayString* aGridsList, APP_SETTINGS_BASE* aCfg, bool mmFirst );
static void BuildChoiceList( wxArrayString* aGridsList, APP_SETTINGS_BASE* aCfg,
EDA_DRAW_FRAME* aParent );
static wxString GridMenuUnits( EDA_UNITS aUnits, double aValue );
private:
ACTION_MENU* create() const override

View File

@ -181,6 +181,7 @@ PL_EDITOR_FRAME::PL_EDITOR_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
// Add the exit key handler
InitExitKey();
setupUnits( config() );
wxPoint originCoord = ReturnCoordOriginCorner();
SetGridOrigin( originCoord );

View File

@ -120,8 +120,7 @@ DIALOG_BOARD_REANNOTATE::DIALOG_BOARD_REANNOTATE( PCB_EDIT_FRAME* aParentFrame )
m_Settings = aParentFrame->config();
wxArrayString gridslist;
GRID_MENU::BuildChoiceList( &gridslist, m_Settings,
aParentFrame->GetUserUnits() != EDA_UNITS::INCHES );
GRID_MENU::BuildChoiceList( &gridslist, m_Settings, aParentFrame );
if( -1 == m_GridIndex ) //If no default loaded
m_GridIndex = m_Settings->m_Window.grid.last_size_idx; //Get the current grid size

View File

@ -249,6 +249,7 @@ FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent,
GetToolManager()->RunAction( ACTIONS::zoomFitScreen, false );
updateTitle();
InitExitKey();
setupUnits( GetSettings() );
// Default shutdown reason until a file is loaded
KIPLATFORM::APP::SetShutdownBlockReason( this, _( "Footprint changes are unsaved" ) );

View File

@ -267,6 +267,7 @@ FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent
updateView();
InitExitKey();
setupUnits( config() );
if( !IsModal() ) // For modal mode, calling ShowModal() will show this frame
{

View File

@ -340,6 +340,7 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
}
InitExitKey();
setupUnits( config() );
// Ensure the Python interpreter is up to date with its environment variables
PythonSyncEnvironmentVariables();

View File

@ -42,6 +42,7 @@
#include <settings/common_settings.h>
#include <tool/action_toolbar.h>
#include <tool/actions.h>
#include <tool/common_tools.h>
#include <tool/tool_manager.h>
#include <tools/pcb_actions.h>
#include <tools/selection_tool.h>
@ -549,13 +550,43 @@ void PCB_EDIT_FRAME::ReCreateAuxiliaryToolbar()
}
static wxString ComboBoxUnits( EDA_UNITS aUnits, double aValue, bool aIncludeLabel = true )
{
wxString text;
const wxChar* format;
switch( aUnits )
{
default: wxASSERT_MSG( false, "Invalid unit" ); KI_FALLTHROUGH;
case EDA_UNITS::UNSCALED: format = wxT( "%.0f" ); break;
case EDA_UNITS::MILLIMETRES: format = wxT( "%.3f" ); break;
case EDA_UNITS::MILS: format = wxT( "%.2f" ); break;
case EDA_UNITS::INCHES: format = wxT( "%.5f" ); break;
}
text.Printf( format, To_User_Unit( aUnits, aValue ) );
if( aIncludeLabel )
{
text += " ";
text += GetAbbreviatedUnitsLabel( aUnits, EDA_DATA_TYPE::DISTANCE );
}
return text;
}
void PCB_EDIT_FRAME::UpdateTrackWidthSelectBox( wxChoice* aTrackWidthSelectBox, bool aEdit )
{
if( aTrackWidthSelectBox == NULL )
return;
EDA_UNITS primaryUnit;
EDA_UNITS secondaryUnit;
GetUnitPair( primaryUnit, secondaryUnit );
wxString msg;
bool mmFirst = GetUserUnits() != EDA_UNITS::INCHES;
aTrackWidthSelectBox->Clear();
@ -563,13 +594,8 @@ void PCB_EDIT_FRAME::UpdateTrackWidthSelectBox( wxChoice* aTrackWidthSelectBox,
{
int size = GetDesignSettings().m_TrackWidthList[ii];
double valueMils = To_User_Unit( EDA_UNITS::INCHES, size ) * 1000;
double value_mm = To_User_Unit( EDA_UNITS::MILLIMETRES, size );
if( mmFirst )
msg.Printf( _( "Track: %.3f mm (%.2f mils)" ), value_mm, valueMils );
else
msg.Printf( _( "Track: %.2f mils (%.3f mm)" ), valueMils, value_mm );
msg.Printf( _( "Track: %s (%s)" ), ComboBoxUnits( primaryUnit, size ),
ComboBoxUnits( secondaryUnit, size ) );
// Mark the netclass track width value (the first in list)
if( ii == 0 )
@ -598,30 +624,48 @@ void PCB_EDIT_FRAME::UpdateViaSizeSelectBox( wxChoice* aViaSizeSelectBox, bool a
aViaSizeSelectBox->Clear();
bool mmFirst = GetUserUnits() != EDA_UNITS::INCHES;
COMMON_TOOLS* cmnTool = m_toolManager->GetTool<COMMON_TOOLS>();
EDA_UNITS primaryUnit = GetUserUnits();
EDA_UNITS secondaryUnit = EDA_UNITS::MILS;
if( IsImperialUnit( primaryUnit ) )
{
if( cmnTool )
secondaryUnit = cmnTool->GetLastMetricUnits();
else
secondaryUnit = EDA_UNITS::MILLIMETRES;
}
else
{
if( cmnTool )
secondaryUnit = cmnTool->GetLastImperialUnits();
else
secondaryUnit = EDA_UNITS::MILS;
}
for( unsigned ii = 0; ii < GetDesignSettings().m_ViasDimensionsList.size(); ii++ )
{
VIA_DIMENSION viaDimension = GetDesignSettings().m_ViasDimensionsList[ii];
wxString msg, mmStr, milsStr;
wxString msg, priStr, secStr;
double diam = To_User_Unit( EDA_UNITS::MILLIMETRES, viaDimension.m_Diameter );
double hole = To_User_Unit( EDA_UNITS::MILLIMETRES, viaDimension.m_Drill );
double diam = viaDimension.m_Diameter;
double hole = viaDimension.m_Drill;
if( hole > 0 )
mmStr.Printf( _( "%.2f / %.2f mm" ), diam, hole );
{
priStr.Printf( _( "%s / %s" ), ComboBoxUnits( primaryUnit, diam, false ),
ComboBoxUnits( primaryUnit, hole, true ) );
secStr.Printf( _( "%s / %s" ), ComboBoxUnits( secondaryUnit, diam, false ),
ComboBoxUnits( secondaryUnit, hole, true ) );
}
else
mmStr.Printf( _( "%.2f mm" ), diam );
{
priStr.Printf( _( "%s" ), ComboBoxUnits( primaryUnit, diam, true ) );
secStr.Printf( _( "%s" ), ComboBoxUnits( secondaryUnit, diam, true ) );
}
diam = To_User_Unit( EDA_UNITS::INCHES, viaDimension.m_Diameter ) * 1000;
hole = To_User_Unit( EDA_UNITS::INCHES, viaDimension.m_Drill ) * 1000;
if( hole > 0 )
milsStr.Printf( _( "%.1f / %.1f mils" ), diam, hole );
else
milsStr.Printf( _( "%.1f mils" ), diam );
msg.Printf( _( "Via: %s (%s)" ), mmFirst ? mmStr : milsStr, mmFirst ? milsStr : mmStr );
msg.Printf( _( "Via: %s (%s)" ), priStr, secStr );
// Mark the netclass via size value (the first in list)
if( ii == 0 )