28#include <wx/translation.h>
57 std::set<DRILL_CHART_COLUMN_ID> seen;
63 if( !seen.insert( col.m_Id ).second )
95const struct DEFAULT_COLUMN
100} g_defaultColumns[] = {
114 for(
const DEFAULT_COLUMN& def : g_defaultColumns )
119 aColumn.
m_Id = def.id;
120 aColumn.
m_Heading = wxString::FromUTF8( def.heading );
133 tmpl.
SetName( wxT(
"Default" ) );
135 for(
const DEFAULT_COLUMN& def : g_defaultColumns )
139 tmpl.
Columns().push_back( col );
154const CHART_TOKEN unitsTokens[] = {
159const CHART_TOKEN columnTokens[] = {
174const CHART_TOKEN alignTokens[] = {
181const char* chartTokenFor(
const CHART_TOKEN ( &aMap )[
N],
int aValue )
183 for(
const CHART_TOKEN& entry : aMap )
185 if( entry.value == aValue )
189 return aMap[0].token;
193bool chartValueFor(
const CHART_TOKEN ( &aMap )[
N],
const wxString& aToken,
int& aValue )
195 for(
const CHART_TOKEN& entry : aMap )
197 if( aToken.IsSameAs( wxString::FromUTF8( entry.token ) ) )
199 aValue = entry.value;
211 return chartTokenFor( unitsTokens, (
int) aUnits );
217 return chartTokenFor( columnTokens, (
int) aId );
223 return chartTokenFor( alignTokens, (
int) aAlign );
231 if( !chartValueFor( unitsTokens, aToken, v ) )
243 if( !chartValueFor( columnTokens, aToken, v ) )
255 if( !chartValueFor( alignTokens, aToken, v ) )
266 js[
"name"] =
m_name.ToUTF8();
271 js[
"columns"] = nlohmann::json::array();
275 nlohmann::json entry;
277 entry[
"heading"] = col.m_Heading.ToUTF8();
279 entry[
"width"] = col.m_Width;
280 js[
"columns"].push_back( entry );
285 std::ofstream out( aPath.fn_str() );
290 *aError = wxString::Format(
_(
"Cannot write '%s'." ), aPath );
295 out << js.dump( 2 ) << std::endl;
302 *aError = wxString::Format(
_(
"Error writing '%s'." ), aPath );
307 catch(
const std::exception& e )
310 *aError = wxString::FromUTF8( e.what() );
327 std::ifstream in( aPath.fn_str() );
332 *aError = wxString::Format(
_(
"Cannot read '%s'." ), aPath );
340 if( !js.is_object() )
343 *aError =
_(
"Template is not a JSON object." );
348 if( js.contains(
"name" ) && js[
"name"].is_string() )
349 loaded.
m_name = wxString::FromUTF8( js[
"name"].get<std::string>() );
351 if( js.contains(
"version" ) && js[
"version"].is_number_integer() )
352 loaded.
m_version = js[
"version"].get<
int>();
354 if( js.contains(
"units" ) && js[
"units"].is_string() )
360 if( js.contains(
"precision" ) && js[
"precision"].is_number_integer() )
361 loaded.
m_precision = std::clamp( js[
"precision"].get<int>(), 0, 6 );
363 if( js.contains(
"show_totals" ) && js[
"show_totals"].is_boolean() )
366 if( js.contains(
"columns" ) && js[
"columns"].is_array() )
368 for(
const nlohmann::json& entry : js[
"columns"] )
370 if( !entry.is_object() || !entry.contains(
"id" ) || !entry[
"id"].is_string() )
383 if( entry.contains(
"heading" ) && entry[
"heading"].is_string() )
384 col.
m_Heading = wxString::FromUTF8( entry[
"heading"].get<std::string>() );
386 if( entry.contains(
"align" ) && entry[
"align"].is_string() )
392 if( entry.contains(
"width" ) && entry[
"width"].is_number_integer() )
393 col.
m_Width = entry[
"width"].get<
int>();
399 catch(
const std::exception& e )
402 *aError = wxString::FromUTF8( e.what() );
410 *aError =
_(
"Template has no usable columns." );
415 *
this = std::move( loaded );
BASE_SET & reset(size_t pos)
bool SaveToFile(const wxString &aPath, wxString *aError) const
Read and write a template as JSON.
void SetName(const wxString &aName)
wxString m_name
Identify the template file to whoever opens it.
bool LoadFromFile(const wxString &aPath, wxString *aError)
std::vector< DRILL_CHART_COLUMN > & Columns()
static DRILL_CHART_TEMPLATE MakeDefault()
std::vector< DRILL_CHART_COLUMN > m_columns
DRILL_CHART_UNITS m_units
LSET is a set of PCB_LAYER_IDs.
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
const char * DrillChartColumnToken(DRILL_CHART_COLUMN_ID aId)
bool DrillChartAlignFromToken(const wxString &aToken, DRILL_CHART_ALIGN &aAlign)
bool DrillChartDefaultColumn(DRILL_CHART_COLUMN_ID aId, DRILL_CHART_COLUMN &aColumn)
The heading and alignment a column starts with, so the writer can leave them out of the file and the ...
bool ValidateDrillChartColumns(std::vector< DRILL_CHART_COLUMN > &aColumns)
Reject a column set that repeats an id or is implausibly wide.
bool DrillChartUnitsFromToken(const wxString &aToken, DRILL_CHART_UNITS &aUnits)
const char * DrillChartUnitsToken(DRILL_CHART_UNITS aUnits)
Stable file tokens, independent of enum ordering so inserting a value later cannot change what an exi...
LSET DrillDocumentationLayers()
Layers a chart or map may live on.
bool DrillChartColumnFromToken(const wxString &aToken, DRILL_CHART_COLUMN_ID &aId)
const char * DrillChartAlignToken(DRILL_CHART_ALIGN aAlign)
const char * DrillChartColumnToken(DRILL_CHART_COLUMN_ID aId)
bool DrillChartAlignFromToken(const wxString &aToken, DRILL_CHART_ALIGN &aAlign)
constexpr int DRILL_CHART_MAX_COLUMN_WIDTH
A chart column can be no wider than this, and no chart wider than that in total.
bool DrillChartDefaultColumn(DRILL_CHART_COLUMN_ID aId, DRILL_CHART_COLUMN &aColumn)
The heading and alignment a column starts with, so the writer can leave them out of the file and the ...
bool ValidateDrillChartColumns(std::vector< DRILL_CHART_COLUMN > &aColumns)
Reject a column set that repeats an id or is implausibly wide.
constexpr int64_t DRILL_CHART_MAX_TOTAL_WIDTH
bool DrillChartUnitsFromToken(const wxString &aToken, DRILL_CHART_UNITS &aUnits)
const char * DrillChartUnitsToken(DRILL_CHART_UNITS aUnits)
Stable file tokens, independent of enum ordering so inserting a value later cannot change what an exi...
bool DrillChartColumnFromToken(const wxString &aToken, DRILL_CHART_COLUMN_ID &aId)
const char * DrillChartAlignToken(DRILL_CHART_ALIGN aAlign)
bool operator==(const DRILL_CHART_COLUMN &aOther) const
DRILL_CHART_COLUMN_ID m_Id
DRILL_CHART_ALIGN m_Align
Which holes a chart reports on.
bool operator==(const DRILL_CHART_FILTER &aOther) const