7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-07 18:45:32 +00:00

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.
This commit is contained in:
Wayne Stambaugh 2023-03-13 12:03:48 -04:00
parent dc78797274
commit 66f6168163
35 changed files with 747 additions and 384 deletions

View File

@ -4,7 +4,7 @@
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
* 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 )

View File

@ -26,22 +26,17 @@
#include <wx/wxhtml.h>
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();
}

View File

@ -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 ) );
}

View File

@ -56,6 +56,7 @@
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnClose">OnClose</event>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bMainSizer</property>
@ -136,7 +137,6 @@
<property name="minimum_size"></property>
<property name="name">m_sdbSizer</property>
<property name="permission">protected</property>
<event name="OnOKButtonClick">OnOK</event>
</object>
</object>
</object>

View File

@ -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:

View File

@ -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 );

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2013 Wayne Stambaugh <stambaughw@gmail.com>
* 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 <functional>
#include <kiface_ids.h>
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<int>( aUnits ) );
e.SetClientData( this );
ProcessEventLocally( e );
}

View File

@ -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 );
}
}

View File

@ -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 <maciej.suminski@cern.ch>
*
* 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 )

View File

@ -49,6 +49,10 @@
#include <string_utils.h>
#include <kiplatform/ui.h>
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<EE_INSPECTION_TOOL>()->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
}

View File

@ -34,6 +34,12 @@
#include <erc_settings.h>
/**
* Event sent to parent when dialog is mode-less.
*/
wxDECLARE_EVENT( EDA_EVT_CLOSE_ERC_DIALOG, wxCommandEvent );
#define DIALOG_ERC_WINDOW_NAME "DialogErcWindowName"

View File

@ -91,12 +91,12 @@ public:
{
m_eval = std::make_unique<NUMERIC_EVALUATOR>( 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 )

View File

@ -293,7 +293,7 @@ void FIELDS_GRID_TABLE<T>::initGrid( WX_GRID* aGrid )
m_eval = std::make_unique<NUMERIC_EVALUATOR>( m_frame->GetUserUnits() );
m_frame->Bind( UNITS_CHANGED, &FIELDS_GRID_TABLE<T>::onUnitsChanged, this );
m_frame->Bind( EDA_EVT_UNITS_CHANGED, &FIELDS_GRID_TABLE<T>::onUnitsChanged, this );
}
@ -316,7 +316,7 @@ FIELDS_GRID_TABLE<T>::~FIELDS_GRID_TABLE()
m_fontAttr->DecRef();
m_colorAttr->DecRef();
m_frame->Unbind( UNITS_CHANGED, &FIELDS_GRID_TABLE<T>::onUnitsChanged, this );
m_frame->Unbind( EDA_EVT_UNITS_CHANGED, &FIELDS_GRID_TABLE<T>::onUnitsChanged, this );
}

View File

@ -27,7 +27,9 @@
#include <symbol_library.h>
#include <confirm.h>
#include <connection_graph.h>
#include <dialogs/dialog_erc.h>
#include <dialogs/dialog_schematic_find.h>
#include <dialogs/dialog_book_reporter.h>
#include <eeschema_id.h>
#include <executable_names.h>
#include <gestfich.h>
@ -90,6 +92,9 @@
#include <drawing_sheet/ds_proxy_view_item.h>
#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;
}
}

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras wanadoo.fr
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
* 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<EDA_ITEM*>& 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

View File

@ -48,12 +48,8 @@
#include <math/util.h> // for KiROUND
#define DIFF_SYMBOLS_DIALOG_NAME wxT( "DiffSymbolsDialog" )
EE_INSPECTION_TOOL::EE_INSPECTION_TOOL() :
EE_TOOL_BASE<SCH_BASE_FRAME>( "eeschema.InspectionTool" ),
m_ercDialog( nullptr )
EE_TOOL_BASE<SCH_BASE_FRAME>( "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<SCH_EDIT_FRAME*>( m_frame ) );
SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( 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<SCH_EDIT_FRAME*>( 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<SCH_EDIT_FRAME*>( 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<SCH_EDIT_FRAME*>( m_frame );
wxCHECK( frame, 0 );
DIALOG_ERC* dlg = frame->GetErcDialog();
wxCHECK( dlg, 0 );
EE_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
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_TOOL>();
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<SCH_MARKER*>( selection.Front() ) );
}
dlg->SelectMarker( static_cast<SCH_MARKER*>( 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<SCH_MARKER*>( 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<SCH_EDIT_FRAME*>( 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<SCH_EDIT_FRAME*>( 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<DIALOG_BOOK_REPORTER*>( 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( "<h7>" ) + _( "Schematic vs library diff for:" ) + wxS( "</h7>" ) );
r->Report( wxS( "<ul><li>" ) + EscapeHTML( symbolDesc ) + wxS( "</li>" )
+ wxS( "<li>" ) + _( "Library: " ) + EscapeHTML( libName ) + wxS( "</li>" )
+ wxS( "<li>" ) + _( "Library item: " ) + EscapeHTML( symbolName ) + wxS( "</li></ul>" ) );
+ wxS( "<li>" ) + _( "Library item: " ) + EscapeHTML( symbolName )
+ wxS( "</li></ul>" ) );
r->Report( "" );

View File

@ -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 */

View File

@ -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 );

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 2009-2015 Jean-Pierre Charras, jp.charras wanadoo.fr
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@gmail.com>
* 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 );
/**

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2008-2016 Wayne Stambaugh <stambaughw@gmail.com>
* 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<wxEvtHandler*> m_boardChangeListeners;
};
#endif // PCB_BASE_FRAME_H

View File

@ -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;
}

View File

@ -50,6 +50,9 @@
#include <vector>
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<LIST_ITEM*> 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<uint64_t, MAX_CU_LAYERS> m_layer_wire_length{};
// dirty bits to record when some attribute has changed. this is to
// avoid unnecessary resort operations.
std::vector<char> 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<LIST_ITEM*> 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<uint64_t, MAX_CU_LAYERS> m_layer_wire_length{};
// dirty bits to record when some attribute has changed. this is to
// avoid unnecessary resort operations.
std::vector<char> 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<std::unique_ptr<LIST_ITEM>> 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<LIST_ITEM>& 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<std::unique_ptr<LIST_ITEM>> 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<int>( sorting_column->GetModelColumn() ) : -1;
g_settings.sorting_column = sorting_column ?
static_cast<int>( 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<PCB_TRACK*>( item ) )
{
new_item->AddLayerWireLength( track->GetLength(), static_cast<int>( track->GetLayer() ) );
new_item->AddLayerWireLength( track->GetLength(),
static_cast<int>( 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();
}

View File

@ -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<int> 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<BOARD_ITEM*>& aBoardItems ) override;
virtual void OnBoardItemRemoved( BOARD& aBoard, BOARD_ITEM* aBoardItem ) override;
virtual void OnBoardItemsRemoved( BOARD& aBoard, std::vector<BOARD_ITEM*>& aBoardItems ) override;
virtual void OnBoardItemsRemoved( BOARD& aBoard,
std::vector<BOARD_ITEM*>& aBoardItems ) override;
virtual void OnBoardNetSettingsChanged( BOARD& aBoard ) override;
virtual void OnBoardItemChanged( BOARD& aBoard, BOARD_ITEM* aBoardItem ) override;
virtual void OnBoardItemsChanged( BOARD& aBoard, std::vector<BOARD_ITEM*>& aBoardItems ) override;
virtual void OnBoardItemsChanged( BOARD& aBoard,
std::vector<BOARD_ITEM*>& aBoardItems ) override;
virtual void OnBoardHighlightNetChanged( BOARD& aBoard ) override;
protected:
virtual void onClose( wxCloseEvent& aEvent ) override;
private:
struct COLUMN_DESC;
class LIST_ITEM;

View File

@ -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 );

View File

@ -56,6 +56,7 @@
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnClose">onClose</event>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bSizerMain</property>
@ -522,14 +523,14 @@
<property name="border">5</property>
<property name="flag">wxEXPAND|wxALL</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="0">
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bSizerListButtons</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxTOP|wxBOTTOM|wxLEFT</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxBitmapButton" expanded="0">
<property name="BottomDockable">1</property>
@ -603,7 +604,7 @@
</object>
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxTOP|wxBOTTOM|wxLEFT</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxBitmapButton" expanded="0">
<property name="BottomDockable">1</property>
@ -687,7 +688,7 @@
</object>
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
<property name="proportion">0</property>
<object class="wxBitmapButton" expanded="0">
<property name="BottomDockable">1</property>

Some files were not shown because too many files have changed in this diff Show More