KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_tablecell.cpp
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
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU 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, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <advanced_config.h>
25#include <common.h>
26#include <sch_edit_frame.h>
27#include <widgets/msgpanel.h>
28#include <string_utils.h>
29#include <sch_table.h>
30#include <sch_tablecell.h>
31
32
33SCH_TABLECELL::SCH_TABLECELL( int aLineWidth, FILL_T aFillType ) :
34 SCH_TEXTBOX( LAYER_NOTES, aLineWidth, aFillType, wxEmptyString, SCH_TABLECELL_T ),
35 m_colSpan( 1 ),
36 m_rowSpan( 1 )
37{
38}
39
40
42{
43 SCH_TEXTBOX::swapData( aItem );
44
45 SCH_TABLECELL* cell = static_cast<SCH_TABLECELL*>( aItem );
46
47 std::swap( m_colSpan, cell->m_colSpan );
48 std::swap( m_rowSpan, cell->m_rowSpan );
49}
50
51
52wxString SCH_TABLECELL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
53{
54 return wxString::Format( _( "Table Cell %s" ), GetAddr() );
55}
56
57
59{
60 const SCH_TABLE* table = static_cast<const SCH_TABLE*>( GetParent() );
61
62 for( int row = 0; row < table->GetRowCount(); ++row )
63 {
64 for( int col = 0; col < table->GetColCount(); ++col )
65 {
66 if( table->GetCell( row, col ) == this )
67 return row;
68 }
69 }
70
71 return -1;
72}
73
74
76{
77 const SCH_TABLE* table = static_cast<const SCH_TABLE*>( GetParent() );
78
79 for( int row = 0; row < table->GetRowCount(); ++row )
80 {
81 for( int col = 0; col < table->GetColCount(); ++col )
82 {
83 if( table->GetCell( row, col ) == this )
84 return col;
85 }
86 }
87
88 return -1;
89}
90
91
92wxString SCH_TABLECELL::GetAddr() const
93{
94 return wxString::Format( wxT( "%c%d" ), 'A' + GetColumn() % 26, GetRow() );
95}
96
97
108static bool parseCellAddress( const wxString& aAddr, int& aRow, int& aCol )
109{
110 if( aAddr.IsEmpty() )
111 return false;
112
113 // Extract column part (letters) and row part (numbers)
114 size_t i = 0;
115 wxString colPart;
116
117 // Read column letters (A-Z, AA-ZZ, etc.)
118 while( i < aAddr.Length() && wxIsalpha( aAddr[i] ) )
119 {
120 colPart += wxToupper( aAddr[i] );
121 i++;
122 }
123
124 // Must have at least one letter
125 if( colPart.IsEmpty() )
126 return false;
127
128 // Convert column letters to 0-based index (A=0, B=1, ..., Z=25, AA=26, AB=27, etc.)
129 aCol = 0;
130 for( size_t j = 0; j < colPart.Length(); j++ )
131 {
132 aCol = aCol * 26 + ( colPart[j] - 'A' + 1 );
133 }
134 aCol -= 1; // Convert to 0-based
135
136 // Read row number (0-based)
137 wxString rowPart = aAddr.Mid( i );
138 if( rowPart.IsEmpty() )
139 return false;
140
141 // Convert row string to number (already 0-based in address string)
142 long rowNum;
143 if( !rowPart.ToLong( &rowNum ) || rowNum < 0 )
144 return false;
145
146 aRow = rowNum; // Already 0-based
147
148 return true;
149}
150
151
152wxString SCH_TABLECELL::GetShownText( const RENDER_SETTINGS* aSettings, const SCH_SHEET_PATH* aPath,
153 bool aAllowExtraText, int aDepth ) const
154{
155 // Local depth counter for ResolveTextVars iteration tracking (separate from cross-cell aDepth)
156 int depth = 0;
157
158 SCH_SHEET* sheet = nullptr;
159
160 if( aPath )
161 sheet = aPath->Last();
162
163 // Text variable resolver supporting:
164 // - ${ROW}, ${COL}, ${ADDR} - cell position variables
165 // - @{expression} - math expression evaluation
166 // - ${CELL("A1")} or ${CELL(row,col)} - reference to another cell's evaluated text
167 // - \${...} and \@{...} - escape sequences for literal display
168 std::function<bool( wxString* )> tableCellResolver = [&]( wxString* token ) -> bool
169 {
170 if( token->IsSameAs( wxT( "ROW" ) ) )
171 {
172 *token = wxString::Format( wxT( "%d" ), GetRow() ); // 0-based
173 return true;
174 }
175 else if( token->IsSameAs( wxT( "COL" ) ) )
176 {
177 *token = wxString::Format( wxT( "%d" ), GetColumn() ); // 0-based
178 return true;
179 }
180 else if( token->IsSameAs( wxT( "ADDR" ) ) )
181 {
182 *token = GetAddr();
183 return true;
184 }
185 else if( token->StartsWith( wxT( "CELL(" ) ) && token->EndsWith( wxT( ")" ) ) )
186 {
187 // Handle CELL("A0") or CELL(0, 1) syntax
188 wxString args = token->Mid( 5, token->Length() - 6 ); // Extract arguments
189 args.Trim( true ).Trim( false ); // Remove whitespace
190
191 SCH_TABLE* table = static_cast<SCH_TABLE*>( GetParent() );
192 if( !table )
193 {
194 *token = wxT( "<Unresolved: CELL() requires table context>" );
195 return true;
196 }
197
198 int targetRow = -1;
199 int targetCol = -1;
200
201 // Check if it's cell("A1") format (string argument with quotes)
202 if( args.StartsWith( wxT( "\"" ) ) && args.EndsWith( wxT( "\"" ) ) )
203 {
204 wxString addr = args.Mid( 1, args.Length() - 2 ); // Remove quotes
205 if( !parseCellAddress( addr, targetRow, targetCol ) )
206 {
207 *token = wxString::Format( wxT( "<Unresolved: Invalid cell address: %s>" ), addr );
208 return true;
209 }
210 }
211 // Check if it's cell(row, col) format (two numeric arguments)
212 else if( args.Find( ',' ) != wxNOT_FOUND )
213 {
214 wxString rowStr = args.BeforeFirst( ',' ).Trim( true ).Trim( false );
215 wxString colStr = args.AfterFirst( ',' ).Trim( true ).Trim( false );
216
217 long rowNum, colNum;
218 if( !rowStr.ToLong( &rowNum ) || !colStr.ToLong( &colNum ) )
219 {
220 *token = wxString::Format( wxT( "<Unresolved: Invalid cell coordinates: %s>" ), args );
221 return true;
222 }
223
224 // Arguments are already 0-based
225 targetRow = rowNum;
226 targetCol = colNum;
227 }
228 else
229 {
230 *token = wxString::Format( wxT( "<Unresolved: Invalid CELL() syntax: %s>" ), args );
231 return true;
232 }
233
234 // Check bounds
235 if( targetRow < 0 || targetRow >= table->GetRowCount() || targetCol < 0
236 || targetCol >= table->GetColCount() )
237 {
238 wxString cellAddr;
239 if( targetRow >= 0 && targetCol >= 0 )
240 {
241 char colLetter = 'A' + ( targetCol % 26 );
242 cellAddr = wxString::Format( wxT( "%c%d" ), colLetter, targetRow );
243 }
244 else
245 {
246 cellAddr = args;
247 }
248 *token = wxString::Format( wxT( "<Unresolved: Cell %s not found>" ), cellAddr );
249 return true;
250 }
251
252 // Get the target cell and return its evaluated text
253 SCH_TABLECELL* targetCell = table->GetCell( targetRow, targetCol );
254 if( targetCell )
255 {
256 // Check for excessive recursion depth (circular references)
258 if( aDepth >= maxDepth )
259 {
260 *token = wxT( "<Circular reference>" );
261 return true;
262 }
263
264 *token = targetCell->GetShownText( aSettings, aPath, aAllowExtraText, aDepth + 1 );
265 return true;
266 }
267 else
268 {
269 *token = wxT( "<Unresolved: Cell not found>" );
270 return true;
271 }
272 }
273
274 // Fall back to sheet variables
275 if( sheet )
276 {
277 if( sheet->ResolveTextVar( aPath, token, depth + 1 ) )
278 return true;
279 }
280
281 return false;
282 };
283
284 wxString text = EDA_TEXT::GetShownText( aAllowExtraText, depth );
285
286 if( HasTextVars() )
287 text = ResolveTextVars( text, &tableCellResolver, depth );
288
289 VECTOR2I size = GetEnd() - GetStart();
290 int colWidth;
291
292 if( GetTextAngle().IsVertical() )
293 colWidth = abs( size.y ) - ( GetMarginTop() + GetMarginBottom() );
294 else
295 colWidth = abs( size.x ) - ( GetMarginLeft() + GetMarginRight() );
296
297 GetDrawFont( aSettings )
299
300 // Convert escape markers back to literal ${} and @{} for final display
301 // Only do this at the top level (aDepth == 0) to avoid premature unescaping in nested CELL() calls
302 if( aDepth == 0 )
303 {
304 text.Replace( wxT( "<<<ESC_DOLLAR:" ), wxT( "${" ) );
305 text.Replace( wxT( "<<<ESC_AT:" ), wxT( "@{" ) );
306 }
307
308 return text;
309}
310
311
313{
314 return static_cast<SCH_TABLE*>( GetParent() )->GetColWidth( GetColumn() );
315}
316
317
319{
320 SCH_TABLE* table = static_cast<SCH_TABLE*>( GetParent() );
321
322 table->SetColWidth( GetColumn(), aWidth );
323 table->Normalize();
324}
325
326
328{
329 return static_cast<SCH_TABLE*>( GetParent() )->GetRowHeight( GetRow() );
330}
331
332
334{
335 SCH_TABLE* table = static_cast<SCH_TABLE*>( GetParent() );
336
337 table->SetRowHeight( GetRow(), aHeight );
338 table->Normalize();
339}
340
341
342void SCH_TABLECELL::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, int aUnit,
343 int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
344{
345 const int cell_body_style = -1; // flage to disable box ouline plotting
346 if( m_colSpan >= 1 && m_rowSpan >= 1 )
347 SCH_TEXTBOX::Plot( aPlotter, aBackground, aPlotOpts, aUnit, cell_body_style, aOffset, aDimmed );
348}
349
350
351void SCH_TABLECELL::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
352{
353 aList.emplace_back( _( "Table Cell" ), GetAddr() );
354
355 // Don't use GetShownText() here; we want to show the user the variable references
356 aList.emplace_back( _( "Text" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
357
358 aList.emplace_back( _( "Cell Width" ), aFrame->MessageTextFromValue( std::abs( GetEnd().x - GetStart().x ) ) );
359 aList.emplace_back( _( "Cell Height" ), aFrame->MessageTextFromValue( std::abs( GetEnd().y - GetStart().y ) ) );
360
361 aList.emplace_back( _( "Font" ), GetFont() ? GetFont()->GetName() : _( "Default" ) );
362
363 wxString textStyle[] = { _( "Normal" ), _( "Italic" ), _( "Bold" ), _( "Bold Italic" ) };
364 int style = IsBold() && IsItalic() ? 3 : IsBold() ? 2 : IsItalic() ? 1 : 0;
365 aList.emplace_back( _( "Style" ), textStyle[style] );
366
367 aList.emplace_back( _( "Text Size" ), aFrame->MessageTextFromValue( GetTextWidth() ) );
368}
369
370
371double SCH_TABLECELL::Similarity( const SCH_ITEM& aOtherItem ) const
372{
373 if( aOtherItem.Type() != Type() )
374 return 0.0;
375
376 const SCH_TABLECELL& other = static_cast<const SCH_TABLECELL&>( aOtherItem );
377
378 double similarity = 1.0;
379
380 if( m_colSpan != other.m_colSpan )
381 similarity *= 0.9;
382
383 if( m_rowSpan != other.m_rowSpan )
384 similarity *= 0.9;
385
386 similarity *= SCH_TEXTBOX::Similarity( other );
387
388 return similarity;
389}
390
391
392bool SCH_TABLECELL::operator==( const SCH_ITEM& aOtherItem ) const
393{
394 if( aOtherItem.Type() != Type() )
395 return false;
396
397 const SCH_TABLECELL& other = static_cast<const SCH_TABLECELL&>( aOtherItem );
398
399 return *this == other;
400}
401
402
403bool SCH_TABLECELL::operator==( const SCH_TABLECELL& aOtherItem ) const
404{
405 return m_colSpan == aOtherItem.m_colSpan && m_rowSpan == aOtherItem.m_rowSpan
406 && SCH_TEXTBOX::operator==( aOtherItem );
407}
408
409
411{
413 {
416
425
426 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Start X" ) );
427 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Start Y" ) );
428 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "End X" ) );
429 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "End Y" ) );
430
431 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Shape" ) );
432 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Width" ) );
433 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Height" ) );
434 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Fill" ) );
435 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Fill Color" ) );
436 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Line Width" ) );
437 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Line Style" ) );
438 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Line Color" ) );
439 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Corner Radius" ) );
440
441 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Width" ) );
442 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Height" ) );
443 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Thickness" ) );
444 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Orientation" ) );
445 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Mirrored" ) );
446 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Visible" ) );
447 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Hyperlink" ) );
448
449 const wxString tableProps = _( "Table" );
450
454 tableProps );
455
459 tableProps );
460
461 const wxString cellProps = _( "Cell Properties" );
462
463 propMgr.AddProperty( new PROPERTY<EDA_SHAPE, bool>( _HKI( "Background Fill" ), &EDA_SHAPE::SetFilled,
465 cellProps );
466
467 propMgr.AddProperty( new PROPERTY<EDA_SHAPE, COLOR4D>( _HKI( "Background Fill Color" ),
469 cellProps )
471 }
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
The base class for create windows for drawing purpose.
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
EDA_ITEM * GetParent() const
Definition eda_item.h:112
virtual void SetFilled(bool aFlag)
Definition eda_shape.h:136
void SetFillColor(const COLOR4D &aColor)
Definition eda_shape.h:153
bool IsSolidFill() const
Definition eda_shape.h:117
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:215
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:173
COLOR4D GetFillColor() const
Definition eda_shape.h:152
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:80
bool IsItalic() const
Definition eda_text.h:169
const EDA_ANGLE & GetTextAngle() const
Definition eda_text.h:147
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:98
KIFONT::FONT * GetFont() const
Definition eda_text.h:247
int GetTextWidth() const
Definition eda_text.h:264
bool HasTextVars() const
Indicates the ShownText has text var references which need to be processed.
Definition eda_text.h:117
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
Definition eda_text.cpp:473
bool IsBold() const
Definition eda_text.h:184
virtual wxString GetShownText(bool aAllowExtraText, int aDepth=0) const
Return the string actually shown after processing of the base text.
Definition eda_text.h:109
VECTOR2I GetTextSize() const
Definition eda_text.h:261
void LinebreakText(wxString &aText, int aColumnWidth, const VECTOR2I &aGlyphSize, int aThickness, bool aBold, bool aItalic) const
Insert characters into text to ensure that no lines are wider than aColumnWidth.
Definition font.cpp:572
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
Base plotter engine class.
Definition plotter.h:136
PROPERTY_BASE & SetIsHiddenFromRulesEditor(bool aHide=true)
Definition property.h:326
Provide class metadata.Helper macro to map type hashes to names.
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
void Mask(TYPE_ID aDerived, TYPE_ID aBase, const wxString &aName)
Sets a base class property as masked in a derived class.
static PROPERTY_MANAGER & Instance()
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
void AddTypeCast(TYPE_CAST_BASE *aCast)
Register a type converter.
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:51
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:47
bool ResolveTextVar(const SCH_SHEET_PATH *aPath, wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the sheet.
double Similarity(const SCH_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
int GetRowHeight() const
void swapData(SCH_ITEM *aItem) override
Swap the internal data structures aItem with the schematic item.
SCH_TABLECELL(int aLineWidth=0, FILL_T aFillType=FILL_T::NO_FILL)
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
wxString GetAddr() const
bool operator==(const SCH_TABLECELL &aOther) const
wxString GetShownText(const RENDER_SETTINGS *aSettings, const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const override
void SetColumnWidth(int aWidth)
int GetColumn() const
void Plot(PLOTTER *aPlotter, bool aBackground, const SCH_PLOT_OPTS &aPlotOpts, int aUnit, int aBodyStyle, const VECTOR2I &aOffset, bool aDimmed) override
Plot the item to aPlotter.
void SetRowHeight(int aHeight)
int GetColumnWidth() const
int GetRow() const
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
int GetMarginBottom() const
Definition sch_textbox.h:66
bool operator==(const SCH_ITEM &aOther) const override
int GetMarginLeft() const
Definition sch_textbox.h:63
int GetMarginRight() const
Definition sch_textbox.h:65
void Plot(PLOTTER *aPlotter, bool aBackground, const SCH_PLOT_OPTS &aPlotOpts, int aUnit, int aBodyStyle, const VECTOR2I &aOffset, bool aDimmed) override
Plot the item to aPlotter.
int GetMarginTop() const
Definition sch_textbox.h:64
void swapData(SCH_ITEM *aItem) override
Swap the internal data structures aItem with the schematic item.
KIFONT::FONT * GetDrawFont(const RENDER_SETTINGS *aSettings) const override
SCH_TEXTBOX(SCH_LAYER_ID aLayer=LAYER_NOTES, int aLineWidth=0, FILL_T aFillType=FILL_T::NO_FILL, const wxString &aText=wxEmptyString, KICAD_T aType=SCH_TEXTBOX_T)
double Similarity(const SCH_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
wxString ResolveTextVars(const wxString &aSource, const std::function< bool(wxString *)> *aResolver, int &aDepth)
Multi-pass text variable expansion and math expression evaluation.
Definition common.cpp:247
The common library.
#define _(s)
FILL_T
Definition eda_shape.h:56
int m_ResolveTextRecursionDepth
The number of recursions to resolve text variables.
@ LAYER_NOTES
Definition layer_ids.h:467
Message panel definition file.
KICOMMON_API wxString EllipsizeStatusText(wxWindow *aWindow, const wxString &aString)
Ellipsize text (at the end) to be no more than 1/3 of the window width.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:400
#define _HKI(x)
Definition page_info.cpp:44
#define TYPE_HASH(x)
Definition property.h:74
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition property.h:63
#define REGISTER_TYPE(x)
static struct SCH_TABLECELL_DESC _SCH_TABLECELL_DESC
static bool parseCellAddress(const wxString &aAddr, int &aRow, int &aCol)
Parse a cell address string like "A0" or "B12" into 0-based row and column indices.
@ SCH_TABLECELL_T
Definition typeinfo.h:170
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695