Enhancements in Create array tool (bad parameters detection and disable parms when not applicable)

This commit is contained in:
unknown
2016-04-02 14:52:29 +02:00
committed by jean-pierre charras
parent 76d099b337
commit b8a91c7a98
10 changed files with 663 additions and 304 deletions
+196 -74
View File
@@ -25,6 +25,7 @@
#include <wxPcbStruct.h>
#include <base_units.h>
#include <macros.h>
#include <boost/algorithm/string/join.hpp>
#include <class_drawpanel.h>
#include <class_board.h>
@@ -37,12 +38,14 @@
DIALOG_CREATE_ARRAY::CREATE_ARRAY_DIALOG_ENTRIES DIALOG_CREATE_ARRAY::m_options;
DIALOG_CREATE_ARRAY::DIALOG_CREATE_ARRAY( PCB_BASE_FRAME* aParent, wxPoint aOrigPos,
ARRAY_OPTIONS** aSettings ) :
DIALOG_CREATE_ARRAY::DIALOG_CREATE_ARRAY( PCB_BASE_FRAME* aParent,
bool enableNumbering,
wxPoint aOrigPos ) :
DIALOG_CREATE_ARRAY_BASE( aParent ),
CONFIG_SAVE_RESTORE_WINDOW( m_options.m_optionsSet ),
m_settings( aSettings ),
m_originalItemPosition( aOrigPos )
m_settings( NULL ),
m_originalItemPosition( aOrigPos ),
m_numberingEnabled(enableNumbering)
{
// Set up numbering scheme drop downs
//
@@ -91,9 +94,6 @@ DIALOG_CREATE_ARRAY::DIALOG_CREATE_ARRAY( PCB_BASE_FRAME* aParent, wxPoint aOrig
Add( m_entryGridPriNumberingOffset, m_options.m_gridPriNumberingOffset );
Add( m_entryGridSecNumberingOffset, m_options.m_gridSecNumberingOffset );
Add( m_rbGridStartNumberingOpt, m_options.m_gridNumberingScheme );
Add( m_rbCircStartNumberingOpt, m_options.m_circNumberingScheme );
RestoreConfigToControls();
// Load units into labels
@@ -118,6 +118,13 @@ DIALOG_CREATE_ARRAY::DIALOG_CREATE_ARRAY( PCB_BASE_FRAME* aParent, wxPoint aOrig
}
DIALOG_CREATE_ARRAY::~DIALOG_CREATE_ARRAY()
{
if( m_settings != NULL )
delete m_settings;
}
void DIALOG_CREATE_ARRAY::OnParameterChanged( wxCommandEvent& event )
{
setControlEnablement();
@@ -125,13 +132,13 @@ void DIALOG_CREATE_ARRAY::OnParameterChanged( wxCommandEvent& event )
}
static const std::string& alphabetFromNumberingScheme(
static const wxString& alphabetFromNumberingScheme(
DIALOG_CREATE_ARRAY::ARRAY_NUMBERING_TYPE_T type )
{
static const std::string alphaNumeric = "0123456789";
static const std::string alphaHex = "0123456789ABCDEF";
static const std::string alphaFull = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static const std::string alphaNoIOSQXZ = "ABCDEFGHJKLMNPRTUVWY";
static const wxString alphaNumeric = "0123456789";
static const wxString alphaHex = "0123456789ABCDEF";
static const wxString alphaFull = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static const wxString alphaNoIOSQXZ = "ABCDEFGHJKLMNPRTUVWY";
switch( type )
{
@@ -164,18 +171,18 @@ static bool schemeNonUnitColsStartAt0( DIALOG_CREATE_ARRAY::ARRAY_NUMBERING_TYPE
}
static bool getNumberingOffset( const std::string& str,
static bool getNumberingOffset( const wxString& str,
DIALOG_CREATE_ARRAY::ARRAY_NUMBERING_TYPE_T type,
int& offsetToFill )
{
const std::string alphabet = alphabetFromNumberingScheme( type );
const wxString alphabet = alphabetFromNumberingScheme( type );
int offset = 0;
const int radix = alphabet.length();
for( unsigned i = 0; i < str.length(); i++ )
{
int chIndex = alphabet.find( str[i], 0 );
int chIndex = alphabet.Find( str[i], false );
if( chIndex == wxNOT_FOUND )
return false;
@@ -195,10 +202,91 @@ static bool getNumberingOffset( const std::string& str,
}
/**
* Validates and saves (if valid) the type and offset of an array axis numbering
*
* @param offsetEntry the entry of the offset (text)
* @param typeEntry the entry of the axis nmbering scheme (choice)
* @param type the destination of the type if valid
* @param offset the destination of the offset if valid
* @param errors error string accumulator
* @return if all valid
*/
static bool validateNumberingTypeAndOffset( const wxTextCtrl& offsetEntry,
const wxChoice& typeEntry,
DIALOG_CREATE_ARRAY::ARRAY_NUMBERING_TYPE_T& type,
int& offset,
wxArrayString& errors )
{
const int typeVal = typeEntry.GetSelection();
// mind undefined casts to enums (should not be able to happen)
bool ok = typeVal <= DIALOG_CREATE_ARRAY::NUMBERING_TYPE_MAX;
if( ok )
{
type = (DIALOG_CREATE_ARRAY::ARRAY_NUMBERING_TYPE_T) typeVal;
}
else
{
wxString err;
err.Printf( _("Unrecognised numbering scheme: %d"), typeVal );
errors.Add( err );
// we can't proceed - we don't know the numbering type
return false;
}
const wxString text = offsetEntry.GetValue();
ok = getNumberingOffset( text, type, offset );
if( !ok )
{
const wxString& alphabet = alphabetFromNumberingScheme( type );
wxString err;
err.Printf( _( "Could not determine numbering start from \"%s\": "
"expected value consistent with alphabet \"%s\"" ),
text, alphabet );
errors.Add(err);
}
return ok;
}
/**
* Validate and save a long integer entry
*
* @param entry the text entry to read from
* @param dest the value destination
* @param description description of the field (used if the value is not OK)
* @param errors a list of errors to add any error to
* @return valid
*/
static bool validateLongEntry( const wxTextEntry& entry,
long& dest,
const wxString description,
wxArrayString& errors )
{
bool ok = true;
if( !entry.GetValue().ToLong( &dest ) )
{
wxString err;
err.Printf( _("Bad integral value for %s: %s"), description, entry.GetValue() );
errors.Add( err );
ok = false;
}
return ok;
}
void DIALOG_CREATE_ARRAY::OnOkClick( wxCommandEvent& event )
{
ARRAY_OPTIONS* newSettings = NULL;
wxArrayString errorStrs;
const wxWindow* page = m_gridTypeNotebook->GetCurrentPage();
if( page == m_gridPanel )
@@ -207,8 +295,11 @@ void DIALOG_CREATE_ARRAY::OnOkClick( wxCommandEvent& event )
bool ok = true;
// ints
ok = ok && m_entryNx->GetValue().ToLong( &newGrid->m_nx );
ok = ok && m_entryNy->GetValue().ToLong( &newGrid->m_ny );
ok = ok && validateLongEntry(*m_entryNx, newGrid->m_nx, _("horizontal count"),
errorStrs);
ok = ok && validateLongEntry(*m_entryNy, newGrid->m_ny, _("vertical count"),
errorStrs);
newGrid->m_delta.x = DoubleValueFromString( g_UserUnit, m_entryDx->GetValue() );
newGrid->m_delta.y = DoubleValueFromString( g_UserUnit, m_entryDy->GetValue() );
@@ -216,40 +307,38 @@ void DIALOG_CREATE_ARRAY::OnOkClick( wxCommandEvent& event )
newGrid->m_offset.x = DoubleValueFromString( g_UserUnit, m_entryOffsetX->GetValue() );
newGrid->m_offset.y = DoubleValueFromString( g_UserUnit, m_entryOffsetY->GetValue() );
ok = ok && m_entryStagger->GetValue().ToLong( &newGrid->m_stagger );
ok = ok && validateLongEntry(*m_entryStagger, newGrid->m_stagger, _("stagger"),
errorStrs);
newGrid->m_stagger_rows = m_radioBoxGridStaggerType->GetSelection() == 0;
newGrid->m_horizontalThenVertical = m_radioBoxGridNumberingAxis->GetSelection() == 0;
newGrid->m_reverseNumberingAlternate = m_checkBoxGridReverseNumbering->GetValue();
newGrid->m_2dArrayNumbering = m_radioBoxGridNumberingScheme->GetSelection() != 0;
newGrid->m_shouldNumber = m_numberingEnabled;
// this is only correct if you set the choice up according to the enum size and order
ok = ok && m_choicePriAxisNumbering->GetSelection() <= NUMBERING_TYPE_MAX
&& m_choiceSecAxisNumbering->GetSelection() <= NUMBERING_TYPE_MAX;
// mind undefined casts to enums (should not be able to happen)
if( ok )
if ( m_numberingEnabled )
{
newGrid->m_priAxisNumType =
(ARRAY_NUMBERING_TYPE_T) m_choicePriAxisNumbering->GetSelection();
newGrid->m_secAxisNumType =
(ARRAY_NUMBERING_TYPE_T) m_choiceSecAxisNumbering->GetSelection();
newGrid->m_2dArrayNumbering = m_radioBoxGridNumberingScheme->GetSelection() != 0;
bool numOk = validateNumberingTypeAndOffset(
*m_entryGridPriNumberingOffset, *m_choicePriAxisNumbering,
newGrid->m_priAxisNumType, newGrid->m_numberingOffsetX,
errorStrs );
if( newGrid->m_2dArrayNumbering )
{
numOk = validateNumberingTypeAndOffset(
*m_entryGridSecNumberingOffset, *m_choiceSecAxisNumbering,
newGrid->m_secAxisNumType, newGrid->m_numberingOffsetY,
errorStrs ) && numOk;
}
ok = ok && numOk;
newGrid->m_numberingStartIsSpecified = m_rbGridStartNumberingOpt->GetSelection() == 1;
}
// Work out the offsets for the numbering
ok = ok && getNumberingOffset(
m_entryGridPriNumberingOffset->GetValue().ToStdString(),
newGrid->m_priAxisNumType, newGrid->m_numberingOffsetX );
if( newGrid->m_2dArrayNumbering )
ok = ok && getNumberingOffset(
m_entryGridSecNumberingOffset->GetValue().ToStdString(),
newGrid->m_secAxisNumType, newGrid->m_numberingOffsetY );
newGrid->m_shouldRenumber = m_rbGridStartNumberingOpt->GetSelection() == 1;
// Only use settings if all values are good
if( ok )
newSettings = newGrid;
@@ -265,13 +354,23 @@ void DIALOG_CREATE_ARRAY::OnOkClick( wxCommandEvent& event )
newCirc->m_centre.y = DoubleValueFromString( g_UserUnit, m_entryCentreY->GetValue() );
newCirc->m_angle = DoubleValueFromString( DEGREES, m_entryCircAngle->GetValue() );
ok = ok && m_entryCircCount->GetValue().ToLong( &newCirc->m_nPts );
ok = ok && validateLongEntry(*m_entryCircCount, newCirc->m_nPts,
_("point count"), errorStrs);
newCirc->m_rotateItems = m_entryRotateItemsCb->GetValue();
newCirc->m_shouldRenumber = m_rbCircStartNumberingOpt->GetSelection() == 1;
newCirc->m_numberingType = NUMBERING_NUMERIC;
ok = ok && m_entryCircNumberingStart->GetValue().ToLong( &newCirc->m_numberingOffset );
newCirc->m_shouldNumber = m_numberingEnabled;
if ( m_numberingEnabled )
{
newCirc->m_numberingStartIsSpecified = m_rbCircStartNumberingOpt->GetSelection() == 1;
newCirc->m_numberingType = NUMBERING_NUMERIC;
ok = ok && validateLongEntry(*m_entryCircNumberingStart,
newCirc->m_numberingOffset,
_("numbering start"), errorStrs);
}
// Only use settings if all values are good
if( ok )
@@ -283,43 +382,70 @@ void DIALOG_CREATE_ARRAY::OnOkClick( wxCommandEvent& event )
// If we got good settings, send them out and finish
if( newSettings )
{
delete *m_settings;
delete m_settings;
// assign pointer and ownership here
*m_settings = newSettings;
m_settings = newSettings;
ReadConfigFromControls();
EndModal( wxID_OK );
}
else
wxMessageBox( _("Bad parameters" ) );
{
wxString errorStr;
if( errorStrs.IsEmpty() )
errorStr = _("Bad parameters");
else
errorStr = boost::algorithm::join( errorStrs, "\n" );
wxMessageBox( errorStr );
}
}
void DIALOG_CREATE_ARRAY::setControlEnablement()
{
const bool renumber = m_rbGridStartNumberingOpt->GetSelection() == 1;
if ( m_numberingEnabled )
{
const bool renumber = m_rbGridStartNumberingOpt->GetSelection() == 1;
// If we're not renumbering, we can't set the numbering scheme
// or axis numbering types
m_radioBoxGridNumberingScheme->Enable( renumber );
m_labelPriAxisNumbering->Enable( renumber );
m_choicePriAxisNumbering->Enable( renumber );
// If we're not renumbering, we can't set the numbering scheme
// or axis numbering types
m_radioBoxGridNumberingScheme->Enable( renumber );
m_labelPriAxisNumbering->Enable( renumber );
m_choicePriAxisNumbering->Enable( renumber );
// Disable the secondary axis numbering option if the
// numbering scheme doesn't have two axes
const bool num2d = m_radioBoxGridNumberingScheme->GetSelection() != 0;
// Disable the secondary axis numbering option if the
// numbering scheme doesn't have two axes
const bool num2d = m_radioBoxGridNumberingScheme->GetSelection() != 0;
m_labelSecAxisNumbering->Enable( renumber && num2d );
m_choiceSecAxisNumbering->Enable( renumber && num2d );
m_labelSecAxisNumbering->Enable( renumber && num2d );
m_choiceSecAxisNumbering->Enable( renumber && num2d );
// We can only set an offset if we renumber
m_labelGridNumberingOffset->Enable( renumber );
m_entryGridPriNumberingOffset->Enable( renumber );
m_entryGridSecNumberingOffset->Enable( renumber && num2d );
// We can only set an offset if we renumber
m_labelGridNumberingOffset->Enable( renumber );
m_entryGridPriNumberingOffset->Enable( renumber );
m_entryGridSecNumberingOffset->Enable( renumber && num2d );
m_entryCircNumberingStart->Enable( m_rbCircStartNumberingOpt->GetSelection() == 1 );
m_entryCircNumberingStart->Enable( m_rbCircStartNumberingOpt->GetSelection() == 1 );
}
else
{
// grid
m_rbGridStartNumberingOpt->Enable( false );
m_checkBoxGridReverseNumbering->Enable( false );
m_radioBoxGridNumberingAxis->Enable( false );
m_radioBoxGridNumberingScheme->Enable( false );
m_choiceSecAxisNumbering->Enable( false );
m_choicePriAxisNumbering->Enable( false );
m_entryGridPriNumberingOffset->Enable( false );
m_entryGridSecNumberingOffset->Enable( false );
// circular
m_rbCircStartNumberingOpt->Enable( false );
m_entryCircNumberingStart->Enable( false );
}
}
@@ -340,16 +466,16 @@ void DIALOG_CREATE_ARRAY::calculateCircularArrayProperties()
// ARRAY OPTION implementation functions --------------------------------------
std::string DIALOG_CREATE_ARRAY::ARRAY_OPTIONS::getCoordinateNumber( int n,
wxString DIALOG_CREATE_ARRAY::ARRAY_OPTIONS::getCoordinateNumber( int n,
ARRAY_NUMBERING_TYPE_T type )
{
std::string itemNum;
const std::string& alphabet = alphabetFromNumberingScheme( type );
wxString itemNum;
const wxString& alphabet = alphabetFromNumberingScheme( type );
const bool nonUnitColsStartAt0 = schemeNonUnitColsStartAt0( type );
bool firstRound = true;
int radix = alphabet.length();
int radix = alphabet.Length();
do {
int modN = n % radix;
@@ -480,9 +606,5 @@ void DIALOG_CREATE_ARRAY::ARRAY_CIRCULAR_OPTIONS::TransformItem( int n, BOARD_IT
wxString DIALOG_CREATE_ARRAY::ARRAY_CIRCULAR_OPTIONS::GetItemNumber( int aN ) const
{
// The first new pad has aN number == 1, not 0
if( m_shouldRenumber ) // numbering pad from initial user value
return getCoordinateNumber( aN - 1 + m_numberingOffset, m_numberingType );
else // numbering pad from inital pad number
return getCoordinateNumber( aN + m_numberingOffset, m_numberingType );
return getCoordinateNumber( aN + m_numberingOffset, m_numberingType );
}