Implement new dimension properties

- Automatic units mode (follow UI units)
- New text and number formatting options
- Automatic/manual text orientation control
- New text positioning options (inline and manual)

Fixes https://gitlab.com/kicad/code/kicad/-/issues/4280
Fixes https://gitlab.com/kicad/code/kicad/-/issues/4497
This commit is contained in:
Jon Evans 2020-09-11 19:52:45 -04:00
parent f1b7903a7d
commit 76c4c959e6
17 changed files with 581 additions and 183 deletions

View File

@ -337,6 +337,45 @@ bool EDA_RECT::Intersects( const wxPoint& aPoint1, const wxPoint& aPoint2 ) cons
}
bool EDA_RECT::Intersects( const wxPoint& aPoint1, const wxPoint& aPoint2,
wxPoint* aIntersection1, wxPoint* aIntersection2 ) const
{
wxPoint point2, point4;
point2.x = GetEnd().x;
point2.y = GetOrigin().y;
point4.x = GetOrigin().x;
point4.y = GetEnd().y;
bool intersects = false;
wxPoint* aPointToFill = aIntersection1;
if( SegmentIntersectsSegment( aPoint1, aPoint2, GetOrigin(), point2, aPointToFill ) )
intersects = true;
if( intersects )
aPointToFill = aIntersection2;
if( SegmentIntersectsSegment( aPoint1, aPoint2, point2, GetEnd(), aPointToFill ) )
intersects = true;
if( intersects )
aPointToFill = aIntersection2;
if( SegmentIntersectsSegment( aPoint1, aPoint2, GetEnd(), point4, aPointToFill ) )
intersects = true;
if( intersects )
aPointToFill = aIntersection2;
if( SegmentIntersectsSegment( aPoint1, aPoint2, point4, GetOrigin(), aPointToFill ) )
intersects = true;
return intersects;
}
bool EDA_RECT::Intersects( const EDA_RECT& aRect ) const
{
if( !m_init )

View File

@ -146,6 +146,7 @@ italic
justify
keepout
keep_end_layers
keep_text_aligned
keep_upright
kicad_pcb
last_trace_width

View File

@ -243,6 +243,17 @@ public:
*/
bool Intersects( const wxPoint& aPoint1, const wxPoint& aPoint2 ) const;
/**
* Tests for intersection between a segment and this rectangle, returning the intersections
* @param aPoint1 is the first point of the segment to test intersection with
* @param aPoint2 is the second point of the segment to test intersection with
* @param aIntersection1 will be filled with the first intersection point, if any
* @param aIntersection2 will be filled with the second intersection point, if any
* @return true if the segment intersects the rect
*/
bool Intersects( const wxPoint& aPoint1, const wxPoint& aPoint2,
wxPoint* aIntersection1, wxPoint* aIntersection2 ) const;
/**
* Return the point in this rect that is closest to the provided point
*/

View File

@ -36,9 +36,9 @@
#include <settings/settings_manager.h>
DIMENSION::DIMENSION( BOARD_ITEM* aParent )
: BOARD_ITEM( aParent, PCB_DIMENSION_T ),
m_overrideValue( false ),
DIMENSION::DIMENSION( BOARD_ITEM* aParent ) :
BOARD_ITEM( aParent, PCB_DIMENSION_T ),
m_overrideTextEnabled( false ),
m_units( EDA_UNITS::INCHES ),
m_useMils( false ),
m_autoUnits( false ),
@ -69,6 +69,81 @@ wxPoint DIMENSION::GetPosition() const
}
void DIMENSION::updateText()
{
wxString text = m_overrideTextEnabled ? m_valueString : GetValueText();
switch( m_unitsFormat )
{
case DIM_UNITS_FORMAT::NO_SUFFIX: // no units
break;
case DIM_UNITS_FORMAT::BARE_SUFFIX: // normal
text += " ";
text += GetAbbreviatedUnitsLabel( m_units, m_useMils );
break;
case DIM_UNITS_FORMAT::PAREN_SUFFIX: // parenthetical
text += " (";
text += GetAbbreviatedUnitsLabel( m_units, m_useMils );
text += ")";
break;
}
text.Prepend( m_prefix );
text.Append( m_suffix );
m_text.SetText( text );
}
wxString DIMENSION::GetValueText() const
{
int val = GetMeasuredValue();
wxString text;
wxString format = wxT( "%." ) + wxString::Format( "%i", m_precision ) + wxT( "f" );
text.Printf( format, To_User_Unit( m_units, val, m_useMils ) );
if( m_suppressZeroes )
{
while( text.Last() == '0' )
{
text.RemoveLast();
if( text.Last() == '.' )
{
text.RemoveLast();
break;
}
}
}
return text;
}
void DIMENSION::SetPrefix( const wxString& aPrefix )
{
m_prefix = aPrefix;
}
void DIMENSION::SetSuffix( const wxString& aSuffix )
{
m_suffix = aSuffix;
}
void DIMENSION::SetUnits( EDA_UNITS aUnits, bool aUseMils )
{
m_units = aUnits;
m_useMils = aUseMils;
}
DIM_UNITS_MODE DIMENSION::GetUnitsMode() const
{
if( m_autoUnits )
@ -84,16 +159,17 @@ DIM_UNITS_MODE DIMENSION::GetUnitsMode() const
void DIMENSION::SetUnitsMode( DIM_UNITS_MODE aMode )
{
m_units = EDA_UNITS::INCHES;
m_autoUnits = false;
m_useMils = false;
switch( aMode )
{
case DIM_UNITS_MODE::INCHES:
m_units = EDA_UNITS::INCHES;
break;
case DIM_UNITS_MODE::MILS:
m_units = EDA_UNITS::INCHES;
m_useMils = true;
break;
@ -110,7 +186,8 @@ void DIMENSION::SetUnitsMode( DIM_UNITS_MODE aMode )
void DIMENSION::SetText( const wxString& aNewText )
{
m_text.SetText( aNewText );
m_valueString = aNewText;
updateText();
}
@ -134,7 +211,7 @@ void DIMENSION::Move( const wxPoint& offset )
m_start += offset;
m_end += offset;
updateGeometry();
Update();
}
@ -157,7 +234,7 @@ void DIMENSION::Rotate( const wxPoint& aRotCentre, double aAngle )
RotatePoint( &m_start, aRotCentre, aAngle );
RotatePoint( &m_end, aRotCentre, aAngle );
updateGeometry();
Update();
}
@ -199,21 +276,21 @@ void DIMENSION::Mirror( const wxPoint& axis_pos, bool aMirrorLeftRight )
INVERT( m_end.y );
}
updateGeometry();
Update();
}
void DIMENSION::SetStart( const wxPoint& aOrigin )
{
m_start = aOrigin;
updateGeometry();
Update();
}
void DIMENSION::SetEnd( const wxPoint& aEnd )
{
m_end = aEnd;
updateGeometry();
Update();
}
@ -333,7 +410,7 @@ ALIGNED_DIMENSION::ALIGNED_DIMENSION( BOARD_ITEM* aParent ) :
m_height( 0 )
{
// To preserve look of old dimensions, initialize extension height based on default arrow length
m_extensionHeight = m_arrowLength * std::sin( DEG2RAD( s_arrowAngle ) );
m_extensionHeight = static_cast<int>( m_arrowLength * std::sin( DEG2RAD( s_arrowAngle ) ) );
}
@ -347,14 +424,15 @@ void ALIGNED_DIMENSION::SwapData( BOARD_ITEM* aImage )
{
assert( aImage->Type() == PCB_DIMENSION_T );
std::swap( *static_cast<ALIGNED_DIMENSION*>( this ), *static_cast<ALIGNED_DIMENSION*>( aImage ) );
std::swap( *static_cast<ALIGNED_DIMENSION*>( this ),
*static_cast<ALIGNED_DIMENSION*>( aImage ) );
}
void ALIGNED_DIMENSION::SetHeight( int aHeight )
{
m_height = aHeight;
updateGeometry();
Update();
}
@ -368,7 +446,7 @@ void ALIGNED_DIMENSION::UpdateHeight( const wxPoint& aCrossbarStart, const wxPoi
else
m_height = height.EuclideanNorm();
updateGeometry();
Update();
}
@ -410,13 +488,71 @@ void ALIGNED_DIMENSION::updateGeometry()
// Update text after calculating crossbar position but before adding crossbar lines
updateText();
// Now that we have the text updated, we can determine if the crossbar needs to be broken
if( m_textPosition == DIM_TEXT_POSITION::INLINE )
{
// Now that we have the text updated, we can determine how to draw the crossbar.
// First we need to create an appropriate bounding polygon to collide with
EDA_RECT textBox = m_text.GetTextBox().Inflate( m_text.GetTextWidth() / 2,
m_text.GetEffectiveTextPenWidth() );
SHAPE_POLY_SET polyBox;
polyBox.NewOutline();
polyBox.Append( textBox.GetOrigin() );
polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
polyBox.Append( textBox.GetEnd() );
polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
polyBox.Rotate( -m_text.GetTextAngleRadians(), textBox.GetCenter() );
// The ideal crossbar, if the text doesn't collide
SEG crossbar( m_crossBarStart, m_crossBarEnd );
auto findEndpoint =
[&]( const VECTOR2I& aStart, const VECTOR2I& aEnd ) -> VECTOR2I
{
VECTOR2I endpoint( aEnd );
for( SHAPE_POLY_SET::SEGMENT_ITERATOR seg = polyBox.IterateSegments(); seg; seg++ )
{
if( OPT_VECTOR2I intersection = ( *seg ).Intersect( crossbar ) )
{
if( ( *intersection - aStart ).SquaredEuclideanNorm() <
( endpoint - aStart ).SquaredEuclideanNorm() )
endpoint = *intersection;
}
}
m_lines.emplace_back( SEG( m_crossBarStart, m_crossBarEnd ) );
return endpoint;
};
// Now we can draw 0, 1, or 2 crossbar lines depending on how the polygon collides
bool containsA = polyBox.Contains( crossbar.A );
bool containsB = polyBox.Contains( crossbar.B );
if( containsA && !containsB )
{
m_lines.emplace_back( SEG( findEndpoint( crossbar.B, crossbar.A ), crossbar.B ) );
}
else if( containsB && !containsA )
{
m_lines.emplace_back( SEG( crossbar.A, findEndpoint( crossbar.A, crossbar.B ) ) );
}
else if( polyBox.Collide( crossbar ) )
{
// text box collides and we need two segs
VECTOR2I endpoint1 = findEndpoint( crossbar.B, crossbar.A );
VECTOR2I endpoint2 = findEndpoint( crossbar.A, crossbar.B );
if( ( crossbar.B - endpoint1 ).SquaredEuclideanNorm() >
( crossbar.B - endpoint2 ).SquaredEuclideanNorm() )
std::swap( endpoint1, endpoint2 );
m_lines.emplace_back( SEG( endpoint1, crossbar.B ) );
m_lines.emplace_back( SEG( crossbar.A, endpoint2 ) );
}
else if( !containsA && !containsB )
{
// No collision
m_lines.emplace_back( crossbar );
}
// Add arrows
VECTOR2I arrowEnd( m_arrowLength, 0 );
@ -442,7 +578,7 @@ void ALIGNED_DIMENSION::updateText()
{
VECTOR2I crossbarCenter( ( m_crossBarEnd - m_crossBarStart ) / 2 );
if( m_textPosition != DIM_TEXT_POSITION::MANUAL )
if( m_textPosition == DIM_TEXT_POSITION::OUTSIDE )
{
int textOffsetDistance = m_text.GetEffectiveTextPenWidth() + m_text.GetTextHeight();
@ -452,6 +588,10 @@ void ALIGNED_DIMENSION::updateText()
m_text.SetTextPos( m_crossBarStart + wxPoint( textOffset ) );
}
else if( m_textPosition == DIM_TEXT_POSITION::INLINE )
{
m_text.SetTextPos( m_crossBarStart + wxPoint( crossbarCenter ) );
}
if( m_keepTextAligned )
{
@ -464,17 +604,6 @@ void ALIGNED_DIMENSION::updateText()
m_text.SetTextAngle( textAngle );
}
else
{
m_text.SetTextAngle( 0 );
}
wxString text;
wxString format = wxT( "%." ) + wxString::Format( "%i", m_precision ) + wxT( "f" );
text.Printf( format, To_User_Unit( m_units, m_measuredValue, m_useMils ) );
text += " ";
text += GetAbbreviatedUnitsLabel( m_units, m_useMils );
SetText( text );
DIMENSION::updateText();
}

View File

@ -106,21 +106,33 @@ public:
wxPoint GetPosition() const override;
void SetPosition( const wxPoint& aPos ) override;
bool GetOverrideValue() const { return m_overrideValue; }
void SetOverrideValue( bool aOverride ) { m_overrideValue = aOverride; }
bool GetOverrideTextEnabled() const { return m_overrideTextEnabled; }
void SetOverrideTextEnabled( bool aOverride ) { m_overrideTextEnabled = aOverride; }
wxString GetOverrideText() const { return m_valueString; }
void SetOverrideText( const wxString& aValue ) { m_valueString = aValue; }
int GetMeasuredValue() const { return m_measuredValue; }
/**
* @return the text that should be shown, including any prefix and suffix
* @return the dimension value, rendered with precision / zero suppression but no units, etc
*/
wxString GetDisplayedText() const;
wxString GetValueText() const;
/**
* Updates the dimension's cached text and geometry
*/
void Update()
{
updateGeometry();
updateText();
}
wxString GetPrefix() const { return m_prefix; }
void SetPrefix( const wxString& aPrefix ) { m_prefix = aPrefix; }
void SetPrefix( const wxString& aPrefix );
wxString GetSuffix() const { return m_suffix; }
void SetSuffix( const wxString& aSuffix ) { m_suffix = aSuffix; }
void SetSuffix( const wxString& aSuffix );
void GetUnits( EDA_UNITS& aUnits, bool& aUseMils ) const
{
@ -128,11 +140,7 @@ public:
aUseMils = m_useMils;
}
void SetUnits( EDA_UNITS aUnits, bool aUseMils )
{
m_units = aUnits;
m_useMils = aUseMils;
}
void SetUnits( EDA_UNITS aUnits, bool aUseMils );
DIM_UNITS_MODE GetUnitsMode() const;
void SetUnitsMode( DIM_UNITS_MODE aMode );
@ -170,7 +178,16 @@ public:
m_text.SetTextSize( aTextSize );
}
/**
* Sets the override text - has no effect if m_overrideValue == false
* @param aNewText is the text to use as the value
*/
void SetText( const wxString& aNewText );
/**
* Retrieves the value text or override text, not including prefix or suffix
* @return the value portion of the dimension text (either overridden or not)
*/
const wxString GetText() const;
TEXTE_PCB& Text() { return m_text; }
@ -222,11 +239,11 @@ protected:
/**
* Updates the text field value from the current geometry (called by updateGeometry normally)
*/
virtual void updateText() {}
virtual void updateText();
// Value format
bool m_overrideValue; ///< Manually specify the displayed measurement value
wxString m_overrideText; ///< The shown value if m_overrideValue is true
bool m_overrideTextEnabled; ///< Manually specify the displayed measurement value
wxString m_valueString; ///< Displayed value when m_overrideValue = true
wxString m_prefix; ///< String prepended to the value
wxString m_suffix; ///< String appended to the value
EDA_UNITS m_units; ///< 0 = inches, 1 = mm

View File

@ -163,6 +163,13 @@ const KICAD_T GENERAL_COLLECTOR::Zones[] = {
};
const KICAD_T GENERAL_COLLECTOR::Dimensions[] = {
PCB_DIMENSION_T,
EOT
};
SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData )
{

View File

@ -317,6 +317,11 @@ public:
*/
static const KICAD_T LockableItems[];
/**
* A scan list for dimensions
*/
static const KICAD_T Dimensions[];
/**
* Constructor GENERALCOLLECTOR
*/

View File

@ -45,6 +45,7 @@ DIALOG_DIMENSION_PROPERTIES::DIALOG_DIMENSION_PROPERTIES( PCB_BASE_EDIT_FRAME* a
{
wxASSERT( aItem->Type() == PCB_DIMENSION_T );
m_dimension = static_cast<DIMENSION*>( aItem );
m_previewDimension = static_cast<DIMENSION*>( m_dimension->Clone() );
// Configure display origin transforms
m_textPosX.SetCoordType( ORIGIN_TRANSFORMS::ABS_X_COORD );
@ -81,14 +82,14 @@ DIALOG_DIMENSION_PROPERTIES::DIALOG_DIMENSION_PROPERTIES( PCB_BASE_EDIT_FRAME* a
m_txtValue->Enable( m_cbOverrideValue->GetValue() );
if( !m_cbOverrideValue->GetValue() )
m_txtValue->SetValue( getValueText() );
m_txtValue->SetValue( m_dimension->GetValueText() );
} );
auto updateEventHandler =
[&]( wxCommandEvent& evt )
{
if( !m_cbOverrideValue->GetValue() )
m_txtValue->ChangeValue( getValueText() );
m_txtValue->ChangeValue( m_dimension->GetValueText() );
updatePreviewText();
};
@ -102,19 +103,36 @@ DIALOG_DIMENSION_PROPERTIES::DIALOG_DIMENSION_PROPERTIES( PCB_BASE_EDIT_FRAME* a
m_cbPrecision->Bind( wxEVT_CHOICE, updateEventHandler );
m_cbSuppressZeroes->Bind( wxEVT_CHECKBOX, updateEventHandler );
m_cbTextPositionMode->Bind( wxEVT_CHOICE,
[&]( wxCommandEvent& aEvt )
{
// manual mode
bool allowPositioning = ( m_cbTextPositionMode->GetSelection() == 2 );
m_txtTextPosX->Enable( allowPositioning );
m_txtTextPosY->Enable( allowPositioning );
} );
m_cbKeepAligned->Bind( wxEVT_CHECKBOX,
[&]( wxCommandEvent& aEvt )
{
m_cbTextOrientation->Enable( !m_cbKeepAligned->GetValue() );
} );
FinishDialogSettings();
}
DIALOG_DIMENSION_PROPERTIES::~DIALOG_DIMENSION_PROPERTIES()
{
delete m_previewDimension;
}
bool DIALOG_DIMENSION_PROPERTIES::TransferDataToWindow()
{
m_txtValue->Enable( m_dimension->GetOverrideValue() );
m_cbOverrideValue->SetValue( m_dimension->GetOverrideValue() );
m_txtValue->Enable( m_dimension->GetOverrideTextEnabled() );
m_cbOverrideValue->SetValue( m_dimension->GetOverrideTextEnabled() );
EDA_UNITS units;
bool useMils;
@ -141,10 +159,20 @@ bool DIALOG_DIMENSION_PROPERTIES::TransferDataToWindow()
m_textWidth.SetValue( text.GetTextSize().x );
m_textHeight.SetValue( text.GetTextSize().y );
m_textThickness.SetValue( text.GetTextThickness() );
m_textPosX.SetValue( text.GetTextPos().x );
m_textPosY.SetValue( text.GetTextPos().y );
m_cbTextPositionMode->SetSelection( static_cast<int>( m_dimension->GetTextPositionMode() ) );
if( m_dimension->GetTextPositionMode() != DIM_TEXT_POSITION::MANUAL )
{
m_txtTextPosX->Disable();
m_txtTextPosY->Disable();
}
m_orientValue = text.GetTextAngleDegrees();
m_cbKeepAligned->SetValue( m_dimension->GetKeepTextAligned() );
m_cbTextOrientation->Enable( !m_dimension->GetKeepTextAligned() );
m_cbItalic->SetValue( text.IsItalic() );
m_cbMirrored->SetValue( text.IsMirrored() );
@ -155,7 +183,12 @@ bool DIALOG_DIMENSION_PROPERTIES::TransferDataToWindow()
m_arrowLength.SetValue( m_dimension->GetArrowLength() );
// Do this last; it depends on the other settings
m_txtValue->SetValue( getValueText() );
if( m_dimension->GetOverrideTextEnabled() )
m_txtValue->SetValue( m_dimension->GetOverrideText() );
else
m_txtValue->SetValue( m_dimension->GetValueText() );
m_orientValidator.TransferToWindow();
return DIALOG_DIMENSION_PROPERTIES_BASE::TransferDataToWindow();
}
@ -163,25 +196,64 @@ bool DIALOG_DIMENSION_PROPERTIES::TransferDataToWindow()
bool DIALOG_DIMENSION_PROPERTIES::TransferDataFromWindow()
{
m_dimension->SetOverrideValue( m_cbOverrideValue->GetValue() );
if( !DIALOG_DIMENSION_PROPERTIES_BASE::TransferDataFromWindow() )
return false;
BOARD_COMMIT commit( m_frame );
commit.Modify( m_dimension );
// If no other command in progress, prepare undo command
// (for a command in progress, will be made later, at the completion of command)
bool pushCommit = ( m_dimension->GetEditFlags() == 0 );
/* set flag in edit to force undo/redo/abort proper operation,
* and avoid new calls to SaveCopyInUndoList for the same dimension
* this can occurs when a dimension is moved, and then rotated, edited ..
*/
if( !pushCommit )
m_dimension->SetFlags( IN_EDIT );
updateDimensionFromDialog( m_dimension );
if( pushCommit )
commit.Push( _( "Change dimension properties" ) );
return true;
}
void DIALOG_DIMENSION_PROPERTIES::updateDimensionFromDialog( DIMENSION* aTarget )
{
m_orientValidator.TransferFromWindow();
aTarget->SetOverrideTextEnabled( m_cbOverrideValue->GetValue() );
if( m_cbOverrideValue->GetValue() )
m_dimension->SetText( m_txtValue->GetValue() );
aTarget->SetOverrideText( m_txtValue->GetValue() );
m_dimension->SetPrefix( m_txtPrefix->GetValue() );
m_dimension->SetSuffix( m_txtSuffix->GetValue() );
m_dimension->SetLayer( static_cast<PCB_LAYER_ID>( m_cbLayer->GetLayerSelection() ) );
aTarget->SetPrefix( m_txtPrefix->GetValue() );
aTarget->SetSuffix( m_txtSuffix->GetValue() );
aTarget->SetLayer( static_cast<PCB_LAYER_ID>( m_cbLayer->GetLayerSelection() ) );
m_dimension->SetUnitsMode( static_cast<DIM_UNITS_MODE>( m_cbUnits->GetSelection() ) );
m_dimension->SetUnitsFormat( static_cast<DIM_UNITS_FORMAT>( m_cbUnitsFormat->GetSelection() ) );
m_dimension->SetPrecision( m_cbPrecision->GetSelection() );
m_dimension->SetSuppressZeroes( m_cbSuppressZeroes->GetValue() );
aTarget->SetUnits( m_frame->GetUserUnits(), false );
aTarget->SetUnitsMode( static_cast<DIM_UNITS_MODE>( m_cbUnits->GetSelection() ) );
aTarget->SetUnitsFormat( static_cast<DIM_UNITS_FORMAT>( m_cbUnitsFormat->GetSelection() ) );
aTarget->SetPrecision( m_cbPrecision->GetSelection() );
aTarget->SetSuppressZeroes( m_cbSuppressZeroes->GetValue() );
TEXTE_PCB& text = m_dimension->Text();
TEXTE_PCB& text = aTarget->Text();
// TODO(JE) text positioning modes
DIM_TEXT_POSITION tpm = static_cast<DIM_TEXT_POSITION>( m_cbTextPositionMode->GetSelection() );
aTarget->SetTextPositionMode( tpm );
if( tpm == DIM_TEXT_POSITION::MANUAL )
{
wxPoint pos( m_textPosX.GetValue(), m_textPosY.GetValue() );
text.SetPosition( pos );
}
aTarget->SetKeepTextAligned( m_cbKeepAligned->GetValue() );
text.SetTextAngle( KiROUND( m_orientValue * 10.0 ) );
text.SetTextWidth( m_textWidth.GetValue() );
text.SetTextHeight( m_textHeight.GetValue() );
@ -190,95 +262,16 @@ bool DIALOG_DIMENSION_PROPERTIES::TransferDataFromWindow()
text.SetMirrored( m_cbMirrored->GetValue() );
int justification = m_cbJustification->GetSelection() - 1;
text.SetHorizJustify( static_cast<EDA_TEXT_HJUSTIFY_T>( justification ) );
m_dimension->SetKeepTextAligned( m_cbKeepAligned->GetValue() );
m_dimension->SetLineThickness( m_lineThickness.GetValue() );
m_dimension->SetArrowLength( m_arrowLength.GetValue() );
aTarget->SetLineThickness( m_lineThickness.GetValue() );
aTarget->SetArrowLength( m_arrowLength.GetValue() );
return true;
}
void DIALOG_DIMENSION_PROPERTIES::getUnitsSelection( EDA_UNITS& aUnits, bool& aUseMils )
{
aUseMils = false;
switch( m_cbUnits->GetSelection() )
{
case 0: // inches
aUnits = EDA_UNITS::INCHES;
break;
case 1: // mils
aUnits = EDA_UNITS::INCHES;
aUseMils = true;
break;
case 2: // mm
aUnits = EDA_UNITS::MILLIMETRES;
break;
case 3: // auto
aUnits = m_frame->GetUserUnits();
break;
default:
break;
}
}
wxString DIALOG_DIMENSION_PROPERTIES::getValueText()
{
int val = m_dimension->GetMeasuredValue();
int precision = m_cbPrecision->GetSelection();
EDA_UNITS units;
bool useMils;
getUnitsSelection( units, useMils );
wxString text;
wxString format = wxT( "%." ) + wxString::Format( "%i", precision ) + wxT( "f" );
text.Printf( format, To_User_Unit( units, val, useMils ) );
if( m_cbSuppressZeroes->GetValue() )
{
while( text[text.Length() - 1] == '0' || text[text.Length() - 1] == '.' )
text.Remove( text.Length() - 1 );
}
return text;
aTarget->Update();
}
void DIALOG_DIMENSION_PROPERTIES::updatePreviewText()
{
wxString text = m_cbOverrideValue->GetValue() ? m_txtValue->GetValue() : getValueText();
EDA_UNITS units;
bool useMils;
getUnitsSelection( units, useMils );
switch( m_cbUnitsFormat->GetSelection() )
{
case 0: // no units
break;
case 1: // normal
text += " ";
text += GetAbbreviatedUnitsLabel( units, useMils );
break;
case 2: // parenthetical
text += " (";
text += GetAbbreviatedUnitsLabel( units, useMils );
text += ")";
break;
}
text.Prepend( m_txtPrefix->GetValue() );
text.Append( m_txtSuffix->GetValue() );
m_staticTextPreview->SetLabel( text );
updateDimensionFromDialog( m_previewDimension );
m_staticTextPreview->SetLabel( m_previewDimension->Text().GetShownText() );
}

View File

@ -49,6 +49,7 @@ private:
PCB_BASE_EDIT_FRAME* m_frame;
DIMENSION* m_dimension;
DIMENSION* m_previewDimension;
UNIT_BINDER m_textWidth;
UNIT_BINDER m_textHeight;
@ -62,9 +63,7 @@ private:
UNIT_BINDER m_lineThickness;
UNIT_BINDER m_arrowLength;
void getUnitsSelection( EDA_UNITS& aUnits, bool& aUseMils );
wxString getValueText();
void updateDimensionFromDialog( DIMENSION* aTarget );
void updatePreviewText();
};

View File

@ -222,14 +222,14 @@ DIALOG_DIMENSION_PROPERTIES_BASE::DIALOG_DIMENSION_PROPERTIES_BASE( wxWindow* pa
m_lblTextOrientation->Wrap( -1 );
m_lblTextOrientation->SetToolTip( _("Text orientation") );
gbSizerText->Add( m_lblTextOrientation, wxGBPosition( 2, 4 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALL, 5 );
gbSizerText->Add( m_lblTextOrientation, wxGBPosition( 3, 4 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALL, 5 );
m_cbTextOrientation = new wxComboBox( sbSizerText->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 );
m_cbTextOrientation->Append( _("0.0") );
m_cbTextOrientation->Append( _("90.0") );
m_cbTextOrientation->Append( _("-90.0") );
m_cbTextOrientation->Append( _("180.0") );
gbSizerText->Add( m_cbTextOrientation, wxGBPosition( 2, 5 ), wxGBSpan( 1, 1 ), wxALL|wxEXPAND, 5 );
gbSizerText->Add( m_cbTextOrientation, wxGBPosition( 3, 5 ), wxGBSpan( 1, 1 ), wxALL|wxEXPAND, 5 );
m_cbItalic = new wxCheckBox( sbSizerText->GetStaticBox(), wxID_ANY, _("Italic"), wxDefaultPosition, wxDefaultSize, 0 );
gbSizerText->Add( m_cbItalic, wxGBPosition( 3, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALL, 5 );
@ -237,7 +237,7 @@ DIALOG_DIMENSION_PROPERTIES_BASE::DIALOG_DIMENSION_PROPERTIES_BASE( wxWindow* pa
m_cbKeepAligned = new wxCheckBox( sbSizerText->GetStaticBox(), wxID_ANY, _("Keep aligned with dimension"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbKeepAligned->SetToolTip( _("Automatically set the text orientation to match the dimension lines") );
gbSizerText->Add( m_cbKeepAligned, wxGBPosition( 3, 4 ), wxGBSpan( 1, 3 ), wxALIGN_CENTER_VERTICAL|wxALL, 5 );
gbSizerText->Add( m_cbKeepAligned, wxGBPosition( 4, 4 ), wxGBSpan( 1, 3 ), wxALIGN_CENTER_VERTICAL|wxALL, 5 );
m_cbMirrored = new wxCheckBox( sbSizerText->GetStaticBox(), wxID_ANY, _("Mirrored"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbMirrored->SetToolTip( _("Mirror text") );
@ -246,13 +246,25 @@ DIALOG_DIMENSION_PROPERTIES_BASE::DIALOG_DIMENSION_PROPERTIES_BASE( wxWindow* pa
m_lblJustification = new wxStaticText( sbSizerText->GetStaticBox(), wxID_ANY, _("Justification:"), wxDefaultPosition, wxDefaultSize, 0 );
m_lblJustification->Wrap( -1 );
gbSizerText->Add( m_lblJustification, wxGBPosition( 4, 4 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALL, 5 );
gbSizerText->Add( m_lblJustification, wxGBPosition( 5, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALL, 5 );
wxString m_cbJustificationChoices[] = { _("Left"), _("Center"), _("Right") };
int m_cbJustificationNChoices = sizeof( m_cbJustificationChoices ) / sizeof( wxString );
m_cbJustification = new wxChoice( sbSizerText->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, m_cbJustificationNChoices, m_cbJustificationChoices, 0 );
m_cbJustification->SetSelection( 0 );
gbSizerText->Add( m_cbJustification, wxGBPosition( 4, 5 ), wxGBSpan( 1, 1 ), wxALL|wxEXPAND, 5 );
gbSizerText->Add( m_cbJustification, wxGBPosition( 5, 1 ), wxGBSpan( 1, 1 ), wxALL|wxEXPAND, 5 );
m_lblTextPositionMode = new wxStaticText( sbSizerText->GetStaticBox(), wxID_ANY, _("Position mode:"), wxDefaultPosition, wxDefaultSize, 0 );
m_lblTextPositionMode->Wrap( -1 );
gbSizerText->Add( m_lblTextPositionMode, wxGBPosition( 2, 4 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALL, 5 );
wxString m_cbTextPositionModeChoices[] = { _("Outside"), _("Inline"), _("Manual") };
int m_cbTextPositionModeNChoices = sizeof( m_cbTextPositionModeChoices ) / sizeof( wxString );
m_cbTextPositionMode = new wxChoice( sbSizerText->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, m_cbTextPositionModeNChoices, m_cbTextPositionModeChoices, 0 );
m_cbTextPositionMode->SetSelection( 0 );
m_cbTextPositionMode->SetToolTip( _("Choose how to position the text relative to the dimension line") );
gbSizerText->Add( m_cbTextPositionMode, wxGBPosition( 2, 5 ), wxGBSpan( 1, 1 ), wxALL|wxEXPAND, 5 );
gbSizerText->AddGrowableCol( 1 );

View File

@ -2309,7 +2309,7 @@
<property name="colspan">1</property>
<property name="column">4</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
<property name="row">2</property>
<property name="row">3</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property>
@ -2373,7 +2373,7 @@
<property name="colspan">1</property>
<property name="column">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="row">2</property>
<property name="row">3</property>
<property name="rowspan">1</property>
<object class="wxComboBox" expanded="0">
<property name="BottomDockable">1</property>
@ -2509,7 +2509,7 @@
<property name="colspan">3</property>
<property name="column">4</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
<property name="row">3</property>
<property name="row">4</property>
<property name="rowspan">1</property>
<object class="wxCheckBox" expanded="1">
<property name="BottomDockable">1</property>
@ -2641,9 +2641,9 @@
<object class="gbsizeritem" expanded="1">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">4</property>
<property name="column">0</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
<property name="row">4</property>
<property name="row">5</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property>
@ -2705,9 +2705,9 @@
<object class="gbsizeritem" expanded="1">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">5</property>
<property name="column">1</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="row">4</property>
<property name="row">5</property>
<property name="rowspan">1</property>
<object class="wxChoice" expanded="0">
<property name="BottomDockable">1</property>
@ -2769,6 +2769,137 @@
<property name="window_style"></property>
</object>
</object>
<object class="gbsizeritem" expanded="1">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">4</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
<property name="row">2</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Position mode:</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_lblTextPositionMode</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
<object class="gbsizeritem" expanded="1">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="row">2</property>
<property name="rowspan">1</property>
<object class="wxChoice" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="choices">&quot;Outside&quot; &quot;Inline&quot; &quot;Manual&quot;</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_cbTextPositionMode</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="selection">0</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Choose how to position the text relative to the dimension line</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
</object>
</object>
</object>

View File

@ -82,6 +82,8 @@ class DIALOG_DIMENSION_PROPERTIES_BASE : public DIALOG_SHIM
wxCheckBox* m_cbMirrored;
wxStaticText* m_lblJustification;
wxChoice* m_cbJustification;
wxStaticText* m_lblTextPositionMode;
wxChoice* m_cbTextPositionMode;
wxStaticText* m_lblLineThickness;
wxTextCtrl* m_txtLineThickness;
wxStaticText* m_lblLineThicknessUnits;

View File

@ -683,17 +683,17 @@ void PCB_IO::format( ALIGNED_DIMENSION* aDimension, int aNestLevel ) const
m_out->Print( aNestLevel+1, "(format" );
if( !aDimension->GetPrefix().IsEmpty() )
m_out->Print( 0, " (prefix %s)", TO_UTF8( aDimension->GetPrefix() ) );
m_out->Print( 0, " (prefix \"%s\")", TO_UTF8( aDimension->GetPrefix() ) );
if( !aDimension->GetSuffix().IsEmpty() )
m_out->Print( 0, " (suffix %s)", TO_UTF8( aDimension->GetSuffix() ) );
m_out->Print( 0, " (suffix \"%s\")", TO_UTF8( aDimension->GetSuffix() ) );
m_out->Print( 0, " (units %d) (units_format %d) (precision %d)",
static_cast<int>( aDimension->GetUnitsMode() ),
static_cast<int>( aDimension->GetUnitsFormat() ), aDimension->GetPrecision() );
if( aDimension->GetOverrideValue() )
m_out->Print( 0, " override_value" );
if( aDimension->GetOverrideTextEnabled() )
m_out->Print( 0, " (override_value \"%s\")", TO_UTF8( aDimension->GetOverrideText() ) );
if( aDimension->GetSuppressZeroes() )
m_out->Print( 0, " suppress_zeroes" );
@ -710,7 +710,7 @@ void PCB_IO::format( ALIGNED_DIMENSION* aDimension, int aNestLevel ) const
FormatInternalUnits( aDimension->GetExtensionOffset() ).c_str() );
if( !aDimension->GetKeepTextAligned() )
m_out->Print( 0, " keep_upright" );
m_out->Print( 0, " keep_text_aligned" );
m_out->Print( 0, ")\n" );

View File

@ -38,6 +38,7 @@
#include <widgets/appearance_controls.h>
#include <dialogs/eda_view_switcher.h>
#include <layer_widget.h>
#include <class_dimension.h>
PCB_BASE_EDIT_FRAME::PCB_BASE_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent,
FRAME_T aFrameType, const wxString& aTitle,
@ -160,6 +161,29 @@ void PCB_BASE_EDIT_FRAME::unitsChangeRefresh()
{
PCB_BASE_FRAME::unitsChangeRefresh();
if( BOARD* board = GetBoard() )
{
EDA_UNITS units = GetUserUnits();
KIGFX::VIEW* view = GetCanvas()->GetView();
INSPECTOR_FUNC inspector =
[units, view]( EDA_ITEM* aItem, void* aTestData )
{
DIMENSION* dimension = static_cast<DIMENSION*>( aItem );
if( dimension->GetUnitsMode() == DIM_UNITS_MODE::AUTOMATIC )
{
dimension->SetUnits( units, false );
dimension->Update();
view->Update( dimension );
}
return SEARCH_RESULT::CONTINUE;
};
board->Visit( inspector, nullptr, GENERAL_COLLECTOR::Dimensions );
}
ReCreateAuxiliaryToolbar();
}

View File

@ -1296,7 +1296,7 @@ void PCB_PAINTER::draw( const DIMENSION* aDimension, int aLayer )
}
m_gal->SetTextAttributes( &text );
m_gal->StrokeText( text.GetShownText(), position, text.GetTextAngleRadians() );
m_gal->StrokeText( aDimension->GetText(), position, text.GetTextAngleRadians() );
}

View File

@ -2486,11 +2486,19 @@ DIMENSION* PCB_PARSER::parseDIMENSION()
break;
case T_override_value:
dimension->SetOverrideValue( true );
NeedSYMBOLorNUMBER();
dimension->SetOverrideTextEnabled( true );
dimension->SetOverrideText( FromUTF8() );
NeedRIGHT();
break;
case T_suppress_zeroes:
dimension->SetSuppressZeroes( true );
break;
default:
Expecting( "prefix, suffix, units, units_format, precision, override_value" );
Expecting( "prefix, suffix, units, units_format, precision, override_value, "
"suppress_zeroes" );
}
}
break;
@ -2498,6 +2506,9 @@ DIMENSION* PCB_PARSER::parseDIMENSION()
case T_style:
{
// new format: default to keep text aligned off unless token is present
dimension->SetKeepTextAligned( false );
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
{
switch( token )
@ -2533,6 +2544,10 @@ DIMENSION* PCB_PARSER::parseDIMENSION()
NeedRIGHT();
break;
case T_keep_text_aligned:
dimension->SetKeepTextAligned( true );
break;
default:
Expecting( "thickness, arrow_length, text_position_mode, extension_height, "
"extension_offset" );
@ -2664,6 +2679,8 @@ DIMENSION* PCB_PARSER::parseDIMENSION()
}
}
dimension->Update();
return dimension.release();
}

View File

@ -80,6 +80,7 @@ enum DIMENSION_POINTS
DIM_CROSSBAREND,
DIM_START,
DIM_END,
DIM_TEXT
};
class EDIT_POINTS_FACTORY
@ -251,6 +252,7 @@ public:
points->AddPoint( dimension->GetCrossbarEnd() );
points->AddPoint( dimension->GetStart() );
points->AddPoint( dimension->GetEnd() );
points->AddPoint( dimension->Text().GetPosition() );
// Dimension height setting - edit points should move only along the feature lines
points->Point( DIM_CROSSBARSTART ).SetConstraint( new EC_LINE( points->Point( DIM_CROSSBARSTART ),
@ -1297,6 +1299,14 @@ void POINT_EDITOR::updateItem() const
m_editPoints->Point( DIM_END ) ) );
}
else if( isModified( m_editPoints->Point(DIM_TEXT ) ) )
{
// Force manual mode if we weren't already in it
dimension->SetTextPositionMode( DIM_TEXT_POSITION::MANUAL );
dimension->Text().SetPosition( wxPoint( m_editedPoint->GetPosition() ) );
dimension->Update();
}
break;
}
@ -1525,6 +1535,7 @@ void POINT_EDITOR::updatePoints()
m_editPoints->Point( DIM_CROSSBAREND ).SetPosition( dimension->GetCrossbarEnd() );
m_editPoints->Point( DIM_START ).SetPosition( dimension->GetStart() );
m_editPoints->Point( DIM_END ).SetPosition( dimension->GetEnd() );
m_editPoints->Point( DIM_TEXT ).SetPosition( dimension->Text().GetPosition() );
break;
}