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#include <properties/property.h>
33
34
35SCH_TABLECELL::SCH_TABLECELL( int aLineWidth, FILL_T aFillType ) :
36 SCH_TEXTBOX( LAYER_NOTES, aLineWidth, aFillType, wxEmptyString, SCH_TABLECELL_T ),
37 m_colSpan( 1 ),
38 m_rowSpan( 1 )
39{
40}
41
42
44{
45 SCH_TEXTBOX::swapData( aItem );
46
47 SCH_TABLECELL* cell = static_cast<SCH_TABLECELL*>( aItem );
48
49 std::swap( m_colSpan, cell->m_colSpan );
50 std::swap( m_rowSpan, cell->m_rowSpan );
51}
52
53
54wxString SCH_TABLECELL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
55{
56 return wxString::Format( _( "Table Cell %s" ), GetAddr() );
57}
58
59
61{
62 const SCH_TABLE* table = static_cast<const SCH_TABLE*>( GetParent() );
63
64 for( int row = 0; row < table->GetRowCount(); ++row )
65 {
66 for( int col = 0; col < table->GetColCount(); ++col )
67 {
68 if( table->GetCell( row, col ) == this )
69 return row;
70 }
71 }
72
73 return -1;
74}
75
76
78{
79 const SCH_TABLE* table = static_cast<const SCH_TABLE*>( GetParent() );
80
81 for( int row = 0; row < table->GetRowCount(); ++row )
82 {
83 for( int col = 0; col < table->GetColCount(); ++col )
84 {
85 if( table->GetCell( row, col ) == this )
86 return col;
87 }
88 }
89
90 return -1;
91}
92
93
94wxString SCH_TABLECELL::GetAddr() const
95{
96 return wxString::Format( wxT( "%c%d" ), 'A' + GetColumn() % 26, GetRow() );
97}
98
99
110static bool parseCellAddress( const wxString& aAddr, int& aRow, int& aCol )
111{
112 if( aAddr.IsEmpty() )
113 return false;
114
115 // Extract column part (letters) and row part (numbers)
116 size_t i = 0;
117 wxString colPart;
118
119 // Read column letters (A-Z, AA-ZZ, etc.)
120 while( i < aAddr.Length() && wxIsalpha( aAddr[i] ) )
121 {
122 colPart += wxToupper( aAddr[i] );
123 i++;
124 }
125
126 // Must have at least one letter
127 if( colPart.IsEmpty() )
128 return false;
129
130 // Convert column letters to 0-based index (A=0, B=1, ..., Z=25, AA=26, AB=27, etc.)
131 aCol = 0;
132 for( size_t j = 0; j < colPart.Length(); j++ )
133 {
134 aCol = aCol * 26 + ( colPart[j] - 'A' + 1 );
135 }
136 aCol -= 1; // Convert to 0-based
137
138 // Read row number (0-based)
139 wxString rowPart = aAddr.Mid( i );
140 if( rowPart.IsEmpty() )
141 return false;
142
143 // Convert row string to number (already 0-based in address string)
144 long rowNum;
145 if( !rowPart.ToLong( &rowNum ) || rowNum < 0 )
146 return false;
147
148 aRow = rowNum; // Already 0-based
149
150 return true;
151}
152
153
154wxString SCH_TABLECELL::GetShownText( const RENDER_SETTINGS* aSettings, const SCH_SHEET_PATH* aPath,
155 bool aAllowExtraText, int aDepth ) const
156{
157 // Local depth counter for ResolveTextVars iteration tracking (separate from cross-cell aDepth)
158 int depth = 0;
159
160 SCH_SHEET* sheet = nullptr;
161
162 if( aPath )
163 sheet = aPath->Last();
164
165 // Text variable resolver supporting:
166 // - ${ROW}, ${COL}, ${ADDR} - cell position variables
167 // - @{expression} - math expression evaluation
168 // - ${CELL("A1")} or ${CELL(row,col)} - reference to another cell's evaluated text
169 // - \${...} and \@{...} - escape sequences for literal display
170 std::function<bool( wxString* )> tableCellResolver = [&]( wxString* token ) -> bool
171 {
172 if( token->IsSameAs( wxT( "ROW" ) ) )
173 {
174 *token = wxString::Format( wxT( "%d" ), GetRow() ); // 0-based
175 return true;
176 }
177 else if( token->IsSameAs( wxT( "COL" ) ) )
178 {
179 *token = wxString::Format( wxT( "%d" ), GetColumn() ); // 0-based
180 return true;
181 }
182 else if( token->IsSameAs( wxT( "ADDR" ) ) )
183 {
184 *token = GetAddr();
185 return true;
186 }
187 else if( token->StartsWith( wxT( "CELL(" ) ) && token->EndsWith( wxT( ")" ) ) )
188 {
189 // Handle CELL("A0") or CELL(0, 1) syntax
190 wxString args = token->Mid( 5, token->Length() - 6 ); // Extract arguments
191 args.Trim( true ).Trim( false ); // Remove whitespace
192
193 SCH_TABLE* table = static_cast<SCH_TABLE*>( GetParent() );
194 if( !table )
195 {
196 *token = wxT( "<Unresolved: CELL() requires table context>" );
197 return true;
198 }
199
200 int targetRow = -1;
201 int targetCol = -1;
202
203 // Check if it's cell("A1") format (string argument with quotes)
204 if( args.StartsWith( wxT( "\"" ) ) && args.EndsWith( wxT( "\"" ) ) )
205 {
206 wxString addr = args.Mid( 1, args.Length() - 2 ); // Remove quotes
207 if( !parseCellAddress( addr, targetRow, targetCol ) )
208 {
209 *token = wxString::Format( wxT( "<Unresolved: Invalid cell address: %s>" ), addr );
210 return true;
211 }
212 }
213 // Check if it's cell(row, col) format (two numeric arguments)
214 else if( args.Find( ',' ) != wxNOT_FOUND )
215 {
216 wxString rowStr = args.BeforeFirst( ',' ).Trim( true ).Trim( false );
217 wxString colStr = args.AfterFirst( ',' ).Trim( true ).Trim( false );
218
219 long rowNum, colNum;
220 if( !rowStr.ToLong( &rowNum ) || !colStr.ToLong( &colNum ) )
221 {
222 *token = wxString::Format( wxT( "<Unresolved: Invalid cell coordinates: %s>" ), args );
223 return true;
224 }
225
226 // Arguments are already 0-based
227 targetRow = rowNum;
228 targetCol = colNum;
229 }
230 else
231 {
232 *token = wxString::Format( wxT( "<Unresolved: Invalid CELL() syntax: %s>" ), args );
233 return true;
234 }
235
236 // Check bounds
237 if( targetRow < 0 || targetRow >= table->GetRowCount() || targetCol < 0
238 || targetCol >= table->GetColCount() )
239 {
240 wxString cellAddr;
241 if( targetRow >= 0 && targetCol >= 0 )
242 {
243 char colLetter = 'A' + ( targetCol % 26 );
244 cellAddr = wxString::Format( wxT( "%c%d" ), colLetter, targetRow );
245 }
246 else
247 {
248 cellAddr = args;
249 }
250 *token = wxString::Format( wxT( "<Unresolved: Cell %s not found>" ), cellAddr );
251 return true;
252 }
253
254 // Get the target cell and return its evaluated text
255 SCH_TABLECELL* targetCell = table->GetCell( targetRow, targetCol );
256 if( targetCell )
257 {
258 // Check for excessive recursion depth (circular references)
260 if( aDepth >= maxDepth )
261 {
262 *token = wxT( "<Circular reference>" );
263 return true;
264 }
265
266 *token = targetCell->GetShownText( aSettings, aPath, aAllowExtraText, aDepth + 1 );
267 return true;
268 }
269 else
270 {
271 *token = wxT( "<Unresolved: Cell not found>" );
272 return true;
273 }
274 }
275
276 // Fall back to sheet variables
277 if( sheet )
278 {
279 if( sheet->ResolveTextVar( aPath, token, depth + 1 ) )
280 return true;
281 }
282
283 return false;
284 };
285
286 wxString text = EDA_TEXT::GetShownText( aAllowExtraText, depth );
287
288 if( HasTextVars() )
289 text = ResolveTextVars( text, &tableCellResolver, depth );
290
291 VECTOR2I size = GetEnd() - GetStart();
292 int colWidth;
293
294 if( GetTextAngle().IsVertical() )
295 colWidth = abs( size.y ) - ( GetMarginTop() + GetMarginBottom() );
296 else
297 colWidth = abs( size.x ) - ( GetMarginLeft() + GetMarginRight() );
298
299 GetDrawFont( aSettings )
301
302 // Convert escape markers back to literal ${} and @{} for final display
303 // Only do this at the top level (aDepth == 0) to avoid premature unescaping in nested CELL() calls
304 if( aDepth == 0 )
305 {
306 text.Replace( wxT( "<<<ESC_DOLLAR:" ), wxT( "${" ) );
307 text.Replace( wxT( "<<<ESC_AT:" ), wxT( "@{" ) );
308 }
309
310 return text;
311}
312
313
315{
316 return static_cast<SCH_TABLE*>( GetParent() )->GetColWidth( GetColumn() );
317}
318
319
321{
322 SCH_TABLE* table = static_cast<SCH_TABLE*>( GetParent() );
323
324 table->SetColWidth( GetColumn(), aWidth );
325 table->Normalize();
326}
327
328
330{
331 return static_cast<SCH_TABLE*>( GetParent() )->GetRowHeight( GetRow() );
332}
333
334
336{
337 SCH_TABLE* table = static_cast<SCH_TABLE*>( GetParent() );
338
339 table->SetRowHeight( GetRow(), aHeight );
340 table->Normalize();
341}
342
343
344void SCH_TABLECELL::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, int aUnit,
345 int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
346{
347 const int cell_body_style = -1; // flag to disable box ouline plotting
348
349 if( m_colSpan >= 1 && m_rowSpan >= 1 )
350 SCH_TEXTBOX::Plot( aPlotter, aBackground, aPlotOpts, aUnit, cell_body_style, aOffset, aDimmed );
351}
352
353
354void SCH_TABLECELL::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
355{
356 aList.emplace_back( _( "Table Cell" ), GetAddr() );
357
358 // Don't use GetShownText() here; we want to show the user the variable references
359 aList.emplace_back( _( "Text" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
360
361 aList.emplace_back( _( "Cell Width" ), aFrame->MessageTextFromValue( std::abs( GetEnd().x - GetStart().x ) ) );
362 aList.emplace_back( _( "Cell Height" ), aFrame->MessageTextFromValue( std::abs( GetEnd().y - GetStart().y ) ) );
363
364 aList.emplace_back( _( "Font" ), GetFont() ? GetFont()->GetName() : _( "Default" ) );
365
366 wxString textStyle[] = { _( "Normal" ), _( "Italic" ), _( "Bold" ), _( "Bold Italic" ) };
367 int style = IsBold() && IsItalic() ? 3 : IsBold() ? 2 : IsItalic() ? 1 : 0;
368 aList.emplace_back( _( "Style" ), textStyle[style] );
369
370 aList.emplace_back( _( "Text Size" ), aFrame->MessageTextFromValue( GetTextWidth() ) );
371}
372
373
374double SCH_TABLECELL::Similarity( const SCH_ITEM& aOtherItem ) const
375{
376 if( aOtherItem.Type() != Type() )
377 return 0.0;
378
379 const SCH_TABLECELL& other = static_cast<const SCH_TABLECELL&>( aOtherItem );
380
381 double similarity = 1.0;
382
383 if( m_colSpan != other.m_colSpan )
384 similarity *= 0.9;
385
386 if( m_rowSpan != other.m_rowSpan )
387 similarity *= 0.9;
388
389 similarity *= SCH_TEXTBOX::Similarity( other );
390
391 return similarity;
392}
393
394
395bool SCH_TABLECELL::operator==( const SCH_ITEM& aOtherItem ) const
396{
397 if( aOtherItem.Type() != Type() )
398 return false;
399
400 const SCH_TABLECELL& other = static_cast<const SCH_TABLECELL&>( aOtherItem );
401
402 return *this == other;
403}
404
405
406bool SCH_TABLECELL::operator==( const SCH_TABLECELL& aOtherItem ) const
407{
408 return m_colSpan == aOtherItem.m_colSpan && m_rowSpan == aOtherItem.m_rowSpan
409 && SCH_TEXTBOX::operator==( aOtherItem );
410}
411
412
414{
416 {
419
428
429 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Start X" ) );
430 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Start Y" ) );
431 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "End X" ) );
432 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "End Y" ) );
433
434 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Shape" ) );
435 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Width" ) );
436 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Height" ) );
437 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Fill" ) );
438 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Fill Color" ) );
439 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Line Width" ) );
440 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Line Style" ) );
441 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Line Color" ) );
442 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Corner Radius" ) );
443
444 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Width" ) );
445 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Height" ) );
446 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Thickness" ) );
447 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Orientation" ) );
448 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Mirrored" ) );
449 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Visible" ) );
450 propMgr.Mask( TYPE_HASH( SCH_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Hyperlink" ) );
451
452 const wxString tableProps = _( "Table" );
453
457 tableProps );
458
462 tableProps );
463
464 const wxString cellProps = _( "Cell Properties" );
465
466 propMgr.AddProperty( new PROPERTY<EDA_SHAPE, bool>( _HKI( "Background Fill" ), &EDA_SHAPE::SetFilled,
468 cellProps );
469
470 propMgr.AddProperty( new PROPERTY<EDA_SHAPE, COLOR4D>( _HKI( "Background Fill Color" ),
472 cellProps )
474 }
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:111
EDA_ITEM * GetParent() const
Definition eda_item.h:113
virtual void SetFilled(bool aFlag)
Definition eda_shape.h:136
void SetFillColor(const COLOR4D &aColor)
Definition eda_shape.h:154
bool IsSolidFill() const
Definition eda_shape.h:117
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:216
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:174
COLOR4D GetFillColor() const
Definition eda_shape.h:153
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:479
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:609
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:56
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:48
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:73
bool operator==(const SCH_ITEM &aOther) const override
int GetMarginLeft() const
Definition sch_textbox.h:70
int GetMarginRight() const
Definition sch_textbox.h:72
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:71
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:296
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