1 /**
2  * @brief class ZONE_SETTINGS used to handle zones parameters
3  */
4 
5 /*
6  * This program source code file is part of KiCad, a free EDA CAD application.
7  *
8  * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
9  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
10  * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, you may find one here:
24  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
25  * or you may search the http://www.gnu.org website for the version 2 license,
26  * or you may write to the Free Software Foundation, Inc.,
27  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
28  */
29 
30 #include <zone_settings.h>
31 
32 #include <convert_to_biu.h>
33 #include <pcbnew.h>
34 #include <pcb_base_frame.h>
35 #include <board.h>
36 #include <settings/color_settings.h>
37 #include <zones.h>
38 
39 #include <zone.h>
40 #include <wx/dataview.h>
41 #include <widgets/color_swatch.h>
42 
ZONE_SETTINGS()43 ZONE_SETTINGS::ZONE_SETTINGS()
44 {
45     m_ZonePriority = 0;
46     m_FillMode = ZONE_FILL_MODE::POLYGONS; // Mode for filling zone
47     // Zone clearance value
48     m_ZoneClearance = Mils2iu( ZONE_CLEARANCE_MIL );
49     // Min thickness value in filled areas (this is the minimum width of copper to fill solid areas) :
50     m_ZoneMinThickness = Mils2iu( ZONE_THICKNESS_MIL );
51     m_HatchThickness = 0;        // good value of grid line thickness if m_FillMode = ZFM_GRID_PATTERN
52     m_HatchGap = 0;              // good value  of grid line gap if m_FillMode = ZFM_GRID_PATTERN
53     m_HatchOrientation = 0.0;    // Grid style: orientation of grid lines in degrees
54     m_HatchSmoothingLevel = 0;   // Grid pattern smoothing type. 0 = no smoothing
55     m_HatchSmoothingValue = 0.1; // Grid pattern chamfer value relative to the gap value
56     m_HatchHoleMinArea = 0.3;    // Min size before holes are dropped (ratio of hole size)
57     m_HatchBorderAlgorithm = 1;  // 0 = use zone min thickness; 1 = use hatch width
58     m_NetcodeSelection = 0;      // Net code selection for the current zone
59     m_ZoneBorderDisplayStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE; // Option to show the zone
60                                                                          // outlines only, short
61                                                                          // hatches or full hatches
62 
63     m_Layers.reset().set( F_Cu );
64     m_Name = wxEmptyString;
65 
66     // thickness of the gap in thermal reliefs:
67     m_ThermalReliefGap = Mils2iu( ZONE_THERMAL_RELIEF_GAP_MIL );
68     // thickness of the copper bridge in thermal reliefs:
69     m_ThermalReliefSpokeWidth = Mils2iu( ZONE_THERMAL_RELIEF_COPPER_WIDTH_MIL );
70 
71     m_padConnection = ZONE_CONNECTION::THERMAL; // How pads are covered by copper in zone
72 
73     m_Zone_45_Only = false;
74     m_Locked = false;
75 
76     m_cornerSmoothingType = SMOOTHING_NONE;
77     m_cornerRadius = 0;
78 
79     m_removeIslands = ISLAND_REMOVAL_MODE::ALWAYS;
80     m_minIslandArea = 0;
81 
82     SetIsRuleArea( false );
83     SetDoNotAllowCopperPour( false );
84     SetDoNotAllowVias( true );
85     SetDoNotAllowTracks( true );
86     SetDoNotAllowPads( true );
87     SetDoNotAllowFootprints( false );
88 }
89 
90 
operator <<(const ZONE & aSource)91 ZONE_SETTINGS& ZONE_SETTINGS::operator << ( const ZONE& aSource )
92 {
93     m_ZonePriority                = aSource.GetPriority();
94     m_FillMode                    = aSource.GetFillMode();
95     m_ZoneClearance               = aSource.GetLocalClearance();
96     m_ZoneMinThickness            = aSource.GetMinThickness();
97     m_HatchThickness              = aSource.GetHatchThickness();
98     m_HatchGap                    = aSource.GetHatchGap();
99     m_HatchOrientation            = aSource.GetHatchOrientation();
100     m_HatchSmoothingLevel         = aSource.GetHatchSmoothingLevel();
101     m_HatchSmoothingValue         = aSource.GetHatchSmoothingValue();
102     m_HatchBorderAlgorithm        = aSource.GetHatchBorderAlgorithm();
103     m_HatchHoleMinArea            = aSource.GetHatchHoleMinArea();
104     m_NetcodeSelection            = aSource.GetNetCode();
105     m_Name                        = aSource.GetZoneName();
106     m_ZoneBorderDisplayStyle      = aSource.GetHatchStyle();
107     m_ThermalReliefGap            = aSource.GetThermalReliefGap();
108     m_ThermalReliefSpokeWidth   = aSource.GetThermalReliefSpokeWidth();
109     m_padConnection               = aSource.GetPadConnection();
110     m_cornerSmoothingType         = aSource.GetCornerSmoothingType();
111     m_cornerRadius                = aSource.GetCornerRadius();
112     m_isRuleArea                  = aSource.GetIsRuleArea();
113     m_keepoutDoNotAllowCopperPour = aSource.GetDoNotAllowCopperPour();
114     m_keepoutDoNotAllowVias       = aSource.GetDoNotAllowVias();
115     m_keepoutDoNotAllowTracks     = aSource.GetDoNotAllowTracks();
116     m_keepoutDoNotAllowPads       = aSource.GetDoNotAllowPads();
117     m_keepoutDoNotAllowFootprints = aSource.GetDoNotAllowFootprints();
118     m_Zone_45_Only                = aSource.GetHV45();
119     m_Locked                      = aSource.IsLocked();
120     m_removeIslands               = aSource.GetIslandRemovalMode();
121     m_minIslandArea               = aSource.GetMinIslandArea();
122 
123     m_Layers = aSource.GetLayerSet();
124 
125     return *this;
126 }
127 
128 
ExportSetting(ZONE & aTarget,bool aFullExport) const129 void ZONE_SETTINGS::ExportSetting( ZONE& aTarget, bool aFullExport ) const
130 {
131     aTarget.SetFillMode( m_FillMode );
132     aTarget.SetLocalClearance( m_ZoneClearance );
133     aTarget.SetMinThickness( m_ZoneMinThickness );
134     aTarget.SetHatchThickness( m_HatchThickness );
135     aTarget.SetHatchGap( m_HatchGap );
136     aTarget.SetHatchOrientation( m_HatchOrientation );
137     aTarget.SetHatchSmoothingLevel( m_HatchSmoothingLevel );
138     aTarget.SetHatchSmoothingValue( m_HatchSmoothingValue );
139     aTarget.SetHatchBorderAlgorithm( m_HatchBorderAlgorithm );
140     aTarget.SetHatchHoleMinArea( m_HatchHoleMinArea );
141     aTarget.SetThermalReliefGap( m_ThermalReliefGap );
142     aTarget.SetThermalReliefSpokeWidth( m_ThermalReliefSpokeWidth );
143     aTarget.SetPadConnection( m_padConnection );
144     aTarget.SetCornerSmoothingType( m_cornerSmoothingType );
145     aTarget.SetCornerRadius( m_cornerRadius );
146     aTarget.SetIsRuleArea( GetIsRuleArea() );
147     aTarget.SetDoNotAllowCopperPour( GetDoNotAllowCopperPour() );
148     aTarget.SetDoNotAllowVias( GetDoNotAllowVias() );
149     aTarget.SetDoNotAllowTracks( GetDoNotAllowTracks() );
150     aTarget.SetDoNotAllowPads( GetDoNotAllowPads() );
151     aTarget.SetDoNotAllowFootprints( GetDoNotAllowFootprints() );
152     aTarget.SetHV45( m_Zone_45_Only );
153     aTarget.SetLocked( m_Locked );
154     aTarget.SetIslandRemovalMode( GetIslandRemovalMode() );
155     aTarget.SetMinIslandArea( GetMinIslandArea() );
156 
157     if( aFullExport )
158     {
159         aTarget.SetPriority( m_ZonePriority );
160         aTarget.SetLayerSet( m_Layers );
161         aTarget.SetZoneName( m_Name );
162 
163         if( !m_isRuleArea )
164             aTarget.SetNetCode( m_NetcodeSelection );
165     }
166 
167     // call SetBorderDisplayStyle last, because hatch lines will be rebuilt,
168     // using new parameters values
169     aTarget.SetBorderDisplayStyle( m_ZoneBorderDisplayStyle, aTarget.GetDefaultHatchPitch(),
170                                    true );
171 }
172 
173 
SetCornerRadius(int aRadius)174 void ZONE_SETTINGS::SetCornerRadius( int aRadius )
175 {
176     if( aRadius < 0 )
177         m_cornerRadius = 0;
178     else
179         m_cornerRadius = aRadius;
180 }
181 
182 
183 #ifdef __WXOSX_MAC__
184 const static wxSize LAYER_BITMAP_SIZE( 28, 28 );  // wxCocoa impl unhappy if this isn't square...
185 #else
186 const static wxSize LAYER_BITMAP_SIZE( 24, 16 );
187 #endif
188 
189 const static wxSize CHECKERBOARD_SIZE( 8, 8 );
190 
191 
192 // A helper for setting up a dialog list for specifying zone layers.  Used by all three
193 // zone settings dialogs.
SetupLayersList(wxDataViewListCtrl * aList,PCB_BASE_FRAME * aFrame,bool aShowCopper,bool aFpEditorMode)194 void ZONE_SETTINGS::SetupLayersList( wxDataViewListCtrl* aList, PCB_BASE_FRAME* aFrame,
195                                      bool aShowCopper, bool aFpEditorMode )
196 {
197     BOARD* board = aFrame->GetBoard();
198     COLOR4D backgroundColor = aFrame->GetColorSettings()->GetColor( LAYER_PCB_BACKGROUND );
199     LSET layers = aShowCopper ? LSET::AllCuMask( board->GetCopperLayerCount() )
200                               : LSET::AllNonCuMask();
201 
202     // In the Footprint Editor In1_Cu is used as a proxy for "all inner layers"
203     if( aFpEditorMode )
204         layers.set( In1_Cu );
205 
206     wxDataViewColumn* checkColumn = aList->AppendToggleColumn( wxEmptyString );
207     wxDataViewColumn* layerColumn = aList->AppendIconTextColumn( wxEmptyString );
208     wxDataViewColumn* layerIDColumn = aList->AppendTextColumn( wxEmptyString );
209     layerIDColumn->SetHidden( true );
210 
211     int textWidth = 0;
212 
213     for( LSEQ layer = layers.UIOrder(); layer; ++layer )
214     {
215         PCB_LAYER_ID layerID = *layer;
216         wxString layerName = board->GetLayerName( layerID );
217 
218         if( aFpEditorMode && layerID == In1_Cu )
219             layerName = _( "Inner layers" );
220 
221         // wxCOL_WIDTH_AUTOSIZE doesn't work on all platforms, so we calculate width here
222         textWidth = std::max( textWidth, KIUI::GetTextSize( layerName, aList ).x );
223 
224         COLOR4D layerColor = aFrame->GetColorSettings()->GetColor( layerID );
225         auto bitmap = COLOR_SWATCH::MakeBitmap( layerColor, backgroundColor, LAYER_BITMAP_SIZE,
226                                                 CHECKERBOARD_SIZE, aList->GetBackgroundColour() );
227         wxIcon icon;
228         icon.CopyFromBitmap( bitmap );
229 
230         wxVector<wxVariant> row;
231         row.push_back( wxVariant( m_Layers.test( layerID ) ) );
232         row.push_back( wxVariant( wxDataViewIconText( layerName, icon ) ) );
233         row.push_back( wxVariant( wxString::Format( "%i", layerID ) ) );
234         aList->AppendItem( row );
235 
236         if( m_Layers.test( layerID ) )
237             aList->SetToggleValue( true, (unsigned) aList->GetItemCount() - 1, 0 );
238     }
239 
240     int checkColSize = 22;
241     int layerColSize = textWidth + LAYER_BITMAP_SIZE.x + 15;
242 
243     // You'd think the fact that m_layers is a list would encourage wxWidgets not to save room
244     // for the tree expanders... but you'd be wrong.  Force indent to 0.
245     aList->SetIndent( 0 );
246     aList->SetMinClientSize( wxSize( checkColSize + layerColSize, aList->GetMinClientSize().y ) );
247 
248     checkColumn->SetWidth( checkColSize );
249     layerColumn->SetWidth( layerColSize );
250 }
251 
252 
253