You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1802 lines
56 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
7 months ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
  5. * Copyright (C) 2015 Wayne Stambaugh <stambaughw@gmail.com>
  6. * Copyright (C) 2018 CERN
  7. * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
  8. * @author Jon Evans <jon@craftyjon.com>
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License
  12. * as published by the Free Software Foundation; either version 2
  13. * of the License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, you may find one here:
  22. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  23. * or you may search the http://www.gnu.org website for the version 2 license,
  24. * or you may write to the Free Software Foundation, Inc.,
  25. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  26. */
  27. #include "sch_pin.h"
  28. #include <base_units.h>
  29. #include <pgm_base.h>
  30. #include <pin_layout_cache.h>
  31. #include <plotters/plotter.h>
  32. #include <sch_draw_panel.h>
  33. #include <sch_edit_frame.h>
  34. #include <symbol_edit_frame.h>
  35. #include <settings/settings_manager.h>
  36. #include <symbol_editor/symbol_editor_settings.h>
  37. #include <trigo.h>
  38. #include <string_utils.h>
  39. // small margin in internal units between the pin text and the pin line
  40. #define PIN_TEXT_MARGIN 4
  41. wxString SCH_PIN::GetCanonicalElectricalTypeName( ELECTRICAL_PINTYPE aType )
  42. {
  43. // These strings are the canonical name of the electrictal type
  44. // Not translated, no space in name, only ASCII chars.
  45. // to use when the string name must be known and well defined
  46. // must have same order than enum ELECTRICAL_PINTYPE (see sch_pin.h)
  47. static const wxChar* msgPinElectricType[] =
  48. {
  49. wxT( "input" ),
  50. wxT( "output" ),
  51. wxT( "bidirectional" ),
  52. wxT( "tri_state" ),
  53. wxT( "passive" ),
  54. wxT( "free" ),
  55. wxT( "unspecified" ),
  56. wxT( "power_in" ),
  57. wxT( "power_out" ),
  58. wxT( "open_collector" ),
  59. wxT( "open_emitter" ),
  60. wxT( "no_connect" )
  61. };
  62. return msgPinElectricType[static_cast<int>( aType )];
  63. }
  64. /// Utility for getting the size of the 'internal' pin decorators (as a radius)
  65. /// i.e. the clock symbols (falling clock is actually external but is of
  66. /// the same kind)
  67. static int internalPinDecoSize( const RENDER_SETTINGS* aSettings, const SCH_PIN &aPin )
  68. {
  69. const SCH_RENDER_SETTINGS* settings = static_cast<const SCH_RENDER_SETTINGS*>( aSettings );
  70. if( settings && settings->m_PinSymbolSize )
  71. return settings->m_PinSymbolSize;
  72. return aPin.GetNameTextSize() != 0 ? aPin.GetNameTextSize() / 2 : aPin.GetNumberTextSize() / 2;
  73. }
  74. /// Utility for getting the size of the 'external' pin decorators (as a radius)
  75. /// i.e. the negation circle, the polarity 'slopes' and the nonlogic
  76. /// marker
  77. static int externalPinDecoSize( const RENDER_SETTINGS* aSettings, const SCH_PIN &aPin )
  78. {
  79. const SCH_RENDER_SETTINGS* settings = static_cast<const SCH_RENDER_SETTINGS*>( aSettings );
  80. if( settings && settings->m_PinSymbolSize )
  81. return settings->m_PinSymbolSize;
  82. return aPin.GetNumberTextSize() / 2;
  83. }
  84. SCH_PIN::SCH_PIN( LIB_SYMBOL* aParentSymbol ) :
  85. SCH_ITEM( aParentSymbol, SCH_PIN_T, 0, 0 ),
  86. m_libPin( nullptr ),
  87. m_position( { 0, 0 } ),
  88. m_orientation( PIN_ORIENTATION::PIN_RIGHT ),
  89. m_shape( GRAPHIC_PINSHAPE::LINE ),
  90. m_type( ELECTRICAL_PINTYPE::PT_UNSPECIFIED ),
  91. m_hidden( false ),
  92. m_isDangling( true ),
  93. m_layoutCache( std::make_unique<PIN_LAYOUT_CACHE>( *this ) )
  94. {
  95. // Use the application settings for pin sizes if exists.
  96. // pgm can be nullptr when running a shared lib from a script, not from a kicad appl
  97. PGM_BASE* pgm = PgmOrNull();
  98. if( pgm )
  99. {
  100. SETTINGS_MANAGER& mgr = pgm->GetSettingsManager();
  101. SYMBOL_EDITOR_SETTINGS* cfg = mgr.GetAppSettings<SYMBOL_EDITOR_SETTINGS>( "symbol_editor" );
  102. m_length = schIUScale.MilsToIU( cfg->m_Defaults.pin_length );
  103. m_numTextSize = schIUScale.MilsToIU( cfg->m_Defaults.pin_num_size );
  104. m_nameTextSize = schIUScale.MilsToIU( cfg->m_Defaults.pin_name_size );
  105. }
  106. else // Use hardcoded eeschema defaults: symbol_editor settings are not existing.
  107. {
  108. m_length = schIUScale.MilsToIU( DEFAULT_PIN_LENGTH );
  109. m_numTextSize = schIUScale.MilsToIU( DEFAULT_PINNUM_SIZE );
  110. m_nameTextSize = schIUScale.MilsToIU( DEFAULT_PINNAME_SIZE );
  111. }
  112. m_layer = LAYER_DEVICE;
  113. }
  114. SCH_PIN::SCH_PIN( LIB_SYMBOL* aParentSymbol, const wxString& aName, const wxString& aNumber,
  115. PIN_ORIENTATION aOrientation, ELECTRICAL_PINTYPE aPinType, int aLength,
  116. int aNameTextSize, int aNumTextSize, int aBodyStyle, const VECTOR2I& aPos,
  117. int aUnit ) :
  118. SCH_ITEM( aParentSymbol, SCH_PIN_T, aUnit, aBodyStyle ),
  119. m_libPin( nullptr ),
  120. m_position( aPos ),
  121. m_length( aLength ),
  122. m_orientation( aOrientation ),
  123. m_shape( GRAPHIC_PINSHAPE::LINE ),
  124. m_type( aPinType ),
  125. m_hidden( false ),
  126. m_numTextSize( aNumTextSize ),
  127. m_nameTextSize( aNameTextSize ),
  128. m_isDangling( true ),
  129. m_layoutCache( std::make_unique<PIN_LAYOUT_CACHE>( *this ) )
  130. {
  131. SetName( aName );
  132. SetNumber( aNumber );
  133. m_layer = LAYER_DEVICE;
  134. }
  135. SCH_PIN::SCH_PIN( SCH_SYMBOL* aParentSymbol, SCH_PIN* aLibPin ) :
  136. SCH_ITEM( aParentSymbol, SCH_PIN_T, 0, 0 ),
  137. m_libPin( aLibPin ),
  138. m_orientation( PIN_ORIENTATION::INHERIT ),
  139. m_shape( GRAPHIC_PINSHAPE::INHERIT ),
  140. m_type( ELECTRICAL_PINTYPE::PT_INHERIT ),
  141. m_isDangling( true ),
  142. m_layoutCache( std::make_unique<PIN_LAYOUT_CACHE>( *this ) )
  143. {
  144. wxASSERT( aParentSymbol );
  145. SetName( m_libPin->GetName() );
  146. SetNumber( m_libPin->GetNumber() );
  147. m_position = m_libPin->GetPosition();
  148. m_layer = LAYER_PIN;
  149. }
  150. SCH_PIN::SCH_PIN( SCH_SYMBOL* aParentSymbol, const wxString& aNumber, const wxString& aAlt,
  151. const KIID& aUuid ) :
  152. SCH_ITEM( aParentSymbol, SCH_PIN_T ),
  153. m_libPin( nullptr ),
  154. m_orientation( PIN_ORIENTATION::INHERIT ),
  155. m_shape( GRAPHIC_PINSHAPE::INHERIT ),
  156. m_type( ELECTRICAL_PINTYPE::PT_INHERIT ),
  157. m_number( aNumber ),
  158. m_alt( aAlt ),
  159. m_isDangling( true ),
  160. m_layoutCache( std::make_unique<PIN_LAYOUT_CACHE>( *this ) )
  161. {
  162. wxASSERT( aParentSymbol );
  163. const_cast<KIID&>( m_Uuid ) = aUuid;
  164. m_layer = LAYER_PIN;
  165. }
  166. SCH_PIN::SCH_PIN( const SCH_PIN& aPin ) :
  167. SCH_ITEM( aPin ),
  168. m_libPin( aPin.m_libPin ),
  169. m_alternates( aPin.m_alternates ),
  170. m_position( aPin.m_position ),
  171. m_length( aPin.m_length ),
  172. m_orientation( aPin.m_orientation ),
  173. m_shape( aPin.m_shape ),
  174. m_type( aPin.m_type ),
  175. m_hidden( aPin.m_hidden ),
  176. m_numTextSize( aPin.m_numTextSize ),
  177. m_nameTextSize( aPin.m_nameTextSize ),
  178. m_alt( aPin.m_alt ),
  179. m_isDangling( aPin.m_isDangling ),
  180. m_layoutCache( std::make_unique<PIN_LAYOUT_CACHE>( *this ) )
  181. {
  182. SetName( aPin.m_name );
  183. SetNumber( aPin.m_number );
  184. m_layer = aPin.m_layer;
  185. }
  186. SCH_PIN::~SCH_PIN()
  187. {
  188. }
  189. SCH_PIN& SCH_PIN::operator=( const SCH_PIN& aPin )
  190. {
  191. SCH_ITEM::operator=( aPin );
  192. m_libPin = aPin.m_libPin;
  193. m_alternates = aPin.m_alternates;
  194. m_alt = aPin.m_alt;
  195. m_name = aPin.m_name;
  196. m_number = aPin.m_number;
  197. m_position = aPin.m_position;
  198. m_length = aPin.m_length;
  199. m_orientation = aPin.m_orientation;
  200. m_shape = aPin.m_shape;
  201. m_type = aPin.m_type;
  202. m_hidden = aPin.m_hidden;
  203. m_numTextSize = aPin.m_numTextSize;
  204. m_nameTextSize = aPin.m_nameTextSize;
  205. m_isDangling = aPin.m_isDangling;
  206. return *this;
  207. }
  208. VECTOR2I SCH_PIN::GetPosition() const
  209. {
  210. if( const SCH_SYMBOL* symbol = dynamic_cast<const SCH_SYMBOL*>( GetParentSymbol() ) )
  211. return symbol->GetTransform().TransformCoordinate( m_position ) + symbol->GetPosition();
  212. else
  213. return m_position;
  214. }
  215. PIN_ORIENTATION SCH_PIN::GetOrientation() const
  216. {
  217. if( m_orientation == PIN_ORIENTATION::INHERIT )
  218. {
  219. if( !m_libPin )
  220. return PIN_ORIENTATION::PIN_RIGHT;
  221. return m_libPin->GetOrientation();
  222. }
  223. return m_orientation;
  224. }
  225. GRAPHIC_PINSHAPE SCH_PIN::GetShape() const
  226. {
  227. if( !m_alt.IsEmpty() )
  228. {
  229. if( !m_libPin )
  230. return GRAPHIC_PINSHAPE::LINE;
  231. return m_libPin->GetAlt( m_alt ).m_Shape;
  232. }
  233. else if( m_shape == GRAPHIC_PINSHAPE::INHERIT )
  234. {
  235. if( !m_libPin )
  236. return GRAPHIC_PINSHAPE::LINE;
  237. return m_libPin->GetShape();
  238. }
  239. return m_shape;
  240. }
  241. int SCH_PIN::GetLength() const
  242. {
  243. if( !m_length.has_value() )
  244. {
  245. if( !m_libPin )
  246. return 0;
  247. return m_libPin->GetLength();
  248. }
  249. return m_length.value();
  250. }
  251. ELECTRICAL_PINTYPE SCH_PIN::GetType() const
  252. {
  253. if( !m_alt.IsEmpty() )
  254. {
  255. if( !m_libPin )
  256. return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
  257. return m_libPin->GetAlt( m_alt ).m_Type;
  258. }
  259. else if( m_type == ELECTRICAL_PINTYPE::PT_INHERIT )
  260. {
  261. if( !m_libPin )
  262. return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
  263. return m_libPin->GetType();
  264. }
  265. return m_type;
  266. }
  267. void SCH_PIN::SetType( ELECTRICAL_PINTYPE aType )
  268. {
  269. if( aType == m_type )
  270. return;
  271. m_type = aType;
  272. m_layoutCache->MarkDirty( PIN_LAYOUT_CACHE::DIRTY_FLAGS::ELEC_TYPE );
  273. }
  274. wxString SCH_PIN::GetCanonicalElectricalTypeName() const
  275. {
  276. if( m_type == ELECTRICAL_PINTYPE::PT_INHERIT )
  277. {
  278. if( !m_libPin )
  279. return GetCanonicalElectricalTypeName( ELECTRICAL_PINTYPE::PT_UNSPECIFIED );
  280. return m_libPin->GetCanonicalElectricalTypeName();
  281. }
  282. return GetCanonicalElectricalTypeName( m_type );
  283. }
  284. wxString SCH_PIN::GetElectricalTypeName() const
  285. {
  286. if( m_type == ELECTRICAL_PINTYPE::PT_INHERIT )
  287. {
  288. if( !m_libPin )
  289. return ElectricalPinTypeGetText( ELECTRICAL_PINTYPE::PT_UNSPECIFIED );
  290. return m_libPin->GetElectricalTypeName();
  291. }
  292. return ElectricalPinTypeGetText( m_type );
  293. }
  294. bool SCH_PIN::IsGlobalPower() const
  295. {
  296. return GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN
  297. && ( !IsVisible() || GetParentSymbol()->IsGlobalPower() );
  298. }
  299. bool SCH_PIN::IsLocalPower() const
  300. {
  301. return GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN
  302. && GetParentSymbol()->IsLocalPower();
  303. }
  304. bool SCH_PIN::IsPower() const
  305. {
  306. return IsLocalPower() || IsGlobalPower();
  307. }
  308. bool SCH_PIN::IsVisible() const
  309. {
  310. if( !m_hidden.has_value() )
  311. {
  312. if( !m_libPin )
  313. return true;
  314. return m_libPin->IsVisible();
  315. }
  316. return !m_hidden.value();
  317. }
  318. const wxString& SCH_PIN::GetName() const
  319. {
  320. if( !m_alt.IsEmpty() )
  321. return m_alt;
  322. return GetBaseName();
  323. }
  324. const wxString& SCH_PIN::GetBaseName() const
  325. {
  326. if( m_libPin )
  327. return m_libPin->GetBaseName();
  328. return m_name;
  329. }
  330. void SCH_PIN::SetName( const wxString& aName )
  331. {
  332. if( m_name == aName )
  333. return;
  334. m_name = aName;
  335. // pin name string does not support spaces
  336. m_name.Replace( wxT( " " ), wxT( "_" ) );
  337. m_layoutCache->MarkDirty( PIN_LAYOUT_CACHE::DIRTY_FLAGS::NAME );
  338. }
  339. void SCH_PIN::SetAlt( const wxString& aAlt )
  340. {
  341. wxString alt = aAlt;
  342. // Do not set the alternate pin definition to the default pin name. This breaks the library
  343. // symbol comparison for the ERC and the library diff tool. It also incorrectly causes the
  344. // schematic symbol pin alternate to be set.
  345. if( aAlt.IsEmpty() || ( alt == GetBaseName() ) )
  346. {
  347. m_alt = wxEmptyString;
  348. return;
  349. }
  350. wxCHECK2_MSG( m_libPin && m_libPin->GetAlternates().count( aAlt ), alt = wxEmptyString,
  351. wxString::Format( wxS( "Pin '%s' does not have an alterate '%s'" ), m_number, aAlt ) );
  352. m_alt = aAlt;
  353. }
  354. bool SCH_PIN::IsDangling() const
  355. {
  356. if( GetType() == ELECTRICAL_PINTYPE::PT_NC || GetType() == ELECTRICAL_PINTYPE::PT_NIC )
  357. return false;
  358. return m_isDangling;
  359. }
  360. void SCH_PIN::SetIsDangling( bool aIsDangling )
  361. {
  362. m_isDangling = aIsDangling;
  363. }
  364. bool SCH_PIN::IsStacked( const SCH_PIN* aPin ) const
  365. {
  366. bool isConnectableType_a = GetType() == ELECTRICAL_PINTYPE::PT_PASSIVE
  367. || GetType() == ELECTRICAL_PINTYPE::PT_NIC;
  368. bool isConnectableType_b = aPin->GetType() == ELECTRICAL_PINTYPE::PT_PASSIVE
  369. || aPin->GetType() == ELECTRICAL_PINTYPE::PT_NIC;
  370. return m_parent == aPin->GetParent()
  371. && GetPosition() == aPin->GetPosition()
  372. && GetName() == aPin->GetName()
  373. && ( GetType() == aPin->GetType() || isConnectableType_a || isConnectableType_b );
  374. }
  375. bool SCH_PIN::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
  376. {
  377. const SCH_SEARCH_DATA& schSearchData =
  378. dynamic_cast<const SCH_SEARCH_DATA&>( aSearchData );
  379. if( schSearchData.searchAllPins
  380. && ( EDA_ITEM::Matches( GetName(), aSearchData )
  381. || EDA_ITEM::Matches( GetNumber(), aSearchData ) ) )
  382. {
  383. return true;
  384. }
  385. SCH_CONNECTION* connection = nullptr;
  386. SCH_SHEET_PATH* sheetPath = reinterpret_cast<SCH_SHEET_PATH*>( aAuxData );
  387. if( schSearchData.searchNetNames && sheetPath && ( connection = Connection( sheetPath ) ) )
  388. {
  389. wxString netName = connection->GetNetName();
  390. if( EDA_ITEM::Matches( netName, aSearchData ) )
  391. return true;
  392. }
  393. return false;
  394. }
  395. bool SCH_PIN::Replace( const EDA_SEARCH_DATA& aSearchData, void* aAuxData )
  396. {
  397. bool isReplaced = false;
  398. /* TODO: waiting on a way to override pins in the schematic...
  399. isReplaced |= EDA_ITEM::Replace( aSearchData, m_name );
  400. isReplaced |= EDA_ITEM::Replace( aSearchData, m_number );
  401. */
  402. return isReplaced;
  403. }
  404. bool SCH_PIN::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
  405. {
  406. // When looking for an "exact" hit aAccuracy will be 0 which works poorly if the pin has
  407. // no pin number or name. Give it a floor.
  408. if( Schematic() )
  409. aAccuracy = std::max( aAccuracy, Schematic()->Settings().m_PinSymbolSize / 4 );
  410. BOX2I rect = GetBoundingBox( false, true, m_flags & SHOW_ELEC_TYPE );
  411. return rect.Inflate( aAccuracy ).Contains( aPosition );
  412. }
  413. bool SCH_PIN::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
  414. {
  415. if( m_flags & (STRUCT_DELETED | SKIP_STRUCT ) )
  416. return false;
  417. BOX2I sel = aRect;
  418. if ( aAccuracy )
  419. sel.Inflate( aAccuracy );
  420. if( aContained )
  421. return sel.Contains( GetBoundingBox( false, false, false ) );
  422. return sel.Intersects( GetBoundingBox( false, true, m_flags & SHOW_ELEC_TYPE ) );
  423. }
  424. wxString SCH_PIN::GetShownName() const
  425. {
  426. if( !m_alt.IsEmpty() )
  427. return m_alt;
  428. else if( m_libPin )
  429. return m_libPin->GetShownName();
  430. return m_name;
  431. }
  432. wxString SCH_PIN::GetShownNumber() const
  433. {
  434. return m_number;
  435. }
  436. void SCH_PIN::SetNumber( const wxString& aNumber )
  437. {
  438. if( m_number == aNumber )
  439. return;
  440. m_number = aNumber;
  441. // pin number string does not support spaces
  442. m_number.Replace( wxT( " " ), wxT( "_" ) );
  443. m_layoutCache->MarkDirty( PIN_LAYOUT_CACHE::DIRTY_FLAGS::NUMBER );
  444. }
  445. int SCH_PIN::GetNameTextSize() const
  446. {
  447. if( !m_nameTextSize.has_value() )
  448. {
  449. if( !m_libPin )
  450. return schIUScale.MilsToIU( DEFAULT_PINNAME_SIZE );
  451. return m_libPin->GetNameTextSize();
  452. }
  453. return m_nameTextSize.value();
  454. }
  455. void SCH_PIN::SetNameTextSize( int aSize )
  456. {
  457. if( aSize == m_nameTextSize )
  458. return;
  459. m_nameTextSize = aSize;
  460. m_layoutCache->MarkDirty( PIN_LAYOUT_CACHE::DIRTY_FLAGS::NAME );
  461. }
  462. int SCH_PIN::GetNumberTextSize() const
  463. {
  464. if( !m_numTextSize.has_value() )
  465. {
  466. if( !m_libPin )
  467. return schIUScale.MilsToIU( DEFAULT_PINNUM_SIZE );
  468. return m_libPin->GetNumberTextSize();
  469. }
  470. return m_numTextSize.value();
  471. }
  472. void SCH_PIN::SetNumberTextSize( int aSize )
  473. {
  474. if( aSize == m_numTextSize )
  475. return;
  476. m_numTextSize = aSize;
  477. m_layoutCache->MarkDirty( PIN_LAYOUT_CACHE::DIRTY_FLAGS::NUMBER );
  478. }
  479. VECTOR2I SCH_PIN::GetPinRoot() const
  480. {
  481. if( const SCH_SYMBOL* symbol = dynamic_cast<const SCH_SYMBOL*>( GetParentSymbol() ) )
  482. {
  483. const TRANSFORM& t = symbol->GetTransform();
  484. if( !m_libPin )
  485. return GetPosition();
  486. return t.TransformCoordinate( m_libPin->GetPinRoot() ) + symbol->GetPosition();
  487. }
  488. switch( GetOrientation() )
  489. {
  490. default:
  491. case PIN_ORIENTATION::PIN_RIGHT: return m_position + VECTOR2I( GetLength(), 0 );
  492. case PIN_ORIENTATION::PIN_LEFT: return m_position + VECTOR2I( -GetLength(), 0 );
  493. case PIN_ORIENTATION::PIN_UP: return m_position + VECTOR2I( 0, -GetLength() );
  494. case PIN_ORIENTATION::PIN_DOWN: return m_position + VECTOR2I( 0, GetLength() );
  495. }
  496. }
  497. void SCH_PIN::PlotPinType( PLOTTER *aPlotter, const VECTOR2I &aPosition,
  498. PIN_ORIENTATION aOrientation, bool aDimmed ) const
  499. {
  500. int MapX1, MapY1, x1, y1;
  501. SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
  502. COLOR4D color = renderSettings->GetLayerColor( LAYER_PIN );
  503. COLOR4D bg = renderSettings->GetBackgroundColor();
  504. int penWidth = GetEffectivePenWidth( renderSettings );
  505. int pinLength = GetLength();
  506. if( bg == COLOR4D::UNSPECIFIED || !aPlotter->GetColorMode() )
  507. bg = COLOR4D::WHITE;
  508. if( aDimmed )
  509. {
  510. color.Desaturate( );
  511. color = color.Mix( bg, 0.5f );
  512. }
  513. aPlotter->SetColor( color );
  514. aPlotter->SetCurrentLineWidth( penWidth );
  515. MapX1 = MapY1 = 0;
  516. x1 = aPosition.x; y1 = aPosition.y;
  517. switch( aOrientation )
  518. {
  519. case PIN_ORIENTATION::PIN_UP: y1 = aPosition.y - pinLength; MapY1 = 1; break;
  520. case PIN_ORIENTATION::PIN_DOWN: y1 = aPosition.y + pinLength; MapY1 = -1; break;
  521. case PIN_ORIENTATION::PIN_LEFT: x1 = aPosition.x - pinLength; MapX1 = 1; break;
  522. case PIN_ORIENTATION::PIN_RIGHT: x1 = aPosition.x + pinLength; MapX1 = -1; break;
  523. case PIN_ORIENTATION::INHERIT: wxFAIL_MSG( wxS( "aOrientation must be resolved!" ) ); break;
  524. }
  525. if( m_shape == GRAPHIC_PINSHAPE::INVERTED || m_shape == GRAPHIC_PINSHAPE::INVERTED_CLOCK )
  526. {
  527. const int radius = externalPinDecoSize( aPlotter->RenderSettings(), *this );
  528. aPlotter->Circle( VECTOR2I( MapX1 * radius + x1, MapY1 * radius + y1 ), radius * 2,
  529. FILL_T::NO_FILL, penWidth );
  530. aPlotter->MoveTo( VECTOR2I( MapX1 * radius * 2 + x1, MapY1 * radius * 2 + y1 ) );
  531. aPlotter->FinishTo( aPosition );
  532. }
  533. else if( m_shape == GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK )
  534. {
  535. const int deco_size = internalPinDecoSize( aPlotter->RenderSettings(), *this );
  536. if( MapY1 == 0 ) /* MapX1 = +- 1 */
  537. {
  538. aPlotter->MoveTo( VECTOR2I( x1, y1 + deco_size ) );
  539. aPlotter->LineTo( VECTOR2I( x1 + MapX1 * deco_size * 2, y1 ) );
  540. aPlotter->FinishTo( VECTOR2I( x1, y1 - deco_size ) );
  541. }
  542. else /* MapX1 = 0 */
  543. {
  544. aPlotter->MoveTo( VECTOR2I( x1 + deco_size, y1 ) );
  545. aPlotter->LineTo( VECTOR2I( x1, y1 + MapY1 * deco_size * 2 ) );
  546. aPlotter->FinishTo( VECTOR2I( x1 - deco_size, y1 ) );
  547. }
  548. aPlotter->MoveTo( VECTOR2I( MapX1 * deco_size * 2 + x1, MapY1 * deco_size * 2 + y1 ) );
  549. aPlotter->FinishTo( aPosition );
  550. }
  551. else
  552. {
  553. aPlotter->MoveTo( VECTOR2I( x1, y1 ) );
  554. aPlotter->FinishTo( aPosition );
  555. }
  556. if( m_shape == GRAPHIC_PINSHAPE::CLOCK
  557. || m_shape == GRAPHIC_PINSHAPE::INVERTED_CLOCK
  558. || m_shape == GRAPHIC_PINSHAPE::CLOCK_LOW )
  559. {
  560. const int deco_size = internalPinDecoSize( aPlotter->RenderSettings(), *this );
  561. if( MapY1 == 0 ) /* MapX1 = +- 1 */
  562. {
  563. aPlotter->MoveTo( VECTOR2I( x1, y1 + deco_size ) );
  564. aPlotter->LineTo( VECTOR2I( x1 - MapX1 * deco_size * 2, y1 ) );
  565. aPlotter->FinishTo( VECTOR2I( x1, y1 - deco_size ) );
  566. }
  567. else /* MapX1 = 0 */
  568. {
  569. aPlotter->MoveTo( VECTOR2I( x1 + deco_size, y1 ) );
  570. aPlotter->LineTo( VECTOR2I( x1, y1 - MapY1 * deco_size * 2 ) );
  571. aPlotter->FinishTo( VECTOR2I( x1 - deco_size, y1 ) );
  572. }
  573. }
  574. if( m_shape == GRAPHIC_PINSHAPE::INPUT_LOW
  575. || m_shape == GRAPHIC_PINSHAPE::CLOCK_LOW ) /* IEEE symbol "Active Low Input" */
  576. {
  577. const int deco_size = externalPinDecoSize( aPlotter->RenderSettings(), *this );
  578. if( MapY1 == 0 ) /* MapX1 = +- 1 */
  579. {
  580. aPlotter->MoveTo( VECTOR2I( x1 + MapX1 * deco_size * 2, y1 ) );
  581. aPlotter->LineTo( VECTOR2I( x1 + MapX1 * deco_size * 2, y1 - deco_size * 2 ) );
  582. aPlotter->FinishTo( VECTOR2I( x1, y1 ) );
  583. }
  584. else /* MapX1 = 0 */
  585. {
  586. aPlotter->MoveTo( VECTOR2I( x1, y1 + MapY1 * deco_size * 2 ) );
  587. aPlotter->LineTo( VECTOR2I( x1 - deco_size * 2, y1 + MapY1 * deco_size * 2 ) );
  588. aPlotter->FinishTo( VECTOR2I( x1, y1 ) );
  589. }
  590. }
  591. if( m_shape == GRAPHIC_PINSHAPE::OUTPUT_LOW ) /* IEEE symbol "Active Low Output" */
  592. {
  593. const int symbol_size = externalPinDecoSize( aPlotter->RenderSettings(), *this );
  594. if( MapY1 == 0 ) /* MapX1 = +- 1 */
  595. {
  596. aPlotter->MoveTo( VECTOR2I( x1, y1 - symbol_size * 2 ) );
  597. aPlotter->FinishTo( VECTOR2I( x1 + MapX1 * symbol_size * 2, y1 ) );
  598. }
  599. else /* MapX1 = 0 */
  600. {
  601. aPlotter->MoveTo( VECTOR2I( x1 - symbol_size * 2, y1 ) );
  602. aPlotter->FinishTo( VECTOR2I( x1, y1 + MapY1 * symbol_size * 2 ) );
  603. }
  604. }
  605. else if( m_shape == GRAPHIC_PINSHAPE::NONLOGIC ) /* NonLogic pin symbol */
  606. {
  607. const int deco_size = externalPinDecoSize( aPlotter->RenderSettings(), *this );
  608. aPlotter->MoveTo( VECTOR2I( x1 - ( MapX1 + MapY1 ) * deco_size,
  609. y1 - ( MapY1 - MapX1 ) * deco_size ) );
  610. aPlotter->FinishTo( VECTOR2I( x1 + ( MapX1 + MapY1 ) * deco_size,
  611. y1 + ( MapY1 - MapX1 ) * deco_size ) );
  612. aPlotter->MoveTo( VECTOR2I( x1 - ( MapX1 - MapY1 ) * deco_size,
  613. y1 - ( MapY1 + MapX1 ) * deco_size ) );
  614. aPlotter->FinishTo( VECTOR2I( x1 + ( MapX1 - MapY1 ) * deco_size,
  615. y1 + ( MapY1 + MapX1 ) * deco_size ) );
  616. }
  617. if( m_type == ELECTRICAL_PINTYPE::PT_NC ) // Draw a N.C. symbol
  618. {
  619. const int deco_size = TARGET_PIN_RADIUS;
  620. const int ex1 = aPosition.x;
  621. const int ey1 = aPosition.y;
  622. aPlotter->MoveTo( VECTOR2I( ex1 - deco_size, ey1 - deco_size ) );
  623. aPlotter->FinishTo( VECTOR2I( ex1 + deco_size, ey1 + deco_size ) );
  624. aPlotter->MoveTo( VECTOR2I( ex1 + deco_size, ey1 - deco_size ) );
  625. aPlotter->FinishTo( VECTOR2I( ex1 - deco_size, ey1 + deco_size ) );
  626. }
  627. }
  628. void SCH_PIN::PlotPinTexts( PLOTTER *aPlotter, const VECTOR2I &aPinPos, PIN_ORIENTATION aPinOrient,
  629. int aTextInside, bool aDrawPinNum, bool aDrawPinName,
  630. bool aDimmed ) const
  631. {
  632. RENDER_SETTINGS* settings = aPlotter->RenderSettings();
  633. KIFONT::FONT* font = KIFONT::FONT::GetFont( settings->GetDefaultFont(), false, false );
  634. wxString name = GetShownName();
  635. wxString number = GetShownNumber();
  636. if( name.IsEmpty() || m_nameTextSize == 0 )
  637. aDrawPinName = false;
  638. if( number.IsEmpty() || m_numTextSize == 0 )
  639. aDrawPinNum = false;
  640. if( !aDrawPinNum && !aDrawPinName )
  641. return;
  642. int namePenWidth = settings->GetDefaultPenWidth();
  643. int numPenWidth = settings->GetDefaultPenWidth();
  644. int name_offset = schIUScale.MilsToIU( PIN_TEXT_MARGIN ) + namePenWidth;
  645. int num_offset = schIUScale.MilsToIU( PIN_TEXT_MARGIN ) + numPenWidth;
  646. /* Get the num and name colors */
  647. COLOR4D nameColor = settings->GetLayerColor( LAYER_PINNAM );
  648. COLOR4D numColor = settings->GetLayerColor( LAYER_PINNUM );
  649. COLOR4D bg = settings->GetBackgroundColor();
  650. if( bg == COLOR4D::UNSPECIFIED || !aPlotter->GetColorMode() )
  651. bg = COLOR4D::WHITE;
  652. if( aDimmed )
  653. {
  654. nameColor.Desaturate( );
  655. numColor.Desaturate( );
  656. nameColor = nameColor.Mix( bg, 0.5f );
  657. numColor = numColor.Mix( bg, 0.5f );
  658. }
  659. int x1 = aPinPos.x;
  660. int y1 = aPinPos.y;
  661. switch( aPinOrient )
  662. {
  663. case PIN_ORIENTATION::PIN_UP: y1 -= GetLength(); break;
  664. case PIN_ORIENTATION::PIN_DOWN: y1 += GetLength(); break;
  665. case PIN_ORIENTATION::PIN_LEFT: x1 -= GetLength(); break;
  666. case PIN_ORIENTATION::PIN_RIGHT: x1 += GetLength(); break;
  667. case PIN_ORIENTATION::INHERIT: wxFAIL_MSG( wxS( "aPinOrient must be resolved!" ) ); break;
  668. }
  669. auto plotName =
  670. [&]( int x, int y, const EDA_ANGLE& angle, GR_TEXT_H_ALIGN_T hJustify,
  671. GR_TEXT_V_ALIGN_T vJustify )
  672. {
  673. TEXT_ATTRIBUTES attrs;
  674. attrs.m_StrokeWidth = namePenWidth;
  675. attrs.m_Angle = angle;
  676. attrs.m_Size = VECTOR2I( GetNameTextSize(), GetNameTextSize() );
  677. attrs.m_Halign = hJustify;
  678. attrs.m_Valign = vJustify;
  679. attrs.m_Multiline = false;
  680. aPlotter->PlotText( VECTOR2I( x, y ), nameColor, name, attrs, font,
  681. GetFontMetrics() );
  682. };
  683. auto plotNum =
  684. [&]( int x, int y, const EDA_ANGLE& angle, GR_TEXT_H_ALIGN_T hJustify,
  685. GR_TEXT_V_ALIGN_T vJustify )
  686. {
  687. TEXT_ATTRIBUTES attrs;
  688. attrs.m_StrokeWidth = numPenWidth;
  689. attrs.m_Angle = angle;
  690. attrs.m_Size = VECTOR2I( GetNumberTextSize(), GetNumberTextSize() );
  691. attrs.m_Halign = hJustify;
  692. attrs.m_Valign = vJustify;
  693. attrs.m_Multiline = false;
  694. aPlotter->PlotText( VECTOR2I( x, y ), numColor, number, attrs, font,
  695. GetFontMetrics() );
  696. };
  697. // Draw the text inside, but the pin numbers outside.
  698. if( aTextInside )
  699. {
  700. if( ( aPinOrient == PIN_ORIENTATION::PIN_LEFT )
  701. || ( aPinOrient == PIN_ORIENTATION::PIN_RIGHT ) ) // It's a horizontal line.
  702. {
  703. if( aDrawPinName )
  704. {
  705. if( aPinOrient == PIN_ORIENTATION::PIN_RIGHT )
  706. {
  707. plotName( x1 + aTextInside, y1, ANGLE_HORIZONTAL,
  708. GR_TEXT_H_ALIGN_LEFT, GR_TEXT_V_ALIGN_CENTER );
  709. }
  710. else // orient == PIN_LEFT
  711. {
  712. plotName( x1 - aTextInside, y1, ANGLE_HORIZONTAL,
  713. GR_TEXT_H_ALIGN_RIGHT, GR_TEXT_V_ALIGN_CENTER );
  714. }
  715. }
  716. if( aDrawPinNum )
  717. {
  718. plotNum( ( x1 + aPinPos.x) / 2, y1 - num_offset, ANGLE_HORIZONTAL,
  719. GR_TEXT_H_ALIGN_CENTER, GR_TEXT_V_ALIGN_BOTTOM );
  720. }
  721. }
  722. else // It's a vertical line.
  723. {
  724. if( aPinOrient == PIN_ORIENTATION::PIN_DOWN )
  725. {
  726. if( aDrawPinName )
  727. {
  728. plotName( x1, y1 + aTextInside, ANGLE_VERTICAL,
  729. GR_TEXT_H_ALIGN_RIGHT, GR_TEXT_V_ALIGN_CENTER );
  730. }
  731. if( aDrawPinNum )
  732. {
  733. plotNum( x1 - num_offset, ( y1 + aPinPos.y) / 2, ANGLE_VERTICAL,
  734. GR_TEXT_H_ALIGN_CENTER, GR_TEXT_V_ALIGN_BOTTOM );
  735. }
  736. }
  737. else /* PIN_UP */
  738. {
  739. if( aDrawPinName )
  740. {
  741. plotName( x1, y1 - aTextInside, ANGLE_VERTICAL,
  742. GR_TEXT_H_ALIGN_LEFT, GR_TEXT_V_ALIGN_CENTER );
  743. }
  744. if( aDrawPinNum )
  745. {
  746. plotNum( x1 - num_offset, ( y1 + aPinPos.y) / 2, ANGLE_VERTICAL,
  747. GR_TEXT_H_ALIGN_CENTER, GR_TEXT_V_ALIGN_BOTTOM );
  748. }
  749. }
  750. }
  751. }
  752. else // Draw num & text pin outside.
  753. {
  754. if( ( aPinOrient == PIN_ORIENTATION::PIN_LEFT )
  755. || ( aPinOrient == PIN_ORIENTATION::PIN_RIGHT ) )
  756. {
  757. // It's an horizontal line.
  758. if( aDrawPinName && aDrawPinNum )
  759. {
  760. plotName( ( x1 + aPinPos.x) / 2, y1 - name_offset, ANGLE_HORIZONTAL,
  761. GR_TEXT_H_ALIGN_CENTER, GR_TEXT_V_ALIGN_BOTTOM );
  762. plotNum( ( x1 + aPinPos.x) / 2, y1 + num_offset, ANGLE_HORIZONTAL,
  763. GR_TEXT_H_ALIGN_CENTER, GR_TEXT_V_ALIGN_TOP );
  764. }
  765. else if( aDrawPinName )
  766. {
  767. plotName( ( x1 + aPinPos.x) / 2, y1 - name_offset, ANGLE_HORIZONTAL,
  768. GR_TEXT_H_ALIGN_CENTER, GR_TEXT_V_ALIGN_BOTTOM );
  769. }
  770. else if( aDrawPinNum )
  771. {
  772. plotNum( ( x1 + aPinPos.x) / 2, y1 - name_offset, ANGLE_HORIZONTAL,
  773. GR_TEXT_H_ALIGN_CENTER, GR_TEXT_V_ALIGN_BOTTOM );
  774. }
  775. }
  776. else
  777. {
  778. // Its a vertical line.
  779. if( aDrawPinName && aDrawPinNum )
  780. {
  781. plotName( x1 - name_offset, ( y1 + aPinPos.y ) / 2, ANGLE_VERTICAL,
  782. GR_TEXT_H_ALIGN_CENTER, GR_TEXT_V_ALIGN_BOTTOM );
  783. plotNum( x1 + num_offset, ( y1 + aPinPos.y ) / 2, ANGLE_VERTICAL,
  784. GR_TEXT_H_ALIGN_CENTER, GR_TEXT_V_ALIGN_TOP );
  785. }
  786. else if( aDrawPinName )
  787. {
  788. plotName( x1 - name_offset, ( y1 + aPinPos.y ) / 2, ANGLE_VERTICAL,
  789. GR_TEXT_H_ALIGN_CENTER, GR_TEXT_V_ALIGN_BOTTOM );
  790. }
  791. else if( aDrawPinNum )
  792. {
  793. plotNum( x1 - num_offset, ( y1 + aPinPos.y ) / 2, ANGLE_VERTICAL,
  794. GR_TEXT_H_ALIGN_CENTER, GR_TEXT_V_ALIGN_BOTTOM );
  795. }
  796. }
  797. }
  798. }
  799. PIN_ORIENTATION SCH_PIN::PinDrawOrient( const TRANSFORM& aTransform ) const
  800. {
  801. PIN_ORIENTATION orient;
  802. VECTOR2I end; // position of pin end starting at 0,0 according to its orientation, length = 1
  803. switch( GetOrientation() )
  804. {
  805. default:
  806. case PIN_ORIENTATION::PIN_RIGHT: end.x = 1; break;
  807. case PIN_ORIENTATION::PIN_UP: end.y = -1; break;
  808. case PIN_ORIENTATION::PIN_DOWN: end.y = 1; break;
  809. case PIN_ORIENTATION::PIN_LEFT: end.x = -1; break;
  810. }
  811. // = pos of end point, according to the symbol orientation.
  812. end = aTransform.TransformCoordinate( end );
  813. orient = PIN_ORIENTATION::PIN_UP;
  814. if( end.x == 0 )
  815. {
  816. if( end.y > 0 )
  817. orient = PIN_ORIENTATION::PIN_DOWN;
  818. }
  819. else
  820. {
  821. orient = PIN_ORIENTATION::PIN_RIGHT;
  822. if( end.x < 0 )
  823. orient = PIN_ORIENTATION::PIN_LEFT;
  824. }
  825. return orient;
  826. }
  827. EDA_ITEM* SCH_PIN::Clone() const
  828. {
  829. //return new SCH_PIN( *this );
  830. SCH_ITEM* newPin = new SCH_PIN( *this );
  831. wxASSERT( newPin->GetUnit() == m_unit && newPin->GetBodyStyle() == m_bodyStyle );
  832. return newPin;
  833. }
  834. void SCH_PIN::ChangeLength( int aLength )
  835. {
  836. int lengthChange = GetLength() - aLength;
  837. int offsetX = 0;
  838. int offsetY = 0;
  839. switch( m_orientation )
  840. {
  841. default:
  842. case PIN_ORIENTATION::PIN_RIGHT:
  843. offsetX = lengthChange;
  844. break;
  845. case PIN_ORIENTATION::PIN_LEFT:
  846. offsetX = -1 * lengthChange;
  847. break;
  848. case PIN_ORIENTATION::PIN_UP:
  849. offsetY = lengthChange;
  850. break;
  851. case PIN_ORIENTATION::PIN_DOWN:
  852. offsetY = -1 * lengthChange;
  853. break;
  854. }
  855. m_position += VECTOR2I( offsetX, offsetY );
  856. m_length = aLength;
  857. }
  858. void SCH_PIN::Move( const VECTOR2I& aOffset )
  859. {
  860. m_position += aOffset;
  861. }
  862. void SCH_PIN::MirrorHorizontallyPin( int aCenter )
  863. {
  864. m_position.x -= aCenter;
  865. m_position.x *= -1;
  866. m_position.x += aCenter;
  867. if( m_orientation == PIN_ORIENTATION::PIN_RIGHT )
  868. m_orientation = PIN_ORIENTATION::PIN_LEFT;
  869. else if( m_orientation == PIN_ORIENTATION::PIN_LEFT )
  870. m_orientation = PIN_ORIENTATION::PIN_RIGHT;
  871. }
  872. void SCH_PIN::MirrorHorizontally( int aCenter )
  873. {
  874. if( dynamic_cast<LIB_SYMBOL*>( GetParentSymbol() ) )
  875. MirrorHorizontallyPin( aCenter );
  876. }
  877. void SCH_PIN::MirrorVerticallyPin( int aCenter )
  878. {
  879. m_position.y -= aCenter;
  880. m_position.y *= -1;
  881. m_position.y += aCenter;
  882. if( m_orientation == PIN_ORIENTATION::PIN_UP )
  883. m_orientation = PIN_ORIENTATION::PIN_DOWN;
  884. else if( m_orientation == PIN_ORIENTATION::PIN_DOWN )
  885. m_orientation = PIN_ORIENTATION::PIN_UP;
  886. }
  887. void SCH_PIN::MirrorVertically( int aCenter )
  888. {
  889. if( dynamic_cast<LIB_SYMBOL*>( GetParentSymbol() ) )
  890. MirrorVerticallyPin( aCenter );
  891. }
  892. void SCH_PIN::RotatePin( const VECTOR2I& aCenter, bool aRotateCCW )
  893. {
  894. if( aRotateCCW )
  895. {
  896. RotatePoint( m_position, aCenter, ANGLE_90 );
  897. switch( GetOrientation() )
  898. {
  899. default:
  900. case PIN_ORIENTATION::PIN_RIGHT: m_orientation = PIN_ORIENTATION::PIN_UP; break;
  901. case PIN_ORIENTATION::PIN_UP: m_orientation = PIN_ORIENTATION::PIN_LEFT; break;
  902. case PIN_ORIENTATION::PIN_LEFT: m_orientation = PIN_ORIENTATION::PIN_DOWN; break;
  903. case PIN_ORIENTATION::PIN_DOWN: m_orientation = PIN_ORIENTATION::PIN_RIGHT; break;
  904. }
  905. }
  906. else
  907. {
  908. RotatePoint( m_position, aCenter, -ANGLE_90 );
  909. switch( GetOrientation() )
  910. {
  911. default:
  912. case PIN_ORIENTATION::PIN_RIGHT: m_orientation = PIN_ORIENTATION::PIN_DOWN; break;
  913. case PIN_ORIENTATION::PIN_UP: m_orientation = PIN_ORIENTATION::PIN_RIGHT; break;
  914. case PIN_ORIENTATION::PIN_LEFT: m_orientation = PIN_ORIENTATION::PIN_UP; break;
  915. case PIN_ORIENTATION::PIN_DOWN: m_orientation = PIN_ORIENTATION::PIN_LEFT; break;
  916. }
  917. }
  918. }
  919. void SCH_PIN::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
  920. {
  921. if( dynamic_cast<LIB_SYMBOL*>( GetParentSymbol() ) )
  922. RotatePin( aCenter, aRotateCCW );
  923. }
  924. void SCH_PIN::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
  925. int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
  926. {
  927. if( aBackground )
  928. return;
  929. SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
  930. if( !IsVisible() && !renderSettings->m_ShowHiddenPins )
  931. return;
  932. const SYMBOL* part = GetParentSymbol();
  933. PIN_ORIENTATION orient = PinDrawOrient( renderSettings->m_Transform );
  934. VECTOR2I pos = renderSettings->TransformCoordinate( m_position ) + aOffset;
  935. PlotPinType( aPlotter, pos, orient, aDimmed );
  936. PlotPinTexts( aPlotter, pos, orient, part->GetPinNameOffset(), part->GetShowPinNumbers(),
  937. part->GetShowPinNames(), aDimmed );
  938. }
  939. void SCH_PIN::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
  940. {
  941. wxString msg;
  942. SYMBOL* symbol = GetParentSymbol();
  943. if( dynamic_cast<LIB_SYMBOL*>( symbol ) )
  944. {
  945. getSymbolEditorMsgPanelInfo( aFrame, aList );
  946. }
  947. else
  948. {
  949. aList.emplace_back( _( "Type" ), _( "Pin" ) );
  950. if( symbol->GetUnitCount() )
  951. {
  952. msg = m_libPin ? GetUnitDescription( m_libPin->GetUnit() ) :
  953. wxString( "Undefined library pin." );
  954. aList.emplace_back( _( "Unit" ), msg );
  955. }
  956. if( symbol->HasAlternateBodyStyle() )
  957. {
  958. msg = m_libPin ? GetBodyStyleDescription( m_libPin->GetBodyStyle() ) :
  959. wxString( "Undefined library pin." );
  960. aList.emplace_back( _( "Body Style" ), msg );
  961. }
  962. }
  963. aList.emplace_back( _( "Name" ), UnescapeString( GetShownName() ) );
  964. aList.emplace_back( _( "Number" ), GetShownNumber() );
  965. aList.emplace_back( _( "Type" ), ElectricalPinTypeGetText( GetType() ) );
  966. aList.emplace_back( _( "Style" ), PinShapeGetText( GetShape() ) );
  967. aList.emplace_back( _( "Visible" ), IsVisible() ? _( "Yes" ) : _( "No" ) );
  968. // Display pin length
  969. aList.emplace_back( _( "Length" ), aFrame->MessageTextFromValue( GetLength(), true ) );
  970. aList.emplace_back( _( "Orientation" ), PinOrientationName( GetOrientation() ) );
  971. if( dynamic_cast<LIB_SYMBOL*>( symbol ) )
  972. {
  973. aList.emplace_back( _( "Pos X" ), aFrame->MessageTextFromValue( GetPosition().x, true ) );
  974. aList.emplace_back( _( "Pos Y" ), aFrame->MessageTextFromValue( GetPosition().y, true ) );
  975. }
  976. else if( SCH_SYMBOL* schsymbol = dynamic_cast<SCH_SYMBOL*>( symbol ) )
  977. {
  978. SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( aFrame );
  979. SCH_SHEET_PATH* currentSheet = schframe ? &schframe->GetCurrentSheet() : nullptr;
  980. // Don't use GetShownText(); we want to see the variable references here
  981. aList.emplace_back( symbol->GetRef( currentSheet ),
  982. UnescapeString( schsymbol->GetField( FIELD_T::VALUE )->GetText() ) );
  983. }
  984. #if defined(DEBUG)
  985. if( !IsConnectivityDirty() && dynamic_cast<SCH_EDIT_FRAME*>( aFrame ) )
  986. {
  987. SCH_CONNECTION* conn = Connection();
  988. if( conn )
  989. conn->AppendInfoToMsgPanel( aList );
  990. }
  991. #endif
  992. }
  993. void SCH_PIN::ClearDefaultNetName( const SCH_SHEET_PATH* aPath )
  994. {
  995. std::lock_guard<std::recursive_mutex> lock( m_netmap_mutex );
  996. if( aPath )
  997. m_net_name_map.erase( *aPath );
  998. else
  999. m_net_name_map.clear();
  1000. }
  1001. wxString SCH_PIN::GetDefaultNetName( const SCH_SHEET_PATH& aPath, bool aForceNoConnect )
  1002. {
  1003. const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( GetParentSymbol() );
  1004. // Need to check for parent as power symbol to make sure we aren't dealing
  1005. // with legacy global power pins on non-power symbols
  1006. if( IsGlobalPower() || IsLocalPower() )
  1007. {
  1008. SYMBOL* parent = GetLibPin()->GetParentSymbol();
  1009. if( parent->IsGlobalPower() || parent->IsLocalPower() )
  1010. {
  1011. return EscapeString( symbol->GetValue( true, &aPath, false ), CTX_NETNAME );
  1012. }
  1013. else
  1014. {
  1015. wxString tmp = m_libPin ? m_libPin->GetName() : wxString( "??" );
  1016. return EscapeString( tmp, CTX_NETNAME );
  1017. }
  1018. }
  1019. std::lock_guard<std::recursive_mutex> lock( m_netmap_mutex );
  1020. auto it = m_net_name_map.find( aPath );
  1021. if( it != m_net_name_map.end() )
  1022. {
  1023. if( it->second.second == aForceNoConnect )
  1024. return it->second.first;
  1025. }
  1026. wxString name = "Net-(";
  1027. bool unconnected = false;
  1028. if( aForceNoConnect || GetType() == ELECTRICAL_PINTYPE::PT_NC )
  1029. {
  1030. unconnected = true;
  1031. name = ( "unconnected-(" );
  1032. }
  1033. bool annotated = true;
  1034. std::vector<SCH_PIN*> pins = symbol->GetPins( &aPath );
  1035. bool has_multiple = false;
  1036. for( SCH_PIN* pin : pins )
  1037. {
  1038. if( pin->GetShownName() == GetShownName()
  1039. && pin->GetShownNumber() != GetShownNumber()
  1040. && unconnected == ( pin->GetType() == ELECTRICAL_PINTYPE::PT_NC ) )
  1041. {
  1042. has_multiple = true;
  1043. break;
  1044. }
  1045. }
  1046. wxString libPinShownName = m_libPin ? m_libPin->GetShownName() : wxString( "??" );
  1047. wxString libPinShownNumber = m_libPin ? m_libPin->GetShownNumber() : wxString( "??" );
  1048. // Use timestamp for unannotated symbols
  1049. if( symbol->GetRef( &aPath, false ).Last() == '?' )
  1050. {
  1051. name << GetParentSymbol()->m_Uuid.AsString();
  1052. wxString libPinNumber = m_libPin ? m_libPin->GetNumber() : wxString( "??" );
  1053. name << "-Pad" << libPinNumber << ")";
  1054. annotated = false;
  1055. }
  1056. else if( !libPinShownName.IsEmpty() && ( libPinShownName != libPinShownNumber ) )
  1057. {
  1058. // Pin names might not be unique between different units so we must have the
  1059. // unit token in the reference designator
  1060. name << symbol->GetRef( &aPath, true );
  1061. name << "-" << EscapeString( libPinShownName, CTX_NETNAME );
  1062. if( unconnected || has_multiple )
  1063. name << "-Pad" << EscapeString( libPinShownNumber, CTX_NETNAME );
  1064. name << ")";
  1065. }
  1066. else
  1067. {
  1068. // Pin numbers are unique, so we skip the unit token
  1069. name << symbol->GetRef( &aPath, false );
  1070. name << "-Pad" << EscapeString( libPinShownNumber, CTX_NETNAME ) << ")";
  1071. }
  1072. if( annotated )
  1073. m_net_name_map[ aPath ] = std::make_pair( name, aForceNoConnect );
  1074. return name;
  1075. }
  1076. const BOX2I SCH_PIN::ViewBBox() const
  1077. {
  1078. return GetBoundingBox( false, true, m_flags & SHOW_ELEC_TYPE );
  1079. }
  1080. std::vector<int> SCH_PIN::ViewGetLayers() const
  1081. {
  1082. return { LAYER_DANGLING, LAYER_DEVICE, LAYER_SELECTION_SHADOWS,
  1083. LAYER_OP_CURRENTS, LAYER_PINNAM, LAYER_PINNUM };
  1084. }
  1085. void SCH_PIN::validateExtentsCache( KIFONT::FONT* aFont, int aSize, const wxString& aText,
  1086. EXTENTS_CACHE* aCache ) const
  1087. {
  1088. if( aCache->m_Font == aFont
  1089. && aCache->m_FontSize == aSize
  1090. && aCache->m_Extents != VECTOR2I() )
  1091. {
  1092. return;
  1093. }
  1094. aCache->m_Font = aFont;
  1095. aCache->m_FontSize = aSize;
  1096. VECTOR2D fontSize( aSize, aSize );
  1097. int penWidth = GetPenSizeForNormal( aSize );
  1098. aCache->m_Extents = aFont->StringBoundaryLimits( aText, fontSize, penWidth, false, false,
  1099. GetFontMetrics() );
  1100. }
  1101. BOX2I SCH_PIN::GetBoundingBox( bool aIncludeLabelsOnInvisiblePins, bool aIncludeNameAndNumber,
  1102. bool aIncludeElectricalType ) const
  1103. {
  1104. // Just defer to the cache
  1105. return m_layoutCache->GetPinBoundingBox( aIncludeLabelsOnInvisiblePins, aIncludeNameAndNumber,
  1106. aIncludeElectricalType );
  1107. }
  1108. bool SCH_PIN::HasConnectivityChanges( const SCH_ITEM* aItem,
  1109. const SCH_SHEET_PATH* aInstance ) const
  1110. {
  1111. // Do not compare to ourself.
  1112. if( aItem == this )
  1113. return false;
  1114. const SCH_PIN* pin = dynamic_cast<const SCH_PIN*>( aItem );
  1115. // Don't compare against a different SCH_ITEM.
  1116. wxCHECK( pin, false );
  1117. if( GetPosition() != pin->GetPosition() )
  1118. return true;
  1119. if( GetNumber() != pin->GetNumber() )
  1120. return true;
  1121. return GetName() != pin->GetName();
  1122. }
  1123. bool SCH_PIN::ConnectionPropagatesTo( const EDA_ITEM* aItem ) const
  1124. {
  1125. if( !m_libPin )
  1126. return false;
  1127. // Reciprocal checking is done in CONNECTION_GRAPH anyway
  1128. return m_libPin->GetType() != ELECTRICAL_PINTYPE::PT_NC;
  1129. }
  1130. BITMAPS SCH_PIN::GetMenuImage() const
  1131. {
  1132. if( m_libPin )
  1133. return m_libPin->GetMenuImage();
  1134. return ElectricalPinTypeGetBitmap( m_type );
  1135. }
  1136. wxString SCH_PIN::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, ALT* aAlt ) const
  1137. {
  1138. return getItemDescription( aAlt );
  1139. }
  1140. wxString SCH_PIN::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
  1141. {
  1142. if( m_libPin )
  1143. {
  1144. SCH_PIN::ALT localStorage;
  1145. SCH_PIN::ALT* alt = nullptr;
  1146. if( !m_alt.IsEmpty() )
  1147. {
  1148. localStorage = m_libPin->GetAlt( m_alt );
  1149. alt = &localStorage;
  1150. }
  1151. wxString itemDesc = m_libPin ? m_libPin->GetItemDescription( aUnitsProvider, alt )
  1152. : wxString( wxS( "Undefined library pin." ) );
  1153. const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( GetParentSymbol() );
  1154. return wxString::Format( "Symbol %s %s",
  1155. UnescapeString( symbol->GetField( FIELD_T::REFERENCE )->GetText() ),
  1156. itemDesc );
  1157. }
  1158. return getItemDescription( nullptr );
  1159. }
  1160. wxString SCH_PIN::getItemDescription( ALT* aAlt ) const
  1161. {
  1162. wxString name = UnescapeString( aAlt ? aAlt->m_Name : GetShownName() );
  1163. wxString electricalTypeName = ElectricalPinTypeGetText( aAlt ? aAlt->m_Type : m_type );
  1164. wxString pinShapeName = PinShapeGetText( aAlt ? aAlt->m_Shape : m_shape );
  1165. if( IsVisible() )
  1166. {
  1167. if ( !name.IsEmpty() )
  1168. {
  1169. return wxString::Format( _( "Pin %s [%s, %s, %s]" ),
  1170. GetShownNumber(),
  1171. name,
  1172. electricalTypeName,
  1173. pinShapeName );
  1174. }
  1175. else
  1176. {
  1177. return wxString::Format( _( "Pin %s [%s, %s]" ),
  1178. GetShownNumber(),
  1179. electricalTypeName,
  1180. pinShapeName );
  1181. }
  1182. }
  1183. else
  1184. {
  1185. if( !name.IsEmpty() )
  1186. {
  1187. return wxString::Format( _( "Hidden pin %s [%s, %s, %s]" ),
  1188. GetShownNumber(),
  1189. name,
  1190. electricalTypeName,
  1191. pinShapeName );
  1192. }
  1193. else
  1194. {
  1195. return wxString::Format( _( "Hidden pin %s [%s, %s]" ),
  1196. GetShownNumber(),
  1197. electricalTypeName,
  1198. pinShapeName );
  1199. }
  1200. }
  1201. }
  1202. int SCH_PIN::compare( const SCH_ITEM& aOther, int aCompareFlags ) const
  1203. {
  1204. // Ignore the UUID here.
  1205. int retv = SCH_ITEM::compare( aOther, aCompareFlags | SCH_ITEM::COMPARE_FLAGS::EQUALITY );
  1206. if( retv )
  1207. return retv;
  1208. const SCH_PIN* tmp = static_cast<const SCH_PIN*>( &aOther );
  1209. wxCHECK( tmp, -1 );
  1210. if( m_number != tmp->m_number )
  1211. return m_number.Cmp( tmp->m_number );
  1212. if( m_position.x != tmp->m_position.x )
  1213. return m_position.x - tmp->m_position.x;
  1214. if( m_position.y != tmp->m_position.y )
  1215. return m_position.y - tmp->m_position.y;
  1216. if( dynamic_cast<const SCH_SYMBOL*>( GetParentSymbol() ) )
  1217. {
  1218. if( ( m_libPin == nullptr ) || ( tmp->m_libPin == nullptr ) )
  1219. return -1;
  1220. retv = m_libPin->compare( *tmp->m_libPin );
  1221. if( retv )
  1222. return retv;
  1223. retv = m_alt.Cmp( tmp->m_alt );
  1224. if( retv )
  1225. return retv;
  1226. }
  1227. if( dynamic_cast<const LIB_SYMBOL*>( GetParentSymbol() ) )
  1228. {
  1229. if( m_length != tmp->m_length )
  1230. return m_length.value_or( 0 ) - tmp->m_length.value_or( 0 );
  1231. if( m_orientation != tmp->m_orientation )
  1232. return static_cast<int>( m_orientation ) - static_cast<int>( tmp->m_orientation );
  1233. if( m_shape != tmp->m_shape )
  1234. return static_cast<int>( m_shape ) - static_cast<int>( tmp->m_shape );
  1235. if( m_type != tmp->m_type )
  1236. return static_cast<int>( m_type ) - static_cast<int>( tmp->m_type );
  1237. if( m_hidden != tmp->m_hidden )
  1238. return m_hidden.value_or( false ) - tmp->m_hidden.value_or( false );
  1239. if( m_numTextSize != tmp->m_numTextSize )
  1240. return m_numTextSize.value_or( 0 ) - tmp->m_numTextSize.value_or( 0 );
  1241. if( m_nameTextSize != tmp->m_nameTextSize )
  1242. return m_nameTextSize.value_or( 0 ) - tmp->m_nameTextSize.value_or( 0 );
  1243. if( m_alternates.size() != tmp->m_alternates.size() )
  1244. return static_cast<int>( m_alternates.size() - tmp->m_alternates.size() );
  1245. auto lhsItem = m_alternates.begin();
  1246. auto rhsItem = tmp->m_alternates.begin();
  1247. while( lhsItem != m_alternates.end() )
  1248. {
  1249. const ALT& lhsAlt = lhsItem->second;
  1250. const ALT& rhsAlt = rhsItem->second;
  1251. retv = lhsAlt.m_Name.Cmp( rhsAlt.m_Name );
  1252. if( retv )
  1253. return retv;
  1254. if( lhsAlt.m_Type != rhsAlt.m_Type )
  1255. return static_cast<int>( lhsAlt.m_Type ) - static_cast<int>( rhsAlt.m_Type );
  1256. if( lhsAlt.m_Shape != rhsAlt.m_Shape )
  1257. return static_cast<int>( lhsAlt.m_Shape ) - static_cast<int>( rhsAlt.m_Shape );
  1258. ++lhsItem;
  1259. ++rhsItem;
  1260. }
  1261. }
  1262. return 0;
  1263. }
  1264. double SCH_PIN::Similarity( const SCH_ITEM& aOther ) const
  1265. {
  1266. if( aOther.m_Uuid == m_Uuid )
  1267. return 1.0;
  1268. if( aOther.Type() != SCH_PIN_T )
  1269. return 0.0;
  1270. const SCH_PIN* other = static_cast<const SCH_PIN*>( &aOther );
  1271. if( m_libPin )
  1272. {
  1273. if( m_number != other->m_number )
  1274. return 0.0;
  1275. if( m_position != other->m_position )
  1276. return 0.0;
  1277. return m_libPin->Similarity( *other->m_libPin );
  1278. }
  1279. double similarity = SimilarityBase( aOther );
  1280. if( m_name != other->m_name )
  1281. similarity *= 0.9;
  1282. if( m_number != other->m_number )
  1283. similarity *= 0.9;
  1284. if( m_position != other->m_position )
  1285. similarity *= 0.9;
  1286. if( m_length != other->m_length )
  1287. similarity *= 0.9;
  1288. if( m_orientation != other->m_orientation )
  1289. similarity *= 0.9;
  1290. if( m_shape != other->m_shape )
  1291. similarity *= 0.9;
  1292. if( m_type != other->m_type )
  1293. similarity *= 0.9;
  1294. if( m_hidden != other->m_hidden )
  1295. similarity *= 0.9;
  1296. if( m_numTextSize != other->m_numTextSize )
  1297. similarity *= 0.9;
  1298. if( m_nameTextSize != other->m_nameTextSize )
  1299. similarity *= 0.9;
  1300. if( m_alternates.size() != other->m_alternates.size() )
  1301. similarity *= 0.9;
  1302. return similarity;
  1303. }
  1304. std::ostream& SCH_PIN::operator<<( std::ostream& aStream )
  1305. {
  1306. aStream << "SCH_PIN:" << std::endl
  1307. << " Name: \"" << m_name << "\"" << std::endl
  1308. << " Number: \"" << m_number << "\"" << std::endl
  1309. << " Position: " << m_position << std::endl
  1310. << " Length: " << GetLength() << std::endl
  1311. << " Orientation: " << PinOrientationName( m_orientation ) << std::endl
  1312. << " Shape: " << PinShapeGetText( m_shape ) << std::endl
  1313. << " Type: " << ElectricalPinTypeGetText( m_type ) << std::endl
  1314. << " Name Text Size: " << GetNameTextSize() << std::endl
  1315. << " Number Text Size: " << GetNumberTextSize() << std::endl;
  1316. return aStream;
  1317. }
  1318. #if defined(DEBUG)
  1319. void SCH_PIN::Show( int nestLevel, std::ostream& os ) const
  1320. {
  1321. NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str()
  1322. << " num=\"" << m_number.mb_str()
  1323. << '"' << "/>\n";
  1324. }
  1325. #endif
  1326. void SCH_PIN::CalcEdit( const VECTOR2I& aPosition )
  1327. {
  1328. if( IsMoving() )
  1329. SetPosition( aPosition );
  1330. }
  1331. static struct SCH_PIN_DESC
  1332. {
  1333. SCH_PIN_DESC()
  1334. {
  1335. auto& pinTypeEnum = ENUM_MAP<ELECTRICAL_PINTYPE>::Instance();
  1336. if( pinTypeEnum.Choices().GetCount() == 0 )
  1337. {
  1338. pinTypeEnum.Map( ELECTRICAL_PINTYPE::PT_INPUT, _HKI( "Input" ) )
  1339. .Map( ELECTRICAL_PINTYPE::PT_OUTPUT, _HKI( "Output" ) )
  1340. .Map( ELECTRICAL_PINTYPE::PT_BIDI, _HKI( "Bidirectional" ) )
  1341. .Map( ELECTRICAL_PINTYPE::PT_TRISTATE, _HKI( "Tri-state" ) )
  1342. .Map( ELECTRICAL_PINTYPE::PT_PASSIVE, _HKI( "Passive" ) )
  1343. .Map( ELECTRICAL_PINTYPE::PT_NIC, _HKI( "Free" ) )
  1344. .Map( ELECTRICAL_PINTYPE::PT_UNSPECIFIED, _HKI( "Unspecified" ) )
  1345. .Map( ELECTRICAL_PINTYPE::PT_POWER_IN, _HKI( "Power input" ) )
  1346. .Map( ELECTRICAL_PINTYPE::PT_POWER_OUT, _HKI( "Power output" ) )
  1347. .Map( ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR, _HKI( "Open collector" ) )
  1348. .Map( ELECTRICAL_PINTYPE::PT_OPENEMITTER, _HKI( "Open emitter" ) )
  1349. .Map( ELECTRICAL_PINTYPE::PT_NC, _HKI( "Unconnected" ) );
  1350. }
  1351. auto& pinShapeEnum = ENUM_MAP<GRAPHIC_PINSHAPE>::Instance();
  1352. if( pinShapeEnum.Choices().GetCount() == 0 )
  1353. {
  1354. pinShapeEnum.Map( GRAPHIC_PINSHAPE::LINE, _HKI( "Line" ) )
  1355. .Map( GRAPHIC_PINSHAPE::INVERTED, _HKI( "Inverted" ) )
  1356. .Map( GRAPHIC_PINSHAPE::CLOCK, _HKI( "Clock" ) )
  1357. .Map( GRAPHIC_PINSHAPE::INVERTED_CLOCK, _HKI( "Inverted clock" ) )
  1358. .Map( GRAPHIC_PINSHAPE::INPUT_LOW, _HKI( "Input low" ) )
  1359. .Map( GRAPHIC_PINSHAPE::CLOCK_LOW, _HKI( "Clock low" ) )
  1360. .Map( GRAPHIC_PINSHAPE::OUTPUT_LOW, _HKI( "Output low" ) )
  1361. .Map( GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK, _HKI( "Falling edge clock" ) )
  1362. .Map( GRAPHIC_PINSHAPE::NONLOGIC, _HKI( "NonLogic" ) );
  1363. }
  1364. auto& orientationEnum = ENUM_MAP<PIN_ORIENTATION>::Instance();
  1365. if( orientationEnum.Choices().GetCount() == 0 )
  1366. {
  1367. orientationEnum.Map( PIN_ORIENTATION::PIN_RIGHT, _( "Right" ) )
  1368. .Map( PIN_ORIENTATION::PIN_LEFT, _( "Left" ) )
  1369. .Map( PIN_ORIENTATION::PIN_UP, _( "Up" ) )
  1370. .Map( PIN_ORIENTATION::PIN_DOWN, _( "Down" ) );
  1371. }
  1372. auto isSymbolEditor =
  1373. []( INSPECTABLE* aItem ) -> bool
  1374. {
  1375. if( SCH_PIN* pin = dynamic_cast<SCH_PIN*>( aItem ) )
  1376. return dynamic_cast<LIB_SYMBOL*>( pin->GetParentSymbol() ) != nullptr;
  1377. return false;
  1378. };
  1379. PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
  1380. REGISTER_TYPE( SCH_PIN );
  1381. propMgr.AddTypeCast( new TYPE_CAST<SCH_PIN, SCH_ITEM> );
  1382. propMgr.InheritsAfter( TYPE_HASH( SCH_PIN ), TYPE_HASH( SCH_ITEM ) );
  1383. propMgr.AddProperty( new PROPERTY<SCH_PIN, wxString>( _HKI( "Pin Name" ),
  1384. &SCH_PIN::SetName, &SCH_PIN::GetName ) )
  1385. .SetWriteableFunc( isSymbolEditor );
  1386. propMgr.AddProperty( new PROPERTY<SCH_PIN, wxString>( _HKI( "Pin Number" ),
  1387. &SCH_PIN::SetNumber, &SCH_PIN::GetNumber ) )
  1388. .SetWriteableFunc( isSymbolEditor );
  1389. propMgr.AddProperty( new PROPERTY_ENUM<SCH_PIN, ELECTRICAL_PINTYPE>(
  1390. _HKI( "Electrical Type" ),
  1391. &SCH_PIN::SetType, &SCH_PIN::GetType ) )
  1392. .SetWriteableFunc( isSymbolEditor );
  1393. propMgr.AddProperty( new PROPERTY_ENUM<SCH_PIN, GRAPHIC_PINSHAPE>(
  1394. _HKI( "Graphic Style" ),
  1395. &SCH_PIN::SetShape, &SCH_PIN::GetShape ) )
  1396. .SetWriteableFunc( isSymbolEditor );
  1397. propMgr.AddProperty( new PROPERTY<SCH_PIN, int>( _HKI( "Position X" ),
  1398. &SCH_PIN::SetX, &SCH_PIN::GetX, PROPERTY_DISPLAY::PT_COORD ) )
  1399. .SetAvailableFunc( isSymbolEditor );
  1400. propMgr.AddProperty( new PROPERTY<SCH_PIN, int>( _HKI( "Position Y" ),
  1401. &SCH_PIN::SetY, &SCH_PIN::GetY, PROPERTY_DISPLAY::PT_COORD ) )
  1402. .SetAvailableFunc( isSymbolEditor );
  1403. propMgr.AddProperty( new PROPERTY_ENUM<SCH_PIN, PIN_ORIENTATION>( _HKI( "Orientation" ),
  1404. &SCH_PIN::SetOrientation, &SCH_PIN::GetOrientation ) )
  1405. .SetWriteableFunc( isSymbolEditor );
  1406. propMgr.AddProperty( new PROPERTY<SCH_PIN, int>( _HKI( "Length" ),
  1407. &SCH_PIN::SetLength, &SCH_PIN::GetLength,
  1408. PROPERTY_DISPLAY::PT_SIZE ) )
  1409. .SetWriteableFunc( isSymbolEditor );
  1410. propMgr.AddProperty( new PROPERTY<SCH_PIN, int>( _HKI( "Name Text Size" ),
  1411. &SCH_PIN::SetNameTextSize, &SCH_PIN::GetNameTextSize,
  1412. PROPERTY_DISPLAY::PT_SIZE ) )
  1413. .SetAvailableFunc( isSymbolEditor );
  1414. propMgr.AddProperty( new PROPERTY<SCH_PIN, int>( _HKI( "Number Text Size" ),
  1415. &SCH_PIN::SetNumberTextSize, &SCH_PIN::GetNumberTextSize,
  1416. PROPERTY_DISPLAY::PT_SIZE ) )
  1417. .SetAvailableFunc( isSymbolEditor );
  1418. propMgr.AddProperty( new PROPERTY<SCH_PIN, bool>( _HKI( "Visible" ),
  1419. &SCH_PIN::SetVisible, &SCH_PIN::IsVisible ) )
  1420. .SetAvailableFunc( isSymbolEditor );
  1421. }
  1422. } _SCH_PIN_DESC;
  1423. ENUM_TO_WXANY( PIN_ORIENTATION )
  1424. ENUM_TO_WXANY( GRAPHIC_PINSHAPE )
  1425. ENUM_TO_WXANY( ELECTRICAL_PINTYPE )