mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 10:13:19 +02:00
Passing a pointer to the CTOR invokes the PCB_FIELD( BOARD_ITEM* ) ctor, which is not what is intended. Passing just the reference is better but still ends up creating a PCB_FIELD class with type PCB_TEXT because it didn't correctly set the type. So we need to properly set our type and our parent, then copy the text attributes over. We can't use the default copy operator because this also copies the struct_id of PCB_TEXT Fixes https://gitlab.com/kicad/code/kicad/-/issues/20875
301 lines
8.3 KiB
C++
301 lines
8.3 KiB
C++
/*
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
*
|
|
* Copyright (C) 2023 Mike Williams, mike@mikebwilliams.com
|
|
* 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 <pcb_field.h>
|
|
#include <footprint.h>
|
|
#include <board_design_settings.h>
|
|
#include <i18n_utility.h>
|
|
#include <pcb_painter.h>
|
|
#include <api/board/board_types.pb.h>
|
|
#include <string_utils.h>
|
|
|
|
|
|
PCB_FIELD::PCB_FIELD( FOOTPRINT* aParent, FIELD_T aFieldId, const wxString& aName ) :
|
|
PCB_TEXT( aParent, PCB_FIELD_T ),
|
|
m_id( aFieldId ),
|
|
m_ordinal( 0 ),
|
|
m_name( aName )
|
|
{
|
|
if( m_id == FIELD_T::USER )
|
|
m_ordinal = aParent->GetNextFieldOrdinal();
|
|
}
|
|
|
|
|
|
PCB_FIELD::PCB_FIELD( const PCB_TEXT& aText, FIELD_T aFieldId, const wxString& aName ) :
|
|
PCB_TEXT( aText.GetParent(), PCB_FIELD_T ),
|
|
m_id( aFieldId ),
|
|
m_ordinal( static_cast<int>( aFieldId ) ),
|
|
m_name( aName )
|
|
{
|
|
// Copy the text properties from the PCB_TEXT
|
|
SetText( aText.GetText() );
|
|
SetVisible( aText.IsVisible() );
|
|
SetLayer( aText.GetLayer() );
|
|
SetPosition( aText.GetPosition() );
|
|
SetAttributes( aText.GetAttributes() );
|
|
}
|
|
|
|
|
|
void PCB_FIELD::Serialize( google::protobuf::Any &aContainer ) const
|
|
{
|
|
kiapi::board::types::Field field;
|
|
|
|
google::protobuf::Any anyText;
|
|
PCB_TEXT::Serialize( anyText );
|
|
anyText.UnpackTo( field.mutable_text() );
|
|
|
|
field.set_name( GetCanonicalName().ToStdString() );
|
|
field.mutable_id()->set_id( (int) GetId() );
|
|
field.set_visible( IsVisible() );
|
|
|
|
aContainer.PackFrom( field );
|
|
}
|
|
|
|
|
|
bool PCB_FIELD::Deserialize( const google::protobuf::Any &aContainer )
|
|
{
|
|
kiapi::board::types::Field field;
|
|
|
|
if( !aContainer.UnpackTo( &field ) )
|
|
return false;
|
|
|
|
if( field.has_id() )
|
|
setId( (FIELD_T) field.id().id() );
|
|
|
|
// Mandatory fields have a blank Name in the KiCad object
|
|
if( !IsMandatory() )
|
|
SetName( wxString( field.name().c_str(), wxConvUTF8 ) );
|
|
|
|
if( field.has_text() )
|
|
{
|
|
google::protobuf::Any anyText;
|
|
anyText.PackFrom( field.text() );
|
|
PCB_TEXT::Deserialize( anyText );
|
|
}
|
|
|
|
SetVisible( field.visible() );
|
|
|
|
if( field.text().layer() == kiapi::board::types::BoardLayer::BL_UNKNOWN )
|
|
SetLayer( F_SilkS );
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
wxString PCB_FIELD::GetName( bool aUseDefaultName ) const
|
|
{
|
|
if( IsMandatory() )
|
|
return GetCanonicalFieldName( m_id );
|
|
else if( m_name.IsEmpty() && aUseDefaultName )
|
|
return GetUserFieldName( m_ordinal, !DO_TRANSLATE );
|
|
else
|
|
return m_name;
|
|
}
|
|
|
|
|
|
wxString PCB_FIELD::GetCanonicalName() const
|
|
{
|
|
return GetName( true );
|
|
}
|
|
|
|
|
|
bool PCB_FIELD::IsMandatory() const
|
|
{
|
|
return m_id == FIELD_T::REFERENCE
|
|
|| m_id == FIELD_T::VALUE
|
|
|| m_id == FIELD_T::DATASHEET
|
|
|| m_id == FIELD_T::DESCRIPTION;
|
|
}
|
|
|
|
|
|
bool PCB_FIELD::IsHypertext() const
|
|
{
|
|
return IsURL( GetShownText( false ) );
|
|
}
|
|
|
|
|
|
wxString PCB_FIELD::GetTextTypeDescription() const
|
|
{
|
|
if( IsMandatory() )
|
|
return GetCanonicalFieldName( m_id );
|
|
else
|
|
return _( "User Field" );
|
|
}
|
|
|
|
|
|
bool PCB_FIELD::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
|
|
{
|
|
if( !IsVisible() && !aSearchData.searchAllFields )
|
|
return false;
|
|
|
|
return PCB_TEXT::Matches( aSearchData, aAuxData );
|
|
}
|
|
|
|
|
|
wxString PCB_FIELD::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
|
|
{
|
|
wxString content = aFull ? GetShownText( false ) : KIUI::EllipsizeMenuText( GetText() );
|
|
wxString ref = GetParentFootprint()->GetReference();
|
|
|
|
switch( m_id )
|
|
{
|
|
case FIELD_T::REFERENCE:
|
|
return wxString::Format( _( "Reference field of %s" ), ref );
|
|
|
|
case FIELD_T::VALUE:
|
|
return wxString::Format( _( "Value field of %s (%s)" ), ref, content );
|
|
|
|
case FIELD_T::FOOTPRINT:
|
|
return wxString::Format( _( "Footprint field of %s (%s)" ), ref, content );
|
|
|
|
case FIELD_T::DATASHEET:
|
|
return wxString::Format( _( "Datasheet field of %s (%s)" ), ref, content );
|
|
|
|
default:
|
|
if( GetName().IsEmpty() )
|
|
return wxString::Format( _( "Field of %s (%s)" ), ref, content );
|
|
else
|
|
return wxString::Format( _( "%s field of %s (%s)" ), GetName(), ref, content );
|
|
}
|
|
}
|
|
|
|
|
|
double PCB_FIELD::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
|
|
{
|
|
if( !aView )
|
|
return LOD_SHOW;
|
|
|
|
KIGFX::PCB_PAINTER* painter = static_cast<KIGFX::PCB_PAINTER*>( aView->GetPainter() );
|
|
KIGFX::PCB_RENDER_SETTINGS* renderSettings = painter->GetSettings();
|
|
|
|
if( GetParentFootprint() && GetParentFootprint()->IsSelected()
|
|
&& renderSettings->m_ForceShowFieldsWhenFPSelected )
|
|
{
|
|
return LOD_SHOW;
|
|
}
|
|
|
|
// Handle Render tab switches
|
|
if( IsValue() && !aView->IsLayerVisible( LAYER_FP_VALUES ) )
|
|
return LOD_HIDE;
|
|
|
|
if( IsReference() && !aView->IsLayerVisible( LAYER_FP_REFERENCES ) )
|
|
return LOD_HIDE;
|
|
|
|
return PCB_TEXT::ViewGetLOD( aLayer, aView );
|
|
}
|
|
|
|
|
|
EDA_ITEM* PCB_FIELD::Clone() const
|
|
{
|
|
return new PCB_FIELD( *this );
|
|
}
|
|
|
|
|
|
void PCB_FIELD::swapData( BOARD_ITEM* aImage )
|
|
{
|
|
assert( aImage->Type() == PCB_FIELD_T );
|
|
|
|
std::swap( *((PCB_FIELD*) this), *((PCB_FIELD*) aImage) );
|
|
}
|
|
|
|
|
|
bool PCB_FIELD::operator==( const BOARD_ITEM& aOther ) const
|
|
{
|
|
if( aOther.Type() != Type() )
|
|
return false;
|
|
|
|
const PCB_FIELD& other = static_cast<const PCB_FIELD&>( aOther );
|
|
|
|
return *this == other;
|
|
}
|
|
|
|
|
|
bool PCB_FIELD::operator==( const PCB_FIELD& aOther ) const
|
|
{
|
|
if( IsMandatory() != aOther.IsMandatory() )
|
|
return false;
|
|
|
|
if( IsMandatory() )
|
|
{
|
|
if( m_id != aOther.m_id )
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
if( m_ordinal != aOther.m_ordinal )
|
|
return false;
|
|
}
|
|
|
|
return m_name == aOther.m_name && EDA_TEXT::operator==( aOther );
|
|
}
|
|
|
|
|
|
double PCB_FIELD::Similarity( const BOARD_ITEM& aOther ) const
|
|
{
|
|
if( m_Uuid == aOther.m_Uuid )
|
|
return 1.0;
|
|
|
|
if( aOther.Type() != Type() )
|
|
return 0.0;
|
|
|
|
const PCB_FIELD& other = static_cast<const PCB_FIELD&>( aOther );
|
|
|
|
if( IsMandatory() || other.IsMandatory() )
|
|
{
|
|
if( m_id == other.m_id )
|
|
return 1.0;
|
|
else
|
|
return 0.0;
|
|
}
|
|
|
|
if( m_name == other.m_name )
|
|
return 1.0;
|
|
|
|
return EDA_TEXT::Similarity( other );
|
|
}
|
|
|
|
static struct PCB_FIELD_DESC
|
|
{
|
|
PCB_FIELD_DESC()
|
|
{
|
|
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
|
|
REGISTER_TYPE( PCB_FIELD );
|
|
propMgr.AddTypeCast( new TYPE_CAST<PCB_FIELD, PCB_TEXT> );
|
|
propMgr.AddTypeCast( new TYPE_CAST<PCB_FIELD, BOARD_ITEM> );
|
|
propMgr.AddTypeCast( new TYPE_CAST<PCB_FIELD, EDA_TEXT> );
|
|
propMgr.InheritsAfter( TYPE_HASH( PCB_FIELD ), TYPE_HASH( BOARD_ITEM ) );
|
|
propMgr.InheritsAfter( TYPE_HASH( PCB_FIELD ), TYPE_HASH( PCB_TEXT ) );
|
|
propMgr.InheritsAfter( TYPE_HASH( PCB_FIELD ), TYPE_HASH( EDA_TEXT ) );
|
|
|
|
propMgr.AddProperty( new PROPERTY<PCB_FIELD, wxString>( _HKI( "Name" ),
|
|
NO_SETTER( PCB_FIELD, wxString ), &PCB_FIELD::GetCanonicalName ) )
|
|
.SetIsHiddenFromLibraryEditors()
|
|
.SetIsHiddenFromPropertiesManager();
|
|
|
|
// These properties, inherited from EDA_TEXT, have no sense for the board editor
|
|
propMgr.Mask( TYPE_HASH( PCB_FIELD ), TYPE_HASH( EDA_TEXT ), _HKI( "Hyperlink" ) );
|
|
propMgr.Mask( TYPE_HASH( PCB_FIELD ), TYPE_HASH( EDA_TEXT ), _HKI( "Color" ) );
|
|
}
|
|
} _PCB_FIELD_DESC;
|