ADDED: automatic zone refilling.
This is for the out-of-box experience for novice users. It is presumed that folks with larger more complicated boards will turn it off. Fixes https://gitlab.com/kicad/code/kicad/issues/6413
This commit is contained in:
parent
f076d07e9e
commit
d465eb6425
|
@ -561,7 +561,7 @@ void TOOL_MANAGER::ResetTools( TOOL_BASE::RESET_REASON aReason )
|
|||
|
||||
void TOOL_MANAGER::InitTools()
|
||||
{
|
||||
for( TOOL_VEC::iterator it = m_toolOrder.begin(); it != m_toolOrder.end(); /* iter inside */ )
|
||||
for( auto it = m_toolOrder.begin(); it != m_toolOrder.end(); /* iter inside */ )
|
||||
{
|
||||
TOOL_BASE* tool = *it;
|
||||
wxASSERT( m_toolState.count( tool ) );
|
||||
|
|
|
@ -133,7 +133,7 @@ public:
|
|||
///< Execute the changes.
|
||||
virtual void Push( const wxString& aMessage = wxT( "A commit" ),
|
||||
bool aCreateUndoEntry = true, bool aSetDirtyBit = true,
|
||||
bool aUpdateConnectivity = true ) = 0;
|
||||
bool aUpdateConnectivity = true, bool aZoneFillOp = false ) = 0;
|
||||
|
||||
///< Revert the commit by restoring the modified items state.
|
||||
virtual void Revert() = 0;
|
||||
|
|
|
@ -66,7 +66,6 @@ public:
|
|||
typedef std::map<std::string, TOOL_STATE*> NAME_STATE_MAP;
|
||||
typedef std::map<TOOL_ID, TOOL_STATE*> ID_STATE_MAP;
|
||||
typedef std::list<TOOL_ID> ID_LIST;
|
||||
typedef std::vector<TOOL_BASE*> TOOL_VEC;
|
||||
|
||||
/**
|
||||
* Generates a unique ID from for a tool with given name.
|
||||
|
@ -226,6 +225,11 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return all registered tools.
|
||||
*/
|
||||
std::vector<TOOL_BASE*> Tools() { return m_toolOrder; }
|
||||
|
||||
/**
|
||||
* Deactivate the currently active tool.
|
||||
*/
|
||||
|
@ -531,7 +535,7 @@ private:
|
|||
void setActiveState( TOOL_STATE* aState );
|
||||
|
||||
///< List of tools in the order they were registered
|
||||
TOOL_VEC m_toolOrder;
|
||||
std::vector<TOOL_BASE*> m_toolOrder;
|
||||
|
||||
///< Index of registered tools current states, associated by tools' objects.
|
||||
TOOL_STATE_MAP m_toolState;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 CERN
|
||||
* Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -28,6 +28,7 @@
|
|||
#include <pcb_group.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tools/pcb_selection_tool.h>
|
||||
#include <tools/zone_filler_tool.h>
|
||||
#include <view/view.h>
|
||||
#include <board_commit.h>
|
||||
#include <tools/pcb_tool_base.h>
|
||||
|
@ -42,6 +43,7 @@ using namespace std::placeholders;
|
|||
BOARD_COMMIT::BOARD_COMMIT( TOOL_MANAGER* aToolMgr ) :
|
||||
m_toolMgr( aToolMgr ),
|
||||
m_isFootprintEditor( false ),
|
||||
m_isBoardEditor( false ),
|
||||
m_resolveNetConflicts( false )
|
||||
{
|
||||
}
|
||||
|
@ -52,6 +54,7 @@ BOARD_COMMIT::BOARD_COMMIT( PCB_TOOL_BASE* aTool ) :
|
|||
{
|
||||
m_toolMgr = aTool->GetManager();
|
||||
m_isFootprintEditor = aTool->IsFootprintEditor();
|
||||
m_isBoardEditor = aTool->IsBoardEditor();
|
||||
}
|
||||
|
||||
|
||||
|
@ -60,6 +63,7 @@ BOARD_COMMIT::BOARD_COMMIT( EDA_DRAW_FRAME* aFrame ) :
|
|||
{
|
||||
m_toolMgr = aFrame->GetToolManager();
|
||||
m_isFootprintEditor = aFrame->IsType( FRAME_FOOTPRINT_EDITOR );
|
||||
m_isBoardEditor = aFrame->IsType( FRAME_PCB_EDITOR );
|
||||
}
|
||||
|
||||
|
||||
|
@ -96,18 +100,59 @@ COMMIT& BOARD_COMMIT::Stage( const PICKED_ITEMS_LIST& aItems, UNDO_REDO aModFlag
|
|||
}
|
||||
|
||||
|
||||
void BOARD_COMMIT::dirtyIntersectingZones( BOARD_ITEM* item )
|
||||
{
|
||||
if( item->Type() == PCB_FOOTPRINT_T )
|
||||
{
|
||||
static_cast<FOOTPRINT*>( item )->RunOnChildren(
|
||||
[&]( BOARD_ITEM* child )
|
||||
{
|
||||
dirtyIntersectingZones( child );
|
||||
} );
|
||||
}
|
||||
else if( item->Type() == PCB_GROUP_T )
|
||||
{
|
||||
static_cast<PCB_GROUP*>( item )->RunOnChildren(
|
||||
[&]( BOARD_ITEM* child )
|
||||
{
|
||||
dirtyIntersectingZones( child );
|
||||
} );
|
||||
}
|
||||
else
|
||||
{
|
||||
ZONE_FILLER_TOOL* zoneFillerTool = m_toolMgr->GetTool<ZONE_FILLER_TOOL>();
|
||||
BOARD* board = static_cast<BOARD*>( m_toolMgr->GetModel() );
|
||||
EDA_RECT bbox = item->GetBoundingBox();
|
||||
LSET layers = item->GetLayerSet();
|
||||
|
||||
for( ZONE* zone : board->Zones() )
|
||||
{
|
||||
if( zone->GetIsRuleArea() )
|
||||
continue;
|
||||
|
||||
if( ( zone->GetLayerSet() & layers ).any()
|
||||
&& zone->GetCachedBoundingBox().Intersects( bbox ) )
|
||||
{
|
||||
zoneFillerTool->DirtyZone( zone );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool aSetDirtyBit,
|
||||
bool aUpdateConnectivity )
|
||||
bool aUpdateConnectivity, bool aZoneFillOp )
|
||||
{
|
||||
// Objects potentially interested in changes:
|
||||
PICKED_ITEMS_LIST undoList;
|
||||
KIGFX::VIEW* view = m_toolMgr->GetView();
|
||||
BOARD* board = (BOARD*) m_toolMgr->GetModel();
|
||||
BOARD* board = static_cast<BOARD*>( m_toolMgr->GetModel() );
|
||||
PCB_BASE_FRAME* frame = dynamic_cast<PCB_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
|
||||
std::set<EDA_ITEM*> savedModules;
|
||||
PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
|
||||
bool itemsDeselected = false;
|
||||
bool solderMaskDirty = false;
|
||||
bool autofillZones = false;
|
||||
|
||||
std::vector<BOARD_ITEM*> bulkAddedItems;
|
||||
std::vector<BOARD_ITEM*> bulkRemovedItems;
|
||||
|
@ -116,6 +161,14 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
|
|||
if( Empty() )
|
||||
return;
|
||||
|
||||
if( m_isBoardEditor && !aZoneFillOp && frame->GetPcbNewSettings()->m_AutoRefillZones )
|
||||
{
|
||||
autofillZones = true;
|
||||
|
||||
for( ZONE* zone : board->Zones() )
|
||||
zone->CacheBoundingBox();
|
||||
}
|
||||
|
||||
for( COMMIT_LINE& ent : m_changes )
|
||||
{
|
||||
int changeType = ent.m_type & CHT_TYPE;
|
||||
|
@ -205,6 +258,9 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
|
|||
}
|
||||
}
|
||||
|
||||
if( autofillZones )
|
||||
dirtyIntersectingZones( boardItem );
|
||||
|
||||
if( view && boardItem->Type() != PCB_NETINFO_T )
|
||||
view->Add( boardItem );
|
||||
|
||||
|
@ -224,6 +280,9 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
|
|||
itemsDeselected = true;
|
||||
}
|
||||
|
||||
if( autofillZones )
|
||||
dirtyIntersectingZones( boardItem );
|
||||
|
||||
switch( boardItem->Type() )
|
||||
{
|
||||
// Footprint items
|
||||
|
@ -334,7 +393,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
|
|||
bulkRemovedItems.push_back( boardItem );
|
||||
break;
|
||||
|
||||
default: // other types do not need to (or should not) be handled
|
||||
default: // other types do not need to (or should not) be handled
|
||||
wxASSERT( false );
|
||||
break;
|
||||
}
|
||||
|
@ -362,6 +421,12 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
|
|||
connectivity->Update( boardItem );
|
||||
}
|
||||
|
||||
if( autofillZones )
|
||||
{
|
||||
dirtyIntersectingZones( static_cast<BOARD_ITEM*>( ent.m_copy )); // before
|
||||
dirtyIntersectingZones( boardItem ); // after
|
||||
}
|
||||
|
||||
if( view )
|
||||
{
|
||||
view->Update( boardItem );
|
||||
|
@ -400,7 +465,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
|
|||
if( itemsChanged.size() > 0 )
|
||||
board->OnItemsChanged( itemsChanged );
|
||||
|
||||
if( !m_isFootprintEditor )
|
||||
if( m_isBoardEditor )
|
||||
{
|
||||
size_t num_changes = m_changes.size();
|
||||
|
||||
|
@ -415,42 +480,38 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
|
|||
connectivity->ClearDynamicRatsnest();
|
||||
}
|
||||
|
||||
if( frame && solderMaskDirty )
|
||||
if( solderMaskDirty )
|
||||
frame->HideSolderMask();
|
||||
|
||||
if( frame )
|
||||
frame->GetCanvas()->RedrawRatsnest();
|
||||
frame->GetCanvas()->RedrawRatsnest();
|
||||
|
||||
if( m_changes.size() > num_changes )
|
||||
// Log undo items for any connectivity changes
|
||||
for( size_t i = num_changes; i < m_changes.size(); ++i )
|
||||
{
|
||||
for( size_t i = num_changes; i < m_changes.size(); ++i )
|
||||
COMMIT_LINE& ent = m_changes[i];
|
||||
|
||||
wxASSERT( ( ent.m_type & CHT_TYPE ) == CHT_MODIFY );
|
||||
|
||||
BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( ent.m_item );
|
||||
|
||||
if( aCreateUndoEntry )
|
||||
{
|
||||
COMMIT_LINE& ent = m_changes[i];
|
||||
|
||||
// This should only be modifications from the connectivity algo
|
||||
wxASSERT( ( ent.m_type & CHT_TYPE ) == CHT_MODIFY );
|
||||
|
||||
BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( ent.m_item );
|
||||
|
||||
if( aCreateUndoEntry )
|
||||
{
|
||||
ITEM_PICKER itemWrapper( nullptr, boardItem, UNDO_REDO::CHANGED );
|
||||
wxASSERT( ent.m_copy );
|
||||
itemWrapper.SetLink( ent.m_copy );
|
||||
undoList.PushItem( itemWrapper );
|
||||
}
|
||||
else
|
||||
{
|
||||
delete ent.m_copy;
|
||||
}
|
||||
|
||||
if( view )
|
||||
view->Update( boardItem );
|
||||
ITEM_PICKER itemWrapper( nullptr, boardItem, UNDO_REDO::CHANGED );
|
||||
wxASSERT( ent.m_copy );
|
||||
itemWrapper.SetLink( ent.m_copy );
|
||||
undoList.PushItem( itemWrapper );
|
||||
}
|
||||
else
|
||||
{
|
||||
delete ent.m_copy;
|
||||
}
|
||||
|
||||
if( view )
|
||||
view->Update( boardItem );
|
||||
}
|
||||
}
|
||||
|
||||
if( !m_isFootprintEditor && aCreateUndoEntry && frame )
|
||||
if( m_isBoardEditor && aCreateUndoEntry )
|
||||
frame->SaveCopyInUndoList( undoList, UNDO_REDO::UNSPECIFIED );
|
||||
|
||||
m_toolMgr->PostEvent( { TC_MESSAGE, TA_MODEL_CHANGE, AS_GLOBAL } );
|
||||
|
@ -458,6 +519,9 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
|
|||
if( itemsDeselected )
|
||||
m_toolMgr->PostEvent( EVENTS::UnselectedEvent );
|
||||
|
||||
if( autofillZones )
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::zoneFillDirty );
|
||||
|
||||
if( frame )
|
||||
{
|
||||
if( aSetDirtyBit )
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 CERN
|
||||
* Copyright (C) 2016-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -22,8 +23,8 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef __BOARD_COMMIT_H
|
||||
#define __BOARD_COMMIT_H
|
||||
#ifndef BOARD_COMMIT_H
|
||||
#define BOARD_COMMIT_H
|
||||
|
||||
#include <commit.h>
|
||||
|
||||
|
@ -45,7 +46,7 @@ public:
|
|||
|
||||
virtual void Push( const wxString& aMessage = wxT( "A commit" ),
|
||||
bool aCreateUndoEntry = true, bool aSetDirtyBit = true,
|
||||
bool aUpdateConnectivity = true ) override;
|
||||
bool aUpdateConnectivity = true, bool aZoneFillOp = false ) override;
|
||||
|
||||
virtual void Revert() override;
|
||||
COMMIT& Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType ) override;
|
||||
|
@ -66,10 +67,13 @@ public:
|
|||
private:
|
||||
virtual EDA_ITEM* parentObject( EDA_ITEM* aItem ) const override;
|
||||
|
||||
void dirtyIntersectingZones( BOARD_ITEM* item );
|
||||
|
||||
private:
|
||||
TOOL_MANAGER* m_toolMgr;
|
||||
bool m_isFootprintEditor;
|
||||
bool m_resolveNetConflicts;
|
||||
TOOL_MANAGER* m_toolMgr;
|
||||
bool m_isFootprintEditor;
|
||||
bool m_isBoardEditor;
|
||||
bool m_resolveNetConflicts;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -363,7 +363,7 @@ PANEL_EDIT_OPTIONS_BASE::PANEL_EDIT_OPTIONS_BASE( wxWindow* parent, wxWindowID i
|
|||
sbSizerPcbGraphics = new wxStaticBoxSizer( new wxStaticBox( pcbPage, wxID_ANY, _("Graphics Editing") ), wxVERTICAL );
|
||||
|
||||
m_cbPcbGraphic45Mode = new wxCheckBox( sbSizerPcbGraphics->GetStaticBox(), wxID_ANY, _("Limit actions to 45 degrees from start"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
sbSizerPcbGraphics->Add( m_cbPcbGraphic45Mode, 0, wxALL, 5 );
|
||||
sbSizerPcbGraphics->Add( m_cbPcbGraphic45Mode, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
|
||||
pcbOptionsSizer->Add( sbSizerPcbGraphics, 0, wxEXPAND|wxTOP, 5 );
|
||||
|
@ -377,11 +377,11 @@ PANEL_EDIT_OPTIONS_BASE::PANEL_EDIT_OPTIONS_BASE( wxWindow* parent, wxWindowID i
|
|||
|
||||
sbSizer4->Add( m_showPageLimits, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_autoRefillZones = new wxCheckBox( sbSizer4->GetStaticBox(), wxID_ANY, _("Refill zones after Zone Properties dialog"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_autoRefillZones = new wxCheckBox( sbSizer4->GetStaticBox(), wxID_ANY, _("Auto-refill zones"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_autoRefillZones->SetValue(true);
|
||||
m_autoRefillZones->SetToolTip( _("If checked, zones will be re-filled after editing the properties of the zone using the Zone Properties dialog") );
|
||||
|
||||
sbSizer4->Add( m_autoRefillZones, 0, wxALL, 5 );
|
||||
sbSizer4->Add( m_autoRefillZones, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
|
||||
pcbOptionsSizer->Add( sbSizer4, 1, wxEXPAND|wxTOP, 5 );
|
||||
|
|
|
@ -3313,7 +3313,7 @@
|
|||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="flag">wxBOTTOM|wxRIGHT|wxLEFT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxCheckBox" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
|
@ -3455,7 +3455,7 @@
|
|||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="flag">wxBOTTOM|wxRIGHT|wxLEFT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxCheckBox" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
|
@ -3486,7 +3486,7 @@
|
|||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Refill zones after Zone Properties dialog</property>
|
||||
<property name="label">Auto-refill zones</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
|
||||
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* Some code comes from FreePCB.
|
||||
*
|
||||
|
@ -33,8 +33,6 @@
|
|||
#include <zones.h>
|
||||
#include <zones_functions_for_undo_redo.h>
|
||||
#include <connectivity/connectivity_data.h>
|
||||
#include <widgets/wx_progress_reporters.h>
|
||||
#include <zone_filler.h>
|
||||
|
||||
|
||||
void PCB_EDIT_FRAME::Edit_Zone_Params( ZONE* aZone )
|
||||
|
@ -103,43 +101,8 @@ void PCB_EDIT_FRAME::Edit_Zone_Params( ZONE* aZone )
|
|||
|
||||
UpdateCopyOfZonesList( pickedList, deletedList, GetBoard() );
|
||||
|
||||
// refill zones with the new properties applied
|
||||
std::vector<ZONE*> zones_to_refill;
|
||||
|
||||
for( unsigned i = 0; i < pickedList.GetCount(); ++i )
|
||||
{
|
||||
ZONE* zone = dyn_cast<ZONE*>( pickedList.GetPickedItem( i ) );
|
||||
|
||||
if( zone == nullptr )
|
||||
{
|
||||
wxASSERT_MSG( false, wxT( "Expected a zone after zone properties edit" ) );
|
||||
continue;
|
||||
}
|
||||
|
||||
// aZone won't be filled if the layer set was modified, but it needs to be updated
|
||||
if( zone->IsFilled() || zone == aZone )
|
||||
zones_to_refill.push_back( zone );
|
||||
}
|
||||
|
||||
commit.Stage( pickedList );
|
||||
|
||||
// Only auto-refill zones here if in user preferences
|
||||
if( Settings().m_AutoRefillZones )
|
||||
{
|
||||
if( zones_to_refill.size() )
|
||||
{
|
||||
ZONE_FILLER filler( GetBoard(), &commit );
|
||||
wxString title = wxString::Format( _( "Refill %d Zones" ),
|
||||
(int) zones_to_refill.size() );
|
||||
|
||||
std::unique_ptr<WX_PROGRESS_REPORTER> reporter;
|
||||
reporter = std::make_unique<WX_PROGRESS_REPORTER>( this, title, 4 );
|
||||
filler.SetProgressReporter( reporter.get() );
|
||||
|
||||
(void) filler.Fill( zones_to_refill );
|
||||
}
|
||||
}
|
||||
|
||||
commit.Push( _( "Modify zone properties" ), true, true, false );
|
||||
GetBoard()->GetConnectivity()->Build( GetBoard() );
|
||||
|
||||
|
|
|
@ -1020,16 +1020,11 @@ void FOOTPRINT_EDIT_FRAME::setupTools()
|
|||
m_toolManager->RegisterTool( new CONVERT_TOOL );
|
||||
m_toolManager->RegisterTool( new SCRIPTING_TOOL );
|
||||
|
||||
m_toolManager->GetTool<PCB_SELECTION_TOOL>()->SetIsFootprintEditor( true );
|
||||
m_toolManager->GetTool<EDIT_TOOL>()->SetIsFootprintEditor( true );
|
||||
m_toolManager->GetTool<PAD_TOOL>()->SetIsFootprintEditor( true );
|
||||
m_toolManager->GetTool<DRAWING_TOOL>()->SetIsFootprintEditor( true );
|
||||
m_toolManager->GetTool<PCB_POINT_EDITOR>()->SetIsFootprintEditor( true );
|
||||
m_toolManager->GetTool<PCB_CONTROL>()->SetIsFootprintEditor( true );
|
||||
m_toolManager->GetTool<PCB_PICKER_TOOL>()->SetIsFootprintEditor( true );
|
||||
m_toolManager->GetTool<POSITION_RELATIVE_TOOL>()->SetIsFootprintEditor( true );
|
||||
m_toolManager->GetTool<GROUP_TOOL>()->SetIsFootprintEditor( true );
|
||||
m_toolManager->GetTool<SCRIPTING_TOOL>()->SetIsFootprintEditor( true );
|
||||
for( TOOL_BASE* tool : m_toolManager->Tools() )
|
||||
{
|
||||
if( PCB_TOOL_BASE* pcbTool = dynamic_cast<PCB_TOOL_BASE*>( tool ) )
|
||||
pcbTool->SetIsFootprintEditor( true );
|
||||
}
|
||||
|
||||
m_toolManager->GetTool<PCB_VIEWER_TOOLS>()->SetFootprintFrame( true );
|
||||
m_toolManager->InitTools();
|
||||
|
|
|
@ -568,6 +568,12 @@ void PCB_EDIT_FRAME::setupTools()
|
|||
m_toolManager->RegisterTool( new SCRIPTING_TOOL );
|
||||
m_toolManager->InitTools();
|
||||
|
||||
for( TOOL_BASE* tool : m_toolManager->Tools() )
|
||||
{
|
||||
if( PCB_TOOL_BASE* pcbTool = dynamic_cast<PCB_TOOL_BASE*>( tool ) )
|
||||
pcbTool->SetIsBoardEditor( true );
|
||||
}
|
||||
|
||||
// Run the selection tool, it is supposed to be always active
|
||||
m_toolManager->InvokeTool( "pcbnew.InteractiveSelection" );
|
||||
}
|
||||
|
|
|
@ -1300,6 +1300,9 @@ TOOL_ACTION PCB_ACTIONS::zoneFillAll( "pcbnew.ZoneFiller.zoneFillAll",
|
|||
_( "Fill All Zones" ), _( "Update copper fill of all zones" ),
|
||||
BITMAPS::fill_zone );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::zoneFillDirty( "pcbnew.ZoneFiller.zoneFillDirty",
|
||||
AS_CONTEXT );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::zoneUnfill( "pcbnew.ZoneFiller.zoneUnfill",
|
||||
AS_GLOBAL, 0, "",
|
||||
_( "Unfill Zone" ), _( "Remove copper fill from selected zone(s)" ),
|
||||
|
|
|
@ -309,6 +309,7 @@ public:
|
|||
// 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;
|
||||
|
|
|
@ -76,7 +76,8 @@ public:
|
|||
* Creates a tool with given id & name. The name must be unique. */
|
||||
PCB_TOOL_BASE( TOOL_ID aId, const std::string& aName ) :
|
||||
TOOL_INTERACTIVE ( aId, aName ),
|
||||
m_isFootprintEditor( false )
|
||||
m_isFootprintEditor( false ),
|
||||
m_isBoardEditor( false )
|
||||
{};
|
||||
|
||||
/**
|
||||
|
@ -85,7 +86,8 @@ public:
|
|||
* Creates a tool with given name. The name must be unique. */
|
||||
PCB_TOOL_BASE( const std::string& aName ) :
|
||||
TOOL_INTERACTIVE ( aName ),
|
||||
m_isFootprintEditor( false )
|
||||
m_isFootprintEditor( false ),
|
||||
m_isBoardEditor( false )
|
||||
{};
|
||||
|
||||
virtual ~PCB_TOOL_BASE() {};
|
||||
|
@ -103,6 +105,9 @@ public:
|
|||
void SetIsFootprintEditor( bool aEnabled ) { m_isFootprintEditor = aEnabled; }
|
||||
bool IsFootprintEditor() const { return m_isFootprintEditor; }
|
||||
|
||||
void SetIsBoardEditor( bool aEnabled ) { m_isBoardEditor = aEnabled; }
|
||||
bool IsBoardEditor() const { return m_isBoardEditor; }
|
||||
|
||||
/**
|
||||
* Should the tool use its 45° mode option?
|
||||
* @return True if set to use 45°
|
||||
|
@ -179,6 +184,7 @@ protected:
|
|||
|
||||
protected:
|
||||
bool m_isFootprintEditor;
|
||||
bool m_isBoardEditor;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include <zone.h>
|
||||
#include <connectivity/connectivity_data.h>
|
||||
#include <board_commit.h>
|
||||
#include <footprint.h>
|
||||
#include <pcb_group.h>
|
||||
#include <board_design_settings.h>
|
||||
#include <progress_reporter.h>
|
||||
#include <widgets/infobar.h>
|
||||
|
@ -66,7 +68,7 @@ void ZONE_FILLER_TOOL::CheckAllZones( wxWindow* aCaller, PROGRESS_REPORTER* aRep
|
|||
std::vector<ZONE*> toFill;
|
||||
|
||||
for( ZONE* zone : board()->Zones() )
|
||||
toFill.push_back(zone);
|
||||
toFill.push_back( zone );
|
||||
|
||||
BOARD_COMMIT commit( this );
|
||||
std::unique_ptr<WX_PROGRESS_REPORTER> reporter;
|
||||
|
@ -84,7 +86,7 @@ void ZONE_FILLER_TOOL::CheckAllZones( wxWindow* aCaller, PROGRESS_REPORTER* aRep
|
|||
|
||||
if( filler.Fill( toFill, true, aCaller ) )
|
||||
{
|
||||
commit.Push( _( "Fill Zone(s)" ), true, true, false );
|
||||
commit.Push( _( "Fill Zone(s)" ), true, true, false, true );
|
||||
getEditFrame<PCB_EDIT_FRAME>()->m_ZoneFillsDirty = false;
|
||||
}
|
||||
else
|
||||
|
@ -159,7 +161,7 @@ void ZONE_FILLER_TOOL::FillAllZones( wxWindow* aCaller, PROGRESS_REPORTER* aRepo
|
|||
{
|
||||
filler.GetProgressReporter()->AdvancePhase();
|
||||
|
||||
commit.Push( _( "Fill Zone(s)" ), true, true, false );
|
||||
commit.Push( _( "Fill Zone(s)" ), true, true, false, true );
|
||||
frame->m_ZoneFillsDirty = false;
|
||||
}
|
||||
else
|
||||
|
@ -181,6 +183,105 @@ void ZONE_FILLER_TOOL::FillAllZones( wxWindow* aCaller, PROGRESS_REPORTER* aRepo
|
|||
}
|
||||
|
||||
|
||||
int ZONE_FILLER_TOOL::ZoneFillDirty( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME>();
|
||||
std::vector<ZONE*> toFill;
|
||||
|
||||
for( ZONE* zone : board()->Zones() )
|
||||
{
|
||||
if( m_dirtyZoneIDs.count( zone->m_Uuid ) )
|
||||
toFill.push_back( zone );
|
||||
}
|
||||
|
||||
if( toFill.empty() )
|
||||
return 0;
|
||||
|
||||
if( m_fillInProgress )
|
||||
return 0;
|
||||
|
||||
m_fillInProgress = true;
|
||||
|
||||
m_dirtyZoneIDs.clear();
|
||||
|
||||
board()->IncrementTimeStamp(); // Clear caches
|
||||
|
||||
BOARD_COMMIT commit( this );
|
||||
std::unique_ptr<WX_PROGRESS_REPORTER> reporter;
|
||||
ZONE_FILLER filler( board(), &commit );
|
||||
int pts = 0;
|
||||
|
||||
if( !board()->GetDesignSettings().m_DRCEngine->RulesValid() )
|
||||
{
|
||||
WX_INFOBAR* infobar = frame->GetInfoBar();
|
||||
wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY, _( "Show DRC rules" ),
|
||||
wxEmptyString );
|
||||
|
||||
button->Bind( wxEVT_COMMAND_HYPERLINK,
|
||||
std::function<void( wxHyperlinkEvent& aEvent )>(
|
||||
[frame]( wxHyperlinkEvent& aEvent )
|
||||
{
|
||||
frame->ShowBoardSetupDialog( _( "Rules" ) );
|
||||
} ) );
|
||||
|
||||
infobar->RemoveAllButtons();
|
||||
infobar->AddButton( button );
|
||||
|
||||
infobar->ShowMessageFor( _( "Zone fills may be inaccurate. DRC rules contain errors." ),
|
||||
10000, wxICON_WARNING );
|
||||
}
|
||||
|
||||
for( ZONE* zone : toFill )
|
||||
{
|
||||
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
|
||||
pts += zone->GetFilledPolysList( layer )->FullPointCount();
|
||||
|
||||
if( pts > 1000 )
|
||||
{
|
||||
wxString title = wxString::Format( _( "Refill %d Zones" ), (int) toFill.size() );
|
||||
|
||||
reporter = std::make_unique<WX_PROGRESS_REPORTER>( frame, title, 5 );
|
||||
filler.SetProgressReporter( reporter.get() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( filler.Fill( toFill ) )
|
||||
commit.Push( _( "Auto-fill Zone(s)" ), false, false, false, true );
|
||||
else
|
||||
commit.Revert();
|
||||
|
||||
board()->GetConnectivity()->Build( board(), reporter.get() );
|
||||
|
||||
if( filler.IsDebug() )
|
||||
frame->UpdateUserInterface();
|
||||
|
||||
canvas()->Refresh();
|
||||
m_fillInProgress = false;
|
||||
|
||||
for( ZONE* zone : toFill )
|
||||
{
|
||||
int outlines = 0;
|
||||
|
||||
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
|
||||
outlines += zone->GetFilledPolysList( layer )->OutlineCount();
|
||||
|
||||
if( outlines == 0 )
|
||||
{
|
||||
// TODO: why does this trash memory?
|
||||
// frame->ShowInfoBarWarning( _( "Zone has no connections." ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// wxWidgets has keyboard focus issues after the progress reporter. Re-setting the focus
|
||||
// here doesn't work, so we delay it to an idle event.
|
||||
canvas()->Bind( wxEVT_IDLE, &ZONE_FILLER_TOOL::singleShotRefocus, this );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ZONE_FILLER_TOOL::ZoneFill( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
if( m_fillInProgress )
|
||||
|
@ -216,7 +317,7 @@ int ZONE_FILLER_TOOL::ZoneFill( const TOOL_EVENT& aEvent )
|
|||
if( filler.Fill( toFill ) )
|
||||
{
|
||||
reporter->AdvancePhase();
|
||||
commit.Push( _( "Fill Zone(s)" ), true, true, false );
|
||||
commit.Push( _( "Fill Zone(s)" ), true, true, false, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -253,7 +354,7 @@ int ZONE_FILLER_TOOL::ZoneUnfill( const TOOL_EVENT& aEvent )
|
|||
zone->UnFill();
|
||||
}
|
||||
|
||||
commit.Push( _( "Unfill Zone" ) );
|
||||
commit.Push( _( "Unfill Zone" ), true, true, true, true );
|
||||
canvas()->Refresh();
|
||||
|
||||
return 0;
|
||||
|
@ -271,7 +372,7 @@ int ZONE_FILLER_TOOL::ZoneUnfillAll( const TOOL_EVENT& aEvent )
|
|||
zone->UnFill();
|
||||
}
|
||||
|
||||
commit.Push( _( "Unfill All Zones" ) );
|
||||
commit.Push( _( "Unfill All Zones" ), true, true, true, true );
|
||||
canvas()->Refresh();
|
||||
|
||||
return 0;
|
||||
|
@ -281,8 +382,9 @@ int ZONE_FILLER_TOOL::ZoneUnfillAll( const TOOL_EVENT& aEvent )
|
|||
void ZONE_FILLER_TOOL::setTransitions()
|
||||
{
|
||||
// Zone actions
|
||||
Go( &ZONE_FILLER_TOOL::ZoneFill, PCB_ACTIONS::zoneFill.MakeEvent() );
|
||||
Go( &ZONE_FILLER_TOOL::ZoneFillAll, PCB_ACTIONS::zoneFillAll.MakeEvent() );
|
||||
Go( &ZONE_FILLER_TOOL::ZoneUnfill, PCB_ACTIONS::zoneUnfill.MakeEvent() );
|
||||
Go( &ZONE_FILLER_TOOL::ZoneUnfillAll, PCB_ACTIONS::zoneUnfillAll.MakeEvent() );
|
||||
Go( &ZONE_FILLER_TOOL::ZoneFill, PCB_ACTIONS::zoneFill.MakeEvent() );
|
||||
Go( &ZONE_FILLER_TOOL::ZoneFillAll, PCB_ACTIONS::zoneFillAll.MakeEvent() );
|
||||
Go( &ZONE_FILLER_TOOL::ZoneFillDirty, PCB_ACTIONS::zoneFillDirty.MakeEvent() );
|
||||
Go( &ZONE_FILLER_TOOL::ZoneUnfill, PCB_ACTIONS::zoneUnfill.MakeEvent() );
|
||||
Go( &ZONE_FILLER_TOOL::ZoneUnfillAll, PCB_ACTIONS::zoneUnfillAll.MakeEvent() );
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2014 CERN
|
||||
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
|
@ -28,6 +28,7 @@
|
|||
#define ZONE_FILLER_TOOL_H
|
||||
|
||||
#include <tools/pcb_tool_base.h>
|
||||
#include <zone.h>
|
||||
|
||||
|
||||
class PCB_EDIT_FRAME;
|
||||
|
@ -52,11 +53,17 @@ public:
|
|||
|
||||
int ZoneFill( const TOOL_EVENT& aEvent );
|
||||
int ZoneFillAll( const TOOL_EVENT& aEvent );
|
||||
int ZoneFillDirty( const TOOL_EVENT& aEvent );
|
||||
int ZoneUnfill( const TOOL_EVENT& aEvent );
|
||||
int ZoneUnfillAll( const TOOL_EVENT& aEvent );
|
||||
|
||||
bool IsBusy() { return m_fillInProgress; }
|
||||
|
||||
void DirtyZone( ZONE* aZone )
|
||||
{
|
||||
m_dirtyZoneIDs.insert( aZone->m_Uuid );
|
||||
}
|
||||
|
||||
private:
|
||||
///< Refocus on an idle event (used after the Progress Reporter messes up the focus).
|
||||
void singleShotRefocus( wxIdleEvent& );
|
||||
|
@ -66,6 +73,8 @@ private:
|
|||
|
||||
private:
|
||||
bool m_fillInProgress;
|
||||
|
||||
std::set<KIID> m_dirtyZoneIDs;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <footprint_wizard_frame.h>
|
||||
#include <footprint.h>
|
||||
#include <tools/pcb_actions.h>
|
||||
#include <tools/zone_filler_tool.h>
|
||||
#include <router/router_tool.h>
|
||||
#include <dialog_find.h>
|
||||
#include <dialog_filter_selection.h>
|
||||
|
@ -619,6 +620,28 @@ bool PCB_TOOL_BASE::Is45Limited() const
|
|||
}
|
||||
|
||||
|
||||
ZONE_FILLER_TOOL::ZONE_FILLER_TOOL() :
|
||||
PCB_TOOL_BASE( "pcbnew.ZoneFiller" ),
|
||||
m_fillInProgress( false )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ZONE_FILLER_TOOL::~ZONE_FILLER_TOOL()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ZONE_FILLER_TOOL::Reset( RESET_REASON aReason )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ZONE_FILLER_TOOL::setTransitions()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PCBNEW_SETTINGS::DISPLAY_OPTIONS& PCB_TOOL_BASE::displayOptions() const
|
||||
{
|
||||
static PCBNEW_SETTINGS::DISPLAY_OPTIONS disp;
|
||||
|
|
Loading…
Reference in New Issue