mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 18:23:15 +02:00
Eeschema: swap label rotations (and include fields)
This means that labels keep the position relative to what they are connected to after the swap. An attempt is made to map the fields of a label into the position of a matching field (i.e. same name) on the swapped-to label. Move the SCH_FIELD rotation justification handling to the SCH_FIELD class, so it's not just SCH_LABEL that handles it. https://gitlab.com/kicad/code/kicad/-/issues/18303
This commit is contained in:
parent
6969b9d64f
commit
bb100994a7
@ -1017,11 +1017,38 @@ bool SCH_FIELD::Replace( const EDA_SEARCH_DATA& aSearchData, void* aAuxData )
|
||||
|
||||
void SCH_FIELD::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
|
||||
{
|
||||
if( GetTextAngle().IsVertical() && GetHorizJustify() == GR_TEXT_H_ALIGN_LEFT )
|
||||
{
|
||||
if( aRotateCCW )
|
||||
SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
|
||||
|
||||
SetTextAngle( ANGLE_HORIZONTAL );
|
||||
}
|
||||
else if( GetTextAngle().IsVertical() && GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
|
||||
{
|
||||
if( aRotateCCW )
|
||||
SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
|
||||
|
||||
SetTextAngle( ANGLE_HORIZONTAL );
|
||||
}
|
||||
else if( GetTextAngle().IsHorizontal() && GetHorizJustify() == GR_TEXT_H_ALIGN_LEFT )
|
||||
{
|
||||
if( !aRotateCCW )
|
||||
SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
|
||||
|
||||
SetTextAngle( ANGLE_VERTICAL );
|
||||
}
|
||||
else if( GetTextAngle().IsHorizontal() && GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
|
||||
{
|
||||
if( !aRotateCCW )
|
||||
SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
|
||||
|
||||
SetTextAngle( ANGLE_VERTICAL );
|
||||
}
|
||||
|
||||
VECTOR2I pt = GetPosition();
|
||||
RotatePoint( pt, aCenter, aRotateCCW ? ANGLE_90 : ANGLE_270 );
|
||||
SetPosition( pt );
|
||||
|
||||
SetTextAngle( GetTextAngle() != ANGLE_HORIZONTAL ? ANGLE_HORIZONTAL : ANGLE_VERTICAL );
|
||||
}
|
||||
|
||||
|
||||
|
@ -203,6 +203,12 @@ SPIN_STYLE SPIN_STYLE::MirrorY()
|
||||
}
|
||||
|
||||
|
||||
unsigned SPIN_STYLE::CCWRotationsTo( const SPIN_STYLE& aOther ) const
|
||||
{
|
||||
return ( ( (int) m_spin - (int) aOther.m_spin ) % 4 + 4 ) % 4;
|
||||
}
|
||||
|
||||
|
||||
SCH_LABEL_BASE::SCH_LABEL_BASE( const VECTOR2I& aPos, const wxString& aText, KICAD_T aType ) :
|
||||
SCH_TEXT( aPos, aText, LAYER_NOTES, aType ),
|
||||
m_shape( L_UNSPECIFIED ),
|
||||
@ -456,42 +462,7 @@ void SCH_LABEL_BASE::Rotate90( bool aClockwise )
|
||||
{
|
||||
for( SCH_FIELD& field : m_fields )
|
||||
{
|
||||
if( field.GetTextAngle().IsVertical()
|
||||
&& field.GetHorizJustify() == GR_TEXT_H_ALIGN_LEFT )
|
||||
{
|
||||
if( !aClockwise )
|
||||
field.SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
|
||||
|
||||
field.SetTextAngle( ANGLE_HORIZONTAL );
|
||||
}
|
||||
else if( field.GetTextAngle().IsVertical()
|
||||
&& field.GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
|
||||
{
|
||||
if( !aClockwise )
|
||||
field.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
|
||||
|
||||
field.SetTextAngle( ANGLE_HORIZONTAL );
|
||||
}
|
||||
else if( field.GetTextAngle().IsHorizontal()
|
||||
&& field.GetHorizJustify() == GR_TEXT_H_ALIGN_LEFT )
|
||||
{
|
||||
if( aClockwise )
|
||||
field.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
|
||||
|
||||
field.SetTextAngle( ANGLE_VERTICAL );
|
||||
}
|
||||
else if( field.GetTextAngle().IsHorizontal()
|
||||
&& field.GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
|
||||
{
|
||||
if( aClockwise )
|
||||
field.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
|
||||
|
||||
field.SetTextAngle( ANGLE_VERTICAL );
|
||||
}
|
||||
|
||||
VECTOR2I pos = field.GetTextPos();
|
||||
RotatePoint( pos, GetPosition(), aClockwise ? -ANGLE_90 : ANGLE_90 );
|
||||
field.SetTextPos( pos );
|
||||
field.Rotate( GetPosition(), !aClockwise );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -81,6 +81,11 @@ public:
|
||||
*/
|
||||
SPIN_STYLE MirrorY();
|
||||
|
||||
/**
|
||||
* Get CCW rotation needed to get to the given spin style.
|
||||
*/
|
||||
unsigned CCWRotationsTo( const SPIN_STYLE& aOther ) const;
|
||||
|
||||
private:
|
||||
SPIN m_spin;
|
||||
};
|
||||
|
@ -1149,6 +1149,90 @@ const std::vector<KICAD_T> swappableItems = {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Swap the positions of the fields in the two lists, aAFields and aBFields,
|
||||
* relative to their parent positions.
|
||||
*
|
||||
* If a field is in both lists, it will be swapped to the position of the
|
||||
* matching field on the counterpart.
|
||||
*
|
||||
* If a field is in only one list, it will simply be rotated by aFallbackRotation
|
||||
* (CW or CCW depending on which list it is in)
|
||||
*/
|
||||
static void swapFieldPositionsWithMatching( std::vector<SCH_FIELD>& aAFields,
|
||||
std::vector<SCH_FIELD>& aBFields,
|
||||
unsigned aFallbackRotationsCCW )
|
||||
{
|
||||
std::set<wxString> handledKeys;
|
||||
|
||||
const auto swapFieldTextProps = []( SCH_FIELD& aField, SCH_FIELD& bField )
|
||||
{
|
||||
const VECTOR2I aRelPos = aField.GetPosition() - aField.GetParentPosition();
|
||||
const GR_TEXT_H_ALIGN_T aTextJustifyH = aField.GetHorizJustify();
|
||||
const GR_TEXT_V_ALIGN_T aTextJustifyV = aField.GetVertJustify();
|
||||
const EDA_ANGLE aTextAngle = aField.GetTextAngle();
|
||||
|
||||
const VECTOR2I bRelPos = bField.GetPosition() - bField.GetParentPosition();
|
||||
const GR_TEXT_H_ALIGN_T bTextJustifyH = bField.GetHorizJustify();
|
||||
const GR_TEXT_V_ALIGN_T bTextJustifyV = bField.GetVertJustify();
|
||||
const EDA_ANGLE bTextAngle = bField.GetTextAngle();
|
||||
|
||||
aField.SetPosition( aField.GetParentPosition() + bRelPos );
|
||||
aField.SetHorizJustify( bTextJustifyH );
|
||||
aField.SetVertJustify( bTextJustifyV );
|
||||
aField.SetTextAngle( bTextAngle );
|
||||
|
||||
bField.SetPosition( bField.GetParentPosition() + aRelPos );
|
||||
bField.SetHorizJustify( aTextJustifyH );
|
||||
bField.SetVertJustify( aTextJustifyV );
|
||||
bField.SetTextAngle( aTextAngle );
|
||||
};
|
||||
|
||||
for( SCH_FIELD& aField : aAFields )
|
||||
{
|
||||
const wxString name = aField.GetCanonicalName();
|
||||
|
||||
auto it = std::find_if( aBFields.begin(), aBFields.end(),
|
||||
[name]( const SCH_FIELD& bField )
|
||||
{
|
||||
return bField.GetCanonicalName() == name;
|
||||
} );
|
||||
|
||||
if( it != aBFields.end() )
|
||||
{
|
||||
// We have a field with the same key in both labels
|
||||
SCH_FIELD& bField = *it;
|
||||
swapFieldTextProps( aField, bField );
|
||||
}
|
||||
else
|
||||
{
|
||||
// We only have this field in A, so just rotate it
|
||||
for( unsigned ii = 0; ii < aFallbackRotationsCCW; ii++ )
|
||||
{
|
||||
aField.Rotate( aField.GetParentPosition(), true );
|
||||
}
|
||||
}
|
||||
|
||||
// And keep track that we did this one
|
||||
handledKeys.insert( name );
|
||||
}
|
||||
|
||||
// Any fields in B that weren't in A weren't handled and need to be rotated
|
||||
// in reverse
|
||||
for( SCH_FIELD& bField : aBFields )
|
||||
{
|
||||
const wxString bName = bField.GetCanonicalName();
|
||||
if( handledKeys.find( bName ) == handledKeys.end() )
|
||||
{
|
||||
for( unsigned ii = 0; ii < aFallbackRotationsCCW; ii++ )
|
||||
{
|
||||
bField.Rotate( bField.GetParentPosition(), false );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int SCH_EDIT_TOOL::Swap( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
EE_SELECTION& selection = m_selectionTool->RequestSelection( swappableItems );
|
||||
@ -1217,9 +1301,26 @@ int SCH_EDIT_TOOL::Swap( const TOOL_EVENT& aEvent )
|
||||
case SCH_GLOBAL_LABEL_T:
|
||||
case SCH_HIER_LABEL_T:
|
||||
case SCH_DIRECTIVE_LABEL_T:
|
||||
m_frame->AutoRotateItem( screen, a );
|
||||
m_frame->AutoRotateItem( screen, b );
|
||||
{
|
||||
SCH_LABEL_BASE& aLabelBase = static_cast<SCH_LABEL_BASE&>( *a );
|
||||
SCH_LABEL_BASE& bLabelBase = static_cast<SCH_LABEL_BASE&>( *b );
|
||||
|
||||
const SPIN_STYLE aSpinStyle = aLabelBase.GetSpinStyle();
|
||||
const SPIN_STYLE bSpinStyle = bLabelBase.GetSpinStyle();
|
||||
|
||||
// First, swap the label orientations
|
||||
aLabelBase.SetSpinStyle( bSpinStyle );
|
||||
bLabelBase.SetSpinStyle( aSpinStyle );
|
||||
|
||||
// And swap the fields as best we can
|
||||
std::vector<SCH_FIELD>& aFields = aLabelBase.GetFields();
|
||||
std::vector<SCH_FIELD>& bFields = bLabelBase.GetFields();
|
||||
|
||||
const unsigned rotationsAtoB = aSpinStyle.CCWRotationsTo( bSpinStyle );
|
||||
|
||||
swapFieldPositionsWithMatching( aFields, bFields, rotationsAtoB );
|
||||
break;
|
||||
}
|
||||
case SCH_SYMBOL_T:
|
||||
{
|
||||
SCH_SYMBOL* aSymbol = static_cast<SCH_SYMBOL*>( a );
|
||||
|
Loading…
x
Reference in New Issue
Block a user