2020-01-13 01:44:19 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
|
2024-01-31 12:18:01 +00:00
|
|
|
* Copyright (C) 2020-2024 KiCad Developers, see AUTHORS.txt for contributors.
|
2020-01-13 01:44:19 +00:00
|
|
|
*
|
|
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2024-01-31 12:18:01 +00:00
|
|
|
#ifndef PARAMETERS_H
|
|
|
|
#define PARAMETERS_H
|
2020-01-13 01:44:19 +00:00
|
|
|
|
2022-10-01 23:53:39 +00:00
|
|
|
#include <set>
|
2020-01-13 01:44:19 +00:00
|
|
|
#include <string>
|
|
|
|
#include <utility>
|
|
|
|
#include <math/util.h>
|
2020-03-07 21:06:33 +00:00
|
|
|
|
2022-08-25 22:50:47 +00:00
|
|
|
#include <optional>
|
2024-03-14 02:49:01 +00:00
|
|
|
#include <gal/color4d.h>
|
2020-03-07 21:06:33 +00:00
|
|
|
#include <settings/json_settings.h>
|
2024-03-14 02:49:01 +00:00
|
|
|
#include <settings/grid_settings.h>
|
|
|
|
#include <kicommon.h>
|
2020-01-13 01:44:19 +00:00
|
|
|
|
2024-03-14 02:49:01 +00:00
|
|
|
class KICOMMON_API PARAM_BASE
|
2020-01-13 01:44:19 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
PARAM_BASE( std::string aJsonPath, bool aReadOnly ) :
|
2020-05-08 18:10:47 +00:00
|
|
|
m_path( std::move( aJsonPath ) ),
|
2024-01-31 14:09:00 +00:00
|
|
|
m_readOnly( aReadOnly ),
|
|
|
|
m_clearUnknownKeys( false )
|
2020-05-08 18:10:47 +00:00
|
|
|
{}
|
2020-01-13 01:44:19 +00:00
|
|
|
|
|
|
|
virtual ~PARAM_BASE() = default;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Loads the value of this parameter from JSON to the underlying storage
|
|
|
|
* @param aSettings is the JSON_SETTINGS object to load from.
|
2020-05-31 21:42:04 +00:00
|
|
|
* @param aResetIfMissing if true will set the parameter to its default value if load fails
|
2020-01-13 01:44:19 +00:00
|
|
|
*/
|
2020-05-31 21:42:04 +00:00
|
|
|
virtual void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const = 0;
|
2020-01-13 01:44:19 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Stores the value of this parameter to the given JSON_SETTINGS object
|
|
|
|
* @param aSettings is the JSON_SETTINGS object to store into.
|
|
|
|
*/
|
|
|
|
virtual void Store( JSON_SETTINGS* aSettings ) const = 0;
|
|
|
|
|
|
|
|
virtual void SetDefault() = 0;
|
|
|
|
|
2020-05-30 16:56:16 +00:00
|
|
|
/**
|
|
|
|
* Checks whether the parameter in memory matches the one in a given JSON file
|
|
|
|
* @param aSettings is a JSON_SETTINGS to check the JSON file contents of
|
|
|
|
* @return true if the parameter in memory matches its value in the file
|
|
|
|
*/
|
|
|
|
virtual bool MatchesFile( JSON_SETTINGS* aSettings ) const = 0;
|
|
|
|
|
2020-05-15 12:55:28 +00:00
|
|
|
/**
|
|
|
|
* @return the path name of the parameter used to store it in the json file
|
2021-06-09 19:32:58 +00:00
|
|
|
* mainly useful in error messages
|
2020-05-15 12:55:28 +00:00
|
|
|
*/
|
2021-02-21 20:32:52 +00:00
|
|
|
const std::string& GetJsonPath() const { return m_path; }
|
2020-01-13 01:44:19 +00:00
|
|
|
|
2024-01-31 14:09:00 +00:00
|
|
|
/**
|
|
|
|
* @return true if keys should be cleared from source file rather than merged. Useful for
|
|
|
|
* things such as text variables that are semantically an array but stored as a map.
|
|
|
|
*/
|
|
|
|
bool ClearUnknownKeys() const { return m_clearUnknownKeys; }
|
|
|
|
|
2020-05-15 12:55:28 +00:00
|
|
|
protected:
|
2024-01-31 12:18:01 +00:00
|
|
|
std::string m_path; ///< Address of the param in the json files
|
|
|
|
bool m_readOnly; ///< Indicates param pointer should never be overwritten
|
2024-01-31 14:09:00 +00:00
|
|
|
bool m_clearUnknownKeys; ///< Keys should be cleared from source rather than merged.
|
|
|
|
///< This is useful for things that are semantically an
|
|
|
|
///< array but stored as a map, such as textVars.
|
2020-01-13 01:44:19 +00:00
|
|
|
};
|
|
|
|
|
2020-05-15 12:55:28 +00:00
|
|
|
|
2020-01-13 01:44:19 +00:00
|
|
|
template<typename ValueType>
|
|
|
|
class PARAM : public PARAM_BASE
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
PARAM( const std::string& aJsonPath, ValueType* aPtr, ValueType aDefault,
|
|
|
|
bool aReadOnly = false ) :
|
2020-05-08 18:10:47 +00:00
|
|
|
PARAM_BASE( aJsonPath, aReadOnly ),
|
|
|
|
m_min(),
|
|
|
|
m_max(),
|
2020-05-31 21:42:04 +00:00
|
|
|
m_use_minmax( false ),
|
|
|
|
m_ptr( aPtr ),
|
2023-12-18 17:19:15 +00:00
|
|
|
m_default( std::move( aDefault ) )
|
2020-05-08 18:10:47 +00:00
|
|
|
{ }
|
2020-01-13 01:44:19 +00:00
|
|
|
|
|
|
|
PARAM( const std::string& aJsonPath, ValueType* aPtr, ValueType aDefault, ValueType aMin,
|
2020-05-08 18:10:47 +00:00
|
|
|
ValueType aMax, bool aReadOnly = false ) :
|
|
|
|
PARAM_BASE( aJsonPath, aReadOnly ),
|
2023-12-18 17:19:15 +00:00
|
|
|
m_min( std::move( aMin ) ),
|
|
|
|
m_max( std::move( aMax ) ),
|
2020-05-31 21:42:04 +00:00
|
|
|
m_use_minmax( true ),
|
|
|
|
m_ptr( aPtr ),
|
2023-12-18 17:19:15 +00:00
|
|
|
m_default( std::move( aDefault ) )
|
2020-05-08 18:10:47 +00:00
|
|
|
{ }
|
2020-01-13 01:44:19 +00:00
|
|
|
|
2020-05-31 21:42:04 +00:00
|
|
|
void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override
|
2020-01-13 01:44:19 +00:00
|
|
|
{
|
|
|
|
if( m_readOnly )
|
|
|
|
return;
|
|
|
|
|
2022-08-25 22:50:47 +00:00
|
|
|
if( std::optional<ValueType> optval = aSettings->Get<ValueType>( m_path ) )
|
2020-01-13 01:44:19 +00:00
|
|
|
{
|
2020-05-31 21:42:04 +00:00
|
|
|
ValueType val = *optval;
|
2020-01-13 01:44:19 +00:00
|
|
|
|
|
|
|
if( m_use_minmax )
|
|
|
|
{
|
2020-04-09 23:34:38 +00:00
|
|
|
if( m_max < val || val < m_min )
|
2020-01-13 01:44:19 +00:00
|
|
|
val = m_default;
|
|
|
|
}
|
|
|
|
|
2020-05-31 21:42:04 +00:00
|
|
|
*m_ptr = val;
|
|
|
|
}
|
|
|
|
else if( aResetIfMissing )
|
2024-01-31 12:18:01 +00:00
|
|
|
{
|
2020-05-31 21:42:04 +00:00
|
|
|
*m_ptr = m_default;
|
2024-01-31 12:18:01 +00:00
|
|
|
}
|
2020-01-13 01:44:19 +00:00
|
|
|
}
|
|
|
|
|
2020-05-30 16:56:16 +00:00
|
|
|
void Store( JSON_SETTINGS* aSettings ) const override
|
2020-01-13 01:44:19 +00:00
|
|
|
{
|
|
|
|
aSettings->Set<ValueType>( m_path, *m_ptr );
|
|
|
|
}
|
|
|
|
|
|
|
|
ValueType GetDefault() const
|
|
|
|
{
|
|
|
|
return m_default;
|
|
|
|
}
|
|
|
|
|
2020-05-30 16:56:16 +00:00
|
|
|
void SetDefault() override
|
2020-01-13 01:44:19 +00:00
|
|
|
{
|
|
|
|
*m_ptr = m_default;
|
|
|
|
}
|
|
|
|
|
2020-05-30 16:56:16 +00:00
|
|
|
bool MatchesFile( JSON_SETTINGS* aSettings ) const override
|
|
|
|
{
|
2022-08-25 22:50:47 +00:00
|
|
|
if( std::optional<ValueType> optval = aSettings->Get<ValueType>( m_path ) )
|
2020-05-30 16:56:16 +00:00
|
|
|
return *optval == *m_ptr;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-01-13 01:44:19 +00:00
|
|
|
private:
|
2024-01-31 12:18:01 +00:00
|
|
|
ValueType m_min;
|
|
|
|
ValueType m_max;
|
|
|
|
bool m_use_minmax;
|
2020-05-31 21:42:04 +00:00
|
|
|
|
|
|
|
protected:
|
|
|
|
ValueType* m_ptr;
|
2024-01-31 12:18:01 +00:00
|
|
|
ValueType m_default;
|
2020-01-13 01:44:19 +00:00
|
|
|
};
|
|
|
|
|
2020-05-31 21:42:04 +00:00
|
|
|
/**
|
|
|
|
* Stores a path as a string with directory separators normalized to unix-style
|
|
|
|
*/
|
2024-03-14 02:49:01 +00:00
|
|
|
class KICOMMON_API PARAM_PATH : public PARAM<wxString>
|
2020-05-31 21:42:04 +00:00
|
|
|
{
|
|
|
|
public:
|
2021-07-27 12:22:27 +00:00
|
|
|
PARAM_PATH( const std::string& aJsonPath, wxString* aPtr, const wxString& aDefault,
|
2020-05-31 21:42:04 +00:00
|
|
|
bool aReadOnly = false ) :
|
|
|
|
PARAM( aJsonPath, aPtr, aDefault, aReadOnly )
|
|
|
|
{ }
|
|
|
|
|
|
|
|
void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override
|
|
|
|
{
|
|
|
|
if( m_readOnly )
|
|
|
|
return;
|
|
|
|
|
|
|
|
PARAM::Load( aSettings, aResetIfMissing );
|
|
|
|
|
|
|
|
*m_ptr = fromFileFormat( *m_ptr );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Store( JSON_SETTINGS* aSettings ) const override
|
|
|
|
{
|
|
|
|
aSettings->Set<wxString>( m_path, toFileFormat( *m_ptr ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MatchesFile( JSON_SETTINGS* aSettings ) const override
|
|
|
|
{
|
2022-08-25 22:50:47 +00:00
|
|
|
if( std::optional<wxString> optval = aSettings->Get<wxString>( m_path ) )
|
2020-05-31 21:42:04 +00:00
|
|
|
return fromFileFormat( *optval ) == *m_ptr;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
wxString toFileFormat( const wxString& aString ) const
|
|
|
|
{
|
|
|
|
wxString ret = aString;
|
|
|
|
ret.Replace( wxT( "\\" ), wxT( "/" ) );
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
wxString fromFileFormat( const wxString& aString ) const
|
|
|
|
{
|
|
|
|
wxString ret = aString;
|
|
|
|
#ifdef __WINDOWS__
|
|
|
|
ret.Replace( wxT( "/" ), wxT( "\\" ) );
|
|
|
|
#endif
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
};
|
2020-05-08 18:10:47 +00:00
|
|
|
|
2020-07-11 01:06:17 +00:00
|
|
|
/**
|
|
|
|
* Stores an enum as an integer
|
|
|
|
*/
|
|
|
|
template<typename EnumType>
|
|
|
|
class PARAM_ENUM : public PARAM_BASE
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
PARAM_ENUM( const std::string& aJsonPath, EnumType* aPtr, EnumType aDefault,
|
|
|
|
EnumType aMin, EnumType aMax, bool aReadOnly = false ) :
|
|
|
|
PARAM_BASE( aJsonPath, aReadOnly ),
|
|
|
|
m_ptr( aPtr ),
|
|
|
|
m_min( aMin ),
|
|
|
|
m_max( aMax ),
|
|
|
|
m_default( aDefault )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override
|
|
|
|
{
|
|
|
|
if( m_readOnly )
|
|
|
|
return;
|
|
|
|
|
2022-08-25 22:50:47 +00:00
|
|
|
if( std::optional<int> val = aSettings->Get<int>( m_path ) )
|
2020-07-11 01:06:17 +00:00
|
|
|
{
|
|
|
|
if( *val >= static_cast<int>( m_min ) && *val <= static_cast<int>( m_max ) )
|
|
|
|
*m_ptr = static_cast<EnumType>( *val );
|
|
|
|
else if( aResetIfMissing )
|
|
|
|
*m_ptr = m_default;
|
|
|
|
|
|
|
|
}
|
|
|
|
else if( aResetIfMissing )
|
2024-01-31 12:18:01 +00:00
|
|
|
{
|
2020-07-11 01:06:17 +00:00
|
|
|
*m_ptr = m_default;
|
2024-01-31 12:18:01 +00:00
|
|
|
}
|
2020-07-11 01:06:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Store( JSON_SETTINGS* aSettings ) const override
|
|
|
|
{
|
|
|
|
aSettings->Set<int>( m_path, static_cast<int>( *m_ptr ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
EnumType GetDefault() const
|
|
|
|
{
|
|
|
|
return m_default;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetDefault() override
|
|
|
|
{
|
|
|
|
*m_ptr = m_default;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MatchesFile( JSON_SETTINGS* aSettings ) const override
|
|
|
|
{
|
2022-08-25 22:50:47 +00:00
|
|
|
if( std::optional<int> val = aSettings->Get<int>( m_path ) )
|
2020-07-11 01:06:17 +00:00
|
|
|
return *val == static_cast<int>( *m_ptr );
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
EnumType* m_ptr;
|
|
|
|
EnumType m_min;
|
|
|
|
EnumType m_max;
|
|
|
|
EnumType m_default;
|
|
|
|
};
|
|
|
|
|
2020-01-13 01:44:19 +00:00
|
|
|
/**
|
|
|
|
* Like a normal param, but with custom getter and setter functions
|
|
|
|
* @tparam ValueType is the value to store
|
|
|
|
*/
|
|
|
|
template<typename ValueType>
|
|
|
|
class PARAM_LAMBDA : public PARAM_BASE
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
PARAM_LAMBDA( const std::string& aJsonPath, std::function<ValueType()> aGetter,
|
2020-05-08 18:10:47 +00:00
|
|
|
std::function<void( ValueType )> aSetter, ValueType aDefault,
|
|
|
|
bool aReadOnly = false ) :
|
|
|
|
PARAM_BASE( aJsonPath, aReadOnly ),
|
2023-12-18 17:01:27 +00:00
|
|
|
m_default( std::move( aDefault ) ),
|
|
|
|
m_getter( std::move( aGetter ) ),
|
|
|
|
m_setter( std::move( aSetter ) )
|
2024-03-20 01:53:21 +00:00
|
|
|
{
|
|
|
|
}
|
2020-01-13 01:44:19 +00:00
|
|
|
|
2024-03-14 02:49:01 +00:00
|
|
|
void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override
|
|
|
|
{
|
|
|
|
if( m_readOnly )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if( std::is_same<ValueType, nlohmann::json>::value )
|
|
|
|
{
|
|
|
|
if( std::optional<nlohmann::json> optval = aSettings->GetJson( m_path ) )
|
|
|
|
m_setter( *optval );
|
|
|
|
else
|
|
|
|
m_setter( m_default );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if( std::optional<ValueType> optval = aSettings->Get<ValueType>( m_path ) )
|
|
|
|
m_setter( *optval );
|
|
|
|
else
|
|
|
|
m_setter( m_default );
|
|
|
|
}
|
|
|
|
}
|
2020-01-13 01:44:19 +00:00
|
|
|
|
2020-05-31 21:42:04 +00:00
|
|
|
void Store( JSON_SETTINGS* aSettings ) const override
|
2020-01-13 01:44:19 +00:00
|
|
|
{
|
2020-02-20 15:59:45 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
aSettings->Set<ValueType>( m_path, m_getter() );
|
|
|
|
}
|
|
|
|
catch( ... )
|
|
|
|
{
|
|
|
|
}
|
2020-01-13 01:44:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ValueType GetDefault() const
|
|
|
|
{
|
|
|
|
return m_default;
|
|
|
|
}
|
|
|
|
|
2020-05-30 16:56:16 +00:00
|
|
|
void SetDefault() override
|
2020-01-13 01:44:19 +00:00
|
|
|
{
|
|
|
|
m_setter( m_default );
|
|
|
|
}
|
|
|
|
|
2024-03-14 02:49:01 +00:00
|
|
|
bool MatchesFile( JSON_SETTINGS* aSettings ) const override
|
|
|
|
{
|
|
|
|
if( std::is_same<ValueType, nlohmann::json>::value )
|
|
|
|
{
|
|
|
|
if( std::optional<nlohmann::json> optval = aSettings->GetJson( m_path ) )
|
|
|
|
return *optval == m_getter();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if( std::optional<ValueType> optval = aSettings->Get<ValueType>( m_path ) )
|
|
|
|
return *optval == m_getter();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Not in file
|
|
|
|
return false;
|
|
|
|
}
|
2020-05-30 16:56:16 +00:00
|
|
|
|
2020-01-13 01:44:19 +00:00
|
|
|
private:
|
2024-01-31 12:18:01 +00:00
|
|
|
ValueType m_default;
|
|
|
|
std::function<ValueType()> m_getter;
|
2020-01-13 01:44:19 +00:00
|
|
|
std::function<void( ValueType )> m_setter;
|
|
|
|
};
|
|
|
|
|
2024-03-21 23:46:12 +00:00
|
|
|
#ifdef __WINDOWS__
|
2024-03-20 01:53:21 +00:00
|
|
|
template class KICOMMON_API PARAM_LAMBDA<bool>;
|
|
|
|
template class KICOMMON_API PARAM_LAMBDA<int>;
|
|
|
|
template class KICOMMON_API PARAM_LAMBDA<nlohmann::json>;
|
|
|
|
template class KICOMMON_API PARAM_LAMBDA<std::string>;
|
|
|
|
#else
|
2024-03-14 02:49:01 +00:00
|
|
|
extern template class APIVISIBLE PARAM_LAMBDA<bool>;
|
|
|
|
extern template class APIVISIBLE PARAM_LAMBDA<int>;
|
|
|
|
extern template class APIVISIBLE PARAM_LAMBDA<nlohmann::json>;
|
|
|
|
extern template class APIVISIBLE PARAM_LAMBDA<std::string>;
|
2024-03-20 01:53:21 +00:00
|
|
|
#endif
|
2024-03-14 02:49:01 +00:00
|
|
|
|
2020-01-13 01:44:19 +00:00
|
|
|
/**
|
|
|
|
* Represents a parameter that has a scaling factor between the value in the file and the
|
|
|
|
* value used internally (i.e. the value pointer). This basically only makes sense to use
|
|
|
|
* with int or double as ValueType.
|
|
|
|
* @tparam ValueType is the internal type: the file always stores a double.
|
|
|
|
*/
|
|
|
|
template<typename ValueType>
|
|
|
|
class PARAM_SCALED: public PARAM_BASE
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
PARAM_SCALED( const std::string& aJsonPath, ValueType* aPtr, ValueType aDefault,
|
|
|
|
double aScale = 1.0, bool aReadOnly = false ) :
|
2020-05-08 18:10:47 +00:00
|
|
|
PARAM_BASE( aJsonPath, aReadOnly ),
|
|
|
|
m_ptr( aPtr ),
|
|
|
|
m_default( aDefault ),
|
|
|
|
m_min(),
|
|
|
|
m_max(),
|
|
|
|
m_use_minmax( false ),
|
2024-02-23 11:48:20 +00:00
|
|
|
m_scale( aScale ),
|
|
|
|
m_invScale( 1.0 / aScale )
|
2020-05-08 18:10:47 +00:00
|
|
|
{ }
|
2020-01-13 01:44:19 +00:00
|
|
|
|
2020-05-08 18:10:47 +00:00
|
|
|
PARAM_SCALED( const std::string& aJsonPath, ValueType* aPtr, ValueType aDefault,
|
|
|
|
ValueType aMin, ValueType aMax, double aScale = 1.0, bool aReadOnly = false ) :
|
|
|
|
PARAM_BASE( aJsonPath, aReadOnly ),
|
|
|
|
m_ptr( aPtr ),
|
|
|
|
m_default( aDefault ),
|
|
|
|
m_min( aMin ),
|
|
|
|
m_max( aMax ),
|
|
|
|
m_use_minmax( true ),
|
2024-02-23 11:48:20 +00:00
|
|
|
m_scale( aScale ),
|
|
|
|
m_invScale( 1.0 / aScale )
|
2020-05-08 18:10:47 +00:00
|
|
|
{ }
|
2020-01-13 01:44:19 +00:00
|
|
|
|
2020-05-31 21:42:04 +00:00
|
|
|
void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override
|
2020-01-13 01:44:19 +00:00
|
|
|
{
|
|
|
|
if( m_readOnly )
|
|
|
|
return;
|
|
|
|
|
2024-02-23 11:48:20 +00:00
|
|
|
double dval = m_default / m_invScale;
|
2020-01-13 01:44:19 +00:00
|
|
|
|
2022-08-25 22:50:47 +00:00
|
|
|
if( std::optional<double> optval = aSettings->Get<double>( m_path ) )
|
2020-03-07 21:10:37 +00:00
|
|
|
dval = *optval;
|
2020-05-31 21:42:04 +00:00
|
|
|
else if( !aResetIfMissing )
|
|
|
|
return;
|
2020-01-13 01:44:19 +00:00
|
|
|
|
2024-02-23 11:48:20 +00:00
|
|
|
ValueType val = KiROUND<double, ValueType>( dval * m_invScale );
|
2020-01-13 01:44:19 +00:00
|
|
|
|
|
|
|
if( m_use_minmax )
|
|
|
|
{
|
|
|
|
if( val > m_max || val < m_min )
|
|
|
|
val = m_default;
|
|
|
|
}
|
|
|
|
|
|
|
|
*m_ptr = val;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Store( JSON_SETTINGS* aSettings) const override
|
|
|
|
{
|
2024-02-23 11:48:20 +00:00
|
|
|
aSettings->Set<double>( m_path, *m_ptr / m_invScale );
|
2020-01-13 01:44:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ValueType GetDefault() const
|
|
|
|
{
|
|
|
|
return m_default;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void SetDefault() override
|
|
|
|
{
|
|
|
|
*m_ptr = m_default;
|
|
|
|
}
|
|
|
|
|
2020-05-30 16:56:16 +00:00
|
|
|
bool MatchesFile( JSON_SETTINGS* aSettings ) const override
|
|
|
|
{
|
2022-08-25 22:50:47 +00:00
|
|
|
if( std::optional<double> optval = aSettings->Get<double>( m_path ) )
|
2024-02-23 11:48:20 +00:00
|
|
|
return *optval == ( *m_ptr / m_invScale );
|
2020-05-30 16:56:16 +00:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-01-13 01:44:19 +00:00
|
|
|
private:
|
|
|
|
ValueType* m_ptr;
|
2024-01-31 12:18:01 +00:00
|
|
|
ValueType m_default;
|
|
|
|
ValueType m_min;
|
|
|
|
ValueType m_max;
|
|
|
|
bool m_use_minmax;
|
|
|
|
double m_scale;
|
2024-02-23 11:48:20 +00:00
|
|
|
double m_invScale;
|
2020-01-13 01:44:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template<typename Type>
|
|
|
|
class PARAM_LIST : public PARAM_BASE
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
PARAM_LIST( const std::string& aJsonPath, std::vector<Type>* aPtr,
|
|
|
|
std::initializer_list<Type> aDefault, bool aReadOnly = false ) :
|
2020-05-08 18:10:47 +00:00
|
|
|
PARAM_BASE( aJsonPath, aReadOnly ),
|
|
|
|
m_ptr( aPtr ),
|
|
|
|
m_default( aDefault )
|
|
|
|
{ }
|
2020-01-13 01:44:19 +00:00
|
|
|
|
|
|
|
PARAM_LIST( const std::string& aJsonPath, std::vector<Type>* aPtr,
|
|
|
|
std::vector<Type> aDefault, bool aReadOnly = false ) :
|
2020-05-08 18:10:47 +00:00
|
|
|
PARAM_BASE( aJsonPath, aReadOnly ),
|
|
|
|
m_ptr( aPtr ),
|
2023-12-18 17:01:27 +00:00
|
|
|
m_default( std::move( aDefault ) )
|
2020-05-08 18:10:47 +00:00
|
|
|
{ }
|
2020-01-13 01:44:19 +00:00
|
|
|
|
2024-03-14 02:49:01 +00:00
|
|
|
void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override
|
|
|
|
{
|
|
|
|
if( m_readOnly )
|
|
|
|
return;
|
2024-03-14 02:49:01 +00:00
|
|
|
|
2024-03-14 02:49:01 +00:00
|
|
|
if( std::optional<nlohmann::json> js = aSettings->GetJson( m_path ) )
|
|
|
|
{
|
|
|
|
std::vector<Type> val;
|
|
|
|
|
|
|
|
if( js->is_array() )
|
|
|
|
{
|
|
|
|
for( const auto& el : js->items() )
|
|
|
|
val.push_back( el.value().get<Type>() );
|
|
|
|
}
|
|
|
|
|
|
|
|
*m_ptr = val;
|
|
|
|
}
|
|
|
|
else if( aResetIfMissing )
|
|
|
|
*m_ptr = m_default;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Store( JSON_SETTINGS* aSettings ) const override
|
|
|
|
{
|
|
|
|
nlohmann::json js = nlohmann::json::array();
|
|
|
|
|
|
|
|
for( const auto& el : *m_ptr )
|
|
|
|
js.push_back( el );
|
|
|
|
|
|
|
|
aSettings->Set<nlohmann::json>( m_path, js );
|
|
|
|
}
|
2020-01-13 01:44:19 +00:00
|
|
|
|
2020-05-30 16:56:16 +00:00
|
|
|
void SetDefault() override
|
2020-01-13 01:44:19 +00:00
|
|
|
{
|
|
|
|
*m_ptr = m_default;
|
|
|
|
}
|
|
|
|
|
2024-03-14 02:49:01 +00:00
|
|
|
bool MatchesFile( JSON_SETTINGS* aSettings ) const override
|
|
|
|
{
|
|
|
|
if( std::optional<nlohmann::json> js = aSettings->GetJson( m_path ) )
|
|
|
|
{
|
|
|
|
if( js->is_array() )
|
|
|
|
{
|
|
|
|
std::vector<Type> val;
|
|
|
|
|
|
|
|
for( const auto& el : js->items() )
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
val.emplace_back( el.value().get<Type>() );
|
|
|
|
}
|
|
|
|
catch( ... )
|
|
|
|
{
|
|
|
|
// Probably typecast didn't work; skip this element
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return val == *m_ptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2020-05-30 16:56:16 +00:00
|
|
|
|
2020-05-26 02:27:27 +00:00
|
|
|
protected:
|
2020-01-13 01:44:19 +00:00
|
|
|
std::vector<Type>* m_ptr;
|
2024-01-31 12:18:01 +00:00
|
|
|
std::vector<Type> m_default;
|
2020-01-13 01:44:19 +00:00
|
|
|
};
|
|
|
|
|
2024-03-14 02:49:01 +00:00
|
|
|
|
2024-03-21 23:46:12 +00:00
|
|
|
#ifdef __WINDOWS__
|
2024-03-20 01:53:21 +00:00
|
|
|
template class KICOMMON_API PARAM_LIST<bool>;
|
|
|
|
template class KICOMMON_API PARAM_LIST<int>;
|
|
|
|
template class KICOMMON_API PARAM_LIST<double>;
|
|
|
|
template class KICOMMON_API PARAM_LIST<KIGFX::COLOR4D>;
|
|
|
|
template class KICOMMON_API PARAM_LIST<GRID>;
|
|
|
|
template class KICOMMON_API PARAM_LIST<wxString>;
|
|
|
|
#else
|
2024-03-14 02:49:01 +00:00
|
|
|
extern template class APIVISIBLE PARAM_LIST<bool>;
|
|
|
|
extern template class APIVISIBLE PARAM_LIST<int>;
|
|
|
|
extern template class APIVISIBLE PARAM_LIST<double>;
|
|
|
|
extern template class APIVISIBLE PARAM_LIST<KIGFX::COLOR4D>;
|
|
|
|
extern template class APIVISIBLE PARAM_LIST<GRID>;
|
|
|
|
extern template class APIVISIBLE PARAM_LIST<wxString>;
|
2024-03-20 01:53:21 +00:00
|
|
|
#endif
|
2024-03-14 02:49:01 +00:00
|
|
|
|
|
|
|
|
2022-10-01 23:53:39 +00:00
|
|
|
template<typename Type>
|
|
|
|
class PARAM_SET : public PARAM_BASE
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
PARAM_SET( const std::string& aJsonPath, std::set<Type>* aPtr,
|
|
|
|
std::initializer_list<Type> aDefault, bool aReadOnly = false ) :
|
|
|
|
PARAM_BASE( aJsonPath, aReadOnly ),
|
|
|
|
m_ptr( aPtr ),
|
|
|
|
m_default( aDefault )
|
|
|
|
{ }
|
|
|
|
|
|
|
|
PARAM_SET( const std::string& aJsonPath, std::set<Type>* aPtr,
|
|
|
|
std::set<Type> aDefault, bool aReadOnly = false ) :
|
|
|
|
PARAM_BASE( aJsonPath, aReadOnly ),
|
|
|
|
m_ptr( aPtr ),
|
|
|
|
m_default( aDefault )
|
|
|
|
{ }
|
|
|
|
|
2024-03-14 02:49:01 +00:00
|
|
|
void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override
|
|
|
|
{
|
|
|
|
if( m_readOnly )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if( std::optional<nlohmann::json> js = aSettings->GetJson( m_path ) )
|
|
|
|
{
|
|
|
|
std::set<Type> val;
|
|
|
|
|
|
|
|
if( js->is_array() )
|
|
|
|
{
|
|
|
|
for( const auto& el : js->items() )
|
|
|
|
val.insert( el.value().get<Type>() );
|
|
|
|
}
|
|
|
|
|
|
|
|
*m_ptr = val;
|
|
|
|
}
|
|
|
|
else if( aResetIfMissing )
|
|
|
|
*m_ptr = m_default;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Store( JSON_SETTINGS* aSettings) const override
|
|
|
|
{
|
|
|
|
nlohmann::json js = nlohmann::json::array();
|
|
|
|
|
|
|
|
for( const auto& el : *m_ptr )
|
|
|
|
js.push_back( el );
|
|
|
|
|
|
|
|
aSettings->Set<nlohmann::json>( m_path, js );
|
|
|
|
}
|
2022-10-01 23:53:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
void SetDefault() override
|
|
|
|
{
|
|
|
|
*m_ptr = m_default;
|
|
|
|
}
|
|
|
|
|
2024-03-14 02:49:01 +00:00
|
|
|
bool MatchesFile( JSON_SETTINGS* aSettings ) const override
|
|
|
|
{
|
|
|
|
if( std::optional<nlohmann::json> js = aSettings->GetJson( m_path ) )
|
|
|
|
{
|
|
|
|
if( js->is_array() )
|
|
|
|
{
|
|
|
|
std::set<Type> val;
|
|
|
|
|
|
|
|
for( const auto& el : js->items() )
|
|
|
|
val.insert( el.value().get<Type>() );
|
|
|
|
|
|
|
|
return val == *m_ptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2022-10-01 23:53:39 +00:00
|
|
|
|
|
|
|
protected:
|
|
|
|
std::set<Type>* m_ptr;
|
2024-01-31 12:18:01 +00:00
|
|
|
std::set<Type> m_default;
|
2022-10-01 23:53:39 +00:00
|
|
|
};
|
|
|
|
|
2024-03-21 23:46:12 +00:00
|
|
|
#ifdef __WINDOWS__
|
2024-03-20 01:53:21 +00:00
|
|
|
template class KICOMMON_API PARAM_SET<wxString>;
|
|
|
|
#else
|
2024-03-14 02:49:01 +00:00
|
|
|
extern template class APIVISIBLE PARAM_SET<wxString>;
|
2024-03-20 01:53:21 +00:00
|
|
|
#endif
|
2024-03-14 02:49:01 +00:00
|
|
|
|
2020-05-26 02:27:27 +00:00
|
|
|
/**
|
|
|
|
* Represents a list of strings holding directory paths.
|
|
|
|
* Normalizes paths to unix directory separator style in the file.
|
|
|
|
*/
|
2024-03-14 02:49:01 +00:00
|
|
|
class KICOMMON_API PARAM_PATH_LIST : public PARAM_LIST<wxString>
|
2020-05-26 02:27:27 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
PARAM_PATH_LIST( const std::string& aJsonPath, std::vector<wxString>* aPtr,
|
|
|
|
std::initializer_list<wxString> aDefault, bool aReadOnly = false ) :
|
|
|
|
PARAM_LIST( aJsonPath, aPtr, aDefault, aReadOnly )
|
|
|
|
{ }
|
|
|
|
|
|
|
|
PARAM_PATH_LIST( const std::string& aJsonPath, std::vector<wxString>* aPtr,
|
|
|
|
std::vector<wxString> aDefault, bool aReadOnly = false ) :
|
|
|
|
PARAM_LIST( aJsonPath, aPtr, aDefault, aReadOnly )
|
|
|
|
{ }
|
|
|
|
|
2020-05-31 21:42:04 +00:00
|
|
|
void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override
|
2020-05-26 02:27:27 +00:00
|
|
|
{
|
|
|
|
if( m_readOnly )
|
|
|
|
return;
|
|
|
|
|
2020-05-31 21:42:04 +00:00
|
|
|
PARAM_LIST::Load( aSettings, aResetIfMissing );
|
2020-05-26 02:27:27 +00:00
|
|
|
|
|
|
|
for( size_t i = 0; i < m_ptr->size(); i++ )
|
|
|
|
( *m_ptr )[i] = fromFileFormat( ( *m_ptr )[i] );
|
|
|
|
}
|
|
|
|
|
2021-06-04 03:52:50 +00:00
|
|
|
void Store( JSON_SETTINGS* aSettings) const override;
|
2020-05-26 02:27:27 +00:00
|
|
|
|
2021-06-04 03:52:50 +00:00
|
|
|
bool MatchesFile( JSON_SETTINGS* aSettings ) const override;
|
2020-05-26 02:27:27 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
wxString toFileFormat( const wxString& aString ) const
|
|
|
|
{
|
|
|
|
wxString ret = aString;
|
|
|
|
ret.Replace( wxT( "\\" ), wxT( "/" ) );
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
wxString fromFileFormat( const wxString& aString ) const
|
|
|
|
{
|
|
|
|
wxString ret = aString;
|
|
|
|
#ifdef __WINDOWS__
|
|
|
|
ret.Replace( wxT( "/" ), wxT( "\\" ) );
|
|
|
|
#endif
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
};
|
2020-05-08 18:10:47 +00:00
|
|
|
|
2020-01-13 01:44:19 +00:00
|
|
|
/**
|
|
|
|
* Represents a map of <std::string, Value>. The key parameter has to be a string in JSON.
|
|
|
|
*
|
|
|
|
* The key must be stored in UTF-8 format, so any translated strings or strings provided by the
|
|
|
|
* user as a key must be converted to UTF-8 at the site where they are placed in the underlying
|
|
|
|
* map that this PARAM_MAP points to.
|
|
|
|
*
|
|
|
|
* Values must also be in UTF-8, but if you use wxString as the value type, this conversion will
|
|
|
|
* be done automatically by the to_json and from_json helpers defined in json_settings.cpp
|
|
|
|
*
|
|
|
|
* @tparam Value is the value type of the map
|
|
|
|
*/
|
|
|
|
template<typename Value>
|
|
|
|
class PARAM_MAP : public PARAM_BASE
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
PARAM_MAP( const std::string& aJsonPath, std::map<std::string, Value>* aPtr,
|
|
|
|
std::initializer_list<std::pair<const std::string, Value>> aDefault,
|
|
|
|
bool aReadOnly = false ) :
|
2020-05-08 18:10:47 +00:00
|
|
|
PARAM_BASE( aJsonPath, aReadOnly ),
|
|
|
|
m_ptr( aPtr ),
|
|
|
|
m_default( aDefault )
|
|
|
|
{ }
|
2020-01-13 01:44:19 +00:00
|
|
|
|
2024-03-14 02:49:01 +00:00
|
|
|
void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override
|
|
|
|
{
|
|
|
|
if( m_readOnly )
|
|
|
|
return;
|
2024-03-14 02:49:01 +00:00
|
|
|
|
2024-03-14 02:49:01 +00:00
|
|
|
if( std::optional<nlohmann::json> js = aSettings->GetJson( m_path ) )
|
|
|
|
{
|
|
|
|
if( js->is_object() )
|
|
|
|
{
|
|
|
|
m_ptr->clear();
|
|
|
|
|
|
|
|
for( const auto& el : js->items() )
|
|
|
|
( *m_ptr )[el.key()] = el.value().get<Value>();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( aResetIfMissing )
|
|
|
|
*m_ptr = m_default;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Store( JSON_SETTINGS* aSettings) const override
|
|
|
|
{
|
|
|
|
nlohmann::json js( {} );
|
|
|
|
|
|
|
|
for( const auto& el : *m_ptr )
|
|
|
|
js[el.first] = el.second;
|
|
|
|
|
|
|
|
aSettings->Set<nlohmann::json>( m_path, js );
|
|
|
|
}
|
2020-01-13 01:44:19 +00:00
|
|
|
|
|
|
|
virtual void SetDefault() override
|
|
|
|
{
|
|
|
|
*m_ptr = m_default;
|
|
|
|
}
|
|
|
|
|
2024-03-14 02:49:01 +00:00
|
|
|
bool MatchesFile( JSON_SETTINGS* aSettings ) const override
|
|
|
|
{
|
|
|
|
if( std::optional<nlohmann::json> js = aSettings->GetJson( m_path ) )
|
|
|
|
{
|
|
|
|
if( js->is_object() )
|
|
|
|
{
|
|
|
|
if( m_ptr->size() != js->size() )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
std::map<std::string, Value> val;
|
|
|
|
|
|
|
|
for( const auto& el : js->items() )
|
|
|
|
val[el.key()] = el.value().get<Value>();
|
|
|
|
|
|
|
|
return val == *m_ptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2020-05-30 16:56:16 +00:00
|
|
|
|
2020-01-13 01:44:19 +00:00
|
|
|
private:
|
|
|
|
std::map<std::string, Value>* m_ptr;
|
2024-01-31 12:18:01 +00:00
|
|
|
std::map<std::string, Value> m_default;
|
2020-01-13 01:44:19 +00:00
|
|
|
};
|
|
|
|
|
2020-06-08 02:19:46 +00:00
|
|
|
|
2024-03-21 23:46:12 +00:00
|
|
|
#ifdef __WINDOWS__
|
2024-03-20 01:53:21 +00:00
|
|
|
template class KICOMMON_API PARAM_MAP<int>;
|
|
|
|
template class KICOMMON_API PARAM_MAP<double>;
|
|
|
|
template class KICOMMON_API PARAM_MAP<bool>;
|
|
|
|
#else
|
2024-03-14 02:49:01 +00:00
|
|
|
extern template class APIVISIBLE PARAM_MAP<int>;
|
|
|
|
extern template class APIVISIBLE PARAM_MAP<double>;
|
|
|
|
extern template class APIVISIBLE PARAM_MAP<bool>;
|
2024-03-20 01:53:21 +00:00
|
|
|
#endif
|
2024-03-14 02:49:01 +00:00
|
|
|
|
|
|
|
|
2020-06-08 02:19:46 +00:00
|
|
|
/**
|
|
|
|
* A helper for <wxString, wxString> maps
|
|
|
|
*/
|
2024-03-14 02:49:01 +00:00
|
|
|
class KICOMMON_API PARAM_WXSTRING_MAP : public PARAM_BASE
|
2020-06-08 02:19:46 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
PARAM_WXSTRING_MAP( const std::string& aJsonPath, std::map<wxString, wxString>* aPtr,
|
2024-01-31 12:18:01 +00:00
|
|
|
std::initializer_list<std::pair<const wxString, wxString>> aDefault,
|
2024-01-31 14:09:00 +00:00
|
|
|
bool aReadOnly = false, bool aArrayBehavior = false ) :
|
2020-06-08 02:19:46 +00:00
|
|
|
PARAM_BASE( aJsonPath, aReadOnly ),
|
|
|
|
m_ptr( aPtr ),
|
|
|
|
m_default( aDefault )
|
2024-01-31 14:09:00 +00:00
|
|
|
{
|
|
|
|
m_clearUnknownKeys = aArrayBehavior;
|
|
|
|
}
|
2020-06-08 02:19:46 +00:00
|
|
|
|
2021-06-04 03:52:50 +00:00
|
|
|
void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override;
|
2020-06-08 02:19:46 +00:00
|
|
|
|
2021-06-04 03:52:50 +00:00
|
|
|
void Store( JSON_SETTINGS* aSettings) const override;
|
2020-06-08 02:19:46 +00:00
|
|
|
|
|
|
|
virtual void SetDefault() override
|
|
|
|
{
|
|
|
|
*m_ptr = m_default;
|
|
|
|
}
|
|
|
|
|
2021-06-04 03:52:50 +00:00
|
|
|
bool MatchesFile( JSON_SETTINGS* aSettings ) const override;
|
2020-06-08 02:19:46 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
std::map<wxString, wxString>* m_ptr;
|
2024-01-31 12:18:01 +00:00
|
|
|
std::map<wxString, wxString> m_default;
|
2020-06-08 02:19:46 +00:00
|
|
|
};
|
|
|
|
|
2020-01-13 01:44:19 +00:00
|
|
|
#endif
|