refactor(control): organize package into logical subpackages#38
Conversation
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.
There was a problem hiding this comment.
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 intoControl.model,Control.render,Control.config, andControl.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 | |||
There was a problem hiding this comment.
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.
| agent: agent | |
| mode: agent |
| muteCheckBox.setSelected(true); | ||
| muteCheckBox.addChangeListener(e -> MainController.sound.setIsMuted(!muteCheckBox.isSelected())); |
There was a problem hiding this comment.
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).
| 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()); | |
| } | |
| }); |
| if (text.equals(text.replaceAll("[^0-9]", ""))) { | ||
| arraySizeOkButton.setEnabled(true); | ||
| arraySizeTextField.setForeground(normalColor); | ||
| } else { | ||
| arraySizeOkButton.setEnabled(false); | ||
| arraySizeTextField.setForeground(errorColor); | ||
| } |
There was a problem hiding this comment.
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.
| 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); |
| 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); |
There was a problem hiding this comment.
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).
| 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); |
Reorganize Control package into focused subpackages:
Updates 100+ imports across main and test sources.