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.

300 lines
8.3 KiB

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 The 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. #include <string_utils.h>
  31. PCB_FIELD::PCB_FIELD( FOOTPRINT* aParent, FIELD_T aFieldId, const wxString& aName ) :
  32. PCB_TEXT( aParent, PCB_FIELD_T ),
  33. m_id( aFieldId ),
  34. m_ordinal( 0 ),
  35. m_name( aName )
  36. {
  37. if( m_id == FIELD_T::USER )
  38. m_ordinal = aParent->GetNextFieldOrdinal();
  39. }
  40. PCB_FIELD::PCB_FIELD( const PCB_TEXT& aText, FIELD_T aFieldId, const wxString& aName ) :
  41. PCB_TEXT( aText.GetParent(), PCB_FIELD_T ),
  42. m_id( aFieldId ),
  43. m_ordinal( static_cast<int>( aFieldId ) ),
  44. m_name( aName )
  45. {
  46. // Copy the text properties from the PCB_TEXT
  47. SetText( aText.GetText() );
  48. SetVisible( aText.IsVisible() );
  49. SetLayer( aText.GetLayer() );
  50. SetPosition( aText.GetPosition() );
  51. SetAttributes( aText.GetAttributes() );
  52. }
  53. void PCB_FIELD::Serialize( google::protobuf::Any &aContainer ) const
  54. {
  55. kiapi::board::types::Field field;
  56. google::protobuf::Any anyText;
  57. PCB_TEXT::Serialize( anyText );
  58. anyText.UnpackTo( field.mutable_text() );
  59. field.set_name( GetCanonicalName().ToStdString() );
  60. field.mutable_id()->set_id( (int) GetId() );
  61. field.set_visible( IsVisible() );
  62. aContainer.PackFrom( field );
  63. }
  64. bool PCB_FIELD::Deserialize( const google::protobuf::Any &aContainer )
  65. {
  66. kiapi::board::types::Field field;
  67. if( !aContainer.UnpackTo( &field ) )
  68. return false;
  69. if( field.has_id() )
  70. setId( (FIELD_T) field.id().id() );
  71. // Mandatory fields have a blank Name in the KiCad object
  72. if( !IsMandatory() )
  73. SetName( wxString( field.name().c_str(), wxConvUTF8 ) );
  74. if( field.has_text() )
  75. {
  76. google::protobuf::Any anyText;
  77. anyText.PackFrom( field.text() );
  78. PCB_TEXT::Deserialize( anyText );
  79. }
  80. SetVisible( field.visible() );
  81. if( field.text().layer() == kiapi::board::types::BoardLayer::BL_UNKNOWN )
  82. SetLayer( F_SilkS );
  83. return true;
  84. }
  85. wxString PCB_FIELD::GetName( bool aUseDefaultName ) const
  86. {
  87. if( IsMandatory() )
  88. return GetCanonicalFieldName( m_id );
  89. else if( m_name.IsEmpty() && aUseDefaultName )
  90. return GetUserFieldName( m_ordinal, !DO_TRANSLATE );
  91. else
  92. return m_name;
  93. }
  94. wxString PCB_FIELD::GetCanonicalName() const
  95. {
  96. return GetName( true );
  97. }
  98. bool PCB_FIELD::IsMandatory() const
  99. {
  100. return m_id == FIELD_T::REFERENCE
  101. || m_id == FIELD_T::VALUE
  102. || m_id == FIELD_T::DATASHEET
  103. || m_id == FIELD_T::DESCRIPTION;
  104. }
  105. bool PCB_FIELD::IsHypertext() const
  106. {
  107. return IsURL( GetShownText( false ) );
  108. }
  109. wxString PCB_FIELD::GetTextTypeDescription() const
  110. {
  111. if( IsMandatory() )
  112. return GetCanonicalFieldName( m_id );
  113. else
  114. return _( "User Field" );
  115. }
  116. bool PCB_FIELD::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
  117. {
  118. if( !IsVisible() && !aSearchData.searchAllFields )
  119. return false;
  120. return PCB_TEXT::Matches( aSearchData, aAuxData );
  121. }
  122. wxString PCB_FIELD::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
  123. {
  124. wxString content = aFull ? GetShownText( false ) : KIUI::EllipsizeMenuText( GetText() );
  125. wxString ref = GetParentFootprint()->GetReference();
  126. switch( m_id )
  127. {
  128. case FIELD_T::REFERENCE:
  129. return wxString::Format( _( "Reference field of %s" ), ref );
  130. case FIELD_T::VALUE:
  131. return wxString::Format( _( "Value field of %s (%s)" ), ref, content );
  132. case FIELD_T::FOOTPRINT:
  133. return wxString::Format( _( "Footprint field of %s (%s)" ), ref, content );
  134. case FIELD_T::DATASHEET:
  135. return wxString::Format( _( "Datasheet field of %s (%s)" ), ref, content );
  136. default:
  137. if( GetName().IsEmpty() )
  138. return wxString::Format( _( "Field of %s (%s)" ), ref, content );
  139. else
  140. return wxString::Format( _( "%s field of %s (%s)" ), GetName(), ref, content );
  141. }
  142. }
  143. double PCB_FIELD::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
  144. {
  145. if( !aView )
  146. return LOD_SHOW;
  147. KIGFX::PCB_PAINTER* painter = static_cast<KIGFX::PCB_PAINTER*>( aView->GetPainter() );
  148. KIGFX::PCB_RENDER_SETTINGS* renderSettings = painter->GetSettings();
  149. if( GetParentFootprint() && GetParentFootprint()->IsSelected()
  150. && renderSettings->m_ForceShowFieldsWhenFPSelected )
  151. {
  152. return LOD_SHOW;
  153. }
  154. // Handle Render tab switches
  155. if( IsValue() && !aView->IsLayerVisible( LAYER_FP_VALUES ) )
  156. return LOD_HIDE;
  157. if( IsReference() && !aView->IsLayerVisible( LAYER_FP_REFERENCES ) )
  158. return LOD_HIDE;
  159. return PCB_TEXT::ViewGetLOD( aLayer, aView );
  160. }
  161. EDA_ITEM* PCB_FIELD::Clone() const
  162. {
  163. return new PCB_FIELD( *this );
  164. }
  165. void PCB_FIELD::swapData( BOARD_ITEM* aImage )
  166. {
  167. assert( aImage->Type() == PCB_FIELD_T );
  168. std::swap( *((PCB_FIELD*) this), *((PCB_FIELD*) aImage) );
  169. }
  170. bool PCB_FIELD::operator==( const BOARD_ITEM& aOther ) const
  171. {
  172. if( aOther.Type() != Type() )
  173. return false;
  174. const PCB_FIELD& other = static_cast<const PCB_FIELD&>( aOther );
  175. return *this == other;
  176. }
  177. bool PCB_FIELD::operator==( const PCB_FIELD& aOther ) const
  178. {
  179. if( IsMandatory() != aOther.IsMandatory() )
  180. return false;
  181. if( IsMandatory() )
  182. {
  183. if( m_id != aOther.m_id )
  184. return false;
  185. }
  186. else
  187. {
  188. if( m_ordinal != aOther.m_ordinal )
  189. return false;
  190. }
  191. return m_name == aOther.m_name && EDA_TEXT::operator==( aOther );
  192. }
  193. double PCB_FIELD::Similarity( const BOARD_ITEM& aOther ) const
  194. {
  195. if( m_Uuid == aOther.m_Uuid )
  196. return 1.0;
  197. if( aOther.Type() != Type() )
  198. return 0.0;
  199. const PCB_FIELD& other = static_cast<const PCB_FIELD&>( aOther );
  200. if( IsMandatory() || other.IsMandatory() )
  201. {
  202. if( m_id == other.m_id )
  203. return 1.0;
  204. else
  205. return 0.0;
  206. }
  207. if( m_name == other.m_name )
  208. return 1.0;
  209. return EDA_TEXT::Similarity( other );
  210. }
  211. static struct PCB_FIELD_DESC
  212. {
  213. PCB_FIELD_DESC()
  214. {
  215. PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
  216. REGISTER_TYPE( PCB_FIELD );
  217. propMgr.AddTypeCast( new TYPE_CAST<PCB_FIELD, PCB_TEXT> );
  218. propMgr.AddTypeCast( new TYPE_CAST<PCB_FIELD, BOARD_ITEM> );
  219. propMgr.AddTypeCast( new TYPE_CAST<PCB_FIELD, EDA_TEXT> );
  220. propMgr.InheritsAfter( TYPE_HASH( PCB_FIELD ), TYPE_HASH( BOARD_ITEM ) );
  221. propMgr.InheritsAfter( TYPE_HASH( PCB_FIELD ), TYPE_HASH( PCB_TEXT ) );
  222. propMgr.InheritsAfter( TYPE_HASH( PCB_FIELD ), TYPE_HASH( EDA_TEXT ) );
  223. propMgr.AddProperty( new PROPERTY<PCB_FIELD, wxString>( _HKI( "Name" ),
  224. NO_SETTER( PCB_FIELD, wxString ), &PCB_FIELD::GetCanonicalName ) )
  225. .SetIsHiddenFromLibraryEditors()
  226. .SetIsHiddenFromPropertiesManager();
  227. // These properties, inherited from EDA_TEXT, have no sense for the board editor
  228. propMgr.Mask( TYPE_HASH( PCB_FIELD ), TYPE_HASH( EDA_TEXT ), _HKI( "Hyperlink" ) );
  229. propMgr.Mask( TYPE_HASH( PCB_FIELD ), TYPE_HASH( EDA_TEXT ), _HKI( "Color" ) );
  230. }
  231. } _PCB_FIELD_DESC;