KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_global_edit_teardrops.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#include <algorithm>
21
22#include <widgets/unit_binder.h>
23#include <pcb_edit_frame.h>
24#include <board.h>
27#include <pad.h>
28#include <pcb_track.h>
29#include <pcb_group.h>
30#include <footprint.h>
31#include <teardrop/teardrop.h>
32#include <zone_filler.h>
35#include <tool/tool_manager.h>
38
39// Globals to remember filters during a session
40static wxString g_netclassFilter;
41static wxString g_netFilter;
42
43
45{
46public:
49
50protected:
51 void onSpecifiedValuesUpdateUi( wxUpdateUIEvent& event ) override
52 {
53 event.Enable( m_specifiedValues->GetValue() );
54 }
55 void onFilterUpdateUi( wxUpdateUIEvent& event ) override
56 {
57 event.Enable( !m_trackToTrack->GetValue() );
58 }
59
60 // Track-to-track teardrops always follow the document-wide settings (there are no teardrop
61 // properties on individual track segments as they're too ephemeral). Therefore we disable
62 // Set-to-specified-values when track-to-track is selected.
63 void onTrackToTrack( wxCommandEvent& event ) override
64 {
65 if( event.IsChecked() && m_specifiedValues->GetValue() )
66 {
67 m_specifiedValues->SetValue( false );
68 m_addTeardrops->SetValue( true );
69 }
70 }
71
72 // These just improve usability so that you don't have to click twice to enable a filter.
73 void OnNetclassFilterSelect( wxCommandEvent& event ) override
74 {
75 m_netclassFilterOpt->SetValue( true );
76 }
77 void OnLayerFilterSelect( wxCommandEvent& event ) override
78 {
79 m_layerFilterOpt->SetValue( true );
80 }
81 void OnNetFilterSelect( wxCommandEvent& event )
82 {
83 m_netFilterOpt->SetValue( true );
84 }
85
86 // Remove "add" terminology when updating only existing teardrops.
87 void OnExistingFilterSelect( wxCommandEvent& event ) override
88 {
89 if( event.IsChecked() )
90 {
91 m_addTeardrops->SetLabel( _( "Set teardrops to default values for shape" ) );
92 m_specifiedValues->SetLabel( _( "Set teardrops to specified values:" ) );
93 }
94 else
95 {
96 m_addTeardrops->SetLabel( _( "Add teardrops with default values for shape" ) );
97 m_specifiedValues->SetLabel( _( "Add teardrops with specified values:" ) );
98 }
99 }
100
101 void setSpecifiedParams( TEARDROP_PARAMETERS* targetParams );
102 void visitItem( BOARD_COMMIT* aCommit, BOARD_CONNECTED_ITEM* aItem,bool aSelectAlways );
103 void processItem( BOARD_COMMIT* aCommit, BOARD_CONNECTED_ITEM* aItem );
104
105 bool TransferDataToWindow() override;
106 bool TransferDataFromWindow() override;
107
108
109 void onShowBoardSetup( wxHyperlinkEvent& event ) override
110 {
111 m_parent->ShowBoardSetupDialog( _( "Teardrops" ) );
112 }
113
114 void buildFilterLists();
115
116private:
120
126};
127
128
136{
137 m_parent = aParent;
138 m_brd = m_parent->GetBoard();
139
141
145
146 m_minTrackWidthHint->SetFont( KIUI::GetStatusFont( this ).Italic() );
147
149
150 SetupStandardButtons( { { wxID_OK, _( "Apply and Close" ) },
151 { wxID_CANCEL, _( "Close" ) } } );
152
153 m_netFilter->Connect( FILTERED_ITEM_SELECTED,
155 nullptr, this );
156
158}
159
160
162{
163 g_netclassFilter = m_netclassFilter->GetStringSelection();
164 g_netFilter = m_netFilter->GetSelectedNetname();
165
166 m_netFilter->Disconnect( FILTERED_ITEM_SELECTED,
168 nullptr, this );
169}
170
171
173{
174 // Populate the net filter list with net names
175 m_netFilter->SetNetInfo( &m_brd->GetNetInfo() );
176
177 if( !m_brd->GetHighLightNetCodes().empty() )
178 m_netFilter->SetSelectedNetcode( *m_brd->GetHighLightNetCodes().begin() );
179
180 // Populate the netclass filter list with netclass names
181 wxArrayString netclassNames;
182 std::shared_ptr<NET_SETTINGS>& settings = m_brd->GetDesignSettings().m_NetSettings;
183
184 netclassNames.push_back( settings->GetDefaultNetclass()->GetName() );
185
186 for( const auto& [name, netclass] : settings->GetNetclasses() )
187 netclassNames.push_back( name );
188
189 m_netclassFilter->Set( netclassNames );
190 m_netclassFilter->SetStringSelection( m_brd->GetDesignSettings().GetCurrentNetClassName() );
191
192 // Populate the layer filter list
193 m_layerFilter->SetBoardFrame( m_parent );
194 m_layerFilter->SetLayersHotkeys( false );
195 m_layerFilter->SetNotAllowedLayerSet( LSET::AllNonCuMask() );
196 m_layerFilter->Resync();
197 m_layerFilter->SetLayerSelection( m_parent->GetActiveLayer() );
198}
199
200
202{
203 BOARD_DESIGN_SETTINGS& bds = m_brd->GetDesignSettings();
204
209
210 m_netclassFilter->SetStringSelection( g_netclassFilter );
211 m_netFilter->SetSelectedNet( g_netFilter );
212
213 m_cbPreferZoneConnection->Set3StateValue( wxCHK_UNDETERMINED );
214 m_cbTeardropsUseNextTrack->Set3StateValue( wxCHK_UNDETERMINED );
220 m_curvedEdges->Set3StateValue( wxCHK_UNDETERMINED );
221
222 return true;
223}
224
225
227{
228 if( m_cbPreferZoneConnection->Get3StateValue() != wxCHK_UNDETERMINED )
229 targetParams->m_TdOnPadsInZones = !m_cbPreferZoneConnection->GetValue();
230
231 if( m_cbTeardropsUseNextTrack->Get3StateValue() != wxCHK_UNDETERMINED )
232 targetParams->m_AllowUseTwoTracks = m_cbTeardropsUseNextTrack->GetValue();
233
234 if( !m_teardropHDPercent.IsIndeterminate() )
235 targetParams->m_WidthtoSizeFilterRatio = m_teardropHDPercent.GetDoubleValue() / 100.0;
236
237 if( !m_teardropLenPercent.IsIndeterminate() )
238 targetParams->m_BestLengthRatio = m_teardropLenPercent.GetDoubleValue() / 100.0;
239
240 if( !m_teardropMaxLen.IsIndeterminate() )
241 targetParams->m_TdMaxLen = m_teardropMaxLen.GetIntValue();
242
243 if( !m_teardropHeightPercent.IsIndeterminate() )
244 targetParams->m_BestWidthRatio = m_teardropHeightPercent.GetDoubleValue() / 100.0;
245
246 if( !m_teardropMaxHeight.IsIndeterminate() )
247 targetParams->m_TdMaxWidth = m_teardropMaxHeight.GetIntValue();
248
249 if( m_curvedEdges->Get3StateValue() != wxCHK_UNDETERMINED )
250 targetParams->m_CurvedEdges = m_curvedEdges->GetValue();
251}
252
253
255{
256 BOARD_DESIGN_SETTINGS& brdSettings = m_brd->GetDesignSettings();
257 TEARDROP_PARAMETERS* targetParams = nullptr;
258
259 if( aItem->Type() == PCB_PAD_T )
260 targetParams = &static_cast<PAD*>( aItem )->GetTeardropParams();
261 else if( aItem->Type() == PCB_VIA_T )
262 targetParams = &static_cast<PCB_VIA*>( aItem )->GetTeardropParams();
263 else
264 return;
265
266 aCommit->Stage( aItem, CHT_MODIFY );
267
268 if( m_removeTeardrops->GetValue() || m_removeAllTeardrops->GetValue() )
269 {
270 targetParams->m_Enabled = false;
271 }
272 else if( m_addTeardrops->GetValue() )
273 {
274 // NOTE: This ignores possible padstack shape variation.
276 *targetParams = *brdSettings.GetTeadropParamsList()->GetParameters( TARGET_ROUND );
277 else
278 *targetParams = *brdSettings.GetTeadropParamsList()->GetParameters( TARGET_RECT );
279
280 targetParams->m_Enabled = true;
281 }
282 else if( m_specifiedValues->GetValue() )
283 {
284 setSpecifiedParams( targetParams );
285
286 if( !m_existingFilter->GetValue() )
287 targetParams->m_Enabled = true;
288 }
289}
290
291
293 bool aSelectAlways )
294{
295 if( m_selectedItemsFilter->GetValue() )
296 {
297 if( !aItem->IsSelected() )
298 {
299 EDA_GROUP* group = aItem->GetParentGroup();
300
301 while( group && !group->AsEdaItem()->IsSelected() )
302 group = group->AsEdaItem()->GetParentGroup();
303
304 if( !group )
305 return;
306 }
307 }
308
309 if( aSelectAlways )
310 {
311 processItem( aCommit, aItem );
312 return;
313 }
314
315
316 if( m_netFilterOpt->GetValue() && m_netFilter->GetSelectedNetcode() >= 0 )
317 {
318 if( aItem->GetNetCode() != m_netFilter->GetSelectedNetcode() )
319 return;
320 }
321
322 if( m_netclassFilterOpt->GetValue() && !m_netclassFilter->GetStringSelection().IsEmpty() )
323 {
324 wxString filterNetclass = m_netclassFilter->GetStringSelection();
325 NETCLASS* netclass = aItem->GetEffectiveNetClass();
326
327 if( !netclass->ContainsNetclassWithName( filterNetclass ) )
328 return;
329 }
330
331 if( m_layerFilterOpt->GetValue() && m_layerFilter->GetLayerSelection() != UNDEFINED_LAYER )
332 {
333 if( aItem->GetLayer() != m_layerFilter->GetLayerSelection() )
334 return;
335 }
336
337 if( m_roundPadsFilter->GetValue() )
338 {
339 // TODO(JE) padstacks -- teardrops needs to support per-layer pad handling
341 return;
342 }
343
344 if( m_existingFilter->GetValue() )
345 {
346 if( aItem->Type() == PCB_PAD_T )
347 {
348 if( !static_cast<PAD*>( aItem )->GetTeardropParams().m_Enabled )
349 return;
350 }
351 else if( aItem->Type() == PCB_VIA_T )
352 {
353 if( !static_cast<PCB_VIA*>( aItem )->GetTeardropParams().m_Enabled )
354 return;
355 }
356 }
357
358 processItem( aCommit, aItem );
359}
360
361
363{
364 m_brd->SetLegacyTeardrops( false );
365
366 BOARD_COMMIT commit( m_parent );
367 wxBusyCursor dummy;
368
369 // Save some dialog options
370 BOARD_DESIGN_SETTINGS& bds = m_brd->GetDesignSettings();
371
372 bds.m_TeardropParamsList.m_TargetVias = m_vias->GetValue();
377
378 bool remove_all = m_removeAllTeardrops->GetValue();
379
380 if( m_vias->GetValue() || remove_all )
381 {
382 for( PCB_TRACK* track : m_brd->Tracks() )
383 {
384 if ( track->Type() == PCB_VIA_T )
385 visitItem( &commit, track, remove_all );
386 }
387 }
388
389 for( FOOTPRINT* footprint : m_brd->Footprints() )
390 {
391 for( PAD* pad : footprint->Pads() )
392 {
393 if( remove_all )
394 {
395 visitItem( &commit, pad, true );
396 continue;
397 }
398
399 if( m_pthPads->GetValue() && pad->GetAttribute() == PAD_ATTRIB::PTH )
400 {
401 visitItem( &commit, pad, false );
402 }
403 else if( m_smdPads->GetValue() && ( pad->GetAttribute() == PAD_ATTRIB::SMD
404 || pad->GetAttribute() == PAD_ATTRIB::CONN ) )
405 {
406 visitItem( &commit, pad, false );
407 }
408 }
409 }
410
411 if( m_trackToTrack->GetValue() )
412 {
413 TEARDROP_PARAMETERS_LIST* paramsList = m_brd->GetDesignSettings().GetTeadropParamsList();
414 TEARDROP_PARAMETERS* targetParams = paramsList->GetParameters( TARGET_TRACK );
415 TEARDROP_MANAGER teardropManager( m_brd, m_parent->GetToolManager() );
416
417 teardropManager.DeleteTrackToTrackTeardrops( commit );
418 teardropManager.BuildTrackCaches();
419
420 if( m_removeTeardrops->GetValue() || m_removeAllTeardrops->GetValue() )
421 {
422 targetParams->m_Enabled = false;
423 }
424 else if( m_addTeardrops->GetValue() )
425 {
426 targetParams->m_Enabled = true;
427 teardropManager.AddTeardropsOnTracks( commit, nullptr, true );
428 }
429 }
430
431 // If there are no filters then a force-full-update is equivalent, and will be faster.
432 if( !m_netFilterOpt->GetValue()
433 && !m_netclassFilterOpt->GetValue()
434 && !m_layerFilterOpt->GetValue()
435 && !m_roundPadsFilter->GetValue()
436 && !m_existingFilter->GetValue()
437 && !m_selectedItemsFilter->GetValue() )
438 {
439 commit.Push( _( "Edit Teardrops" ), SKIP_TEARDROPS );
440
441 TEARDROP_MANAGER teardropMgr( m_brd, m_parent->GetToolManager() );
442 teardropMgr.UpdateTeardrops( commit, nullptr, nullptr, true /* forceFullUpdate */ );
443 commit.Push( _( "Edit Teardrops" ), SKIP_TEARDROPS | APPEND_UNDO );
444 }
445 else
446 {
447 commit.Push( _( "Edit Teardrops" ) );
448 }
449
450 // Showing the unfilled, fully cross-hatched teardrops seems to be working fairly well, and
451 // accurate fills can then be manually generated by doing a zone fill.
452 //
453 // But here's the old code which allowed for either "draft" fills or an automatic full zone
454 // fill in case we decide the current situation isn't good enough:
455#if 0
456 if( aFillAfter )
457 {
458 ZONE_FILLER filler( m_board, aCommit );
459
460 if( m_reporter )
461 filler.SetProgressReporter( m_reporter );
462
463 filler.Fill( m_board->Zones() );
464
465 if( aCommit )
466 aCommit->Push( _( "Edit Teardrops" ), APPEND_UNDO );
467 }
468 else
469 {
470 // Fill raw teardrop shapes. This is a rough calculation, just to show a filled
471 // shape on screen without the (potentially large) performance hit of a zone refill
472 int epsilon = pcbIUScale.mmToIU( 0.001 );
473 int allowed_error = pcbIUScale.mmToIU( 0.005 );
474
475 for( ZONE* zone: m_createdTdList )
476 {
477 int half_min_width = zone->GetMinThickness() / 2;
478 int numSegs = GetArcToSegmentCount( half_min_width, allowed_error, FULL_CIRCLE );
479 SHAPE_POLY_SET filledPolys = *zone->Outline();
480
481 filledPolys.Deflate( half_min_width - epsilon, numSegs );
482
483 // Re-inflate after pruning of areas that don't meet minimum-width criteria
484 if( half_min_width - epsilon > epsilon )
485 filledPolys.Inflate( half_min_width - epsilon, numSegs );
486
487 zone->SetFilledPolysList( zone->GetFirstLayer(), filledPolys );
488 }
489 }
490#endif
491
492 m_parent->Refresh();
493 return true;
494}
495
496
498{
500 DIALOG_GLOBAL_EDIT_TEARDROPS dlg( editFrame );
501
502 dlg.ShowQuasiModal(); // QuasiModal required for NET_SELECTOR
503 return 0;
504}
const char * name
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:106
#define SKIP_TEARDROPS
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
COMMIT & Stage(EDA_ITEM *aItem, CHANGE_TYPE aChangeType, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE) override
Add a change of the item aItem of type aChangeType to the change list.
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
virtual NETCLASS * GetEffectiveNetClass() const
Return the NETCLASS for this item.
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Container for design settings for a BOARD object.
TEARDROP_PARAMETERS_LIST * GetTeadropParamsList()
TEARDROP_PARAMETERS_LIST m_TeardropParamsList
The parameters of teardrops for the different teardrop targets (via/pad, track end).
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:372
DIALOG_GLOBAL_EDIT_TEARDROPS_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Set Teardrops"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
void processItem(BOARD_COMMIT *aCommit, BOARD_CONNECTED_ITEM *aItem)
void visitItem(BOARD_COMMIT *aCommit, BOARD_CONNECTED_ITEM *aItem, bool aSelectAlways)
void OnNetFilterSelect(wxCommandEvent &event)
void setSpecifiedParams(TEARDROP_PARAMETERS *targetParams)
void OnNetclassFilterSelect(wxCommandEvent &event) override
DIALOG_GLOBAL_EDIT_TEARDROPS(PCB_EDIT_FRAME *aParent)
void onTrackToTrack(wxCommandEvent &event) override
void onSpecifiedValuesUpdateUi(wxUpdateUIEvent &event) override
void OnExistingFilterSelect(wxCommandEvent &event) override
void onShowBoardSetup(wxHyperlinkEvent &event) override
void onFilterUpdateUi(wxUpdateUIEvent &event) override
void OnLayerFilterSelect(wxCommandEvent &event) override
void SetupStandardButtons(std::map< int, wxString > aLabels={})
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
A set of EDA_ITEMs (i.e., without duplicates).
Definition eda_group.h:42
virtual EDA_GROUP * GetParentGroup() const
Definition eda_item.h:114
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:108
bool IsSelected() const
Definition eda_item.h:132
int EditTeardrops(const TOOL_EVENT &aEvent)
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition lset.cpp:623
A collection of nets and the parameters used to route or test these nets.
Definition netclass.h:38
bool ContainsNetclassWithName(const wxString &netclass) const
Determines if the given netclass name is a constituent of this (maybe aggregate) netclass.
Definition netclass.cpp:310
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition padstack.h:177
Definition pad.h:61
The main frame for Pcbnew.
Represent a set of closed polygons.
void Inflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify=false)
Perform outline inflation/deflation.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
void Deflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError)
TEARDROP_MANAGER manage and build teardrop areas A teardrop area is a polygonal area (a copper ZONE) ...
Definition teardrop.h:90
static bool IsRound(BOARD_ITEM *aItem, PCB_LAYER_ID aLayer)
void UpdateTeardrops(BOARD_COMMIT &aCommit, const std::vector< BOARD_ITEM * > *dirtyPadsAndVias, const std::set< PCB_TRACK * > *dirtyTracks, bool aForceFullUpdate=false)
Update teardrops on a list of items.
Definition teardrop.cpp:225
void AddTeardropsOnTracks(BOARD_COMMIT &aCommit, const std::set< PCB_TRACK * > *aTracks, bool aForceFullUpdate=false)
Add teardrop on tracks of different sizes connected by their end.
Definition teardrop.cpp:446
void DeleteTrackToTrackTeardrops(BOARD_COMMIT &aCommit)
Definition teardrop.cpp:390
TEARDROP_PARAMETERS_LIST is a helper class to handle the list of TEARDROP_PARAMETERS needed to build ...
bool m_UseRoundShapesOnly
True to create teardrops for round shapes only.
bool m_TargetVias
True to create teardrops for vias.
bool m_TargetPTHPads
True to create teardrops for pads with holes.
bool m_TargetTrack2Track
True to create teardrops at the end of a track connected to the end of another track having a differe...
TEARDROP_PARAMETERS * GetParameters(TARGET_TD aTdType)
bool m_TargetSMDPads
True to create teardrops for pads SMD, edge connectors,.
TEARDROP_PARAMETARS is a helper class to handle parameters needed to build teardrops for a board thes...
double m_BestWidthRatio
The height of a teardrop as ratio between height and size of pad/via.
int m_TdMaxLen
max allowed length for teardrops in IU. <= 0 to disable
bool m_AllowUseTwoTracks
True to create teardrops using 2 track segments if the first in too small.
int m_TdMaxWidth
max allowed height for teardrops in IU. <= 0 to disable
double m_BestLengthRatio
The length of a teardrop as ratio between length and size of pad/via.
double m_WidthtoSizeFilterRatio
The ratio (H/D) between the via/pad size and the track width max value to create a teardrop 1....
bool m_TdOnPadsInZones
A filter to exclude pads inside zone fills.
bool m_Enabled
Flag to enable teardrops.
bool m_CurvedEdges
True if the teardrop should be curved.
T * getEditFrame() const
Return the application window object, casted to requested user type.
Definition tool_base.h:182
Generic, UI-independent tool event.
Definition tool_event.h:167
void SetProgressReporter(PROGRESS_REPORTER *aReporter)
bool Fill(const std::vector< ZONE * > &aZones, bool aCheck=false, wxWindow *aParent=nullptr)
Fills the given list of zones.
Handle a list of polygons defining a copper zone.
Definition zone.h:70
@ CHT_MODIFY
Definition commit.h:40
static wxString g_netclassFilter
static wxString g_netFilter
#define _(s)
static constexpr EDA_ANGLE FULL_CIRCLE
Definition eda_angle.h:409
int GetArcToSegmentCount(int aRadius, int aErrorMax, const EDA_ANGLE &aArcAngle)
@ UNDEFINED_LAYER
Definition layer_ids.h:57
KICOMMON_API wxFont GetStatusFont(wxWindow *aWindow)
@ SMD
Smd pad, appears on the solder paste layer (default)
Definition padstack.h:99
@ PTH
Plated through hole pad.
Definition padstack.h:98
@ CONN
Like smd, does not appear on the solder paste layer (default) Note: also has a special attribute in G...
Definition padstack.h:100
Class to handle a set of BOARD_ITEMs.
const double epsilon
#define APPEND_UNDO
Definition sch_commit.h:37
std::vector< FAB_LAYER_COLOR > dummy
@ TARGET_ROUND
@ TARGET_RECT
@ TARGET_TRACK
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition typeinfo.h:90
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition typeinfo.h:80
#define INDETERMINATE_ACTION
Definition ui_common.h:47