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.

389 lines
18 KiB

14 years ago
14 years ago
14 years ago
14 years ago
8 years ago
14 years ago
14 years ago
8 years ago
  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 The 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 <zone_settings.h>
  26. #include <pcb_base_frame.h>
  27. #include <board.h>
  28. #include <lset.h>
  29. #include <settings/color_settings.h>
  30. #include <zones.h>
  31. #include <zone.h>
  32. #include <wx/dataview.h>
  33. #include <widgets/color_swatch.h>
  34. bool ZONE_LAYER_PROPERTIES::operator==( const ZONE_LAYER_PROPERTIES& aOther ) const
  35. {
  36. return hatching_offset == aOther.hatching_offset;
  37. }
  38. ZONE_SETTINGS::ZONE_SETTINGS()
  39. {
  40. m_ZonePriority = 0;
  41. m_FillMode = ZONE_FILL_MODE::POLYGONS; // Mode for filling zone
  42. // Zone clearance value
  43. m_ZoneClearance = pcbIUScale.mmToIU( ZONE_CLEARANCE_MM );
  44. // Min thickness value in filled areas (this is the minimum width of copper to fill solid areas) :
  45. m_ZoneMinThickness = pcbIUScale.mmToIU( ZONE_THICKNESS_MM );
  46. // Arbitrary defaults for the hatch settings
  47. m_HatchThickness = std::max( m_ZoneMinThickness * 4, pcbIUScale.mmToIU( 1.0 ) );
  48. m_HatchGap = std::max( m_ZoneMinThickness * 6, pcbIUScale.mmToIU( 1.5 ) );
  49. m_HatchOrientation = ANGLE_0; // Grid style: orientation of grid lines
  50. m_HatchSmoothingLevel = 0; // Grid pattern smoothing type. 0 = no smoothing
  51. m_HatchSmoothingValue = 0.1; // Grid pattern chamfer value relative to the gap value
  52. m_HatchHoleMinArea = 0.3; // Min size before holes are dropped (ratio of hole size)
  53. m_HatchBorderAlgorithm = 1; // 0 = use zone min thickness; 1 = use hatch width
  54. m_NetcodeSelection = 0; // Net code selection for the current zone
  55. m_ZoneBorderDisplayStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE; // Option to show the zone
  56. // outlines only, short
  57. // hatches or full hatches
  58. m_BorderHatchPitch = pcbIUScale.mmToIU( ZONE_BORDER_HATCH_DIST_MM );
  59. m_Layers.reset().set( F_Cu );
  60. m_Name = wxEmptyString;
  61. // thickness of the gap in thermal reliefs:
  62. m_ThermalReliefGap = pcbIUScale.mmToIU( ZONE_THERMAL_RELIEF_GAP_MM );
  63. // thickness of the copper bridge in thermal reliefs:
  64. m_ThermalReliefSpokeWidth = pcbIUScale.mmToIU( ZONE_THERMAL_RELIEF_COPPER_WIDTH_MM );
  65. m_padConnection = ZONE_CONNECTION::THERMAL; // How pads are covered by copper in zone
  66. m_Locked = false;
  67. m_cornerSmoothingType = SMOOTHING_NONE;
  68. m_cornerRadius = 0;
  69. m_removeIslands = ISLAND_REMOVAL_MODE::ALWAYS;
  70. m_minIslandArea = 10 * pcbIUScale.IU_PER_MM * pcbIUScale.IU_PER_MM;
  71. SetIsRuleArea( false );
  72. SetRuleAreaPlacementSourceType( RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME );
  73. SetDoNotAllowZoneFills( false );
  74. SetDoNotAllowVias( true );
  75. SetDoNotAllowTracks( true );
  76. SetDoNotAllowPads( true );
  77. SetDoNotAllowFootprints( false );
  78. m_TeardropType = TEARDROP_TYPE::TD_NONE;
  79. m_ruleAreaPlacementEnabled = false;
  80. }
  81. bool ZONE_SETTINGS::operator==( const ZONE_SETTINGS& aOther ) const
  82. {
  83. if( m_ZonePriority != aOther.m_ZonePriority ) return false;
  84. if( m_FillMode != aOther.m_FillMode ) return false;
  85. if( m_ZoneClearance != aOther.m_ZoneClearance ) return false;
  86. if( m_ZoneMinThickness != aOther.m_ZoneMinThickness ) return false;
  87. if( m_HatchThickness != aOther.m_HatchThickness ) return false;
  88. if( m_HatchGap != aOther.m_HatchGap ) return false;
  89. if( m_HatchOrientation != aOther.m_HatchOrientation ) return false;
  90. if( m_HatchSmoothingLevel != aOther.m_HatchSmoothingLevel ) return false;
  91. if( m_HatchSmoothingValue != aOther.m_HatchSmoothingValue ) return false;
  92. if( m_HatchBorderAlgorithm != aOther.m_HatchBorderAlgorithm ) return false;
  93. if( m_HatchHoleMinArea != aOther.m_HatchHoleMinArea ) return false;
  94. if( m_NetcodeSelection != aOther.m_NetcodeSelection ) return false;
  95. if( m_Name != aOther.m_Name ) return false;
  96. if( m_ZoneBorderDisplayStyle != aOther.m_ZoneBorderDisplayStyle ) return false;
  97. if( m_BorderHatchPitch != aOther.m_BorderHatchPitch ) return false;
  98. if( m_ThermalReliefGap != aOther.m_ThermalReliefGap ) return false;
  99. if( m_ThermalReliefSpokeWidth != aOther.m_ThermalReliefSpokeWidth ) return false;
  100. if( m_padConnection != aOther.m_padConnection ) return false;
  101. if( m_cornerSmoothingType != aOther.m_cornerSmoothingType ) return false;
  102. if( m_cornerRadius != aOther.m_cornerRadius ) return false;
  103. if( m_isRuleArea != aOther.m_isRuleArea ) return false;
  104. if( m_ruleAreaPlacementEnabled != aOther.m_ruleAreaPlacementEnabled ) return false;
  105. if( m_ruleAreaPlacementSourceType != aOther.m_ruleAreaPlacementSourceType ) return false;
  106. if( m_ruleAreaPlacementSource != aOther.m_ruleAreaPlacementSource ) return false;
  107. if( m_keepoutDoNotAllowZoneFills != aOther.m_keepoutDoNotAllowZoneFills ) return false;
  108. if( m_keepoutDoNotAllowVias != aOther.m_keepoutDoNotAllowVias ) return false;
  109. if( m_keepoutDoNotAllowTracks != aOther.m_keepoutDoNotAllowTracks ) return false;
  110. if( m_keepoutDoNotAllowPads != aOther.m_keepoutDoNotAllowPads ) return false;
  111. if( m_keepoutDoNotAllowFootprints != aOther.m_keepoutDoNotAllowFootprints ) return false;
  112. if( m_Locked != aOther.m_Locked ) return false;
  113. if( m_removeIslands != aOther.m_removeIslands ) return false;
  114. if( m_minIslandArea != aOther.m_minIslandArea ) return false;
  115. if( !std::equal( std::begin( m_layerProperties ), std::end( m_layerProperties ),
  116. std::begin( aOther.m_layerProperties ) ) )
  117. return false;
  118. // Currently, the teardrop area type is not really a ZONE_SETTINGS parameter,
  119. // but a ZONE parameter only.
  120. // However it can be used in dialogs
  121. if( m_TeardropType != aOther.m_TeardropType ) return false;
  122. if( m_Layers != aOther.m_Layers ) return false;
  123. return true;
  124. }
  125. ZONE_SETTINGS& ZONE_SETTINGS::operator << ( const ZONE& aSource )
  126. {
  127. m_ZonePriority = aSource.GetAssignedPriority();
  128. m_FillMode = aSource.GetFillMode();
  129. m_ZoneClearance = aSource.GetLocalClearance().value();
  130. m_ZoneMinThickness = aSource.GetMinThickness();
  131. m_HatchThickness = aSource.GetHatchThickness();
  132. m_HatchGap = aSource.GetHatchGap();
  133. m_HatchOrientation = aSource.GetHatchOrientation();
  134. m_HatchSmoothingLevel = aSource.GetHatchSmoothingLevel();
  135. m_HatchSmoothingValue = aSource.GetHatchSmoothingValue();
  136. m_HatchBorderAlgorithm = aSource.GetHatchBorderAlgorithm();
  137. m_HatchHoleMinArea = aSource.GetHatchHoleMinArea();
  138. m_NetcodeSelection = aSource.GetNetCode();
  139. m_Name = aSource.GetZoneName();
  140. m_ZoneBorderDisplayStyle = aSource.GetHatchStyle();
  141. m_BorderHatchPitch = aSource.GetBorderHatchPitch();
  142. m_ThermalReliefGap = aSource.GetThermalReliefGap();
  143. m_ThermalReliefSpokeWidth = aSource.GetThermalReliefSpokeWidth();
  144. m_padConnection = aSource.GetPadConnection();
  145. m_cornerSmoothingType = aSource.GetCornerSmoothingType();
  146. m_cornerRadius = aSource.GetCornerRadius();
  147. m_isRuleArea = aSource.GetIsRuleArea();
  148. m_ruleAreaPlacementEnabled = aSource.GetRuleAreaPlacementEnabled();
  149. m_ruleAreaPlacementSourceType = aSource.GetRuleAreaPlacementSourceType();
  150. m_ruleAreaPlacementSource = aSource.GetRuleAreaPlacementSource();
  151. m_keepoutDoNotAllowZoneFills = aSource.GetDoNotAllowZoneFills();
  152. m_keepoutDoNotAllowVias = aSource.GetDoNotAllowVias();
  153. m_keepoutDoNotAllowTracks = aSource.GetDoNotAllowTracks();
  154. m_keepoutDoNotAllowPads = aSource.GetDoNotAllowPads();
  155. m_keepoutDoNotAllowFootprints = aSource.GetDoNotAllowFootprints();
  156. m_Locked = aSource.IsLocked();
  157. m_removeIslands = aSource.GetIslandRemovalMode();
  158. m_minIslandArea = aSource.GetMinIslandArea();
  159. m_layerProperties.clear();
  160. std::ranges::copy( aSource.LayerProperties(),
  161. std::inserter( m_layerProperties, std::end( m_layerProperties ) ) );
  162. // Currently, the teardrop area type is not really a ZONE_SETTINGS parameter,
  163. // but a ZONE parameter only.
  164. // However it can be used in dialogs
  165. m_TeardropType = aSource.GetTeardropAreaType();
  166. m_Layers = aSource.GetLayerSet();
  167. return *this;
  168. }
  169. void ZONE_SETTINGS::ExportSetting( ZONE& aTarget, bool aFullExport ) const
  170. {
  171. aTarget.SetFillMode( m_FillMode );
  172. aTarget.SetLocalClearance( m_ZoneClearance );
  173. aTarget.SetMinThickness( m_ZoneMinThickness );
  174. aTarget.SetHatchThickness( m_HatchThickness );
  175. aTarget.SetHatchGap( m_HatchGap );
  176. aTarget.SetHatchOrientation( m_HatchOrientation );
  177. aTarget.SetHatchSmoothingLevel( m_HatchSmoothingLevel );
  178. aTarget.SetHatchSmoothingValue( m_HatchSmoothingValue );
  179. aTarget.SetHatchBorderAlgorithm( m_HatchBorderAlgorithm );
  180. aTarget.SetHatchHoleMinArea( m_HatchHoleMinArea );
  181. aTarget.SetThermalReliefGap( m_ThermalReliefGap );
  182. aTarget.SetThermalReliefSpokeWidth( m_ThermalReliefSpokeWidth );
  183. aTarget.SetPadConnection( m_padConnection );
  184. aTarget.SetCornerSmoothingType( m_cornerSmoothingType );
  185. aTarget.SetCornerRadius( m_cornerRadius );
  186. aTarget.SetIsRuleArea( GetIsRuleArea() );
  187. aTarget.SetRuleAreaPlacementEnabled( GetRuleAreaPlacementEnabled() );
  188. aTarget.SetRuleAreaPlacementSourceType( GetRuleAreaPlacementSourceType() );
  189. aTarget.SetRuleAreaPlacementSource( GetRuleAreaPlacementSource() );
  190. aTarget.SetDoNotAllowZoneFills( GetDoNotAllowZoneFills() );
  191. aTarget.SetDoNotAllowVias( GetDoNotAllowVias() );
  192. aTarget.SetDoNotAllowTracks( GetDoNotAllowTracks() );
  193. aTarget.SetDoNotAllowPads( GetDoNotAllowPads() );
  194. aTarget.SetDoNotAllowFootprints( GetDoNotAllowFootprints() );
  195. aTarget.SetLocked( m_Locked );
  196. aTarget.SetIslandRemovalMode( GetIslandRemovalMode() );
  197. aTarget.SetMinIslandArea( GetMinIslandArea() );
  198. // Currently, the teardrop area type is not imported from a ZONE_SETTINGS, because
  199. // it is not really a ZONE_SETTINGS parameter, but a ZONE parameter only
  200. #if 0
  201. aTarget.SetTeardropAreaType( m_TeardropType );
  202. #endif
  203. if( aFullExport )
  204. {
  205. aTarget.SetAssignedPriority( m_ZonePriority );
  206. aTarget.SetLayerProperties( m_layerProperties );
  207. aTarget.SetLayerSet( m_Layers );
  208. aTarget.SetZoneName( m_Name );
  209. if( !m_isRuleArea )
  210. aTarget.SetNetCode( m_NetcodeSelection );
  211. }
  212. // call SetBorderDisplayStyle last, because hatch lines will be rebuilt,
  213. // using new parameters values
  214. aTarget.SetBorderDisplayStyle( m_ZoneBorderDisplayStyle,
  215. m_BorderHatchPitch, true );
  216. }
  217. void ZONE_SETTINGS::CopyFrom( const ZONE_SETTINGS& aOther, bool aCopyFull )
  218. {
  219. // clang-format off
  220. m_ZonePriority = aOther.m_ZonePriority;
  221. m_FillMode = aOther.m_FillMode;
  222. m_ZoneClearance = aOther.m_ZoneClearance;
  223. m_ZoneMinThickness = aOther.m_ZoneMinThickness;
  224. m_HatchThickness = aOther.m_HatchThickness;
  225. m_HatchGap = aOther.m_HatchGap;
  226. m_HatchOrientation = aOther.m_HatchOrientation;
  227. m_HatchSmoothingLevel = aOther.m_HatchSmoothingLevel;
  228. m_HatchSmoothingValue = aOther.m_HatchSmoothingValue;
  229. m_HatchBorderAlgorithm = aOther.m_HatchBorderAlgorithm;
  230. m_HatchHoleMinArea = aOther.m_HatchHoleMinArea;
  231. m_NetcodeSelection = aOther.m_NetcodeSelection;
  232. m_Name = aOther.m_Name;
  233. m_ZoneBorderDisplayStyle = aOther.m_ZoneBorderDisplayStyle;
  234. m_BorderHatchPitch = aOther.m_BorderHatchPitch;
  235. m_ThermalReliefGap = aOther.m_ThermalReliefGap;
  236. m_ThermalReliefSpokeWidth = aOther.m_ThermalReliefSpokeWidth;
  237. m_padConnection = aOther.m_padConnection;
  238. m_cornerSmoothingType = aOther.m_cornerSmoothingType;
  239. m_cornerRadius = aOther.m_cornerRadius;
  240. m_isRuleArea = aOther.m_isRuleArea;
  241. m_ruleAreaPlacementEnabled = aOther.m_ruleAreaPlacementEnabled;
  242. m_ruleAreaPlacementSourceType = aOther.m_ruleAreaPlacementSourceType;
  243. m_ruleAreaPlacementSource = aOther.m_ruleAreaPlacementSource;
  244. m_keepoutDoNotAllowZoneFills = aOther.m_keepoutDoNotAllowZoneFills;
  245. m_keepoutDoNotAllowVias = aOther.m_keepoutDoNotAllowVias;
  246. m_keepoutDoNotAllowTracks = aOther.m_keepoutDoNotAllowTracks;
  247. m_keepoutDoNotAllowPads = aOther.m_keepoutDoNotAllowPads;
  248. m_keepoutDoNotAllowFootprints = aOther.m_keepoutDoNotAllowFootprints;
  249. m_Locked = aOther.m_Locked;
  250. m_removeIslands = aOther.m_removeIslands;
  251. m_minIslandArea = aOther.m_minIslandArea;
  252. // clang-format on
  253. if( aCopyFull )
  254. {
  255. m_layerProperties.clear();
  256. std::ranges::copy( aOther.m_layerProperties,
  257. std::inserter( m_layerProperties, std::end( m_layerProperties ) ) );
  258. m_TeardropType = aOther.m_TeardropType;
  259. m_Layers = aOther.m_Layers;
  260. }
  261. }
  262. void ZONE_SETTINGS::SetCornerRadius( int aRadius )
  263. {
  264. if( aRadius < 0 )
  265. m_cornerRadius = 0;
  266. else
  267. m_cornerRadius = aRadius;
  268. }
  269. #ifdef __WXOSX_MAC__
  270. const static wxSize LAYER_BITMAP_SIZE( 28, 28 ); // wxCocoa impl unhappy if this isn't square...
  271. #else
  272. const static wxSize LAYER_BITMAP_SIZE( 24, 16 );
  273. #endif
  274. const static wxSize CHECKERBOARD_SIZE( 8, 8 );
  275. const ZONE_SETTINGS& ZONE_SETTINGS::GetDefaultSettings()
  276. {
  277. static ZONE_SETTINGS defaultSettings;
  278. return defaultSettings;
  279. }
  280. // A helper for setting up a dialog list for specifying zone layers. Used by all three
  281. // zone settings dialogs.
  282. void ZONE_SETTINGS::SetupLayersList( wxDataViewListCtrl* aList, PCB_BASE_FRAME* aFrame,
  283. LSET aLayers, bool aFpEditorMode )
  284. {
  285. BOARD* board = aFrame->GetBoard();
  286. COLOR4D backgroundColor = aFrame->GetColorSettings()->GetColor( LAYER_PCB_BACKGROUND );
  287. // In the Footprint Editor In1_Cu is used as a proxy for "all inner layers"
  288. if( aFpEditorMode )
  289. aLayers.set( In1_Cu );
  290. wxDataViewColumn* checkColumn = aList->AppendToggleColumn(
  291. wxEmptyString, wxDATAVIEW_CELL_ACTIVATABLE, wxCOL_WIDTH_DEFAULT, wxALIGN_CENTER );
  292. wxDataViewColumn* layerColumn = aList->AppendIconTextColumn( wxEmptyString );
  293. wxDataViewColumn* layerIDColumn = aList->AppendTextColumn( wxEmptyString );
  294. layerIDColumn->SetHidden( true );
  295. int textWidth = 0;
  296. for( PCB_LAYER_ID layerID : aLayers.UIOrder() )
  297. {
  298. wxString layerName = board->GetLayerName( layerID );
  299. if( aFpEditorMode && layerID == In1_Cu )
  300. layerName = _( "Inner layers" );
  301. // wxCOL_WIDTH_AUTOSIZE doesn't work on all platforms, so we calculate width here
  302. textWidth = std::max( textWidth, KIUI::GetTextSize( layerName, aList ).x );
  303. COLOR4D layerColor = aFrame->GetColorSettings()->GetColor( layerID );
  304. auto bitmap = COLOR_SWATCH::MakeBitmap( layerColor, backgroundColor, LAYER_BITMAP_SIZE,
  305. CHECKERBOARD_SIZE, aList->GetBackgroundColour() );
  306. wxIcon icon;
  307. icon.CopyFromBitmap( bitmap );
  308. wxVector<wxVariant> row;
  309. row.push_back( wxVariant( m_Layers.test( layerID ) ) );
  310. row.push_back( wxVariant( wxDataViewIconText( layerName, icon ) ) );
  311. row.push_back( wxVariant( wxString::Format( wxT( "%i" ), layerID ) ) );
  312. aList->AppendItem( row );
  313. if( m_Layers.test( layerID ) )
  314. aList->SetToggleValue( true, (unsigned) aList->GetItemCount() - 1, 0 );
  315. }
  316. int checkColSize = aList->FromDIP( 22 );
  317. int layerColSize = textWidth + LAYER_BITMAP_SIZE.x + aList->FromDIP( 15 );
  318. // You'd think the fact that m_layers is a list would encourage wxWidgets not to save room
  319. // for the tree expanders... but you'd be wrong. Force indent to 0.
  320. aList->SetIndent( 0 );
  321. aList->SetMinClientSize( wxSize( checkColSize + layerColSize,
  322. aList->GetMinClientSize().y ) );
  323. checkColumn->SetWidth( checkColSize );
  324. layerColumn->SetWidth( layerColSize );
  325. }