Skip to content

refactor(control): organize package into logical subpackages#38

Merged
66-m merged 2 commits into
mainfrom
refactor/settings-ui-component-extraction
Mar 12, 2026
Merged

refactor(control): organize package into logical subpackages#38
66-m merged 2 commits into
mainfrom
refactor/settings-ui-component-extraction

Conversation

@66-m
Copy link
Copy Markdown
Owner

@66-m 66-m commented Mar 12, 2026

Reorganize Control package into focused subpackages:

  • ui/ - UI components, theming, settings
  • model/ - Data models and state management
  • config/ - Configuration and strategies
  • render/ - Rendering contexts
  • shuffle/ - Shuffle implementations

Updates 100+ imports across main and test sources.

66-m added 2 commits March 12, 2026 12:50
Introduce UiTheme, ComponentFactory, and StyledCard to centralize
styling constants and component creation. Reorganize Settings.java
into discrete factory methods (createSortingCard, createSpeedCard,
createVisualizationCard, createGradientCard, createDisplayCard,
createSoundCard, createActionPanel) for better separation of concerns.
Move run-all dialog logic to showRunAllDialog() and image selection
to selectImageFile().
Reorganize the Control package into focused subpackages by concern:
- ui/ - UI components, theming, settings (ComponentFactory, StyledCard, UiTheme, Settings)
- model/ - Data models and state management (ArrayModel, ArrayController, SortingStateManager, SortingSessionManager)
- config/ - Configuration and strategies (MainControllerConfig, DelayStrategy, ShuffleStrategy, ShuffleType)
- render/ - Rendering contexts (RenderContext, HeadlessRenderContext, ProcessingContext)
- shuffle/ - Shuffle implementations (unchanged, already separate)

Updates all imports (100+) across main and test sources. Improves code organization,
clarity of dependencies, and maintainability.
Copilot AI review requested due to automatic review settings March 12, 2026 12:00
@66-m 66-m merged commit 1b5df64 into main Mar 12, 2026
4 checks passed
@66-m 66-m deleted the refactor/settings-ui-component-extraction branch March 12, 2026 12:00
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR completes a package re-organization of the Control layer (splitting model/render/config/ui concerns), updates all dependent imports across sorting algorithms/visualizations/tests, and replaces the legacy IntelliJ UI Designer-based Settings window with a modernized Swing implementation and shared styling components.

Changes:

  • Refactor io.github.compilerstuck.Control.* types into Control.model, Control.render, Control.config, and Control.ui, updating imports throughout the codebase.
  • Replace the legacy Settings UI with a new custom Swing Settings window plus reusable theme/styled components.
  • Update test code and headless contexts to use the new package layout.

Reviewed changes

Copilot reviewed 84 out of 85 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/test/java/io/github/compilerstuck/SortingAlgorithms/SortingAlgorithmsTest.java Update test imports to new Control.model / Control.render packages
src/test/java/io/github/compilerstuck/Control/HeadlessVisualizationAndSoundTest.java Update headless test imports for moved controller/render types
src/test/java/io/github/compilerstuck/Control/ArrayModelAndStrategyTest.java Update imports for config/model/render refactor
src/main/java/io/github/compilerstuck/Visual/Visualization.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/SwirlDots.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/SphericDisparityLines.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/SphereHoops.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/Sphere.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/ScatterPlotLinked.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/ScatterPlot.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/Pyramid.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/Plane.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/Phyllotaxis.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/NumberPlot.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/MosaicSquares.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/MorphingShell.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/ImageVertical.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/ImageHorizontal.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/HorizontalPyramid.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/Hoops.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/DisparitySquareScatter.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/DisparitySphereHoops.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/DisparityPlane.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/DisparityGraphMirrored.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/DisparityGraph.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/DisparityCircleScatterLinked.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/DisparityCircleScatter.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/DisparityCircle.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/DisparityChords.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/CubicLines.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/Cube.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/ColorGradientGraph.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/Circle.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Visual/Bars.java Switch ArrayModel/RenderContext imports to new packages
src/main/java/io/github/compilerstuck/Sound/Sound.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/Sound/MinimSound.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/Sound/MidiSys.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/Sound/HeadlessSound.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/SortingAlgorithms/TimSort.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/SortingAlgorithms/SortingAlgorithm.java Switch ArrayModel/DelayStrategy/ProcessingContext imports to new packages
src/main/java/io/github/compilerstuck/SortingAlgorithms/ShellSort.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/SortingAlgorithms/ShakerSort.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/SortingAlgorithms/SelectionSort.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/SortingAlgorithms/RadixLSDSortBase10.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/SortingAlgorithms/QuickSortMiddlePivot.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/SortingAlgorithms/QuickSortDualPivot.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/SortingAlgorithms/PigeonholeSort.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/SortingAlgorithms/OddEvenSort.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/SortingAlgorithms/MergeSort.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/SortingAlgorithms/InsertionSort.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/SortingAlgorithms/HeapSort.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/SortingAlgorithms/GravitySort.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/SortingAlgorithms/GnomeSort.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/SortingAlgorithms/DoubleSelectionSort.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/SortingAlgorithms/CycleSort.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/SortingAlgorithms/CountingSort.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/SortingAlgorithms/CombSort.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/SortingAlgorithms/BucketSort.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/SortingAlgorithms/BubbleSort.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/SortingAlgorithms/BogoSort.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/SortingAlgorithms/AmericanFlagSort.java Switch ArrayModel import to Control.model
src/main/java/io/github/compilerstuck/Control/ui/UiTheme.java New centralized UI theme constants (colors/fonts/sizing)
src/main/java/io/github/compilerstuck/Control/ui/StyledCard.java New card container component with custom painting/hover
src/main/java/io/github/compilerstuck/Control/ui/Settings.java New modernized Settings window implementation
src/main/java/io/github/compilerstuck/Control/ui/Settings.form UI Designer form file present alongside new Settings UI
src/main/java/io/github/compilerstuck/Control/ui/JCheckBoxList.java Move JCheckBoxList into Control.ui package
src/main/java/io/github/compilerstuck/Control/ui/ComponentFactory.java New factory for consistent styled Swing components
src/main/java/io/github/compilerstuck/Control/shuffle/SortedShuffleStrategy.java Update imports to new model/render/config packages
src/main/java/io/github/compilerstuck/Control/shuffle/ReverseShuffleStrategy.java Update imports to new model/render/config packages
src/main/java/io/github/compilerstuck/Control/shuffle/RandomShuffleStrategy.java Update imports to new model/render/config packages
src/main/java/io/github/compilerstuck/Control/shuffle/AlmostSortedShuffleStrategy.java Update imports to new model/render/config packages
src/main/java/io/github/compilerstuck/Control/Settings.java Remove legacy IntelliJ UI Designer-based Settings implementation
src/main/java/io/github/compilerstuck/Control/render/RenderContext.java Move RenderContext to Control.render package
src/main/java/io/github/compilerstuck/Control/render/ProcessingContext.java Move ProcessingContext to Control.render package
src/main/java/io/github/compilerstuck/Control/render/HeadlessRenderContext.java Move HeadlessRenderContext to Control.render package
src/main/java/io/github/compilerstuck/Control/model/SortingStateManager.java Move SortingStateManager to Control.model package
src/main/java/io/github/compilerstuck/Control/model/SortingSessionManager.java Move SortingSessionManager to Control.model package and update imports
src/main/java/io/github/compilerstuck/Control/model/ArrayModel.java Move ArrayModel to Control.model package
src/main/java/io/github/compilerstuck/Control/model/ArrayController.java Move ArrayController to Control.model and update imports
src/main/java/io/github/compilerstuck/Control/MainController.java Update imports/wiring for new subpackages and new Settings UI
src/main/java/io/github/compilerstuck/Control/config/ShuffleType.java Move ShuffleType to Control.config package
src/main/java/io/github/compilerstuck/Control/config/ShuffleStrategy.java Move ShuffleStrategy to Control.config and update dependent imports
src/main/java/io/github/compilerstuck/Control/config/MainControllerConfig.java Move MainControllerConfig to Control.config package
src/main/java/io/github/compilerstuck/Control/config/DelayStrategy.java Move DelayStrategy to Control.config package
.github/prompts/commit.prompt.md Adjust prompt frontmatter key/value

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

@@ -1,5 +1,5 @@
---
mode: agent
agent: agent
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The frontmatter key was changed from mode: agent to agent: agent. GitHub prompt files typically use mode to declare how the prompt should run; agent: agent is likely an invalid/ignored key and may break this prompt being recognized. Revert to mode: agent (or whatever the correct schema key is for this repo) and keep agent only if there’s a separate, documented purpose for it.

Suggested change
agent: agent
mode: agent

Copilot uses AI. Check for mistakes.
Comment on lines +609 to +610
muteCheckBox.setSelected(true);
muteCheckBox.addChangeListener(e -> MainController.sound.setIsMuted(!muteCheckBox.isSelected()));
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MainController.sound can be null (e.g., when MIDI initialization fails in MainController). This change listener will throw a NullPointerException in that case. Consider using MainController.getSound() and guarding for null (e.g., disable the checkbox when sound is unavailable, or no-op when sound is null).

Suggested change
muteCheckBox.setSelected(true);
muteCheckBox.addChangeListener(e -> MainController.sound.setIsMuted(!muteCheckBox.isSelected()));
boolean soundAvailable = MainController.getSound() != null;
muteCheckBox.setSelected(soundAvailable);
muteCheckBox.setEnabled(soundAvailable);
muteCheckBox.addChangeListener(e -> {
var sound = MainController.getSound();
if (sound != null) {
sound.setIsMuted(!muteCheckBox.isSelected());
}
});

Copilot uses AI. Check for mistakes.
Comment on lines +271 to +277
if (text.equals(text.replaceAll("[^0-9]", ""))) {
arraySizeOkButton.setEnabled(true);
arraySizeTextField.setForeground(normalColor);
} else {
arraySizeOkButton.setEnabled(false);
arraySizeTextField.setForeground(errorColor);
}
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The size text field enables the “Apply” button whenever the input contains only digits, including the empty string. Since validateAndApplySize() ignores empty input, this leaves an enabled button that does nothing. Update the validation to also require non-empty input (and ideally also enforce the length/max constraints) before enabling Apply.

Suggested change
if (text.equals(text.replaceAll("[^0-9]", ""))) {
arraySizeOkButton.setEnabled(true);
arraySizeTextField.setForeground(normalColor);
} else {
arraySizeOkButton.setEnabled(false);
arraySizeTextField.setForeground(errorColor);
}
// Enable Apply only for non-empty, numeric, in-range values
if (text != null && !text.isEmpty() && text.equals(text.replaceAll("[^0-9]", ""))) {
try {
int value = Integer.parseInt(text);
if (value >= 3 && value <= maxSize) {
arraySizeOkButton.setEnabled(true);
arraySizeTextField.setForeground(normalColor);
return;
}
} catch (NumberFormatException ignored) {
// Fall through to disable state below
}
}
arraySizeOkButton.setEnabled(false);
arraySizeTextField.setForeground(errorColor);

Copilot uses AI. Check for mistakes.
Comment on lines +763 to +772
arraySizeSlider.setEnabled(enabled);
algorithmListComboBox.setEnabled(enabled);
runAllCheckBox.setEnabled(enabled);
shuffleListBox.setEnabled(enabled);
runButton.setEnabled(enabled);
arraySizeOkButton.setEnabled(enabled);
arraySizeTextField.setEnabled(enabled);
visualizationListComboBox.setEnabled(enabled);
buttonRunAllSettings.setEnabled(enabled);
speedSlider.setEnabled(enabled);
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setEnableInputs(true) re-enables algorithmListComboBox and buttonRunAllSettings unconditionally, which can desync the UI from the current runAllCheckBox state (e.g., Run-all checked but algorithm combo becomes enabled again, or Configure becomes enabled while Run-all is unchecked). Re-apply the same gating logic used in the Run-all checkbox listener when re-enabling controls (e.g., combo enabled only when not run-all, configure enabled only when run-all).

Suggested change
arraySizeSlider.setEnabled(enabled);
algorithmListComboBox.setEnabled(enabled);
runAllCheckBox.setEnabled(enabled);
shuffleListBox.setEnabled(enabled);
runButton.setEnabled(enabled);
arraySizeOkButton.setEnabled(enabled);
arraySizeTextField.setEnabled(enabled);
visualizationListComboBox.setEnabled(enabled);
buttonRunAllSettings.setEnabled(enabled);
speedSlider.setEnabled(enabled);
if (!enabled) {
arraySizeSlider.setEnabled(false);
algorithmListComboBox.setEnabled(false);
runAllCheckBox.setEnabled(false);
shuffleListBox.setEnabled(false);
runButton.setEnabled(false);
arraySizeOkButton.setEnabled(false);
arraySizeTextField.setEnabled(false);
visualizationListComboBox.setEnabled(false);
buttonRunAllSettings.setEnabled(false);
speedSlider.setEnabled(false);
return;
}
// Base enablement when inputs are allowed
arraySizeSlider.setEnabled(true);
runAllCheckBox.setEnabled(true);
shuffleListBox.setEnabled(true);
runButton.setEnabled(true);
arraySizeOkButton.setEnabled(true);
arraySizeTextField.setEnabled(true);
visualizationListComboBox.setEnabled(true);
speedSlider.setEnabled(true);
// Apply the same gating logic as the Run-all checkbox listener
boolean runAllSelected = runAllCheckBox.isSelected();
algorithmListComboBox.setEnabled(!runAllSelected);
buttonRunAllSettings.setEnabled(runAllSelected);

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants