Eeschema: fix illegal field characters causing corrupt schematic files on Linux. (fixes lp:1529358)

* Refactor edit one field dialogs to use validators and transfer data to and
  from window functions.
* Add code to DIALOG_SHIM to handle validation and transfer functions since
  the base dialog class code is not called by EndQuasiModal().
* Add custom validator class for filtering field text control characters.
* Add new field validator to edit schematic component dialog field text
  control.
* Add new field validator to edit fields in library editor dialog field
  text control.
* Make a few LIB_PART member functions const.
This commit is contained in:
Wayne Stambaugh 2016-04-02 08:25:44 -04:00
parent 78d96afe28
commit 76d099b337
13 changed files with 647 additions and 547 deletions

View File

@ -505,6 +505,11 @@ int DIALOG_SHIM::ShowQuasiModal()
void DIALOG_SHIM::EndQuasiModal( int retCode )
{
// Hook up validator and transfer data from controls handling so quasi-modal dialogs
// handle validation in the same way as other dialogs.
if( ( retCode == wxID_OK ) && ( !Validate() || !TransferDataFromWindow() ) )
return;
SetReturnCode( retCode );
if( !IsQuasiModal() )

View File

@ -155,6 +155,7 @@ set( EESCHEMA_SRCS
sch_sheet_path.cpp
sch_sheet_pin.cpp
sch_text.cpp
sch_validators.cpp
schedit.cpp
schematic_undo_redo.cpp
schframe.cpp

View File

@ -351,14 +351,14 @@ public:
bool LoadAliases( char* aLine, wxString& aErrorMsg );
bool LoadFootprints( LINE_READER& aReader, wxString& aErrorMsg );
bool IsPower() { return m_options == ENTRY_POWER; }
bool IsNormal() { return m_options == ENTRY_NORMAL; }
bool IsPower() const { return m_options == ENTRY_POWER; }
bool IsNormal() const { return m_options == ENTRY_NORMAL; }
void SetPower() { m_options = ENTRY_POWER; }
void SetNormal() { m_options = ENTRY_NORMAL; }
void LockUnits( bool aLockUnits ) { m_unitsLocked = aLockUnits; }
bool UnitsLocked() { return m_unitsLocked; }
bool UnitsLocked() const { return m_unitsLocked; }
/**
* Function SetFields

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2004-2015 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2004-2016 KiCad Developers, see change_log.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
@ -43,6 +43,8 @@
#include <class_library.h>
#include <sch_component.h>
#include <dialog_helpers.h>
#include <sch_validators.h>
#include <dialog_edit_component_in_schematic_fbp.h>
@ -840,6 +842,7 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copySelectedFieldToPanel()
// may only delete user defined fields
deleteFieldButton->Enable( fieldNdx >= MANDATORY_FIELDS );
fieldValueTextCtrl->SetValidator( SCH_FIELD_VALIDATOR( field.GetId() ) );
fieldValueTextCtrl->SetValue( field.GetText() );
m_show_datasheet_button->Enable( fieldNdx == DATASHEET || fieldNdx == FOOTPRINT );
@ -897,6 +900,11 @@ bool DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::copyPanelToSelectedField()
if( fieldNdx >= m_FieldsBuf.size() ) // traps the -1 case too
return true;
// Check for illegal field text.
if( fieldValueTextCtrl->GetValidator()
&& !fieldValueTextCtrl->GetValidator()->Validate( this ) )
return false;
SCH_FIELD& field = m_FieldsBuf[fieldNdx];
field.SetVisible( showCheckBox->GetValue() );

View File

@ -3,7 +3,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2011-2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2007 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2007-2016 KiCad Developers, see change_log.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
@ -42,6 +42,7 @@
#include <sch_field.h>
#include <template_fieldnames.h>
#include <dialog_helpers.h>
#include <sch_validators.h>
#include <dialog_edit_libentry_fields_in_lib_base.h>
@ -240,7 +241,7 @@ void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::OnOKButtonClick( wxCommandEvent& event
// test if reference prefix is acceptable
if( !SCH_COMPONENT::IsReferenceStringValid( m_FieldsBuf[REFERENCE].GetText() ) )
{
DisplayError( NULL, _( "Illegal reference prefix. A reference must start by a letter" ) );
DisplayError( NULL, _( "Illegal reference. References must start with a letter." ) );
return;
}
@ -282,15 +283,6 @@ void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::OnOKButtonClick( wxCommandEvent& event
++i;
}
#if defined(DEBUG)
for( unsigned i = 0; i<m_FieldsBuf.size(); ++i )
{
printf( "save[%u].name:'%s' value:'%s'\n", i,
TO_UTF8( m_FieldsBuf[i].GetName() ),
TO_UTF8( m_FieldsBuf[i].GetText() ) );
}
#endif
// copy all the fields back, fully replacing any previous fields
m_libEntry->SetFields( m_FieldsBuf );
@ -415,7 +407,6 @@ void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::showButtonHandler( wxCommandEvent& even
if( frame->ShowModal( &fpid, this ) )
{
// DBG( printf( "%s: %s\n", __func__, TO_UTF8( fpid ) ); )
fieldValueTextCtrl->SetValue( fpid );
}
@ -486,13 +477,6 @@ void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::initBuffers()
m_libEntry->GetFields( cmpFields );
#if defined(DEBUG)
for( unsigned i=0; i<cmpFields.size(); ++i )
{
printf( "cmpFields[%u].name:%s\n", i, TO_UTF8( cmpFields[i].GetName() ) );
}
#endif
/* We have 3 component related field lists to be aware of: 1) UI
presentation (m_FieldsBuf), 2) fields in component ram copy, and 3)
fields recorded with component on disk. m_FieldsBuf is the list of UI
@ -517,7 +501,6 @@ void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::initBuffers()
// fixed fields:
for( int i=0; i<MANDATORY_FIELDS; ++i )
{
DBG( printf( "add fixed:%s\n", TO_UTF8( cmpFields[i].GetName() ) ); )
m_FieldsBuf.push_back( cmpFields[i] );
}
@ -543,8 +526,6 @@ void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::initBuffers()
// values from the component will be set.
if( !libField )
{
DBG( printf( "add template:%s\n", TO_UTF8( it->m_Name ) ); )
fld.SetName( it->m_Name );
fld.SetText( it->m_Value ); // empty? ok too.
@ -555,7 +536,6 @@ void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::initBuffers()
}
else
{
DBG( printf( "match template:%s\n", TO_UTF8( libField->GetName() ) ); )
fld = *libField; // copy values from component, m_Name too
}
@ -571,7 +551,6 @@ void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::initBuffers()
if( !buf )
{
DBG( printf( "add cmp:%s\n", TO_UTF8( cmp->GetName() ) ); )
m_FieldsBuf.push_back( *cmp );
}
}
@ -687,6 +666,7 @@ void DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::copySelectedFieldToPanel()
// if fieldNdx == REFERENCE, VALUE, then disable delete button
deleteFieldButton->Enable( fieldNdx >= MANDATORY_FIELDS );
fieldValueTextCtrl->SetValidator( SCH_FIELD_VALIDATOR( field.GetId() ) );
fieldValueTextCtrl->SetValue( field.GetText() );
textSizeTextCtrl->SetValue( EDA_GRAPHIC_TEXT_CTRL::FormatSize( g_UserUnit, field.GetSize().x ) );
@ -739,6 +719,11 @@ bool DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::copyPanelToSelectedField()
if( fieldNdx >= m_FieldsBuf.size() ) // traps the -1 case too
return true;
// Check for illegal field text.
if( fieldValueTextCtrl->GetValidator()
&& !fieldValueTextCtrl->GetValidator()->Validate( this ) )
return false;
LIB_FIELD& field = m_FieldsBuf[fieldNdx];
if( showCheckBox->GetValue() )
@ -776,12 +761,9 @@ bool DIALOG_EDIT_LIBENTRY_FIELDS_IN_LIB::copyPanelToSelectedField()
if( field.GetId() >= MANDATORY_FIELDS )
{
wxString name = fieldNameTextCtrl->GetValue();
DBG( printf("name:%s\n", TO_UTF8( name ) ); )
field.SetName( name );
}
DBG( printf("setname:%s\n", TO_UTF8( field.GetName() ) ); )
setRowItem( fieldNdx, field ); // update fieldListCtrl
int tmp = EDA_GRAPHIC_TEXT_CTRL::ParseSize( textSizeTextCtrl->GetValue(), g_UserUnit );

View File

@ -7,7 +7,8 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.com
* Copyright (C) 2004-2012 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2016 Wayne Stambaugh, stambaughw@gmail.com
* Copyright (C) 2004-2016 KiCad Developers, see change_log.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
@ -31,82 +32,111 @@
#include <common.h>
#include <base_units.h>
#include <kiway.h>
#include <confirm.h>
#include <general.h>
#include <sch_base_frame.h>
#include <sch_component.h>
#include <template_fieldnames.h>
#include <class_libentry.h>
#include <lib_field.h>
#include <sch_component.h>
#include <template_fieldnames.h>
#include <class_library.h>
#include <sch_validators.h>
#include <dialog_edit_one_field.h>
void DIALOG_EDIT_ONE_FIELD::initDlg_base()
// These should probably moved into some other file as helpers.
EDA_TEXT_HJUSTIFY_T IntToEdaTextHorizJustify( int aHorizJustify )
{
wxASSERT( aHorizJustify >= GR_TEXT_HJUSTIFY_LEFT && aHorizJustify <= GR_TEXT_HJUSTIFY_RIGHT );
if( aHorizJustify > GR_TEXT_HJUSTIFY_RIGHT )
return GR_TEXT_HJUSTIFY_RIGHT;
if( aHorizJustify < GR_TEXT_HJUSTIFY_LEFT )
return GR_TEXT_HJUSTIFY_LEFT;
return (EDA_TEXT_HJUSTIFY_T) aHorizJustify;
}
EDA_TEXT_VJUSTIFY_T IntToEdaTextVertJustify( int aVertJustify )
{
wxASSERT( aVertJustify >= GR_TEXT_VJUSTIFY_TOP && aVertJustify <= GR_TEXT_VJUSTIFY_BOTTOM );
if( aVertJustify > GR_TEXT_VJUSTIFY_BOTTOM )
return GR_TEXT_VJUSTIFY_BOTTOM;
if( aVertJustify < GR_TEXT_VJUSTIFY_TOP )
return GR_TEXT_VJUSTIFY_TOP;
return (EDA_TEXT_VJUSTIFY_T) aVertJustify;
}
DIALOG_EDIT_ONE_FIELD::DIALOG_EDIT_ONE_FIELD( SCH_BASE_FRAME* aParent, const wxString& aTitle,
const EDA_TEXT* aTextItem ) :
DIALOG_LIB_EDIT_TEXT_BASE( aParent )
{
SetTitle( aTitle );
// The field ID and power status are Initialized in the derived object's ctor.
m_fieldId = VALUE;
m_isPower = false;
m_text = aTextItem->GetText();
m_style = aTextItem->IsItalic() ? 1 : 0;
m_style += aTextItem->IsBold() ? 2 : 0;
m_size = aTextItem->GetSize().x;
m_orientation = ( aTextItem->GetOrientation() == TEXT_ORIENT_VERT );
m_verticalJustification = aTextItem->GetVertJustify() + 1;
m_horizontalJustification = aTextItem->GetHorizJustify() + 1;
m_isVisible = aTextItem->IsVisible();
}
void DIALOG_EDIT_ONE_FIELD::init()
{
wxString msg;
m_TextValue->SetFocus();
m_TextValue->SetValidator( SCH_FIELD_VALIDATOR( m_fieldId, &m_text ) );
// Disable options for graphic text edition, not existing in fields
// Disable options for graphic text editing which are not needed for fields.
m_CommonConvert->Show( false );
m_CommonUnit->Show( false );
msg = StringFromValue( g_UserUnit, m_textsize );
m_TextSize->SetValue( msg );
if( m_textorient == TEXT_ORIENT_VERT )
m_Orient->SetValue( true );
m_Invisible->SetValue( m_text_invisible );
m_TextShapeOpt->SetSelection( m_textshape );
SetPowerWarning( false );
switch ( m_textHjustify )
// Show the footprint selection dialog if this is the footprint field.
if( m_fieldId == FOOTPRINT )
{
case GR_TEXT_HJUSTIFY_LEFT:
m_TextHJustificationOpt->SetSelection( 0 );
break;
case GR_TEXT_HJUSTIFY_CENTER:
m_TextHJustificationOpt->SetSelection( 1 );
break;
case GR_TEXT_HJUSTIFY_RIGHT:
m_TextHJustificationOpt->SetSelection( 2 );
break;
m_TextValueSelectButton->Show();
m_TextValueSelectButton->Enable();
}
switch ( m_textVjustify )
else
{
case GR_TEXT_VJUSTIFY_BOTTOM:
m_TextVJustificationOpt->SetSelection( 0 );
break;
case GR_TEXT_VJUSTIFY_CENTER:
m_TextVJustificationOpt->SetSelection( 1 );
break;
case GR_TEXT_VJUSTIFY_TOP:
m_TextVJustificationOpt->SetSelection( 2 );
break;
m_TextValueSelectButton->Hide();
m_TextValueSelectButton->Disable();
}
msg = m_TextSizeText->GetLabel() + ReturnUnitSymbol();
m_TextSizeText->SetLabel( msg );
// Value fields of power components cannot be modified. This will grey out
// the text box and display an explanation.
if( m_fieldId == VALUE && m_isPower )
{
m_PowerComponentValues->Show( true );
m_TextValue->Enable( false );
}
m_sdbSizerButtonsOK->SetDefault();
GetSizer()->SetSizeHints( this );
Centre();
}
void DIALOG_EDIT_ONE_FIELD::SetPowerWarning( bool aWarn )
{
m_PowerComponentValues->Show( aWarn );
m_TextValue->Enable( ! aWarn );
Fit();
}
void DIALOG_EDIT_ONE_FIELD::OnTextValueSelectButtonClick( wxCommandEvent& aEvent )
{
@ -117,7 +147,6 @@ void DIALOG_EDIT_ONE_FIELD::OnTextValueSelectButtonClick( wxCommandEvent& aEvent
if( frame->ShowModal( &fpid, this ) )
{
// DBG( printf( "%s: %s\n", __func__, TO_UTF8( fpid ) ); )
m_TextValue->SetValue( fpid );
}
@ -125,192 +154,96 @@ void DIALOG_EDIT_ONE_FIELD::OnTextValueSelectButtonClick( wxCommandEvent& aEvent
}
void DIALOG_LIB_EDIT_ONE_FIELD::initDlg()
bool DIALOG_EDIT_ONE_FIELD::TransferDataToWindow()
{
m_textsize = m_field->GetSize().x;
m_TextValue->SetValue( m_field->GetText() );
m_textorient = m_field->GetOrientation();
m_text_invisible = m_field->IsVisible() ? false : true;
wxLogDebug( "In DIALOG_EDIT_ONE_FIELD::TransferDataToWindow()" );
m_textshape = 0;
m_TextValue->SetValue( m_text );
m_Orient->SetValue( m_orientation );
m_TextSize->SetValue( StringFromValue( g_UserUnit, m_size ) );
m_TextHJustificationOpt->SetSelection( m_horizontalJustification );
m_TextVJustificationOpt->SetSelection( m_verticalJustification );
m_Invisible->SetValue( !m_isVisible );
m_TextShapeOpt->SetSelection( m_style );
if( m_field->IsItalic() )
m_textshape = 1;
if( m_field->IsBold() )
m_textshape |= 2;
m_textHjustify = m_field->GetHorizJustify();
m_textVjustify = m_field->GetVertJustify();
if( m_field->GetId() == FOOTPRINT )
{
m_TextValueSelectButton->Show();
m_TextValueSelectButton->Enable();
}
else
{
m_TextValueSelectButton->Hide();
m_TextValueSelectButton->Disable();
}
initDlg_base();
return true;
}
wxString DIALOG_LIB_EDIT_ONE_FIELD::GetTextField()
bool DIALOG_EDIT_ONE_FIELD::TransferDataFromWindow()
{
wxString line = m_TextValue->GetValue();
wxLogDebug( "In DIALOG_EDIT_ONE_FIELD::TransferDataFromWindow()" );
// Spaces are not allowed in reference or value
if( m_field->GetId() == REFERENCE || m_field->GetId() == VALUE )
m_text = m_TextValue->GetValue();
// There are lots of specific tests required to validate field text.
if( m_fieldId == REFERENCE )
{
if( line.Replace( wxT( " " ), wxT( "_" ) ) )
// Test if the reference string is valid:
if( !SCH_COMPONENT::IsReferenceStringValid( m_text ) )
{
wxString msg;
msg.Printf( _(
"Whitespace is not permitted inside references or values (symbol names in lib).\n"
"The text you entered has been converted to use underscores: %s" ),
line
);
wxMessageDialog dlg( this, msg );
dlg.ShowModal();
DisplayError( this, _( "Illegal reference field value!" ) );
return false;
}
}
// Prevent the message from appearing twice by restuffing the text box.
m_TextValue->SetValue( line );
m_orientation = m_Orient->GetValue();
m_size = ValueFromString( g_UserUnit, m_TextSize->GetValue() );
m_horizontalJustification = m_TextHJustificationOpt->GetSelection();
m_verticalJustification = m_TextVJustificationOpt->GetSelection();
m_isVisible = !m_Invisible->GetValue();
m_style = m_TextShapeOpt->GetSelection();
return line;
return true;
}
void DIALOG_EDIT_ONE_FIELD::TransfertDataToField( bool aIncludeText )
void DIALOG_EDIT_ONE_FIELD::updateText( EDA_TEXT* aText )
{
// This method doesn't transfer text anyway.
(void) aIncludeText;
m_textorient = m_Orient->GetValue() ? TEXT_ORIENT_VERT : TEXT_ORIENT_HORIZ;
wxString msg = m_TextSize->GetValue();
m_textsize = ValueFromString( g_UserUnit, msg );
switch( m_TextHJustificationOpt->GetSelection() )
{
case 0:
m_textHjustify = GR_TEXT_HJUSTIFY_LEFT;
break;
case 1:
m_textHjustify = GR_TEXT_HJUSTIFY_CENTER;
break;
case 2:
m_textHjustify = GR_TEXT_HJUSTIFY_RIGHT;
break;
}
switch( m_TextVJustificationOpt->GetSelection() )
{
case 0:
m_textVjustify = GR_TEXT_VJUSTIFY_BOTTOM;
break;
case 1:
m_textVjustify = GR_TEXT_VJUSTIFY_CENTER;
break;
case 2:
m_textVjustify = GR_TEXT_VJUSTIFY_TOP;
break;
}
aText->SetSize( wxSize( m_size, m_size ) );
aText->SetVisible( m_isVisible );
aText->SetOrientation( m_orientation ? TEXT_ORIENT_VERT : TEXT_ORIENT_HORIZ );
aText->SetItalic( (m_style & 1) != 0 );
aText->SetBold( (m_style & 2) != 0 );
aText->SetHorizJustify( IntToEdaTextHorizJustify( m_horizontalJustification - 1 ) );
aText->SetVertJustify( IntToEdaTextVertJustify( m_verticalJustification - 1 ) );
}
void DIALOG_LIB_EDIT_ONE_FIELD::TransfertDataToField( bool aIncludeText )
DIALOG_LIB_EDIT_ONE_FIELD::DIALOG_LIB_EDIT_ONE_FIELD( SCH_BASE_FRAME* aParent,
const wxString& aTitle,
const LIB_FIELD* aField ) :
DIALOG_EDIT_ONE_FIELD( aParent, aTitle, dynamic_cast< const EDA_TEXT* >( aField ) )
{
DIALOG_EDIT_ONE_FIELD::TransfertDataToField( aIncludeText );
m_fieldId = aField->GetId();
if( aIncludeText )
m_field->SetText( GetTextField() );
LIB_PART* part = aField->GetParent();
m_field->SetSize( wxSize( m_textsize, m_textsize ) );
m_field->SetOrientation( m_textorient );
m_field->SetVisible( !m_Invisible->GetValue() );
m_field->SetItalic( ( m_TextShapeOpt->GetSelection() & 1 ) != 0 );
m_field->SetBold( ( m_TextShapeOpt->GetSelection() & 2 ) != 0 );
m_field->SetHorizJustify( m_textHjustify );
m_field->SetVertJustify( m_textVjustify );
wxASSERT_MSG( part, wxT( "LIB_FIELD has no LIB_PART as parent." ) );
m_isPower = part->IsPower();
init();
}
void DIALOG_SCH_EDIT_ONE_FIELD::initDlg()
DIALOG_SCH_EDIT_ONE_FIELD::DIALOG_SCH_EDIT_ONE_FIELD( SCH_BASE_FRAME* aParent,
const wxString& aTitle,
const SCH_FIELD* aField ) :
DIALOG_EDIT_ONE_FIELD( aParent, aTitle, dynamic_cast< const EDA_TEXT* >( aField ) )
{
m_textsize = m_field->GetSize().x;
m_TextValue->SetValue( m_field->GetText() );
m_textorient = m_field->GetOrientation();
m_text_invisible = m_field->IsVisible() ? false : true;
m_fieldId = aField->GetId();
m_textshape = 0;
const SCH_COMPONENT* component = (SCH_COMPONENT*) aField->GetParent();
if( m_field->IsItalic() )
m_textshape = 1;
wxASSERT_MSG( component != NULL && component->Type() == SCH_COMPONENT_T,
wxT( "Invalid schematic field parent item." ) );
if( m_field->IsBold() )
m_textshape |= 2;
const LIB_PART* part = GetParent()->Prj().SchLibs()->FindLibPart( component->GetPartName() );
m_textHjustify = m_field->GetHorizJustify();
m_textVjustify = m_field->GetVertJustify();
wxASSERT_MSG( part, wxT( "Library part for component <" ) +
component->GetPartName() + wxT( "> could not be found." ) );
if( m_field->GetId() == FOOTPRINT )
{
m_TextValueSelectButton->Show();
m_TextValueSelectButton->Enable();
}
else
{
m_TextValueSelectButton->Hide();
m_TextValueSelectButton->Disable();
}
m_isPower = part->IsPower();
initDlg_base();
}
wxString DIALOG_SCH_EDIT_ONE_FIELD::GetTextField()
{
wxString line = m_TextValue->GetValue();
line.Trim( true );
line.Trim( false );
return line;
};
void DIALOG_SCH_EDIT_ONE_FIELD::TransfertDataToField( bool aIncludeText )
{
DIALOG_EDIT_ONE_FIELD::TransfertDataToField( aIncludeText );
if( aIncludeText )
m_field->SetText( GetTextField() );
m_field->SetSize( wxSize( m_textsize, m_textsize ) );
m_field->SetOrientation( m_textorient );
m_field->SetVisible( !m_Invisible->GetValue() );
m_field->SetItalic( ( m_TextShapeOpt->GetSelection() & 1 ) != 0 );
m_field->SetBold( ( m_TextShapeOpt->GetSelection() & 2 ) != 0 );
// Because field autoplace can change justification, check whether this has
// been changed, and clear the autoplace flag if so.
EDA_TEXT_HJUSTIFY_T old_hjust = m_field->GetHorizJustify();
EDA_TEXT_VJUSTIFY_T old_vjust = m_field->GetVertJustify();
if( old_hjust != m_textHjustify || old_vjust != m_textVjustify )
{
EDA_ITEM *parent = m_field->GetParent();
if( SCH_COMPONENT* component = dynamic_cast<SCH_COMPONENT*>( parent ) )
component->ClearFieldsAutoplaced();
}
m_field->SetHorizJustify( m_textHjustify );
m_field->SetVertJustify( m_textVjustify );
init();
}

View File

@ -6,7 +6,8 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.com
* Copyright (C) 2004-2012 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2016 Wayne Stambaugh, stambaughw@gmail.com
* Copyright (C) 2004-2016 KiCad Developers, see change_log.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
@ -28,80 +29,42 @@
#include <dialog_lib_edit_text_base.h>
class SCH_BASE_FRAME;
class LIB_FIELD;
class SCH_FIELD;
class EDA_TEXT;
/**
* Class DIALOG_EDIT_ONE_FIELD
* is a basic class to edit a field: a schematic or a lib component field
* is a base class to edit schematic and component library fields.
* <p>
* This class is setup in expectation of its children
* possibly using Kiway player so ShowQuasiModal is required when calling
* any subclasses.
*</p>
*/
class DIALOG_EDIT_ONE_FIELD : public DIALOG_LIB_EDIT_TEXT_BASE
{
protected:
SCH_BASE_FRAME* m_parent;
int m_textshape;
int m_textsize;
int m_textorient;
EDA_TEXT_HJUSTIFY_T m_textHjustify;
EDA_TEXT_VJUSTIFY_T m_textVjustify;
bool m_text_invisible;
public:
DIALOG_EDIT_ONE_FIELD( SCH_BASE_FRAME* aParent, const wxString& aTitle ):
DIALOG_LIB_EDIT_TEXT_BASE( aParent )
{
m_parent = aParent;
SetTitle( aTitle );
DIALOG_EDIT_ONE_FIELD( SCH_BASE_FRAME* aParent, const wxString& aTitle,
const EDA_TEXT* aTextItem );
// Avoid not initialized members:
m_textshape = 0;
m_textsize = 0;
m_textorient = 0;
m_textHjustify = GR_TEXT_HJUSTIFY_CENTER;
m_textVjustify = GR_TEXT_VJUSTIFY_CENTER;
m_text_invisible = false;
}
~DIALOG_EDIT_ONE_FIELD() {}
// ~DIALOG_EDIT_ONE_FIELD() {};
virtual bool TransferDataToWindow();
/**
* Function TransfertDataToField
* Converts fields from dialog window to variables to be used by child classes
*
* @param aIncludeText Whether the valies transferred should include the actual
* item text. If this is false, formatting will be transferred, but text will
* not.
*/
virtual void TransfertDataToField( bool aIncludeText = true );
virtual bool TransferDataFromWindow();
void SetTextField( const wxString& aText )
{
m_TextValue->SetValue( aText );
}
SCH_BASE_FRAME* GetParent() { return dynamic_cast< SCH_BASE_FRAME* >( wxDialog::GetParent() ); }
/**
* Function SetPowerWarning
* Disables the Text field and displays the "Power component values cannot
* be modified!" warning, if aWarn is true. Performs the inverse if aWarn
* is false (this, however, is the default).
*
* @param aWarn whether or not to produce the warning
*/
void SetPowerWarning( bool aWarn );
const wxString& GetText() const { return m_text; }
protected:
/**
* Function initDlg_base
* Common dialog option initialization for the subclasses to call
*/
void initDlg_base();
void init();
void updateText( EDA_TEXT* aText );
/**
* Function OnTextValueSelectButtonClick
@ -114,106 +77,87 @@ protected:
*/
void OnTextValueSelectButtonClick( wxCommandEvent& aEvent );
/// @todo Update DIALOG_SHIM to handle this transparently so no matter what mode the
/// dialogs is shown, everything is handled without this ugliness.
void OnOkClick( wxCommandEvent& aEvent )
{
EndQuasiModal( wxID_OK );
if( IsQuasiModal() )
EndQuasiModal( wxID_OK );
else
EndDialog( wxID_OK );
}
void OnCancelClick( wxCommandEvent& event )
{
EndQuasiModal( wxID_CANCEL );
if( IsQuasiModal() )
EndQuasiModal( wxID_CANCEL );
else
EndDialog( wxID_CANCEL );
}
void OnCloseDialog( wxCloseEvent& aEvent )
{
EndQuasiModal( wxID_CANCEL );
if( IsQuasiModal() )
EndQuasiModal( wxID_CANCEL );
else
EndDialog( wxID_CANCEL );
}
int m_fieldId;
bool m_isPower;
wxString m_text;
int m_style;
int m_size;
bool m_orientation;
int m_verticalJustification;
int m_horizontalJustification;
bool m_isVisible;
};
/**
* Class DIALOG_LIB_EDIT_ONE_FIELD
* is a the class to handle editing a single component field
* in the library editor.
* is a the class to handle editing a single component field in the library editor.
* <p>
* Note: Use ShowQuasiModal when calling this class!
* @note Use ShowQuasiModal when calling this class!
* </p>
*/
class DIALOG_LIB_EDIT_ONE_FIELD : public DIALOG_EDIT_ONE_FIELD
{
private:
LIB_FIELD* m_field;
public:
DIALOG_LIB_EDIT_ONE_FIELD( SCH_BASE_FRAME* aParent, const wxString& aTitle,
LIB_FIELD* aField ):
DIALOG_EDIT_ONE_FIELD( aParent, aTitle )
const LIB_FIELD* aField );
~DIALOG_LIB_EDIT_ONE_FIELD() {}
void UpdateField( LIB_FIELD* aField )
{
m_field = aField;
initDlg();
GetSizer()->SetSizeHints( this );
Centre();
aField->SetText( m_text );
updateText( aField );
}
~DIALOG_LIB_EDIT_ONE_FIELD() {};
void TransfertDataToField( bool aIncludeText = true );
/**
* Function GetTextField
* Returns the dialog's text field value with spaces filtered to underscores
*/
wxString GetTextField();
private:
/**
* Function initDlg
* Initializes dialog data using the LIB_FIELD container of data, this function is
* otherwise identical to DIALOG_SCH_EDIT_ONE_FIELD::initDlg()
*/
void initDlg( );
};
/**
* Class DIALOG_SCH_EDIT_ONE_FIELD
* is a the class to handle editing a single component field
* in the schematic editor.
* is a the class to handle editing a single component field in the schematic editor.
* <p>
* Note: Use ShowQuasiModal when calling this class!
* @note Use ShowQuasiModal when calling this class!
* </p>
*/
class DIALOG_SCH_EDIT_ONE_FIELD : public DIALOG_EDIT_ONE_FIELD
{
private:
SCH_FIELD* m_field;
public:
DIALOG_SCH_EDIT_ONE_FIELD( SCH_BASE_FRAME* aParent,
const wxString& aTitle, SCH_FIELD* aField ):
DIALOG_EDIT_ONE_FIELD( aParent, aTitle )
DIALOG_SCH_EDIT_ONE_FIELD( SCH_BASE_FRAME* aParent, const wxString& aTitle,
const SCH_FIELD* aField );
~DIALOG_SCH_EDIT_ONE_FIELD() {}
void UpdateField( SCH_FIELD* aField )
{
m_field = aField;
initDlg();
GetSizer()->SetSizeHints( this );
Centre();
aField->SetText( m_text );
updateText( aField );
}
// ~DIALOG_SCH_EDIT_ONE_FIELD() {};
void TransfertDataToField( bool aIncludeText = true );
/**
* Function GetTextField
* Retrieves text field value from dialog with whitespaced on both sides trimmed
*/
wxString GetTextField();
private:
/**
* Function initDlg
* Initializes dialog data using the SCH_FIELD container of data, this function is
* otherwise identical to DIALOG_LIB_EDIT_ONE_FIELD::initDlg()
*/
void initDlg( );
};
#endif // DIALOG_EDIT_ONE_FIELD_H_

View File

@ -44,7 +44,7 @@
<property name="minimum_size"></property>
<property name="name">DIALOG_LIB_EDIT_TEXT_BASE</property>
<property name="pos"></property>
<property name="size">615,343</property>
<property name="size">-1,-1</property>
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
<property name="title">Library Text Properties</property>
@ -204,9 +204,9 @@
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="border">0</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bTextValueOptsSizer</property>
@ -406,7 +406,7 @@
<property name="permission">none</property>
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxTOP|wxRIGHT|wxLEFT</property>
<property name="flag">wxBOTTOM|wxLEFT|wxRIGHT|wxTOP</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property>
@ -1121,94 +1121,194 @@
</object>
</object>
</object>
<object class="sizeritem" expanded="0">
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxRadioBox" expanded="0">
<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;Normal&quot; &quot;Italic&quot; &quot;Bold&quot; &quot;Bold Italic&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>
<object class="wxStaticBoxSizer" expanded="1">
<property name="id">wxID_ANY</property>
<property name="label">Style</property>
<property name="majorDimension">1</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_TextShapeOpt</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">wxRA_SPECIFY_COLS</property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></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>
<event name="OnChar"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRadioBox"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<property name="name">sbSizer2</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<event name="OnUpdateUI"></event>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxCheckBox" 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="checked">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">Italics</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_cbItalics</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"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type">bool</property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable">m_italics</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnChar"></event>
<event name="OnCheckBox"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxCheckBox" 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="checked">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">Bold</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_cbBold</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"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type">bool</property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable">m_bold</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnChar"></event>
<event name="OnCheckBox"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="0">

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2008-2013 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 2008-2016 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 2004-2016 KiCad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
@ -47,7 +47,6 @@ void SCH_EDIT_FRAME::EditComponentFieldText( SCH_FIELD* aField )
wxCHECK_RET( aField != NULL && aField->Type() == SCH_FIELD_T,
wxT( "Cannot edit invalid schematic field." ) );
int fieldNdx;
SCH_COMPONENT* component = (SCH_COMPONENT*) aField->GetParent();
wxCHECK_RET( component != NULL && component->Type() == SCH_COMPONENT_T,
@ -58,9 +57,6 @@ void SCH_EDIT_FRAME::EditComponentFieldText( SCH_FIELD* aField )
wxCHECK_RET( part, wxT( "Library part for component <" ) +
component->GetPartName() + wxT( "> could not be found." ) );
fieldNdx = aField->GetId();
// Save old component in undo list if not already in edit, or moving.
if( aField->GetFlags() == 0 )
SaveCopyInUndoList( component, UR_CHANGED );
@ -74,75 +70,24 @@ void SCH_EDIT_FRAME::EditComponentFieldText( SCH_FIELD* aField )
DIALOG_SCH_EDIT_ONE_FIELD dlg( this, title, aField );
// Value fields of power components cannot be modified. This will grey out
// the text box and display an explanation.
if( fieldNdx == VALUE && part->IsPower() )
// The dialog may invoke a kiway player for footprint fields
// so we must use a quasimodal
if( dlg.ShowQuasiModal() != wxID_OK )
{
dlg.SetPowerWarning( true );
m_canvas->MoveCursorToCrossHair();
m_canvas->SetIgnoreMouseEvents( false );
return;
}
//The diag may invoke a kiway player for footprint fields
//so we must use a quasimodal
int response = dlg.ShowQuasiModal();
dlg.UpdateField( aField );
m_canvas->MoveCursorToCrossHair();
m_canvas->SetIgnoreMouseEvents( false );
wxString newtext = dlg.GetTextField( );
OnModify();
if ( response != wxID_OK )
return; // canceled by user
if( m_autoplaceFields )
component->AutoAutoplaceFields( GetScreen() );
// make some tests
bool can_update = true;
if( !newtext.IsEmpty() )
{
if( fieldNdx == REFERENCE )
{
// Test if the reference string is valid:
if( SCH_COMPONENT::IsReferenceStringValid( newtext ) )
{
component->SetRef( m_CurrentSheet, newtext );
}
else
{
DisplayError( this, _( "Illegal reference string! No change" ) );
can_update = false;
}
}
}
else
{
if( fieldNdx == REFERENCE )
{
DisplayError( this, _( "The reference field cannot be empty! No change" ) );
can_update = false;
}
else if( fieldNdx == VALUE && ! part->IsPower() )
{
// Note that power components also should not have empty value fields - but
// since the user is forbidden from changing the value field here, if it
// were to happen somehow, it'd be awfully confusing if an error were to
// be displayed!
DisplayError( this, _( "The value field cannot be empty! No change" ) );
can_update = false;
}
else if ( !( fieldNdx == VALUE && part->IsPower() ) )
{
dlg.SetTextField( wxT( "~" ) );
}
}
if( can_update )
{
dlg.TransfertDataToField( /* aIncludeText = */ !( fieldNdx == VALUE && part->IsPower() ) );
OnModify();
if( m_autoplaceFields )
component->AutoAutoplaceFields( GetScreen() );
m_canvas->Refresh();
}
m_canvas->Refresh();
MSG_PANEL_ITEMS items;
component->SetCurrentSheetPath( &GetCurrentSheet() );

View File

@ -128,7 +128,7 @@ public:
*/
void SetName( const wxString& aName );
int GetId() { return m_id; }
int GetId() const { return m_id; }
void SetId( int aId ) { m_id = aId; }

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2007 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2014 KiCad Developers, see CHANGELOG.TXT for contributors.
* Copyright (C) 2007-2016 KiCad Developers, see CHANGELOG.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
@ -38,7 +38,7 @@
void LIB_EDIT_FRAME::EditField( LIB_FIELD* aField )
{
wxString text;
wxString newFieldValue;
wxString title;
wxString caption;
wxString oldName;
@ -46,7 +46,7 @@ void LIB_EDIT_FRAME::EditField( LIB_FIELD* aField )
if( aField == NULL )
return;
LIB_PART* parent = aField->GetParent();
LIB_PART* parent = aField->GetParent();
wxASSERT( parent );
@ -66,48 +66,31 @@ void LIB_EDIT_FRAME::EditField( LIB_FIELD* aField )
DIALOG_LIB_EDIT_ONE_FIELD dlg( this, caption, aField );
//The diag may invoke a kiway player for footprint fields
//so we must use a quasimodal
if( dlg.ShowQuasiModal() != wxID_OK )
// The dialog may invoke a kiway player for footprint fields
// so we must use a quasimodal dialog.
if( dlg.ShowQuasiModal() != wxID_OK )
return;
text = dlg.GetTextField();
// Perform some controls:
if( ( aField->GetId() == REFERENCE || aField->GetId() == VALUE ) && text.IsEmpty ( ) )
{
title.Printf( _( "A %s field cannot be empty." ), GetChars(aField->GetName().Lower() ) );
DisplayError( this, title );
return;
}
// Ensure the reference prefix is acceptable:
if( ( aField->GetId() == REFERENCE ) &&
! SCH_COMPONENT::IsReferenceStringValid( text ) )
{
DisplayError( this, _( "Illegal reference. A reference must start by a letter" ) );
return;
}
newFieldValue = dlg.GetText();
wxString fieldText = aField->GetFullText( m_unit );
/* If the value field is changed, this is equivalent to creating a new component from
* the old one. Rename the component and remove any conflicting aliases to prevent name
* errors when updating the library.
*/
if( aField->GetId() == VALUE && text != aField->GetText() )
if( aField->GetId() == VALUE && newFieldValue != aField->GetText() )
{
wxString msg;
PART_LIB* lib = GetCurLib();
// Test the current library for name conflicts.
if( lib && lib->FindEntry( text ) )
if( lib && lib->FindEntry( newFieldValue ) )
{
msg.Printf( _(
"The name '%s' conflicts with an existing entry in the component library '%s'.\n\n"
"Do you wish to replace the current component in library with this one?" ),
GetChars( text ),
"Do you wish to replace the current component in the library with this one?" ),
GetChars( newFieldValue ),
GetChars( lib->GetName() )
);
@ -119,29 +102,28 @@ void LIB_EDIT_FRAME::EditField( LIB_FIELD* aField )
}
// Test the current component for name conflicts.
if( parent->HasAlias( text ) )
if( parent->HasAlias( newFieldValue ) )
{
msg.Printf( _(
"The current component already has an alias named '%s'.\n\n"
"Do you wish to remove this alias from the component?" ),
GetChars( text )
);
msg.Printf( _( "The current component already has an alias named '%s'.\n\n"
"Do you wish to remove this alias from the component?" ),
GetChars( newFieldValue ) );
int rsp = wxMessageBox( msg, _( "Confirm" ), wxYES_NO | wxICON_QUESTION, this );
if( rsp == wxNO )
return;
parent->RemoveAlias( text );
parent->RemoveAlias( newFieldValue );
}
parent->SetName( text );
parent->SetName( newFieldValue );
// Test the library for any conflicts with the any aliases in the current component.
if( parent->GetAliasCount() > 1 && lib && lib->Conflicts( parent ) )
{
msg.Printf( _(
"The new component contains alias names that conflict with entries in the component library '%s'.\n\n"
"The new component contains alias names that conflict with entries in the "
"component library '%s'.\n\n"
"Do you wish to remove all of the conflicting aliases from this component?" ),
GetChars( lib->GetName() )
);
@ -164,19 +146,14 @@ void LIB_EDIT_FRAME::EditField( LIB_FIELD* aField )
}
if( !parent->HasAlias( m_aliasName ) )
m_aliasName = text;
}
else
{
aField->SetText( text );
m_aliasName = newFieldValue;
}
dlg.UpdateField( aField );
if( !aField->InEditMode() )
SaveCopyInUndoList( parent );
// Update field
dlg.TransfertDataToField();
m_canvas->Refresh();
OnModify();

139
eeschema/sch_validators.cpp Normal file
View File

@ -0,0 +1,139 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 Wayne Stambaugh, stambaughw@gmail.com
* Copyright (C) 2016 KiCad Developers, see change_log.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
*/
/**
* @file sch_validators.cpp
* @brief Implementation of control validators for schematic dialogs.
*/
#include <sch_validators.h>
#include <template_fieldnames.h>
SCH_FIELD_VALIDATOR::SCH_FIELD_VALIDATOR( int aFieldId, wxString* aValue ) :
wxTextValidator( wxFILTER_EXCLUDE_CHAR_LIST, aValue )
{
m_fieldId = aFieldId;
// Fields cannot contain carriage returns, line feeds, or tabs.
wxString excludes( "\r\n\t" );
// The reference field cannot contain spaces.
if( aFieldId == REFERENCE )
excludes += " ";
long style = GetStyle();
// The reference and value fields cannot be empty.
if( aFieldId == REFERENCE || aFieldId == VALUE )
style |= wxFILTER_EMPTY;
SetStyle( style );
SetCharExcludes( excludes );
}
SCH_FIELD_VALIDATOR::SCH_FIELD_VALIDATOR( const SCH_FIELD_VALIDATOR& aValidator ) :
wxTextValidator( aValidator )
{
m_fieldId = aValidator.m_fieldId;
}
bool SCH_FIELD_VALIDATOR::Validate( wxWindow *aParent )
{
// If window is disabled, simply return
if( !m_validatorWindow->IsEnabled() )
return true;
wxTextEntry * const text = GetTextEntry();
if( !text )
return false;
wxString val( text->GetValue() );
wxString tmp = val.Clone(); // For trailing and leading white space tests.
wxString fieldName;
switch( m_fieldId )
{
case REFERENCE: fieldName = _( "reference designator" ); break;
case VALUE: fieldName = _( "value" ); break;
case FOOTPRINT: fieldName = _( "footprint" ); break;
case DATASHEET: fieldName = _( "data sheet" ); break;
default: fieldName = _( "user definded" ); break;
};
wxString errorMsg;
// We can only do some kinds of validation once the input is complete, so
// check for them here:
if( HasFlag( wxFILTER_EMPTY ) && val.empty() )
errorMsg.Printf( _( "The %s field cannot be empty." ), fieldName );
else if( HasFlag( wxFILTER_EXCLUDE_CHAR_LIST ) && ContainsExcludedCharacters( val ) )
{
wxArrayString whiteSpace;
if( val.Find( '\r' ) != wxNOT_FOUND )
whiteSpace.Add( _( "carriage return" ) );
if( val.Find( '\n' ) != wxNOT_FOUND )
whiteSpace.Add( _( "line feed" ) );
if( val.Find( '\t' ) != wxNOT_FOUND )
whiteSpace.Add( _( "tab" ) );
if( (m_fieldId == REFERENCE) && (val.Find( ' ' ) != wxNOT_FOUND) )
whiteSpace.Add( _( "space" ) );
wxString badChars;
if( whiteSpace.size() == 1 )
badChars = whiteSpace[0];
else if( whiteSpace.size() == 2 )
badChars.Printf( _( "%s or %s" ), whiteSpace[0], whiteSpace[1] );
else if( whiteSpace.size() == 3 )
badChars.Printf( _( "%s, %s, or %s" ), whiteSpace[0], whiteSpace[1], whiteSpace[2] );
else if( whiteSpace.size() == 4 )
badChars.Printf( _( "%s, %s, %s, or %s" ),
whiteSpace[0], whiteSpace[1], whiteSpace[2], whiteSpace[3] );
else
wxCHECK_MSG( false, true, wxT( "Invalid illegal character in field validator." ) );
errorMsg.Printf( _( "The %s field cannot contain %s characters." ), fieldName, badChars );
}
else if( (tmp.Trim().Length() != val.Length()) || (tmp.Trim( false ).Length() != val.Length()) )
{
errorMsg.Printf( _( "The %s field cannot contain leading and/or trailing white space." ),
fieldName );
}
if ( !errorMsg.empty() )
{
m_validatorWindow->SetFocus();
wxMessageBox( errorMsg, _( "Field Validation Error" ),
wxOK | wxICON_EXCLAMATION, aParent );
return false;
}
return true;
}

66
eeschema/sch_validators.h Normal file
View File

@ -0,0 +1,66 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 Wayne Stambaugh, stambaughw@gmail.com
* Copyright (C) 2016 KiCad Developers, see change_log.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
*/
/**
* @file sch_validators.h
* @brief Defintions of control validators for schematic dialogs.
*/
#ifndef _SCH_VALIDATORS_H_
#define _SCH_VALIDATORS_H_
#include <wx/valtext.h>
/**
* class SCH_FILED_VALIDATOR
*
* is the text control validator used for validating the text allowed in library and
* schematic component fields.
*/
class SCH_FIELD_VALIDATOR : public wxTextValidator
{
int m_fieldId;
public:
SCH_FIELD_VALIDATOR( int aFieldId, wxString* aValue = NULL );
SCH_FIELD_VALIDATOR( const SCH_FIELD_VALIDATOR& aValidator );
virtual wxObject* Clone() const { return new SCH_FIELD_VALIDATOR( *this ); }
/**
* Function Validate
*
* overrides the default Validate() function provided by wxTextValidate to provide
* better error messages.
*
* @param aParent - a pointer to the parent window of the error message dialog.
* @return true if the text in the control is valid otherwise false.
*/
virtual bool Validate( wxWindow *aParent );
};
#endif // _SCH_VALIDATORS_H_