You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

718 lines
23 KiB

8 years ago
18 years ago
18 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
18 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
  1. /**
  2. * @file dialog_drc.cpp
  3. */
  4. /*
  5. * This program source code file is part of KiCad, a free EDA CAD application.
  6. *
  7. * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
  8. * Copyright (C) 2009-2016 Dick Hollenbeck, dick@softplc.com
  9. * Copyright (C) 2004-2018 KiCad Developers, see AUTHORS.txt for contributors.
  10. *
  11. * This program is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU General Public License
  13. * as published by the Free Software Foundation; either version 2
  14. * of the License, or (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, you may find one here:
  23. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  24. * or you may search the http://www.gnu.org website for the version 2 license,
  25. * or you may write to the Free Software Foundation, Inc.,
  26. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  27. */
  28. #include <fctsys.h>
  29. #include <kiface_i.h>
  30. #include <confirm.h>
  31. #include <wildcards_and_files_ext.h>
  32. #include <bitmaps.h>
  33. #include <pgm_base.h>
  34. #include <dialog_drc.h>
  35. #include <pcb_edit_frame.h>
  36. #include <base_units.h>
  37. #include <board_design_settings.h>
  38. #include <class_draw_panel_gal.h>
  39. #include <view/view.h>
  40. #include <collectors.h>
  41. #include <tool/tool_manager.h>
  42. #include <tools/pcb_actions.h>
  43. #include <tool/tool_manager.h>
  44. #include <tools/pcb_actions.h>
  45. /* class DIALOG_DRC_CONTROL: a dialog to set DRC parameters (clearance, min cooper size)
  46. * and run DRC tests
  47. */
  48. // Keywords for read and write config
  49. #define DrcRefillZonesKey wxT( "RefillZonesBeforeDrc" )
  50. #define DrcTrackToZoneTestKey wxT( "DrcTrackToZoneTest" )
  51. #define DrcTestFootprintsKey wxT( "DrcTestFootprints" )
  52. DIALOG_DRC_CONTROL::DIALOG_DRC_CONTROL( DRC* aTester, PCB_EDIT_FRAME* aEditorFrame,
  53. wxWindow* aParent ) :
  54. DIALOG_DRC_CONTROL_BASE( aParent ),
  55. m_trackMinWidth( aEditorFrame, m_TrackMinWidthTitle, m_SetTrackMinWidthCtrl, m_TrackMinWidthUnit, true ),
  56. m_viaMinSize( aEditorFrame, m_ViaMinTitle, m_SetViaMinSizeCtrl, m_ViaMinUnit, true ),
  57. m_uviaMinSize( aEditorFrame, m_MicroViaMinTitle, m_SetMicroViakMinSizeCtrl, m_MicroViaMinUnit, true )
  58. {
  59. m_config = Kiface().KifaceSettings();
  60. m_tester = aTester;
  61. m_brdEditor = aEditorFrame;
  62. m_currentBoard = m_brdEditor->GetBoard();
  63. m_BrdSettings = m_brdEditor->GetBoard()->GetDesignSettings();
  64. wxFont messagesLabelFont = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
  65. messagesLabelFont.SetSymbolicSize( wxFONTSIZE_SMALL );
  66. m_messagesLabel->SetFont( messagesLabelFont );
  67. m_BrowseButton->SetBitmap( KiBitmap( folder_xpm ) );
  68. // We use a sdbSizer here to get the order right, which is platform-dependent
  69. m_sdbSizer1OK->SetLabel( _( "Run DRC" ) );
  70. m_sdbSizer1Cancel->SetLabel( _( "Close" ) );
  71. m_sizerButtons->Layout();
  72. m_sdbSizer1OK->SetDefault();
  73. InitValues();
  74. // Connect events
  75. m_ClearanceListBox->Connect( ID_CLEARANCE_LIST, wxEVT_LEFT_DCLICK,
  76. wxMouseEventHandler( DIALOG_DRC_CONTROL::OnLeftDClickClearance ), NULL, this );
  77. m_ClearanceListBox->Connect( ID_CLEARANCE_LIST, wxEVT_RIGHT_UP,
  78. wxMouseEventHandler( DIALOG_DRC_CONTROL::OnRightUpClearance ), NULL, this );
  79. m_UnconnectedListBox->Connect( ID_UNCONNECTED_LIST, wxEVT_LEFT_DCLICK,
  80. wxMouseEventHandler( DIALOG_DRC_CONTROL::OnLeftDClickUnconnected ), NULL, this );
  81. m_UnconnectedListBox->Connect( ID_UNCONNECTED_LIST, wxEVT_RIGHT_UP,
  82. wxMouseEventHandler( DIALOG_DRC_CONTROL::OnRightUpUnconnected ), NULL, this );
  83. m_FootprintsListBox->Connect( ID_FOOTPRINTS_LIST, wxEVT_LEFT_DCLICK,
  84. wxMouseEventHandler( DIALOG_DRC_CONTROL::OnLeftDClickFootprints ), NULL, this );
  85. m_FootprintsListBox->Connect( ID_FOOTPRINTS_LIST, wxEVT_RIGHT_UP,
  86. wxMouseEventHandler( DIALOG_DRC_CONTROL::OnRightUpFootprints ), NULL, this );
  87. // Now all widgets have the size fixed, call FinishDialogSettings
  88. FinishDialogSettings();
  89. }
  90. DIALOG_DRC_CONTROL::~DIALOG_DRC_CONTROL()
  91. {
  92. m_config->Write( DrcRefillZonesKey, m_cbRefillZones->GetValue() );
  93. m_config->Write( DrcTrackToZoneTestKey, m_cbReportTracksToZonesErrors->GetValue() );
  94. m_config->Write( DrcTestFootprintsKey, m_cbTestFootprints->GetValue() );
  95. // Disconnect events
  96. m_ClearanceListBox->Disconnect( ID_CLEARANCE_LIST, wxEVT_LEFT_DCLICK,
  97. wxMouseEventHandler( DIALOG_DRC_CONTROL::OnLeftDClickClearance ), NULL, this );
  98. m_ClearanceListBox->Disconnect( ID_CLEARANCE_LIST, wxEVT_RIGHT_UP,
  99. wxMouseEventHandler( DIALOG_DRC_CONTROL::OnRightUpClearance ), NULL, this );
  100. m_UnconnectedListBox->Disconnect( ID_UNCONNECTED_LIST, wxEVT_LEFT_DCLICK,
  101. wxMouseEventHandler( DIALOG_DRC_CONTROL::OnLeftDClickUnconnected ), NULL, this );
  102. m_UnconnectedListBox->Disconnect( ID_UNCONNECTED_LIST, wxEVT_RIGHT_UP,
  103. wxMouseEventHandler( DIALOG_DRC_CONTROL::OnRightUpUnconnected ), NULL, this );
  104. m_FootprintsListBox->Disconnect( ID_FOOTPRINTS_LIST, wxEVT_LEFT_DCLICK,
  105. wxMouseEventHandler( DIALOG_DRC_CONTROL::OnLeftDClickFootprints ), NULL, this );
  106. m_FootprintsListBox->Disconnect( ID_FOOTPRINTS_LIST, wxEVT_RIGHT_UP,
  107. wxMouseEventHandler( DIALOG_DRC_CONTROL::OnRightUpFootprints ), NULL, this );
  108. }
  109. void DIALOG_DRC_CONTROL::OnActivateDlg( wxActivateEvent& event )
  110. {
  111. if( m_currentBoard != m_brdEditor->GetBoard() )
  112. {
  113. // If m_currentBoard is not the current parent board,
  114. // (for instance because a new board was loaded),
  115. // close the dialog, because many pointers are now invalid
  116. // in lists
  117. SetReturnCode( wxID_CANCEL );
  118. Close();
  119. m_tester->DestroyDRCDialog( wxID_CANCEL );
  120. return;
  121. }
  122. // updating data which can be modified outside the dialog (DRC parameters, units ...)
  123. // because the dialog is not modal
  124. m_BrdSettings = m_brdEditor->GetBoard()->GetDesignSettings();
  125. DisplayDRCValues();
  126. }
  127. void DIALOG_DRC_CONTROL::DisplayDRCValues()
  128. {
  129. m_trackMinWidth.SetValue( m_BrdSettings.m_TrackMinWidth );
  130. m_viaMinSize.SetValue( m_BrdSettings.m_ViasMinSize );
  131. m_uviaMinSize.SetValue( m_BrdSettings.m_MicroViasMinSize );
  132. }
  133. void DIALOG_DRC_CONTROL::InitValues()
  134. {
  135. m_markersTitleTemplate = m_Notebook->GetPageText( 0 );
  136. m_unconnectedTitleTemplate = m_Notebook->GetPageText( 1 );
  137. m_footprintsTitleTemplate = m_Notebook->GetPageText( 2 );
  138. m_DeleteCurrentMarkerButton->Enable( false );
  139. DisplayDRCValues();
  140. // read options
  141. bool value;
  142. m_config->Read( DrcRefillZonesKey, &value, false );
  143. m_cbRefillZones->SetValue( value );
  144. m_config->Read( DrcTrackToZoneTestKey, &value, false );
  145. m_cbReportTracksToZonesErrors->SetValue( value );
  146. m_config->Read( DrcTestFootprintsKey, &value, false );
  147. m_cbTestFootprints->SetValue( value );
  148. Layout(); // adding the units above expanded Clearance text, now resize.
  149. SetFocus();
  150. }
  151. /* accept DRC parameters (min clearance value and min sizes
  152. */
  153. void DIALOG_DRC_CONTROL::SetDrcParmeters( )
  154. {
  155. m_BrdSettings.m_TrackMinWidth = m_trackMinWidth.GetValue();
  156. m_BrdSettings.m_ViasMinSize = m_viaMinSize.GetValue();
  157. m_BrdSettings.m_MicroViasMinSize = m_uviaMinSize.GetValue();
  158. m_brdEditor->GetBoard()->SetDesignSettings( m_BrdSettings );
  159. }
  160. void DIALOG_DRC_CONTROL::SetRptSettings( bool aEnable, const wxString& aFileName )
  161. {
  162. m_RptFilenameCtrl->SetValue( aFileName );
  163. m_CreateRptCtrl->SetValue( aEnable );
  164. }
  165. void DIALOG_DRC_CONTROL::GetRptSettings( bool* aEnable, wxString& aFileName )
  166. {
  167. *aEnable = m_CreateRptCtrl->GetValue();
  168. aFileName = m_RptFilenameCtrl->GetValue();
  169. }
  170. void DIALOG_DRC_CONTROL::OnStartdrcClick( wxCommandEvent& event )
  171. {
  172. wxString reportName, msg;
  173. bool make_report = m_CreateRptCtrl->IsChecked();
  174. if( make_report ) // Create a rpt file
  175. {
  176. reportName = m_RptFilenameCtrl->GetValue();
  177. if( reportName.IsEmpty() )
  178. {
  179. wxCommandEvent dummy;
  180. OnButtonBrowseRptFileClick( dummy );
  181. }
  182. if( !reportName.IsEmpty() )
  183. reportName = makeValidFileNameReport();
  184. }
  185. SetDrcParmeters();
  186. m_tester->m_doZonesTest = m_cbReportTracksToZonesErrors->GetValue();
  187. m_tester->m_rptFilename = reportName;
  188. m_tester->m_doCreateRptFile = make_report;
  189. m_tester->m_refillZones = m_cbRefillZones->GetValue();
  190. m_tester->m_drcInLegacyRoutingMode = false;
  191. m_tester->m_reportAllTrackErrors = m_cbReportAllTrackErrors->GetValue();
  192. m_tester->m_testFootprints = m_cbTestFootprints->GetValue();
  193. DelDRCMarkers();
  194. wxBeginBusyCursor();
  195. wxWindowDisabler disabler;
  196. // run all the tests, with no UI at this time.
  197. m_Messages->Clear();
  198. wxSafeYield(); // Allows time slice to refresh the Messages
  199. m_brdEditor->GetBoard()->m_Status_Pcb = 0; // Force full connectivity and ratsnest calculations
  200. m_tester->RunTests(m_Messages);
  201. m_Notebook->ChangeSelection( 0 ); // display the "Problems/Markers" tab
  202. // Generate the report
  203. if( !reportName.IsEmpty() )
  204. {
  205. if( writeReport( reportName ) )
  206. {
  207. msg.Printf( _( "Report file \"%s\" created" ), GetChars( reportName ) );
  208. wxMessageDialog popupWindow( this, msg, _( "Disk File Report Completed" ) );
  209. popupWindow.ShowModal();
  210. }
  211. else
  212. {
  213. msg.Printf( _( "Unable to create report file \"%s\"" ), GetChars( reportName ) );
  214. DisplayError( this, msg );
  215. }
  216. }
  217. wxEndBusyCursor();
  218. RedrawDrawPanel();
  219. }
  220. void DIALOG_DRC_CONTROL::OnDeleteAllClick( wxCommandEvent& event )
  221. {
  222. DelDRCMarkers();
  223. RedrawDrawPanel();
  224. UpdateDisplayedCounts();
  225. }
  226. void DIALOG_DRC_CONTROL::OnButtonBrowseRptFileClick( wxCommandEvent& )
  227. {
  228. wxFileName fn = m_brdEditor->GetBoard()->GetFileName();
  229. fn.SetExt( ReportFileExtension );
  230. wxString prj_path = Prj().GetProjectPath();
  231. wxFileDialog dlg( this, _( "Save DRC Report File" ), prj_path, fn.GetFullName(),
  232. ReportFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
  233. if( dlg.ShowModal() == wxID_CANCEL )
  234. return;
  235. m_CreateRptCtrl->SetValue( true );
  236. m_RptFilenameCtrl->SetValue( dlg.GetPath() );
  237. }
  238. void DIALOG_DRC_CONTROL::OnCancelClick( wxCommandEvent& event )
  239. {
  240. SetReturnCode( wxID_CANCEL );
  241. SetDrcParmeters();
  242. // The dialog can be modal or not modal.
  243. // Leave the DRC caller destroy (or not) the dialog
  244. m_tester->DestroyDRCDialog( wxID_CANCEL );
  245. }
  246. void DIALOG_DRC_CONTROL::OnReportCheckBoxClicked( wxCommandEvent& event )
  247. {
  248. if( m_CreateRptCtrl->IsChecked() )
  249. m_RptFilenameCtrl->SetFocus();
  250. }
  251. void DIALOG_DRC_CONTROL::OnReportFilenameEdited( wxCommandEvent &event )
  252. {
  253. m_CreateRptCtrl->SetValue( event.GetString().Length() );
  254. }
  255. void DIALOG_DRC_CONTROL::OnLeftDClickClearance( wxMouseEvent& event )
  256. {
  257. event.Skip();
  258. int selection = m_ClearanceListBox->GetSelection();
  259. if( selection != wxNOT_FOUND )
  260. {
  261. // Find the selected MARKER in the PCB, position cursor there.
  262. // Then close the dialog.
  263. const DRC_ITEM* item = m_ClearanceListBox->GetItem( selection );
  264. if( item )
  265. {
  266. auto pos = item->GetPointA();
  267. if( auto marker = item->GetParent() )
  268. pos = marker->GetPos();
  269. // When selecting a item, center it on GAL and just move the graphic
  270. // cursor in legacy mode gives the best result
  271. bool center = m_brdEditor->IsGalCanvasActive() ? true : false;
  272. m_brdEditor->FocusOnLocation( pos, true, center );
  273. if( !IsModal() )
  274. {
  275. // turn control over to m_brdEditor, hide this DIALOG_DRC_CONTROL window,
  276. // no destruction so we can preserve listbox cursor
  277. Show( false );
  278. // We do not want the clarify selection popup when releasing the
  279. // left button in the main window
  280. m_brdEditor->SkipNextLeftButtonReleaseEvent();
  281. }
  282. }
  283. }
  284. }
  285. void DIALOG_DRC_CONTROL::OnRightUpFootprints( wxMouseEvent& event )
  286. {
  287. // popup menu to go to either of the items listed in the DRC_ITEM.
  288. int selection = m_FootprintsListBox->GetSelection();
  289. if( selection != wxNOT_FOUND )
  290. doSelectionMenu( m_FootprintsListBox->GetItem( selection ) );
  291. }
  292. void DIALOG_DRC_CONTROL::OnRightUpUnconnected( wxMouseEvent& event )
  293. {
  294. // popup menu to go to either of the items listed in the DRC_ITEM.
  295. int selection = m_UnconnectedListBox->GetSelection();
  296. if( selection != wxNOT_FOUND )
  297. doSelectionMenu( m_UnconnectedListBox->GetItem( selection ) );
  298. }
  299. void DIALOG_DRC_CONTROL::OnRightUpClearance( wxMouseEvent& event )
  300. {
  301. // popup menu to go to either of the items listed in the DRC_ITEM.
  302. int selection = m_ClearanceListBox->GetSelection();
  303. if( selection != wxNOT_FOUND )
  304. doSelectionMenu( m_ClearanceListBox->GetItem( selection ) );
  305. }
  306. void DIALOG_DRC_CONTROL::doSelectionMenu( const DRC_ITEM* aItem )
  307. {
  308. // popup menu to go to either of the items listed in the DRC_ITEM.
  309. GENERAL_COLLECTOR items;
  310. items.Append( aItem->GetMainItem( m_brdEditor->GetBoard() ) );
  311. if( aItem->HasSecondItem() )
  312. items.Append( aItem->GetAuxiliaryItem( m_brdEditor->GetBoard() ) );
  313. WINDOW_THAWER thawer( m_brdEditor );
  314. m_brdEditor->GetToolManager()->RunAction( PCB_ACTIONS::selectionMenu, true, &items );
  315. m_brdEditor->GetCanvas()->Refresh();
  316. }
  317. void DIALOG_DRC_CONTROL::OnLeftDClickFootprints( wxMouseEvent& event )
  318. {
  319. event.Skip();
  320. int selection = m_FootprintsListBox->GetSelection();
  321. if( selection != wxNOT_FOUND )
  322. {
  323. // Find the selected DRC_ITEM in the listbox, position cursor there.
  324. // Then hide the dialog.
  325. const DRC_ITEM* item = m_FootprintsListBox->GetItem( selection );
  326. if( item )
  327. {
  328. // When selecting a item, center it on GAL and just move the graphic
  329. // cursor in legacy mode gives the best result
  330. bool center = m_brdEditor->IsGalCanvasActive() ? true : false;
  331. m_brdEditor->FocusOnLocation( item->GetPointA(), true, center );
  332. if( !IsModal() )
  333. {
  334. Show( false );
  335. // We do not want the clarify selection popup when releasing the
  336. // left button in the main window
  337. m_brdEditor->SkipNextLeftButtonReleaseEvent();
  338. }
  339. }
  340. }
  341. }
  342. void DIALOG_DRC_CONTROL::OnLeftDClickUnconnected( wxMouseEvent& event )
  343. {
  344. event.Skip();
  345. int selection = m_UnconnectedListBox->GetSelection();
  346. if( selection != wxNOT_FOUND )
  347. {
  348. // Find the selected DRC_ITEM in the listbox, position cursor there.
  349. // Then hide the dialog.
  350. const DRC_ITEM* item = m_UnconnectedListBox->GetItem( selection );
  351. if( item )
  352. {
  353. // When selecting a item, center it on GAL and just move the graphic
  354. // cursor in legacy mode gives the best result
  355. bool center = m_brdEditor->IsGalCanvasActive() ? true : false;
  356. m_brdEditor->FocusOnLocation( item->GetPointA(), true, center );
  357. if( !IsModal() )
  358. {
  359. Show( false );
  360. // We do not want the clarify selection popup when releasing the
  361. // left button in the main window
  362. m_brdEditor->SkipNextLeftButtonReleaseEvent();
  363. }
  364. }
  365. }
  366. }
  367. /* called when switching from Error list to Unconnected list
  368. * To avoid mistakes, the current marker is selection is cleared
  369. */
  370. void DIALOG_DRC_CONTROL::OnChangingMarkerList( wxNotebookEvent& event )
  371. {
  372. // Shouldn't be necessary, but is on at least OSX
  373. if( event.GetSelection() >= 0 )
  374. m_Notebook->ChangeSelection( (unsigned) event.GetSelection() );
  375. m_DeleteCurrentMarkerButton->Enable( false );
  376. m_ClearanceListBox->SetSelection( -1 );
  377. m_UnconnectedListBox->SetSelection( -1 );
  378. }
  379. void DIALOG_DRC_CONTROL::OnMarkerSelectionEvent( wxCommandEvent& event )
  380. {
  381. int selection = event.GetSelection();
  382. if( selection != wxNOT_FOUND )
  383. {
  384. // until a MARKER is selected, this button is not enabled.
  385. m_DeleteCurrentMarkerButton->Enable( true );
  386. // Find the selected DRC_ITEM in the listbox, position cursor there.
  387. const DRC_ITEM* item = m_ClearanceListBox->GetItem( selection );
  388. if( item )
  389. {
  390. auto pos = item->GetPointA();
  391. if( auto marker = item->GetParent() )
  392. pos = marker->GetPos();
  393. // When selecting a item, center it on GAL and just move the graphic
  394. // cursor in legacy mode gives the best result
  395. bool center = m_brdEditor->IsGalCanvasActive() ? true : false;
  396. m_brdEditor->FocusOnLocation( pos, false, center );
  397. RedrawDrawPanel();
  398. }
  399. }
  400. event.Skip();
  401. }
  402. void DIALOG_DRC_CONTROL::OnUnconnectedSelectionEvent( wxCommandEvent& event )
  403. {
  404. int selection = event.GetSelection();
  405. if( selection != wxNOT_FOUND )
  406. {
  407. // until a MARKER is selected, this button is not enabled.
  408. m_DeleteCurrentMarkerButton->Enable( true );
  409. // Find the selected DRC_ITEM in the listbox, position cursor there.
  410. const DRC_ITEM* item = m_UnconnectedListBox->GetItem( selection );
  411. if( item )
  412. {
  413. // When selecting a item, center it on GAL and just move the graphic
  414. // cursor in legacy mode gives the best result
  415. bool center = m_brdEditor->IsGalCanvasActive() ? true : false;
  416. m_brdEditor->FocusOnLocation( item->GetPointA(), false, center );
  417. RedrawDrawPanel();
  418. }
  419. }
  420. event.Skip();
  421. }
  422. void DIALOG_DRC_CONTROL::OnFootprintsSelectionEvent( wxCommandEvent& event )
  423. {
  424. int selection = event.GetSelection();
  425. if( selection != wxNOT_FOUND )
  426. {
  427. // until a MARKER is selected, this button is not enabled.
  428. m_DeleteCurrentMarkerButton->Enable( true );
  429. // Find the selected DRC_ITEM in the listbox, position cursor there.
  430. const DRC_ITEM* item = m_FootprintsListBox->GetItem( selection );
  431. if( item )
  432. {
  433. // When selecting a item, center it on GAL and just move the graphic
  434. // cursor in legacy mode gives the best result
  435. bool center = m_brdEditor->IsGalCanvasActive() ? true : false;
  436. m_brdEditor->FocusOnLocation( item->GetPointA(), false, center );
  437. RedrawDrawPanel();
  438. }
  439. }
  440. event.Skip();
  441. }
  442. void DIALOG_DRC_CONTROL::RedrawDrawPanel()
  443. {
  444. WINDOW_THAWER thawer( m_brdEditor );
  445. m_brdEditor->GetCanvas()->Refresh();
  446. }
  447. void DIALOG_DRC_CONTROL::DelDRCMarkers()
  448. {
  449. m_brdEditor->SetCurItem( NULL ); // clear curr item, because it could be a DRC marker
  450. // Clear current selection list to avoid selection of deleted items
  451. m_brdEditor->GetToolManager()->RunAction( PCB_ACTIONS::selectionClear, true );
  452. m_ClearanceListBox->DeleteAllItems();
  453. m_UnconnectedListBox->DeleteAllItems();
  454. m_DeleteCurrentMarkerButton->Enable( false );
  455. }
  456. const wxString DIALOG_DRC_CONTROL::makeValidFileNameReport()
  457. {
  458. wxFileName fn = m_RptFilenameCtrl->GetValue();
  459. if( !fn.HasExt() )
  460. {
  461. fn.SetExt( ReportFileExtension );
  462. m_RptFilenameCtrl->SetValue( fn.GetFullPath() );
  463. }
  464. // Ensure it is an absolute filename. if it is given relative
  465. // it will be made relative to the project
  466. if( !fn.IsAbsolute() )
  467. {
  468. wxString prj_path = Prj().GetProjectPath();
  469. fn.MakeAbsolute( prj_path );
  470. }
  471. return fn.GetFullPath();
  472. }
  473. bool DIALOG_DRC_CONTROL::writeReport( const wxString& aFullFileName )
  474. {
  475. FILE* fp = wxFopen( aFullFileName, wxT( "w" ) );
  476. if( fp == NULL )
  477. return false;
  478. int count;
  479. EDA_UNITS_T units = GetUserUnits();
  480. fprintf( fp, "** Drc report for %s **\n",
  481. TO_UTF8( m_brdEditor->GetBoard()->GetFileName() ) );
  482. wxDateTime now = wxDateTime::Now();
  483. fprintf( fp, "** Created on %s **\n", TO_UTF8( now.Format( wxT( "%F %T" ) ) ) );
  484. count = m_ClearanceListBox->GetItemCount();
  485. fprintf( fp, "\n** Found %d DRC errors **\n", count );
  486. for( int i = 0; i<count; ++i )
  487. fprintf( fp, "%s", TO_UTF8( m_ClearanceListBox->GetItem( i )->ShowReport( units ) ) );
  488. count = m_UnconnectedListBox->GetItemCount();
  489. fprintf( fp, "\n** Found %d unconnected pads **\n", count );
  490. for( int i = 0; i<count; ++i )
  491. fprintf( fp, "%s", TO_UTF8( m_UnconnectedListBox->GetItem( i )->ShowReport( units ) ) );
  492. fprintf( fp, "\n** End of Report **\n" );
  493. fclose( fp );
  494. return true;
  495. }
  496. void DIALOG_DRC_CONTROL::OnDeleteOneClick( wxCommandEvent& event )
  497. {
  498. int selectedIndex;
  499. int curTab = m_Notebook->GetSelection();
  500. if( curTab == 0 )
  501. {
  502. selectedIndex = m_ClearanceListBox->GetSelection();
  503. if( selectedIndex != wxNOT_FOUND )
  504. {
  505. m_ClearanceListBox->DeleteItem( selectedIndex );
  506. // redraw the pcb
  507. RedrawDrawPanel();
  508. }
  509. }
  510. else if( curTab == 1 )
  511. {
  512. selectedIndex = m_UnconnectedListBox->GetSelection();
  513. if( selectedIndex != wxNOT_FOUND )
  514. {
  515. m_UnconnectedListBox->DeleteItem( selectedIndex );
  516. /* these unconnected DRC_ITEMs are not currently visible on the pcb
  517. * RedrawDrawPanel();
  518. */
  519. }
  520. }
  521. UpdateDisplayedCounts();
  522. }
  523. void DIALOG_DRC_CONTROL::UpdateDisplayedCounts()
  524. {
  525. wxString msg;
  526. if( m_tester->m_drcRun )
  527. {
  528. msg.sprintf( m_markersTitleTemplate, (int) m_ClearanceListBox->GetItemCount() );
  529. m_Notebook->SetPageText( 0, msg );
  530. msg.sprintf( m_unconnectedTitleTemplate, (int) m_UnconnectedListBox->GetItemCount() );
  531. m_Notebook->SetPageText( 1, msg );
  532. if( m_tester->m_footprintsTested )
  533. msg.sprintf( m_footprintsTitleTemplate, (int) m_FootprintsListBox->GetItemCount() );
  534. else
  535. {
  536. msg = m_footprintsTitleTemplate;
  537. msg.Replace( wxT( "%d" ), _( "not run" ) );
  538. }
  539. m_Notebook->SetPageText( 2, msg );
  540. }
  541. else
  542. {
  543. msg = m_markersTitleTemplate;
  544. msg.Replace( wxT( "(%d)" ), wxEmptyString );
  545. m_Notebook->SetPageText( 0, msg );
  546. msg = m_unconnectedTitleTemplate;
  547. msg.Replace( wxT( "(%d)" ), wxEmptyString );
  548. m_Notebook->SetPageText( 1, msg );
  549. msg = m_footprintsTitleTemplate;
  550. msg.Replace( wxT( "(%d)" ), wxEmptyString );
  551. m_Notebook->SetPageText( 2, msg );
  552. }
  553. }