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.

321 lines
8.0 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2018 CERN
  5. * Copyright (C) 2019-2021 KiCad Developers, see change_log.txt for contributors.
  6. * @author Jon Evans <jon@craftyjon.com>
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. #include <lib_pin.h>
  22. #include <sch_symbol.h>
  23. #include <sch_pin.h>
  24. #include <schematic.h>
  25. #include <schematic_settings.h>
  26. #include <sch_sheet_path.h>
  27. #include <sch_edit_frame.h>
  28. SCH_PIN::SCH_PIN( LIB_PIN* aLibPin, SCH_SYMBOL* aParentSymbol ) :
  29. SCH_ITEM( aParentSymbol, SCH_PIN_T )
  30. {
  31. m_alt = wxEmptyString;
  32. m_number = aLibPin->GetNumber();
  33. m_libPin = aLibPin;
  34. SetPosition( aLibPin->GetPosition() );
  35. m_isDangling = true;
  36. }
  37. /**
  38. * Create a proxy pin from an alternate pin designation.
  39. * The LIB_PIN data will be filled in when the pin is resolved (see SCH_SYMBOL::UpdatePins).
  40. */
  41. SCH_PIN::SCH_PIN( SCH_SYMBOL* aParentSymbol, const wxString& aNumber, const wxString& aAlt ) :
  42. SCH_ITEM( aParentSymbol, SCH_PIN_T )
  43. {
  44. m_alt = aAlt;
  45. m_number = aNumber;
  46. m_libPin = nullptr;
  47. m_isDangling = true;
  48. }
  49. SCH_PIN::SCH_PIN( const SCH_PIN& aPin ) :
  50. SCH_ITEM( aPin )
  51. {
  52. m_alt = aPin.m_alt;
  53. m_number = aPin.m_number;
  54. m_libPin = aPin.m_libPin;
  55. m_position = aPin.m_position;
  56. m_isDangling = aPin.m_isDangling;
  57. }
  58. SCH_PIN& SCH_PIN::operator=( const SCH_PIN& aPin )
  59. {
  60. SCH_ITEM::operator=( aPin );
  61. m_alt = aPin.m_alt;
  62. m_number = aPin.m_number;
  63. m_libPin = aPin.m_libPin;
  64. m_position = aPin.m_position;
  65. m_isDangling = aPin.m_isDangling;
  66. return *this;
  67. }
  68. wxString SCH_PIN::GetName() const
  69. {
  70. if( !m_alt.IsEmpty() )
  71. return m_alt;
  72. return m_libPin->GetName();
  73. }
  74. wxString SCH_PIN::GetShownName() const
  75. {
  76. wxString name = m_libPin->GetName();
  77. if( !m_alt.IsEmpty() )
  78. name = m_alt;
  79. if( name == "~" )
  80. return wxEmptyString;
  81. else
  82. return name;
  83. }
  84. wxString SCH_PIN::GetShownNumber() const
  85. {
  86. if( m_number == "~" )
  87. return wxEmptyString;
  88. else
  89. return m_number;
  90. }
  91. ELECTRICAL_PINTYPE SCH_PIN::GetType() const
  92. {
  93. if( !m_alt.IsEmpty() )
  94. return m_libPin->GetAlt( m_alt ).m_Type;
  95. return m_libPin->GetType();
  96. }
  97. GRAPHIC_PINSHAPE SCH_PIN::GetShape() const
  98. {
  99. if( !m_alt.IsEmpty() )
  100. return m_libPin->GetAlt( m_alt ).m_Shape;
  101. return m_libPin->GetShape();
  102. }
  103. int SCH_PIN::GetOrientation() const
  104. {
  105. return m_libPin->GetOrientation();
  106. }
  107. int SCH_PIN::GetLength() const
  108. {
  109. return m_libPin->GetLength();
  110. }
  111. bool SCH_PIN::Matches( const wxFindReplaceData& aSearchData, void* aAuxDat ) const
  112. {
  113. if( !( aSearchData.GetFlags() & FR_SEARCH_ALL_PINS ) )
  114. return false;
  115. return EDA_ITEM::Matches( GetName(), aSearchData )
  116. || EDA_ITEM::Matches( GetNumber(), aSearchData );
  117. }
  118. bool SCH_PIN::Replace( const wxFindReplaceData& aSearchData, void* aAuxData )
  119. {
  120. bool isReplaced = false;
  121. /* TODO: waiting on a way to override pins in the schematic...
  122. isReplaced |= EDA_ITEM::Replace( aSearchData, m_name );
  123. isReplaced |= EDA_ITEM::Replace( aSearchData, m_number );
  124. */
  125. return isReplaced;
  126. }
  127. SCH_SYMBOL* SCH_PIN::GetParentSymbol() const
  128. {
  129. return static_cast<SCH_SYMBOL*>( GetParent() );
  130. }
  131. wxString SCH_PIN::GetSelectMenuText( EDA_UNITS aUnits ) const
  132. {
  133. return wxString::Format( "%s %s",
  134. GetParentSymbol()->GetSelectMenuText( aUnits ),
  135. m_libPin->GetSelectMenuText( aUnits ) );
  136. }
  137. void SCH_PIN::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
  138. {
  139. wxString msg;
  140. aList.emplace_back( _( "Type" ), _( "Pin" ) );
  141. if( m_libPin->GetUnit() == 0 )
  142. msg = _( "All" );
  143. else
  144. msg.Printf( wxT( "%d" ), m_libPin->GetUnit() );
  145. aList.emplace_back( _( "Unit" ), msg );
  146. if( m_libPin->GetConvert() == LIB_ITEM::LIB_CONVERT::BASE )
  147. msg = _( "no" );
  148. else if( m_libPin->GetConvert() == LIB_ITEM::LIB_CONVERT::DEMORGAN )
  149. msg = _( "yes" );
  150. else
  151. msg = wxT( "?" );
  152. aList.emplace_back( _( "Converted" ), msg );
  153. aList.emplace_back( _( "Name" ), GetShownName() );
  154. aList.emplace_back( _( "Number" ), GetShownNumber() );
  155. aList.emplace_back( _( "Type" ), ElectricalPinTypeGetText( GetType() ) );
  156. aList.emplace_back( _( "Style" ), PinShapeGetText( GetShape() ) );
  157. aList.emplace_back( _( "Visible" ), IsVisible() ? _( "Yes" ) : _( "No" ) );
  158. aList.emplace_back( _( "Length" ), StringFromValue( aFrame->GetUserUnits(), GetLength() ) );
  159. int i = PinOrientationIndex( GetOrientation() );
  160. aList.emplace_back( _( "Orientation" ), PinOrientationName( (unsigned) i ) );
  161. SCH_EDIT_FRAME* schframe = dynamic_cast<SCH_EDIT_FRAME*>( aFrame );
  162. SCH_SHEET_PATH* currentSheet = schframe ? &schframe->GetCurrentSheet() : nullptr;
  163. SCH_SYMBOL* symbol = GetParentSymbol();
  164. aList.emplace_back( symbol->GetRef( currentSheet ), symbol->GetValue( currentSheet, true ) );
  165. #if defined(DEBUG)
  166. if( dynamic_cast<SCH_EDIT_FRAME*>( aFrame ) )
  167. {
  168. SCH_CONNECTION* conn = Connection();
  169. if( conn )
  170. conn->AppendInfoToMsgPanel( aList );
  171. }
  172. #endif
  173. }
  174. void SCH_PIN::ClearDefaultNetName( const SCH_SHEET_PATH* aPath )
  175. {
  176. std::lock_guard<std::recursive_mutex> lock( m_netmap_mutex );
  177. if( aPath )
  178. m_net_name_map.erase( *aPath );
  179. else
  180. m_net_name_map.clear();
  181. }
  182. wxString SCH_PIN::GetDefaultNetName( const SCH_SHEET_PATH& aPath, bool aForceNoConnect )
  183. {
  184. if( m_libPin->IsPowerConnection() )
  185. return m_libPin->GetName();
  186. std::lock_guard<std::recursive_mutex> lock( m_netmap_mutex );
  187. auto it = m_net_name_map.find( aPath );
  188. if( it != m_net_name_map.end() )
  189. {
  190. if( it->second.second == aForceNoConnect )
  191. return it->second.first;
  192. }
  193. wxString name = "Net-(";
  194. if( aForceNoConnect || GetType() == ELECTRICAL_PINTYPE::PT_NC )
  195. name = ( "unconnected-(" );
  196. name << GetParentSymbol()->GetRef( &aPath );
  197. bool annotated = true;
  198. // Add timestamp for uninitialized symbols
  199. if( name.Last() == '?' )
  200. {
  201. name << GetParentSymbol()->m_Uuid.AsString();
  202. annotated = false;
  203. }
  204. name << "-Pad" << m_libPin->GetNumber() << ")";
  205. if( annotated )
  206. m_net_name_map[ aPath ] = std::make_pair( name, aForceNoConnect );
  207. return name;
  208. }
  209. wxPoint SCH_PIN::GetTransformedPosition() const
  210. {
  211. TRANSFORM t = GetParentSymbol()->GetTransform();
  212. return t.TransformCoordinate( GetLocalPosition() ) + GetParentSymbol()->GetPosition();
  213. }
  214. const EDA_RECT SCH_PIN::GetBoundingBox() const
  215. {
  216. TRANSFORM t = GetParentSymbol()->GetTransform();
  217. EDA_RECT r = m_libPin->GetBoundingBox();
  218. r.RevertYAxis();
  219. r = t.TransformCoordinate( r );
  220. r.Offset( GetParentSymbol()->GetPosition() );
  221. return r;
  222. }
  223. bool SCH_PIN::HitTest( const wxPoint& aPosition, int aAccuracy ) const
  224. {
  225. // When looking for an "exact" hit aAccuracy will be 0 which works poorly if the pin has
  226. // no pin number or name. Give it a floor.
  227. if( Schematic() )
  228. aAccuracy = std::max( aAccuracy, Schematic()->Settings().m_PinSymbolSize / 4 );
  229. EDA_RECT rect = GetBoundingBox();
  230. return rect.Inflate( aAccuracy ).Contains( aPosition );
  231. }
  232. bool SCH_PIN::ConnectionPropagatesTo( const EDA_ITEM* aItem ) const
  233. {
  234. // Reciprocal checking is done in CONNECTION_GRAPH anyway
  235. return !( m_libPin->GetType() == ELECTRICAL_PINTYPE::PT_NC );
  236. }