KiCad PCB EDA Suite
Loading...
Searching...
No Matches
drc_tool.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, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <pcb_edit_frame.h>
25#include <tool/tool_manager.h>
26#include <tools/pcb_actions.h>
27#include <tools/pcb_tool_base.h>
30#include <tools/drc_tool.h>
31#include <kiface_base.h>
32#include <dialog_drc.h>
33#include <board_commit.h>
35#include <progress_reporter.h>
36#include <drc/drc_engine.h>
37#include <drc/drc_item.h>
39#include <macros.h>
42
43
45 PCB_TOOL_BASE( "pcbnew.DRCTool" ),
46 m_editFrame( nullptr ),
47 m_pcb( nullptr ),
48 m_drcDialog( nullptr ),
49 m_designRuleEditorDlg( nullptr ),
50 m_drcRunning( false )
51{
52}
53
54
58
59
61{
63
64 if( m_pcb != m_editFrame->GetBoard() )
65 {
66 if( m_drcDialog )
68
69 m_pcb = m_editFrame->GetBoard();
70 m_drcEngine = m_pcb->GetDesignSettings().m_DRCEngine;
71 }
72}
73
74
75void DRC_TOOL::ShowDRCDialog( wxWindow* aParent )
76{
77 bool show_dlg_modal = true;
78
79 // the dialog needs a parent frame. if it is not specified, this is the PCB editor frame
80 // specified in DRC_TOOL class.
81 if( !aParent )
82 {
83 // if any parent is specified, the dialog is modal.
84 // if this is the default PCB editor frame, it is not modal
85 show_dlg_modal = false;
86 aParent = m_editFrame;
87 }
88
89 Activate();
91
92 if( !m_drcDialog )
93 {
94 m_drcDialog = new DIALOG_DRC( m_editFrame, aParent );
95 updatePointers( false );
96
97 if( show_dlg_modal )
98 m_drcDialog->ShowModal();
99 else
100 m_drcDialog->Show( true );
101 }
102 else // The dialog is just not visible (because the user has double clicked on an error item)
103 {
104 updatePointers( false );
105 m_drcDialog->Show( true );
106 }
107}
108
109
111{
112 ShowDRCDialog( nullptr );
113 return 0;
114}
115
116
118{
119 if( m_drcDialog )
120 return m_drcDialog->IsShownOnScreen();
121
122 return false;
123}
124
125
127{
128 if( m_drcDialog )
129 {
130 m_drcDialog->Destroy();
131 m_drcDialog = nullptr;
132 }
133}
134
135
136void DRC_TOOL::RunTests( PROGRESS_REPORTER* aProgressReporter, bool aRefillZones,
137 bool aReportAllTrackErrors, bool aTestFootprints )
138{
139 // One at a time, please.
140 // Note that the main GUI entry points to get here are blocked, so this is really an
141 // insurance policy and as such we make no attempts to queue up the DRC run or anything.
142 if( m_drcRunning )
143 return;
144
145 ZONE_FILLER_TOOL* zoneFiller = m_toolMgr->GetTool<ZONE_FILLER_TOOL>();
146 BOARD_COMMIT commit( m_editFrame );
148 bool netlistFetched = false;
149
150 if( m_drcDialog )
151 wxWindowDisabler disabler( /* disable everything except: */ m_drcDialog );
152
153 m_drcRunning = true;
154
155 if( m_drcDialog )
156 {
157 if( aRefillZones )
158 {
159 aProgressReporter->AdvancePhase( _( "Refilling all zones..." ) );
160
161 zoneFiller->FillAllZones( m_drcDialog, aProgressReporter );
162 }
163
164 m_drcEngine->SetDrawingSheet( m_editFrame->GetCanvas()->GetDrawingSheet() );
165
166 if( aTestFootprints && !Kiface().IsSingle() )
167 {
168 if( m_editFrame->FetchNetlistFromSchematic( netlist,
169 _( "Schematic parity tests require a "
170 "fully annotated schematic." ) ) )
171 {
172 netlistFetched = true;
173 }
174
175 if( m_drcDialog )
176 m_drcDialog->Raise();
177
178 m_drcEngine->SetSchematicNetlist( &netlist );
179 }
180 }
181
182 m_drcEngine->SetProgressReporter( aProgressReporter );
183
184 m_drcEngine->SetViolationHandler(
185 [&]( const std::shared_ptr<DRC_ITEM>& aItem, const VECTOR2I& aPos, int aLayer,
186 const std::function<void( PCB_MARKER* )>& aPathGenerator )
187 {
188 PCB_MARKER* marker = new PCB_MARKER( aItem, aPos, aLayer );
189 aPathGenerator( marker );
190 commit.Add( marker );
191 } );
192
193 m_drcEngine->RunTests( m_editFrame->GetUserUnits(), aReportAllTrackErrors, aTestFootprints,
194 &commit );
195
196 m_drcEngine->SetProgressReporter( nullptr );
197 m_drcEngine->ClearViolationHandler();
198
199 if( m_drcDialog )
200 {
201 m_drcDialog->SetDrcRun();
202
203 if( aTestFootprints && netlistFetched )
204 m_drcDialog->SetFootprintTestsRun();
205 }
206
207 commit.Push( _( "DRC" ), SKIP_UNDO | SKIP_SET_DIRTY );
208
209 m_drcRunning = false;
210
211 m_editFrame->ShowSolderMask();
212
213 // update the m_drcDialog listboxes
214 updatePointers( aProgressReporter->IsCancelled() );
215}
216
217
218void DRC_TOOL::updatePointers( bool aDRCWasCancelled )
219{
220 // update my pointers, m_editFrame is the only unchangeable one
221 m_pcb = m_editFrame->GetBoard();
222
223 m_editFrame->ResolveDRCExclusions( aDRCWasCancelled );
224
225 if( m_drcDialog )
226 m_drcDialog->UpdateData();
227}
228
229
231{
232 if( m_drcDialog )
233 {
234 m_drcDialog->Show( true );
235 m_drcDialog->Raise();
236 m_drcDialog->PrevMarker();
237 }
238 else
239 {
240 ShowDRCDialog( nullptr );
241 }
242
243 return 0;
244}
245
246
248{
249 if( m_drcDialog )
250 {
251 m_drcDialog->Show( true );
252 m_drcDialog->Raise();
253 m_drcDialog->NextMarker();
254 }
255 else
256 {
257 ShowDRCDialog( nullptr );
258 }
259
260 return 0;
261}
262
263
265{
266 if( m_drcDialog && m_drcDialog->IsShownOnScreen() )
267 {
268 PCB_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
269 PCB_SELECTION& selection = selectionTool->GetSelection();
270
271 if( selection.GetSize() == 1 && selection.Front()->Type() == PCB_MARKER_T )
272 m_drcDialog->SelectMarker( static_cast<PCB_MARKER*>( selection.Front() ) );
273 }
274
275 return 0;
276}
277
278
279void DRC_TOOL::CrossProbe( const PCB_MARKER* aMarker )
280{
281 if( !IsDRCDialogShown() )
282 ShowDRCDialog( nullptr );
283
284 m_drcDialog->SelectMarker( aMarker );
285}
286
287
289{
290 if( m_drcDialog )
291 m_drcDialog->ExcludeMarker();
292
293 return 0;
294}
295
296
297wxString DRC_TOOL::FixDRCErrorMenuText( const std::shared_ptr<RC_ITEM>& aDRCItem )
298{
299 if( aDRCItem->GetErrorCode() == DRCE_LIB_FOOTPRINT_ISSUES )
300 {
301 return frame()->GetRunMenuCommandDescription( PCB_ACTIONS::showFootprintLibTable );
302 }
303 else if( aDRCItem->GetErrorCode() == DRCE_LIB_FOOTPRINT_MISMATCH )
304 {
305 return frame()->GetRunMenuCommandDescription( PCB_ACTIONS::updateFootprint );
306 }
307 else if( aDRCItem->GetErrorCode() == DRCE_FOOTPRINT_FILTERS )
308 {
309 return frame()->GetRunMenuCommandDescription( PCB_ACTIONS::changeFootprint );
310 }
311 else if( aDRCItem->GetErrorCode() == DRCE_SCHEMATIC_PARITY
312 || aDRCItem->GetErrorCode() == DRCE_SCHEMATIC_FIELDS_PARITY
313 || aDRCItem->GetErrorCode() == DRCE_MISSING_FOOTPRINT
314 || aDRCItem->GetErrorCode() == DRCE_DUPLICATE_FOOTPRINT
315 || aDRCItem->GetErrorCode() == DRCE_EXTRA_FOOTPRINT )
316 {
317 return frame()->GetRunMenuCommandDescription( PCB_ACTIONS::updatePcbFromSchematic );
318 }
319 else if( aDRCItem->GetErrorCode() == DRCE_FOOTPRINT_TYPE_MISMATCH
320 || aDRCItem->GetErrorCode() == DRCE_FOOTPRINT )
321 {
322 return _( "Edit Footprint Properties..." );
323 }
324 else if( aDRCItem->GetErrorCode() == DRCE_PADSTACK
325 || aDRCItem->GetErrorCode() == DRCE_PADSTACK_INVALID )
326 {
327 return _( "Edit Pad Properties..." );
328 }
329 else if( aDRCItem->GetErrorCode() == DRCE_TEXT_HEIGHT
330 || aDRCItem->GetErrorCode() == DRCE_TEXT_THICKNESS
331 || aDRCItem->GetErrorCode() == DRCE_MIRRORED_TEXT_ON_FRONT_LAYER
332 || aDRCItem->GetErrorCode() == DRCE_NONMIRRORED_TEXT_ON_BACK_LAYER )
333 {
334 BOARD_ITEM* item = m_pcb->ResolveItem( aDRCItem->GetMainItemID() );
335
336 if( item && BaseType( item->Type() ) == PCB_DIMENSION_T )
337 return _( "Edit Dimension Properties..." );
338 else if( item && item->Type() == PCB_FIELD_T )
339 return _( "Edit Field Properties..." );
340 else
341 return _( "Edit Text Properties..." );
342 }
343 else if( aDRCItem->GetErrorCode() == DRCE_DANGLING_TRACK
344 || aDRCItem->GetErrorCode() == DRCE_DANGLING_VIA )
345 {
346 return frame()->GetRunMenuCommandDescription( PCB_ACTIONS::cleanupTracksAndVias );
347 }
348
349 return wxEmptyString;
350}
351
352
353void DRC_TOOL::FixDRCError( const std::shared_ptr<RC_ITEM>& aDRCItem )
354{
355 if( aDRCItem->GetErrorCode() == DRCE_LIB_FOOTPRINT_ISSUES )
356 {
358 }
359 else if( aDRCItem->GetErrorCode() == DRCE_LIB_FOOTPRINT_MISMATCH
360 || aDRCItem->GetErrorCode() == DRCE_FOOTPRINT_FILTERS )
361 {
362 bool updateMode = aDRCItem->GetErrorCode() == DRCE_LIB_FOOTPRINT_MISMATCH;
363 BOARD_ITEM* item = m_pcb->ResolveItem( aDRCItem->GetMainItemID() );
364
365 if( FOOTPRINT* footprint = dynamic_cast<FOOTPRINT*>( item ) )
366 {
367 DIALOG_EXCHANGE_FOOTPRINTS dialog( m_editFrame, footprint, updateMode, true );
368 dialog.ShowQuasiModal();
369 }
370 }
371 else if( aDRCItem->GetErrorCode() == DRCE_SCHEMATIC_PARITY
372 || aDRCItem->GetErrorCode() == DRCE_SCHEMATIC_FIELDS_PARITY
373 || aDRCItem->GetErrorCode() == DRCE_MISSING_FOOTPRINT
374 || aDRCItem->GetErrorCode() == DRCE_DUPLICATE_FOOTPRINT
375 || aDRCItem->GetErrorCode() == DRCE_EXTRA_FOOTPRINT )
376 {
378 }
379 else if( aDRCItem->GetErrorCode() == DRCE_FOOTPRINT_TYPE_MISMATCH
380 || aDRCItem->GetErrorCode() == DRCE_FOOTPRINT
381 || aDRCItem->GetErrorCode() == DRCE_PADSTACK
382 || aDRCItem->GetErrorCode() == DRCE_PADSTACK_INVALID
383 || aDRCItem->GetErrorCode() == DRCE_TEXT_HEIGHT
384 || aDRCItem->GetErrorCode() == DRCE_TEXT_THICKNESS
385 || aDRCItem->GetErrorCode() == DRCE_MIRRORED_TEXT_ON_FRONT_LAYER
386 || aDRCItem->GetErrorCode() == DRCE_NONMIRRORED_TEXT_ON_BACK_LAYER)
387
388 {
389 BOARD_ITEM* item = m_pcb->ResolveItem( aDRCItem->GetMainItemID() );
390
391 m_editFrame->OnEditItemRequest( item );
392 }
393 else if( aDRCItem->GetErrorCode() == DRCE_DANGLING_TRACK
394 || aDRCItem->GetErrorCode() == DRCE_DANGLING_VIA )
395 {
397 }
398}
399
400
402{
403 bool show_dlg_modal = true;
404
405 // the dialog needs a parent frame. if it is not specified, this is the PCB editor frame
406 // specified in DRC_TOOL class.
407 if( !aParent )
408 {
409 // if any parent is specified, the dialog is modal.
410 // if this is the default PCB editor frame, it is not modal
411 show_dlg_modal = false;
412 aParent = m_editFrame;
413 }
414
415 Activate();
417
419 {
421 updatePointers( false );
422
423 if( show_dlg_modal )
424 m_designRuleEditorDlg->ShowModal();
425 else
426 m_designRuleEditorDlg->Show( true );
427 }
428 else // The dialog is just not visible (because the user has double clicked on an error item)
429 {
430 updatePointers( false );
431 m_designRuleEditorDlg->Show( true );
432 }
433}
434
435
437{
439 return 0;
440}
441
442
444{
446 {
447 m_designRuleEditorDlg->Destroy();
448 m_designRuleEditorDlg = nullptr;
449 }
450}
451
452
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
static TOOL_ACTION updatePcbFromSchematic
Definition actions.h:264
static TOOL_ACTION excludeMarker
Definition actions.h:129
static TOOL_ACTION nextMarker
Definition actions.h:128
static TOOL_ACTION showFootprintLibTable
Definition actions.h:283
static TOOL_ACTION prevMarker
Definition actions.h:127
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:224
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:83
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
Definition drc_tool.cpp:60
void updatePointers(bool aDRCWasCancelled)
Update needed pointers from the one pointer which is known not to change.
Definition drc_tool.cpp:218
void ShowDRCDialog(wxWindow *aParent)
Opens the DRC dialog.
Definition drc_tool.cpp:75
void FixDRCError(const std::shared_ptr< RC_ITEM > &aDRCItem)
Definition drc_tool.cpp:353
int NextMarker(const TOOL_EVENT &aEvent)
Definition drc_tool.cpp:247
wxString FixDRCErrorMenuText(const std::shared_ptr< RC_ITEM > &aDRCItem)
Definition drc_tool.cpp:297
void DestroyDRCDialog()
Close and free the DRC dialog.
Definition drc_tool.cpp:126
DIALOG_DRC * m_drcDialog
Definition drc_tool.h:124
PCB_EDIT_FRAME * m_editFrame
Definition drc_tool.h:122
void DestroyDesignRuleEditorDialog()
Definition drc_tool.cpp:443
bool IsDRCDialogShown()
Check to see if the DRC_TOOL dialog is currently shown.
Definition drc_tool.cpp:117
int CrossProbe(const TOOL_EVENT &aEvent)
Definition drc_tool.cpp:264
int ExcludeMarker(const TOOL_EVENT &aEvent)
Definition drc_tool.cpp:288
void setTransitions() override
< Set up handlers for various events.
Definition drc_tool.cpp:453
BOARD * m_pcb
Definition drc_tool.h:123
int PrevMarker(const TOOL_EVENT &aEvent)
Definition drc_tool.cpp:230
bool m_drcRunning
Definition drc_tool.h:126
DIALOG_DRC_RULE_EDITOR * m_designRuleEditorDlg
Definition drc_tool.h:125
void RunTests(PROGRESS_REPORTER *aProgressReporter, bool aRefillZones, bool aReportAllTrackErrors, bool aTestFootprints)
Run the DRC tests.
Definition drc_tool.cpp:136
std::shared_ptr< DRC_ENGINE > m_drcEngine
Definition drc_tool.h:127
void ShowDesignRuleEditorDialog(wxWindow *aParent)
Definition drc_tool.cpp:401
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
static const TOOL_EVENT SelectedEvent
Definition actions.h:345
static const TOOL_EVENT PointSelectedEvent
Definition actions.h:344
Store information read from a netlist along with the flags used to update the NETLIST in the BOARD.
static TOOL_ACTION updateFootprint
static TOOL_ACTION cleanupTracksAndVias
static TOOL_ACTION runDRC
static TOOL_ACTION changeFootprint
The selection tool: currently supports:
PCB_SELECTION & GetSelection()
T * frame() const
PCB_TOOL_BASE(TOOL_ID aId, const std::string &aName)
Constructor.
const PCB_SELECTION & selection() const
FOOTPRINT * footprint() const
A progress reporter interface for use in multi-threaded environments.
virtual bool IsCancelled() const =0
virtual void AdvancePhase()=0
Use the next available virtual zone of the dialog progress bar.
T * getEditFrame() const
Return the application window object, casted to requested user type.
Definition tool_base.h:186
TOOL_MANAGER * m_toolMgr
Definition tool_base.h:220
RESET_REASON
Determine the reason of reset for a tool.
Definition tool_base.h:78
Generic, UI-independent tool event.
Definition tool_event.h:171
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
void Activate()
Run the tool.
Handle actions specific to filling copper zones.
void FillAllZones(wxWindow *aCaller, PROGRESS_REPORTER *aReporter=nullptr, bool aHeadless=false)
@ DRCE_FOOTPRINT_FILTERS
Definition drc_item.h:80
@ DRCE_PADSTACK
Definition drc_item.h:63
@ DRCE_MIRRORED_TEXT_ON_FRONT_LAYER
Definition drc_item.h:110
@ DRCE_LIB_FOOTPRINT_ISSUES
Definition drc_item.h:83
@ DRCE_SCHEMATIC_FIELDS_PARITY
Definition drc_item.h:118
@ DRCE_DANGLING_VIA
Definition drc_item.h:51
@ DRCE_PADSTACK_INVALID
Definition drc_item.h:64
@ DRCE_FOOTPRINT_TYPE_MISMATCH
Definition drc_item.h:82
@ DRCE_NONMIRRORED_TEXT_ON_BACK_LAYER
Definition drc_item.h:111
@ DRCE_DUPLICATE_FOOTPRINT
Definition drc_item.h:76
@ DRCE_DANGLING_TRACK
Definition drc_item.h:52
@ DRCE_TEXT_HEIGHT
Definition drc_item.h:101
@ DRCE_EXTRA_FOOTPRINT
Definition drc_item.h:77
@ DRCE_LIB_FOOTPRINT_MISMATCH
Definition drc_item.h:84
@ DRCE_MISSING_FOOTPRINT
Definition drc_item.h:75
@ DRCE_FOOTPRINT
Definition drc_item.h:86
@ DRCE_TEXT_THICKNESS
Definition drc_item.h:102
@ DRCE_SCHEMATIC_PARITY
Definition drc_item.h:79
#define _(s)
This file contains miscellaneous commonly used macros and functions.
#define SKIP_SET_DIRTY
Definition sch_commit.h:42
#define SKIP_UNDO
Definition sch_commit.h:40
constexpr KICAD_T BaseType(const KICAD_T aType)
Return the underlying type of the given type.
Definition typeinfo.h:254
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition typeinfo.h:90
@ PCB_MARKER_T
class PCB_MARKER, a marker used to show something
Definition typeinfo.h:99
@ PCB_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
Definition typeinfo.h:100
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695