KiCad PCB EDA Suite
Loading...
Searching...
No Matches
api_generated_table_utils.h
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#ifndef API_GENERATED_TABLE_UTILS_H
21#define API_GENERATED_TABLE_UTILS_H
22
23#include <algorithm>
24#include <cstdint>
25#include <type_traits>
26
27#include <api/api_utils.h>
28#include <base_units.h>
29#include <pcb_generated_table.h>
30
31#include <google/protobuf/any.pb.h>
32
33
41template <typename MSG>
42void PackGeneratedTable( const PCB_GENERATED_TABLE& aTable, MSG& aMsg )
43{
44 google::protobuf::Any tableAny;
45 aTable.PCB_TABLE::Serialize( tableAny );
46 tableAny.UnpackTo( aMsg.mutable_table() );
47
48 for( const GENERATED_TABLE_COLUMN& col : aTable.Columns() )
49 {
50 auto* proto = aMsg.add_columns();
51
52 using ID = std::remove_cvref_t<decltype( proto->id() )>;
53 using ALIGN = std::remove_cvref_t<decltype( proto->align() )>;
54
55 proto->set_id( static_cast<ID>( col.m_Id + 1 ) );
56 proto->set_heading( col.m_Heading.ToStdString() );
57 proto->set_align( static_cast<ALIGN>( static_cast<int>( col.m_Align ) + 1 ) );
58 kiapi::common::PackDistance( *proto->mutable_width(), col.m_Width );
59 }
60
61 switch( aTable.GetUnits() )
62 {
63 case GENERATED_TABLE_UNITS::MM: aMsg.set_units( kiapi::common::types::U_MM ); break;
64 case GENERATED_TABLE_UNITS::INCH: aMsg.set_units( kiapi::common::types::U_INCH ); break;
65 case GENERATED_TABLE_UNITS::MILS: aMsg.set_units( kiapi::common::types::U_MILS ); break;
66 }
67
68 aMsg.set_precision( aTable.GetPrecision() );
69
70 for( const auto& [row, key] : aTable.RowKeys() )
71 ( *aMsg.mutable_row_keys() )[row] = key;
72}
73
74
80template <typename MSG>
81bool UnpackGeneratedTable( const MSG& aMsg, PCB_GENERATED_TABLE& aTable )
82{
83 google::protobuf::Any tableAny;
84 tableAny.PackFrom( aMsg.table() );
85
86 if( !aTable.PCB_TABLE::Deserialize( tableAny ) )
87 return false;
88
89 // The table carries the layer. A table on a manufacturing layer would be plotted into a
90 // fabrication output rather than the documentation
91 if( !DocumentationLayers().Contains( aTable.GetLayer() ) )
92 return false;
93
94 std::vector<GENERATED_TABLE_COLUMN>& columns = aTable.Columns();
95 columns.clear();
96
97 for( const auto& proto : aMsg.columns() )
98 {
99 const int wireId = static_cast<int>( proto.id() );
100
101 // Zero is the unset value. A negative id is refused before the offset can overflow
102 if( wireId == 0 )
103 continue;
104
105 if( wireId < 0 )
106 return false;
107
108 const int id = wireId - 1;
109
110 if( !aTable.Schema().Find( id ) )
111 return false;
112
113 const int align = static_cast<int>( proto.align() );
114
115 if( align < 0 || align > static_cast<int>( GENERATED_TABLE_ALIGN::RIGHT ) + 1 )
116 return false;
117
119 col.m_Id = id;
120 col.m_Heading = wxString::FromUTF8( proto.heading() );
121
122 if( align > 0 )
123 col.m_Align = static_cast<GENERATED_TABLE_ALIGN>( align - 1 );
124
125 kiapi::common::types::Distance width;
126 width.set_value_nm( std::clamp<int64_t>( proto.width().value_nm(), 0,
129 columns.push_back( col );
130 }
131
132 // No columns divides by zero the next time this is rebuilt or autosized. Repeats and
133 // implausible widths reach table geometry
134 if( !aTable.Schema().Validate( columns ) )
135 return false;
136
137 // The shared enum also carries metres and tenths. A table has no rendering for those, so
138 // anything but inches or mils reads back as millimetres rather than as a broken table
139 switch( aMsg.units() )
140 {
141 case kiapi::common::types::U_INCH: aTable.SetUnits( GENERATED_TABLE_UNITS::INCH ); break;
142 case kiapi::common::types::U_MILS: aTable.SetUnits( GENERATED_TABLE_UNITS::MILS ); break;
143 default: aTable.SetUnits( GENERATED_TABLE_UNITS::MM ); break;
144 }
145
146 aTable.RowKeys().clear();
147
148 for( const auto& [row, key] : aMsg.row_keys() )
149 aTable.RowKeys()[row] = key;
150
151 aTable.SetPrecision( aMsg.precision() );
152
153 return true;
154}
155
156#endif // API_GENERATED_TABLE_UTILS_H
void PackGeneratedTable(const PCB_GENERATED_TABLE &aTable, MSG &aMsg)
Pack what every generated table shares into its message.
bool UnpackGeneratedTable(const MSG &aMsg, PCB_GENERATED_TABLE &aTable)
The reverse of PackGeneratedTable.
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:128
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
const GENERATED_TABLE_COLUMN_DEF * Find(int aId) const
bool Validate(std::vector< GENERATED_TABLE_COLUMN > &aColumns) const
Drop a column whose id the schema does not know and a column that repeats an id already kept,...
A table whose cell text is derived from the board and rebuilt whenever it goes stale.
const std::map< int, std::string > & RowKeys() const
What each generated row reports on, by table row.
void SetPrecision(int aPrecision)
Clamped.
std::vector< GENERATED_TABLE_COLUMN > & Columns()
virtual const GENERATED_TABLE_SCHEMA & Schema() const =0
GENERATED_TABLE_UNITS GetUnits() const
void SetUnits(GENERATED_TABLE_UNITS aUnits)
LSET DocumentationLayers()
Layers a drill chart or drill map may live on.
constexpr int GENERATED_TABLE_MAX_COLUMN_WIDTH
A column can be no wider than this.
GENERATED_TABLE_ALIGN
KICOMMON_API int UnpackDistance(const types::Distance &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void PackDistance(types::Distance &aOutput, int aInput, const EDA_IU_SCALE &aScale)
A column as a generated table actually carries it: what a row's cell in that column holds and how it ...
GENERATED_TABLE_ALIGN m_Align