From 6e7b22904e2aa9bdda13d2b9e1159f51f1e556ff Mon Sep 17 00:00:00 2001
From: John Beard <john.j.beard@gmail.com>
Date: Thu, 16 Jan 2025 18:54:18 +0800
Subject: [PATCH] Array tool: when changing axis numbering, default to valid
 numbering

Otherwise, when you change the axis numbering type, and don't update
the start offset string, you get an error on dialog save. Instead,
if the number isn't valid, change it to a valid one.
---
 include/array_axis.h                        |  8 +++++
 pcbnew/dialogs/dialog_create_array.cpp      | 38 +++++++++++++++++++++
 pcbnew/dialogs/dialog_create_array.h        |  7 ++--
 pcbnew/dialogs/dialog_create_array_base.cpp |  6 ++++
 pcbnew/dialogs/dialog_create_array_base.fbp | 19 ++++++-----
 pcbnew/dialogs/dialog_create_array_base.h   |  1 +
 6 files changed, 69 insertions(+), 10 deletions(-)

diff --git a/include/array_axis.h b/include/array_axis.h
index 493415a391..8bd7fafcb7 100644
--- a/include/array_axis.h
+++ b/include/array_axis.h
@@ -54,6 +54,14 @@ public:
         NUMBERING_ALPHA_FULL,      ///< Full 26-character alphabet
     };
 
+    /**
+     * Check if a numbering type is a numeric type.
+     */
+    static bool TypeIsNumeric( NUMBERING_TYPE type )
+    {
+        return type == NUMBERING_NUMERIC || type == NUMBERING_HEX;
+    };
+
     ARRAY_AXIS();
 
     /**
diff --git a/pcbnew/dialogs/dialog_create_array.cpp b/pcbnew/dialogs/dialog_create_array.cpp
index 6e6b451edd..1f5a099864 100644
--- a/pcbnew/dialogs/dialog_create_array.cpp
+++ b/pcbnew/dialogs/dialog_create_array.cpp
@@ -262,6 +262,44 @@ void DIALOG_CREATE_ARRAY::OnSelectCenterButton( wxCommandEvent& event )
 }
 
 
+void DIALOG_CREATE_ARRAY::OnAxisNumberingChange( wxCommandEvent& aEvent )
+{
+    // On an alphabet change, make sure the offset control is valid by default.
+
+    const unsigned newAlphabet = aEvent.GetSelection();
+
+    wxCHECK( newAlphabet >= 0 && newAlphabet < numberingTypeData.size(), /* void */ );
+
+    const ARRAY_AXIS::NUMBERING_TYPE numberingType =
+            numberingTypeData[newAlphabet].m_numbering_type;
+
+    wxTextCtrl* matchingTextCtrl = nullptr;
+
+    if( aEvent.GetEventObject() == m_choicePriAxisNumbering )
+        matchingTextCtrl = m_entryGridPriNumberingOffset;
+    else if( aEvent.GetEventObject() == m_choiceSecAxisNumbering )
+        matchingTextCtrl = m_entryGridSecNumberingOffset;
+    else if( aEvent.GetEventObject() == m_choiceCircNumbering )
+        matchingTextCtrl = m_entryCircNumberingStart;
+
+    wxCHECK( matchingTextCtrl, /* void */ );
+
+    ARRAY_AXIS dummyAxis;
+    dummyAxis.SetAxisType( numberingType );
+
+    // If the text control has a valid value for the new alphabet, keep it
+    // else reset to the first value in the new alphabet.
+
+    const bool isAlreadyOK = dummyAxis.SetOffset( matchingTextCtrl->GetValue() );
+
+    if( !isAlreadyOK )
+    {
+        dummyAxis.SetOffset( ARRAY_AXIS::TypeIsNumeric( numberingType ) ? 1 : 0 );
+        matchingTextCtrl->SetValue( dummyAxis.GetItemNumber( 0 ) );
+    }
+}
+
+
 // Implement the RECEIVER interface for the callback from the TOOL
 void DIALOG_CREATE_ARRAY::UpdatePickedItem( const EDA_ITEM* aItem )
 {
diff --git a/pcbnew/dialogs/dialog_create_array.h b/pcbnew/dialogs/dialog_create_array.h
index 78e3022de8..ecb0dea093 100644
--- a/pcbnew/dialogs/dialog_create_array.h
+++ b/pcbnew/dialogs/dialog_create_array.h
@@ -58,10 +58,13 @@ public:
 
 private:
     // Event callbacks
-    void OnParameterChanged( wxCommandEvent& event ) override;
+    void OnParameterChanged( wxCommandEvent& aEvent ) override;
 
     // Center select buttons
-    void OnSelectCenterButton( wxCommandEvent& event ) override;
+    void OnSelectCenterButton( wxCommandEvent& aEvent ) override;
+
+    // Axis numbering alphabet
+    void OnAxisNumberingChange( wxCommandEvent& aEvent ) override;
 
     // Internal callback handlers
     void setControlEnablement();
diff --git a/pcbnew/dialogs/dialog_create_array_base.cpp b/pcbnew/dialogs/dialog_create_array_base.cpp
index 3949463185..9bec7a79b5 100644
--- a/pcbnew/dialogs/dialog_create_array_base.cpp
+++ b/pcbnew/dialogs/dialog_create_array_base.cpp
@@ -516,6 +516,8 @@ DIALOG_CREATE_ARRAY_BASE::DIALOG_CREATE_ARRAY_BASE( wxWindow* parent, wxWindowID
 	m_entryStagger->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
 	m_rbGridStartNumberingOpt->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, 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::OnAxisNumberingChange ), NULL, this );
+	m_choiceSecAxisNumbering->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnAxisNumberingChange ), 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_btnSelectCenterPoint->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnSelectCenterButton ), NULL, this );
@@ -524,6 +526,7 @@ DIALOG_CREATE_ARRAY_BASE::DIALOG_CREATE_ARRAY_BASE( wxWindow* parent, wxWindowID
 	m_entryCircAngle->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
 	m_entryCircCount->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
 	m_rbCircStartNumberingOpt->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
+	m_choiceCircNumbering->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnAxisNumberingChange ), NULL, this );
 }
 
 DIALOG_CREATE_ARRAY_BASE::~DIALOG_CREATE_ARRAY_BASE()
@@ -539,6 +542,8 @@ DIALOG_CREATE_ARRAY_BASE::~DIALOG_CREATE_ARRAY_BASE()
 	m_entryStagger->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
 	m_rbGridStartNumberingOpt->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, 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::OnAxisNumberingChange ), NULL, this );
+	m_choiceSecAxisNumbering->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnAxisNumberingChange ), 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_btnSelectCenterPoint->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnSelectCenterButton ), NULL, this );
@@ -547,5 +552,6 @@ DIALOG_CREATE_ARRAY_BASE::~DIALOG_CREATE_ARRAY_BASE()
 	m_entryCircAngle->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
 	m_entryCircCount->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
 	m_rbCircStartNumberingOpt->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
+	m_choiceCircNumbering->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnAxisNumberingChange ), NULL, this );
 
 }
diff --git a/pcbnew/dialogs/dialog_create_array_base.fbp b/pcbnew/dialogs/dialog_create_array_base.fbp
index 683cd7d668..8200386787 100644
--- a/pcbnew/dialogs/dialog_create_array_base.fbp
+++ b/pcbnew/dialogs/dialog_create_array_base.fbp
@@ -1741,11 +1741,11 @@
                           </object>
                         </object>
                       </object>
-                      <object class="sizeritem" expanded="false">
+                      <object class="sizeritem" expanded="true">
                         <property name="border">5</property>
                         <property name="flag">wxEXPAND</property>
                         <property name="proportion">1</property>
-                        <object class="wxPanel" expanded="false">
+                        <object class="wxPanel" expanded="true">
                           <property name="BottomDockable">1</property>
                           <property name="LeftDockable">1</property>
                           <property name="RightDockable">1</property>
@@ -1797,16 +1797,16 @@
                           <property name="window_extra_style"></property>
                           <property name="window_name"></property>
                           <property name="window_style">wxTAB_TRAVERSAL</property>
-                          <object class="wxBoxSizer" expanded="false">
+                          <object class="wxBoxSizer" expanded="true">
                             <property name="minimum_size"></property>
                             <property name="name">bSizer15</property>
                             <property name="orient">wxVERTICAL</property>
                             <property name="permission">none</property>
-                            <object class="sizeritem" expanded="false">
+                            <object class="sizeritem" expanded="true">
                               <property name="border">10</property>
                               <property name="flag">wxEXPAND|wxLEFT</property>
                               <property name="proportion">1</property>
-                              <object class="wxBoxSizer" expanded="false">
+                              <object class="wxBoxSizer" expanded="true">
                                 <property name="minimum_size"></property>
                                 <property name="name">m_gridPadNumberingSizer</property>
                                 <property name="orient">wxVERTICAL</property>
@@ -2204,6 +2204,7 @@
                                     <property name="window_extra_style"></property>
                                     <property name="window_name"></property>
                                     <property name="window_style"></property>
+                                    <event name="OnChoice">OnAxisNumberingChange</event>
                                   </object>
                                 </object>
                                 <object class="sizeritem" expanded="false">
@@ -2331,6 +2332,7 @@
                                     <property name="window_extra_style"></property>
                                     <property name="window_name"></property>
                                     <property name="window_style"></property>
+                                    <event name="OnChoice">OnAxisNumberingChange</event>
                                   </object>
                                 </object>
                                 <object class="sizeritem" expanded="false">
@@ -3935,7 +3937,7 @@
                           <property name="window_extra_style"></property>
                           <property name="window_name"></property>
                           <property name="window_style">wxTAB_TRAVERSAL</property>
-                          <object class="wxBoxSizer" expanded="false">
+                          <object class="wxBoxSizer" expanded="true">
                             <property name="minimum_size"></property>
                             <property name="name">bSizer13</property>
                             <property name="orient">wxHORIZONTAL</property>
@@ -3950,11 +3952,11 @@
                                 <property name="width">10</property>
                               </object>
                             </object>
-                            <object class="sizeritem" expanded="false">
+                            <object class="sizeritem" expanded="true">
                               <property name="border">5</property>
                               <property name="flag">wxEXPAND</property>
                               <property name="proportion">1</property>
-                              <object class="wxStaticBoxSizer" expanded="false">
+                              <object class="wxStaticBoxSizer" expanded="true">
                                 <property name="id">wxID_ANY</property>
                                 <property name="label">Numbering Options</property>
                                 <property name="minimum_size"></property>
@@ -4155,6 +4157,7 @@
                                     <property name="window_extra_style"></property>
                                     <property name="window_name"></property>
                                     <property name="window_style"></property>
+                                    <event name="OnChoice">OnAxisNumberingChange</event>
                                   </object>
                                 </object>
                                 <object class="sizeritem" expanded="false">
diff --git a/pcbnew/dialogs/dialog_create_array_base.h b/pcbnew/dialogs/dialog_create_array_base.h
index 7fcd636296..d107574dfb 100644
--- a/pcbnew/dialogs/dialog_create_array_base.h
+++ b/pcbnew/dialogs/dialog_create_array_base.h
@@ -121,6 +121,7 @@ class DIALOG_CREATE_ARRAY_BASE : public DIALOG_SHIM
 		// Virtual event handlers, override them in your derived class
 		virtual void OnClose( wxCloseEvent& event ) { event.Skip(); }
 		virtual void OnParameterChanged( wxCommandEvent& event ) { event.Skip(); }
+		virtual void OnAxisNumberingChange( wxCommandEvent& event ) { event.Skip(); }
 		virtual void OnSelectCenterButton( wxCommandEvent& event ) { event.Skip(); }