@@ -30,6 +30,13 @@ public class RandomGraphDialog extends JDialog {
3030
3131 private static final long serialVersionUID = 1L ;
3232
33+ // ── Model name constants (avoid magic strings) ────────────────────────
34+ static final String MODEL_ERDOS_RENYI = "erdos-renyi" ;
35+ static final String MODEL_BARABASI = "barabasi-albert" ;
36+ static final String MODEL_WATTS_STROGATZ = "watts-strogatz" ;
37+ static final String MODEL_RANDOM_REGULAR = "random-regular" ;
38+ static final String MODEL_GRID = "grid" ;
39+
3340 private Graph <String , Edge > generatedGraph = null ;
3441
3542 private final JComboBox <String > modelCombo ;
@@ -41,7 +48,8 @@ public class RandomGraphDialog extends JDialog {
4148 private final JSpinner rowsSpinner ;
4249 private final JSpinner colsSpinner ;
4350
44- private final JLabel pLabel , mLabel , kLabel , betaLabel , rowsLabel , colsLabel ;
51+ private final JLabel nLabel , pLabel , mLabel , kLabel , betaLabel , rowsLabel , colsLabel ;
52+ private final JLabel descLabel ;
4553
4654 public RandomGraphDialog (Frame owner ) {
4755 super (owner , "Random Graph Generator" , true );
@@ -60,63 +68,24 @@ public RandomGraphDialog(Frame owner) {
6068 c .gridx = 1 ;
6169 String [] models = RandomGraphGenerator .catalog ().keySet ().toArray (new String [0 ]);
6270 modelCombo = new JComboBox <>(models );
63- modelCombo .addActionListener (e -> updateVisibility ());
6471 form .add (modelCombo , c );
6572
66- // n (vertices)
67- c .gridx = 0 ; c .gridy = 1 ;
68- form .add (new JLabel ("Vertices (n):" ), c );
69- c .gridx = 1 ;
70- nSpinner = new JSpinner (new SpinnerNumberModel (20 , 2 , 500 , 1 ));
71- form .add (nSpinner , c );
72-
73- // p (edge probability)
74- c .gridx = 0 ; c .gridy = 2 ;
75- pLabel = new JLabel ("Edge prob (p):" );
76- form .add (pLabel , c );
77- c .gridx = 1 ;
78- pSpinner = new JSpinner (new SpinnerNumberModel (0.15 , 0.01 , 1.0 , 0.01 ));
79- form .add (pSpinner , c );
80-
81- // m (edges per new vertex)
82- c .gridx = 0 ; c .gridy = 3 ;
83- mLabel = new JLabel ("Edges/vertex (m):" );
84- form .add (mLabel , c );
85- c .gridx = 1 ;
86- mSpinner = new JSpinner (new SpinnerNumberModel (2 , 1 , 50 , 1 ));
87- form .add (mSpinner , c );
88-
89- // k (degree / neighbors)
90- c .gridx = 0 ; c .gridy = 4 ;
91- kLabel = new JLabel ("Degree (k):" );
92- form .add (kLabel , c );
93- c .gridx = 1 ;
94- kSpinner = new JSpinner (new SpinnerNumberModel (4 , 2 , 50 , 1 ));
95- form .add (kSpinner , c );
96-
97- // beta (rewiring)
98- c .gridx = 0 ; c .gridy = 5 ;
99- betaLabel = new JLabel ("Rewire (β):" );
100- form .add (betaLabel , c );
101- c .gridx = 1 ;
102- betaSpinner = new JSpinner (new SpinnerNumberModel (0.3 , 0.0 , 1.0 , 0.05 ));
103- form .add (betaSpinner , c );
104-
105- // rows
106- c .gridx = 0 ; c .gridy = 6 ;
107- rowsLabel = new JLabel ("Rows:" );
108- form .add (rowsLabel , c );
109- c .gridx = 1 ;
110- rowsSpinner = new JSpinner (new SpinnerNumberModel (5 , 1 , 50 , 1 ));
111- form .add (rowsSpinner , c );
112-
113- // cols
114- c .gridx = 0 ; c .gridy = 7 ;
115- colsLabel = new JLabel ("Columns:" );
116- form .add (colsLabel , c );
117- c .gridx = 1 ;
118- colsSpinner = new JSpinner (new SpinnerNumberModel (5 , 1 , 50 , 1 ));
119- form .add (colsSpinner , c );
73+ // Parameter rows — each builds (label, spinner) pair and returns them.
74+ nSpinner = new JSpinner (new SpinnerNumberModel (20 , 2 , 500 , 1 ));
75+ pSpinner = new JSpinner (new SpinnerNumberModel (0.15 , 0.01 , 1.0 , 0.01 ));
76+ mSpinner = new JSpinner (new SpinnerNumberModel (2 , 1 , 50 , 1 ));
77+ kSpinner = new JSpinner (new SpinnerNumberModel (4 , 2 , 50 , 1 ));
78+ betaSpinner = new JSpinner (new SpinnerNumberModel (0.3 , 0.0 , 1.0 , 0.05 ));
79+ rowsSpinner = new JSpinner (new SpinnerNumberModel (5 , 1 , 50 , 1 ));
80+ colsSpinner = new JSpinner (new SpinnerNumberModel (5 , 1 , 50 , 1 ));
81+
82+ nLabel = addSpinnerRow (form , c , 1 , "Vertices (n):" , nSpinner );
83+ pLabel = addSpinnerRow (form , c , 2 , "Edge prob (p):" , pSpinner );
84+ mLabel = addSpinnerRow (form , c , 3 , "Edges/vertex (m):" , mSpinner );
85+ kLabel = addSpinnerRow (form , c , 4 , "Neighbors (k):" , kSpinner );
86+ betaLabel = addSpinnerRow (form , c , 5 , "Rewire (\u03B2 ):" , betaSpinner );
87+ rowsLabel = addSpinnerRow (form , c , 6 , "Rows:" , rowsSpinner );
88+ colsLabel = addSpinnerRow (form , c , 7 , "Columns:" , colsSpinner );
12089
12190 add (form , BorderLayout .CENTER );
12291
@@ -139,46 +108,80 @@ public RandomGraphDialog(Frame owner) {
139108 btnPanel .add (cancelBtn );
140109 add (btnPanel , BorderLayout .SOUTH );
141110
142- // Description label
143- JLabel desc = new JLabel ();
144- desc .setBorder (BorderFactory .createEmptyBorder (8 , 12 , 4 , 12 ));
145- desc .setFont (desc .getFont ().deriveFont (Font .ITALIC , 11f ));
146- Map < String , String > catalog = RandomGraphGenerator . catalog ( );
147- modelCombo . addActionListener ( e -> {
148- String sel = ( String ) modelCombo . getSelectedItem ();
149- desc . setText ( "<html>" + catalog . getOrDefault ( sel , "" ) + "</html>" );
150- });
151- desc . setText ( "<html>" + catalog . getOrDefault ( models [ 0 ], "" ) + "</html>" );
152- add ( desc , BorderLayout . NORTH );
111+ // Description label (driven by the same listener as visibility)
112+ descLabel = new JLabel ();
113+ descLabel .setBorder (BorderFactory .createEmptyBorder (8 , 12 , 4 , 12 ));
114+ descLabel .setFont (descLabel .getFont ().deriveFont (Font .ITALIC , 11f ));
115+ add ( descLabel , BorderLayout . NORTH );
116+
117+ // Single listener: previously the dialog registered two separate
118+ // ActionListeners on modelCombo (one for visibility, one for the
119+ // description label). Consolidated into one to keep update logic
120+ // atomic and avoid ordering surprises if either ever throws.
121+ modelCombo . addActionListener ( e -> onModelChanged () );
153122
154- updateVisibility ();
123+ onModelChanged (); // initial sync
155124 pack ();
156125 setLocationRelativeTo (owner );
157126 }
158127
159- private void updateVisibility () {
128+ /**
129+ * Adds a (label, spinner) row to {@code form} at the given grid row and
130+ * returns the created label so callers can toggle its visibility.
131+ *
132+ * <p>Extracted to remove the seven nearly-identical
133+ * "set gridx/y, new JLabel(text), set gridx, add(spinner)" blocks in
134+ * the original constructor.</p>
135+ */
136+ private static JLabel addSpinnerRow (JPanel form , GridBagConstraints c ,
137+ int gridY , String text , JSpinner spinner ) {
138+ JLabel label = new JLabel (text );
139+ c .gridx = 0 ; c .gridy = gridY ;
140+ form .add (label , c );
141+ c .gridx = 1 ;
142+ form .add (spinner , c );
143+ return label ;
144+ }
145+
146+ /**
147+ * Reacts to a model-selection change: updates which parameter rows are
148+ * visible and refreshes the description text. Package-private so unit
149+ * tests can drive it directly without firing Swing events.
150+ */
151+ void onModelChanged () {
160152 String model = (String ) modelCombo .getSelectedItem ();
161- boolean showP = "erdos-renyi" .equals (model );
162- boolean showM = "barabasi-albert" .equals (model );
163- boolean showK = "watts-strogatz" .equals (model ) || "random-regular" .equals (model );
164- boolean showBeta = "watts-strogatz" .equals (model );
165- boolean showGrid = "grid" .equals (model );
166- boolean showN = !showGrid ;
167-
168- pLabel .setVisible (showP ); pSpinner .setVisible (showP );
169- mLabel .setVisible (showM ); mSpinner .setVisible (showM );
170- kLabel .setVisible (showK ); kSpinner .setVisible (showK );
171- betaLabel .setVisible (showBeta ); betaSpinner .setVisible (showBeta );
172- rowsLabel .setVisible (showGrid ); rowsSpinner .setVisible (showGrid );
173- colsLabel .setVisible (showGrid ); colsSpinner .setVisible (showGrid );
174- nSpinner .setVisible (showN );
175-
176- // Update k label text
177- if ("random-regular" .equals (model )) {
178- kLabel .setText ("Degree (k):" );
179- } else {
180- kLabel .setText ("Neighbors (k):" );
181- }
153+ applyVisibility (model );
154+ applyDescription (model );
155+ }
156+
157+ private void applyVisibility (String model ) {
158+ boolean showP = MODEL_ERDOS_RENYI .equals (model );
159+ boolean showM = MODEL_BARABASI .equals (model );
160+ boolean showK = MODEL_WATTS_STROGATZ .equals (model ) || MODEL_RANDOM_REGULAR .equals (model );
161+ boolean showBeta = MODEL_WATTS_STROGATZ .equals (model );
162+ boolean showGrid = MODEL_GRID .equals (model );
163+ boolean showN = !showGrid ;
164+
165+ setRowVisible (nLabel , nSpinner , showN );
166+ setRowVisible (pLabel , pSpinner , showP );
167+ setRowVisible (mLabel , mSpinner , showM );
168+ setRowVisible (kLabel , kSpinner , showK );
169+ setRowVisible (betaLabel , betaSpinner , showBeta );
170+ setRowVisible (rowsLabel , rowsSpinner , showGrid );
171+ setRowVisible (colsLabel , colsSpinner , showGrid );
172+
173+ // k-row label depends on which model is showing it
174+ kLabel .setText (MODEL_RANDOM_REGULAR .equals (model ) ? "Degree (k):" : "Neighbors (k):" );
175+ }
176+
177+ private static void setRowVisible (JLabel label , JSpinner spinner , boolean visible ) {
178+ label .setVisible (visible );
179+ spinner .setVisible (visible );
180+ }
181+
182+ private void applyDescription (String model ) {
183+ String desc = RandomGraphGenerator .catalog ().getOrDefault (model , "" );
184+ descLabel .setText ("<html>" + desc + "</html>" );
182185 }
183186
184187 private Graph <String , Edge > buildGraph () {
@@ -198,4 +201,35 @@ private Graph<String, Edge> buildGraph() {
198201 public Graph <String , Edge > getGeneratedGraph () {
199202 return generatedGraph ;
200203 }
204+
205+ // ── Package-private hooks for tests ───────────────────────────────────
206+
207+ /** @return the currently selected model name */
208+ String getSelectedModel () {
209+ return (String ) modelCombo .getSelectedItem ();
210+ }
211+
212+ /** Selects a model by name; intended for tests. */
213+ void setSelectedModel (String model ) {
214+ modelCombo .setSelectedItem (model );
215+ }
216+
217+ /** @return the parameter spinner for grid rows (test-only access). */
218+ JSpinner getRowsSpinner () { return rowsSpinner ; }
219+ /** @return the parameter spinner for grid columns (test-only access). */
220+ JSpinner getColsSpinner () { return colsSpinner ; }
221+ /** @return the n (vertex count) label (test-only access). */
222+ JLabel getNLabel () { return nLabel ; }
223+ /** @return the p (edge probability) label (test-only access). */
224+ JLabel getPLabel () { return pLabel ; }
225+ /** @return the m (edges per vertex) label (test-only access). */
226+ JLabel getMLabel () { return mLabel ; }
227+ /** @return the k (degree / neighbors) label (test-only access). */
228+ JLabel getKLabel () { return kLabel ; }
229+ /** @return the beta (rewiring probability) label (test-only access). */
230+ JLabel getBetaLabel () { return betaLabel ; }
231+ /** @return the rows label (test-only access). */
232+ JLabel getRowsLabel () { return rowsLabel ; }
233+ /** @return the cols label (test-only access). */
234+ JLabel getColsLabel () { return colsLabel ; }
201235}
0 commit comments