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