kicad/cvpcb/tools/cvpcb_association_tool.cpp

318 lines
8.6 KiB
C++

/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 Ian McInerney <Ian.S.McInerney@ieee.org>
* Copyright (C) 2019 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 <confirm.h>
#include <cstdint>
#include <functional>
#include <kiface_i.h>
#include <kiway_express.h>
#include <lib_id.h>
#include <tool/actions.h>
#include <tool/tool_manager.h>
#include <wx/clipbrd.h>
#include <cvpcb_association.h>
#include <cvpcb_mainframe.h>
#include <dialogs/dialog_config_equfiles.h>
#include <display_footprints_frame.h>
#include <listboxes.h>
#include <tools/cvpcb_actions.h>
#include <tools/cvpcb_association_tool.h>
using namespace std::placeholders;
CVPCB_ASSOCIATION_TOOL::CVPCB_ASSOCIATION_TOOL() :
TOOL_INTERACTIVE( "cvpcb.Association" ),
m_frame( nullptr )
{
}
int CVPCB_ASSOCIATION_TOOL::CopyAssoc( const TOOL_EVENT& aEvent )
{
COMPONENT* comp;
LIB_ID fpid;
// Default to using the component control as the source of the copy
CVPCB_MAINFRAME::CONTROL_TYPE copyControl = CVPCB_MAINFRAME::CONTROL_COMPONENT;
// If using the keyboard to copy, find out what control we are in and use that.
if( aEvent.HasPosition() )
copyControl = m_frame->GetFocusedControl();
switch( copyControl )
{
case CVPCB_MAINFRAME::CONTROL_FOOTPRINT:
fpid.Parse( m_frame->GetSelectedFootprint(), LIB_ID::ID_PCB );
break;
case CVPCB_MAINFRAME::CONTROL_COMPONENT:
// Get the selection
comp = m_frame->GetSelectedComponent();
if( !comp )
return 0;
// Get the fpid and save it to the clipboard
fpid = comp->GetFPID();
break;
default:
// Do nothing
break;
}
// if no valid fpid, then skip
if( !fpid.IsValid() )
return 0;
if( wxTheClipboard->Open() )
{
if( !wxTheClipboard->SetData( new wxTextDataObject( fpid.GetUniStringLibId() ) ) )
wxLogDebug( "Failed to copy data to clipboard" );
wxTheClipboard->Flush();
wxTheClipboard->Close();
}
else
wxLogDebug( "Failed to open the clipboard" );
return 0;
}
int CVPCB_ASSOCIATION_TOOL::CutAssoc( const TOOL_EVENT& aEvent )
{
// If using the keyboard, only cut in the component frame
if( aEvent.HasPosition()
&& ( m_frame->GetFocusedControl() != CVPCB_MAINFRAME::CONTROL_COMPONENT ) )
return 0;
// Get the selection, but only use the first one
COMPONENT* comp = m_frame->GetSelectedComponent();
std::vector<unsigned int> idx = m_frame->GetComponentIndices( CVPCB_MAINFRAME::SEL_COMPONENTS );
if( idx.empty() || !comp )
return 0;
// Get the fpid
LIB_ID fpid;
fpid = comp->GetFPID();
// if no valid fpid, then skip
if( !fpid.IsValid() )
return 0;
// Save it to the clipboard
if( wxTheClipboard->Open() )
{
if( !wxTheClipboard->SetData( new wxTextDataObject( fpid.GetUniStringLibId() ) ) )
{
wxLogDebug( "Failed to cut data to clipboard" );
wxTheClipboard->Close();
return 0;
}
wxTheClipboard->Flush();
wxTheClipboard->Close();
}
else
{
wxLogDebug( "Failed to open the clipboard" );
return 0;
}
// Remove the association
m_frame->AssociateFootprint( CVPCB_ASSOCIATION( idx.front(), "" ) );
return 0;
}
int CVPCB_ASSOCIATION_TOOL::PasteAssoc( const TOOL_EVENT& aEvent )
{
// Get the selection
std::vector<unsigned int> idx = m_frame->GetComponentIndices( CVPCB_MAINFRAME::SEL_COMPONENTS );
if( idx.empty() )
return 0;
// Get the clipboard data and ensure it is valid
LIB_ID fpid;
wxTextDataObject data;
if( wxTheClipboard->Open() )
{
wxTheClipboard->GetData( data );
wxTheClipboard->Close();
}
else
{
wxLogDebug( "Failed to open the clipboard" );
return 0;
}
if( fpid.Parse( data.GetText(), LIB_ID::ID_PCB ) >= 0 )
return 0;
// Assign the fpid to the selections
bool firstAssoc = true;
for( auto i : idx )
{
m_frame->AssociateFootprint( CVPCB_ASSOCIATION( i, fpid ), firstAssoc );
firstAssoc = false;
}
return 0;
}
void CVPCB_ASSOCIATION_TOOL::Reset( RESET_REASON aReason )
{
m_frame = getEditFrame<CVPCB_MAINFRAME>();
}
int CVPCB_ASSOCIATION_TOOL::Undo( const TOOL_EVENT& aEvent )
{
m_frame->UndoAssociation();
return 0;
}
int CVPCB_ASSOCIATION_TOOL::Redo( const TOOL_EVENT& aEvent )
{
m_frame->RedoAssociation();
return 0;
}
int CVPCB_ASSOCIATION_TOOL::Associate( const TOOL_EVENT& aEvent )
{
// Get the currently selected footprint
LIB_ID fpid;
wxString fp = m_frame->GetSelectedFootprint();
fpid.Parse( fp, LIB_ID::ID_PCB );
// Ignore the action if the footprint is empty (nothing selected)
if( fpid.empty() )
return 0;
// Test for validity of the requested footprint
if( !fpid.IsValid() )
{
wxString msg =
wxString::Format( _( "\"%s\" is not a valid footprint." ), fpid.Format().wx_str() );
DisplayErrorMessage( m_frame, msg );
}
// Get all the components that are selected and associate them with the current footprint
std::vector<unsigned int> sel = m_frame->GetComponentIndices( CVPCB_MAINFRAME::SEL_COMPONENTS );
bool firstAssoc = true;
for( auto i : sel )
{
CVPCB_ASSOCIATION newfp( i, fpid );
m_frame->AssociateFootprint( newfp, firstAssoc );
firstAssoc = false;
}
// Move to the next not associated component
m_toolMgr->RunAction( CVPCB_ACTIONS::gotoNextNA );
return 0;
}
int CVPCB_ASSOCIATION_TOOL::AutoAssociate( const TOOL_EVENT& aEvent )
{
m_frame->AutomaticFootprintMatching();
return 0;
}
int CVPCB_ASSOCIATION_TOOL::DeleteAssoc( const TOOL_EVENT& aEvent )
{
// Get all the components that are selected
std::vector<unsigned int> sel = m_frame->GetComponentIndices( CVPCB_MAINFRAME::SEL_COMPONENTS );
// Delete the association
bool firstAssoc = true;
for( auto i : sel )
{
m_frame->AssociateFootprint( CVPCB_ASSOCIATION( i, LIB_ID() ), firstAssoc );
firstAssoc = false;
}
return 0;
}
int CVPCB_ASSOCIATION_TOOL::DeleteAll( const TOOL_EVENT& aEvent )
{
if( IsOK( m_frame, _( "Delete all associations?" ) ) )
{
// Remove all selections to avoid issues when setting the fpids
m_frame->SetSelectedComponent( -1, true );
std::vector<unsigned int> idx =
m_frame->GetComponentIndices( CVPCB_MAINFRAME::ALL_COMPONENTS );
bool firstAssoc = true;
for( auto i : idx )
{
m_frame->AssociateFootprint( CVPCB_ASSOCIATION( i, LIB_ID() ), firstAssoc );
firstAssoc = false;
}
// Remove all selections after setting the fpids and select the first component
m_frame->SetSelectedComponent( -1, true );
m_frame->SetSelectedComponent( 0 );
}
// Update the status display
m_frame->DisplayStatus();
return 0;
}
void CVPCB_ASSOCIATION_TOOL::setTransitions()
{
// Association
Go( &CVPCB_ASSOCIATION_TOOL::Associate, CVPCB_ACTIONS::associate.MakeEvent() );
Go( &CVPCB_ASSOCIATION_TOOL::AutoAssociate, CVPCB_ACTIONS::autoAssociate.MakeEvent() );
// Deletion
Go( &CVPCB_ASSOCIATION_TOOL::DeleteAll, CVPCB_ACTIONS::deleteAll.MakeEvent() );
Go( &CVPCB_ASSOCIATION_TOOL::DeleteAssoc, CVPCB_ACTIONS::deleteAssoc.MakeEvent() );
// Helpers
Go( &CVPCB_ASSOCIATION_TOOL::Undo, ACTIONS::undo.MakeEvent() );
Go( &CVPCB_ASSOCIATION_TOOL::Redo, ACTIONS::redo.MakeEvent() );
// Clipboard
Go( &CVPCB_ASSOCIATION_TOOL::CutAssoc, ACTIONS::cut.MakeEvent() );
Go( &CVPCB_ASSOCIATION_TOOL::CopyAssoc, ACTIONS::copy.MakeEvent() );
Go( &CVPCB_ASSOCIATION_TOOL::PasteAssoc, ACTIONS::paste.MakeEvent() );
}