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 <bitmaps.h>
23#include <widgets/unit_binder.h>
24#include <pcb_edit_frame.h>
25#include <board.h>
28#include <pad.h>
29#include <pcb_track.h>
30#include <pcb_group.h>
31#include <footprint.h>
32#include <teardrop/teardrop.h>
33#include <zone_filler.h>
36#include <tool/tool_manager.h>
39
40// Globals to remember filters during a session
41static wxString g_netclassFilter;
42static wxString g_netFilter;
43
44
46{
47public:
50
51 bool TransferDataToWindow() override;
52 bool TransferDataFromWindow() override;
53
54protected:
55 void onSpecifiedValuesUpdateUi( wxUpdateUIEvent& event ) override
56 {
57 event.Enable( m_specifiedValues->GetValue() );
58 }
59
60 void onFilterUpdateUi( wxUpdateUIEvent& event ) override
61 {
62 event.Enable( !m_trackToTrack->GetValue() );
63 }
64
65 // Track-to-track teardrops always follow the document-wide settings (there are no teardrop
66 // properties on individual track segments as they're too ephemeral). Therefore we disable
67 // Set-to-specified-values when track-to-track is selected.
68 void onTrackToTrack( wxCommandEvent& event ) override
69 {
70 if( event.IsChecked() && m_specifiedValues->GetValue() )
71 {
72 m_specifiedValues->SetValue( false );
73 m_addTeardrops->SetValue( true );
74 }
75 }
76
77 // These just improve usability so that you don't have to click twice to enable a filter.
78 void OnNetclassFilterSelect( wxCommandEvent& event ) override
79 {
80 m_netclassFilterOpt->SetValue( true );
81 }
82
83 void OnLayerFilterSelect( wxCommandEvent& event ) override
84 {
85 m_layerFilterOpt->SetValue( true );
86 }
87
88 void OnNetFilterSelect( wxCommandEvent& event )
89 {
90 m_netFilterOpt->SetValue( true );
91 }
92
93 // Remove "add" terminology when updating only existing teardrops.
94 void OnExistingFilterSelect( wxCommandEvent& event ) override
95 {
96 if( event.IsChecked() )
97 {
98 m_addTeardrops->SetLabel( _( "Set teardrops to default values for shape" ) );
99 m_specifiedValues->SetLabel( _( "Set teardrops to specified values:" ) );
100 }
101 else
102 {
103 m_addTeardrops->SetLabel( _( "Add teardrops with default values for shape" ) );
104 m_specifiedValues->SetLabel( _( "Add teardrops with specified values:" ) );
105 }
106 }
107
108 void setSpecifiedParams( TEARDROP_PARAMETERS* targetParams );
109 void visitItem( BOARD_COMMIT* aCommit, BOARD_CONNECTED_ITEM* aItem,bool aSelectAlways );
110 void processItem( BOARD_COMMIT* aCommit, BOARD_CONNECTED_ITEM* aItem );
111
112 void onShowBoardSetup( wxHyperlinkEvent& event ) override
113 {
114 m_parent->ShowBoardSetupDialog( _( "Teardrops" ) );
115 }
116
117 void buildFilterLists();
118
119private:
122
128};
129
130
138{
139 m_parent = aParent;
140 m_brd = m_parent->GetBoard();
141
143
147
148 m_minTrackWidthHint->SetFont( KIUI::GetStatusFont( this ).Italic() );
149
151
152 SetupStandardButtons( { { wxID_OK, _( "Apply and Close" ) },
153 { wxID_CANCEL, _( "Close" ) } } );
154
155 m_netFilter->Connect( FILTERED_ITEM_SELECTED,
157 nullptr, this );
158
160}
161
162
164{
165 g_netclassFilter = m_netclassFilter->GetStringSelection();
166 g_netFilter = m_netFilter->GetSelectedNetname();
167
168 m_netFilter->Disconnect( FILTERED_ITEM_SELECTED,
170 nullptr, this );
171}
172
173
175{
176 // Populate the net filter list with net names
177 m_netFilter->SetNetInfo( &m_brd->GetNetInfo() );
178
179 if( !m_brd->GetHighLightNetCodes().empty() )
180 m_netFilter->SetSelectedNetcode( *m_brd->GetHighLightNetCodes().begin() );
181
182 // Populate the netclass filter list with netclass names
183 wxArrayString netclassNames;
184 std::shared_ptr<NET_SETTINGS>& settings = m_brd->GetDesignSettings().m_NetSettings;
185
186 netclassNames.push_back( settings->GetDefaultNetclass()->GetName() );
187
188 for( const auto& [name, netclass] : settings->GetNetclasses() )
189 netclassNames.push_back( name );
190
191 m_netclassFilter->Set( netclassNames );
192 m_netclassFilter->SetStringSelection( m_brd->GetDesignSettings().GetCurrentNetClassName() );
193
194 // Populate the layer filter list
195 m_layerFilter->SetBoardFrame( m_parent );
196 m_layerFilter->SetLayersHotkeys( false );
197 m_layerFilter->SetNotAllowedLayerSet( LSET::AllNonCuMask() );
198 m_layerFilter->Resync();
199 m_layerFilter->SetLayerSelection( m_parent->GetActiveLayer() );
200}
201
202
204{
205 BOARD_DESIGN_SETTINGS& bds = m_brd->GetDesignSettings();
206
211
212 m_netclassFilter->SetStringSelection( g_netclassFilter );
213 m_netFilter->SetSelectedNet( g_netFilter );
214
215 m_cbPreferZoneConnection->Set3StateValue( wxCHK_UNDETERMINED );
216 m_cbTeardropsUseNextTrack->Set3StateValue( wxCHK_UNDETERMINED );
222 m_curvedEdges->Set3StateValue( wxCHK_UNDETERMINED );
223
224 return true;
225}
226
227
229{
230 if( m_cbPreferZoneConnection->Get3StateValue() != wxCHK_UNDETERMINED )
231 targetParams->m_TdOnPadsInZones = !m_cbPreferZoneConnection->GetValue();
232
233 if( m_cbTeardropsUseNextTrack->Get3StateValue() != wxCHK_UNDETERMINED )
234 targetParams->m_AllowUseTwoTracks = m_cbTeardropsUseNextTrack->GetValue();
235
236 if( !m_teardropHDPercent.IsIndeterminate() )
237 targetParams->m_WidthtoSizeFilterRatio = m_teardropHDPercent.GetDoubleValue() / 100.0;
238
239 if( !m_teardropLenPercent.IsIndeterminate() )
240 targetParams->m_BestLengthRatio = m_teardropLenPercent.GetDoubleValue() / 100.0;
241
242 if( !m_teardropMaxLen.IsIndeterminate() )
243 targetParams->m_TdMaxLen = m_teardropMaxLen.GetIntValue();
244
245 if( !m_teardropHeightPercent.IsIndeterminate() )
246 targetParams->m_BestWidthRatio = m_teardropHeightPercent.GetDoubleValue() / 100.0;
247
248 if( !m_teardropMaxHeight.IsIndeterminate() )
249 targetParams->m_TdMaxWidth = m_teardropMaxHeight.GetIntValue();
250
251 if( m_curvedEdges->Get3StateValue() != wxCHK_UNDETERMINED )
252 targetParams->m_CurvedEdges = m_curvedEdges->GetValue();
253}
254
255
257{
258 BOARD_DESIGN_SETTINGS& brdSettings = m_brd->GetDesignSettings();
259 TEARDROP_PARAMETERS& targetParams = aItem->GetTeardropParams();
260
261 aCommit->Stage( aItem, CHT_MODIFY );
262
263 if( m_removeTeardrops->GetValue() || m_removeAllTeardrops->GetValue() )
264 {
265 targetParams.m_Enabled = false;
266 }
267 else if( m_addTeardrops->GetValue() )
268 {
270 targetParams = *brdSettings.GetTeadropParamsList()->GetParameters( TARGET_ROUND );
271 else
272 targetParams = *brdSettings.GetTeadropParamsList()->GetParameters( TARGET_RECT );
273
274 targetParams.m_Enabled = true;
275 }
276 else if( m_specifiedValues->GetValue() )
277 {
278 setSpecifiedParams( &targetParams );
279
280 if( !m_existingFilter->GetValue() )
281 targetParams.m_Enabled = true;
282 }
283}
284
285
287 bool aSelectAlways )
288{
289 if( m_selectedItemsFilter->GetValue() )
290 {
291 if( !aItem->IsSelected() )
292 {
293 EDA_GROUP* group = aItem->GetParentGroup();
294
295 while( group && !group->AsEdaItem()->IsSelected() )
296 group = group->AsEdaItem()->GetParentGroup();
297
298 if( !group )
299 return;
300 }
301 }
302
303 if( aSelectAlways )
304 {
305 processItem( aCommit, aItem );
306 return;
307 }
308
309 if( m_netFilterOpt->GetValue() && m_netFilter->GetSelectedNetcode() >= 0 )
310 {
311 if( aItem->GetNetCode() != m_netFilter->GetSelectedNetcode() )
312 return;
313 }
314
315 if( m_netclassFilterOpt->GetValue() && !m_netclassFilter->GetStringSelection().IsEmpty() )
316 {
317 wxString filterNetclass = m_netclassFilter->GetStringSelection();
318 NETCLASS* netclass = aItem->GetEffectiveNetClass();
319
320 if( !netclass->ContainsNetclassWithName( filterNetclass ) )
321 return;
322 }
323
324 if( m_layerFilterOpt->GetValue() && m_layerFilter->GetLayerSelection() != UNDEFINED_LAYER )
325 {
326 if( aItem->GetLayer() != m_layerFilter->GetLayerSelection() )
327 return;
328 }
329
330 if( m_roundPadsFilter->GetValue() )
331 {
333 return;
334 }
335
336 if( m_existingFilter->GetValue() )
337 {
338 if( !aItem->GetTeardropParams().m_Enabled )
339 return;
340 }
341
342 processItem( aCommit, aItem );
343}
344
345
347{
348 m_brd->SetLegacyTeardrops( false );
349
350 BOARD_COMMIT commit( m_parent );
351 wxBusyCursor dummy;
352
353 // Save some dialog options
354 BOARD_DESIGN_SETTINGS& bds = m_brd->GetDesignSettings();
355
356 bds.m_TeardropParamsList.m_TargetVias = m_vias->GetValue();
361
362 bool remove_all = m_removeAllTeardrops->GetValue();
363
364 if( m_vias->GetValue() || remove_all )
365 {
366 for( PCB_TRACK* track : m_brd->Tracks() )
367 {
368 if ( track->Type() == PCB_VIA_T )
369 visitItem( &commit, track, remove_all );
370 }
371 }
372
373 for( FOOTPRINT* footprint : m_brd->Footprints() )
374 {
375 for( PAD* pad : footprint->Pads() )
376 {
377 if( remove_all )
378 {
379 visitItem( &commit, pad, true );
380 continue;
381 }
382
383 if( m_pthPads->GetValue() && pad->GetAttribute() == PAD_ATTRIB::PTH )
384 {
385 visitItem( &commit, pad, false );
386 }
387 else if( m_smdPads->GetValue() && ( pad->GetAttribute() == PAD_ATTRIB::SMD
388 || pad->GetAttribute() == PAD_ATTRIB::CONN ) )
389 {
390 visitItem( &commit, pad, false );
391 }
392 }
393 }
394
395 // "Remove all" has to reach track-to-track too, or the update below rebuilds them at once.
396 if( m_trackToTrack->GetValue() || remove_all )
397 {
398 TEARDROP_PARAMETERS_LIST* paramsList = m_brd->GetDesignSettings().GetTeadropParamsList();
399 TEARDROP_PARAMETERS* targetParams = paramsList->GetParameters( TARGET_TRACK );
400 TEARDROP_MANAGER teardropManager( m_brd, m_parent->GetToolManager() );
401
402 teardropManager.DeleteTrackToTrackTeardrops( commit );
403
404 if( m_removeTeardrops->GetValue() || m_removeAllTeardrops->GetValue() )
405 {
406 targetParams->m_Enabled = false;
407 }
408 else if( m_addTeardrops->GetValue() )
409 {
410 targetParams->m_Enabled = true;
411 teardropManager.BuildTrackCaches();
412 teardropManager.AddTeardropsOnTracks( commit, nullptr, true );
413 }
414 }
415
416 // If there are no filters then a force-full-update is equivalent, and will be faster.
417 if( !m_netFilterOpt->GetValue()
418 && !m_netclassFilterOpt->GetValue()
419 && !m_layerFilterOpt->GetValue()
420 && !m_roundPadsFilter->GetValue()
421 && !m_existingFilter->GetValue()
422 && !m_selectedItemsFilter->GetValue() )
423 {
424 commit.Push( _( "Edit Teardrops" ), SKIP_TEARDROPS );
425
426 TEARDROP_MANAGER teardropMgr( m_brd, m_parent->GetToolManager() );
427 teardropMgr.UpdateTeardrops( commit, nullptr, nullptr, true /* forceFullUpdate */ );
428 commit.Push( _( "Edit Teardrops" ), SKIP_TEARDROPS | APPEND_UNDO );
429 }
430 else
431 {
432 commit.Push( _( "Edit Teardrops" ) );
433 }
434
435 // Showing the unfilled, fully cross-hatched teardrops seems to be working fairly well, and
436 // accurate fills can then be manually generated by doing a zone fill.
437 //
438 // But here's the old code which allowed for either "draft" fills or an automatic full zone
439 // fill in case we decide the current situation isn't good enough:
440#if 0
441 if( aFillAfter )
442 {
443 ZONE_FILLER filler( m_board, aCommit );
444
445 if( m_reporter )
446 filler.SetProgressReporter( m_reporter );
447
448 filler.Fill( m_board->Zones() );
449
450 if( aCommit )
451 aCommit->Push( _( "Edit Teardrops" ), APPEND_UNDO );
452 }
453 else
454 {
455 // Fill raw teardrop shapes. This is a rough calculation, just to show a filled
456 // shape on screen without the (potentially large) performance hit of a zone refill
457 int epsilon = pcbIUScale.mmToIU( 0.001 );
458 int allowed_error = pcbIUScale.mmToIU( 0.005 );
459
460 for( ZONE* zone: m_createdTdList )
461 {
462 int half_min_width = zone->GetMinThickness() / 2;
463 int numSegs = GetArcToSegmentCount( half_min_width, allowed_error, FULL_CIRCLE );
464 SHAPE_POLY_SET filledPolys = *zone->Outline();
465
466 filledPolys.Deflate( half_min_width - epsilon, numSegs );
467
468 // Re-inflate after pruning of areas that don't meet minimum-width criteria
469 if( half_min_width - epsilon > epsilon )
470 filledPolys.Inflate( half_min_width - epsilon, numSegs );
471
472 zone->SetFilledPolysList( zone->GetFirstLayer(), filledPolys );
473 }
474 }
475#endif
476
477 m_parent->Refresh();
478 return true;
479}
480
481
483{
485 DIALOG_GLOBAL_EDIT_TEARDROPS dlg( editFrame );
486
487 dlg.ShowQuasiModal(); // QuasiModal required for NET_SELECTOR
488 return 0;
489}
const char * name
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:128
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:106
#define SKIP_TEARDROPS
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.
TEARDROP_PARAMETERS & GetTeardropParams()
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:411
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:43
virtual EDA_GROUP * GetParentGroup() const
Definition eda_item.h:116
bool IsSelected() const
Definition eda_item.h:134
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:44
bool ContainsNetclassWithName(const wxString &netclass) const
Determines if the given netclass name is a constituent of this (maybe aggregate) netclass.
Definition netclass.cpp:336
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:87
static bool IsUniformlyRound(BOARD_ITEM *aItem)
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:437
void AddTeardropsOnTracks(BOARD_COMMIT &aCommit, const std::set< PCB_TRACK * > *aTracks, bool aForceFullUpdate=false, bool aSetPriorities=true)
Add teardrop on tracks of different sizes connected by their end.
Definition teardrop.cpp:697
void DeleteTrackToTrackTeardrops(BOARD_COMMIT &aCommit)
Definition teardrop.cpp:619
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:470
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:100
@ PTH
Plated through hole pad.
Definition padstack.h:99
@ CONN
Like smd, does not appear on the solder paste layer (default) Note: also has a special attribute in G...
Definition padstack.h:101
Class to handle a set of BOARD_ITEMs.
const double epsilon
#define APPEND_UNDO
Definition sch_commit.h:39
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:89
#define INDETERMINATE_ACTION
Definition ui_common.h:48