mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-13 17:53:11 +02:00
Compare commits
4 Commits
56ad08cdd8
...
32ee4ebdfa
Author | SHA1 | Date | |
---|---|---|---|
|
32ee4ebdfa | ||
|
2c102a62e0 | ||
|
aa4de22ef4 | ||
|
79a3b7ac5f |
@ -1087,14 +1087,16 @@ void EDA_3D_CANVAS::OnLeftDown( wxMouseEvent& event )
|
||||
|
||||
if( footprint )
|
||||
{
|
||||
std::string command =
|
||||
fmt::format( "$SELECT: 0,F{}",
|
||||
EscapeString( footprint->GetReference(), CTX_IPC ).ToStdString() );
|
||||
|
||||
EDA_3D_VIEWER_FRAME* frame = static_cast<EDA_3D_VIEWER_FRAME*>( GetParent() );
|
||||
// We send a message (by ExpressMail) to the board and schematic editor, but only
|
||||
// if the manager of this canvas is a EDA_3D_VIEWER_FRAME, because only this
|
||||
// kind of frame has ExpressMail stuff
|
||||
EDA_3D_VIEWER_FRAME* frame = dynamic_cast<EDA_3D_VIEWER_FRAME*>( GetParent() );
|
||||
|
||||
if( frame )
|
||||
{
|
||||
std::string command = fmt::format( "$SELECT: 0,F{}",
|
||||
EscapeString( footprint->GetReference(), CTX_IPC ).ToStdString() );
|
||||
|
||||
frame->Kiway().ExpressMail( FRAME_PCB_EDITOR, MAIL_SELECTION, command, frame );
|
||||
frame->Kiway().ExpressMail( FRAME_SCH, MAIL_SELECTION, command, frame );
|
||||
}
|
||||
|
@ -708,6 +708,104 @@ double EDA_UNIT_UTILS::UI::DoubleValueFromString( const EDA_IU_SCALE& aIuScale,
|
||||
}
|
||||
|
||||
|
||||
bool EDA_UNIT_UTILS::UI::DoubleValueFromString( const EDA_IU_SCALE& aIuScale, const wxString& aTextValue,
|
||||
double& aDoubleValue )
|
||||
{
|
||||
double dtmp = 0;
|
||||
|
||||
// Acquire the 'right' decimal point separator
|
||||
const struct lconv* lc = localeconv();
|
||||
|
||||
wxChar decimal_point = lc->decimal_point[0];
|
||||
wxString buf( aTextValue.Strip( wxString::both ) );
|
||||
|
||||
// Convert any entered decimal point separators to the 'right' one
|
||||
buf.Replace( wxT( "." ), wxString( decimal_point, 1 ) );
|
||||
buf.Replace( wxT( "," ), wxString( decimal_point, 1 ) );
|
||||
|
||||
// Find the end of the numeric part
|
||||
unsigned brk_point = 0;
|
||||
|
||||
while( brk_point < buf.Len() )
|
||||
{
|
||||
wxChar ch = buf[brk_point];
|
||||
|
||||
if( !( (ch >= '0' && ch <= '9') || (ch == decimal_point) || (ch == '-') || (ch == '+') ) )
|
||||
break;
|
||||
|
||||
++brk_point;
|
||||
}
|
||||
|
||||
if( brk_point == 0 )
|
||||
return false;
|
||||
|
||||
// Extract the numeric part
|
||||
buf.Left( brk_point ).ToDouble( &dtmp );
|
||||
|
||||
// Check the unit designator
|
||||
wxString unit( buf.Mid( brk_point ).Strip( wxString::both ).Lower() );
|
||||
EDA_UNITS units;
|
||||
|
||||
//check for um, μm (µ is MICRO SIGN) and µm (µ is GREEK SMALL LETTER MU) for micrometre
|
||||
if( unit == wxT( "um" ) || unit == wxT( "\u00B5m" ) || unit == wxT( "\u03BCm" ) )
|
||||
{
|
||||
units = EDA_UNITS::UM;
|
||||
}
|
||||
else if( unit == wxT( "mm" ) )
|
||||
{
|
||||
units = EDA_UNITS::MM;
|
||||
}
|
||||
else if( unit == wxT( "cm" ) )
|
||||
{
|
||||
units = EDA_UNITS::CM;
|
||||
}
|
||||
else if( unit == wxT( "mil" ) || unit == wxT( "mils" ) || unit == wxT( "thou" ) )
|
||||
{
|
||||
units = EDA_UNITS::MILS;
|
||||
}
|
||||
else if( unit == wxT( "in" ) || unit == wxT( "\"" ) )
|
||||
{
|
||||
units = EDA_UNITS::INCH;
|
||||
}
|
||||
else if( unit == wxT( "oz" ) ) // 1 oz = 1.37 mils
|
||||
{
|
||||
units = EDA_UNITS::MILS;
|
||||
dtmp *= 1.37;
|
||||
}
|
||||
else if( unit == wxT( "ra" ) ) // Radians
|
||||
{
|
||||
dtmp *= 180.0f / M_PI;
|
||||
}
|
||||
else if( unit == wxT( "fs" ) )
|
||||
{
|
||||
units = EDA_UNITS::FS;
|
||||
}
|
||||
else if( unit == wxT( "ps" ) )
|
||||
{
|
||||
units = EDA_UNITS::PS;
|
||||
}
|
||||
else if( unit == wxT( "ps/in" ) )
|
||||
{
|
||||
units = EDA_UNITS::PS_PER_INCH;
|
||||
}
|
||||
else if( unit == wxT( "ps/cm" ) )
|
||||
{
|
||||
units = EDA_UNITS::PS_PER_CM;
|
||||
}
|
||||
else if( unit == wxT( "ps/mm" ) )
|
||||
{
|
||||
units = EDA_UNITS::PS_PER_MM;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
aDoubleValue = FromUserUnit( aIuScale, units, dtmp );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
long long int EDA_UNIT_UTILS::UI::ValueFromString( const EDA_IU_SCALE& aIuScale, EDA_UNITS aUnits,
|
||||
const wxString& aTextValue, EDA_DATA_TYPE aType )
|
||||
{
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define KICAD_GIT_ERRORS_H
|
||||
|
||||
#include <vector>
|
||||
#include <import_export.h>
|
||||
|
||||
#include <wx/translation.h>
|
||||
|
||||
|
@ -1697,16 +1697,35 @@ int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags, REPORTER* aR
|
||||
if( !aReporter )
|
||||
return retv;
|
||||
}
|
||||
else if( int tmp = aField->SCH_ITEM::compare( *bField, aCompareFlags ) )
|
||||
else
|
||||
{
|
||||
retv = tmp;
|
||||
REPORT( wxString::Format( _( "Field '%s' differs: %s; %s." ),
|
||||
aField->GetName( false ),
|
||||
ITEM_DESC( aField ),
|
||||
ITEM_DESC( bField ) ) );
|
||||
int tmp = 0;
|
||||
|
||||
if( !aReporter )
|
||||
return retv;
|
||||
// For EQUALITY comparison, we need to compare field content directly
|
||||
// since SCH_ITEM::compare() returns 0 for EQUALITY flag
|
||||
if( aCompareFlags & SCH_ITEM::COMPARE_FLAGS::EQUALITY )
|
||||
{
|
||||
// Compare field text content
|
||||
tmp = aField->GetText().CmpNoCase( bField->GetText() );
|
||||
}
|
||||
|
||||
if( tmp == 0 )
|
||||
{
|
||||
// Fall back to base class comparison for other properties
|
||||
tmp = aField->SCH_ITEM::compare( *bField, aCompareFlags );
|
||||
}
|
||||
|
||||
if( tmp != 0 )
|
||||
{
|
||||
retv = tmp;
|
||||
REPORT( wxString::Format( _( "Field '%s' differs: %s; %s." ),
|
||||
aField->GetName( false ),
|
||||
ITEM_DESC( aField ),
|
||||
ITEM_DESC( bField ) ) );
|
||||
|
||||
if( !aReporter )
|
||||
return retv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -750,7 +750,9 @@ std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> PIN_LAYOUT_CACHE::GetPinNameInfo( int
|
||||
info->m_Thickness = m_nameThickness;
|
||||
info->m_Angle = ANGLE_HORIZONTAL;
|
||||
|
||||
if( m_pin.GetParentSymbol()->GetPinNameOffset() > 0 )
|
||||
bool nameInside = m_pin.GetParentSymbol()->GetPinNameOffset() > 0;
|
||||
|
||||
if( nameInside )
|
||||
{
|
||||
// This means name inside the pin
|
||||
VECTOR2I pos = { m_pin.GetLength() + m_pin.GetParentSymbol()->GetPinNameOffset(), 0 };
|
||||
@ -760,6 +762,7 @@ std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> PIN_LAYOUT_CACHE::GetPinNameInfo( int
|
||||
info->m_TextPosition = pos + VECTOR2I{ thickOffset, 0 };
|
||||
info->m_HAlign = GR_TEXT_H_ALIGN_LEFT;
|
||||
info->m_VAlign = GR_TEXT_V_ALIGN_CENTER;
|
||||
transformTextForPin( *info );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -769,42 +772,44 @@ std::optional<PIN_LAYOUT_CACHE::TEXT_INFO> PIN_LAYOUT_CACHE::GetPinNameInfo( int
|
||||
info->m_TextPosition = pos;
|
||||
info->m_HAlign = GR_TEXT_H_ALIGN_CENTER;
|
||||
info->m_VAlign = GR_TEXT_V_ALIGN_BOTTOM;
|
||||
}
|
||||
|
||||
// New policy: names follow same positioning semantics as numbers.
|
||||
const SYMBOL* parentSym = m_pin.GetParentSymbol();
|
||||
if( parentSym )
|
||||
{
|
||||
int maxHalfHeight = 0;
|
||||
for( const SCH_PIN* p : parentSym->GetPins() )
|
||||
// New policy: names follow same positioning semantics as numbers except when
|
||||
// specified as inside. When names are inside, they should not overlap with the
|
||||
// number position.
|
||||
const SYMBOL* parentSym = m_pin.GetParentSymbol();
|
||||
if( parentSym )
|
||||
{
|
||||
wxString n = p->GetShownName();
|
||||
if( n.IsEmpty() )
|
||||
continue;
|
||||
maxHalfHeight = std::max( maxHalfHeight, p->GetNameTextSize() / 2 );
|
||||
}
|
||||
int clearance = getPinTextOffset() + schIUScale.MilsToIU( PIN_TEXT_MARGIN );
|
||||
VECTOR2I pinPos = m_pin.GetPosition();
|
||||
PIN_ORIENTATION orient = m_pin.PinDrawOrient( DefaultTransform );
|
||||
bool verticalOrient = ( orient == PIN_ORIENTATION::PIN_UP || orient == PIN_ORIENTATION::PIN_DOWN );
|
||||
int maxHalfHeight = 0;
|
||||
for( const SCH_PIN* p : parentSym->GetPins() )
|
||||
{
|
||||
wxString n = p->GetShownName();
|
||||
if( n.IsEmpty() )
|
||||
continue;
|
||||
maxHalfHeight = std::max( maxHalfHeight, p->GetNameTextSize() / 2 );
|
||||
}
|
||||
int clearance = getPinTextOffset() + schIUScale.MilsToIU( PIN_TEXT_MARGIN );
|
||||
VECTOR2I pinPos = m_pin.GetPosition();
|
||||
PIN_ORIENTATION orient = m_pin.PinDrawOrient( DefaultTransform );
|
||||
bool verticalOrient = ( orient == PIN_ORIENTATION::PIN_UP || orient == PIN_ORIENTATION::PIN_DOWN );
|
||||
|
||||
if( verticalOrient )
|
||||
{
|
||||
// Vertical pins: name mirrors number placement (left + rotated) for visual consistency.
|
||||
int boxWidth = info->m_TextSize * (int) info->m_Text.Length() * 0.6; // heuristic width
|
||||
int centerX = pinPos.x - clearance - boxWidth / 2;
|
||||
info->m_TextPosition = { centerX, pinPos.y };
|
||||
info->m_Angle = ANGLE_VERTICAL;
|
||||
info->m_HAlign = GR_TEXT_H_ALIGN_CENTER;
|
||||
info->m_VAlign = GR_TEXT_V_ALIGN_CENTER;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Horizontal pins: name above (negative Y) aligned to same Y offset logic as numbers.
|
||||
info->m_TextPosition = { pinPos.x, pinPos.y - ( maxHalfHeight + clearance ) };
|
||||
info->m_Angle = ANGLE_HORIZONTAL;
|
||||
info->m_HAlign = GR_TEXT_H_ALIGN_CENTER;
|
||||
info->m_VAlign = GR_TEXT_V_ALIGN_CENTER;
|
||||
if( verticalOrient )
|
||||
{
|
||||
// Vertical pins: name mirrors number placement (left + rotated) for visual consistency.
|
||||
int boxWidth = info->m_TextSize * (int) info->m_Text.Length() * 0.6; // heuristic width
|
||||
int centerX = pinPos.x - clearance - boxWidth / 2;
|
||||
info->m_TextPosition = { centerX, pinPos.y };
|
||||
info->m_Angle = ANGLE_VERTICAL;
|
||||
info->m_HAlign = GR_TEXT_H_ALIGN_CENTER;
|
||||
info->m_VAlign = GR_TEXT_V_ALIGN_CENTER;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Horizontal pins: name above (negative Y) aligned to same Y offset logic as numbers.
|
||||
info->m_TextPosition = { pinPos.x, pinPos.y - ( maxHalfHeight + clearance ) };
|
||||
info->m_Angle = ANGLE_HORIZONTAL;
|
||||
info->m_HAlign = GR_TEXT_H_ALIGN_CENTER;
|
||||
info->m_VAlign = GR_TEXT_V_ALIGN_CENTER;
|
||||
}
|
||||
}
|
||||
}
|
||||
return info;
|
||||
|
@ -256,6 +256,9 @@ namespace EDA_UNIT_UTILS
|
||||
|
||||
KICOMMON_API double DoubleValueFromString( const wxString& aTextValue );
|
||||
|
||||
KICOMMON_API bool DoubleValueFromString( const EDA_IU_SCALE& aIuScale, const wxString& aTextValue,
|
||||
double& aDoubleValue );
|
||||
|
||||
/**
|
||||
* Convert \a aTextValue in \a aUnits to internal units used by the application.
|
||||
*
|
||||
|
@ -447,28 +447,33 @@ LIBEVAL::VALUE* PCBEXPR_VAR_REF::GetValue( LIBEVAL::CONTEXT* aCtx )
|
||||
|
||||
if( it->second->Name() == wxT( "Pin Type" ) )
|
||||
return new PCBEXPR_PINTYPE_VALUE( str );
|
||||
else
|
||||
return new LIBEVAL::VALUE( str );
|
||||
|
||||
// If it quacks like a duck, it is a duck
|
||||
double doubleVal;
|
||||
|
||||
if( EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, str, doubleVal ) )
|
||||
return new LIBEVAL::VALUE( doubleVal );
|
||||
|
||||
return new LIBEVAL::VALUE( str );
|
||||
}
|
||||
else
|
||||
else if( it->second->Name() == wxT( "Layer" )
|
||||
|| it->second->Name() == wxT( "Layer Top" )
|
||||
|| it->second->Name() == wxT( "Layer Bottom" ) )
|
||||
{
|
||||
const wxAny& any = item->Get( it->second );
|
||||
PCB_LAYER_ID layer;
|
||||
|
||||
if( it->second->Name() == wxT( "Layer" )
|
||||
|| it->second->Name() == wxT( "Layer Top" )
|
||||
|| it->second->Name() == wxT( "Layer Bottom" ) )
|
||||
{
|
||||
if( any.GetAs<PCB_LAYER_ID>( &layer ) )
|
||||
return new PCBEXPR_LAYER_VALUE( layer );
|
||||
else if( any.GetAs<wxString>( &str ) )
|
||||
return new PCBEXPR_LAYER_VALUE( context->GetBoard()->GetLayerID( str ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( any.GetAs<wxString>( &str ) )
|
||||
return new LIBEVAL::VALUE( str );
|
||||
}
|
||||
if( any.GetAs<PCB_LAYER_ID>( &layer ) )
|
||||
return new PCBEXPR_LAYER_VALUE( layer );
|
||||
else if( any.GetAs<wxString>( &str ) )
|
||||
return new PCBEXPR_LAYER_VALUE( context->GetBoard()->GetLayerID( str ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
const wxAny& any = item->Get( it->second );
|
||||
|
||||
if( any.GetAs<wxString>( &str ) )
|
||||
return new LIBEVAL::VALUE( str );
|
||||
}
|
||||
|
||||
return new LIBEVAL::VALUE();
|
||||
|
@ -46,6 +46,9 @@ static std::unique_ptr<LIB_SYMBOL> createTestResistorSymbol()
|
||||
{
|
||||
auto symbol = std::make_unique<LIB_SYMBOL>( wxT( "TestResistor" ) );
|
||||
|
||||
// Set pin name offset to 0 so names are positioned outside (like numbers)
|
||||
symbol->SetPinNameOffset( 0 );
|
||||
|
||||
// Create first pin with stacked numbers [1-5]
|
||||
auto pin1 = std::make_unique<SCH_PIN>( symbol.get() );
|
||||
pin1->SetPosition( VECTOR2I( 0, schIUScale.MilsToIU( 250 ) ) ); // top pin
|
||||
|
Loading…
x
Reference in New Issue
Block a user