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.

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