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