From 66f6168163d6b26c1dc638c4ee438e4a46528cd9 Mon Sep 17 00:00:00 2001 From: Wayne Stambaugh Date: Mon, 13 Mar 2023 12:03:48 -0400 Subject: [PATCH] Fix mode-less dialog issues. Don't assume the dialog is mode-less and call Destroy() from within a dialog method. This will most assuredly crash if the dialog is shown modally or quasi-modally. Don't leak memory for mode-less dialogs created on the stack. Make sure when the parent frame window is closed that all mode-less dialog memory is cleaned up. Dialogs are not child windows like controls and toolbars so their memory does not automatically get cleaned up when the parent window is destroyed. Do not directly access frame parent window's pointer in dialog destructors. Apparently the tear down order when destroying mode-less dialogs is not guaranteed so the parent window may get deleted before the dialog causing a crash when accessing the parent window pointer from the dialog dtor. Do not close mode-less dialogs in the parent frame's destructor. This doesn't guarantee that the dialog(s) will be destroyed before the parent but it may reduce some careless mode-less dialog event handling in the future. --- 3d-viewer/dialogs/panel_preview_3d_model.cpp | 8 +- common/dialogs/dialog_book_reporter.cpp | 41 ++-- common/dialogs/dialog_book_reporter_base.cpp | 4 +- common/dialogs/dialog_book_reporter_base.fbp | 2 +- common/dialogs/dialog_book_reporter_base.h | 2 +- common/dialogs/panel_setup_netclasses.cpp | 11 +- common/eda_base_frame.cpp | 22 +- common/eda_draw_frame.cpp | 2 +- common/widgets/unit_binder.cpp | 20 +- eeschema/dialogs/dialog_erc.cpp | 32 ++- eeschema/dialogs/dialog_erc.h | 6 + .../dialogs/dialog_lib_edit_pin_table.cpp | 4 +- eeschema/fields_grid_table.cpp | 4 +- eeschema/sch_edit_frame.cpp | 111 +++++++--- eeschema/sch_edit_frame.h | 25 ++- eeschema/tools/ee_inspection_tool.cpp | 149 +++++++------ eeschema/tools/ee_inspection_tool.h | 2 - include/dialogs/dialog_book_reporter.h | 12 +- include/eda_base_frame.h | 4 +- include/pcb_base_frame.h | 10 +- .../dialog_global_edit_tracks_and_vias.cpp | 8 +- pcbnew/dialogs/dialog_net_inspector.cpp | 205 ++++++++++-------- pcbnew/dialogs/dialog_net_inspector.h | 16 +- pcbnew/dialogs/dialog_net_inspector_base.cpp | 8 +- pcbnew/dialogs/dialog_net_inspector_base.fbp | 9 +- pcbnew/dialogs/dialog_net_inspector_base.h | 1 + .../dialogs/dialog_track_via_properties.cpp | 6 +- .../dialogs/panel_setup_text_and_graphics.cpp | 12 +- .../dialogs/panel_setup_tracks_and_vias.cpp | 6 +- pcbnew/fp_text_grid_table.cpp | 4 +- pcbnew/pcb_base_frame.cpp | 41 +++- pcbnew/pcb_edit_frame.cpp | 185 ++++++++++++++-- pcbnew/pcb_edit_frame.h | 37 +++- pcbnew/tools/board_inspection_tool.cpp | 106 ++++----- pcbnew/widgets/pcb_search_pane.cpp | 16 +- 35 files changed, 747 insertions(+), 384 deletions(-) diff --git a/3d-viewer/dialogs/panel_preview_3d_model.cpp b/3d-viewer/dialogs/panel_preview_3d_model.cpp index 82055706a9..5bfec8d492 100644 --- a/3d-viewer/dialogs/panel_preview_3d_model.cpp +++ b/3d-viewer/dialogs/panel_preview_3d_model.cpp @@ -4,7 +4,7 @@ * Copyright (C) 2016 Mario Luzeiro * Copyright (C) 2015 Cirilo Bernardo * Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 2015-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2015-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -144,7 +144,8 @@ PANEL_PREVIEW_3D_MODEL::PANEL_PREVIEW_3D_MODEL( wxWindow* aParent, PCB_BASE_FRAM this ); } - aFrame->Connect( UNITS_CHANGED, wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL::onUnitsChanged ), + aFrame->Connect( EDA_EVT_UNITS_CHANGED, + wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL::onUnitsChanged ), nullptr, this ); #ifdef __WXOSX__ @@ -451,7 +452,8 @@ void PANEL_PREVIEW_3D_MODEL::doIncrementOffset( wxSpinEvent& event, double aSign double step_mm = OFFSET_INCREMENT_MM; double curr_value_mm = - EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, m_userUnits, textCtrl->GetValue() ) + EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, m_userUnits, + textCtrl->GetValue() ) / pcbIUScale.IU_PER_MM; if( m_userUnits == EDA_UNITS::MILS || m_userUnits == EDA_UNITS::INCHES ) diff --git a/common/dialogs/dialog_book_reporter.cpp b/common/dialogs/dialog_book_reporter.cpp index db65c6b441..82c5322bfa 100644 --- a/common/dialogs/dialog_book_reporter.cpp +++ b/common/dialogs/dialog_book_reporter.cpp @@ -26,22 +26,17 @@ #include -DIALOG_BOOK_REPORTER::DIALOG_BOOK_REPORTER( KIWAY_PLAYER* aParent, const wxString& aDialogName, - const wxString& aDialogTitle ) : - DIALOG_BOOK_REPORTER_BASE( aParent ), - m_frame( aParent ) +wxDEFINE_EVENT( EDA_EVT_CLOSE_DIALOG_BOOK_REPORTER, wxCommandEvent ); + + +DIALOG_BOOK_REPORTER::DIALOG_BOOK_REPORTER( KIWAY_PLAYER* aParent, const wxString& aName, + const wxString& aTitle ) : + DIALOG_BOOK_REPORTER_BASE( aParent, wxID_ANY, aTitle ), + m_frame( aParent ) { - SetName( aDialogName ); - SetTitle( aDialogTitle ); - - aParent->Bind( wxEVT_CLOSE_WINDOW, - [this]( wxCloseEvent& aEvent ) - { - Close(); - aEvent.Skip(); - } ); - + SetName( aName ); SetupStandardButtons(); + finishDialogSettings(); } @@ -96,3 +91,21 @@ int DIALOG_BOOK_REPORTER::GetPageCount() const return m_notebook->GetPageCount(); } + +void DIALOG_BOOK_REPORTER::OnClose( wxCloseEvent& aEvent ) +{ + // Dialog is mode-less so let the parent know that it needs to be destroyed. + if( !IsModal() && !IsQuasiModal() ) + { + wxCommandEvent* evt = new wxCommandEvent( EDA_EVT_CLOSE_DIALOG_BOOK_REPORTER, wxID_ANY ); + + evt->SetEventObject( this ); + evt->SetString( GetName() ); + wxWindow* parent = GetParent(); + + if( parent ) + wxQueueEvent( parent, evt ); + } + + aEvent.Skip(); +} diff --git a/common/dialogs/dialog_book_reporter_base.cpp b/common/dialogs/dialog_book_reporter_base.cpp index e3dcaa58ed..61145f52b8 100644 --- a/common/dialogs/dialog_book_reporter_base.cpp +++ b/common/dialogs/dialog_book_reporter_base.cpp @@ -37,12 +37,12 @@ DIALOG_BOOK_REPORTER_BASE::DIALOG_BOOK_REPORTER_BASE( wxWindow* parent, wxWindow this->Centre( wxBOTH ); // Connect Events - m_sdbSizerOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_BOOK_REPORTER_BASE::OnOK ), NULL, this ); + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_BOOK_REPORTER_BASE::OnClose ) ); } DIALOG_BOOK_REPORTER_BASE::~DIALOG_BOOK_REPORTER_BASE() { // Disconnect Events - m_sdbSizerOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_BOOK_REPORTER_BASE::OnOK ), NULL, this ); + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_BOOK_REPORTER_BASE::OnClose ) ); } diff --git a/common/dialogs/dialog_book_reporter_base.fbp b/common/dialogs/dialog_book_reporter_base.fbp index 3ba1437cbe..0520c8bb7f 100644 --- a/common/dialogs/dialog_book_reporter_base.fbp +++ b/common/dialogs/dialog_book_reporter_base.fbp @@ -56,6 +56,7 @@ + OnClose bMainSizer @@ -136,7 +137,6 @@ m_sdbSizer protected - OnOK diff --git a/common/dialogs/dialog_book_reporter_base.h b/common/dialogs/dialog_book_reporter_base.h index 53dbd31d76..36d38fbc6a 100644 --- a/common/dialogs/dialog_book_reporter_base.h +++ b/common/dialogs/dialog_book_reporter_base.h @@ -37,7 +37,7 @@ class DIALOG_BOOK_REPORTER_BASE : public DIALOG_SHIM wxButton* m_sdbSizerOK; // Virtual event handlers, override them in your derived class - virtual void OnOK( wxCommandEvent& event ) { event.Skip(); } + virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } public: diff --git a/common/dialogs/panel_setup_netclasses.cpp b/common/dialogs/panel_setup_netclasses.cpp index d82ab7640e..d58e50d494 100644 --- a/common/dialogs/panel_setup_netclasses.cpp +++ b/common/dialogs/panel_setup_netclasses.cpp @@ -218,7 +218,7 @@ PANEL_SETUP_NETCLASSES::PANEL_SETUP_NETCLASSES( PAGED_DIALOG* aParent, EDA_DRAW_ &PANEL_SETUP_NETCLASSES::OnNetclassGridMouseEvent, this ); - m_frame->Bind( UNITS_CHANGED, &PANEL_SETUP_NETCLASSES::onUnitsChanged, this ); + m_frame->Bind( EDA_EVT_UNITS_CHANGED, &PANEL_SETUP_NETCLASSES::onUnitsChanged, this ); m_netclassGrid->EndBatch(); m_assignmentGrid->EndBatch(); @@ -243,7 +243,7 @@ PANEL_SETUP_NETCLASSES::~PANEL_SETUP_NETCLASSES() wxGridEventHandler( PANEL_SETUP_NETCLASSES::OnNetclassGridCellChanging ), nullptr, this ); - m_frame->Unbind( UNITS_CHANGED, &PANEL_SETUP_NETCLASSES::onUnitsChanged, this ); + m_frame->Unbind( EDA_EVT_UNITS_CHANGED, &PANEL_SETUP_NETCLASSES::onUnitsChanged, this ); } @@ -287,8 +287,8 @@ bool PANEL_SETUP_NETCLASSES::TransferDataToWindow() if( lineStyleIdx >= (int) g_lineStyleNames.size() ) lineStyleIdx = 0; - m_netclassGrid->SetCellValue( aRow, GRID_LINESTYLE, g_lineStyleNames[ lineStyleIdx ] ); - + m_netclassGrid->SetCellValue( aRow, GRID_LINESTYLE, + g_lineStyleNames[ lineStyleIdx ] ); m_netclassGrid->SetUnitValue( aRow, GRID_CLEARANCE, nc->GetClearance() ); m_netclassGrid->SetUnitValue( aRow, GRID_TRACKSIZE, nc->GetTrackWidth() ); m_netclassGrid->SetUnitValue( aRow, GRID_VIASIZE, nc->GetViaDiameter() ); @@ -331,9 +331,6 @@ bool PANEL_SETUP_NETCLASSES::TransferDataToWindow() } -/* - * Populates drop-downs with the list of net classes - */ void PANEL_SETUP_NETCLASSES::rebuildNetclassDropdowns() { m_assignmentGrid->CommitPendingChanges( true ); diff --git a/common/eda_base_frame.cpp b/common/eda_base_frame.cpp index 1fd1d4c9bf..0602a8947a 100644 --- a/common/eda_base_frame.cpp +++ b/common/eda_base_frame.cpp @@ -3,7 +3,7 @@ * * Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2013 Wayne Stambaugh - * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -67,7 +67,7 @@ #include #include -wxDEFINE_EVENT( UNITS_CHANGED, wxCommandEvent ); +wxDEFINE_EVENT( EDA_EVT_UNITS_CHANGED, wxCommandEvent ); // Minimum window size @@ -664,7 +664,8 @@ void EDA_BASE_FRAME::ensureWindowIsOnScreen() wxSize size = GetWindowSize(); wxLogTrace( traceDisplayLocation, - wxS( "ensureWindowIsOnScreen: clientArea (%d, %d) w %d h %d" ), clientSize.x, clientSize.y, + wxS( "ensureWindowIsOnScreen: clientArea (%d, %d) w %d h %d" ), + clientSize.x, clientSize.y, clientSize.width, clientSize.height ); if( pos.y < clientSize.y ) @@ -678,8 +679,8 @@ void EDA_BASE_FRAME::ensureWindowIsOnScreen() if( pos.x < clientSize.x ) { wxLogTrace( traceDisplayLocation, - wxS( "ensureWindowIsOnScreen: x pos %d is off the client rect, setting to %d" ), pos.x, - clientSize.x ); + wxS( "ensureWindowIsOnScreen: x pos %d is off the client rect, setting to %d" ), + pos.x, clientSize.x ); pos.x = clientSize.x; } @@ -687,8 +688,8 @@ void EDA_BASE_FRAME::ensureWindowIsOnScreen() { int newWidth = clientSize.width - ( pos.x - clientSize.x ); wxLogTrace( traceDisplayLocation, - wxS( "ensureWindowIsOnScreen: effective width %d above available %d, setting to %d" ), - pos.x + size.x, clientSize.width, newWidth ); + wxS( "ensureWindowIsOnScreen: effective width %d above available %d, setting " + "to %d" ), pos.x + size.x, clientSize.width, newWidth ); size.x = newWidth; } @@ -696,8 +697,8 @@ void EDA_BASE_FRAME::ensureWindowIsOnScreen() { int newHeight = clientSize.height - ( pos.y - clientSize.y ); wxLogTrace( traceDisplayLocation, - wxS( "ensureWindowIsOnScreen: effective height %d above available %d, setting to %d" ), - pos.y + size.y, clientSize.height, newHeight ); + wxS( "ensureWindowIsOnScreen: effective height %d above available %d, setting " + "to %d" ), pos.y + size.y, clientSize.height, newHeight ); size.y = newHeight; } @@ -1354,7 +1355,8 @@ void EDA_BASE_FRAME::ChangeUserUnits( EDA_UNITS aUnits ) SetUserUnits( aUnits ); unitsChangeRefresh(); - wxCommandEvent e( UNITS_CHANGED ); + wxCommandEvent e( EDA_EVT_UNITS_CHANGED ); + e.SetInt( static_cast( aUnits ) ); e.SetClientData( this ); ProcessEventLocally( e ); } diff --git a/common/eda_draw_frame.cpp b/common/eda_draw_frame.cpp index 9912e5f048..67499d6cf7 100644 --- a/common/eda_draw_frame.cpp +++ b/common/eda_draw_frame.cpp @@ -284,7 +284,7 @@ void EDA_DRAW_FRAME::ToggleUserUnits() : EDA_UNITS::INCHES ); unitsChangeRefresh(); - wxCommandEvent e( UNITS_CHANGED ); + wxCommandEvent e( EDA_EVT_UNITS_CHANGED ); ProcessEventLocally( e ); } } diff --git a/common/widgets/unit_binder.cpp b/common/widgets/unit_binder.cpp index 176ad6e90e..e0808c2017 100644 --- a/common/widgets/unit_binder.cpp +++ b/common/widgets/unit_binder.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2014-2015 CERN - * Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors. * Author: Maciej Suminski * * This program is free software; you can redistribute it and/or @@ -101,7 +101,8 @@ UNIT_BINDER::UNIT_BINDER( UNITS_PROVIDER* aUnitsProvider, wxWindow* aEventSource if( m_eventSource ) { - m_eventSource->Connect( UNITS_CHANGED, wxCommandEventHandler( UNIT_BINDER::onUnitsChanged ), + m_eventSource->Connect( EDA_EVT_UNITS_CHANGED, + wxCommandEventHandler( UNIT_BINDER::onUnitsChanged ), nullptr, this ); } } @@ -117,7 +118,8 @@ UNIT_BINDER::~UNIT_BINDER() if( m_eventSource ) { - m_eventSource->Disconnect( UNITS_CHANGED, wxCommandEventHandler( UNIT_BINDER::onUnitsChanged ), + m_eventSource->Disconnect( EDA_EVT_UNITS_CHANGED, + wxCommandEventHandler( UNIT_BINDER::onUnitsChanged ), nullptr, this ); } @@ -126,9 +128,9 @@ UNIT_BINDER::~UNIT_BINDER() m_valueCtrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( UNIT_BINDER::onSetFocus ), nullptr, this ); m_valueCtrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( UNIT_BINDER::onKillFocus ), - nullptr, this ); + nullptr, this ); m_valueCtrl->Disconnect( wxEVT_LEFT_UP, wxMouseEventHandler( UNIT_BINDER::onClick ), - nullptr, this ); + nullptr, this ); } } @@ -318,7 +320,8 @@ bool UNIT_BINDER::Validate( double aMin, double aMax, EDA_UNITS aUnits ) m_errorMessage = wxString::Format( _( "%s must be at least %s." ), valueDescriptionFromLabel( m_label ), EDA_UNIT_UTILS::UI::StringFromValue( *m_iuScale, m_units, - val_min_iu, true ) ); + val_min_iu, + true ) ); textEntry->SelectAll(); @@ -334,7 +337,8 @@ bool UNIT_BINDER::Validate( double aMin, double aMax, EDA_UNITS aUnits ) m_errorMessage = wxString::Format( _( "%s must be less than %s." ), valueDescriptionFromLabel( m_label ), EDA_UNIT_UTILS::UI::StringFromValue( *m_iuScale, m_units, - val_max_iu, true ) ); + val_max_iu, + true ) ); textEntry->SelectAll(); @@ -395,7 +399,7 @@ void UNIT_BINDER::SetValue( const wxString& aValue ) value += EDA_UNIT_UTILS::GetLabel( m_units, m_dataType ); } - + if( textEntry ) textEntry->SetValue( value ); else if( staticText ) diff --git a/eeschema/dialogs/dialog_erc.cpp b/eeschema/dialogs/dialog_erc.cpp index 7a24b1e966..c8c0f0a532 100644 --- a/eeschema/dialogs/dialog_erc.cpp +++ b/eeschema/dialogs/dialog_erc.cpp @@ -49,6 +49,10 @@ #include #include + +wxDEFINE_EVENT( EDA_EVT_CLOSE_ERC_DIALOG, wxCommandEvent ); + + // wxWidgets spends *far* too long calcuating column widths (most of it, believe it or // not, in repeatedly creating/destroying a wxDC to do the measurement in). // Use default column widths instead. @@ -177,8 +181,6 @@ void DIALOG_ERC::UpdateAnnotationWarning() } -// PROGRESS_REPORTER calls - bool DIALOG_ERC::updateUI() { // If ERC checks ever get slow enough we'll want a progress indicator... @@ -285,8 +287,6 @@ void DIALOG_ERC::OnDeleteOneClick( wxCommandEvent& aEvent ) } -/* Delete the old ERC markers, over the whole hierarchy - */ void DIALOG_ERC::OnDeleteAllClick( wxCommandEvent& event ) { bool includeExclusions = false; @@ -318,7 +318,6 @@ void DIALOG_ERC::OnDeleteAllClick( wxCommandEvent& event ) } -// This is a modeless dialog so we have to handle these ourselves. void DIALOG_ERC::OnCancelClick( wxCommandEvent& aEvent ) { if( m_running ) @@ -329,15 +328,26 @@ void DIALOG_ERC::OnCancelClick( wxCommandEvent& aEvent ) m_parent->FocusOnItem( nullptr ); - Close(); + aEvent.Skip(); } -void DIALOG_ERC::OnCloseErcDialog( wxCloseEvent& event ) +void DIALOG_ERC::OnCloseErcDialog( wxCloseEvent& aEvent ) { m_parent->FocusOnItem( nullptr ); - m_parent->GetToolManager()->GetTool()->DestroyERCDialog(); + // Dialog is mode-less so let the parent know that it needs to be destroyed. + if( !IsModal() && !IsQuasiModal() ) + { + wxCommandEvent* evt = new wxCommandEvent( EDA_EVT_CLOSE_ERC_DIALOG, wxID_ANY ); + + wxWindow* parent = GetParent(); + + if( parent ) + wxQueueEvent( parent, evt ); + } + + aEvent.Skip(); } @@ -511,8 +521,8 @@ void DIALOG_ERC::testErc() // Test pins on each net against the pin connection table if( settings.IsTestEnabled( ERCE_PIN_TO_PIN_ERROR ) - || settings.IsTestEnabled( ERCE_POWERPIN_NOT_DRIVEN ) - || settings.IsTestEnabled( ERCE_PIN_NOT_DRIVEN ) ) + || settings.IsTestEnabled( ERCE_POWERPIN_NOT_DRIVEN ) + || settings.IsTestEnabled( ERCE_PIN_NOT_DRIVEN ) ) { tester.TestPinToPin(); } @@ -678,7 +688,7 @@ void DIALOG_ERC::OnERCItemRClick( wxDataViewEvent& aEvent ) menu.AppendSeparator(); if( rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_WARNING - || rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_ERROR ) + || rcItem->GetErrorCode() == ERCE_PIN_TO_PIN_ERROR ) { // Pin to pin severities edited through pin conflict map } diff --git a/eeschema/dialogs/dialog_erc.h b/eeschema/dialogs/dialog_erc.h index 0482f73300..a0c56eb143 100644 --- a/eeschema/dialogs/dialog_erc.h +++ b/eeschema/dialogs/dialog_erc.h @@ -34,6 +34,12 @@ #include +/** + * Event sent to parent when dialog is mode-less. + */ +wxDECLARE_EVENT( EDA_EVT_CLOSE_ERC_DIALOG, wxCommandEvent ); + + #define DIALOG_ERC_WINDOW_NAME "DialogErcWindowName" diff --git a/eeschema/dialogs/dialog_lib_edit_pin_table.cpp b/eeschema/dialogs/dialog_lib_edit_pin_table.cpp index 1f262fa878..df89f772c5 100644 --- a/eeschema/dialogs/dialog_lib_edit_pin_table.cpp +++ b/eeschema/dialogs/dialog_lib_edit_pin_table.cpp @@ -91,12 +91,12 @@ public: { m_eval = std::make_unique( m_frame->GetUserUnits() ); - m_frame->Bind( UNITS_CHANGED, &PIN_TABLE_DATA_MODEL::onUnitsChanged, this ); + m_frame->Bind( EDA_EVT_UNITS_CHANGED, &PIN_TABLE_DATA_MODEL::onUnitsChanged, this ); } ~PIN_TABLE_DATA_MODEL() { - m_frame->Unbind( UNITS_CHANGED, &PIN_TABLE_DATA_MODEL::onUnitsChanged, this ); + m_frame->Unbind( EDA_EVT_UNITS_CHANGED, &PIN_TABLE_DATA_MODEL::onUnitsChanged, this ); } void onUnitsChanged( wxCommandEvent& aEvent ) diff --git a/eeschema/fields_grid_table.cpp b/eeschema/fields_grid_table.cpp index 5e67968115..5376f2a3dc 100644 --- a/eeschema/fields_grid_table.cpp +++ b/eeschema/fields_grid_table.cpp @@ -293,7 +293,7 @@ void FIELDS_GRID_TABLE::initGrid( WX_GRID* aGrid ) m_eval = std::make_unique( m_frame->GetUserUnits() ); - m_frame->Bind( UNITS_CHANGED, &FIELDS_GRID_TABLE::onUnitsChanged, this ); + m_frame->Bind( EDA_EVT_UNITS_CHANGED, &FIELDS_GRID_TABLE::onUnitsChanged, this ); } @@ -316,7 +316,7 @@ FIELDS_GRID_TABLE::~FIELDS_GRID_TABLE() m_fontAttr->DecRef(); m_colorAttr->DecRef(); - m_frame->Unbind( UNITS_CHANGED, &FIELDS_GRID_TABLE::onUnitsChanged, this ); + m_frame->Unbind( EDA_EVT_UNITS_CHANGED, &FIELDS_GRID_TABLE::onUnitsChanged, this ); } diff --git a/eeschema/sch_edit_frame.cpp b/eeschema/sch_edit_frame.cpp index 85356fbcbe..386621c04b 100644 --- a/eeschema/sch_edit_frame.cpp +++ b/eeschema/sch_edit_frame.cpp @@ -27,7 +27,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -90,6 +92,9 @@ #include +#define DIFF_SYMBOLS_DIALOG_NAME wxT( "DiffSymbolsDialog" ) + + BEGIN_EVENT_TABLE( SCH_EDIT_FRAME, SCH_BASE_FRAME ) EVT_SOCKET( ID_EDA_SOCKET_EVENT_SERV, EDA_DRAW_FRAME::OnSockRequestServer ) EVT_SOCKET( ID_EDA_SOCKET_EVENT, EDA_DRAW_FRAME::OnSockRequest ) @@ -115,7 +120,9 @@ END_EVENT_TABLE() SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : SCH_BASE_FRAME( aKiway, aParent, FRAME_SCH, wxT( "Eeschema" ), wxDefaultPosition, wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE, SCH_EDIT_FRAME_NAME ), - m_highlightedConn( nullptr ) + m_highlightedConn( nullptr ), + m_ercDialog( nullptr ), + m_diffSymbolDialog( nullptr ) { m_maximizeByDefault = true; m_schematic = new SCHEMATIC( nullptr ); @@ -286,6 +293,9 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : // top-left corner of the canvas wxPoint canvas_pos = GetCanvas()->GetScreenPosition(); hierarchy_pane.FloatingPosition( canvas_pos.x + 10, canvas_pos.y + 10 ); + + Bind( EDA_EVT_CLOSE_DIALOG_BOOK_REPORTER, &SCH_EDIT_FRAME::onCloseSymbolDiffDialog, this ); + Bind( EDA_EVT_CLOSE_ERC_DIALOG, &SCH_EDIT_FRAME::onCloseErcDialog, this ); } @@ -294,23 +304,10 @@ SCH_EDIT_FRAME::~SCH_EDIT_FRAME() m_hierarchy->Disconnect( wxEVT_SIZE, wxSizeEventHandler( SCH_EDIT_FRAME::OnResizeHierarchyNavigator ), NULL, this ); + // Ensure m_canvasType is up to date, to save it in config m_canvasType = GetCanvas()->GetBackend(); - // Close modeless dialogs - wxWindow* open_dlg = wxWindow::FindWindowByName( DIALOG_ERC_WINDOW_NAME ); - - if( open_dlg ) - open_dlg->Close( true ); - - // Shutdown all running tools - if( m_toolManager ) - { - m_toolManager->ShutdownAllTools(); - delete m_toolManager; - m_toolManager = nullptr; - } - SetScreen( nullptr ); delete m_schematic; @@ -439,9 +436,12 @@ void SCH_EDIT_FRAME::setupUIConditions() mgr->SetConditions( ACTIONS::inchesUnits, CHECK( cond.Units( EDA_UNITS::INCHES ) ) ); mgr->SetConditions( ACTIONS::milsUnits, CHECK( cond.Units( EDA_UNITS::MILS ) ) ); - mgr->SetConditions( EE_ACTIONS::lineModeFree, CHECK( cond.LineMode( LINE_MODE::LINE_MODE_FREE ) ) ); - mgr->SetConditions( EE_ACTIONS::lineMode90, CHECK( cond.LineMode( LINE_MODE::LINE_MODE_90 ) ) ); - mgr->SetConditions( EE_ACTIONS::lineMode45, CHECK( cond.LineMode( LINE_MODE::LINE_MODE_45 ) ) ); + mgr->SetConditions( EE_ACTIONS::lineModeFree, + CHECK( cond.LineMode( LINE_MODE::LINE_MODE_FREE ) ) ); + mgr->SetConditions( EE_ACTIONS::lineMode90, + CHECK( cond.LineMode( LINE_MODE::LINE_MODE_90 ) ) ); + mgr->SetConditions( EE_ACTIONS::lineMode45, + CHECK( cond.LineMode( LINE_MODE::LINE_MODE_45 ) ) ); mgr->SetConditions( ACTIONS::cut, ENABLE( hasElements ) ); mgr->SetConditions( ACTIONS::copy, ENABLE( hasElements ) ); @@ -822,13 +822,6 @@ bool SCH_EDIT_FRAME::canCloseWindow( wxCloseEvent& aEvent ) } } - // Close modeless dialogs. They're trouble when they get destroyed after the frame and/or - // board. - wxWindow* open_dlg = wxWindow::FindWindowByName( DIALOG_ERC_WINDOW_NAME ); - - if( open_dlg ) - open_dlg->Close( true ); - return true; } @@ -841,6 +834,15 @@ void SCH_EDIT_FRAME::doCloseWindow() if( m_toolManager ) m_toolManager->ShutdownAllTools(); + // Close modeless dialogs. They're trouble when they get destroyed after the frame. + Unbind( EDA_EVT_CLOSE_DIALOG_BOOK_REPORTER, &SCH_EDIT_FRAME::onCloseSymbolDiffDialog, this ); + Unbind( EDA_EVT_CLOSE_ERC_DIALOG, &SCH_EDIT_FRAME::onCloseErcDialog, this ); + + wxWindow* open_dlg = wxWindow::FindWindowByName( DIALOG_ERC_WINDOW_NAME ); + + if( open_dlg ) + open_dlg->Destroy(); + // Close the find dialog and preserve its setting if it is displayed. if( m_findReplaceDialog ) { @@ -851,6 +853,26 @@ void SCH_EDIT_FRAME::doCloseWindow() m_findReplaceDialog = nullptr; } + if( m_diffSymbolDialog ) + { + m_diffSymbolDialog->Destroy(); + m_diffSymbolDialog = nullptr; + } + + if( m_ercDialog ) + { + m_ercDialog->Destroy(); + m_ercDialog = nullptr; + } + + // Shutdown all running tools + if( m_toolManager ) + { + m_toolManager->ShutdownAllTools(); + delete m_toolManager; + m_toolManager = nullptr; + } + wxAuiPaneInfo& hierarchy_pane = m_auimgr.GetPane( SchematicHierarchyPaneName() ); if( hierarchy_pane.IsShown() && hierarchy_pane.IsFloating() ) @@ -2075,3 +2097,42 @@ void SCH_EDIT_FRAME::DisplayCurrentSheet() m_hierarchy->UpdateHierarchySelection(); } + + +DIALOG_BOOK_REPORTER* SCH_EDIT_FRAME::GetSymbolDiffDialog() +{ + if( !m_diffSymbolDialog ) + m_diffSymbolDialog = new DIALOG_BOOK_REPORTER( this, DIFF_SYMBOLS_DIALOG_NAME, + _( "Diff Symbol with Library" ) ); + + return m_diffSymbolDialog; +} + + +void SCH_EDIT_FRAME::onCloseSymbolDiffDialog( wxCommandEvent& aEvent ) +{ + if( m_diffSymbolDialog && aEvent.GetString() == DIFF_SYMBOLS_DIALOG_NAME ) + { + m_diffSymbolDialog->Destroy(); + m_diffSymbolDialog = nullptr; + } +} + + +DIALOG_ERC* SCH_EDIT_FRAME::GetErcDialog() +{ + if( !m_ercDialog ) + m_ercDialog = new DIALOG_ERC( this ); + + return m_ercDialog; +} + + +void SCH_EDIT_FRAME::onCloseErcDialog( wxCommandEvent& aEvent ) +{ + if( m_ercDialog ) + { + m_ercDialog->Destroy(); + m_ercDialog = nullptr; + } +} diff --git a/eeschema/sch_edit_frame.h b/eeschema/sch_edit_frame.h index 6c3878bb5f..dc3ad0b780 100644 --- a/eeschema/sch_edit_frame.h +++ b/eeschema/sch_edit_frame.h @@ -3,7 +3,7 @@ * * Copyright (C) 2015 Jean-Pierre Charras, jp.charras wanadoo.fr * Copyright (C) 2008 Wayne Stambaugh - * Copyright (C) 2004-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2004-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -54,6 +54,8 @@ class SCH_SYMBOL; class SCH_FIELD; class SCH_JUNCTION; class SCHEMATIC; +class DIALOG_BOOK_REPORTER; +class DIALOG_ERC; class DIALOG_SCH_FIND; class wxFindReplaceData; class RESCUER; @@ -271,16 +273,18 @@ public: void TestDanglingEnds(); /** - * Sends items to Pcbnew for selection + * Send items to board editor for selection. + * + * This is used for when the eeschema user is using the cross-probe tool. * * @param aItems are the items to select - * @param aForce select the element in pcbnew whether or not the user has the select option chosen - * This is used for when the eeschema user is using the cross-probe tool + * @param aForce select the element in pcbnew whether or not the user has the select option + * chosen */ void SendSelectItemsToPcb( const std::vector& aItems, bool aForce ); /** - * Sends a net name to Pcbnew for highlighting + * Send a net name to Pcbnew for highlighting. * * @param aNetName is the name of a net, or empty string to clear highlight */ @@ -814,6 +818,10 @@ public: */ void ToggleSchematicHierarchy(); + DIALOG_BOOK_REPORTER* GetSymbolDiffDialog(); + + DIALOG_ERC* GetErcDialog(); + /** * @return the name of the wxAuiPaneInfo managing the Hierarchy Navigator panel */ @@ -843,6 +851,10 @@ protected: void saveProjectSettings() override; + void onCloseSymbolDiffDialog( wxCommandEvent& aEvent ); + + void onCloseErcDialog( wxCommandEvent& aEvent ); + private: // Called when resizing the Hierarchy Navigator panel void OnResizeHierarchyNavigator( wxSizeEvent& aEvent ); @@ -932,7 +944,8 @@ private: ///< to call a custom net list generator. DIALOG_SCH_FIND* m_findReplaceDialog; - + DIALOG_ERC* m_ercDialog; + DIALOG_BOOK_REPORTER* m_diffSymbolDialog; HIERARCHY_PANE* m_hierarchy; bool m_syncingPcbToSchSelection; // Recursion guard when synchronizing selection from PCB diff --git a/eeschema/tools/ee_inspection_tool.cpp b/eeschema/tools/ee_inspection_tool.cpp index 0a2d1342a3..e9ee3ad3e8 100644 --- a/eeschema/tools/ee_inspection_tool.cpp +++ b/eeschema/tools/ee_inspection_tool.cpp @@ -48,12 +48,8 @@ #include // for KiROUND -#define DIFF_SYMBOLS_DIALOG_NAME wxT( "DiffSymbolsDialog" ) - - EE_INSPECTION_TOOL::EE_INSPECTION_TOOL() : - EE_TOOL_BASE( "eeschema.InspectionTool" ), - m_ercDialog( nullptr ) + EE_TOOL_BASE( "eeschema.InspectionTool" ) { } @@ -79,9 +75,11 @@ void EE_INSPECTION_TOOL::Reset( RESET_REASON aReason ) { EE_TOOL_BASE::Reset( aReason ); - if( aReason == MODEL_RELOAD ) + if( aReason == MODEL_RELOAD && m_frame ) { - DestroyERCDialog(); + wxCommandEvent* evt = new wxCommandEvent( EDA_EVT_CLOSE_ERC_DIALOG, wxID_ANY ); + + wxQueueEvent( m_frame, evt ); } } @@ -95,46 +93,35 @@ int EE_INSPECTION_TOOL::RunERC( const TOOL_EVENT& aEvent ) void EE_INSPECTION_TOOL::ShowERCDialog() { - if( m_frame->IsType( FRAME_SCH ) ) - { - if( m_ercDialog ) - { - // Needed at least on Windows. Raise() is not enough - m_ercDialog->Show( true ); - // Bring it to the top if already open. Dual monitor users need this. - m_ercDialog->Raise(); - } - else - { - // This is a modeless dialog, so new it rather than instantiating on stack. - m_ercDialog = new DIALOG_ERC( static_cast( m_frame ) ); + SCH_EDIT_FRAME* frame = dynamic_cast( m_frame ); - m_ercDialog->Show( true ); - } - } -} + wxCHECK( frame, /* void */ ); + DIALOG_ERC* dlg = frame->GetErcDialog(); -void EE_INSPECTION_TOOL::DestroyERCDialog() -{ - if( m_ercDialog ) - m_ercDialog->Destroy(); + wxCHECK( dlg, /* void */ ); - m_ercDialog = nullptr; + // Needed at least on Windows. Raise() is not enough + dlg->Show( true ); + + // Bring it to the top if already open. Dual monitor users need this. + dlg->Raise(); } int EE_INSPECTION_TOOL::PrevMarker( const TOOL_EVENT& aEvent ) { - if( m_ercDialog ) + SCH_EDIT_FRAME* frame = dynamic_cast( m_frame ); + + wxCHECK( frame, 0 ); + + DIALOG_ERC* dlg = frame->GetErcDialog(); + + if( dlg ) { - m_ercDialog->Show( true ); - m_ercDialog->Raise(); - m_ercDialog->PrevMarker(); - } - else - { - ShowERCDialog(); + dlg->Show( true ); + dlg->Raise(); + dlg->PrevMarker(); } return 0; @@ -143,16 +130,17 @@ int EE_INSPECTION_TOOL::PrevMarker( const TOOL_EVENT& aEvent ) int EE_INSPECTION_TOOL::NextMarker( const TOOL_EVENT& aEvent ) { - if( m_ercDialog ) - { - m_ercDialog->Show( true ); - m_ercDialog->Raise(); - m_ercDialog->NextMarker(); - } - else - { - ShowERCDialog(); - } + SCH_EDIT_FRAME* frame = dynamic_cast( m_frame ); + + wxCHECK( frame, 0 ); + + DIALOG_ERC* dlg = frame->GetErcDialog(); + + wxCHECK( dlg, 0 ); + + dlg->Show( true ); + dlg->Raise(); + dlg->NextMarker(); return 0; } @@ -160,18 +148,26 @@ int EE_INSPECTION_TOOL::NextMarker( const TOOL_EVENT& aEvent ) int EE_INSPECTION_TOOL::CrossProbe( const TOOL_EVENT& aEvent ) { - if( m_ercDialog ) + SCH_EDIT_FRAME* frame = dynamic_cast( m_frame ); + + wxCHECK( frame, 0 ); + + DIALOG_ERC* dlg = frame->GetErcDialog(); + + wxCHECK( dlg, 0 ); + + EE_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool(); + + wxCHECK( selectionTool, 0 ); + + EE_SELECTION& selection = selectionTool->GetSelection(); + + if( selection.GetSize() == 1 && selection.Front()->Type() == SCH_MARKER_T ) { - EE_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool(); - EE_SELECTION& selection = selectionTool->GetSelection(); + if( !dlg->IsShown() ) + dlg->Show( true ); - if( selection.GetSize() == 1 && selection.Front()->Type() == SCH_MARKER_T ) - { - if( !m_ercDialog->IsShown() ) - m_ercDialog->Show( true ); - - m_ercDialog->SelectMarker( static_cast( selection.Front() ) ); - } + dlg->SelectMarker( static_cast( selection.Front() ) ); } // Show the item info on a left click on this item @@ -190,14 +186,20 @@ int EE_INSPECTION_TOOL::ExcludeMarker( const TOOL_EVENT& aEvent ) if( selection.GetSize() == 1 && selection.Front()->Type() == SCH_MARKER_T ) marker = static_cast( selection.Front() ); - if( m_ercDialog ) - { - // Let the ERC dialog handle it since it has more update hassles to worry about - // Note that if marker is nullptr the dialog will exclude whichever marker is selected - // in the dialog itself - m_ercDialog->ExcludeMarker( marker ); - } - else if( marker != nullptr ) + SCH_EDIT_FRAME* frame = dynamic_cast( m_frame ); + + wxCHECK( frame, 0 ); + + DIALOG_ERC* dlg = frame->GetErcDialog(); + + wxCHECK( dlg, 0 ); + + // Let the ERC dialog handle it since it has more update hassles to worry about + // Note that if marker is nullptr the dialog will exclude whichever marker is selected + // in the dialog itself + dlg->ExcludeMarker( marker ); + + if( marker != nullptr ) { marker->SetExcluded( true ); m_frame->GetCanvas()->GetView()->Update( marker ); @@ -244,8 +246,9 @@ int EE_INSPECTION_TOOL::CheckSymbol( const TOOL_EVENT& aEvent ) int EE_INSPECTION_TOOL::DiffSymbol( const TOOL_EVENT& aEvent ) { - if( !m_frame->IsType( FRAME_SCH ) ) - return 0; + SCH_EDIT_FRAME* schEditorFrame = dynamic_cast( m_frame ); + + wxCHECK( schEditorFrame, 0 ); EE_SELECTION& selection = m_selectionTool->RequestSelection( { SCH_SYMBOL_T } ); @@ -255,14 +258,9 @@ int EE_INSPECTION_TOOL::DiffSymbol( const TOOL_EVENT& aEvent ) return 0; } - wxWindow* window = wxWindow::FindWindowByName( DIFF_SYMBOLS_DIALOG_NAME ); - DIALOG_BOOK_REPORTER* dialog = dynamic_cast( window ); + DIALOG_BOOK_REPORTER* dialog = schEditorFrame->GetSymbolDiffDialog(); - if( !dialog ) - { - dialog = new DIALOG_BOOK_REPORTER( m_frame, DIFF_SYMBOLS_DIALOG_NAME, - _( "Diff Symbol with Library" ) ); - } + wxCHECK( dialog, 0 ); dialog->DeleteAllPages(); @@ -278,7 +276,8 @@ int EE_INSPECTION_TOOL::DiffSymbol( const TOOL_EVENT& aEvent ) r->Report( wxS( "" ) + _( "Schematic vs library diff for:" ) + wxS( "" ) ); r->Report( wxS( "
  • " ) + EscapeHTML( symbolDesc ) + wxS( "
  • " ) + wxS( "
  • " ) + _( "Library: " ) + EscapeHTML( libName ) + wxS( "
  • " ) - + wxS( "
  • " ) + _( "Library item: " ) + EscapeHTML( symbolName ) + wxS( "
" ) ); + + wxS( "
  • " ) + _( "Library item: " ) + EscapeHTML( symbolName ) + + wxS( "
  • " ) ); r->Report( "" ); diff --git a/eeschema/tools/ee_inspection_tool.h b/eeschema/tools/ee_inspection_tool.h index 1842961299..73e2df7cef 100644 --- a/eeschema/tools/ee_inspection_tool.h +++ b/eeschema/tools/ee_inspection_tool.h @@ -49,7 +49,6 @@ public: int RunERC( const TOOL_EVENT& aEvent ); void ShowERCDialog(); - void DestroyERCDialog(); int PrevMarker( const TOOL_EVENT& aEvent ); int NextMarker( const TOOL_EVENT& aEvent ); @@ -76,7 +75,6 @@ private: void setTransitions() override; private: - DIALOG_ERC* m_ercDialog; }; #endif /* EE_INSPECTION_TOOL_H */ diff --git a/include/dialogs/dialog_book_reporter.h b/include/dialogs/dialog_book_reporter.h index d8c90f6f53..5a47b9263d 100644 --- a/include/dialogs/dialog_book_reporter.h +++ b/include/dialogs/dialog_book_reporter.h @@ -30,16 +30,18 @@ class KIWAY_PLAYER; class WX_HTML_REPORT_BOX; class wxHtmlLinkEvent; +/** + * Event sent to parent when dialog is mode-less. + */ +wxDECLARE_EVENT( EDA_EVT_CLOSE_DIALOG_BOOK_REPORTER, wxCommandEvent ); + class DIALOG_BOOK_REPORTER : public DIALOG_BOOK_REPORTER_BASE { public: - DIALOG_BOOK_REPORTER( KIWAY_PLAYER* aParent, const wxString& aDialogName, + DIALOG_BOOK_REPORTER( KIWAY_PLAYER* aParent, const wxString& aName, const wxString& aDialogTitle ); - void OnOK( wxCommandEvent& aEvent ) override - { - Destroy(); - } + void OnClose( wxCloseEvent& aEvent ) override; void OnErrorLinkClicked( wxHtmlLinkEvent& aEvent ); diff --git a/include/eda_base_frame.h b/include/eda_base_frame.h index 7105ab12c3..e45b5566c8 100644 --- a/include/eda_base_frame.h +++ b/include/eda_base_frame.h @@ -3,7 +3,7 @@ * * Copyright (C) 2009-2015 Jean-Pierre Charras, jp.charras wanadoo.fr * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -89,7 +89,7 @@ struct WINDOW_STATE; /// This is the handler functor for the update UI events typedef std::function< void( wxUpdateUIEvent& ) > UIUpdateHandler; -wxDECLARE_EVENT( UNITS_CHANGED, wxCommandEvent ); +wxDECLARE_EVENT( EDA_EVT_UNITS_CHANGED, wxCommandEvent ); /** diff --git a/include/pcb_base_frame.h b/include/pcb_base_frame.h index 5b8b16d60a..cc95b80552 100644 --- a/include/pcb_base_frame.h +++ b/include/pcb_base_frame.h @@ -3,7 +3,7 @@ * * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2008-2016 Wayne Stambaugh - * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -61,7 +61,7 @@ struct MAGNETIC_SETTINGS; class NL_PCBNEW_PLUGIN; class PROGRESS_REPORTER; -wxDECLARE_EVENT( BOARD_CHANGED, wxCommandEvent ); +wxDECLARE_EVENT( EDA_EVT_BOARD_CHANGED, wxCommandEvent ); /** * Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer. @@ -382,6 +382,10 @@ public: virtual void ActivateGalCanvas() override; + void AddBoardChangeListener( wxEvtHandler* aListener ); + + void RemoveBoardChangeListener( wxEvtHandler* aListener ); + protected: bool canCloseWindow( wxCloseEvent& aCloseEvent ) override; @@ -413,6 +417,8 @@ protected: private: NL_PCBNEW_PLUGIN* m_spaceMouse; + + std::vector m_boardChangeListeners; }; #endif // PCB_BASE_FRAME_H diff --git a/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp b/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp index c8a7cb4921..ae28f51f0f 100644 --- a/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp +++ b/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2009-2016 Jean-Pierre Charras, jean-pierre.charras at wanadoo.fr - * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -143,7 +143,8 @@ DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS( PCB_EDIT wxCommandEventHandler( DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::OnNetFilterSelect ), nullptr, this ); - m_parent->Bind( UNITS_CHANGED, &DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::onUnitsChanged, this ); + m_parent->Bind( EDA_EVT_UNITS_CHANGED, &DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::onUnitsChanged, + this ); finishDialogSettings(); } @@ -165,7 +166,8 @@ DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::~DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS() wxCommandEventHandler( DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::OnNetFilterSelect ), nullptr, this ); - m_parent->Unbind( UNITS_CHANGED, &DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::onUnitsChanged, this ); + m_parent->Unbind( EDA_EVT_UNITS_CHANGED, + &DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::onUnitsChanged, this ); delete[] m_originalColWidths; } diff --git a/pcbnew/dialogs/dialog_net_inspector.cpp b/pcbnew/dialogs/dialog_net_inspector.cpp index 996067809d..9756283c04 100644 --- a/pcbnew/dialogs/dialog_net_inspector.cpp +++ b/pcbnew/dialogs/dialog_net_inspector.cpp @@ -50,6 +50,9 @@ #include +wxDEFINE_EVENT( EDA_EVT_CLOSE_NET_INSPECTOR_DIALOG, wxCommandEvent ); + + static DIALOG_NET_INSPECTOR::SETTINGS g_settings; @@ -62,9 +65,10 @@ enum class CSV_COLUMN_DESC : int struct DIALOG_NET_INSPECTOR::COLUMN_DESC { - COLUMN_DESC( unsigned aNum, PCB_LAYER_ID aLayer, const wxString& aDisp, const wxString& aCsv, CSV_COLUMN_DESC aFlags ) : - num( aNum ), layer( aLayer ), display_name( aDisp ), csv_name( aCsv ), csv_flags( aFlags ) - {} + COLUMN_DESC( unsigned aNum, PCB_LAYER_ID aLayer, const wxString& aDisp, const wxString& aCsv, + CSV_COLUMN_DESC aFlags ) : + num( aNum ), layer( aLayer ), display_name( aDisp ), csv_name( aCsv ), csv_flags( aFlags ) + {} unsigned int num; PCB_LAYER_ID layer; @@ -94,30 +98,6 @@ enum class DIALOG_NET_INSPECTOR::LIST_ITEM { -private: - // an item can be the child of only one parent at a time. - // FIXME: could use a more lightweight container like intrusive forward list. - LIST_ITEM* m_parent = nullptr; - std::vector m_children; - - bool m_is_group = false; - unsigned int m_group_number = 0; - NETINFO_ITEM* m_net = nullptr; - unsigned int m_pad_count = 0; - unsigned int m_via_count = 0; - uint64_t m_via_length = 0; - uint64_t m_chip_wire_length = 0; - - std::array m_layer_wire_length{}; - - - // dirty bits to record when some attribute has changed. this is to - // avoid unnecessary resort operations. - std::vector m_column_changed; - - // cached formatted net name for faster display sorting. - wxString m_net_name; - public: LIST_ITEM( unsigned int aGroupNumber, const wxString& aGroupName ) : m_is_group( true ), @@ -162,7 +142,7 @@ public: std::fill( m_column_changed.begin(), m_column_changed.end(), 0 ); } - decltype( m_pad_count ) GetPadCount() const + unsigned int GetPadCount() const { return m_pad_count; } @@ -172,7 +152,7 @@ public: return m_column_changed[COLUMN_PAD_COUNT]; } - void SetPadCount( const decltype( m_pad_count ) &aValue ) + void SetPadCount( unsigned int aValue ) { if( m_parent ) m_parent->SetPadCount( m_parent->GetPadCount() - m_pad_count + aValue ); @@ -181,7 +161,7 @@ public: m_pad_count = aValue; } - void AddPadCount( const decltype( m_pad_count ) &aValue ) + void AddPadCount( unsigned int aValue ) { if( m_parent ) m_parent->AddPadCount( aValue ); @@ -190,7 +170,7 @@ public: m_pad_count += aValue; } - void SubPadCount( const decltype( m_pad_count ) &aValue ) + void SubPadCount( unsigned int aValue ) { if( m_parent ) m_parent->SubPadCount( aValue ); @@ -209,7 +189,7 @@ public: return m_column_changed[COLUMN_VIA_COUNT]; } - void SetViaCount( const decltype( m_via_count ) &aValue ) + void SetViaCount( unsigned int aValue ) { if( m_parent ) m_parent->SetViaCount( m_parent->GetViaCount() - m_via_count + aValue ); @@ -218,7 +198,7 @@ public: m_via_count = aValue; } - void AddViaCount( const decltype( m_via_count ) &aValue ) + void AddViaCount( unsigned int aValue ) { if( m_parent ) m_parent->AddViaCount( aValue ); @@ -227,7 +207,7 @@ public: m_via_count += aValue; } - void SubViaCount( const decltype( m_via_count ) &aValue ) + void SubViaCount( unsigned int aValue ) { if( m_parent ) m_parent->SubViaCount( aValue ); @@ -246,7 +226,7 @@ public: return m_column_changed[COLUMN_VIA_LENGTH]; } - void SetViaLength( const decltype( m_via_length ) &aValue ) + void SetViaLength( unsigned int aValue ) { if( m_parent ) m_parent->SetViaLength( m_parent->GetViaLength() - m_via_length + aValue ); @@ -255,7 +235,7 @@ public: m_via_length = aValue; } - void AddViaLength( const decltype( m_via_length ) &aValue ) + void AddViaLength( unsigned int aValue ) { if( m_parent ) m_parent->AddViaLength( aValue ); @@ -264,7 +244,7 @@ public: m_via_length += aValue; } - void SubViaLength( const decltype( m_via_length ) &aValue ) + void SubViaLength( uint64_t aValue ) { if( m_parent ) m_parent->SubViaLength( aValue ); @@ -335,7 +315,7 @@ public: return m_column_changed[COLUMN_CHIP_LENGTH]; } - void SetChipWireLength( const decltype( m_chip_wire_length ) &aValue ) + void SetChipWireLength( uint64_t aValue ) { if( m_parent ) m_parent->SetChipWireLength( @@ -345,7 +325,7 @@ public: m_chip_wire_length = aValue; } - void AddChipWireLength( const decltype( m_chip_wire_length ) &aValue ) + void AddChipWireLength( uint64_t aValue ) { if( m_parent ) m_parent->AddChipWireLength( aValue ); @@ -354,7 +334,7 @@ public: m_chip_wire_length += aValue; } - void SubChipWireLength( const decltype( m_chip_wire_length ) &aValue ) + void SubChipWireLength( uint64_t aValue ) { if( m_parent ) m_parent->SubChipWireLength( aValue ); @@ -362,7 +342,6 @@ public: m_column_changed[COLUMN_CHIP_LENGTH] |= ( aValue != 0 ); m_chip_wire_length -= aValue; } - ; // the total length column is always computed, never stored. unsigned long long int GetTotalLength() const @@ -416,6 +395,29 @@ public: m_parent->m_children.push_back( this ); } } + +private: + // an item can be the child of only one parent at a time. + // FIXME: could use a more lightweight container like intrusive forward list. + LIST_ITEM* m_parent = nullptr; + std::vector m_children; + + bool m_is_group = false; + unsigned int m_group_number = 0; + NETINFO_ITEM* m_net = nullptr; + unsigned int m_pad_count = 0; + unsigned int m_via_count = 0; + uint64_t m_via_length = 0; + uint64_t m_chip_wire_length = 0; + + std::array m_layer_wire_length{}; + + // dirty bits to record when some attribute has changed. this is to + // avoid unnecessary resort operations. + std::vector m_column_changed; + + // cached formatted net name for faster display sorting. + wxString m_net_name; }; @@ -443,15 +445,6 @@ struct DIALOG_NET_INSPECTOR::LIST_ITEM_NETCODE_CMP_LESS class DIALOG_NET_INSPECTOR::DATA_MODEL : public wxDataViewModel { -private: - DIALOG_NET_INSPECTOR& m_parent; - - // primary container, sorted by netcode number. - // groups have netcode < 0, so they always come first, in the order - // of the filter strings as input by the user (group mode 0, 1) or - // in order of occurrence (group mode 2, 3). - std::vector> m_items; - public: DATA_MODEL( DIALOG_NET_INSPECTOR& parent ) : m_parent( parent ) @@ -618,7 +611,8 @@ public: if( match ) { - wxString match_str = i->GetNetName().substr( match.start, match.length ); + wxString match_str = i->GetNetName().substr( match.start, + match.length ); auto group = std::find_if( groups.begin(), groups.end(), [&]( const std::unique_ptr& x ) @@ -956,24 +950,39 @@ protected: { return wxS( "string" ); } + +private: + DIALOG_NET_INSPECTOR& m_parent; + + // primary container, sorted by netcode number. + // groups have netcode < 0, so they always come first, in the order + // of the filter strings as input by the user (group mode 0, 1) or + // in order of occurrence (group mode 2, 3). + std::vector> m_items; }; -DIALOG_NET_INSPECTOR::DIALOG_NET_INSPECTOR( PCB_EDIT_FRAME* aParent, const wxString& aDialogName ) : +DIALOG_NET_INSPECTOR::DIALOG_NET_INSPECTOR( PCB_EDIT_FRAME* aParent ) : DIALOG_NET_INSPECTOR_BASE( aParent ), m_zero_netitem( nullptr ), m_frame( aParent ) { - SetName( aDialogName ); - - m_columns.emplace_back( 0u, UNDEFINED_LAYER, _( "Net" ), _( "Net Code" ), CSV_COLUMN_DESC::CSV_NONE ); - m_columns.emplace_back( 1u, UNDEFINED_LAYER, _( "Name" ), _( "Net Name" ), CSV_COLUMN_DESC::CSV_QUOTE ); - m_columns.emplace_back( 2u, UNDEFINED_LAYER, _( "Pad Count" ), _( "Pad Count" ), CSV_COLUMN_DESC::CSV_NONE ); - m_columns.emplace_back( 3u, UNDEFINED_LAYER, _( "Via Count" ), _( "Via Count" ), CSV_COLUMN_DESC::CSV_NONE ); - m_columns.emplace_back( 4u, UNDEFINED_LAYER, _( "Via Length" ), _( "Via Length" ), CSV_COLUMN_DESC::CSV_NONE ); - m_columns.emplace_back( 5u, UNDEFINED_LAYER, _( "Track Length" ), _( "Track Length" ), CSV_COLUMN_DESC::CSV_NONE ); - m_columns.emplace_back( 6u, UNDEFINED_LAYER, _( "Die Length" ), _( "Die Length" ), CSV_COLUMN_DESC::CSV_NONE ); - m_columns.emplace_back( 7u, UNDEFINED_LAYER, _( "Total Length" ), _( "Net Length" ), CSV_COLUMN_DESC::CSV_NONE ); + m_columns.emplace_back( 0u, UNDEFINED_LAYER, _( "Net" ), _( "Net Code" ), + CSV_COLUMN_DESC::CSV_NONE ); + m_columns.emplace_back( 1u, UNDEFINED_LAYER, _( "Name" ), _( "Net Name" ), + CSV_COLUMN_DESC::CSV_QUOTE ); + m_columns.emplace_back( 2u, UNDEFINED_LAYER, _( "Pad Count" ), _( "Pad Count" ), + CSV_COLUMN_DESC::CSV_NONE ); + m_columns.emplace_back( 3u, UNDEFINED_LAYER, _( "Via Count" ), _( "Via Count" ), + CSV_COLUMN_DESC::CSV_NONE ); + m_columns.emplace_back( 4u, UNDEFINED_LAYER, _( "Via Length" ), _( "Via Length" ), + CSV_COLUMN_DESC::CSV_NONE ); + m_columns.emplace_back( 5u, UNDEFINED_LAYER, _( "Track Length" ), _( "Track Length" ), + CSV_COLUMN_DESC::CSV_NONE ); + m_columns.emplace_back( 6u, UNDEFINED_LAYER, _( "Die Length" ), _( "Die Length" ), + CSV_COLUMN_DESC::CSV_NONE ); + m_columns.emplace_back( 7u, UNDEFINED_LAYER, _( "Total Length" ), _( "Net Length" ), + CSV_COLUMN_DESC::CSV_NONE ); m_brd = aParent->GetBoard(); @@ -989,44 +998,51 @@ DIALOG_NET_INSPECTOR::DIALOG_NET_INSPECTOR( PCB_EDIT_FRAME* aParent, const wxStr }, [&]() { - m_netsList->AppendTextColumn( m_columns[COLUMN_NAME].display_name, m_columns[COLUMN_NAME], + m_netsList->AppendTextColumn( m_columns[COLUMN_NAME].display_name, + m_columns[COLUMN_NAME], wxDATAVIEW_CELL_INERT, -1, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_SORTABLE ); }, [&]() { - m_netsList->AppendTextColumn( m_columns[COLUMN_PAD_COUNT].display_name, m_columns[COLUMN_PAD_COUNT], + m_netsList->AppendTextColumn( m_columns[COLUMN_PAD_COUNT].display_name, + m_columns[COLUMN_PAD_COUNT], wxDATAVIEW_CELL_INERT, -1, wxALIGN_CENTER, wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_SORTABLE ); }, [&]() { - m_netsList->AppendTextColumn( m_columns[COLUMN_VIA_COUNT].display_name, m_columns[COLUMN_VIA_COUNT], + m_netsList->AppendTextColumn( m_columns[COLUMN_VIA_COUNT].display_name, + m_columns[COLUMN_VIA_COUNT], wxDATAVIEW_CELL_INERT, -1, wxALIGN_CENTER, wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_SORTABLE ); }, [&]() { - m_netsList->AppendTextColumn( m_columns[COLUMN_VIA_LENGTH].display_name, m_columns[COLUMN_VIA_LENGTH], + m_netsList->AppendTextColumn( m_columns[COLUMN_VIA_LENGTH].display_name, + m_columns[COLUMN_VIA_LENGTH], wxDATAVIEW_CELL_INERT, -1, wxALIGN_CENTER, wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_SORTABLE ); }, [&]() { - m_netsList->AppendTextColumn( m_columns[COLUMN_BOARD_LENGTH].display_name, m_columns[COLUMN_BOARD_LENGTH], + m_netsList->AppendTextColumn( m_columns[COLUMN_BOARD_LENGTH].display_name, + m_columns[COLUMN_BOARD_LENGTH], wxDATAVIEW_CELL_INERT, -1, wxALIGN_CENTER, wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_SORTABLE ); }, [&]() { - m_netsList->AppendTextColumn( m_columns[COLUMN_CHIP_LENGTH].display_name, m_columns[COLUMN_CHIP_LENGTH], + m_netsList->AppendTextColumn( m_columns[COLUMN_CHIP_LENGTH].display_name, + m_columns[COLUMN_CHIP_LENGTH], wxDATAVIEW_CELL_INERT, -1, wxALIGN_CENTER, wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_SORTABLE ); }, [&]() { - m_netsList->AppendTextColumn( m_columns[COLUMN_TOTAL_LENGTH].display_name, m_columns[COLUMN_TOTAL_LENGTH], + m_netsList->AppendTextColumn( m_columns[COLUMN_TOTAL_LENGTH].display_name, + m_columns[COLUMN_TOTAL_LENGTH], wxDATAVIEW_CELL_INERT, -1, wxALIGN_CENTER, wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_SORTABLE ); } @@ -1095,19 +1111,8 @@ DIALOG_NET_INSPECTOR::DIALOG_NET_INSPECTOR( PCB_EDIT_FRAME* aParent, const wxStr finishDialogSettings(); - m_frame->Bind( wxEVT_CLOSE_WINDOW, - [this]( wxCloseEvent& aEvent ) - { - Close(); - aEvent.Skip(); - } ); - - m_frame->Connect( UNITS_CHANGED, - wxCommandEventHandler( DIALOG_NET_INSPECTOR::onUnitsChanged ), - nullptr, this ); - m_frame->Connect( BOARD_CHANGED, - wxCommandEventHandler( DIALOG_NET_INSPECTOR::onBoardChanged ), - nullptr, this ); + Bind( EDA_EVT_UNITS_CHANGED, &DIALOG_NET_INSPECTOR::onUnitsChanged, this ); + Bind( EDA_EVT_BOARD_CHANGED, &DIALOG_NET_INSPECTOR::onBoardChanged, this ); if( m_brd != nullptr ) { @@ -1133,7 +1138,8 @@ DIALOG_NET_INSPECTOR::~DIALOG_NET_INSPECTOR() g_settings.group_by = m_groupBy->IsChecked(); g_settings.group_by_kind = m_groupByKind->GetSelection(); g_settings.group_by_text = m_groupByText->GetValue(); - g_settings.sorting_column = sorting_column ? static_cast( sorting_column->GetModelColumn() ) : -1; + g_settings.sorting_column = sorting_column ? + static_cast( sorting_column->GetModelColumn() ) : -1; g_settings.sort_order_asc = sorting_column ? sorting_column->IsSortOrderAscending() : true; g_settings.column_order = column_order; @@ -1142,23 +1148,17 @@ DIALOG_NET_INSPECTOR::~DIALOG_NET_INSPECTOR() // from now on. so just disassociate it. m_netsList->AssociateModel( nullptr ); - m_frame->Disconnect( UNITS_CHANGED, - wxCommandEventHandler( DIALOG_NET_INSPECTOR::onUnitsChanged ), - nullptr, this ); - m_frame->Disconnect( BOARD_CHANGED, - wxCommandEventHandler( DIALOG_NET_INSPECTOR::onBoardChanged ), - nullptr, this ); + Unbind( EDA_EVT_UNITS_CHANGED, &DIALOG_NET_INSPECTOR::onUnitsChanged, this ); + Unbind( EDA_EVT_BOARD_CHANGED, &DIALOG_NET_INSPECTOR::onBoardChanged, this ); if( m_brd != nullptr ) m_brd->RemoveListener( this ); - - m_frame->GetCanvas()->SetFocus(); } void DIALOG_NET_INSPECTOR::onUnitsChanged( wxCommandEvent& event ) { - this->m_units = m_frame->GetUserUnits(); + m_units = m_frame->GetUserUnits(); m_data_model->updateAllItems(); @@ -1636,7 +1636,8 @@ DIALOG_NET_INSPECTOR::buildNewItem( NETINFO_ITEM* aNet, unsigned int aPadCount, else if( PCB_TRACK* track = dynamic_cast( item ) ) { - new_item->AddLayerWireLength( track->GetLength(), static_cast( track->GetLayer() ) ); + new_item->AddLayerWireLength( track->GetLength(), + static_cast( track->GetLayer() ) ); if( item->Type() == PCB_VIA_T ) { @@ -2241,3 +2242,21 @@ void DIALOG_NET_INSPECTOR::onReport( wxCommandEvent& aEvent ) f.Write(); f.Close(); } + + +void DIALOG_NET_INSPECTOR::onClose( wxCloseEvent& aEvent ) +{ + // Dialog is mode-less so let the parent know that it needs to be destroyed. + if( !IsModal() && !IsQuasiModal() ) + { + wxCommandEvent* evt = new wxCommandEvent( EDA_EVT_CLOSE_NET_INSPECTOR_DIALOG, wxID_ANY ); + + evt->SetEventObject( this ); + wxWindow* parent = GetParent(); + + if( parent ) + wxQueueEvent( parent, evt ); + } + + aEvent.Skip(); +} diff --git a/pcbnew/dialogs/dialog_net_inspector.h b/pcbnew/dialogs/dialog_net_inspector.h index 8caa592283..536f9fa098 100644 --- a/pcbnew/dialogs/dialog_net_inspector.h +++ b/pcbnew/dialogs/dialog_net_inspector.h @@ -37,6 +37,11 @@ class CN_ITEM; class EDA_PATTERN_MATCH; class PCB_TRACK; +/** + * Event sent to parent when dialog is mode-less. + */ +wxDECLARE_EVENT( EDA_EVT_CLOSE_NET_INSPECTOR_DIALOG, wxCommandEvent ); + class DIALOG_NET_INSPECTOR : public DIALOG_NET_INSPECTOR_BASE, public BOARD_LISTENER { public: @@ -53,18 +58,23 @@ public: std::vector column_order; }; - DIALOG_NET_INSPECTOR( PCB_EDIT_FRAME* aParent, const wxString& aDialogName ); + DIALOG_NET_INSPECTOR( PCB_EDIT_FRAME* aParent ); ~DIALOG_NET_INSPECTOR(); virtual void OnBoardItemAdded( BOARD& aBoard, BOARD_ITEM* aBoardItem ) override; virtual void OnBoardItemsAdded( BOARD& aBoard, std::vector& aBoardItems ) override; virtual void OnBoardItemRemoved( BOARD& aBoard, BOARD_ITEM* aBoardItem ) override; - virtual void OnBoardItemsRemoved( BOARD& aBoard, std::vector& aBoardItems ) override; + virtual void OnBoardItemsRemoved( BOARD& aBoard, + std::vector& aBoardItems ) override; virtual void OnBoardNetSettingsChanged( BOARD& aBoard ) override; virtual void OnBoardItemChanged( BOARD& aBoard, BOARD_ITEM* aBoardItem ) override; - virtual void OnBoardItemsChanged( BOARD& aBoard, std::vector& aBoardItems ) override; + virtual void OnBoardItemsChanged( BOARD& aBoard, + std::vector& aBoardItems ) override; virtual void OnBoardHighlightNetChanged( BOARD& aBoard ) override; +protected: + virtual void onClose( wxCloseEvent& aEvent ) override; + private: struct COLUMN_DESC; class LIST_ITEM; diff --git a/pcbnew/dialogs/dialog_net_inspector_base.cpp b/pcbnew/dialogs/dialog_net_inspector_base.cpp index 8f1799a77e..6aab43e88e 100644 --- a/pcbnew/dialogs/dialog_net_inspector_base.cpp +++ b/pcbnew/dialogs/dialog_net_inspector_base.cpp @@ -73,16 +73,16 @@ DIALOG_NET_INSPECTOR_BASE::DIALOG_NET_INSPECTOR_BASE( wxWindow* parent, wxWindow bSizerListButtons = new wxBoxSizer( wxHORIZONTAL ); m_addNet = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); - bSizerListButtons->Add( m_addNet, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); + bSizerListButtons->Add( m_addNet, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); m_renameNet = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); - bSizerListButtons->Add( m_renameNet, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); + bSizerListButtons->Add( m_renameNet, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); bSizerListButtons->Add( 20, 0, 0, wxEXPAND, 5 ); m_deleteNet = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 ); - bSizerListButtons->Add( m_deleteNet, 0, wxALL, 5 ); + bSizerListButtons->Add( m_deleteNet, 0, wxALIGN_CENTER_VERTICAL, 5 ); bSizerListButtons->Add( 0, 0, 1, wxEXPAND, 5 ); @@ -101,6 +101,7 @@ DIALOG_NET_INSPECTOR_BASE::DIALOG_NET_INSPECTOR_BASE( wxWindow* parent, wxWindow this->Centre( wxBOTH ); // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_NET_INSPECTOR_BASE::onClose ) ); m_textCtrlFilter->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_NET_INSPECTOR_BASE::onFilterChange ), NULL, this ); m_cbShowZeroPad->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_NET_INSPECTOR_BASE::onFilterChange ), NULL, this ); m_groupBy->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_NET_INSPECTOR_BASE::onFilterChange ), NULL, this ); @@ -118,6 +119,7 @@ DIALOG_NET_INSPECTOR_BASE::DIALOG_NET_INSPECTOR_BASE( wxWindow* parent, wxWindow DIALOG_NET_INSPECTOR_BASE::~DIALOG_NET_INSPECTOR_BASE() { // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_NET_INSPECTOR_BASE::onClose ) ); m_textCtrlFilter->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_NET_INSPECTOR_BASE::onFilterChange ), NULL, this ); m_cbShowZeroPad->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_NET_INSPECTOR_BASE::onFilterChange ), NULL, this ); m_groupBy->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_NET_INSPECTOR_BASE::onFilterChange ), NULL, this ); diff --git a/pcbnew/dialogs/dialog_net_inspector_base.fbp b/pcbnew/dialogs/dialog_net_inspector_base.fbp index 6bf5f87b93..8bc77dbb7f 100644 --- a/pcbnew/dialogs/dialog_net_inspector_base.fbp +++ b/pcbnew/dialogs/dialog_net_inspector_base.fbp @@ -56,6 +56,7 @@ + onClose bSizerMain @@ -522,14 +523,14 @@ 5 wxEXPAND|wxALL 0 - + bSizerListButtons wxHORIZONTAL none 5 - wxTOP|wxBOTTOM|wxLEFT + wxALIGN_CENTER_VERTICAL|wxLEFT 0 1 @@ -603,7 +604,7 @@ 5 - wxTOP|wxBOTTOM|wxLEFT + wxALIGN_CENTER_VERTICAL|wxLEFT 0 1 @@ -687,7 +688,7 @@ 5 - wxALL + wxALIGN_CENTER_VERTICAL 0 1 diff --git a/pcbnew/dialogs/dialog_net_inspector_base.h b/pcbnew/dialogs/dialog_net_inspector_base.h index 9554cdee39..9fb51343f4 100644 --- a/pcbnew/dialogs/dialog_net_inspector_base.h +++ b/pcbnew/dialogs/dialog_net_inspector_base.h @@ -55,6 +55,7 @@ class DIALOG_NET_INSPECTOR_BASE : public DIALOG_SHIM wxButton* m_ReportButt; // Virtual event handlers, override them in your derived class + virtual void onClose( wxCloseEvent& event ) { event.Skip(); } virtual void onFilterChange( wxCommandEvent& event ) { event.Skip(); } virtual void onSortingChanged( wxDataViewEvent& event ) { event.Skip(); } virtual void onSelChanged( wxDataViewEvent& event ) { event.Skip(); } diff --git a/pcbnew/dialogs/dialog_track_via_properties.cpp b/pcbnew/dialogs/dialog_track_via_properties.cpp index 0c2196f067..f2c0eb3c3c 100644 --- a/pcbnew/dialogs/dialog_track_via_properties.cpp +++ b/pcbnew/dialogs/dialog_track_via_properties.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015 CERN - * Copyright (C) 2018-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2018-2023 KiCad Developers, see AUTHORS.txt for contributors. * @author Maciej Suminski * * This program is free software; you can redistribute it and/or @@ -388,7 +388,7 @@ DIALOG_TRACK_VIA_PROPERTIES::DIALOG_TRACK_VIA_PROPERTIES( PCB_BASE_FRAME* aParen SetupStandardButtons(); - m_frame->Bind( UNITS_CHANGED, &DIALOG_TRACK_VIA_PROPERTIES::onUnitsChanged, this ); + m_frame->Bind( EDA_EVT_UNITS_CHANGED, &DIALOG_TRACK_VIA_PROPERTIES::onUnitsChanged, this ); m_netSelector->Bind( NET_SELECTED, &DIALOG_TRACK_VIA_PROPERTIES::onNetSelector, this ); // Now all widgets have the size fixed, call FinishDialogSettings @@ -398,7 +398,7 @@ DIALOG_TRACK_VIA_PROPERTIES::DIALOG_TRACK_VIA_PROPERTIES( PCB_BASE_FRAME* aParen DIALOG_TRACK_VIA_PROPERTIES::~DIALOG_TRACK_VIA_PROPERTIES() { - m_frame->Unbind( UNITS_CHANGED, &DIALOG_TRACK_VIA_PROPERTIES::onUnitsChanged, this ); + m_frame->Unbind( EDA_EVT_UNITS_CHANGED, &DIALOG_TRACK_VIA_PROPERTIES::onUnitsChanged, this ); } diff --git a/pcbnew/dialogs/panel_setup_text_and_graphics.cpp b/pcbnew/dialogs/panel_setup_text_and_graphics.cpp index a7efc6b907..3b9a8c8fd3 100644 --- a/pcbnew/dialogs/panel_setup_text_and_graphics.cpp +++ b/pcbnew/dialogs/panel_setup_text_and_graphics.cpp @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2018-2022 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 2018-2023 KiCad Developers, see change_log.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -95,7 +95,7 @@ PANEL_SETUP_TEXT_AND_GRAPHICS::PANEL_SETUP_TEXT_AND_GRAPHICS( PAGED_DIALOG* aPar m_grid->PushEventHandler( new GRID_TRICKS( m_grid ) ); - m_Frame->Bind( UNITS_CHANGED, &PANEL_SETUP_TEXT_AND_GRAPHICS::onUnitsChanged, this ); + m_Frame->Bind( EDA_EVT_UNITS_CHANGED, &PANEL_SETUP_TEXT_AND_GRAPHICS::onUnitsChanged, this ); } @@ -104,7 +104,7 @@ PANEL_SETUP_TEXT_AND_GRAPHICS::~PANEL_SETUP_TEXT_AND_GRAPHICS() // destroy GRID_TRICKS before m_grid. m_grid->PopEventHandler( true ); - m_Frame->Unbind( UNITS_CHANGED, &PANEL_SETUP_TEXT_AND_GRAPHICS::onUnitsChanged, this ); + m_Frame->Unbind( EDA_EVT_UNITS_CHANGED, &PANEL_SETUP_TEXT_AND_GRAPHICS::onUnitsChanged, this ); } @@ -151,8 +151,10 @@ bool PANEL_SETUP_TEXT_AND_GRAPHICS::TransferDataToWindow() SET_MILS_CELL( i, COL_TEXT_WIDTH, m_BrdSettings->m_TextSize[ i ].x ); SET_MILS_CELL( i, COL_TEXT_HEIGHT, m_BrdSettings->m_TextSize[ i ].y ); SET_MILS_CELL( i, COL_TEXT_THICKNESS, m_BrdSettings->m_TextThickness[ i ] ); - m_grid->SetCellValue( i, COL_TEXT_ITALIC, m_BrdSettings->m_TextItalic[ i ] ? wxT( "1" ) : wxT( "" ) ); - m_grid->SetCellValue( i, COL_TEXT_UPRIGHT, m_BrdSettings->m_TextUpright[ i ] ? wxT( "1" ) : wxT( "" ) ); + m_grid->SetCellValue( i, COL_TEXT_ITALIC, + m_BrdSettings->m_TextItalic[ i ] ? wxT( "1" ) : wxT( "" ) ); + m_grid->SetCellValue( i, COL_TEXT_UPRIGHT, + m_BrdSettings->m_TextUpright[ i ] ? wxT( "1" ) : wxT( "" ) ); auto attr = new wxGridCellAttr; attr->SetRenderer( new wxGridCellBoolRenderer() ); diff --git a/pcbnew/dialogs/panel_setup_tracks_and_vias.cpp b/pcbnew/dialogs/panel_setup_tracks_and_vias.cpp index 52e1016d71..71656d8883 100644 --- a/pcbnew/dialogs/panel_setup_tracks_and_vias.cpp +++ b/pcbnew/dialogs/panel_setup_tracks_and_vias.cpp @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2018-2022 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 2018-2023 KiCad Developers, see change_log.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -122,7 +122,7 @@ PANEL_SETUP_TRACKS_AND_VIAS::PANEL_SETUP_TRACKS_AND_VIAS( PAGED_DIALOG* aParent, } } - m_Frame->Bind( UNITS_CHANGED, &PANEL_SETUP_TRACKS_AND_VIAS::onUnitsChanged, this ); + m_Frame->Bind( EDA_EVT_UNITS_CHANGED, &PANEL_SETUP_TRACKS_AND_VIAS::onUnitsChanged, this ); } @@ -133,7 +133,7 @@ PANEL_SETUP_TRACKS_AND_VIAS::~PANEL_SETUP_TRACKS_AND_VIAS() m_viaSizesGrid->PopEventHandler( true ); m_diffPairsGrid->PopEventHandler( true ); - m_Frame->Unbind( UNITS_CHANGED, &PANEL_SETUP_TRACKS_AND_VIAS::onUnitsChanged, this ); + m_Frame->Unbind( EDA_EVT_UNITS_CHANGED, &PANEL_SETUP_TRACKS_AND_VIAS::onUnitsChanged, this ); } diff --git a/pcbnew/fp_text_grid_table.cpp b/pcbnew/fp_text_grid_table.cpp index 43ab242935..ba9c64a448 100644 --- a/pcbnew/fp_text_grid_table.cpp +++ b/pcbnew/fp_text_grid_table.cpp @@ -69,7 +69,7 @@ FP_TEXT_GRID_TABLE::FP_TEXT_GRID_TABLE( PCB_BASE_FRAME* aFrame ) : m_eval = std::make_unique( m_frame->GetUserUnits() ); - m_frame->Bind( UNITS_CHANGED, &FP_TEXT_GRID_TABLE::onUnitsChanged, this ); + m_frame->Bind( EDA_EVT_UNITS_CHANGED, &FP_TEXT_GRID_TABLE::onUnitsChanged, this ); } @@ -80,7 +80,7 @@ FP_TEXT_GRID_TABLE::~FP_TEXT_GRID_TABLE() m_orientationColAttr->DecRef(); m_layerColAttr->DecRef(); - m_frame->Unbind( UNITS_CHANGED, &FP_TEXT_GRID_TABLE::onUnitsChanged, this ); + m_frame->Unbind( EDA_EVT_UNITS_CHANGED, &FP_TEXT_GRID_TABLE::onUnitsChanged, this ); } diff --git a/pcbnew/pcb_base_frame.cpp b/pcbnew/pcb_base_frame.cpp index e4ca369d73..3ba6237c56 100644 --- a/pcbnew/pcb_base_frame.cpp +++ b/pcbnew/pcb_base_frame.cpp @@ -4,7 +4,7 @@ * Copyright (C) 2018 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2022 CERN * * This program is free software; you can redistribute it and/or @@ -70,12 +70,13 @@ using KIGFX::RENDER_SETTINGS; using KIGFX::PCB_RENDER_SETTINGS; -wxDEFINE_EVENT( BOARD_CHANGED, wxCommandEvent ); +wxDEFINE_EVENT( EDA_EVT_BOARD_CHANGED, wxCommandEvent ); PCB_BASE_FRAME::PCB_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType, const wxString& aTitle, const wxPoint& aPos, const wxSize& aSize, long aStyle, const wxString& aFrameName ) : - EDA_DRAW_FRAME( aKiway, aParent, aFrameType, aTitle, aPos, aSize, aStyle, aFrameName, pcbIUScale ), + EDA_DRAW_FRAME( aKiway, aParent, aFrameType, aTitle, aPos, aSize, aStyle, aFrameName, + pcbIUScale ), m_pcb( nullptr ), m_originTransforms( *this ), m_spaceMouse( nullptr ) @@ -226,12 +227,44 @@ void PCB_BASE_FRAME::SetBoard( BOARD* aBoard, PROGRESS_REPORTER* aReporter ) } } - wxCommandEvent e( BOARD_CHANGED ); + wxCommandEvent e( EDA_EVT_BOARD_CHANGED ); ProcessEventLocally( e ); + + for( wxEvtHandler* listener : m_boardChangeListeners ) + { + wxCHECK2( listener, continue ); + + wxWindow* win = dynamic_cast( listener ); + + if( win ) + win->HandleWindowEvent( e ); + else + listener->SafelyProcessEvent( e ); + } } } +void PCB_BASE_FRAME::AddBoardChangeListener( wxEvtHandler* aListener ) +{ + auto it = std::find( m_boardChangeListeners.begin(), m_boardChangeListeners.end(), aListener ); + + // Don't add duplicate listeners. + if( it == m_boardChangeListeners.end() ) + m_boardChangeListeners.push_back( aListener ); +} + + +void PCB_BASE_FRAME::RemoveBoardChangeListener( wxEvtHandler* aListener ) +{ + auto it = std::find( m_boardChangeListeners.begin(), m_boardChangeListeners.end(), aListener ); + + // Don't add duplicate listeners. + if( it != m_boardChangeListeners.end() ) + m_boardChangeListeners.erase( it ); +} + + void PCB_BASE_FRAME::AddFootprintToBoard( FOOTPRINT* aFootprint ) { if( aFootprint ) diff --git a/pcbnew/pcb_edit_frame.cpp b/pcbnew/pcb_edit_frame.cpp index 942bb936d2..1125e4d5cd 100644 --- a/pcbnew/pcb_edit_frame.cpp +++ b/pcbnew/pcb_edit_frame.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -114,6 +115,12 @@ using namespace std::placeholders; +#define INSPECT_DRC_ERROR_DIALOG_NAME wxT( "InspectDrcErrorDialog" ) +#define INSPECT_CLEARANCE_DIALOG_NAME wxT( "InspectClearanceDialog" ) +#define INSPECT_CONSTRAINTS_DIALOG_NAME wxT( "InspectConstraintsDialog" ) +#define FOOTPRINT_DIFF_DIALOG_NAME wxT( "FootprintDiffDialog" ) + + BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME ) EVT_SOCKET( ID_EDA_SOCKET_EVENT_SERV, PCB_EDIT_FRAME::OnSockRequestServer ) EVT_SOCKET( ID_EDA_SOCKET_EVENT, PCB_EDIT_FRAME::OnSockRequest ) @@ -183,7 +190,13 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : PCB_BASE_EDIT_FRAME( aKiway, aParent, FRAME_PCB_EDITOR, _( "PCB Editor" ), wxDefaultPosition, wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE, PCB_EDIT_FRAME_NAME ), - m_exportNetlistAction( nullptr ), m_findDialog( nullptr ) + m_exportNetlistAction( nullptr ), + m_findDialog( nullptr ), + m_inspectDrcErrorDlg( nullptr ), + m_inspectClearanceDlg( nullptr ), + m_inspectConstraintsDlg( nullptr ), + m_footprintDiffDlg( nullptr ), + m_netInspectorDlg( nullptr ) { m_maximizeByDefault = true; m_showBorderAndTitleBlock = true; // true to display sheet references @@ -407,9 +420,9 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : wxFileName appK2S( strK2S, wxT( "kicad2step" ) ); - #ifdef _WIN32 +#ifdef _WIN32 appK2S.SetExt( wxT( "exe" ) ); - #endif +#endif // Ensure the window is on top Raise(); @@ -457,6 +470,11 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : m_eventCounterTimer->Start( 1000 ); } + Bind( EDA_EVT_CLOSE_DIALOG_BOOK_REPORTER, &PCB_EDIT_FRAME::onCloseModelessBookReporterDialogs, + this ); + Bind( EDA_EVT_CLOSE_NET_INSPECTOR_DIALOG, &PCB_EDIT_FRAME::onCloseNetInspectorDialog, this ); + Bind( EDA_EVT_UNITS_CHANGED, &PCB_EDIT_FRAME::onUnitsChanged, this ); + m_acceptedExts.emplace( KiCadPcbFileExtension, &PCB_ACTIONS::ddAppendBoard ); m_acceptedExts.emplace( LegacyPcbFileExtension, &PCB_ACTIONS::ddAppendBoard ); DragAcceptFiles( true ); @@ -467,17 +485,12 @@ PCB_EDIT_FRAME::~PCB_EDIT_FRAME() { if( ADVANCED_CFG::GetCfg().m_ShowEventCounters ) { - // Stop the timer during destruction early to avoid potential event race conditions (that do happen on windows) + // Stop the timer during destruction early to avoid potential event race conditions (that + // do happen on windows) m_eventCounterTimer->Stop(); delete m_eventCounterTimer; } - // Close modeless dialogs - wxWindow* open_dlg = wxWindow::FindWindowByName( DIALOG_DRC_WINDOW_NAME ); - - if( open_dlg ) - open_dlg->Close( true ); - // Shutdown all running tools if( m_toolManager ) m_toolManager->ShutdownAllTools(); @@ -1059,13 +1072,6 @@ bool PCB_EDIT_FRAME::canCloseWindow( wxCloseEvent& aEvent ) } } - // Close modeless dialogs. They're trouble when they get destroyed after the frame and/or - // board. - wxWindow* open_dlg = wxWindow::FindWindowByName( DIALOG_DRC_WINDOW_NAME ); - - if( open_dlg ) - open_dlg->Close( true ); - return PCB_BASE_EDIT_FRAME::canCloseWindow( aEvent ); } @@ -1082,6 +1088,54 @@ void PCB_EDIT_FRAME::doCloseWindow() GetCanvas()->StopDrawing(); + // Clean up mode-less dialogs. + Unbind( EDA_EVT_CLOSE_DIALOG_BOOK_REPORTER, + &PCB_EDIT_FRAME::onCloseModelessBookReporterDialogs, this ); + Unbind( EDA_EVT_CLOSE_NET_INSPECTOR_DIALOG, &PCB_EDIT_FRAME::onCloseNetInspectorDialog, this ); + Unbind( EDA_EVT_UNITS_CHANGED, &PCB_EDIT_FRAME::onUnitsChanged, this ); + + wxWindow* open_dlg = wxWindow::FindWindowByName( DIALOG_DRC_WINDOW_NAME ); + + if( open_dlg ) + open_dlg->Close( true ); + + if( m_findDialog ) + { + m_findDialog->Destroy(); + m_findDialog = nullptr; + } + + if( m_inspectDrcErrorDlg ) + { + m_inspectDrcErrorDlg->Destroy(); + m_inspectDrcErrorDlg = nullptr; + } + + if( m_inspectClearanceDlg ) + { + m_inspectClearanceDlg->Destroy(); + m_inspectClearanceDlg = nullptr; + } + + if( m_inspectConstraintsDlg ) + { + m_inspectConstraintsDlg->Destroy(); + m_inspectConstraintsDlg = nullptr; + } + + if( m_footprintDiffDlg ) + { + m_footprintDiffDlg->Destroy(); + m_footprintDiffDlg = nullptr; + } + + if( m_netInspectorDlg ) + { + RemoveBoardChangeListener( m_netInspectorDlg ); + m_netInspectorDlg->Destroy(); + m_netInspectorDlg = nullptr; + } + // Delete the auto save file if it exists. wxFileName fn = GetBoard()->GetFileName(); @@ -2338,3 +2392,100 @@ void PCB_EDIT_FRAME::onSize( wxSizeEvent& aEvent ) // Skip() is called in the base class. EDA_DRAW_FRAME::OnSize( aEvent ); } + + +DIALOG_BOOK_REPORTER* PCB_EDIT_FRAME::GetInspectDrcErrorDialog() +{ + if( !m_inspectDrcErrorDlg ) + m_inspectDrcErrorDlg = new DIALOG_BOOK_REPORTER( this, INSPECT_DRC_ERROR_DIALOG_NAME, + _( "Violation Report" ) ); + + return m_inspectDrcErrorDlg; +} + + +DIALOG_BOOK_REPORTER* PCB_EDIT_FRAME::GetInspectClearanceDialog() +{ + if( !m_inspectClearanceDlg ) + m_inspectClearanceDlg = new DIALOG_BOOK_REPORTER( this, INSPECT_CLEARANCE_DIALOG_NAME, + _( "Clearance Report" ) ); + + return m_inspectClearanceDlg; +} + + +DIALOG_BOOK_REPORTER* PCB_EDIT_FRAME::GetInspectConstraintsDialog() +{ + if( !m_inspectConstraintsDlg ) + m_inspectConstraintsDlg = new DIALOG_BOOK_REPORTER( this, INSPECT_CONSTRAINTS_DIALOG_NAME, + _( "Constraints Report" ) ); + + return m_inspectConstraintsDlg; +} + + +DIALOG_BOOK_REPORTER* PCB_EDIT_FRAME::GetFootprintDiffDialog() +{ + if( !m_footprintDiffDlg ) + m_footprintDiffDlg = new DIALOG_BOOK_REPORTER( this, FOOTPRINT_DIFF_DIALOG_NAME, + _( "Diff Footprint with Library" ) ); + + return m_footprintDiffDlg; +} + + +void PCB_EDIT_FRAME::onCloseModelessBookReporterDialogs( wxCommandEvent& aEvent ) +{ + if( m_inspectDrcErrorDlg && aEvent.GetString() == INSPECT_DRC_ERROR_DIALOG_NAME ) + { + m_inspectDrcErrorDlg->Destroy(); + m_inspectDrcErrorDlg = nullptr; + } + else if( m_inspectClearanceDlg && aEvent.GetString() == INSPECT_CLEARANCE_DIALOG_NAME ) + { + m_inspectClearanceDlg->Destroy(); + m_inspectClearanceDlg = nullptr; + } + else if( m_inspectConstraintsDlg && aEvent.GetString() == INSPECT_CONSTRAINTS_DIALOG_NAME ) + { + m_inspectConstraintsDlg->Destroy(); + m_inspectConstraintsDlg = nullptr; + } + else if( m_footprintDiffDlg && aEvent.GetString() == INSPECT_CONSTRAINTS_DIALOG_NAME ) + { + m_footprintDiffDlg->Destroy(); + m_footprintDiffDlg = nullptr; + } +} + + +DIALOG_NET_INSPECTOR* PCB_EDIT_FRAME::GetNetInspectorDialog() +{ + if( !m_netInspectorDlg ) + { + m_netInspectorDlg = new DIALOG_NET_INSPECTOR( this ); + AddBoardChangeListener( m_netInspectorDlg ); + } + + return m_netInspectorDlg; +} + + +void PCB_EDIT_FRAME::onCloseNetInspectorDialog( wxCommandEvent& aEvent ) +{ + if( m_netInspectorDlg ) + { + RemoveBoardChangeListener( m_netInspectorDlg ); + m_netInspectorDlg->Destroy(); + m_netInspectorDlg = nullptr; + } +} + + +void PCB_EDIT_FRAME::onUnitsChanged( wxCommandEvent& aEvent ) +{ + wxCommandEvent evt( EDA_EVT_UNITS_CHANGED ); + + if( m_netInspectorDlg ) + m_netInspectorDlg->HandleWindowEvent( evt ); +} diff --git a/pcbnew/pcb_edit_frame.h b/pcbnew/pcb_edit_frame.h index af838614c2..863d68fc0c 100644 --- a/pcbnew/pcb_edit_frame.h +++ b/pcbnew/pcb_edit_frame.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2010 Jean-Pierre Charras, jp.charras@wanadoo.fr - * Copyright (C) 2010-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2010-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -30,6 +30,8 @@ class PCB_SCREEN; class BOARD; class BOARD_COMMIT; class BOARD_ITEM_CONTAINER; +class DIALOG_BOOK_REPORTER; +class DIALOG_NET_INSPECTOR; class FOOTPRINT; class PCB_TRACK; class PCB_VIA; @@ -702,6 +704,16 @@ public: TOOL_ACTION* GetExportNetlistAction() { return m_exportNetlistAction; } + DIALOG_BOOK_REPORTER* GetInspectDrcErrorDialog(); + + DIALOG_BOOK_REPORTER* GetInspectConstraintsDialog(); + + DIALOG_BOOK_REPORTER* GetInspectClearanceDialog(); + + DIALOG_BOOK_REPORTER* GetFootprintDiffDialog(); + + DIALOG_NET_INSPECTOR* GetNetInspectorDialog(); + DECLARE_EVENT_TABLE() protected: @@ -805,18 +817,24 @@ protected: void saveProjectSettings() override; -public: - PCB_LAYER_BOX_SELECTOR* m_SelLayerBox; // a combo box to display and select active layer + void onCloseModelessBookReporterDialogs( wxCommandEvent& aEvent ); - wxComboBox* m_SelTrackWidthBox; // a choice box to display and select current track width - wxComboBox* m_SelViaSizeBox; // a choice box to display and select current via diameter + void onCloseNetInspectorDialog( wxCommandEvent& aEvent ); + + void onUnitsChanged( wxCommandEvent& aEvent ); + +public: + PCB_LAYER_BOX_SELECTOR* m_SelLayerBox; // a combo box to display and select active layer + + wxComboBox* m_SelTrackWidthBox; // a choice box to display and select current track width + wxComboBox* m_SelViaSizeBox; // a choice box to display and select current via diameter bool m_show_layer_manager_tools; bool m_show_search; - bool m_ZoneFillsDirty; // Board has been modified since last zone fill. + bool m_ZoneFillsDirty; // Board has been modified since last zone fill. - bool m_probingSchToPcb; // Recursion guard when synchronizing selection from schematic + bool m_probingSchToPcb; // Recursion guard when synchronizing selection from schematic private: friend struct PCB::IFACE; @@ -832,6 +850,11 @@ private: TOOL_ACTION* m_exportNetlistAction; DIALOG_FIND* m_findDialog; + DIALOG_BOOK_REPORTER* m_inspectDrcErrorDlg; + DIALOG_BOOK_REPORTER* m_inspectClearanceDlg; + DIALOG_BOOK_REPORTER* m_inspectConstraintsDlg; + DIALOG_BOOK_REPORTER* m_footprintDiffDlg; + DIALOG_NET_INSPECTOR* m_netInspectorDlg; /** * Keep track of viewport so that track net labels can be adjusted when it changes. diff --git a/pcbnew/tools/board_inspection_tool.cpp b/pcbnew/tools/board_inspection_tool.cpp index c024fa5e06..eaf011af48 100644 --- a/pcbnew/tools/board_inspection_tool.cpp +++ b/pcbnew/tools/board_inspection_tool.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -44,12 +45,6 @@ #include -#define LIST_NETS_DIALOG_NAME wxT( "ListNetsDialog" ) -#define INSPECT_CLEARANCE_DIALOG_NAME wxT( "InspectClearanceDialog" ) -#define INSPECT_CONSTRAINTS_DIALOG_NAME wxT( "InspectConstraintsDialog" ) -#define DIFF_FOOTPRINTS_DIALOG_NAME wxT( "DiffFootprintsDialog" ) - - BOARD_INSPECTION_TOOL::BOARD_INSPECTION_TOOL() : PCB_TOOL_BASE( "pcbnew.InspectionTool" ), m_frame( nullptr ) @@ -198,7 +193,7 @@ void BOARD_INSPECTION_TOOL::reportHeader( const wxString& aTitle, BOARD_ITEM* a, { r->Report( wxT( "" ) + EscapeHTML( aTitle ) + wxT( "" ) ); r->Report( wxT( "
    • " ) + EscapeHTML( getItemDescription( a ) ) + wxT( "
    • " ) - + wxT( "
    • " ) + EscapeHTML( getItemDescription( b ) ) + wxT( "
    " ) ); + + wxT( "
  • " ) + EscapeHTML( getItemDescription( b ) ) + wxT( "
  • " ) ); } @@ -209,8 +204,8 @@ void BOARD_INSPECTION_TOOL::reportHeader( const wxString& aTitle, BOARD_ITEM* a, r->Report( wxT( "" ) + EscapeHTML( aTitle ) + wxT( "" ) ); r->Report( wxT( "
    • " ) + EscapeHTML( layerStr ) + wxT( "
    • " ) - + wxT( "
    • " ) + EscapeHTML( getItemDescription( a ) ) + wxT( "
    • " ) - + wxT( "
    • " ) + EscapeHTML( getItemDescription( b ) ) + wxT( "
    " ) ); + + wxT( "
  • " ) + EscapeHTML( getItemDescription( a ) ) + wxT( "
  • " ) + + wxT( "
  • " ) + EscapeHTML( getItemDescription( b ) ) + wxT( "
  • " ) ); } @@ -248,14 +243,12 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr& aDR BOARD_CONNECTED_ITEM* ac = dynamic_cast( a ); BOARD_CONNECTED_ITEM* bc = dynamic_cast( b ); PCB_LAYER_ID layer = m_frame->GetActiveLayer(); - wxWindow* window = wxWindow::FindWindowByName( INSPECT_CLEARANCE_DIALOG_NAME ); - DIALOG_BOOK_REPORTER* dialog = dynamic_cast( window ); - if( !dialog ) - { - dialog = new DIALOG_BOOK_REPORTER( m_frame, INSPECT_CLEARANCE_DIALOG_NAME, - _( "Violation Report" ) ); - } + wxCHECK( m_frame, /* void */ ); + + DIALOG_BOOK_REPORTER* dialog = m_frame->GetInspectDrcErrorDialog(); + + wxCHECK( dialog, /* void */ ); WX_HTML_REPORT_BOX* r = nullptr; bool compileError = false; @@ -478,7 +471,8 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr& aDR { layer = b->GetLayer(); } - else if( a->Type() == PCB_PAD_T && static_cast( a )->GetAttribute() == PAD_ATTRIB::SMD ) + else if( a->Type() == PCB_PAD_T + && static_cast( a )->GetAttribute() == PAD_ATTRIB::SMD ) { PAD* pad = static_cast( a ); @@ -487,7 +481,8 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr& aDR else layer = B_Cu; } - else if( b->Type() == PCB_PAD_T && static_cast( a )->GetAttribute() == PAD_ATTRIB::SMD ) + else if( b->Type() == PCB_PAD_T + && static_cast( a )->GetAttribute() == PAD_ATTRIB::SMD ) { PAD* pad = static_cast( b ); @@ -553,7 +548,12 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr& aDR int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent ) { + wxCHECK( m_frame, 0 ); + PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool(); + + wxCHECK( selTool, 0 ); + const PCB_SELECTION& selection = selTool->GetSelection(); if( selection.Size() != 2 ) @@ -596,14 +596,9 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent ) // a and b could be null after group tests above. wxCHECK( a && b, 0 ); - wxWindow* window = wxWindow::FindWindowByName( INSPECT_CLEARANCE_DIALOG_NAME ); - DIALOG_BOOK_REPORTER* dialog = dynamic_cast( window ); + DIALOG_BOOK_REPORTER* dialog = m_frame->GetInspectClearanceDialog(); - if( !dialog ) - { - dialog = new DIALOG_BOOK_REPORTER( m_frame, INSPECT_CLEARANCE_DIALOG_NAME, - _( "Clearance Report" ) ); - } + wxCHECK( dialog, 0 ); dialog->DeleteAllPages(); @@ -722,8 +717,8 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent ) clearance = constraint.m_Value.Min(); r->Report( "" ); - r->Report( wxString::Format( _( "Overridden by larger physical hole clearance from %s;" - "clearance: %s." ), + r->Report( wxString::Format( _( "Overridden by larger physical hole clearance " + "from %s; clearance: %s." ), EscapeHTML( constraint.GetName() ), m_frame->StringFromValue( clearance, true ) ) ); } @@ -781,7 +776,8 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent ) if( clearance < 0 ) { - r->Report( wxString::Format( _( "Resolved clearance: %s; clearance will not be tested." ), + r->Report( wxString::Format( _( "Resolved clearance: %s; clearance will not be " + "tested." ), m_frame->StringFromValue( clearance, true ) ) ); } else @@ -817,7 +813,8 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent ) r->Report( "" ); r->Report( "" ); r->Report( "" ); - reportHeader( _( "Diff pair max uncoupled length resolution for:" ), ac, bc, active, r ); + reportHeader( _( "Diff pair max uncoupled length resolution for:" ), ac, bc, + active, r ); if( !drcEngine.HasRulesForConstraintType( DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT ) ) { @@ -1132,7 +1129,12 @@ int BOARD_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent ) { #define EVAL_RULES( constraint, a, b, layer, r ) drcEngine.EvalRules( constraint, a, b, layer, r ) + wxCHECK( m_frame, 0 ); + PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool(); + + wxCHECK( selTool, 0 ); + const PCB_SELECTION& selection = selTool->GetSelection(); if( selection.Size() != 1 ) @@ -1141,14 +1143,9 @@ int BOARD_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent ) return 0; } - wxWindow* window = wxWindow::FindWindowByName( INSPECT_CONSTRAINTS_DIALOG_NAME ); - DIALOG_BOOK_REPORTER* dialog = dynamic_cast( window ); + DIALOG_BOOK_REPORTER* dialog = m_frame->GetInspectConstraintsDialog(); - if( !dialog ) - { - dialog = new DIALOG_BOOK_REPORTER( m_frame, INSPECT_CONSTRAINTS_DIALOG_NAME, - _( "Constraints Report" ) ); - } + wxCHECK( dialog, 0 ); dialog->DeleteAllPages(); @@ -1287,7 +1284,8 @@ int BOARD_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent ) r->Report( "" ); r->Report( _( "Report may be incomplete: some footprint courtyards are malformed." ) + wxS( "  " ) - + wxS( "" ) + _( "Run DRC for a full analysis." ) + wxS( "" ) ); + + wxS( "" ) + _( "Run DRC for a full analysis." ) + + wxS( "" ) ); } r->Report( "" ); @@ -1310,7 +1308,8 @@ int BOARD_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent ) r->Report( "" ); r->Report( _( "Report may be incomplete: some footprint courtyards are malformed." ) + wxS( "  " ) - + wxS( "" ) + _( "Run DRC for a full analysis." ) + wxS( "" ) ); + + wxS( "" ) + _( "Run DRC for a full analysis." ) + + wxS( "" ) ); } drcEngine.ProcessAssertions( item, []( const DRC_CONSTRAINT* c ){}, r ); @@ -1324,7 +1323,12 @@ int BOARD_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent ) int BOARD_INSPECTION_TOOL::DiffFootprint( const TOOL_EVENT& aEvent ) { + wxCHECK( m_frame, 0 ); + PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool(); + + wxCHECK( selTool, 0 ); + const PCB_SELECTION& selection = selTool->RequestSelection( []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool ) { @@ -1341,18 +1345,14 @@ int BOARD_INSPECTION_TOOL::DiffFootprint( const TOOL_EVENT& aEvent ) if( selection.Size() != 1 ) { - m_frame->ShowInfoBarError( _( "Select a footprint to diff against its library equivalent." ) ); + m_frame->ShowInfoBarError( _( "Select a footprint to diff against its library " + "equivalent." ) ); return 0; } - wxWindow* window = wxWindow::FindWindowByName( DIFF_FOOTPRINTS_DIALOG_NAME ); - DIALOG_BOOK_REPORTER* dialog = dynamic_cast( window ); + DIALOG_BOOK_REPORTER* dialog = m_frame->GetFootprintDiffDialog(); - if( !dialog ) - { - dialog = new DIALOG_BOOK_REPORTER( m_frame, DIFF_FOOTPRINTS_DIALOG_NAME, - _( "Diff Footprint with Library" ) ); - } + wxCHECK( dialog, 0 ); dialog->DeleteAllPages(); @@ -1387,14 +1387,16 @@ int BOARD_INSPECTION_TOOL::DiffFootprint( const TOOL_EVENT& aEvent ) { r->Report( _( "The library is not included in the current configuration." ) + wxS( "   " ) - + wxS( "" ) + _( "Manage Footprint Libraries" ) + wxS( "" ) ); + + wxS( "" ) + _( "Manage Footprint Libraries" ) + + wxS( "" ) ); } else if( !libTable->HasLibrary( libName, true ) ) { r->Report( _( "The library is not enabled in the current configuration." ) + wxS( "   " ) - + wxS( "" ) + _( "Manage Footprint Libraries" ) + wxS( "" ) ); + + wxS( "" ) + _( "Manage Footprint Libraries" ) + + wxS( "" ) ); } else @@ -1870,11 +1872,11 @@ void BOARD_INSPECTION_TOOL::calculateSelectionRatsnest( const VECTOR2I& aDelta ) int BOARD_INSPECTION_TOOL::ListNets( const TOOL_EVENT& aEvent ) { - wxWindow* window = wxWindow::FindWindowByName( LIST_NETS_DIALOG_NAME ); - DIALOG_NET_INSPECTOR* dialog = dynamic_cast( window ); + wxCHECK( m_frame, 0 ); - if( !dialog ) - dialog = new DIALOG_NET_INSPECTOR( m_frame, LIST_NETS_DIALOG_NAME ); + DIALOG_NET_INSPECTOR* dialog = m_frame->GetNetInspectorDialog(); + + wxCHECK( dialog, 0 ); dialog->Raise(); dialog->Show( true ); diff --git a/pcbnew/widgets/pcb_search_pane.cpp b/pcbnew/widgets/pcb_search_pane.cpp index 02f7aa3c0c..de8f8b854d 100644 --- a/pcbnew/widgets/pcb_search_pane.cpp +++ b/pcbnew/widgets/pcb_search_pane.cpp @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -30,10 +30,12 @@ PCB_SEARCH_PANE::PCB_SEARCH_PANE( PCB_EDIT_FRAME* aFrame ) : if( m_brd != nullptr ) m_brd->AddListener( this ); - m_pcbFrame->Connect( UNITS_CHANGED, wxCommandEventHandler( PCB_SEARCH_PANE::onUnitsChanged ), + m_pcbFrame->Connect( EDA_EVT_UNITS_CHANGED, + wxCommandEventHandler( PCB_SEARCH_PANE::onUnitsChanged ), nullptr, this ); - m_pcbFrame->Connect( BOARD_CHANGED, wxCommandEventHandler( PCB_SEARCH_PANE::onBoardChanged ), + m_pcbFrame->Connect( EDA_EVT_BOARD_CHANGED, + wxCommandEventHandler( PCB_SEARCH_PANE::onBoardChanged ), nullptr, this ); wxFont infoFont = KIUI::GetDockedPaneFont( this ); @@ -49,9 +51,11 @@ PCB_SEARCH_PANE::PCB_SEARCH_PANE( PCB_EDIT_FRAME* aFrame ) : PCB_SEARCH_PANE::~PCB_SEARCH_PANE() { - m_pcbFrame->Disconnect( UNITS_CHANGED, wxCommandEventHandler( PCB_SEARCH_PANE::onUnitsChanged ), + m_pcbFrame->Disconnect( EDA_EVT_UNITS_CHANGED, + wxCommandEventHandler( PCB_SEARCH_PANE::onUnitsChanged ), nullptr, this ); - m_pcbFrame->Disconnect( BOARD_CHANGED, wxCommandEventHandler( PCB_SEARCH_PANE::onBoardChanged ), + m_pcbFrame->Disconnect( EDA_EVT_BOARD_CHANGED, + wxCommandEventHandler( PCB_SEARCH_PANE::onBoardChanged ), nullptr, this ); } @@ -137,4 +141,4 @@ void PCB_SEARCH_PANE::OnBoardItemsChanged( BOARD& aBoard, std::vector