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.

326 lines
9.1 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
  5. * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
  6. * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
  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
  19. * along with this program; if not, you may find one here:
  20. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  21. * or you may search the http://www.gnu.org website for the version 2 license,
  22. * or you may write to the Free Software Foundation, Inc.,
  23. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  24. */
  25. #include <bitmaps.h>
  26. #include <base_units.h>
  27. #include <eda_draw_frame.h>
  28. #include <board.h>
  29. #include <board_design_settings.h>
  30. #include <pcb_marker.h>
  31. #include <layer_ids.h>
  32. #include <settings/color_settings.h>
  33. #include <settings/settings_manager.h>
  34. #include <geometry/shape_null.h>
  35. #include <widgets/ui_common.h>
  36. #include <pgm_base.h>
  37. #include <drc/drc_item.h>
  38. #include <trigo.h>
  39. /// Factor to convert the maker unit shape to internal units:
  40. #define SCALING_FACTOR pcbIUScale.mmToIU( 0.1625 )
  41. PCB_MARKER::PCB_MARKER( std::shared_ptr<RC_ITEM> aItem, const VECTOR2I& aPosition, int aLayer ) :
  42. BOARD_ITEM( nullptr, PCB_MARKER_T, F_Cu ), // parent set during BOARD::Add()
  43. MARKER_BASE( SCALING_FACTOR, aItem )
  44. {
  45. if( m_rcItem )
  46. {
  47. m_rcItem->SetParent( this );
  48. if( aLayer == LAYER_DRAWINGSHEET )
  49. {
  50. SetMarkerType( MARKER_BASE::MARKER_DRAWING_SHEET );
  51. }
  52. else
  53. {
  54. switch( m_rcItem->GetErrorCode() )
  55. {
  56. case DRCE_UNCONNECTED_ITEMS:
  57. SetMarkerType( MARKER_BASE::MARKER_RATSNEST );
  58. break;
  59. case DRCE_MISSING_FOOTPRINT:
  60. case DRCE_DUPLICATE_FOOTPRINT:
  61. case DRCE_EXTRA_FOOTPRINT:
  62. case DRCE_NET_CONFLICT:
  63. SetMarkerType( MARKER_BASE::MARKER_PARITY );
  64. break;
  65. default:
  66. SetMarkerType( MARKER_BASE::MARKER_DRC );
  67. break;
  68. }
  69. SetLayer( ToLAYER_ID( aLayer ) );
  70. }
  71. }
  72. m_Pos = aPosition;
  73. }
  74. /* destructor */
  75. PCB_MARKER::~PCB_MARKER()
  76. {
  77. if( m_rcItem )
  78. m_rcItem->SetParent( nullptr );
  79. }
  80. wxString PCB_MARKER::Serialize() const
  81. {
  82. wxString lastItem;
  83. if( m_rcItem->GetErrorCode() == DRCE_COPPER_SLIVER )
  84. {
  85. return wxString::Format( wxT( "%s|%d|%d|%s|%s" ),
  86. m_rcItem->GetSettingsKey(),
  87. m_Pos.x,
  88. m_Pos.y,
  89. m_rcItem->GetMainItemID().AsString(),
  90. LayerName( m_layer ) );
  91. }
  92. else if( m_rcItem->GetErrorCode() == DRCE_UNRESOLVED_VARIABLE
  93. && m_rcItem->GetParent()->GetMarkerType() == MARKER_DRAWING_SHEET )
  94. {
  95. return wxString::Format( wxT( "%s|%d|%d|%s|%s" ),
  96. m_rcItem->GetSettingsKey(),
  97. m_Pos.x,
  98. m_Pos.y,
  99. // Drawing sheet KIIDs aren't preserved between runs
  100. wxEmptyString,
  101. wxEmptyString );
  102. }
  103. else
  104. {
  105. return wxString::Format( wxT( "%s|%d|%d|%s|%s" ),
  106. m_rcItem->GetSettingsKey(),
  107. m_Pos.x,
  108. m_Pos.y,
  109. m_rcItem->GetMainItemID().AsString(),
  110. m_rcItem->GetAuxItemID().AsString() );
  111. }
  112. }
  113. PCB_MARKER* PCB_MARKER::Deserialize( const wxString& data )
  114. {
  115. wxArrayString props = wxSplit( data, '|' );
  116. int markerLayer = F_Cu;
  117. VECTOR2I markerPos( (int) strtol( props[1].c_str(), nullptr, 10 ),
  118. (int) strtol( props[2].c_str(), nullptr, 10 ) );
  119. std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( props[0] );
  120. if( !drcItem )
  121. return nullptr;
  122. if( drcItem->GetErrorCode() == DRCE_COPPER_SLIVER )
  123. {
  124. drcItem->SetItems( KIID( props[3] ) );
  125. for( int layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
  126. {
  127. if( LayerName( ToLAYER_ID( layer ) ) == props[4] )
  128. {
  129. markerLayer = layer;
  130. break;
  131. }
  132. }
  133. }
  134. else if( drcItem->GetErrorCode() == DRCE_UNRESOLVED_VARIABLE
  135. && props[3].IsEmpty() && props[4].IsEmpty() )
  136. {
  137. // Note: caller must load our item pointer with the drawing sheet proxy item
  138. markerLayer = LAYER_DRAWINGSHEET;
  139. }
  140. else
  141. {
  142. drcItem->SetItems( KIID( props[3] ), KIID( props[4] ) );
  143. }
  144. return new PCB_MARKER( drcItem, markerPos, markerLayer );
  145. }
  146. void PCB_MARKER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
  147. {
  148. aList.emplace_back( _( "Type" ), _( "Marker" ) );
  149. aList.emplace_back( _( "Violation" ), m_rcItem->GetErrorMessage() );
  150. switch( GetSeverity() )
  151. {
  152. case RPT_SEVERITY_IGNORE:
  153. aList.emplace_back( _( "Severity" ), _( "Ignore" ) );
  154. break;
  155. case RPT_SEVERITY_WARNING:
  156. aList.emplace_back( _( "Severity" ), _( "Warning" ) );
  157. break;
  158. case RPT_SEVERITY_ERROR:
  159. aList.emplace_back( _( "Severity" ), _( "Error" ) );
  160. break;
  161. default:
  162. break;
  163. }
  164. if( GetMarkerType() == MARKER_DRAWING_SHEET )
  165. {
  166. aList.emplace_back( _( "Drawing Sheet" ), wxEmptyString );
  167. }
  168. else
  169. {
  170. wxString mainText;
  171. wxString auxText;
  172. EDA_ITEM* mainItem = nullptr;
  173. EDA_ITEM* auxItem = nullptr;
  174. if( m_rcItem->GetMainItemID() != niluuid )
  175. mainItem = aFrame->GetItem( m_rcItem->GetMainItemID() );
  176. if( m_rcItem->GetAuxItemID() != niluuid )
  177. auxItem = aFrame->GetItem( m_rcItem->GetAuxItemID() );
  178. if( mainItem )
  179. mainText = mainItem->GetSelectMenuText( aFrame );
  180. if( auxItem )
  181. auxText = auxItem->GetSelectMenuText( aFrame );
  182. aList.emplace_back( mainText, auxText );
  183. }
  184. }
  185. void PCB_MARKER::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
  186. {
  187. // Marker geometry isn't user-editable
  188. }
  189. void PCB_MARKER::Flip( const VECTOR2I& aCentre, bool aFlipLeftRight )
  190. {
  191. // Marker geometry isn't user-editable
  192. }
  193. std::shared_ptr<SHAPE> PCB_MARKER::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
  194. {
  195. // Markers do not participate in the board geometry space, and therefore have no
  196. // effectiven shape.
  197. return std::make_shared<SHAPE_NULL>();
  198. }
  199. wxString PCB_MARKER::GetSelectMenuText( UNITS_PROVIDER* aUnitsProvider ) const
  200. {
  201. // m_rcItem->GetErrorMessage() could be used instead, but is probably too long
  202. // for menu duty.
  203. return wxString::Format( _( "Marker (%s)" ), m_rcItem->GetErrorText() );
  204. }
  205. BITMAPS PCB_MARKER::GetMenuImage() const
  206. {
  207. return BITMAPS::drc;
  208. }
  209. SEVERITY PCB_MARKER::GetSeverity() const
  210. {
  211. if( IsExcluded() )
  212. return RPT_SEVERITY_EXCLUSION;
  213. DRC_ITEM* item = static_cast<DRC_ITEM*>( m_rcItem.get() );
  214. DRC_RULE* rule = item->GetViolatingRule();
  215. if( rule && rule->m_Severity != RPT_SEVERITY_UNDEFINED )
  216. return rule->m_Severity;
  217. return GetBoard()->GetDesignSettings().GetSeverity( item->GetErrorCode() );
  218. }
  219. void PCB_MARKER::ViewGetLayers( int aLayers[], int& aCount ) const
  220. {
  221. if( GetMarkerType() == MARKER_RATSNEST )
  222. {
  223. aCount = 0;
  224. return;
  225. }
  226. aCount = 2;
  227. aLayers[1] = LAYER_MARKER_SHADOWS;
  228. switch( GetSeverity() )
  229. {
  230. default:
  231. case SEVERITY::RPT_SEVERITY_ERROR: aLayers[0] = LAYER_DRC_ERROR; break;
  232. case SEVERITY::RPT_SEVERITY_WARNING: aLayers[0] = LAYER_DRC_WARNING; break;
  233. case SEVERITY::RPT_SEVERITY_EXCLUSION: aLayers[0] = LAYER_DRC_EXCLUSION; break;
  234. }
  235. }
  236. GAL_LAYER_ID PCB_MARKER::GetColorLayer() const
  237. {
  238. switch( GetSeverity() )
  239. {
  240. default:
  241. case SEVERITY::RPT_SEVERITY_ERROR: return LAYER_DRC_ERROR;
  242. case SEVERITY::RPT_SEVERITY_WARNING: return LAYER_DRC_WARNING;
  243. case SEVERITY::RPT_SEVERITY_EXCLUSION: return LAYER_DRC_EXCLUSION;
  244. }
  245. }
  246. KIGFX::COLOR4D PCB_MARKER::getColor() const
  247. {
  248. COLOR_SETTINGS* colors = Pgm().GetSettingsManager().GetColorSettings();
  249. return colors->GetColor( GetColorLayer() );
  250. }
  251. void PCB_MARKER::SetZoom( double aZoomFactor )
  252. {
  253. SetMarkerScale( SCALING_FACTOR * aZoomFactor );
  254. }
  255. const BOX2I PCB_MARKER::GetBoundingBox() const
  256. {
  257. return GetBoundingBoxMarker();
  258. }
  259. const BOX2I PCB_MARKER::ViewBBox() const
  260. {
  261. return GetBoundingBox();
  262. }