← Back to team overview

kicad-developers team mailing list archive

[PATCH] Add error checking to array create dialog

 

Hey

Currently array create dialog doesn't give any errors if some fields are invalid, it just doesn't do anything. This patch adds error checking to array create dialog which informs the user about the invalid parameters with a message box.

Other fixes:
* Change the numbering start fields to default value if alphabet is changed and numbering start isn't found in the alphabet. * Avoid hang when creating arrays with negative count. This could also be fixed in the code that generates the array.
* Use getNumberingOffset also for circular arrays.

Henrik Forstén
=== modified file 'pcbnew/dialogs/dialog_create_array.cpp'
--- pcbnew/dialogs/dialog_create_array.cpp	2015-04-09 23:41:08 +0000
+++ pcbnew/dialogs/dialog_create_array.cpp	2015-04-19 06:47:27 +0000
@@ -32,6 +32,11 @@
 
 #include "dialog_create_array.h"
 
+static const std::string& alphabetFromNumberingScheme(
+        DIALOG_CREATE_ARRAY::ARRAY_NUMBERING_TYPE_T type );
+static bool getNumberingOffset( const std::string& str,
+        DIALOG_CREATE_ARRAY::ARRAY_NUMBERING_TYPE_T type,
+        int& offsetToFill );
 
 // initialise statics
 DIALOG_CREATE_ARRAY::CREATE_ARRAY_DIALOG_ENTRIES DIALOG_CREATE_ARRAY::m_options;
@@ -130,6 +135,57 @@
     {
         calculateCircularArrayProperties();
     }
+    // If alphabet was changed, check that start of numbering is in the
+    // alphabet. If not set the default value.
+    if ( evObj == m_choicePriAxisNumbering || evObj == m_choiceSecAxisNumbering )
+    {
+        DIALOG_CREATE_ARRAY::ARRAY_NUMBERING_TYPE_T priAxisNumType, secAxisNumType;
+
+        bool ok = m_choicePriAxisNumbering->GetSelection() < NUMBERING_TYPE_Max
+             && m_choiceSecAxisNumbering->GetSelection() < NUMBERING_TYPE_Max;
+
+        if( !ok )
+        {
+            return;
+        }
+
+        priAxisNumType =
+            (ARRAY_NUMBERING_TYPE_T) m_choicePriAxisNumbering->GetSelection();
+        secAxisNumType =
+            (ARRAY_NUMBERING_TYPE_T) m_choiceSecAxisNumbering->GetSelection();
+
+        int dummy;
+
+        // Check primary axis numbering
+        if ( !getNumberingOffset(
+                m_entryGridPriNumberingOffset->GetValue().ToStdString(),
+                priAxisNumType, dummy ) )
+        {
+            const std::string alphabet = alphabetFromNumberingScheme( priAxisNumType );
+            if (alphabet.length() > 0)
+            {
+                wxString start = alphabet[0];
+                if ( start == "0" )
+                    start = "1";
+                m_entryGridPriNumberingOffset->SetValue( start );
+            }
+        }
+
+        // Secondary axis
+        if ( !getNumberingOffset(
+                m_entryGridSecNumberingOffset->GetValue().ToStdString(),
+                secAxisNumType, dummy ) )
+        {
+            const std::string alphabet = alphabetFromNumberingScheme( secAxisNumType );
+            if (alphabet.length() > 0)
+            {
+                wxString start = alphabet[0];
+                if ( start == "0" )
+                    start = "1";
+                m_entryGridSecNumberingOffset->SetValue( start );
+            }
+        }
+    }
 }
 
 
@@ -218,18 +274,35 @@
 void DIALOG_CREATE_ARRAY::OnOkClick( wxCommandEvent& event )
 {
     ARRAY_OPTIONS* newSettings = NULL;
+    ARRAY_GRID_OPTIONS* newGrid;
+    ARRAY_CIRCULAR_OPTIONS* newCirc;
 
     const wxWindow* page = m_gridTypeNotebook->GetCurrentPage();
 
+    UTF8 msg;
+
     if( page == m_gridPanel )
     {
-        ARRAY_GRID_OPTIONS* newGrid = new ARRAY_GRID_OPTIONS();
+        newGrid = new ARRAY_GRID_OPTIONS();
         bool ok = true;
 
         // ints
         ok  = ok && m_entryNx->GetValue().ToLong( &newGrid->m_nx );
+
+        if( !ok || newGrid->m_nx < 0 )
+        {
+            msg = StrPrintf("Invalid x count");
+            goto grid_err;
+        }
+
         ok  = ok && m_entryNy->GetValue().ToLong( &newGrid->m_ny );
 
+        if( !ok || newGrid->m_ny < 0 )
+        {
+            msg = StrPrintf("Invalid y count");
+            goto grid_err;
+        }
+
         newGrid->m_delta.x = DoubleValueFromString( g_UserUnit, m_entryDx->GetValue() );
         newGrid->m_delta.y = DoubleValueFromString( g_UserUnit, m_entryDy->GetValue() );
 
@@ -238,6 +311,12 @@
 
         ok = ok && m_entryStagger->GetValue().ToLong( &newGrid->m_stagger );
 
+        if( !ok )
+        {
+            msg = StrPrintf("Invalid stagger value");
+            goto grid_err;
+        }
+
         newGrid->m_stagger_rows = m_radioBoxGridStaggerType->GetSelection() == 0;
 
         newGrid->m_horizontalThenVertical = m_radioBoxGridNumberingAxis->GetSelection() == 0;
@@ -257,28 +336,51 @@
             newGrid->m_secAxisNumType =
                 (ARRAY_NUMBERING_TYPE_T) m_choiceSecAxisNumbering->GetSelection();
         }
+        else
+        {
+            msg = StrPrintf("Invalid primary or secondary axis numbering");
+            goto grid_err;
+        }
 
         // Work out the offsets for the numbering
         ok = ok && getNumberingOffset(
                 m_entryGridPriNumberingOffset->GetValue().ToStdString(),
                 newGrid->m_priAxisNumType, newGrid->m_numberingOffsetX );
 
+        if ( !ok )
+        {
+            msg = StrPrintf("Primary axis numbering start not found in the primary axis alphabet");
+            goto grid_err;
+        }
+
         if( newGrid->m_2dArrayNumbering )
             ok = ok && getNumberingOffset(
                     m_entryGridSecNumberingOffset->GetValue().ToStdString(),
                     newGrid->m_secAxisNumType, newGrid->m_numberingOffsetY );
 
+        if ( !ok )
+        {
+            msg = StrPrintf("Secondary axis numbering start not found in the secondary axis alphabet");
+            goto grid_err;
+        }
+
         newGrid->m_shouldRenumber = m_checkBoxGridRestartNumbering->GetValue();
 
         // Only use settings if all values are good
         if( ok )
+        {
             newSettings = newGrid;
+        }
         else
-            delete newGrid;
+        {
+            msg = StrPrintf("Failed to generate array");
+            goto grid_err;
+        }
+
     }
     else if( page == m_circularPanel )
     {
-        ARRAY_CIRCULAR_OPTIONS* newCirc = new ARRAY_CIRCULAR_OPTIONS();
+        newCirc = new ARRAY_CIRCULAR_OPTIONS();
         bool ok = true;
 
         newCirc->m_centre.x = DoubleValueFromString( g_UserUnit, m_entryCentreX->GetValue() );
@@ -287,6 +389,18 @@
         newCirc->m_angle = DoubleValueFromString( DEGREES, m_entryCircAngle->GetValue() );
         ok = ok && m_entryCircCount->GetValue().ToLong( &newCirc->m_nPts );
 
+        if ( !ok )
+        {
+            msg = StrPrintf("Invalid count");
+            goto circ_err;
+        }
+
+        if ( newCirc->m_nPts < 0 )
+        {
+            msg = StrPrintf("Count must be positive");
+            goto circ_err;
+        }
+
         newCirc->m_rotateItems = m_entryRotateItemsCb->GetValue();
 
         newCirc->m_shouldRenumber = m_checkBoxCircRestartNumbering->GetValue();
@@ -296,16 +410,30 @@
 
         // Mind undefined casts to enums (should not be able to happen)
         if( ok )
+        {
             newCirc->m_numberingType =
                 (ARRAY_NUMBERING_TYPE_T) m_choiceCircNumberingType->GetSelection();
+        }
+        else
+        {
+            msg = StrPrintf("Invalid numbering");
+            goto circ_err;
+        }
 
-        ok = ok && m_entryCircNumberingStart->GetValue().ToLong( &newCirc->m_numberingOffset );
+        ok = ok && getNumberingOffset(
+                m_entryCircNumberingStart->GetValue().ToStdString(),
+                newCirc->m_numberingType, newCirc->m_numberingOffset );
 
         // Only use settings if all values are good
         if( ok )
+        {
             newSettings = newCirc;
+        }
         else
-            delete newCirc;
+        {
+            msg = StrPrintf("Invalid numbering offset");
+            goto circ_err;
+        }
     }
 
     // If we got good settings, send them out and finish
@@ -320,6 +448,17 @@
 
         EndModal( CREATE_ARRAY_OK );
     }
+
+    return;
+
+grid_err:
+            wxMessageBox( msg );
+            delete newGrid;
+            return;
+circ_err:
+            wxMessageBox( msg );
+            delete newCirc;
+            return;
 }
 
 

=== modified file 'pcbnew/dialogs/dialog_create_array.h'
--- pcbnew/dialogs/dialog_create_array.h	2015-04-05 09:52:41 +0000
+++ pcbnew/dialogs/dialog_create_array.h	2015-04-19 06:40:48 +0000
@@ -286,7 +286,7 @@
         wxPoint m_centre;
         bool m_rotateItems;
         ARRAY_NUMBERING_TYPE_T m_numberingType;
-        long m_numberingOffset;
+        int m_numberingOffset;
 
         void        TransformItem( int n, BOARD_ITEM* item, const wxPoint& rotPoint ) const;    // override virtual
         int         GetArraySize() const;                                                       // override virtual

=== modified file 'pcbnew/dialogs/dialog_create_array_base.cpp'
--- pcbnew/dialogs/dialog_create_array_base.cpp	2015-04-05 09:52:41 +0000
+++ pcbnew/dialogs/dialog_create_array_base.cpp	2015-04-19 06:01:51 +0000
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version Jun  5 2014)
+// C++ code generated with wxFormBuilder (version Nov 10 2014)
 // http://www.wxformbuilder.org/
 //
 // PLEASE DO "NOT" EDIT THIS FILE!
@@ -310,6 +310,8 @@
 	m_entryStagger->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
 	m_checkBoxGridRestartNumbering->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
 	m_radioBoxGridNumberingScheme->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
+	m_choicePriAxisNumbering->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
+	m_choiceSecAxisNumbering->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
 	m_entryCentreX->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
 	m_entryCentreY->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
 	m_entryCircAngle->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
@@ -331,6 +333,8 @@
 	m_entryStagger->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
 	m_checkBoxGridRestartNumbering->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
 	m_radioBoxGridNumberingScheme->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
+	m_choicePriAxisNumbering->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
+	m_choiceSecAxisNumbering->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
 	m_entryCentreX->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
 	m_entryCentreY->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
 	m_entryCircAngle->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );

=== modified file 'pcbnew/dialogs/dialog_create_array_base.fbp'
--- pcbnew/dialogs/dialog_create_array_base.fbp	2015-04-05 09:52:41 +0000
+++ pcbnew/dialogs/dialog_create_array_base.fbp	2015-04-19 06:01:49 +0000
@@ -2569,7 +2569,7 @@
                                                     <property name="window_name"></property>
                                                     <property name="window_style"></property>
                                                     <event name="OnChar"></event>
-                                                    <event name="OnChoice"></event>
+                                                    <event name="OnChoice">OnParameterChanged</event>
                                                     <event name="OnEnterWindow"></event>
                                                     <event name="OnEraseBackground"></event>
                                                     <event name="OnKeyDown"></event>
@@ -2740,7 +2740,7 @@
                                                     <property name="window_name"></property>
                                                     <property name="window_style"></property>
                                                     <event name="OnChar"></event>
-                                                    <event name="OnChoice"></event>
+                                                    <event name="OnChoice">OnParameterChanged</event>
                                                     <event name="OnEnterWindow"></event>
                                                     <event name="OnEraseBackground"></event>
                                                     <event name="OnKeyDown"></event>

=== modified file 'pcbnew/dialogs/dialog_create_array_base.h'
--- pcbnew/dialogs/dialog_create_array_base.h	2015-04-05 09:52:41 +0000
+++ pcbnew/dialogs/dialog_create_array_base.h	2015-04-19 05:41:36 +0000
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version Jun  5 2014)
+// C++ code generated with wxFormBuilder (version Nov 10 2014)
 // http://www.wxformbuilder.org/
 //
 // PLEASE DO "NOT" EDIT THIS FILE!