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.

280 lines
7.9 KiB

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) 2023 Mike Williams, mike@mikebwilliams.com
  5. * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, you may find one here:
  19. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  20. * or you may search the http://www.gnu.org website for the version 2 license,
  21. * or you may write to the Free Software Foundation, Inc.,
  22. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  23. */
  24. #include <pcb_field.h>
  25. #include <footprint.h>
  26. #include <board_design_settings.h>
  27. #include <i18n_utility.h>
  28. #include <pcb_painter.h>
  29. #include <api/board/board_types.pb.h>
  30. PCB_FIELD::PCB_FIELD( FOOTPRINT* aParent, int aFieldId, const wxString& aName ) :
  31. PCB_TEXT( aParent, PCB_FIELD_T ),
  32. m_id( aFieldId ),
  33. m_name( aName )
  34. {
  35. }
  36. PCB_FIELD::PCB_FIELD( const PCB_TEXT& aText, int aFieldId, const wxString& aName ) :
  37. PCB_TEXT( aText ),
  38. m_id( aFieldId ),
  39. m_name( aName )
  40. {
  41. }
  42. void PCB_FIELD::Serialize( google::protobuf::Any &aContainer ) const
  43. {
  44. kiapi::board::types::Field field;
  45. google::protobuf::Any anyText;
  46. PCB_TEXT::Serialize( anyText );
  47. anyText.UnpackTo( field.mutable_text() );
  48. field.set_name( GetCanonicalName().ToStdString() );
  49. field.mutable_id()->set_id( GetId() );
  50. aContainer.PackFrom( field );
  51. }
  52. bool PCB_FIELD::Deserialize( const google::protobuf::Any &aContainer )
  53. {
  54. kiapi::board::types::Field field;
  55. if( !aContainer.UnpackTo( &field ) )
  56. return false;
  57. if( field.has_id() )
  58. setId( field.id().id() );
  59. // Mandatory fields have a blank Name in the KiCad object
  60. if( m_id >= MANDATORY_FIELDS )
  61. SetName( wxString( field.name().c_str(), wxConvUTF8 ) );
  62. if( field.has_text() )
  63. {
  64. google::protobuf::Any anyText;
  65. anyText.PackFrom( field.text() );
  66. PCB_TEXT::Deserialize( anyText );
  67. }
  68. if( field.text().layer() == kiapi::board::types::BoardLayer::BL_UNKNOWN )
  69. SetLayer( F_SilkS );
  70. return true;
  71. }
  72. wxString PCB_FIELD::GetName( bool aUseDefaultName ) const
  73. {
  74. if( m_parent && m_parent->Type() == PCB_FOOTPRINT_T )
  75. {
  76. if( m_id >= 0 && m_id < MANDATORY_FIELDS )
  77. return GetCanonicalFieldName( m_id );
  78. else if( m_name.IsEmpty() && aUseDefaultName )
  79. return TEMPLATE_FIELDNAME::GetDefaultFieldName( m_id );
  80. else
  81. return m_name;
  82. }
  83. else
  84. {
  85. wxFAIL_MSG( "Unhandled field owner type." );
  86. return m_name;
  87. }
  88. }
  89. wxString PCB_FIELD::GetCanonicalName() const
  90. {
  91. if( m_parent && m_parent->Type() == PCB_FOOTPRINT_T )
  92. {
  93. if( m_id < MANDATORY_FIELDS )
  94. return GetCanonicalFieldName( m_id );
  95. else
  96. return m_name;
  97. }
  98. else
  99. {
  100. if( m_parent )
  101. {
  102. wxFAIL_MSG( wxString::Format( "Unhandled field owner type (id %d, parent type %d).",
  103. m_id, m_parent->Type() ) );
  104. }
  105. return m_name;
  106. }
  107. }
  108. wxString PCB_FIELD::GetTextTypeDescription() const
  109. {
  110. if( m_id < MANDATORY_FIELDS )
  111. return GetCanonicalFieldName( m_id );
  112. else
  113. return _( "User Field" );
  114. }
  115. wxString PCB_FIELD::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
  116. {
  117. switch( m_id )
  118. {
  119. case REFERENCE_FIELD:
  120. return wxString::Format( _( "Reference '%s'" ),
  121. GetParentFootprint()->GetReference() );
  122. case VALUE_FIELD:
  123. return wxString::Format( _( "Value '%s' of %s" ),
  124. KIUI::EllipsizeMenuText( GetText() ),
  125. GetParentFootprint()->GetReference() );
  126. case FOOTPRINT_FIELD:
  127. return wxString::Format( _( "Footprint '%s' of %s" ),
  128. KIUI::EllipsizeMenuText( GetText() ),
  129. GetParentFootprint()->GetReference() );
  130. case DATASHEET_FIELD:
  131. return wxString::Format( _( "Datasheet '%s' of %s" ),
  132. KIUI::EllipsizeMenuText( GetText() ),
  133. GetParentFootprint()->GetReference() );
  134. default:
  135. break; // avoid unreachable code / missing return statement warnings
  136. }
  137. return wxString::Format( _( "Field '%s' of %s" ), KIUI::EllipsizeMenuText( GetText() ),
  138. GetParentFootprint()->GetReference() );
  139. }
  140. double PCB_FIELD::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
  141. {
  142. constexpr double HIDE = std::numeric_limits<double>::max();
  143. if( !aView )
  144. return 0.0;
  145. KIGFX::PCB_PAINTER* painter = static_cast<KIGFX::PCB_PAINTER*>( aView->GetPainter() );
  146. KIGFX::PCB_RENDER_SETTINGS* renderSettings = painter->GetSettings();
  147. if( GetParentFootprint() && GetParentFootprint()->IsSelected()
  148. && renderSettings->m_ForceShowFieldsWhenFPSelected )
  149. {
  150. return 0.0;
  151. }
  152. // Handle Render tab switches
  153. if( IsValue() && !aView->IsLayerVisible( LAYER_FP_VALUES ) )
  154. return HIDE;
  155. if( IsReference() && !aView->IsLayerVisible( LAYER_FP_REFERENCES ) )
  156. return HIDE;
  157. return PCB_TEXT::ViewGetLOD( aLayer, aView );
  158. }
  159. EDA_ITEM* PCB_FIELD::Clone() const
  160. {
  161. return new PCB_FIELD( *this );
  162. }
  163. void PCB_FIELD::swapData( BOARD_ITEM* aImage )
  164. {
  165. assert( aImage->Type() == PCB_FIELD_T );
  166. std::swap( *((PCB_FIELD*) this), *((PCB_FIELD*) aImage) );
  167. }
  168. bool PCB_FIELD::operator==( const BOARD_ITEM& aOther ) const
  169. {
  170. if( aOther.Type() != Type() )
  171. return false;
  172. const PCB_FIELD& other = static_cast<const PCB_FIELD&>( aOther );
  173. return *this == other;
  174. }
  175. bool PCB_FIELD::operator==( const PCB_FIELD& aOther ) const
  176. {
  177. return m_id == aOther.m_id && m_name == aOther.m_name && EDA_TEXT::operator==( aOther );
  178. }
  179. double PCB_FIELD::Similarity( const BOARD_ITEM& aOther ) const
  180. {
  181. if( m_Uuid == aOther.m_Uuid )
  182. return 1.0;
  183. if( aOther.Type() != Type() )
  184. return 0.0;
  185. const PCB_FIELD& other = static_cast<const PCB_FIELD&>( aOther );
  186. if( m_id < MANDATORY_FIELDS || other.m_id < MANDATORY_FIELDS )
  187. {
  188. if( m_id == other.m_id )
  189. return 1.0;
  190. else
  191. return 0.0;
  192. }
  193. if( m_name == other.m_name )
  194. return 1.0;
  195. return EDA_TEXT::Similarity( other );
  196. }
  197. static struct PCB_FIELD_DESC
  198. {
  199. PCB_FIELD_DESC()
  200. {
  201. PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
  202. REGISTER_TYPE( PCB_FIELD );
  203. propMgr.AddTypeCast( new TYPE_CAST<PCB_FIELD, PCB_TEXT> );
  204. propMgr.AddTypeCast( new TYPE_CAST<PCB_FIELD, BOARD_ITEM> );
  205. propMgr.AddTypeCast( new TYPE_CAST<PCB_FIELD, EDA_TEXT> );
  206. propMgr.InheritsAfter( TYPE_HASH( PCB_FIELD ), TYPE_HASH( BOARD_ITEM ) );
  207. propMgr.InheritsAfter( TYPE_HASH( PCB_FIELD ), TYPE_HASH( PCB_TEXT ) );
  208. propMgr.InheritsAfter( TYPE_HASH( PCB_FIELD ), TYPE_HASH( EDA_TEXT ) );
  209. auto isNotFootprintFootprint =
  210. []( INSPECTABLE* aItem ) -> bool
  211. {
  212. if( PCB_FIELD* field = dynamic_cast<PCB_FIELD*>( aItem ) )
  213. return !field->IsFootprint();
  214. return true;
  215. };
  216. propMgr.OverrideAvailability( TYPE_HASH( PCB_FIELD ), TYPE_HASH( EDA_TEXT ), _HKI( "Text" ),
  217. isNotFootprintFootprint );
  218. }
  219. } _PCB_FIELD_DESC;