7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-03-30 06:56:57 +00:00

Add tool framework to fp preview widget.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/17107

Fixes https://gitlab.com/kicad/code/kicad/-/issues/19651
This commit is contained in:
Jeff Young 2025-01-24 22:27:25 +00:00
parent 97a0ec504b
commit 9d051d096e
15 changed files with 289 additions and 46 deletions

View File

@ -20,6 +20,7 @@
#include <widgets/footprint_preview_widget.h>
#include <lib_id.h>
#include <class_draw_panel_gal.h>
#include <wx/stattext.h>
#include <wx/sizer.h>
#include <kiway.h>
@ -61,7 +62,7 @@ FOOTPRINT_PREVIEW_WIDGET::FOOTPRINT_PREVIEW_WIDGET( wxWindow* aParent, KIWAY& aK
m_outerSizer = new wxBoxSizer( wxVERTICAL );
if( m_prev_panel )
m_outerSizer->Add( m_prev_panel->GetWindow(), 1, wxALL | wxEXPAND, 0 );
m_outerSizer->Add( m_prev_panel->GetCanvas(), 1, wxALL | wxEXPAND, 0 );
m_outerSizer->Add( m_statusPanel, 1, wxALL | wxEXPAND, 0 );
@ -77,7 +78,7 @@ void FOOTPRINT_PREVIEW_WIDGET::SetStatusText( wxString const& aText )
m_statusPanel->Show();
if( m_prev_panel )
m_prev_panel->GetWindow()->Hide();
m_prev_panel->GetCanvas()->Hide();
Layout();
}
@ -89,7 +90,7 @@ void FOOTPRINT_PREVIEW_WIDGET::ClearStatus()
m_statusPanel->Hide();
if( m_prev_panel )
m_prev_panel->GetWindow()->Show();
m_prev_panel->GetCanvas()->Show();
Layout();
}

View File

@ -31,6 +31,8 @@
class FOOTPRINT_PREVIEW_PANEL_BASE;
class FOOTPRINT;
class KIWAY;
class TOOL_DISPATCHER;
class EDA_DRAW_PANEL_GAL;
class wxStaticText;
class wxSizer;
@ -141,9 +143,9 @@ public:
virtual void RefreshAll() = 0;
/**
* Get the underlying wxWindow.
* Get the GAL canvas.
*/
virtual wxWindow* GetWindow() = 0;
virtual EDA_DRAW_PANEL_GAL* GetCanvas() = 0;
/**
* Get the colors to use in a preview widget to match the preview panel.

View File

@ -395,6 +395,7 @@ set( PCBNEW_CLASS_SRCS
tools/global_edit_tool.cpp
tools/group_tool.cpp
tools/footprint_editor_control.cpp
tools/footprint_chooser_selection_tool.cpp
tools/item_modification_routine.cpp
tools/pad_tool.cpp
tools/pcb_control.cpp

View File

@ -1479,6 +1479,19 @@ void BOARD::DeleteAllFootprints()
}
void BOARD::DetachAllFootprints()
{
for( FOOTPRINT* footprint : m_footprints )
{
m_itemByIdCache.erase( footprint->m_Uuid );
footprint->SetParent( nullptr );
}
m_footprints.clear();
IncrementTimeStamp();
}
BOARD_ITEM* BOARD::GetItem( const KIID& aID ) const
{
if( aID == niluuid )

View File

@ -469,6 +469,11 @@ public:
*/
void DeleteAllFootprints();
/**
* Remove all footprints without deleting. Footprint lifecycle MUST be managed elsewhere.
*/
void DetachAllFootprints();
/**
* @return null if aID is null. Returns an object of Type() == NOT_USED if the aID is not found.
*/

View File

@ -293,13 +293,10 @@ void DIALOG_FOOTPRINT_CHOOSER::TearDownQuasiModal()
{
FOOTPRINT_PREVIEW_PANEL_BASE* previewPanel = viewerWidget->GetPreviewPanel();
FOOTPRINT_PREVIEW_PANEL* fpPreviewPanel =
static_cast<FOOTPRINT_PREVIEW_PANEL*>( previewPanel );
if( fpPreviewPanel )
if( previewPanel )
{
wxLogDebug( wxS( "Stopping footprint preview panel drawing." ) );
fpPreviewPanel->StopDrawing();
previewPanel->GetCanvas()->StopDrawing();
}
}
}

View File

@ -35,11 +35,21 @@
#include <settings/settings_manager.h>
#include <footprint_editor_settings.h>
#include <footprint_chooser_frame.h>
#include <tool/tool_manager.h>
#include <tool/tool_dispatcher.h>
#include <tool/common_tools.h>
#include <tool/zoom_tool.h>
#include <tools/footprint_chooser_selection_tool.h>
#include <tools/pcb_actions.h>
#include <tools/pcb_picker_tool.h>
#include <tools/pcb_viewer_tools.h>
#include "wx/display.h"
#include <footprint_preview_panel.h>
#include <3d_canvas/eda_3d_canvas.h>
#include <project_pcb.h>
#include <widgets/bitmap_button.h>
#include <3d_viewer/eda_3d_viewer_frame.h>
#include <tools/pcb_editor_conditions.h>
static wxArrayString s_FootprintHistoryList;
@ -117,6 +127,7 @@ FOOTPRINT_CHOOSER_FRAME::FOOTPRINT_CHOOSER_FRAME( KIWAY* aKiway, wxWindow* aPare
frameSizer->Add( m_chooserPanel, 1, wxEXPAND );
SetCanvas( m_chooserPanel->GetViewerPanel()->GetPreviewPanel()->GetCanvas() );
SetBoard( new BOARD() );
// This board will only be used to hold a footprint for viewing
@ -176,6 +187,27 @@ FOOTPRINT_CHOOSER_FRAME::FOOTPRINT_CHOOSER_FRAME( KIWAY* aKiway, wxWindow* aPare
Layout();
m_chooserPanel->FinishSetup();
// Create the manager and dispatcher & route draw panel events to the dispatcher
m_toolManager = new TOOL_MANAGER;
m_toolManager->SetEnvironment( GetBoard(), GetCanvas()->GetView(),
GetCanvas()->GetViewControls(), GetViewerSettingsBase(), this );
m_actions = new PCB_ACTIONS();
m_toolDispatcher = new TOOL_DISPATCHER( m_toolManager );
GetCanvas()->SetEventDispatcher( m_toolDispatcher );
m_toolManager->RegisterTool( new COMMON_TOOLS ); // for std context menus (zoom & grid)
m_toolManager->RegisterTool( new PCB_PICKER_TOOL ); // for setting grid origin
m_toolManager->RegisterTool( new ZOOM_TOOL );
m_toolManager->RegisterTool( new PCB_VIEWER_TOOLS );
m_toolManager->RegisterTool( new FOOTPRINT_CHOOSER_SELECTION_TOOL );
m_toolManager->GetTool<PCB_VIEWER_TOOLS>()->SetFootprintFrame( true );
m_toolManager->GetTool<PCB_VIEWER_TOOLS>()->SetIsDefaultTool( true );
m_toolManager->InitTools();
setupUIConditions();
// Connect Events
m_grButton3DView->Connect( wxEVT_COMMAND_BUTTON_CLICKED ,
wxCommandEventHandler( FOOTPRINT_CHOOSER_FRAME::on3DviewReq ),
@ -481,6 +513,12 @@ void FOOTPRINT_CHOOSER_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
}
BOARD_ITEM_CONTAINER* FOOTPRINT_CHOOSER_FRAME::GetModel() const
{
return static_cast<FOOTPRINT_PREVIEW_PANEL*>( m_chooserPanel->GetViewerPanel()->GetPreviewPanel() )->GetCurrentFootprint();
}
bool FOOTPRINT_CHOOSER_FRAME::ShowModal( wxString* aFootprint, wxWindow* aParent )
{
if( aFootprint && !aFootprint->IsEmpty() )
@ -715,3 +753,33 @@ void FOOTPRINT_CHOOSER_FRAME::updatePanelsVisibility()
updateViews();
}
void FOOTPRINT_CHOOSER_FRAME::setupUIConditions()
{
PCB_BASE_FRAME::setupUIConditions();
ACTION_MANAGER* mgr = m_toolManager->GetActionManager();
PCB_EDITOR_CONDITIONS cond( this );
wxASSERT( mgr );
// clang-format off
#define CHECK( x ) ACTION_CONDITIONS().Check( x )
mgr->SetConditions( ACTIONS::toggleGrid, CHECK( cond.GridVisible() ) );
mgr->SetConditions( ACTIONS::toggleCursorStyle, CHECK( cond.FullscreenCursor() ) );
mgr->SetConditions( ACTIONS::millimetersUnits, CHECK( cond.Units( EDA_UNITS::MILLIMETRES ) ) );
mgr->SetConditions( ACTIONS::inchesUnits, CHECK( cond.Units( EDA_UNITS::INCHES ) ) );
mgr->SetConditions( ACTIONS::milsUnits, CHECK( cond.Units( EDA_UNITS::MILS ) ) );
mgr->SetConditions( PCB_ACTIONS::showPadNumbers, CHECK( cond.PadNumbersDisplay() ) );
mgr->SetConditions( PCB_ACTIONS::padDisplayMode, CHECK( !cond.PadFillDisplay() ) );
mgr->SetConditions( PCB_ACTIONS::textOutlines, CHECK( !cond.TextFillDisplay() ) );
mgr->SetConditions( PCB_ACTIONS::graphicsOutlines, CHECK( !cond.GraphicsFillDisplay() ) );
#undef CHECK
// clang-format on
}

View File

@ -49,7 +49,7 @@ public:
~FOOTPRINT_CHOOSER_FRAME();
///< @copydoc PCB_BASE_FRAME::GetModel()
BOARD_ITEM_CONTAINER* GetModel() const override { return nullptr; }
BOARD_ITEM_CONTAINER* GetModel() const override;
/**
* @param aFootprint an optional FPID string to initialize the viewer with and to
@ -68,6 +68,10 @@ public:
bool Show( bool show ) override;
// We don't have a status bar
void SetStatusText( const wxString& aText, int aNumber = 0 ) override {}
void UpdateStatusBar() override {}
protected:
FOOTPRINT_CHOOSER_FRAME( KIWAY* aKiway, wxWindow* aParent );
@ -77,6 +81,8 @@ private:
bool filterFootprint( LIB_TREE_NODE& aNode );
void Show3DViewerFrame();
void setupUIConditions() override;
/// @copydoc PCB_BASE_FRAME::Update3DView
void Update3DView( bool aMarkDirty, bool aRefresh, const wxString* aTitle = nullptr ) override;

View File

@ -76,19 +76,15 @@ FOOTPRINT_PREVIEW_PANEL::FOOTPRINT_PREVIEW_PANEL( KIWAY* aKiway, wxWindow* aPare
FOOTPRINT_PREVIEW_PANEL::~FOOTPRINT_PREVIEW_PANEL( )
{
m_dummyBoard->DetachAllFootprints();
if( m_currentFootprint )
{
GetView()->Remove( m_currentFootprint.get() );
GetView()->Clear();
m_currentFootprint->SetParent( nullptr );
}
if( m_otherFootprint )
{
GetView()->Remove( m_otherFootprint.get() );
GetView()->Clear();
m_otherFootprint->SetParent( nullptr );
}
GetView()->Clear();
}
@ -112,7 +108,7 @@ const COLOR4D& FOOTPRINT_PREVIEW_PANEL::GetForegroundColor() const
void FOOTPRINT_PREVIEW_PANEL::renderFootprint( std::shared_ptr<FOOTPRINT> aFootprint )
{
aFootprint->SetParent( m_dummyBoard.get() );
m_dummyBoard->Add( aFootprint.get() );
INSPECTOR_FUNC inspector =
[&]( EDA_ITEM* descendant, void* aTestData )
@ -161,12 +157,12 @@ void FOOTPRINT_PREVIEW_PANEL::fitToCurrentFootprint()
bool FOOTPRINT_PREVIEW_PANEL::DisplayFootprint( const LIB_ID& aFPID )
{
m_dummyBoard->DetachAllFootprints();
if( m_currentFootprint )
{
GetView()->Remove( m_currentFootprint.get() );
GetView()->Clear();
m_currentFootprint->SetParent( nullptr );
}
GetView()->Clear();
FP_LIB_TABLE* fptbl = PROJECT_PCB::PcbFootprintLibs( &Prj() );
@ -200,18 +196,15 @@ bool FOOTPRINT_PREVIEW_PANEL::DisplayFootprint( const LIB_ID& aFPID )
void FOOTPRINT_PREVIEW_PANEL::DisplayFootprints( std::shared_ptr<FOOTPRINT> aFootprintA,
std::shared_ptr<FOOTPRINT> aFootprintB )
{
m_dummyBoard->DetachAllFootprints();
if( m_currentFootprint )
{
GetView()->Remove( m_currentFootprint.get() );
m_currentFootprint->SetParent( nullptr );
wxASSERT( m_otherFootprint );
if( m_otherFootprint )
GetView()->Remove( m_otherFootprint.get() );
m_otherFootprint->SetParent( nullptr );
GetView()->Clear();
}
GetView()->Clear();
m_currentFootprint = aFootprintA;
m_otherFootprint = aFootprintB;
@ -237,12 +230,6 @@ void FOOTPRINT_PREVIEW_PANEL::RefreshAll()
}
wxWindow* FOOTPRINT_PREVIEW_PANEL::GetWindow()
{
return static_cast<wxWindow*>( this );
}
FOOTPRINT_PREVIEW_PANEL* FOOTPRINT_PREVIEW_PANEL::New( KIWAY* aKiway, wxWindow* aParent,
UNITS_PROVIDER* aUnitsProvider )
{

View File

@ -67,14 +67,14 @@ public:
virtual const KIGFX::COLOR4D& GetBackgroundColor() const override;
virtual const KIGFX::COLOR4D& GetForegroundColor() const override;
virtual wxWindow* GetWindow() override;
virtual EDA_DRAW_PANEL_GAL* GetCanvas() override { return this; };
BOARD* GetBoard() { return m_dummyBoard.get(); }
virtual void RefreshAll() override;
static FOOTPRINT_PREVIEW_PANEL* New( KIWAY* aKiway, wxWindow* aParent,
UNITS_PROVIDER* aUnitsProvider );
const FOOTPRINT* GetCurrentFootprint() const { return m_currentFootprint.get(); }
FOOTPRINT* GetCurrentFootprint() const { return m_currentFootprint.get(); }
private:
/**

View File

@ -0,0 +1,76 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <tools/pcb_viewer_tools.h>
#include <tool/actions.h>
#include <tool/tool_event.h>
#include <tool/tool_manager.h>
#include <tools/pcb_actions.h>
#include <tools/footprint_chooser_selection_tool.h>
FOOTPRINT_CHOOSER_SELECTION_TOOL::FOOTPRINT_CHOOSER_SELECTION_TOOL() :
TOOL_INTERACTIVE( "footprintChooserDummySelectionTool" )
{
}
bool FOOTPRINT_CHOOSER_SELECTION_TOOL::Init()
{
PCB_VIEWER_TOOLS* viewerTools = m_toolMgr->GetTool<PCB_VIEWER_TOOLS>();
CONDITIONAL_MENU& menu = viewerTools->GetToolMenu().GetMenu();
menu.AddSeparator( 1 );
menu.AddCheckItem( ACTIONS::toggleGrid, SELECTION_CONDITIONS::ShowAlways, 1 );
menu.AddCheckItem( ACTIONS::toggleCursorStyle, SELECTION_CONDITIONS::ShowAlways, 1 );
menu.AddSeparator( 10 );
menu.AddCheckItem( ACTIONS::inchesUnits, SELECTION_CONDITIONS::ShowAlways, 10 );
menu.AddCheckItem( ACTIONS::milsUnits, SELECTION_CONDITIONS::ShowAlways, 10 );
menu.AddCheckItem( ACTIONS::millimetersUnits, SELECTION_CONDITIONS::ShowAlways, 10 );
menu.AddSeparator( 20 );
menu.AddCheckItem( PCB_ACTIONS::showPadNumbers, SELECTION_CONDITIONS::ShowAlways, 20 );
menu.AddCheckItem( PCB_ACTIONS::padDisplayMode, SELECTION_CONDITIONS::ShowAlways, 20 );
menu.AddCheckItem( PCB_ACTIONS::textOutlines, SELECTION_CONDITIONS::ShowAlways, 20 );
menu.AddCheckItem( PCB_ACTIONS::graphicsOutlines, SELECTION_CONDITIONS::ShowAlways, 20 );
return true;
}
int FOOTPRINT_CHOOSER_SELECTION_TOOL::UpdateMenu( const TOOL_EVENT& aEvent )
{
ACTION_MENU* actionMenu = aEvent.Parameter<ACTION_MENU*>();
CONDITIONAL_MENU* conditionalMenu = dynamic_cast<CONDITIONAL_MENU*>( actionMenu );
if( conditionalMenu )
conditionalMenu->Evaluate( m_selection );
if( actionMenu )
actionMenu->UpdateAll();
return 0;
}
void FOOTPRINT_CHOOSER_SELECTION_TOOL::setTransitions()
{
Go( &FOOTPRINT_CHOOSER_SELECTION_TOOL::UpdateMenu, ACTIONS::updateMenu.MakeEvent() );
}

View File

@ -0,0 +1,69 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FOOTPRINT_CHOOSER_SELECTION_TOOL_H_
#define FOOTPRINT_CHOOSER_SELECTION_TOOL_H_
#include <tool/action_menu.h>
#include <tool/selection.h>
#include <tool/tool_interactive.h>
#include <tool/tool_menu.h>
/**
* Selection tool for the footprint viewer in CvPcb.
*/
class FOOTPRINT_CHOOSER_SELECTION_TOOL : public TOOL_INTERACTIVE
{
public:
FOOTPRINT_CHOOSER_SELECTION_TOOL();
~FOOTPRINT_CHOOSER_SELECTION_TOOL() {}
/// @copydoc TOOL_BASE::Init()
bool Init() override;
/// @copydoc TOOL_BASE::Reset()
void Reset( RESET_REASON aReason ) override {}
/**
* Selections aren't currently supported in the footprint viewer.
*/
SELECTION& GetSelection()
{
return m_selection;
}
void clearSelection() {}
/**
* Update the menu to reflect the current tool states.
*
* @param aEvent is the event generated by the tool framework.
*/
int UpdateMenu( const TOOL_EVENT& aEvent );
/// Set up handlers for various events.
void setTransitions() override;
private:
/// Current state of selection (not really used: no selection in display footprints frame).
SELECTION m_selection;
};
#endif

View File

@ -30,7 +30,6 @@
#include <gal/graphics_abstraction_layer.h>
#include <kiplatform/ui.h>
#include <pcb_base_frame.h>
#include <pcbnew_settings.h>
#include <preview_items/ruler_item.h>
#include <pgm_base.h>
#include <settings/settings_manager.h>
@ -51,14 +50,17 @@ bool PCB_VIEWER_TOOLS::Init()
CONDITIONAL_MENU& ctxMenu = m_menu->GetMenu();
// "Cancel" goes at the top of the context menu when a tool is active
ctxMenu.AddItem( ACTIONS::cancelInteractive, activeToolCondition, 1 );
ctxMenu.AddSeparator( 1 );
if( !m_isDefaultTool )
{
ctxMenu.AddItem( ACTIONS::cancelInteractive, activeToolCondition, 1 );
ctxMenu.AddSeparator( 1 );
}
ctxMenu.AddCheckItem( PCB_ACTIONS::toggleHV45Mode, activeToolCondition, 2 );
ctxMenu.AddSeparator( activeToolCondition, 2 );
ctxMenu.AddCheckItem( PCB_ACTIONS::toggleHV45Mode, activeToolCondition, 2 );
ctxMenu.AddSeparator( activeToolCondition, 2 );
ctxMenu.AddItem( ACTIONS::copy, activeToolCondition, 3 );
ctxMenu.AddSeparator( activeToolCondition, 3 );
ctxMenu.AddItem( ACTIONS::copy, activeToolCondition, 3 );
ctxMenu.AddSeparator( activeToolCondition, 3 );
frame()->AddStandardSubMenus( *m_menu.get() );
@ -275,6 +277,11 @@ int PCB_VIEWER_TOOLS::MeasureTool( const TOOL_EVENT& aEvent )
{
cleanup();
}
else if( m_isDefaultTool )
{
view.SetVisible( &ruler, false );
view.Remove( &ruler );
}
else
{
frame()->PopTool( aEvent );

View File

@ -80,6 +80,11 @@ public:
m_footprintFrame = aIsFrame;
}
void SetIsDefaultTool( bool aIsDefaultTool )
{
m_isDefaultTool = aIsDefaultTool;
}
bool IsFootprintFrame() const
{
return m_footprintFrame;
@ -116,7 +121,9 @@ protected:
return board()->GetFirstFootprint();
}
protected:
bool m_footprintFrame; ///< Is this tool associated with a footprint frame
bool m_isDefaultTool; ///< Indicates no selection tool is present in the current toolset
};
#endif

View File

@ -43,6 +43,8 @@
#include <footprint_info_impl.h>
#include <project_pcb.h>
#include <kiface_base.h>
#include <tool/actions.h>
#include <tool/tool_manager.h>
// When a new footprint is selected, a custom event is sent, for instance to update
// 3D viewer. So define a FP_SELECTION_EVENT event
@ -371,6 +373,8 @@ void PANEL_FOOTPRINT_CHOOSER::onFootprintSelected( wxCommandEvent& aEvent )
event.SetEventObject( this );
ProcessWindowEvent( event );
m_frame->GetToolManager()->RunAction( ACTIONS::measureTool );
}