kicad-source/common/widgets/net_selector.cpp
Seth Hillbrand 0b2d4d4879 Revise Copyright statement to align with TLF
Recommendation is to avoid using the year nomenclature as this
information is already encoded in the git repo.  Avoids needing to
repeatly update.

Also updates AUTHORS.txt from current repo with contributor names
2025-01-01 14:12:04 -08:00

292 lines
8.4 KiB
C++

/*
* 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 2
* 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, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "widgets/net_selector.h"
#include <string_utils.h>
#include <board.h>
#include <netinfo.h>
#define NO_NET _( "<no net>" )
#define CREATE_NET _( "<create net>" )
class NET_SELECTOR_COMBOPOPUP : public FILTER_COMBOPOPUP
{
public:
NET_SELECTOR_COMBOPOPUP() :
m_netinfoList( nullptr ),
m_board( nullptr ),
m_selectedNetcode( 0 )
{ }
wxString GetStringValue() const override
{
if( m_selectedNetcode == -1 )
return m_indeterminateLabel;
NETINFO_ITEM* netInfo = m_netinfoList->GetNetItem( m_selectedNetcode );
if( netInfo && netInfo->GetNetCode() > 0 )
return netInfo->GetNetname();
return NO_NET;
}
void SetNetInfo( const NETINFO_LIST* aNetInfoList )
{
m_netinfoList = aNetInfoList;
rebuildList();
}
void SetIndeterminateLabel( const wxString& aIndeterminateLabel )
{
m_indeterminateLabel = aIndeterminateLabel;
rebuildList();
}
void SetBoard( BOARD* aBoard )
{
m_board = aBoard;
}
void SetIndeterminate() { m_selectedNetcode = -1; }
bool IsIndeterminate() { return m_selectedNetcode == -1; }
void SetSelectedNetcode( int aNetcode ) { m_selectedNetcode = aNetcode; }
int GetSelectedNetcode() { return m_selectedNetcode; }
void SetSelectedNet( const wxString& aNetname )
{
if( m_netinfoList && m_netinfoList->GetNetItem( aNetname ) )
m_selectedNetcode = m_netinfoList->GetNetItem( aNetname )->GetNetCode();
}
wxString GetSelectedNetname()
{
if( m_netinfoList && m_netinfoList->GetNetItem( m_selectedNetcode ) )
return m_netinfoList->GetNetItem( m_selectedNetcode )->GetNetname();
else
return wxEmptyString;
}
void Accept() override
{
wxString escapedNetName;
wxString remainingName;
wxString selectedNetName = getSelectedValue().value_or( wxEmptyString );
auto it = m_unescapedNetNameMap.find( selectedNetName );
if( it != m_unescapedNetNameMap.end() )
escapedNetName = it->second;
else // shouldn't happen....
escapedNetName = selectedNetName;
Dismiss();
if( escapedNetName.IsEmpty() || escapedNetName == m_indeterminateLabel )
{
m_selectedNetcode = -1;
GetComboCtrl()->SetValue( m_indeterminateLabel );
}
else if( escapedNetName == NO_NET )
{
m_selectedNetcode = 0;
GetComboCtrl()->SetValue( NO_NET );
}
else if( escapedNetName.StartsWith( CREATE_NET, &remainingName ) &&
!remainingName.IsEmpty() )
{
// Remove the first character ':' and all whitespace
remainingName = remainingName.Mid( 1 ).Trim().Trim( false );
BOARD* board = m_netinfoList->GetParent();
NETINFO_ITEM *newnet = new NETINFO_ITEM( m_board, remainingName, 0 );
wxASSERT( board );
if( board )
board->Add( newnet );
rebuildList();
if( newnet->GetNetCode() > 0 )
{
m_selectedNetcode = newnet->GetNetCode();
GetComboCtrl()->SetValue( UnescapeString( remainingName ) );
}
else
{
// This indicates that the NETINFO_ITEM was not successfully appended to the
// list for unknown reasons
if( board )
board->Remove( newnet );
delete newnet;
}
}
else
{
NETINFO_ITEM* netInfo = m_netinfoList->GetNetItem( escapedNetName );
if( netInfo == nullptr || netInfo->GetNetCode() == 0 )
{
m_selectedNetcode = 0;
GetComboCtrl()->SetValue( NO_NET );
}
else
{
m_selectedNetcode = netInfo->GetNetCode();
GetComboCtrl()->SetValue( UnescapeString( escapedNetName ) );
}
}
wxCommandEvent changeEvent( FILTERED_ITEM_SELECTED );
wxPostEvent( GetComboCtrl(), changeEvent );
}
protected:
void getListContent( wxArrayString& aNetnames ) override
{
wxString netstring = getFilterValue();
wxString filter = netstring.Lower();
m_unescapedNetNameMap.clear();
if( !filter.IsEmpty() )
filter = wxT( "*" ) + filter + wxT( "*" );
for( NETINFO_ITEM* netinfo : *m_netinfoList )
{
if( netinfo->GetNetCode() > 0 && netinfo->IsCurrent() )
{
wxString netname = UnescapeString( netinfo->GetNetname() );
if( filter.IsEmpty() || wxString( netname ).MakeLower().Matches( filter ) )
{
aNetnames.push_back( netname );
m_unescapedNetNameMap[ netname ] = netinfo->GetNetname();
}
}
}
std::sort( aNetnames.begin(), aNetnames.end(),
[]( const wxString& lhs, const wxString& rhs )
{
return StrNumCmp( lhs, rhs, true /* ignore case */ ) < 0;
} );
// Special handling for <no net>
if( filter.IsEmpty() || wxString( NO_NET ).MakeLower().Matches( filter ) )
aNetnames.insert( aNetnames.begin(), NO_NET );
if( !filter.IsEmpty() && !m_netinfoList->GetNetItem( netstring ) )
{
wxString newnet = wxString::Format( "%s: %s", CREATE_NET, netstring );
aNetnames.insert( aNetnames.end(), newnet );
}
if( !m_indeterminateLabel.IsEmpty() )
aNetnames.push_back( m_indeterminateLabel );
}
const NETINFO_LIST* m_netinfoList;
wxString m_indeterminateLabel;
BOARD* m_board;
int m_selectedNetcode;
std::map<wxString, wxString> m_unescapedNetNameMap;
};
NET_SELECTOR::NET_SELECTOR( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
long style ) :
FILTER_COMBOBOX( parent, id, pos, size, style )
{
m_netSelectorPopup = new NET_SELECTOR_COMBOPOPUP();
setFilterPopup( m_netSelectorPopup );
}
void NET_SELECTOR::SetNetInfo( const NETINFO_LIST* aNetInfoList )
{
m_netSelectorPopup->SetNetInfo( aNetInfoList );
}
void NET_SELECTOR::SetIndeterminateString( const wxString& aString )
{
m_indeterminateString = aString;
m_netSelectorPopup->SetIndeterminateLabel( aString );
}
void NET_SELECTOR::SetBoard( BOARD* aBoard )
{
m_netSelectorPopup->SetBoard( aBoard );
}
void NET_SELECTOR::SetSelectedNetcode( int aNetcode )
{
m_netSelectorPopup->SetSelectedNetcode( aNetcode );
SetValue( UnescapeString( m_netSelectorPopup->GetStringValue() ) );
}
void NET_SELECTOR::SetSelectedNet( const wxString& aNetname )
{
m_netSelectorPopup->SetSelectedNet( aNetname );
SetValue( UnescapeString( m_netSelectorPopup->GetStringValue() ) );
}
wxString NET_SELECTOR::GetSelectedNetname()
{
return m_netSelectorPopup->GetSelectedNetname();
}
void NET_SELECTOR::SetIndeterminate()
{
m_netSelectorPopup->SetIndeterminate();
SetValue( m_indeterminateString );
}
bool NET_SELECTOR::IsIndeterminate()
{
return m_netSelectorPopup->IsIndeterminate();
}
int NET_SELECTOR::GetSelectedNetcode()
{
return m_netSelectorPopup->GetSelectedNetcode();
}