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