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.

243 lines
6.8 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2017 Chris Pavlina <pavlina.chris@gmail.com>
  5. * Copyright (C) 2017-2022 KiCad Developers, see AUTHORS.txt for contributors.
  6. *
  7. * This program is free software: you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License as published by the
  9. * Free Software Foundation, either version 3 of the License, or (at your
  10. * option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include <generate_alias_info.h>
  21. #include <string_utils.h>
  22. #include <template_fieldnames.h>
  23. #include <lib_symbol.h>
  24. #include <symbol_lib_table.h>
  25. #include <wx/log.h>
  26. static const wxString DescriptionFormat =
  27. "<b>__NAME__</b>"
  28. "__ALIASOF__"
  29. "__DESC__"
  30. "__KEY__"
  31. "<hr><table border=0>"
  32. "__FIELDS__"
  33. "</table>";
  34. static const wxString AliasOfFormat = "<br><i>" + _( "Derived from" ) + " %s (%s)</i>";
  35. static const wxString DescFormat = "<br>%s";
  36. static const wxString KeywordsFormat = "<br>" + _( "Keywords" ) + ": %s";
  37. static const wxString FieldFormat =
  38. "<tr>"
  39. " <td><b>__NAME__</b></td>"
  40. " <td>__VALUE__</td>"
  41. "</tr>";
  42. static const wxString DatasheetLinkFormat = "<a href=\"__HREF__\">__TEXT__</a>";
  43. class FOOTPRINT_INFO_GENERATOR
  44. {
  45. wxString m_html;
  46. SYMBOL_LIB_TABLE* m_sym_lib_table;
  47. LIB_ID const m_lib_id;
  48. LIB_SYMBOL* m_symbol;
  49. int m_unit;
  50. public:
  51. FOOTPRINT_INFO_GENERATOR( SYMBOL_LIB_TABLE* aSymbolLibTable, LIB_ID const& aLibId, int aUnit )
  52. : m_html( DescriptionFormat ),
  53. m_sym_lib_table( aSymbolLibTable ),
  54. m_lib_id( aLibId ),
  55. m_symbol( nullptr ),
  56. m_unit( aUnit )
  57. { }
  58. /**
  59. * Generate the HTML internally.
  60. */
  61. void GenerateHtml()
  62. {
  63. wxCHECK_RET( m_sym_lib_table, "Symbol library table pointer is not valid" );
  64. if( !m_lib_id.IsValid() )
  65. return;
  66. try
  67. {
  68. m_symbol = m_sym_lib_table->LoadSymbol( m_lib_id );
  69. }
  70. catch( const IO_ERROR& ioe )
  71. {
  72. wxLogError( _( "Error loading symbol %s from library '%s'." ) + wxS( "\n%s" ),
  73. m_lib_id.GetLibItemName().wx_str(),
  74. m_lib_id.GetLibNickname().wx_str(),
  75. ioe.What() );
  76. return;
  77. }
  78. if( m_symbol )
  79. {
  80. SetHtmlName();
  81. SetHtmlAliasOf();
  82. SetHtmlDesc();
  83. SetHtmlKeywords();
  84. SetHtmlFieldTable();
  85. }
  86. }
  87. /**
  88. * Return the generated HTML.
  89. */
  90. wxString GetHtml() const
  91. {
  92. return m_html;
  93. }
  94. protected:
  95. void SetHtmlName()
  96. {
  97. m_html.Replace( "__NAME__", EscapeHTML( UnescapeString( m_symbol->GetName() ) ) );
  98. }
  99. void SetHtmlAliasOf()
  100. {
  101. if( m_symbol->IsRoot() )
  102. {
  103. m_html.Replace( "__ALIASOF__", wxEmptyString );
  104. }
  105. else
  106. {
  107. wxString root_name = _( "Unknown" );
  108. wxString root_desc = "";
  109. std::shared_ptr< LIB_SYMBOL > parent = m_symbol->GetParent().lock();
  110. if( parent )
  111. {
  112. root_name = parent->GetName();
  113. root_desc = parent->GetDescription();
  114. }
  115. m_html.Replace( "__ALIASOF__", wxString::Format( AliasOfFormat,
  116. EscapeHTML( UnescapeString( root_name ) ),
  117. EscapeHTML( root_desc ) ) );
  118. }
  119. }
  120. void SetHtmlDesc()
  121. {
  122. wxString raw_desc = m_symbol->GetDescription();
  123. m_html.Replace( "__DESC__", wxString::Format( DescFormat, EscapeHTML( raw_desc ) ) );
  124. }
  125. void SetHtmlKeywords()
  126. {
  127. wxString keywords = m_symbol->GetKeyWords();
  128. if( keywords.empty() )
  129. m_html.Replace( "__KEY__", wxEmptyString );
  130. else
  131. m_html.Replace( "__KEY__", wxString::Format( KeywordsFormat, EscapeHTML( keywords ) ) );
  132. }
  133. wxString GetHtmlFieldRow( const LIB_FIELD& aField ) const
  134. {
  135. wxString name = aField.GetCanonicalName();
  136. wxString text = aField.GetFullText( m_unit > 0 ? m_unit : 1 );
  137. wxString fieldhtml = FieldFormat;
  138. fieldhtml.Replace( "__NAME__", EscapeHTML( name ) );
  139. switch( aField.GetId() )
  140. {
  141. case DATASHEET_FIELD:
  142. text = m_symbol->GetDatasheetField().GetText();
  143. if( text.IsEmpty() || text == wxT( "~" ) )
  144. {
  145. fieldhtml.Replace( "__VALUE__", text );
  146. }
  147. else
  148. {
  149. wxString datasheetlink = DatasheetLinkFormat;
  150. datasheetlink.Replace( "__HREF__", EscapeHTML( text ) );
  151. if( text.Length() > 75 )
  152. text = text.Left( 72 ) + wxT( "..." );
  153. datasheetlink.Replace( "__TEXT__", EscapeHTML( text ) );
  154. fieldhtml.Replace( "__VALUE__", datasheetlink );
  155. }
  156. break;
  157. case VALUE_FIELD:
  158. // showing the value just repeats the name, so that's not much use...
  159. return wxEmptyString;
  160. default:
  161. fieldhtml.Replace( "__VALUE__", EscapeHTML( text ) );
  162. }
  163. return fieldhtml;
  164. }
  165. void SetHtmlFieldTable()
  166. {
  167. wxString fieldtable;
  168. std::vector<LIB_FIELD*> fields;
  169. m_symbol->GetFields( fields );
  170. for( const LIB_FIELD* field: fields )
  171. fieldtable += GetHtmlFieldRow( *field );
  172. if( m_symbol->IsAlias() )
  173. {
  174. std::shared_ptr<LIB_SYMBOL> parent = m_symbol->GetParent().lock();
  175. // Append all of the unique parent fields if this is an alias.
  176. if( parent )
  177. {
  178. std::vector<LIB_FIELD*> parentFields;
  179. parent->GetFields( parentFields );
  180. for( const LIB_FIELD* parentField : parentFields )
  181. {
  182. if( m_symbol->FindField( parentField->GetCanonicalName() ) )
  183. continue;
  184. fieldtable += GetHtmlFieldRow( *parentField );
  185. }
  186. }
  187. }
  188. m_html.Replace( "__FIELDS__", fieldtable );
  189. }
  190. };
  191. wxString GenerateAliasInfo( SYMBOL_LIB_TABLE* aSymLibTable, LIB_ID const& aLibId, int aUnit )
  192. {
  193. FOOTPRINT_INFO_GENERATOR gen( aSymLibTable, aLibId, aUnit );
  194. gen.GenerateHtml();
  195. return gen.GetHtml();
  196. }