Fix zone manager crash when no board is loaded

Fixes https://gitlab.com/kicad/code/kicad/-/issues/17187
This commit is contained in:
Ethan Chien 2024-03-01 10:47:49 +08:00 committed by Wayne Stambaugh
parent a902898522
commit 8d19d27483
2 changed files with 38 additions and 28 deletions

View File

@ -60,6 +60,13 @@
#include "pane_zone_viewer.h" #include "pane_zone_viewer.h"
#include "zone_manager_preference.h" #include "zone_manager_preference.h"
inline void DIALOG_ZONE_MANAGER::FitCanvasToScreen()
{
if( PANEL_ZONE_GAL* canvas = m_zoneViewer->GetZoneGAL() )
canvas->ZoomFitScreen();
}
inline void DIALOG_ZONE_MANAGER::PostProcessZoneViewSelectionChange( wxDataViewItem const& aItem ) inline void DIALOG_ZONE_MANAGER::PostProcessZoneViewSelectionChange( wxDataViewItem const& aItem )
{ {
bool textCtrlHasFocus = m_filterCtrl->HasFocus(); bool textCtrlHasFocus = m_filterCtrl->HasFocus();
@ -119,12 +126,11 @@ void DIALOG_ZONE_MANAGER::OnIDle( wxIdleEvent& aEvent )
m_viewZonesOverview->SetFocus(); m_viewZonesOverview->SetFocus();
Unbind( wxEVT_IDLE, &DIALOG_ZONE_MANAGER::OnIDle, this ); Unbind( wxEVT_IDLE, &DIALOG_ZONE_MANAGER::OnIDle, this );
//NOTE - Required on Linux if( !m_needZoomGAL )
if( m_needZoomGAL ) return;
{
Canvas().ZoomFitScreen(); m_needZoomGAL = false;
m_needZoomGAL = false; FitCanvasToScreen();
}
} }
@ -136,7 +142,7 @@ DIALOG_ZONE_MANAGER::DIALOG_ZONE_MANAGER( PCB_BASE_FRAME* aParent, ZONE_SETTINGS
new MODEL_ZONES_OVERVIEW_TABLE( m_zonesContainer->GetZonesPriorityContainers(), new MODEL_ZONES_OVERVIEW_TABLE( m_zonesContainer->GetZonesPriorityContainers(),
aParent->GetBoard(), aParent, this ) ), aParent->GetBoard(), aParent, this ) ),
m_zoneViewer( new PANE_ZONE_VIEWER( this, aParent ) ), m_priorityDragIndex( {} ), m_zoneViewer( new PANE_ZONE_VIEWER( this, aParent ) ), m_priorityDragIndex( {} ),
m_needZoomGAL( true ) m_needZoomGAL( true ), m_isFillingZones( false ), m_zoneFillComplete( false )
{ {
#ifdef __APPLE__ #ifdef __APPLE__
m_sizerZoneOP->InsertSpacer( m_sizerZoneOP->GetItemCount(), 5 ); m_sizerZoneOP->InsertSpacer( m_sizerZoneOP->GetItemCount(), 5 );
@ -196,7 +202,7 @@ DIALOG_ZONE_MANAGER::DIALOG_ZONE_MANAGER( PCB_BASE_FRAME* aParent, ZONE_SETTINGS
m_MainBoxSizer->Fit( this ); m_MainBoxSizer->Fit( this );
//NOTE - Works on Windows and MacOS , need further handling in IDLE on Ubuntu //NOTE - Works on Windows and MacOS , need further handling in IDLE on Ubuntu
Canvas().ZoomFitScreen(); FitCanvasToScreen();
} }
DIALOG_ZONE_MANAGER::~DIALOG_ZONE_MANAGER() = default; DIALOG_ZONE_MANAGER::~DIALOG_ZONE_MANAGER() = default;
@ -362,30 +368,38 @@ void DIALOG_ZONE_MANAGER::OnFilterCtrlEnter( wxCommandEvent& aEvent )
void DIALOG_ZONE_MANAGER::OnButtonApplyClick( wxCommandEvent& aEvent ) void DIALOG_ZONE_MANAGER::OnButtonApplyClick( wxCommandEvent& aEvent )
{ {
if( m_isFillingZones )
return;
m_isFillingZones = true;
m_zonesContainer->FlushZoneSettingsChange(); m_zonesContainer->FlushZoneSettingsChange();
m_zonesContainer->FlushPriorityChange(); m_zonesContainer->FlushPriorityChange();
BOARD* board = m_pcbFrame->GetBoard(); BOARD* board = m_pcbFrame->GetBoard();
board->IncrementTimeStamp(); board->IncrementTimeStamp();
m_commit = std::make_unique<BOARD_COMMIT>( m_pcbFrame ); auto commit = std::make_unique<BOARD_COMMIT>( m_pcbFrame );
m_filler = std::make_unique<ZONE_FILLER>( board, m_commit.get() ); m_filler = std::make_unique<ZONE_FILLER>( board, commit.get() );
auto reporter = std::make_unique<WX_PROGRESS_REPORTER>( this, _( "Fill All Zones" ), 5 ); auto reporter = std::make_unique<WX_PROGRESS_REPORTER>( this, _( "Fill All Zones" ), 5 );
m_filler->SetProgressReporter( reporter.get() ); m_filler->SetProgressReporter( reporter.get() );
board->Zones() = m_zonesContainer->GetClonedZoneList(); board->Zones() = m_zonesContainer->GetClonedZoneList();
m_filler->Fill( board->Zones() ); //NOTE - Nether revert nor commit is needed here , cause the cloned zones are not owned by the pcb frame
m_zoneFillComplete = m_filler->Fill( board->Zones() );
board->BuildConnectivity(); board->BuildConnectivity();
board->Zones() = m_zonesContainer->GetOriginalZoneList(); board->Zones() = m_zonesContainer->GetOriginalZoneList();
PANEL_ZONE_GAL* gal = m_zoneViewer->GetZoneGAL(); if( auto gal = m_zoneViewer->GetZoneGAL() )
gal->RedrawRatsnest(); {
gal->GetView()->UpdateItems(); gal->RedrawRatsnest();
gal->Refresh(); gal->GetView()->UpdateItems();
int layer = gal->GetLayer(); gal->Refresh();
gal->ActivateSelectedZone( int layer = gal->GetLayer();
m_modelZoneOverviewTable->GetZone( m_viewZonesOverview->GetSelection() ) ); gal->ActivateSelectedZone(
gal->OnLayerSelected( layer ); m_modelZoneOverviewTable->GetZone( m_viewZonesOverview->GetSelection() ) );
gal->OnLayerSelected( layer );
}
m_isFillingZones = false;
} }
@ -447,8 +461,3 @@ void DIALOG_ZONE_MANAGER::MoveSelectedZonePriority( ZONE_INDEX_MOVEMENT aMove )
PostProcessZoneViewSelectionChange( new_item ); PostProcessZoneViewSelectionChange( new_item );
} }
} }
PANEL_ZONE_GAL& DIALOG_ZONE_MANAGER::Canvas()
{
return *m_zoneViewer->GetZoneGAL();
}

View File

@ -119,13 +119,13 @@ protected:
void OnTableCharHook( wxKeyEvent& event ) override; void OnTableCharHook( wxKeyEvent& event ) override;
PANEL_ZONE_GAL& Canvas();
private: private:
void GenericProcessChar( wxKeyEvent& event ); void GenericProcessChar( wxKeyEvent& event );
void OnIDle( wxIdleEvent& aEvent ); void OnIDle( wxIdleEvent& aEvent );
void FitCanvasToScreen();
private: private:
PCB_BASE_FRAME* m_pcbFrame; PCB_BASE_FRAME* m_pcbFrame;
@ -136,8 +136,9 @@ private:
PANE_ZONE_VIEWER* m_zoneViewer; PANE_ZONE_VIEWER* m_zoneViewer;
std::optional<unsigned> m_priorityDragIndex; std::optional<unsigned> m_priorityDragIndex;
std::unique_ptr<ZONE_FILLER> m_filler; std::unique_ptr<ZONE_FILLER> m_filler;
std::unique_ptr<COMMIT> m_commit;
bool m_needZoomGAL; bool m_needZoomGAL;
bool m_isFillingZones;
bool m_zoneFillComplete;
}; };
#endif #endif