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.

352 lines
10 KiB

2 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.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 <sch_draw_panel.h>
  25. #include <trigo.h>
  26. #include <widgets/msgpanel.h>
  27. #include <bitmaps.h>
  28. #include <base_units.h>
  29. #include <eda_draw_frame.h>
  30. #include <erc_settings.h>
  31. #include <sch_marker.h>
  32. #include <schematic.h>
  33. #include <widgets/ui_common.h>
  34. #include <pgm_base.h>
  35. #include <settings/settings_manager.h>
  36. #include <settings/color_settings.h>
  37. #include <erc_item.h>
  38. #include <sch_screen.h>
  39. /// Factor to convert the maker unit shape to internal units:
  40. #define SCALING_FACTOR schIUScale.mmToIU( 0.15 )
  41. SCH_MARKER::SCH_MARKER( std::shared_ptr<ERC_ITEM> aItem, const VECTOR2I& aPos ) :
  42. SCH_ITEM( nullptr, SCH_MARKER_T ),
  43. MARKER_BASE( SCALING_FACTOR, aItem, MARKER_BASE::MARKER_ERC )
  44. {
  45. if( m_rcItem )
  46. m_rcItem->SetParent( this );
  47. m_Pos = aPos;
  48. m_isLegacyMarker = false;
  49. }
  50. SCH_MARKER::~SCH_MARKER()
  51. {
  52. if( m_rcItem )
  53. m_rcItem->SetParent( nullptr );
  54. }
  55. EDA_ITEM* SCH_MARKER::Clone() const
  56. {
  57. return new SCH_MARKER( *this );
  58. }
  59. void SCH_MARKER::SwapData( SCH_ITEM* aItem )
  60. {
  61. SCH_ITEM::SwapFlags( aItem );
  62. SCH_MARKER* item = static_cast<SCH_MARKER*>( aItem );
  63. std::swap( m_isLegacyMarker, item->m_isLegacyMarker );
  64. std::swap( m_Pos, item->m_Pos );
  65. std::swap( m_markerType, item->m_markerType );
  66. std::swap( m_excluded, item->m_excluded );
  67. std::swap( m_rcItem, item->m_rcItem );
  68. std::swap( m_scalingFactor, item->m_scalingFactor );
  69. std::swap( m_shapeBoundingBox, item->m_shapeBoundingBox );
  70. std::swap( *((SCH_MARKER*) this), *((SCH_MARKER*) aItem ) );
  71. }
  72. wxString SCH_MARKER::Serialize() const
  73. {
  74. std::shared_ptr<ERC_ITEM> erc = std::static_pointer_cast<ERC_ITEM>( m_rcItem );
  75. wxString sheetSpecificPath, mainItemPath, auxItemPath;
  76. if( erc->IsSheetSpecific() )
  77. sheetSpecificPath = erc->GetSpecificSheetPath().Path().AsString();
  78. if( erc->MainItemHasSheetPath() )
  79. mainItemPath = erc->GetMainItemSheetPath().Path().AsString();
  80. if( erc->AuxItemHasSheetPath() )
  81. auxItemPath = erc->GetAuxItemSheetPath().Path().AsString();
  82. return wxString::Format( wxT( "%s|%d|%d|%s|%s|%s|%s|%s" ), m_rcItem->GetSettingsKey(), m_Pos.x,
  83. m_Pos.y, m_rcItem->GetMainItemID().AsString(),
  84. m_rcItem->GetAuxItemID().AsString(), sheetSpecificPath, mainItemPath,
  85. auxItemPath );
  86. }
  87. SCH_MARKER* SCH_MARKER::Deserialize( SCHEMATIC* schematic, const wxString& data )
  88. {
  89. wxArrayString props = wxSplit( data, '|' );
  90. VECTOR2I markerPos( (int) strtol( props[1].c_str(), nullptr, 10 ),
  91. (int) strtol( props[2].c_str(), nullptr, 10 ) );
  92. std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( props[0] );
  93. if( !ercItem )
  94. return nullptr;
  95. ercItem->SetItems( KIID( props[3] ), KIID( props[4] ) );
  96. bool isLegacyMarker = true;
  97. // Deserialize sheet / item specific paths - we are not able to use the file version to determine
  98. // if markers are legacy as there could be a file opened with a prior version but which has
  99. // new markers - this code is called not just during schematic load, but also to match new
  100. // ERC exceptions to exclusions.
  101. if( props.size() == 8 )
  102. {
  103. isLegacyMarker = false;
  104. SCH_SHEET_LIST sheetPaths = schematic->GetSheets();
  105. if( !props[5].IsEmpty() )
  106. {
  107. KIID_PATH sheetSpecificKiidPath( props[5] );
  108. std::optional<SCH_SHEET_PATH> sheetSpecificPath =
  109. sheetPaths.GetSheetPathByKIIDPath( sheetSpecificKiidPath, true );
  110. if( sheetSpecificPath.has_value() )
  111. ercItem->SetSheetSpecificPath( sheetSpecificPath.value() );
  112. }
  113. if( !props[6].IsEmpty() )
  114. {
  115. KIID_PATH mainItemKiidPath( props[6] );
  116. std::optional<SCH_SHEET_PATH> mainItemPath =
  117. sheetPaths.GetSheetPathByKIIDPath( mainItemKiidPath, true );
  118. if( mainItemPath.has_value() )
  119. {
  120. if( props[7].IsEmpty() )
  121. {
  122. ercItem->SetItemsSheetPaths( mainItemPath.value() );
  123. }
  124. else
  125. {
  126. KIID_PATH auxItemKiidPath( props[7] );
  127. std::optional<SCH_SHEET_PATH> auxItemPath =
  128. sheetPaths.GetSheetPathByKIIDPath( auxItemKiidPath, true );
  129. if( auxItemPath.has_value() )
  130. ercItem->SetItemsSheetPaths( mainItemPath.value(), auxItemPath.value() );
  131. }
  132. }
  133. }
  134. }
  135. SCH_MARKER* marker = new SCH_MARKER( ercItem, markerPos );
  136. marker->SetIsLegacyMarker( isLegacyMarker );
  137. return marker;
  138. }
  139. #if defined(DEBUG)
  140. void SCH_MARKER::Show( int nestLevel, std::ostream& os ) const
  141. {
  142. // for now, make it look like XML:
  143. NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << GetPos() << "/>\n";
  144. }
  145. #endif
  146. void SCH_MARKER::ViewGetLayers( int aLayers[], int& aCount ) const
  147. {
  148. wxCHECK_RET( Schematic(), "No SCHEMATIC set for SCH_MARKER!" );
  149. // Don't display sheet-specific markers when SCH_SHEET_PATHs do not match
  150. std::shared_ptr<ERC_ITEM> ercItem = std::static_pointer_cast<ERC_ITEM>( GetRCItem() );
  151. if( ercItem->IsSheetSpecific()
  152. && ( ercItem->GetSpecificSheetPath() != Schematic()->CurrentSheet() ) )
  153. {
  154. aCount = 0;
  155. return;
  156. }
  157. aCount = 2;
  158. if( IsExcluded() )
  159. {
  160. aLayers[0] = LAYER_ERC_EXCLUSION;
  161. }
  162. else
  163. {
  164. switch( Schematic()->ErcSettings().GetSeverity( m_rcItem->GetErrorCode() ) )
  165. {
  166. default:
  167. case SEVERITY::RPT_SEVERITY_ERROR: aLayers[0] = LAYER_ERC_ERR; break;
  168. case SEVERITY::RPT_SEVERITY_WARNING: aLayers[0] = LAYER_ERC_WARN; break;
  169. }
  170. }
  171. aLayers[1] = LAYER_SELECTION_SHADOWS;
  172. }
  173. SCH_LAYER_ID SCH_MARKER::GetColorLayer() const
  174. {
  175. if( IsExcluded() )
  176. return LAYER_ERC_EXCLUSION;
  177. wxCHECK_MSG( Schematic(), LAYER_ERC_ERR, "No SCHEMATIC set for SCH_MARKER!" );
  178. switch( Schematic()->ErcSettings().GetSeverity( m_rcItem->GetErrorCode() ) )
  179. {
  180. default:
  181. case SEVERITY::RPT_SEVERITY_ERROR: return LAYER_ERC_ERR;
  182. case SEVERITY::RPT_SEVERITY_WARNING: return LAYER_ERC_WARN;
  183. }
  184. }
  185. KIGFX::COLOR4D SCH_MARKER::getColor() const
  186. {
  187. COLOR_SETTINGS* colors = Pgm().GetSettingsManager().GetColorSettings();
  188. return colors->GetColor( GetColorLayer() );
  189. }
  190. SEVERITY SCH_MARKER::GetSeverity() const
  191. {
  192. if( IsExcluded() )
  193. return RPT_SEVERITY_EXCLUSION;
  194. ERC_ITEM* item = static_cast<ERC_ITEM*>( m_rcItem.get() );
  195. return Schematic()->ErcSettings().GetSeverity( item->GetErrorCode() );
  196. }
  197. void SCH_MARKER::Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset )
  198. {
  199. PrintMarker( aSettings, aOffset );
  200. }
  201. bool SCH_MARKER::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
  202. {
  203. return SCH_ITEM::Matches( m_rcItem->GetErrorMessage(), aSearchData );
  204. }
  205. const BOX2I SCH_MARKER::GetBoundingBox() const
  206. {
  207. return GetBoundingBoxMarker();
  208. }
  209. void SCH_MARKER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
  210. {
  211. aList.emplace_back( _( "Type" ), _( "Marker" ) );
  212. aList.emplace_back( _( "Violation" ), m_rcItem->GetErrorMessage() );
  213. switch( GetSeverity() )
  214. {
  215. case RPT_SEVERITY_IGNORE:
  216. aList.emplace_back( _( "Severity" ), _( "Ignore" ) );
  217. break;
  218. case RPT_SEVERITY_WARNING:
  219. aList.emplace_back( _( "Severity" ), _( "Warning" ) );
  220. break;
  221. case RPT_SEVERITY_ERROR:
  222. aList.emplace_back( _( "Severity" ), _( "Error" ) );
  223. break;
  224. default:
  225. break;
  226. }
  227. if( GetMarkerType() == MARKER_DRAWING_SHEET )
  228. {
  229. aList.emplace_back( _( "Drawing Sheet" ), wxEmptyString );
  230. }
  231. else
  232. {
  233. wxString mainText;
  234. wxString auxText;
  235. EDA_ITEM* mainItem = nullptr;
  236. EDA_ITEM* auxItem = nullptr;
  237. if( m_rcItem->GetMainItemID() != niluuid )
  238. mainItem = aFrame->GetItem( m_rcItem->GetMainItemID() );
  239. if( m_rcItem->GetAuxItemID() != niluuid )
  240. auxItem = aFrame->GetItem( m_rcItem->GetAuxItemID() );
  241. if( mainItem )
  242. mainText = mainItem->GetItemDescription( aFrame );
  243. if( auxItem )
  244. auxText = auxItem->GetItemDescription( aFrame );
  245. aList.emplace_back( mainText, auxText );
  246. }
  247. if( IsExcluded() )
  248. aList.emplace_back( _( "Excluded" ), m_comment );
  249. }
  250. BITMAPS SCH_MARKER::GetMenuImage() const
  251. {
  252. return BITMAPS::erc;
  253. }
  254. void SCH_MARKER::Rotate( const VECTOR2I& aCenter )
  255. {
  256. // Marker geometry isn't user-editable
  257. }
  258. void SCH_MARKER::MirrorVertically( int aCenter )
  259. {
  260. // Marker geometry isn't user-editable
  261. }
  262. void SCH_MARKER::MirrorHorizontally( int aCenter )
  263. {
  264. // Marker geometry isn't user-editable
  265. }
  266. bool SCH_MARKER::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
  267. {
  268. return HitTestMarker( aPosition, aAccuracy );
  269. }