Don't allow zone filling during other editing operations.

It's a very heavy op, and is likely to violate all manner of
assumptions the other ops make.

Fixes https://gitlab.com/kicad/code/kicad/issues/12736
This commit is contained in:
Jeff Young 2022-11-14 23:39:08 +00:00
parent 93c6d99a6d
commit 9724f6e736
13 changed files with 146 additions and 102 deletions

View File

@ -23,6 +23,7 @@
#include <dialogs/dialog_pns_length_tuning_settings.h>
#include <tool/tool_manager.h>
#include <tools/pcb_actions.h>
#include <tools/zone_filler_tool.h>
#include "pns_router.h"
#include "pns_meander_placer.h" // fixme: move settings to separate header
#include "pns_tune_status_popup.h"
@ -239,6 +240,12 @@ void LENGTH_TUNER_TOOL::performTuning()
meanderSettingsDialog( dummy );
statusPopup.Show();
}
// TODO: It'd be nice to be able to say "don't allow any non-trivial editing actions",
// but we don't at present have that, so we just knock out some of the egregious ones.
else if( ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
{
wxBell();
}
else
{
evt->SetPassEvent();

View File

@ -56,6 +56,7 @@ using namespace std::placeholders;
#include <tools/pcb_selection_tool.h>
#include <tools/pcb_grid_helper.h>
#include <tools/drc_tool.h>
#include <tools/zone_filler_tool.h>
#include <drc/drc_interactive_courtyard_clearance.h>
#include <project.h>
@ -1416,6 +1417,12 @@ void ROUTER_TOOL::performRouting()
{
m_menu.ShowContextMenu( selection() );
}
// TODO: It'd be nice to be able to say "don't allow any non-trivial editing actions",
// but we don't at present have that, so we just knock out some of the egregious ones.
else if( ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
{
wxBell();
}
else
{
evt->SetPassEvent();
@ -1868,11 +1875,13 @@ void ROUTER_TOOL::performDragging( int aMode )
}
else if( evt->Category() == TC_COMMAND )
{
// disallow editing commands
// TODO: It'd be nice to be able to say "don't allow any non-trivial editing actions",
// but we don't at present have that, so we just knock out some of the egregious ones.
if( evt->IsAction( &ACTIONS::cut )
|| evt->IsAction( &ACTIONS::copy )
|| evt->IsAction( &ACTIONS::paste )
|| evt->IsAction( &ACTIONS::pasteSpecial ) )
|| evt->IsAction( &ACTIONS::pasteSpecial )
|| ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
{
wxBell();
}
@ -2262,11 +2271,13 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
}
else if( evt->Category() == TC_COMMAND )
{
// disallow editing commands
// TODO: It'd be nice to be able to say "don't allow any non-trivial editing actions",
// but we don't at present have that, so we just knock out some of the egregious ones.
if( evt->IsAction( &ACTIONS::cut )
|| evt->IsAction( &ACTIONS::copy )
|| evt->IsAction( &ACTIONS::paste )
|| evt->IsAction( &ACTIONS::pasteSpecial ) )
|| evt->IsAction( &ACTIONS::pasteSpecial )
|| ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
{
wxBell();
}

View File

@ -61,6 +61,7 @@
#include <tools/pcb_selection_tool.h>
#include <tools/edit_tool.h>
#include <tools/tool_event_utils.h>
#include <tools/zone_filler_tool.h>
#include <router/router_tool.h>
#include <view/view_controls.h>
#include <view/view_group.h>
@ -1153,6 +1154,10 @@ int BOARD_EDITOR_CONTROL::PlaceFootprint( const TOOL_EVENT& aEvent )
// Calling 'Properties' action clears the selection, so we need to restore it
reselect = true;
}
else if( fp && ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
{
wxBell();
}
else
{
evt->SetPassEvent();

View File

@ -30,7 +30,7 @@
#include <board_commit.h>
#include <scoped_set_reset.h>
#include <painter.h>
#include <board.h>
#include <tools/zone_filler_tool.h>
#include <board_design_settings.h>
#include <footprint.h>
#include <fp_shape.h>
@ -564,24 +564,22 @@ int DRAWING_TOOL::InteractivePlaceWithPreview( const TOOL_EVENT& aEvent,
m_toolMgr->PrimeTool( aEvent.Position() );
// Main loop: keep receiving events
wxPoint wxCursorPosition = wxPoint();
wxPoint wxPreviousCursorPosition = wxPoint( 0, 0 );
VECTOR2I cursorPosition;
VECTOR2I previousCursorPosition;
view()->ClearPreview();
view()->InitPreview();
for( BOARD_ITEM* item : aPreview )
{
item->Move( wxCursorPosition - wxPreviousCursorPosition );
item->Move( cursorPosition - previousCursorPosition );
view()->AddToPreview( item );
}
while( TOOL_EVENT* evt = Wait() )
{
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
VECTOR2D pos = m_controls->GetCursorPosition();
wxCursorPosition.x = pos.x;
wxCursorPosition.y = pos.y;
cursorPosition = m_controls->GetCursorPosition();
if( evt->IsCancelInteractive() )
{
@ -589,25 +587,19 @@ int DRAWING_TOOL::InteractivePlaceWithPreview( const TOOL_EVENT& aEvent,
cancelled = true;
break;
}
if( evt->IsMotion() )
else if( evt->IsMotion() )
{
view()->ShowPreview( false );
for( auto item : aPreview )
{
item->Move( wxCursorPosition - wxPreviousCursorPosition );
}
for( BOARD_ITEM* item : aPreview )
item->Move( cursorPosition - previousCursorPosition );
view()->ShowPreview( true );
wxPreviousCursorPosition.x = wxCursorPosition.x;
wxPreviousCursorPosition.y = wxCursorPosition.y;
previousCursorPosition = cursorPosition;
}
else if( evt->IsActivate() )
{
if( evt->IsMoveTool() )
{
// leave ourselves on the stack so we come back after the move
@ -653,7 +645,7 @@ int DRAWING_TOOL::InteractivePlaceWithPreview( const TOOL_EVENT& aEvent,
for( BOARD_ITEM* item : aItems )
{
item->Move( wxCursorPosition );
item->Move( cursorPosition );
if( item->Type() == PCB_GROUP_T )
static_cast<PCB_GROUP*>( item )->AddChildrenToCommit( commit );
@ -666,6 +658,12 @@ int DRAWING_TOOL::InteractivePlaceWithPreview( const TOOL_EVENT& aEvent,
break;
}
// TODO: It'd be nice to be able to say "don't allow any non-trivial editing actions",
// but we don't at present have that, so we just knock out some of the egregious ones.
else if( ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
{
wxBell();
}
else
{
evt->SetPassEvent();

View File

@ -45,6 +45,7 @@
#include <tools/pcb_selection_tool.h>
#include <tools/tool_event_utils.h>
#include <tools/zone_create_helper.h>
#include <tools/zone_filler_tool.h>
#include <view/view.h>
#include <widgets/appearance_controls.h>
#include <widgets/infobar.h>
@ -741,6 +742,10 @@ int DRAWING_TOOL::PlaceImage( const TOOL_EVENT& aEvent )
{
cleanup();
}
else if( image && ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
{
wxBell();
}
else
{
evt->SetPassEvent();
@ -987,6 +992,10 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
selection().SetReferencePoint( cursorPos );
m_view->Update( &selection() );
}
else if( text && ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
{
wxBell();
}
else if( evt->IsAction( &PCB_ACTIONS::properties ) )
{
if( text )
@ -1413,34 +1422,27 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
// Show a preview of the item
m_view->Update( &preview );
}
else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) )
else if( dimension && evt->IsAction( &PCB_ACTIONS::layerChanged ) )
{
if( dimension )
PCB_LAYER_ID layer = m_frame->GetActiveLayer();
if( !m_view->IsLayerVisible( layer ) )
{
PCB_LAYER_ID layer = m_frame->GetActiveLayer();
if( !m_view->IsLayerVisible( layer ) )
{
m_frame->GetAppearancePanel()->SetLayerVisible( layer, true );
m_frame->GetCanvas()->Refresh();
}
dimension->SetLayer( layer );
dimension->Text().SetTextSize( boardSettings.GetTextSize( layer ) );
dimension->Text().SetTextThickness( boardSettings.GetTextThickness( layer ) );
dimension->Text().SetItalic( boardSettings.GetTextItalic( layer ) );
dimension->SetLineThickness( boardSettings.GetLineThickness( layer ) );
dimension->Update();
m_view->Update( &preview );
frame()->SetMsgPanel( dimension );
}
else
{
evt->SetPassEvent();
m_frame->GetAppearancePanel()->SetLayerVisible( layer, true );
m_frame->GetCanvas()->Refresh();
}
dimension->SetLayer( layer );
dimension->Text().SetTextSize( boardSettings.GetTextSize( layer ) );
dimension->Text().SetTextThickness( boardSettings.GetTextThickness( layer ) );
dimension->Text().SetItalic( boardSettings.GetTextItalic( layer ) );
dimension->SetLineThickness( boardSettings.GetLineThickness( layer ) );
dimension->Update();
m_view->Update( &preview );
frame()->SetMsgPanel( dimension );
}
else if( evt->IsAction( &PCB_ACTIONS::properties ) )
else if( dimension && evt->IsAction( &PCB_ACTIONS::properties ) )
{
if( step == SET_END || step == SET_HEIGHT )
{
@ -1451,9 +1453,13 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
}
else
{
evt->SetPassEvent();
wxBell();
}
}
else if( dimension && ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
{
wxBell();
}
else
{
evt->SetPassEvent();
@ -1623,6 +1629,10 @@ int DRAWING_TOOL::PlaceImportedGraphics( const TOOL_EVENT& aEvent )
commit.Push( _( "Place a DXF_SVG drawing" ) );
break; // This is a one-shot command, not a tool
}
else if( ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
{
wxBell();
}
else
{
evt->SetPassEvent();
@ -1926,20 +1936,6 @@ bool DRAWING_TOOL::drawShape( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
evt->SetPassEvent();
}
}
else if( evt->IsAction( &PCB_ACTIONS::properties ) )
{
if( started )
{
frame()->OnEditItemRequest( graphic );
m_view->Update( &preview );
frame()->SetMsgPanel( graphic );
break;
}
else
{
evt->SetPassEvent();
}
}
else if( evt->IsClick( BUT_RIGHT ) )
{
m_menu.ShowContextMenu( selection() );
@ -2074,19 +2070,16 @@ bool DRAWING_TOOL::drawShape( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
m_view->Update( &preview );
m_view->Update( &twoPointAsst );
}
else if( evt->IsAction( &PCB_ACTIONS::incWidth ) )
else if( graphic && evt->IsAction( &PCB_ACTIONS::incWidth ) )
{
if( graphic )
{
m_stroke.SetWidth( m_stroke.GetWidth() + WIDTH_STEP );
graphic->SetStroke( m_stroke );
m_view->Update( &preview );
frame()->SetMsgPanel( graphic );
}
m_stroke.SetWidth( m_stroke.GetWidth() + WIDTH_STEP );
graphic->SetStroke( m_stroke );
m_view->Update( &preview );
frame()->SetMsgPanel( graphic );
}
else if( evt->IsAction( &PCB_ACTIONS::decWidth ) )
else if( graphic && evt->IsAction( &PCB_ACTIONS::decWidth ) )
{
if( graphic && (unsigned) m_stroke.GetWidth() > WIDTH_STEP )
if( (unsigned) m_stroke.GetWidth() > WIDTH_STEP )
{
m_stroke.SetWidth( m_stroke.GetWidth() - WIDTH_STEP );
graphic->SetStroke( m_stroke );
@ -2094,6 +2087,17 @@ bool DRAWING_TOOL::drawShape( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
frame()->SetMsgPanel( graphic );
}
}
else if( started && evt->IsAction( &PCB_ACTIONS::properties ) )
{
frame()->OnEditItemRequest( graphic );
m_view->Update( &preview );
frame()->SetMsgPanel( graphic );
break;
}
else if( started && ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
{
wxBell();
}
else if( evt->IsAction( &ACTIONS::resetLocalCoords ) )
{
isLocalOriginSet = true;
@ -2208,7 +2212,7 @@ bool DRAWING_TOOL::drawArc( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
// Set initial cursor
setCursor();
bool firstPoint = false;
bool started = false;
bool cancelled = false;
m_toolMgr->RunAction( ACTIONS::refreshPreview );
@ -2219,7 +2223,7 @@ bool DRAWING_TOOL::drawArc( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
// Main loop: keep receiving events
while( TOOL_EVENT* evt = Wait() )
{
if( firstPoint )
if( started )
m_frame->SetMsgPanel( graphic );
setCursor();
@ -2236,7 +2240,7 @@ bool DRAWING_TOOL::drawArc( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
{
cleanup();
if( !firstPoint )
if( !started )
{
// We've handled the cancel event. Don't cancel other tools
evt->SetPassEvent( false );
@ -2269,7 +2273,7 @@ bool DRAWING_TOOL::drawArc( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
}
else if( evt->IsClick( BUT_LEFT ) )
{
if( !firstPoint )
if( !started )
{
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
@ -2289,7 +2293,7 @@ bool DRAWING_TOOL::drawArc( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
preview.Add( graphic );
frame()->SetMsgPanel( graphic );
firstPoint = true;
started = true;
}
arcManager.AddPoint( cursorPos, true );
@ -2389,6 +2393,10 @@ bool DRAWING_TOOL::drawArc( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
m_view->Update( &arcAsst );
evt->SetPassEvent();
}
else if( started && ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
{
wxBell();
}
else
{
evt->SetPassEvent();
@ -2404,7 +2412,7 @@ bool DRAWING_TOOL::drawArc( const TOOL_EVENT& aTool, PCB_SHAPE** aGraphic,
m_view->Update( &preview );
m_view->Update( &arcAsst );
if( firstPoint )
if( started )
frame()->SetMsgPanel( graphic );
else
frame()->SetMsgPanel( board() );
@ -2657,18 +2665,15 @@ int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent )
{
polyGeomMgr.SetCursorPosition( cursorPos );
}
else if( evt->IsAction( &PCB_ACTIONS::properties ) )
else if( started && ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
{
if( started )
{
frame()->OnEditItemRequest( zoneTool.GetZone() );
zoneTool.OnGeometryChange( polyGeomMgr );
frame()->SetMsgPanel( zoneTool.GetZone() );
}
else
{
evt->SetPassEvent();
}
wxBell();
}
else if( started&& evt->IsAction( &PCB_ACTIONS::properties ) )
{
frame()->OnEditItemRequest( zoneTool.GetZone() );
zoneTool.OnGeometryChange( polyGeomMgr );
frame()->SetMsgPanel( zoneTool.GetZone() );
}
/*else if( evt->IsAction( &ACTIONS::updateUnits ) )
{

View File

@ -42,6 +42,7 @@
#include <tools/pcb_grid_helper.h>
#include <tools/drc_tool.h>
#include <tools/drawing_tool.h>
#include <tools/zone_filler_tool.h>
#include <view/view_controls.h>
#include <connectivity/connectivity_algo.h>
#include <connectivity/connectivity_items.h>
@ -765,6 +766,10 @@ int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent )
displayConstraintsMessage( hv45Mode );
evt->SetPassEvent( false );
}
else if( ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
{
wxBell();
}
else
{
evt->SetPassEvent();

View File

@ -332,10 +332,8 @@ public:
static TOOL_ACTION assignNetClass;
// Zone actions
static TOOL_ACTION zoneFill;
static TOOL_ACTION zoneFillAll;
static TOOL_ACTION zoneFillDirty;
static TOOL_ACTION zoneUnfill;
static TOOL_ACTION zoneUnfillAll;
static TOOL_ACTION zoneMerge;

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 CERN
* Copyright (C) 2019-2020 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2019-2022 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
@ -27,6 +27,7 @@
#include "pcb_actions.h"
#include "pcb_grid_helper.h"
#include <view/view_controls.h>
#include <tools/zone_filler_tool.h>
PCB_PICKER_TOOL::PCB_PICKER_TOOL() :
@ -94,7 +95,6 @@ int PCB_PICKER_TOOL::Main( const TOOL_EVENT& aEvent )
break;
}
else if( evt->IsClick( BUT_LEFT ) )
{
bool getNext = false;
@ -124,7 +124,6 @@ int PCB_PICKER_TOOL::Main( const TOOL_EVENT& aEvent )
setControls();
}
}
else if( evt->IsMotion() )
{
if( m_motionHandler )
@ -138,18 +137,21 @@ int PCB_PICKER_TOOL::Main( const TOOL_EVENT& aEvent )
}
}
}
else if( evt->IsDblClick( BUT_LEFT ) || evt->IsDrag( BUT_LEFT ) )
{
// Not currently used, but we don't want to pass them either
}
else if( evt->IsClick( BUT_RIGHT ) )
{
PCB_SELECTION dummy;
m_menu.ShowContextMenu( dummy );
}
// TODO: It'd be nice to be able to say "don't allow any non-trivial editing actions",
// but we don't at present have that, so we just knock out some of the egregious ones.
else if( ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
{
wxBell();
}
else
{
evt->SetPassEvent();

View File

@ -37,7 +37,6 @@ using namespace std::placeholders;
#include <tools/pcb_point_editor.h>
#include <tools/pcb_grid_helper.h>
#include <board_commit.h>
#include <status_popup.h>
#include <pcb_edit_frame.h>
#include <fp_shape.h>
#include <fp_textbox.h>
@ -655,7 +654,6 @@ int PCB_POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
{
break;
}
else
{
evt->SetPassEvent();

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2017-2022 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
@ -35,6 +35,8 @@
#include <tools/pcb_selection_tool.h>
#include <tools/pcb_actions.h>
#include <tools/tool_event_utils.h>
#include <tools/zone_filler_tool.h>
void PCB_TOOL_BASE::doInteractiveItemPlacement( const TOOL_EVENT& aTool,
INTERACTIVE_PLACER_BASE* aPlacer,
@ -235,6 +237,10 @@ void PCB_TOOL_BASE::doInteractiveItemPlacement( const TOOL_EVENT& aTool,
// Notify other tools of the changes
m_toolMgr->ProcessEvent( EVENTS::SelectedItemsModified );
}
else if( ZONE_FILLER_TOOL::IsZoneFillAction( evt ) )
{
wxBell();
}
else if( evt->IsAction( &ACTIONS::refreshPreview ) )
{
preview.Clear();

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2017-2022 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
@ -37,7 +37,6 @@ using namespace std::placeholders;
#include <pad.h>
#include <footprint.h>
#include <pcb_group.h>
#include <pcbnew_settings.h>
POSITION_RELATIVE_TOOL::POSITION_RELATIVE_TOOL() :

View File

@ -319,10 +319,18 @@ void ZONE_FILLER_TOOL::refresh()
}
bool ZONE_FILLER_TOOL::IsZoneFillAction( const TOOL_EVENT* aEvent )
{
return aEvent->IsAction( &PCB_ACTIONS::zoneFillAll )
|| aEvent->IsAction( &PCB_ACTIONS::zoneFillDirty )
|| aEvent->IsAction( &PCB_ACTIONS::zoneUnfillAll );
}
void ZONE_FILLER_TOOL::setTransitions()
{
// Zone actions
Go( &ZONE_FILLER_TOOL::ZoneFillAll, PCB_ACTIONS::zoneFillAll.MakeEvent() );
Go( &ZONE_FILLER_TOOL::ZoneFillDirty, PCB_ACTIONS::zoneFillDirty.MakeEvent() );
Go( &ZONE_FILLER_TOOL::ZoneFillDirty, PCB_ACTIONS::zoneFillDirty.MakeEvent() );
Go( &ZONE_FILLER_TOOL::ZoneUnfillAll, PCB_ACTIONS::zoneUnfillAll.MakeEvent() );
}

View File

@ -62,6 +62,8 @@ public:
m_dirtyZoneIDs.insert( aZone->m_Uuid );
}
static bool IsZoneFillAction( const TOOL_EVENT* aEvent );
private:
///< Refocus on an idle event (used after the Progress Reporter messes up the focus).
void singleShotRefocus( wxIdleEvent& );